Ray-casting algorithm: Difference between revisions
Added Algol 68
(Added Algol 68) |
|||
(20 intermediate revisions by 12 users not shown) | |||
Line 75:
(To avoid the "ray on vertex" problem, the point is moved upward of a small quantity <big>ε</big>.)
<br><br>
=={{header|11l}}==
{{trans|Python}}
<syntaxhighlight lang="11l">T Pt
Float x, y
F (x, y)
.x = x
.y = y
F String()
R ‘Pt(x=#., y=#.)’.format(.x, .y)
T Edge
Pt a, b
F (a, b)
.a = a
.b = b
F String()
R ‘Edge(a=#., b=#.)’.format(.a, .b)
T Poly
String name
[Edge] edges
F (name, edges)
.name = name
.edges = edges
V _eps = 0.00001
V _huge = 1e+100
V _tiny = 1e-100
F rayintersectseg(=p, edge)
V a = edge.a
V b = edge.b
I a.y > b.y
swap(&a, &b)
I p.y == a.y | p.y == b.y
p = Pt(p.x, p.y + :_eps)
V intersect = 0B
I (p.y > b.y | p.y < a.y) | (p.x > max(a.x, b.x))
R 0B
I p.x < min(a.x, b.x)
intersect = 1B
E
Float m_red, m_blue
I abs(a.x - b.x) > :_tiny
m_red = (b.y - a.y) / Float(b.x - a.x)
E
m_red = :_huge
I abs(a.x - p.x) > :_tiny
m_blue = (p.y - a.y) / Float(p.x - a.x)
E
m_blue = :_huge
intersect = m_blue >= m_red
R intersect
F ispointinside(p, poly)
R sum(poly.edges.map(edge -> Int(rayintersectseg(@p, edge)))) % 2 == 1
F polypp(poly)
print("\n Polygon(name='#.', edges=(".format(poly.name))
print(‘ ’(poly.edges.map(e -> String(e)).join(",\n ")"\n ))"))
V polys = [
Poly(name' ‘square’, edges' [Edge(Pt(0, 0), Pt(10, 0)), Edge(Pt(10, 0), Pt(10, 10)), Edge(Pt(10, 10), Pt(0, 10)), Edge(Pt(0, 10), Pt(0, 0))]),
Poly(name' ‘square_hole’, edges' [Edge(Pt(0, 0), Pt(10, 0)), Edge(Pt(10, 0), Pt(10, 10)), Edge(Pt(10, 10), Pt(0, 10)), Edge(Pt(0, 10), Pt(0, 0)), Edge(Pt(2.5, 2.5), Pt(7.5, 2.5)), Edge(Pt(7.5, 2.5), Pt(7.5, 7.5)), Edge(Pt(7.5, 7.5), Pt(2.5, 7.5)), Edge(Pt(2.5, 7.5), Pt(2.5, 2.5))]),
Poly(name' ‘strange’, edges' [Edge(Pt(0, 0), Pt(2.5, 2.5)), Edge(Pt(2.5, 2.5), Pt(0, 10)), Edge(Pt(0, 10), Pt(2.5, 7.5)), Edge(Pt(2.5, 7.5), Pt(7.5, 7.5)), Edge(Pt(7.5, 7.5), Pt(10, 10)), Edge(Pt(10, 10), Pt(10, 0)), Edge(Pt(10, 0), Pt(2.5, 2.5))]),
Poly(name' ‘exagon’, edges' [Edge(Pt(3, 0), Pt(7, 0)), Edge(Pt(7, 0), Pt(10, 5)), Edge(Pt(10, 5), Pt(7, 10)), Edge(Pt(7, 10), Pt(3, 10)), Edge(Pt(3, 10), Pt(0, 5)), Edge(Pt(0, 5), Pt(3, 0))])]
V testpoints = [Pt(5, 5), Pt(5, 8),
Pt(-10, 5), Pt(0, 5),
Pt(10, 5), Pt(8, 5),
Pt(10, 10)]
print("\n TESTING WHETHER POINTS ARE WITHIN POLYGONS")
L(poly) polys
polypp(poly)
print(‘ ’testpoints[0.<3].map(p -> ‘#.: #.’.format(p, I ispointinside(p, @poly) {‘True’} E ‘False’)).join("\t"))
print(‘ ’testpoints[3.<6].map(p -> ‘#.: #.’.format(p, I ispointinside(p, @poly) {‘True’} E ‘False’)).join("\t"))
print(‘ ’testpoints[6.. ].map(p -> ‘#.: #.’.format(p, I ispointinside(p, @poly) {‘True’} E ‘False’)).join("\t"))</syntaxhighlight>
{{out}}
<pre style="height:20em;overflow:scroll">
TESTING WHETHER POINTS ARE WITHIN POLYGONS
Polygon(name='square', edges=(
Edge(a=Pt(x=0, y=0), b=Pt(x=10, y=0)),
Edge(a=Pt(x=10, y=0), b=Pt(x=10, y=10)),
Edge(a=Pt(x=10, y=10), b=Pt(x=0, y=10)),
Edge(a=Pt(x=0, y=10), b=Pt(x=0, y=0))
))
Pt(x=5, y=5): True Pt(x=5, y=8): True Pt(x=-10, y=5): False
Pt(x=0, y=5): False Pt(x=10, y=5): True Pt(x=8, y=5): True
Pt(x=10, y=10): False
Polygon(name='square_hole', edges=(
Edge(a=Pt(x=0, y=0), b=Pt(x=10, y=0)),
Edge(a=Pt(x=10, y=0), b=Pt(x=10, y=10)),
Edge(a=Pt(x=10, y=10), b=Pt(x=0, y=10)),
Edge(a=Pt(x=0, y=10), b=Pt(x=0, y=0)),
Edge(a=Pt(x=2.5, y=2.5), b=Pt(x=7.5, y=2.5)),
Edge(a=Pt(x=7.5, y=2.5), b=Pt(x=7.5, y=7.5)),
Edge(a=Pt(x=7.5, y=7.5), b=Pt(x=2.5, y=7.5)),
Edge(a=Pt(x=2.5, y=7.5), b=Pt(x=2.5, y=2.5))
))
Pt(x=5, y=5): False Pt(x=5, y=8): True Pt(x=-10, y=5): False
Pt(x=0, y=5): False Pt(x=10, y=5): True Pt(x=8, y=5): True
Pt(x=10, y=10): False
Polygon(name='strange', edges=(
Edge(a=Pt(x=0, y=0), b=Pt(x=2.5, y=2.5)),
Edge(a=Pt(x=2.5, y=2.5), b=Pt(x=0, y=10)),
Edge(a=Pt(x=0, y=10), b=Pt(x=2.5, y=7.5)),
Edge(a=Pt(x=2.5, y=7.5), b=Pt(x=7.5, y=7.5)),
Edge(a=Pt(x=7.5, y=7.5), b=Pt(x=10, y=10)),
Edge(a=Pt(x=10, y=10), b=Pt(x=10, y=0)),
Edge(a=Pt(x=10, y=0), b=Pt(x=2.5, y=2.5))
))
Pt(x=5, y=5): True Pt(x=5, y=8): False Pt(x=-10, y=5): False
Pt(x=0, y=5): False Pt(x=10, y=5): True Pt(x=8, y=5): True
Pt(x=10, y=10): False
Polygon(name='exagon', edges=(
Edge(a=Pt(x=3, y=0), b=Pt(x=7, y=0)),
Edge(a=Pt(x=7, y=0), b=Pt(x=10, y=5)),
Edge(a=Pt(x=10, y=5), b=Pt(x=7, y=10)),
Edge(a=Pt(x=7, y=10), b=Pt(x=3, y=10)),
Edge(a=Pt(x=3, y=10), b=Pt(x=0, y=5)),
Edge(a=Pt(x=0, y=5), b=Pt(x=3, y=0))
))
Pt(x=5, y=5): True Pt(x=5, y=8): True Pt(x=-10, y=5): False
Pt(x=0, y=5): False Pt(x=10, y=5): True Pt(x=8, y=5): True
Pt(x=10, y=10): False
</pre>
=={{header|Ada}}==
polygons.ads:
<
type Point is record
Line 91 ⟶ 234:
function Is_Inside (Who : Point; Where : Polygon) return Boolean;
end Polygons;</
polygons.adb:
<
EPSILON : constant := 0.00001;
Line 180 ⟶ 323:
end Is_Inside;
end Polygons;</
Example use:
main.adb:
<
with Polygons;
procedure Main is
Line 275 ⟶ 418:
Ada.Text_IO.New_Line;
end loop;
end Main;</
Output:
Line 313 ⟶ 456:
Point(8.0,5.0): TRUE
Point(10.0,10.0): FALSE</pre>
=={{header|ALGOL 68}}==
{{Trans|Lua}}
<syntaxhighlight lang="algol68">
BEGIN
MODE POINT = STRUCT( REAL x, y );
MODE POLYGON = STRUCT( STRING name, FLEX[ 1 : 0 ]POINT points );
PROC contains = ( POLYGON self, POINT p )BOOL:
BEGIN
BOOL odd := FALSE, REAL eps = 1e-9;
PROC rayseg = ( POINT p in, a in, b in )BOOL:
BEGIN
PROC max = ( REAL m, n )REAL: IF m > n THEN m ELSE n FI;
PROC min = ( REAL m, n )REAL: IF m < n THEN m ELSE n FI;
POINT p := p in, a := a in, b := b in;
IF y OF a > y OF b THEN POINT t = a; a := b; b := t FI;
IF y OF p = y OF a OR y OF p = y OF b THEN y OF p+:= eps FI;
IF y OF p < y OF a OR y OF p > y OF b OR x OF p > max( x OF a, x OF b )
THEN FALSE
ELIF x OF p < min( x OF a, x OF b )
THEN TRUE
ELSE
REAL red = IF x OF a = x OF b THEN max real ELSE ( y OF b - y OF a ) / ( x OF b - x OF a ) FI;
REAL blu = IF x OF a = x OF p THEN max real ELSE ( y OF p - y OF a ) / ( x OF p - x OF a ) FI;
blu >= red
FI
END # rayseq # ;
INT len points = ( UPB points OF self - LWB points OF self ) + 1;
FOR i FROM LWB points OF self TO UPB points OF self DO
POINT a = ( points OF self )[ i ];
POINT b = ( points OF self )[ ( i MOD len points ) + 1 ];
IF rayseg( p, a, b ) THEN odd := NOT odd FI
OD;
odd
END # contains # ;
[]POLYGON polygons =
( ( "square"
, ( ( 0, 0 ), ( 10, 0 ), ( 10, 10 ), ( 0, 10 ) )
)
, ( "squarehole"
, ( ( 0, 0 ), ( 10, 0 ), ( 10, 10 ), ( 0, 10 ), ( 2.5, 2.5 ), ( 7.5, 2.5 ), ( 7.5, 7.5 ), ( 2.5, 7.5 ) )
)
, ( "strange"
, ( ( 0, 0 ), ( 2.5, 2.5 ), ( 0, 10 ), ( 2.5, 7.5 ), ( 7.5, 7.5 ), ( 10, 10 ), ( 10, 0 ), ( 2.5, 2.5 ) )
)
, ( "hexagon"
, ( ( 3, 0 ), ( 7, 0 ), ( 10, 5 ), ( 7, 10 ), ( 3, 10 ), ( 0, 5 ) )
)
);
[]POINT points = ( ( 5, 5 ), (5 , 8 ), ( -10, 5 ), ( 0, 5 ), ( 10, 5 ), ( 8, 5 ), ( 10, 10 ) );
FOR p FROM LWB polygons TO UPB polygons DO
POLYGON poly = polygons[ p ];
print(( "Does '", name OF poly, "' contain the point..", newline ) );
FOR i FROM LWB points TO UPB points DO
POINT pt = points[ i ];
print( ( " ( ", fixed( x OF pt, -5, 1 ), ", ", fixed( y OF pt, -5, 1 ), " ) " ) );
print( ( IF contains( poly, pt ) THEN " true" ELSE " false" FI, newline ) )
OD;
print( ( newline ) )
OD
END
</syntaxhighlight>
{{out}}
<pre>
Does 'square' contain the point..
( 5.0, 5.0 ) true
( 5.0, 8.0 ) true
( -10.0, 5.0 ) false
( 0.0, 5.0 ) false
( 10.0, 5.0 ) true
( 8.0, 5.0 ) true
( 10.0, 10.0 ) false
Does 'squarehole' contain the point..
( 5.0, 5.0 ) false
( 5.0, 8.0 ) true
( -10.0, 5.0 ) false
( 0.0, 5.0 ) false
( 10.0, 5.0 ) true
( 8.0, 5.0 ) true
( 10.0, 10.0 ) false
Does 'strange' contain the point..
( 5.0, 5.0 ) true
( 5.0, 8.0 ) false
( -10.0, 5.0 ) false
( 0.0, 5.0 ) false
( 10.0, 5.0 ) true
( 8.0, 5.0 ) true
( 10.0, 10.0 ) false
Does 'hexagon' contain the point..
( 5.0, 5.0 ) true
( 5.0, 8.0 ) true
( -10.0, 5.0 ) false
( 0.0, 5.0 ) false
( 10.0, 5.0 ) true
( 8.0, 5.0 ) true
( 10.0, 10.0 ) false
</pre>
=={{header|AutoHotkey}}==
{{works with|AutoHotkey L}}
<syntaxhighlight lang="ahk">Points :=[{x: 5.0, y: 5.0}
, {x: 5.0, y: 8.0}
, {x:-10.0, y: 5.0}
, {x: 0.0, y: 5.0}
, {x: 10.0, y: 5.0}
, {x: 8.0, y: 5.0}
, {x: 10.0, y:10.0}]
Square :=[{x: 0.0, y: 0.0}, {x:10.0, y: 0.0}
, {x:10.0, y: 0.0}, {x:10.0, y:10.0}
, {x:10.0, y:10.0}, {x: 0.0, y:10.0}
, {x: 0.0, y:10.0}, {x: 0.0, y: 0.0}]
Sq_Hole:=[{x: 0.0, y: 0.0}, {x:10.0, y: 0.0}
, {x:10.0, y: 0.0}, {x:10.0, y:10.0}
, {x:10.0, y:10.0}, {x: 0.0, y:10.0}
, {x: 0.0, y:10.0}, {x: 0.0, y: 0.0}
, {x: 2.5, y: 2.5}, {x: 7.5, y: 2.5}
, {x: 7.5, y: 2.5}, {x: 7.5, y: 7.5}
, {x: 7.5, y: 7.5}, {x: 2.5, y: 7.5}
, {x: 2.5, y: 7.5}, {x: 2.5, y: 2.5}]
Strange:=[{x: 0.0, y: 0.0}, {x: 2.5, y: 2.5}
, {x: 2.5, y: 2.5}, {x: 0.0, y:10.0}
, {x: 0.0, y:10.0}, {x: 2.5, y: 7.5}
, {x: 2.5, y: 7.5}, {x: 7.5, y: 7.5}
, {x: 7.5, y: 7.5}, {x:10.0, y:10.0}
, {x:10.0, y:10.0}, {x:10.0, y: 0.0}
, {x:10.0, y: 0.0}, {x: 2.5, y: 2.5}]
Exagon :=[{x: 3.0, y: 0.0}, {x: 7.0, y: 0.0}
, {x: 7.0, y: 0.0}, {x:10.0, y: 5.0}
, {x:10.0, y: 5.0}, {x: 7.0, y:10.0}
, {x: 7.0, y:10.0}, {x: 3.0, y:10.0}
, {x: 3.0, y:10.0}, {x: 0.0, y: 5.0}
, {x: 0.0, y: 5.0}, {x: 3.0, y: 0.0}]
Polygons := {"Square":Square, "Sq_Hole":Sq_Hole, "Strange":Strange, "Exagon":Exagon}
For j, Poly in Polygons
For i, Point in Points
If (point_in_polygon(Point,Poly))
s.= j " does contain point " i "`n"
Else
s.= j " doesn't contain point " i "`n"
Msgbox %s%
point_in_polygon(Point,Poly) {
n:=Poly.MaxIndex()
count:=0
loop, %n% {
if (ray_intersects_segment(Point,Poly[A_Index],Poly[mod(A_Index,n)+1])) {
count++
}
}
if (mod(count,2)) { ; true = inside, false = outside
return true ; P is in the polygon
} else {
return false ; P isn't in the polygon
}
}
ray_intersects_segment(P,A,B) {
;P = the point from which the ray starts
;A = the end-point of the segment with the smallest y coordinate
;B = the end-point of the segment with the greatest y coordinate
if (A.y > B.y) {
temp:=A
A:=B
B:=temp
}
if (P.y = A.y or P.y = B.y) {
P.y += 0.000001
}
if (P.y < A.y or P.y > B.y) {
return false
} else if (P.x > A.x && P.x > B.x) {
return false
} else {
if (P.x < A.x && P.x < B.x) {
return true
} else {
if (A.x != B.x) {
m_red := (B.y - A.y)/(B.x - A.x)
} else {
m_red := "inf"
}
if (A.x != P.x) {
m_blue := (P.y - A.y)/(P.x - A.x)
} else {
m_blue := "inf"
}
if (m_blue >= m_red) {
return true
} else {
return false
}
}
}
}</syntaxhighlight>
{{out}}
<pre>---------------------------
Ray-casting_algorithm.ahkl
---------------------------
Exagon does contain point 1
Exagon does contain point 2
Exagon doesn't contain point 3
Exagon doesn't contain point 4
Exagon does contain point 5
Exagon does contain point 6
Exagon doesn't contain point 7
Sq_Hole doesn't contain point 1
Sq_Hole does contain point 2
Sq_Hole doesn't contain point 3
Sq_Hole doesn't contain point 4
Sq_Hole does contain point 5
Sq_Hole does contain point 6
Sq_Hole doesn't contain point 7
Square does contain point 1
Square does contain point 2
Square doesn't contain point 3
Square doesn't contain point 4
Square does contain point 5
Square does contain point 6
Square doesn't contain point 7
Strange does contain point 1
Strange doesn't contain point 2
Strange doesn't contain point 3
Strange doesn't contain point 4
Strange does contain point 5
Strange does contain point 6
Strange doesn't contain point 7
---------------------------
OK
---------------------------</pre>
=={{header|BASIC}}==
==={{header|ANSI BASIC}}===
{{trans|FreeBASIC}}
{{works with|Decimal BASIC}}
<syntaxhighlight lang="basic">1000 PUBLIC NUMERIC x,y
1010 LET x=1
1020 LET y=2
Line 498 ⟶ 883:
2810 NEXT z
2820 END
</syntaxhighlight>
{{out}}
<pre>
squared
(5,5) in
(5,8) in
(-10,5) out
(0,5) out
(10,5) in
(8,5) in
(10,10) out
squared hole
(5,5) out
(5,8) in
(-10,5) out
(0,5) out
(10,10) out
strange
(5,5) in
(5,8) out
(-10,5) out
(0,5) out
(10,5) in
(8,5) in
(10,10) out
exagon
(5,5) in
(5,8) in
(-10,5) out
(0,5) out
(10,5) in
(8,5) in
(10,10) out
</pre>
=={{header|C}}==
<
#include <stdlib.h>
#include <math.h>
Line 774 ⟶ 1,064:
return 0;
}</
=={{header|C#}}==
{{trans|Java}}
<syntaxhighlight lang="C#">
using System;
class RayCasting {
static bool Intersects(int[] A, int[] B, double[] P) {
if (A[1] > B[1])
return Intersects(B, A, P);
if (P[1] == A[1] || P[1] == B[1])
P[1] += 0.0001;
if (P[1] > B[1] || P[1] < A[1] || P[0] >= Math.Max(A[0], B[0]))
return false;
if (P[0] < Math.Min(A[0], B[0]))
return true;
double red = (P[1] - A[1]) / (P[0] - A[0]);
double blue = (B[1] - A[1]) / (B[0] - A[0]);
return red >= blue;
}
static bool Contains(int[][] shape, double[] pnt) {
bool inside = false;
int len = shape.Length;
for (int i = 0; i < len; i++) {
if (Intersects(shape[i], shape[(i + 1) % len], pnt))
inside = !inside;
}
return inside;
}
public static void Main(string[] args) {
double[][] testPoints = new double[][] {
new double[] { 10, 10 }, new double[] { 10, 16 }, new double[] { -20, 10 },
new double[] { 0, 10 }, new double[] { 20, 10 }, new double[] { 16, 10 },
new double[] { 20, 20 }
};
foreach (int[][] shape in shapes) {
foreach (double[] pnt in testPoints)
Console.Write($"{Contains(shape, pnt),7} ");
Console.WriteLine();
}
}
readonly static int[][] square = new int[][] {
new int[] { 0, 0 }, new int[] { 20, 0 }, new int[] { 20, 20 }, new int[] { 0, 20 }
};
readonly static int[][] squareHole = new int[][] {
new int[] { 0, 0 }, new int[] { 20, 0 }, new int[] { 20, 20 }, new int[] { 0, 20 },
new int[] { 5, 5 }, new int[] { 15, 5 }, new int[] { 15, 15 }, new int[] { 5, 15 }
};
readonly static int[][] strange = new int[][] {
new int[] { 0, 0 }, new int[] { 5, 5 }, new int[] { 0, 20 }, new int[] { 5, 15 },
new int[] { 15, 15 }, new int[] { 20, 20 }, new int[] { 20, 0 }
};
readonly static int[][] hexagon = new int[][] {
new int[] { 6, 0 }, new int[] { 14, 0 }, new int[] { 20, 10 }, new int[] { 14, 20 },
new int[] { 6, 20 }, new int[] { 0, 10 }
};
readonly static int[][][] shapes = new int[][][] { square, squareHole, strange, hexagon };
}
</syntaxhighlight>
{{out}}
<pre>
True True False True False True False
False True False False False True False
True False False False False True False
True True False False False True False
</pre>
=={{header|C++}}==
{{works with|C++|11}}
{{trans|D}}
<
#include <cstdlib>
#include <iomanip>
Line 859 ⟶ 1,231:
return EXIT_SUCCESS;
}</
{{output}}
As D.
Line 865 ⟶ 1,237:
=={{header|CoffeeScript}}==
Takes a polygon as a list of points joining segments, and creates segments between them.
<
pointInPoly = (point,poly) ->
Line 892 ⟶ 1,264:
mAB = (b.y - a.y) / (b.x - a.x)
mAP = (p.y - a.y) / (p.x - a.x)
mAP > mAB</
=={{header|Common Lisp}}==
Points are represented as cons cells whose car is an x value and whose cdr is a y value. A line segment is a cons cell of two points. A polygon is a list of line segments.
<
(do ((in-p nil)) ((endp polygon) in-p)
(when (ray-intersects-segment point (pop polygon))
Line 925 ⟶ 1,297:
((null m-blue) t)
((null m-red) nil)
(t (>= m-blue m-red)))))))))</
Testing code
<
#((0 . 0) (10 . 0) (10 . 10) (0 . 10)
(2.5 . 2.5) (7.5 . 2.5) (7.5 . 7.5) (2.5 . 7.5)
Line 962 ⟶ 1,334:
do (format t "~&~w ~:[outside~;inside ~]."
test-point
(point-in-polygon test-point polygon)))))</
=={{header|D}}==
<
immutable struct Point { double x, y; }
Line 1,032 ⟶ 1,404:
writeln;
}
}</
{{out}}
<pre>Is point inside figure "Square"?
Line 1,072 ⟶ 1,444:
=={{header|Factor}}==
To test whether a ray intersects a line, we test that the starting point is between the endpoints in y value, and that it is to the left of the point on the segment with the same y value. Note that this implementation does not support polygons with horizontal edges.
<
IN: raycasting
Line 1,090 ⟶ 1,462:
[ dup first suffix [ rest-slice ] [ but-last-slice ] bi ] dip
[ ray ] curry 2map
f [ xor ] reduce ;</
Usage:
<
( scratchpad ) square { 0 0 } raycast .
t
Line 1,098 ⟶ 1,470:
f
( scratchpad ) square { 2 0 } raycast .
f</
=={{header|Fortran}}==
Line 1,105 ⟶ 1,477:
This module ''defines'' "polygons".
<
use Points_Module
implicit none
Line 1,139 ⟶ 1,511:
end subroutine free_polygon
end module Polygons</
The ray casting algorithm module:
<
use Polygons
implicit none
Line 1,218 ⟶ 1,590:
end function point_is_inside
end module Ray_Casting_Algo</
'''Testing'''
<
use Points_Module
use Ray_Casting_Algo
Line 1,260 ⟶ 1,632:
end do
end program Pointpoly</
=={{header|FreeBASIC}}==
Inpolygon by Winding number method
<
As Single x,y
End Type
Line 1,377 ⟶ 1,749:
End Select
Next z
Sleep</
Output:
<pre>squared
Line 1,419 ⟶ 1,791:
The first solution given here follows the model of most other solutions on the page in defining a polygon as a list of segments. Unfortunately this representation does not require that the polygon is ''closed''. Input to the ray-casting algorithm, as noted in the WP article though, is specified to be a closed polygon. The "strange" shape defined here is not a closed polygon and so gives incorrect results against some points. (Graphically it may appear closed but mathematically it needs an additional segment returning to the starting point.)
<
import (
Line 1,520 ⟶ 1,892:
}
}
}</
{{out}}
<pre>
Line 1,567 ⟶ 1,939:
Here input is given as a list of N vertices defining N segments, where one segment extends from each vertex to the next, and one more extends from the last vertex to the first. In the case of the "strange" shape, this mathematically closes the polygon and allows the program to give correct results.
<
import (
Line 1,642 ⟶ 2,014:
}
}
}</
{{out}}
<pre>
Line 1,663 ⟶ 2,035:
This solution is preferred over the two above.
<syntaxhighlight lang="text">package main
import "fmt"
Line 1,712 ⟶ 2,084:
}
}
}</
=={{header|Haskell}}==
<
type Point = (Rational, Rational)
Line 1,763 ⟶ 2,135:
(py /= by || ay < py)
((ax, ay), (bx, by)) = side
line = carrier side</
=={{header|J}}==
<
NB. bool=. points crossPnP polygon
crossPnP=: 4 : 0"2
Line 1,774 ⟶ 2,146:
p2=. (x0-/X) < (x0-x1) * (y0-/Y) % (y0 - y1)
2|+/ p1*.p2
)</
Sample data:
<
SQUAREV=: SQUAREV, 2.5 2.5 , 7.5 0.1 , 7.5 7.5 ,: 2.5 7.5
Line 1,787 ⟶ 2,159:
STRANGE=: (0 4,4 3,3 7,7 6,6 2,2 1,1 5,:5 0) , .{ SQUAREV
POINTS=: 5 5,5 8,2 2,0 0,10 10,2.5 2.5,0.01 5,2.2 7.4,0 5,10 5,:_4 10</
Testing:
<
1 1 1 0 0 1 1 1 0 1 0
1 1 1 0 0 1 1 1 0 1 0
0 1 1 0 0 1 1 1 0 1 0
1 0 0 0 0 0 0 1 0 1 0</
=={{header|Java}}==
<
public class RayCasting {
Line 1,852 ⟶ 2,224:
final static int[][][] shapes = {square, squareHole, strange, hexagon};
}</
<pre>
false
true
true true false false false true false
</pre>
=={{header|Javascript}}==
<
/**
* @return {boolean} true if (lng, lat) is in bounds
Line 1,919 ⟶ 2,293:
}
}
</syntaxhighlight>
=={{header|Julia}}==
{{trans|Python}}
'''Module''':
<
export Point
Line 1,970 ⟶ 2,343:
[(a, b) for (a, b) in zip(vcat(a, b...), vcat(b..., a))]
end # module RayCastings</
'''Main''':
<syntaxhighlight lang
let A = Point(0.0, 0.0),
B = Point(0.0, 10.0),
C = Point(10.0, 10.0),
Line 2,003 ⟶ 2,378:
end
end
end</
{{out}}
Line 2,076 ⟶ 2,451:
=={{header|Kotlin}}==
{{trans|D}}
<
import java.lang.Double.MIN_VALUE
import java.lang.Math.abs
Line 2,111 ⟶ 2,486:
}
}
}</
<
val figures = arrayOf(Figure("Square", arrayOf(Edge(Point(0.0, 0.0), Point(10.0, 0.0)), Edge(Point(10.0, 0.0), Point(10.0, 10.0)),
Edge(Point(10.0, 10.0), Point(0.0, 10.0)),Edge(Point(0.0, 10.0), Point(0.0, 0.0)))),
Line 2,128 ⟶ 2,503:
Ray_casting.check(figures, points)
}</
{{out}}
<pre>points: [Point(x=5.0, y=5.0), Point(x=5.0, y=8.0), Point(x=-10.0, y=5.0), Point(x=0.0, y=5.0), Point(x=10.0, y=5.0), Point(x=8.0, y=5.0), Point(x=10.0, y=10.0)]
Line 2,170 ⟶ 2,545:
Displays interactively on-screen.
<
Global sw, sh, verts
Line 2,245 ⟶ 2,620:
Function rand(loNum,hiNum)
rand = Int(Rnd(0)*(hiNum-loNum+1)+loNum)
End Function </
=={{header|Lua}}==
<syntaxhighlight lang="lua">function Point(x,y) return {x=x, y=y} end
function Polygon(name, points)
local function contains(self, p)
local odd, eps = false, 1e-9
local function rayseg(p, a, b)
if a.y > b.y then a, b = b, a end
if p.y == a.y or p.y == b.y then p.y = p.y + eps end
if p.y < a.y or p.y > b.y or p.x > math.max(a.x, b.x) then return false end
if p.x < math.min(a.x, b.x) then return true end
local red = a.x == b.x and math.huge or (b.y-a.y)/(b.x-a.x)
local blu = a.x == p.x and math.huge or (p.y-a.y)/(p.x-a.x)
return blu >= red
end
for i, a in ipairs(self.points) do
local b = self.points[i%#self.points+1]
if rayseg(p, a, b) then odd = not odd end
end
return odd
end
return {name=name, points=points, contains=contains}
end
polygons = {
Polygon("square", { Point(0,0), Point(10,0), Point(10,10), Point(0,10) }),
Polygon("squarehole", { Point(0,0), Point(10,0), Point(10,10), Point(0,10), Point(2.5,2.5), Point(7.5,2.5), Point(7.5,7.5), Point(2.5,7.5) }),
Polygon("strange", { Point(0,0), Point(2.5,2.5), Point(0, 10), Point(2.5,7.5), Point(7.5,7.5), Point(10,10), Point(10,0), Point(2.5,2.5) }),
Polygon("hexagon", { Point(3,0), Point(7,0), Point(10,5), Point(7,10), Point(3,10), Point(0,5) })
}
points = { Point(5,5), Point(5,8), Point(-10,5), Point(0,5), Point(10,5), Point(8,5), Point(10,10) }
for _,poly in ipairs(polygons) do
print("Does '"..poly.name.."' contain the point..")
for _,pt in ipairs(points) do
print(string.format(" (%3.f, %2.f)? %s", pt.x, pt.y, tostring(poly:contains(pt))))
end
print()
end</syntaxhighlight>
{{out}}
<pre>Does 'square' contain..
( 5, 5)? true
( 5, 8)? true
(-10, 5)? false
( 0, 5)? false
( 10, 5)? true
( 8, 5)? true
( 10, 10)? false
Does 'squarehole' contain..
( 5, 5)? false
( 5, 8)? true
(-10, 5)? false
( 0, 5)? false
( 10, 5)? true
( 8, 5)? true
( 10, 10)? false
Does 'strange' contain..
( 5, 5)? true
( 5, 8)? false
(-10, 5)? false
( 0, 5)? false
( 10, 5)? true
( 8, 5)? true
( 10, 10)? false
Does 'hexagon' contain..
( 5, 5)? true
( 5, 8)? true
(-10, 5)? false
( 0, 5)? false
( 10, 5)? true
( 8, 5)? true
( 10, 10)? false</pre>
=={{header|Nim}}==
{{trans|D}}
<syntaxhighlight lang="nim">import fenv, sequtils, strformat
type
Point = tuple[x, y: float]
Edge = tuple[a, b: Point]
Figure = tuple[name: string; edges: seq[Edge]]
func contains(poly: Figure; p: Point): bool =
func raySegI(p: Point; edge: Edge): bool =
const Epsilon = 0.00001
if edge.a.y > edge.b.y:
# Swap "a" and "b".
return p.raySegI((edge.b, edge.a))
if p.y == edge.a.y or p.y == edge.b.y:
# p.y += Epsilon.
return (p.x, p.y + Epsilon).raySegI(edge)
if p.y > edge.b.y or p.y < edge.a.y or p.x > max(edge.a.x, edge.b.x):
return false
if p.x < min(edge.a.x, edge.b.x):
return true
let blue = if abs(edge.a.x - p.x) > minimumPositiveValue(float):
(p.y - edge.a.y) / (p.x - edge.a.x)
else:
maximumPositiveValue(float)
let red = if abs(edge.a.x - edge.b.x) > minimumPositiveValue(float):
(edge.b.y - edge.a.y) / (edge.b.x - edge.a.x)
else:
maximumPositiveValue(float)
result = blue >= red
result = (poly.edges.filterIt(p.raySegI(it)).len and 1) != 0
when isMainModule:
const
Polys: array[4, Figure] =
[("Square",
@[(( 0.0, 0.0), (10.0, 0.0)), ((10.0, 0.0), (10.0, 10.0)),
((10.0, 10.0), ( 0.0, 10.0)), (( 0.0, 10.0), ( 0.0, 0.0))]),
("Square hole",
@[(( 0.0, 0.0), (10.0, 0.0)), ((10.0, 0.0), (10.0, 10.0)),
((10.0, 10.0), ( 0.0, 10.0)), (( 0.0, 10.0), ( 0.0, 0.0)),
(( 2.5, 2.5), ( 7.5, 2.5)), (( 7.5, 2.5), ( 7.5, 7.5)),
(( 7.5, 7.5), ( 2.5, 7.5)), (( 2.5, 7.5), ( 2.5, 2.5))]),
("Strange",
@[(( 0.0, 0.0), ( 2.5, 2.5)), (( 2.5, 2.5), ( 0.0, 10.0)),
(( 0.0, 10.0), ( 2.5, 7.5)), (( 2.5, 7.5), ( 7.5, 7.5)),
(( 7.5, 7.5), (10.0, 10.0)), ((10.0, 10.0), (10.0, 0.0)),
((10.0, 0.0), ( 2.5, 2.5))]),
("Hexagon",
@[(( 3.0, 0.0), ( 7.0, 0.0)), (( 7.0, 0.0), (10.0, 5.0)),
((10.0, 5.0), ( 7.0, 10.0)), (( 7.0, 10.0), ( 3.0, 10.0)),
(( 3.0, 10.0), ( 0.0, 5.0)), (( 0.0, 5.0), ( 3.0, 0.0))])
]
TestPoints: array[7, Point] =
[(5.0, 5.0), (5.0, 8.0), (-10.0, 5.0), (0.0, 5.0), (10.0, 5.0), (8.0, 5.0), (10.0, 10.0)]
for poly in Polys:
echo &"Is point inside figure {poly.name}?"
for p in TestPoints:
echo &" ({p.x:3},{p.y:3}): {poly.contains(p)}"</syntaxhighlight>
{{out}}
<pre>Is point inside figure Square?
( 5, 5): true
( 5, 8): true
(-10, 5): false
( 0, 5): false
( 10, 5): true
( 8, 5): true
( 10, 10): false
Is point inside figure Square hole?
( 5, 5): false
( 5, 8): true
(-10, 5): false
( 0, 5): false
( 10, 5): true
( 8, 5): true
( 10, 10): false
Is point inside figure Strange?
( 5, 5): true
( 5, 8): false
(-10, 5): false
( 0, 5): false
( 10, 5): true
( 8, 5): true
( 10, 10): false
Is point inside figure Hexagon?
( 5, 5): true
( 5, 8): true
(-10, 5): false
( 0, 5): false
( 10, 5): true
( 8, 5): true
( 10, 10): false</pre>
=={{header|OCaml}}==
{{Trans|C}}
<
type polygon = {
Line 2,345 ⟶ 2,898:
print_newline()
) test_points;
;;</
=={{header|Perl}}==
<
use List::Util qw(max min);
Line 2,385 ⟶ 2,938:
return ($m_blue >= $m_red) ? 1 : 0;
}</
Testing:
<
sub point
{
Line 2,426 ⟶ 2,979:
( point_in_polygon($tp, $rp) ? "INSIDE" : "OUTSIDE" ) . "\n";
}
}</
=={{header|Phix}}==
<!--<syntaxhighlight lang="phix">-->
<span style="color: #008080;">constant</span> <span style="color: #000000;">inf</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1e300</span><span style="color: #0000FF;">*</span><span style="color: #000000;">1e300</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">rayIntersectsSegment</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">point</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">segment</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">sequence</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">segment</span>
<span style="color: #004080;">atom</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">pX</span><span style="color: #0000FF;">,</span><span style="color: #000000;">pY</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">point</span><span style="color: #0000FF;">,</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">aX</span><span style="color: #0000FF;">,</span><span style="color: #000000;">aY</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">bX</span><span style="color: #0000FF;">,</span><span style="color: #000000;">bY</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">,</span>
<span style="color: #000000;">m_red</span><span style="color: #0000FF;">,</span><span style="color: #000000;">m_blue</span>
<span style="color: #000080;font-style:italic;">-- ensure {aX,aY} is the segment end-point with the smallest y coordinate</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">aY</span><span style="color: #0000FF;">></span><span style="color: #000000;">bY</span> <span style="color: #008080;">then</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">bX</span><span style="color: #0000FF;">,</span><span style="color: #000000;">bY</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">a</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">aX</span><span style="color: #0000FF;">,</span><span style="color: #000000;">aY</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">b</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">pY</span><span style="color: #0000FF;">=</span><span style="color: #000000;">aY</span> <span style="color: #008080;">or</span> <span style="color: #000000;">pY</span><span style="color: #0000FF;">=</span><span style="color: #000000;">bY</span> <span style="color: #008080;">then</span>
<span style="color: #000080;font-style:italic;">--
-- Consider a ray passing through the top or left corner of a diamond:
-- /
-- --- or -
-- ^ \
-- In both cases it touches both edges, but ends up outside in the
-- top case, whereas it ends up inside in the left case. Just move
-- the y co-ordinate down a smidge and it'll work properly, by
-- missing one line in the left/right cases and hitting both/none
-- in the top/bottom cases.
--</span>
<span style="color: #000000;">pY</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">0.000001</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">pY</span><span style="color: #0000FF;"><</span><span style="color: #000000;">aY</span> <span style="color: #008080;">or</span> <span style="color: #000000;">pY</span><span style="color: #0000FF;">></span><span style="color: #000000;">bY</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #004600;">false</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">pX</span><span style="color: #0000FF;">></span><span style="color: #7060A8;">max</span><span style="color: #0000FF;">(</span><span style="color: #000000;">aX</span><span style="color: #0000FF;">,</span><span style="color: #000000;">bX</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #004600;">false</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">pX</span><span style="color: #0000FF;"><</span><span style="color: #7060A8;">min</span><span style="color: #0000FF;">(</span><span style="color: #000000;">aX</span><span style="color: #0000FF;">,</span><span style="color: #000000;">bX</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #004600;">true</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">aX</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">bX</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">m_red</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">bY</span><span style="color: #0000FF;">-</span><span style="color: #000000;">aY</span><span style="color: #0000FF;">)/(</span><span style="color: #000000;">bX</span><span style="color: #0000FF;">-</span><span style="color: #000000;">aX</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">else</span>
<span style="color: #000000;">m_red</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">inf</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">aX</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">pX</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">m_blue</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">pY</span><span style="color: #0000FF;">-</span><span style="color: #000000;">aY</span><span style="color: #0000FF;">)/(</span><span style="color: #000000;">pX</span><span style="color: #0000FF;">-</span><span style="color: #000000;">aX</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">else</span>
<span style="color: #000000;">m_blue</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">inf</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">m_blue</span> <span style="color: #0000FF;">>=</span> <span style="color: #000000;">m_red</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">inside</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">point</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">sequence</span> <span style="color: #000000;">poly</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">bool</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #004600;">false</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">poly</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">rayIntersectsSegment</span><span style="color: #0000FF;">(</span><span style="color: #000000;">point</span><span style="color: #0000FF;">,</span><span style="color: #000000;">poly</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">])</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #008080;">not</span> <span style="color: #000000;">res</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">instr</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">flag</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">expected</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">string</span> <span style="color: #000000;">res</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span><span style="color: #008000;">"in"</span><span style="color: #0000FF;">,</span> <span style="color: #008000;">"out"</span><span style="color: #0000FF;">}[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">-</span><span style="color: #000000;">flag</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">flag</span><span style="color: #0000FF;">!=</span><span style="color: #000000;">expected</span> <span style="color: #008080;">then</span>
<span style="color: #000000;">res</span> <span style="color: #0000FF;">&=</span> <span style="color: #008000;">"*** ERROR ***"</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">return</span> <span style="color: #000000;">res</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">function</span> <span style="color: #000000;">instar</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">flag</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">return</span> <span style="color: #008000;">"* "</span><span style="color: #0000FF;">[</span><span style="color: #000000;">2</span><span style="color: #0000FF;">-</span><span style="color: #000000;">flag</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">test_points</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">5</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">8</span><span style="color: #0000FF;">},{-</span><span style="color: #000000;">10</span><span style="color: #0000FF;">,</span><span style="color: #000000;">5</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">5</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">10</span><span style="color: #0000FF;">,</span><span style="color: #000000;">5</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">8</span><span style="color: #0000FF;">,</span><span style="color: #000000;">5</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">10</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">}}</span>
<span style="color: #000080;font-style:italic;">--constant NAME = 1, POLY = 2, EXPECTED = 3</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">test_polygons</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"square"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{{{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">10</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">}},{{</span><span style="color: #000000;">10</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">10</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">}},{{</span><span style="color: #000000;">10</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">}},{{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">}}},</span>
<span style="color: #0000FF;">{</span><span style="color: #004600;">true</span><span style="color: #0000FF;">,</span><span style="color: #004600;">true</span><span style="color: #0000FF;">,</span><span style="color: #004600;">false</span><span style="color: #0000FF;">,</span><span style="color: #004600;">false</span><span style="color: #0000FF;">,</span><span style="color: #004600;">true</span><span style="color: #0000FF;">,</span><span style="color: #004600;">true</span><span style="color: #0000FF;">,</span><span style="color: #004600;">false</span><span style="color: #0000FF;">}},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"square hole"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{{{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">10</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">}},{{</span><span style="color: #000000;">10</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">10</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">}},{{</span><span style="color: #000000;">10</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">}},{{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">}},</span>
<span style="color: #0000FF;">{{</span><span style="color: #000000;">2.5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2.5</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">7.5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2.5</span><span style="color: #0000FF;">}},{{</span><span style="color: #000000;">7.5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2.5</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">7.5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">7.5</span><span style="color: #0000FF;">}},{{</span><span style="color: #000000;">7.5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">7.5</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">2.5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">7.5</span><span style="color: #0000FF;">}},{{</span><span style="color: #000000;">2.5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">7.5</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">2.5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2.5</span><span style="color: #0000FF;">}}},</span>
<span style="color: #0000FF;">{</span><span style="color: #004600;">false</span><span style="color: #0000FF;">,</span><span style="color: #004600;">true</span><span style="color: #0000FF;">,</span><span style="color: #004600;">false</span><span style="color: #0000FF;">,</span><span style="color: #004600;">false</span><span style="color: #0000FF;">,</span><span style="color: #004600;">true</span><span style="color: #0000FF;">,</span><span style="color: #004600;">true</span><span style="color: #0000FF;">,</span><span style="color: #004600;">false</span><span style="color: #0000FF;">}},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"strange"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{{{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">5</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">2.5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2.5</span><span style="color: #0000FF;">}},{{</span><span style="color: #000000;">2.5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2.5</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">}},{{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">2.5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">7.5</span><span style="color: #0000FF;">}},{{</span><span style="color: #000000;">2.5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">7.5</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">7.5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">7.5</span><span style="color: #0000FF;">}},</span>
<span style="color: #0000FF;">{{</span><span style="color: #000000;">7.5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">7.5</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">10</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">}},{{</span><span style="color: #000000;">10</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">10</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">}},{{</span><span style="color: #000000;">10</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">2.5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2.5</span><span style="color: #0000FF;">}}},</span>
<span style="color: #0000FF;">{</span><span style="color: #004600;">true</span><span style="color: #0000FF;">,</span><span style="color: #004600;">false</span><span style="color: #0000FF;">,</span><span style="color: #004600;">false</span><span style="color: #0000FF;">,</span><span style="color: #004600;">false</span><span style="color: #0000FF;">,</span><span style="color: #004600;">true</span><span style="color: #0000FF;">,</span><span style="color: #004600;">true</span><span style="color: #0000FF;">,</span><span style="color: #004600;">false</span><span style="color: #0000FF;">}},</span>
<span style="color: #0000FF;">{</span><span style="color: #008000;">"exagon"</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">{{{</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">7</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">}},{{</span><span style="color: #000000;">7</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">10</span><span style="color: #0000FF;">,</span><span style="color: #000000;">5</span><span style="color: #0000FF;">}},{{</span><span style="color: #000000;">10</span><span style="color: #0000FF;">,</span><span style="color: #000000;">5</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">7</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">}},{{</span><span style="color: #000000;">7</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">}},{{</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">5</span><span style="color: #0000FF;">}},{{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">5</span><span style="color: #0000FF;">},{</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">}}},</span>
<span style="color: #0000FF;">{</span><span style="color: #004600;">true</span><span style="color: #0000FF;">,</span><span style="color: #004600;">true</span><span style="color: #0000FF;">,</span><span style="color: #004600;">false</span><span style="color: #0000FF;">,</span><span style="color: #004600;">false</span><span style="color: #0000FF;">,</span><span style="color: #004600;">true</span><span style="color: #0000FF;">,</span><span style="color: #004600;">true</span><span style="color: #0000FF;">,</span><span style="color: #004600;">false</span><span style="color: #0000FF;">}}</span>
<span style="color: #0000FF;">}</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">name</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">poly</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">expected</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">tp</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">test_polygons</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #0000FF;">{</span><span style="color: #000000;">name</span><span style="color: #0000FF;">,</span><span style="color: #000000;">poly</span><span style="color: #0000FF;">,</span><span style="color: #000000;">expected</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">test_polygons</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">]</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\n%12s:"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">name</span><span style="color: #0000FF;">})</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">test_points</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">tp</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">test_points</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">" %s, %-4s"</span><span style="color: #0000FF;">,{</span><span style="color: #7060A8;">sprint</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tp</span><span style="color: #0000FF;">),</span><span style="color: #000000;">instr</span><span style="color: #0000FF;">(</span><span style="color: #000000;">inside</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tp</span><span style="color: #0000FF;">,</span><span style="color: #000000;">poly</span><span style="color: #0000FF;">),</span><span style="color: #000000;">expected</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">])})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\n\n\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">10</span> <span style="color: #008080;">do</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">test_polygons</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">do</span>
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">" "</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">poly</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">test_polygons</span><span style="color: #0000FF;">[</span><span style="color: #000000;">j</span><span style="color: #0000FF;">][</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">k</span><span style="color: #0000FF;">=</span><span style="color: #000000;">0</span> <span style="color: #008080;">to</span> <span style="color: #000000;">10</span> <span style="color: #008080;">do</span>
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">instar</span><span style="color: #0000FF;">(</span><span style="color: #000000;">inside</span><span style="color: #0000FF;">({</span><span style="color: #000000;">k</span><span style="color: #0000FF;">+</span><span style="color: #000000;">0.5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10.5</span><span style="color: #0000FF;">-</span><span style="color: #000000;">i</span><span style="color: #0000FF;">},</span><span style="color: #000000;">poly</span><span style="color: #0000FF;">)))</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #7060A8;">puts</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"\n"</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
Line 2,656 ⟶ 3,106:
********** ********** **** ******
********** ********** * ****
</pre>
=={{header|PHP}}==
<syntaxhighlight lang="php">
<?php
function contains($bounds, $lat, $lng)
{
$count = 0;
$bounds_count = count($bounds);
for ($b = 0; $b < $bounds_count; $b++) {
$vertex1 = $bounds[$b];
$vertex2 = $bounds[($b + 1) % $bounds_count];
if (west($vertex1, $vertex2, $lng, $lat))
$count++;
}
return $count % 2;
}
function west($A, $B, $x, $y)
{
if ($A['y'] <= $B['y']) {
if ($y <= $A['y'] || $y > $B['y'] ||
$x >= $A['x'] && $x >= $B['x']) {
return false;
}
if ($x < $A['x'] && $x < $B['x']) {
return true;
}
if ($x == $A['x']) {
if ($y == $A['y']) {
$result1 = NAN;
} else {
$result1 = INF;
}
} else {
$result1 = ($y - $A['y']) / ($x - $A['x']);
}
if ($B['x'] == $A['x']) {
if ($B['y'] == $A['y']) {
$result2 = NAN;
} else {
$result2 = INF;
}
} else {
$result2 = ($B['y'] - $A['y']) / ($B['x'] - $A['x']);
}
return $result1 > $result2;
}
return west($B, $A, $x, $y);
}
$square = [
'name' => 'square',
'bounds' => [['x' => 0, 'y' => 0], ['x' => 20, 'y' => 0], ['x' => 20, 'y' => 20], ['x' => 0, 'y' => 20]]
];
$squareHole = [
'name' => 'squareHole',
'bounds' => [['x' => 0, 'y' => 0], ['x' => 20, 'y' => 0], ['x' => 20, 'y' => 20], ['x' => 0, 'y' => 20], ['x' => 5, 'y' => 5], ['x' => 15, 'y' => 5], ['x' => 15, 'y' => 15], ['x' => 5, 'y' => 15]]
];
$strange = [
'name' => 'strange',
'bounds' => [['x' => 0, 'y' => 0], ['x' => 5, 'y' => 5], ['x' => 0, 'y' => 20], ['x' => 5, 'y' => 15], ['x' => 15, 'y' => 15], ['x' => 20, 'y' => 20], ['x' => 20, 'y' => 0]]
];
$hexagon = [
'name' => 'hexagon',
'bounds' => [['x' => 6, 'y' => 0], ['x' => 14, 'y' => 0], ['x' => 20, 'y' => 10], ['x' => 14, 'y' => 20], ['x' => 6, 'y' => 20], ['x' => 0, 'y' => 10]]
];
$shapes = [$square, $squareHole, $strange, $hexagon];
$testPoints = [
['lng' => 10, 'lat' => 10],
['lng' => 10, 'lat' => 16],
['lng' => -20, 'lat' => 10],
['lng' => 0, 'lat' => 10],
['lng' => 20, 'lat' => 10],
['lng' => 16, 'lat' => 10],
['lng' => 20, 'lat' => 20]
];
for ($s = 0; $s < count($shapes); $s++) {
$shape = $shapes[$s];
for ($tp = 0; $tp < count($testPoints); $tp++) {
$testPoint = $testPoints[$tp];
echo json_encode($testPoint) . "\tin " . $shape['name'] . "\t" . contains($shape['bounds'], $testPoint['lat'], $testPoint['lng']) . PHP_EOL;
}
}</syntaxhighlight>
{{out}}<pre>{"lng":10,"lat":10} in square 1
{"lng":10,"lat":16} in square 1
{"lng":-20,"lat":10} in square 0
{"lng":0,"lat":10} in square 1
{"lng":20,"lat":10} in square 0
{"lng":16,"lat":10} in square 1
{"lng":20,"lat":20} in square 0
{"lng":10,"lat":10} in squareHole 0
{"lng":10,"lat":16} in squareHole 1
{"lng":-20,"lat":10} in squareHole 0
{"lng":0,"lat":10} in squareHole 0
{"lng":20,"lat":10} in squareHole 0
{"lng":16,"lat":10} in squareHole 1
{"lng":20,"lat":20} in squareHole 0
{"lng":10,"lat":10} in strange 1
{"lng":10,"lat":16} in strange 0
{"lng":-20,"lat":10} in strange 0
{"lng":0,"lat":10} in strange 0
{"lng":20,"lat":10} in strange 0
{"lng":16,"lat":10} in strange 1
{"lng":20,"lat":20} in strange 0
{"lng":10,"lat":10} in hexagon 1
{"lng":10,"lat":16} in hexagon 1
{"lng":-20,"lat":10} in hexagon 0
{"lng":0,"lat":10} in hexagon 1
{"lng":20,"lat":10} in hexagon 0
{"lng":16,"lat":10} in hexagon 1
{"lng":20,"lat":20} in hexagon 0
</pre>
=={{header|PicoLisp}}==
<
(de intersects (Px Py Ax Ay Bx By)
Line 2,685 ⟶ 3,253:
(when (apply intersects Edge (car Pt) (cdr Pt))
(onOff Res) ) )
Res ) )</
Test data:
<pre style="height:20em;overflow:scroll">(de Square
Line 2,782 ⟶ 3,350:
=={{header|PureBasic}}==
The code below is includes a GUI for drawing a polygon with the mouse that constantly tests whether the mouse is inside or outside the polygon. It displays a message and changes the windows color slightly to indicate if the pointer is inside or outside the polygon being drawn. The routine that does the checking is called inpoly() and it returns a value of one if the point is with the polygon and zero if it isn't.
<
x.f
y.f
Line 2,864 ⟶ 3,432:
FlipBuffers()
Until KeyboardReleased(#PB_Key_Escape) Or EventID = #PB_Event_CloseWindow</
=={{header|Python}}==
<
from pprint import pprint as pp
import sys
Line 2,968 ⟶ 3,536:
for p in testpoints[3:6]))
print (' ', '\t'.join("%s: %s" % (p, ispointinside(p, poly))
for p in testpoints[6:]))</
'''Sample output'''
Line 3,024 ⟶ 3,592:
'''Helper routine to convert Fortran Polygons and points to Python'''
<
point = Pt
pts = (point(0,0), point(10,0), point(10,10), point(0,10),
Line 3,050 ⟶ 3,618:
print ' ', ',\n '.join(str(e) for e in p.edges) + '\n )),'
print ' ]'
_convert_fortran_shapes()</
=={{header|R}}==
<
count <- 0
for(side in polygon) {
Line 3,096 ⟶ 3,664:
}
}
}</
<
point <- function(x,y) list(x=x, y=y)
Line 3,110 ⟶ 3,678:
}
pol
}</
<
pts <- list(point(0,0), point(10,0), point(10,10), point(0,10),
Line 3,137 ⟶ 3,705:
p$x, p$y, point_in_polygon(polygons[[polysi]], p), names(polygons[polysi])))
}
}</
=={{header|Racket}}==
Straightforward implementation of pseudocode
<
#lang racket
Line 3,223 ⟶ 3,791:
(test-figure square "square")
(test-figure exagon "exagon")
</syntaxhighlight>
{{out}}
Line 3,245 ⟶ 3,813:
testing (point 10.0 10.0): #f
</pre>
=={{header|Raku}}==
(formerly Perl 6)
<syntaxhighlight lang="raku" line>constant ε = 0.0001;
sub ray-hits-seg([\Px,\Py], [[\Ax,\Ay], [\Bx,\By]] --> Bool) {
Py += ε if Py == Ay | By;
if Py < Ay or Py > By or Px > (Ax max Bx) {
False;
}
elsif Px < (Ax min Bx) {
True;
}
else {
my \red = Ax == Bx ?? Inf !! (By - Ay) / (Bx - Ax);
my \blue = Ax == Px ?? Inf !! (Py - Ay) / (Px - Ax);
blue >= red;
}
}
sub point-in-poly(@point, @polygon --> Bool) {
so 2 R% [+] gather for @polygon -> @side {
take ray-hits-seg @point, @side.sort(*.[1]);
}
}
my %poly =
squared =>
[[[ 0.0, 0.0], [10.0, 0.0]],
[[10.0, 0.0], [10.0, 10.0]],
[[10.0, 10.0], [ 0.0, 10.0]],
[[ 0.0, 10.0], [ 0.0, 0.0]]],
squaredhole =>
[[[ 0.0, 0.0], [10.0, 0.0]],
[[10.0, 0.0], [10.0, 10.0]],
[[10.0, 10.0], [ 0.0, 10.0]],
[[ 0.0, 10.0], [ 0.0, 0.0]],
[[ 2.5, 2.5], [ 7.5, 2.5]],
[[ 7.5, 2.5], [ 7.5, 7.5]],
[[ 7.5, 7.5], [ 2.5, 7.5]],
[[ 2.5, 7.5], [ 2.5, 2.5]]],
strange =>
[[[ 0.0, 0.0], [ 2.5, 2.5]],
[[ 2.5, 2.5], [ 0.0, 10.0]],
[[ 0.0, 10.0], [ 2.5, 7.5]],
[[ 2.5, 7.5], [ 7.5, 7.5]],
[[ 7.5, 7.5], [10.0, 10.0]],
[[10.0, 10.0], [10.0, 0.0]],
[[10.0, 0.0], [ 2.5, 2.5]],
[[ 2.5, 2.5], [ 0.0, 0.0]]], # conjecturally close polygon
exagon =>
[[[ 3.0, 0.0], [ 7.0, 0.0]],
[[ 7.0, 0.0], [10.0, 5.0]],
[[10.0, 5.0], [ 7.0, 10.0]],
[[ 7.0, 10.0], [ 3.0, 10.0]],
[[ 3.0, 10.0], [ 0.0, 5.0]],
[[ 0.0, 5.0], [ 3.0, 0.0]]];
my @test-points =
[ 5.0, 5.0],
[ 5.0, 8.0],
[-10.0, 5.0],
[ 0.0, 5.0],
[ 10.0, 5.0],
[ 8.0, 5.0],
[ 10.0, 10.0];
for <squared squaredhole strange exagon> -> $polywanna {
say "$polywanna";
my @poly = %poly{$polywanna}[];
for @test-points -> @point {
say "\t(@point.fmt('%.1f',','))\t{ point-in-poly(@point, @poly) ?? 'IN' !! 'OUT' }";
}
}</syntaxhighlight>
{{out}}
<pre>squared
(5.0,5.0) IN
(5.0,8.0) IN
(-10.0,5.0) OUT
(0.0,5.0) OUT
(10.0,5.0) IN
(8.0,5.0) IN
(10.0,10.0) OUT
squaredhole
(5.0,5.0) OUT
(5.0,8.0) IN
(-10.0,5.0) OUT
(0.0,5.0) OUT
(10.0,5.0) IN
(8.0,5.0) IN
(10.0,10.0) OUT
strange
(5.0,5.0) IN
(5.0,8.0) OUT
(-10.0,5.0) OUT
(0.0,5.0) OUT
(10.0,5.0) IN
(8.0,5.0) IN
(10.0,10.0) OUT
exagon
(5.0,5.0) IN
(5.0,8.0) IN
(-10.0,5.0) OUT
(0.0,5.0) OUT
(10.0,5.0) IN
(8.0,5.0) IN
(10.0,10.0) OUT</pre>
=={{header|REXX}}==
Line 3,250 ⟶ 3,926:
Code was added to facilitate easier specification of polygon sides by just specifying their ''vertices'' instead of specifying their ''line segments''.
<
call points 5 5, 5 8, -10 5, 0 5, 10 5, 8 5, 10 10
A= 2.5; B= 7.5
call poly 0 0, 10 0, 10 10, 0 10 ; call test 'square'
call poly 0 0, 10 0, 10 10, 0 10, A A, B A, B B, A B ; call test 'square hole'
call poly 0 0, A A, 0 10, A B, B B, 10 10, 10 0 ; call test 'irregular'
call poly 3 0, 7 0, 10 5, 7 10, 3 10, 0 5 ; call test 'hexagon'
exit
/*──────────────────────────────────────────────────────────────────────────────────────*/
in$out: procedure expose point. poly.; parse arg p; #= 0
do side=1 to poly.0 by 2;
return # // 2 /*ODD is inside. EVEN is outside.*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
intersect: procedure expose point. poly.; parse arg ?,s;
epsilon= '1e' || (-digits() %
Px= point.?.x;
Py= point.?.y;
if Ay>By then parse value Ax Ay Bx By with Bx By Ax Ay
if Py=Ay | Py=By then Py= Py + epsilon
if Py<Ay | Py>By | Px>max(Ax, Bx) then return 0
if Px<min(Ax, Bx) then return 1
if Ax\=Bx then red = (By-Ay) / (Bx-Ax)
else red = i"1e" || (digits() *2) /* ◄─── infinity.*/
if Ax\=Px then
else return 1
/*──────────────────────────────────────────────────────────────────────────────────────*/
points: wx= 0; wy= 0;
wx= max(wx, length(xx) );
wy= max(wy, length(yy) );
end /*j*/
call value point.0, j-1 /*define the number of points. */
return /* [↑] adjust J (for DO loop)*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
poly: @= 'POLY.'; parse arg Fx Fy /* [↓] process the X,Y points.*/
n= 0
do j=1 for arg(); n= n + 1;
call value @ || n'.X', xx ;
if n//2 then iterate; n= n + 1
call value @ || n'.X', xx ;
end /*j*/
n= n + 1
call value @ || n'.X', Fx; call value @ || n".Y", Fy;
return
/*──────────────────────────────────────────────────────────────────────────────────────*/
test: say; do k=1 for point.0; w= wx + wy + 2 /*W, WX, WY ≡are
say right(' ['arg(1)"] point:", 30),
right( right(point.k.x, wx)', 'right(point.k.y, wy), w) " is ",
right( word('outside inside', in$out(k) + 1), 7)
end /*k*/
return /* [↑] format the output nicely*/</syntaxhighlight>
{{out|output|text= when using the default inputs:}}
<pre>
Line 3,337 ⟶ 4,013:
=={{header|Rust}}==
{{trans|Python}}
<
const _EPS: f64 = 0.00001;
Line 3,467 ⟶ 4,143:
}
println!();
}</
{{out}}
<pre>
Line 3,478 ⟶ 4,154:
=={{header|Scala}}==
{{trans|D}}
<
case class Edge(_1: (Double, Double), _2: (Double, Double)) {
Line 3,524 ⟶ 4,200:
private implicit def to_edge(p: ((Double, Double), (Double, Double))): Edge = Edge(p._1, p._2)
}</
{{out}}
<pre>points: List((5.0,5.0), (5.0,8.0), (-10.0,5.0), (0.0,5.0), (10.0,5.0), (8.0,5.0), (10.0,10.0))
Line 3,544 ⟶ 4,220:
{{works with|GNU Smalltalk}}
The class Segment holds the code to test if a ray starting from a point (and going towards "right") intersects the segment (method <tt>doesIntersectRayFrom</tt>); while the class Polygon hosts the code to test if a point is inside the polygon (method <tt>pointInside</tt>).
<
|pts|
Segment class >> new: points [ |a|
Line 3,620 ⟶ 4,296:
^ ( cnt \\ 2 = 0 ) not
]
].</
'''Testing'''
<
points := {
Line 3,664 ⟶ 4,340:
].
' ' displayNl.
]</
=={{header|Tcl}}==
<
proc point_in_polygon {point polygon} {
Line 3,724 ⟶ 4,400:
} {
puts "$point in $poly = [point_in_polygon $point $poly]"
}</
=={{header|Ursala}}==
Line 3,731 ⟶ 4,407:
value if it's outside, using the algorithm described above.
For points on the boundary the result is unspecified.
<
in =
Line 3,737 ⟶ 4,413:
@lrzyCipPX ~|afatPRZaq ~&EZ+fleq~~lrPrbr2G&& ~&B+fleq~~lrPrbl2G!| -&
~&Y+ ~~lrPrbl2G fleq,
^E(fleq@lrrPX,@rl fleq\0.)^/~&lr ^(~&r,times)^/minus@llPrll2X vid+ minus~~rbbI&-</
This test program tries it on a couple of examples.
<
examples =
Line 3,745 ⟶ 4,421:
in* <
((0.5,0.6),<(0.,0.),(1.,2.),(1.,0.)>),
((0.5,0.6),<(0.,0.),(1.,1.),(1.,0.)>)></
output:
<pre><true,false></pre>
Line 3,751 ⟶ 4,427:
=={{header|Visual Basic .NET}}==
{{trans|Java}}
<
Module RayCasting
Line 3,790 ⟶ 4,466:
If a(1) > b(1) Then Return Intersects(b, a, p)
If p(1) = a(1) Or p(1) = b(1) Then p(1) += 0.0001
If p(1) > b(1) Or p(1) < a(1) Or p(0) >= Max(a(0), b(0)) Then Return False
If p(0) < Min(a(0), b(0)) Then Return True
Dim red As Double = (p(1) - a(1)) / (p(0) - a(0))
Line 3,797 ⟶ 4,473:
Return red >= blue
End Function
End Module</
{{out}}
<pre>
True True False True False True False
False True False False False True False
True False False False False True False
True True False False False True False
</pre>
=={{header|Wren}}==
{{trans|Java}}
{{libheader|Wren-fmt}}
<syntaxhighlight lang="wren">import "./fmt" for Fmt
class RayCasting {
static intersects(a, b, p) {
if (a[1] > b[1]) return intersects(b, a, p)
if (p[1] == a[1] || p[1] == b[1]) p[1] = p[1] + 0.0001
if (p[1] > b[1] || p[1] < a[1] || p[0] >= a[0].max(b[0])) return false
if (p[0] < a[0].min(b[0])) return true
var red = (p[1] - a[1]) / (p[0] - a[0])
var blue = (b[1] - a[1]) / (b[0] - a[0])
return red >= blue
}
static contains(shape, pnt) {
var inside = false
var len = shape.count
for (i in 0...len) {
if (intersects(shape[i], shape[(i + 1) % len], pnt)) inside = !inside
}
return inside
}
static square { [[0, 0], [20, 0], [20, 20], [0, 20]] }
static squareHole { [[0, 0], [20, 0], [20, 20], [0, 20], [5, 5], [15, 5], [15, 15], [5, 15]] }
static strange { [[0, 0], [5, 5], [0, 20], [5, 15], [15, 15], [20, 20], [20, 0]] }
static hexagon { [[6, 0], [14, 0], [20, 10], [14, 20], [6, 20], [0, 10]] }
static shapes { [square, squareHole, strange, hexagon] }
}
var testPoints = [[10, 10], [10, 16], [-20, 10], [0, 10], [20, 10], [16, 10], [20, 20]]
for (shape in RayCasting.shapes) {
for (pnt in testPoints) Fmt.write("$7s ", RayCasting.contains(shape, pnt))
System.print()
}</syntaxhighlight>
{{out}}
<pre>
</pre>
=={{header|zkl}}==
{{trans|
<
fcn rayHitsSeg([(Px,Py)],[(Ax,Ay)],[(Bx,By)]){ // --> Bool
Line 3,824 ⟶ 4,550:
})
.len().isOdd; // True if crossed an odd number of borders ie inside polygon
}</
<
T("squared",
T(T(T( 0.0, 0.0), T(10.0, 0.0)),
Line 3,874 ⟶ 4,600:
pointInPoly(testPoint,polywanna) and "IN" or "OUT");
}
}</
{{out}}
<pre>
|