source: git/src/gpx.cc @ a72ed95

RELEASE/1.2debug-cidebug-ci-sanitisersstereowalls-data
Last change on this file since a72ed95 was 6d3938b, checked in by Olly Betts <olly@…>, 10 years ago

lib/survex.pot,src/: If the 3d file specifies a coordinate system,
then use it for exporting to formats which need to know (currently
GPX). If the input file doesn't specify, allow the user to enter
one in the export dialog.

  • Property mode set to 100644
File size: 4.7 KB
Line 
1/* gpx.cc
2 * Export from Aven as GPX.
3 */
4/* Copyright (C) 2012 Olaf Kähler
5 * Copyright (C) 2012,2013,2014 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#ifdef HAVE_CONFIG_H
23# include <config.h>
24#endif
25
26#include "gpx.h"
27
28#include "export.h" // For LABELS, etc
29
30#include <stdio.h>
31#include <string>
32#include <time.h>
33#include <math.h>
34
35#include "useful.h"
36#include <proj_api.h>
37
38#include "aven.h"
39#include "message.h"
40
41using namespace std;
42
43#define WGS84_DATUM_STRING "+proj=longlat +ellps=WGS84 +datum=WGS84"
44
45static void
46html_escape(FILE *fh, const char *s)
47{
48    while (*s) {
49        switch (*s) {
50            case '<':
51                fputs("&lt;", fh);
52                break;
53            case '>':
54                fputs("&gt;", fh);
55                break;
56            case '&':
57                fputs("&amp;", fh);
58                break;
59            default:
60                PUTC(*s, fh);
61        }
62        ++s;
63    }
64}
65
66GPX::GPX(const char * input_datum)
67    : pj_input(NULL), pj_output(NULL), in_trkseg(false)
68{
69    if (!(pj_input = pj_init_plus(input_datum))) {
70        wxString m = wmsg(/*Failed to initialise input coordinate system “%s”*/287);
71        m = wxString::Format(m.c_str(), input_datum);
72        throw m;
73    }
74    if (!(pj_output = pj_init_plus(WGS84_DATUM_STRING))) {
75        wxString m = wmsg(/*Failed to initialise output coordinate system “%s”*/288);
76        m = wxString::Format(m.c_str(), WGS84_DATUM_STRING);
77        throw m;
78    }
79}
80
81GPX::~GPX()
82{
83    if (pj_input)
84        pj_free(pj_input);
85    if (pj_output)
86        pj_free(pj_output);
87}
88
89const int *
90GPX::passes() const
91{
92    static const int default_passes[] = { LABELS|ENTS|FIXES|EXPORTS, LEGS|SURF, 0 };
93    return default_passes;
94}
95
96/* Initialise GPX routines. */
97void GPX::header(const char * title, const char *, time_t datestamp_numeric)
98{
99    fputs(
100"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
101"<gpx version=\"1.0\" creator=\""PACKAGE_STRING" (aven) - http://survex.com/\""
102" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""
103" xmlns=\"http://www.topografix.com/GPX/1/0\""
104" xsi:schemaLocation=\"http://www.topografix.com/GPX/1/0"
105" http://www.topografix.com/GPX/1/0/gpx.xsd\">\n", fh);
106    if (title) {
107        fputs("<name>", fh);
108        html_escape(fh, title);
109        fputs("</name>\n", fh);
110    }
111    if (datestamp_numeric != time_t(-1)) {
112        struct tm * tm = gmtime(&datestamp_numeric);
113        if (tm) {
114            char buf[32];
115            if (strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%SZ", tm)) {
116                fputs("<time>", fh);
117                fputs(buf, fh);
118                fputs("</time>\n", fh);
119            }
120        }
121    }
122    // FIXME: optional in GPX, but perhaps useful:
123    // <bounds minlat="..." minlon="..." maxlat="..." maxlon="..." />
124    // NB Not necessarily the same as the bounds in survex coords translated
125    // to WGS84 lat+long...
126}
127
128void
129GPX::line(const img_point *p1, const img_point *p, bool /*fSurface*/, bool fPendingMove)
130{
131    if (fPendingMove) {
132        if (in_trkseg) {
133            fputs("</trkseg><trkseg>\n", fh);
134        } else {
135            fputs("<trk><trkseg>\n", fh);
136            in_trkseg = true;
137        }
138        double X = p1->x, Y = p1->y, Z = p1->z;
139        pj_transform(pj_input, pj_output, 1, 1, &X, &Y, &Z);
140        X = deg(X);
141        Y = deg(Y);
142        // %.8f is at worst just over 1mm.
143        fprintf(fh, "<trkpt lon=\"%.8f\" lat=\"%.8f\"><ele>%.2f</ele></trkpt>\n", X, Y, Z);
144    }
145    double X = p->x, Y = p->y, Z = p->z;
146    pj_transform(pj_input, pj_output, 1, 1, &X, &Y, &Z);
147    X = deg(X);
148    Y = deg(Y);
149    // %.8f is at worst just over 1mm.
150    fprintf(fh, "<trkpt lon=\"%.8f\" lat=\"%.8f\"><ele>%.2f</ele></trkpt>\n", X, Y, Z);
151}
152
153void
154GPX::label(const img_point *p, const char *s, bool /*fSurface*/, int type)
155{
156    double X = p->x, Y = p->y, Z = p->z;
157    pj_transform(pj_input, pj_output, 1, 1, &X, &Y, &Z);
158    X = deg(X);
159    Y = deg(Y);
160    // %.8f is at worst just over 1mm.
161    fprintf(fh, "<wpt lon=\"%.8f\" lat=\"%.8f\"><ele>%.2f</ele><name>", X, Y, Z);
162    html_escape(fh, s);
163    fputs("</name>", fh);
164    // Add a "pin" symbol with colour matching what aven shows.
165    switch (type) {
166        case FIXES:
167            fputs("<sym>Pin, Red</sym>", fh);
168            break;
169        case EXPORTS:
170            fputs("<sym>Pin, Blue</sym>", fh);
171            break;
172        case ENTS:
173            fputs("<sym>Pin, Green</sym>", fh);
174            break;
175    }
176    fputs("</wpt>\n", fh);
177}
178
179void
180GPX::footer()
181{
182    if (in_trkseg)
183        fputs("</trkseg></trk>\n", fh);
184    fputs("</gpx>\n", fh);
185}
Note: See TracBrowser for help on using the repository browser.