source: git/src/validate.c @ f498802

stereo-2025
Last change on this file since f498802 was f498802, checked in by Olly Betts <olly@…>, 4 months ago

Increase MAX_POS to allow for UTM outside zones

This only matters if validation checks are enabled (which they
aren't by default - they're expensive and intended to help find
and fix bugs), but it's more helpful if they don't reject any
coordinates which might be seen in real world data.

  • Property mode set to 100644
File size: 7.9 KB
RevLine 
[421b7d2]1/* validate.c
[d1b1380]2 *
3 *   Checks that SURVEX's data structures are valid and consistent
4 *
5 *   NB The checks currently done aren't very comprehensive - more will be
6 *    added if bugs require them
7 *
[bf9faf6]8 *   Copyright (C) 1993,1994,1996,2000,2001,2024 Olly Betts
[846746e]9 *
[89231c4]10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
[846746e]14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
[89231c4]17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 * GNU General Public License for more details.
[846746e]19 *
[89231c4]20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
[ecbc6c18]22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
[d1b1380]23 */
24
[4c83f84]25#include <config.h>
[d1b1380]26
[a420b49]27#include "cavern.h"
[c082b69]28#include "filename.h"
29#include "message.h"
[d1b1380]30#include "netbits.h"
31#include "validate.h"
32
[f498802]33/* Maximum absolute value of a coordinate of a fixed station for validate()
34 * to allow, in metres.
35 *
36 * The Northing of the equator in southern hemisphere UTM zones is 10000000m,
37 * which seems to be the largest coordinate in any common CRS.  We add an
38 * extra 100km to allow for extending such a zone North to cover a cave system
39 * which straddles the equator.
40 */
41#define MAX_POS 10100000.0
[d1b1380]42
[a420b49]43static bool validate_prefix_tree(void);
44static bool validate_prefix_subtree(prefix *pfx);
[d1b1380]45
[a420b49]46static bool validate_station_list(void);
[d1b1380]47
[a420b49]48#undef validate
49extern bool
50validate(void)
51{
[63d4f07]52   bool fOk = true;
53   if (!validate_prefix_tree()) fOk = false;
54   if (!validate_station_list()) fOk = false;
[a420b49]55   if (fOk) puts("*** Data structures passed consistency checks");
[6d3f931]56   else puts("*** Data structures FAILED consistency checks");
[a420b49]57   return fOk;
58}
[d1b1380]59
[a420b49]60static bool
61validate_prefix_tree(void)
62{
[63d4f07]63   bool fOk = true;
[a420b49]64   if (root->up != NULL) {
65      printf("*** root->up == %p\n", root->up);
[63d4f07]66      fOk = false;
[a420b49]67   }
68   if (root->right != NULL) {
69      printf("*** root->right == %p\n", root->right);
[63d4f07]70      fOk = false;
[a420b49]71   }
72   if (root->stn != NULL) {
73      printf("*** root->stn == %p\n", root->stn);
[63d4f07]74      fOk = false;
[a420b49]75   }
76   if (root->pos != NULL) {
77      printf("*** root->pos == %p\n", root->pos);
[63d4f07]78      fOk = false;
[a420b49]79   }
80   fOk &= validate_prefix_subtree(root);
81   return fOk;
82}
[d1b1380]83
[a420b49]84static bool
85validate_prefix_subtree(prefix *pfx)
86{
[63d4f07]87   bool fOk = true;
[a420b49]88   prefix *pfx2;
89   pfx2 = pfx->down;
90   /* this happens now, as nodes are freed after solving */
[d1b1380]91#if 0
[a420b49]92   if (pfx2 == NULL) {
93      if (pfx->stn == NULL) {
94         printf("*** Leaf prefix '");
95         print_prefix(pfx);
96         printf("' has no station attached\n");
[63d4f07]97         fOk = false;
[a420b49]98      }
99      return fOk;
[d1b1380]100   }
101#endif
102
[a420b49]103   while (pfx2 != NULL) {
104      if (pfx2->stn != NULL && pfx2->stn->name != pfx2) {
105         printf("*** Prefix '");
106         print_prefix(pfx2);
107         printf("' ->stn->name is '");
108         print_prefix(pfx2->stn->name);
109         printf("'\n");
[63d4f07]110         fOk = false;
[a420b49]111      }
112      if (pfx2->up != pfx) {
113         printf("*** Prefix '");
114         print_prefix(pfx2);
115         printf("' ->up is '");
116         print_prefix(pfx);
117         printf("'\n");
[63d4f07]118         fOk = false;
[a420b49]119      }
120      fOk &= validate_prefix_subtree(pfx2);
121      pfx2 = pfx2->right;
[d1b1380]122   }
[a420b49]123   return fOk;
124}
125
126static bool
127validate_station_list(void)
128{
[63d4f07]129   bool fOk = true;
[bf9faf6]130   node *stn2;
[a420b49]131   int d, d2;
132
[4c07c51]133   SVX_ASSERT(!stnlist || !stnlist->prev);
[6d3f931]134   /* NB: don't use FOR_EACH_STN as it isn't reentrant at present */
[bf9faf6]135   for (int fixed = 0; fixed < 2; ++fixed) {
136      for (node *stn = fixed ? fixedlist : stnlist; stn; stn = stn->next) {
137         if (fixed(stn) != fixed) {
138             printf("*** Station '");
139             print_prefix(stn->name);
140             printf("' is %sfixed but on %sfixed list\n",
141                    fixed ? "un" : "", fixed ? "" : "un");
142             fOk = false;
143         }
144
145         bool fGap = false;
[095ef764]146#if 0
[bf9faf6]147         printf("V [%p]<-[%p]->[%p] ", stn->prev, stn, stn->next); print_prefix(stn->name); putnl();
[095ef764]148#endif
[bf9faf6]149         SVX_ASSERT(stn->prev == NULL || stn->prev->next == stn);
150         SVX_ASSERT(stn->next == NULL || stn->next->prev == stn);
151         for (d = 0; d <= 2; d++) {
152            if (!stn->leg[d]) {
153               fGap = true;
154            } else {
155               if (fGap) {
[a420b49]156                  printf("*** Station '");
157                  print_prefix(stn->name);
[bf9faf6]158                  printf("', leg %d is used, but an earlier leg isn't\n", d);
[63d4f07]159                  fOk = false;
[a420b49]160               }
[bf9faf6]161               stn2 = stn->leg[d]->l.to;
162               SVX_ASSERT(stn2);
163               d2 = reverse_leg_dirn(stn->leg[d]);
164               if (stn2->leg[d2] == NULL) {
165                  /* fine iff stn is at the disconnected end of a fragment */
166                  node *s;
167                  /* NB: don't use FOR_EACH_STN as it isn't reentrant at present */
168                  for (s = stnlist; s; s = s->next) if (s == stn) break;
169                  if (!s) for (s = fixedlist; s; s = s->next) if (s == stn) break;
170                  if (s) {
171                     printf("*** Station '");
172                     print_prefix(stn->name);
173                     printf("', leg %d doesn't reciprocate from station '", d);
174                     print_prefix(stn2->name);
175                     printf("'\n");
176                     fOk = false;
177                  }
178               } else if (stn2->leg[d2]->l.to == NULL) {
[a420b49]179                  printf("*** Station '");
180                  print_prefix(stn2->name);
[bf9faf6]181                  printf("' [%p], leg %d points to NULL\n", stn2, d2);
[63d4f07]182                  fOk = false;
[bf9faf6]183               } else if (stn2->leg[d2]->l.to!=stn) {
184                  /* fine iff stn is at the disconnected end of a fragment */
185                  node *s;
186                  /* NB: don't use FOR_EACH_STN as it isn't reentrant at present */
187                  for (s = stnlist; s; s = s->next) if (s == stn) break;
188                  if (!s) for (s = fixedlist; s; s = s->next) if (s == stn) break;
189                  if (s) {
[a420b49]190                     printf("*** Station '");
191                     print_prefix(stn->name);
[bf9faf6]192                     printf("' [%p], leg %d reciprocates via station '", stn, d);
193                     print_prefix(stn2->name);
194                     printf("' to station '");
195                     print_prefix(stn2->leg[d2]->l.to->name);
196                     printf("'\n");
[63d4f07]197                     fOk = false;
[a420b49]198                  }
[bf9faf6]199               } else if ((data_here(stn->leg[d]) != 0) ^
200                          (data_here(stn2->leg[d2]) == 0)) {
201                  printf("*** Station '");
202                  print_prefix(stn->name);
203                  printf("' [%p], leg %d reciprocates via station '", stn, d);
204                  print_prefix(stn2->name);
205                  if (data_here(stn->leg[d]))
206                     printf("' - data on both legs\n");
207                  else
208                     printf("' - data on neither leg\n");
209                  fOk = false;
210               }
211               if (data_here(stn->leg[d])) {
212                  int i;
213                  for (i = 0; i < 3; i++)
214                     if (fabs(stn->leg[d]->d[i]) > MAX_POS) {
215                        printf("*** Station '");
216                        print_prefix(stn->name);
217                        printf("', leg %d, d[%d] = %g\n",
218                               d, i, (double)(stn->leg[d]->d[i]));
219                        fOk = false;
220                     }
221               }
[a420b49]222            }
223
[bf9faf6]224            if (fixed(stn)) {
225               if (fabs(POS(stn, 0)) > MAX_POS ||
226                   fabs(POS(stn, 1)) > MAX_POS ||
227                   fabs(POS(stn, 2)) > MAX_POS) {
228                  printf("*** Station '");
229                  print_prefix(stn->name);
230                  printf("' fixed at coords (%f,%f,%f)\n",
231                         POS(stn, 0), POS(stn, 1), POS(stn, 2) );
232                  fOk = false;
233               }
[a420b49]234            }
235         }
[d1b1380]236      }
[a420b49]237   }
238   return fOk;
239}
240
241#undef dump_node
242extern void
243dump_node(node *stn)
244{
[f192c5c]245    printf("stn [%p]", stn);
246    if (stn->name) {
247        if (stn->name->stn == stn) {
248            printf("<->");
249        } else {
250            printf("-->");
251        }
252        printf("name ");
253        print_prefix(stn->name);
254        printf(" (%p)", stn->name);
255    } else {
256        printf("-->NULL");
257    }
[d1b1380]258
[f192c5c]259    printf(" colour %ld", stn->colour);
260    if (fixed(stn)) {
261        printf(" FIXED\n");
262    } else {
263        putnl();
264    }
[d1b1380]265
[f192c5c]266    for (int d = 0; d <= 2; d++) {
267        linkfor *leg = stn->leg[d];
268        if (leg) {
269            const char* type;
270            if (data_here(leg)) {
271                type = fZeros(&leg->v) ? "=>" : "->";
272            } else {
273                type = fZeros(&reverse_leg(leg)->v) ? "<=" : "<-";
274            }
275            printf("  leg #%d %s stn [%p] ", d, type, leg->l.to);
276            print_prefix(leg->l.to->name);
277            printf(" | rev %d\n", reverse_leg_dirn(leg));
278        }
279    }
[a420b49]280}
[d1b1380]281
[b6e9e7e]282/* This doesn't cover removed stations - might be nice to have
283 * dump_entire_network() which iterates prefix tree */
[cb3d1e2]284#undef dump_network
[a420b49]285extern void
286dump_network(void)
287{
288   node *stn;
[6d3f931]289   /* NB: don't use FOR_EACH_STN as it isn't reentrant at present */
[bf9faf6]290   for (stn = fixedlist; stn; stn = stn->next) dump_node(stn);
[6d3f931]291   for (stn = stnlist; stn; stn = stn->next) dump_node(stn);
[a420b49]292}
Note: See TracBrowser for help on using the repository browser.