Shoelace formula for polygonal area: Difference between revisions
(→{{header|Python}}: added zkl header) |
(→{{header|zkl}}: added code) |
||
Line 67: | Line 67: | ||
=={{header|zkl}}== |
=={{header|zkl}}== |
||
By the "book": |
|||
⚫ | |||
<lang zkl>fcn areaByShoelace(points){ // ( (x,y),(x,y)...) |
|||
⚫ | |||
xs,ys:=Utils.Helpers.listUnzip(points); // (x,x,...), (y,y,,,) |
|||
( xs.zipWith('*,ys[1,*]).sum(0) + xs[-1]*ys[0] - |
|||
xs[1,*].zipWith('*,ys).sum(0) - xs[0]*ys[-1] ) |
|||
.abs().toFloat()/2; |
|||
⚫ | |||
or an iterative solution: |
|||
<lang zkl>fcn areaByShoelace2(points){ // ( (x,y),(x,y)...) |
|||
xs,ys:=Utils.Helpers.listUnzip(points); // (x,x,...), (y,y,,,) |
|||
N:=points.len(); |
|||
N.reduce('wrap(s,n){ s + xs[n]*ys[(n+1)%N] - xs[(n+1)%N]*ys[n] },0) |
|||
.abs().toFloat()/2; |
|||
⚫ | |||
<lang zkl>points:=T(T(3,4), T(5,11), T(12,8), T(9,5), T(5,6)); |
|||
areaByShoelace(points).println(); |
|||
areaByShoelace2(points).println();</lang> |
|||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
30 |
|||
30 |
|||
</pre> |
</pre> |
Revision as of 02:39, 10 August 2017
Write a function/method/routine to use the the Shoelace formula to calculate the area of the polygon described by the ordered points:
(3,4), (5,11), (12,8), (9,5), and (5,6)
Show the answer here, on this page.
ALGOL 68
<lang algol68>BEGIN
# returns the area of the polygon defined by the points p using the Shoelace formula # OP AREA = ( [,]REAL p )REAL: BEGIN [,]REAL points = p[ AT 1, AT 1 ]; # normalise array bounds to start at 1 # IF 2 UPB points /= 2 THEN # the points do not have 2 coordinates # -1 ELSE REAL result := 0; INT n = 1 UPB points; IF n > 1 THEN # there at least two points # []REAL x = points[ :, 1 ]; []REAL y = points[ :, 2 ]; FOR i TO 1 UPB points - 1 DO result +:= x[ i ] * y[ i + 1 ]; result -:= x[ i + 1 ] * y[ i ] OD; result +:= x[ n ] * y[ 1 ]; result -:= x[ 1 ] * y[ n ] FI; ( ABS result ) / 2 FI END # AREA # ;
# test case as per the task # print( ( fixed( AREA [,]REAL( ( 3.0, 4.0 ), ( 5.0, 11.0 ), ( 12.0, 8.0 ), ( 9.0, 5.0 ), ( 5.0, 6.0 ) ), -6, 2 ), newline ) )
END </lang>
- Output:
30.00
Perl 6
<lang perl6>sub area-by-shoelace(@p) {
(^@p).map({@p[$_;0] * @p[($_+1)%@p;1] - @p[$_;1] * @p[($_+1)%@p;0]}).sum.abs / 2
}
say area-by-shoelace( [ (3,4), (5,11), (12,8), (9,5), (5,6) ] );</lang>
- Output:
30
Python
<lang python>>>> def area_by_shoelace(x, y):
"Assumes x,y points go around the polygon in one direction" return abs( sum(i * j for i, j in zip(x, y[1:] + y[:1])) -sum(i * j for i, j in zip(x[1:] + x[:1], y ))) / 2
>>> points = [(3,4), (5,11), (12,8), (9,5), (5,6)] >>> x, y = zip(*points) >>> area_by_shoelace(x, y) 30.0 >>> </lang>
zkl
By the "book": <lang zkl>fcn areaByShoelace(points){ // ( (x,y),(x,y)...)
xs,ys:=Utils.Helpers.listUnzip(points); // (x,x,...), (y,y,,,) ( xs.zipWith('*,ys[1,*]).sum(0) + xs[-1]*ys[0] - xs[1,*].zipWith('*,ys).sum(0) - xs[0]*ys[-1] ) .abs().toFloat()/2;
}</lang> or an iterative solution: <lang zkl>fcn areaByShoelace2(points){ // ( (x,y),(x,y)...)
xs,ys:=Utils.Helpers.listUnzip(points); // (x,x,...), (y,y,,,) N:=points.len(); N.reduce('wrap(s,n){ s + xs[n]*ys[(n+1)%N] - xs[(n+1)%N]*ys[n] },0) .abs().toFloat()/2;
}</lang> <lang zkl>points:=T(T(3,4), T(5,11), T(12,8), T(9,5), T(5,6)); areaByShoelace(points).println(); areaByShoelace2(points).println();</lang>
- Output:
30 30