SuperMap Objects开发中的小技巧.doc_第1页
SuperMap Objects开发中的小技巧.doc_第2页
SuperMap Objects开发中的小技巧.doc_第3页
SuperMap Objects开发中的小技巧.doc_第4页
SuperMap Objects开发中的小技巧.doc_第5页
已阅读5页,还剩12页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

开发中的小技巧实际的开发过程中经常会遇到一些很细节的功能问题。为了尽量避免这些小问题给我们带来的困扰,也为了提起很多SuperMap开发者的兴趣,今后大家可以将自己在开发时灵光一现,或者自己觉得很满意的小技巧,小方法贴出来,大家一起分享一下。在这里先做个抛砖引玉吧。首先介绍三个小技巧,当然如果有更好的方法欢迎大家一起讨论。=问:在SuperMap Objects中如何实现反选?答:假设选择了若干对象的SMID分别为2,4,5,7,10实现反选时,设置查询条件SMiD not in (2,4,5,7,10),再对此图层数据集查询出的记录集转换为选择集,实现的效果就是选中了除了这几个ID之外的对象了。=问:在SuperMap Objects中如何绘制岛洞多边形?答:以选中的两个面对象为例,先用union方法得到这两个面的并集,再使用Intersect得到它们的交集,用这个交集面去Erase并集面,最后的结果就是岛洞多边形了。=问:为什么有时候绘制对象会失败?分析原因:当向一个数据集上绘制几何对象出现画不上的问题,如果通过重新计算范围和重建空间索引不能解决问题,请检查一下该数据集的属性字段是否存在必填字段,而且该字段没有设置缺省值,这个就是问题所在。解决办法:新建字段,使用“更新列”将原始字段值复制过来;删除原有字段,重新建立一个同名字段并设置缺省值,再更新复制回该列的值,删除中间字段即可。再介绍一个制作一个快速的如Deskpro数据追加列的功能。*说明:A,B两个数据集,将A中存在而B中不存在的字段添加到B数据集中,然后根据公共字段值相等的字段值也添加到B中。Private Sub btnComfirm_Click() Dim setOK As Boolean Dim oRecF As soRecordset Dim oRecT As soRecordset Dim oDtF As soDatasetVector Dim oDtT As soDatasetVector Dim oFldsF As soFieldInfos Dim oFldsT As soFieldInfos Dim oFldInfo As soFieldInfo Dim oDss As soDataSources Dim UpID As Integer Dim crtFldOk As Boolean Dim i As Integer Dim j As Integer Dim m As Integer Dim a As Integer Dim n() As String Dim fldVF As String Dim fldVT As String Dim fldPub As String Dim StrSqlT As String Dim oErr As New soError On Error Resume Next Set oDss = FrmEnterMap.SuperWorkspace1.Datasources If oDss.Count = 0 Then Exit Sub Set oDtF = oDss.Item(Trim(cmbDsFrom.text).Datasets(Trim(cmbDtFrom.text) Set oDtT = oDss.Item(Trim(cmbDsTo.text).Datasets.Item(Trim(cmbDtTo.text) Set oRecF = oDtF.Query(, True, Nothing, )得到原数据集的记录集 Set oFldsF = oRecF.GetFieldInfos Set oRecT = oDtT.Query(, False, Nothing, )得到目标数据集的数据集,第二个参数为False,否则不能使用之后的FindFirst方法 Set oFldsT = oRecT.GetFieldInfos fldPub = Trim(cmbPubFlds.text) 返回公共字段不能为空 ReDim n(oFldsF.Count) Dim BfFldCount As Integer Dim FindOk As Boolean 返回FindFirst是否成功 BfFldCount = oRecF.FieldCount For i = 1 To oFldsF.Count先完成创建字段的功能 If oDtT.IsAvailableFieldName(oFldsF(i).name) Then条件为True则可以添加该字段 oDtT.ClearRecordsets crtFldOk = oDtT.CreateField(oFldsF(i) If crtFldOk=True Then n(a) = oFldsF(i).name用数据组记录下创建的字段名 a = a + 1 End If End If Next i Set oRecT = oDtT.Query(, False, Nothing, ) If BfFldCount = oRecT.FieldCount Then MsgBox oErr.LastErrorMsg Set oRecT = Nothing Set oRecF = Nothing Set oFldsF = Nothing Set oFldsT = Nothing Set oErr = Nothing Set oDtF = Nothing Set oDtT = Nothing Set oDss = Nothing Exit Sub Else oRecF.MoveFirst oRecT.MoveFirst For i = 1 To oRecF.RecordCount 以源数据集做循环 StrSqlT = fldPub & = & oRecF.GetFieldValue(fldPub)根据公共字段查询将游标移动到该位置 FindOk = oRecT.FindFirst(StrSqlT) If FindOk = True Then For m = 1 To a 循环添加的字段值 oRecT.Edit setOK = oRecT.SetFieldValue(n(m - 1), oRecF.GetFieldValue(n(m - 1) UpID = oRecT.Update Next m End If oRecF.MoveNext Next i End If Set oRecT = Nothing Set oRecF = Nothing Set oFldInfo = Nothing Set oFldsF = Nothing Set oFldsT = Nothing Set oErr = Nothing Set oDss = Nothing Set oDtF = Nothing Set oDtT = NothingEnd Sub这段代码测试22000多条记录添加4列属性,时间在1分钟左右。如果有更快更好的方法欢迎介绍一下。再介绍一个制作一个快速的如Deskpro数据追加列的功能。*说明:A,B两个数据集,将A中存在而B中不存在的字段添加到B数据集中,然后根据公共字段值相等的字段值也添加到B中。Private Sub btnComfirm_Click() Dim setOK As Boolean Dim oRecF As soRecordset Dim oRecT As soRecordset Dim oDtF As soDatasetVector Dim oDtT As soDatasetVector Dim oFldsF As soFieldInfos Dim oFldsT As soFieldInfos Dim oFldInfo As soFieldInfo Dim oDss As soDataSources Dim UpID As Integer Dim crtFldOk As Boolean Dim i As Integer Dim j As Integer Dim m As Integer Dim a As Integer Dim n() As String Dim fldVF As String Dim fldVT As String Dim fldPub As String Dim StrSqlT As String Dim oErr As New soError On Error Resume Next Set oDss = FrmEnterMap.SuperWorkspace1.Datasources If oDss.Count = 0 Then Exit Sub Set oDtF = oDss.Item(Trim(cmbDsFrom.text).Datasets(Trim(cmbDtFrom.text) Set oDtT = oDss.Item(Trim(cmbDsTo.text).Datasets.Item(Trim(cmbDtTo.text) Set oRecF = oDtF.Query(, True, Nothing, )得到原数据集的记录集 Set oFldsF = oRecF.GetFieldInfos Set oRecT = oDtT.Query(, False, Nothing, )得到目标数据集的数据集,第二个参数为False,否则不能使用之后的FindFirst方法 Set oFldsT = oRecT.GetFieldInfos fldPub = Trim(cmbPubFlds.text) 返回公共字段不能为空 ReDim n(oFldsF.Count) Dim BfFldCount As Integer Dim FindOk As Boolean 返回FindFirst是否成功 BfFldCount = oRecF.FieldCount For i = 1 To oFldsF.Count先完成创建字段的功能 If oDtT.IsAvailableFieldName(oFldsF(i).name) Then条件为True则可以添加该字段 oDtT.ClearRecordsets crtFldOk = oDtT.CreateField(oFldsF(i) If crtFldOk=True Then n(a) = oFldsF(i).name用数据组记录下创建的字段名 a = a + 1 End If End If Next i Set oRecT = oDtT.Query(, False, Nothing, ) If BfFldCount = oRecT.FieldCount Then MsgBox oErr.LastErrorMsg Set oRecT = Nothing Set oRecF = Nothing Set oFldsF = Nothing Set oFldsT = Nothing Set oErr = Nothing Set oDtF = Nothing Set oDtT = Nothing Set oDss = Nothing Exit Sub Else oRecF.MoveFirst oRecT.MoveFirst For i = 1 To oRecF.RecordCount 以源数据集做循环 StrSqlT = fldPub & = & oRecF.GetFieldValue(fldPub)根据公共字段查询将游标移动到该位置 FindOk = oRecT.FindFirst(StrSqlT) If FindOk = True Then For m = 1 To a 循环添加的字段值 oRecT.Edit setOK = oRecT.SetFieldValue(n(m - 1), oRecF.GetFieldValue(n(m - 1) UpID = oRecT.Update Next m End If oRecF.MoveNext Next i End If Set oRecT = Nothing Set oRecF = Nothing Set oFldInfo = Nothing Set oFldsF = Nothing Set oFldsT = Nothing Set oErr = Nothing Set oDss = Nothing Set oDtF = Nothing Set oDtT = NothingEnd Sub这段代码测试22000多条记录添加4列属性,时间在1分钟左右。如果有更快更好的方法欢迎介绍一下。当在第一个地图中只想对一定小范围内对空间对象做SQL条件查询,比如自定义圈定一个多边形范围内进行查询。可以使用QueryEx(geometry as soGeometry,nSpatialQueryModeas seSpatialQueryMode,strFilter as string)方法.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(index as VARIANT,.)这个索引问题。 如果选择使用整型索引,那么就要判断好数据引擎类型。因为同一属性字段数据库型要比文件型+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格式导入就可以了。效果是没有差别的。/archiver/?tid-956.html是对.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(objNetworkDataset As soDatasetVector,nNode As Long,nDirection As sePathFindingDirection,nLevel As Long) 方法求得起点的临近边。nNode:起始节点。nDirection:scdForward 只有正方向。nLevel:1因为只求直接相连的弧段。这样返回的是一个soSelection对象,下面要使用soRecordset soSelection.ToRecordset(false)得到记录集,soRecordset.GetFieldValue(SmTNode)得到这条弧段的SmTNode字段。这个字段就是终结点的ID。对记录集的每条记录循环,返回该字段值,与最开始确定的终结点ID比较。如果相等就说明从起点到终点间存在一条直通的弧段。那么这就是所需要的结果了,如果不存在再使用Path方法做路径分析就可以了。注意:soNetWorkAnalyst对象是属于SuperMap.ocx控件中,所以在使用时创建(New)一个该对象的实例就可以使用其中的方法了。最近比较忙没时间总结,昨天遇到了一个问题比较有意义。安装了oracle服务器端或者客户端的系统中后,就可以在Deskpro中建立,打开oracle数据源和工作空间。有时候发现虽然安装了oracle,并且启动了服务,但在Deskpro中oracle的图标还是不显示(5.2版本中是不显示,2008之后就是显示但是灰色的)。这个问题回想了一下发现一个问题,原因是这样的。之前安装了Java IDE,Eclipse。提示我的JDK版本过低,检查发现我的环境变量的Path中确实只有指向oracle 10g的1.4.2版本的jre的目录。为了重新设置更高版本的jdk,添加了1.5的目录在最前面,后来有些犯傻除了1.5的路径,其它的就都删掉了。其中包含了几个指向oracle的目录,这就是导致Deskpro不能识别Oracle类型的原因。解决办法很简单,添加了环境变量的Path中几个Oracle的目录D:Oracleproduct10.1.0Db_1BIN;D:Oracleproduct10.1.0Db_1jre1.4.2;D:Oracleproduct10.1.0Client_1bin;D:Oracleproduct10.1.0Db_1jdkjre之后问题解决了,Deskpro可以正常使用Oracle了。后来发现这样误操作对于Objects也有影响,不过没有确认,有兴趣的朋友可以自己测试一下。关闭数据源的问题。经常打开工作空间,打开地图之后会使用到关闭数据源的功能。在Deskpro里面处理很顺畅,使用Objects的接口也很简单,就是soDataSources.Remove(Index As VARIANT)。可是如果直接使用这个方法很可能就会报内存问题的错误,系统就会崩溃掉。这个问题的经常在于该数据源中的一些数据集已经打开在地图窗口中显示了。那么我们可以想象,只要在关闭数据源之前把所有的图层Layers移除掉不就可以了么。这样也是不行的,因为地图窗口的图层中很可能有很多,有的图层来自要关闭的数据源,有些则可能是其它数据源中的。这些其它数据源中保存的图层是不应该被移除的。那么好了,我们通过图层的名称判断(图层名是数据集名成+数据源别名组成的)所属的数据源是哪个,如果是要关闭的数据源那么就使用soLayers.RemoveAt(Index As VARIANT)方法移除该图层就可以了。但是问题出现了,当循环所有图层使用该方法移除图层之后,再移除数据源还是会崩溃,报错还是内存问题。这样就比较麻烦了,其实问题很简单。一般循环移除都会这样做:for (i = 1; i = objLayers.Count; i+)objLayer = objLayersi;if ()/数据源别名等于图层后面的数据源别名objLayers.RemoveAt(i);这样就是错误的,原因在于移除一个图层之后objLayers.Count就错了,就算换作不变的变量也是一样会错。解决这个问题有几种方法,给人建议可以使用一种比较清晰易懂的方法:首先定义一个soStrings对象:soStrings objStr = new soStringsClass();然后再第一个循环中不要移除而是将符合条件的图层名添加到objStr 中:for (i = 1; i = objLayers.Count; i+)objLayer = objLayersi;if ()/数据源别名等于图层后面的数据源别名objStr.Add(objLayer.Name);然后在根据objStr做循环for (int m = 1; m = objStr.Count;m+ ) objLayers.RemoveAt(objStrm);这样移除之后在关闭数据源就正常了。跟踪层修改对象。在5.2系列产品的SuperMap Objects中,如果使用到跟踪层并在跟踪层上绘制对象,有时会设计修改原有的对象的对象,风格等等。原来的方法比较麻烦,需要根据soGeoEvent的Tag找到跟踪层上的Event然后移除(Remove)掉,然后添加新的对象上去,当然Tag也要一致。在现在的2008中提供了一个新的接口,可以直接修改制定Tag的跟踪层上的几何对象。但是这个接口暂时还没有开放,只是作为一个隐藏接口,并且VC中可以看到,vb6是没有的。其它的环境还没有一一确认,也许CBuilder会有。总之使用这个接口就可以简单的实现替换跟踪层对象的功能。具体使用示例如下:之前添加了一个对象,它的Tag是1。替换的示例程序:CsoStyle objStyle;CsoTrackingLayer objtrl;CsoGeoLine objGeoL;CsoPoints objPts;objStyle.CreateDispatch(supermap.sostyle);objStyle.SetPenStyle(4);objStyle.SetPenColor(RGB(255,0,0);objStyle.SetPenWidth(100);objPts.CreateDispatch(supermap.soPoints);objPts.Add2(m_SuperMap.GetCenterX(),m_SuperMap.GetCenterY()+500000);objPts.Add2(m_SuperMap.GetCenterX(),m_SuperMap.GetCenterY()-500000);objGeoL.CreateDispatch(supermap.soGeoLine);objGeoL.AddPart(objPts);objGeoL.SetStyle(objStyle);/如果需要替换的对象风格和原来被替换的风格一样需要在这里设置一下,如果不设置风格会是默认的风格,当然需要其它风格也要在这里设置。objtrl=m_SuperMap.GetTrackingLayer();objtrl.SetRefEvent(COleVariant(1),objGeoL);/就是这个接口,第一个参数是要替换的Event的Tag,第二个参数是用来替换的几何对象。m_SuperMap.GetTrackingLayer().*();objStyle.ReleaseDispatch();objtrl.ReleaseDispatch();objGeoL.ReleaseDispatch();objPts.ReleaseDispatch();好久没有来更新了,非常不好意思。今天同事处理了一个数据,使用到了SuperMap Deskpro 2008(5.3.2)最新版本,的新功能,在此和大家分享下。需求:数据处理,两个数据集,一个点,一个道路线,所有点有的在线上,有的不在线上。用户需要将点数据集中所有在线数据集线上点提取出来,保存为一个新的数据集。解决办法: 这个思路同样也适用于开发。首先使用新功能数据集拓扑检查,查询点,规则是点必须在线上。这个功能在Objects的对象是soTopoCheck.CheckTopoError()。 检查结果是一个纯属性表,将其中的ErrorObjectID_1(属性表中记录查询数据集中不符合规则的对象ID,也就是点不在线上的。)字段追加到点数据集中,关联字段是点数据集的smid和属性数据集的ErrorObjectID_1。这样点数据集中ErrorObjectID_1字段值为空的记录即为点在线上的记录,另存为数据集就完成了。 如果用程序实现也没有必要追加列,直接优化一个循环把点数据集中smid和属性表中ErrorObjectID_1字段值相同的记录删了就可以了。 PS:个人感觉用Deskpor更方便,不过追加列,本主题其它楼我也介绍了优化的算法,会比Deskpro快。不过新版的Deskpro算法是否修改了,还没有验证过,有兴趣的可以比较下,呵呵。问题: 最近处理了一个问题,关于对大数据量的数据集进行裁剪,裁剪结果还要导出为DXF的功能,搞得比较麻烦。具体情况是这样的:用户的数据集比例尺较大,每个图层基本上都上万条记录,有的有好几万条。这样组成的地图,一个功能就是要将拉框范围内的每层数据导出为一个DXF,这样当然还要合并图层。客户思路: 一开始的思路,客户选择了使用soOverLayAnalyst.Clip(objInDataset As soDatasetVector,objClipItem As Object,objOutDataset As soDatasetVector)方法对每个数据集进行裁剪,结果数据集objOutDataset 是创建的一个复合CAD数据集,这样循环裁剪后的记录全部追加到了这个结果中去了。 但是奇怪的是用户的环境下裁剪几个数据集后就报内存读写错误的问题了,这样的错误一般是对象太复杂,记录太多造成的。当然也和数据库、操作系统、机器硬件有直接的关系。 通过多方测试也没有重现这个问题,可能是我得机器比较稳定吧。T61P AK1,2G内存,T7500。不能重现就不能解决问题。所以灵机一动想到了一个绕过去的方法。解决方法: 拉框后用这个面对每个图层做范围查询,查询得到的记录集直接追加到事先创建好的复合数据集中去(Append),最后再将这个复合数据集导出为DXF就可以了。这样做的最大好处就是快,大家知道范围查询比起裁剪来讲空间运算的效率要高很多了。很简单问题就解决了,如果对于结果数据边界的地方要严格属于框内,也就是要以框为严格边界,那么再用这个框对结果复合数据集做裁剪就可以了,这样数据量小,裁得也就更快了!建议: 建议今后有想对大数据量数据集做裁剪的朋友,

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论