The odd solution to the intersection of two polygon in the GPS fence and the odd solution to the gps fence

Source: Internet
Author: User

The odd solution to the intersection of two polygon in the GPS fence and the odd solution to the gps fence
Preface

The area of the origin area measured by the GPS measuring instrument is then submitted to the system. The system needs to check whether the origin area overlaps with other regions. If the overlap exceeds 10%, it is necessary to warn that the origin area has been registered by XXX. The data measured by GPS is consecutive coordinate data of longitude and latitude. The current problem is to find whether there is an intersection between a series of points and other areas. I think it should be easy to get this requirement. There should be ready-made code on the Internet.

First finished

 

Initial ideas

At first, I thought (XMin, YMin) should be in the lower left corner of the polygon, and (XMax, YMin) should be in the lower right corner. It would be better to find four vertices and convert them into rectangles. However, the data measured by GPS is not the rectangle of the vertical coordinate axis, and some are skewed, so XMin and YMin cannot be found. What should we do if it is an irregular polygon, if you want to convert it into a rectangle, the error is very big.

 

Orthodox Solution

According to the information found on the Internet, this problem is solved by the subject of computational ry. Then it involves a lot of vectors, the cross product of vectors, and various geometric knowledge. It seems a very difficult process to learn these knowledge within 2-3 days and then write the code.

The most complex of the above steps is to find the concave package and the intersection, forgive me for having to give up after learning the convex polygon.

 

Wonderful Solution

Why is it a wonderful solution? In fact, it is just to earn a wave of attention. The final solution I chose was completed through the windowsAPI provided by gdi32.dll. The following describes several API functions used.

Create a polygon based on the vertex set

 

IntPtr CreatePolygonRgn(Point[] lpPoint, int nCount, int nPolyFillMode);

  

Merge two polygon, which can be OR/AND/XOR. Here we use AND.

 

int CombineRgn(IntPtr dest, IntPtr src1, IntPtr src2, int flags);

  

Obtain detailed data of a polygon and split it into several rectangles.

 

int GetRegionData(HandleRef hRgn, int size, IntPtr lpRgnData);

  

So our last step is

The whole process looks very simple. Here I will introduce some code and explain the difficult part.

 

Create a polygon

Reference dll first

 

[DllImport("gdi32")]private static extern IntPtr CreatePolygonRgn(Point[] lpPoint, int nCount, int nPolyFillMode);

  

In the code, the Point is in the System. Drawing space.

X and Y * 1000000 are because the GPS information is 118.12334232. If the int value is taken directly, the data is changed to 118, which is not accurate enough.

In the code, IntPtr is a handle, and Windows API programming provides a handle, similar to a memory pointer.

 

Point[] poin = new Point[gpsList.Count()];for (int i = 0; i < gpsList.Count(); i++){    string[] xy = gpsList[i].Split(',');    double x = ConvertHelp.obj2Double(xy[0], 0);    double y = ConvertHelp.obj2Double(xy[1], 0);    poin[i].X = (int)(x * 1000000);    poin[i].Y = (int)(y * 1000000);}IntPtr orginRgn = IntPtr.Zero;orginRgn = CreatePolygonRgn(poin, poin.Count(), 1);

 

 

Compare two polygon

Reference dll first

 

/// <Summary>/** CombineRgn (p1: HRGN; {merged region} p2, p3: HRGN; {two original regions} p4: Integer {merge option; see the table below}): Integer; {four possible return values} // merging options: RGN_AND = 1; RGN_OR = 2; RGN_XOR = 3; RGN_DIFF = 4; RGN_COPY = 5; {copy the first region} // return value: ERROR = 0; {ERROR} NULLREGION = 1; {empty region} SIMPLEREGION = 2; {single rectangular region} COMPLEXREGION = 3; {multi-rectangle area} * // </summary> /// <param name = "dest"> </param> /// <param name = "src1"> </param> /// <param name = "src2"> </param> /// <param name = "flags"> </param> /// <returns> </returns> [DllImport ("gdi32.dll ", charSet = CharSet. auto)] public static extern int CombineRgn (IntPtr dest, IntPtr src1, IntPtr src2, int flags );

 

It is easy to use. Three parameters are provided. The first parameter is the handle returned after merging. The first parameter is polygon 1 and the second parameter is polygon 2, the last flag parameter is the merge option, where 1 is and, And 2 is or. Here, and is used.

If the returned result is 0, the error is returned, that is, there is no intersection. 1 indicates that there is no intersection in the blank area, and 2 and 3 indicate that there is an intersection.

 

Int nMix = CombineRgn (nextRgn, orginRgn, nextRgn, 1); if (nMix! = 1 & nMix! = 0) {// intersection exists}

 

 

Obtain intersection data

Calculating the intersection area is actually how to read data in the memory based on the handle, because most of the data on the Internet is written in C ++ and is rarely found. Net, so this part took me one afternoon, including taking some detours, and finally found a positive solution through google.

Reference the dll first and create the corresponding structure based on the data structure returned by the API

 

Public struct RGNDATAHEADER {public int dwSize; public int iType; public int nCount; public int nRgnSize; public RECT rcBound;} public struct RECT {public int Left; public int Top; public int Right; public int Bottom;} // <summary> // For more information, see http://www.pinvoke.net/default.aspx/gdi32/GetRegionData.html. // data structure Reference: http://www.cnblogs.com/del/archive/2008/05/20/1203446.html /// </summary> /// <param name = "hRgn"> </param> /// <param name = "size"> </param> // /<param name = "lpRgnData"> </param> // <returns> </returns> [DllImport ("gdi32.dll ", charSet = CharSet. auto, SetLastError = true, ExactSpelling = true)] public static extern int GetRegionData (HandleRef hRgn, int size, IntPtr lpRgnData );

 

 

The following code only describes the special features of the call to the GetRegionData API. First, you must call the API twice to obtain the correct data.

Call GetRegionData (hr, 0, IntPtr. Zero) for the first time and pass an empty handle. At this time, an int value is returned, indicating the size of the memory zone to be prepared.

Then, you need to apply for a memory region to prepare a value for decoupling. IntPtr bytes = Marshal. AllocCoTaskMem (dataSize); it is used to prepare a handle for a specific memory area.

When GetRegionData (hr, dataSize, bytes) is called for the second time, the data we want can be filled in the memory area pointed to by the bytes handle.

The next question is how to obtain structured data with a handle. in C #, pointer operations are supported, but the code is unsafe. The most critical sentence has been annotated below.

 

Const int RDH_RECTANGLES = 1; /// <summary> // returns a polygon, obtain all the rectangles In the polygon /// </summary> /// <param name = "hRgn"> </param> /// <returns> </returns> public unsafe static RECT [] RectsFromRegion (IntPtr hRgn) {RECT [] rects = null; var hr = new HandleRef (null, hRgn); // First we call GetRegionData () with a null buffer. // The return from this call shocould be the size of buffer // we need to allocate in order to re Ceive the data. int dataSize = GetRegionData (hr, 0, IntPtr. Zero); if (dataSize! = 0) {IntPtr bytes = IntPtr. zero; // Allocate as much space as the GetRegionData call // said was needed bytes = Marshal. allocCoTaskMem (dataSize); // Now, make the call again to actually get the data int retValue = GetRegionData (hr, dataSize, bytes); // From here on out, we have the data in a buffer, and we // just need to convert it into a form that is more useful // Since pointers are used, this Whole routine is 'unsafe '// It's a small sacrifice to make in order to get this to work. // [RBS] Added missing second pointer identifier RGNDATAHEADER * header = (RGNDATAHEADER *) bytes; if (header-> iType = RDH_RECTANGLES) {rects = new RECT [header-> nCount]; // The rectangle data follows the header, so we offset the specified // header size and start reading rectangles. // get the offset int rectOffset = he Ader-> dwSize; for (int I = 0; I 

 

Calculated Area

Because the data obtained above is actually a RECT array, and the RECT contains the coordinate information of the top, bottom, and left vertices, we obviously get an array of rectangles, there are more than 2000 rectangles in each decomposition, so you can use them directly.

 

/// <Summary> /// calculate the area of the polygon /// </summary> /// <param name = "rgn"> </param> // <returns> </returns> public static int CalculateAreas (IntPtr rgn) {RECT [] rectData = RectsFromRegion (rgn); int ret = 0; foreach (var rect in rectData) {int areas = (rect. bottom-rect. top) * (rect. right-rect. left); if (areas <0) areas = areas *-1; ret + = areas; // Console. writeLine ("{0}, {1}, {2}, {3}, {4}", rect. top, rect. left, rect. right, rect. bottom, areas);} return ret ;}

 

 

Summary

This requirement was not complex at the beginning. There should be ready-made code on the Internet. In fact, after searching, we found that the knowledge of computational ry involved has a high requirement on ry and algorithms, however, all geometric knowledge is returned to the teacher. It may be too late to complete the tutorial in just 2-3 days. After all, Baidu's capabilities are limited. Sometimes google can provide more help. I used windowsAPI to solve this problem and learned about C # pointer operations.

Related Article

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.