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