source: git/src/kml.cc @ 0fe63d3

RELEASE/1.2debug-cidebug-ci-sanitisersfaster-cavernloglog-selectstereostereo-2025walls-datawalls-data-hanging-as-warningwarn-only-for-hanging-survey
Last change on this file since 0fe63d3 was 0fe63d3, checked in by Olly Betts <olly@…>, 8 years ago

Fix unused parameter warning

  • Property mode set to 100644
File size: 7.8 KB
RevLine 
[1534ed9]1/* kml.cc
2 * Export from Aven as KML.
3 */
4/* Copyright (C) 2012 Olaf Kähler
[f03d89e]5 * Copyright (C) 2012,2013,2014,2015,2016,2017 Olly Betts
[1534ed9]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 "kml.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
65KML::KML(const char * input_datum)
[e63994c]66    : pj_input(NULL), pj_output(NULL), in_linestring(false), in_wall(false)
[1534ed9]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        throw m;
72    }
73    if (!(pj_output = pj_init_plus(WGS84_DATUM_STRING))) {
74        wxString m = wmsg(/*Failed to initialise output coordinate system “%s”*/288);
75        m = wxString::Format(m.c_str(), WGS84_DATUM_STRING);
76        throw m;
77    }
78}
79
80KML::~KML()
81{
82    if (pj_input)
83        pj_free(pj_input);
84    if (pj_output)
85        pj_free(pj_output);
86}
87
88const int *
89KML::passes() const
90{
[f2cb101]91    static const int default_passes[] = {
[e63994c]92        PASG, XSECT, WALL1, WALL2, LEGS|SURF, LABELS|ENTS|FIXES|EXPORTS, 0
[f2cb101]93    };
[1534ed9]94    return default_passes;
95}
96
97/* Initialise KML routines. */
[55a861a]98void KML::header(const char * title, const char *, time_t,
99                 double, double, double, double, double, double)
[1534ed9]100{
101    fputs(
102"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
103"<kml xmlns=\"http://www.opengis.net/kml/2.2\">\n", fh);
104    fputs("<Document><name>", fh);
105    html_escape(fh, title);
106    fputs("</name>\n", fh);
[7aed359]107    // Set up styles for the icons to reduce the file size.
108    fputs("<Style id=\"fix\"><IconStyle>"
[72e6593]109          "<Icon><href>http://maps.google.com/mapfiles/kml/paddle/red-blank.png</href></Icon>"
[7aed359]110          "</IconStyle></Style>\n", fh);
111    fputs("<Style id=\"exp\"><IconStyle>"
[72e6593]112          "<Icon><href>http://maps.google.com/mapfiles/kml/paddle/blu-blank.png</href></Icon>"
[7aed359]113          "</IconStyle></Style>\n", fh);
114    fputs("<Style id=\"ent\"><IconStyle>"
[72e6593]115          "<Icon><href>http://maps.google.com/mapfiles/kml/paddle/grn-blank.png</href></Icon>"
[7aed359]116          "</IconStyle></Style>\n", fh);
[1534ed9]117    // FIXME: does KML allow bounds?
118    // NB Lat+long bounds are not necessarily the same as the bounds in survex
119    // coords translated to WGS84 lat+long...
120}
121
[f03d89e]122void
[0fe63d3]123KML::start_pass(int)
[f03d89e]124{
125    if (in_linestring) {
126        fputs("</coordinates></LineString></MultiGeometry></Placemark>\n", fh);
127        in_linestring = false;
128    }
129}
130
[1534ed9]131void
[a2c29c1]132KML::line(const img_point *p1, const img_point *p, unsigned /*flags*/, bool fPendingMove)
[1534ed9]133{
134    if (fPendingMove) {
[3b23819]135        if (!in_linestring) {
136            in_linestring = true;
137            fputs("<Placemark><MultiGeometry>\n", fh);
138        } else {
139            fputs("</coordinates></LineString>\n", fh);
140        }
141        fputs("<LineString><altitudeMode>absolute</altitudeMode><coordinates>\n", fh);
[1534ed9]142        double X = p1->x, Y = p1->y, Z = p1->z;
143        pj_transform(pj_input, pj_output, 1, 1, &X, &Y, &Z);
144        X = deg(X);
145        Y = deg(Y);
146        // %.8f is at worst just over 1mm.
[ae6a68c]147        fprintf(fh, "%.8f,%.8f,%.2f\n", X, Y, Z);
[1534ed9]148    }
149    double X = p->x, Y = p->y, Z = p->z;
150    pj_transform(pj_input, pj_output, 1, 1, &X, &Y, &Z);
151    X = deg(X);
152    Y = deg(Y);
153    // %.8f is at worst just over 1mm.
[ae6a68c]154    fprintf(fh, "%.8f,%.8f,%.2f\n", X, Y, Z);
[1534ed9]155}
156
[e63994c]157void
158KML::xsect(const img_point *p, double angle, double d1, double d2)
159{
160    double s = sin(rad(angle));
161    double c = cos(rad(angle));
162
163    double x1 = p->x + c * d1;
164    double y1 = p->y + s * d1;
165    double z1 = p->z;
166    pj_transform(pj_input, pj_output, 1, 1, &x1, &y1, &z1);
167    x1 = deg(x1);
168    y1 = deg(y1);
169
170    double x2 = p->x - c * d2;
171    double y2 = p->y - s * d2;
172    double z2 = p->z;
173    pj_transform(pj_input, pj_output, 1, 1, &x2, &y2, &z2);
174    x2 = deg(x2);
175    y2 = deg(y2);
176
177    fputs("<Placemark><name></name><LineString><altitudeMode>absolute</altitudeMode><coordinates>", fh);
[9ada71a]178    fprintf(fh, "%.8f,%.8f,%.2f %.8f,%.8f,%.2f", x1, y1, z1, x2, y2, z2);
[e63994c]179    fputs("</coordinates></LineString></Placemark>\n", fh);
180}
181
182void
183KML::wall(const img_point *p, double angle, double d)
184{
185    double s = sin(rad(angle));
186    double c = cos(rad(angle));
187
188    double x = p->x + c * d;
189    double y = p->y + s * d;
190    double z = p->z;
191    pj_transform(pj_input, pj_output, 1, 1, &x, &y, &z);
192    x = deg(x);
193    y = deg(y);
194
195    if (!in_wall) {
196        fputs("<Placemark><name></name><LineString><altitudeMode>absolute</altitudeMode><coordinates>", fh);
197        in_wall = true;
198    }
[9ada71a]199    fprintf(fh, "%.8f,%.8f,%.2f\n", x, y, z);
[e63994c]200}
201
[f2cb101]202void
203KML::passage(const img_point *p, double angle, double d1, double d2)
204{
205    double s = sin(rad(angle));
206    double c = cos(rad(angle));
207
208    // Draw along one side and push the other onto a stack, then at the end pop
209    // the stack and write out those points to give one polygon, fewer points,
210    // and a smaller file.
211    double x1 = p->x + c * d1;
212    double y1 = p->y + s * d1;
213    double z1 = p->z;
214    pj_transform(pj_input, pj_output, 1, 1, &x1, &y1, &z1);
215    x1 = deg(x1);
216    y1 = deg(y1);
217
218    double x2 = p->x - c * d2;
219    double y2 = p->y - s * d2;
220    double z2 = p->z;
221    pj_transform(pj_input, pj_output, 1, 1, &x2, &y2, &z2);
222    x2 = deg(x2);
223    y2 = deg(y2);
224
225    if (psg.empty()) {
226        fprintf(fh, "<Placemark><name></name><Polygon><altitudeMode>absolute</altitudeMode>"
227                    "<outerBoundaryIs><LinearRing><coordinates>\n");
228    }
229    // NB - order of vertices should be anti-clockwise in a KML file, so go
230    // along the right wall now, and put the left wall points on a stack to
231    // come back along at the end.
[9ada71a]232    fprintf(fh, "%.8f,%.8f,%.2f\n", x2, y2, z2);
[f2cb101]233    psg.push_back(Vector3(x1, y1, z1));
234}
235
236void
237KML::tube_end()
238{
[e63994c]239    if (!psg.empty()) {
240        vector<Vector3>::const_reverse_iterator i;
241        for (i = psg.rbegin(); i != psg.rend(); ++i) {
[9ada71a]242            fprintf(fh, "%.8f,%.8f,%.2f\n", i->GetX(), i->GetY(), i->GetZ());
[e63994c]243        }
244        psg.clear();
245        fputs("</coordinates></LinearRing></outerBoundaryIs>"
246              "</Polygon></Placemark>\n", fh);
247    }
248    if (in_wall) {
249        fputs("</coordinates></LineString></Placemark>\n", fh);
250        in_wall = false;
[f2cb101]251    }
252}
253
[1534ed9]254void
255KML::label(const img_point *p, const char *s, bool /*fSurface*/, int type)
256{
257    double X = p->x, Y = p->y, Z = p->z;
258    pj_transform(pj_input, pj_output, 1, 1, &X, &Y, &Z);
259    X = deg(X);
260    Y = deg(Y);
261    // %.8f is at worst just over 1mm.
262    fprintf(fh, "<Placemark><Point><coordinates>%.8f,%.8f,%.2f</coordinates></Point><name>", X, Y, Z);
263    html_escape(fh, s);
264    fputs("</name>", fh);
265    // Add a "pin" symbol with colour matching what aven shows.
266    switch (type) {
267        case FIXES:
[7aed359]268            fputs("<styleUrl>#fix</styleUrl>", fh);
[1534ed9]269            break;
270        case EXPORTS:
[7aed359]271            fputs("<styleUrl>#exp</styleUrl>", fh);
[1534ed9]272            break;
273        case ENTS:
[7aed359]274            fputs("<styleUrl>#ent</styleUrl>", fh);
[1534ed9]275            break;
276    }
277    fputs("</Placemark>\n", fh);
278}
279
280void
281KML::footer()
282{
[ae6a68c]283    if (in_linestring)
[3b23819]284        fputs("</coordinates></LineString></MultiGeometry></Placemark>\n", fh);
[1534ed9]285    fputs("</Document></kml>\n", fh);
286}
Note: See TracBrowser for help on using the repository browser.