接边算法研究2

Posted by 蒋波涛 10 December,2006 Views (38)Comment

在上一篇blog中,我介绍了如何将一个集合中的对象进行两两比较的方法,实际上,对于选择集中的要素,并非使用的是for语句,而是do...loop语句来完成的,我们需要分别获得两个指向要素选择集中所有要素的FeatureCursor,然后做嵌套的do...loop运算。但其实质却是与for语句是一样的,如:
pCurFeat=pCurFeatCursor.NextFeature
pConFeat=pConFeatCursor.NextFeature
do while not pCurFeat is Nothing
       do while not pConFeat Is Nothing
             if pCurFeat.oid=pConFeat.oid then goto e1
                    <进行要素对判断>
e1:
             pConFeat=pConFeatCursor.NextFeature     
       Loop
       pCurFeat=pCurFeatCursor.NextFeature
Loop

好了,我们下面来讨论第二个问题,即限制条件的设置,如何设置必要的限制条件以得到符合条件的“要素对”。

第一个条件是当前要素必须是我们做接边运算的当前项目中的要素,这个限制条件看起来很简单,但却可以在后面省略掉一个耗时的处理运算。举一个例子,如果有1,2,3三个要素进行两两比较,则一共需要进行6次,且这6次中有3次的效果是重复的,即寻找到的1-2和2-1的要素对信息是一样的,我们还得花气力把这6次信息进行过滤,删掉重复的信息。但如果在取信息的时候就限制在当前项目中,如1属于当前项目,2和3都是别的项目的要素,它们将与当前项目要素进行接边,那么我们就可以直接得到1-2,1-3两个要素对的信息了。

第二个条件是两个要素的距离小于或等于容差,如何用AO实现这个条件,其实也是非常简单的。还记得IProximityOperator.ReturnDistance方法吗,它可以返回任意两个geometry对象之间的距离,使用这个方法即可以设置这个限制条件。

我们要求接边的对象肯定是处于更新线两边的不同项目或不同图幅的要素,这也是个限制条件。

Related Items

Categories : ArcObjects Tags :
Comments
2006-12-10 19:06:16

你好,我买了你的书,很有用!
我想请教个问题,在c#里用AE做Identify对话框,可有完整思路?我被卡住了。。

Jack 于 2009-10-23 8:32:00 回复
蒋老师,您好,您的算法,我学习了,是可以实现,但效率很低。可以考虑空间查询的方法。提高效率

Posted by 433 Gravatar Icon

2006-12-10 21:10:40

找我以前的帖子

Posted by 蒋波涛 Gravatar Icon

2006-12-11 0:29:14

不行,我就是参照你的代码,翻译成c#出问题:

for(nField=0;nField<=FieldCount - 1;nField++)
{
al_fieldname[nField] = pFeat.Fields.get_Field(nField).Name;

//这个正常

if(pFeat.Fields.get_Field(nField).Name!="Shape")
{

if(pFeat.get_Value(nField).ToString()!="")

MessageBox.Show(pFeat.get_Value(nField).ToString());
//取不到值,总是null

else
al_fieldvalue[nField] = "<NULL>";

}
。。。。。。。。

Posted by 433 Gravatar Icon

2006-12-11 0:30:37

可否把我的工程让您给改改呢?我可通过邮件发过去。。

Posted by 433 Gravatar Icon

2006-12-11 9:40:56

pFeat.Fields.get_Field(nField).Name!="Shape"
改为
pFeat.Fields.get_Field(nField).Name!=pFeatClass.ShapeFieldName
试试看。另外我不太清楚你的表结构和表中是否有数据。

Posted by 蒋波涛 Gravatar Icon

2006-12-11 12:37:51

你好。问题好象解决了,是这样的:

在你的代码里,vb好象不用转换类型?但c#必须转换类型,我先是这样强制转换:

pFeatureLayer = (IFeatureLayer)this.axMapControl1.Map.get_Layer(0);

后来改成这样:

pFeatureLayer = this.axMapControl1.Map.get_Layer(0) as IFeatureLayer;

好象就可以了。

这两种方式有什么区别吗?

另外,显示的时候怎么区别要素的主键是哪个啊?比如lake图层的主键应该是Name吧,这个主键是shp文件里已经定义的吧?

谢谢!

Posted by 433 Gravatar Icon

2006-12-12 0:07:41

以下代码:

pixelExtent =

pActiveView.ScreenDisplay.DisplayTransformation.DeviceFrame.right -

pActiveView.ScreenDisplay.DisplayTransformation.DeviceFrame.left;



出错为:

属性、索引器或事件“DeviceFrame”不受该语言支持;请尝试直接调用访问器方法“

ESRI.ArcGIS.Display.IDisplayTransformation.get_DeviceFrame()”或“

ESRI.ArcGIS.Display.IDisplayTransformation.set_DeviceFrame(ref

ESRI.ArcGIS.Display.tagRECT)”



但get_DeviceFrame在c#好象并不存在,如何解决这问题呢?您一定要帮帮我!

Posted by 433 Gravatar Icon

2006-12-12 0:08:34

以下代码:

pixelExtent =

pActiveView.ScreenDisplay.DisplayTransformation.DeviceFrame.right -

pActiveView.ScreenDisplay.DisplayTransformation.DeviceFrame.left;



出错为:

属性、索引器或事件“DeviceFrame”不受该语言支持;请尝试直接调用访问器方法“

ESRI.ArcGIS.Display.IDisplayTransformation.get_DeviceFrame()”或“

ESRI.ArcGIS.Display.IDisplayTransformation.set_DeviceFrame(ref

ESRI.ArcGIS.Display.tagRECT)”


但get_DeviceFrame在c#好象并不存在,如何解决这问题呢?请您一定帮帮我!

Posted by 433 Gravatar Icon

2006-12-12 12:08:17

不用这么麻烦,如果你使用控件的话,直接用MapX和MapY属性好了。

Posted by 蒋波涛 Gravatar Icon

2006-12-14 14:15:16

您好,有个问题想请教一下:
我想把从SDE查询的要素类添加到MapControl上,ipFeatureClass->Search(ipFilter, VARIANT_TRUE, &ipFeatureCursor);
不知道怎么由IFeatureCursor生成IFeatureClass或IFeatureLayer?
MapControl.AddLayer(FeatureLayer);
能帮帮我吗?

Posted by 小熊 Gravatar Icon

2006-12-14 16:57:24

你取错了,游标是用来取单个要素的,没法指回到要素类或图层上去.你的问题,在Exploring ArcObjects一书第一章就可以找到答案.即如何把一个要素类取出,新建一个关联图层并添加到控件中.

Posted by 蒋波涛 Gravatar Icon

2006-12-14 17:26:26

pFeatCursor = pFeatureClass.Search(pSpatialFilter,false);

IFeature pFeat;

pFeat = pFeatCursor.NextFeature();

----------------------------------------------------------
这样完了后,如何把pFeat倒到某一类型X,使得当前的对象

X.name和X.flash属性都可用呢?

Posted by 433 Gravatar Icon

2006-12-14 17:27:41

我的意思是:我不知道怎么关联当前cursor的featureobj对象

Posted by 433 Gravatar Icon

2006-12-14 20:17:26

只能从一个Feature找到它的要素类.IFeature.Class即可以.

Posted by 蒋波涛 Gravatar Icon

2006-12-14 21:07:45

是这样的,在您的书中有个例子:
pFeaIdObj = pIarray.get_Element(0) as IFeatureIdentifyObj;

pIdObj = pFeaIdObj as IIdentifyObj;

pIdObj.Flash(this.axMapControl1.ActiveView.ScreenDisplay);

现在我要用pIdObj的flash和name属性但转不过去:

IFeature pFeat;
pFeat = pFeatCursor.NextFeature();

IIdentifyObj pIdentifyObj;
IFeatureIdentifyObj pFeatureIdentifyObj;

pFeatureIdentifyObj = pFeat as IFeatureIdentifyObj;

pIdentifyObj = pFeatureIdentifyObj as IIdentifyObj;

请问具体如何写代码?谢谢您!

Posted by 433 Gravatar Icon

2006-12-14 21:11:12

如果转换不过去,我还有什么办法来获得数据表中的主键吗?我要用来作为要素的标志。我不知道是否有这个概念。。

Posted by 433 Gravatar Icon

2006-12-15 9:03:34

我大概看了一下Exploring ArcObjects,没有找到啊。能不能给我说一下大概思路?
我想把FeatureClass执行空间查询的结果生成FeatureLayer并添加到MapControl中。

Posted by 小熊 Gravatar Icon

2006-12-15 16:09:56

第一章最后一页的代码.另外,如果你想执行查询后返回结果,并不一定需要通过要素类进行,IGeoFeatureLayer接口也可以办到.

Posted by 蒋波涛 Gravatar Icon

2006-12-15 16:11:26

443,一个要素类的主键是OID字段.获取的方法是IFeatureClass.OID

Posted by 蒋波涛 Gravatar Icon

2006-12-15 16:21:56

真的没办法转过去吗?

arcmap里它的identifydialog里的左边树视图里取得的要素的名字,不是OID,它是怎么取的?

点选法只有缓冲一条路吗?有没有方法接受容差再象iidentify接口那样选的?

Posted by 433 Gravatar Icon

2006-12-16 9:38:02

最后一页的代码是讲怎么把FeauteClass关联到FeatureLayer,然后添加到MapControl,这个我知道。我要做的程序是:用户在MapControl中框选一个区域,我用SpatialFilter在SDE的FeatureClass中做空间查询,然后把范围内的实体显示到MapControl中。

Posted by 小熊 Gravatar Icon

2006-12-16 9:49:32

目前我的做法是:
先在FeatureClass中查询满足条件的所有ObjectID,然后构造IQueryDef,重新在FeatureClass中用IFeatureWorkspace.OpenFeatureQuery得到一个FeatureClass,最后由得到的FeatureClass生成Featurelayer加载进来。这样的话,我得在同一个FeaureClass中查询两遍,速度非常慢。代码如下:

Posted by 小熊 Gravatar Icon

2006-12-16 9:52:25

IGeometryPtr ipGeo;//用户框选的区域
IFeatureClassPtr ipFC;//SDE的要素类
ipFeatureWS->OpenFeatureClass(FeatureName, &ipFC);
IFeatureCursorPtr ipFCursor;
ISpatialFilterPtr ipFilter(CLSID_SpatialFilter);
ipFilter->put_SpatialRel(esriSpatialRelEnvelopeIntersects);
ipFilter->putref_Geometry(ipGeo);
ipFC->Search(ipFilter, VARIANT_TRUE, &ipFCursor);
ipFCursor->NextFeature(&ipFeature);
TArrLong idArr;//所有查询到的ObjectID
while (ipFeature)
{
IRowBufferPtr ipRow(ipFeature);
ipRow->get_Value(0, &var);
idArr.Add(var.lVal);
ipFCursor->NextFeature(&ipFeature);
}

Posted by 小熊 Gravatar Icon

2006-12-16 9:52:43

IQueryDefPtr ipQuery;
IFeatureDatasetPtr ipFD;
IFeatureClassContainerPtr ipFCC;
ipFeatureWS->CreateQueryDef(&ipQuery);
ipQuery->put_Tables(FeatureName);
//用IdArr生成WhereClause,略
ipQuery->put_WhereClause(strWhere);
ipFeatureWS->OpenFeatureQuery(FeatureName, ipQuery, &ipFD);
ipFCC = ipFD;
ipFCC->get_Class(0, &ipFC);
//添加到MapControl中
IFeatureLayerPtr ipFL(CLSID_FeatureLayer);
ipFL->putref_FeatureClass(ipFC);
ipFL->put_Name(strLayer);
ILayerPtr ipLayer(ipFL);
MapControl.AddLayer(ipLayer, 0);

Posted by 小熊 Gravatar Icon

2006-12-16 9:55:44

IFeatureWorkspace::OpenFeatureQuery没法执行空间查询,只能按属性查询,有没有什么办法只查询一次就可以添加到MapControl中?

Posted by 小熊 Gravatar Icon

2006-12-16 14:08:33

IMap.ClipGeometry 。用这个看看

Posted by 蒋波涛 Gravatar Icon

2006-12-17 14:19:42

如果是先把SDE的FeatureClass添加到控件中,然后在剪切,这样的话速度会更慢。我的一个FeatureClass有100万条记录

Posted by 小熊 Gravatar Icon

2006-12-17 17:52:21

在控件中只放置一个最大范围的图层,然后在后台对要素类进行裁减,再将裁减后的要素类放到一个临时库中显示出来。

Posted by 蒋波涛 Gravatar Icon

2007-1-17 16:03:28

怎末可以买到你的书?

Posted by 宽一 Gravatar Icon

2007-5-28 18:16:40

10楼小熊提的问题我也遇到了,就是空间查询结果显示在MapControl中,我用的是map.ClipGeometry,非常慢! 请问有没有解决方案, 谢谢!

Posted by jiangying Gravatar Icon

2007-6-3 16:24:20

不要使用ClipGeometry的方法,而是自己处理,要素分为两种情况:
1.点要素类和标注要素类,由于其Geometry是Point,故而指需要寻找裁剪多边形内部的要素
2.线要素类和面要素类除了要处理多边形内部的要素外,还需要处理在多边形边界上的要素,这个时候要使用ITopologicalOperator接口的方法,将本身的Geometry进行处理,如只删除与裁剪多边形相交的部分。

Posted by 蒋波涛 Gravatar Icon


2007-8-18 16:49:25

你好,我想买你的那本书,昨天在光谷书城没有找到哦

Posted by liddy Gravatar Icon

2007-8-20 16:42:04

您好,我想看看你开放的实例框架程序,在你给的下载地址里下载不了,请麻烦传给我一份好么,frq0224@163.com.

Posted by 你好 Gravatar Icon

2007-8-21 15:26:06

这个东西没有了,我没有继续写它,在做另一个插件式的框架。

Posted by 蒋波涛 Gravatar Icon

2007-8-22 13:20:43

小气

Posted by frq Gravatar Icon

2007-8-23 14:01:59

你不相信我也没办法。你只要注意几个事实就明白了,一是这个程序使用了第三方界面控件,使得程序发布很困难;二是坐标转换使用的dll是需要保密的;第三是这个程序的成型时间是一年前。

Posted by 蒋波涛 Gravatar Icon

2007-8-23 14:12:44

算了,我脸皮也没那么厚,我也实验过了用第三方控件,发布还是相当的容易(我编写的直接拷贝到另一台就可以直接用,不用安装和注册),你应该算是arcgis的高手了,有些走在前沿的东西给大家分享分享,没人抢你的饭碗!

Posted by frq Gravatar Icon

Leave a comment

Or, take a look at Archives and Categories

目录

存档