ArcGIS API for Silverlight 使用GeometryService求解线与线的交点(二)

ArcGIS API for Silverlight 使用GeometryService求解线与线的交点(二),第1张

概述在前一篇的博文中说到了线与面交点求解,其中使用的方法是利用GeometryService的Simplify+Intersect服务,通过获得线与面的交点,间接的通过交线的端点得到线与面的交点。过程如下所示: 然而在上文中我们提到过一句,Geometry中的Intersect无法得到线与线的交点,尽管当我们使用Intersect求线与线相交时,可以返回相交的结果,但是无法获取交点,因为Inters

在前一篇的博文中说到了线与面交点的求解,其中使用的方法是利用GeometryService的Simplify+Intersect服务,通过获得线与面的交点,间接的通过交线的端点得到线与面的交点。过程如下所示:

然而在上文中我们提到过一句,Geometry中的Intersect无法得到线与线的交点,尽管当我们使用Intersect求线与线相交时,可以返回相交的结果,但是无法获取交点,因为Intersect求线与线交点返回的是一个Extent为null的线要素,我们无法将其用点在地图上表达出来。

那么这里我们该怎么做呢?

这里我们用到了Geometry的另一个服务:TrimExtend(修剪扩展)

具体示例可参考:

http://help.arcgis.com/en/webapi/silverlight/samples/start.htm#TrimExtend

关于TrimExtend功能的效果图:

我们发现,使用TrimExtend之后网格水平线向右方向进行了衍生,并与线要素相交了,而位于河流下方的网格则被剪切掉了。

关于裁剪和延伸的方向(比如上图是向右延伸,还可以设置向左延伸,或者双向延伸等),可以通过CurveExtension属性来设置,关于CurveExtension的属性说明参看官方文档:

http://help.arcgis.com/en/webapi/silverlight/apiref/api_start.htm

需要说明的是,TrimExtend返回的结果是线要素,而返回线要素的一端就是线要素与线要素的交点(仅当线要素相交时,从上图我们会发现没有相交的要素也被返回了,因此这里还需要进一步的筛选,具体将在后面说明)

通过以上分析,我们知道只要获取返回线要素的端点就可以得到相交的结果。

下面是具体步骤:

1.构建网格(这里也可以使用某一图层的线要素,本文采用自己构建网格,求网格与线要素相交的节点)

关键代码:

a.根据两个点构造一条直线

   public voID Createline(MapPoint p1,MapPoint p2)          {              ESRI.ArcGIS.ClIEnt.Geometry.polyline polyline = new ESRI.ArcGIS.ClIEnt.Geometry.polyline();              ESRI.ArcGIS.ClIEnt.Geometry.PointCollection pc=new ESRI.ArcGIS.ClIEnt.Geometry.PointCollection ();              pc.Add(p1);              pc.Add(p2);              polyline.Paths.Add(pc);              //记得对空间坐标系赋值,否则Simplify会出错。              polyline.SpatialReference = map1.SpatialReference;              AddlineGraphic(polyline);            }

AddlineGraphic为自定义方法,作用是将线要素添加到图层中,示例代码如下:

  public voID AddlineGraphic(ESRI.ArcGIS.ClIEnt.Geometry.polyline polyline)          {              Graphic g = new Graphic()              {                  Geometry = polyline,Symbol = LayoutRoot.Resources["linesymbol"] as Simplelinesymbol              };                          glayer.Graphics.Add(g);          }

这里用户可以自定义网格的步长,根据绘制的矩形或多边形范围构建网格。

   public voID CreateGrID(double xMin,double xMax,double yMin,double yMax,double xstep,double ystep)          {              //定义两个Point,确定一条直线              MapPoint mp1;              MapPoint mp2;              //由步长确定划分成多少份              int Nx = Convert.ToInt32((xMax - xMin)/xstep);              int Ny = Convert.ToInt32((yMax - yMin) / ystep);              //构造竖直方向的线              for (int i = 0; i <Nx+1; i++)              {                  mp1=CreateMapPoint(xMin+i*xstep,yMin);                  //mp2=CreateMapPoint(xMin + i * xstep,yMax);                  mp2 = CreateMapPoint(xMin + i * xstep,yMin + Ny * ystep);                  Createline(mp1,mp2);              }              //构造水平方向的线              for (int i = 0; i < Ny+1; i++)              {                  mp1 = CreateMapPoint(xMin,yMin +i * ystep);                  mp2 = CreateMapPoint(xMin + Nx * xstep,yMin + i * ystep);                  //mp2 = CreateMapPoint(xMax,yMin + i * ystep);                  Createline(mp1,mp2);              }              //RectExtent为自定义的一种结构体,存储每一次网格划分时的矩形范围              recExtent = new RectExtent()              {                  Xmin = Convert.Todouble((xMin).ToString("#0.000")),Xmax = Convert.Todouble((xMin + Nx * xstep).ToString("#0.000")),Ymin = Convert.Todouble((yMin).ToString("#0.000")),Ymax = Convert.Todouble((yMin + Ny * ystep).ToString("#0.000"))              };          }       

效果示意图:

下面就通过TrimExtend服务来实现获取交点的功能

2.调用TrimExtend功能

private voID intersectCenterlinebutton_Click(object sender,RoutedEventArgs e)          {              //存储线要素的集合              List<ESRI.ArcGIS.ClIEnt.Geometry.polyline> polylineListGrID = new List<ESRI.ArcGIS.ClIEnt.Geometry.polyline>();              List<ESRI.ArcGIS.ClIEnt.Geometry.polyline> polylineListriver = new List<ESRI.ArcGIS.ClIEnt.Geometry.polyline>();                if (glayer.Graphics.Count == 0 || flayer.Graphics.Count == 0)              {                  MessageBox.Show("请确认输入的线要素不为空");                  return;              }              //遍历图层的线要素              foreach (Graphic g in glayer.Graphics)              {                  polylineListGrID.Add(g.Geometry as ESRI.ArcGIS.ClIEnt.Geometry.polyline);              }                            foreach (Graphic g in flayer.Graphics)              {                  polylineListriver.Add(g.Geometry as ESRI.ArcGIS.ClIEnt.Geometry.polyline);              }              /*************************************               * 被相交的图层(在本文中只有一个要素,所以索引为0)               * 第一个参数表示相交的要素,例如网格,因此是一个集合               * 第二个参数表示被相交的要素,例如一条河流,因此是一个线要素,而不是要素的集合               * 第三个参数表示延伸(剪切)的属性               *************************************/              geometryService.TrimExtendAsync(polylineListGrID,polylineListriver[0],CurveExtension.NoExtendAtFrom);          }

 接下来就是对结果进行处理,上面我们说过,所有交线的一个端点即为直线的交点。下图是返回直线的结果(红色线段即为结果),这里需要注意的是

使用TrimExtend功能时,CurveExtension属性设置为NoExtendAtFrom,这样网格就会从起点向右寻找格线的交点,没有交点则向右延长,直到相交。

(1)交线的长度一定小于初始时绘制的网格的范围,即

   水平方向的交线长度<|Xmax-Xmin|,Xmax,Xmin为网格X轴的最大与最小值。

   垂直方向的交线长度<|Ymax-Ymin|,Ymax,Ymin为网格Y轴的最大与最小值。

(2)针对于水平和垂直网格,交点的坐标始终是最小值(当是斜线的时候,可通过获取交线的斜率,然后再求得交点)

知道了这两点,我们实现起来就I叫容易了。下面是获取结果的代码:

    voID geometryService_TrimExtendCompleted(object sender,GraphicsEventArgs e)          {              glayer.Graphics.Clear();              MapPoint intersectPoint = null;                foreach (Graphic g in e.Results)              {                  g.Symbol = LayoutRoot.Resources["Resultslinesymbol"] as ESRI.ArcGIS.ClIEnt.Symbols.Symbol;                  glayer.Graphics.Add(g);                  if (g.Geometry.Extent != null)                  {                      /*recExtent结构体存储了绘制矩形的范围                       * 这里通过比较返回结果中线段长度来判断其是不是交线                       * 同时本文绘制的网格是垂直和水平的,                       * 所以交线的长度肯定小于绘制矩形的范围(这里只需要判断水平方向即可)                       * 关于斜线的情况,判断方法类似                       */                      if ((g.Geometry.Extent.XMax - g.Geometry.Extent.XMin) < (recExtent.Xmax - recExtent.Xmin))                      {                          intersectPoint = CreateMapPoint(g.Geometry.Extent.XMin,g.Geometry.Extent.YMin);                          AddPointGraphic(intersectPoint);                      }                  }              }          }      

其中CreateMapPoint方法表示通过X,Y坐标构造一个点,AddPointGraphic表示将点添加到地图中显示。

 //由X,Y构造一个点  public MapPoint CreateMapPoint(double x,double y)          {              return new MapPoint(x,y);          }    //将一个点添加到Layer中   public voID AddPointGraphic(ESRI.ArcGIS.ClIEnt.Geometry.MapPoint point)          {              Graphic g = new Graphic()              {                  Geometry = point,Symbol = LayoutRoot.Resources["PointSymbol"] as SimpleMarkerSymbol,};                glayer.Graphics.Add(g);          }

这样我们就求得了线与线的交点。

示例图:

a.构造的网格线

 

 b.交点

总结:

本文使用TrimExtend来求解交点,过程是:获取TrimExtend功能返回的线段,筛选出交线,然后获得交线的端点,即为交点。本文讲解了网格是水平和垂直时相交的情况,当线段是不规则的情况下,可以通过交线的斜率来确定交点。

 下一篇,将讲解构造斜线网格来求交点,欢迎继续关注。

(版权所有,转载请标明出处)

总结

以上是内存溢出为你收集整理的ArcGIS API for Silverlight 使用GeometryService求解线与线的交点(二)全部内容,希望文章能够帮你解决ArcGIS API for Silverlight 使用GeometryService求解线与线的交点(二)所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1022866.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-23
下一篇 2022-05-23

发表评论

登录后才能评论

评论列表(0条)

保存