From 5e08b7fa55ec320c8452f5962a20f5eacd63967b Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Sat, 3 Apr 2010 18:34:52 +0200 Subject: [PATCH] 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. --- src/lib/commands/coas.c | 24 +++++++----------------- src/lib/commands/skyw.c | 24 +++++++----------------- 2 files changed, 14 insertions(+), 34 deletions(-) diff --git a/src/lib/commands/coas.c b/src/lib/commands/coas.c index 894649a0..9576586f 100644 --- a/src/lib/commands/coas.c +++ b/src/lib/commands/coas.c @@ -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; diff --git a/src/lib/commands/skyw.c b/src/lib/commands/skyw.c index 349ca7e9..422c8596 100644 --- a/src/lib/commands/skyw.c +++ b/src/lib/commands/skyw.c @@ -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;