## Point inside polygon and distance point to polygon

htuser
Posts: 437
Joined: December 19th, 2011, 6:26 pm
Location: HAITI

### Point inside polygon and distance point to polygon

Dear Cspro Developer Team,
Maybe i'm the CSProuser who request more functionalities and features to you, and since you're a small team with limited ressources, it's impossible to respond to all CSProusers request. Latest weeks i'm trying to do my best to implement some functionalities such as Point inside polygon and distance point to polygon, this using the CSPro Programming Language. But, also, since i'm a Agricultural economics engineer, i'm limited in programming. I learned C/C++ at bachelor degree, years ago.

This would be worse if i used CAPI systems who don't have any code editor, compiler and don't supporting any know programming language.

Fortunately, CSPro Programming Language helped me to maintain a certain level in programming, mainly with your incredible support. And also, i realize that, if i spend more time to design advanced function in CSPro Logic, rather than waiting to you this will help me a lot in advanced programming. Also, the community will have access to them. However, since CSPro logic doesn't support object programming, such as Python or R, it limit us...

Following my early year post: http://csprousers.org/forum/viewtopic.php?f=1&t=2858, i would like to implement some algorithms from:
a.- http://geomalgorithms.com
b.- https://stackoverflow.com/questions/924 ... de-polygon

in CSPro Logic.

For this 2D polygon, i would like to:
a.- transform it in point (there's a lot of tools to to that in QGIS and the attribute table of points can be exported to Excel);
store these points in CSdb in a table having a table named polygon with 4 columns: pk_number, polygon_id, X, Y (i hope CSdb and Excel2CSPro will
support stored in multiple tables and columns soon. Normally, i can load the Excel-CSV file in an independent sqlite database, since Josh discourage to create other table in CSdb or CSlog, but i don't know how to synchronize an independent sqlite database to CSWeb..., so i maintain using CSdb);
b.- sync this CSdb to CSweb;
c.- using this CSdb in CSEntry application as external dictionary;
d.- using sqlquery to retrieve theses points as a numeric array : Does CSPro support array with decimal? In Javascript, it's easy:
https://stackoverflow.com/questions/703 ... javascript.
e.- the point that i want to know if it's inside the polygon is this recorded in CSEntry (application or in paradata).
f.- it's possible to transform this array of polygon in a object or similar element in CSPro logic? It's possible to implement this algorithm in CSPro logic:
(algorithm from: http://geomalgorithms.com )

Code: Select all

``````//===================================================================

// wn_PnPoly(): winding number test for a point in a polygon
//      Input:   P = a point,
//               V[] = vertex points of a polygon V[n+1] with V[n]=V
//      Return:  wn = the winding number (=0 only when P is outside)
int
wn_PnPoly( Point P, Point* V, int n )
{
int    wn = 0;    // the  winding number counter

// loop through all edges of the polygon
for (int i=0; i<n; i++) {   // edge from V[i] to  V[i+1]
if (V[i].y <= P.y) {          // start y <= P.y
if (V[i+1].y  > P.y)      // an upward crossing
if (isLeft( V[i], V[i+1], P) > 0)  // P left of  edge
++wn;            // have  a valid up intersect
}
else {                        // start y > P.y (no test needed)
if (V[i+1].y  <= P.y)     // a downward crossing
if (isLeft( V[i], V[i+1], P) < 0)  // P right of  edge
--wn;            // have  a valid down intersect
}
}
return wn;
}
//===================================================================
``````
Also can you advise me on better idea to do this?

josh
Posts: 2003
Joined: May 5th, 2014, 12:49 pm
Location: Washington DC

### Re: Point inside polygon and distance point to polygon

First off, no need to involve sql in this at all. For those who are used to using sql database, a lookup file in CSPro is the rough equivalent of a table in a sql database and loadcase is how you do the equivalent of a select.

You can easily store your polygons in a lookup file where each row represents a point in the polygon. The points are grouped by polygon id. The file below contains two polygons: one with 6 points and another with 5.

Code: Select all

``````id	lon	            lat
1	-76.94626808	38.83964076
1	-76.94137573	38.83295506
1	-76.93030357	38.83001315
1	-76.92635536	38.8328882
1	-76.93279266	38.84284967
1	-76.94626808	38.83964076
2	-76.9330287	38.84532311
2	-76.92815781	38.84532311
2	-76.92815781	38.84980183
2	-76.9330287	38.84980183
2	-76.9330287	38.84532311
``````
You can create a file like the above in Excel. Then create a CSPro dictionary to match it. It should have a single id-item (polygon id) and a repeating record that contains two items: longitude and latitude. Use Excel2CSPro to convert the spreadsheet to a CSPro data file.

You can load a polygon from your lookup file using loadcase. For example, if you want to load the polygon with ID 1 you would do:
POLY_ID = 1;
No need to convert to arrays since the repeating record already acts like an array. You can get the length with count() and you can reference the nth latitude and longitude for the polygon using subscripts. If your record is POLYS_REC then you would use count(POLYS_REC) to get the number of points in the polygon. If your items are POLY_LON and POLY_LAT then you can use POLY_LON(1) and POLY_LAT(1) to get the coordinates of the first point in the polygon.

Now it is easy to port the point in polygon test from C to CSPro. Assume LON and LAT are the coordinates of the point you want to test and the polygon to test against has been loaded using loadcase so its coordinates are POLY_LON and POLY_LAT.
numeric wn = 0;    // the  winding number counter
numeric n = count(POLYS_REC) - 1;

// loop through all edges of the polygon
do numeric i=1 while i <= n    // edge from V to  V[i+1]
if POLY_LAT(i) <= LAT then         // start y <= P.y
if POLY_LAT(i+1) > LAT then      // an upward crossing
if isLeft(POLY_LON(i), POLY_LAT(i), POLY_LON(i+1), POLY_LAT(i+1), LON, LAT) > 0 then  // P left of  edge
wn = wn + 1;            // have  a valid up intersect
endif;
endif;
else                         // start y > P.y (no test needed)
if POLY_LAT(i+1)  <= LAT then     // a downward crossing
if isLeft(POLY_LON(i), POLY_LAT(i), POLY_LON(i+1), POLY_LAT(i+1), LON, LAT) < 0 then // P right of  edge
wn = wn -1;            // have  a valid down intersect
endif;
endif;
endif;
enddo;

if wn = 0 then
errmsg("Point outside");
else
errmsg("Point inside");
endif;

The function isLeft is defined as:

function isLeft(P0x, P0y, P1x, P1y, P2x, P2y)
isLeft = (P1x - P0x) * (P2y - P0y)
- (P2x -  P0x) * (P1y - P0y);
end

I'm attaching a simple test project that puts this all together.
Attachments
pointinpoly.zip

htuser
Posts: 437
Joined: December 19th, 2011, 6:26 pm
Location: HAITI

### Re: Point inside polygon and distance point to polygon

A lot of highly thanks to you Josh!

This example show to us how the CSPro Programming Language is enough to implement advanced algorithms.
So it's better to try solving some request in CSPro Logic rather than asking you specific CSPro function.
Also, for you, it's very important to continue improving CSPro Programming Language.
Best Regards,

Posts: 367
Joined: July 9th, 2012, 11:32 am