]> git.pond.sub.org Git - empserver/commitdiff
coastwatch and skywatch could see too far
authorMarkus Armbruster <armbru@pond.sub.org>
Sat, 3 Apr 2010 16:34:52 +0000 (18:34 +0200)
committerMarkus Armbruster <armbru@pond.sub.org>
Sun, 4 Apr 2010 05:31:06 +0000 (07:31 +0200)
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
src/lib/commands/skyw.c

index 894649a0f8e5a2ac7f1750b0fcf49c24f2ba7a6c..9576586f03612740ed6ba53f1c8df4ec7e2c9bd6 100644 (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;
index 349ca7e96c77edfde10d670dddc5241be561c0d7..422c8596b08fbf27cf9c96f8bd24141f9b45d588 100644 (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;