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 "EPSG:4326"
46 html_escape(FILE *fh
, const char *s
)
66 static void discarding_proj_logger(void *, int, const char *) { }
68 GPX::GPX(const char * input_datum
)
70 /* Prevent stderr spew from PROJ. */
71 proj_log_func(PJ_DEFAULT_CTX
, nullptr, discarding_proj_logger
);
73 pj
= proj_create_crs_to_crs(PJ_DEFAULT_CTX
,
74 input_datum
, WGS84_DATUM_STRING
,
78 // Normalise the output order so x is longitude and y latitude - by
79 // default new PROJ has them switched for EPSG:4326 which just seems
81 PJ
* pj_norm
= proj_normalize_for_visualization(PJ_DEFAULT_CTX
, pj
);
87 wxString m
= wmsg(/*Failed to initialise input coordinate system “%s”*/287);
88 m
= wxString::Format(m
.c_str(), input_datum
);
97 free((void*)trk_name
);
103 static const int default_passes
[] = { LABELS
|ENTS
|FIXES
|EXPORTS
, LEGS
|SURF
, 0 };
104 return default_passes
;
107 /* Initialise GPX routines. */
108 void GPX::header(const char * title
, const char *, time_t datestamp_numeric
,
109 double, double, double, double, double, double)
112 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
113 "<gpx version=\"1.0\" creator=\"" PACKAGE_STRING
" (aven) - https://survex.com/\""
114 " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""
115 " xmlns=\"http://www.topografix.com/GPX/1/0\""
116 " xsi:schemaLocation=\"http://www.topografix.com/GPX/1/0"
117 " http://www.topografix.com/GPX/1/0/gpx.xsd\">\n", fh
);
120 html_escape(fh
, title
);
121 fputs("</name>\n", fh
);
122 trk_name
= strdup(title
);
124 if (datestamp_numeric
!= time_t(-1)) {
125 struct tm
* tm
= gmtime(&datestamp_numeric
);
128 if (strftime(buf
, sizeof(buf
), "%Y-%m-%dT%H:%M:%SZ", tm
)) {
131 fputs("</time>\n", fh
);
135 // FIXME: optional in GPX, but perhaps useful:
136 // <bounds minlat="..." minlon="..." maxlat="..." maxlon="..." />
137 // NB Not necessarily the same as the bounds in survex coords translated
138 // to WGS84 lat+long...
142 GPX::line(const img_point
*p1
, const img_point
*p
, unsigned /*flags*/, bool fPendingMove
)
146 fputs("</trkseg><trkseg>\n", fh
);
151 html_escape(fh
, trk_name
);
152 fputs("</name>", fh
);
154 fputs("<trkseg>\n", fh
);
157 PJ_COORD coord
= {p1
->x
, p1
->y
, p1
->z
, HUGE_VAL
};
158 coord
= proj_trans(pj
, PJ_FWD
, coord
);
159 if (coord
.xyzt
.x
== HUGE_VAL
||
160 coord
.xyzt
.y
== HUGE_VAL
||
161 coord
.xyzt
.z
== HUGE_VAL
) {
162 // FIXME report errors
164 // %.8f is at worst just over 1mm.
165 fprintf(fh
, "<trkpt lon=\"%.8f\" lat=\"%.8f\"><ele>%.2f</ele></trkpt>\n",
171 PJ_COORD coord
= {p
->x
, p
->y
, p
->z
, HUGE_VAL
};
172 coord
= proj_trans(pj
, PJ_FWD
, coord
);
173 if (coord
.xyzt
.x
== HUGE_VAL
||
174 coord
.xyzt
.y
== HUGE_VAL
||
175 coord
.xyzt
.z
== HUGE_VAL
) {
176 // FIXME report errors
178 // %.8f is at worst just over 1mm.
179 fprintf(fh
, "<trkpt lon=\"%.8f\" lat=\"%.8f\"><ele>%.2f</ele></trkpt>\n",
186 GPX::label(const img_point
*p
, const char *s
, bool /*fSurface*/, int type
)
188 PJ_COORD coord
= {p
->x
, p
->y
, p
->z
, HUGE_VAL
};
189 coord
= proj_trans(pj
, PJ_FWD
, coord
);
190 if (coord
.xyzt
.x
== HUGE_VAL
||
191 coord
.xyzt
.y
== HUGE_VAL
||
192 coord
.xyzt
.z
== HUGE_VAL
) {
193 // FIXME report errors
195 // %.8f is at worst just over 1mm.
196 fprintf(fh
, "<wpt lon=\"%.8f\" lat=\"%.8f\"><ele>%.2f</ele><name>",
201 fputs("</name>", fh
);
202 // Add a "pin" symbol with colour matching what aven shows.
205 fputs("<sym>Pin, Red</sym>", fh
);
208 fputs("<sym>Pin, Blue</sym>", fh
);
211 fputs("<sym>Pin, Green</sym>", fh
);
214 fputs("</wpt>\n", fh
);
221 fputs("</trkseg></trk>\n", fh
);
222 fputs("</gpx>\n", fh
);