2 * Reads in survey files, dealing with special characters, keywords & data
3 * Copyright (C) 1991-2003,2005,2009,2010,2011,2012,2013,2014,2015,2016 Olly Betts
4 * Copyright (C) 2004 Simeon Warner
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.
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.
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
43 #define EPSILON (REAL_EPSILON * 1000)
45 #define var(I) (pcs->Var[(I)])
47 /* true if x is not-a-number value in Compass (999.0 or -999.0) */
48 /* Compass uses 999.0 but understands Karst data which used -999.0 */
49 #define is_compass_NaN(x) ( fabs(fabs(x)-999.0) < EPSILON )
54 CTYPE_OMIT
, CTYPE_READING
, CTYPE_PLUMB
, CTYPE_INFERPLUMB
, CTYPE_HORIZ
57 /* Don't explicitly initialise as we can't set the jmp_buf - this has
58 * static scope so will be initialised like this anyway */
59 parse file
/* = { NULL, NULL, 0, fFalse, NULL } */ ;
63 static real value
[Fr
- 1];
64 #define VAL(N) value[(N)-1]
65 static real variance
[Fr
- 1];
66 #define VAR(N) variance[(N)-1]
67 static long location
[Fr
- 1];
68 #define LOC(N) location[(N)-1]
71 static void data_normal(void);
72 static void data_cartesian(void);
73 static void data_passage(void);
74 static void data_nosurvey(void);
75 static void data_ignore(void);
81 fp
->offset
= ftell(file
.fh
);
83 fatalerror_in_file(file
.filename
, 0, /*Error reading file*/18);
87 set_pos(const filepos
*fp
)
90 if (fseek(file
.fh
, fp
->offset
, SEEK_SET
) == -1)
91 fatalerror_in_file(file
.filename
, 0, /*Error reading file*/18);
95 report_parent(parse
* p
) {
97 report_parent(p
->parent
);
98 /* Force re-report of include tree for further errors in
100 p
->reported_where
= fFalse
;
101 /* TRANSLATORS: %s is replaced by the filename of the parent file, and %u
102 * by the line number in that file. Your translation should also contain
103 * %s:%u so that automatic parsing of error messages to determine the file
104 * and line number still works. */
105 fprintf(STDERR
, msg(/*In file included from %s:%u:\n*/5), p
->filename
, p
->line
);
109 error_list_parent_files(void)
111 if (!file
.reported_where
&& file
.parent
) {
112 report_parent(file
.parent
);
113 /* Suppress reporting of full include tree for further errors
115 file
.reported_where
= fTrue
;
119 void v_report_line_contents(const char *filename
, unsigned line
, ...);
123 v_report_line_contents(const char *filename
, unsigned line
, ...)
127 v_report(-1, filename
, line
, 0, 0, ap
);
132 char *get_line_contents();
137 #define MAX_REPORTING_WIDTH 80
140 static char line
[MAX_REPORTING_WIDTH
+ 1];
143 /* Rewind to beginning of line */
147 fp
.offset
= file
.lpos
;
150 /* Read the line until EOL */
151 while((p
< MAX_REPORTING_WIDTH
) && (!feof(file
.fh
)))
159 /* Revert to where we were */
166 compile_v_report(int severity
, int en
, va_list ap
)
169 error_list_parent_files();
172 if (file
.fh
) col
= ftell(file
.fh
) - file
.lpos
;
175 v_report_line_contents(file
.filename
, file
.line
, get_line_contents());
176 v_report(severity
, file
.filename
, file
.line
, col
, en
, ap
);
180 compile_error(int en
, ...)
184 compile_v_report(1, en
, ap
);
189 compile_error_skip(int en
, ...)
193 compile_v_report(1, en
, ap
);
199 compile_error_reading(reading r
, int en
, ...)
204 error_list_parent_files();
205 if (LOC(r
) >= file
.lpos
) col
= LOC(r
) - file
.lpos
;
206 v_report(1, file
.filename
, file
.line
, col
, en
, ap
);
211 compile_error_reading_skip(reading r
, int en
, ...)
216 error_list_parent_files();
217 if (LOC(r
) >= file
.lpos
) col
= LOC(r
) - file
.lpos
;
218 v_report(1, file
.filename
, file
.line
, col
, en
, ap
);
224 compile_error_at(const char * filename
, unsigned line
, int en
, ...)
228 v_report(1, filename
, line
, 0, en
, ap
);
233 compile_error_pfx(const prefix
* pfx
, int en
, ...)
237 v_report(1, pfx
->filename
, pfx
->line
, 0, en
, ap
);
242 compile_error_token(int en
)
247 while (!isBlank(ch
) && !isEol(ch
)) {
248 s_catchar(&p
, &len
, (char)ch
);
251 compile_error(en
, p
? p
: "");
256 compile_warning(int en
, ...)
260 compile_v_report(0, en
, ap
);
265 compile_warning_at(const char * filename
, unsigned line
, int en
, ...)
269 v_report(0, filename
, line
, 0, en
, ap
);
274 compile_warning_pfx(const prefix
* pfx
, int en
, ...)
278 v_report(0, pfx
->filename
, pfx
->line
, 0, en
, ap
);
282 /* This function makes a note where to put output files */
284 using_data_file(const char *fnm
)
286 if (!fnm_output_base
) {
287 /* was: fnm_output_base = base_from_fnm(fnm); */
288 fnm_output_base
= baseleaf_from_fnm(fnm
);
289 } else if (fnm_output_base_is_dir
) {
290 /* --output pointed to directory so use the leaf basename in that dir */
292 lf
= baseleaf_from_fnm(fnm
);
293 p
= use_path(fnm_output_base
, lf
);
295 osfree(fnm_output_base
);
297 fnm_output_base_is_dir
= 0;
304 while (!isBlank(ch
) && !isEol(ch
)) nextch();
310 while (isBlank(ch
)) nextch();
316 while (!isEol(ch
)) nextch();
327 if (!isComm(ch
)) compile_error(-/*End of line not blank*/15);
333 /* skip any different eol characters so we get line counts correct on
334 * DOS text files and similar, but don't count several adjacent blank
338 if (ch
== eolchar
|| !isEol(ch
)) {
341 if (ch
== '\n') eolchar
= ch
;
343 file
.lpos
= ftell(file
.fh
) - 1;
347 process_non_data_line(void)
351 if (isData(ch
)) return fFalse
;
364 read_reading(reading r
, bool f_optional
)
369 case Tape
: q
= Q_LENGTH
; break;
370 case BackTape
: q
= Q_BACKLENGTH
; break;
371 case Comp
: q
= Q_BEARING
; break;
372 case BackComp
: q
= Q_BACKBEARING
; break;
373 case Clino
: q
= Q_GRADIENT
; break;
374 case BackClino
: q
= Q_BACKGRADIENT
; break;
375 case FrDepth
: case ToDepth
: q
= Q_DEPTH
; break;
376 case Dx
: q
= Q_DX
; break;
377 case Dy
: q
= Q_DY
; break;
378 case Dz
: q
= Q_DZ
; break;
379 case FrCount
: case ToCount
: q
= Q_COUNT
; break;
380 case Left
: q
= Q_LEFT
; break;
381 case Right
: q
= Q_RIGHT
; break;
382 case Up
: q
= Q_UP
; break;
383 case Down
: q
= Q_DOWN
; break;
385 q
= Q_NULL
; /* Suppress compiler warning */;
386 BUG("Unexpected case");
388 LOC(r
) = ftell(file
.fh
);
389 VAL(r
) = read_numeric_multi(f_optional
, &n_readings
);
391 if (n_readings
> 1) VAR(r
) /= sqrt(n_readings
);
395 read_bearing_or_omit(reading r
)
398 q_quantity q
= Q_NULL
;
399 LOC(r
) = ftell(file
.fh
);
400 VAL(r
) = read_numeric_multi_or_omit(&n_readings
);
402 case Comp
: q
= Q_BEARING
; break;
403 case BackComp
: q
= Q_BACKBEARING
; break;
405 q
= Q_NULL
; /* Suppress compiler warning */;
406 BUG("Unexpected case");
409 if (n_readings
> 1) VAR(r
) /= sqrt(n_readings
);
412 /* For reading Compass MAK files which have a freeform syntax */
414 nextch_handling_eol(void)
417 while (ch
!= EOF
&& isEol(ch
)) {
422 #define LITLEN(S) (sizeof(S"") - 1)
423 #define has_ext(F,L,E) ((L) > LITLEN(E) + 1 &&\
424 (F)[(L) - LITLEN(E) - 1] == FNM_SEP_EXT &&\
425 strcasecmp((F) + (L) - LITLEN(E), E) == 0)
427 data_file(const char *pth
, const char *fnm
)
429 int begin_lineno_store
;
431 volatile enum {FMT_SVX
, FMT_DAT
, FMT_MAK
} fmt
= FMT_SVX
;
439 /* file specified on command line - don't do special translation */
440 fh
= fopenWithPthAndExt(pth
, fnm
, EXT_SVX_DATA
, "rb", &filename
);
442 fh
= fopen_portable(pth
, fnm
, EXT_SVX_DATA
, "rb", &filename
);
446 compile_error(-/*Couldnāt open file ā%sā*/24, fnm
);
450 len
= strlen(filename
);
451 if (has_ext(filename
, len
, "dat")) {
453 } else if (has_ext(filename
, len
, "mak")) {
458 if (file
.fh
) file
.parent
= &file_store
;
460 file
.filename
= filename
;
463 file
.reported_where
= fFalse
;
467 using_data_file(file
.filename
);
469 begin_lineno_store
= pcs
->begin_lineno
;
470 pcs
->begin_lineno
= 0;
472 if (fmt
== FMT_DAT
) {
477 pcsNew
= osnew(settings
);
478 *pcsNew
= *pcs
; /* copy contents */
479 pcsNew
->begin_lineno
= 0;
485 pcs
->style
= STYLE_NORMAL
;
486 pcs
->units
[Q_LENGTH
] = METRES_PER_FOOT
;
487 t
= ((short*)osmalloc(ossizeof(short) * 257)) + 1;
489 t
[EOF
] = SPECIAL_EOL
;
490 memset(t
, 0, sizeof(short) * 33);
491 for (i
= 33; i
< 127; i
++) t
[i
] = SPECIAL_NAMES
;
493 for (i
= 128; i
< 256; i
++) t
[i
] = SPECIAL_NAMES
;
494 t
['\t'] |= SPECIAL_BLANK
;
495 t
[' '] |= SPECIAL_BLANK
;
496 t
['\032'] |= SPECIAL_EOL
; /* Ctrl-Z, so olde DOS text files are handled ok */
497 t
['\n'] |= SPECIAL_EOL
;
498 t
['\r'] |= SPECIAL_EOL
;
499 t
['.'] |= SPECIAL_DECIMAL
;
500 t
['-'] |= SPECIAL_MINUS
;
501 t
['+'] |= SPECIAL_PLUS
;
504 pcs
->Truncate
= INT_MAX
;
505 pcs
->infer
= BIT(INFER_EQUATES
)|BIT(INFER_EXPORTS
)|BIT(INFER_PLUMBS
);
506 } else if (fmt
== FMT_MAK
) {
511 pcsNew
= osnew(settings
);
512 *pcsNew
= *pcs
; /* copy contents */
513 pcsNew
->begin_lineno
= 0;
517 t
= ((short*)osmalloc(ossizeof(short) * 257)) + 1;
519 t
[EOF
] = SPECIAL_EOL
;
520 memset(t
, 0, sizeof(short) * 33);
521 for (i
= 33; i
< 127; i
++) t
[i
] = SPECIAL_NAMES
;
523 for (i
= 128; i
< 256; i
++) t
[i
] = SPECIAL_NAMES
;
524 t
['['] = t
[','] = t
[';'] = 0;
525 t
['\t'] |= SPECIAL_BLANK
;
526 t
[' '] |= SPECIAL_BLANK
;
527 t
['\032'] |= SPECIAL_EOL
; /* Ctrl-Z, so olde DOS text files are handled ok */
528 t
['\n'] |= SPECIAL_EOL
;
529 t
['\r'] |= SPECIAL_EOL
;
530 t
['.'] |= SPECIAL_DECIMAL
;
531 t
['-'] |= SPECIAL_MINUS
;
532 t
['+'] |= SPECIAL_PLUS
;
535 pcs
->Truncate
= INT_MAX
;
539 /* errors in nested functions can longjmp here */
540 if (setjmp(file
.jbSkipLine
)) {
546 if (fmt
== FMT_DAT
) {
547 while (!feof(file
.fh
) && !ferror(file
.fh
)) {
548 static reading compass_order
[] = {
549 Fr
, To
, Tape
, CompassDATComp
, CompassDATClino
,
550 CompassDATLeft
, CompassDATRight
, CompassDATUp
, CompassDATDown
,
551 CompassDATFlags
, IgnoreAll
553 static reading compass_order_backsights
[] = {
554 Fr
, To
, Tape
, CompassDATComp
, CompassDATClino
,
555 CompassDATLeft
, CompassDATRight
, CompassDATUp
, CompassDATDown
,
556 CompassDATBackComp
, CompassDATBackClino
,
557 CompassDATFlags
, IgnoreAll
562 /* SURVEY NAME: <Short name> */
565 /* if (ch != ':') ... */
570 /* SURVEY DATE: 7 10 79 COMMENT:<Long name> */
573 copy_on_write_meta(pcs
);
575 int year
, month
, day
;
579 /* NB order is *month* *day* year */
583 /* Note: Larry says a 2 digit year is always 19XX */
584 if (year
< 100) year
+= 1900;
586 pcs
->meta
->days1
= pcs
->meta
->days2
= days_since_1900(year
, month
, day
);
588 pcs
->meta
->days1
= pcs
->meta
->days2
= -1;
590 pcs
->declination
= HUGE_REAL
;
602 /* DECLINATION: 1.00 FORMAT: DDDDLUDRADLN CORRECTIONS: 2.00 3.00 4.00 */
606 pcs
->z
[Q_DECLINATION
] = -read_numeric(fFalse
);
607 pcs
->z
[Q_DECLINATION
] *= pcs
->units
[Q_DECLINATION
];
609 pcs
->ordering
= compass_order
;
610 if (strcmp(buffer
, "FORMAT") == 0) {
613 if (strlen(buffer
) >= 12 && buffer
[11] == 'B') {
614 /* We have backsights for compass and clino */
615 pcs
->ordering
= compass_order_backsights
;
619 if (strcmp(buffer
, "CORRECTIONS") == 0) {
621 pcs
->z
[Q_BEARING
] = -rad(read_numeric(fFalse
));
622 pcs
->z
[Q_GRADIENT
] = -rad(read_numeric(fFalse
));
623 pcs
->z
[Q_LENGTH
] = -read_numeric(fFalse
);
625 pcs
->z
[Q_BEARING
] = 0;
626 pcs
->z
[Q_GRADIENT
] = 0;
627 pcs
->z
[Q_LENGTH
] = 0;
640 while (!feof(file
.fh
)) {
651 settings
*pcsParent
= pcs
->next
;
652 SVX_ASSERT(pcsParent
);
653 pcs
->ordering
= NULL
;
657 } else if (fmt
== FMT_MAK
) {
658 nextch_handling_eol();
659 while (!feof(file
.fh
) && !ferror(file
.fh
)) {
663 char *dat_pth
= path_from_fnm(file
.filename
);
664 char *dat_fnm
= NULL
;
666 nextch_handling_eol();
667 while (ch
!= ',' && ch
!= ';' && ch
!= EOF
) {
668 while (isEol(ch
)) process_eol();
669 s_catchar(&dat_fnm
, &dat_fnm_len
, (char)ch
);
670 nextch_handling_eol();
672 while (ch
!= ';' && ch
!= EOF
) {
674 nextch_handling_eol();
675 name
= read_prefix(PFX_STATION
|PFX_OPT
);
682 name
->sflags
|= BIT(SFLAGS_FIXED
);
683 nextch_handling_eol();
684 while (!isdigit(ch
) && ch
!= '+' && ch
!= '-' &&
685 ch
!= '.' && ch
!= ']' && ch
!= EOF
) {
686 nextch_handling_eol();
688 x
= read_numeric(fFalse
);
689 while (!isdigit(ch
) && ch
!= '+' && ch
!= '-' &&
690 ch
!= '.' && ch
!= ']' && ch
!= EOF
) {
691 nextch_handling_eol();
693 y
= read_numeric(fFalse
);
694 while (!isdigit(ch
) && ch
!= '+' && ch
!= '-' &&
695 ch
!= '.' && ch
!= ']' && ch
!= EOF
) {
696 nextch_handling_eol();
698 z
= read_numeric(fFalse
);
699 stn
= StnFromPfx(name
);
706 if (x
!= POS(stn
, 0) || y
!= POS(stn
, 1) ||
708 compile_error(/*Station already fixed or equated to a fixed point*/46);
710 compile_warning(/*Station already fixed at the same coordinates*/55);
713 while (ch
!= ']' && ch
!= EOF
) nextch_handling_eol();
715 nextch_handling_eol();
719 /* FIXME: link station - ignore for now */
720 /* FIXME: perhaps issue warning? */
722 while (ch
!= ',' && ch
!= ';' && ch
!= EOF
)
723 nextch_handling_eol();
728 data_file(dat_pth
, dat_fnm
);
733 /* FIXME: also check for % and $ later */
734 nextch_handling_eol();
738 settings
*pcsParent
= pcs
->next
;
739 SVX_ASSERT(pcsParent
);
744 while (!feof(file
.fh
) && !ferror(file
.fh
)) {
745 if (!process_non_data_line()) {
746 f_export_ok
= fFalse
;
747 switch (pcs
->style
) {
753 case STYLE_CARTESIAN
:
773 /* don't allow *BEGIN at the end of a file, then *EXPORT in the
775 f_export_ok
= fFalse
;
777 if (pcs
->begin_lineno
) {
778 error_in_file(file
.filename
, pcs
->begin_lineno
,
779 /*BEGIN with no matching END in this file*/23);
780 /* Implicitly close any unclosed BEGINs from this file */
782 settings
*pcsParent
= pcs
->next
;
783 SVX_ASSERT(pcsParent
);
786 } while (pcs
->begin_lineno
);
789 pcs
->begin_lineno
= begin_lineno_store
;
792 fatalerror_in_file(file
.filename
, 0, /*Error reading file*/18);
794 (void)fclose(file
.fh
);
798 /* don't free this - it may be pointed to by prefix.file */
799 /* osfree(file.filename); */
805 return a
- floor(a
/ (2 * M_PI
)) * (2 * M_PI
);
809 handle_plumb(clino_type
*p_ctype
)
812 CLINO_NULL
=-1, CLINO_UP
, CLINO_DOWN
, CLINO_LEVEL
814 static sztok clino_tab
[] = {
816 {"DOWN", CLINO_DOWN
},
818 {"LEVEL", CLINO_LEVEL
},
823 static real clinos
[] = {(real
)M_PI_2
, (real
)(-M_PI_2
), (real
)0.0};
831 tok
= match_tok(clino_tab
, TABSIZE(clino_tab
));
832 if (tok
!= CLINO_NULL
) {
833 *p_ctype
= (tok
== CLINO_LEVEL
? CTYPE_HORIZ
: CTYPE_PLUMB
);
837 } else if (isSign(ch
)) {
840 if (toupper(ch
) == 'V') {
842 *p_ctype
= CTYPE_PLUMB
;
843 return (!isMinus(chOld
) ? M_PI_2
: -M_PI_2
);
847 *p_ctype
= CTYPE_OMIT
;
848 /* no clino reading, so assume 0 with large sd */
851 } else if (isOmit(ch
)) {
852 /* OMIT char may not be a SIGN char too so we need to check here as
853 * well as above... */
855 *p_ctype
= CTYPE_OMIT
;
856 /* no clino reading, so assume 0 with large sd */
863 warn_readings_differ(int msgno
, real diff
, int units
)
867 diff
/= get_units_factor(units
);
868 sprintf(buf
, "%.2f", fabs(diff
));
869 for (p
= buf
; *p
; ++p
) {
873 if (*p
!= '0') z
= p
+ 1;
879 strcpy(p
, get_units_string(units
));
880 compile_warning(msgno
, buf
);
884 handle_comp_units(void)
886 bool fNoComp
= fTrue
;
887 if (VAL(Comp
) != HUGE_REAL
) {
889 VAL(Comp
) *= pcs
->units
[Q_BEARING
];
890 if (VAL(Comp
) < (real
)0.0 || VAL(Comp
) - M_PI
* 2.0 > EPSILON
) {
891 /* TRANSLATORS: Suspicious means something like 410 degrees or -20
893 compile_warning(/*Suspicious compass reading*/59);
894 VAL(Comp
) = mod2pi(VAL(Comp
));
897 if (VAL(BackComp
) != HUGE_REAL
) {
899 VAL(BackComp
) *= pcs
->units
[Q_BACKBEARING
];
900 if (VAL(BackComp
) < (real
)0.0 || VAL(BackComp
) - M_PI
* 2.0 > EPSILON
) {
901 /* FIXME: different message for BackComp? */
902 compile_warning(/*Suspicious compass reading*/59);
903 VAL(BackComp
) = mod2pi(VAL(BackComp
));
910 handle_compass(real
*p_var
)
912 real compvar
= VAR(Comp
);
913 real comp
= VAL(Comp
);
914 real backcomp
= VAL(BackComp
);
916 if (pcs
->z
[Q_DECLINATION
] != HUGE_REAL
) {
917 declination
= -pcs
->z
[Q_DECLINATION
];
918 } else if (pcs
->declination
!= HUGE_REAL
) {
919 /* Cached value calculated for a previous compass reading taken on the
920 * same date (by the 'else' just below).
922 declination
= pcs
->declination
;
924 if (!pcs
->meta
|| pcs
->meta
->days1
== -1) {
925 compile_warning(/*No survey date specified - using 0 for magnetic declination*/304);
928 int avg_days
= (pcs
->meta
->days1
+ pcs
->meta
->days2
) / 2;
929 double dat
= julian_date_from_days_since_1900(avg_days
);
930 /* thgeomag() takes (lat, lon, h, dat) - i.e. (y, x, z, date). */
931 declination
= thgeomag(pcs
->dec_y
, pcs
->dec_x
, pcs
->dec_z
, dat
);
933 declination
-= pcs
->convergence
;
934 /* We cache the calculated declination as the calculation is relatively
935 * expensive. We also cache an "assumed 0" answer so that we only
936 * warn once per such survey rather than for every line with a compass
938 pcs
->declination
= declination
;
940 if (comp
!= HUGE_REAL
) {
941 comp
= (comp
- pcs
->z
[Q_BEARING
]) * pcs
->sc
[Q_BEARING
];
944 if (backcomp
!= HUGE_REAL
) {
945 backcomp
= (backcomp
- pcs
->z
[Q_BACKBEARING
])
946 * pcs
->sc
[Q_BACKBEARING
];
947 backcomp
+= declination
;
949 if (comp
!= HUGE_REAL
) {
950 real diff
= comp
- backcomp
;
951 real adj
= fabs(diff
) > M_PI
? M_PI
: 0;
952 diff
-= floor((diff
+ M_PI
) / (2 * M_PI
)) * 2 * M_PI
;
953 if (sqrd(diff
/ 3.0) > compvar
+ VAR(BackComp
)) {
954 /* fore and back readings differ by more than 3 sds */
955 /* TRANSLATORS: %s is replaced by the amount the readings disagree
956 * by, e.g. "2.5Ā°" or "3įµ". */
957 warn_readings_differ(/*COMPASS reading and BACKCOMPASS reading disagree by %s*/98,
958 diff
, get_angle_units(Q_BEARING
));
960 comp
= (comp
/ compvar
+ backcomp
/ VAR(BackComp
));
961 compvar
= (compvar
+ VAR(BackComp
)) / 4;
966 compvar
= VAR(BackComp
);
974 process_normal(prefix
*fr
, prefix
*to
, bool fToFirst
,
975 clino_type ctype
, clino_type backctype
)
977 real tape
= VAL(Tape
);
978 real clin
= VAL(Clino
);
979 real backclin
= VAL(BackClino
);
983 #ifndef NO_COVARIANCES
989 /* adjusted tape is negative -- probably the calibration is wrong */
990 if (tape
< (real
)0.0) {
991 /* TRANSLATE different message for topofil? */
992 compile_warning(/*Negative adjusted tape reading*/79);
995 fNoComp
= handle_comp_units();
997 if (ctype
== CTYPE_READING
) {
1000 real diff_from_abs90
;
1001 clin
*= pcs
->units
[Q_GRADIENT
];
1002 /* percentage scale */
1003 if (pcs
->f_clino_percent
) clin
= atan(clin
);
1004 /* We want to warn if there's a reading which it would be impossible
1005 * to have read from the instrument (e.g. on a -90 to 90 degree scale
1006 * you can't read "96" (it's probably a typo for "69"). However, the
1007 * gradient reading from a topofil is typically in the range 0 to 180,
1008 * with 90 being horizontal.
1010 * Really we should allow the valid range to be specified, but for now
1011 * we infer it from the zero error - if this is within 45 degrees of
1012 * 90 then we assume the range is 0 to 180.
1014 z
= pcs
->z
[Q_GRADIENT
];
1015 range_0_180
= (z
> M_PI_4
&& z
< 3*M_PI_4
);
1016 diff_from_abs90
= fabs(clin
) - M_PI_2
;
1017 if (diff_from_abs90
> EPSILON
) {
1019 int clino_units
= get_angle_units(Q_GRADIENT
);
1020 const char * units
= get_units_string(clino_units
);
1021 real right_angle
= M_PI_2
/ get_units_factor(clino_units
);
1022 /* TRANSLATORS: %.f%s will be replaced with a right angle in the
1023 * units currently in use, e.g. "90Ā°" or "100įµ". And "absolute
1024 * value" means the reading ignoring the sign (so it might be
1025 * < -90Ā° or > 90Ā°. */
1026 compile_warning(/*Clino reading over %.f%s (absolute value)*/51,
1027 right_angle
, units
);
1029 } else if (TSTBIT(pcs
->infer
, INFER_PLUMBS
) &&
1030 diff_from_abs90
>= -EPSILON
) {
1031 ctype
= CTYPE_INFERPLUMB
;
1033 if (range_0_180
&& ctype
!= CTYPE_INFERPLUMB
) {
1034 /* FIXME: Warning message not ideal... */
1035 if (clin
< 0.0 || clin
- M_PI
> EPSILON
) {
1036 int clino_units
= get_angle_units(Q_GRADIENT
);
1037 const char * units
= get_units_string(clino_units
);
1038 real right_angle
= M_PI_2
/ get_units_factor(clino_units
);
1039 compile_warning(/*Clino reading over %.f%s (absolute value)*/51,
1040 right_angle
, units
);
1045 if (backctype
== CTYPE_READING
) {
1046 backclin
*= pcs
->units
[Q_BACKGRADIENT
];
1047 /* percentage scale */
1048 if (pcs
->f_backclino_percent
) backclin
= atan(backclin
);
1049 /* FIXME: Add range_0_180 handling here too */
1050 if (ctype
!= CTYPE_READING
) {
1051 real diff_from_abs90
= fabs(backclin
) - M_PI_2
;
1052 if (diff_from_abs90
> EPSILON
) {
1053 /* FIXME: different message for BackClino? */
1054 int clino_units
= get_angle_units(Q_BACKGRADIENT
);
1055 const char * units
= get_units_string(clino_units
);
1056 real right_angle
= M_PI_2
/ get_units_factor(clino_units
);
1057 compile_warning(/*Clino reading over %.f%s (absolute value)*/51,
1058 right_angle
, units
);
1059 } else if (TSTBIT(pcs
->infer
, INFER_PLUMBS
) &&
1060 diff_from_abs90
>= -EPSILON
) {
1061 backctype
= CTYPE_INFERPLUMB
;
1066 /* un-infer the plumb if the backsight was just a reading */
1067 if (ctype
== CTYPE_INFERPLUMB
&& backctype
== CTYPE_READING
) {
1068 ctype
= CTYPE_READING
;
1071 if (ctype
!= CTYPE_OMIT
&& backctype
!= CTYPE_OMIT
&& ctype
!= backctype
) {
1072 /* TRANSLATORS: In data with backsights, the user has tried to give a
1073 * plumb for the foresight and a clino reading for the backsight, or
1074 * something similar. */
1075 compile_error_reading_skip(Clino
, /*CLINO and BACKCLINO readings must be of the same type*/84);
1079 if (ctype
== CTYPE_PLUMB
|| ctype
== CTYPE_INFERPLUMB
||
1080 backctype
== CTYPE_PLUMB
|| backctype
== CTYPE_INFERPLUMB
) {
1083 if (ctype
== CTYPE_PLUMB
||
1084 (ctype
== CTYPE_INFERPLUMB
&& VAL(Comp
) != 0.0) ||
1085 backctype
== CTYPE_PLUMB
||
1086 (backctype
== CTYPE_INFERPLUMB
&& VAL(BackComp
) != 0.0)) {
1087 /* FIXME: Different message for BackComp? */
1088 /* TRANSLATORS: A "plumbed leg" is one measured using a plumbline
1089 * (a weight on a string). So the problem here is that the leg is
1090 * vertical, so a compass reading has no meaning! */
1091 compile_warning(/*Compass reading given on plumbed leg*/21);
1095 dx
= dy
= (real
)0.0;
1096 if (ctype
!= CTYPE_OMIT
) {
1097 if (backctype
!= CTYPE_OMIT
&& (clin
> 0) == (backclin
> 0)) {
1098 /* TRANSLATORS: We've been told the foresight and backsight are
1099 * both "UP", or that they're both "DOWN". */
1100 compile_error_reading_skip(Clino
, /*Plumbed CLINO and BACKCLINO readings can't be in the same direction*/92);
1103 dz
= (clin
> (real
)0.0) ? tape
: -tape
;
1105 dz
= (backclin
< (real
)0.0) ? tape
: -tape
;
1107 vx
= vy
= var(Q_POS
) / 3.0 + dz
* dz
* var(Q_PLUMB
);
1108 vz
= var(Q_POS
) / 3.0 + VAR(Tape
);
1109 #ifndef NO_COVARIANCES
1110 /* Correct values - no covariances in this case! */
1111 cxy
= cyz
= czx
= (real
)0.0;
1114 /* Each of ctype and backctype are either CTYPE_READING/CTYPE_HORIZ
1117 real L2
, cosG
, LcosG
, cosG2
, sinB
, cosB
, dx2
, dy2
, dz2
, v
, V
;
1119 /* TRANSLATORS: Here "legs" are survey legs, i.e. measurements between
1120 * survey stations. */
1121 compile_error_reading_skip(Comp
, /*Compass reading may not be omitted except on plumbed legs*/14);
1124 if (tape
== (real
)0.0) {
1125 dx
= dy
= dz
= (real
)0.0;
1126 vx
= vy
= vz
= (real
)(var(Q_POS
) / 3.0); /* Position error only */
1127 #ifndef NO_COVARIANCES
1128 cxy
= cyz
= czx
= (real
)0.0;
1131 printf("Zero length leg: vx = %f, vy = %f, vz = %f\n", vx
, vy
, vz
);
1135 /* take into account variance in LEVEL case */
1136 real var_clin
= var(Q_LEVEL
);
1138 real comp
= handle_compass(&var_comp
);
1139 /* ctype != CTYPE_READING is LEVEL case */
1140 if (ctype
== CTYPE_READING
) {
1141 clin
= (clin
- pcs
->z
[Q_GRADIENT
]) * pcs
->sc
[Q_GRADIENT
];
1142 var_clin
= VAR(Clino
);
1144 if (backctype
== CTYPE_READING
) {
1145 backclin
= (backclin
- pcs
->z
[Q_BACKGRADIENT
])
1146 * pcs
->sc
[Q_BACKGRADIENT
];
1147 if (ctype
== CTYPE_READING
) {
1148 if (sqrd((clin
+ backclin
) / 3.0) > var_clin
+ VAR(BackClino
)) {
1149 /* fore and back readings differ by more than 3 sds */
1150 /* TRANSLATORS: %s is replaced by the amount the readings disagree
1151 * by, e.g. "2.5Ā°" or "3įµ". */
1152 warn_readings_differ(/*CLINO reading and BACKCLINO reading disagree by %s*/99,
1153 clin
+ backclin
, get_angle_units(Q_GRADIENT
));
1155 clin
= (clin
/ var_clin
- backclin
/ VAR(BackClino
));
1156 var_clin
= (var_clin
+ VAR(BackClino
)) / 4;
1160 var_clin
= VAR(BackClino
);
1165 printf(" %4.2f %4.2f %4.2f\n", tape
, comp
, clin
);
1168 LcosG
= tape
* cosG
;
1172 printf("sinB = %f, cosG = %f, LcosG = %f\n", sinB
, cosG
, LcosG
);
1176 dz
= tape
* sin(clin
);
1177 /* printf("%.2f\n",clin); */
1179 printf("dx = %f\ndy = %f\ndz = %f\n", dx
, dy
, dz
);
1185 cosG2
= cosG
* cosG
;
1186 sinGcosG
= sin(clin
) * cosG
;
1189 #ifdef NO_COVARIANCES
1190 vx
= (var(Q_POS
) / 3.0 + dx2
* V
+ dy2
* var_comp
+
1191 (.5 + sinB
* sinB
* cosG2
) * v
);
1192 vy
= (var(Q_POS
) / 3.0 + dy2
* V
+ dx2
* var_comp
+
1193 (.5 + cosB
* cosB
* cosG2
) * v
);
1194 if (ctype
== CTYPE_OMIT
&& backctype
== CTYPE_OMIT
) {
1195 /* if no clino, assume sd=tape/sqrt(10) so 3sds = .95*tape */
1196 vz
= var(Q_POS
) / 3.0 + L2
* (real
)0.1;
1198 vz
= var(Q_POS
) / 3.0 + dz2
* V
+ L2
* cosG2
* var_clin
;
1200 /* for Surveyor87 errors: vx=vy=vz=var(Q_POS)/3.0; */
1202 vx
= var(Q_POS
) / 3.0 + dx2
* V
+ dy2
* var_comp
+
1204 vy
= var(Q_POS
) / 3.0 + dy2
* V
+ dx2
* var_comp
+
1206 if (ctype
== CTYPE_OMIT
&& backctype
== CTYPE_OMIT
) {
1207 /* if no clino, assume sd=tape/sqrt(10) so 3sds = .95*tape */
1208 vz
= var(Q_POS
) / 3.0 + L2
* (real
)0.1;
1210 vz
= var(Q_POS
) / 3.0 + dz2
* V
+ L2
* cosG2
* var_clin
;
1212 /* usual covariance formulae are fine in no clino case since
1213 * dz = 0 so value of var_clin is ignored */
1214 cxy
= sinB
* cosB
* (VAR(Tape
) * cosG2
+ var_clin
* dz2
)
1215 - var_comp
* dx
* dy
;
1216 czx
= VAR(Tape
) * sinB
* sinGcosG
- var_clin
* dx
* dz
;
1217 cyz
= VAR(Tape
) * cosB
* sinGcosG
- var_clin
* dy
* dz
;
1219 printf("vx = %6.3f, vy = %6.3f, vz = %6.3f\n", vx
, vy
, vz
);
1220 printf("cxy = %6.3f, cyz = %6.3f, czx = %6.3f\n", cxy
, cyz
, czx
);
1224 printf("In DATAIN.C, vx = %f, vy = %f, vz = %f\n", vx
, vy
, vz
);
1229 printf("Just before addleg, vx = %f\n", vx
);
1231 /*printf("dx,dy,dz = %.2f %.2f %.2f\n\n", dx, dy, dz);*/
1232 addlegbyname(fr
, to
, fToFirst
, dx
, dy
, dz
, vx
, vy
, vz
1233 #ifndef NO_COVARIANCES
1241 process_diving(prefix
*fr
, prefix
*to
, bool fToFirst
, bool fDepthChange
)
1243 real tape
= VAL(Tape
);
1247 #ifndef NO_COVARIANCES
1248 real cxy
= 0, cyz
= 0, czx
= 0;
1251 handle_comp_units();
1253 /* depth gauge readings increase upwards with default calibration */
1255 SVX_ASSERT(VAL(FrDepth
) == 0.0);
1256 dz
= VAL(ToDepth
) * pcs
->units
[Q_DEPTH
] - pcs
->z
[Q_DEPTH
];
1257 dz
*= pcs
->sc
[Q_DEPTH
];
1259 dz
= VAL(ToDepth
) - VAL(FrDepth
);
1260 dz
*= pcs
->units
[Q_DEPTH
] * pcs
->sc
[Q_DEPTH
];
1263 /* adjusted tape is negative -- probably the calibration is wrong */
1264 if (tape
< (real
)0.0) {
1265 compile_warning(/*Negative adjusted tape reading*/79);
1268 /* check if tape is less than depth change */
1269 if (tape
< fabs(dz
)) {
1270 /* FIXME: allow margin of error based on variances? */
1271 /* TRANSLATORS: This means that the data fed in said this.
1273 * It could be a gross error (e.g. the decimal point is missing from the
1274 * depth gauge reading) or it could just be due to random error on a near
1276 compile_warning(/*Tape reading is less than change in depth*/62);
1279 if (tape
== (real
)0.0 && dz
== 0.0) {
1280 dx
= dy
= dz
= (real
)0.0;
1281 vx
= vy
= vz
= (real
)(var(Q_POS
) / 3.0); /* Position error only */
1282 } else if (VAL(Comp
) == HUGE_REAL
&&
1283 VAL(BackComp
) == HUGE_REAL
) {
1285 dx
= dy
= (real
)0.0;
1286 if (dz
< 0) tape
= -tape
;
1287 /* FIXME: Should use FrDepth sometimes... */
1288 dz
= (dz
* VAR(Tape
) + tape
* 2 * VAR(ToDepth
))
1289 / (VAR(Tape
) * 2 * VAR(ToDepth
));
1290 vx
= vy
= var(Q_POS
) / 3.0 + dz
* dz
* var(Q_PLUMB
);
1291 /* FIXME: Should use FrDepth sometimes... */
1292 vz
= var(Q_POS
) / 3.0 + VAR(Tape
) * 2 * VAR(ToDepth
)
1293 / (VAR(Tape
) + VAR(ToDepth
));
1295 real L2
, sinB
, cosB
, dz2
, D2
;
1297 real comp
= handle_compass(&var_comp
);
1303 if (D2
<= (real
)0.0) {
1304 /* FIXME: Should use FrDepth sometimes... */
1305 real vsum
= VAR(Tape
) + 2 * VAR(ToDepth
);
1306 dx
= dy
= (real
)0.0;
1307 vx
= vy
= var(Q_POS
) / 3.0;
1308 /* FIXME: Should use FrDepth sometimes... */
1309 vz
= var(Q_POS
) / 3.0 + VAR(Tape
) * 2 * VAR(ToDepth
) / vsum
;
1311 /* FIXME: Should use FrDepth sometimes... */
1312 dz
= (dz
* VAR(Tape
) + tape
* 2 * VAR(ToDepth
)) / vsum
;
1314 dz
= (dz
* VAR(Tape
) - tape
* 2 * VAR(ToDepth
)) / vsum
;
1318 /* FIXME: Should use FrDepth sometimes... */
1319 real F
= VAR(Tape
) * L2
+ 2 * VAR(ToDepth
) * D2
;
1323 vx
= var(Q_POS
) / 3.0 +
1324 sinB
* sinB
* F
/ D2
+ var_comp
* dy
* dy
;
1325 vy
= var(Q_POS
) / 3.0 +
1326 cosB
* cosB
* F
/ D2
+ var_comp
* dx
* dx
;
1327 /* FIXME: Should use FrDepth sometimes... */
1328 vz
= var(Q_POS
) / 3.0 + 2 * VAR(ToDepth
);
1330 #ifndef NO_COVARIANCES
1331 cxy
= sinB
* cosB
* (F
/ D2
+ var_comp
* D2
);
1332 /* FIXME: Should use FrDepth sometimes... */
1333 cyz
= -2 * VAR(ToDepth
) * dy
/ D
;
1334 czx
= -2 * VAR(ToDepth
) * dx
/ D
;
1337 /* FIXME: If there's a clino reading, check it against the depth reading,
1339 * if (VAL(Clino) != HUGE_REAL || VAL(BackClino) != HUGE_REAL) { ... }
1342 addlegbyname(fr
, to
, fToFirst
, dx
, dy
, dz
, vx
, vy
, vz
1343 #ifndef NO_COVARIANCES
1351 process_cartesian(prefix
*fr
, prefix
*to
, bool fToFirst
)
1353 real dx
= (VAL(Dx
) * pcs
->units
[Q_DX
] - pcs
->z
[Q_DX
]) * pcs
->sc
[Q_DX
];
1354 real dy
= (VAL(Dy
) * pcs
->units
[Q_DY
] - pcs
->z
[Q_DY
]) * pcs
->sc
[Q_DY
];
1355 real dz
= (VAL(Dz
) * pcs
->units
[Q_DZ
] - pcs
->z
[Q_DZ
]) * pcs
->sc
[Q_DZ
];
1357 addlegbyname(fr
, to
, fToFirst
, dx
, dy
, dz
, VAR(Dx
), VAR(Dy
), VAR(Dz
)
1358 #ifndef NO_COVARIANCES
1366 data_cartesian(void)
1368 prefix
*fr
= NULL
, *to
= NULL
;
1370 bool fMulti
= fFalse
;
1372 reading first_stn
= End
;
1378 for (ordering
= pcs
->ordering
; ; ordering
++) {
1380 switch (*ordering
) {
1382 fr
= read_prefix(PFX_STATION
|PFX_ALLOW_ROOT
);
1383 if (first_stn
== End
) first_stn
= Fr
;
1386 to
= read_prefix(PFX_STATION
|PFX_ALLOW_ROOT
);
1387 if (first_stn
== End
) first_stn
= To
;
1391 to
= read_prefix(PFX_STATION
);
1394 case Dx
: case Dy
: case Dz
:
1395 read_reading(*ordering
, fFalse
);
1399 case IgnoreAllAndNewLine
:
1404 if (!process_cartesian(fr
, to
, first_stn
== To
))
1411 if (isData(ch
)) break;
1422 process_cartesian(fr
, to
, first_stn
== To
);
1429 } while (isComm(ch
));
1431 default: BUG("Unknown reading in ordering");
1437 process_cylpolar(prefix
*fr
, prefix
*to
, bool fToFirst
, bool fDepthChange
)
1439 real tape
= VAL(Tape
);
1443 #ifndef NO_COVARIANCES
1447 handle_comp_units();
1449 /* depth gauge readings increase upwards with default calibration */
1451 SVX_ASSERT(VAL(FrDepth
) == 0.0);
1452 dz
= VAL(ToDepth
) * pcs
->units
[Q_DEPTH
] - pcs
->z
[Q_DEPTH
];
1453 dz
*= pcs
->sc
[Q_DEPTH
];
1455 dz
= VAL(ToDepth
) - VAL(FrDepth
);
1456 dz
*= pcs
->units
[Q_DEPTH
] * pcs
->sc
[Q_DEPTH
];
1459 /* adjusted tape is negative -- probably the calibration is wrong */
1460 if (tape
< (real
)0.0) {
1461 compile_warning(/*Negative adjusted tape reading*/79);
1464 if (VAL(Comp
) == HUGE_REAL
&& VAL(BackComp
) == HUGE_REAL
) {
1466 dx
= dy
= (real
)0.0;
1467 vx
= vy
= var(Q_POS
) / 3.0 + dz
* dz
* var(Q_PLUMB
);
1468 /* FIXME: Should use FrDepth sometimes... */
1469 vz
= var(Q_POS
) / 3.0 + 2 * VAR(ToDepth
);
1473 real comp
= handle_compass(&var_comp
);
1480 vx
= var(Q_POS
) / 3.0 +
1481 VAR(Tape
) * sinB
* sinB
+ var_comp
* dy
* dy
;
1482 vy
= var(Q_POS
) / 3.0 +
1483 VAR(Tape
) * cosB
* cosB
+ var_comp
* dx
* dx
;
1484 /* FIXME: Should use FrDepth sometimes... */
1485 vz
= var(Q_POS
) / 3.0 + 2 * VAR(ToDepth
);
1487 #ifndef NO_COVARIANCES
1488 cxy
= (VAR(Tape
) - var_comp
* tape
* tape
) * sinB
* cosB
;
1491 addlegbyname(fr
, to
, fToFirst
, dx
, dy
, dz
, vx
, vy
, vz
1492 #ifndef NO_COVARIANCES
1499 /* Process tape/compass/clino, diving, and cylpolar styles of survey data
1500 * Also handles topofil (fromcount/tocount or count) in place of tape */
1504 prefix
*fr
= NULL
, *to
= NULL
;
1505 reading first_stn
= End
;
1507 bool fTopofil
= fFalse
, fMulti
= fFalse
;
1509 clino_type ctype
, backctype
;
1511 unsigned long compass_dat_flags
= 0;
1515 VAL(Tape
) = VAL(BackTape
) = HUGE_REAL
;
1516 VAL(Comp
) = VAL(BackComp
) = HUGE_REAL
;
1517 VAL(FrCount
) = VAL(ToCount
) = 0;
1518 VAL(FrDepth
) = VAL(ToDepth
) = 0;
1519 VAL(Left
) = VAL(Right
) = VAL(Up
) = VAL(Down
) = HUGE_REAL
;
1522 ctype
= backctype
= CTYPE_OMIT
;
1523 fDepthChange
= fFalse
;
1525 /* ordering may omit clino reading, so set up default here */
1526 /* this is also used if clino reading is the omit character */
1527 VAL(Clino
) = VAL(BackClino
) = 0;
1531 /* We clear these flags in the normal course of events, but if there's an
1532 * error in a reading, we might not, so make sure it has been cleared here.
1534 pcs
->flags
&= ~(BIT(FLAGS_ANON_ONE_END
) | BIT(FLAGS_IMPLICIT_SPLAY
));
1535 for (ordering
= pcs
->ordering
; ; ordering
++) {
1537 switch (*ordering
) {
1539 fr
= read_prefix(PFX_STATION
|PFX_ALLOW_ROOT
|PFX_ANON
);
1540 if (first_stn
== End
) first_stn
= Fr
;
1543 to
= read_prefix(PFX_STATION
|PFX_ALLOW_ROOT
|PFX_ANON
);
1544 if (first_stn
== End
) first_stn
= To
;
1548 to
= read_prefix(PFX_STATION
);
1553 DIR_NULL
=-1, DIR_FORE
, DIR_BACK
1555 static sztok dir_tab
[] = {
1561 tok
= match_tok(dir_tab
, TABSIZE(dir_tab
));
1569 file
.lpos
+= strlen(buffer
);
1570 compile_error_skip(-/*Found ā%sā, expecting āFā or āBā*/131,
1577 case Tape
: case BackTape
: {
1578 reading r
= *ordering
;
1579 read_reading(r
, fTrue
);
1580 if (VAL(r
) == HUGE_REAL
) {
1582 compile_error_token(-/*Expecting numeric field, found ā%sā*/9);
1583 /* Avoid also warning about omitted tape reading. */
1588 } else if (VAL(r
) < (real
)0.0) {
1589 compile_warning(-/*Negative tape reading*/60);
1594 VAL(FrCount
) = VAL(ToCount
);
1595 LOC(FrCount
) = LOC(ToCount
);
1596 read_reading(ToCount
, fFalse
);
1600 read_reading(FrCount
, fFalse
);
1603 read_reading(ToCount
, fFalse
);
1606 case Comp
: case BackComp
:
1607 read_bearing_or_omit(*ordering
);
1609 case Clino
: case BackClino
: {
1610 reading r
= *ordering
;
1611 clino_type
* p_ctype
= (r
== Clino
? &ctype
: &backctype
);
1612 read_reading(r
, fTrue
);
1613 if (VAL(r
) == HUGE_REAL
) {
1614 VAL(r
) = handle_plumb(p_ctype
);
1615 if (VAL(r
) != HUGE_REAL
) break;
1616 compile_error_token(-/*Expecting numeric field, found ā%sā*/9);
1621 *p_ctype
= CTYPE_READING
;
1624 case FrDepth
: case ToDepth
:
1625 read_reading(*ordering
, fFalse
);
1628 VAL(FrDepth
) = VAL(ToDepth
);
1629 LOC(FrDepth
) = LOC(ToDepth
);
1630 read_reading(ToDepth
, fFalse
);
1633 fDepthChange
= fTrue
;
1635 read_reading(ToDepth
, fFalse
);
1637 case CompassDATComp
:
1638 read_bearing_or_omit(Comp
);
1639 if (is_compass_NaN(VAL(Comp
))) VAL(Comp
) = HUGE_REAL
;
1641 case CompassDATBackComp
:
1642 read_bearing_or_omit(BackComp
);
1643 if (is_compass_NaN(VAL(BackComp
))) VAL(BackComp
) = HUGE_REAL
;
1645 case CompassDATClino
: case CompassDATBackClino
: {
1647 clino_type
* p_ctype
;
1648 if (*ordering
== CompassDATClino
) {
1653 p_ctype
= &backctype
;
1655 read_reading(r
, fFalse
);
1656 if (is_compass_NaN(VAL(r
))) {
1658 *p_ctype
= CTYPE_OMIT
;
1660 *p_ctype
= CTYPE_READING
;
1664 case CompassDATLeft
: case CompassDATRight
:
1665 case CompassDATUp
: case CompassDATDown
: {
1666 /* FIXME: need to actually make use of these entries! */
1667 reading actual
= Left
+ (*ordering
- CompassDATLeft
);
1668 read_reading(actual
, fFalse
);
1669 if (VAL(actual
) < 0) VAL(actual
) = HUGE_REAL
;
1672 case CompassDATFlags
:
1679 while (ch
>= 'A' && ch
<= 'Z') {
1680 compass_dat_flags
|= BIT(ch
- 'A');
1681 /* We currently understand:
1682 * L (exclude from length)
1684 * FIXME: but should also handle at least some of:
1685 * C (no adjustment) (set all (co)variances to 0?)
1686 * P (no plot) (new flag in 3d for "hidden by default"?)
1693 compass_dat_flags
= 0;
1703 case IgnoreAllAndNewLine
:
1712 VAL(Tape
) = VAL(ToCount
) - VAL(FrCount
);
1713 LOC(Tape
) = LOC(ToCount
);
1715 /* Note: frdepth == todepth test works regardless of fDepthChange
1716 * (frdepth always zero, todepth is change of depth) and also
1717 * works for STYLE_NORMAL (both remain 0) */
1718 if (TSTBIT(pcs
->infer
, INFER_EQUATES
) &&
1719 (VAL(Tape
) == (real
)0.0 || VAL(Tape
) == HUGE_REAL
) &&
1720 (VAL(BackTape
) == (real
)0.0 || VAL(BackTape
) == HUGE_REAL
) &&
1721 VAL(FrDepth
) == VAL(ToDepth
)) {
1722 process_equate(fr
, to
);
1723 goto inferred_equate
;
1731 VAL(Tape
) *= pcs
->units
[Q_COUNT
] * pcs
->sc
[Q_COUNT
];
1732 } else if (VAL(Tape
) != HUGE_REAL
) {
1733 VAL(Tape
) *= pcs
->units
[Q_LENGTH
];
1734 VAL(Tape
) -= pcs
->z
[Q_LENGTH
];
1735 VAL(Tape
) *= pcs
->sc
[Q_LENGTH
];
1737 if (VAL(BackTape
) != HUGE_REAL
) {
1738 VAL(BackTape
) *= pcs
->units
[Q_BACKLENGTH
];
1739 VAL(BackTape
) -= pcs
->z
[Q_BACKLENGTH
];
1740 VAL(BackTape
) *= pcs
->sc
[Q_BACKLENGTH
];
1741 if (VAL(Tape
) != HUGE_REAL
) {
1742 real diff
= VAL(Tape
) - VAL(BackTape
);
1743 if (sqrd(diff
/ 3.0) > VAR(Tape
) + VAR(BackTape
)) {
1744 /* fore and back readings differ by more than 3 sds */
1745 /* TRANSLATORS: %s is replaced by the amount the readings disagree
1746 * by, e.g. "0.12m" or "0.2ft". */
1747 warn_readings_differ(/*TAPE reading and BACKTAPE reading disagree by %s*/97,
1748 diff
, get_length_units(Q_LENGTH
));
1750 VAL(Tape
) = VAL(Tape
) / VAR(Tape
) + VAL(BackTape
) / VAR(BackTape
);
1751 VAR(Tape
) = (VAR(Tape
) + VAR(BackTape
)) / 4;
1752 VAL(Tape
) *= VAR(Tape
);
1754 VAL(Tape
) = VAL(BackTape
);
1755 VAR(Tape
) = VAR(BackTape
);
1757 } else if (VAL(Tape
) == HUGE_REAL
) {
1758 compile_error_reading(Tape
, /*Tape reading may not be omitted*/94);
1759 goto inferred_equate
;
1761 implicit_splay
= TSTBIT(pcs
->flags
, FLAGS_IMPLICIT_SPLAY
);
1762 pcs
->flags
&= ~(BIT(FLAGS_ANON_ONE_END
) | BIT(FLAGS_IMPLICIT_SPLAY
));
1763 save_flags
= pcs
->flags
;
1764 if (implicit_splay
) {
1765 pcs
->flags
|= BIT(FLAGS_SPLAY
);
1767 switch (pcs
->style
) {
1769 r
= process_normal(fr
, to
, (first_stn
== To
) ^ fRev
,
1773 /* FIXME: Handle any clino readings */
1774 r
= process_diving(fr
, to
, (first_stn
== To
) ^ fRev
,
1777 case STYLE_CYLPOLAR
:
1778 r
= process_cylpolar(fr
, to
, (first_stn
== To
) ^ fRev
,
1782 r
= 0; /* avoid warning */
1785 pcs
->flags
= save_flags
;
1788 /* Swap fr and to back to how they were for next line */
1797 ctype
= backctype
= CTYPE_OMIT
;
1798 fDepthChange
= fFalse
;
1800 /* ordering may omit clino reading, so set up default here */
1801 /* this is also used if clino reading is the omit character */
1802 VAL(Clino
) = VAL(BackClino
) = 0;
1803 LOC(Clino
) = LOC(BackClino
) = -1;
1811 if (isData(ch
)) break;
1824 /* Compass ignore flag is 'X' */
1825 if ((compass_dat_flags
& BIT('X' - 'A'))) {
1835 VAL(Tape
) = VAL(ToCount
) - VAL(FrCount
);
1836 LOC(Tape
) = LOC(ToCount
);
1838 /* Note: frdepth == todepth test works regardless of fDepthChange
1839 * (frdepth always zero, todepth is change of depth) and also
1840 * works for STYLE_NORMAL (both remain 0) */
1841 if (TSTBIT(pcs
->infer
, INFER_EQUATES
) &&
1842 (VAL(Tape
) == (real
)0.0 || VAL(Tape
) == HUGE_REAL
) &&
1843 (VAL(BackTape
) == (real
)0.0 || VAL(BackTape
) == HUGE_REAL
) &&
1844 VAL(FrDepth
) == VAL(ToDepth
)) {
1845 process_equate(fr
, to
);
1850 VAL(Tape
) *= pcs
->units
[Q_COUNT
] * pcs
->sc
[Q_COUNT
];
1851 } else if (VAL(Tape
) != HUGE_REAL
) {
1852 VAL(Tape
) *= pcs
->units
[Q_LENGTH
];
1853 VAL(Tape
) -= pcs
->z
[Q_LENGTH
];
1854 VAL(Tape
) *= pcs
->sc
[Q_LENGTH
];
1856 if (VAL(BackTape
) != HUGE_REAL
) {
1857 VAL(BackTape
) *= pcs
->units
[Q_BACKLENGTH
];
1858 VAL(BackTape
) -= pcs
->z
[Q_BACKLENGTH
];
1859 VAL(BackTape
) *= pcs
->sc
[Q_BACKLENGTH
];
1860 if (VAL(Tape
) != HUGE_REAL
) {
1861 real diff
= VAL(Tape
) - VAL(BackTape
);
1862 if (sqrd(diff
/ 3.0) > VAR(Tape
) + VAR(BackTape
)) {
1863 /* fore and back readings differ by more than 3 sds */
1864 /* TRANSLATORS: %s is replaced by the amount the readings disagree
1865 * by, e.g. "0.12m" or "0.2ft". */
1866 warn_readings_differ(/*TAPE reading and BACKTAPE reading disagree by %s*/97,
1867 diff
, get_length_units(Q_LENGTH
));
1869 VAL(Tape
) = VAL(Tape
) / VAR(Tape
) + VAL(BackTape
) / VAR(BackTape
);
1870 VAR(Tape
) = (VAR(Tape
) + VAR(BackTape
)) / 4;
1871 VAL(Tape
) *= VAR(Tape
);
1873 VAL(Tape
) = VAL(BackTape
);
1874 VAR(Tape
) = VAR(BackTape
);
1876 } else if (VAL(Tape
) == HUGE_REAL
) {
1877 compile_error_reading(Tape
, /*Tape reading may not be omitted*/94);
1881 implicit_splay
= TSTBIT(pcs
->flags
, FLAGS_IMPLICIT_SPLAY
);
1882 pcs
->flags
&= ~(BIT(FLAGS_ANON_ONE_END
) | BIT(FLAGS_IMPLICIT_SPLAY
));
1883 save_flags
= pcs
->flags
;
1884 if (implicit_splay
) {
1885 pcs
->flags
|= BIT(FLAGS_SPLAY
);
1887 if ((compass_dat_flags
& BIT('L' - 'A'))) {
1888 /* 'L' means "exclude from length" - map this to Survex's
1889 * FLAGS_DUPLICATE. */
1890 pcs
->flags
|= BIT(FLAGS_DUPLICATE
);
1892 switch (pcs
->style
) {
1894 process_normal(fr
, to
, (first_stn
== To
) ^ fRev
,
1898 /* FIXME: Handle any clino readings */
1899 process_diving(fr
, to
, (first_stn
== To
) ^ fRev
,
1902 case STYLE_CYLPOLAR
:
1903 process_cylpolar(fr
, to
, (first_stn
== To
) ^ fRev
,
1909 pcs
->flags
= save_flags
;
1917 } while (isComm(ch
));
1920 BUG("Unknown reading in ordering");
1926 process_lrud(prefix
*stn
)
1928 SVX_ASSERT(next_lrud
);
1929 lrud
* xsect
= osnew(lrud
);
1931 xsect
->l
= (VAL(Left
) * pcs
->units
[Q_LEFT
] - pcs
->z
[Q_LEFT
]) * pcs
->sc
[Q_LEFT
];
1932 xsect
->r
= (VAL(Right
) * pcs
->units
[Q_RIGHT
] - pcs
->z
[Q_RIGHT
]) * pcs
->sc
[Q_RIGHT
];
1933 xsect
->u
= (VAL(Up
) * pcs
->units
[Q_UP
] - pcs
->z
[Q_UP
]) * pcs
->sc
[Q_UP
];
1934 xsect
->d
= (VAL(Down
) * pcs
->units
[Q_DOWN
] - pcs
->z
[Q_DOWN
]) * pcs
->sc
[Q_DOWN
];
1935 xsect
->meta
= pcs
->meta
;
1936 if (pcs
->meta
) ++pcs
->meta
->ref_count
;
1939 next_lrud
= &(xsect
->next
);
1950 for (ordering
= pcs
->ordering
; ; ordering
++) {
1952 switch (*ordering
) {
1954 stn
= read_prefix(PFX_STATION
);
1956 case Left
: case Right
: case Up
: case Down
: {
1957 reading r
= *ordering
;
1958 read_reading(r
, fTrue
);
1959 if (VAL(r
) == HUGE_REAL
) {
1961 compile_error_token(-/*Expecting numeric field, found ā%sā*/9);
1979 default: BUG("Unknown reading in ordering");
1985 process_nosurvey(prefix
*fr
, prefix
*to
, bool fToFirst
)
1989 /* Suppress "unused fixed point" warnings for these stations */
1990 fr
->sflags
|= BIT(SFLAGS_USED
);
1991 to
->sflags
|= BIT(SFLAGS_USED
);
1993 /* add to linked list which is dealt with after network is solved */
1994 link
= osnew(nosurveylink
);
1996 link
->to
= StnFromPfx(to
);
1997 link
->fr
= StnFromPfx(fr
);
1999 link
->fr
= StnFromPfx(fr
);
2000 link
->to
= StnFromPfx(to
);
2002 link
->flags
= pcs
->flags
| (STYLE_NOSURVEY
<< FLAGS_STYLE_BIT0
);
2003 link
->meta
= pcs
->meta
;
2004 if (pcs
->meta
) ++pcs
->meta
->ref_count
;
2005 link
->next
= nosurveyhead
;
2006 nosurveyhead
= link
;
2013 prefix
*fr
= NULL
, *to
= NULL
;
2015 bool fMulti
= fFalse
;
2017 reading first_stn
= End
;
2023 for (ordering
= pcs
->ordering
; ; ordering
++) {
2025 switch (*ordering
) {
2027 fr
= read_prefix(PFX_STATION
|PFX_ALLOW_ROOT
);
2028 if (first_stn
== End
) first_stn
= Fr
;
2031 to
= read_prefix(PFX_STATION
|PFX_ALLOW_ROOT
);
2032 if (first_stn
== End
) first_stn
= To
;
2036 to
= read_prefix(PFX_STATION
);
2041 case IgnoreAllAndNewLine
:
2046 if (!process_nosurvey(fr
, to
, first_stn
== To
))
2049 if (ordering
[1] == End
) {
2053 } while (isComm(ch
));
2063 if (isData(ch
)) break;
2074 (void)process_nosurvey(fr
, to
, first_stn
== To
);
2081 } while (isComm(ch
));
2083 default: BUG("Unknown reading in ordering");
2088 /* totally ignore a line of survey data */