SuperMap Objects开发中的小技巧.docx
《SuperMap Objects开发中的小技巧.docx》由会员分享,可在线阅读,更多相关《SuperMap Objects开发中的小技巧.docx(21页珍藏版)》请在冰豆网上搜索。
![SuperMap Objects开发中的小技巧.docx](https://file1.bdocx.com/fileroot1/2023-2/21/84028f97-181d-452b-96fe-8a955e4bb99f/84028f97-181d-452b-96fe-8a955e4bb99f1.gif)
SuperMapObjects开发中的小技巧
开发中的小技巧
实际的开发过程中经常会遇到一些很细节的功能问题。
为了尽量避免这些小问题给我们带来的困扰,也为了提起很多SuperMap开发者的兴趣,今后大家可以将自己在开发时灵光一现,或者自己觉得很满意的小技巧,小方法贴出来,大家一起分享一下。
在这里先做个抛砖引玉吧。
首先介绍三个小技巧,当然如果有更好的方法欢迎大家一起讨论。
==================================
问:
在SuperMapObjects中如何实现反选?
答:
假设选择了若干对象的SMID分别为2,4,5,7,10实现反选时,设置查询条件"SMiDnotin
(2,4,5,7,10)",再对此图层数据集查询出的记录集转换为选择集,实现的效果就是选中了除了这几
个ID之外的对象了。
========================
问:
在SuperMapObjects中如何绘制岛洞多边形?
答:
以选中的两个面对象为例,先用union方法得到这两个面的并集,再使用Intersect得到它们的
交集,用这个交集面去Erase并集面,最后的结果就是岛洞多边形了。
===============================
问:
为什么有时候绘制对象会失败?
分析原因:
当向一个数据集上绘制几何对象出现画不上的问题,如果通过重新计算范围和重建空间
索引不能解决问题,请检查一下该数据集的属性字段是否存在必填字段,而且该字段没有设置缺省
值,这个就是问题所在。
解决办法:
新建字段,使用“更新列”将原始字段值复制过来;删除原有字段,重新建立一个同名
字段并设置缺省值,再更新复制回该列的值,删除中间字段即可。
再介绍一个制作一个快速的如Deskpro数据追加列的功能。
*说明:
A,B两个数据集,将A中存在而B中不存在的字段添加到B数据集中,然后根据公共字段值相等的字段值也添加到B中。
PrivateSubbtnComfirm_Click()
DimsetOKAsBoolean
DimoRecFAssoRecordset
DimoRecTAssoRecordset
DimoDtFAssoDatasetVector
DimoDtTAssoDatasetVector
DimoFldsFAssoFieldInfos
DimoFldsTAssoFieldInfos
DimoFldInfoAssoFieldInfo
DimoDssAssoDataSources
DimUpIDAsInteger
DimcrtFldOkAsBoolean
DimiAsInteger
DimjAsInteger
DimmAsInteger
DimaAsInteger
Dimn()AsString
DimfldVFAsString
DimfldVTAsString
DimfldPubAsString
DimStrSqlTAsString
DimoErrAsNewsoError
'
'
OnErrorResumeNext
SetoDss=FrmEnterMap.SuperWorkspace1.Datasources
IfoDss.Count=0ThenExitSub
SetoDtF=oDss.Item(Trim(cmbDsFrom.text)).Datasets(Trim(cmbDtFrom.text))
SetoDtT=oDss.Item(Trim(cmbDsTo.text)).Datasets.Item(Trim(cmbDtTo.text))
SetoRecF=oDtF.Query("",True,Nothing,"")'得到原数据集的记录集
SetoFldsF=oRecF.GetFieldInfos
SetoRecT=oDtT.Query("",False,Nothing,"")'得到目标数据集的数据集,第二个参数为False,否则不能使用之后的FindFirst方法
SetoFldsT=oRecT.GetFieldInfos
fldPub=Trim(cmbPubFlds.text) '返回公共字段不能为空
ReDimn(oFldsF.Count)
DimBfFldCountAsInteger
DimFindOkAsBoolean'返回FindFirst是否成功
BfFldCount=oRecF.FieldCount
Fori=1TooFldsF.Count'先完成创建字段的功能
IfoDtT.IsAvailableFieldName(oFldsF(i).name)Then'条件为True则可以添加该字段
oDtT.ClearRecordsets
crtFldOk=oDtT.CreateField(oFldsF(i))
IfcrtFldOk=TrueThen
n(a)=oFldsF(i).name '用数据组记录下创建的字段名
a=a+1
EndIf
EndIf
Nexti
SetoRecT=oDtT.Query("",False,Nothing,"")
IfBfFldCount=oRecT.FieldCountThen
MsgBoxoErr.LastErrorMsg
SetoRecT=Nothing
SetoRecF=Nothing
SetoFldsF=Nothing
SetoFldsT=Nothing
SetoErr=Nothing
SetoDtF=Nothing
SetoDtT=Nothing
SetoDss=Nothing
ExitSub
Else
oRecF.MoveFirst
oRecT.MoveFirst
Fori=1TooRecF.RecordCount'以源数据集做循环
StrSqlT=fldPub&"="&oRecF.GetFieldValue(fldPub)'根据公共字段查询将游标移动到该位置
FindOk=oRecT.FindFirst(StrSqlT)
IfFindOk=TrueThen
Form=1Toa'循环添加的字段值
oRecT.Edit
setOK=oRecT.SetFieldValue(n(m-1),oRecF.GetFieldValue(n(m-1)))
UpID=oRecT.Update
Nextm
EndIf
oRecF.MoveNext
Nexti
EndIf
SetoRecT=Nothing
SetoRecF=Nothing
SetoFldInfo=Nothing
SetoFldsF=Nothing
SetoFldsT=Nothing
SetoErr=Nothing
SetoDss=Nothing
SetoDtF=Nothing
SetoDtT=Nothing
EndSub
这段代码测试22000多条记录添加4列属性,时间在1分钟左右。
如果有更快更好的方法欢迎介绍一下。
再介绍一个制作一个快速的如Deskpro数据追加列的功能。
*说明:
A,B两个数据集,将A中存在而B中不存在的字段添加到B数据集中,然后根据公共字段值相等的字段值也添加到B中。
PrivateSubbtnComfirm_Click()
DimsetOKAsBoolean
DimoRecFAssoRecordset
DimoRecTAssoRecordset
DimoDtFAssoDatasetVector
DimoDtTAssoDatasetVector
DimoFldsFAssoFieldInfos
DimoFldsTAssoFieldInfos
DimoFldInfoAssoFieldInfo
DimoDssAssoDataSources
DimUpIDAsInteger
DimcrtFldOkAsBoolean
DimiAsInteger
DimjAsInteger
DimmAsInteger
DimaAsInteger
Dimn()AsString
DimfldVFAsString
DimfldVTAsString
DimfldPubAsString
DimStrSqlTAsString
DimoErrAsNewsoError
'
'
OnErrorResumeNext
SetoDss=FrmEnterMap.SuperWorkspace1.Datasources
IfoDss.Count=0ThenExitSub
SetoDtF=oDss.Item(Trim(cmbDsFrom.text)).Datasets(Trim(cmbDtFrom.text))
SetoDtT=oDss.Item(Trim(cmbDsTo.text)).Datasets.Item(Trim(cmbDtTo.text))
SetoRecF=oDtF.Query("",True,Nothing,"")'得到原数据集的记录集
SetoFldsF=oRecF.GetFieldInfos
SetoRecT=oDtT.Query("",False,Nothing,"")'得到目标数据集的数据集,第二个参数为False,否则不能使用之后的FindFirst方法
SetoFldsT=oRecT.GetFieldInfos
fldPub=Trim(cmbPubFlds.text) '返回公共字段不能为空
ReDimn(oFldsF.Count)
DimBfFldCountAsInteger
DimFindOkAsBoolean'返回FindFirst是否成功
BfFldCount=oRecF.FieldCount
Fori=1TooFldsF.Count'先完成创建字段的功能
IfoDtT.IsAvailableFieldName(oFldsF(i).name)Then'条件为True则可以添加该字段
oDtT.ClearRecordsets
crtFldOk=oDtT.CreateField(oFldsF(i))
IfcrtFldOk=TrueThen
n(a)=oFldsF(i).name '用数据组记录下创建的字段名
a=a+1
EndIf
EndIf
Nexti
SetoRecT=oDtT.Query("",False,Nothing,"")
IfBfFldCount=oRecT.FieldCountThen
MsgBoxoErr.LastErrorMsg
SetoRecT=Nothing
SetoRecF=Nothing
SetoFldsF=Nothing
SetoFldsT=Nothing
SetoErr=Nothing
SetoDtF=Nothing
SetoDtT=Nothing
SetoDss=Nothing
ExitSub
Else
oRecF.MoveFirst
oRecT.MoveFirst
Fori=1TooRecF.RecordCount'以源数据集做循环
StrSqlT=fldPub&"="&oRecF.GetFieldValue(fldPub)'根据公共字段查询将游标移动到该位置
FindOk=oRecT.FindFirst(StrSqlT)
IfFindOk=TrueThen
Form=1Toa'循环添加的字段值
oRecT.Edit
setOK=oRecT.SetFieldValue(n(m-1),oRecF.GetFieldValue(n(m-1)))
UpID=oRecT.Update
Nextm
EndIf
oRecF.MoveNext
Nexti
EndIf
SetoRecT=Nothing
SetoRecF=Nothing
SetoFldInfo=Nothing
SetoFldsF=Nothing
SetoFldsT=Nothing
SetoErr=Nothing
SetoDss=Nothing
SetoDtF=Nothing
SetoDtT=Nothing
EndSub
这段代码测试22000多条记录添加4列属性,时间在1分钟左右。
如果有更快更好的方法欢迎介绍一下。
当在第一个地图中只想对一定小范围内对空间对象做SQL条件查询,比如自定义圈定一个多边形范围内进行查询。
可以使用
QueryEx(geometryassoGeometry,nSpatialQueryMode asseSpatialQueryMode,strFilterasstring)方法.geometry是自己在跟踪层上添加的多边形,即查询的区域范围。
nSpatialQueryMode是选择合适的空间查询方式一般可以用Containing,strFilter为查询的SQL条件语句,相当于Where…
当使用IDW方法进行查值得时候,所有参数是正确的,而且进度条也正常运行。
但是如果跟踪一下结果,发现定义的soDatasetRaster对象的实例并没有值。
更奇怪的是,重新打开这个数据源,发现结果数据集就在那里,而且是正确的。
不要觉得奇怪,不是Bug,也没有见鬼。
你一定丢掉了一句重要的代码:
在初始的时候:
SuperAnalyst.connect(SuperWorkspace.Handle)就OK了。
今天发现一个小问题,挺有意思。
在使用工作空间管理器控件时,如果只想使用地图的选项卡,只用来显示地图,那么开始的时候可能会遇到这样的问题。
就是打开工作空间之后,显示在控件地图选项卡中的是数据而不是地图,但是如果点击一下地图的标签的时候就刷新显示地图名称了。
有点奇怪开始怀疑是缺陷,但实际上并不是。
这时候需要设置另一个相关的属性SuperWkspManager.ActiveTab=2;因为默认的每一个Tab都是有索引的,数据为1,地图为2,布局为3,资源为4。
如果设置了某些Tab为False那么就会默认顺序递推。
所以在设置某些Tab为False之前要先设置但前默认打开时显示的Tab的索引。
SuperWkspManager1.ActiveTab=2'默认激活状态的Tab索引为2,即地图Tab
SuperWkspManager1.DataTab=False
SuperWkspManager1.LayoutTab=False
SuperWkspManager1.ResourceTab=False
SuperWkspManager1.SenceTab=False
注意:
SuperWkspManager1.ActiveTab=2一定要写在最前面,如果写在后面也是没有效果的。
有兴趣的可以试试,这个原理还是很好理解的。
提供两个文件型和数据库行数据在开发时要注意的区别。
(一)设置点对象属性问题。
在新版本的数据引擎中,SuperMap将点数据集的空间坐标从空间信息中提取出来,作为了两个属性字段来存放,即SmX和SmY。
那么在开发的时候如果设计一些自动添加记录,设置属性字段值的时候,就要考虑到SetFieldValue(indexasVARIANT,..)这个索引问题。
如果选择使用整型索引,那么就要判断好数据引擎类型。
因为同一属性字段数据库型要比文件型+2。
如果使用字段名作为索引的话是比较安全一点。
当然,这需要根据实际数据条件而定。
(二)设置SQL语句进行查询问题。
在设置SQL查询条件的时候,经常会设置模糊查询语句,即使用“Like”.
而在设置Like后面的查询值时,需要设置通配符。
如'*市'。
但是在数据库中使用的是'%市',文件型使用的则是'*市'。
这个小问题,大家可以注意区分一下。
程序中也有必要判断一下,避免数据源类型改变后,查询功能失灵。
(二)设置SQL语句进行查询问题。
在设置SQL查询条件的时候,经常会设置模糊查询语句,即使用“Like”.
而在设置Like后面的查询值时,需要设置通配符。
如'*市'。
但是在数据库中使用的是'%市',文件型使用的则是'*市'。
这个小问题,大家可以注意区分一下。
程序中也有必要判断一下,避免数据源类型改变后,查询功能失灵。
关于soTreeView的几点注意。
1.在SuperWkspaceManager里面如果设置右键菜单,并不会直接设定右键点击的节点为选中状态。
而是根节点为选中。
这时候就可以利用MouseUp事件参数中提供的x,y坐标,使用soTreeView.GetNodeAt方法返回一个soTreeNode对象。
用它设置SuperWkspaceManager.TreeView.SelectedNode就算可以了。
2.在SuperLegend中也可以得到soTreeView对象。
可以利用它设置所有的图例节点的Text等等。
也可以移除指定的节点,主要就是显示指定图层的图例。
但是这个是全部添加节点再移除。
所以如果使用VisualStudio的TreeView写起来可能会方便些。
在导入jpg影像数据的时候,为了设置影像地理坐标范围,需要使用影像地理坐标配置文件。
如果得到的配制文件是.jgw格式的,那么SuperMap是不支持直接导入的。
这个时候只要看一下这个文件的内容就会发现,格式和.tfw是一样的。
那么改变一下文件格式,通过.tfw格式导入就可以了。
效果是没有差别的。
是对.jgw的简单介绍。
以下是.tfw的格式
10
//地图中一个象素在X方向上的X分辨率
0
//X方向旋转量
0
//Y方向旋转量
-10
//地图中一个象素在Y方向上的Y分辨率的負值
18263450.000000
//象素1,1中心位置的X坐标
3658590.000000
//象素1,1中心位置的Y坐标
提供一个网线分析的小例子:
在有的网线分析中,确定了终止点,要进行路径分析,路线的选择。
这个功能要用到网络分析soNetWorkAnalystEx.Path等类似的方法。
但是,有些业务中,对于两点间的路径如果是直接连通的,即两点之间只有一条弧段相连且没有任何中间节点。
这种情况不论该路线是否为最短都要作为第一选择方案。
所以,针对这个问题可以使用soNetWorkAnalyst.FindConnectEdges(objNetworkDatasetAssoDatasetVector,nNodeAsLong,nDirectionAssePathFindingDirection,nLevelAsLong)方法求得起点的临近边。
nNode:
起始节点。
nDirection:
scdForward只有正方向。
nLevel:
1因为只求直接相连的弧段。
这样返回的是一个soSelection对象,下面要使用soRecordsetsoSelection.ToRecordset(false)得到记录集,soRecordset.GetFieldValue("SmTNode")得到这条弧段的SmTNode字段。
这个字段就是终结点的ID。
对记录集的每条记录循环,返回该字段值,与最开始确定的终结点ID比较。
如果相等就说明从起点到终点间存在一条直通的弧段。
那么这就是所需要的结果了,如果不存在再使用P