source: git/src/cavern.h @ 66be513

stereo-2025
Last change on this file since 66be513 was bf9faf6, checked in by Olly Betts <olly@…>, 8 months ago

Fix component counting bugs

The component count was wrong in some cases, and we calculate the number
of loops using this component count, so the loop count would be wrong by
the same amount in these cases.

  • Property mode set to 100644
File size: 16.1 KB
Line 
1/* cavern.h
2 * SURVEX Cave surveying software - header file
3 * Copyright (C) 1991-2024 Olly Betts
4 * Copyright (C) 2004 Simeon Warner
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
19 */
20
21#ifndef CAVERN_H
22#define CAVERN_H
23
24/* Using covariances increases the memory required somewhat - may be
25 * desirable to disable this for small memory machines */
26
27/* #define NO_COVARIANCES 1 */
28
29#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
32#include <ctype.h>
33#include <math.h>
34#include <float.h>
35
36#include <proj.h>
37
38#include "img_hosted.h"
39#include "str.h"
40#include "useful.h"
41
42typedef double real; /* so we can change the precision used easily */
43#define HUGE_REAL HUGE_VAL
44#define REAL_EPSILON DBL_EPSILON
45
46#define SPECIAL_EOL             0x0001
47#define SPECIAL_BLANK           0x0002
48#define SPECIAL_KEYWORD         0x0004
49#define SPECIAL_COMMENT         0x0008
50#define SPECIAL_OMIT            0x0010
51#ifndef NO_DEPRECATED
52#define SPECIAL_ROOT            0x0020
53#endif
54#define SPECIAL_SEPARATOR       0x0040
55#define SPECIAL_NAMES           0x0080
56#define SPECIAL_DECIMAL         0x0100
57#define SPECIAL_MINUS           0x0200
58#define SPECIAL_PLUS            0x0400
59#define SPECIAL_OPEN            0x0800
60#define SPECIAL_CLOSE           0x1000
61
62extern char *fnm_output_base;
63extern int fnm_output_base_is_dir;
64
65extern bool fExportUsed;
66
67extern int current_days_since_1900;
68
69/* Types */
70
71typedef enum {
72   Q_NULL = -1, Q_DEFAULT, Q_POS, Q_PLUMB, Q_LEVEL,
73   Q_GRADIENT, Q_BACKGRADIENT, Q_BEARING, Q_BACKBEARING,
74   Q_LENGTH, Q_BACKLENGTH, Q_DEPTH, Q_DX, Q_DY, Q_DZ, Q_COUNT, Q_DECLINATION,
75   Q_LEFT, Q_RIGHT, Q_UP, Q_DOWN,
76   Q_MAC
77} q_quantity;
78
79typedef enum {
80   INFER_NULL = -1,
81   INFER_EQUATES,
82   INFER_EXPORTS,
83   INFER_PLUMBS,
84   INFER_SUBSURVEYS,
85   /* In Compass DAT files a dummy zero-length leg from a station to itself is
86    * used to provide a place to specify LRUD for the start or end of a
87    * traverse (depending if dimensions are measured at the from or to
88    * station), so we shouldn't warn about equating a station to itself.
89    * This should be set *as well as* INFER_EQUATES.
90    */
91   INFER_EQUATES_SELF_OK
92} infer_what;
93
94/* unsigned long to cope with 16-bit int-s */
95#define BIT(N) (1UL << (N))
96#define BITA(N) (1UL << ((N) - 'a'))
97
98#define TSTBIT(W, N) (((W)>>(N))&1)
99
100/* masks for quantities which are length and angles respectively */
101#define LEN_QMASK (BIT(Q_LENGTH) | BIT(Q_BACKLENGTH) | BIT(Q_DEPTH) |\
102   BIT(Q_DX) | BIT(Q_DY) | BIT(Q_DZ) | BIT(Q_POS) | BIT(Q_COUNT) |\
103   BIT(Q_LEFT) | BIT(Q_RIGHT) | BIT(Q_UP) | BIT(Q_DOWN))
104#define ANG_QMASK (BIT(Q_BEARING) | BIT(Q_BACKBEARING) |\
105   BIT(Q_GRADIENT) | BIT(Q_BACKGRADIENT) | BIT(Q_PLUMB) | BIT(Q_LEVEL) |\
106   BIT(Q_DECLINATION))
107
108/* if you add/change the order, check factor_tab in commands.c */
109typedef enum {
110   UNITS_NULL = -1, UNITS_METRES, UNITS_FEET, UNITS_YARDS,
111   UNITS_DEGS, UNITS_QUADRANTS, UNITS_GRADS, UNITS_PERCENT, UNITS_MINUTES,
112   UNITS_MAC, UNITS_DEPRECATED_ALIAS_FOR_GRADS
113} u_units;
114
115/* don't reorder these values!  They need to match with img.h too */
116typedef enum {
117   FLAGS_NOT = -2, FLAGS_UNKNOWN = -1, FLAGS_SURFACE, FLAGS_DUPLICATE,
118   FLAGS_SPLAY,
119#if 0
120   /* underground, but through rock (e.g. radiolocation).  Want to hide from
121    * plots by default (so not cave) but don't want to include in surface
122    * triangulation nets (so not surface) */
123   FLAGS_SKELETAL, /* FIXME */
124#endif
125   /* Don't need to match img.h: */
126   FLAGS_ANON_ONE_END,
127   FLAGS_IMPLICIT_SPLAY,
128   FLAGS_STYLE_BIT0, FLAGS_STYLE_BIT1, FLAGS_STYLE_BIT2
129} flags;
130
131/* flags are currently stored in an unsigned char */
132typedef int compiletimeassert_flags0[FLAGS_STYLE_BIT2 <= 7 ? 1 : -1];
133
134/* Mask to AND with to get bits to pass to img library. */
135#define FLAGS_MASK \
136    (BIT(FLAGS_SURFACE) | BIT(FLAGS_DUPLICATE) | BIT(FLAGS_SPLAY))
137
138typedef int compiletimeassert_flags1[BIT(FLAGS_SURFACE) == img_FLAG_SURFACE ? 1 : -1];
139typedef int compiletimeassert_flags2[BIT(FLAGS_DUPLICATE) == img_FLAG_DUPLICATE ? 1 : -1];
140typedef int compiletimeassert_flags3[BIT(FLAGS_SPLAY) == img_FLAG_SPLAY ? 1 : -1];
141
142typedef enum {
143   /* Don't reorder these values!  They need to match with img.h too. */
144   SFLAGS_SURFACE = 0, SFLAGS_UNDERGROUND, SFLAGS_ENTRANCE, SFLAGS_EXPORTED,
145   SFLAGS_FIXED, SFLAGS_ANON, SFLAGS_WALL,
146   /* These values don't need to match img.h, but mustn't clash. */
147   SFLAGS_HANGING = 9,
148   SFLAGS_USED = 10,
149   SFLAGS_SOLVED = 11,
150   SFLAGS_SUSPECTTYPO = 12,
151   SFLAGS_SURVEY = 13,
152   SFLAGS_PREFIX_ENTERED = 14,
153   // If set, use ident.i; if unset, use ident.p
154   SFLAGS_IDENT_INLINE = 15
155} sflags;
156
157/* Mask to AND with to get bits to pass to img library. */
158#define SFLAGS_MASK (BIT(SFLAGS_SURFACE) | BIT(SFLAGS_UNDERGROUND) |\
159        BIT(SFLAGS_ENTRANCE) | BIT(SFLAGS_EXPORTED) | BIT(SFLAGS_FIXED) |\
160        BIT(SFLAGS_ANON) | BIT(SFLAGS_WALL))
161
162typedef int compiletimeassert_sflags1[BIT(SFLAGS_SURFACE) == img_SFLAG_SURFACE ? 1 : -1];
163typedef int compiletimeassert_sflags2[BIT(SFLAGS_UNDERGROUND) == img_SFLAG_UNDERGROUND ? 1 : -1];
164typedef int compiletimeassert_sflags3[BIT(SFLAGS_ENTRANCE) == img_SFLAG_ENTRANCE ? 1 : -1];
165typedef int compiletimeassert_sflags4[BIT(SFLAGS_EXPORTED) == img_SFLAG_EXPORTED ? 1 : -1];
166typedef int compiletimeassert_sflags5[BIT(SFLAGS_FIXED) == img_SFLAG_FIXED ? 1 : -1];
167typedef int compiletimeassert_sflags6[BIT(SFLAGS_ANON) == img_SFLAG_ANON ? 1 : -1];
168typedef int compiletimeassert_sflags7[BIT(SFLAGS_WALL) == img_SFLAG_WALL ? 1 : -1];
169
170/* enumeration of field types */
171typedef enum {
172   End = 0, Tape, Comp, Clino, BackTape, BackComp, BackClino,
173   Left, Right, Up, Down,
174   FrDepth, ToDepth, Dx, Dy, Dz, FrCount, ToCount,
175   /* Up to here are readings are allowed multiple values
176    * and have slot in the value[] array in datain.c.
177    * (Depth, DepthChange, and Count can have multiple
178    * readings, but are actually handled using tokens
179    * above rather than as themselves).
180    *
181    * Fr must be the first reading after this comment!
182    */
183   Fr, To, Station, Depth, DepthChange, Count, Dir,
184   Newline, IgnoreAllAndNewLine, Ignore, IgnoreAll,
185   /* IgnoreAll must be the last reading before this comment!
186    *
187    * Readings after this comment are only used in datain.c
188    * so can have enum values >= 32 because we only use a
189    * bitmask for those readings used in commands.c.
190    */
191   CompassDATFr, CompassDATTo,
192   CompassDATComp, CompassDATClino, CompassDATBackComp, CompassDATBackClino,
193   CompassDATLeft, CompassDATRight, CompassDATUp, CompassDATDown,
194   CompassDATFlags,
195
196   WallsSRVFr, WallsSRVTo, WallsSRVTape, WallsSRVComp, WallsSRVClino,
197   // Optional pair of readings giving heights above stations on CT surveys.
198   WallsSRVHeights,
199   // Optional delimited LRUD and variance overrides.
200   WallsSRVExtras
201} reading;
202
203/* if IgnoreAll is >= 32, the compiler will choke on this */
204typedef char compiletimeassert_reading[IgnoreAll < 32 ? 1 : -1];
205
206/* position or length vector */
207typedef real delta[3];
208
209/* variance */
210#ifdef NO_COVARIANCES
211typedef real var[3];
212typedef var svar;
213#else
214typedef real var[3][3];
215typedef real svar[6];
216#endif
217
218/* station name */
219typedef struct Prefix {
220   struct Prefix *up, *down, *right;
221   struct Node *stn;
222   struct Pos *pos;
223   union {
224       const char *p;
225       char i[sizeof(const char*)];
226   } ident;
227   // A filename:line where this name was used.  If it's a station used in *fix
228   // then this will be the location of such a *fix, otherwise if it's a
229   // station used in *equate then it's the location of such a *equate.
230   // Otherwise it's the first place it was used.
231   const char *filename;
232   unsigned int line;
233   /* If (min_export == 0) then max_export is max # levels above is this
234    * prefix is used (and so needs to be exported) (0 == parent only).
235    * If (min_export > 0) then max_export is max # levels above this
236    * prefix has been exported, and min_export is how far down the exports
237    * have got (if min_export > 1 after a run, this prefix hasn't been
238    * exported from below enough).
239    * If INFER_EXPORTS is active when a station is encountered, we
240    * set min_export = USHRT_MAX and max_export gets set as usual.  Then at
241    * the end of the run, we also mark stations with min_export == USHRT_MAX
242    * and max_export > 0 as exported. */
243   unsigned short max_export, min_export;
244   /* stn flags - e.g. surface, underground, entrance
245    * also suspecttypo and survey */
246   unsigned short sflags;
247   short shape;
248} prefix;
249
250static inline const char *prefix_ident(const prefix *p) {
251    return TSTBIT(p->sflags, SFLAGS_IDENT_INLINE) ? p->ident.i : p->ident.p;
252}
253
254/* survey metadata */
255typedef struct Meta_data {
256    size_t ref_count;
257    /* Days since 1900 for start and end date of survey, or -1 if undated. */
258    int days1, days2;
259} meta_data;
260
261/* stuff stored for both forward & reverse legs */
262typedef struct {
263   struct Node *to;
264   /* bits 0..1 = reverse leg number; bit7 is fFullLeg */
265   /* bit6 = fReplacementLeg (by reduction rules) */
266   /* bit5 = articulation leg (i.e. carries no error) */
267   unsigned char reverse;
268   /* flags - e.g. surface, duplicate survey
269    * only used if (FLAG_DATAHERE & !(FLAG_REPLACEMENTLEG|FLAG_FAKE))
270    * This could be only in linkfor, but this is actually more space
271    * efficient.
272    */
273   unsigned char flags;
274} linkcommon;
275
276#define FLAG_DATAHERE 0x80
277#define FLAG_REPLACEMENTLEG 0x40
278#define FLAG_ARTICULATION 0x20
279#define FLAG_FAKE 0x10 /* an equate or leg inside an sdfix */
280#define MASK_REVERSEDIRN 0x03
281
282/* reverse leg - deltas & vars stored on other dirn */
283typedef struct LinkRev {
284   linkcommon l;
285} linkrev;
286
287/* forward leg - deltas & vars stored here */
288typedef struct Link {
289   linkcommon l;
290   delta d; /* Delta */
291   svar v; /* Variances */
292   meta_data *meta;
293} linkfor;
294
295/* node - like a station, except several nodes are used to represent a
296 * station with more than 3 legs connected to it
297 */
298typedef struct Node {
299   struct Prefix *name;
300   struct Link *leg[3];
301   struct Node *prev, *next;
302   // Used in netartic.c to identify unconnected components and articulation
303   // points within components.
304   //
305   // Used in matrix.c to record the matrix row corresponding to this node
306   // or -1 for nodes already fixed (more than one node may map to the same
307   // row).
308   long colour;
309} node;
310
311/* station position */
312typedef struct Pos {
313   // Easting, Northing, Altitude.
314   real p[3];
315} pos;
316
317/*
318typedef struct Inst {
319   real zero, scale, units;
320} inst;
321*/
322
323/* Survey data styles */
324#define STYLE_NORMAL     0
325#define STYLE_DIVING     1
326#define STYLE_CARTESIAN  2
327#define STYLE_CYLPOLAR   3
328#define STYLE_NOSURVEY   4
329#define STYLE_PASSAGE    5
330#define STYLE_IGNORE     6
331
332typedef int compiletimeassert_style1[STYLE_NORMAL == img_STYLE_NORMAL ? 1 : -1];
333typedef int compiletimeassert_style2[STYLE_DIVING == img_STYLE_DIVING ? 1 : -1];
334typedef int compiletimeassert_style3[STYLE_CARTESIAN == img_STYLE_CARTESIAN ? 1 : -1];
335typedef int compiletimeassert_style4[STYLE_CYLPOLAR == img_STYLE_CYLPOLAR ? 1 : -1];
336typedef int compiletimeassert_style5[STYLE_NOSURVEY == img_STYLE_NOSURVEY ? 1 : -1];
337
338/* various settings preserved by *BEGIN and *END */
339typedef struct Settings {
340   struct Settings *next;
341   unsigned int Truncate;
342   bool f_clino_percent;
343   bool f_backclino_percent;
344   bool f_bearing_quadrants;
345   bool f_backbearing_quadrants;
346   bool dash_for_anon_wall_station;
347   bool from_equals_to_is_only_a_warning;
348   unsigned char infer;
349   enum {OFF, LOWER, UPPER} Case;
350   /* STYLE_xxx value to process data as. */
351   int style;
352   /* STYLE_xxx value to put in 3d file (different for Compass DAT diving
353    * data, as the data in the DAT file is always presented in the format
354    * tape,compass,clino even if that isn't how it was really measured).
355    */
356   int recorded_style;
357   prefix *Prefix;
358   prefix *begin_survey; /* used to check BEGIN and END match */
359   short *Translate; /* if short is >= 16 bits, which ANSI requires */
360   real Var[Q_MAC];
361   real z[Q_MAC];
362   real sc[Q_MAC];
363   real units[Q_MAC];
364   const reading *ordering;
365   long begin_lpos; /* File offset for start of BEGIN line */
366   int begin_lineno; /* 0 means no block started in this file */
367   int begin_col; /* Column of prefix in BEGIN line (or 0 if none) */
368   int flags;
369   char* proj_str;
370   /* Location at which we calculate the declination if
371    * z[Q_DECLINATION] == HUGE_REAL.
372    *
373    * Latitude and longitude are in radians; altitude is in metres above the
374    * ellipsoid.
375    */
376   real dec_lat, dec_lon, dec_alt;
377   /* Cached auto-declination in radians, or HUGE_REAL for no cached value.
378    * Only meaningful if date1 != -1.
379    */
380   real declination;
381   double min_declination, max_declination;
382   int min_declination_days, max_declination_days;
383   const char* dec_filename;
384   int dec_line;
385   /* Copy of the text of the `*declination auto ...` line (malloced). */
386   char* dec_context;
387   /* Grid convergence in radians. */
388   real convergence;
389   /* Input grid convergence in radians. */
390   real input_convergence;
391   /* Rotation from North for `*data cartesian`. */
392   real cartesian_rotation;
393   /* Which North to use for `*data cartesian`. */
394   enum { TRUE_NORTH, GRID_NORTH, MAGNETIC_NORTH } cartesian_north;
395   meta_data * meta;
396} settings;
397
398/* global variables */
399extern settings *pcs;
400extern prefix *root;
401extern prefix *anon_list;
402extern node *fixedlist;
403extern node *stnlist;
404extern unsigned long optimize;
405extern char * proj_str_out;
406extern PJ * pj_cached;
407
408extern string survey_title;
409
410extern bool fExplicitTitle;
411extern long cLegs, cStns, cComponents;
412extern bool hanging_surveys;
413extern FILE *fhErrStat;
414extern img *pimg;
415extern real totadj, total, totplan, totvert;
416extern real min[6], max[6];
417extern prefix *pfxHi[6], *pfxLo[6];
418extern bool fQuiet; /* just show brief summary + errors */
419extern bool fMute; /* just show errors */
420extern bool fSuppress; /* only output 3d file */
421
422/* macros */
423
424#define POS(S, D) ((S)->name->pos->p[(D)])
425#define POSD(S) ((S)->name->pos->p)
426
427#define data_here(L) ((L)->l.reverse & FLAG_DATAHERE)
428#define reverse_leg_dirn(L) ((L)->l.reverse & MASK_REVERSEDIRN)
429#define reverse_leg(L) ((L)->l.to->leg[reverse_leg_dirn(L)])
430
431/* if p[0]==UNFIXED_VAL, station is unfixed */
432#define UNFIXED_VAL HUGE_VAL
433#define pfx_fixed(N) ((N)->pos->p[0] != UNFIXED_VAL)
434#define pos_fixed(P) ((P)->p[0] != UNFIXED_VAL)
435#define unfix(S) POS((S), 0) = UNFIXED_VAL
436#define fixed(S) pfx_fixed((S)->name)
437
438/* macros for special chars */
439
440#define isEol(c)    (pcs->Translate[(c)] & SPECIAL_EOL)
441#define isBlank(c)  (pcs->Translate[(c)] & SPECIAL_BLANK)
442#define isKeywd(c)  (pcs->Translate[(c)] & SPECIAL_KEYWORD)
443#define isComm(c)   (pcs->Translate[(c)] & SPECIAL_COMMENT)
444#define isOmit(c)   (pcs->Translate[(c)] & SPECIAL_OMIT)
445#ifndef NO_DEPRECATED
446#define isRoot(c)   (pcs->Translate[(c)] & SPECIAL_ROOT)
447#endif
448#define isSep(c)    (pcs->Translate[(c)] & SPECIAL_SEPARATOR)
449#define isNames(c)  (pcs->Translate[(c)] & SPECIAL_NAMES)
450#define isDecimal(c) (pcs->Translate[(c)] & SPECIAL_DECIMAL)
451#define isMinus(c)  (pcs->Translate[(c)] & SPECIAL_MINUS)
452#define isPlus(c)   (pcs->Translate[(c)] & SPECIAL_PLUS)
453#define isOpen(c)   (pcs->Translate[(c)] & SPECIAL_OPEN)
454#define isClose(c)  (pcs->Translate[(c)] & SPECIAL_CLOSE)
455
456#define isSign(c)   (pcs->Translate[(c)] & (SPECIAL_PLUS | SPECIAL_MINUS))
457#define isData(c)   (pcs->Translate[(c)] & (SPECIAL_OMIT | SPECIAL_ROOT|\
458   SPECIAL_SEPARATOR | SPECIAL_NAMES | SPECIAL_DECIMAL | SPECIAL_PLUS |\
459   SPECIAL_MINUS))
460
461typedef struct nosurveylink {
462   node *fr, *to;
463   int flags;
464   meta_data *meta;
465   struct nosurveylink *next;
466} nosurveylink;
467
468extern nosurveylink *nosurveyhead;
469
470typedef struct lrud {
471    struct lrud * next;
472    prefix *stn;
473    meta_data *meta;
474    real l, r, u, d;
475} lrud;
476
477typedef struct lrudlist {
478    lrud * tube;
479    struct lrudlist * next;
480} lrudlist;
481
482extern lrudlist * model;
483
484extern lrud ** next_lrud;
485
486extern char output_separator;
487
488#endif /* CAVERN_H */
Note: See TracBrowser for help on using the repository browser.