PostGIS  2.2.7dev-r@@SVN_REVISION@@
lwout_x3d.c
Go to the documentation of this file.
1 /**********************************************************************
2  *
3  * PostGIS - Spatial Types for PostgreSQL
4  * http://postgis.net
5  * adapted from lwout_asgml.c
6  * Copyright 2011-2015 Arrival 3D
7  * Regina Obe with input from Dave Arendash
8  *
9  * This is free software; you can redistribute and/or modify it under
10  * the terms of the GNU General Public Licence. See the COPYING file.
11  *
12  **********************************************************************/
19 #include <string.h>
20 #include "liblwgeom_internal.h"
21 
23 static size_t asx3d3_point_size(const LWPOINT *point, char *srs, int precision, int opts, const char *defid);
24 static char *asx3d3_point(const LWPOINT *point, char *srs, int precision, int opts, const char *defid);
25 static size_t asx3d3_line_size(const LWLINE *line, char *srs, int precision, int opts, const char *defid);
26 static char *asx3d3_line(const LWLINE *line, char *srs, int precision, int opts, const char *defid);
27 static size_t asx3d3_poly_size(const LWPOLY *poly, char *srs, int precision, int opts, const char *defid);
28 static size_t asx3d3_triangle_size(const LWTRIANGLE *triangle, char *srs, int precision, int opts, const char *defid);
29 static char *asx3d3_triangle(const LWTRIANGLE *triangle, char *srs, int precision, int opts, const char *defid);
30 static size_t asx3d3_multi_size(const LWCOLLECTION *col, char *srs, int precisioSn, int opts, const char *defid);
31 static char *asx3d3_multi(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid);
32 static char *asx3d3_psurface(const LWPSURFACE *psur, char *srs, int precision, int opts, const char *defid);
33 static char *asx3d3_tin(const LWTIN *tin, char *srs, int precision, int opts, const char *defid);
34 static size_t asx3d3_collection_size(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid);
35 static char *asx3d3_collection(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid);
36 static size_t pointArray_toX3D3(POINTARRAY *pa, char *buf, int precision, int opts, int is_closed);
37 
38 static size_t pointArray_X3Dsize(POINTARRAY *pa, int precision);
39 
40 
41 /*
42  * VERSION X3D 3.0.2 http://www.web3d.org/specifications/x3d-3.0.dtd
43  */
44 
45 
46 /* takes a GEOMETRY and returns an X3D representation */
47 extern char *
48 lwgeom_to_x3d3(const LWGEOM *geom, char *srs, int precision, int opts, const char *defid)
49 {
50  int type = geom->type;
51 
52  switch (type)
53  {
54  case POINTTYPE:
55  return asx3d3_point((LWPOINT*)geom, srs, precision, opts, defid);
56 
57  case LINETYPE:
58  return asx3d3_line((LWLINE*)geom, srs, precision, opts, defid);
59 
60  case POLYGONTYPE:
61  {
66  char *ret = asx3d3_multi(tmp, srs, precision, opts, defid);
67  lwcollection_free(tmp);
68  return ret;
69  }
70 
71  case TRIANGLETYPE:
72  return asx3d3_triangle((LWTRIANGLE*)geom, srs, precision, opts, defid);
73 
74  case MULTIPOINTTYPE:
75  case MULTILINETYPE:
76  case MULTIPOLYGONTYPE:
77  return asx3d3_multi((LWCOLLECTION*)geom, srs, precision, opts, defid);
78 
80  return asx3d3_psurface((LWPSURFACE*)geom, srs, precision, opts, defid);
81 
82  case TINTYPE:
83  return asx3d3_tin((LWTIN*)geom, srs, precision, opts, defid);
84 
85  case COLLECTIONTYPE:
86  return asx3d3_collection((LWCOLLECTION*)geom, srs, precision, opts, defid);
87 
88  default:
89  lwerror("lwgeom_to_x3d3: '%s' geometry type not supported", lwtype_name(type));
90  return NULL;
91  }
92 }
93 
94 static size_t
95 asx3d3_point_size(const LWPOINT *point, char *srs, int precision, int opts, const char *defid)
96 {
97  int size;
98  /* size_t defidlen = strlen(defid); */
99 
100  size = pointArray_X3Dsize(point->point, precision);
101  /* size += ( sizeof("<point><pos>/") + (defidlen*2) ) * 2; */
102  /* if (srs) size += strlen(srs) + sizeof(" srsName=.."); */
103  return size;
104 }
105 
106 static size_t
107 asx3d3_point_buf(const LWPOINT *point, char *srs, char *output, int precision, int opts, const char *defid)
108 {
109  char *ptr = output;
110  /* int dimension=2; */
111 
112  /* if (FLAGS_GET_Z(point->flags)) dimension = 3; */
113  /* if ( srs )
114  {
115  ptr += sprintf(ptr, "<%sPoint srsName=\"%s\">", defid, srs);
116  }
117  else*/
118  /* ptr += sprintf(ptr, "%s", defid); */
119 
120  /* ptr += sprintf(ptr, "<%spos>", defid); */
121  ptr += pointArray_toX3D3(point->point, ptr, precision, opts, 0);
122  /* ptr += sprintf(ptr, "</%spos></%sPoint>", defid, defid); */
123 
124  return (ptr-output);
125 }
126 
127 static char *
128 asx3d3_point(const LWPOINT *point, char *srs, int precision, int opts, const char *defid)
129 {
130  char *output;
131  int size;
132 
133  size = asx3d3_point_size(point, srs, precision, opts, defid);
134  output = lwalloc(size);
135  asx3d3_point_buf(point, srs, output, precision, opts, defid);
136  return output;
137 }
138 
139 
140 static size_t
141 asx3d3_line_size(const LWLINE *line, char *srs, int precision, int opts, const char *defid)
142 {
143  int size;
144  size_t defidlen = strlen(defid);
145 
146  size = pointArray_X3Dsize(line->points, precision)*2;
147 
148  if ( X3D_USE_GEOCOORDS(opts) ) {
149  size += (
150  sizeof("<LineSet vertexCount=''><GeoCoordinate geoSystem='\"GD\" \"WE\" \"longitude_first\"' point='' /></LineSet>") + defidlen
151  ) * 2;
152  }
153  else {
154  size += (
155  sizeof("<LineSet vertexCount=''><Coordinate point='' /></LineSet>") + defidlen
156  ) * 2;
157  }
158 
159  /* if (srs) size += strlen(srs) + sizeof(" srsName=.."); */
160  return size;
161 }
162 
163 static size_t
164 asx3d3_line_buf(const LWLINE *line, char *srs, char *output, int precision, int opts, const char *defid)
165 {
166  char *ptr=output;
167  /* int dimension=2; */
168  POINTARRAY *pa;
169 
170 
171  /* if (FLAGS_GET_Z(line->flags)) dimension = 3; */
172 
173  pa = line->points;
174  ptr += sprintf(ptr, "<LineSet %s vertexCount='%d'>", defid, pa->npoints);
175 
176  if ( X3D_USE_GEOCOORDS(opts) ) ptr += sprintf(ptr, "<GeoCoordinate geoSystem='\"GD\" \"WE\" \"%s\"' point='", ( (opts & LW_X3D_FLIP_XY) ? "latitude_first" : "longitude_first") );
177  else
178  ptr += sprintf(ptr, "<Coordinate point='");
179  ptr += pointArray_toX3D3(line->points, ptr, precision, opts, lwline_is_closed((LWLINE *) line));
180 
181  ptr += sprintf(ptr, "' />");
182 
183  ptr += sprintf(ptr, "</LineSet>");
184  return (ptr-output);
185 }
186 
187 static size_t
188 asx3d3_line_coords(const LWLINE *line, char *output, int precision, int opts)
189 {
190  char *ptr=output;
191  /* ptr += sprintf(ptr, ""); */
192  ptr += pointArray_toX3D3(line->points, ptr, precision, opts, lwline_is_closed(line));
193  return (ptr-output);
194 }
195 
196 /* Calculate the coordIndex property of the IndexedLineSet for the multilinestring */
197 static size_t
198 asx3d3_mline_coordindex(const LWMLINE *mgeom, char *output)
199 {
200  char *ptr=output;
201  LWLINE *geom;
202  int i, j, k, si;
203  POINTARRAY *pa;
204  int np;
205 
206  j = 0;
207  for (i=0; i < mgeom->ngeoms; i++)
208  {
209  geom = (LWLINE *) mgeom->geoms[i];
210  pa = geom->points;
211  np = pa->npoints;
212  si = j; /* start index of first point of linestring */
213  for (k=0; k < np ; k++)
214  {
215  if (k)
216  {
217  ptr += sprintf(ptr, " ");
218  }
222  if (!lwline_is_closed(geom) || k < (np -1) )
223  {
224  ptr += sprintf(ptr, "%d", j);
225  j += 1;
226  }
227  else
228  {
229  ptr += sprintf(ptr,"%d", si);
230  }
231  }
232  if (i < (mgeom->ngeoms - 1) )
233  {
234  ptr += sprintf(ptr, " -1 "); /* separator for each linestring */
235  }
236  }
237  return (ptr-output);
238 }
239 
240 /* Calculate the coordIndex property of the IndexedLineSet for a multipolygon
241  This is not ideal -- would be really nice to just share this function with psurf,
242  but I'm not smart enough to do that yet*/
243 static size_t
244 asx3d3_mpoly_coordindex(const LWMPOLY *psur, char *output)
245 {
246  char *ptr=output;
247  LWPOLY *patch;
248  int i, j, k, l;
249  int np;
250  j = 0;
251  for (i=0; i<psur->ngeoms; i++)
252  {
253  patch = (LWPOLY *) psur->geoms[i];
254  for (l=0; l < patch->nrings; l++)
255  {
256  np = patch->rings[l]->npoints - 1;
257  for (k=0; k < np ; k++)
258  {
259  if (k)
260  {
261  ptr += sprintf(ptr, " ");
262  }
263  ptr += sprintf(ptr, "%d", (j + k));
264  }
265  j += k;
266  if (l < (patch->nrings - 1) )
267  {
276  ptr += sprintf(ptr, " -1 "); /* separator for each inner ring. Ideally we should probably triangulate and cut around as others do */
277  }
278  }
279  if (i < (psur->ngeoms - 1) )
280  {
281  ptr += sprintf(ptr, " -1 "); /* separator for each subgeom */
282  }
283  }
284  return (ptr-output);
285 }
286 
288 static char *
289 asx3d3_line(const LWLINE *line, char *srs, int precision, int opts, const char *defid)
290 {
291  char *output;
292  int size;
293 
294  size = sizeof("<LineSet><CoordIndex ='' /></LineSet>") + asx3d3_line_size(line, srs, precision, opts, defid);
295  output = lwalloc(size);
296  asx3d3_line_buf(line, srs, output, precision, opts, defid);
297  return output;
298 }
299 
301 static size_t
302 asx3d3_poly_size(const LWPOLY *poly, char *srs, int precision, int opts, const char *defid)
303 {
304  size_t size;
305  size_t defidlen = strlen(defid);
306  int i;
307 
308  size = ( sizeof("<IndexedFaceSet></IndexedFaceSet>") + (defidlen*3) ) * 2 + 6 * (poly->nrings - 1);
309 
310  for (i=0; i<poly->nrings; i++)
311  size += pointArray_X3Dsize(poly->rings[i], precision);
312 
313  return size;
314 }
315 
317 static size_t
318 asx3d3_poly_buf(const LWPOLY *poly, char *srs, char *output, int precision, int opts, int is_patch, const char *defid)
319 {
320  int i;
321  char *ptr=output;
322 
323  ptr += pointArray_toX3D3(poly->rings[0], ptr, precision, opts, 1);
324  for (i=1; i<poly->nrings; i++)
325  {
326  ptr += sprintf(ptr, " "); /* inner ring points start */
327  ptr += pointArray_toX3D3(poly->rings[i], ptr, precision, opts,1);
328  }
329  return (ptr-output);
330 }
331 
332 static size_t
333 asx3d3_triangle_size(const LWTRIANGLE *triangle, char *srs, int precision, int opts, const char *defid)
334 {
335  size_t size;
336  size_t defidlen = strlen(defid);
337 
339  size = sizeof("<IndexedTriangleSet index=''></IndexedTriangleSet>") + defidlen + 6;
340  size += pointArray_X3Dsize(triangle->points, precision);
341 
342  return size;
343 }
344 
345 static size_t
346 asx3d3_triangle_buf(const LWTRIANGLE *triangle, char *srs, char *output, int precision, int opts, const char *defid)
347 {
348  char *ptr=output;
349  ptr += pointArray_toX3D3(triangle->points, ptr, precision, opts, 1);
350 
351  return (ptr-output);
352 }
353 
354 static char *
355 asx3d3_triangle(const LWTRIANGLE *triangle, char *srs, int precision, int opts, const char *defid)
356 {
357  char *output;
358  int size;
359 
360  size = asx3d3_triangle_size(triangle, srs, precision, opts, defid);
361  output = lwalloc(size);
362  asx3d3_triangle_buf(triangle, srs, output, precision, opts, defid);
363  return output;
364 }
365 
366 
372 static size_t
373 asx3d3_multi_size(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid)
374 {
375  int i;
376  size_t size;
377  size_t defidlen = strlen(defid);
378  LWGEOM *subgeom;
379 
380  /* the longest possible multi version needs to hold DEF=defid and coordinate breakout */
381  if ( X3D_USE_GEOCOORDS(opts) )
382  size = sizeof("<PointSet><GeoCoordinate geoSystem='\"GD\" \"WE\" \"longitude_first\"' point='' /></PointSet>");
383  else
384  size = sizeof("<PointSet><Coordinate point='' /></PointSet>") + defidlen;
385 
386 
387  /* if ( srs ) size += strlen(srs) + sizeof(" srsName=.."); */
388 
389  for (i=0; i<col->ngeoms; i++)
390  {
391  subgeom = col->geoms[i];
392  if (subgeom->type == POINTTYPE)
393  {
394  /* size += ( sizeof("point=''") + defidlen ) * 2; */
395  size += asx3d3_point_size((LWPOINT*)subgeom, 0, precision, opts, defid);
396  }
397  else if (subgeom->type == LINETYPE)
398  {
399  /* size += ( sizeof("<curveMember>/") + defidlen ) * 2; */
400  size += asx3d3_line_size((LWLINE*)subgeom, 0, precision, opts, defid);
401  }
402  else if (subgeom->type == POLYGONTYPE)
403  {
404  /* size += ( sizeof("<surfaceMember>/") + defidlen ) * 2; */
405  size += asx3d3_poly_size((LWPOLY*)subgeom, 0, precision, opts, defid);
406  }
407  }
408 
409  return size;
410 }
411 
412 /*
413  * Don't call this with single-geoms inspected!
414  */
415 static size_t
416 asx3d3_multi_buf(const LWCOLLECTION *col, char *srs, char *output, int precision, int opts, const char *defid)
417 {
418  char *ptr, *x3dtype;
419  int i;
420  int dimension=2;
421 
422  if (FLAGS_GET_Z(col->flags)) dimension = 3;
423  LWGEOM *subgeom;
424  ptr = output;
425  x3dtype="";
426 
427 
428  switch (col->type)
429  {
430  case MULTIPOINTTYPE:
431  x3dtype = "PointSet";
432  if ( dimension == 2 ){
433  x3dtype = "Polypoint2D";
434  ptr += sprintf(ptr, "<%s %s point='", x3dtype, defid);
435  }
436  else {
437  ptr += sprintf(ptr, "<%s %s>", x3dtype, defid);
438  }
439  break;
440  case MULTILINETYPE:
441  x3dtype = "IndexedLineSet";
442  ptr += sprintf(ptr, "<%s %s coordIndex='", x3dtype, defid);
443  ptr += asx3d3_mline_coordindex((const LWMLINE *)col, ptr);
444  ptr += sprintf(ptr, "'>");
445  break;
446  case MULTIPOLYGONTYPE:
447  x3dtype = "IndexedFaceSet";
448  ptr += sprintf(ptr, "<%s %s convex='false' coordIndex='", x3dtype, defid);
449  ptr += asx3d3_mpoly_coordindex((const LWMPOLY *)col, ptr);
450  ptr += sprintf(ptr, "'>");
451  break;
452  default:
453  lwerror("asx3d3_multi_buf: '%s' geometry type not supported", lwtype_name(col->type));
454  return 0;
455  }
456  if (dimension == 3){
457  if ( X3D_USE_GEOCOORDS(opts) )
458  ptr += sprintf(ptr, "<GeoCoordinate geoSystem='\"GD\" \"WE\" \"%s\"' point='", ((opts & LW_X3D_FLIP_XY) ? "latitude_first" : "longitude_first") );
459  else
460  ptr += sprintf(ptr, "<Coordinate point='");
461  }
462 
463  for (i=0; i<col->ngeoms; i++)
464  {
465  subgeom = col->geoms[i];
466  if (subgeom->type == POINTTYPE)
467  {
468  ptr += asx3d3_point_buf((LWPOINT*)subgeom, 0, ptr, precision, opts, defid);
469  ptr += sprintf(ptr, " ");
470  }
471  else if (subgeom->type == LINETYPE)
472  {
473  ptr += asx3d3_line_coords((LWLINE*)subgeom, ptr, precision, opts);
474  ptr += sprintf(ptr, " ");
475  }
476  else if (subgeom->type == POLYGONTYPE)
477  {
478  ptr += asx3d3_poly_buf((LWPOLY*)subgeom, 0, ptr, precision, opts, 0, defid);
479  ptr += sprintf(ptr, " ");
480  }
481  }
482 
483  /* Close outmost tag */
484  if (dimension == 3){
485  ptr += sprintf(ptr, "' /></%s>", x3dtype);
486  }
487  else { ptr += sprintf(ptr, "' />"); }
488  return (ptr-output);
489 }
490 
491 /*
492  * Don't call this with single-geoms inspected!
493  */
494 static char *
495 asx3d3_multi(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid)
496 {
497  char *x3d;
498  size_t size;
499 
500  size = asx3d3_multi_size(col, srs, precision, opts, defid);
501  x3d = lwalloc(size);
502  asx3d3_multi_buf(col, srs, x3d, precision, opts, defid);
503  return x3d;
504 }
505 
506 
507 static size_t
508 asx3d3_psurface_size(const LWPSURFACE *psur, char *srs, int precision, int opts, const char *defid)
509 {
510  int i;
511  size_t size;
512  size_t defidlen = strlen(defid);
513 
514  if ( X3D_USE_GEOCOORDS(opts) ) size = sizeof("<IndexedFaceSet convex='false' coordIndex=''><GeoCoordinate geoSystem='\"GD\" \"WE\" \"longitude_first\"' point='' />") + defidlen;
515  else size = sizeof("<IndexedFaceSet convex='false' coordIndex=''><Coordinate point='' />") + defidlen;
516 
517 
518  for (i=0; i<psur->ngeoms; i++)
519  {
520  size += asx3d3_poly_size(psur->geoms[i], 0, precision, opts, defid)*5;
521  }
522 
523  return size;
524 }
525 
526 
527 /*
528  * Don't call this with single-geoms inspected!
529  */
530 static size_t
531 asx3d3_psurface_buf(const LWPSURFACE *psur, char *srs, char *output, int precision, int opts, const char *defid)
532 {
533  char *ptr;
534  int i;
535  int j;
536  int k;
537  int np;
538  LWPOLY *patch;
539 
540  ptr = output;
541 
542  /* Open outmost tag */
543  ptr += sprintf(ptr, "<IndexedFaceSet convex='false' %s coordIndex='",defid);
544 
545  j = 0;
546  for (i=0; i<psur->ngeoms; i++)
547  {
548  patch = (LWPOLY *) psur->geoms[i];
549  np = patch->rings[0]->npoints - 1;
550  for (k=0; k < np ; k++)
551  {
552  if (k)
553  {
554  ptr += sprintf(ptr, " ");
555  }
556  ptr += sprintf(ptr, "%d", (j + k));
557  }
558  if (i < (psur->ngeoms - 1) )
559  {
560  ptr += sprintf(ptr, " -1 "); /* separator for each subgeom */
561  }
562  j += k;
563  }
564 
565  if ( X3D_USE_GEOCOORDS(opts) )
566  ptr += sprintf(ptr, "'><GeoCoordinate geoSystem='\"GD\" \"WE\" \"%s\"' point='", ( (opts & LW_X3D_FLIP_XY) ? "latitude_first" : "longitude_first") );
567  else ptr += sprintf(ptr, "'><Coordinate point='");
568 
569  for (i=0; i<psur->ngeoms; i++)
570  {
571  ptr += asx3d3_poly_buf(psur->geoms[i], 0, ptr, precision, opts, 1, defid);
572  if (i < (psur->ngeoms - 1) )
573  {
574  ptr += sprintf(ptr, " "); /* only add a trailing space if its not the last polygon in the set */
575  }
576  }
577 
578  /* Close outmost tag */
579  ptr += sprintf(ptr, "' /></IndexedFaceSet>");
580 
581  return (ptr-output);
582 }
583 
584 /*
585  * Don't call this with single-geoms inspected!
586  */
587 static char *
588 asx3d3_psurface(const LWPSURFACE *psur, char *srs, int precision, int opts, const char *defid)
589 {
590  char *x3d;
591  size_t size;
592 
593  size = asx3d3_psurface_size(psur, srs, precision, opts, defid);
594  x3d = lwalloc(size);
595  asx3d3_psurface_buf(psur, srs, x3d, precision, opts, defid);
596  return x3d;
597 }
598 
599 
600 static size_t
601 asx3d3_tin_size(const LWTIN *tin, char *srs, int precision, int opts, const char *defid)
602 {
603  int i;
604  size_t size;
605  size_t defidlen = strlen(defid);
606  /* int dimension=2; */
607 
610  size = sizeof("<IndexedTriangleSet coordIndex=''></IndexedTriangleSet>") + defidlen + tin->ngeoms*12;
611 
612  for (i=0; i<tin->ngeoms; i++)
613  {
614  size += (asx3d3_triangle_size(tin->geoms[i], 0, precision, opts, defid) * 20);
615  }
616 
617  return size;
618 }
619 
620 
621 /*
622  * Don't call this with single-geoms inspected!
623  */
624 static size_t
625 asx3d3_tin_buf(const LWTIN *tin, char *srs, char *output, int precision, int opts, const char *defid)
626 {
627  char *ptr;
628  int i;
629  int k;
630  /* int dimension=2; */
631 
632  ptr = output;
633 
634  ptr += sprintf(ptr, "<IndexedTriangleSet %s index='",defid);
635  k = 0;
637  for (i=0; i<tin->ngeoms; i++)
638  {
639  ptr += sprintf(ptr, "%d %d %d", k, (k+1), (k+2));
640  if (i < (tin->ngeoms - 1) )
641  {
642  ptr += sprintf(ptr, " ");
643  }
644  k += 3;
645  }
646 
647  if ( X3D_USE_GEOCOORDS(opts) ) ptr += sprintf(ptr, "'><GeoCoordinate geoSystem='\"GD\" \"WE\" \"%s\"' point='", ( (opts & LW_X3D_FLIP_XY) ? "latitude_first" : "longitude_first") );
648  else ptr += sprintf(ptr, "'><Coordinate point='");
649 
650  for (i=0; i<tin->ngeoms; i++)
651  {
652  ptr += asx3d3_triangle_buf(tin->geoms[i], 0, ptr, precision,
653  opts, defid);
654  if (i < (tin->ngeoms - 1) )
655  {
656  ptr += sprintf(ptr, " ");
657  }
658  }
659 
660  /* Close outmost tag */
661 
662  ptr += sprintf(ptr, "'/></IndexedTriangleSet>");
663 
664  return (ptr-output);
665 }
666 
667 /*
668  * Don't call this with single-geoms inspected!
669  */
670 static char *
671 asx3d3_tin(const LWTIN *tin, char *srs, int precision, int opts, const char *defid)
672 {
673  char *x3d;
674  size_t size;
675 
676  size = asx3d3_tin_size(tin, srs, precision, opts, defid);
677  x3d = lwalloc(size);
678  asx3d3_tin_buf(tin, srs, x3d, precision, opts, defid);
679  return x3d;
680 }
681 
682 static size_t
683 asx3d3_collection_size(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid)
684 {
685  int i;
686  size_t size;
687  size_t defidlen = strlen(defid);
688  LWGEOM *subgeom;
689 
690  /* size = sizeof("<MultiGeometry></MultiGeometry>") + defidlen*2; */
691  size = defidlen*2;
692 
696  for (i=0; i<col->ngeoms; i++)
697  {
698  subgeom = col->geoms[i];
699  size += ( sizeof("<Shape />") + defidlen ) * 2;
700  if ( subgeom->type == POINTTYPE )
701  {
702  size += asx3d3_point_size((LWPOINT*)subgeom, 0, precision, opts, defid);
703  }
704  else if ( subgeom->type == LINETYPE )
705  {
706  size += asx3d3_line_size((LWLINE*)subgeom, 0, precision, opts, defid);
707  }
708  else if ( subgeom->type == POLYGONTYPE )
709  {
710  size += asx3d3_poly_size((LWPOLY*)subgeom, 0, precision, opts, defid);
711  }
712  else if ( subgeom->type == TINTYPE )
713  {
714  size += asx3d3_tin_size((LWTIN*)subgeom, 0, precision, opts, defid);
715  }
716  else if ( subgeom->type == POLYHEDRALSURFACETYPE )
717  {
718  size += asx3d3_psurface_size((LWPSURFACE*)subgeom, 0, precision, opts, defid);
719  }
720  else if ( lwgeom_is_collection(subgeom) )
721  {
722  size += asx3d3_multi_size((LWCOLLECTION*)subgeom, 0, precision, opts, defid);
723  }
724  else
725  lwerror("asx3d3_collection_size: unknown geometry type");
726  }
727 
728  return size;
729 }
730 
731 static size_t
732 asx3d3_collection_buf(const LWCOLLECTION *col, char *srs, char *output, int precision, int opts, const char *defid)
733 {
734  char *ptr;
735  int i;
736  LWGEOM *subgeom;
737 
738  ptr = output;
739 
740  /* Open outmost tag */
742 #ifdef PGIS_X3D_OUTERMOST_TAGS
743  if ( srs )
744  {
745  ptr += sprintf(ptr, "<%sMultiGeometry srsName=\"%s\">", defid, srs);
746  }
747  else
748  {
749  ptr += sprintf(ptr, "<%sMultiGeometry>", defid);
750  }
751 #endif
752 
753  for (i=0; i<col->ngeoms; i++)
754  {
755  subgeom = col->geoms[i];
756  ptr += sprintf(ptr, "<Shape%s>", defid);
757  if ( subgeom->type == POINTTYPE )
758  {
759  ptr += asx3d3_point_buf((LWPOINT*)subgeom, 0, ptr, precision, opts, defid);
760  }
761  else if ( subgeom->type == LINETYPE )
762  {
763  ptr += asx3d3_line_buf((LWLINE*)subgeom, 0, ptr, precision, opts, defid);
764  }
765  else if ( subgeom->type == POLYGONTYPE )
766  {
767  ptr += asx3d3_poly_buf((LWPOLY*)subgeom, 0, ptr, precision, opts, 0, defid);
768  }
769  else if ( subgeom->type == TINTYPE )
770  {
771  ptr += asx3d3_tin_buf((LWTIN*)subgeom, srs, ptr, precision, opts, defid);
772 
773  }
774  else if ( subgeom->type == POLYHEDRALSURFACETYPE )
775  {
776  ptr += asx3d3_psurface_buf((LWPSURFACE*)subgeom, srs, ptr, precision, opts, defid);
777 
778  }
779  else if ( lwgeom_is_collection(subgeom) )
780  {
781  if ( subgeom->type == COLLECTIONTYPE )
782  ptr += asx3d3_collection_buf((LWCOLLECTION*)subgeom, 0, ptr, precision, opts, defid);
783  else
784  ptr += asx3d3_multi_buf((LWCOLLECTION*)subgeom, 0, ptr, precision, opts, defid);
785  }
786  else
787  lwerror("asx3d3_collection_buf: unknown geometry type");
788 
789  ptr += printf(ptr, "</Shape>");
790  }
791 
792  /* Close outmost tag */
793 #ifdef PGIS_X3D_OUTERMOST_TAGS
794  ptr += sprintf(ptr, "</%sMultiGeometry>", defid);
795 #endif
796 
797  return (ptr-output);
798 }
799 
800 /*
801  * Don't call this with single-geoms inspected!
802  */
803 static char *
804 asx3d3_collection(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid)
805 {
806  char *x3d;
807  size_t size;
808 
809  size = asx3d3_collection_size(col, srs, precision, opts, defid);
810  x3d = lwalloc(size);
811  asx3d3_collection_buf(col, srs, x3d, precision, opts, defid);
812  return x3d;
813 }
814 
815 
818 static size_t
819 pointArray_toX3D3(POINTARRAY *pa, char *output, int precision, int opts, int is_closed)
820 {
821  int i;
822  char *ptr;
826 
827  ptr = output;
828 
829  if ( ! FLAGS_GET_Z(pa->flags) )
830  {
831  for (i=0; i<pa->npoints; i++)
832  {
834  if ( !is_closed || i < (pa->npoints - 1) )
835  {
836  POINT2D pt;
837  getPoint2d_p(pa, i, &pt);
838 
839  if (fabs(pt.x) < OUT_MAX_DOUBLE)
840  sprintf(x, "%.*f", precision, pt.x);
841  else
842  sprintf(x, "%g", pt.x);
844 
845  if (fabs(pt.y) < OUT_MAX_DOUBLE)
846  sprintf(y, "%.*f", precision, pt.y);
847  else
848  sprintf(y, "%g", pt.y);
850 
851  if ( i )
852  ptr += sprintf(ptr, " ");
853 
854  if ( ( opts & LW_X3D_FLIP_XY) )
855  ptr += sprintf(ptr, "%s %s", y, x);
856  else
857  ptr += sprintf(ptr, "%s %s", x, y);
858  }
859  }
860  }
861  else
862  {
863  for (i=0; i<pa->npoints; i++)
864  {
866  if ( !is_closed || i < (pa->npoints - 1) )
867  {
868  POINT4D pt;
869  getPoint4d_p(pa, i, &pt);
870 
871  if (fabs(pt.x) < OUT_MAX_DOUBLE)
872  sprintf(x, "%.*f", precision, pt.x);
873  else
874  sprintf(x, "%g", pt.x);
876 
877  if (fabs(pt.y) < OUT_MAX_DOUBLE)
878  sprintf(y, "%.*f", precision, pt.y);
879  else
880  sprintf(y, "%g", pt.y);
882 
883  if (fabs(pt.z) < OUT_MAX_DOUBLE)
884  sprintf(z, "%.*f", precision, pt.z);
885  else
886  sprintf(z, "%g", pt.z);
888 
889  if ( i )
890  ptr += sprintf(ptr, " ");
891 
892  if ( ( opts & LW_X3D_FLIP_XY) )
893  ptr += sprintf(ptr, "%s %s %s", y, x, z);
894  else
895  ptr += sprintf(ptr, "%s %s %s", x, y, z);
896  }
897  }
898  }
899 
900  return ptr-output;
901 }
902 
903 
904 
908 static size_t
910 {
911  if (FLAGS_NDIMS(pa->flags) == 2)
912  return (OUT_MAX_DIGS_DOUBLE + precision + sizeof(" "))
913  * 2 * pa->npoints;
914 
915  return (OUT_MAX_DIGS_DOUBLE + precision + sizeof(" ")) * 3 * pa->npoints;
916 }
double x
Definition: liblwgeom.h:336
#define LINETYPE
Definition: liblwgeom.h:71
static char * asx3d3_line(const LWLINE *line, char *srs, int precision, int opts, const char *defid)
Return the linestring as an X3D LineSet.
Definition: lwout_x3d.c:289
static size_t asx3d3_collection_buf(const LWCOLLECTION *col, char *srs, char *output, int precision, int opts, const char *defid)
Definition: lwout_x3d.c:732
static size_t pointArray_X3Dsize(POINTARRAY *pa, int precision)
Returns maximum size of rendered pointarray in bytes.
Definition: lwout_x3d.c:909
POINTARRAY * points
Definition: liblwgeom.h:417
static size_t asx3d3_multi_buf(const LWCOLLECTION *col, char *srs, char *output, int precision, int opts, const char *defid)
Definition: lwout_x3d.c:416
int lwgeom_is_collection(const LWGEOM *lwgeom)
Determine whether a LWGEOM can contain sub-geometries or not.
Definition: lwgeom.c:991
int npoints
Definition: liblwgeom.h:355
uint8_t type
Definition: liblwgeom.h:487
#define OUT_MAX_DOUBLE_PRECISION
static char * asx3d3_multi(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid)
Definition: lwout_x3d.c:495
void trim_trailing_zeros(char *num)
Definition: lwutil.c:224
static char * asx3d3_point(const LWPOINT *point, char *srs, int precision, int opts, const char *defid)
Definition: lwout_x3d.c:128
#define POLYGONTYPE
Definition: liblwgeom.h:72
#define MULTIPOINTTYPE
Definition: liblwgeom.h:73
#define TRIANGLETYPE
Definition: liblwgeom.h:83
#define POLYHEDRALSURFACETYPE
Definition: liblwgeom.h:82
static char * asx3d3_tin(const LWTIN *tin, char *srs, int precision, int opts, const char *defid)
Definition: lwout_x3d.c:671
static size_t asx3d3_poly_size(const LWPOLY *poly, char *srs, int precision, int opts, const char *defid)
Compute the string space needed for the IndexedFaceSet representation of the polygon.
Definition: lwout_x3d.c:302
LWPOLY ** geoms
Definition: liblwgeom.h:558
LWGEOM * lwgeom_as_multi(const LWGEOM *lwgeom)
Create a new LWGEOM of the appropriate MULTI* type.
Definition: lwgeom.c:284
static char * asx3d3_psurface(const LWPSURFACE *psur, char *srs, int precision, int opts, const char *defid)
Definition: lwout_x3d.c:588
POINTARRAY * point
Definition: liblwgeom.h:395
#define X3D_USE_GEOCOORDS(x)
Definition: liblwgeom.h:1489
int ngeoms
Definition: liblwgeom.h:465
double x
Definition: liblwgeom.h:312
uint8_t flags
Definition: liblwgeom.h:488
int ngeoms
Definition: liblwgeom.h:569
const char * lwtype_name(uint8_t type)
Return the type name string associated with a type number (e.g.
Definition: lwutil.c:188
static size_t asx3d3_collection_size(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid)
Definition: lwout_x3d.c:683
uint8_t flags
Definition: liblwgeom.h:353
static size_t asx3d3_tin_buf(const LWTIN *tin, char *srs, char *output, int precision, int opts, const char *defid)
Definition: lwout_x3d.c:625
LWPOLY ** geoms
Definition: liblwgeom.h:480
LWGEOM ** geoms
Definition: liblwgeom.h:493
static size_t asx3d3_point_buf(const LWPOINT *point, char *srs, char *output, int precision, int opts, const char *defid)
Definition: lwout_x3d.c:107
#define TINTYPE
Definition: liblwgeom.h:84
LWTRIANGLE ** geoms
Definition: liblwgeom.h:571
POINTARRAY ** rings
Definition: liblwgeom.h:441
static size_t asx3d3_line_coords(const LWLINE *line, char *output, int precision, int opts)
Definition: lwout_x3d.c:188
static char * asx3d3_collection(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid)
Definition: lwout_x3d.c:804
#define LW_X3D_FLIP_XY
Macros for specifying X3D options.
Definition: liblwgeom.h:1487
uint8_t precision
Definition: cu_in_twkb.c:25
char * lwgeom_to_x3d3(const LWGEOM *geom, char *srs, int precision, int opts, const char *defid)
Definition: lwout_x3d.c:48
static size_t asx3d3_triangle_size(const LWTRIANGLE *triangle, char *srs, int precision, int opts, const char *defid)
Definition: lwout_x3d.c:333
int nrings
Definition: liblwgeom.h:439
double y
Definition: liblwgeom.h:312
int getPoint2d_p(const POINTARRAY *pa, int n, POINT2D *point)
Definition: lwgeom_api.c:448
#define FLAGS_GET_Z(flags)
Macros for manipulating the 'flags' byte.
Definition: liblwgeom.h:124
double z
Definition: liblwgeom.h:336
tuple x
Definition: pixval.py:53
int ngeoms
Definition: liblwgeom.h:478
static size_t asx3d3_mpoly_coordindex(const LWMPOLY *psur, char *output)
Definition: lwout_x3d.c:244
static size_t asx3d3_mline_coordindex(const LWMLINE *mgeom, char *output)
Definition: lwout_x3d.c:198
#define MULTIPOLYGONTYPE
Definition: liblwgeom.h:75
#define OUT_MAX_DOUBLE
LWLINE ** geoms
Definition: liblwgeom.h:467
static size_t asx3d3_tin_size(const LWTIN *tin, char *srs, int precision, int opts, const char *defid)
Definition: lwout_x3d.c:601
int lwline_is_closed(const LWLINE *line)
Definition: lwline.c:439
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition: liblwgeom.h:70
uint8_t type
Definition: liblwgeom.h:380
void lwcollection_free(LWCOLLECTION *col)
Definition: lwcollection.c:326
static size_t asx3d3_poly_buf(const LWPOLY *poly, char *srs, char *output, int precision, int opts, int is_patch, const char *defid)
Compute the X3D coordinates of the polygon.
Definition: lwout_x3d.c:318
static char * asx3d3_triangle(const LWTRIANGLE *triangle, char *srs, int precision, int opts, const char *defid)
Definition: lwout_x3d.c:355
void * lwalloc(size_t size)
Definition: lwutil.c:199
#define OUT_MAX_DIGS_DOUBLE
static size_t asx3d3_triangle_buf(const LWTRIANGLE *triangle, char *srs, char *output, int precision, int opts, const char *defid)
Definition: lwout_x3d.c:346
double y
Definition: liblwgeom.h:336
#define MULTILINETYPE
Definition: liblwgeom.h:74
static size_t asx3d3_psurface_size(const LWPSURFACE *psur, char *srs, int precision, int opts, const char *defid)
Definition: lwout_x3d.c:508
#define FLAGS_NDIMS(flags)
Definition: liblwgeom.h:136
static size_t asx3d3_point_size(const LWPOINT *point, char *srs, int precision, int opts, const char *defid)
defid is the id of the coordinate can be used to hold other elements DEF='abc' transform='' etc...
Definition: lwout_x3d.c:95
int ngeoms
Definition: liblwgeom.h:556
static size_t asx3d3_line_buf(const LWLINE *line, char *srs, char *output, int precision, int opts, const char *defid)
Definition: lwout_x3d.c:164
static size_t asx3d3_line_size(const LWLINE *line, char *srs, int precision, int opts, const char *defid)
Definition: lwout_x3d.c:141
static size_t asx3d3_psurface_buf(const LWPSURFACE *psur, char *srs, char *output, int precision, int opts, const char *defid)
Definition: lwout_x3d.c:531
void lwerror(const char *fmt,...)
Write a notice out to the error handler.
Definition: lwutil.c:74
static size_t pointArray_toX3D3(POINTARRAY *pa, char *buf, int precision, int opts, int is_closed)
In X3D3, coordinates are separated by a space separator.
Definition: lwout_x3d.c:819
tuple y
Definition: pixval.py:54
int getPoint4d_p(const POINTARRAY *pa, int n, POINT4D *point)
Definition: lwgeom_api.c:231
#define COLLECTIONTYPE
Definition: liblwgeom.h:76
static size_t asx3d3_multi_size(const LWCOLLECTION *col, char *srs, int precisioSn, int opts, const char *defid)
Compute max size required for X3D version of this inspected geometry.
Definition: lwout_x3d.c:373
POINTARRAY * points
Definition: liblwgeom.h:406