Ray-casting algorithm: Difference between revisions

m
→‎{{header|REXX}}: added/changed whitespace and comments, aligned the numbers in the output better, simplified a subroutine name.
m (→‎{{header|REXX}}: fixed a cut 'n paste mishap (trailing apostrophe).)
m (→‎{{header|REXX}}: added/changed whitespace and comments, aligned the numbers in the output better, simplified a subroutine name.)
Line 2,613:
 
=={{header|REXX}}==
Over half of the REXX program is devoted to specifying/defining/assigning the points for the test cases and for the various --[[User:Gerard Schildberger|Gerard Schildberger]] ([[User talk:Gerard Schildberger|talk]]) 00:47, 19 November 2015 (UTC)polygons.
 
Code was added to facilitate easier specification of polygon sides by just specifying their vertices instead of specifying line segments.
Line 2,619:
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 pgmprogram checks to seeverifies 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 /*◄───forfor shorter argsarguments.*/
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'
Line 2,628:
exit /*stick a fork in it, we're all done. */
/*────────────────────────────────────────────────────────────────────────────*/
in_outin$out: procedure expose point. poly.; parse arg p; #=0
do side=1 to poly.0 by 2; #=#+ray_intersectintersect(p,side)
end /*side*/
return #//2 /*ODD is inside. EVEN is outside. */
/*────────────────────────────────────────────────────────────────────────────*/
pointsintersect: n=0;procedure v='POINTexpose point. poly.'; do j=1 for arg(); n=n+1; _=parse arg(j) ?,s; parse var _ xx yysp=s+1
epsilon='1e' || (digits()%2); infinity='1e' call value v||n'.X',xx (digits() *2)
Px=point.?.x; Ax=poly.s.x; call value v||n'Ay=poly.s.Y',yyy
Py=point.?.y; Bx=poly.sp.x; By=poly.sp.y /* [↓] enddo a /*jswap*/
call value v'0',n if Ay>By then parse value Ax Ay Bx B y with /*define theBx numberBy ofAx points.*/Ay
if Py=Ay | Py=By then Py=Py+epsilon
return
if Py<Ay | Py>By | Px>max(Ax,Bx) then return 0
if Px<min(Ax,Bx) then return 1
if Ax\=Bx then m_red =(By-Ay)/(Bx-Ax)
else m_red =infinity
if Ax\=Px then m_blue=(Py-Ay)/(Px-Ax)
else return 1
return m_blue>=m_red
/*────────────────────────────────────────────────────────────────────────────*/
points: wx=0
poly: n=0; v='POLY.'; parse arg Fx Fy /* [↓] process the X,Y points*/
wy=0; do j=1 for arg(); if Ay>By then parse value Ax Ay Bx Byarg(j) with Bx Byxx Ax Ayyy
 
do jwx=1 for argmax(wx,length(xx)); n=n+1; call _=arg(j); value parse var'POINT.'j".X", _ xx yy
call value v||n'.X', wordwy=max(_wy,1length(yy)); call value v||n 'POINT.Y'j".Y", word(_,2) yy
end /*j*/
call value POINT.0,j-1 /*define the number of points. */
return
/*────────────────────────────────────────────────────────────────────────────*/
poly: n=0; v@='POLY.'; parse arg Fx Fy /* [↓] process the X,Y points.*/
n=0
do j=1 for arg(); n=n+1; parse value arg(j) with xx yy
call value @||n'.X', xx ; call value @||n'.Y', yy
if n//2 then iterate
n=n+1
call value v@||n'.X', word(_,1)xx ; call value v @||n'.Y', word(_,2)yy
end /*j*/
n=n+1
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: procedure expose point. poly.; parse arg ?,s; sp=s+1
epsilon='1e' || (digits()%2); infinity='1e' || (digits() *2)
Px=point.?.x; Ax=poly.s.x; Ay=poly.s.y
Py=point.?.y; Bx=poly.sp.x; By=poly.sp.y /* [↓] do a swap*/
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 m_red =(By-Ay)/(Bx-Ax)
else m_red =infinity
if Ax\=Px then m_blue=(Py-Ay)/(Px-Ax)
else return 1
return m_blue>=m_red
/*────────────────────────────────────────────────────────────────────────────*/
test: say; do k=1 for point.0; say right(' ['arg(1)"] point:",30), w=wx+wy+1
say right(point.k.x', ['point.k.y, 9arg(1) "] is point:",30),
right( right(point.k.x,wx)','right(point.k.y,wy),w) " is word('outside inside'", in_out(k)+1)
right( word('outside inside', in$out(k)+1), 7)
end /*k*/
return</lang>
'''output'''
<pre>
[square] point: 5, 5 is inside
[square] point: 5, 8 is inside
[square] point: -10, 5 is outside inside
[square] point: 0, 5 is outside inside
[square] point: 10, 5 is inside
[square] point: 8, 5 is inside
[square] point: 10, 10 is outside
 
[square hole] point: 5, 5 is outside
[square hole] point: 5, 8 is inside
[square hole] point: -10, 5 is outside
[square hole] point: 0, 5 is outside
[square hole] point: 10, 5 is inside
[square hole] point: 8, 5 is inside
[square hole] point: 10, 10 is outside
 
[irregular] point: 5, 5 is insideoutside
[irregular] point: 5, 8 is outside inside
[irregular] point: -10, 5 is outside inside
[irregular] point: 0, 5 is outside inside
[irregular] point: 10, 5 is insideoutside
[irregular] point: 8, 5 is insideoutside
[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>