http://www.gissky.net- GIS空间站

我要投稿 投稿指南 RSS订阅 网站资讯通告:
搜索: 您现在的位置: GIS空间站 >> 技术专栏 >> ArcGIS >> ArcGIS入门与应用 >> 正文

ArcGIS中的线性参考/动态分段技术

作者:diligent…    文章来源:ESRI    点击数:    更新时间:2009-12-15
摘要:Linear Referencing翻译过来是线性参考,在公路,管网等行业的GIS应用中时常提到。LR是一种利用沿着可测量的线要素的相对方位来存储地理位置的方法。


以上所有具体操作可参考桌面帮助中的内容,如果安装了ArcTutor,还会有Linear Referencing Tutorial的PDF可供学习。

首先来思考几个LinearReferencing的应用场景(后面会对这些场景一一实现):
1、对于某条公路上的一点进行Identify操作,要求返回该点处在公路上的里程值;
2、输入起始和终止桩号,要求将其间的路段显示在地图上;
3、类似GoogleMap的交通流量地图。
要将这些功能在ArcGISServer中“落地”,首先决定采用哪种开发方式:客户端API还是Web ADF?两者皆可。但是稍加思考,两种方式的API中都没有提供有关Linear Referencing的解决办法。所以,Linear ReferencingArcGIS Server中的实现原理还是得依靠ArcObjects了。
ArcObjects中,Linear Referencing的功能在ESRI.ArcGIS.Location库中,请见:http://resources.esri.com/help/9.3/ArcGISEngine/dotnet/10745641-b5e3-4600-979f-cdf9d2bbc7ce.htm#About%20linear%20referencing
为了实现上述功能,其中比较关键的有两个类:RouteLocatorRouteEventSourceRouteLocatorIRouteLocator2接口有IdentifyLocate两个方法,前者可根据地理坐标识别出Route上的位置(M值);后者可根据M值来定位出Route上相应的Geometry。如果已有EventTable,需要对上面的每个Event进行定位,除了重复使用IRouteLocator2.Locate方法(或者LocateRow方法)外,也可通过构建RouteEventSource来实现。它是一种特殊的FeatureClass(继承自FeatureClass),其中的每个Feature代表了EventTable中的一个Event,而这个FeatureShape字段内容则是根据EventTableRoute
FeatureClass,利用Dynamic
Segmentation技术实时计算出来的。
关于如何获得可用的IRouteLocator2接口和RouteEventSource,文档中已经讲的很清楚;另外ESRI.ArcGIS.Location中还提供了实现ArcMapLinearReferencing里所有功能的接口,有兴趣的朋友可以仔细阅读。

现在来实现上面提到的3个功能。
1、对于某条公路上的一点进行Identify操作,要求返回该点在公路上的桩号值:
以Silverlight API为例。为了在服务器端使用ArcObjects,在Asp.net工程中添加一个名为LinearRef的Silverlight-Enabled WCF Service,在LinearRef.svc.cs文件中添加以下代码:

  1. namespace RoadDycSeg.Web.WCF
  2. {
  3.     [ServiceContract(Namespace = "")]
  4.     [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
  5.     public class LinearRef
  6.     {
  7.         public IRouteLocator2 pRtLocator = null;
  8.         ESRI.ArcGIS.Server.IServerObjectManager pSOM = null;
  9.         public ESRI.ArcGIS.Server.IServerContext pServerContext = null;

  10.         public LinearRef()
  11.         {
  12.             ESRI.ArcGIS.ADF.Identity identity = new ESRI.ArcGIS.ADF.Identity("ArcGISWebServices", "yourpassword", "");
  13.             ESRI.ArcGIS.ADF.Connection.AGS.AGSServerConnection agsconn = new ESRI.ArcGIS.ADF.Connection.AGS.AGSServerConnection("localhost", identity);
  14.             agsconn.Connect();
  15.             pSOM = agsconn.ServerObjectManager;
  16.             pServerContext = pSOM.CreateServerContext("shaanxi", "MapServer");
  17.             ESRI.ArcGIS.Carto.IMapServer2 pMapServer = pServerContext.ServerObject as ESRI.ArcGIS.Carto.IMapServer2;
  18.             ESRI.ArcGIS.Carto.IMapServerObjects2 pMapServerObjects = pMapServer as ESRI.ArcGIS.Carto.IMapServerObjects2;
  19.             ESRI.ArcGIS.Carto.IMap pMap = pMapServerObjects.get_Map(pMapServer.DefaultMapName);
  20.             IFeatureClass pFC = (pMap.get_Layer(2) as ESRI.ArcGIS.Carto.IFeatureLayer).FeatureClass;

  21.             //create the RouteLocator
  22.             IDataset dS = (IDataset)pFC; // A polylineM feature class.
  23.             IName name = dS.FullName;
  24.             IRouteLocatorName rtLocatorName = pServerContext.CreateObject("esriLocation.RouteMeasureLocatorName") as IRouteLocatorName;
  25.             rtLocatorName.RouteFeatureClassName = name;
  26.             rtLocatorName.RouteIDFieldName = "道路编码";
  27.             rtLocatorName.RouteMeasureUnit = esriUnits.esriUnknownUnits;
  28.             name = (IName)rtLocatorName;
  29.             pRtLocator = (IRouteLocator2)name.Open();

  30.             pServerContext.ReleaseContext();
  31.         }

  32. // Add more operations here and mark them with [OperationContract]

  33.         [OperationContract]
  34.         /// <summary>
  35.         /// used by the client Identify operation and return the result
  36.         /// </summary>
  37.         /// <param name="mapX">the x coords of the mouseclick in map units</param>
  38.         /// <param name="mapY">the y coords of the mouseclick in map units</param>
  39.         /// <param name="resolution">the map distance of 1 pixel</param>
  40.         /// <returns>a identifyresult class defined in Classes.cs. If no result, mvalue=x=y=-1</returns>
  41.         public IdentifyResult Identify(double mapX, double mapY, double resolution)
  42.         {
  43.             pServerContext = pSOM.CreateServerContext("shaanxi", "MapServer");

  44.             IdentifyResult ir = new IdentifyResult("", -1, -1, -1);

  45.             IPoint pPoint = pServerContext.CreateObject("esriGeometry.Point") as IPoint;
  46.             pPoint.PutCoords(mapX, mapY);
  47.             IEnvelope pEnvelope = pPoint.Envelope;
  48.             pEnvelope.Expand(10 * resolution, 10 * resolution, false);

  49.             IEnumRouteIdentifyResult pEnumResult = pRtLocator.Identify(pEnvelope, "");
  50.             pEnumResult.Reset();
  51.             //only get the first result
  52.             if (pEnumResult.Count > 0)
  53.             {
  54.                 IRouteLocation pRL = null;
  55.                 IFeature pF = null;
  56.                 pEnumResult.Next(out pRL, out pF);
  57.                 IRouteMeasurePointLocation pRMPL = pRL as IRouteMeasurePointLocation;

  58.                 //retrieve the location geometry by calling LOCATE method
  59.                 IRouteLocation routeLocation = pServerContext.CreateObject("esriLocation.RouteMeasurePointLocation") as IRouteLocation;
  60.                 routeLocation.MeasureUnit = esriUnits.esriUnknownUnits;
  61.                 routeLocation.RouteID = pRL.RouteID;
  62.                 routeLocation.LateralOffset = 0;
  63.                 IRouteMeasurePointLocation rMPointLoc = (IRouteMeasurePointLocation)routeLocation;
  64.                 rMPointLoc.Measure = pRMPL.Measure;

  65.                 IGeometry geom;
  66.                 esriLocatingError locError;
  67.                 pRtLocator.Locate((IRouteLocation)rMPointLoc, out geom, out locError);

  68.                 ir.RouteID = pRL.RouteID.ToString();
  69.                 ir.MValue = pRMPL.Measure;
  70.                 ir.X = (geom as IPointCollection5).get_Point(0).X;
  71.                 ir.Y = (geom as IPointCollection5).get_Point(0).Y;
  72.             }

  73.             pServerContext.ReleaseContext();

  74.             return ir;
  75.         }

其中,IdentifyResult是自定义的一个类,用来存储查询的结果:

  1. namespace RoadDycSeg.Web.WCF
  2. {
  3.     /// <summary>
  4.     /// the result of Identify operation
  5.     /// </summary>
  6.     [DataContract]
  7.     public class IdentifyResult
  8.     {
  9.         [DataMember]
  10.         public string RouteID {get;set;}
  11.         [DataMember]
  12.         public double MValue {get;set;}
  13.         [DataMember]
  14.         public double X {get;set;}
  15.         [DataMember]
  16.         public double Y {get;set;}

  17.         public IdentifyResult(string routeid, double mvalue, double x, double y)
  18.         {
  19.             RouteID = routeid;
  20.             MValue = mvalue;
  21.             X = x;
  22.             Y = y;
  23.         }
  24.     }
  25. }

Identify方法需要传入3个参数,一个点的地理坐标以及当前地图的Resolution,后者用来生成一个10像素的缓冲区,方便用户的点击操作;其中利用IRouteLocator2.Identify方法获得M值,据此利用 IRouteLocator2.Locate方法获得精确落在公路上的点的Geometry,用以显示在客户端;如果用户点击的点距离公路较远,则IRouteLocator2.Identify结果为空,返回的IdentifyResult中M值为-1。
在Silverlight工程中,Add Service Reference,找到刚才的LinearRef服务,取名为LRService。
客户端中,新建一个COperation类,实现业务操作。

  1. public class COperation
  2. {
  3. private LRService.LinearRefClient LR = null;
  4.         private GraphicsLayer glayer = null;
  5.         private bool isBusy = false;//indicate whether there is an operation is performing
  6.         private Map Map1 = null;
  7.         public COperation(Map map)
  8.         {
  9.             Map1=map;
  10.             glayer = Map1.Layers["glayer"] as GraphicsLayer;
  11.             //initialize the LR object
  12.             LR = new RoadDycSeg.LRService.LinearRefClient();
  13.             LR.IdentifyCompleted += new EventHandler<RoadDycSeg.LRService.IdentifyCompletedEventArgs>(LR_IdentifyCompleted);
  14.         }
  15.         private void LR_IdentifyCompleted(object sender, LRService.IdentifyCompletedEventArgs e)
  16.         {
  17.             LRService.IdentifyResult ir = e.Result;
  18.             //add a point graphic to the map with attributes displaying by the maptip, maptip defined in mainpage.xaml
  19.             if (ir.X > 0)//the result exists
  20.             {
  21.                 Graphic g = new Graphic()
  22.                 {
  23.                     Geometry = new MapPoint(ir.X, ir.Y),
  24.                     Symbol = Application.Current.Resources["strobeSymbol"] as Symbol,
  25.                 };
  26.                 g.Attributes.Add("RouteID", ir.RouteID);
  27.                 g.Attributes.Add("桩号", ir.MValue);
  28.                 g.Attributes.Add("X坐标", ir.X);
  29.                 g.Attributes.Add("Y坐标", ir.Y);
  30.                 glayer.Graphics.Clear();
  31.                 glayer.Graphics.Add(g);
  32.             }
  33.             isBusy = false;
  34.         }
  35.         
  36.         private void Map1_Identify(object sender, ESRI.ArcGIS.Client.Map.MouseEventArgs e)
  37.         {
  38.             if (!isBusy)
  39.             {
  40.                 LR.IdentifyAsync(e.MapPoint.X, e.MapPoint.Y, Map1.Resolution);
  41.                 isBusy = true;
  42.             }
  43.         }

在需要使用Identify功能时,将Map控件的Click事件绑定到Map1_Identify即可。

上一页  [1] [2] [3] 下一页

Tags:ArcGIS,线性参考  
责任编辑:gissky
关于我们 - 联系我们 - 广告服务 - 友情链接 - 网站地图 - 中国地图