Dates from approximately 1992: SEF - An exchange standard for porting survey data -------------------------------------------------- Standard Exchange Format (SEF) files are used to import raw survey data into and out of cave survey processing systems such as SMAPS. The exchange mechanism currently supports two types of data within an exchange file. These two data types are Control Point groups which define the locations of points in space and Compass and Tape Survey groups based on the use of a magnetic compass and a tape. 1. General information. An SEF consists of the actual survey and control point groups interspersed with directives which define how the data should be interpreted. In general, a line beginning with a space in the first column is treated as a data line, a line beginning with a pound sign (#) is a directive, and any other line is treated as a comment. Each line must be terminated with either a linefeed (UNIX style) or a carriage return/linefeed (MSDOS style). Upper and lowercase are not distinct for directives but may be distinct for control point and survey station names in some programs. Each exchange file may have any number of Compass and Tape Survey or Control Point groups. A simple example is shown below: #ctsurvey This is a compass & tape survey group. : : Directives and survey data go here : : #endctsurvey #cpoint This is a control point group. : : Directives and control point data go here : : #endcpoint The string of characters following the "#ctsurvey" and "#cpoint" directives is the descriptive name of the file if the file has been exported by SMAPS. If the file is being imported into SMAPS then the string following the directive will be used as the descriptive name of the file created to contain the data within SMAPS. 2. The "#include" directive. At any point within an SEF, an "#include" directive will direct the import processor to insert the specified file into the input data stream. If a filename is given then the file is assumed to be in the same directory as the SEF being processed. If a partial or complete pathname is specified then the pathname will be used directly. An example of the use of the "#include" directive is shown below: #cpoint This is a control point group. : : #include cpdata.sef : : #endcpoint The contents of the file cpdata.sef will be inserted into the SEF at the point where the "#include" directive is encountered. Included files may themselves contain "#include" directives. The limit of the nesting of included files is related to the number of files that can be opened simultaneously in the language and operating system used. 3. Control Point Groups. Control Point groups are used to specify points which have known locations in space. The most common use of control points is to specify the geographical or UTM coordinates of benchmarks used as reference points. Control points may also be used to specify the locations of points within a local unreferenced coordinate system. 3.1 Control Point Group directives. A Control Point group begins with the "#cpoint " directive and ends with the "#endcpoint" directive. Several additional directives are used to direct the processing of control point data. 3.1.1 #units The "#units" directive determines the units in which control points are specified (not including elevation). The valid forms of the "#units" directive are: #units feet Unreferenced feet #units meters Unreferenced meters #units geog Geographical (Lat/Long/Elev) #units utm UTM coordinates Geographical coordinates are specified as follows with "d" meaning degrees, "m" meaning minutes, "s" meaning seconds, "x" meaning the letter "E" or "W", and "y" meaning "N" or "S": Longitudes: ddd-mm-ss.ssssx ex. 109-10.23-3245W Latitudes: dd-mm-ss.ssssy ex. 46-12-45.0110S The default units are unreferenced feet. The "#units" directive may only be specified prior to the first control point data line and may not be changed again within a group. 3.1.2 #elevunits The "#elevunits" directive specifies the units for elevation values. The default is feet. The "#elevunits" directive may only appear prior to the first control point data line within a group and may not be changed again within the group. Valid "#elevunits" directives are: #elevunits feet #elevunits meters 3.1.3 #com The "#com" directive is used to insert a comment into the General Comments section of a SMAPS Control Point File. A maximum of 16 comments may be inserted, each comment may be 60 characters long. 3.1.4 #zone The "#zone" directive is used to specify the zone to be used for a UTM coordinate system. An example "#zone" directive is shown below: #zone 16 3.2 Control Point Group data line format. The default data line format uses simple fixed fields: Columns Item ------- ---------------------------- 2-5 record type (SMAPS specific) 6-17 control point name 18-33 easting or longitude 34-49 northing or latitude 50-59 elevation The input format may be modified by using the "#data" directive. The "#data" directive has several forms allowing the user to specify the ordering of data items, the delimiters between data items, or the starting column and/or width of each data item. Several examples appear below: #data station,east,north,elev This specifies that the data will appear as the station name followed by the easting, northing, and elevation separated by commas. Extraneous spaces are not allowed. Any character may appear in place of the comma as the delimiter. The user must be careful that the delimiter character does not conflict with valid data characters. For example, a period will conflict with the decimal point. Only a single character may be specified as the delimiter but the delimiter may be different between each field. #data station north east elev This specifies that data will be entered as station name followed by northing, easting, and elevation each separated by an arbitrary number of spaces. A non-specified value may be indicated with an asterisk. #data station(12)east(16)north(16)elev(16) This specifies the column widths of each data item. The order of the data items is the same as specified in the "#data" directive. Since column 1 has special significance, data fields start in column 2. #data station(2,12)north(16,16)east(34,16)elev(52,16) This specifies the starting column and width of each data field. The field specifiers will not be checked for overlap. No data field may begin in column 1. The data format may be changed within a Control Point group. The format specifiers may be mixed and matched in any way that makes sense. The allowable data items for Control Point Groups are: Name Item ------- ------------------------------------------------------- type record type (SMAPS feature, 4 ASCII characters max) station control point name (12 chars max, no embedded blanks) east easting, longitude, or x coordinate (negative => west) north northing, latitude, or y coordinate (negative => south) elev elevation, or z coordinate. 3.3 Embedded comments. Any line appearing in a group which does not have a blank in column 1 will be treated as a comment. During an import operation the text of the comment will be placed in the Control Point File as an in-line comment. During an export operation any in-line comments in the Control Point File will be written in a manner that will guarantee a non-blank character appears in column 1. 4. Compass and Tape Survey Groups. Compass and Tape Survey Groups serve as the major data type in cave surveys. The basic format for specifying Compass and Tape Survey groups is the same as that of the Control Point groups the only difference being the directives and the data items. 4.1 Compass and Tape Survey Directives. Compass and Tape Survey groups always begin with a "#ctsurvey " directive and end with an "#endctsurvey" directive. Note: the equal sign is optional with all directives in SEF. The following directives are available for Compass and Tape Survey Groups: Directive Description Default --------- -------------------------------------------- ------- #atc=x Aux tape correction (x=#units) 0 #atdec=x Auxiliary decimal places 2 #atid=x Auxiliary tape identification None #bcc=x Backsight compass correction (x=degrees) 0 #bcdec=x Backsight compass decimal places (x=places) 2 #bcid=x Backsight compass identification None #bic=x Backsight incline correction (x=degrees) 0 #bidec=x Backsight incline decimal places (x=places) 2 #biid=x Backsight inclinometer identification None #clinerr=x Max allowable fs/bs inclinometer error 2 #com ... General survey comment (max 16 #comment directives, 60 characters each) None #compbs=x Compass backsight type (normal or corrected) Norm #comperr=x Max allowable fs/bs compass error 2 #date=x Survey date (mm/dd/yyyy) None #decl=x Declination (added to compass readings,units are degrees) 0 #duty ... Survey team member duty (max 8 #duty directives, 20 characters each) None #fcc=x Foresight compass correction (x=degrees) 0 #fcdec=x Foresight compass decimal places (x=places) 2 #fcid=x Foresight compass identification None #fic=x Foresight incline correction (x=degrees) 0 #fidec=x Foresight incline decimal places (x=places) 2 #fiid=x Foresight inclinometer identification None #incbs=x Inclinometer backsight type (normal or corrected) normal #mtc=x Main tape correction (x=#units) 0 #mtdec=x Main tape decimal places 2 #mtid=x Main tape identification None #person ... Survey team member name (max 8 #person directives, 20 characters each) None #tapemethod=x Taping method. Options available are: ss is = instrument to station it = instrument to target ss = station to station st = station to target #units=x Linear units (feet or meters) feet All angular measurements are in degrees. These directives must be specified prior to any data lines within a group. 4.2 Data line format. The data line format for Compass & Tape Survey group data lines follows the same scheme as Control Point data lines. A "#data" directive is used to describe the ordering and format of each line. The available data items are described below: Item Description ---- ------------------------- type record type (SMAPS feature, 4 ASCII characters max) from station from (12 characters max, no embedded blanks) to station to (12 characters max, no embedded blanks) dist distance between stations fazi forward azimuth bazi back azimuth finc forward incline binc back incline left distance to left wall right distance to right wall ceil distance to ceiling floor distance to floor iab instrument above station tab target above station vdist vertical distance (between from and to) Passage dimensions are measured relative to the from station looking towards the to station. The passage dimension of the last station in a dead-end sequence may be specified by placing the station name in the from field and the left, right, ceiling, and floor in the appropriate fields. The measurements are assumed to be perpendicular to the survey shot that connects to the dead-end station. The data line containing the dead-end station must immediately follow the line containing the survey shot connecting to it. The following is an example: a b l r c f b l r c f The default format of a data line is as follows: Column Item ------ ----- 2-5 type 6-17 from 18-29 to 30-39 dist 40-49 fazi 50-59 bazi 60-69 finc 70-79 binc 80-89 left 90-99 right 100-109 ceil 110-119 floor 120-129 iab 130-139 tab 140-149 vdist The default line format may be overridden by using a "#data" directive in the same manner as used in Control Point groups. Multiple "#data" directives may be used to change the data line format within a group. 4.3 Embedded comments. Any line appearing in the group which does not have a blank in column 1 will be treated as a comment. During an import operation the text of the comment will be placed in the Compass and Tape Survey file as an in-line comment. During an export operation any in-line comments in the Compass and Tape Survey file will be written in a manner that will guarantee a non-blank character in column 1. 5. Directory tree control directives. SMAPS utilizes a hierarchical (tree structured) file system to organize files. This structure is quite flexible and has proven to be a very powerful and usable paradigm. During an SEF export operation, directives are generated which will allow the directory structure to be recreated during a subsequent import operation. These directives must appear outside of any group and may be safely ignored by programs utilizing arcane flat file systems. 5.1 #dir The "#dir" directive may have any of the following formats: #dir or #dir (tag) or #dir (tag) is a character string of up to 40 characters which will be used as the directory name within SMAPS. The tag field may be used to attach a simple identifier to a directory. This is used to re-enter a previously created directory without having to correctly type the long descriptive name. If the tag is not given, then a new directory is created regardless if it already exists. Several examples here should help clarify matters: #dir Trout Rocks Caves This will create a directory named "Trout Rocks Caves" and make it the current directory. All groups imported will be placed into this directory until the directory is changed by another directive. #dir (a) Trout Cave Operates the same as the previous example except the tag "a" may now be used as a synonym for the Trout Cave directory. The Trout Cave directory is made current and will receive all imported groups until another directive changed to another directory. Since the tag a has now been used, it cannot be used again in conjunction with a descriptive name. #dir (a) This directive will move back to the Trout Cave directory regardless of what directory is currently active. The SMAPS limitation on directory levels is 10. If a directory becomes filled, then a new directory is automatically created as the last entry in the current directory. Further groups will be placed in the new directory. This process repeats as necessary. 5.2 #initdir The "#initdir" directive moves back to the original directory that was active when the import operation was started. It is not possible to move to a directory that is above the directory that was current when an import operation was started. 5.3 Building a directory tree. The following example shows a straightforward method of building a directory tree. The use of the "#include" directive makes the task simpler by allowing the data to be grouped into separate files. #dir (trout) Trout Rocks Caves #dir Trout Cave #include trout.sef #dir (trout) #dir New Trout Cave #include newtrout.sef #dir (trout) #dir Hamilton Cave #include hamilton.sef The previous example creates a tree of the following structure: +-------------------+ + Trout Rocks Caves + +-------------------+ | | | +--------------+ | +--------------+ | | | V V V +----------------+ +----------------+ +----------------+ | Trout Cave | | New Trout Cave | | Hamilton Cave | +----------------+ +----------------+ +----------------+ 6. Software availability An SEF import processor is available free of charge from Speleotechnologies, P.O. Box 293, Frostburg, Maryland 21532-0293. The software is written in ANSI C and compiles under Microsoft C Version 6.0a or later. As distributed, the processor is inthe form of a standalone program which will convert SEF to a fixed column format. The program is not intended to be used as an as-is utility but rather as a template for developing import processors for other survey processing systems. ========================================================================== Message 1/4 From Doug Dotson Oct 24, 94 05:47:19 pm EDT Return-Path: X-Disclaimer: Nyx is a public access Unix system run by the University of Denver. The University has neither control over nor responsibility for the opinions or correct identity of users. Date: Mon, 24 Oct 94 17:47:19 EDT To: nyx.cs.du.edu!lfish@uu5.psi.com Subject: Re: SEF Larry, The info you need in included in the README file on the SMAPS 5.2 distribution disk. I have appended a copy in case you can't locate a copy. Doug ----- Begin Included File ----- SMAPS 5.2 - Release Notes - November 11, 1992 Dear SMAPS user: As is typical with the first release of many software packages, SMAPS 5.1 had it's fair share of annoying bugs as well as a couple of rather serious ones. SMAPS 5.2 is being distributed free of charge in an attempt to "smooth over" any frazzled nerves resulting from these problems. 1) Installation instructions. a) Create a new directory to contain the new release. SMAPS52 is a good choice. b) Copy the entire contents of the distribution diskette into the new directory. c) Make the new directory the current directory (cd \smaps52). d) Install SMAPS by typing "install" at the prompt. 2) Preparing SMAPS 5.1 data for SMAPS 5.2. The format of the coordinate data files was changed to accomodate the changes made in SMAPS 5.2. It is therefore necessary to perform a "Purge" operation of any subtree that has associated coordinate data. These can be identified by a "C" or "CA" at the right side of the directory entry. Position the selection bar at each entry and press F1,F,P and then confirm by responding with the Yes response. This process MUST be performed for each directory that has coordinate data. If you have multiple MSDOS directories containing SMAPS file systems, it is best to purge all of them at one sitting so that you don't forget later. Trying to adjust or display coordinate data from SMAPS 5.1 will usually result in rather bewildering results! 3) Bugs Fixed. Several bugs (mostly minor) have been fixed. The following list covers most of them. Compass & Tape Survey Editor ---------------------------- a) Backsights for clinometer backsights were not always processed correctly. Fixed. b) Backsights for compass backsights were not always processed correctly. Fixed. c) If the declination was changed for an existing survey file, the change was not reflected in the relative coordinates. d) Foresight/backsight discrepancies were not always calculated correctly. Fixed. Loop Adjustment --------------- a) Loop adjustment did not always correctly identify loops when the data contained forward references. This usually resulted in no closure of loops. In other cases adjustments were unpredictable. b) Data that didnot contain loops was not adjusted to fit constrained stations. Graphics -------- a) The production of plot files during plotting was horribly slow. It has been speeded up by a factor of several hundred. b) Wall data was not displayed correctly when the data contained forward references. Also, wall information for dead-end sequences was not displayed at all. Fixed. NOTE: In SMAPS 4.4 and earlier, forward referencing was not supported. In many cases the editor features to invert and reverse shots were used to eliminate forward references. Unfortunately this made the wall data invalid for the shot. SMAPS 5.2 handles forward references. This means that data may be entered exactly as measured. The invert and reverse may be entered exactly as measured. The invert and reverse features should never be used on shots that have associated wall data. In this way the wall data remains valid. SMAPS 4 to SMAPS 5 Conversion Utility ------------------------------------- a) Occationally did not convert the declination of SMAPS 4 files correctly. Fixed. Data Printing ------------- a) Distances were not printed correctly for C&T Survey files. Fixed. 4. Enhancements to existing features. A number of enhancements to existing features were implemented. Some of these were at the request of users and others were to increase the speed or capacity of the system. Loop Adjustment --------------- Loop adjustment will now use extended memory (XMS) as supported by "himem.sys". If your system has at least 1.5 megabytes of extended memory managed by himem.sys, the loop adjuster will use it. Otherwise disk will be used. This was actually necessary to implement the rather complex task of performing loop adjustment on forward referenced data. The down side is that data with more than about 20 thousand shots can not be processed without extended memory. Memory is cheap, go buy some. Graphics -------- Several users suggested that it would be useful to assign colors to surveys automatically. The colors themselves are not too inportant but having the surveys different colors would help identify the surveys on the screen. Assigning colors by sequencing through all the available colors did not seem too good since black is a color and some of the colors are rather ugly. A more controlled approach was taken. Using the video palette editor, create some attributes of the form "AUTOx" where x is a number (ie AUTO1, AUTO2, AUTO3, ...). Give each of these attributes a different color. From the "Attribute Usage" menu, select "Automatic". When a map is displayed, each survey will be displayed with the next attribute in the sequence. ie. The first survey displayed will have the attribute AUTO1, the second survey displayed will have the attribute AUTO2, etc. When the last attribute is processed, the sequence starts over. A "Hot Refresh" mode has been implemented. Once enabled, the map will be refreshed with each change of the gnomon's position during a change view operation. This allows smaller maps to be interactively rotated. Data Printing ------------- a) In SMAPS 4.4 and earlier, the absolute coordinates printed with the "from" and "to" station names always corresponded to the "to" station. Beacuse of the forward referencing features of SMAPS 5.1 shots may be automatically reversed during processing to resolve a forward reference. As a result, if the shot was reversed during processing, the coordinate data corresponds to the "from" station. In a coordinate data printout, the station corresponding to the absolute data is surrounded by <>. For example: a 10.0 20.0 30.0 says that station "b" is at coordinate (10.0, 20.0, 30.0), while d 1.0 2.0 3.0 says that station "c" is at coordinate (1.0, 2.0, 3.0). 5. New features!!! Several new features have been implemented. Some of these are intended to make SMAPS easier to use, some correct deficiencies, and some were suggested by users. a) A subtree from a SMAPS filesystem may be exported to another MSDOS directory forming a new SMAPS filesystem. The original tree is not modified. This is intended to be used to prune a tree that has grown beyond managable size. Once the subtree has been exported, the original subtree may be placed in the trash and then the trash emptied. To export a subtree, place the selection on the directory which is to be the root of the new tree. Press F1,T,E and type in the pathname of the MSDOS directory to contain the new filesystem. If the directory does not exist, you will be prompted whether the directory should be created. The new directory may be used by specifying it as the Data Directory in the F1,C,R menu. b) A SMAPS filesystem in another MSDOS directory may be imported into an existing filesystem. The new filesystem will be imported into the current directory as a subdirectory and will be placed just prior to the entry at the selection bar. To import a filesystem, place the selection bar at the desired insertion point, press F1,T,I and enter the name of the MSDOS directory containg the sesired SMAPS filesystem. The imported filesystem is not altered. This is a convienient way to merging separate projects into a single one as is the case when surveyed passage appears to be approaching another cave. 6) SMAPS Exchange Format (SEF) changes. The SEF import/export language has been changed to be more flexible at the request of several users. The easiest way to understand the changes is to explain the export procedure first. To export a subtree or file to an SEF file, position the selection bar on the desired entry any press F1,A,E. Specify the name of the file to contain the exported data. If a path is not given, the file will be placed in the Auxilliary Directory with a .SEF extension. The directory manipulation directives have been changed to be more powerful. When data, a choice of Absolute or Relative export is available. The following is an example of an Absolute export of a subtree called Cube Cave with one control point file and one compass & tape survey file. #root #dir Cube #cpoint Cube Cave Control Point #units feet #dec 4 #elevunits feet #elevdec 4 #data type(2,4)station(6,12)east(18,16)north(34,16)elev(50,10) A 0.0000 0.0000 0.0000 #endcpoint #root #dir Cube #ctsurvey Cube Cave #comperr 3.00 #clinerr 3.00 #data type(2,4)from(7,12)to(20,12)fazi(33,5)bazi(39,5)finc(45,5)binc(51,5)dist(5 7,7)left(65,7)right(73,7)ceil(81,7)floor(89,7) A B 0.0 0.0 10.0 B C 90.0 0.0 10.0 L C D 180.0 0.0 10.0 D A 270.0 0.0 10.0 L A E 90.0 10.0 B F 90.0 10.0 L C G 90.0 10.0 D H 90.0 10.0 E F 0.0 0.0 10.0 F G 90.0 0.0 10.0 G H 180.0 0.0 10.0 H E 270.0 0.0 10.0 #endctsurvey The #root causes a move to the root directory in the SMAPS filesystem. The #dir Cube causes the Cube directory to be entered (or created if it doesn't exist). This as called an Absolute export because complete directory path information is included. When this file is imported, it will be placed in the exact directory structure as that from which it was exported. This is useful for distributing updates to multiple users on the same project. A relative export of the same subtree appear as follows: #dir Cube #cpoint Cube Cave Control Point #units feet #dec 4 #elevunits feet #elevdec 4 #data type(2,4)station(6,12)east(18,16)north(34,16)elev(50,10) A 0.0000 0.0000 0.0000 #endcpoint #ctsurvey Cube Cave #comperr 3.00 #clinerr 3.00 #data type(2,4)from(7,12)to(20,12)fazi(33,5)bazi(39,5)finc(45,5)binc(51,5)dist(5 7,7)left(65,7)right(73,7)ceil(81,7)floor(89,7) A B 0.0 0.0 10.0 B C 90.0 0.0 10.0 L C D 180.0 0.0 10.0 D A 270.0 0.0 10.0 L A E 90.0 10.0 B F 90.0 10.0 L C G 90.0 10.0 D H 90.0 10.0 E F 0.0 0.0 10.0 F G 90.0 0.0 10.0 G H 180.0 0.0 10.0 H E 270.0 0.0 10.0 #endctsurvey #up Notice the the #root directives are missing. If this file is imported, it will be placed in the current directory even if the directory tree has a different configuration than the one from which it was exported. In summary, #root moves to the root directory. #dir moves to the named directory if present and create the directory if not already present. #up moves up one directory level. #initdir move to the directory that was current when the import was initiated. SEF import is basically the same as described in the user's manual. The new directory directives will direct how the data in placed in the tree. Several changes and corrections ------------------------------- a) In Control Point groups, #elevdec specifies the number of decimal places for elevation values. #dec specifies the number or decimal places for unreferenced feet or meters. b) On page 101 section 9.1.4.2, in the "Item" column, "distance" should be "dist". c) Tags on #dir directives have been eliminated. Two SEF files are included with the distribution. "testrel.sef" contains the relative path file shown above, "testabs.sef" contains the absolute path data. New Plotter Drivers ------------------- A plotting driver for a HP LaserJet III in HPGL mode is now available. Current Projects ---------------- Progress continues on SMAPS. Here are a few of the current projects: Depth gauge support for you diver folks. Vector data files for importing digitized data. DXF import and export. Postscript plot driver. Incremental loop adjustment for you CRF folks. General speedup by using extended memory. More features in SMAPS/GIS involving elevation data. Tagging survey stations with database records including image data. SMAPS for Windows (maybe by next summer) If you have any problems, suggestions, or any other comments please call or write. Evenings are best. 410-437-2515 (H) 410-581-0422 (W) ========================================================================= 11-21-94 > | 2. There is a default format for all of the data in a ".SEF" | > | file. You can also change the default format in various ways. | > | For example, you can change the format using a "#data" | > | statement. After you change the format, does it stay changed | > | or does is revert to the default under some condition? For | > | example, does it revert to the default condition when you | > | encounter a "#endcpoint" or "#endctsurvey"? | Everything reverts back to defaults for each new survey or CP file. > | 3. In the "#data" directive, I want to make sure I understand | > | the format where only the width is specified. For example: | > | | > | #data station(12)east(16)north(16)elev(16) | > | | > | I assume that you start on the second character and read 12 | > | characters for the station, 16 characters for east, 16 | > | characters for north etc. I also assume that there may or may | > | not be any separator between fields. Let me know if I've got | > | this right. | Correct. There are never any separators in this case. The blanks between fields if the data does not fill the field would not really be considered as separators. > | 4. I notice that there are missing fields in the ".SEF" file | > | I have. This raises some issues for some of the data formats. | > | For example, I'm not sure if you could have a missing field | > | in the data format with single character separators. In | > | general, I'm sure what kind of missing fields I might see in | > | a SEF file and how they should be dealt with in the various | > | data formats. | I'm not clear on what you mean on this one. > | 5. In the document on the "SEF" format, in the section on the | > | "Control Point Group data line format", it says: "A | > | non-specified value may be indicated with an asterisk." I'm | > | not sure what this means. Does this mean a non-specified | > | value in the actual data or in the line that specifies the | > | data format? Is this how a missing data field is specified in | > | the single character separator format? | The asterisk appears in the actual data record. There really isn't any problem in the #data directive. The #data directive specifies only what data is going to be provided. An example of missing data in a Control Point would be a GPS position providing lat + long but no elevation. > | 6. I presume that correction factors such as #atc, #bcc, | > | #bic, etc. are reset to zero when #endctsurvey is encounterd. | > | Do you have to maintain a list compass, tape and inclinometer | > | identifiers so you can look a previously entered correction | > | factors? | Yes, reset to zero. No list of instruments in maintained. I have considered doing this in the feature though. > | 7. I presume that the units specification gets reset to feet | > | or something when #endctsurvey is encountered. | Yes. Feet. > | 8. There doesn't seem to be a units specifier for compass or | > | inclination readings. I assume this means that in the SEF | > | file these units are always in degrees. | #fcunits #bcunits #fiunits #biunits > | 9. I'm not sure I understand some of the correction factors. | > | It makes sense to add a correction factor to a compass | > | reading. This is because a compass error would have to be an | > | offset. However, a tape error is unlikely to be an offset. It | > | more likely to be a percent error or something like that. For | > | example, if a tape has a 0.5 foot error you wouldn't want to | > | add it to a one foot shot. | If you discover that your tape is missing 0.3 feet off of the beginning of the tape, this is a way of fixing it. It is not intended to compenstate for stretch or something like that. Very simple minded approach to a problem that almost never occurrs. ========================================================================= /* File: sefin.h /* Header file for SEF import processor */ /* Author: Douglas P. Dotson /* Date: 07 Aug 91 /* Edit: 28 May 1992 1602 DPD */ /* Definitions for SEF import processor */ /* General purpose stuff */ #define BOOL int #define FALSE 0 #define TRUE 1 #define forever for(;;) #define streq(s1,s2) (strcmp(s1,s2)==0) #define EMPTYDOUBLE -9999.9 typedef char FILENAME [9]; typedef char PATHNAME [41]; /* Maximum length of an input line */ #define LINESIZE 300 /* CurState values */ #define OUTSIDE 0 #define INCTS 1 #define INCP 2 typedef char STRING [13]; typedef char STR21 [21]; /* Location Units */ #define LOC_FEET 0 /* Location in feet */ #define LOC_METERS 1 /* Location in meters */ #define LOC_LATLONG 2 /* Location in latitude and longitude */ #define LOC_UTM 3 /* Location in UTM Coordinates */ /* Elevation Units */ #define ELEV_FEET 0 /* Elevation in feet */ #define ELEV_METERS 1 /* Elevation in meters */ /* Distance units */ #define DIST_FEET 0 /* Distance in decimal feet */ #define DIST_METERS 1 /* Distance in decimal meters */ /* Conversion factors */ #define RADS2DEG ((double)57.29577951308329) #define METERS2FEET ((double)3.280839895) ======================================================================== May 28, 1992 from Speleotechnologies. SEFIN -- Convert SEF file to general format. SEFIN is intended as a template to allow programmers to provide SEF import capability to their cave survey processing systems. As provided, the program accepts an SEF input file and produces an output file which is an a straightforward format. The program is invoked as follows: sefin SEFIN is not intended to be used as-is for any actual purpose but rather to provide a starting point for developers wishing to implement SEF import capability. The modules are reasonably well documented and any functions where data should be output is well commented with the names of the variables available at that point. Searching for the keyword "CUSTOM" will get you to all of these places. The current output of SEFIN could be actually useful since all lines of an informative nature have an asterisk in column 1. Control points and survey shots are in fixed column format in the same fields as described on page 99 and 102 of the SMAPS User's Manual. A makefile named 'sefin' is also provided. All modules are written in ANSI C and compile under Microsoft C Version 6.0a using Make version 4.07. Porting to other compilers should be straightforward. ================================ NEXT FILE ================================= /* File: sefin.c /* Import SEF file */ /* Author: Douglas P. Dotson /* Date: 07 Aug 91 /* Edit: 03 Jun 1992 0924 DPD */ #define LINT_ARGS #include #include #include #include "sefin.h" /* Functions defined in this module */ BOOL ImportSEF (char *); static BOOL GetLine (FILE *); void SkipBlanks (void); static void ConvertLine (void); static void DoData (void); static void DoComment (void); double GetNumeric (char *); void RemoveSpaces (char *); void Error (char *); void StrLwr (char *); /* Various data items */ FILE *SEFFile; /* SEF input file */ FILE *OutFile; /* Output File */ static BOOL ErrorFound; /* Error flag */ static long LineNumber; /* SEF input file line number */ char Line [LINESIZE];/* Current line being processed */ int LineIx; /* Current position in Line */ int LineLength; /* Length of Line */ int CurState; /* Current processing state */ BOOL DataStarted; /* Started processing data lines */ /*----------*/ main (int argc, char *argv[]) /* argv [1] = Name of SEF file for import */ /* argv [2] = Output file name */ { /* Check for proper number of args */ if (argc != 3) { fprintf (stderr, "Usage: sefin \n"); exit (1); } /* Create the output file */ OutFile = fopen (argv [2], "wt"); if (OutFile == NULL) { fprintf (stderr, "Unable to create %s\n", argv [2]); exit (1); } /* Initialize a few things */ ErrorFound = FALSE; LineNumber = 0L; CurState = OUTSIDE; /* Perform import */ ImportSEF (argv [1]); /* Close the output file */ fclose (OutFile); exit (0); } /* end main */ /*----------*/ BOOL ImportSEF (char *PathName) /* Import SEF file */ { /* Open the SEF file for input */ SEFFile = fopen (PathName, "rt"); if (SEFFile == NULL) { fprintf (stderr, "Unable to find %s\n", PathName); return FALSE; } /* Convert all lines in the file */ while (GetLine (SEFFile)) { ConvertLine (); if (ErrorFound) break; } fclose (SEFFile); return !ErrorFound; } /* end ImportSEF */ /*----------*/ static BOOL GetLine (FILE *File) /* Read a line from the SEF file */ { int Last; /* Read a line and check for end of file */ if (fgets (Line, LINESIZE, File) == NULL) return (FALSE); /* If a newline character is at the end of the line, remove it. */ Last = strlen (Line) - 1; if (Line [Last] == '\n') Last--; /* Remove any trailing blanks */ while (Last >= 0) if (isspace (Line [Last])) Last--; else break; Line [++Last] = '\0'; /* Set current line index to the beginning of the line */ LineIx = 0; LineNumber++; return TRUE; } /* end GetLine */ /*----------*/ void SkipBlanks (void) /* Skip characters up to next non-blank */ { while (Line [LineIx]) { if (isspace (Line [LineIx])) LineIx++; else break; } } /* end SkipBlanks */ /*----------*/ static void ConvertLine (void) /* Convert SEF line */ { /* Classify line and dispatch to appropriate function */ switch (Line [LineIx]) { case ' ': /* Data record */ LineIx++; LineLength = strlen (Line); DoData (); break; case '#': /* Directive */ LineIx++; DoDirective (); break; default: /* Comments */ DoComment (); break; } } /* end ConvertLine */ /*----------*/ static void DoComment (void) /* Process a comment line */ { if (CurState == OUTSIDE) return; /****************************************************************/ /* A comment line has been encountered inside a group. The */ /* Comments starts at &Line [LineIx] and is terminated with a */ /* NULL. */ /****************************************************************/ fprintf (OutFile, "*Comment: %s\n", &Line [LineIx]); } /* end DoComment */ /*----------*/ static void DoData (void) /* Process a data line */ { /* If line is blank, just ignore it */ if (strlen (Line) == 0) return; if (CurState == OUTSIDE) { Error ("Data line encountered outside of a group."); return; } /* If this is the first data line encountered, call the */ /* function to enable writing of group information prior */ /* to data lines. */ if (!DataStarted) { if (CurState == INCP) WriteCPInfo (); else WriteCTSInfo (); } /* Set flag indicating that data lines have begun. */ DataStarted = TRUE; /* Dispatch to the appropriate line reader */ if (CurState == INCP) ConvCPRec (); else ConvCTSRec (); } /* end DoData */ /*----------*/ double GetNumeric (char *Buffer) { char Message [80]; if (strlen (Buffer) == 0) return EMPTYDOUBLE; if (ValidDouble (Buffer)) return atof (Buffer); else if (streq (Buffer, "*")) return EMPTYDOUBLE; else { sprintf (Message, "Invalid numeric value: \'%s\'", Buffer); Error (Message); return 0; } } /* end GetNumeric */ /*----------*/ void RemoveSpaces (char *Buf) /* Remove any spaces in string */ { char *p, *q; p = q = Buf; while (*p) { if (*p != ' ') *q++ = *p; p++; } *q = '\0'; } /* end RemoveSpaces */ /*----------*/ void Error (char *Msg) /* Display an error message and setup for termination */ { fprintf (stderr, "Error in SEF file line %ld:\n %s\n%s\n", LineNumber, Msg, Line); ErrorFound = TRUE; } /* end Error */ /*----------*/ void StrLwr (char *s) /* Convert string to all lowercase */ { while (*s) { *s = tolower (*s); s++; } } /* end StrLwr */ ================================ NEXT FILE ================================= /* File: valids.c /* Validation functions for sefin */ /* Author: Douglas P. Dotson /* Date: 17 Dec 90 /* Edit: 03 Jun 1992 1208 DPD */ #define LINT_ARGS #include #include #include #include #include "sefin.h" /* Functions in this module */ BOOL ValidInt (char *); BOOL ValidDouble (char *); static int FClassify (char); BOOL ValLatLong (char *, char *, int); static void DoAction (int, char); static int Classify (char); BOOL EmptyDouble (double); /* Various definitions */ #define ACC -1 #define REJ -2 /* Local variables */ static int Degrees, Minutes, WholeSecs; static double FracSecs, Mult; static char Horiz; static BOOL Latitude; static int State, Class; static char *p; static double Dir, MaxDeg, TotSecs; static int StateTab [8][6] = { /* space digit - NEWS . else */ /* 0 */ { 0, 1, -1, -1, -1, -1}, /* 1 */ {-1, 1, 2, 6, -1, -1}, /* 2 */ {-1, 3, -1, -1, -1, -1}, /* 3 */ {-1, 3, 4, 6, -1, -1}, /* 4 */ {-1, 5, -1, -1, -1, -1}, /* 5 */ {-1, 5, -1, 6, 7, -1}, /* 6 */ { 6, -1, -1, -1, -1, -1}, /* 7 */ {-1, 7, -1, 6, -1, -1}, }; static int ActionTab [8][6] = { /* space digit - NEWS . else */ /* 0 */ {0, 1, 0, 0, 0, 0}, /* 1 */ {0, 1, 0, 4, 0, 0}, /* 2 */ {0, 2, 0, 0, 0, 0}, /* 3 */ {0, 2, 0, 4, 0, 0}, /* 4 */ {0, 3, 0, 0, 0, 0}, /* 5 */ {0, 3, 0, 4, 0, 0}, /* 6 */ {0, 0, 0, 0, 0, 0}, /* 7 */ {0, 5, 0, 4, 0, 0} }; /*----------*/ BOOL ValidInt (char *Buf) /* check for valid integer */ { if (!*Buf) return (FALSE); /* skip leading blanks */ while (*Buf && (*Buf == ' ')) Buf++; /* check for digits */ while (*Buf && (isdigit (*Buf))) Buf++; /* check that remain characters are spaces */ while (*Buf) { if (*Buf != ' ') return (FALSE); Buf++; } return (TRUE); } /* end ValInt */ /*----------*/ BOOL ValidDouble (char *Buf) /* check for valid number in field */ { static int StateTable [6][4] = { /* state */ /* 0 1 2 3 */ /* digit */ { 1, 1, 2, REJ}, /* space */ { 0, 3, 3, 3}, /* point */ { 2, 2, REJ, REJ}, /* minus */ { 1, REJ, REJ, REJ}, /* end */ { REJ, ACC, ACC, ACC}, /* else */ { REJ, REJ, REJ, REJ}}; int Type, State; char *p; /* an empty field is a valid field */ if (strlen (Buf) == 0) return (TRUE); State = 0; p = Buf; while (*Buf) { Type = FClassify (*Buf++); if (Type == REJ) return (FALSE); State = StateTable [Type][State]; } return (StateTable [4][State] == ACC); } /* end ValidDouble */ /*----------*/ static int FClassify (char Ch) /* classify character for ValidDouble */ { if (isdigit (Ch)) return (0); else if (Ch == ' ') return (1); else if (Ch == '.') return (2); else if ((Ch == '-') || (Ch == '+')) return (3); else return (REJ); } /* end FClassify */ /*----------*/ BOOL ValLatLong (Buf, LatOrLong, Decimals) /* Verify that Buf contains a valid Latitude or longitude */ /* in deg-min-sec format. If value is valid reformat into */ /* standard format and return TRUE, otherwise return FALSE. */ /* Buf contains value, LatOrLong is "LAT" or "LONG". */ char *Buf; /* Buffer containing Direction string */ char *LatOrLong; int Decimals; /* Places to right of decimal point */ { char Ch; Latitude = (strcmp (LatOrLong, "LAT") == 0); State = 0; p = Buf; Degrees = 0; Minutes = 0; WholeSecs = 0; FracSecs = 0.0; Mult = 0.1; MaxDeg = Latitude ? 90.0 : 180.0; /* Cycle through FSM and perform actions */ while (Ch = *p++) { Ch = toupper (Ch); Class = Classify (Ch); if (StateTab [State][Class] == -1) return (FALSE); DoAction (ActionTab [State][Class], Ch); State = StateTab [State][Class]; } /* Check for rejecting State */ if (State == 0) { strcpy (Buf, ""); return (TRUE); } if (State != 6) return (FALSE); /* Combine all parts and Check for validity */ if (Minutes >= 60) return (FALSE); TotSecs = WholeSecs + FracSecs; if (TotSecs >= 60.0) return (FALSE); Dir = Degrees + (Minutes / 60.0) + (TotSecs / 3600.0); if (Dir > MaxDeg) return (FALSE); /* Reformat into standard format */ if (Latitude) if (TotSecs >= 10.0) sprintf (Buf, "%02u-%02u-%0.*lf%c", Degrees, Minutes, Decimals, TotSecs, Horiz); else sprintf (Buf, "%02u-%02u-0%0.*lf%c", Degrees, Minutes, Decimals, TotSecs, Horiz); else if (TotSecs >= 10.0) sprintf (Buf, "%03u-%02u-%0.*lf%c", Degrees, Minutes, Decimals, TotSecs, Horiz); else sprintf (Buf, "%03u-%02u-0%0.*lf%c", Degrees, Minutes, Decimals, TotSecs, Horiz); return (TRUE); } /* end ValLatLong /*----------*/ static int Classify (char Ch) /* determine character Class */ { if (isdigit (Ch)) return (1); switch (Ch) { case ' ': return (0); case 'N': case 'S': if (Latitude) return (3); return (5); case '-': case '/': return (2); case 'E': case 'W': if (Latitude) return (5); return (3); case '.': return (4); default: return (5); } } /* end Classify */ /*----------*/ static void DoAction (int Action, char Ch) /* perform Action, return false if error */ { switch (Action) { case 0: /* no Action */ break; case 1: /* accumulate digit into Degrees */ Degrees = Degrees * 10 + (Ch - '0'); break; case 2: /* accumulate digit into Minutes */ Minutes = Minutes * 10 + (Ch - '0'); break; case 3: /* accumulate digit into seconds */ WholeSecs = WholeSecs * 10 + (Ch - '0'); break; case 4: /* save NEWS indicator */ Horiz = Ch; break; case 5: /* frActional seconds */ FracSecs = FracSecs + (Ch - '0') * Mult; Mult /= 10.0; break; } } /* end DoAction */ /*----------*/ BOOL EmptyDouble (Val) /* check for empty double variable */ double Val; { BOOL Diff; Diff = fabs (Val - EMPTYDOUBLE) < 0.05; return (Diff); } /* end EmptyDouble */ ================================ NEXT FILE ================================ ; This is a makefile to build the sample program "sefin.exe" ; It works with Microsoft Make 4.07 sefin.obj: sefin.c sefin.h cl /AL /Zp /Os sefin.c /c direct.obj: direct.c sefin.h cl /AL /Zp /Os direct.c /c data.obj: data.c sefin.h cl /AL /Zp /Os data.c /c valids.obj: valids.c sefin.h cl /AL /Zp /Os valids.c /c makecp.obj: makecp.c sefin.h cl /AL /Zp /Os makecp.c /c makects.obj: makects.c sefin.h cl /AL /Zp /Os makects.c /c sefin.exe: sefin.obj direct.obj data.obj valids.obj makecp.obj makects.obj link /NOE sefin+direct+data+valids+makecp+makects; ================================ NEXT FILE ================================ examp.sef This is a sample SEF file for testing the import processor #dir (a) Control Points directory #cpoint Sample Control Point Group #units=geog #dec=4 #elevunits = feet #elevdec 2 #com This is a comment. #data type(2,4)station(6,12)east(18,16)north(34,16)elev(50,10) abcdA0 079-22-15.0000W 38-36-20.0000N 2025.00 This is an inline comment #endcpoint #initdir #dir (b) Survey data directory #ctsurvey Sample C&T Survey Group #date 10-04-1954 #fcid Doug's Compass #fcdec 3 #bcid Beth's Compass #bcdec 3 #decl 1.20 #person Beth #duty Instruments #person Doug #duty Tape #person Bob #duty Sketch #com Here are some comments. #data from(2,12)to(15,12)dist(28,8)fazi(37,7)finc(45,7)iab(53,8)tab(62,8) NWC PMR19 60.70 225.500 -8.000 PMR19 PMR18 98.50 221.000 -3.000 PMR18 PMR17 66.50 208.000 2.000 PMR17 PMR16 42.70 203.000 -7.000 PMR16 PMR15 99.60 189.000 -7.500 PMR15 PMR14 98.50 198.000 -2.000 PMR14 PMR13 83.20 175.000 -4.500 PMR13 PMR12 96.90 166.500 -5.000 PMR12 PMR11 51.30 175.000 -10.000 PMR11 PMR10 83.60 181.500 -12.000 PMR10 PMR9 98.90 174.500 -0.500 PMR9 PMR8 59.40 166.500 -3.000 PMR8 PMR7 54.70 169.500 -6.500 PMR7 PMR6 53.40 162.000 -7.000 PMR6 PMR5 98.80 157.000 -8.000 PMR5 PMR4 61.50 126.000 -1.000 PMR4 PMR3 64.20 109.500 -5.500 #endctsurvey ========================================================================== /* File: data.c #data directive processing routines /* Author: Douglas P. Dotson /* Date: 09 Mar 1992 /* Edit: 03 Jun 1992 1207 DPD */ #define LINT_ARGS #include #include #include #include #include "sefin.h" /* Field Descriptors */ #define NUM_FIELDS 15 typedef struct { int ItemType; /* 0=>column, 1=>delimited */ char Delimiter; /* Delimiter between fields */ int StartColumn; /* Starting column of field */ int Width; /* Width of field */ int Offset; /* Offset into data array */ } FieldDesc; static FieldDesc Fields [NUM_FIELDS]; /* Item types */ #define ITYPE_COLUMN 0 #define ITYPE_DELIMITED 1 /* Default item descriptors for control point groups */ static FieldDesc CPDefaults [] = { /* type */ {ITYPE_COLUMN, 0, 2, 4, 0}, /* station */ {ITYPE_COLUMN, 0, 6, 12, 1}, /* easting */ {ITYPE_COLUMN, 0, 18, 16, 2}, /* northing */ {ITYPE_COLUMN, 0, 34, 16, 3}, /* elev */ {ITYPE_COLUMN, 0, 50, 10, 4} }; /* Default item descriptors for compass & tape groups */ static FieldDesc CTSDefaults [] = { /* type */ {ITYPE_COLUMN, 0, 2, 4, 0}, /* from */ {ITYPE_COLUMN, 0, 6, 12, 1}, /* to */ {ITYPE_COLUMN, 0, 18, 12, 2}, /* fazi */ {ITYPE_COLUMN, 0, 40, 10, 3}, /* bazi */ {ITYPE_COLUMN, 0, 50, 10, 4}, /* finc */ {ITYPE_COLUMN, 0, 60, 10, 5}, /* binc */ {ITYPE_COLUMN, 0, 70, 10, 6}, /* dist */ {ITYPE_COLUMN, 0, 30, 10, 7}, /* left */ {ITYPE_COLUMN, 0, 80, 10, 8}, /* right */ {ITYPE_COLUMN, 0, 90, 10, 9}, /* ceil */ {ITYPE_COLUMN, 0, 100, 10, 10}, /* floor */ {ITYPE_COLUMN, 0, 110, 10, 11}, /* iab */ {ITYPE_COLUMN, 0, 120, 10, 12}, /* tab */ {ITYPE_COLUMN, 0, 130, 10, 13}, /* vdist */ {ITYPE_COLUMN, 0, 140, 10, 14} }; /* Tables of keywords for converting fields to offsets */ static char *CPFields [] = {"type", "station", "east", "north", "elev", NULL}; static char *CTSFields [] = {"type", "from", "to", "fazi", "bazi", "finc", "binc", "dist", "left", "right", "ceil", "floor", "iab", "tab", "vdist", NULL}; /* Various local variables */ static char **DataFields; /* Pointer to current list of fields */ static char Line [200]; /* Current line being scanned */ static int LineIx; /* Current position in Line */ static char TokValueStr [50]; /* Token value for strings */ static int TokValueNum; /* Token value for numbers */ static char TokValueChar; /* Token value for characters */ static BOOL UnGot; /* An ungotten token exists */ static int UnGotToken; /* The ungotten token */ static int NumFields; /* Number of fields in current field list */ static BOOL (*ProcessField) (int, char *); /* Processing function */ int Columns [30]; /* Column ordering information */ /* Functions defined in this module */ void SetCPData (void); void SetCTSData (void); BOOL ParseData (char *); static void ScanInit (char *); static int GetToken (void); static void UnGetToken (int); static int GetOffset (char *); BOOL GetFields (char *); static void DataError (int, char *); /* External functions */ extern BOOL ProcessCP (int, char *); extern BOOL ProcessCTS (int, char *); extern void Error (char *); extern void StrLwr (char *); /* Token Classes */ #define TOK_STRING 0 #define TOK_NUMBER 1 #define TOK_SPACES 2 #define TOK_LPAREN 3 #define TOK_RPAREN 4 #define TOK_COMMA 5 #define TOK_ENDLINE 6 #define TOK_OTHER 7 /*----------*/ void SetCPData (void) /* Setup for CP data line parsing */ { DataFields = CPFields; memcpy (&Fields, &CPDefaults, sizeof (CPDefaults)); NumFields = sizeof (CPDefaults) / sizeof (FieldDesc); ProcessField = ProcessCP; } /* end SetCPData */ /*----------*/ void SetCTSData (void) /* Setup for CTS data line parsing */ { DataFields = CTSFields; memcpy (&Fields, &CTSDefaults, sizeof (CTSDefaults)); NumFields = sizeof (CTSDefaults) / sizeof (FieldDesc); ProcessField = ProcessCTS; } /* end SetCTSData */ /*----------*/ BOOL ParseData (char *DataLine) /* Parse the #data line */ { int Offset, Token, Start, Col; ScanInit (DataLine); NumFields = 0; Col = 0; memset (&Fields, 0, sizeof (Fields)); while ((Token = GetToken ()) != TOK_ENDLINE) { if (Token == TOK_STRING) { /* Get the offset of the field */ Offset = GetOffset (TokValueStr); if (Offset != -1) { Fields [NumFields].Offset = Offset; Columns [Col++] = Offset; } else { DataError (Token, "Unknown field name"); return FALSE; } /* Next token can be spaces, delimeter, or ( */ Fields [NumFields].ItemType = ITYPE_DELIMITED; Token = GetToken (); if ((Token == TOK_SPACES) || (Token == TOK_COMMA) || (Token == TOK_OTHER)) { Fields [NumFields].Delimiter = TokValueChar; } else if (Token == TOK_LPAREN) { Fields [NumFields].ItemType = ITYPE_COLUMN; Token = GetToken (); if (Token == TOK_NUMBER) { Start = TokValueNum; Token = GetToken (); if (Token == TOK_COMMA) { Token = GetToken (); if (Token == TOK_NUMBER) { Fields [NumFields].StartColumn = Start; Fields [NumFields].Width = TokValueNum; Token = GetToken (); if (Token != TOK_RPAREN) { DataError (Token, "Invalid"); return FALSE; } } else { DataError (Token, "Invalid after comma"); return FALSE; } } else if (Token == TOK_RPAREN) { Fields [NumFields].StartColumn = -1; Fields [NumFields].Width = Start; } else { DataError (Token, "Invalid after number"); return FALSE; } } else { DataError (Token, "Invalid"); return FALSE; } } else if ((Token == TOK_OTHER) || (Token == TOK_COMMA)) { Fields [NumFields].Delimiter = TokValueChar; } else if (Token == TOK_ENDLINE) { NumFields++; break; } else { DataError (Token, "Invalid delimeter"); return FALSE; } NumFields++; } else { DataError (Token, "Invalid field specifier"); return FALSE; } } Columns [Col] = -1; return TRUE; } /* end ParseData */ /*----------*/ static void ScanInit (char *Str) /* Initialize the scanner */ { strcpy (Line, Str); LineIx = 0; UnGot = FALSE; } /* end ScanInit */ /*----------*/ static int GetToken () /* Get the next token */ { int i; /* return ungotten token if one exists */ if (UnGot) { UnGot = FALSE; return UnGotToken; } /* Check for an alpha string */ if (isalpha (Line [LineIx])) { i = 0; while (isalpha (Line [LineIx])) TokValueStr [i++] = Line [LineIx++]; TokValueStr [i] = '\0'; StrLwr (TokValueStr); return TOK_STRING; } /* Check for a number */ if (isdigit (Line [LineIx])) { i = 0; while (isdigit (Line [LineIx])) TokValueStr [i++] = Line [LineIx++]; TokValueStr [i] = '\0'; TokValueNum = atoi (TokValueStr); return TOK_NUMBER; } /* Check for other types of tokens */ switch (Line [LineIx++]) { case ' ': /* Any sequence of spaces */ while (Line [LineIx] == ' ') LineIx++; TokValueChar = ' '; return TOK_SPACES; case '(': return TOK_LPAREN; case ')': return TOK_RPAREN; case ',': TokValueChar = ','; return TOK_COMMA; case '\0': return TOK_ENDLINE; default: TokValueChar = Line [LineIx-1]; return TOK_OTHER; } } /* end GetToken */ /*----------*/ static void UnGetToken (int Token) /* Unget a token */ { UnGot = TRUE; UnGotToken = Token; } /* end UnGetToken */ /*----------*/ static int GetOffset (char *Str) /* Get offset for given string */ { char **p; p = DataFields; while (*p) { if (stricmp (*p, Str) == 0) break; p++; } if (*p) return p - DataFields; else return -1; } /* end GetOffset */ /*----------*/ BOOL GetFields (char *DataLine) { int i, j; char Field [100], *p, *LastPos; /* The data begins at column 2 since column 1 has special significance. */ p = DataLine + 1; LastPos = DataLine + (strlen (DataLine) - 1); for (i=0 ; i #include #include #include "sefin.h" /* Functions in this module */ void ConvCPRec (void); void WriteCPInfo (void); BOOL ProcessCP (int, char *); static BOOL VLong (char *); static BOOL VLat (char *); static double Long2Bin (char *); static double Lat2Bin (char *); static double Geo2Degrees (char *); /* External functions */ extern BOOL ValLatLong (char *, char *, int); extern double GetNumeric (char *); extern void RemoveSpaces (char *); extern BOOL GetFields (char *); extern void Error (char *); /* External data */ extern FILE *OutFile; extern char Line []; extern int LineIx; extern int elevunits; extern int units; extern int dec; extern int elevdec; extern int zone; extern char Comments [1000]; extern int Columns []; /* Local variables */ static STRING Type, Station; static double East, North, Elev; static double Conv, ElevConv; /*----------*/ void ConvCPRec (void) { /* Set up conversion factor */ Conv = (units == LOC_FEET) ? METERS2FEET : 1.0; ElevConv = (elevunits == ELEV_FEET) ? METERS2FEET : 1.0; /* Initialize the data fields to empty */ strcpy (Type, ""); strcpy (Station, ""); East = EMPTYDOUBLE; North = EMPTYDOUBLE; Elev = EMPTYDOUBLE; /* Read the data fields */ GetFields (Line); /*CUSTOM*************************************************/ /* At this point the following are defined: */ /* Type = Control point type */ /* Station = Name of control point */ /* East = easting (meters or degrees) */ /* North = northing (meters or degrees) */ /* Elev = elevation (meters) */ /* A value of EMPTYDOUBLE will be in any double fields */ /* not defined in the input line. Eastings and northings*/ /* are in meters if defined as 'feet', 'meters', or */ /* 'utm', or in degrees if defined as 'geog'. */ /********************************************************/ fprintf (OutFile, " %-4s%-12s%16.4lf%16.4lf%10.2lf\n", Type, Station, East, North, Elev); } /* end ConvCPRec */ /*----------*/ BOOL ProcessCP (int FldNum, char *FldValue) { switch (FldNum) { case 0: /* type */ RemoveSpaces (FldValue); strcpy (Type, FldValue); break; case 1: /* station */ RemoveSpaces (FldValue); strcpy (Station, FldValue); if (strlen (Station) == 0) Error ("Missing control point name."); break; case 2: /* easting */ if (!VLong (FldValue)) { Error ("Invalid easting."); break; } East = Long2Bin (FldValue); break; case 3: /* northing */ if (!VLat (FldValue)) { Error ("Invalid northing."); break; } North = Lat2Bin (FldValue); break; case 4: /* elev */ Elev = GetNumeric (FldValue); if (!EmptyDouble (Elev)) Elev /= ElevConv; break; } return TRUE; } /* end ProcessCP */ /*----------*/ static BOOL VLat (char *FldPtr) /* Latitude verification function */ { if (strlen (FldPtr) == 0) return (TRUE); switch (units) { case LOC_FEET: case LOC_METERS: case LOC_UTM: if (!ValidDouble (FldPtr)) return FALSE; break; case LOC_LATLONG: if (!ValLatLong (FldPtr, "LAT", dec)) return FALSE; break; } return TRUE; } /* end VLat */ /*----------*/ static BOOL VLong (char *FldPtr) /* Longitude verification function */ { if (strlen (FldPtr) == 0) return (TRUE); switch (units) { case LOC_FEET: case LOC_METERS: case LOC_UTM: if (!ValidDouble (FldPtr)) return FALSE; break; case LOC_LATLONG: if (!ValLatLong (FldPtr, "LONG", dec)) return FALSE; break; } return TRUE; } /* end VLong */ /*----------*/ static double Lat2Bin (char *Str) /* Convert a latitude to binary */ { /* Feet or meters are converted to meters, Latitudes are converted */ /* to degrees, UTM are stored in meters (not changed) */ double Loc; if (strlen (Str) == 0) return EMPTYDOUBLE; switch (units) { case LOC_FEET: /* Convert to meters */ Loc = atof (Str) / METERS2FEET; break; case LOC_UTM: /* UTM is already in meters */ case LOC_METERS: Loc = atof (Str); break; case LOC_LATLONG: /* Convert to degrees */ Loc = Geo2Degrees (Str); break; } return Loc; } /* end Lat2Bin */ /*----------*/ static double Long2Bin (char *Str) /* Convert a longitude to binary */ { /* Feet are converted to meters, Latitudes are converted */ /* to degrees, UTM are stored in meters (not changed) */ double Loc; if (strlen (Str) == 0) return EMPTYDOUBLE; switch (units) { case LOC_FEET: Loc = atof (Str) / METERS2FEET; break; case LOC_METERS: case LOC_UTM: Loc = atof (Str); break; case LOC_LATLONG: /* Convert to degrees */ Loc = Geo2Degrees (Str); break; } return Loc; } /* end Long2Bin */ /*----------*/ double Geo2Degrees (char *GeogCoord) /* Convert geographical coord to degrees */ { int Degrees, Minutes, Last, Srce, Dest; char Buf [16], Buf2 [4], Letter; long double Degs, Seconds; strcpy (Buf, GeogCoord); /* Strip off and save letter */ Last = strlen (Buf) - 1; Letter = toupper (Buf [Last]); Buf [Last] = '\0'; /* Get and convert degrees */ Srce = 0; Dest = 0; while (Buf [Srce] != '-') Buf2 [Dest++] = Buf [Srce++]; Buf2 [Dest] = '\0'; Degrees = atoi (Buf2); /* Get and convert minutes */ Srce++; Dest = 0; while (Buf [Srce] != '-') Buf2 [Dest++] = Buf [Srce++]; Buf2 [Dest] = '\0'; Minutes = atoi (Buf2); /* Remainder is seconds */ Srce++; Seconds = atof (&Buf [Srce]); /* Combine and correct for west or south */ Degs = Degrees + Minutes / 60.0L + Seconds / 3600.0L; if ((Letter == 'S') || (Letter == 'W')) Degs = -Degs; return Degs; } /* end Geo2Degrees */ /*----------*/ void WriteCPInfo (void) /* Build and write info record */ { /*CUSTOM*********************************************************/ /* At this point the following values are defined: */ /* Comments = Contents of all #com directives */ /* units = Original units for control points */ /* dec = Original decimal places for easting and northing */ /* elevunits = Original units for elevation */ /* elevdec = Original units for elevations */ /* zone = UTM zone */ /****************************************************************/ fprintf (OutFile, "*Doing WriteCPInfo.\n"); fprintf (OutFile, "* units=%d, dec=%d, elevunits=%d, elevdec=%d, zone=%d\n", units, dec, elevunits, elevdec, zone); } /* end WriteCPInfo */ =============================== NEXT FILE =============================== /* File: makects.c /* Create a CTS file */ /* Author: Douglas P. Dotson /* Date: 21 Aug 91 /* Edit: 08 Jun 1992 0807 DPD */ #define LINT_ARGS #include #include #include #include "sefin.h" /* Functions in this module */ void ConvCTSRec (void); void WriteCTSInfo (void); BOOL ProcessCTS (int, char *); /* External functions */ extern double GetNumeric (char *); extern void RemoveSpaces (char *); extern BOOL GetFields (char *); extern void Error (char *); /* External data */ extern FILE *OutFile; extern char Line []; /* Line containing data items */ extern double atc; extern int atdec; extern STR21 atid; extern int atunits; extern double bcc; extern int bcdec; extern STR21 bcid; extern int bcunits; extern double bic; extern int bidec; extern STR21 biid; extern int biunits; extern double clinerr; extern BOOL compbs; extern double comperr; extern double decl; extern int elevunits; extern double fcc; extern int fcdec; extern STR21 fcid; extern int fcunits; extern double fic; extern int fidec; extern STR21 fiid; extern int fiunits; extern BOOL incbs; extern double mtc; extern int mtdec; extern STR21 mtid; extern int mtunits; extern int tapemethod; extern int units; extern char Date []; extern char Comments [1000]; extern STR21 Person [8]; extern STR21 Duty [8]; extern int PersonIx; extern int DutyIx; extern int Columns []; /* Local Variables */ static STRING Type, FromStat, ToStat; static double Dist, Fazi, Bazi, Finc, Binc; static double Left, Right, Ceiling, FloorDist; static double Iab, Tab, Vdist; static double Conv; /*----------*/ void ConvCTSRec (void) { /* Set up conversion factor */ Conv = (units == DIST_FEET) ? METERS2FEET : 1.0; /* Initialize all fields to empty */ strcpy (Type, ""); strcpy (FromStat, ""); strcpy (ToStat, ""); Fazi = EMPTYDOUBLE; Bazi = EMPTYDOUBLE; Finc = EMPTYDOUBLE; Binc = EMPTYDOUBLE; Dist = EMPTYDOUBLE; Left = EMPTYDOUBLE; Right = EMPTYDOUBLE; Ceiling = EMPTYDOUBLE; FloorDist = EMPTYDOUBLE; Iab = EMPTYDOUBLE; Tab = EMPTYDOUBLE; Vdist = EMPTYDOUBLE; /* Retrieve and validate fields from input line */ GetFields (Line); /*CUSTOM*********************************************************/ /* At this point the following items are defined: */ /* Type = Shot type */ /* FromStat = Station from */ /* ToStat = To Station */ /* Fazi = Forward azimuth (degrees) */ /* Bazi = Backsight azimuth (degrees) */ /* Finc = Forward incline (degrees) */ /* Binc = Backsight include (degrees) */ /* Dist = Distance between stations (meters) */ /* Left = Distance to left wall (meters) */ /* Right = Distance to right wall (meters) */ /* Ceiling = Distance to ceiling (meters) */ /* FloorDist = Distance to floor (meters) */ /* Iab = Instrument above station (meters) */ /* Tab = Target above station (meters) */ /* Vdist = Vertical distance between station (meters) */ /****************************************************************/ fprintf (OutFile, " %-4s", Type); fprintf (OutFile, "%-12s", FromStat); fprintf (OutFile, "%-12s", ToStat); fprintf (OutFile, "%10.2lf", Fazi); fprintf (OutFile, "%10.2lf", Bazi); fprintf (OutFile, "%10.2lf", Finc); fprintf (OutFile, "%10.2lf", Binc); fprintf (OutFile, "%10.2lf", Dist); fprintf (OutFile, "%10.2lf", Left); fprintf (OutFile, "%10.2lf", Right); fprintf (OutFile, "%10.2lf", Ceiling); fprintf (OutFile, "%10.2lf", FloorDist); fprintf (OutFile, "%10.2lf", Iab); fprintf (OutFile, "%10.2lf", Tab); fprintf (OutFile, "%10.2lf\n", Vdist); } /* end ConvCTSRec */ /*----------*/ BOOL ProcessCTS (int FldNum, char *FldValue) { RemoveSpaces (FldValue); switch (FldNum) { case 0: /* type */ strcpy (Type, FldValue); break; case 1: /* from */ strcpy (FromStat, FldValue); break; case 2: /* to */ strcpy (ToStat, FldValue); break; case 3: /* fazi */ Fazi = GetNumeric (FldValue); break; case 4: /* bazi */ Bazi = GetNumeric (FldValue); break; case 5: /* finc */ Finc = GetNumeric (FldValue); break; case 6: /* binc */ Binc = GetNumeric (FldValue); break; case 7: /* dist */ Dist = GetNumeric (FldValue); if (!EmptyDouble (Dist)) Dist /= Conv; break; case 8: /* left */ Left = GetNumeric (FldValue); if (!EmptyDouble (Left)) Left /= Conv; break; case 9: /* right */ Right = GetNumeric (FldValue); if (!EmptyDouble (Right)) Right /= Conv; break; case 10: /* ceil */ Ceiling = GetNumeric (FldValue); if (!EmptyDouble (Ceiling)) Ceiling /= Conv; break; case 11: /* floor */ FloorDist = GetNumeric (FldValue); if (!EmptyDouble (FloorDist)) FloorDist /= Conv; break; case 12: /* iab */ Iab = GetNumeric (FldValue); if (!EmptyDouble (Iab)) Iab /= Conv; break; case 13: /* tab */ Tab = GetNumeric (FldValue); if (!EmptyDouble (Tab)) Tab /= Conv; break; case 14: /* vdist */ Vdist = GetNumeric (FldValue); if (!EmptyDouble (Vdist)) Vdist /= Conv; break; } return TRUE; } /* end ProcessCTS */ /*----------*/ void WriteCTSInfo (void) { /*CUSTOM*********************************************************/ /* At this point the following are defined: */ /* */ /* atc = Aux tape correction (meters) */ /* bcc = Backsight compass correction (degrees) */ /* bic = Backsight inclinometer correction (degrees) */ /* compbs = Corrected backsights on backsight compass */ /* 0 => normal, 1 => corrected */ /* decl = magnetic declination as a string (degrees) */ /* fcc = Foresight compass correction (degrees) */ /* fic = Foresight inclinometer correction (degrees) */ /* incbs = Corrected backsight on backsight inclinometer */ /* 0 => normal, 1 => corrected */ /* mtc = Main tape correction (meters) */ /* tapemethod = Taping Method */ /* 0 = Station to station */ /* 1 = Instrument to station */ /* 2 = Station to target */ /* 3 = Instrument to target */ /* units = Linear units (0=feet, 1=meters) */ /* */ /* Most of these are for the purpose of configuring survey */ /* editors such as that in SMAPS and may be ignored by most */ /* survey data processing programs. */ /* */ /* atdec = Aux tape decimal places */ /* atid = Aux tape identification */ /* atunits = Aux tape units */ /* 0 => feet */ /* 1 => meters */ /* 2 => feet/inches */ /* 3 => centimeters */ /* bcdec = Backsight compass decimal places */ /* bcid = Backsight compass identification */ /* bcunits = Backsight compass units */ /* 0 => degrees */ /* 1 => mils */ /* 2 => grads */ /* 3 => bearing (dms) */ /* 4 => bearing (dec) */ /* bidec = Backsight inclinometer decimal places */ /* biid = Backsight inclinometer identification */ /* biunits = Backsight inclinometer units */ /* 0 => degrees */ /* 1 => mils */ /* 2 => grads */ /* clinerr = Inclinometer fs/bs allowable error */ /* Comments = Contents of all #com directives */ /* comperr = Compass fs/bs allowable error */ /* Date = File date as a string */ /* fcdec = Foresight compass decimal places */ /* fcid = Foresight compass identification */ /* fcunits = Foresight compass units */ /* 0 => degrees */ /* 1 => mils */ /* 2 => grads */ /* 3 => bearing (dms) */ /* 4 => bearing (dec) */ /* fidec = Foresight inclinometer decimal places */ /* fiid = Foresight inclinometer identification */ /* fiunits = Foresight inclinometer units */ /* 0 => degrees */ /* 1 => mils */ /* 2 => grads */ /* mtdec = Main tape decimal places */ /* mtid = Main tape identification */ /* mtunits = Main tape units */ /* 0 => feet */ /* 1 => meters */ /* 2 => feet/inches */ /* 3 => centimeters */ /* Person = Contents of #person directives */ /* PersonIx = Number of #person directives */ /* Duty = Contents of #duty directives */ /* DutyIx = Number of #duty directives */ /* */ /****************************************************************/ fprintf (OutFile, "*Doing WriteCTSInfo.\n"); fprintf (OutFile, "* atc=%.2lf, atdec=%d, atid=%s, atunits=%d\n", atc, atdec, atid, atunits); fprintf (OutFile, "* mtc=%.2lf, mtdec=%d, mtid=%s, mtunits=%d\n", mtc, mtdec, mtid, mtunits); fprintf (OutFile, "* fcc=%.2lf, fcdec=%d, fcid=%s, fcunits=%d\n", fcc, fcdec, fcid, fcunits); fprintf (OutFile, "* bcc=%.2lf, bcdec=%d, bcid=%s, bcunits=%d\n", bcc, bcdec, bcid, bcunits); fprintf (OutFile, "* fic=%.2lf, fidec=%d, fiid=%s, fiunits=%d\n", fic, fidec, fiid, fiunits); fprintf (OutFile, "* compbs=%d, comperr=%.2lf\n", compbs, comperr); fprintf (OutFile, "* bic=%.2lf, bidec=%d, biid=%s, biunits=%d\n", bic, bidec, biid, biunits); fprintf (OutFile, "* incbs=%d, clinerr=%.2lf\n", incbs, clinerr); fprintf (OutFile, "* decl=%.2lf, tapemethod=%d, units=%d, date=%s\n", decl, tapemethod, units, Date); } /* end WriteCTSInfo */ ========================================================================= /* File: direct.c /* SEF Import directives processors */ /* Author: Douglas P. Dotson /* Date: 08 Aug 91 /* Edit: 08 Jun 1992 0807 DPD */ #define LINT_ARGS #include #include #include #include #include "sefin.h" /* Functions defined in this module */ void DoDirective (void); static void Dir_Atc (void); static void Dir_Atdec (void); static void Dir_Atid (void); static void Dir_Atunits (void); static void Dir_Bcc (void); static void Dir_Bcdec (void); static void Dir_Bcid (void); static void Dir_Bcunits (void); static void Dir_Bic (void); static void Dir_Bidec (void); static void Dir_Biid (void); static void Dir_Biunits (void); static void Dir_Clinerr (void); static void Dir_Com (void); static void Dir_Compbs (void); static void Dir_Comperr (void); static void Dir_Confirm (void); static void Dir_Cpoint (void); static void Dir_Ctsurvey (void); static void Dir_Data (void); static void Dir_Date (void); static void Dir_Dec (void); static void Dir_Decl (void); static void Dir_Dir (void); static void Dir_Duty (void); static void Dir_Elevdec (void); static void Dir_Elevunits (void); static void Dir_Endcpoint (void); static void Dir_Endctsurvey (void); static void Dir_Fcc (void); static void Dir_Fcdec (void); static void Dir_Fcid (void); static void Dir_Fcunits (void); static void Dir_Fic (void); static void Dir_Fidec (void); static void Dir_Fiid (void); static void Dir_Fiunits (void); static void Dir_Incbs (void); static void Dir_Include (void); static void Dir_Initdir (void); static void Dir_Mtc (void); static void Dir_Mtdec (void); static void Dir_Mtid (void); static void Dir_Mtunits (void); static void Dir_Person (void); static void Dir_Root (void); static void Dir_Tapemethod (void); static void Dir_Units (void); static void Dir_Up (void); static void Dir_Zone (void); static void InitInfo (void); static int GetIntArg (void); static double GetDoubleArg (void); static void GetStringArg (char *); /* External functions */ extern BOOL ImportSEF (char *); extern BOOL ValidInt (char *); extern BOOL ValidDouble (char *); extern void SetCPData (void); extern void SetCTSData (void); extern BOOL ParseData (char *); extern void Error (char *); extern void StrLwr (char *); /* Various variables */ extern FILE *OutFile; extern char Line []; extern int LineIx; extern int CurState; extern BOOL DataStarted; /* Started processing data lines */ extern BOOL Confirm; /* Confirm on replace flag */ extern int Columns []; /* Column order information */ /* Local variables */ static char CurDirective [300]; /* Dispatch table for directives. Must be in ahphabetical order because */ /* a binary search is used to during lookup. */ typedef struct { char *DirName; void (*ProcName) (); } ProcListEntry; static ProcListEntry ProcList [] = { /* These must be in alphabetical order */ {"atc", Dir_Atc}, {"atdec", Dir_Atdec}, {"atid", Dir_Atid}, {"atunits", Dir_Atunits}, {"bcc", Dir_Bcc}, {"bcdec", Dir_Bcdec}, {"bcid", Dir_Bcid}, {"bcunits", Dir_Bcunits}, {"bic", Dir_Bic}, {"bidec", Dir_Bidec}, {"biid", Dir_Biid}, {"biunits", Dir_Biunits}, {"clinerr", Dir_Clinerr}, {"com", Dir_Com}, {"compbs", Dir_Compbs}, {"comperr", Dir_Comperr}, {"confirm", Dir_Confirm}, {"cpoint", Dir_Cpoint}, {"ctsurvey", Dir_Ctsurvey}, {"data", Dir_Data}, {"date", Dir_Date}, {"dec", Dir_Dec}, {"decl", Dir_Decl}, {"dir", Dir_Dir}, {"duty", Dir_Duty}, {"elevdec", Dir_Elevdec}, {"elevunits", Dir_Elevunits}, {"endcpoint", Dir_Endcpoint}, {"endctsurvey", Dir_Endctsurvey}, {"fcc", Dir_Fcc}, {"fcdec", Dir_Fcdec}, {"fcid", Dir_Fcid}, {"fcunits", Dir_Fcunits}, {"fic", Dir_Fic}, {"fidec", Dir_Fidec}, {"fiid", Dir_Fiid}, {"fiunits", Dir_Fiunits}, {"incbs", Dir_Incbs}, {"include", Dir_Include}, {"initdir", Dir_Initdir}, {"mtc", Dir_Mtc}, {"mtdec", Dir_Mtdec}, {"mtid", Dir_Mtid}, {"mtunits", Dir_Mtunits}, {"person", Dir_Person}, {"root", Dir_Root}, {"tapemethod", Dir_Tapemethod}, {"units", Dir_Units}, {"up", Dir_Up}, {"zone", Dir_Zone}, }; #define PLISTSIZE (sizeof (ProcList) / sizeof (ProcListEntry)) static int PLCompare (char *, ProcListEntry *); /* Many directives just set up the values of these variables */ char GroupName [41]; double atc; /* Aux tape correction */ int atdec; /* Aux tape decimal places */ STR21 atid; /* Aux tape identification */ int atunits; /* Aux tape units */ /* 0 => feet */ /* 1 => meters */ /* 2 => feet/inches */ /* 3 => centimeters */ double bcc; /* Backsight compass correction */ int bcdec; /* Backsight compass decimal places */ STR21 bcid; /* Backsight compass identification */ int bcunits; /* Backsight compass units */ /* 0 => degrees */ /* 1 => mils */ /* 2 => grads */ /* 3 => bearing (dms) */ /* 4 => bearing (dec) */ double bic; /* Backsight inclinometer correction */ int bidec; /* Backsight inclinometer decimal places */ STR21 biid; /* Backsight inclinometer identification */ int biunits; /* Backsight inclimometer units */ /* 0 => degrees */ /* 1 => mils */ /* 2 => grads */ double clinerr; /* Max allowable inclinometer fs/bs error */ BOOL compbs; /* Corrected backsights on backsight compass */ /* 0 => normal, 1=> corrected */ double comperr; /* Max allowable compass fs/bs error */ int dec; /* Easting and Northing decimal places */ double decl; /* Magnetic declination */ int elevdec; /* Decimal places for control point elevations */ int elevunits; /* Units for control point elevations */ /* 0=>feet, 1=>meters */ double fcc; /* Foresight compass correction */ int fcdec; /* Foresight compass decimal places */ STR21 fcid; /* Foresight compass identification */ int fcunits; /* Foresight compass units */ /* 0 => degrees */ /* 1 => mils */ /* 2 => grads */ /* 3 => bearing (dms) */ /* 4 => bearing (dec) */ double fic; /* Foresight inclinometer correction */ int fidec; /* Foresight inclinometer decimal places */ STR21 fiid; /* Foresight inclinometer identification */ int fiunits; /* Foresight inclinometer units */ /* 0 => degrees */ /* 1 => mils */ /* 2 => grads */ BOOL incbs; /* Corrected backsights on backsight inclinometer */ /* 0 => normal, 1=> corrected */ double mtc; /* Main tape correction */ int mtdec; /* Main tape decimal places */ STR21 mtid; /* Main tape identification */ int mtunits; /* main tape units */ /* 0 => feet */ /* 1 => meters */ /* 2 => feet/inches */ /* 3 => centimeters */ int tapemethod; /* Taping method */ /* 0 => Station to station */ /* 1 => Instrument to station */ /* 2 => Station to target */ /* 3 => Instrument to target */ int units; /* Linear units, 0=>feet, 1=>meters */ char Date [20]; /* File date */ int zone; /* UTM Zone */ /* Various buffers are used to hold strings */ char Comments [1000]; /* All internal file comments */ STR21 Person [8]; /* Crew persons */ STR21 Duty [8]; /* Crew duties */ int PersonIx; /* Index into Person */ int DutyIx; /* Index into Duty */ /*----------*/ void DoDirective () /* Process a directive */ { char Ch; int DirIx; ProcListEntry *PEntry; /* Get the directive name */ SkipBlanks (); DirIx = 0; forever { Ch = Line [LineIx]; if (isalpha (Ch)) { CurDirective [DirIx++] = tolower (Ch); LineIx++; } else break; } CurDirective [DirIx] = '\0'; /* Lookup the directive in the dispatch table */ PEntry = (ProcListEntry *) bsearch (CurDirective, &ProcList, PLISTSIZE, sizeof (ProcListEntry), PLCompare); /* Skip any blanks prior to the directive arguments */ SkipBlanks (); /* If not found, print an error message. Otherwise transfer control */ /* to the appropriate function. */ if (PEntry == NULL) Error ("Unknown directive."); else (*(PEntry->ProcName)) (); } /* end DoDirective */ /*----------*/ static int PLCompare (Key, Entry) /* Compare for bsearch above */ char *Key; ProcListEntry *Entry; { return (strcmp (Key, Entry->DirName)); } /* end PLCompare */ /*----------*/ static void Dir_Atc () { /* Check if inside a ctsurvey group */ if (CurState != INCTS) { Error ("#atc not valid outside of a ctsurvey group."); return; } /* Check if started processing data lines */ if (DataStarted) { Error ("Cannot use #atc after data lines."); return; } /* Get the argument and store it */ atc = GetDoubleArg (); } /* end Dir_Atc */ /*----------*/ static void Dir_Atdec () { /* Check if inside a ctsurvey group */ if (CurState != INCTS) { Error ("#atdec not valid outside of a ctsurvey group."); return; } /* Check if started processing data lines */ if (DataStarted) { Error ("Cannot use #atdec after data lines."); return; } /* Get the argument and store it */ atdec = GetIntArg (); } /* end Dir_Atdec */ /*----------*/ static void Dir_Atid () { /* Check if inside a ctsurvey group */ if (CurState != INCTS) { Error ("#atid not valid outside of a ctsurvey group."); return; } /* Check if started processing data lines */ if (DataStarted) { Error ("Cannot use #atid after data lines."); return; } /* Get the argument and store it */ GetStringArg (atid); } /* end Dir_Atid */ /*----------*/ static void Dir_Atunits () /* Aux tape units */ { char Units [80]; /* Check if inside a ctsurvey group */ if (CurState != INCTS) { Error ("#atunits not valid outside of a ctsurvey group."); return; } /* Check if started processing data lines */ if (DataStarted) { Error ("Cannot use #atunits after data lines."); return; } /* Get the argument and store it */ GetStringArg (Units); strlwr (Units); if (streq (Units, "feet")) atunits = 0; else if (streq (Units, "meters")) atunits = 1; else if (streq (Units, "ftin")) atunits = 2; else if (streq (Units, "centimeters")) atunits = 3; } /* end Dir_Atunits */ /*----------*/ static void Dir_Bcc () { /* Check if inside a ctsurvey group */ if (CurState != INCTS) { Error ("#bcc not valid outside of a ctsurvey group."); return; } /* Check if started processing data lines */ if (DataStarted) { Error ("Cannot use #bcc after data lines."); return; } /* Get the argument and store it */ bcc = GetDoubleArg (); } /* end Dir_Bcc */ /*----------*/ static void Dir_Bcdec () { /* Check if inside a ctsurvey group */ if (CurState != INCTS) { Error ("#bcdec not valid outside of a ctsurvey group."); return; } /* Check if started processing data lines */ if (DataStarted) { Error ("Cannot use #bcdec after data lines."); return; } /* Get the argument and store it */ bcdec = GetIntArg (); if (bcdec > 4) Error ("Too many decimal places specified"); } /* end Dir_Bcdec */ /*----------*/ static void Dir_Bcid () { /* Check if inside a ctsurvey group */ if (CurState != INCTS) { Error ("#bcid not valid outside of a ctsurvey group."); return; } /* Check if started processing data lines */ if (DataStarted) { Error ("Cannot use #bcid after data lines."); return; } /* Get the argument and store it */ GetStringArg (bcid); } /* end Dir_Bcid */ /*----------*/ static void Dir_Bcunits () /* Backsight compass units */ { char Units [80]; /* Check if inside a ctsurvey group */ if (CurState != INCTS) { Error ("#bcunits not valid outside of a ctsurvey group."); return; } /* Check if started processing data lines */ if (DataStarted) { Error ("Cannot use #bcunits after data lines."); return; } /* Get the argument and store it */ GetStringArg (Units); strlwr (Units); if (streq (Units, "degrees")) bcunits = 0; else if (streq (Units, "mils")) bcunits = 1; else if (streq (Units, "grads")) bcunits = 2; else if (streq (Units, "bearingdms")) bcunits = 3; else if (streq (Units, "bearingdec")) bcunits = 4; } /* end Dir_Bcunits */ /*----------*/ static void Dir_Bic () { /* Check if inside a ctsurvey group */ if (CurState != INCTS) { Error ("#bic not valid outside of a ctsurvey group."); return; } /* Check if started processing data lines */ if (DataStarted) { Error ("Cannot use #bic after data lines."); return; } /* Get the argument and store it */ bic = GetDoubleArg (); } /* end Dir_Bic */ /*----------*/ static void Dir_Bidec () { /* Check if inside a ctsurvey group */ if (CurState != INCTS) { Error ("#bidec not valid outside of a ctsurvey group."); return; } /* Check if started processing data lines */ if (DataStarted) { Error ("Cannot use #bidec after data lines."); return; } /* Get the argument and store it */ bidec = GetIntArg (); if (bidec > 4) Error ("Too many decimal places specified"); } /* end Dir_Bidec */ /*----------*/ static void Dir_Biid () { /* Check if inside a ctsurvey group */ if (CurState != INCTS) { Error ("#biid not valid outside of a ctsurvey group."); return; } /* Check if started processing data lines */ if (DataStarted) { Error ("Cannot use #biid after data lines."); return; } /* Get the argument and store it */ GetStringArg (biid); } /* end Dir_Biid */ /*----------*/ static void Dir_Biunits () /* Backsight inclinometer units */ { char Units [80]; /* Check if inside a ctsurvey group */ if (CurState != INCTS) { Error ("#biunits not valid outside of a ctsurvey group."); return; } /* Check if started processing data lines */ if (DataStarted) { Error ("Cannot use #biunits after data lines."); return; } /* Get the argument and store it */ GetStringArg (Units); strlwr (Units); if (streq (Units, "degrees")) biunits = 0; else if (streq (Units, "mils")) biunits = 1; else if (streq (Units, "grads")) biunits = 2; } /* end Dir_Biunits */ /*----------*/ static void Dir_Clinerr () { /* Check if inside a ctsurvey group */ if (CurState != INCTS) { Error ("#clinerr not valid outside of a ctsurvey group."); return; } /* Check if started processing data lines */ if (DataStarted) { Error ("Cannot use #clinerr after data lines."); return; } /* Get the argument and store it */ clinerr = GetDoubleArg (); } /* end Dir_Clinerr */ /*----------*/ static void Dir_Com () { /* Check if inside a group */ if (CurState == OUTSIDE) { Error ("#com not valid outside of a group."); return; } /* Check if enough room for this comment */ if (strlen (Comments) + strlen (&Line [LineIx]) > 1000) { Error ("Too many #com directives"); return; } /* Append the comment to the end of the comment buffer */ strcat (Comments, &Line [LineIx]); } /* end Dir_Com */ /*----------*/ static void Dir_Compbs () { char String [100]; /* Check if inside a ctsurvey group */ if (CurState != INCTS) { Error ("#compbs not valid outside of a ctsurvey group."); return; } /* Check if started processing data lines */ if (DataStarted) { Error ("Cannot use #compbs after data lines."); return; } GetStringArg (String); if (streq (String, "normal")) compbs = 0; else if (streq (String, "corrected")) compbs = 1; else Error ("Invalid value to right of ="); } /* end Dir_Compbs */ /*----------*/ static void Dir_Comperr () { /* Check if inside a ctsurvey group */ if (CurState != INCTS) { Error ("#comperr not valid outside of a ctsurvey group."); return; } /* Check if started processing data lines */ if (DataStarted) { Error ("Cannot use #comperr after data lines."); return; } /* Get the argument and store it */ comperr = GetDoubleArg (); } /* end Dir_Comperr */ /*----------*/ static void Dir_Confirm (void) { char Option [4]; SkipBlanks (); strncpy (Option, &Line [LineIx], 3); Option [3] = '\0'; StrLwr (Option); if (streq (Option, "on")) Confirm = TRUE; else if (streq (Option, "off")) Confirm = FALSE; else { Error ("Unknown option for #confirm"); return; } } /* end Dir_Confirm */ /*----------*/ static void Dir_Cpoint () { /* Check if outside of a group */ if (CurState != OUTSIDE) { Error ("#cpoint not valid inside of a group."); return; } /* Set state variable to indicate an active cpoint group */ CurState = INCP; /* Indicate no data lines processed yet */ DataStarted = FALSE; Columns [0] = -1; /* No columns define yet */ /* Initialize info items to default values */ InitInfo (); /* Get the name of the group */ SkipBlanks (); if (strlen (&Line [LineIx]) > 40) Error ("Group name too long."); else strcpy (GroupName, &Line [LineIx]); /* Setup #data processing for control points */ SetCPData (); /*CUSTOM*********************************************************/ /* A Control Point group has been started. The name of the */ /* group is contained in 'GroupName'. */ /****************************************************************/ fprintf (OutFile, "*Control Point Group: %s\n", GroupName); } /* end Dir_Cpoint */ /*----------*/ static void Dir_Ctsurvey () { /* Check if outside of a group */ if (CurState != OUTSIDE) { Error ("#ctsurvey not valid inside of a group."); return; } /* Set state variable to indicate an active ctsurvey group */ CurState = INCTS; /* Indicate no data lines processed yet */ DataStarted = FALSE; Columns [0] = -1; /* No columns define yet */ /* Initialize info items to default values */ InitInfo (); /* Get the name of the group */ SkipBlanks (); if (strlen (&Line [LineIx]) > 40) Error ("Group name too long."); else strcpy (GroupName, &Line [LineIx]); /* Setup #data processing for C&T Survey group */ SetCTSData (); /*CUSTOM*********************************************************/ /* A C&T Survey group has been started. The name of the */ /* group is contained in 'GroupName'. */ /****************************************************************/ fprintf (OutFile, "*C&T Survey Group: %s\n", GroupName); } /* end Dir_Ctsurvey */ /*----------*/ static void Dir_Data () { /* Check if inside a group */ if (CurState == OUTSIDE) { Error ("#data not valid outside of a group."); return; } /* Process the field descriptions */ SkipBlanks (); if (!ParseData (&Line [LineIx])) return; } /* end Dir_Data */ /*----------*/ static void Dir_Date () { /* Check if inside a group */ if (CurState == OUTSIDE) { Error ("#date not valid outside of a group."); return; } /* Retrieve the text string date */ GetStringArg (Date); } /* end Dir_Date */ /*----------*/ static void Dir_Dec () { /* Check if inside a cpoint group */ if (CurState != INCP) { Error ("#dec not valid outside of a cpoint group."); return; } /* Check if started processing data lines */ if (DataStarted) { Error ("Cannot use #dec after data lines."); return; } /* Get the argument and store it */ dec = GetIntArg (); if (dec > 4) Error ("Too many decimal places specified"); } /* end Dir_Dec */ /*----------*/ static void Dir_Decl () { /* Check if inside a ctsurvey group */ if (CurState != INCTS) { Error ("#decl not valid outside of a ctsurvey group."); return; } /* Check if started processing data lines */ if (DataStarted) { Error ("Cannot use #decl after data lines."); return; } /* Get the argument and store it */ decl = GetDoubleArg (); } /* end Dir_Decl */ /*----------*/ static void Dir_Dir () { /*CUSTOM*********************************************************/ /* Everything in this function can be ignored if data is not */ /* being imported into a hierarchical file system. */ /****************************************************************/ char DescName [41]; /* Check if inside a group */ if (CurState != OUTSIDE) { Error ("#dir not valid inside of a group."); return; } SkipBlanks (); if (strlen (&Line [LineIx])) { if (strlen (&Line [LineIx]) > 40) { Error ("Descriptive name too long."); return; } strcpy (DescName, &Line [LineIx]); } else { Error ("#dir missing filename"); return; } /* Perform the appropriate action */ /*CUSTOM*************************************************/ /* A #dir directive has been found. The filename is */ /* in 'DescName'. */ /********************************************************/ fprintf (OutFile, "* #dir found: Name=%s\n", DescName); } /* end Dir_Dir */ /*----------*/ static void Dir_Duty () { /* Check if inside a ctsurvey group */ if (CurState != INCTS) { Error ("#duty not valid outside of a ctsurvey group."); return; } /* Check if room in the duty list */ if (DutyIx == 8) { Error ("Too many #duty directives"); return; } /* Check for too long */ if (strlen (&Line [LineIx]) > 20) Error ("Duty too long"); else strcpy (Duty [DutyIx++], &Line [LineIx]); } /* end Dir_Duty */ /*----------*/ static void Dir_Elevdec () { /* Check if inside a cpoint group */ if (CurState != INCP) { Error ("#elevdec not valid outside of a cpoint group."); return; } /* Check if started processing data lines */ if (DataStarted) { Error ("Cannot use #elevdec after data lines."); return; } /* Get the argument and store it */ elevdec = GetIntArg (); if (elevdec > 4) Error ("Too many decimal places specified"); } /* end Dir_Elevdec */ /*----------*/ static void Dir_Elevunits () { char String [500]; /* Check if inside a cpoint group */ if (CurState != INCP) { Error ("#elevunits not valid outside of a cpoint group."); return; } /* Check if started processing data lines */ if (DataStarted) { Error ("Cannot use #elevunits after data lines."); return; } GetStringArg (String); if (streq (String, "feet")) elevunits = 0; else if (streq (String, "meters")) elevunits = 1; else Error ("Invalid value to right of ="); } /* end Dir_Elevunits */ /*----------*/ static void Dir_Endcpoint () { /* Check if inside a cpoint group */ if (CurState != INCP) { Error ("#endcpoint not valid unless inside a cpoint group."); return; } /* Set state variable to indicate no active group */ CurState = OUTSIDE; /*CUSTOM*********************************/ /* End of a control point group reached */ /****************************************/ fprintf (OutFile, "*End Control Point Group\n"); } /* end Dir_Endcpoint */ /*----------*/ static void Dir_Endctsurvey () { /* Check if inside a ctsurvey group */ if (CurState != INCTS) { Error ("#endctsurvey not valid unless inside a ctsurvey group."); return; } /* Set state variable to indicate no active group */ CurState = OUTSIDE; /*CUSTOM*********************************/ /* End of a control point group reached */ /****************************************/ fprintf (OutFile, "*End C&T Survey Group\n"); } /* end Dir_Endctsurvey */ /*----------*/ static void Dir_Fcc () { /* Check if inside a ctsurvey group */ if (CurState != INCTS) { Error ("#fcc not valid outside of a ctsurvey group."); return; } /* Check if started processing data lines */ if (DataStarted) { Error ("Cannot use #fcc after data lines."); return; } /* Get the argument and store it */ fcc = GetDoubleArg (); } /* end Dir_Fcc */ /*----------*/ static void Dir_Fcdec () { /* Check if inside a ctsurvey group */ if (CurState != INCTS) { Error ("#fcdec not valid outside of a ctsurvey group."); return; } /* Check if started processing data lines */ if (DataStarted) { Error ("Cannot use #fcdec after data lines."); return; } /* Get the argument and store it */ fcdec = GetIntArg (); if (fcdec > 4) Error ("Too many decimal places specified"); } /* end Dir_Fcdec */ /*----------*/ static void Dir_Fcid () { /* Check if inside a ctsurvey group */ if (CurState != INCTS) { Error ("#fcid not valid outside of a ctsurvey group."); return; } /* Check if started processing data lines */ if (DataStarted) { Error ("Cannot use #fcid after data lines."); return; } /* Get the argument and store it */ GetStringArg (fcid); } /* end Dir_Fcid */ /*----------*/ static void Dir_Fcunits () /* Foresight compass units */ { char Units [80]; /* Check if inside a ctsurvey group */ if (CurState != INCTS) { Error ("#fcunits not valid outside of a ctsurvey group."); return; } /* Check if started processing data lines */ if (DataStarted) { Error ("Cannot use #fcunits after data lines."); return; } /* Get the argument and store it */ GetStringArg (Units); strlwr (Units); if (streq (Units, "degrees")) fcunits = 0; else if (streq (Units, "mils")) fcunits = 1; else if (streq (Units, "grads")) fcunits = 2; else if (streq (Units, "bearingdms")) fcunits = 3; else if (streq (Units, "bearingdec")) fcunits = 4; } /* end Dir_Fcunits */ /*----------*/ static void Dir_Fiunits () /* Backsight inclinometer units */ { char Units [80]; /* Check if inside a ctsurvey group */ if (CurState != INCTS) { Error ("#biunits not valid outside of a ctsurvey group."); return; } /* Check if started processing data lines */ if (DataStarted) { Error ("Cannot use #biunits after data lines."); return; } /* Get the argument and store it */ GetStringArg (Units); strlwr (Units); if (streq (Units, "degrees")) fiunits = 0; else if (streq (Units, "mils")) fiunits = 1; else if (streq (Units, "grads")) fiunits = 2; } /* end Dir_Fiunits */ /*----------*/ static void Dir_Fic () { /* Check if inside a ctsurvey group */ if (CurState != INCTS) { Error ("#fic not valid outside of a ctsurvey group."); return; } /* Check if started processing data lines */ if (DataStarted) { Error ("Cannot use #fic after data lines."); return; } /* Get the argument and store it */ fic = GetDoubleArg (); } /* end Dir_Fic */ /*----------*/ static void Dir_Fidec () { /* Check if inside a ctsurvey group */ if (CurState != INCTS) { Error ("#fidec not valid outside of a ctsurvey group."); return; } /* Check if started processing data lines */ if (DataStarted) { Error ("Cannot use #fidec after data lines."); return; } /* Get the argument and store it */ fidec = GetIntArg (); if (fidec > 4) Error ("Too many decimal places specified"); } /* end Dir_Fidec */ /*----------*/ static void Dir_Fiid () { /* Check if inside a ctsurvey group */ if (CurState != INCTS) { Error ("#fiid not valid outside of a ctsurvey group."); return; } /* Check if started processing data lines */ if (DataStarted) { Error ("Cannot use #fiid after data lines."); return; } /* Get the argument and store it */ GetStringArg (fiid); } /* end Dir_Fiid */ /*----------*/ static void Dir_Mtunits () /* Main tape units */ { char Units [80]; /* Check if inside a ctsurvey group */ if (CurState != INCTS) { Error ("#mtunits not valid outside of a ctsurvey group."); return; } /* Check if started processing data lines */ if (DataStarted) { Error ("Cannot use #mtunits after data lines."); return; } /* Get the argument and store it */ GetStringArg (Units); strlwr (Units); if (streq (Units, "feet")) mtunits = 0; else if (streq (Units, "meters")) mtunits = 1; else if (streq (Units, "ftin")) mtunits = 2; else if (streq (Units, "centimeters")) mtunits = 3; } /* end Dir_Mtunits */ /*----------*/ static void Dir_Incbs () { char String [500]; /* Check if inside a ctsurvey group */ if (CurState != INCTS) { Error ("#incbs not valid outside of a ctsurvey group."); return; } /* Check if started processing data lines */ if (DataStarted) { Error ("Cannot use #incbs after data lines."); return; } GetStringArg (String); if (streq (String, "normal")) incbs = 0; else if (streq (String, "corrected")) incbs = 1; else Error ("Invalid value"); } /* end Dir_Incbs */ /*----------*/ static void Dir_Include () { char *IncludeFile; char Msg [80]; IncludeFile = &Line [LineIx]; if (!ImportSEF (IncludeFile)) { sprintf (Msg, "Unable to find include file - %s", IncludeFile); Error (Msg); } } /* end Dir_Include */ /*----------*/ static void Dir_Initdir () /* Move to initial directory */ { /*CUSTOM*********************************************************/ /* Everything in this function can be ignored if data is not */ /* being imported into a hierarchical file system. */ /****************************************************************/ /* Check if inside a group */ if (CurState != OUTSIDE) { Error ("#initdir not valid inside of a group."); return; } fprintf (OutFile, "* #initdir found\n"); } /* end Dir_Initdir */ /*----------*/ static void Dir_Mtc () { /* Check if inside a ctsurvey group */ if (CurState != INCTS) { Error ("#mtc not valid outside of a ctsurvey group."); return; } /* Check if started processing data lines */ if (DataStarted) { Error ("Cannot use #mtc after data lines."); return; } /* Get the argument and store it */ mtc = GetDoubleArg (); } /* end Dir_Mtc */ /*----------*/ static void Dir_Mtdec () { /* Check if inside a ctsurvey group */ if (CurState != INCTS) { Error ("#mtdec not valid outside of a ctsurvey group."); return; } /* Check if started processing data lines */ if (DataStarted) { Error ("Cannot use #mtdec after data lines."); return; } /* Get the argument and store it */ mtdec = GetIntArg (); } /* end Dir_Mtdec */ /*----------*/ static void Dir_Mtid () { /* Check if inside a ctsurvey group */ if (CurState != INCTS) { Error ("#mtid not valid outside of a ctsurvey group."); return; } /* Check if started processing data lines */ if (DataStarted) { Error ("Cannot use #mtid after data lines."); return; } /* Get the argument and store it */ GetStringArg (mtid); } /* end Dir_Mtid */ /*----------*/ static void Dir_Person () { /* Check if inside a ctsurvey group */ if (CurState != INCTS) { Error ("#person not valid outside of a ctsurvey group."); return; } /* Check if room in the person list */ if (PersonIx == 8) { Error ("Too many #person directives"); return; } /* Check for too long */ if (strlen (&Line [LineIx]) > 20) Error ("Person too long"); else strcpy (Person [PersonIx++], &Line [LineIx]); } /* end Dir_Person */ /*----------*/ static void Dir_Root () /* Move to root directory */ { /*CUSTOM*********************************************************/ /* Everything in this function can be ignored if data is not */ /* being imported into a hierarchical file system. */ /****************************************************************/ /* Check if inside a group */ if (CurState != OUTSIDE) { Error ("#initdir not valid inside of a group."); return; } fprintf (OutFile, "* #root found\n"); } /* end Dir_Root */ /*----------*/ static void Dir_Tapemethod () { char String [500]; /* Check if inside a ctsurvey group */ if (CurState != INCTS) { Error ("#tapemethod not valid outside of a ctsurvey group."); return; } /* Check if started processing data lines */ if (DataStarted) { Error ("Cannot use #tapemethod after data lines."); return; } GetStringArg (String); if (streq (String, "ss")) tapemethod = 0; else if (streq (String, "is")) tapemethod = 1; else if (streq (String, "st")) tapemethod = 2; else if (streq (String, "it")) tapemethod = 3; else Error ("Invalid value to right of ="); } /* end Dir_Tapemethod */ /*----------*/ static void Dir_Units () { char String [100]; /* Check if inside a group */ if (CurState == OUTSIDE) { Error ("#units not valid outside of a group."); return; } /* Check if started processing data lines */ if (DataStarted) { Error ("Cannot use #units after data lines."); return; } GetStringArg (String); if (CurState == INCP) { if (streq (String, "feet")) units = 0; else if (streq (String, "meters")) units = 1; else if (streq (String, "geog")) units = 2; else if (streq (String, "utm")) units = 3; else Error ("Invalid value"); } else { /* INCTS */ if (streq (String, "feet")) units = 0; else if (streq (String, "meters")) units = 1; else Error ("Invalid value"); } } /* end Dir_Units */ /*----------*/ static void Dir_Up () /* Move up 1 directory level */ { /*CUSTOM*********************************************************/ /* Everything in this function can be ignored if data is not */ /* being imported into a hierarchical file system. */ /****************************************************************/ /* Check if inside a group */ if (CurState != OUTSIDE) { Error ("#initdir not valid inside of a group."); return; } fprintf (OutFile, "* #up found\n"); } /* end Dir_Up */ /*----------*/ static void Dir_Zone () { /* Check if inside a cpoint group */ if (CurState != INCP) { Error ("#zone not valid outside of a cpoint group."); return; } /* Check if started processing data lines */ if (DataStarted) { Error ("Cannot use #zone after data lines."); return; } /* Get the argument and store it */ zone = GetIntArg (); if ((zone < 1) || (zone > 60)) Error ("Invalid UTM zone."); } /* end Dir_Zone */ /*----------*/ static void InitInfo () /* Initialize various info fields to defaults */ { atc = 0.0; /* Aux Tape Correction */ atdec = 2; /* Aux tape decimals */ strcpy (atid, ""); /* Aux tape id */ bcc = 0.0; /* Backsight compass correction */ bcdec = 2; /* Backsight comapss decimal places */ strcpy (bcid, ""); /* Backsight compass id */ bic = 0.0; /* Backsight inclinometer correction */ bidec = 2; /* Backsight inclinometer decimal places */ strcpy (biid, ""); /* Backsight inclinometer id */ clinerr = 2.0; /* Inclinometer FS/BS Max Error */ compbs = FALSE; /* Compass Corrected Backsights */ comperr = 2.0; /* Compass FS/BS Max error */ dec = 2; /* Control point decimals */ decl = 0.0; /* Magnetic declination */ elevunits = 0; /* Elevation units for CP files (feet) */ fcc = 0.0; /* Foresight compass correction */ fcdec = 2; /* Foresight compass decimal places */ strcpy (fcid, ""); /* Foresight compass id */ fic = 0.0; /* Foresight inclinometer correction */ fidec = 2; /* Foresight inclinometer decimal places */ strcpy (fiid, ""); /* Foresight inclinometer id */ incbs = FALSE; /* Inclinometer corrected backsights */ mtc = 0.0; /* Main tape correction */ mtdec = 2; /* Main tape decimals */ strcpy (mtid, ""); /* Main tape id */ tapemethod = 0; /* Taping method (stat-stat) */ units = 0; /* Tape units for CTS, Horiz units for CP (feet) */ zone = 16; /* UTM Zone */ strcpy (Date, ""); /* File date */ strcpy (Comments, ""); /* Reset comments index to beginning */ PersonIx = 0; /* Reset person index to beginning */ DutyIx = 0; /* Reset duty index to beginning */ } /* end InitInfo */ /*----------*/ static int GetIntArg () { /* Skip any blanks */ SkipBlanks (); /* If an equals sign is present, skip over it */ if (Line [LineIx] == '=') { LineIx++; SkipBlanks (); } /* The rest of the line should be a valid integer. */ /* Check it and convert it to binary. */ if (ValidInt (&Line [LineIx])) { return (atoi (&Line [LineIx])); } else { Error ("Invalid numeric operand."); return (0); } } /* end GetIntArg */ /*----------*/ static double GetDoubleArg () { /* Skip any blanks */ SkipBlanks (); /* If an equals sign is present, skip over it */ if (Line [LineIx] == '=') { LineIx++; SkipBlanks (); } /* The rest of the line should be a valid real. */ /* Check it and convert it to binary. */ if (ValidDouble (&Line [LineIx])) { return (atof (&Line [LineIx])); } else { Error ("Invalid numeric operand."); return 0; } } /* end GetDoubleArg */ /*----------*/ static void GetStringArg (Str) char *Str; { /* Skip any blanks */ SkipBlanks (); /* If an equals sign is present, skip over it */ if (Line [LineIx] == '=') { LineIx++; SkipBlanks (); } /* Convert rest of line to lowercase */ strcpy (Str, &Line [LineIx]); StrLwr (Str); } /* end GetStringArg */