source: git/src/findentrances.cc @ cd971de

RELEASE/1.2debug-cidebug-ci-sanitisersfaster-cavernlogstereowalls-datawalls-data-hanging-as-warning
Last change on this file since cd971de was 48e82bf, checked in by Olly Betts <olly@…>, 12 years ago

src/findentrances.cc: Add commenting noting precision of lat and lon.

  • Property mode set to 100644
File size: 5.4 KB
Line 
1/* findentrances.cc
2 * Simple converter from survex .3d files to a list of entrances in GPX format
3 *
4 * Copyright (C) 2012 Olaf Kähler
5 * Copyright (C) 2012 Olly Betts
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20 */
21
22/*
23 * This program parses the survex file, creates a list of entrances and does
24 * the coordinate transformations from almost arbitrary formats into WGS84
25 * using the PROJ.4 library. The output is then written as a GPX file ready
26 * for use in your favourite GPS software. Everything else is kept as simple
27 * and minimalistic as possible.
28 *
29 * Usage:
30 *   findentrances -d <+proj +datum +string> <input.3d>
31 *
32 * Example for data given in BMN M31 (Totes Gebirge, Austria):
33 *   findentrances -d '+proj=tmerc +lat_0=0 +lon_0=13d20 +k=1 +x_0=0 +y_0=-5200000 +ellps=bessel +towgs84=577.326,90.129,463.919,5.137,1.474,5.297,2.4232' cucc_austria.3d > ent.gpx
34 *
35 * Example for data given in british grid SD (Yorkshire):
36 *   findentrances -d '+proj=tmerc +lat_0=49d +lon_0=-2d +k=0.999601 +x_0=100000 +y_0=-500000 +ellps=airy +towgs84=375,-111,431,0,0,0,0' yorkshire/all.3d > ent.gpx
37 *
38 * Example for data given as proper british grid reference:
39 *   findentrances -d '+proj=tmerc +lat_0=49d +lon_0=-2d +k=0.999601 +x_0=400000 +y_0=-100000 +ellps=airy +towgs84=375,-111,431,0,0,0,0' all.3d > ent.gpx
40 *
41 */
42
43#include <stdio.h>
44#include <string>
45#include <vector>
46#include <iostream>
47#include <algorithm>
48#include <math.h>
49
50#include <proj_api.h>
51
52#include "message.h"
53#include "cmdline.h"
54#include "img.h"
55
56using namespace std;
57
58struct Point {
59    string label;
60    double x, y, z;
61};
62
63bool readSurvey(const char *filename, vector<Point> & points)
64{
65    img *survey = img_open_survey(filename, NULL);
66    if (!survey) {
67        fprintf(stderr, "failed to open survey '%s'\n", filename);
68        return false;
69    }
70
71    int result;
72    do {
73        img_point pt;
74        result = img_read_item(survey, &pt);
75
76        if (result == img_LABEL) {
77            if (survey->flags & img_SFLAG_ENTRANCE) {
78                Point newPt;
79                newPt.label.assign(survey->label);
80                newPt.x = pt.x;
81                newPt.y = pt.y;
82                newPt.z = pt.z;
83                points.push_back(newPt);
84            }
85        } else if (result == img_BAD) {
86            fprintf(stderr, "error while reading file\n");
87            return false;
88        }
89    } while (result != img_STOP);
90
91    img_close(survey);
92
93    return true;
94}
95
96bool convertCoordinates(vector<Point> & points, const char *inputDatum, const char *outputDatum)
97{
98    projPJ pj_input, pj_output;
99    if (!(pj_input = pj_init_plus(inputDatum))) {
100        fprintf(stderr, "failed to initialise input coordinate system '%s'\n", inputDatum);
101        return false;
102    }
103    if (!(pj_output = pj_init_plus(outputDatum))) {
104        fprintf(stderr, "failed to initialise output coordinate system '%s'\n", outputDatum);
105        return false;
106    }
107
108    for (size_t i=0; i<points.size(); ++i) {
109        pj_transform(pj_input, pj_output, 1, 1, &(points[i].x), &(points[i].y), &(points[i].z));
110    }
111
112    return true;
113}
114
115struct SortPointsByLabel {
116    bool operator()(const Point & a, const Point & b)
117    { return a.label < b.label; }
118} SortPointsByLabel;
119
120bool sortPoints(vector<Point> & points)
121{
122    sort(points.begin(), points.end(), SortPointsByLabel);
123    return true;
124}
125
126bool writeGPX(const vector<Point> & points, FILE *file)
127{
128    fprintf(file, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<gpx version=\"1.0\" creator=\"survex - findentrances\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://www.topografix.com/GPX/1/0\" xsi:schemaLocation=\"http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd\">\n");
129    for (size_t i=0; i<points.size(); ++i) {
130        const Point & pt = points[i];
131        // %.8f is at worst just over 1mm.
132        fprintf(file, "<wpt lon=\"%.8f\" lat=\"%.8f\"><ele>%.2f</ele><name>%s</name></wpt>\n", pt.x*180.0/M_PI, pt.y*180.0/M_PI, pt.z, pt.label.c_str());
133    }
134
135    fprintf(file, "</gpx>\n");
136    return true;
137}
138
139
140static const struct option long_opts[] = {
141    {"datum", required_argument, 0, 'd'},
142    {"help", no_argument, 0, HLP_HELP},
143    {"version", no_argument, 0, HLP_VERSION},
144    {0, 0, 0, 0}
145};
146
147static const char *short_opts = "d:";
148
149int main(int argc, char **argv)
150{
151    msg_init(argv);
152
153    const char *datum_string = NULL;
154    cmdline_init(argc, argv, short_opts, long_opts, NULL, NULL, 1, 1);
155    while (1) {
156        int opt = cmdline_getopt();
157        if (opt == EOF) break;
158        else if (opt == 'd') datum_string = optarg;
159    }
160
161    if (!datum_string) {
162        cerr << argv[0] << ": -d DATUM_STRING is required" << endl;
163        cmdline_syntax();
164        exit(1);
165    }
166
167    const char *survey_filename = argv[optind];
168
169    vector<Point> points;
170    if (!readSurvey(survey_filename, points)) return -1;
171    if (!convertCoordinates(points, datum_string, "+proj=longlat +ellps=WGS84 +datum=WGS84")) return -1;
172    if (!sortPoints(points)) return -1;
173    if (!writeGPX(points, stdout)) return -1;
174
175    return 0;
176}
177
Note: See TracBrowser for help on using the repository browser.