当前位置:文档之家› ESRI中国社区学习心得---之Field Calculator

ESRI中国社区学习心得---之Field Calculator

ESRI中国社区学习心得---之Field Calculator
ESRI中国社区学习心得---之Field Calculator

目录

1.重复记录标上记号 (1)

2.计算[B].max + [B].min + [B] (2)

3.按照需求对字段[D]编号 (5)

4.将点x y坐标值写入字段[E] (6)

5.对图形的操作 (7)

6.距离小于一定数值的点之间连线 (11)

7.如何求曲线上任意点到端点的距离 (15)

8.在arcmap中如何将线自动闭合 (18)

第一层初出茅庐-工具的使用 (22)

1、属性表中的Field Calculator (22)

2、toolbox中的Calculate field (23)

第二层牛刀小试 (23)

1、字段批量赋值 (23)

2、字段之间赋值 (24)

第三层潜心修炼-变量、语法使用 (24)

1、基本函数的应用 (24)

2、简单语法的应用 (26)

第四层初露锋芒-利用复杂语句完成属性计算 (27)

1、复杂计算 (27)

第五层日新月异-简单图形计算 (30)

1、简单图形计算 (30)

2、如何判断一个面是多部分要素、还是环状要素 (31)

第六层大显身手-简单图形操作 (33)

1、批量改变线方向 (33)

2、在ArcMap中如何将线自动闭合 (34)

第七层游刃有余-复杂图形操作 (34)

1、如何求多边形质心到多边形边界最远的距离 (34)

2、提取改字段的最大值,提取这个字段的最小值,然后进行该地段+最大值+最小值的操作 (37)

3、怎样求得一个不规则多边形的极点? (38)

依据已知点及该点某属性,做线 (43)

如何绘制一点至平面内任意点之间的距离图层 (45)

在ESRI用AO框架搭建起应用程序范例 (48)

1.Field Calculator中的遍历(执行自动遍历每个要素) (49)

2.在Field Calculator中再次使用遍历(同VBA中写法) (49)

3.加标志使得Field Calculator中不做不必要的多次执行 (50)

ARCGIS学习心得——之Field Calculator

为什么要把Field Calculator专门作为一章呢,是因为Field Calculator着实很强大,利用Field Calculator总能达到事半功倍的效果,具体有多厉害,我们下面来一一介绍。

[学习笔记]ArcMap中的VBA之Field Calculator

https://www.doczj.com/doc/b84976657.html,/ESRI/viewthread.php?tid=54293

- - - - - -<学习笔记>- - - - - -

ArcMap中,无论是在属性框中右击字段打开的Field Calculator还是在Arctoolbox\Data Management Tools\Field\ 工具箱中的Calculate field ,都支持vba表达式。

字段计算器,用以计算字段值。这些字段值,可以是属性表里相关字段的综合,比如百分比,分解字段等;可以是和图形有关的值,比如点的xy坐标,面的中心点坐标,线的长度等等;也可以是为了满足某种特定需求而创造出来的值。

比如如下问题:

1.要找出图层某字段[A]里的重复值,并标上记号;

2.图层某字段[B],现在要将字段[B]中的{最大值+最小值+该行值} 写入一个新字段[C]中;

3.字段[D]需要进行编号,号码格式为"000001","000002","000003","000004"...,"000202"…;

4.将点层的xy坐标按x , y 的格式输出到[E] 字段

1.重复记录标上记号

要找出图层某字段的重复记录,对于存储在Personal Geodatabase中feature而言,可以通过select by attribute找出重复值的记录:

1.Sql: select * from layer where:

2.[A] in (select [A] from 层名group by [A] having count([A]) >1)

这样执行下来的结果,就是该图层中,[A]字段值重复数大于等于2的所有记录,而对于不支持子查询的比如shapefile格式文件,可以怎么办呢?在属性表中新建一个字段,取名"test',类型设置为long integer,然后右击该字段,选择Field Calculator,勾选advanced,写入以下代码:

1.' ----------------------------------------

2.' ESRI Support Home > Knowledge Base > Technical Articles > Article Detail

3.' 代码参见HowTo: Identify duplicate field values

4.' @ Tsonghua 090924

5.' ----------------------------------------

6.Static d As Object

7.Static i As Long

8.Dim iDup As Integer

9.Dim sField

10.' ----------------------------------------

11.'这里填写需要检查的字段名

12.sField = [A]

13.' ----------------------------------------

14.If (i = 0) Then

15.Set d = CreateObject("Scripting.Dictionary")

16.End If

17.If (d.Exists(CStr(sField))) Then

18.iDup = 1

19.Else

20. d.Add CStr(sField), 1

21.iDup = 0

22.End If

23.i = i + 1

在Pre_Logic VBA Script Code下方的A= 窗口中填iDup

这是一段在ESRI Support(https://www.doczj.com/doc/b84976657.html,)上找到的代码,功能就是可以讲重复值做上记号,属于重复值的记录,[test]字段值计算结果为 1 ,否则为0 。就是说,如果有三条记录[A]字段值分别为"aa","aa","aa",那么有一条被标上0 ,剩余2条被标上 1 。

对重复记录做了记号,如何处理,就可以随心所欲啦。这算是一个为了满足某种需求,而重新新建字段,并计算其值的例子

2.计算 [B].max + [B].min + [B]

这个问题,就是根据属性表里其他字段来重新提取所需要的信息进行组合。

这个例子,是在论坛上看到有人问的问题。同样,去ESRI的支持中心去搜了一下,找到了如下代码:

1.' ----------------------------------------

2.' ESRI Support

3.' Author Christian Degrassig

4.' @ Tsonghua 090924

5.' ----------------------------------------

6.Dim pMxDoc As IMxDocument

7.Dim pFLayer As IFeatureLayer

8.Dim pData As IDataStatistics

9.Dim pCursor As ICursor

10.Dim pStatResults As IStatisticsResults

11.Static lngFlag as long

12.Dim lngLayerIndex as long

13.Dim strFieldName as string

14.'因为不清楚你的字段类型,所以这里设置三个变量类型为Variant

15.Static varZMax as Variant

16.Static varZMin as Variant

17.Dim varVal as Variant

18.if lngFlag = 0 then

19.'1.注:这里填你需要取最大最小值的字段名

20.strFieldName = "B"

21.'2.这里设置你需要计算字段值的图层所在图层索引号

22.'TOC中,从上至下,第一层LayerIndex=0,第二层为1,以此类推..

23.'这里LayerIndex值是第二个需要设置的地方

24.lngLayerIndex = 0

25.Set pMxDoc = ThisDocument

26.Set pFLayer = https://www.doczj.com/doc/b84976657.html,yer(lngLayerIndex)

27.Set pCursor = pFLayer.Search(Nothing, False)

28.Set pData = New DataStatistics

29.pData.Field = strFieldName

30.Set pData.Cursor = pCursor

31.Set pStatResults = pData.Statistics

32.varZMax = pStatResults.Maximum

33.varZMin = pStatResults.Minimum

34.lngFlag = 1

35.End If

36.'3.这里,第三个数请双击上面fields框中的对应字段

varVal= varZMax + varZMin + [B]

同样,在"C =" 的框框中填入varVal

字段计算器里,不管是一般的赋值表达式抑或是advanced里写的较复杂的表达式,其实

都是在每一行运行一次,对该记录进行赋值运算。因此,如果需要将某参数值传递下去的话,可以用" static 参数as 类型"这样的参数声明方式,"Dim 参数as 类型"的声明方式,只是在进行某条记录赋值的时候有效,一旦结束,参数值被清空。

例如,如果想对某字段赋值为1,2,3,4… 可以用如下赋值表达式:

1.Static i as long

2.Dim a as string

3.a=i+1

4.i=i+1

5.__esri_field_calculator_splitter__

6.a

注:__esri_field_calculator_splitter__ 是分割标志,具体的可以在Field Calculator中写一个表达式,然后点击save ,保存的文件是".cal"格式,可以用记事本打开编辑。对于一个经常用的表达式,可以写好之后保存("save")起来,下次使用的时候,只需要点"Load"加载过来即可

对比,

1.dim i as long

2.Dim a as string

3.a=i+1

4.i=i+1

5.__esri_field_calculator_splitter__

6.a

对比发现,用static 方式声明的结果是1,2,3,4… 而用dim方式声明的结果是1,1,1,1,…也就是说,dim声明的参数i在Field Calculator逐行运行的过程中,没有把参数值传递下去。

回过头来分析一下这段重新分析字段,获取最大值,最小值来组成新字段值的问题

1.if lngFlag = 0 then

2.'1.注:这里填你需要取最大最小值的字段名

3.strFieldName = "自定义的字段名"

4.'2.这里设置你需要计算字段值的图层所在图层索引号

5.'TOC中,从上至下,第一层LayerIndex=0,第二层为1,以此类推..

6.'这里LayerIndex值是第二个需要设置的地方

7.lngLayerIndex = 0

8.Set pMxDoc = ThisDocument

9.Set pFLayer = https://www.doczj.com/doc/b84976657.html,yer(lngLayerIndex)

10.Set pCursor = pFLayer.Search(Nothing, False)

11.Set pData = New DataStatistics

12.pData.Field = strFieldName

13.Set pData.Cursor = pCursor

14.Set pStatResults = pData.Statistics

15.varZMax = pStatResults.Maximum

16.varZMin = pStatResults.Minimum

17.lngFlag = 1

18.End If

这段是解决问题的关键所在,它在Field Calculator对第一行记录赋值的时候,已经对整层进行统计并获取了最大值pStatResults.Maximum 储存在参数varZMax中,同时把获取的最小值pStatResults.Minimum 存在参数varZMin中。因为对整层该字段的赋值过程中,只需要获取一次最大值最小值即可,因此这里做了个标志- - -lngFlag。一旦最大最小值获取完成,就让lngFlag值为1,以后的逐行赋值中,不再进行统计,而直接使用参数varZMax,varZMin 的值。

最后一行varVal= varZMax + varZMin + [待计算字段名]这就很简单了,直接进行加减运算。

3.按照需求对字段[D]编号

有了上面两则例子的提示,这里不难分析,其实只需要先按要求生成1,2,3,4… 然后对其格式标准化(也就是让字段长度一致,不足的补零)。

参照如下代码:

为了有更大的延展性,这段优秀的代码里将起始值、步长(就是编号每次增加的值)、字段规范长度等都设置为可以改变的参数,分别为:lStart,lInterval

,iStringLength

自然地,可以有其他思路来解决问题:简单地生成1,2,3,。。。,然后规范一下格式为"0000000" 这种。如下参考代码:

1.'-------------------------------------

2.'rec_Number_ConstantLengthString2.cal

3.'Author: Ianko Tchoukanski

4.'https://www.doczj.com/doc/b84976657.html,

5.'@ Tsonghua

6.'-------------------------------------

7.Dim sID As String

8.Dim sFormatString As String

9.sFormatString = "000000000"

10.sID= Format( [FID], sFormatString)

11.__esri_field_calculator_splitter__

12.sID

这段代码,同样地,也是我为了寻求某GIS交流群里群友问题答案的时候再ESRI支持中心上找到的,网址是https://www.doczj.com/doc/b84976657.html,,他们写了一批优秀的表达式,打包为"

EasyCalculate50.zip ",免费提供下载使用。同时还有个工具"ETGeoWizards99_92.exe",一样地很优秀,作为ArcGIS的插件,有很多实用的功能,只是这个插件只有些基本的处理是共享,其他更高级一些处理过程还有搭建的模块就是需要注册了。

要研究Field Calculator中的vba,认真学习https://www.doczj.com/doc/b84976657.html,提供的免费的EasyCalculate50,是个不错的选择。

4.将点x y坐标值写入字段[E]

前面提到的几个例子,都是纯粹的属性字段的操作,Field Calculator里提供使用vba对图形的某些属性性质进行获取或者修改的方法。

本例中,需要获取点层数据个点的坐标值,示例代码如下:

1.' ----------------------------------------

2.' @ Tsonghua 090924

3.' ----------------------------------------

4.Dim Output As string

5.Dim pPoint As IPoint

6.Set pPoint = [Shape]

7.Output = pPoint.X & "," & pPoint.Y

8.__esri_field_calculator_splitter__

9.Output

这一段的绝大部分是拷贝自Field Calculator的Help文档

5.对图形的操作

求距离小于指定值的任意两点连线的长度和角度

1、先用add xy coordinate将点的座标加入属性表,下图是加入点座标后的属性表

2、用point distance求出指定距离内任意两点的距离,下图指定距离为1500米

注意search radius为1500

求出的结果,为一dbf文件:

3、将上步结果中distance为0的记录删掉(arcgis9.3这步不需要做,因它不会求点和自身的距离),增加angle、fx、fy、tx、ty几个double类型字段,用以存放角度,起点x、y座标和终点x、y座标

4、用上表中input_fid字段将上表和第一步中加了点座标的属性表连接,连接字段为属性表中的fid,并将属性表中的point_x、point_y分别赋给fx和fy。

5、去掉连接,然后按上步的方法再用near_fid连接属性表,给tx、ty赋值。

连接后的结果:

6、计算角度

在angle字段名上点右键,选field calculator,选中advanced,在Pre-logid VBA Script Code 窗口内输入下列内容:

if [tx]-[fx]>0 and [ty]-[fy]>0 then

a=atn(([ty]-[fy])/([tx]-[fx]))*180/4/atn(1)

elseif [tx]-[fx]<0 then

a=(4*atn(1)+atn(([ty]-[fy])/([tx]-[fx])))*180/4/atn(1)

elseif [tx]-[fx]>0 and [ty]-[fy]<0 then

a=(8*atn(1)+atn(([ty]-[fy])/([tx]-[fx])))*180/4/atn(1)

elseif [tx]-[fx]=0 and [ty]-[fy]>0 then

a=90

elseif [tx]-[fx]=0 and [ty]-[fy]<0 then

a=270

elseif [tx]-[fx]>0 and [ty]-[fy]=0 then

a=0

end if

在angle=下面的窗口内输入a

至此距离小于指定值的任意两点连线的长度和角度都已求出。

前面的部分的结果是个dbf文件,将这个dbf文件按(fx,fy)展成点文件后即可利用https://www.doczj.com/doc/b84976657.html,/ESRI/thread-53035-1-1.html帖子中的第二步将满足条件的点之间连线。连线之前注意将代码中的

dLength = [NEAR_DIST]

dAngle = [NEAR_ANGLE]

修改为:

dLength = [DISTANCE]

dAngle = [ANGLE]

6.距离小于一定数值的点之间连线

近日偶得一个距离小于一定数值的点之间连线方法,写出来与大家同享。

假设要将点文件or_point中距离小于1000的点之间连线,下面是具体步骤:

1、首先用near工具找出距离小于1000的点:

文件原属性表:

使用下面的工具:

参数设置:

input features和near features均填你的点文件,search radius填1000,angle选项选中。

运行工具后的点文件属性表:

然后按属性选出距离大于0的点导出到另一文件(比如new_point.shp),并在新文件中建一整型字段,比如dummy。

2、新建一线文件(比如p2l.shp),和new_point一起加入arcmap,并使线文件为最上一层:

打开new_point的属性表,在dummy上点右键,选field calculator,在弹出的窗口内点advanced,在Pre-logid VBA Script Code窗口内输入下列代码:

Dim pMxDoc As IMxDocument

Dim pMap As IMap

Dim pPoint As IPoint

Dim pEndPoint As IPoint

Dim pLine As esriGeometry.ILine

Dim pTransform As ITransform2D

Dim dLength As Double

Dim dAngle As Double

Dim pSegColl As ISegmentCollection

Dim Pi As Double

Dim pFeatcls As IFeatureClass

Dim pFeatLayer As IFeatureLayer

Dim iLayerOrder As Integer

Dim pFCursor As IFeatureCursor

Dim pFBuffer As IFeatureBuffer

dLength = [NEAR_DIST]

dAngle = [NEAR_ANGLE]

Pi = 4 * Atn(1)

Set pMxDoc = ThisDocument

Set pMap = pMxDoc.FocusMap

Set pFeatLayer = https://www.doczj.com/doc/b84976657.html,yer(iLayerOrder)

Set pFeatcls = pFeatLayer.FeatureClass

Set pFBuffer = pFeatcls.CreateFeatureBuffer

Set pFCursor = pFeatcls.Insert(True)

If (Not IsNull([Shape])) Then

Set pPoint = [Shape]

If (Not pPoint.IsEmpty) Then

Set pEndPoint = New Point

pEndPoint.PutCoords pPoint.X + dLength, pPoint.Y

Set pLine = New esriGeometry.Line

pLine.PutCoords pPoint, pEndPoint

dAngle = dAngle * Pi / 180

Set pSegColl = New Polyline

pSegColl.AddSegment pLine

Set pTransform = pSegColl

pTransform.Rotate pPoint, dAngle

Set pFBuffer.Shape = pSegColl

pFCursor.InsertFeature pFBuffer

End If

End If

在下面的窗口内输入任意的整数

点OK,大功告成:

生成的线会有重复的,选中所有线,点拓扑工具条上的planarize line工具处理一下即可

上述方法有一定的局限性,即当有若干个点满足条件时,只能连接最近的两点,这倒适合于连接局部断开的线段,算是歪打正着吧。大家有什么更好的方法欢迎提出。

7.如何求曲线上任意点到端点的距离

问题中,用合适的vba实现求算曲线上任一点到线端点距离。

上次看到一个帖是求曲线上两点的距离,现在在网上找到了一段代码,利用它可以求曲线上任意点到端点的距离,应该可以满足求曲线上任意两点沿曲线的距离的要求,大家可以看一下,希望能提出宝贵的意见

具体做法如下:

1、在ARCMAP中加载点图层和对应的线图层,注意只能加载这两个图层,且点图层必须在线图层之上,为了便于大家更清楚地看清起点,我把符号改为指向末端的方向箭头

2、在点图层属性表中新加到端点的字段如aa,类型为double,如下

3、选中列aa ,在field caculator中输入以下代码

' ----- You'll need to change this value ----

Const TOLERANCE As Double = 500

' -这个容差的设置一定要注意,要多次尝试.若属性表中出现-1,就加大这个值

Static pMxDoc As IMxDocument

Static pFtrLyr As IFeatureLayer

Static pFtrCls As IFeatureClass

Static pSpFltr As ISpatialFilter

Static pOutPt As IPoint

Dim pInPt As IPoint

Dim pTopOp As ITopologicalOperator

Dim pFtrCsr As IFeatureCursor

Dim pFtr As IFeature

Dim pPline As IPolyline

Dim dDis As Double

Dim dDummy As Double

Dim bDummy As Boolean

Set pInPt = [Shape]

Set pTopOp = pInPt

If pMxDoc Is Nothing Then

Set pMxDoc = ThisDocument

Set pFtrLyr = https://www.doczj.com/doc/b84976657.html,yer(1)

Set pFtrCls = pFtrLyr.FeatureClass

Set pSpFltr = New SpatialFilter

pSpFltr.SpatialRel = esriSpatialRelIntersects

Set pOutPt = New Point

End If

Set pSpFltr.Geometry = pTopOp.Buffer(TOLERANCE)

Set pFtrCsr = pFtrLyr.Search(pSpFltr, False)

Set pFtr = pFtrCsr.NextFeature

If pFtr Is Nothing Then

dDis = -1

Else

Set pPline = pFtr.Shape

pPline.QueryPointAndDistance esriNoExtension, pInPt, False, pOutPt, dDis, dDummy, bDummy

End If

Set pFtrCsr = Nothing

'

' Put dDis in the box below the Advanced window

'

见下图

这里要特别注意的是第二行的容差的设置一定要得当,不能过于大,也不能太小。太大的话,就可能算成了点到另一条曲线端点的距离,太小的话不能判断点在曲线上。所以要多次尝试,取最佳值。

算出来的表格结果如下:

以上表表示的是曲线上的每个点到各自曲线起点的距离

可以看看这个图,可能会更加清楚

大家可以看上图,越到曲线末端(箭头方向)值越大。

要是要使结果更精确些,在选点时要设好snapping值,使点最好能落在线上。

8.在arcmap中如何将线自动闭合

直接编辑了线层,使得线终点与起点重合,达到闭合的效果。

前段时间本人遇到过类似的问题,所以一直在寻求解决方案,有一天在一个网站上看到了下面的解决方法,现在对其进行扩充与更详细的操作,希望大家能够一起分享,谢谢支持。

1、这是原SHAPE格式的待闭合的线

2、打开其属性表,选择Shape*这一列

3、选择需要闭合的曲线,如第一行,后右键选择field calculater这一项

4、选择YES

相关主题
文本预览
相关文档 最新文档