2 * Export from Aven as GPX.
4 /* Copyright (C) 2012 Olaf Kähler
5 * Copyright (C) 2012,2013,2014,2015,2016 Olly Betts
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.
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.
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
28 #include "export.h" // For LABELS, etc
43 #define WGS84_DATUM_STRING "+proj=longlat +ellps=WGS84 +datum=WGS84"
46 html_escape(FILE *fh
, const char *s
)
66 GPX::GPX(const char * input_datum
)
67 : pj_input(NULL
), pj_output(NULL
), in_trkseg(false), trk_name(NULL
)
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
);
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
);
87 free((void*)trk_name
);
93 static const int default_passes
[] = { LABELS
|ENTS
|FIXES
|EXPORTS
, LEGS
|SURF
, 0 };
94 return default_passes
;
97 /* Initialise GPX routines. */
98 void GPX::header(const char * title
, const char *, time_t datestamp_numeric
,
99 double, double, double, double, double, double)
102 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
103 "<gpx version=\"1.0\" creator=\"" PACKAGE_STRING
" (aven) - https://survex.com/\""
104 " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""
105 " xmlns=\"http://www.topografix.com/GPX/1/0\""
106 " xsi:schemaLocation=\"http://www.topografix.com/GPX/1/0"
107 " http://www.topografix.com/GPX/1/0/gpx.xsd\">\n", fh
);
110 html_escape(fh
, title
);
111 fputs("</name>\n", fh
);
112 trk_name
= strdup(title
);
114 if (datestamp_numeric
!= time_t(-1)) {
115 struct tm
* tm
= gmtime(&datestamp_numeric
);
118 if (strftime(buf
, sizeof(buf
), "%Y-%m-%dT%H:%M:%SZ", tm
)) {
121 fputs("</time>\n", fh
);
125 // FIXME: optional in GPX, but perhaps useful:
126 // <bounds minlat="..." minlon="..." maxlat="..." maxlon="..." />
127 // NB Not necessarily the same as the bounds in survex coords translated
128 // to WGS84 lat+long...
132 GPX::line(const img_point
*p1
, const img_point
*p
, unsigned /*flags*/, bool fPendingMove
)
136 fputs("</trkseg><trkseg>\n", fh
);
141 html_escape(fh
, trk_name
);
142 fputs("</name>", fh
);
144 fputs("<trkseg>\n", fh
);
147 double X
= p1
->x
, Y
= p1
->y
, Z
= p1
->z
;
148 pj_transform(pj_input
, pj_output
, 1, 1, &X
, &Y
, &Z
);
151 // %.8f is at worst just over 1mm.
152 fprintf(fh
, "<trkpt lon=\"%.8f\" lat=\"%.8f\"><ele>%.2f</ele></trkpt>\n", X
, Y
, Z
);
154 double X
= p
->x
, Y
= p
->y
, Z
= p
->z
;
155 pj_transform(pj_input
, pj_output
, 1, 1, &X
, &Y
, &Z
);
158 // %.8f is at worst just over 1mm.
159 fprintf(fh
, "<trkpt lon=\"%.8f\" lat=\"%.8f\"><ele>%.2f</ele></trkpt>\n", X
, Y
, Z
);
163 GPX::label(const img_point
*p
, const char *s
, bool /*fSurface*/, int type
)
165 double X
= p
->x
, Y
= p
->y
, Z
= p
->z
;
166 pj_transform(pj_input
, pj_output
, 1, 1, &X
, &Y
, &Z
);
169 // %.8f is at worst just over 1mm.
170 fprintf(fh
, "<wpt lon=\"%.8f\" lat=\"%.8f\"><ele>%.2f</ele><name>", X
, Y
, Z
);
172 fputs("</name>", fh
);
173 // Add a "pin" symbol with colour matching what aven shows.
176 fputs("<sym>Pin, Red</sym>", fh
);
179 fputs("<sym>Pin, Blue</sym>", fh
);
182 fputs("<sym>Pin, Green</sym>", fh
);
185 fputs("</wpt>\n", fh
);
192 fputs("</trkseg></trk>\n", fh
);
193 fputs("</gpx>\n", fh
);