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