Ray-casting algorithm: Difference between revisions

Added Algol 68
(→‎{{header|Lua}}: added Lua solution)
(Added Algol 68)
(6 intermediate revisions by 4 users not shown)
Line 79:
{{trans|Python}}
 
<langsyntaxhighlight lang="11l">T Pt
Float x, y
 
Line 162:
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"))</langsyntaxhighlight>
 
{{out}}
Line 221:
=={{header|Ada}}==
polygons.ads:
<langsyntaxhighlight Adalang="ada">package Polygons is
 
type Point is record
Line 234:
function Is_Inside (Who : Point; Where : Polygon) return Boolean;
 
end Polygons;</langsyntaxhighlight>
 
polygons.adb:
<langsyntaxhighlight Adalang="ada">package body Polygons is
EPSILON : constant := 0.00001;
 
Line 323:
end Is_Inside;
 
end Polygons;</langsyntaxhighlight>
 
Example use:
 
main.adb:
<langsyntaxhighlight Adalang="ada">with Ada.Text_IO;
with Polygons;
procedure Main is
Line 418:
Ada.Text_IO.New_Line;
end loop;
end Main;</langsyntaxhighlight>
 
Output:
Line 457:
Point(10.0,10.0): FALSE</pre>
 
=={{header|ANSIALGOL Standard BASIC68}}==
{{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}}
<lang ANSI Standard BASIC>1000 PUBLIC NUMERIC x,y
<syntaxhighlight lang="basic">1000 PUBLIC NUMERIC x,y
1010 LET x=1
1020 LET y=2
Line 642 ⟶ 883:
2810 NEXT z
2820 END
</syntaxhighlight>
</lang>
{{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
=={{header|AutoHotkey}}==
(5,5) out
{{works with|AutoHotkey L}}
(5,8) in
<lang ahk>Points :=[{x: 5.0, y: 5.0}
(-10,5) out
, {x: 5.0, y: 8.0}
(0,5) out
, {x:-10.0, y: 5.0}
(10,5) {x: 0.0, y: 5.0}in
(8,5) {x: 10.0, y: 5.0} in
(10,10) out
, {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%
 
strange
point_in_polygon(Point,Poly) {
(5,5) in
n:=Poly.MaxIndex()
(5,8) out
count:=0
(-10,5) out
loop, %n% {
(0,5) out
if (ray_intersects_segment(Point,Poly[A_Index],Poly[mod(A_Index,n)+1])) {
(10,5) in
count++
(8,5) in
}
(10,10) out
}
if (mod(count,2)) { ; true = inside, false = outside
return true ; P is in the polygon
} else {
return false ; P isn't in the polygon
}
}
 
exagon
ray_intersects_segment(P,A,B) {
(5,5) in
;P = the point from which the ray starts
(5,8) in
;A = the end-point of the segment with the smallest y coordinate
(-10,5) out
;B = the end-point of the segment with the greatest y coordinate
(0,5) out
if (A.y > B.y) {
(10,5) in
temp:=A
(8,5) in
A:=B
(10,10) out
B:=temp
</pre>
}
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
}
}
}
}</lang>
{{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|C}}==
<langsyntaxhighlight lang="c">#include <stdio.h>
#include <stdlib.h>
#include <math.h>
Line 918 ⟶ 1,064:
 
return 0;
}</langsyntaxhighlight>
 
 
 
=={{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}}
<langsyntaxhighlight lang="cpp">#include <algorithm>
#include <cstdlib>
#include <iomanip>
Line 1,003 ⟶ 1,231:
 
return EXIT_SUCCESS;
}</langsyntaxhighlight>
{{output}}
As D.
Line 1,009 ⟶ 1,237:
=={{header|CoffeeScript}}==
Takes a polygon as a list of points joining segments, and creates segments between them.
<langsyntaxhighlight lang="coffeescript"> Point = (@x,@y) ->
 
pointInPoly = (point,poly) ->
Line 1,036 ⟶ 1,264:
mAB = (b.y - a.y) / (b.x - a.x)
mAP = (p.y - a.y) / (p.x - a.x)
mAP > mAB</langsyntaxhighlight>
 
=={{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.
<langsyntaxhighlight lang="lisp">(defun point-in-polygon (point polygon)
(do ((in-p nil)) ((endp polygon) in-p)
(when (ray-intersects-segment point (pop polygon))
Line 1,069 ⟶ 1,297:
((null m-blue) t)
((null m-red) nil)
(t (>= m-blue m-red)))))))))</langsyntaxhighlight>
 
Testing code
<langsyntaxhighlight lang="lisp">(defparameter *points*
#((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 1,106 ⟶ 1,334:
do (format t "~&~w ~:[outside~;inside ~]."
test-point
(point-in-polygon test-point polygon)))))</langsyntaxhighlight>
 
=={{header|D}}==
<langsyntaxhighlight lang="d">import std.stdio, std.math, std.algorithm;
 
immutable struct Point { double x, y; }
Line 1,176 ⟶ 1,404:
writeln;
}
}</langsyntaxhighlight>
{{out}}
<pre>Is point inside figure "Square"?
Line 1,216 ⟶ 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.
<langsyntaxhighlight lang="factor">USING: kernel prettyprint sequences arrays math math.vectors ;
IN: raycasting
 
Line 1,234 ⟶ 1,462:
[ dup first suffix [ rest-slice ] [ but-last-slice ] bi ] dip
[ ray ] curry 2map
f [ xor ] reduce ;</langsyntaxhighlight>
Usage:
<langsyntaxhighlight lang="factor">( scratchpad ) CONSTANT: square { { -2 -1 } { 1 -2 } { 2 1 } { -1 2 } }
( scratchpad ) square { 0 0 } raycast .
t
Line 1,242 ⟶ 1,470:
f
( scratchpad ) square { 2 0 } raycast .
f</langsyntaxhighlight>
 
=={{header|Fortran}}==
Line 1,249 ⟶ 1,477:
 
This module ''defines'' "polygons".
<langsyntaxhighlight lang="fortran">module Polygons
use Points_Module
implicit none
Line 1,283 ⟶ 1,511:
end subroutine free_polygon
 
end module Polygons</langsyntaxhighlight>
 
The ray casting algorithm module:
<langsyntaxhighlight lang="fortran">module Ray_Casting_Algo
use Polygons
implicit none
Line 1,362 ⟶ 1,590:
end function point_is_inside
 
end module Ray_Casting_Algo</langsyntaxhighlight>
 
'''Testing'''
<langsyntaxhighlight lang="fortran">program Pointpoly
use Points_Module
use Ray_Casting_Algo
Line 1,404 ⟶ 1,632:
end do
 
end program Pointpoly</langsyntaxhighlight>
 
=={{header|FreeBASIC}}==
Inpolygon by Winding number method
<langsyntaxhighlight FreeBASIClang="freebasic">Type Point
As Single x,y
End Type
Line 1,521 ⟶ 1,749:
End Select
Next z
Sleep</langsyntaxhighlight>
Output:
<pre>squared
Line 1,563 ⟶ 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.)
<langsyntaxhighlight lang="go">package main
 
import (
Line 1,664 ⟶ 1,892:
}
}
}</langsyntaxhighlight>
{{out}}
<pre>
Line 1,711 ⟶ 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.
<langsyntaxhighlight lang="go">package main
 
import (
Line 1,786 ⟶ 2,014:
}
}
}</langsyntaxhighlight>
{{out}}
<pre>
Line 1,807 ⟶ 2,035:
 
This solution is preferred over the two above.
<syntaxhighlight lang="text">package main
 
import "fmt"
Line 1,856 ⟶ 2,084:
}
}
}</langsyntaxhighlight>
 
=={{header|Haskell}}==
<langsyntaxhighlight lang="haskell">import Data.Ratio
 
type Point = (Rational, Rational)
Line 1,907 ⟶ 2,135:
(py /= by || ay < py)
((ax, ay), (bx, by)) = side
line = carrier side</langsyntaxhighlight>
 
=={{header|J}}==
<langsyntaxhighlight lang="j">NB.*crossPnP v point in closed polygon, crossing number
NB. bool=. points crossPnP polygon
crossPnP=: 4 : 0"2
Line 1,918 ⟶ 2,146:
p2=. (x0-/X) < (x0-x1) * (y0-/Y) % (y0 - y1)
2|+/ p1*.p2
)</langsyntaxhighlight>
 
Sample data:
<langsyntaxhighlight lang="j">SQUAREV=: 0 0 , 10 0 , 10 10 ,: 0 10
SQUAREV=: SQUAREV, 2.5 2.5 , 7.5 0.1 , 7.5 7.5 ,: 2.5 7.5
 
Line 1,931 ⟶ 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</langsyntaxhighlight>
 
Testing:
<langsyntaxhighlight lang="j"> (<POINTS) crossPnP every ESA;SQUARE;SQUAREHOLE;STRANGE
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</langsyntaxhighlight>
 
=={{header|Java}}==
<langsyntaxhighlight lang="java">import static java.lang.Math.*;
 
public class RayCasting {
Line 1,996 ⟶ 2,224:
 
final static int[][][] shapes = {square, squareHole, strange, hexagon};
}</langsyntaxhighlight>
 
<pre>
Line 2,006 ⟶ 2,234:
 
=={{header|Javascript}}==
<langsyntaxhighlight lang="javascript">
/**
* @return {boolean} true if (lng, lat) is in bounds
Line 2,065 ⟶ 2,293:
}
}
</syntaxhighlight>
</lang>
 
=={{header|Julia}}==
Line 2,071 ⟶ 2,299:
 
'''Module''':
<langsyntaxhighlight lang="julia">module RayCastings
 
export Point
Line 2,115 ⟶ 2,343:
[(a, b) for (a, b) in zip(vcat(a, b...), vcat(b..., a))]
 
end # module RayCastings</langsyntaxhighlight>
 
'''Main''':
<langsyntaxhighlight lang="julia">using Printf
 
let A = Point(0.0, 0.0),
Line 2,150 ⟶ 2,378:
end
end
end</langsyntaxhighlight>
 
{{out}}
Line 2,223 ⟶ 2,451:
=={{header|Kotlin}}==
{{trans|D}}
<langsyntaxhighlight lang="scala">import java.lang.Double.MAX_VALUE
import java.lang.Double.MIN_VALUE
import java.lang.Math.abs
Line 2,258 ⟶ 2,486:
}
}
}</langsyntaxhighlight>
<langsyntaxhighlight lang="scala">fun main(args: Array<String>) {
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,275 ⟶ 2,503:
 
Ray_casting.check(figures, points)
}</langsyntaxhighlight>
{{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,317 ⟶ 2,545:
 
Displays interactively on-screen.
<langsyntaxhighlight lang="lb">NoMainWin
Global sw, sh, verts
 
Line 2,392 ⟶ 2,620:
Function rand(loNum,hiNum)
rand = Int(Rnd(0)*(hiNum-loNum+1)+loNum)
End Function </langsyntaxhighlight>
 
=={{header|Lua}}==
<langsyntaxhighlight lang="lua">function Point(x,y) return {x=x, y=y} end
 
function Polygon(name, points)
Line 2,432 ⟶ 2,660:
end
print()
end</langsyntaxhighlight>
{{out}}
<pre>Does 'square' contain..
Line 2,472 ⟶ 2,700:
=={{header|Nim}}==
{{trans|D}}
<langsyntaxhighlight Nimlang="nim">import fenv, sequtils, strformat
 
type
Line 2,536 ⟶ 2,764:
echo &"Is point inside figure {poly.name}?"
for p in TestPoints:
echo &" ({p.x:3},{p.y:3}): {poly.contains(p)}"</langsyntaxhighlight>
 
{{out}}
Line 2,574 ⟶ 2,802:
=={{header|OCaml}}==
{{Trans|C}}
<langsyntaxhighlight lang="ocaml">type point = { x:float; y:float }
type polygon = {
Line 2,670 ⟶ 2,898:
print_newline()
) test_points;
;;</langsyntaxhighlight>
 
=={{header|Perl}}==
<langsyntaxhighlight lang="perl">use strict;
use List::Util qw(max min);
 
Line 2,710 ⟶ 2,938:
 
return ($m_blue >= $m_red) ? 1 : 0;
}</langsyntaxhighlight>
 
Testing:
<langsyntaxhighlight lang="perl"># the following are utilities to use the same Fortran data...
sub point
{
Line 2,751 ⟶ 2,979:
( point_in_polygon($tp, $rp) ? "INSIDE" : "OUTSIDE" ) . "\n";
}
}</langsyntaxhighlight>
 
=={{header|Phix}}==
<!--<langsyntaxhighlight Phixlang="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>
Line 2,859 ⟶ 3,087:
<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>
<!--</langsyntaxhighlight>-->
{{out}}
<pre>
Line 2,881 ⟶ 3,109:
 
=={{header|PHP}}==
<langsyntaxhighlight lang="php">
<?php
 
Line 2,967 ⟶ 3,195:
echo json_encode($testPoint) . "\tin " . $shape['name'] . "\t" . contains($shape['bounds'], $testPoint['lat'], $testPoint['lng']) . PHP_EOL;
}
}</langsyntaxhighlight>
{{out}}<pre>{"lng":10,"lat":10} in square 1
{"lng":10,"lat":16} in square 1
Line 2,999 ⟶ 3,227:
 
=={{header|PicoLisp}}==
<langsyntaxhighlight PicoLisplang="picolisp">(scl 4)
 
(de intersects (Px Py Ax Ay Bx By)
Line 3,025 ⟶ 3,253:
(when (apply intersects Edge (car Pt) (cdr Pt))
(onOff Res) ) )
Res ) )</langsyntaxhighlight>
Test data:
<pre style="height:20em;overflow:scroll">(de Square
Line 3,122 ⟶ 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.
<langsyntaxhighlight PureBasiclang="purebasic">Structure point_f
x.f
y.f
Line 3,204 ⟶ 3,432:
FlipBuffers()
Until KeyboardReleased(#PB_Key_Escape) Or EventID = #PB_Event_CloseWindow</langsyntaxhighlight>
 
=={{header|Python}}==
<langsyntaxhighlight lang="python">from collections import namedtuple
from pprint import pprint as pp
import sys
Line 3,308 ⟶ 3,536:
for p in testpoints[3:6]))
print (' ', '\t'.join("%s: %s" % (p, ispointinside(p, poly))
for p in testpoints[6:]))</langsyntaxhighlight>
 
'''Sample output'''
Line 3,364 ⟶ 3,592:
 
'''Helper routine to convert Fortran Polygons and points to Python'''
<langsyntaxhighlight lang="python">def _convert_fortran_shapes():
point = Pt
pts = (point(0,0), point(10,0), point(10,10), point(0,10),
Line 3,390 ⟶ 3,618:
print ' ', ',\n '.join(str(e) for e in p.edges) + '\n )),'
print ' ]'
_convert_fortran_shapes()</langsyntaxhighlight>
 
=={{header|R}}==
<langsyntaxhighlight Rlang="r">point_in_polygon <- function(polygon, p) {
count <- 0
for(side in polygon) {
Line 3,436 ⟶ 3,664:
}
}
}</langsyntaxhighlight>
 
<langsyntaxhighlight Rlang="r">######## utility functions #########
 
point <- function(x,y) list(x=x, y=y)
Line 3,450 ⟶ 3,678:
}
pol
}</langsyntaxhighlight>
 
<langsyntaxhighlight Rlang="r">#### testing ####
 
pts <- list(point(0,0), point(10,0), point(10,10), point(0,10),
Line 3,477 ⟶ 3,705:
p$x, p$y, point_in_polygon(polygons[[polysi]], p), names(polygons[polysi])))
}
}</langsyntaxhighlight>
 
=={{header|Racket}}==
Straightforward implementation of pseudocode
<langsyntaxhighlight lang="scheme">
#lang racket
 
Line 3,563 ⟶ 3,791:
(test-figure square "square")
(test-figure exagon "exagon")
</syntaxhighlight>
</lang>
 
{{out}}
Line 3,588 ⟶ 3,816:
=={{header|Raku}}==
(formerly Perl 6)
<syntaxhighlight lang="raku" perl6line>constant ε = 0.0001;
sub ray-hits-seg([\Px,\Py], [[\Ax,\Ay], [\Bx,\By]] --> Bool) {
Line 3,659 ⟶ 3,887:
say "\t(@point.fmt('%.1f',','))\t{ point-in-poly(@point, @poly) ?? 'IN' !! 'OUT' }";
}
}</langsyntaxhighlight>
{{out}}
<pre>squared
Line 3,698 ⟶ 3,926:
 
Code was added to facilitate easier specification of polygon sides by just specifying their &nbsp; ''vertices'' &nbsp; instead of specifying their &nbsp; ''line segments''.
<langsyntaxhighlight lang="rexx">/*REXX program verifies if a horizontal ray from point P intersects a polygon. */
call points 5 5, 5 8, -10 5, 0 5, 10 5, 8 5, 10 10
A= 2.5; B= 7.5 /* ◄───── used for shorter arguments (below).*/
Line 3,747 ⟶ 3,975:
right( word('outside inside', in$out(k) + 1), 7)
end /*k*/
return /* [↑] format the output nicely*/</langsyntaxhighlight>
{{out|output|text=&nbsp; when using the default inputs:}}
<pre>
Line 3,785 ⟶ 4,013:
=={{header|Rust}}==
{{trans|Python}}
<langsyntaxhighlight lang="rust">use std::f64;
 
const _EPS: f64 = 0.00001;
Line 3,915 ⟶ 4,143:
}
println!();
}</langsyntaxhighlight>
{{out}}
<pre>
Line 3,926 ⟶ 4,154:
=={{header|Scala}}==
{{trans|D}}
<langsyntaxhighlight lang="scala">package scala.ray_casting
 
case class Edge(_1: (Double, Double), _2: (Double, Double)) {
Line 3,972 ⟶ 4,200:
 
private implicit def to_edge(p: ((Double, Double), (Double, Double))): Edge = Edge(p._1, p._2)
}</langsyntaxhighlight>
{{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,992 ⟶ 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>).
<langsyntaxhighlight lang="smalltalk">Object subclass: Segment [
|pts|
Segment class >> new: points [ |a|
Line 4,068 ⟶ 4,296:
^ ( cnt \\ 2 = 0 ) not
]
].</langsyntaxhighlight>
 
'''Testing'''
<langsyntaxhighlight lang="smalltalk">|points names polys|
 
points := {
Line 4,112 ⟶ 4,340:
].
' ' displayNl.
]</langsyntaxhighlight>
 
=={{header|Tcl}}==
<langsyntaxhighlight Tcllang="tcl">package require Tcl 8.5
proc point_in_polygon {point polygon} {
Line 4,172 ⟶ 4,400:
} {
puts "$point in $poly = [point_in_polygon $point $poly]"
}</langsyntaxhighlight>
 
=={{header|Ursala}}==
Line 4,179 ⟶ 4,407:
value if it's outside, using the algorithm described above.
For points on the boundary the result is unspecified.
<langsyntaxhighlight Ursalalang="ursala">#import flo
 
in =
Line 4,185 ⟶ 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&-</langsyntaxhighlight>
This test program tries it on a couple of examples.
<langsyntaxhighlight Ursalalang="ursala">#cast %bL
 
examples =
Line 4,193 ⟶ 4,421:
in* <
((0.5,0.6),<(0.,0.),(1.,2.),(1.,0.)>),
((0.5,0.6),<(0.,0.),(1.,1.),(1.,0.)>)></langsyntaxhighlight>
output:
<pre><true,false></pre>
Line 4,199 ⟶ 4,427:
=={{header|Visual Basic .NET}}==
{{trans|Java}}
<langsyntaxhighlight lang="vbnet">Imports System.Math
 
Module RayCasting
Line 4,245 ⟶ 4,473:
Return red >= blue
End Function
End Module</langsyntaxhighlight>
{{out}}
<pre>
Line 4,256 ⟶ 4,484:
=={{header|Wren}}==
{{trans|Java}}
{{libheader|Wren-math}}
{{libheader|Wren-fmt}}
<langsyntaxhighlight ecmascriptlang="wren">import "./mathfmt" for MathFmt
import "/fmt" for Fmt
 
class RayCasting {
Line 4,265 ⟶ 4,491:
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] >= Math.max(a[0], .max(b[0])) return false
if (p[0] < Math.min(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])
Line 4,296 ⟶ 4,522:
for (pnt in testPoints) Fmt.write("$7s ", RayCasting.contains(shape, pnt))
System.print()
}</langsyntaxhighlight>
 
{{out}}
Line 4,308 ⟶ 4,534:
=={{header|zkl}}==
{{trans|Raku}}
<langsyntaxhighlight lang="zkl">const E = 0.0001;
fcn rayHitsSeg([(Px,Py)],[(Ax,Ay)],[(Bx,By)]){ // --> Bool
Line 4,324 ⟶ 4,550:
})
.len().isOdd; // True if crossed an odd number of borders ie inside polygon
}</langsyntaxhighlight>
<langsyntaxhighlight lang="zkl">polys:=T( //(name,( ((a,b),(c,d)),((a,b),(c,d))... ), ... )==(nm,(ln,ln..) ..)
T("squared",
T(T(T( 0.0, 0.0), T(10.0, 0.0)),
Line 4,374 ⟶ 4,600:
pointInPoly(testPoint,polywanna) and "IN" or "OUT");
}
}</langsyntaxhighlight>
{{out}}
<pre>
3,022

edits