Does point fall within polygon? VBA Function

sijpie

Well-known Member
Joined
Nov 1, 2008
Messages
4,241
Office Version
  1. 365
Platform
  1. Windows
  2. MacOS
This is not a question, just a post of some code to help find if a point falls within a (complex) polygon.

I found the original code written in C here:
Determining Whether A Point Is Inside A Complex Polygon

The page also explains the issues with complex polygons. But the code of course also works for simple polygons.

I have modified the code to run as a function in Excel, and so it can be called as any other function.

The function takes as arguments the point to be checked as a range with X & Y, and a range with all the points of the polygon, X & Y.

In my example I am checking if wells drilled in the past are within a certain area.


Excel 2010
ABCDEFGHI
1Stage 1 Polygon
2Well DatabaseSurfaceCoordinates
3Stereo70In Stage1 Area
4xy
5549926313550Well NameEastingY[m]NorthingX[m]Yes/No
65493573133161 A Est559,008.51309,204.47FALSE
75499233121761 Ar Est550,000.30313,130.16TRUE
85506503125731 Ar Vest543,011.50313,106.58FALSE
95511643132051 I Est556,226.56312,713.64TRUE
105499263135501 K Vest-Blejesti539,357.63313,165.48FALSE
112 A Est559,388.41309,234.32FALSE
122 Ar Est549,925.25313,140.10TRUE
132 Ar Vest543,080.28312,970.75FALSE
142 I Est554,430.45313,551.15FALSE
152 P Vest545,170.00310,055.00FALSE
163 A Est559,722.95309,279.51FALSE
Wells inSt1 (2)
Cell Formulas
RangeFormula
I6=PointInPolygon(G6:H6,Stage1Poly)
Named Ranges
NameRefers ToCells
'Wells inSt1 (2)'!Stage1Poly='Wells inSt1 (2)'!$B$5:$C$9


A2tz4zbUgeWf8OjuIbeJf4e9ZC8KGbFyXYcWSLhi4cE=w267-h201-p-no



To use the function, copy the code below. In Excel press Alt-F11 to open the VBA editor. Rightclick on the workbook name in the top left panel, and select Insert/Module. In the right hand pane, paste the code. Now in the workbook you can use the function as shown above. The range holding the polygone nodes is range Stage1Poly, which is B5:C9

The function code is as follows:

<font face=Courier New><SPAN style="color:#00007F">Function</SPAN> PointInPolygon(rXY <SPAN style="color:#00007F">As</SPAN> Range, rpolyXY <SPAN style="color:#00007F">As</SPAN> Range) <SPAN style="color:#00007F">As</SPAN> <SPAN style="color:#00007F">Boolean</SPAN><br>    <SPAN style="color:#007F00">' Function checks if X,Y given in rXY falls within complex _<br>      polygon as defined by node list rpolyXY. _<br>      rXY to be 2 cell range with one X and one Y value _<br>      rpolyXY to be 2 column range with for each node on the polygon _<br>      the X and the Y point</SPAN><br>    <br>    <SPAN style="color:#00007F">Dim</SPAN> i <SPAN style="color:#00007F">As</SPAN> <SPAN style="color:#00007F">Integer</SPAN>, j <SPAN style="color:#00007F">As</SPAN> <SPAN style="color:#00007F">Integer</SPAN>, polySides <SPAN style="color:#00007F">As</SPAN> <SPAN style="color:#00007F">Integer</SPAN><br>    <SPAN style="color:#00007F">Dim</SPAN> oddNodes <SPAN style="color:#00007F">As</SPAN> <SPAN style="color:#00007F">Boolean</SPAN><br>    <SPAN style="color:#00007F">Dim</SPAN> x <SPAN style="color:#00007F">As</SPAN> <SPAN style="color:#00007F">Double</SPAN>, y <SPAN style="color:#00007F">As</SPAN> <SPAN style="color:#00007F">Double</SPAN><br>    <SPAN style="color:#00007F">Dim</SPAN> aXY <SPAN style="color:#00007F">As</SPAN> <SPAN style="color:#00007F">Variant</SPAN><br>    <br>    oddNodes = <SPAN style="color:#00007F">False</SPAN><br>    x = rXY.Cells.Value2(1, 1)<br>    y = rXY.Cells.Value2(1, 2)<br>    aXY = rpolyXY.Value<br>    <br>    polySides = rpolyXY.Rows.Count<br>    j = polySides - 1<br>    <br>    <SPAN style="color:#00007F">For</SPAN> i = 1 <SPAN style="color:#00007F">To</SPAN> polySides<br>        <SPAN style="color:#00007F">If</SPAN> (((aXY(i, 2) < y And aXY(j, 2) >= y) _<br>            <SPAN style="color:#00007F">Or</SPAN> (aXY(j, 2) < y And aXY(i, 2) >= y)) _<br>            And (aXY(i, 1) <= x <SPAN style="color:#00007F">Or</SPAN> aXY(j, 1) <= x)) <SPAN style="color:#00007F">Then</SPAN><br>            oddNodes = oddNodes Xor (aXY(i, 1) + (y - aXY(i, 2)) / (aXY(j, 2) - aXY(i, 2)) * (aXY(j, 1) - aXY(i, 1)) < x)<br>        <SPAN style="color:#00007F">End</SPAN> <SPAN style="color:#00007F">If</SPAN><br>        j = i<br>    <SPAN style="color:#00007F">Next</SPAN> i<br>    PointInPolygon = oddNodes<br><SPAN style="color:#00007F">End</SPAN> <SPAN style="color:#00007F">Function</SPAN><br></FONT>
 
The problem has to do with an elevated area, composed of lets say 10 points NOT guaranteed to lie on a flat plane. The polygon is enclosed by many tilted planes, leaving not only several points componing it, but also areas with different inclination. There are few planes componing it so atm I have separated them into different pieces, creating several flat, tilted polygons of which I have calculated if the point is within the area (x,y coord.). As I said to sijpie, afterwards just check the height of my point and the tilted plane on those x,y coord to compare if it lies either above or below.
 
Upvote 0

Excel Facts

Workdays for a market open Mon, Wed, Friday?
Yes! Use "0101011" for the weekend argument in NETWORKDAYS.INTL or WORKDAY.INTL. The 7 digits start on Monday. 1 means it is a weekend.
Lets say my polyline has the following coordinates;
Code:
419897,90	4571392,20426946,98	4574500,10
424965,89	4573245,30
422182,78	4572016,75
419897,90	4571392,20
422235,05	4572399,10
422281,17	4572419,76
422327,20	4572440,36
422373,46	4572460,96
422421,18	4572482,44
422466,42	4572502,10
422514,32	4572522,77
422563,70	4572543,76
422605,61	4572561,90
422651,84	4572581,62
422699,93	4572602,09
422744,67	4572621,34
422792,40	4572641,09
422840,79	4572661,02
422887,66	4572680,06
422933,59	4572698,74
422984,10	4572719,81
423026,68	4572737,11
423074,53	4572756,80
423117,65	4572775,42
423167,15	4572796,92
423212,31	4572817,48
423260,11	4572839,58
423305,44	4572860,43
423356,15	4572883,83
423398,14	4572903,16
423444,36	4572924,39
423490,05	4572945,39
423535,16	4572966,07
423554,82	4572974,96
423713,87	4573046,65
423766,75	4573070,07
423811,49	4573090,13
423858,73	4573110,72
423904,14	4573131,02
423950,05	4573151,48
423996,08	4573171,92
424043,26	4573192,94
424089,75	4573213,76
424135,13	4573233,93
424180,88	4573254,34
424227,07	4573275,19
424270,68	4573294,63
424320,38	4573316,86
424367,17	4573337,50
424412,74	4573357,87
424464,28	4573380,96
424506,47	4573399,23
424552,14	4573419,04
424597,70	4573438,77
424645,53	4573459,63
424690,76	4573479,14
424742,27	4573501,50
424780,01	4573517,81
424834,89	4573542,04
426946,98	4574500,10
424965,89	4573245,30
424911,00	4573221,08
424873,39	4573204,47
424822,02	4573181,80
424776,96	4573161,90
424729,22	4573140,83
424683,80	4573120,78
424638,26	4573100,68
424596,20	4573082,11
424544,54	4573059,31
424498,87	4573039,15
424452,08	4573018,49
424402,28	4572996,51
424358,60	4572977,23
424312,24	4572956,76
424266,41	4572936,53
424220,98	4572916,48
424174,38	4572895,91
424127,12	4572875,05
424081,05	4572854,71
424035,07	4572834,41
423989,57	4572814,33
423942,43	4572793,52
423897,57	4572773,71
423844,66	4572750,36
423685,07	4572679,91
423665,33	4572671,20
423619,93	4572651,16
423573,93	4572630,85
423527,41	4572610,31
423485,13	4572591,65
423434,05	4572569,10
423388,40	4572548,95
423340,23	4572527,69
423294,85	4572507,65
423245,47	4572485,86
423202,51	4572466,89
423155,18	4572446,00
423113,16	4572427,45
423063,10	4572405,35
423017,76	4572385,34
422971,50	4572364,92
422923,64	4572343,79
422876,40	4572322,93
422831,84	4572303,27
422784,03	4572282,16
422738,05	4572261,87
422696,28	4572243,42
422647,20	4572221,76
422599,47	4572200,69
422554,35	4572180,77
422506,48	4572159,64
422460,15	4572139,19
422414,01	4572118,82
422367,78	4572098,42
422321,77	4572078,10
422275,56	4572057,71
422237,66	4572040,98
422182,78	4572016,75
419897,90	4571392,20

When introducing a point which is INSIDE; (421949,72 4572170,48), the function says its not
while analyzing a point which is OUTSIDE; (421955,14 4572299,19), the function says its inside... any ideas why could this error be?
 
Upvote 0
also note that windows has to find where the mouse is and what parts of an object are showing on the screen
so there are a set of api's for many related tasks.
They work in longs BUT with scaling can work most cases
eg a scaling of 2 ^ 17 works KML coordinates lat lng like 153.45634564333 accuracy of about 0.01 of a mm

so factor points in with * factor and if not Boolean out with * factorInv

Option Explicit
' windows api guide
Declare Function CreateRectRgn& Lib "gdi32" (ByVal X1&, ByVal Y1&, ByVal X2&, ByVal Y2&)
Declare Function CombineRgn& Lib "gdi32" (ByVal hDestRgn&, ByVal hSrcRgn1&, ByVal hSrcRgn2&, ByVal nCombineMode&)
Declare Function DeleteObject& Lib "gdi32" (ByVal hObject&)
Declare Function CreatePolygonRgn& Lib "gdi32" (lpPoint As POINTAPI, ByVal nCount&, ByVal nPolyFillMode&)
Declare Function CrePolRgnA& Lib "gdi32" Alias "CreatePolygonRgn" (Pt0x&, ByVal HalfCount&, ByVal FillMode&)
' for region from WPA&() ... RegX = CrePolRgn&(WPA(0), UBound(wpa)\2 +1, 1)
Declare Function CreateEllipticRgn& Lib "gdi32" (ByVal X1&, ByVal Y1&, ByVal X2&, ByVal Y2&)
'Declare Function PtInRegion& Lib "gdi32.dll" (ByVal hRgn&, ByVal x&, ByVal y&)
'Declare Function RectInRegion& Lib "gdi32.dll" (ByVal hRgn&, lpRect As RECT)
'Declare Function GetRgnBox Lib "gdi32.dll" (ByVal hRgn As Long, lpRect As RECT) As Long

Type POINTAPI ' Point or Line vector
X As Long
y As Long
End Type
Type RectA
LTRB(3) As Long
End Type
Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
Type BBoxAS
A(5) As Double
R As RectA
P As POINTAPI
S As String
End Type

Type BouBoxCen
TLX As Double
TLY As Double
BRX As Double
BRY As Double
CX As Double
CY As Double
End Type

Type PointDou
X As Double
y As Double
End Type

Public Const RGN_AND = 1 'Calculates the intersection of the two source areas (the area they have in common.)
Public Const RGN_OR = 2 'Calculates the union of the two areas (the area either occupy.)
Public Const RGN_XOR = 3 'Takes the union of the two areas and subtracts their intersecti
Public Const RGN_DIFF = 4 'difference this subtracts the second region from the first
Public Const RGN_COPY = 5 'Returns a copy of the first region, a clone region.
Public Const RGN_MIN = RGN_AND
Public Const RGN_MAX = RGN_COPY
Const ERROR = 0
Const NULLREGION = 1
Const SIMPLEREGION = 2
Const COMPLEXREGION = 3

Public RegLook&(), NumReg&, WsA$()
Public WPA() As POINTAPI
Public AUR&, WUR&, WI&, wPAPI As POINTAPI
Public Const XYOff = 32&, BBFac = 262144, XYFaC& = 65536 '16384'32768'262144'1048576
Public wRectCl As RectCL
 
Upvote 0
To test if a polygon comes within a distance DD# of a path

does any one have a solution for this
given a path as a range of x y points
( distinct start end points)
( 2 ,3,5,.. consecutive line segments may be in line or reverse')
(Path may cross it self)

find a polygon that surrounds the line
as a range of points
so that each line segment of the polygon is a distance DD# from the line's segments
 
Upvote 0
Thanks a lot. This is really useful.
Could you please let me know what changes need in the code for 'not to rejecting point on polygon'?
 
Upvote 0
Could you please let me know what changes need in the code for 'not to rejecting point on polygon'?
I am not exactly sure what your question is. Can you add a little more detail to your description of what you are looking for?
 
Upvote 0
I am not exactly sure what your question is. Can you add a little more detail to your description of what you are looking for?
Hi Rick,
Many thanks for the repose. At the moment function return value "false" if the point on the polygon. I want to return the value "true" even if the point is on the polygon. Thanks.
 
Upvote 0
Hi Rick,
Many thanks for the repose. At the moment function return value "false" if the point on the polygon. I want to return the value "true" even if the point is on the polygon. Thanks.
I hope you got my point Rick.
I meant that I need to check whether a point within polygon or on the polygon.
Tried with a few changes to the code but It was not successful.

Kind Regards,
Shan
 
Upvote 0
I would first point you to Message #4 in this thread. Then I would refer you to the original article in my mini-blog where I first posted my code...

Test Whether A Point Is In A Polygon Or Not

The following are responses I gave as follow ups to people's questions within the above linked article. If you read through the entire thread, you will see them. If you do not want to read the entire thread, I believe these three responses I gave might be of interest to you...

See this link for the answer I gave someone with the same question you are asking...

Test Whether A Point Is In A Polygon Or Not - Page 2

Some thoughts I had about points lying on the polygon itself (note the two links below take you to different Messages even though their text reads the same)...

Test Whether A Point Is In A Polygon Or Not - Page 3

Test Whether A Point Is In A Polygon Or Not - Page 3
 
Upvote 0

Forum statistics

Threads
1,215,479
Messages
6,125,041
Members
449,206
Latest member
Healthydogs

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top