Anonymous user
Total circles area: Difference between revisions
→C: Scanline Method: removed separate sorting pass to have fewer things to look at; some comments
m (→C: Scanline Method: make it not compile, so users trying it won't be puzzled by incorrect-looking output) |
(→C: Scanline Method: removed separate sorting pass to have fewer things to look at; some comments) |
||
Line 167:
This version performs about 5 million scanlines in about a second, result should be accurate to maybe 10 decimal points.
<lang c>#include <stdio.h>
#include <
#include <stdlib.h>
#include <
typedef double
typedef struct {
flt x, y, r, r2;
flt y0, y1; // extent of circle y+r and y-r
flt x0, x1; // where scanline intersects circle
} circle_t;
#define SZ sizeof(circle_t)
#error data snipped
};
flt cdist(circle_t *c1, circle_t *c2) {
return sqrt(sq(c1->x - c2->x) + sq(c1->y - c2->y));
}
inline void swap_c(circle_t *c)
{
circle_t tmp = c[0];
c[0] = c[1], c[1] = tmp;
}
flt area(circle_t *circs, int n_circ, flt ymin, flt ymax, flt step)
{
int i, n = n_circ;
circle_t *c = malloc(SZ * n);
memcpy(c, circs, SZ * n);
while (n--)
for (i = 0; i < n; i++)
if (c[i].y1 < c[i+1].y1) swap_c(c + i);
flt total = 0;
int row = 1 + ceil((ymax - ymin) / step);
while (row--) {
flt y = ymin + step * row;
for (n = 0; n < n_circ; n++)
if (y >= c[n].y1) // rest of circles below scanline, ignore
break;
else if (y > c[n].y0) {
flt dx = sqrt(c[n].r2 - sq(y - c[n].y));
c[n].x0 = c[n].x - dx;
c[n].x1 = c[n].x + dx;
// keep circles sorted by left intersection
for (i = n; i-- && c[i].x0 > c[i+1].x0; swap_c(c + i));
} else {// remove a circle when scanline has passed it
memmove(c + n, c + n + 1,
n--;
}
flt right = c->x1;
total += c->x1 - c->x0;
for (i = 1; i < n; i++) {
if (c[i].x1 <= right) continue;
total += c[i].x1 - max(c[i].x0, right);
right = c[i].x1;
}
}
free(c);
return total * step;
}
int main(void)
{
int n_circ = sizeof(circles) / SZ;
flt ymin = INFINITY, ymax = -INFINITY;
circle_t *c1, *c2;
if (c1 != c2 && cdist(c1, c2) +
*c1 = circles[--n_circ];
break;
}
ymin = min(ymin, c1->y0 = c1->y - c1->r);
ymax = max(ymax, c1->y1 = c1->y + c1->r);
c1->r2 = sq(c1->r);
}
flt s = 1. / (1 << 20);
flt y0 = floor(ymin / s) * s;
flt a = area(circles, n_circ, y0, ymax, s);
int nlines = (ymax - y0) / s;
// roughly, it cease to make sense if sqrt(nlines) * 1e-14 >> s * s
printf("area = %.10f\tat %d scanlines\n", a, nlines);
}</lang>
{{out}}
=={{header|D}}==
|