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
Line 
1/* validate.c
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 *
8 *   Copyright (C) 1993,1994,1996,2000,2001,2024 Olly Betts
9 *
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.
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
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 * GNU General Public License for more details.
19 *
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
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
23 */
24
25#include <config.h>
26
27#include "cavern.h"
28#include "filename.h"
29#include "message.h"
30#include "netbits.h"
31#include "validate.h"
32
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
42
43static bool validate_prefix_tree(void);
44static bool validate_prefix_subtree(prefix *pfx);
45
46static bool validate_station_list(void);
47
48#undef validate
49extern bool
50validate(void)
51{
52   bool fOk = true;
53   if (!validate_prefix_tree()) fOk = false;
54   if (!validate_station_list()) fOk = false;
55   if (fOk) puts("*** Data structures passed consistency checks");
56   else puts("*** Data structures FAILED consistency checks");
57   return fOk;
58}
59
60static bool
61validate_prefix_tree(void)
62{
63   bool fOk = true;
64   if (root->up != NULL) {
65      printf("*** root->up == %p\n", root->up);
66      fOk = false;
67   }
68   if (root->right != NULL) {
69      printf("*** root->right == %p\n", root->right);
70      fOk = false;
71   }
72   if (root->stn != NULL) {
73      printf("*** root->stn == %p\n", root->stn);
74      fOk = false;
75   }
76   if (root->pos != NULL) {
77      printf("*** root->pos == %p\n", root->pos);
78      fOk = false;
79   }
80   fOk &= validate_prefix_subtree(root);
81   return fOk;
82}
83
84static bool
85validate_prefix_subtree(prefix *pfx)
86{
87   bool fOk = true;
88   prefix *pfx2;
89   pfx2 = pfx->down;
90   /* this happens now, as nodes are freed after solving */
91#if 0
92   if (pfx2 == NULL) {
93      if (pfx->stn == NULL) {
94         printf("*** Leaf prefix '");
95         print_prefix(pfx);
96         printf("' has no station attached\n");
97         fOk = false;
98      }
99      return fOk;
100   }
101#endif
102
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");
110         fOk = false;
111      }
112      if (pfx2->up != pfx) {
113         printf("*** Prefix '");
114         print_prefix(pfx2);
115         printf("' ->up is '");
116         print_prefix(pfx);
117         printf("'\n");
118         fOk = false;
119      }
120      fOk &= validate_prefix_subtree(pfx2);
121      pfx2 = pfx2->right;
122   }
123   return fOk;
124}
125
126static bool
127validate_station_list(void)
128{
129   bool fOk = true;
130   node *stn2;
131   int d, d2;
132
133   SVX_ASSERT(!stnlist || !stnlist->prev);
134   /* NB: don't use FOR_EACH_STN as it isn't reentrant at present */
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;
146#if 0
147         printf("V [%p]<-[%p]->[%p] ", stn->prev, stn, stn->next); print_prefix(stn->name); putnl();
148#endif
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) {
156                  printf("*** Station '");
157                  print_prefix(stn->name);
158                  printf("', leg %d is used, but an earlier leg isn't\n", d);
159                  fOk = false;
160               }
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) {
179                  printf("*** Station '");
180                  print_prefix(stn2->name);
181                  printf("' [%p], leg %d points to NULL\n", stn2, d2);
182                  fOk = false;
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) {
190                     printf("*** Station '");
191                     print_prefix(stn->name);
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");
197                     fOk = false;
198                  }
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               }
222            }
223
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               }
234            }
235         }
236      }
237   }
238   return fOk;
239}
240
241#undef dump_node
242extern void
243dump_node(node *stn)
244{
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    }
258
259    printf(" colour %ld", stn->colour);
260    if (fixed(stn)) {
261        printf(" FIXED\n");
262    } else {
263        putnl();
264    }
265
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    }
280}
281
282/* This doesn't cover removed stations - might be nice to have
283 * dump_entire_network() which iterates prefix tree */
284#undef dump_network
285extern void
286dump_network(void)
287{
288   node *stn;
289   /* NB: don't use FOR_EACH_STN as it isn't reentrant at present */
290   for (stn = fixedlist; stn; stn = stn->next) dump_node(stn);
291   for (stn = stnlist; stn; stn = stn->next) dump_node(stn);
292}
Note: See TracBrowser for help on using the repository browser.