source: git/src/findentrances.cc @ 53496ab3

RELEASE/1.2debug-cidebug-ci-sanitisersstereowalls-datawalls-data-hanging-as-warning
Last change on this file since 53496ab3 was a405bc1, checked in by Olly Betts <olly@…>, 11 years ago

src/: IMG_HOSTED no longer affects the img API at all.

  • Property mode set to 100644
File size: 5.4 KB
RevLine 
[1686083]1/* findentrances.cc
2 * Simple converter from survex .3d files to a list of entrances in GPX format
[ac71f8a]3 *
[1686083]4 * Copyright (C) 2012 Olaf Kähler
[a405bc1]5 * Copyright (C) 2012,2013 Olly Betts
[1686083]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/*
[ac71f8a]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:
[e34a704b]30 *   findentrances -d <+proj +datum +string> <input.3d>
[ac71f8a]31 *
32 * Example for data given in BMN M31 (Totes Gebirge, Austria):
[e34a704b]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
[ac71f8a]34 *
35 * Example for data given in british grid SD (Yorkshire):
[e34a704b]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
[ac71f8a]37 *
38 * Example for data given as proper british grid reference:
[e34a704b]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
[ac71f8a]40 *
41 */
42
43#include <stdio.h>
44#include <string>
45#include <vector>
46#include <algorithm>
47#include <math.h>
48
49#include <proj_api.h>
50
51#include "message.h"
52#include "cmdline.h"
[a405bc1]53#include "img_hosted.h"
[ac71f8a]54
[8ec699d]55using namespace std;
56
[4d34e1f]57#define WGS84_DATUM_STRING "+proj=longlat +ellps=WGS84 +datum=WGS84"
58
[ac71f8a]59struct Point {
[8ec699d]60    string label;
[23dc8cb]61    double x, y, z;
[ac71f8a]62};
63
[4d34e1f]64static void
65read_survey(const char *filename, vector<Point> & points)
[ac71f8a]66{
[23dc8cb]67    img *survey = img_open_survey(filename, NULL);
68    if (!survey) {
[a405bc1]69        fatalerror(img_error2msg(img_error()), filename);
[23dc8cb]70    }
71
72    int result;
73    do {
74        img_point pt;
75        result = img_read_item(survey, &pt);
76
77        if (result == img_LABEL) {
78            if (survey->flags & img_SFLAG_ENTRANCE) {
79                Point newPt;
[ea788a3]80                newPt.label.assign(survey->label);
[23dc8cb]81                newPt.x = pt.x;
82                newPt.y = pt.y;
83                newPt.z = pt.z;
84                points.push_back(newPt);
85            }
86        } else if (result == img_BAD) {
[4d34e1f]87            img_close(survey);
[a405bc1]88            fatalerror(img_error2msg(img_error()), filename);
[ac71f8a]89        }
[23dc8cb]90    } while (result != img_STOP);
[ac71f8a]91
[23dc8cb]92    img_close(survey);
[ac71f8a]93}
94
[4d34e1f]95static void
96convert_coordinates(vector<Point> & points, const char *inputDatum, const char *outputDatum)
[ac71f8a]97{
[23dc8cb]98    projPJ pj_input, pj_output;
99    if (!(pj_input = pj_init_plus(inputDatum))) {
[4d34e1f]100        fatalerror(/*Failed to initialise input coordinate system “%s”*/287, inputDatum);
[23dc8cb]101    }
102    if (!(pj_output = pj_init_plus(outputDatum))) {
[4d34e1f]103        fatalerror(/*Failed to initialise output coordinate system “%s”*/288, outputDatum);
[23dc8cb]104    }
105
106    for (size_t i=0; i<points.size(); ++i) {
107        pj_transform(pj_input, pj_output, 1, 1, &(points[i].x), &(points[i].y), &(points[i].z));
108    }
[ac71f8a]109}
110
111struct SortPointsByLabel {
[23dc8cb]112    bool operator()(const Point & a, const Point & b)
113    { return a.label < b.label; }
[ac71f8a]114} SortPointsByLabel;
115
[4d34e1f]116static void
117sort_points(vector<Point> & points)
[ac71f8a]118{
[8ec699d]119    sort(points.begin(), points.end(), SortPointsByLabel);
[ac71f8a]120}
121
[4d34e1f]122static void
123write_gpx(const vector<Point> & points, FILE *file)
[ac71f8a]124{
[34b9d54]125    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");
[23dc8cb]126    for (size_t i=0; i<points.size(); ++i) {
127        const Point & pt = points[i];
[48e82bf]128        // %.8f is at worst just over 1mm.
[34b9d54]129        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());
[23dc8cb]130    }
131
[34b9d54]132    fprintf(file, "</gpx>\n");
[ac71f8a]133}
134
135static const struct option long_opts[] = {
[23dc8cb]136    {"datum", required_argument, 0, 'd'},
[56c01a3]137    {"help", no_argument, 0, HLP_HELP},
138    {"version", no_argument, 0, HLP_VERSION},
[23dc8cb]139    {0, 0, 0, 0}
[ac71f8a]140};
141
[375de6a]142static const char *short_opts = "d:";
[ac71f8a]143
[4d34e1f]144static struct help_msg help[] = {
145/*                              <-- */
146   {HLP_ENCODELONG(0),        /*input datum as string to pass to PROJ*/389, 0},
147   {0, 0, 0}
148};
149
[ac71f8a]150int main(int argc, char **argv)
151{
[23dc8cb]152    msg_init(argv);
153
[dcc50a4]154    const char *datum_string = NULL;
[4d34e1f]155    cmdline_set_syntax_message(/*-d PROJ_DATUM 3D_FILE*/388, 0, NULL);
156    cmdline_init(argc, argv, short_opts, long_opts, NULL, help, 1, 1);
[23dc8cb]157    while (1) {
158        int opt = cmdline_getopt();
159        if (opt == EOF) break;
160        else if (opt == 'd') datum_string = optarg;
161    }
[dcc50a4]162
163    if (!datum_string) {
164        cmdline_syntax();
165        exit(1);
166    }
167
[375de6a]168    const char *survey_filename = argv[optind];
[23dc8cb]169
[8ec699d]170    vector<Point> points;
[4d34e1f]171    read_survey(survey_filename, points);
172    convert_coordinates(points, datum_string, WGS84_DATUM_STRING);
173    sort_points(points);
174    write_gpx(points, stdout);
[ac71f8a]175}
Note: See TracBrowser for help on using the repository browser.