Ray-casting algorithm: Difference between revisions
Content added Content deleted
m (comment: edges not corners) |
m (→{{header|REXX}}: corrected a typo, changed some comments.) |
||
Line 2,525: | Line 2,525: | ||
=={{header|REXX}}== |
=={{header|REXX}}== |
||
Over half of the REXX program is devoted to |
Over half of the REXX program is devoted to specifying/defining/assigning the points for the test cases and the polygons. |
||
<br>the test cases and the polygons. |
|||
Code was added to facilitate easier specification of polygon sides by just specifying their vertices instead of specifying line segments. |
|||
<br>just specifying their vertices instead of specifying line segments. |
|||
Points on a vertex (or side) don't obtain ''coherent'' results, but casual observation |
|||
seems to indicate that this code considers those points as outside the polygon. |
|||
<lang rexx>/*REXX |
<lang rexx>/*REXX pgm checks to see if a horizontal ray from point P intersects a polygon*/ |
||
call points 5 5, |
call points 5 5, 5 8, -10 5, 0 5, 10 5, 8 5, 10 10 |
||
call polygon 0 0, |
call polygon 0 0, 10 0, 10 10, 0 10 ; call test 'square' |
||
call polygon 0 0, 10 0, 10 10, 0 10, 2.5 2.5, 7.5 2.5, 7.5 7.5, 2.5 7.5 ; call test 'square hole' |
call polygon 0 0, 10 0, 10 10, 0 10, 2.5 2.5, 7.5 2.5, 7.5 7.5, 2.5 7.5 ; call test 'square hole' |
||
call polygon 0 0, 2.5 2.5, 0 10, 2.5 7.5, 7.5 7.5, 10 10, 10 0 ; call test 'irregular' |
call polygon 0 0, 2.5 2.5, 0 10, 2.5 7.5, 7.5 7.5, 10 10, 10 0 ; call test 'irregular' |
||
call polygon 3 0, 7 0, 10 5, 7 10, 3 10, 0 5 ; call test ' |
call polygon 3 0, 7 0, 10 5, 7 10, 3 10, 0 5 ; call test 'hexagon' |
||
exit /*stick a fork in it, we're done.*/ |
exit /*stick a fork in it, we're all done. */ |
||
/*────────────────────────────────────────────────────────────────────────────*/ |
|||
/*──────────────────────────────────IN_OUT subroutine────────────────────*/ |
|||
in_out: procedure expose point. poly. |
in_out: procedure expose point. poly.; parse arg p; #=0 |
||
do side=1 to poly.0 by 2; #=#+ray_intersect(p,side) |
|||
end /*side*/ |
end /*side*/ |
||
return #//2 /*ODD is inside. EVEN is outside. */ |
|||
/*────────────────────────────────────────────────────────────────────────────*/ |
|||
/*──────────────────────────────────POINTS subroutine───────────────────*/ |
|||
points: |
points: n=0; v='POINT.'; do j=1 for arg(); n=n+1; _=arg(j); parse var _ xx yy |
||
call value v||n'.X',xx |
|||
call value v||n'.Y',yy |
|||
end /*j*/ |
|||
call value v'0',n |
call value v'0',n /*define the number of points.*/ |
||
return |
return |
||
/*────────────────────────────────────────────────────────────────────────────*/ |
|||
/*──────────────────────────────────POLYGON subroutine──────────────────*/ |
|||
polygon: |
polygon: n=0; v='POLY.'; parse arg Fx Fy /* [↓] process the X,Y points*/ |
||
do j=1 for arg(); _=arg(j); |
do j=1 for arg(); n=n+1; _=arg(j); parse var _ xx yy |
||
call value v||n'.X', word(_,1); call value v||n'.Y', word(_,2) |
call value v||n'.X', word(_,1); call value v||n'.Y', word(_,2) |
||
if n//2 then iterate |
if n//2 then iterate |
||
n=n+1 |
n=n+1 |
||
call value v||n'.X', word(_,1); call value v||n'.Y', word(_,2) |
call value v||n'.X', word(_,1); call value v||n'.Y', word(_,2) |
||
end /*j*/ |
end /*j*/ |
||
n=n+1 |
n=n+1 |
||
call value v||n".X", Fx; |
call value v||n".X", Fx; call value v||n".Y", Fy; call value v'0',n |
||
return /*POLY.0 is number of segments/sides.*/ |
|||
/*────────────────────────────────────────────────────────────────────────────*/ |
|||
/*──────────────────────────────────RAY_INTERSECT subroutine────────────*/ |
|||
ray_intersect: procedure expose point. poly.; parse arg ?,s; sp=s+1 |
ray_intersect: procedure expose point. poly.; parse arg ?,s; sp=s+1 |
||
epsilon='1e' || (digits()%2); infinity='1e' || (digits()*2) |
|||
Px=point.?.x; Py=point.?.y |
Px=point.?.x; Py=point.?.y |
||
Ax=poly.s.x; Bx=poly.sp.x |
Ax=poly.s.x; Bx=poly.sp.x; Ay=poly.s.y; By=poly.sp.y |
||
if Ay>By |
if Ay>By then parse value Ax Ay Bx By with Bx By Ax Ay |
||
if Py=Ay | Py=By |
if Py=Ay | Py=By then Py=Py+epsilon |
||
if Py<Ay | Py>By | |
if Py<Ay | Py>By | Px>max(Ax,Bx) then return 0 |
||
if Px<min(Ax,Bx) |
if Px<min(Ax,Bx) then return 1 |
||
if Ax\=Bx then m_red |
if Ax\=Bx then m_red =(By-Ay)/(Bx-Ax) |
||
else m_red=infinity |
|||
if Ax\=Px then m_blue |
if Ax\=Px then m_blue=(Py-Ay)/(Px-Ax) |
||
return m_blue>=m_red |
|||
else return 1 |
|||
/*──────────────────────────────────TEST procedure──────────────────────*/ |
|||
return m_blue>=m_red |
|||
/*────────────────────────────────────────────────────────────────────────────*/ |
|||
⚫ | |||
test: say; do k=1 for point.0; say right(' ['arg(1)"] point:",30), |
|||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
'''output''' |
'''output''' |
||
<pre> |
|||
<pre style="height:50ex"> |
|||
[square] point: |
[square] point: 5, 5 is inside |
||
[square] point: |
[square] point: 5, 8 is inside |
||
[square] point: |
[square] point: -10, 5 is outside |
||
[square] point: |
[square] point: 0, 5 is outside |
||
[square] point: |
[square] point: 10, 5 is inside |
||
[square] point: |
[square] point: 8, 5 is inside |
||
[square] point: |
[square] point: 10, 10 is outside |
||
[square hole] point: |
[square hole] point: 5, 5 is outside |
||
[square hole] point: |
[square hole] point: 5, 8 is inside |
||
[square hole] point: |
[square hole] point: -10, 5 is outside |
||
[square hole] point: |
[square hole] point: 0, 5 is outside |
||
[square hole] point: |
[square hole] point: 10, 5 is inside |
||
[square hole] point: |
[square hole] point: 8, 5 is inside |
||
[square hole] point: |
[square hole] point: 10, 10 is outside |
||
[irregular] point: |
[irregular] point: 5, 5 is inside |
||
[irregular] point: |
[irregular] point: 5, 8 is outside |
||
[irregular] point: |
[irregular] point: -10, 5 is outside |
||
[irregular] point: |
[irregular] point: 0, 5 is outside |
||
[irregular] point: |
[irregular] point: 10, 5 is inside |
||
[irregular] point: |
[irregular] point: 8, 5 is inside |
||
[irregular] point: |
[irregular] point: 10, 10 is outside |
||
[ |
[hexagon] point: 5, 5 is outside |
||
[ |
[hexagon] point: 5, 8 is inside |
||
[ |
[hexagon] point: -10, 5 is outside |
||
[ |
[hexagon] point: 0, 5 is outside |
||
[ |
[hexagon] point: 10, 5 is outside |
||
[ |
[hexagon] point: 8, 5 is outside |
||
[ |
[hexagon] point: 10, 10 is outside |
||
</pre> |
</pre> |
||