coastwatch and skywatch could see too far

Both coas() and skyw() want to iterate over a circular area with
radius vrange.  They did that by iterating over a rectangle that
encloses the circle, skipping coordinates out of range.  To "save
time", they used a rather odd predicate for "out of range", namely
"vrange * vrange < (j * j + 3 * k * k) / 4)".

The predicate is wrong.  coastwatch and skywatch could see one sector
too far in certain directions for practical radar ranges, and up to
two sectors for not so practical tech 1900+ radar stations.

For instance, with j = 13 and k = 3, vrange = 7, the predicate
evaluates to false (49 < 48), i.e. in range.  However, the true
distance is 8, i.e. out of range.  Likewise, j = 22, k = 8, vrange =
13: 169 < 169, true distance 15.

Fix by iterating over the circle directly, without comparing
distances.
This commit is contained in:
Markus Armbruster 2010-04-03 18:34:52 +02:00
parent 38befcb446
commit 5e08b7fa55
2 changed files with 14 additions and 34 deletions

View file

@ -59,10 +59,9 @@ coas(void)
struct nstr_sect nstr;
struct coast *cp;
struct coast *list[TSIZE];
int i, k, j, n;
int i, n;
int vrange, see;
int x, y;
int mink, minj, maxk, maxj;
int x, y, dx, dy, dxmax;
int nship = 0;
double tech;
struct nstr_item ni;
@ -104,20 +103,11 @@ coas(void)
vrange = (int)(sect.sct_effic / 100.0 * see * tech);
if (vrange < 1)
vrange = 1;
maxk = vrange;
maxj = vrange * 2;
vrange *= vrange;
mink = -maxk;
minj = -maxj;
for (j = minj; j <= maxj && nship; j++) {
x = xnorm(sect.sct_x + j);
for (k = mink; k <= maxk && nship; k++) {
if ((j + k) & 01)
continue;
/* quick range check to save time... */
if (vrange < (j * j + 3 * k * k) / 4)
continue;
y = ynorm(sect.sct_y + k);
for (dy = -vrange; dy <= vrange; dy++) {
y = ynorm(sect.sct_y + dy);
dxmax = 2 * vrange - abs(dy);
for (dx = -dxmax; dx <= dxmax; dx += 2) {
x = xnorm(sect.sct_x + dx);
n = scthash(x, y, TSIZE);
if (!list[n])
continue;

View file

@ -57,10 +57,9 @@ skyw(void)
struct nstr_sect nstr;
struct sky *skyp;
struct sky *list[TSIZE];
int i, k, j, n;
int i, n;
int vrange, see;
int x, y;
int mink, minj, maxk, maxj;
int x, y, dx, dy, dxmax;
int nsat = 0;
double tech;
struct nstr_item ni;
@ -96,20 +95,11 @@ skyw(void)
vrange = (int)(sect.sct_effic / 100.0 * see * tech);
if (vrange < 1)
vrange = 1;
maxk = vrange;
maxj = vrange * 2;
vrange *= vrange;
mink = -maxk;
minj = -maxj;
for (j = minj; j <= maxj && nsat; j++) {
x = xnorm(sect.sct_x + j);
for (k = mink; k <= maxk && nsat; k++) {
if ((j + k) & 01)
continue;
/* quick range check to save time... */
if (vrange < (j * j + 3 * k * k) / 4)
continue;
y = ynorm(sect.sct_y + k);
for (dy = -vrange; dy <= vrange; dy++) {
y = ynorm(sect.sct_y + dy);
dxmax = 2 * vrange - abs(dy);
for (dx = -dxmax; dx <= dxmax; dx += 2) {
x = xnorm(sect.sct_x + dx);
n = scthash(x, y, TSIZE);
if (!list[n])
continue;