|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T p
Length: 3815 (0xee7)
Types: TextFile
Names: »polygon_area.c«
└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987
└─⟦this⟧ »EUUGD18/Sun/Qix/polygon_area.c«
└─⟦this⟧ »EUUGD18/X/Qix/polygon_area.c«
/*
* File: polygon_area.c
* By: Don Hatch
*
* For: Yaq (Yet Another Qix)
*
* This procedure efficiently calculates the area of a closed polygon
* consisting only of alternating horizontal and vertical segments.
*
* Running time is O(n), where n is the number of segments (or, equivalently,
* the number of vertices).
*
* Input: p -- an array containing the vertices
* n -- number of vertices (must be even, of course)
*
* Output: function returns the area (always non-negative).
* The p array is not disturbed.
*
* Implementation:
* Total is initialized to zero.
*
* Three consecutive points are chosen, namely p[n-1], p[n-2]
* and p[n-3]. These three points are replaced by a single point,
* effectively "ironing out" the kink p[n-2], and making a simpler
* polygon. The area of the ironed-out kink (which is a rectangle)
* is added or subtracted from total, as appropriate.
*
* We now have a polygon with two fewer vertices; decrement n by two
* and repeat the above until there's only two points left.
* The absolute value of total is returned (since we may have calculated
* the area "inside-out").
*
* At the top of the loop, temp always represents p[n-1] in the current
* (simplified) polygon; we use temp so as not to disturb the input array.
*
* Note that the type of coordinates need not be integer; this algorithm
* would work with floating-point coordinates as well.
*/
#include <pixrect/pixrect_hs.h>
#define rect_area(a, b) (((b).x - (a).x) * ((b).y - (a).y))
simple_polygon_area0(p, n) /* works if polygon is alternating
horizontal/vertical segments */
register struct pr_pos *p;
register int n;
{
register int total = 0;
register int first_line_is_horizontal = p[0].y == p[1].y;
register struct pr_pos temp; /* doesn't hurt */
temp = p[n-1];
for (; n > 2; n -= 2) {
if (first_line_is_horizontal)
temp.y = p[n-3].y;
else
temp.x = p[n-3].x;
total += rect_area(p[n-2], temp);
}
return abs(total);
}
simple_polygon_area1(p, n) /* works if polygon is alternating
horizontal/vertical segments */
register struct pr_pos *p;
register int n;
{
register int total = 0;
while (n--)
total = p[n].x * p[n].y - total; /* alternately add/subtract */
return abs(total);
}
#define twice_triangle_area(a,b,c) ((b.y-a.y)*(c.x-a.x)-(c.y-a.y)*(b.x-a.x))
polygon_area(p, n) /* works on arbitrary polygons */
register struct pr_pos *p;
register int n;
{
register int total = 0;
for (; n > 2; n --)
total += twice_triangle_area(p[0], p[n-1], p[n-2]);
return abs(total)/2; /* note roundoff error if actual area is fractional*/
}
#define twice_segment_area(b,c) ((b.y * c.x) - (c.y * b.x))
polygon_area2(p, n) /* works on arbitrary polygons, if coords are close to 0 */
register struct pr_pos *p;
register int n;
{
register int total = segment_area(p[n-1], p[0]);
for (; --n > 0; ++p)
total += segment_area(p[0], p[1]);
return abs(total)/2; /* note roundoff error if actual area is fractional*/
}
#ifdef DRIVER
#define MAXPTS 10000
main(argc, argv)
char **argv;
{
struct pr_pos p[MAXPTS];
int n, is_tty = isatty(0);
is_tty && printf("Enter x,y coords of the vertices, one per line.\n");
while (is_tty && printf("--> "), scanf("%d %d", &p[n].x, &p[n].y) == 2)
if (++n == MAXPTS) {
printf("That's quite enough!\n");
break;
}
dump(p, n);
printf("simple area is %d\n", old_simple_polygon_area(p, n));
printf("simple simple area is %d\n", simple_polygon_area(p, n));
printf("area is %d\n", polygon_area(p, n));
dump(p, n); /* make sure it's the same */
}
dump(p, n)
struct pr_pos *p;
{
int i;
printf("%d pts: ", n);
for (i = 0; i < n; ++i)
printf("%d %d ", p[i].x, p[i].y);
printf("\n");
}
#endif