ArcGIS API for Silverlight use geometryservice to solve the intersection between a line and a plane (1)

Source: Internet
Author: User
Tags polyline

Recently, I encountered a problem in the project, which is roughly as follows:

If you know the surface elements of a river, you need to divide the river into grids based on the rectangle entered by the user and the preset step size, and obtain the intersection between the grid and the riverbanks on both sides.

I checked the information and found that the native ArcGIS API for Silverlight did not provide an excuse to implement this function. However, geometryservice provides a similar function: intersect.

Intersect: There are three kinds of intersection conditions:

Note the last one: Line and line intersection. From a geometric point of view, the final result is a point. However, in geometryservice, the final result is polyline, that is, the line, And the extent attribute of the line is null, that is, the length of the Line Segment is 0. therefore, if you want to use intersect to solve the intersection of the two lines, it is not advisable. So what is the purpose here? Is used to determine the number of intersections.

From the point of view, our situation is the second: the surface and line intersection.

But we found that what we get here is the intersection line, and what we want is the point. How can we solve this problem?

As a matter of fact, we can find that since we can get the intersection line, can we get the two endpoints of the line? If we can get two endpoints, is it our problem solved?

The answer is only half the answer, because when we think about it, we will find that although we can get two endpoints, some endpoints are not the intersection of grid and river elements, as shown in:

Indicates the grid for dividing rivers.

If we follow the above ideas, we will get the following results:

We found that although the intersection with the river was obtained, the endpoints of the horizontal lines on both sides of the left and right were also included, and apparently they were not the intersection with the river, how should we remove them here?

As you can see, the intersection of non-riverbanks on the left and right boundary is located at the edge of the grid. Assume that the area of the grid rectangle is (xmin, ymin, xmax, Ymax ), the X coordinates of these points are xmin or xmax, so we can remove the points on the boundary. However, there is a problem here:

When we divide the data according to a certain step, the entire score may not be fixed, that is, the following situation occurs:

We found that the top and right sides are not just equal. The top and right sides of the line are out of the "range". Although this does not affect the extraction of the intersection points of the river, it is not so nice.

Next, let's take a look at the code for constructing a grid:

Public void creategrid (double xmin, double xmax, double ymin, double Ymax, double xstep, double ystep) {// define two points to determine a straight line mappoint MP1; mappoint MP2; // determine the number of parts divided by step. Int Nx = convert. toint32 (xmax-xmin)/xstep); int ny = convert. toint32 (Ymax-ymin)/ystep); // construct the vertical line for (INT I = 0; I <NX + 1; I ++) {MP1 = createmappoint (xmin + I * xstep, ymin); MP2 = createmappoint (xmin + I * xstep, Ymax); createline (MP1, MP2 );} // construct a horizontal line for (INT I = 0; I <ny + 1; I ++) {MP1 = createmappoint (xmin, ymin + I * ystep ); MP2 = createmappoint (xmax, ymin + I * ystep); createline (MP1, MP2);} // rectextent is a custom struct, 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 "))};}

The above createmappoint is a custom method, indicating that a new point (mappoint) is created based on the X and Y coordinates. The sample code is as follows:

 public MapPoint CreateMapPoint(double x,double y)        {            return new MapPoint(x, y);        }

Createline indicates to draw a straight line based on the two points:

Public void createline (mappoint P1, mappoint P2) {ESRI. arcGIS. client. geometry. 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); // remember to assign values to the space coordinate system; otherwise, the simplify operation will fail. Polyline. spatialreference = map1.spatialreference; addlinegraphic (polyline );}

Addlinegraphic indicates to add the generated line to the layer:

 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);        }

Similarly, addpointgraphic adds some points to the 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);        }

The mesh is drawn here, but you will find that the mesh is shown in the 3rd images in this article.

This is not what we want. Here we modify the code for constructing horizontal and vertical straight lines, as shown below:

// Construct a vertical line 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 );} // construct a horizontal line 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 );}

Here we changed xmax to xmax + NX * xstep.

In this way, we can get a closed mesh.

However, we still didn't talk about how to solve the problem mentioned above. we mentioned that xmin and xmax can be used to determine whether it is the intersection of a river, but it cannot be implemented when the program is actually running, why?

Because when we use geometry's intersect, the coordinate values of each point (the endpoint of the intersection) in the Intersect process will be simplified accordingly (rounded up ), in this way, we get the endpoint value in the event function completed by intersect is not equal to that before intersect, so we cannot choose the intersection point based on whether the xmin and xmax values of the Line Segment endpoint are equal to the boundary value.

The specific process can be viewed below:

Therefore, neither xmin nor xmax can be used. What should I do?

Here we will find that the xmin and xmax after Intersect are very similar to the actual x range, Because intersect is actually rounding the X range.

In general, the range of X after intersect and the initial range of X do not exceed 1. Or even 0.1. Therefore, we need to take the absolute value of the value after intersect and the initial value, so that we can determine whether the endpoint of the line segment is the intersection point after intersect.

The following code shows the event processing function of geometryservice intersect:

Void geometryservice_intersectcompleted (Object sender, graphicseventargs e) {glayer. graphics. clear (); foreach (Graphic g in E. results) {G. symbol = layoutroot. resources ["resultslinesymbol"] As simplelinesymbol; If (G. geometry. extent! = NULL) {# region vertical line if (G. geometry. extent. width = 0.0) // The two endpoints of the vertical line are the intersection of {foreach (ESRI. arcGIS. client. geometry. pointcollection PC in (G. geometry as ESRI. arcGIS. client. geometry. polyline ). paths) {foreach (mappoint MP in PC) {If (math. ABS (MP. y-recextent. ymin) <0.1 | math. ABS (MP. y-recextent. ymax) <0.1) {continue;} else {addpointgraphic (MP) ;}}}# endregion # region horizontal line if (G. geometry. extent. height = 0.0) {foreach (ESRI. arcGIS. client. geometry. pointcollection PC in (G. geometry as ESRI. arcGIS. client. geometry. polyline ). paths) {foreach (mappoint MP in PC) {If (math. ABS (MP. x-recextent. xmin) <0.1 | math. ABS (MP. x-recextent. xmax) <0.1) {continue;} else {addpointgraphic (MP) ;}}}# endregion} glayer. graphics. add (g );}}
Here we compare the value of the boundary point with the endpoint value of the intersection. If the difference between the two is less than 0.1, it indicates that the point is the boundary point and is removed.

The above explains the key part of the implementation process. Let's take a look at the specific implementation process:

(1): Draw a rectangle and divide the mesh.

Custom struct:

 public struct RectExtent    {       public double Xmin;       public double Ymin;       public double Xmax;       public double Ymax;    }

Declare the following variables:

// Define the paint brush private draw drawrect = NULL for drawing the rectangle; // define the set service variable private geometryservice = NULL; // It is used to hold the drawn line and vertex graphicslayer glayer = NULL; // river element featurelayer fpolygonlayer = NULL; // custom struct variable private rectextent recextent;

Instantiate In the constructor:

   public MainPage()        {            InitializeComponent();            geometryService = new GeometryService("http://qzj-pc/ArcGIS/rest/services/Geometry/GeometryServer");            geometryService.IntersectCompleted += new EventHandler<GraphicsEventArgs>(geometryService_IntersectCompleted);            geometryService.SimplifyCompleted += new EventHandler<GraphicsEventArgs>(geometryService_SimplifyCompleted);                        geometryService.Failed += new EventHandler<TaskFailedEventArgs>(geometryService_Failed);            glayer=map1.Layers["LineLayer"] as GraphicsLayer;            fpolygonlayer = map1.Layers["RiverPolygon"] as FeatureLayer;            drawGridButton.Click += new RoutedEventHandler(drawGridButton_Click);            intersectButton.Click += new RoutedEventHandler(intersectButton_Click);            ClearButton.Click += new RoutedEventHandler(ClearButton_Click);            drawRect = new Draw(map1);            drawRect.DrawMode = DrawMode.Rectangle;            drawRect.DrawComplete += new EventHandler<DrawEventArgs>(drawRect_DrawComplete);            drawRect.IsEnabled = false;        }

Click the button to draw the grid.

Void drawgridbutton_click (Object sender, routedeventargs e) {// you have entered the step size information if (xsteptextbox. text. trim () = "" | ysteptextbox. text. trim () = "") {MessageBox. show ("Enter step size information"); return;} drawrect. isenabled = true ;}
 void drawRect_DrawComplete(object sender, DrawEventArgs e)        {            drawRect.IsEnabled = false;                      CreateGrid(e.Geometry.Extent.XMin, e.Geometry.Extent.XMax, e.Geometry.Extent.YMin, e.Geometry.Extent.YMax, Convert.ToDouble(xStepTextBox.Text), Convert.ToDouble(yStepTextBox.Text));        }

Creategrid has been given above and is not described here.

(2) silmplify river Elements

 void intersectButton_Click(object sender, RoutedEventArgs e)        {            geometryService.SimplifyAsync(fpolygonlayer.Graphics);        }

(3) The simplify event completes the Intersect operation in the function.

Because the river element used here has only one layer, the generated result results has only one element, that is, the index value is 0.

  void geometryService_SimplifyCompleted(object sender, GraphicsEventArgs e)        {            geometryService.IntersectAsync(glayer.Graphics, e.Results[0].Geometry);        }

(4). filter the correct intersection points in the Intersect event completion function. The code is provided above and is not described here.

(5) Add the correct points to the layer.

Finally, we can get the correct result:

Thinking: how to draw the point of intersection of the grid?

Notice: the next article will explain how to solve the intersection of line and line. Please stay tuned!

(All Rights Reserved. For details, refer to the source)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.