source: git/src/gpx.cc @ 6a1c384

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

src/gpx.cc: Don't try to write the title if it isn't set or is
empty.

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