1 /*
2
3 gg_wkt.c -- Gaia common support for WKT encoded geometries
4
5 version 5.0, 2020 August 1
6
7 Author: Sandro Furieri a.furieri@lqt.it
8
9 ------------------------------------------------------------------------------
10
11 Version: MPL 1.1/GPL 2.0/LGPL 2.1
12
13 The contents of this file are subject to the Mozilla Public License Version
14 1.1 (the "License"); you may not use this file except in compliance with
15 the License. You may obtain a copy of the License at
16 http://www.mozilla.org/MPL/
17
18 Software distributed under the License is distributed on an "AS IS" basis,
19 WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
20 for the specific language governing rights and limitations under the
21 License.
22
23 The Original Code is the SpatiaLite library
24
25 The Initial Developer of the Original Code is Alessandro Furieri
26
27 Portions created by the Initial Developer are Copyright (C) 2008-2021
28 the Initial Developer. All Rights Reserved.
29
30 Contributor(s):
31 Klaus Foerster klaus.foerster@svg.cc
32
33 Alternatively, the contents of this file may be used under the terms of
34 either the GNU General Public License Version 2 or later (the "GPL"), or
35 the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
36 in which case the provisions of the GPL or the LGPL are applicable instead
37 of those above. If you wish to allow use of your version of this file only
38 under the terms of either the GPL or the LGPL, and not to allow others to
39 use your version of this file under the terms of the MPL, indicate your
40 decision by deleting the provisions above and replace them with the notice
41 and other provisions required by the GPL or the LGPL. If you do not delete
42 the provisions above, a recipient may use your version of this file under
43 the terms of any one of the MPL, the GPL or the LGPL.
44
45 */
46
47 #include <sys/types.h>
48 #include <stdlib.h>
49 #include <stdio.h>
50 #include <string.h>
51
52 #if defined(_WIN32) && !defined(__MINGW32__)
53 #include "config-msvc.h"
54 #else
55 #include "config.h"
56 #endif
57
58 #include <spatialite/sqlite.h>
59
60 #include <spatialite/gaiageo.h>
61
62 static void
gaiaOutClean(char * buffer)63 gaiaOutClean (char *buffer)
64 {
65 /* cleans unneeded trailing zeros */
66 int i;
67 for (i = strlen (buffer) - 1; i > 0; i--)
68 {
69 if (buffer[i] == '0')
70 buffer[i] = '\0';
71 else
72 break;
73 }
74 if (buffer[i] == '.')
75 buffer[i] = '\0';
76 if (strcmp (buffer, "-0") == 0)
77 {
78 /* avoiding to return embarassing NEGATIVE ZEROes */
79 strcpy (buffer, "0");
80 }
81
82 if (strcmp (buffer, "-1.#QNAN") == 0 || strcmp (buffer, "NaN") == 0
83 || strcmp (buffer, "1.#QNAN") == 0
84 || strcmp (buffer, "-1.#IND") == 0 || strcmp (buffer, "1.#IND") == 0)
85 {
86 /* on Windows a NaN could be represented in "odd" ways */
87 /* this is intended to restore a consistent behaviour */
88 strcpy (buffer, "nan");
89 }
90 }
91
92 GAIAGEO_DECLARE void
gaiaOutBufferInitialize(gaiaOutBufferPtr buf)93 gaiaOutBufferInitialize (gaiaOutBufferPtr buf)
94 {
95 /* initializing a dynamically growing output buffer */
96 buf->Buffer = NULL;
97 buf->WriteOffset = 0;
98 buf->BufferSize = 0;
99 buf->Error = 0;
100 }
101
102 GAIAGEO_DECLARE void
gaiaOutBufferReset(gaiaOutBufferPtr buf)103 gaiaOutBufferReset (gaiaOutBufferPtr buf)
104 {
105 /* cleaning a dynamically growing output buffer */
106 if (buf->Buffer)
107 free (buf->Buffer);
108 buf->Buffer = NULL;
109 buf->WriteOffset = 0;
110 buf->BufferSize = 0;
111 buf->Error = 0;
112 }
113
114 GAIAGEO_DECLARE void
gaiaAppendToOutBuffer(gaiaOutBufferPtr buf,const char * text)115 gaiaAppendToOutBuffer (gaiaOutBufferPtr buf, const char *text)
116 {
117 /* appending a text string */
118 int len = strlen (text);
119 int free_size = buf->BufferSize - buf->WriteOffset;
120 if ((len + 1) > free_size)
121 {
122 /* we must allocate a bigger buffer */
123 int new_size;
124 char *new_buf;
125 if (buf->BufferSize == 0)
126 new_size = (len + 1) + 1024;
127 else if (buf->BufferSize <= 4196)
128 new_size = buf->BufferSize + (len + 1) + 4196;
129 else if (buf->BufferSize <= 65536)
130 new_size = buf->BufferSize + (len + 1) + 65536;
131 else
132 new_size = buf->BufferSize + (len + 1) + (1024 * 1024);
133 new_buf = malloc (new_size);
134 if (!new_buf)
135 {
136 buf->Error = 1;
137 return;
138 }
139 memcpy (new_buf, buf->Buffer, buf->WriteOffset);
140 if (buf->Buffer)
141 free (buf->Buffer);
142 buf->Buffer = new_buf;
143 buf->BufferSize = new_size;
144 }
145 strcpy (buf->Buffer + buf->WriteOffset, text);
146 buf->WriteOffset += len;
147 }
148
149 static void
gaiaOutPointStrict(gaiaOutBufferPtr out_buf,gaiaPointPtr point,int precision)150 gaiaOutPointStrict (gaiaOutBufferPtr out_buf, gaiaPointPtr point, int precision)
151 {
152 /* formats a WKT POINT [Strict 2D] */
153 char *buf_x;
154 char *buf_y;
155 char *buf;
156 buf_x = sqlite3_mprintf ("%.*f", precision, point->X);
157 gaiaOutClean (buf_x);
158 buf_y = sqlite3_mprintf ("%.*f", precision, point->Y);
159 gaiaOutClean (buf_y);
160 buf = sqlite3_mprintf ("%s %s", buf_x, buf_y);
161 sqlite3_free (buf_x);
162 sqlite3_free (buf_y);
163 gaiaAppendToOutBuffer (out_buf, buf);
164 sqlite3_free (buf);
165 }
166
167 static void
gaiaOutPoint(gaiaOutBufferPtr out_buf,gaiaPointPtr point,int precision)168 gaiaOutPoint (gaiaOutBufferPtr out_buf, gaiaPointPtr point, int precision)
169 {
170 /* formats a WKT POINT */
171 char *buf_x;
172 char *buf_y;
173 char *buf;
174 if (precision < 0)
175 buf_x = sqlite3_mprintf ("%1.6f", point->X);
176 else
177 buf_x = sqlite3_mprintf ("%.*f", precision, point->X);
178 gaiaOutClean (buf_x);
179 if (precision < 0)
180 buf_y = sqlite3_mprintf ("%1.6f", point->Y);
181 else
182 buf_y = sqlite3_mprintf ("%.*f", precision, point->Y);
183 gaiaOutClean (buf_y);
184 buf = sqlite3_mprintf ("%s %s", buf_x, buf_y);
185 sqlite3_free (buf_x);
186 sqlite3_free (buf_y);
187 gaiaAppendToOutBuffer (out_buf, buf);
188 sqlite3_free (buf);
189 }
190
191 GAIAGEO_DECLARE void
gaiaOutPointZex(gaiaOutBufferPtr out_buf,gaiaPointPtr point,int precision)192 gaiaOutPointZex (gaiaOutBufferPtr out_buf, gaiaPointPtr point, int precision)
193 {
194 /* formats a WKT POINTZ */
195 char *buf_x;
196 char *buf_y;
197 char *buf_z;
198 char *buf;
199 if (precision < 0)
200 buf_x = sqlite3_mprintf ("%1.6f", point->X);
201 else
202 buf_x = sqlite3_mprintf ("%.*f", precision, point->X);
203 gaiaOutClean (buf_x);
204 if (precision < 0)
205 buf_y = sqlite3_mprintf ("%1.6f", point->Y);
206 else
207 buf_y = sqlite3_mprintf ("%.*f", precision, point->Y);
208 gaiaOutClean (buf_y);
209 if (precision < 0)
210 buf_z = sqlite3_mprintf ("%1.6f", point->Z);
211 else
212 buf_z = sqlite3_mprintf ("%.*f", precision, point->Z);
213 gaiaOutClean (buf_z);
214 buf = sqlite3_mprintf ("%s %s %s", buf_x, buf_y, buf_z);
215 sqlite3_free (buf_x);
216 sqlite3_free (buf_y);
217 sqlite3_free (buf_z);
218 gaiaAppendToOutBuffer (out_buf, buf);
219 sqlite3_free (buf);
220 }
221
222 GAIAGEO_DECLARE void
gaiaOutPointZ(gaiaOutBufferPtr out_buf,gaiaPointPtr point)223 gaiaOutPointZ (gaiaOutBufferPtr out_buf, gaiaPointPtr point)
224 {
225 /*
226 * formats a WKT POINTZ
227 * convenience method - default decimal precision
228 */
229 gaiaOutPointZex (out_buf, point, -1);
230 }
231
232 static void
gaiaOutPointM(gaiaOutBufferPtr out_buf,gaiaPointPtr point,int precision)233 gaiaOutPointM (gaiaOutBufferPtr out_buf, gaiaPointPtr point, int precision)
234 {
235 /* formats a WKT POINTM */
236 char *buf_x;
237 char *buf_y;
238 char *buf_m;
239 char *buf;
240 if (precision < 0)
241 buf_x = sqlite3_mprintf ("%1.6f", point->X);
242 else
243 buf_x = sqlite3_mprintf ("%.*f", precision, point->X);
244 gaiaOutClean (buf_x);
245 if (precision < 0)
246 buf_y = sqlite3_mprintf ("%1.6f", point->Y);
247 else
248 buf_y = sqlite3_mprintf ("%.*f", precision, point->Y);
249 gaiaOutClean (buf_y);
250 if (precision < 0)
251 buf_m = sqlite3_mprintf ("%1.6f", point->M);
252 else
253 buf_m = sqlite3_mprintf ("%.*f", precision, point->M);
254 gaiaOutClean (buf_m);
255 buf = sqlite3_mprintf ("%s %s %s", buf_x, buf_y, buf_m);
256 sqlite3_free (buf_x);
257 sqlite3_free (buf_y);
258 sqlite3_free (buf_m);
259 gaiaAppendToOutBuffer (out_buf, buf);
260 sqlite3_free (buf);
261 }
262
263 static void
gaiaOutPointZM(gaiaOutBufferPtr out_buf,gaiaPointPtr point,int precision)264 gaiaOutPointZM (gaiaOutBufferPtr out_buf, gaiaPointPtr point, int precision)
265 {
266 /* formats a WKT POINTZM */
267 char *buf_x;
268 char *buf_y;
269 char *buf_z;
270 char *buf_m;
271 char *buf;
272 if (precision < 0)
273 buf_x = sqlite3_mprintf ("%1.6f", point->X);
274 else
275 buf_x = sqlite3_mprintf ("%.*f", precision, point->X);
276 gaiaOutClean (buf_x);
277 if (precision < 0)
278 buf_y = sqlite3_mprintf ("%1.6f", point->Y);
279 else
280 buf_y = sqlite3_mprintf ("%.*f", precision, point->Y);
281 gaiaOutClean (buf_y);
282 if (precision < 0)
283 buf_z = sqlite3_mprintf ("%1.6f", point->Z);
284 else
285 buf_z = sqlite3_mprintf ("%.*f", precision, point->Z);
286 gaiaOutClean (buf_z);
287 if (precision < 0)
288 buf_m = sqlite3_mprintf ("%1.6f", point->M);
289 else
290 buf_m = sqlite3_mprintf ("%.*f", precision, point->M);
291 gaiaOutClean (buf_m);
292 buf = sqlite3_mprintf ("%s %s %s %s", buf_x, buf_y, buf_z, buf_m);
293 sqlite3_free (buf_x);
294 sqlite3_free (buf_y);
295 sqlite3_free (buf_z);
296 sqlite3_free (buf_m);
297 gaiaAppendToOutBuffer (out_buf, buf);
298 sqlite3_free (buf);
299 }
300
301 static void
gaiaOutEwktPoint(gaiaOutBufferPtr out_buf,gaiaPointPtr point)302 gaiaOutEwktPoint (gaiaOutBufferPtr out_buf, gaiaPointPtr point)
303 {
304 /* formats an EWKT POINT */
305 char *buf_x;
306 char *buf_y;
307 char *buf;
308 buf_x = sqlite3_mprintf ("%1.15f", point->X);
309 gaiaOutClean (buf_x);
310 buf_y = sqlite3_mprintf ("%1.15f", point->Y);
311 gaiaOutClean (buf_y);
312 buf = sqlite3_mprintf ("%s %s", buf_x, buf_y);
313 sqlite3_free (buf_x);
314 sqlite3_free (buf_y);
315 gaiaAppendToOutBuffer (out_buf, buf);
316 sqlite3_free (buf);
317 }
318
319 GAIAGEO_DECLARE void
gaiaOutEwktPointZ(gaiaOutBufferPtr out_buf,gaiaPointPtr point)320 gaiaOutEwktPointZ (gaiaOutBufferPtr out_buf, gaiaPointPtr point)
321 {
322 /* formats an EWKT POINTZ */
323 char *buf_x;
324 char *buf_y;
325 char *buf_z;
326 char *buf;
327 buf_x = sqlite3_mprintf ("%1.15f", point->X);
328 gaiaOutClean (buf_x);
329 buf_y = sqlite3_mprintf ("%1.15f", point->Y);
330 gaiaOutClean (buf_y);
331 buf_z = sqlite3_mprintf ("%1.15f", point->Z);
332 gaiaOutClean (buf_z);
333 buf = sqlite3_mprintf ("%s %s %s", buf_x, buf_y, buf_z);
334 sqlite3_free (buf_x);
335 sqlite3_free (buf_y);
336 sqlite3_free (buf_z);
337 gaiaAppendToOutBuffer (out_buf, buf);
338 sqlite3_free (buf);
339 }
340
341 static void
gaiaOutEwktPointM(gaiaOutBufferPtr out_buf,gaiaPointPtr point)342 gaiaOutEwktPointM (gaiaOutBufferPtr out_buf, gaiaPointPtr point)
343 {
344 /* formats an EWKT POINTM */
345 char *buf_x;
346 char *buf_y;
347 char *buf_m;
348 char *buf;
349 buf_x = sqlite3_mprintf ("%1.15f", point->X);
350 gaiaOutClean (buf_x);
351 buf_y = sqlite3_mprintf ("%1.15f", point->Y);
352 gaiaOutClean (buf_y);
353 buf_m = sqlite3_mprintf ("%1.15f", point->M);
354 gaiaOutClean (buf_m);
355 buf = sqlite3_mprintf ("%s %s %s", buf_x, buf_y, buf_m);
356 sqlite3_free (buf_x);
357 sqlite3_free (buf_y);
358 sqlite3_free (buf_m);
359 gaiaAppendToOutBuffer (out_buf, buf);
360 sqlite3_free (buf);
361 }
362
363 static void
gaiaOutEwktPointZM(gaiaOutBufferPtr out_buf,gaiaPointPtr point)364 gaiaOutEwktPointZM (gaiaOutBufferPtr out_buf, gaiaPointPtr point)
365 {
366 /* formats an EWKT POINTZM */
367 char *buf_x;
368 char *buf_y;
369 char *buf_z;
370 char *buf_m;
371 char *buf;
372 buf_x = sqlite3_mprintf ("%1.15f", point->X);
373 gaiaOutClean (buf_x);
374 buf_y = sqlite3_mprintf ("%1.15f", point->Y);
375 gaiaOutClean (buf_y);
376 buf_z = sqlite3_mprintf ("%1.15f", point->Z);
377 gaiaOutClean (buf_z);
378 buf_m = sqlite3_mprintf ("%1.15f", point->M);
379 gaiaOutClean (buf_m);
380 buf = sqlite3_mprintf ("%s %s %s %s", buf_x, buf_y, buf_z, buf_m);
381 sqlite3_free (buf_x);
382 sqlite3_free (buf_y);
383 sqlite3_free (buf_z);
384 sqlite3_free (buf_m);
385 gaiaAppendToOutBuffer (out_buf, buf);
386 sqlite3_free (buf);
387 }
388
389 static void
gaiaOutLinestringStrict(gaiaOutBufferPtr out_buf,gaiaLinestringPtr line,int precision)390 gaiaOutLinestringStrict (gaiaOutBufferPtr out_buf, gaiaLinestringPtr line,
391 int precision)
392 {
393 /* formats a WKT LINESTRING [Strict 2D] */
394 char *buf_x;
395 char *buf_y;
396 char *buf;
397 double x;
398 double y;
399 double z;
400 double m;
401 int iv;
402 for (iv = 0; iv < line->Points; iv++)
403 {
404 if (line->DimensionModel == GAIA_XY_Z)
405 {
406 gaiaGetPointXYZ (line->Coords, iv, &x, &y, &z);
407 }
408 else if (line->DimensionModel == GAIA_XY_M)
409 {
410 gaiaGetPointXYM (line->Coords, iv, &x, &y, &m);
411 }
412 else if (line->DimensionModel == GAIA_XY_Z_M)
413 {
414 gaiaGetPointXYZM (line->Coords, iv, &x, &y, &z, &m);
415 }
416 else
417 {
418 gaiaGetPoint (line->Coords, iv, &x, &y);
419 }
420 buf_x = sqlite3_mprintf ("%.*f", precision, x);
421 gaiaOutClean (buf_x);
422 buf_y = sqlite3_mprintf ("%.*f", precision, y);
423 gaiaOutClean (buf_y);
424 if (iv > 0)
425 buf = sqlite3_mprintf (",%s %s", buf_x, buf_y);
426 else
427 buf = sqlite3_mprintf ("%s %s", buf_x, buf_y);
428 sqlite3_free (buf_x);
429 sqlite3_free (buf_y);
430 gaiaAppendToOutBuffer (out_buf, buf);
431 sqlite3_free (buf);
432 }
433 }
434
435 static void
gaiaOutLinestring(gaiaOutBufferPtr out_buf,gaiaLinestringPtr line,int precision)436 gaiaOutLinestring (gaiaOutBufferPtr out_buf, gaiaLinestringPtr line,
437 int precision)
438 {
439 /* formats a WKT LINESTRING */
440 char *buf_x;
441 char *buf_y;
442 char *buf;
443 double x;
444 double y;
445 int iv;
446 for (iv = 0; iv < line->Points; iv++)
447 {
448 gaiaGetPoint (line->Coords, iv, &x, &y);
449 if (precision < 0)
450 buf_x = sqlite3_mprintf ("%1.6f", x);
451 else
452 buf_x = sqlite3_mprintf ("%.*f", precision, x);
453 gaiaOutClean (buf_x);
454 if (precision < 0)
455 buf_y = sqlite3_mprintf ("%1.6f", y);
456 else
457 buf_y = sqlite3_mprintf ("%.*f", precision, y);
458 gaiaOutClean (buf_y);
459 if (iv > 0)
460 buf = sqlite3_mprintf (", %s %s", buf_x, buf_y);
461 else
462 buf = sqlite3_mprintf ("%s %s", buf_x, buf_y);
463 sqlite3_free (buf_x);
464 sqlite3_free (buf_y);
465 gaiaAppendToOutBuffer (out_buf, buf);
466 sqlite3_free (buf);
467 }
468 }
469
470 GAIAGEO_DECLARE void
gaiaOutLinestringZex(gaiaOutBufferPtr out_buf,gaiaLinestringPtr line,int precision)471 gaiaOutLinestringZex (gaiaOutBufferPtr out_buf, gaiaLinestringPtr line,
472 int precision)
473 {
474 /* formats a WKT LINESTRINGZ */
475 char *buf_x;
476 char *buf_y;
477 char *buf_z;
478 char *buf;
479 double x;
480 double y;
481 double z;
482 int iv;
483 for (iv = 0; iv < line->Points; iv++)
484 {
485 gaiaGetPointXYZ (line->Coords, iv, &x, &y, &z);
486 if (precision < 0)
487 buf_x = sqlite3_mprintf ("%1.6f", x);
488 else
489 buf_x = sqlite3_mprintf ("%.*f", precision, x);
490 gaiaOutClean (buf_x);
491 if (precision < 0)
492 buf_y = sqlite3_mprintf ("%1.6f", y);
493 else
494 buf_y = sqlite3_mprintf ("%.*f", precision, y);
495 gaiaOutClean (buf_y);
496 if (precision < 0)
497 buf_z = sqlite3_mprintf ("%1.6f", z);
498 else
499 buf_z = sqlite3_mprintf ("%.*f", precision, z);
500 gaiaOutClean (buf_z);
501 if (iv > 0)
502 buf = sqlite3_mprintf (", %s %s %s", buf_x, buf_y, buf_z);
503 else
504 buf = sqlite3_mprintf ("%s %s %s", buf_x, buf_y, buf_z);
505 sqlite3_free (buf_x);
506 sqlite3_free (buf_y);
507 sqlite3_free (buf_z);
508 gaiaAppendToOutBuffer (out_buf, buf);
509 sqlite3_free (buf);
510 }
511 }
512
513 GAIAGEO_DECLARE void
gaiaOutLinestringZ(gaiaOutBufferPtr out_buf,gaiaLinestringPtr line)514 gaiaOutLinestringZ (gaiaOutBufferPtr out_buf, gaiaLinestringPtr line)
515 {
516 /*
517 * formats a WKT LINESTRINGZ
518 * convenience method - default decimal precision
519 */
520 gaiaOutLinestringZex (out_buf, line, -1);
521 }
522
523 static void
gaiaOutLinestringM(gaiaOutBufferPtr out_buf,gaiaLinestringPtr line,int precision)524 gaiaOutLinestringM (gaiaOutBufferPtr out_buf, gaiaLinestringPtr line,
525 int precision)
526 {
527 /* formats a WKT LINESTRINGM */
528 char *buf_x;
529 char *buf_y;
530 char *buf_m;
531 char *buf;
532 double x;
533 double y;
534 double m;
535 int iv;
536 for (iv = 0; iv < line->Points; iv++)
537 {
538 gaiaGetPointXYM (line->Coords, iv, &x, &y, &m);
539 if (precision < 0)
540 buf_x = sqlite3_mprintf ("%1.6f", x);
541 else
542 buf_x = sqlite3_mprintf ("%.*f", precision, x);
543 gaiaOutClean (buf_x);
544 if (precision < 0)
545 buf_y = sqlite3_mprintf ("%1.6f", y);
546 else
547 buf_y = sqlite3_mprintf ("%.*f", precision, y);
548 gaiaOutClean (buf_y);
549 if (precision < 0)
550 buf_m = sqlite3_mprintf ("%1.6f", m);
551 else
552 buf_m = sqlite3_mprintf ("%.*f", precision, m);
553 gaiaOutClean (buf_m);
554 if (iv > 0)
555 buf = sqlite3_mprintf (", %s %s %s", buf_x, buf_y, buf_m);
556 else
557 buf = sqlite3_mprintf ("%s %s %s", buf_x, buf_y, buf_m);
558 sqlite3_free (buf_x);
559 sqlite3_free (buf_y);
560 sqlite3_free (buf_m);
561 gaiaAppendToOutBuffer (out_buf, buf);
562 sqlite3_free (buf);
563 }
564 }
565
566 static void
gaiaOutLinestringZM(gaiaOutBufferPtr out_buf,gaiaLinestringPtr line,int precision)567 gaiaOutLinestringZM (gaiaOutBufferPtr out_buf, gaiaLinestringPtr line,
568 int precision)
569 {
570 /* formats a WKT LINESTRINGZM */
571 char *buf_x;
572 char *buf_y;
573 char *buf_z;
574 char *buf_m;
575 char *buf;
576 double x;
577 double y;
578 double z;
579 double m;
580 int iv;
581 for (iv = 0; iv < line->Points; iv++)
582 {
583 gaiaGetPointXYZM (line->Coords, iv, &x, &y, &z, &m);
584 if (precision < 0)
585 buf_x = sqlite3_mprintf ("%1.6f", x);
586 else
587 buf_x = sqlite3_mprintf ("%.*f", precision, x);
588 gaiaOutClean (buf_x);
589 if (precision < 0)
590 buf_y = sqlite3_mprintf ("%1.6f", y);
591 else
592 buf_y = sqlite3_mprintf ("%.*f", precision, y);
593 gaiaOutClean (buf_y);
594 if (precision < 0)
595 buf_z = sqlite3_mprintf ("%1.6f", z);
596 else
597 buf_z = sqlite3_mprintf ("%.*f", precision, z);
598 gaiaOutClean (buf_z);
599 if (precision < 0)
600 buf_m = sqlite3_mprintf ("%1.6f", m);
601 else
602 buf_m = sqlite3_mprintf ("%.*f", precision, m);
603 gaiaOutClean (buf_m);
604 if (iv > 0)
605 buf =
606 sqlite3_mprintf (", %s %s %s %s", buf_x, buf_y, buf_z, buf_m);
607 else
608 buf = sqlite3_mprintf ("%s %s %s %s", buf_x, buf_y, buf_z, buf_m);
609 sqlite3_free (buf_x);
610 sqlite3_free (buf_y);
611 sqlite3_free (buf_z);
612 sqlite3_free (buf_m);
613 gaiaAppendToOutBuffer (out_buf, buf);
614 sqlite3_free (buf);
615 }
616 }
617
618 static void
gaiaOutEwktLinestring(gaiaOutBufferPtr out_buf,gaiaLinestringPtr line)619 gaiaOutEwktLinestring (gaiaOutBufferPtr out_buf, gaiaLinestringPtr line)
620 {
621 /* formats an EWKT LINESTRING */
622 char *buf_x;
623 char *buf_y;
624 char *buf;
625 double x;
626 double y;
627 int iv;
628 for (iv = 0; iv < line->Points; iv++)
629 {
630 gaiaGetPoint (line->Coords, iv, &x, &y);
631 buf_x = sqlite3_mprintf ("%1.15f", x);
632 gaiaOutClean (buf_x);
633 buf_y = sqlite3_mprintf ("%1.15f", y);
634 gaiaOutClean (buf_y);
635 if (iv > 0)
636 buf = sqlite3_mprintf (",%s %s", buf_x, buf_y);
637 else
638 buf = sqlite3_mprintf ("%s %s", buf_x, buf_y);
639 sqlite3_free (buf_x);
640 sqlite3_free (buf_y);
641 gaiaAppendToOutBuffer (out_buf, buf);
642 sqlite3_free (buf);
643 }
644 }
645
646 GAIAGEO_DECLARE void
gaiaOutEwktLinestringZ(gaiaOutBufferPtr out_buf,gaiaLinestringPtr line)647 gaiaOutEwktLinestringZ (gaiaOutBufferPtr out_buf, gaiaLinestringPtr line)
648 {
649 /* formats an EWKT LINESTRINGZ */
650 char *buf_x;
651 char *buf_y;
652 char *buf_z;
653 char *buf;
654 double x;
655 double y;
656 double z;
657 int iv;
658 for (iv = 0; iv < line->Points; iv++)
659 {
660 gaiaGetPointXYZ (line->Coords, iv, &x, &y, &z);
661 buf_x = sqlite3_mprintf ("%1.15f", x);
662 gaiaOutClean (buf_x);
663 buf_y = sqlite3_mprintf ("%1.15f", y);
664 gaiaOutClean (buf_y);
665 buf_z = sqlite3_mprintf ("%1.15f", z);
666 gaiaOutClean (buf_z);
667 if (iv > 0)
668 buf = sqlite3_mprintf (",%s %s %s", buf_x, buf_y, buf_z);
669 else
670 buf = sqlite3_mprintf ("%s %s %s", buf_x, buf_y, buf_z);
671 sqlite3_free (buf_x);
672 sqlite3_free (buf_y);
673 sqlite3_free (buf_z);
674 gaiaAppendToOutBuffer (out_buf, buf);
675 sqlite3_free (buf);
676 }
677 }
678
679 static void
gaiaOutEwktLinestringM(gaiaOutBufferPtr out_buf,gaiaLinestringPtr line)680 gaiaOutEwktLinestringM (gaiaOutBufferPtr out_buf, gaiaLinestringPtr line)
681 {
682 /* formats an EWKT LINESTRINGM */
683 char *buf_x;
684 char *buf_y;
685 char *buf_m;
686 char *buf;
687 double x;
688 double y;
689 double m;
690 int iv;
691 for (iv = 0; iv < line->Points; iv++)
692 {
693 gaiaGetPointXYM (line->Coords, iv, &x, &y, &m);
694 buf_x = sqlite3_mprintf ("%1.15f", x);
695 gaiaOutClean (buf_x);
696 buf_y = sqlite3_mprintf ("%1.15f", y);
697 gaiaOutClean (buf_y);
698 buf_m = sqlite3_mprintf ("%1.15f", m);
699 gaiaOutClean (buf_m);
700 if (iv > 0)
701 buf = sqlite3_mprintf (",%s %s %s", buf_x, buf_y, buf_m);
702 else
703 buf = sqlite3_mprintf ("%s %s %s", buf_x, buf_y, buf_m);
704 sqlite3_free (buf_x);
705 sqlite3_free (buf_y);
706 sqlite3_free (buf_m);
707 gaiaAppendToOutBuffer (out_buf, buf);
708 sqlite3_free (buf);
709 }
710 }
711
712 static void
gaiaOutEwktLinestringZM(gaiaOutBufferPtr out_buf,gaiaLinestringPtr line)713 gaiaOutEwktLinestringZM (gaiaOutBufferPtr out_buf, gaiaLinestringPtr line)
714 {
715 /* formats an EWKT LINESTRINGZM */
716 char *buf_x;
717 char *buf_y;
718 char *buf_z;
719 char *buf_m;
720 char *buf;
721 double x;
722 double y;
723 double z;
724 double m;
725 int iv;
726 for (iv = 0; iv < line->Points; iv++)
727 {
728 gaiaGetPointXYZM (line->Coords, iv, &x, &y, &z, &m);
729 buf_x = sqlite3_mprintf ("%1.15f", x);
730 gaiaOutClean (buf_x);
731 buf_y = sqlite3_mprintf ("%1.15f", y);
732 gaiaOutClean (buf_y);
733 buf_z = sqlite3_mprintf ("%1.15f", z);
734 gaiaOutClean (buf_z);
735 buf_m = sqlite3_mprintf ("%1.15f", m);
736 gaiaOutClean (buf_m);
737 if (iv > 0)
738 buf =
739 sqlite3_mprintf (",%s %s %s %s", buf_x, buf_y, buf_z, buf_m);
740 else
741 buf = sqlite3_mprintf ("%s %s %s %s", buf_x, buf_y, buf_z, buf_m);
742 sqlite3_free (buf_x);
743 sqlite3_free (buf_y);
744 sqlite3_free (buf_z);
745 sqlite3_free (buf_m);
746 gaiaAppendToOutBuffer (out_buf, buf);
747 sqlite3_free (buf);
748 }
749 }
750
751 static void
gaiaOutPolygonStrict(gaiaOutBufferPtr out_buf,gaiaPolygonPtr polyg,int precision)752 gaiaOutPolygonStrict (gaiaOutBufferPtr out_buf, gaiaPolygonPtr polyg,
753 int precision)
754 {
755 /* formats a WKT POLYGON [Strict 2D] */
756 char *buf_x;
757 char *buf_y;
758 char *buf;
759 int ib;
760 int iv;
761 double x;
762 double y;
763 double z;
764 double m;
765 gaiaRingPtr ring = polyg->Exterior;
766 for (iv = 0; iv < ring->Points; iv++)
767 {
768 if (ring->DimensionModel == GAIA_XY_Z)
769 {
770 gaiaGetPointXYZ (ring->Coords, iv, &x, &y, &z);
771 }
772 else if (ring->DimensionModel == GAIA_XY_M)
773 {
774 gaiaGetPointXYM (ring->Coords, iv, &x, &y, &m);
775 }
776 else if (ring->DimensionModel == GAIA_XY_Z_M)
777 {
778 gaiaGetPointXYZM (ring->Coords, iv, &x, &y, &z, &m);
779 }
780 else
781 {
782 gaiaGetPoint (ring->Coords, iv, &x, &y);
783 }
784 buf_x = sqlite3_mprintf ("%.*f", precision, x);
785 gaiaOutClean (buf_x);
786 buf_y = sqlite3_mprintf ("%.*f", precision, y);
787 gaiaOutClean (buf_y);
788 if (iv == 0)
789 buf = sqlite3_mprintf ("(%s %s", buf_x, buf_y);
790 else if (iv == (ring->Points - 1))
791 buf = sqlite3_mprintf (",%s %s)", buf_x, buf_y);
792 else
793 buf = sqlite3_mprintf (",%s %s", buf_x, buf_y);
794 sqlite3_free (buf_x);
795 sqlite3_free (buf_y);
796 gaiaAppendToOutBuffer (out_buf, buf);
797 sqlite3_free (buf);
798 }
799 for (ib = 0; ib < polyg->NumInteriors; ib++)
800 {
801 ring = polyg->Interiors + ib;
802 for (iv = 0; iv < ring->Points; iv++)
803 {
804 if (ring->DimensionModel == GAIA_XY_Z)
805 {
806 gaiaGetPointXYZ (ring->Coords, iv, &x, &y, &z);
807 }
808 else if (ring->DimensionModel == GAIA_XY_M)
809 {
810 gaiaGetPointXYM (ring->Coords, iv, &x, &y, &m);
811 }
812 else if (ring->DimensionModel == GAIA_XY_Z_M)
813 {
814 gaiaGetPointXYZM (ring->Coords, iv, &x, &y, &z, &m);
815 }
816 else
817 {
818 gaiaGetPoint (ring->Coords, iv, &x, &y);
819 }
820 buf_x = sqlite3_mprintf ("%.*f", precision, x);
821 gaiaOutClean (buf_x);
822 buf_y = sqlite3_mprintf ("%.*f", precision, y);
823 gaiaOutClean (buf_y);
824 if (iv == 0)
825 buf = sqlite3_mprintf (",(%s %s", buf_x, buf_y);
826 else if (iv == (ring->Points - 1))
827 buf = sqlite3_mprintf (",%s %s)", buf_x, buf_y);
828 else
829 buf = sqlite3_mprintf (",%s %s", buf_x, buf_y);
830 sqlite3_free (buf_x);
831 sqlite3_free (buf_y);
832 gaiaAppendToOutBuffer (out_buf, buf);
833 sqlite3_free (buf);
834 }
835 }
836 }
837
838 static void
gaiaOutPolygon(gaiaOutBufferPtr out_buf,gaiaPolygonPtr polyg,int precision)839 gaiaOutPolygon (gaiaOutBufferPtr out_buf, gaiaPolygonPtr polyg, int precision)
840 {
841 /* formats a WKT POLYGON */
842 char *buf_x;
843 char *buf_y;
844 char *buf;
845 int ib;
846 int iv;
847 double x;
848 double y;
849 gaiaRingPtr ring = polyg->Exterior;
850 for (iv = 0; iv < ring->Points; iv++)
851 {
852 gaiaGetPoint (ring->Coords, iv, &x, &y);
853 if (precision < 0)
854 buf_x = sqlite3_mprintf ("%1.6f", x);
855 else
856 buf_x = sqlite3_mprintf ("%.*f", precision, x);
857 gaiaOutClean (buf_x);
858 if (precision < 0)
859 buf_y = sqlite3_mprintf ("%1.6f", y);
860 else
861 buf_y = sqlite3_mprintf ("%.*f", precision, y);
862 gaiaOutClean (buf_y);
863 if (iv == 0)
864 buf = sqlite3_mprintf ("(%s %s", buf_x, buf_y);
865 else if (iv == (ring->Points - 1))
866 buf = sqlite3_mprintf (", %s %s)", buf_x, buf_y);
867 else
868 buf = sqlite3_mprintf (", %s %s", buf_x, buf_y);
869 sqlite3_free (buf_x);
870 sqlite3_free (buf_y);
871 gaiaAppendToOutBuffer (out_buf, buf);
872 sqlite3_free (buf);
873 }
874 for (ib = 0; ib < polyg->NumInteriors; ib++)
875 {
876 ring = polyg->Interiors + ib;
877 for (iv = 0; iv < ring->Points; iv++)
878 {
879 gaiaGetPoint (ring->Coords, iv, &x, &y);
880 if (precision < 0)
881 buf_x = sqlite3_mprintf ("%1.6f", x);
882 else
883 buf_x = sqlite3_mprintf ("%.*f", precision, x);
884 gaiaOutClean (buf_x);
885 if (precision < 0)
886 buf_y = sqlite3_mprintf ("%1.6f", y);
887 else
888 buf_y = sqlite3_mprintf ("%.*f", precision, y);
889 gaiaOutClean (buf_y);
890 if (iv == 0)
891 buf = sqlite3_mprintf (", (%s %s", buf_x, buf_y);
892 else if (iv == (ring->Points - 1))
893 buf = sqlite3_mprintf (", %s %s)", buf_x, buf_y);
894 else
895 buf = sqlite3_mprintf (", %s %s", buf_x, buf_y);
896 sqlite3_free (buf_x);
897 sqlite3_free (buf_y);
898 gaiaAppendToOutBuffer (out_buf, buf);
899 sqlite3_free (buf);
900 }
901 }
902 }
903
904 GAIAGEO_DECLARE void
gaiaOutPolygonZex(gaiaOutBufferPtr out_buf,gaiaPolygonPtr polyg,int precision)905 gaiaOutPolygonZex (gaiaOutBufferPtr out_buf, gaiaPolygonPtr polyg,
906 int precision)
907 {
908 /* formats a WKT POLYGONZ */
909 char *buf_x;
910 char *buf_y;
911 char *buf_z;
912 char *buf;
913 int ib;
914 int iv;
915 double x;
916 double y;
917 double z;
918 gaiaRingPtr ring = polyg->Exterior;
919 for (iv = 0; iv < ring->Points; iv++)
920 {
921 gaiaGetPointXYZ (ring->Coords, iv, &x, &y, &z);
922 if (precision < 0)
923 buf_x = sqlite3_mprintf ("%1.6f", x);
924 else
925 buf_x = sqlite3_mprintf ("%.*f", precision, x);
926 gaiaOutClean (buf_x);
927 if (precision < 0)
928 buf_y = sqlite3_mprintf ("%1.6f", y);
929 else
930 buf_y = sqlite3_mprintf ("%.*f", precision, y);
931 gaiaOutClean (buf_y);
932 if (precision < 0)
933 buf_z = sqlite3_mprintf ("%1.6f", z);
934 else
935 buf_z = sqlite3_mprintf ("%.*f", precision, z);
936 gaiaOutClean (buf_z);
937 if (iv == 0)
938 buf = sqlite3_mprintf ("(%s %s %s", buf_x, buf_y, buf_z);
939 else if (iv == (ring->Points - 1))
940 buf = sqlite3_mprintf (", %s %s %s)", buf_x, buf_y, buf_z);
941 else
942 buf = sqlite3_mprintf (", %s %s %s", buf_x, buf_y, buf_z);
943 sqlite3_free (buf_x);
944 sqlite3_free (buf_y);
945 sqlite3_free (buf_z);
946 gaiaAppendToOutBuffer (out_buf, buf);
947 sqlite3_free (buf);
948 }
949 for (ib = 0; ib < polyg->NumInteriors; ib++)
950 {
951 ring = polyg->Interiors + ib;
952 for (iv = 0; iv < ring->Points; iv++)
953 {
954 gaiaGetPointXYZ (ring->Coords, iv, &x, &y, &z);
955 if (precision < 0)
956 buf_x = sqlite3_mprintf ("%1.6f", x);
957 else
958 buf_x = sqlite3_mprintf ("%.*f", precision, x);
959 gaiaOutClean (buf_x);
960 if (precision < 0)
961 buf_y = sqlite3_mprintf ("%1.6f", y);
962 else
963 buf_y = sqlite3_mprintf ("%.*f", precision, y);
964 gaiaOutClean (buf_y);
965 if (precision < 0)
966 buf_z = sqlite3_mprintf ("%1.6f", z);
967 else
968 buf_z = sqlite3_mprintf ("%.*f", precision, z);
969 gaiaOutClean (buf_z);
970 if (iv == 0)
971 buf = sqlite3_mprintf (", (%s %s %s", buf_x, buf_y, buf_z);
972 else if (iv == (ring->Points - 1))
973 buf = sqlite3_mprintf (", %s %s %s)", buf_x, buf_y, buf_z);
974 else
975 buf = sqlite3_mprintf (", %s %s %s", buf_x, buf_y, buf_z);
976 sqlite3_free (buf_x);
977 sqlite3_free (buf_y);
978 sqlite3_free (buf_z);
979 gaiaAppendToOutBuffer (out_buf, buf);
980 sqlite3_free (buf);
981 }
982 }
983 }
984
985 GAIAGEO_DECLARE void
gaiaOutPolygonZ(gaiaOutBufferPtr out_buf,gaiaPolygonPtr polyg)986 gaiaOutPolygonZ (gaiaOutBufferPtr out_buf, gaiaPolygonPtr polyg)
987 {
988 /*
989 * formats a WKT POLYGONZ
990 * convenience method - default decimal precision
991 */
992 gaiaOutPolygonZex (out_buf, polyg, -1);
993 }
994
995 static void
gaiaOutPolygonM(gaiaOutBufferPtr out_buf,gaiaPolygonPtr polyg,int precision)996 gaiaOutPolygonM (gaiaOutBufferPtr out_buf, gaiaPolygonPtr polyg, int precision)
997 {
998 /* formats a WKT POLYGONM */
999 char *buf_x;
1000 char *buf_y;
1001 char *buf_m;
1002 char *buf;
1003 int ib;
1004 int iv;
1005 double x;
1006 double y;
1007 double m;
1008 gaiaRingPtr ring = polyg->Exterior;
1009 for (iv = 0; iv < ring->Points; iv++)
1010 {
1011 gaiaGetPointXYM (ring->Coords, iv, &x, &y, &m);
1012 if (precision < 0)
1013 buf_x = sqlite3_mprintf ("%1.6f", x);
1014 else
1015 buf_x = sqlite3_mprintf ("%.*f", precision, x);
1016 gaiaOutClean (buf_x);
1017 if (precision < 0)
1018 buf_y = sqlite3_mprintf ("%1.6f", y);
1019 else
1020 buf_y = sqlite3_mprintf ("%.*f", precision, y);
1021 gaiaOutClean (buf_y);
1022 if (precision < 0)
1023 buf_m = sqlite3_mprintf ("%1.6f", m);
1024 else
1025 buf_m = sqlite3_mprintf ("%.*f", precision, m);
1026 gaiaOutClean (buf_m);
1027 if (iv == 0)
1028 buf = sqlite3_mprintf ("(%s %s %s", buf_x, buf_y, buf_m);
1029 else if (iv == (ring->Points - 1))
1030 buf = sqlite3_mprintf (", %s %s %s)", buf_x, buf_y, buf_m);
1031 else
1032 buf = sqlite3_mprintf (", %s %s %s", buf_x, buf_y, buf_m);
1033 sqlite3_free (buf_x);
1034 sqlite3_free (buf_y);
1035 sqlite3_free (buf_m);
1036 gaiaAppendToOutBuffer (out_buf, buf);
1037 sqlite3_free (buf);
1038 }
1039 for (ib = 0; ib < polyg->NumInteriors; ib++)
1040 {
1041 ring = polyg->Interiors + ib;
1042 for (iv = 0; iv < ring->Points; iv++)
1043 {
1044 gaiaGetPointXYM (ring->Coords, iv, &x, &y, &m);
1045 if (precision < 0)
1046 buf_x = sqlite3_mprintf ("%1.6f", x);
1047 else
1048 buf_x = sqlite3_mprintf ("%.*f", precision, x);
1049 gaiaOutClean (buf_x);
1050 if (precision < 0)
1051 buf_y = sqlite3_mprintf ("%1.6f", y);
1052 else
1053 buf_y = sqlite3_mprintf ("%.*f", precision, y);
1054 gaiaOutClean (buf_y);
1055 if (precision < 0)
1056 buf_m = sqlite3_mprintf ("%1.6f", m);
1057 else
1058 buf_m = sqlite3_mprintf ("%.*f", precision, m);
1059 gaiaOutClean (buf_m);
1060 if (iv == 0)
1061 buf = sqlite3_mprintf (", (%s %s %s", buf_x, buf_y, buf_m);
1062 else if (iv == (ring->Points - 1))
1063 buf = sqlite3_mprintf (", %s %s %s)", buf_x, buf_y, buf_m);
1064 else
1065 buf = sqlite3_mprintf (", %s %s %s", buf_x, buf_y, buf_m);
1066 sqlite3_free (buf_x);
1067 sqlite3_free (buf_y);
1068 sqlite3_free (buf_m);
1069 gaiaAppendToOutBuffer (out_buf, buf);
1070 sqlite3_free (buf);
1071 }
1072 }
1073 }
1074
1075 static void
gaiaOutPolygonZM(gaiaOutBufferPtr out_buf,gaiaPolygonPtr polyg,int precision)1076 gaiaOutPolygonZM (gaiaOutBufferPtr out_buf, gaiaPolygonPtr polyg, int precision)
1077 {
1078 /* formats a WKT POLYGONZM */
1079 char *buf_x;
1080 char *buf_y;
1081 char *buf_z;
1082 char *buf_m;
1083 char *buf;
1084 int ib;
1085 int iv;
1086 double x;
1087 double y;
1088 double z;
1089 double m;
1090 gaiaRingPtr ring = polyg->Exterior;
1091 for (iv = 0; iv < ring->Points; iv++)
1092 {
1093 gaiaGetPointXYZM (ring->Coords, iv, &x, &y, &z, &m);
1094 if (precision < 0)
1095 buf_x = sqlite3_mprintf ("%1.6f", x);
1096 else
1097 buf_x = sqlite3_mprintf ("%.*f", precision, x);
1098 gaiaOutClean (buf_x);
1099 if (precision < 0)
1100 buf_y = sqlite3_mprintf ("%1.6f", y);
1101 else
1102 buf_y = sqlite3_mprintf ("%.*f", precision, y);
1103 gaiaOutClean (buf_y);
1104 if (precision < 0)
1105 buf_z = sqlite3_mprintf ("%1.6f", z);
1106 else
1107 buf_z = sqlite3_mprintf ("%.*f", precision, z);
1108 gaiaOutClean (buf_z);
1109 if (precision < 0)
1110 buf_m = sqlite3_mprintf ("%1.6f", m);
1111 else
1112 buf_m = sqlite3_mprintf ("%.*f", precision, m);
1113 gaiaOutClean (buf_m);
1114 if (iv == 0)
1115 buf =
1116 sqlite3_mprintf ("(%s %s %s %s", buf_x, buf_y, buf_z, buf_m);
1117 else if (iv == (ring->Points - 1))
1118 buf =
1119 sqlite3_mprintf (", %s %s %s %s)", buf_x, buf_y, buf_z,
1120 buf_m);
1121 else
1122 buf =
1123 sqlite3_mprintf (", %s %s %s %s", buf_x, buf_y, buf_z, buf_m);
1124 sqlite3_free (buf_x);
1125 sqlite3_free (buf_y);
1126 sqlite3_free (buf_z);
1127 sqlite3_free (buf_m);
1128 gaiaAppendToOutBuffer (out_buf, buf);
1129 sqlite3_free (buf);
1130 }
1131 for (ib = 0; ib < polyg->NumInteriors; ib++)
1132 {
1133 ring = polyg->Interiors + ib;
1134 for (iv = 0; iv < ring->Points; iv++)
1135 {
1136 gaiaGetPointXYZM (ring->Coords, iv, &x, &y, &z, &m);
1137 if (precision < 0)
1138 buf_x = sqlite3_mprintf ("%1.6f", x);
1139 else
1140 buf_x = sqlite3_mprintf ("%.*f", precision, x);
1141 gaiaOutClean (buf_x);
1142 if (precision < 0)
1143 buf_y = sqlite3_mprintf ("%1.6f", y);
1144 else
1145 buf_y = sqlite3_mprintf ("%.*f", precision, y);
1146 gaiaOutClean (buf_y);
1147 if (precision < 0)
1148 buf_z = sqlite3_mprintf ("%1.6f", z);
1149 else
1150 buf_z = sqlite3_mprintf ("%.*f", precision, z);
1151 gaiaOutClean (buf_z);
1152 if (precision < 0)
1153 buf_m = sqlite3_mprintf ("%1.6f", m);
1154 else
1155 buf_m = sqlite3_mprintf ("%.*f", precision, m);
1156 gaiaOutClean (buf_m);
1157 if (iv == 0)
1158 buf =
1159 sqlite3_mprintf (", (%s %s %s %s", buf_x, buf_y, buf_z,
1160 buf_m);
1161 else if (iv == (ring->Points - 1))
1162 buf =
1163 sqlite3_mprintf (", %s %s %s %s)", buf_x, buf_y, buf_z,
1164 buf_m);
1165 else
1166 buf =
1167 sqlite3_mprintf (", %s %s %s %s", buf_x, buf_y, buf_z,
1168 buf_m);
1169 sqlite3_free (buf_x);
1170 sqlite3_free (buf_y);
1171 sqlite3_free (buf_z);
1172 sqlite3_free (buf_m);
1173 gaiaAppendToOutBuffer (out_buf, buf);
1174 sqlite3_free (buf);
1175 }
1176 }
1177 }
1178
1179 static void
gaiaOutEwktPolygon(gaiaOutBufferPtr out_buf,gaiaPolygonPtr polyg)1180 gaiaOutEwktPolygon (gaiaOutBufferPtr out_buf, gaiaPolygonPtr polyg)
1181 {
1182 /* formats an EWKT POLYGON */
1183 char *buf_x;
1184 char *buf_y;
1185 char *buf;
1186 int ib;
1187 int iv;
1188 double x;
1189 double y;
1190 gaiaRingPtr ring = polyg->Exterior;
1191 for (iv = 0; iv < ring->Points; iv++)
1192 {
1193 gaiaGetPoint (ring->Coords, iv, &x, &y);
1194 buf_x = sqlite3_mprintf ("%1.15f", x);
1195 gaiaOutClean (buf_x);
1196 buf_y = sqlite3_mprintf ("%1.15f", y);
1197 gaiaOutClean (buf_y);
1198 if (iv == 0)
1199 buf = sqlite3_mprintf ("(%s %s", buf_x, buf_y);
1200 else if (iv == (ring->Points - 1))
1201 buf = sqlite3_mprintf (",%s %s)", buf_x, buf_y);
1202 else
1203 buf = sqlite3_mprintf (",%s %s", buf_x, buf_y);
1204 sqlite3_free (buf_x);
1205 sqlite3_free (buf_y);
1206 gaiaAppendToOutBuffer (out_buf, buf);
1207 sqlite3_free (buf);
1208 }
1209 for (ib = 0; ib < polyg->NumInteriors; ib++)
1210 {
1211 ring = polyg->Interiors + ib;
1212 for (iv = 0; iv < ring->Points; iv++)
1213 {
1214 gaiaGetPoint (ring->Coords, iv, &x, &y);
1215 buf_x = sqlite3_mprintf ("%1.15f", x);
1216 gaiaOutClean (buf_x);
1217 buf_y = sqlite3_mprintf ("%1.15f", y);
1218 gaiaOutClean (buf_y);
1219 if (iv == 0)
1220 buf = sqlite3_mprintf (",(%s %s", buf_x, buf_y);
1221 else if (iv == (ring->Points - 1))
1222 buf = sqlite3_mprintf (",%s %s)", buf_x, buf_y);
1223 else
1224 buf = sqlite3_mprintf (",%s %s", buf_x, buf_y);
1225 sqlite3_free (buf_x);
1226 sqlite3_free (buf_y);
1227 gaiaAppendToOutBuffer (out_buf, buf);
1228 sqlite3_free (buf);
1229 }
1230 }
1231 }
1232
1233 GAIAGEO_DECLARE void
gaiaOutEwktPolygonZ(gaiaOutBufferPtr out_buf,gaiaPolygonPtr polyg)1234 gaiaOutEwktPolygonZ (gaiaOutBufferPtr out_buf, gaiaPolygonPtr polyg)
1235 {
1236 /* formats an EWKT POLYGONZ */
1237 char *buf_x;
1238 char *buf_y;
1239 char *buf_z;
1240 char *buf;
1241 int ib;
1242 int iv;
1243 double x;
1244 double y;
1245 double z;
1246 gaiaRingPtr ring = polyg->Exterior;
1247 for (iv = 0; iv < ring->Points; iv++)
1248 {
1249 gaiaGetPointXYZ (ring->Coords, iv, &x, &y, &z);
1250 buf_x = sqlite3_mprintf ("%1.15f", x);
1251 gaiaOutClean (buf_x);
1252 buf_y = sqlite3_mprintf ("%1.15f", y);
1253 gaiaOutClean (buf_y);
1254 buf_z = sqlite3_mprintf ("%1.15f", z);
1255 gaiaOutClean (buf_z);
1256 if (iv == 0)
1257 buf = sqlite3_mprintf ("(%s %s %s", buf_x, buf_y, buf_z);
1258 else if (iv == (ring->Points - 1))
1259 buf = sqlite3_mprintf (",%s %s %s)", buf_x, buf_y, buf_z);
1260 else
1261 buf = sqlite3_mprintf (",%s %s %s", buf_x, buf_y, buf_z);
1262 sqlite3_free (buf_x);
1263 sqlite3_free (buf_y);
1264 sqlite3_free (buf_z);
1265 gaiaAppendToOutBuffer (out_buf, buf);
1266 sqlite3_free (buf);
1267 }
1268 for (ib = 0; ib < polyg->NumInteriors; ib++)
1269 {
1270 ring = polyg->Interiors + ib;
1271 for (iv = 0; iv < ring->Points; iv++)
1272 {
1273 gaiaGetPointXYZ (ring->Coords, iv, &x, &y, &z);
1274 buf_x = sqlite3_mprintf ("%1.15f", x);
1275 gaiaOutClean (buf_x);
1276 buf_y = sqlite3_mprintf ("%1.15f", y);
1277 gaiaOutClean (buf_y);
1278 buf_z = sqlite3_mprintf ("%1.15f", z);
1279 gaiaOutClean (buf_z);
1280 if (iv == 0)
1281 buf = sqlite3_mprintf (",(%s %s %s", buf_x, buf_y, buf_z);
1282 else if (iv == (ring->Points - 1))
1283 buf = sqlite3_mprintf (",%s %s %s)", buf_x, buf_y, buf_z);
1284 else
1285 buf = sqlite3_mprintf (",%s %s %s", buf_x, buf_y, buf_z);
1286 sqlite3_free (buf_x);
1287 sqlite3_free (buf_y);
1288 sqlite3_free (buf_z);
1289 gaiaAppendToOutBuffer (out_buf, buf);
1290 sqlite3_free (buf);
1291 }
1292 }
1293 }
1294
1295 static void
gaiaOutEwktPolygonM(gaiaOutBufferPtr out_buf,gaiaPolygonPtr polyg)1296 gaiaOutEwktPolygonM (gaiaOutBufferPtr out_buf, gaiaPolygonPtr polyg)
1297 {
1298 /* formats an EWKT POLYGONM */
1299 char *buf_x;
1300 char *buf_y;
1301 char *buf_m;
1302 char *buf;
1303 int ib;
1304 int iv;
1305 double x;
1306 double y;
1307 double m;
1308 gaiaRingPtr ring = polyg->Exterior;
1309 for (iv = 0; iv < ring->Points; iv++)
1310 {
1311 gaiaGetPointXYM (ring->Coords, iv, &x, &y, &m);
1312 buf_x = sqlite3_mprintf ("%1.15f", x);
1313 gaiaOutClean (buf_x);
1314 buf_y = sqlite3_mprintf ("%1.15f", y);
1315 gaiaOutClean (buf_y);
1316 buf_m = sqlite3_mprintf ("%1.15f", m);
1317 gaiaOutClean (buf_m);
1318 if (iv == 0)
1319 buf = sqlite3_mprintf ("(%s %s %s", buf_x, buf_y, buf_m);
1320 else if (iv == (ring->Points - 1))
1321 buf = sqlite3_mprintf (",%s %s %s)", buf_x, buf_y, buf_m);
1322 else
1323 buf = sqlite3_mprintf (",%s %s %s", buf_x, buf_y, buf_m);
1324 sqlite3_free (buf_x);
1325 sqlite3_free (buf_y);
1326 sqlite3_free (buf_m);
1327 gaiaAppendToOutBuffer (out_buf, buf);
1328 sqlite3_free (buf);
1329 }
1330 for (ib = 0; ib < polyg->NumInteriors; ib++)
1331 {
1332 ring = polyg->Interiors + ib;
1333 for (iv = 0; iv < ring->Points; iv++)
1334 {
1335 gaiaGetPointXYM (ring->Coords, iv, &x, &y, &m);
1336 buf_x = sqlite3_mprintf ("%1.15f", x);
1337 gaiaOutClean (buf_x);
1338 buf_y = sqlite3_mprintf ("%1.15f", y);
1339 gaiaOutClean (buf_y);
1340 buf_m = sqlite3_mprintf ("%1.15f", m);
1341 gaiaOutClean (buf_m);
1342 if (iv == 0)
1343 buf = sqlite3_mprintf (",(%s %s %s", buf_x, buf_y, buf_m);
1344 else if (iv == (ring->Points - 1))
1345 buf = sqlite3_mprintf (",%s %s %s)", buf_x, buf_y, buf_m);
1346 else
1347 buf = sqlite3_mprintf (",%s %s %s", buf_x, buf_y, buf_m);
1348 sqlite3_free (buf_x);
1349 sqlite3_free (buf_y);
1350 sqlite3_free (buf_m);
1351 gaiaAppendToOutBuffer (out_buf, buf);
1352 sqlite3_free (buf);
1353 }
1354 }
1355 }
1356
1357 static void
gaiaOutEwktPolygonZM(gaiaOutBufferPtr out_buf,gaiaPolygonPtr polyg)1358 gaiaOutEwktPolygonZM (gaiaOutBufferPtr out_buf, gaiaPolygonPtr polyg)
1359 {
1360 /* formats an EWKT POLYGONZM */
1361 char *buf_x;
1362 char *buf_y;
1363 char *buf_z;
1364 char *buf_m;
1365 char *buf;
1366 int ib;
1367 int iv;
1368 double x;
1369 double y;
1370 double z;
1371 double m;
1372 gaiaRingPtr ring = polyg->Exterior;
1373 for (iv = 0; iv < ring->Points; iv++)
1374 {
1375 gaiaGetPointXYZM (ring->Coords, iv, &x, &y, &z, &m);
1376 buf_x = sqlite3_mprintf ("%1.15f", x);
1377 gaiaOutClean (buf_x);
1378 buf_y = sqlite3_mprintf ("%1.15f", y);
1379 gaiaOutClean (buf_y);
1380 buf_z = sqlite3_mprintf ("%1.15f", z);
1381 gaiaOutClean (buf_z);
1382 buf_m = sqlite3_mprintf ("%1.15f", m);
1383 gaiaOutClean (buf_m);
1384 if (iv == 0)
1385 buf =
1386 sqlite3_mprintf ("(%s %s %s %s", buf_x, buf_y, buf_z, buf_m);
1387 else if (iv == (ring->Points - 1))
1388 buf =
1389 sqlite3_mprintf (",%s %s %s %s)", buf_x, buf_y, buf_z, buf_m);
1390 else
1391 buf =
1392 sqlite3_mprintf (",%s %s %s %s", buf_x, buf_y, buf_z, buf_m);
1393 sqlite3_free (buf_x);
1394 sqlite3_free (buf_y);
1395 sqlite3_free (buf_z);
1396 sqlite3_free (buf_m);
1397 gaiaAppendToOutBuffer (out_buf, buf);
1398 sqlite3_free (buf);
1399 }
1400 for (ib = 0; ib < polyg->NumInteriors; ib++)
1401 {
1402 ring = polyg->Interiors + ib;
1403 for (iv = 0; iv < ring->Points; iv++)
1404 {
1405 gaiaGetPointXYZM (ring->Coords, iv, &x, &y, &z, &m);
1406 buf_x = sqlite3_mprintf ("%1.15f", x);
1407 gaiaOutClean (buf_x);
1408 buf_y = sqlite3_mprintf ("%1.15f", y);
1409 gaiaOutClean (buf_y);
1410 buf_z = sqlite3_mprintf ("%1.15f", z);
1411 gaiaOutClean (buf_z);
1412 buf_m = sqlite3_mprintf ("%1.15f", m);
1413 gaiaOutClean (buf_m);
1414 if (iv == 0)
1415 buf =
1416 sqlite3_mprintf (",(%s %s %s %s", buf_x, buf_y, buf_z,
1417 buf_m);
1418 else if (iv == (ring->Points - 1))
1419 buf =
1420 sqlite3_mprintf (",%s %s %s %s)", buf_x, buf_y, buf_z,
1421 buf_m);
1422 else
1423 buf =
1424 sqlite3_mprintf (",%s %s %s %s", buf_x, buf_y, buf_z,
1425 buf_m);
1426 sqlite3_free (buf_x);
1427 sqlite3_free (buf_y);
1428 sqlite3_free (buf_z);
1429 sqlite3_free (buf_m);
1430 gaiaAppendToOutBuffer (out_buf, buf);
1431 sqlite3_free (buf);
1432 }
1433 }
1434 }
1435
1436 GAIAGEO_DECLARE void
gaiaOutWktEx(gaiaOutBufferPtr out_buf,gaiaGeomCollPtr geom,int precision)1437 gaiaOutWktEx (gaiaOutBufferPtr out_buf, gaiaGeomCollPtr geom, int precision)
1438 {
1439 /* prints the WKT representation of current geometry */
1440 int pts = 0;
1441 int lns = 0;
1442 int pgs = 0;
1443 gaiaPointPtr point;
1444 gaiaLinestringPtr line;
1445 gaiaPolygonPtr polyg;
1446 if (!geom)
1447 return;
1448 point = geom->FirstPoint;
1449 while (point)
1450 {
1451 /* counting how many POINTs are there */
1452 pts++;
1453 point = point->Next;
1454 }
1455 line = geom->FirstLinestring;
1456 while (line)
1457 {
1458 /* counting how many LINESTRINGs are there */
1459 lns++;
1460 line = line->Next;
1461 }
1462 polyg = geom->FirstPolygon;
1463 while (polyg)
1464 {
1465 /* counting how many POLYGONs are there */
1466 pgs++;
1467 polyg = polyg->Next;
1468 }
1469 if ((pts + lns + pgs) == 1
1470 && (geom->DeclaredType == GAIA_POINT
1471 || geom->DeclaredType == GAIA_LINESTRING
1472 || geom->DeclaredType == GAIA_POLYGON))
1473 {
1474 /* we have only one elementary geometry */
1475 point = geom->FirstPoint;
1476 while (point)
1477 {
1478 if (point->DimensionModel == GAIA_XY_Z)
1479 {
1480 /* processing POINTZ */
1481 gaiaAppendToOutBuffer (out_buf, "POINT Z(");
1482 gaiaOutPointZex (out_buf, point, precision);
1483 }
1484 else if (point->DimensionModel == GAIA_XY_M)
1485 {
1486 /* processing POINTM */
1487 gaiaAppendToOutBuffer (out_buf, "POINT M(");
1488 gaiaOutPointM (out_buf, point, precision);
1489 }
1490 else if (point->DimensionModel == GAIA_XY_Z_M)
1491 {
1492 /* processing POINTZM */
1493 gaiaAppendToOutBuffer (out_buf, "POINT ZM(");
1494 gaiaOutPointZM (out_buf, point, precision);
1495 }
1496 else
1497 {
1498 /* processing POINT */
1499 gaiaAppendToOutBuffer (out_buf, "POINT(");
1500 gaiaOutPoint (out_buf, point, precision);
1501 }
1502 gaiaAppendToOutBuffer (out_buf, ")");
1503 point = point->Next;
1504 }
1505 line = geom->FirstLinestring;
1506 while (line)
1507 {
1508 if (line->DimensionModel == GAIA_XY_Z)
1509 {
1510 /* processing LINESTRINGZ */
1511 gaiaAppendToOutBuffer (out_buf, "LINESTRING Z(");
1512 gaiaOutLinestringZex (out_buf, line, precision);
1513 }
1514 else if (line->DimensionModel == GAIA_XY_M)
1515 {
1516 /* processing LINESTRINGM */
1517 gaiaAppendToOutBuffer (out_buf, "LINESTRING M(");
1518 gaiaOutLinestringM (out_buf, line, precision);
1519 }
1520 else if (line->DimensionModel == GAIA_XY_Z_M)
1521 {
1522 /* processing LINESTRINGZM */
1523 gaiaAppendToOutBuffer (out_buf, "LINESTRING ZM(");
1524 gaiaOutLinestringZM (out_buf, line, precision);
1525 }
1526 else
1527 {
1528 /* processing LINESTRING */
1529 gaiaAppendToOutBuffer (out_buf, "LINESTRING(");
1530 gaiaOutLinestring (out_buf, line, precision);
1531 }
1532 gaiaAppendToOutBuffer (out_buf, ")");
1533 line = line->Next;
1534 }
1535 polyg = geom->FirstPolygon;
1536 while (polyg)
1537 {
1538 if (polyg->DimensionModel == GAIA_XY_Z)
1539 {
1540 /* processing POLYGONZ */
1541 gaiaAppendToOutBuffer (out_buf, "POLYGON Z(");
1542 gaiaOutPolygonZex (out_buf, polyg, precision);
1543 }
1544 else if (polyg->DimensionModel == GAIA_XY_M)
1545 {
1546 /* processing POLYGONM */
1547 gaiaAppendToOutBuffer (out_buf, "POLYGON M(");
1548 gaiaOutPolygonM (out_buf, polyg, precision);
1549 }
1550 else if (polyg->DimensionModel == GAIA_XY_Z_M)
1551 {
1552 /* processing POLYGONZM */
1553 gaiaAppendToOutBuffer (out_buf, "POLYGON ZM(");
1554 gaiaOutPolygonZM (out_buf, polyg, precision);
1555 }
1556 else
1557 {
1558 /* processing POLYGON */
1559 gaiaAppendToOutBuffer (out_buf, "POLYGON(");
1560 gaiaOutPolygon (out_buf, polyg, precision);
1561 }
1562 gaiaAppendToOutBuffer (out_buf, ")");
1563 polyg = polyg->Next;
1564 }
1565 }
1566 else
1567 {
1568 /* we have some kind of complex geometry */
1569 if (pts > 0 && lns == 0 && pgs == 0
1570 && geom->DeclaredType == GAIA_MULTIPOINT)
1571 {
1572 /* some kind of MULTIPOINT */
1573 if (geom->DimensionModel == GAIA_XY_Z)
1574 gaiaAppendToOutBuffer (out_buf, "MULTIPOINT Z(");
1575 else if (geom->DimensionModel == GAIA_XY_M)
1576 gaiaAppendToOutBuffer (out_buf, "MULTIPOINT M(");
1577 else if (geom->DimensionModel == GAIA_XY_Z_M)
1578 gaiaAppendToOutBuffer (out_buf, "MULTIPOINT ZM(");
1579 else
1580 gaiaAppendToOutBuffer (out_buf, "MULTIPOINT(");
1581 point = geom->FirstPoint;
1582 while (point)
1583 {
1584 if (point->DimensionModel == GAIA_XY_Z)
1585 {
1586 if (point != geom->FirstPoint)
1587 gaiaAppendToOutBuffer (out_buf, ", ");
1588 gaiaOutPointZex (out_buf, point, precision);
1589 }
1590 else if (point->DimensionModel == GAIA_XY_M)
1591 {
1592 if (point != geom->FirstPoint)
1593 gaiaAppendToOutBuffer (out_buf, ", ");
1594 gaiaOutPointM (out_buf, point, precision);
1595 }
1596 else if (point->DimensionModel == GAIA_XY_Z_M)
1597 {
1598 if (point != geom->FirstPoint)
1599 gaiaAppendToOutBuffer (out_buf, ", ");
1600 gaiaOutPointZM (out_buf, point, precision);
1601 }
1602 else
1603 {
1604 if (point != geom->FirstPoint)
1605 gaiaAppendToOutBuffer (out_buf, ", ");
1606 gaiaOutPoint (out_buf, point, precision);
1607 }
1608 point = point->Next;
1609 }
1610 gaiaAppendToOutBuffer (out_buf, ")");
1611 }
1612 else if (pts == 0 && lns > 0 && pgs == 0
1613 && geom->DeclaredType == GAIA_MULTILINESTRING)
1614 {
1615 /* some kind of MULTILINESTRING */
1616 if (geom->DimensionModel == GAIA_XY_Z)
1617 gaiaAppendToOutBuffer (out_buf, "MULTILINESTRING Z(");
1618 else if (geom->DimensionModel == GAIA_XY_M)
1619 gaiaAppendToOutBuffer (out_buf, "MULTILINESTRING M(");
1620 else if (geom->DimensionModel == GAIA_XY_Z_M)
1621 gaiaAppendToOutBuffer (out_buf, "MULTILINESTRING ZM(");
1622 else
1623 gaiaAppendToOutBuffer (out_buf, "MULTILINESTRING(");
1624 line = geom->FirstLinestring;
1625 while (line)
1626 {
1627 if (line != geom->FirstLinestring)
1628 gaiaAppendToOutBuffer (out_buf, ", (");
1629 else
1630 gaiaAppendToOutBuffer (out_buf, "(");
1631 if (line->DimensionModel == GAIA_XY_Z)
1632 {
1633 gaiaOutLinestringZex (out_buf, line, precision);
1634 gaiaAppendToOutBuffer (out_buf, ")");
1635 }
1636 else if (line->DimensionModel == GAIA_XY_M)
1637 {
1638 gaiaOutLinestringM (out_buf, line, precision);
1639 gaiaAppendToOutBuffer (out_buf, ")");
1640 }
1641 else if (line->DimensionModel == GAIA_XY_Z_M)
1642 {
1643 gaiaOutLinestringZM (out_buf, line, precision);
1644 gaiaAppendToOutBuffer (out_buf, ")");
1645 }
1646 else
1647 {
1648 gaiaOutLinestring (out_buf, line, precision);
1649 gaiaAppendToOutBuffer (out_buf, ")");
1650 }
1651 line = line->Next;
1652 }
1653 gaiaAppendToOutBuffer (out_buf, ")");
1654 }
1655 else if (pts == 0 && lns == 0 && pgs > 0
1656 && geom->DeclaredType == GAIA_MULTIPOLYGON)
1657 {
1658 /* some kind of MULTIPOLYGON */
1659 if (geom->DimensionModel == GAIA_XY_Z)
1660 gaiaAppendToOutBuffer (out_buf, "MULTIPOLYGON Z(");
1661 else if (geom->DimensionModel == GAIA_XY_M)
1662 gaiaAppendToOutBuffer (out_buf, "MULTIPOLYGON M(");
1663 else if (geom->DimensionModel == GAIA_XY_Z_M)
1664 gaiaAppendToOutBuffer (out_buf, "MULTIPOLYGON ZM(");
1665 else
1666 gaiaAppendToOutBuffer (out_buf, "MULTIPOLYGON(");
1667 polyg = geom->FirstPolygon;
1668 while (polyg)
1669 {
1670 if (polyg != geom->FirstPolygon)
1671 gaiaAppendToOutBuffer (out_buf, ", (");
1672 else
1673 gaiaAppendToOutBuffer (out_buf, "(");
1674 if (polyg->DimensionModel == GAIA_XY_Z)
1675 {
1676 gaiaOutPolygonZex (out_buf, polyg, precision);
1677 gaiaAppendToOutBuffer (out_buf, ")");
1678 }
1679 else if (polyg->DimensionModel == GAIA_XY_M)
1680 {
1681 gaiaOutPolygonM (out_buf, polyg, precision);
1682 gaiaAppendToOutBuffer (out_buf, ")");
1683 }
1684 else if (polyg->DimensionModel == GAIA_XY_Z_M)
1685 {
1686 gaiaOutPolygonZM (out_buf, polyg, precision);
1687 gaiaAppendToOutBuffer (out_buf, ")");
1688 }
1689 else
1690 {
1691 gaiaOutPolygon (out_buf, polyg, precision);
1692 gaiaAppendToOutBuffer (out_buf, ")");
1693 }
1694 polyg = polyg->Next;
1695 }
1696 gaiaAppendToOutBuffer (out_buf, ")");
1697 }
1698 else
1699 {
1700 /* some kind of GEOMETRYCOLLECTION */
1701 int ie = 0;
1702 if (geom->DimensionModel == GAIA_XY_Z)
1703 gaiaAppendToOutBuffer (out_buf, "GEOMETRYCOLLECTION Z(");
1704 else if (geom->DimensionModel == GAIA_XY_M)
1705 gaiaAppendToOutBuffer (out_buf, "GEOMETRYCOLLECTION M(");
1706 else if (geom->DimensionModel == GAIA_XY_Z_M)
1707 gaiaAppendToOutBuffer (out_buf, "GEOMETRYCOLLECTION ZM(");
1708 else
1709 gaiaAppendToOutBuffer (out_buf, "GEOMETRYCOLLECTION(");
1710 point = geom->FirstPoint;
1711 while (point)
1712 {
1713 /* processing POINTs */
1714 if (ie > 0)
1715 gaiaAppendToOutBuffer (out_buf, ", ");
1716 ie++;
1717 if (point->DimensionModel == GAIA_XY_Z)
1718 {
1719 gaiaAppendToOutBuffer (out_buf, "POINT Z(");
1720 gaiaOutPointZex (out_buf, point, precision);
1721 }
1722 else if (point->DimensionModel == GAIA_XY_M)
1723 {
1724 gaiaAppendToOutBuffer (out_buf, "POINT M(");
1725 gaiaOutPointM (out_buf, point, precision);
1726 }
1727 else if (point->DimensionModel == GAIA_XY_Z_M)
1728 {
1729 gaiaAppendToOutBuffer (out_buf, "POINT ZM(");
1730 gaiaOutPointZM (out_buf, point, precision);
1731 }
1732 else
1733 {
1734 gaiaAppendToOutBuffer (out_buf, "POINT(");
1735 gaiaOutPoint (out_buf, point, precision);
1736 }
1737 gaiaAppendToOutBuffer (out_buf, ")");
1738 point = point->Next;
1739 }
1740 line = geom->FirstLinestring;
1741 while (line)
1742 {
1743 /* processing LINESTRINGs */
1744 if (ie > 0)
1745 gaiaAppendToOutBuffer (out_buf, ", ");
1746 ie++;
1747 if (line->DimensionModel == GAIA_XY_Z)
1748 {
1749 gaiaAppendToOutBuffer (out_buf, "LINESTRING Z(");
1750 gaiaOutLinestringZex (out_buf, line, precision);
1751 }
1752 else if (line->DimensionModel == GAIA_XY_M)
1753 {
1754 gaiaAppendToOutBuffer (out_buf, "LINESTRING M(");
1755 gaiaOutLinestringM (out_buf, line, precision);
1756 }
1757 else if (line->DimensionModel == GAIA_XY_Z_M)
1758 {
1759 gaiaAppendToOutBuffer (out_buf, "LINESTRING ZM(");
1760 gaiaOutLinestringZM (out_buf, line, precision);
1761 }
1762 else
1763 {
1764 gaiaAppendToOutBuffer (out_buf, "LINESTRING(");
1765 gaiaOutLinestring (out_buf, line, precision);
1766 }
1767 gaiaAppendToOutBuffer (out_buf, ")");
1768 line = line->Next;
1769 }
1770 polyg = geom->FirstPolygon;
1771 while (polyg)
1772 {
1773 /* processing POLYGONs */
1774 if (ie > 0)
1775 gaiaAppendToOutBuffer (out_buf, ", ");
1776 ie++;
1777 if (polyg->DimensionModel == GAIA_XY_Z)
1778 {
1779 gaiaAppendToOutBuffer (out_buf, "POLYGON Z(");
1780 gaiaOutPolygonZex (out_buf, polyg, precision);
1781 }
1782 else if (polyg->DimensionModel == GAIA_XY_M)
1783 {
1784 gaiaAppendToOutBuffer (out_buf, "POLYGON M(");
1785 gaiaOutPolygonM (out_buf, polyg, precision);
1786 }
1787 else if (polyg->DimensionModel == GAIA_XY_Z_M)
1788 {
1789 gaiaAppendToOutBuffer (out_buf, "POLYGON ZM(");
1790 gaiaOutPolygonZM (out_buf, polyg, precision);
1791 }
1792 else
1793 {
1794 gaiaAppendToOutBuffer (out_buf, "POLYGON(");
1795 gaiaOutPolygon (out_buf, polyg, precision);
1796 }
1797 gaiaAppendToOutBuffer (out_buf, ")");
1798 polyg = polyg->Next;
1799 }
1800 gaiaAppendToOutBuffer (out_buf, ")");
1801 }
1802 }
1803 }
1804
1805 GAIAGEO_DECLARE void
gaiaOutWkt(gaiaOutBufferPtr out_buf,gaiaGeomCollPtr geom)1806 gaiaOutWkt (gaiaOutBufferPtr out_buf, gaiaGeomCollPtr geom)
1807 {
1808 /*
1809 * prints the WKT representation of current geometry
1810 * convenience method - default decimal precision
1811 */
1812 gaiaOutWktEx (out_buf, geom, -1);
1813 }
1814
1815 GAIAGEO_DECLARE void
gaiaOutWktStrict(gaiaOutBufferPtr out_buf,gaiaGeomCollPtr geom,int precision)1816 gaiaOutWktStrict (gaiaOutBufferPtr out_buf, gaiaGeomCollPtr geom, int precision)
1817 {
1818 /*
1819 * prints the WKT representation of current geometry
1820 * strictly conformant 2D WKT implementation
1821 */
1822 int pts = 0;
1823 int lns = 0;
1824 int pgs = 0;
1825 gaiaPointPtr point;
1826 gaiaLinestringPtr line;
1827 gaiaPolygonPtr polyg;
1828 if (precision > 18)
1829 precision = 18;
1830 if (!geom)
1831 return;
1832 point = geom->FirstPoint;
1833 while (point)
1834 {
1835 /* counting how many POINTs are there */
1836 pts++;
1837 point = point->Next;
1838 }
1839 line = geom->FirstLinestring;
1840 while (line)
1841 {
1842 /* counting how many LINESTRINGs are there */
1843 lns++;
1844 line = line->Next;
1845 }
1846 polyg = geom->FirstPolygon;
1847 while (polyg)
1848 {
1849 /* counting how many POLYGONs are there */
1850 pgs++;
1851 polyg = polyg->Next;
1852 }
1853 if ((pts + lns + pgs) == 1
1854 && (geom->DeclaredType == GAIA_POINT
1855 || geom->DeclaredType == GAIA_LINESTRING
1856 || geom->DeclaredType == GAIA_POLYGON))
1857 {
1858 /* we have only one elementary geometry */
1859 point = geom->FirstPoint;
1860 while (point)
1861 {
1862 /* processing POINT */
1863 gaiaAppendToOutBuffer (out_buf, "POINT(");
1864 gaiaOutPointStrict (out_buf, point, precision);
1865 gaiaAppendToOutBuffer (out_buf, ")");
1866 point = point->Next;
1867 }
1868 line = geom->FirstLinestring;
1869 while (line)
1870 {
1871 /* processing LINESTRING */
1872 gaiaAppendToOutBuffer (out_buf, "LINESTRING(");
1873 gaiaOutLinestringStrict (out_buf, line, precision);
1874 gaiaAppendToOutBuffer (out_buf, ")");
1875 line = line->Next;
1876 }
1877 polyg = geom->FirstPolygon;
1878 while (polyg)
1879 {
1880 /* processing POLYGON */
1881 gaiaAppendToOutBuffer (out_buf, "POLYGON(");
1882 gaiaOutPolygonStrict (out_buf, polyg, precision);
1883 gaiaAppendToOutBuffer (out_buf, ")");
1884 polyg = polyg->Next;
1885 }
1886 }
1887 else
1888 {
1889 /* we have some kind of complex geometry */
1890 if (pts > 0 && lns == 0 && pgs == 0
1891 && geom->DeclaredType == GAIA_MULTIPOINT)
1892 {
1893 /* some kind of MULTIPOINT */
1894 gaiaAppendToOutBuffer (out_buf, "MULTIPOINT(");
1895 point = geom->FirstPoint;
1896 while (point)
1897 {
1898 if (point != geom->FirstPoint)
1899 gaiaAppendToOutBuffer (out_buf, ",");
1900 gaiaOutPointStrict (out_buf, point, precision);
1901 point = point->Next;
1902 }
1903 gaiaAppendToOutBuffer (out_buf, ")");
1904 }
1905 else if (pts == 0 && lns > 0 && pgs == 0
1906 && geom->DeclaredType == GAIA_MULTILINESTRING)
1907 {
1908 /* some kind of MULTILINESTRING */
1909 gaiaAppendToOutBuffer (out_buf, "MULTILINESTRING(");
1910 line = geom->FirstLinestring;
1911 while (line)
1912 {
1913 if (line != geom->FirstLinestring)
1914 gaiaAppendToOutBuffer (out_buf, ",(");
1915 else
1916 gaiaAppendToOutBuffer (out_buf, "(");
1917 gaiaOutLinestringStrict (out_buf, line, precision);
1918 gaiaAppendToOutBuffer (out_buf, ")");
1919 line = line->Next;
1920 }
1921 gaiaAppendToOutBuffer (out_buf, ")");
1922 }
1923 else if (pts == 0 && lns == 0 && pgs > 0
1924 && geom->DeclaredType == GAIA_MULTIPOLYGON)
1925 {
1926 /* some kind of MULTIPOLYGON */
1927 gaiaAppendToOutBuffer (out_buf, "MULTIPOLYGON(");
1928 polyg = geom->FirstPolygon;
1929 while (polyg)
1930 {
1931 if (polyg != geom->FirstPolygon)
1932 gaiaAppendToOutBuffer (out_buf, ",(");
1933 else
1934 gaiaAppendToOutBuffer (out_buf, "(");
1935 gaiaOutPolygonStrict (out_buf, polyg, precision);
1936 gaiaAppendToOutBuffer (out_buf, ")");
1937 polyg = polyg->Next;
1938 }
1939 gaiaAppendToOutBuffer (out_buf, ")");
1940 }
1941 else
1942 {
1943 /* some kind of GEOMETRYCOLLECTION */
1944 int ie = 0;
1945 gaiaAppendToOutBuffer (out_buf, "GEOMETRYCOLLECTION(");
1946 point = geom->FirstPoint;
1947 while (point)
1948 {
1949 /* processing POINTs */
1950 if (ie > 0)
1951 gaiaAppendToOutBuffer (out_buf, ",");
1952 ie++;
1953 gaiaAppendToOutBuffer (out_buf, "POINT(");
1954 gaiaOutPointStrict (out_buf, point, precision);
1955 gaiaAppendToOutBuffer (out_buf, ")");
1956 point = point->Next;
1957 }
1958 line = geom->FirstLinestring;
1959 while (line)
1960 {
1961 /* processing LINESTRINGs */
1962 if (ie > 0)
1963 gaiaAppendToOutBuffer (out_buf, ",");
1964 ie++;
1965 gaiaAppendToOutBuffer (out_buf, "LINESTRING(");
1966 gaiaOutLinestringStrict (out_buf, line, precision);
1967 gaiaAppendToOutBuffer (out_buf, ")");
1968 line = line->Next;
1969 }
1970 polyg = geom->FirstPolygon;
1971 while (polyg)
1972 {
1973 /* processing POLYGONs */
1974 if (ie > 0)
1975 gaiaAppendToOutBuffer (out_buf, ",");
1976 ie++;
1977 gaiaAppendToOutBuffer (out_buf, "POLYGON(");
1978 gaiaOutPolygonStrict (out_buf, polyg, precision);
1979 gaiaAppendToOutBuffer (out_buf, ")");
1980 polyg = polyg->Next;
1981 }
1982 gaiaAppendToOutBuffer (out_buf, ")");
1983 }
1984 }
1985 }
1986
1987 GAIAGEO_DECLARE void
gaiaToEWKT(gaiaOutBufferPtr out_buf,gaiaGeomCollPtr geom)1988 gaiaToEWKT (gaiaOutBufferPtr out_buf, gaiaGeomCollPtr geom)
1989 {
1990 /* prints the EWKT representation of current geometry */
1991 char buf[128];
1992 int pts = 0;
1993 int lns = 0;
1994 int pgs = 0;
1995 gaiaPointPtr point;
1996 gaiaLinestringPtr line;
1997 gaiaPolygonPtr polyg;
1998 if (!geom)
1999 return;
2000 sprintf (buf, "SRID=%d;", geom->Srid);
2001 gaiaAppendToOutBuffer (out_buf, buf);
2002 point = geom->FirstPoint;
2003 while (point)
2004 {
2005 /* counting how many POINTs are there */
2006 pts++;
2007 point = point->Next;
2008 }
2009 line = geom->FirstLinestring;
2010 while (line)
2011 {
2012 /* counting how many LINESTRINGs are there */
2013 lns++;
2014 line = line->Next;
2015 }
2016 polyg = geom->FirstPolygon;
2017 while (polyg)
2018 {
2019 /* counting how many POLYGONs are there */
2020 pgs++;
2021 polyg = polyg->Next;
2022 }
2023 if ((pts + lns + pgs) == 1
2024 && (geom->DeclaredType == GAIA_POINT
2025 || geom->DeclaredType == GAIA_LINESTRING
2026 || geom->DeclaredType == GAIA_POLYGON))
2027 {
2028 /* we have only one elementary geometry */
2029 point = geom->FirstPoint;
2030 while (point)
2031 {
2032 if (point->DimensionModel == GAIA_XY_Z)
2033 {
2034 /* processing POINTZ */
2035 gaiaAppendToOutBuffer (out_buf, "POINT(");
2036 gaiaOutEwktPointZ (out_buf, point);
2037 }
2038 else if (point->DimensionModel == GAIA_XY_M)
2039 {
2040 /* processing POINTM */
2041 gaiaAppendToOutBuffer (out_buf, "POINTM(");
2042 gaiaOutEwktPointM (out_buf, point);
2043 }
2044 else if (point->DimensionModel == GAIA_XY_Z_M)
2045 {
2046 /* processing POINTZM */
2047 gaiaAppendToOutBuffer (out_buf, "POINT(");
2048 gaiaOutEwktPointZM (out_buf, point);
2049 }
2050 else
2051 {
2052 /* processing POINT */
2053 gaiaAppendToOutBuffer (out_buf, "POINT(");
2054 gaiaOutEwktPoint (out_buf, point);
2055 }
2056 gaiaAppendToOutBuffer (out_buf, ")");
2057 point = point->Next;
2058 }
2059 line = geom->FirstLinestring;
2060 while (line)
2061 {
2062 if (line->DimensionModel == GAIA_XY_Z)
2063 {
2064 /* processing LINESTRINGZ */
2065 gaiaAppendToOutBuffer (out_buf, "LINESTRING(");
2066 gaiaOutEwktLinestringZ (out_buf, line);
2067 }
2068 else if (line->DimensionModel == GAIA_XY_M)
2069 {
2070 /* processing LINESTRINGM */
2071 gaiaAppendToOutBuffer (out_buf, "LINESTRINGM(");
2072 gaiaOutEwktLinestringM (out_buf, line);
2073 }
2074 else if (line->DimensionModel == GAIA_XY_Z_M)
2075 {
2076 /* processing LINESTRINGZM */
2077 gaiaAppendToOutBuffer (out_buf, "LINESTRING(");
2078 gaiaOutEwktLinestringZM (out_buf, line);
2079 }
2080 else
2081 {
2082 /* processing LINESTRING */
2083 gaiaAppendToOutBuffer (out_buf, "LINESTRING(");
2084 gaiaOutEwktLinestring (out_buf, line);
2085 }
2086 gaiaAppendToOutBuffer (out_buf, ")");
2087 line = line->Next;
2088 }
2089 polyg = geom->FirstPolygon;
2090 while (polyg)
2091 {
2092 if (polyg->DimensionModel == GAIA_XY_Z)
2093 {
2094 /* processing POLYGONZ */
2095 gaiaAppendToOutBuffer (out_buf, "POLYGON(");
2096 gaiaOutEwktPolygonZ (out_buf, polyg);
2097 }
2098 else if (polyg->DimensionModel == GAIA_XY_M)
2099 {
2100 /* processing POLYGONM */
2101 gaiaAppendToOutBuffer (out_buf, "POLYGONM(");
2102 gaiaOutEwktPolygonM (out_buf, polyg);
2103 }
2104 else if (polyg->DimensionModel == GAIA_XY_Z_M)
2105 {
2106 /* processing POLYGONZM */
2107 gaiaAppendToOutBuffer (out_buf, "POLYGON(");
2108 gaiaOutEwktPolygonZM (out_buf, polyg);
2109 }
2110 else
2111 {
2112 /* processing POLYGON */
2113 gaiaAppendToOutBuffer (out_buf, "POLYGON(");
2114 gaiaOutEwktPolygon (out_buf, polyg);
2115 }
2116 gaiaAppendToOutBuffer (out_buf, ")");
2117 polyg = polyg->Next;
2118 }
2119 }
2120 else
2121 {
2122 /* we have some kind of complex geometry */
2123 if (pts > 0 && lns == 0 && pgs == 0
2124 && geom->DeclaredType == GAIA_MULTIPOINT)
2125 {
2126 /* some kind of MULTIPOINT */
2127 if (geom->DimensionModel == GAIA_XY_M)
2128 gaiaAppendToOutBuffer (out_buf, "MULTIPOINTM(");
2129 else
2130 gaiaAppendToOutBuffer (out_buf, "MULTIPOINT(");
2131 point = geom->FirstPoint;
2132 while (point)
2133 {
2134 if (point->DimensionModel == GAIA_XY_Z)
2135 {
2136 if (point != geom->FirstPoint)
2137 gaiaAppendToOutBuffer (out_buf, ",");
2138 gaiaOutEwktPointZ (out_buf, point);
2139 }
2140 else if (point->DimensionModel == GAIA_XY_M)
2141 {
2142 if (point != geom->FirstPoint)
2143 gaiaAppendToOutBuffer (out_buf, ",");
2144 gaiaOutEwktPointM (out_buf, point);
2145 }
2146 else if (point->DimensionModel == GAIA_XY_Z_M)
2147 {
2148 if (point != geom->FirstPoint)
2149 gaiaAppendToOutBuffer (out_buf, ",");
2150 gaiaOutEwktPointZM (out_buf, point);
2151 }
2152 else
2153 {
2154 if (point != geom->FirstPoint)
2155 gaiaAppendToOutBuffer (out_buf, ",");
2156 gaiaOutEwktPoint (out_buf, point);
2157 }
2158 point = point->Next;
2159 }
2160 gaiaAppendToOutBuffer (out_buf, ")");
2161 }
2162 else if (pts == 0 && lns > 0 && pgs == 0
2163 && geom->DeclaredType == GAIA_MULTILINESTRING)
2164 {
2165 /* some kind of MULTILINESTRING */
2166 if (geom->DimensionModel == GAIA_XY_M)
2167 gaiaAppendToOutBuffer (out_buf, "MULTILINESTRINGM(");
2168 else
2169 gaiaAppendToOutBuffer (out_buf, "MULTILINESTRING(");
2170 line = geom->FirstLinestring;
2171 while (line)
2172 {
2173 if (line != geom->FirstLinestring)
2174 gaiaAppendToOutBuffer (out_buf, ",(");
2175 else
2176 gaiaAppendToOutBuffer (out_buf, "(");
2177 if (line->DimensionModel == GAIA_XY_Z)
2178 {
2179 gaiaOutEwktLinestringZ (out_buf, line);
2180 gaiaAppendToOutBuffer (out_buf, ")");
2181 }
2182 else if (line->DimensionModel == GAIA_XY_M)
2183 {
2184 gaiaOutEwktLinestringM (out_buf, line);
2185 gaiaAppendToOutBuffer (out_buf, ")");
2186 }
2187 else if (line->DimensionModel == GAIA_XY_Z_M)
2188 {
2189 gaiaOutEwktLinestringZM (out_buf, line);
2190 gaiaAppendToOutBuffer (out_buf, ")");
2191 }
2192 else
2193 {
2194 gaiaOutEwktLinestring (out_buf, line);
2195 gaiaAppendToOutBuffer (out_buf, ")");
2196 }
2197 line = line->Next;
2198 }
2199 gaiaAppendToOutBuffer (out_buf, ")");
2200 }
2201 else if (pts == 0 && lns == 0 && pgs > 0
2202 && geom->DeclaredType == GAIA_MULTIPOLYGON)
2203 {
2204 /* some kind of MULTIPOLYGON */
2205 if (geom->DimensionModel == GAIA_XY_M)
2206 gaiaAppendToOutBuffer (out_buf, "MULTIPOLYGONM(");
2207 else
2208 gaiaAppendToOutBuffer (out_buf, "MULTIPOLYGON(");
2209 polyg = geom->FirstPolygon;
2210 while (polyg)
2211 {
2212 if (polyg != geom->FirstPolygon)
2213 gaiaAppendToOutBuffer (out_buf, ",(");
2214 else
2215 gaiaAppendToOutBuffer (out_buf, "(");
2216 if (polyg->DimensionModel == GAIA_XY_Z)
2217 {
2218 gaiaOutEwktPolygonZ (out_buf, polyg);
2219 gaiaAppendToOutBuffer (out_buf, ")");
2220 }
2221 else if (polyg->DimensionModel == GAIA_XY_M)
2222 {
2223 gaiaOutEwktPolygonM (out_buf, polyg);
2224 gaiaAppendToOutBuffer (out_buf, ")");
2225 }
2226 else if (polyg->DimensionModel == GAIA_XY_Z_M)
2227 {
2228 gaiaOutEwktPolygonZM (out_buf, polyg);
2229 gaiaAppendToOutBuffer (out_buf, ")");
2230 }
2231 else
2232 {
2233 gaiaOutEwktPolygon (out_buf, polyg);
2234 gaiaAppendToOutBuffer (out_buf, ")");
2235 }
2236 polyg = polyg->Next;
2237 }
2238 gaiaAppendToOutBuffer (out_buf, ")");
2239 }
2240 else
2241 {
2242 /* some kind of GEOMETRYCOLLECTION */
2243 int ie = 0;
2244 if (geom->DimensionModel == GAIA_XY_M)
2245 gaiaAppendToOutBuffer (out_buf, "GEOMETRYCOLLECTIONM(");
2246 else
2247 gaiaAppendToOutBuffer (out_buf, "GEOMETRYCOLLECTION(");
2248 point = geom->FirstPoint;
2249 while (point)
2250 {
2251 /* processing POINTs */
2252 if (ie > 0)
2253 gaiaAppendToOutBuffer (out_buf, ",");
2254 ie++;
2255 if (point->DimensionModel == GAIA_XY_Z)
2256 {
2257 gaiaAppendToOutBuffer (out_buf, "POINT(");
2258 gaiaOutEwktPointZ (out_buf, point);
2259 }
2260 else if (point->DimensionModel == GAIA_XY_M)
2261 {
2262 gaiaAppendToOutBuffer (out_buf, "POINTM(");
2263 gaiaOutEwktPointM (out_buf, point);
2264 }
2265 else if (point->DimensionModel == GAIA_XY_Z_M)
2266 {
2267 gaiaAppendToOutBuffer (out_buf, "POINT(");
2268 gaiaOutEwktPointZM (out_buf, point);
2269 }
2270 else
2271 {
2272 gaiaAppendToOutBuffer (out_buf, "POINT(");
2273 gaiaOutEwktPoint (out_buf, point);
2274 }
2275 gaiaAppendToOutBuffer (out_buf, ")");
2276 point = point->Next;
2277 }
2278 line = geom->FirstLinestring;
2279 while (line)
2280 {
2281 /* processing LINESTRINGs */
2282 if (ie > 0)
2283 gaiaAppendToOutBuffer (out_buf, ",");
2284 ie++;
2285 if (line->DimensionModel == GAIA_XY_Z)
2286 {
2287 gaiaAppendToOutBuffer (out_buf, "LINESTRING(");
2288 gaiaOutEwktLinestringZ (out_buf, line);
2289 }
2290 else if (line->DimensionModel == GAIA_XY_M)
2291 {
2292 gaiaAppendToOutBuffer (out_buf, "LINESTRINGM(");
2293 gaiaOutEwktLinestringM (out_buf, line);
2294 }
2295 else if (line->DimensionModel == GAIA_XY_Z_M)
2296 {
2297 gaiaAppendToOutBuffer (out_buf, "LINESTRING(");
2298 gaiaOutEwktLinestringZM (out_buf, line);
2299 }
2300 else
2301 {
2302 gaiaAppendToOutBuffer (out_buf, "LINESTRING(");
2303 gaiaOutEwktLinestring (out_buf, line);
2304 }
2305 gaiaAppendToOutBuffer (out_buf, ")");
2306 line = line->Next;
2307 }
2308 polyg = geom->FirstPolygon;
2309 while (polyg)
2310 {
2311 /* processing POLYGONs */
2312 if (ie > 0)
2313 gaiaAppendToOutBuffer (out_buf, ",");
2314 ie++;
2315 if (polyg->DimensionModel == GAIA_XY_Z)
2316 {
2317 gaiaAppendToOutBuffer (out_buf, "POLYGON(");
2318 gaiaOutEwktPolygonZ (out_buf, polyg);
2319 }
2320 else if (polyg->DimensionModel == GAIA_XY_M)
2321 {
2322 gaiaAppendToOutBuffer (out_buf, "POLYGONM(");
2323 gaiaOutEwktPolygonM (out_buf, polyg);
2324 }
2325 else if (polyg->DimensionModel == GAIA_XY_Z_M)
2326 {
2327 gaiaAppendToOutBuffer (out_buf, "POLYGON(");
2328 gaiaOutEwktPolygonZM (out_buf, polyg);
2329 }
2330 else
2331 {
2332 gaiaAppendToOutBuffer (out_buf, "POLYGON(");
2333 gaiaOutEwktPolygon (out_buf, polyg);
2334 }
2335 gaiaAppendToOutBuffer (out_buf, ")");
2336 polyg = polyg->Next;
2337 }
2338 gaiaAppendToOutBuffer (out_buf, ")");
2339 }
2340 }
2341 }
2342
2343 /*
2344 /
2345 / Gaia common support for SVG encoded geometries
2346 /
2347 ////////////////////////////////////////////////////////////
2348 /
2349 / Author: Klaus Foerster klaus.foerster@svg.cc
2350 / version 0.9. 2008 September 21
2351 /
2352 */
2353
2354 static void
SvgCoords(gaiaOutBufferPtr out_buf,gaiaPointPtr point,int precision)2355 SvgCoords (gaiaOutBufferPtr out_buf, gaiaPointPtr point, int precision)
2356 {
2357 /* formats POINT as SVG-attributes x,y */
2358 char *buf_x;
2359 char *buf_y;
2360 char *buf;
2361 buf_x = sqlite3_mprintf ("%.*f", precision, point->X);
2362 gaiaOutClean (buf_x);
2363 buf_y = sqlite3_mprintf ("%.*f", precision, point->Y * -1);
2364 gaiaOutClean (buf_y);
2365 buf = sqlite3_mprintf ("x=\"%s\" y=\"%s\"", buf_x, buf_y);
2366 sqlite3_free (buf_x);
2367 sqlite3_free (buf_y);
2368 gaiaAppendToOutBuffer (out_buf, buf);
2369 sqlite3_free (buf);
2370 }
2371
2372 static void
SvgCircle(gaiaOutBufferPtr out_buf,gaiaPointPtr point,int precision)2373 SvgCircle (gaiaOutBufferPtr out_buf, gaiaPointPtr point, int precision)
2374 {
2375 /* formats POINT as SVG-attributes cx,cy */
2376 char *buf_x;
2377 char *buf_y;
2378 char *buf;
2379 buf_x = sqlite3_mprintf ("%.*f", precision, point->X);
2380 gaiaOutClean (buf_x);
2381 buf_y = sqlite3_mprintf ("%.*f", precision, point->Y * -1);
2382 gaiaOutClean (buf_y);
2383 buf = sqlite3_mprintf ("cx=\"%s\" cy=\"%s\"", buf_x, buf_y);
2384 sqlite3_free (buf_x);
2385 sqlite3_free (buf_y);
2386 gaiaAppendToOutBuffer (out_buf, buf);
2387 sqlite3_free (buf);
2388 }
2389
2390 static void
SvgPathRelative(gaiaOutBufferPtr out_buf,int dims,int points,double * coords,int precision,int closePath)2391 SvgPathRelative (gaiaOutBufferPtr out_buf, int dims, int points, double *coords,
2392 int precision, int closePath)
2393 {
2394 /* formats LINESTRING as SVG-path d-attribute with relative coordinate moves */
2395 char *buf_x;
2396 char *buf_y;
2397 char *buf;
2398 double x;
2399 double y;
2400 double z;
2401 double m;
2402 double lastX = 0.0;
2403 double lastY = 0.0;
2404 int iv;
2405 for (iv = 0; iv < points; iv++)
2406 {
2407 if (dims == GAIA_XY_Z)
2408 {
2409 gaiaGetPointXYZ (coords, iv, &x, &y, &z);
2410 }
2411 else if (dims == GAIA_XY_M)
2412 {
2413 gaiaGetPointXYM (coords, iv, &x, &y, &m);
2414 }
2415 else if (dims == GAIA_XY_Z_M)
2416 {
2417 gaiaGetPointXYZM (coords, iv, &x, &y, &z, &m);
2418 }
2419 else
2420 {
2421 gaiaGetPoint (coords, iv, &x, &y);
2422 }
2423 buf_x = sqlite3_mprintf ("%.*f", precision, x - lastX);
2424 gaiaOutClean (buf_x);
2425 buf_y = sqlite3_mprintf ("%.*f", precision, (y - lastY) * -1);
2426 gaiaOutClean (buf_y);
2427 if (iv == 0)
2428 buf = sqlite3_mprintf ("M %s %s l ", buf_x, buf_y);
2429 else
2430 buf = sqlite3_mprintf ("%s %s ", buf_x, buf_y);
2431 sqlite3_free (buf_x);
2432 sqlite3_free (buf_y);
2433 lastX = x;
2434 lastY = y;
2435 if (iv == points - 1 && closePath == 1)
2436 gaiaAppendToOutBuffer (out_buf, "z ");
2437 else
2438 gaiaAppendToOutBuffer (out_buf, buf);
2439 sqlite3_free (buf);
2440 }
2441 }
2442
2443 static void
SvgPathAbsolute(gaiaOutBufferPtr out_buf,int dims,int points,double * coords,int precision,int closePath)2444 SvgPathAbsolute (gaiaOutBufferPtr out_buf, int dims, int points, double *coords,
2445 int precision, int closePath)
2446 {
2447 /* formats LINESTRING as SVG-path d-attribute with relative coordinate moves */
2448 char *buf_x;
2449 char *buf_y;
2450 char *buf;
2451 double x;
2452 double y;
2453 double z;
2454 double m;
2455 int iv;
2456 for (iv = 0; iv < points; iv++)
2457 {
2458 if (dims == GAIA_XY_Z)
2459 {
2460 gaiaGetPointXYZ (coords, iv, &x, &y, &z);
2461 }
2462 else if (dims == GAIA_XY_M)
2463 {
2464 gaiaGetPointXYM (coords, iv, &x, &y, &m);
2465 }
2466 else if (dims == GAIA_XY_Z_M)
2467 {
2468 gaiaGetPointXYZM (coords, iv, &x, &y, &z, &m);
2469 }
2470 else
2471 {
2472 gaiaGetPoint (coords, iv, &x, &y);
2473 }
2474 buf_x = sqlite3_mprintf ("%.*f", precision, x);
2475 gaiaOutClean (buf_x);
2476 buf_y = sqlite3_mprintf ("%.*f", precision, y * -1);
2477 gaiaOutClean (buf_y);
2478 if (iv == 0)
2479 buf = sqlite3_mprintf ("M %s %s L ", buf_x, buf_y);
2480 else
2481 buf = sqlite3_mprintf ("%s %s ", buf_x, buf_y);
2482 sqlite3_free (buf_x);
2483 sqlite3_free (buf_y);
2484 if (iv == points - 1 && closePath == 1)
2485 gaiaAppendToOutBuffer (out_buf, "z ");
2486 else
2487 gaiaAppendToOutBuffer (out_buf, buf);
2488 sqlite3_free (buf);
2489 }
2490 }
2491
2492 GAIAGEO_DECLARE void
gaiaOutSvg(gaiaOutBufferPtr out_buf,gaiaGeomCollPtr geom,int relative,int precision)2493 gaiaOutSvg (gaiaOutBufferPtr out_buf, gaiaGeomCollPtr geom, int relative,
2494 int precision)
2495 {
2496 /* prints the SVG representation of current geometry */
2497 int pts = 0;
2498 int lns = 0;
2499 int pgs = 0;
2500 int ib;
2501 gaiaPointPtr point;
2502 gaiaLinestringPtr line;
2503 gaiaPolygonPtr polyg;
2504 gaiaRingPtr ring;
2505 if (precision > 18)
2506 precision = 18;
2507 if (!geom)
2508 return;
2509 point = geom->FirstPoint;
2510 while (point)
2511 {
2512 /* counting how many POINTs are there */
2513 pts++;
2514 point = point->Next;
2515 }
2516 line = geom->FirstLinestring;
2517 while (line)
2518 {
2519 /* counting how many LINESTRINGs are there */
2520 lns++;
2521 line = line->Next;
2522 }
2523 polyg = geom->FirstPolygon;
2524 while (polyg)
2525 {
2526 /* counting how many POLYGONs are there */
2527 pgs++;
2528 polyg = polyg->Next;
2529 }
2530
2531 if ((pts + lns + pgs) == 1)
2532 {
2533 /* we have only one elementary geometry */
2534 point = geom->FirstPoint;
2535 while (point)
2536 {
2537 /* processing POINT */
2538 if (relative == 1)
2539 SvgCoords (out_buf, point, precision);
2540 else
2541 SvgCircle (out_buf, point, precision);
2542 point = point->Next;
2543 }
2544 line = geom->FirstLinestring;
2545 while (line)
2546 {
2547 /* processing LINESTRING */
2548 if (relative == 1)
2549 SvgPathRelative (out_buf, line->DimensionModel,
2550 line->Points, line->Coords, precision, 0);
2551 else
2552 SvgPathAbsolute (out_buf, line->DimensionModel,
2553 line->Points, line->Coords, precision, 0);
2554 line = line->Next;
2555 }
2556 polyg = geom->FirstPolygon;
2557 while (polyg)
2558 {
2559 /* process exterior and interior rings */
2560 ring = polyg->Exterior;
2561 if (relative == 1)
2562 {
2563 SvgPathRelative (out_buf, ring->DimensionModel,
2564 ring->Points, ring->Coords, precision,
2565 1);
2566 for (ib = 0; ib < polyg->NumInteriors; ib++)
2567 {
2568 ring = polyg->Interiors + ib;
2569 SvgPathRelative (out_buf, ring->DimensionModel,
2570 ring->Points, ring->Coords,
2571 precision, 1);
2572 }
2573 }
2574 else
2575 {
2576 SvgPathAbsolute (out_buf, ring->DimensionModel,
2577 ring->Points, ring->Coords, precision,
2578 1);
2579 for (ib = 0; ib < polyg->NumInteriors; ib++)
2580 {
2581 ring = polyg->Interiors + ib;
2582 SvgPathAbsolute (out_buf, ring->DimensionModel,
2583 ring->Points, ring->Coords,
2584 precision, 1);
2585 }
2586 }
2587 polyg = polyg->Next;
2588 }
2589 }
2590 else
2591 {
2592 /* we have some kind of complex geometry */
2593 if (pts > 0 && lns == 0 && pgs == 0)
2594 {
2595 /* this one is a MULTIPOINT */
2596 point = geom->FirstPoint;
2597 while (point)
2598 {
2599 /* processing POINTs */
2600 if (point != geom->FirstPoint)
2601 gaiaAppendToOutBuffer (out_buf, ",");
2602 if (relative == 1)
2603 SvgCoords (out_buf, point, precision);
2604 else
2605 SvgCircle (out_buf, point, precision);
2606 point = point->Next;
2607 }
2608 }
2609 else if (pts == 0 && lns > 0 && pgs == 0)
2610 {
2611 /* this one is a MULTILINESTRING */
2612 line = geom->FirstLinestring;
2613 while (line)
2614 {
2615 /* processing LINESTRINGs */
2616 if (relative == 1)
2617 SvgPathRelative (out_buf, line->DimensionModel,
2618 line->Points, line->Coords,
2619 precision, 0);
2620 else
2621 SvgPathAbsolute (out_buf, line->DimensionModel,
2622 line->Points, line->Coords,
2623 precision, 0);
2624 line = line->Next;
2625 }
2626 }
2627 else if (pts == 0 && lns == 0 && pgs > 0)
2628 {
2629 /* this one is a MULTIPOLYGON */
2630 polyg = geom->FirstPolygon;
2631 while (polyg)
2632 {
2633 /* processing POLYGONs */
2634 ring = polyg->Exterior;
2635 if (relative == 1)
2636 {
2637 SvgPathRelative (out_buf, ring->DimensionModel,
2638 ring->Points, ring->Coords,
2639 precision, 1);
2640 for (ib = 0; ib < polyg->NumInteriors; ib++)
2641 {
2642 ring = polyg->Interiors + ib;
2643 SvgPathRelative (out_buf,
2644 ring->DimensionModel,
2645 ring->Points, ring->Coords,
2646 precision, 1);
2647 }
2648 }
2649 else
2650 {
2651 SvgPathAbsolute (out_buf, ring->DimensionModel,
2652 ring->Points, ring->Coords,
2653 precision, 1);
2654 for (ib = 0; ib < polyg->NumInteriors; ib++)
2655 {
2656 ring = polyg->Interiors + ib;
2657 SvgPathAbsolute (out_buf,
2658 ring->DimensionModel,
2659 ring->Points, ring->Coords,
2660 precision, 1);
2661 }
2662 }
2663 polyg = polyg->Next;
2664 }
2665 }
2666 else
2667 {
2668 /* this one is a GEOMETRYCOLLECTION */
2669 int ie = 0;
2670 point = geom->FirstPoint;
2671 while (point)
2672 {
2673 /* processing POINTs */
2674 if (ie > 0)
2675 {
2676 gaiaAppendToOutBuffer (out_buf, ";");
2677 }
2678 ie++;
2679 if (relative == 1)
2680 SvgCoords (out_buf, point, precision);
2681 else
2682 SvgCircle (out_buf, point, precision);
2683 point = point->Next;
2684 }
2685 line = geom->FirstLinestring;
2686 while (line)
2687 {
2688 /* processing LINESTRINGs */
2689 if (ie > 0)
2690 gaiaAppendToOutBuffer (out_buf, ";");
2691 ie++;
2692 if (relative == 1)
2693 SvgPathRelative (out_buf, line->DimensionModel,
2694 line->Points, line->Coords,
2695 precision, 0);
2696 else
2697 SvgPathAbsolute (out_buf, line->DimensionModel,
2698 line->Points, line->Coords,
2699 precision, 0);
2700 line = line->Next;
2701 }
2702 polyg = geom->FirstPolygon;
2703 while (polyg)
2704 {
2705 /* processing POLYGONs */
2706 ie++;
2707 /* process exterior and interior rings */
2708 ring = polyg->Exterior;
2709 if (relative == 1)
2710 {
2711 SvgPathRelative (out_buf, ring->DimensionModel,
2712 ring->Points, ring->Coords,
2713 precision, 1);
2714 for (ib = 0; ib < polyg->NumInteriors; ib++)
2715 {
2716 ring = polyg->Interiors + ib;
2717 SvgPathRelative (out_buf,
2718 ring->DimensionModel,
2719 ring->Points, ring->Coords,
2720 precision, 1);
2721 }
2722 }
2723 else
2724 {
2725 SvgPathAbsolute (out_buf, ring->DimensionModel,
2726 ring->Points, ring->Coords,
2727 precision, 1);
2728 for (ib = 0; ib < polyg->NumInteriors; ib++)
2729 {
2730 ring = polyg->Interiors + ib;
2731 SvgPathAbsolute (out_buf,
2732 ring->DimensionModel,
2733 ring->Points, ring->Coords,
2734 precision, 1);
2735 }
2736 }
2737 polyg = polyg->Next;
2738 }
2739 }
2740 }
2741
2742 if (out_buf->Error == 0 && out_buf->WriteOffset > 0)
2743 {
2744 /* sandro 2012-02-23 cleaning extra trailing spaces */
2745 int i;
2746 for (i = out_buf->WriteOffset - 1; i >= 0; i--)
2747 {
2748 if (*(out_buf->Buffer + i) == ' ')
2749 {
2750 *(out_buf->Buffer + i) = '\0';
2751 out_buf->WriteOffset -= 1;
2752 }
2753 else
2754 break;
2755 }
2756 }
2757 }
2758
2759 /* END of Klaus Foerster SVG implementation */
2760
2761
2762 static char *
XmlClean(const char * string)2763 XmlClean (const char *string)
2764 {
2765 /* well formatting a text string for XML */
2766 int ind;
2767 char *clean;
2768 char *p_out;
2769 int len = strlen (string);
2770 clean = malloc (len * 3);
2771 if (!clean)
2772 return NULL;
2773 p_out = clean;
2774 for (ind = 0; ind < len; ind++)
2775 {
2776 /* masking XML special chars */
2777 switch (string[ind])
2778 {
2779 case '&':
2780 *p_out++ = '&';
2781 *p_out++ = 'a';
2782 *p_out++ = 'm';
2783 *p_out++ = 'p';
2784 *p_out++ = ';';
2785 break;
2786 case '<':
2787 *p_out++ = '&';
2788 *p_out++ = 'l';
2789 *p_out++ = 't';
2790 *p_out++ = ';';
2791 break;
2792 case '>':
2793 *p_out++ = '&';
2794 *p_out++ = 'g';
2795 *p_out++ = 't';
2796 *p_out++ = ';';
2797 break;
2798 case '"':
2799 *p_out++ = '&';
2800 *p_out++ = 'q';
2801 *p_out++ = 'u';
2802 *p_out++ = 'o';
2803 *p_out++ = 't';
2804 *p_out++ = ';';
2805 break;
2806 default:
2807 *p_out++ = string[ind];
2808 break;
2809 };
2810 }
2811 *p_out = '\0';
2812 return clean;
2813 }
2814
2815 static void
out_kml_point(gaiaOutBufferPtr out_buf,gaiaPointPtr point,int precision)2816 out_kml_point (gaiaOutBufferPtr out_buf, gaiaPointPtr point, int precision)
2817 {
2818 /* formats POINT as KML [x,y] */
2819 char *buf_x = NULL;
2820 char *buf_y = NULL;
2821 char *buf_z = NULL;
2822 char *buf = NULL;
2823 buf_x = sqlite3_mprintf ("%.*f", precision, point->X);
2824 gaiaOutClean (buf_x);
2825 buf_y = sqlite3_mprintf ("%.*f", precision, point->Y);
2826 gaiaOutClean (buf_y);
2827 if (point->DimensionModel == GAIA_XY_Z
2828 || point->DimensionModel == GAIA_XY_Z_M)
2829 {
2830 buf_z = sqlite3_mprintf ("%.*f", precision, point->Z);
2831 gaiaOutClean (buf_z);
2832 }
2833 gaiaAppendToOutBuffer (out_buf, "<Point><coordinates>");
2834 if (point->DimensionModel == GAIA_XY_Z
2835 || point->DimensionModel == GAIA_XY_Z_M)
2836 {
2837 buf = sqlite3_mprintf ("%s,%s,%s", buf_x, buf_y, buf_z);
2838 sqlite3_free (buf_z);
2839 }
2840 else
2841 buf = sqlite3_mprintf ("%s,%s", buf_x, buf_y);
2842 sqlite3_free (buf_x);
2843 sqlite3_free (buf_y);
2844 gaiaAppendToOutBuffer (out_buf, buf);
2845 sqlite3_free (buf);
2846 gaiaAppendToOutBuffer (out_buf, "</coordinates></Point>");
2847 }
2848
2849 static void
out_kml_linestring(gaiaOutBuffer * out_buf,int dims,int points,double * coords,int precision)2850 out_kml_linestring (gaiaOutBuffer * out_buf, int dims, int points,
2851 double *coords, int precision)
2852 {
2853 /* formats LINESTRING as KML [x,y] */
2854 char *buf_x = NULL;
2855 char *buf_y = NULL;
2856 char *buf_z = NULL;
2857 char *buf = NULL;
2858 int iv;
2859 double x = 0.0;
2860 double y = 0.0;
2861 double z = 0.0;
2862 double m = 0.0;
2863 gaiaAppendToOutBuffer (out_buf, "<LineString><coordinates>");
2864 for (iv = 0; iv < points; iv++)
2865 {
2866 /* exporting vertices */
2867 if (dims == GAIA_XY_Z)
2868 {
2869 gaiaGetPointXYZ (coords, iv, &x, &y, &z);
2870 }
2871 else if (dims == GAIA_XY_M)
2872 {
2873 gaiaGetPointXYM (coords, iv, &x, &y, &m);
2874 }
2875 else if (dims == GAIA_XY_Z_M)
2876 {
2877 gaiaGetPointXYZM (coords, iv, &x, &y, &z, &m);
2878 }
2879 else
2880 {
2881 gaiaGetPoint (coords, iv, &x, &y);
2882 }
2883 buf_x = sqlite3_mprintf ("%.*f", precision, x);
2884 gaiaOutClean (buf_x);
2885 buf_y = sqlite3_mprintf ("%.*f", precision, y);
2886 gaiaOutClean (buf_y);
2887 if (dims == GAIA_XY_Z || dims == GAIA_XY_Z_M)
2888 {
2889 buf_z = sqlite3_mprintf ("%.*f", precision, z);
2890 gaiaOutClean (buf_z);
2891 if (iv == 0)
2892 buf = sqlite3_mprintf ("%s,%s,%s", buf_x, buf_y, buf_z);
2893 else
2894 buf = sqlite3_mprintf (" %s,%s,%s", buf_x, buf_y, buf_z);
2895 sqlite3_free (buf_z);
2896 }
2897 else
2898 {
2899 if (iv == 0)
2900 buf = sqlite3_mprintf ("%s,%s", buf_x, buf_y);
2901 else
2902 buf = sqlite3_mprintf (" %s,%s", buf_x, buf_y);
2903 }
2904 sqlite3_free (buf_x);
2905 sqlite3_free (buf_y);
2906 gaiaAppendToOutBuffer (out_buf, buf);
2907 sqlite3_free (buf);
2908 }
2909 gaiaAppendToOutBuffer (out_buf, "</coordinates></LineString>");
2910 }
2911
2912 static void
out_kml_polygon(gaiaOutBufferPtr out_buf,gaiaPolygonPtr polygon,int precision)2913 out_kml_polygon (gaiaOutBufferPtr out_buf, gaiaPolygonPtr polygon,
2914 int precision)
2915 {
2916 /* formats POLYGON as KML [x,y] */
2917 char *buf_x = NULL;
2918 char *buf_y = NULL;
2919 char *buf_z = NULL;
2920 char *buf = NULL;
2921 gaiaRingPtr ring;
2922 int iv;
2923 int ib;
2924 double x = 0.0;
2925 double y = 0.0;
2926 double z = 0.0;
2927 double m = 0.0;
2928 gaiaAppendToOutBuffer (out_buf, "<Polygon>");
2929 gaiaAppendToOutBuffer (out_buf,
2930 "<outerBoundaryIs><LinearRing><coordinates>");
2931 ring = polygon->Exterior;
2932 for (iv = 0; iv < ring->Points; iv++)
2933 {
2934 /* exporting vertices [Exterior Ring] */
2935 if (ring->DimensionModel == GAIA_XY_Z)
2936 {
2937 gaiaGetPointXYZ (ring->Coords, iv, &x, &y, &z);
2938 }
2939 else if (ring->DimensionModel == GAIA_XY_M)
2940 {
2941 gaiaGetPointXYM (ring->Coords, iv, &x, &y, &m);
2942 }
2943 else if (ring->DimensionModel == GAIA_XY_Z_M)
2944 {
2945 gaiaGetPointXYZM (ring->Coords, iv, &x, &y, &z, &m);
2946 }
2947 else
2948 {
2949 gaiaGetPoint (ring->Coords, iv, &x, &y);
2950 }
2951 buf_x = sqlite3_mprintf ("%.*f", precision, x);
2952 gaiaOutClean (buf_x);
2953 buf_y = sqlite3_mprintf ("%.*f", precision, y);
2954 gaiaOutClean (buf_y);
2955 if (ring->DimensionModel == GAIA_XY_Z
2956 || ring->DimensionModel == GAIA_XY_Z_M)
2957 {
2958 buf_z = sqlite3_mprintf ("%.*f", precision, z);
2959 gaiaOutClean (buf_z);
2960 if (iv == 0)
2961 buf = sqlite3_mprintf ("%s,%s,%s", buf_x, buf_y, buf_z);
2962 else
2963 buf = sqlite3_mprintf (" %s,%s,%s", buf_x, buf_y, buf_z);
2964 sqlite3_free (buf_z);
2965 }
2966 else
2967 {
2968 if (iv == 0)
2969 buf = sqlite3_mprintf ("%s,%s", buf_x, buf_y);
2970 else
2971 buf = sqlite3_mprintf (" %s,%s", buf_x, buf_y);
2972 }
2973 sqlite3_free (buf_x);
2974 sqlite3_free (buf_y);
2975 gaiaAppendToOutBuffer (out_buf, buf);
2976 sqlite3_free (buf);
2977 }
2978 gaiaAppendToOutBuffer (out_buf,
2979 "</coordinates></LinearRing></outerBoundaryIs>");
2980 for (ib = 0; ib < polygon->NumInteriors; ib++)
2981 {
2982 /* interior rings */
2983 ring = polygon->Interiors + ib;
2984 gaiaAppendToOutBuffer (out_buf,
2985 "<innerBoundaryIs><LinearRing><coordinates>");
2986 for (iv = 0; iv < ring->Points; iv++)
2987 {
2988 /* exporting vertices [Interior Ring] */
2989 if (ring->DimensionModel == GAIA_XY_Z)
2990 {
2991 gaiaGetPointXYZ (ring->Coords, iv, &x, &y, &z);
2992 }
2993 else if (ring->DimensionModel == GAIA_XY_M)
2994 {
2995 gaiaGetPointXYM (ring->Coords, iv, &x, &y, &m);
2996 }
2997 else if (ring->DimensionModel == GAIA_XY_Z_M)
2998 {
2999 gaiaGetPointXYZM (ring->Coords, iv, &x, &y, &z, &m);
3000 }
3001 else
3002 {
3003 gaiaGetPoint (ring->Coords, iv, &x, &y);
3004 }
3005 buf_x = sqlite3_mprintf ("%.*f", precision, x);
3006 gaiaOutClean (buf_x);
3007 buf_y = sqlite3_mprintf ("%.*f", precision, y);
3008 gaiaOutClean (buf_y);
3009 if (ring->DimensionModel == GAIA_XY_Z
3010 || ring->DimensionModel == GAIA_XY_Z_M)
3011 {
3012 buf_z = sqlite3_mprintf ("%.*f", precision, z);
3013 gaiaOutClean (buf_z);
3014 if (iv == 0)
3015 buf =
3016 sqlite3_mprintf ("%s,%s,%s", buf_x, buf_y, buf_z);
3017 else
3018 buf =
3019 sqlite3_mprintf (" %s,%s,%s", buf_x, buf_y,
3020 buf_z);
3021 sqlite3_free (buf_z);
3022 }
3023 else
3024 {
3025 if (iv == 0)
3026 buf = sqlite3_mprintf ("%s,%s", buf_x, buf_y);
3027 else
3028 buf = sqlite3_mprintf (" %s,%s", buf_x, buf_y);
3029 }
3030 sqlite3_free (buf_x);
3031 sqlite3_free (buf_y);
3032 gaiaAppendToOutBuffer (out_buf, buf);
3033 sqlite3_free (buf);
3034 }
3035 gaiaAppendToOutBuffer (out_buf,
3036 "</coordinates></LinearRing></innerBoundaryIs>");
3037 }
3038 gaiaAppendToOutBuffer (out_buf, "</Polygon>");
3039 }
3040
3041 GAIAGEO_DECLARE void
gaiaOutFullKml(gaiaOutBufferPtr out_buf,const char * name,const char * desc,gaiaGeomCollPtr geom,int precision)3042 gaiaOutFullKml (gaiaOutBufferPtr out_buf, const char *name, const char *desc,
3043 gaiaGeomCollPtr geom, int precision)
3044 {
3045 /* prints the 'full' KML representation of current geometry */
3046 gaiaPointPtr point;
3047 gaiaLinestringPtr line;
3048 gaiaPolygonPtr polyg;
3049 int count = 0;
3050 char *xml_clean;
3051 if (!geom)
3052 return;
3053 if (precision > 18)
3054 precision = 18;
3055
3056 /* counting how many elementary geometries are there */
3057 point = geom->FirstPoint;
3058 while (point)
3059 {
3060 count++;
3061 point = point->Next;
3062 }
3063 line = geom->FirstLinestring;
3064 while (line)
3065 {
3066 count++;
3067 line = line->Next;
3068 }
3069 polyg = geom->FirstPolygon;
3070 while (polyg)
3071 {
3072 count++;
3073 polyg = polyg->Next;
3074 }
3075 if (count == 1)
3076 {
3077 if (geom->DeclaredType == GAIA_MULTIPOINT ||
3078 geom->DeclaredType == GAIA_MULTILINESTRING ||
3079 geom->DeclaredType == GAIA_MULTIPOLYGON ||
3080 geom->DeclaredType == GAIA_GEOMETRYCOLLECTION)
3081 count = 2;
3082 }
3083
3084 gaiaAppendToOutBuffer (out_buf, "<Placemark><name>");
3085 xml_clean = XmlClean (name);
3086 if (xml_clean)
3087 {
3088 gaiaAppendToOutBuffer (out_buf, xml_clean);
3089 free (xml_clean);
3090 }
3091 else
3092 gaiaAppendToOutBuffer (out_buf, " ");
3093 gaiaAppendToOutBuffer (out_buf, "</name><description>");
3094 xml_clean = XmlClean (desc);
3095 if (xml_clean)
3096 {
3097 gaiaAppendToOutBuffer (out_buf, xml_clean);
3098 free (xml_clean);
3099 }
3100 else
3101 gaiaAppendToOutBuffer (out_buf, " ");
3102 gaiaAppendToOutBuffer (out_buf, "</description>");
3103
3104 if (count > 1)
3105 {
3106 /* MultiGeometry start */
3107 gaiaAppendToOutBuffer (out_buf, "<MultiGeometry>");
3108 }
3109
3110 point = geom->FirstPoint;
3111 while (point)
3112 {
3113 /* processing POINT */
3114 out_kml_point (out_buf, point, precision);
3115 point = point->Next;
3116 }
3117 line = geom->FirstLinestring;
3118 while (line)
3119 {
3120 /* processing LINESTRING */
3121 out_kml_linestring (out_buf, line->DimensionModel,
3122 line->Points, line->Coords, precision);
3123 line = line->Next;
3124 }
3125 polyg = geom->FirstPolygon;
3126 while (polyg)
3127 {
3128 /* processing POLYGON */
3129 out_kml_polygon (out_buf, polyg, precision);
3130 polyg = polyg->Next;
3131 }
3132
3133 if (count > 1)
3134 {
3135 /* MultiGeometry end */
3136 gaiaAppendToOutBuffer (out_buf, "</MultiGeometry>");
3137 }
3138 gaiaAppendToOutBuffer (out_buf, "</Placemark>");
3139 }
3140
3141 GAIAGEO_DECLARE void
gaiaOutBareKml(gaiaOutBufferPtr out_buf,gaiaGeomCollPtr geom,int precision)3142 gaiaOutBareKml (gaiaOutBufferPtr out_buf, gaiaGeomCollPtr geom, int precision)
3143 {
3144 /* prints the 'bare' KML representation of current geometry */
3145 gaiaPointPtr point;
3146 gaiaLinestringPtr line;
3147 gaiaPolygonPtr polyg;
3148 int count = 0;
3149 if (!geom)
3150 return;
3151 if (precision > 18)
3152 precision = 18;
3153
3154 /* counting how many elementary geometries are there */
3155 point = geom->FirstPoint;
3156 while (point)
3157 {
3158 count++;
3159 point = point->Next;
3160 }
3161 line = geom->FirstLinestring;
3162 while (line)
3163 {
3164 count++;
3165 line = line->Next;
3166 }
3167 polyg = geom->FirstPolygon;
3168 while (polyg)
3169 {
3170 count++;
3171 polyg = polyg->Next;
3172 }
3173 if (count == 1)
3174 {
3175 if (geom->DeclaredType == GAIA_MULTIPOINT ||
3176 geom->DeclaredType == GAIA_MULTILINESTRING ||
3177 geom->DeclaredType == GAIA_MULTIPOLYGON ||
3178 geom->DeclaredType == GAIA_GEOMETRYCOLLECTION)
3179 count = 2;
3180 }
3181
3182 if (count > 1)
3183 {
3184 /* MultiGeometry start */
3185 gaiaAppendToOutBuffer (out_buf, "<MultiGeometry>");
3186 }
3187
3188 point = geom->FirstPoint;
3189 while (point)
3190 {
3191 /* processing POINT */
3192 out_kml_point (out_buf, point, precision);
3193 point = point->Next;
3194 }
3195 line = geom->FirstLinestring;
3196 while (line)
3197 {
3198 /* processing LINESTRING */
3199 out_kml_linestring (out_buf, line->DimensionModel, line->Points,
3200 line->Coords, precision);
3201 line = line->Next;
3202 }
3203 polyg = geom->FirstPolygon;
3204 while (polyg)
3205 {
3206 /* processing POLYGON */
3207 out_kml_polygon (out_buf, polyg, precision);
3208 polyg = polyg->Next;
3209 }
3210
3211 if (count > 1)
3212 {
3213 /* MultiGeometry end */
3214 gaiaAppendToOutBuffer (out_buf, "</MultiGeometry>");
3215 }
3216 }
3217
3218 GAIAGEO_DECLARE void
gaiaOutGml(gaiaOutBufferPtr out_buf,int version,int precision,gaiaGeomCollPtr geom)3219 gaiaOutGml (gaiaOutBufferPtr out_buf, int version, int precision,
3220 gaiaGeomCollPtr geom)
3221 {
3222 /*
3223 / prints the GML representation of current geometry
3224 / *result* returns the encoded GML or NULL if any error is encountered
3225 */
3226 gaiaPointPtr point;
3227 gaiaLinestringPtr line;
3228 gaiaPolygonPtr polyg;
3229 gaiaRingPtr ring;
3230 int iv;
3231 int ib;
3232 double x;
3233 double y;
3234 double z;
3235 double m;
3236 int has_z;
3237 int is_multi = 1;
3238 int is_coll = 0;
3239 char buf[2048];
3240 char *xbuf;
3241 char *buf_x;
3242 char *buf_y;
3243 char *buf_z;
3244 if (!geom)
3245 return;
3246 if (precision > 18)
3247 precision = 18;
3248
3249 switch (geom->DeclaredType)
3250 {
3251 case GAIA_POINT:
3252 case GAIA_LINESTRING:
3253 case GAIA_POLYGON:
3254 *buf = '\0';
3255 is_multi = 0;
3256 break;
3257 case GAIA_MULTIPOINT:
3258 if (geom->Srid <= 0)
3259 strcpy (buf, "<gml:MultiPoint>");
3260 else
3261 sprintf (buf, "<gml:MultiPoint srsName=\"EPSG:%d\">", geom->Srid);
3262 break;
3263 case GAIA_MULTILINESTRING:
3264 if (version == 3)
3265 {
3266 if (geom->Srid <= 0)
3267 strcpy (buf, "<gml:MultiCurve>");
3268 else
3269 sprintf (buf, "<gml:MultiCurve srsName=\"EPSG:%d\">",
3270 geom->Srid);
3271 }
3272 else
3273 {
3274 if (geom->Srid <= 0)
3275 strcpy (buf, "<gml:MultiLineString>");
3276 else
3277 sprintf (buf,
3278 "<gml:MultiLineString srsName=\"EPSG:%d\">",
3279 geom->Srid);
3280 }
3281 break;
3282 case GAIA_MULTIPOLYGON:
3283 if (version == 3)
3284 {
3285 if (geom->Srid <= 0)
3286 strcpy (buf, "<gml:MultiSurface>");
3287 else
3288 sprintf (buf, "<gml:MultiSurface srsName=\"EPSG:%d\">",
3289 geom->Srid);
3290 }
3291 else
3292 {
3293 if (geom->Srid <= 0)
3294 strcpy (buf, "<gml:MultiPolygon>");
3295 else
3296 sprintf (buf, "<gml:MultiPolygon srsName=\"EPSG:%d\">",
3297 geom->Srid);
3298 }
3299 break;
3300 default:
3301 if (geom->Srid <= 0)
3302 strcpy (buf, "<gml:MultiGeometry>");
3303 else
3304 sprintf (buf, "<gml:MultiGeometry srsName=\"EPSG:%d\">",
3305 geom->Srid);
3306 is_coll = 1;
3307 break;
3308 };
3309 gaiaAppendToOutBuffer (out_buf, buf);
3310 point = geom->FirstPoint;
3311 while (point)
3312 {
3313 /* processing POINT */
3314 if (is_multi)
3315 {
3316 if (is_coll)
3317 strcpy (buf, "<gml:geometryMember>");
3318 else
3319 strcpy (buf, "<gml:pointMember>");
3320 strcat (buf, "<gml:Point>");
3321 }
3322 else
3323 {
3324 if (geom->Srid <= 0)
3325 strcpy (buf, "<gml:Point>");
3326 else
3327 sprintf (buf, "<gml:Point srsName=\"EPSG:%d\">",
3328 geom->Srid);
3329 }
3330 if (version == 3)
3331 {
3332 if (point->DimensionModel == GAIA_XY_Z
3333 || point->DimensionModel == GAIA_XY_Z_M)
3334 strcat (buf, "<gml:pos srsDimension=\"3\">");
3335 else
3336 strcat (buf, "<gml:pos srsDimension=\"2\">");
3337 }
3338 else
3339 strcat (buf, "<gml:coordinates>");
3340 gaiaAppendToOutBuffer (out_buf, buf);
3341 buf_x = sqlite3_mprintf ("%.*f", precision, point->X);
3342 gaiaOutClean (buf_x);
3343 buf_y = sqlite3_mprintf ("%.*f", precision, point->Y);
3344 gaiaOutClean (buf_y);
3345 if (point->DimensionModel == GAIA_XY_Z
3346 || point->DimensionModel == GAIA_XY_Z_M)
3347 {
3348 buf_z = sqlite3_mprintf ("%.*f", precision, point->Z);
3349 gaiaOutClean (buf_z);
3350 if (version == 3)
3351 {
3352 xbuf = sqlite3_mprintf ("%s %s %s", buf_x, buf_y, buf_z);
3353 sqlite3_free (buf_x);
3354 sqlite3_free (buf_y);
3355 sqlite3_free (buf_z);
3356 }
3357 else
3358 {
3359 xbuf = sqlite3_mprintf ("%s,%s,%s", buf_x, buf_y, buf_z);
3360 sqlite3_free (buf_x);
3361 sqlite3_free (buf_y);
3362 sqlite3_free (buf_z);
3363 }
3364 }
3365 else
3366 {
3367 if (version == 3)
3368 {
3369 xbuf = sqlite3_mprintf ("%s %s", buf_x, buf_y);
3370 sqlite3_free (buf_x);
3371 sqlite3_free (buf_y);
3372 }
3373 else
3374 {
3375 xbuf = sqlite3_mprintf ("%s,%s", buf_x, buf_y);
3376 sqlite3_free (buf_x);
3377 sqlite3_free (buf_y);
3378 }
3379 }
3380 gaiaAppendToOutBuffer (out_buf, xbuf);
3381 sqlite3_free (xbuf);
3382 if (version == 3)
3383 strcpy (buf, "</gml:pos>");
3384 else
3385 strcpy (buf, "</gml:coordinates>");
3386 if (is_multi)
3387 {
3388 strcat (buf, "</gml:Point>");
3389 if (is_coll)
3390 strcat (buf, "</gml:geometryMember>");
3391 else
3392 strcat (buf, "</gml:pointMember>");
3393 }
3394 else
3395 strcat (buf, "</gml:Point>");
3396 gaiaAppendToOutBuffer (out_buf, buf);
3397 point = point->Next;
3398 }
3399 line = geom->FirstLinestring;
3400 while (line)
3401 {
3402 /* processing LINESTRING */
3403 if (is_multi)
3404 {
3405 if (version == 3)
3406 {
3407 if (is_coll)
3408 strcpy (buf, "<gml:geometryMember>");
3409 else
3410 strcpy (buf, "<gml:curveMember>");
3411 strcat (buf, "<gml:Curve>");
3412 strcat (buf, "<gml:segments>");
3413 strcat (buf, "<gml:LineStringSegment>");
3414 if (line->DimensionModel == GAIA_XY_Z
3415 || line->DimensionModel == GAIA_XY_Z_M)
3416 strcat (buf, "<gml:posList srsDimension=\"3\">");
3417 else
3418 strcat (buf, "<gml:posList srsDimension=\"2\">");
3419 }
3420 else
3421 {
3422 if (is_coll)
3423 strcpy (buf, "<gml:geometryMember>");
3424 else
3425 strcpy (buf, "<gml:lineStringMember>");
3426 strcat (buf, "<gml:LineString>");
3427 strcat (buf, "<gml:coordinates>");
3428 }
3429 }
3430 else
3431 {
3432 if (version == 3)
3433 {
3434 if (geom->Srid <= 0)
3435 strcpy (buf, "<gml:Curve>");
3436 else
3437 sprintf (buf, "<gml:Curve srsName=\"EPSG:%d\">",
3438 geom->Srid);
3439 strcat (buf, "<gml:segments>");
3440 strcat (buf, "<gml:LineStringSegment>");
3441 if (line->DimensionModel == GAIA_XY_Z
3442 || line->DimensionModel == GAIA_XY_Z_M)
3443 strcat (buf, "<gml:posList srsDimension=\"3\">");
3444 else
3445 strcat (buf, "<gml:posList srsDimension=\"2\">");
3446 }
3447 else
3448 {
3449 if (geom->Srid <= 0)
3450 strcpy (buf, "<gml:LineString>");
3451 else
3452 sprintf (buf, "<gml:LineString srsName=\"EPSG:%d\">",
3453 geom->Srid);
3454 strcat (buf, "<gml:coordinates>");
3455 }
3456 }
3457 gaiaAppendToOutBuffer (out_buf, buf);
3458 for (iv = 0; iv < line->Points; iv++)
3459 {
3460 /* exporting vertices */
3461 has_z = 0;
3462 z = 0.0;
3463 if (line->DimensionModel == GAIA_XY_Z)
3464 {
3465 has_z = 1;
3466 gaiaGetPointXYZ (line->Coords, iv, &x, &y, &z);
3467 }
3468 else if (line->DimensionModel == GAIA_XY_M)
3469 {
3470 gaiaGetPointXYM (line->Coords, iv, &x, &y, &m);
3471 }
3472 else if (line->DimensionModel == GAIA_XY_Z_M)
3473 {
3474 has_z = 1;
3475 gaiaGetPointXYZM (line->Coords, iv, &x, &y, &z, &m);
3476 }
3477 else
3478 {
3479 gaiaGetPoint (line->Coords, iv, &x, &y);
3480 }
3481 if (iv == 0)
3482 *buf = '\0';
3483 else
3484 strcpy (buf, " ");
3485 if (has_z)
3486 {
3487 buf_x = sqlite3_mprintf ("%.*f", precision, x);
3488 gaiaOutClean (buf_x);
3489 buf_y = sqlite3_mprintf ("%.*f", precision, y);
3490 gaiaOutClean (buf_y);
3491 buf_z = sqlite3_mprintf ("%.*f", precision, z);
3492 gaiaOutClean (buf_z);
3493 if (version == 3)
3494 {
3495 xbuf =
3496 sqlite3_mprintf ("%s%s %s %s", buf, buf_x,
3497 buf_y, buf_z);
3498 sqlite3_free (buf_x);
3499 sqlite3_free (buf_y);
3500 sqlite3_free (buf_z);
3501 }
3502 else
3503 {
3504 xbuf =
3505 sqlite3_mprintf ("%s%s,%s,%s", buf, buf_x,
3506 buf_y, buf_z);
3507 sqlite3_free (buf_x);
3508 sqlite3_free (buf_y);
3509 sqlite3_free (buf_z);
3510 }
3511 }
3512 else
3513 {
3514 buf_x = sqlite3_mprintf ("%.*f", precision, x);
3515 gaiaOutClean (buf_x);
3516 buf_y = sqlite3_mprintf ("%.*f", precision, y);
3517 gaiaOutClean (buf_y);
3518 if (version == 3)
3519 {
3520 xbuf =
3521 sqlite3_mprintf ("%s%s %s", buf, buf_x, buf_y);
3522 sqlite3_free (buf_x);
3523 sqlite3_free (buf_y);
3524 }
3525 else
3526 {
3527 xbuf =
3528 sqlite3_mprintf ("%s%s,%s", buf, buf_x, buf_y);
3529 sqlite3_free (buf_x);
3530 sqlite3_free (buf_y);
3531 }
3532 }
3533 gaiaAppendToOutBuffer (out_buf, xbuf);
3534 sqlite3_free (xbuf);
3535 }
3536 if (is_multi)
3537 {
3538 if (version == 3)
3539 {
3540 strcpy (buf, "</gml:posList>");
3541 strcat (buf, "</gml:LineStringSegment>");
3542 strcat (buf, "</gml:segments>");
3543 strcat (buf, "</gml:Curve>");
3544 if (is_coll)
3545 strcat (buf, "</gml:geometryMember>");
3546 else
3547 strcat (buf, "</gml:curveMember>");
3548 }
3549 else
3550 {
3551 strcpy (buf, "</gml:coordinates>");
3552 strcat (buf, "</gml:LineString>");
3553 if (is_coll)
3554 strcat (buf, "</gml:geometryMember>");
3555 else
3556 strcat (buf, "</gml:lineStringMember>");
3557 }
3558 }
3559 else
3560 {
3561 if (version == 3)
3562 {
3563 strcpy (buf, "</gml:posList>");
3564 strcat (buf, "</gml:LineStringSegment>");
3565 strcat (buf, "</gml:segments>");
3566 strcat (buf, "</gml:Curve>");
3567 }
3568 else
3569 {
3570 strcpy (buf, "</gml:coordinates>");
3571 strcat (buf, "</gml:LineString>");
3572 }
3573 }
3574 gaiaAppendToOutBuffer (out_buf, buf);
3575 line = line->Next;
3576 }
3577 polyg = geom->FirstPolygon;
3578 while (polyg)
3579 {
3580 /* processing POLYGON */
3581 ring = polyg->Exterior;
3582 if (is_multi)
3583 {
3584 if (version == 3)
3585 {
3586 if (is_coll)
3587 strcpy (buf, "<gml:geometryMember>");
3588 else
3589 strcpy (buf, "<gml:surfaceMember>");
3590 strcat (buf, "<gml:Polygon>");
3591 strcat (buf, "<gml:exterior>");
3592 strcat (buf, "<gml:LinearRing>");
3593 if (ring->DimensionModel == GAIA_XY_Z
3594 || ring->DimensionModel == GAIA_XY_Z_M)
3595 strcat (buf, "<gml:posList srsDimension=\"3\">");
3596 else
3597 strcat (buf, "<gml:posList srsDimension=\"2\">");
3598 }
3599 else
3600 {
3601 if (is_coll)
3602 strcpy (buf, "<gml:geometryMember>");
3603 else
3604 strcpy (buf, "<gml:polygonMember>");
3605 strcat (buf, "<gml:Polygon>");
3606 strcat (buf, "<gml:outerBoundaryIs>");
3607 strcat (buf, "<gml:LinearRing>");
3608 strcat (buf, "<gml:coordinates>");
3609 }
3610 }
3611 else
3612 {
3613 if (geom->Srid <= 0)
3614 strcpy (buf, "<gml:Polygon>");
3615 else
3616 sprintf (buf, "<gml:Polygon srsName=\"EPSG:%d\">",
3617 geom->Srid);
3618 if (version == 3)
3619 {
3620 strcat (buf, "<gml:exterior>");
3621 strcat (buf, "<gml:LinearRing>");
3622 if (ring->DimensionModel == GAIA_XY_Z
3623 || ring->DimensionModel == GAIA_XY_Z_M)
3624 strcat (buf, "<gml:posList srsDimension=\"3\">");
3625 else
3626 strcat (buf, "<gml:posList srsDimension=\"2\">");
3627 }
3628 else
3629 {
3630 strcat (buf, "<gml:outerBoundaryIs>");
3631 strcat (buf, "<gml:LinearRing>");
3632 strcat (buf, "<gml:coordinates>");
3633 }
3634 }
3635 gaiaAppendToOutBuffer (out_buf, buf);
3636 for (iv = 0; iv < ring->Points; iv++)
3637 {
3638 /* exporting vertices [Interior Ring] */
3639 has_z = 0;
3640 z = 0.0;
3641 if (ring->DimensionModel == GAIA_XY_Z)
3642 {
3643 has_z = 1;
3644 gaiaGetPointXYZ (ring->Coords, iv, &x, &y, &z);
3645 }
3646 else if (ring->DimensionModel == GAIA_XY_M)
3647 {
3648 gaiaGetPointXYM (ring->Coords, iv, &x, &y, &m);
3649 }
3650 else if (ring->DimensionModel == GAIA_XY_Z_M)
3651 {
3652 has_z = 1;
3653 gaiaGetPointXYZM (ring->Coords, iv, &x, &y, &z, &m);
3654 }
3655 else
3656 {
3657 gaiaGetPoint (ring->Coords, iv, &x, &y);
3658 }
3659 if (iv == 0)
3660 *buf = '\0';
3661 else
3662 strcpy (buf, " ");
3663 if (has_z)
3664 {
3665 buf_x = sqlite3_mprintf ("%.*f", precision, x);
3666 gaiaOutClean (buf_x);
3667 buf_y = sqlite3_mprintf ("%.*f", precision, y);
3668 gaiaOutClean (buf_y);
3669 buf_z = sqlite3_mprintf ("%.*f", precision, z);
3670 gaiaOutClean (buf_z);
3671 if (version == 3)
3672 {
3673 xbuf =
3674 sqlite3_mprintf ("%s%s %s %s", buf, buf_x,
3675 buf_y, buf_z);
3676 sqlite3_free (buf_x);
3677 sqlite3_free (buf_y);
3678 sqlite3_free (buf_z);
3679 }
3680 else
3681 {
3682 xbuf =
3683 sqlite3_mprintf ("%s%s,%s,%s", buf, buf_x,
3684 buf_y, buf_z);
3685 sqlite3_free (buf_x);
3686 sqlite3_free (buf_y);
3687 sqlite3_free (buf_z);
3688 }
3689 }
3690 else
3691 {
3692 buf_x = sqlite3_mprintf ("%.*f", precision, x);
3693 gaiaOutClean (buf_x);
3694 buf_y = sqlite3_mprintf ("%.*f", precision, y);
3695 gaiaOutClean (buf_y);
3696 if (version == 3)
3697 {
3698 xbuf =
3699 sqlite3_mprintf ("%s%s %s", buf, buf_x, buf_y);
3700 sqlite3_free (buf_x);
3701 sqlite3_free (buf_y);
3702 }
3703 else
3704 {
3705 xbuf =
3706 sqlite3_mprintf ("%s%s,%s", buf, buf_x, buf_y);
3707 sqlite3_free (buf_x);
3708 sqlite3_free (buf_y);
3709 }
3710 }
3711 gaiaAppendToOutBuffer (out_buf, xbuf);
3712 sqlite3_free (xbuf);
3713 }
3714 /* closing the Exterior Ring */
3715 if (version == 3)
3716 {
3717 strcpy (buf, "</gml:posList>");
3718 strcat (buf, "</gml:LinearRing>");
3719 strcat (buf, "</gml:exterior>");
3720 }
3721 else
3722 {
3723 strcpy (buf, "</gml:coordinates>");
3724 strcat (buf, "</gml:LinearRing>");
3725 strcat (buf, "</gml:outerBoundaryIs>");
3726 }
3727 gaiaAppendToOutBuffer (out_buf, buf);
3728 for (ib = 0; ib < polyg->NumInteriors; ib++)
3729 {
3730 /* interior rings */
3731 ring = polyg->Interiors + ib;
3732 if (version == 3)
3733 {
3734 strcpy (buf, "<gml:interior>");
3735 strcat (buf, "<gml:LinearRing>");
3736 if (ring->DimensionModel == GAIA_XY_Z
3737 || ring->DimensionModel == GAIA_XY_Z_M)
3738 strcat (buf, "<gml:posList srsDimension=\"3\">");
3739 else
3740 strcat (buf, "<gml:posList srsDimension=\"2\">");
3741 }
3742 else
3743 {
3744 strcpy (buf, "<gml:innerBoundaryIs>");
3745 strcat (buf, "<gml:LinearRing>");
3746 strcat (buf, "<gml:coordinates>");
3747 }
3748 gaiaAppendToOutBuffer (out_buf, buf);
3749 for (iv = 0; iv < ring->Points; iv++)
3750 {
3751 /* exporting vertices [Interior Ring] */
3752 has_z = 0;
3753 z = 0.0;
3754 if (ring->DimensionModel == GAIA_XY_Z)
3755 {
3756 has_z = 1;
3757 gaiaGetPointXYZ (ring->Coords, iv, &x, &y, &z);
3758 }
3759 else if (ring->DimensionModel == GAIA_XY_M)
3760 {
3761 gaiaGetPointXYM (ring->Coords, iv, &x, &y, &m);
3762 }
3763 else if (ring->DimensionModel == GAIA_XY_Z_M)
3764 {
3765 has_z = 1;
3766 gaiaGetPointXYZM (ring->Coords, iv, &x, &y, &z, &m);
3767 }
3768 else
3769 {
3770 gaiaGetPoint (ring->Coords, iv, &x, &y);
3771 }
3772 if (iv == 0)
3773 *buf = '\0';
3774 else
3775 strcpy (buf, " ");
3776 if (has_z)
3777 {
3778 buf_x = sqlite3_mprintf ("%.*f", precision, x);
3779 gaiaOutClean (buf_x);
3780 buf_y = sqlite3_mprintf ("%.*f", precision, y);
3781 gaiaOutClean (buf_y);
3782 buf_z = sqlite3_mprintf ("%.*f", precision, z);
3783 gaiaOutClean (buf_z);
3784 if (version == 3)
3785 {
3786 xbuf =
3787 sqlite3_mprintf ("%s%s %s %s", buf, buf_x,
3788 buf_y, buf_z);
3789 sqlite3_free (buf_x);
3790 sqlite3_free (buf_y);
3791 sqlite3_free (buf_z);
3792 }
3793 else
3794 {
3795 xbuf =
3796 sqlite3_mprintf ("%s%s,%s,%s", buf, buf_x,
3797 buf_y, buf_z);
3798 sqlite3_free (buf_x);
3799 sqlite3_free (buf_y);
3800 sqlite3_free (buf_z);
3801 }
3802 }
3803 else
3804 {
3805 buf_x = sqlite3_mprintf ("%.*f", precision, x);
3806 gaiaOutClean (buf_x);
3807 buf_y = sqlite3_mprintf ("%.*f", precision, y);
3808 gaiaOutClean (buf_y);
3809 if (version == 3)
3810 {
3811 xbuf =
3812 sqlite3_mprintf ("%s%s %s", buf, buf_x,
3813 buf_y);
3814 sqlite3_free (buf_x);
3815 sqlite3_free (buf_y);
3816 }
3817 else
3818 {
3819 xbuf =
3820 sqlite3_mprintf ("%s%s,%s", buf, buf_x,
3821 buf_y);
3822 sqlite3_free (buf_x);
3823 sqlite3_free (buf_y);
3824 }
3825 }
3826 gaiaAppendToOutBuffer (out_buf, xbuf);
3827 sqlite3_free (xbuf);
3828 }
3829 /* closing the Interior Ring */
3830 if (version == 3)
3831 {
3832 strcpy (buf, "</gml:posList>");
3833 strcat (buf, "</gml:LinearRing>");
3834 strcat (buf, "</gml:interior>");
3835 }
3836 else
3837 {
3838 strcpy (buf, "</gml:coordinates>");
3839 strcat (buf, "</gml:LinearRing>");
3840 strcat (buf, "</gml:innerBoundaryIs>");
3841 }
3842 gaiaAppendToOutBuffer (out_buf, buf);
3843 }
3844 /* closing the Polygon */
3845 if (is_multi)
3846 {
3847 if (version == 3)
3848 {
3849 strcpy (buf, "</gml:Polygon>");
3850 if (is_coll)
3851 strcat (buf, "</gml:geometryMember>");
3852 else
3853 strcat (buf, "</gml:surfaceMember>");
3854 }
3855 else
3856 {
3857 strcpy (buf, "</gml:Polygon>");
3858 if (is_coll)
3859 strcat (buf, "</gml:geometryMember>");
3860 else
3861 strcat (buf, "</gml:polygonMember>");
3862 }
3863 }
3864 else
3865 strcpy (buf, "</gml:Polygon>");
3866 gaiaAppendToOutBuffer (out_buf, buf);
3867 polyg = polyg->Next;
3868 }
3869 switch (geom->DeclaredType)
3870 {
3871 case GAIA_POINT:
3872 case GAIA_LINESTRING:
3873 case GAIA_POLYGON:
3874 *buf = '\0';
3875 break;
3876 case GAIA_MULTIPOINT:
3877 sprintf (buf, "</gml:MultiPoint>");
3878 break;
3879 case GAIA_MULTILINESTRING:
3880 if (version == 3)
3881 sprintf (buf, "</gml:MultiCurve>");
3882 else
3883 sprintf (buf, "</gml:MultiLineString>");
3884 break;
3885 case GAIA_MULTIPOLYGON:
3886 if (version == 3)
3887 sprintf (buf, "</gml:MultiSurface>");
3888 else
3889 sprintf (buf, "</gml:MultiPolygon>");
3890 break;
3891 default:
3892 sprintf (buf, "</gml:MultiGeometry>");
3893 break;
3894 };
3895 gaiaAppendToOutBuffer (out_buf, buf);
3896 }
3897
3898 GAIAGEO_DECLARE void
gaiaOutGeoJSON(gaiaOutBufferPtr out_buf,gaiaGeomCollPtr geom,int precision,int options)3899 gaiaOutGeoJSON (gaiaOutBufferPtr out_buf, gaiaGeomCollPtr geom, int precision,
3900 int options)
3901 {
3902 /*
3903 / prints the GeoJSON representation of current geometry
3904 / *result* returns the encoded GeoJSON or NULL if any error is encountered
3905 */
3906 gaiaPointPtr point;
3907 gaiaLinestringPtr line;
3908 gaiaPolygonPtr polyg;
3909 gaiaRingPtr ring;
3910 int iv;
3911 int ib;
3912 double x;
3913 double y;
3914 double z;
3915 double m;
3916 int has_z;
3917 int is_multi = 0;
3918 int multi_count = 0;
3919 char *bbox;
3920 char crs[2048];
3921 char *buf;
3922 char *buf_x;
3923 char *buf_y;
3924 char *buf_m;
3925 char *buf_z = NULL;
3926 char endJson[16];
3927 if (!geom)
3928 return;
3929 if (precision > 18)
3930 precision = 18;
3931
3932 if (options != 0)
3933 {
3934 bbox = NULL;
3935 *crs = '\0';
3936 if (geom->Srid > 0)
3937 {
3938 if (options == 2 || options == 3)
3939 {
3940 /* including short CRS */
3941 sprintf (crs,
3942 ",\"crs\":{\"type\":\"name\",\"properties\":{\"name\":\"EPSG:%d\"}}",
3943 geom->Srid);
3944 }
3945 if (options == 4 || options == 5)
3946 {
3947 /* including long CRS */
3948 sprintf (crs,
3949 ",\"crs\":{\"type\":\"name\",\"properties\":{\"name\":\"urn:ogc:def:crs:EPSG:%d\"}}",
3950 geom->Srid);
3951 }
3952 }
3953 if (options == 1 || options == 3 || options == 5)
3954 {
3955 /* including BBOX */
3956 gaiaMbrGeometry (geom);
3957 buf_x = sqlite3_mprintf ("%.*f", precision, geom->MinX);
3958 gaiaOutClean (buf_x);
3959 buf_y = sqlite3_mprintf ("%.*f", precision, geom->MinY);
3960 gaiaOutClean (buf_y);
3961 buf_z = sqlite3_mprintf ("%.*f", precision, geom->MaxX);
3962 gaiaOutClean (buf_z);
3963 buf_m = sqlite3_mprintf ("%.*f", precision, geom->MaxY);
3964 gaiaOutClean (buf_m);
3965 bbox =
3966 sqlite3_mprintf (",\"bbox\":[%s,%s,%s,%s]", buf_x, buf_y,
3967 buf_z, buf_m);
3968 sqlite3_free (buf_x);
3969 sqlite3_free (buf_y);
3970 sqlite3_free (buf_z);
3971 sqlite3_free (buf_m);
3972 }
3973 switch (geom->DeclaredType)
3974 {
3975 case GAIA_POINT:
3976 buf =
3977 sqlite3_mprintf ("{\"type\":\"Point\"%s%s,\"coordinates\":",
3978 crs, bbox);
3979 strcpy (endJson, "}");
3980 break;
3981 case GAIA_LINESTRING:
3982 buf =
3983 sqlite3_mprintf
3984 ("{\"type\":\"LineString\"%s%s,\"coordinates\":[", crs,
3985 bbox);
3986 strcpy (endJson, "}");
3987 break;
3988 case GAIA_POLYGON:
3989 buf =
3990 sqlite3_mprintf
3991 ("{\"type\":\"Polygon\"%s%s,\"coordinates\":[", crs, bbox);
3992 strcpy (endJson, "}");
3993 break;
3994 case GAIA_MULTIPOINT:
3995 buf =
3996 sqlite3_mprintf
3997 ("{\"type\":\"MultiPoint\"%s%s,\"coordinates\":[", crs,
3998 bbox);
3999 strcpy (endJson, "]}");
4000 break;
4001 case GAIA_MULTILINESTRING:
4002 buf =
4003 sqlite3_mprintf
4004 ("{\"type\":\"MultiLineString\"%s%s,\"coordinates\":[[",
4005 crs, bbox);
4006 strcpy (endJson, "]}");
4007 break;
4008 case GAIA_MULTIPOLYGON:
4009 buf =
4010 sqlite3_mprintf
4011 ("{\"type\":\"MultiPolygon\"%s%s,\"coordinates\":[[", crs,
4012 bbox);
4013 strcpy (endJson, "]}");
4014 break;
4015 default:
4016 buf =
4017 sqlite3_mprintf
4018 ("{\"type\":\"GeometryCollection\"%s%s,\"geometries\":[",
4019 crs, bbox);
4020 strcpy (endJson, "]}");
4021 is_multi = 1;
4022 break;
4023 };
4024 if (bbox)
4025 sqlite3_free (bbox);
4026 }
4027 else
4028 {
4029 /* omitting BBOX */
4030 switch (geom->DeclaredType)
4031 {
4032 case GAIA_POINT:
4033 buf = sqlite3_mprintf ("{\"type\":\"Point\",\"coordinates\":");
4034 strcpy (endJson, "}");
4035 break;
4036 case GAIA_LINESTRING:
4037 buf =
4038 sqlite3_mprintf
4039 ("{\"type\":\"LineString\",\"coordinates\":[");
4040 strcpy (endJson, "}");
4041 break;
4042 case GAIA_POLYGON:
4043 buf =
4044 sqlite3_mprintf ("{\"type\":\"Polygon\",\"coordinates\":[");
4045 strcpy (endJson, "}");
4046 break;
4047 case GAIA_MULTIPOINT:
4048 buf =
4049 sqlite3_mprintf
4050 ("{\"type\":\"MultiPoint\",\"coordinates\":[");
4051 strcpy (endJson, "]}");
4052 break;
4053 case GAIA_MULTILINESTRING:
4054 buf =
4055 sqlite3_mprintf
4056 ("{\"type\":\"MultiLineString\",\"coordinates\":[[");
4057 strcpy (endJson, "]}");
4058 break;
4059 case GAIA_MULTIPOLYGON:
4060 buf =
4061 sqlite3_mprintf
4062 ("{\"type\":\"MultiPolygon\",\"coordinates\":[[");
4063 strcpy (endJson, "]}");
4064 break;
4065 default:
4066 buf =
4067 sqlite3_mprintf
4068 ("{\"type\":\"GeometryCollection\",\"geometries\":[");
4069 strcpy (endJson, "]}");
4070 is_multi = 1;
4071 break;
4072 };
4073 }
4074 gaiaAppendToOutBuffer (out_buf, buf);
4075 sqlite3_free (buf);
4076 point = geom->FirstPoint;
4077 while (point)
4078 {
4079 /* processing POINT */
4080 if (is_multi)
4081 {
4082 if (multi_count > 0)
4083 buf = ",{\"type\":\"Point\",\"coordinates\":";
4084 else
4085 buf = "{\"type\":\"Point\",\"coordinates\":";
4086 gaiaAppendToOutBuffer (out_buf, buf);
4087 }
4088 else if (point != geom->FirstPoint)
4089 {
4090 /* adding a further Point */
4091 gaiaAppendToOutBuffer (out_buf, ",");
4092 }
4093 buf_x = sqlite3_mprintf ("%.*f", precision, point->X);
4094 gaiaOutClean (buf_x);
4095 buf_y = sqlite3_mprintf ("%.*f", precision, point->Y);
4096 gaiaOutClean (buf_y);
4097 has_z = 0;
4098 if (point->DimensionModel == GAIA_XY_Z
4099 || point->DimensionModel == GAIA_XY_Z_M)
4100 {
4101 buf_z = sqlite3_mprintf ("%.*f", precision, point->Z);
4102 gaiaOutClean (buf_z);
4103 has_z = 1;
4104 }
4105 if (has_z)
4106 {
4107 buf = sqlite3_mprintf ("[%s,%s,%s]", buf_x, buf_y, buf_z);
4108 sqlite3_free (buf_x);
4109 sqlite3_free (buf_y);
4110 sqlite3_free (buf_z);
4111 }
4112 else
4113 {
4114 buf = sqlite3_mprintf ("[%s,%s]", buf_x, buf_y);
4115 sqlite3_free (buf_x);
4116 sqlite3_free (buf_y);
4117 }
4118 gaiaAppendToOutBuffer (out_buf, buf);
4119 sqlite3_free (buf);
4120 if (is_multi)
4121 {
4122 gaiaAppendToOutBuffer (out_buf, "}");
4123 multi_count++;
4124 }
4125 point = point->Next;
4126 }
4127 line = geom->FirstLinestring;
4128 while (line)
4129 {
4130 /* processing LINESTRING */
4131 if (is_multi)
4132 {
4133 if (multi_count > 0)
4134 buf = ",{\"type\":\"LineString\",\"coordinates\":[";
4135 else
4136 buf = "{\"type\":\"LineString\",\"coordinates\":[";
4137 gaiaAppendToOutBuffer (out_buf, buf);
4138 }
4139 else if (line != geom->FirstLinestring)
4140 {
4141 /* opening a further LineString */
4142 gaiaAppendToOutBuffer (out_buf, ",[");
4143 }
4144 for (iv = 0; iv < line->Points; iv++)
4145 {
4146 /* exporting vertices */
4147 has_z = 0;
4148 z = 0.0;
4149 if (line->DimensionModel == GAIA_XY_Z)
4150 {
4151 has_z = 1;
4152 gaiaGetPointXYZ (line->Coords, iv, &x, &y, &z);
4153 }
4154 else if (line->DimensionModel == GAIA_XY_M)
4155 {
4156 gaiaGetPointXYM (line->Coords, iv, &x, &y, &m);
4157 }
4158 else if (line->DimensionModel == GAIA_XY_Z_M)
4159 {
4160 has_z = 1;
4161 gaiaGetPointXYZM (line->Coords, iv, &x, &y, &z, &m);
4162 }
4163 else
4164 {
4165 gaiaGetPoint (line->Coords, iv, &x, &y);
4166 }
4167 if (has_z)
4168 {
4169 buf_x = sqlite3_mprintf ("%.*f", precision, x);
4170 gaiaOutClean (buf_x);
4171 buf_y = sqlite3_mprintf ("%.*f", precision, y);
4172 gaiaOutClean (buf_y);
4173 buf_z = sqlite3_mprintf ("%.*f", precision, z);
4174 gaiaOutClean (buf_z);
4175 if (iv == 0)
4176 buf =
4177 sqlite3_mprintf ("[%s,%s,%s]", buf_x, buf_y,
4178 buf_z);
4179 else
4180 buf =
4181 sqlite3_mprintf (",[%s,%s,%s]", buf_x, buf_y,
4182 buf_z);
4183 sqlite3_free (buf_x);
4184 sqlite3_free (buf_y);
4185 sqlite3_free (buf_z);
4186 }
4187 else
4188 {
4189 buf_x = sqlite3_mprintf ("%.*f", precision, x);
4190 gaiaOutClean (buf_x);
4191 buf_y = sqlite3_mprintf ("%.*f", precision, y);
4192 gaiaOutClean (buf_y);
4193 if (iv == 0)
4194 buf = sqlite3_mprintf ("[%s,%s]", buf_x, buf_y);
4195 else
4196 buf = sqlite3_mprintf (",[%s,%s]", buf_x, buf_y);
4197 sqlite3_free (buf_x);
4198 sqlite3_free (buf_y);
4199 }
4200 gaiaAppendToOutBuffer (out_buf, buf);
4201 sqlite3_free (buf);
4202 }
4203 /* closing the LineString */
4204 gaiaAppendToOutBuffer (out_buf, "]");
4205 if (is_multi)
4206 {
4207 gaiaAppendToOutBuffer (out_buf, "}");
4208 multi_count++;
4209 }
4210 line = line->Next;
4211 }
4212 polyg = geom->FirstPolygon;
4213 while (polyg)
4214 {
4215 /* processing POLYGON */
4216 if (is_multi)
4217 {
4218 if (multi_count > 0)
4219 buf = ",{\"type\":\"Polygon\",\"coordinates\":[";
4220 else
4221 buf = "{\"type\":\"Polygon\",\"coordinates\":[";
4222 gaiaAppendToOutBuffer (out_buf, buf);
4223 }
4224 else if (polyg != geom->FirstPolygon)
4225 {
4226 /* opening a further Polygon */
4227 gaiaAppendToOutBuffer (out_buf, ",[");
4228 }
4229 ring = polyg->Exterior;
4230 for (iv = 0; iv < ring->Points; iv++)
4231 {
4232 /* exporting vertices [Interior Ring] */
4233 has_z = 0;
4234 z = 0.0;
4235 if (ring->DimensionModel == GAIA_XY_Z)
4236 {
4237 has_z = 1;
4238 gaiaGetPointXYZ (ring->Coords, iv, &x, &y, &z);
4239 }
4240 else if (ring->DimensionModel == GAIA_XY_M)
4241 {
4242 gaiaGetPointXYM (ring->Coords, iv, &x, &y, &m);
4243 }
4244 else if (ring->DimensionModel == GAIA_XY_Z_M)
4245 {
4246 has_z = 1;
4247 gaiaGetPointXYZM (ring->Coords, iv, &x, &y, &z, &m);
4248 }
4249 else
4250 {
4251 gaiaGetPoint (ring->Coords, iv, &x, &y);
4252 }
4253 if (has_z)
4254 {
4255 buf_x = sqlite3_mprintf ("%.*f", precision, x);
4256 gaiaOutClean (buf_x);
4257 buf_y = sqlite3_mprintf ("%.*f", precision, y);
4258 gaiaOutClean (buf_y);
4259 buf_z = sqlite3_mprintf ("%.*f", precision, z);
4260 gaiaOutClean (buf_z);
4261 if (iv == 0)
4262 buf =
4263 sqlite3_mprintf ("[[%s,%s,%s]", buf_x, buf_y,
4264 buf_z);
4265 else
4266 buf =
4267 sqlite3_mprintf (",[%s,%s,%s]", buf_x, buf_y,
4268 buf_z);
4269 sqlite3_free (buf_x);
4270 sqlite3_free (buf_y);
4271 sqlite3_free (buf_z);
4272 }
4273 else
4274 {
4275 buf_x = sqlite3_mprintf ("%.*f", precision, x);
4276 gaiaOutClean (buf_x);
4277 buf_y = sqlite3_mprintf ("%.*f", precision, y);
4278 gaiaOutClean (buf_y);
4279 if (iv == 0)
4280 buf = sqlite3_mprintf ("[[%s,%s]", buf_x, buf_y);
4281 else
4282 buf = sqlite3_mprintf (",[%s,%s]", buf_x, buf_y);
4283 sqlite3_free (buf_x);
4284 sqlite3_free (buf_y);
4285 }
4286 gaiaAppendToOutBuffer (out_buf, buf);
4287 sqlite3_free (buf);
4288 }
4289 /* closing the Exterior Ring */
4290 gaiaAppendToOutBuffer (out_buf, "]");
4291 for (ib = 0; ib < polyg->NumInteriors; ib++)
4292 {
4293 /* interior rings */
4294 ring = polyg->Interiors + ib;
4295 for (iv = 0; iv < ring->Points; iv++)
4296 {
4297 /* exporting vertices [Interior Ring] */
4298 has_z = 0;
4299 z = 0.0;
4300 if (ring->DimensionModel == GAIA_XY_Z)
4301 {
4302 has_z = 1;
4303 gaiaGetPointXYZ (ring->Coords, iv, &x, &y, &z);
4304 }
4305 else if (ring->DimensionModel == GAIA_XY_M)
4306 {
4307 gaiaGetPointXYM (ring->Coords, iv, &x, &y, &m);
4308 }
4309 else if (ring->DimensionModel == GAIA_XY_Z_M)
4310 {
4311 has_z = 1;
4312 gaiaGetPointXYZM (ring->Coords, iv, &x, &y, &z, &m);
4313 }
4314 else
4315 {
4316 gaiaGetPoint (ring->Coords, iv, &x, &y);
4317 }
4318 if (has_z)
4319 {
4320 buf_x = sqlite3_mprintf ("%.*f", precision, x);
4321 gaiaOutClean (buf_x);
4322 buf_y = sqlite3_mprintf ("%.*f", precision, y);
4323 gaiaOutClean (buf_y);
4324 buf_z = sqlite3_mprintf ("%.*f", precision, z);
4325 gaiaOutClean (buf_z);
4326 if (iv == 0)
4327 buf =
4328 sqlite3_mprintf (",[[%s,%s,%s]", buf_x,
4329 buf_y, buf_z);
4330 else
4331 buf =
4332 sqlite3_mprintf (",[%s,%s,%s]", buf_x,
4333 buf_y, buf_z);
4334 sqlite3_free (buf_x);
4335 sqlite3_free (buf_y);
4336 sqlite3_free (buf_z);
4337 }
4338 else
4339 {
4340 buf_x = sqlite3_mprintf ("%.*f", precision, x);
4341 gaiaOutClean (buf_x);
4342 buf_y = sqlite3_mprintf ("%.*f", precision, y);
4343 gaiaOutClean (buf_y);
4344 if (iv == 0)
4345 buf =
4346 sqlite3_mprintf (",[[%s,%s]", buf_x, buf_y);
4347 else
4348 buf =
4349 sqlite3_mprintf (",[%s,%s]", buf_x, buf_y);
4350 sqlite3_free (buf_x);
4351 sqlite3_free (buf_y);
4352 }
4353 gaiaAppendToOutBuffer (out_buf, buf);
4354 sqlite3_free (buf);
4355 }
4356 /* closing the Interior Ring */
4357 gaiaAppendToOutBuffer (out_buf, "]");
4358 }
4359 /* closing the Polygon */
4360 gaiaAppendToOutBuffer (out_buf, "]");
4361 if (is_multi)
4362 {
4363 gaiaAppendToOutBuffer (out_buf, "}");
4364 multi_count++;
4365 }
4366 polyg = polyg->Next;
4367 }
4368 gaiaAppendToOutBuffer (out_buf, endJson);
4369 }
4370