2 * Export from Aven as GPX.
4 /* Copyright (C) 2012 Olaf Kähler
5 * Copyright (C) 2012-2024 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
26 #include "export.h" // For LABELS, etc
41 #define WGS84_DATUM_STRING "EPSG:4326"
44 html_escape(FILE *fh
, const char *s
)
64 static void discarding_proj_logger(void *, int, const char *) { }
66 GPX::GPX(const char * input_datum
)
68 /* Prevent stderr spew from PROJ. */
69 proj_log_func(PJ_DEFAULT_CTX
, nullptr, discarding_proj_logger
);
71 pj
= proj_create_crs_to_crs(PJ_DEFAULT_CTX
,
72 input_datum
, WGS84_DATUM_STRING
,
76 // Normalise the output order so x is longitude and y latitude - by
77 // default new PROJ has them switched for EPSG:4326 which just seems
79 PJ
* pj_norm
= proj_normalize_for_visualization(PJ_DEFAULT_CTX
, pj
);
85 wxString m
= wmsg(/*Failed to initialise input coordinate system “%s”*/287);
86 m
= wxString::Format(m
.c_str(), input_datum
);
95 free((void*)trk_name
);
101 static const int default_passes
[] = { LABELS
|ENTS
|FIXES
|EXPORTS
, LEGS
|SURF
, 0 };
102 return default_passes
;
105 /* Initialise GPX routines. */
106 void GPX::header(const char * title
, const char *, time_t datestamp_numeric
,
107 double, double, double, double, double, double)
110 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
111 "<gpx version=\"1.0\" creator=\"" PACKAGE_STRING
" (aven) - https://survex.com/\""
112 " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""
113 " xmlns=\"http://www.topografix.com/GPX/1/0\""
114 " xsi:schemaLocation=\"http://www.topografix.com/GPX/1/0"
115 " http://www.topografix.com/GPX/1/0/gpx.xsd\">\n", fh
);
118 html_escape(fh
, title
);
119 fputs("</name>\n", fh
);
120 trk_name
= strdup(title
);
122 if (datestamp_numeric
!= time_t(-1)) {
123 struct tm
* tm
= gmtime(&datestamp_numeric
);
126 if (strftime(buf
, sizeof(buf
), "%Y-%m-%dT%H:%M:%SZ", tm
)) {
129 fputs("</time>\n", fh
);
133 // FIXME: optional in GPX, but perhaps useful:
134 // <bounds minlat="..." minlon="..." maxlat="..." maxlon="..." />
135 // NB Not necessarily the same as the bounds in survex coords translated
136 // to WGS84 lat+long...
140 GPX::line(const img_point
*p1
, const img_point
*p
, unsigned /*flags*/, bool fPendingMove
)
144 fputs("</trkseg><trkseg>\n", fh
);
149 html_escape(fh
, trk_name
);
150 fputs("</name>", fh
);
152 fputs("<trkseg>\n", fh
);
155 PJ_COORD coord
{{p1
->x
, p1
->y
, p1
->z
, HUGE_VAL
}};
156 coord
= proj_trans(pj
, PJ_FWD
, coord
);
157 if (coord
.xyzt
.x
== HUGE_VAL
||
158 coord
.xyzt
.y
== HUGE_VAL
||
159 coord
.xyzt
.z
== HUGE_VAL
) {
160 // FIXME report errors
162 // %.8f is at worst just over 1mm.
163 fprintf(fh
, "<trkpt lon=\"%.8f\" lat=\"%.8f\"><ele>%.2f</ele></trkpt>\n",
169 PJ_COORD coord
{{p
->x
, p
->y
, p
->z
, HUGE_VAL
}};
170 coord
= proj_trans(pj
, PJ_FWD
, coord
);
171 if (coord
.xyzt
.x
== HUGE_VAL
||
172 coord
.xyzt
.y
== HUGE_VAL
||
173 coord
.xyzt
.z
== HUGE_VAL
) {
174 // FIXME report errors
176 // %.8f is at worst just over 1mm.
177 fprintf(fh
, "<trkpt lon=\"%.8f\" lat=\"%.8f\"><ele>%.2f</ele></trkpt>\n",
184 GPX::label(const img_point
*p
, const wxString
& str
, int /*sflags*/, int type
)
186 const char* s
= str
.utf8_str();
187 PJ_COORD coord
{{p
->x
, p
->y
, p
->z
, HUGE_VAL
}};
188 coord
= proj_trans(pj
, PJ_FWD
, coord
);
189 if (coord
.xyzt
.x
== HUGE_VAL
||
190 coord
.xyzt
.y
== HUGE_VAL
||
191 coord
.xyzt
.z
== HUGE_VAL
) {
192 // FIXME report errors
194 // %.8f is at worst just over 1mm.
195 fprintf(fh
, "<wpt lon=\"%.8f\" lat=\"%.8f\"><ele>%.2f</ele><name>",
200 fputs("</name>", fh
);
201 // Add a "pin" symbol with colour matching what aven shows.
204 fputs("<sym>Pin, Red</sym>", fh
);
207 fputs("<sym>Pin, Blue</sym>", fh
);
210 fputs("<sym>Pin, Green</sym>", fh
);
213 fputs("</wpt>\n", fh
);
220 fputs("</trkseg></trk>\n", fh
);
221 fputs("</gpx>\n", fh
);