source: git/src/gpx.cc @ e24b7fb

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

src/gpx.cc: Use fputs rather than fprintf for constant strings.

  • Property mode set to 100644
File size: 5.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/* We us the PROJ.4 library to transform coordinates from almost arbitrary
27 * grids into WGS84.  The output is then written as a GPX file ready for use in
28 * your favourite GPS software.
29 *
30 * Example for data given in BMN M31 (Totes Gebirge, Austria):
31 *   +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
32 *
33 * Example for data given in british grid SD (Yorkshire):
34 *   +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
35 *
36 * Example for data given as proper british grid reference:
37 *   +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
38 */
39
40#include "gpx.h"
41
42#include "export.h" // For LABELS, etc
43
44#include <stdio.h>
45#include <string>
46#include <math.h>
47
48#include "useful.h"
49#include <proj_api.h>
50
51#include "aven.h"
52#include "message.h"
53
54using namespace std;
55
56#define WGS84_DATUM_STRING "+proj=longlat +ellps=WGS84 +datum=WGS84"
57
58//   {HLP_ENCODELONG(0),        /*input datum as string to pass to PROJ*/389, 0},
59
60// cmdline_set_syntax_message(/*-d PROJ_DATUM 3D_FILE*/388, 0, NULL);
61static const char * input_datum = "+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";
62
63static void
64html_escape(FILE *fh, const char *s)
65{
66    while (*s) {
67        switch (*s) {
68            case '<':
69                fputs("&lt;", fh);
70                break;
71            case '>':
72                fputs("&gt;", fh);
73                break;
74            case '&':
75                fputs("&amp;", fh);
76                break;
77            default:
78                PUTC(*s, fh);
79        }
80        ++s;
81    }
82}
83
84GPX::GPX()
85    : pj_input(NULL), pj_output(NULL), in_trkseg(false)
86{
87    if (!(pj_input = pj_init_plus(input_datum))) {
88        wxString m = wmsg(/*Failed to initialise input coordinate system “%s”*/287);
89        m = wxString::Format(m.c_str(), input_datum);
90        wxGetApp().ReportError(m);
91        return;
92    }
93    if (!(pj_output = pj_init_plus(WGS84_DATUM_STRING))) {
94        wxString m = wmsg(/*Failed to initialise output coordinate system “%s”*/288);
95        m = wxString::Format(m.c_str(), WGS84_DATUM_STRING);
96        wxGetApp().ReportError(m);
97        return;
98    }
99}
100
101GPX::~GPX()
102{
103    if (pj_input)
104        pj_free(pj_input);
105    if (pj_output)
106        pj_free(pj_output);
107}
108
109const int *
110GPX::passes() const
111{
112    static const int default_passes[] = { LABELS|ENTS|FIXES|EXPORTS, LEGS|SURF, 0 };
113    return default_passes;
114}
115
116/* Initialise GPX routines. */
117void GPX::header(const char * title)
118{
119    fputs(
120"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
121"<gpx version=\"1.0\" creator=\""PACKAGE_STRING" (aven) - http://survex.com/\""
122" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""
123" xmlns=\"http://www.topografix.com/GPX/1/0\""
124" xsi:schemaLocation=\"http://www.topografix.com/GPX/1/0"
125" http://www.topografix.com/GPX/1/0/gpx.xsd\">\n", fh);
126    fputs("<name>", fh);
127    html_escape(fh, title);
128    fputs("</name>\n", fh);
129    // FIXME: optional in GPX, but perhaps useful:
130    // <bounds minlat="..." minlon="..." maxlat="..." maxlon="..." />
131    // NB Not necessarily the same as the bounds in survex coords translated
132    // to WGS85 lat+long...
133}
134
135void
136GPX::line(const img_point *p1, const img_point *p, bool /*fSurface*/, bool fPendingMove)
137{
138    if (fPendingMove) {
139        if (in_trkseg) {
140            fputs("</trkseg><trkseg>\n", fh);
141        } else {
142            fputs("<trk><trkseg>\n", fh);
143            in_trkseg = true;
144        }
145        double X = p1->x, Y = p1->y, Z = p1->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    double X = p->x, Y = p->y, Z = p->z;
153    pj_transform(pj_input, pj_output, 1, 1, &X, &Y, &Z);
154    X = deg(X);
155    Y = deg(Y);
156    // %.8f is at worst just over 1mm.
157    fprintf(fh, "<trkpt lon=\"%.8f\" lat=\"%.8f\"><ele>%.2f</ele></trkpt>\n", X, Y, Z);
158}
159
160void
161GPX::label(const img_point *p, const char *s, bool /*fSurface*/, int type)
162{
163    double X = p->x, Y = p->y, Z = p->z;
164    pj_transform(pj_input, pj_output, 1, 1, &X, &Y, &Z);
165    X = deg(X);
166    Y = deg(Y);
167    // %.8f is at worst just over 1mm.
168    fprintf(fh, "<wpt lon=\"%.8f\" lat=\"%.8f\"><ele>%.2f</ele><name>", X, Y, Z);
169    html_escape(fh, s);
170    fputs("</name>", fh);
171    // Add a "pin" symbol with colour matching what aven shows.
172    switch (type) {
173        case FIXES:
174            fputs("<sym>Pin, Red</sym>", fh);
175            break;
176        case EXPORTS:
177            fputs("<sym>Pin, Blue</sym>", fh);
178            break;
179        case ENTS:
180            fputs("<sym>Pin, Green</sym>", fh);
181            break;
182    }
183    fputs("</wpt>\n", fh);
184}
185
186void
187GPX::footer()
188{
189    if (in_trkseg)
190        fputs("</trkseg></trk>\n", fh);
191    fputs("</gpx>\n", fh);
192}
Note: See TracBrowser for help on using the repository browser.