[postgis-users] X3D and Postgis
Randy George
rkgeorge at cadmaps.com
Tue Apr 3 13:19:07 PDT 2007
Hi Olivier,
How close would this be to XAML MeshGeometry? i.e.
<MeshGeometry3D
Positions=" x y z, x1 y1 z1, ..."
TriangularIndices="3 0 4, 0 2 4, 2 0 3, ..."
/>
Thanks
Randy
-----Original Message-----
From: postgis-users-bounces at postgis.refractions.net
[mailto:postgis-users-bounces at postgis.refractions.net] On Behalf Of Olivier
Courtin
Sent: Tuesday, April 03, 2007 10:17 AM
To: postgis-users at postgis.refractions.net
Cc: david.desbuisson at tplm-3d.fr
Subject: [postgis-users] X3D and Postgis
Hi Folks,
I've recently started playing with X3D output and Postgis...
First problem i met, was 3D storage in order to be able to
output 3D triangle (aka: mesh).
Usually output from 3D software (Blender for example) is
expressed like a MULTIPOINT, and then by a nodes sequence
to construct each mesh:
-0.3068164315138165 0.3362340357492064 0.08543229250743267
-0.1394644092204649 0.02167141020453666 0.2313872251951948
-0.07491186826947319 -0.04377333172017087 0.3016102088630295
0.1627740875471142 -0.2559157826527169 -0.1765609543552259
-0.4599623796157188 0.4122854856888629 0.2821508331989411
3 3 0 4
3 0 2 4
3 2 0 3
3 1 3 4
3 2 1 4
3 1 2 3
For the moment i choose to store points as a MULTIPOINT in
EWKT, and nodes index sequence as an array int (PostgreSQL native)
So a feature is related to both a geometry (Multipoint) and a
int[] faces index
I've not yet found something usefull in the specs (SFS or SQL/MM)
related to 3D storage to provide mesh rendering.
Would you accept a patch with such a new geometry type in Postgis ?
A right way to handle that, should be something like:
MESH(MULTIPOINT(x y z, x1 y1 z1,...), NODES(3 0 4, 0 2 4, 2 0 3, ...))
Right now, as i need to go on 3D rendering, i wrote with David Desbuisson
a first asX3D function below
Any reaction, comments and/or help are welcome ! :)
Patch against today SVN postgis version:
diff -Nu lwgeom/lwgeom_x3d.c ../postgis-svn/lwgeom/lwgeom_x3d.c
--- lwgeom/lwgeom_x3d.c 2007-04-03 17:44:22.000000000 +0200
+++ ../postgis-svn/lwgeom/lwgeom_x3d.c 1970-01-01 01:00:00.000000000 +0100
@@ -1,368 +0,0 @@
-/**********************************************************************
- * $Id$
- *
- * PostGIS - Spatial Types for PostgreSQL
- * http://postgis.refractions.net
- * Copyright 2001-2003 Refractions Research Inc.
- *
- * This is free software; you can redistribute and/or modify it under
- * the terms of hte GNU General Public Licence. See the COPYING file.
- *
- **********************************************************************
- *
- * X3D output routines.
- *
- * This file is, widely inspired from lwgeom_kml.c, written by:
- * David Desbuisson <david.desbuisson at tplm-3d.fr>
- * Olivier Courtin <olivier.courtin at camptocamp.com>
- *
- **********************************************************************/
-
-
-#include "postgres.h"
-#include "utils/array.h"
-
-#include "stringBuffer.h"
-
-#include "lwgeom_pg.h"
-#include "liblwgeom.h"
-
-Datum LWGEOM_asX3D(PG_FUNCTION_ARGS);
-
-char *geometry_to_x3d(uchar *srl);
-static size_t asx3d_point_size(LWPOINT *point);
-static char *asx3d_point(LWPOINT *point);
-static char *array_to_faces(ArrayType *array);
-static size_t asx3d_inspected_size(LWGEOM_INSPECTED *geom);
-static char *asx3d_inspected(LWGEOM_INSPECTED *geom);
-static size_t pointArray_X3Dsize(POINTARRAY *pa);
-static size_t pointArray_toX3D(POINTARRAY *pa, char *buf);
-
-#define DEF_PRECISION 15
-/* Add dot, sign, exponent sign, 'e', exponent digits */
-#define SHOW_DIGS (precision + 8)
-
-/* Globals */
-int precision;
-
-
-/**
- * Encode feature in X3D
- */
-PG_FUNCTION_INFO_V1(LWGEOM_asX3D);
-Datum LWGEOM_asX3D(PG_FUNCTION_ARGS)
-{
- PG_LWGEOM *geom;
- int len;
- Datum datum;
- STRBUFF *buf;
- text *result;
- char *x3d;
- ArrayType *faces = NULL;
-
- precision = DEF_PRECISION;
-
- if ( PG_ARGISNULL(0) || PG_ARGISNULL(1)) PG_RETURN_NULL();
-
- /* geom related to MULTIPOINT */
- geom = (PG_LWGEOM *)PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0));
-
- /* faces */
- datum = PG_GETARG_DATUM(1);
- if ( (Pointer *) datum == NULL) {
- elog(ERROR, "asX3D: 'faces' parameter is Null !");
- PG_RETURN_NULL();
- }
- faces = (ArrayType *) PG_DETOAST_DATUM_COPY(datum);
- /* FIXME: what about a check related to too
- small faces datas (i.e below 3) ? */
-
- /* Get precision (if provided) */
- if ( PG_NARGS() > 2 && ! PG_ARGISNULL(2) )
- precision = PG_GETARG_INT32(2);
-
- if ( precision < 1 || precision > 15 )
- {
- elog(ERROR, "Precision out of range 1..15");
- PG_RETURN_NULL();
- }
-
-
- buf = new_strBUFF(1024);
-
- add_str_simple(buf, array_to_faces(faces));
- add_str_simple(buf, geometry_to_x3d(SERIALIZED_FORM(geom)));
- add_str_simple(buf, "\n</IndexedFaceSet>\n");
-
- x3d = to_CString(buf);
- delete_StrBUFF(buf);
-
- PG_FREE_IF_COPY(geom, 0);
-
- len = strlen(x3d) + VARHDRSZ;
-
- result = palloc(len);
- VARATT_SIZEP(result) = len;
-
- memcpy(VARDATA(result), x3d, len - VARHDRSZ);
- pfree(x3d);
-
-
- PG_RETURN_POINTER(result);
-}
-
-/*
- * Handle transform from postgres int array to IndexedFaceSet
- */
- static char *
-array_to_faces(ArrayType *array)
-{
- int i,j;
- int nelems;
- int offset;
- int value;
- STRBUFF *buf_face;
- char *result;
- char buf[64];
-
- buf_face = new_strBUFF(1024);
- nelems = ArrayGetNItems(ARR_NDIM(array),
ARR_DIMS(array));postgis-users at postgis.refractions.net>
-
- add_str_simple(buf_face, "<IndexedFaceSet coordIndex='");
-
- for (i=0, j=0, offset=0; i<nelems ; i++, offset += sizeof(int)) {
-
- /* Add a -1 as a face separator (X3D syntax) */
- if (!(j % ARR_DIMS(array)[1]) && j!=0)
- {
- sprintf(buf, "-1,");
- add_str_simple(buf_face, buf);
- }
-
- /* retrieve current array value */
- value = *( (int *) (ARR_DATA_PTR(array) + offset) );
-
- /* -1 value are ignored (could be a way to code
postgis-users at postgis.refractions.net>
- various faces dimension in Postgres array) */
- if (value != -1)
- {
- j++;
- sprintf(buf,"%i,",value);
- add_str_simple(buf_face, buf);
- }
- }
-
- /* remove last comma and close IndexedFaceSet tag*/
- buf_face->length--;
- add_str_simple(buf_face, "'>\n");
-
- /* retrieve string to return */
- result = to_CString(buf_face);
- delete_StrBUFF(buf_face);
-
- return result;
-}
-
-/*
- * takes a GEOMETRY and returns a X3D representation (point related)
- */
- char *
-geometry_to_x3d(uchar *geom)
-{
- int type;
- LWPOINT *point;
- LWGEOM_INSPECTED *inspected;
-
- type = lwgeom_getType(geom[0]);
-
- switch (type)
- {
-
- case POINTTYPE:
- point = lwpoint_deserialize(geom);
- return asx3d_point(point);
-
- case MULTIPOINTTYPE:
- inspected = lwgeom_inspect(geom);
- return asx3d_inspected(inspected);
-
- default:
- lwerror("geometry_to_x3d: '%s' are not supported",
- lwgeom_typename(type));
- return NULL;
- }
-}
-
- static size_t
-asx3d_point_size(LWPOINT *point)
-{
- int size;
- size = pointArray_X3Dsize(point->point);
- size += sizeof(",");
- return size;
-}
-
- static size_t
-asx3d_point_buf(LWPOINT *point, char *output)
-{
- char *ptr = output;
-
- ptr += pointArray_toX3D(point->point, ptr);
- ptr += sprintf(ptr, ",");
-
- return (ptr-output);
-}
-
- static char *
-asx3d_point(LWPOINT *point)
-{
- char *output;
- int size;
-
- size = asx3d_point_size(point);
- output = palloc(size);
- asx3d_point_buf(point, output);
- return output;
-}
-
-/*
- * Compute max size required for X3D version of this
- * inspected geometry. Will recurse when needed.
- * Don't call this with single-geoms inspected.
- */
- static size_t
-asx3d_inspected_size(LWGEOM_INSPECTED *insp)
-{
- int i;
- size_t size;
-
- /* the longest possible multi version */
- size = sizeof("<Coordinate point=''/>");
-
- for (i=0; i<insp->ngeometries; i++)
- {
- LWPOINT *point;
- LWGEOM_INSPECTED *subinsp;
- uchar *subgeom;
-
- if ((point=lwgeom_getpoint_inspected(insp, i)))
- {
- size += asx3d_point_size(point);
- pfree_point(point);
- }
- else
- {
- subgeom = lwgeom_getsubgeometry_inspected(insp, i);
- subinsp = lwgeom_inspect(subgeom);
- size += asx3d_inspected_size(subinsp);
- pfree_inspected(subinsp);
- }
- }
-
- return size;
-}
-
-/*
- * Don't call this with single-geoms inspected!
- */
- static size_t
-asx3d_inspected_buf(LWGEOM_INSPECTED *insp, char *output)
-{
- char *ptr;
- int i;
-
- ptr = output;
-
- ptr += sprintf(ptr, "<Coordinate point='");
-
- for (i=0; i<insp->ngeometries; i++)
- {
- LWPOINT *point;
- LWGEOM_INSPECTED *subinsp;
- uchar *subgeom;
-
- if ((point=lwgeom_getpoint_inspected(insp, i)))
- {
- ptr += asx3d_point_buf(point, ptr);
- pfree_point(point);
- }
- else
- {
- subgeom = lwgeom_getsubgeometry_inspected(insp, i);
- subinsp = lwgeom_inspect(subgeom);
- ptr += asx3d_inspected_buf(subinsp, ptr);
- pfree_inspected(subinsp);
- }
- }
-
- /* Remove last comma and close outmost tag */
- ptr += sprintf(--ptr, "'/>");
-
- return (ptr-output);
-}
-
-/*
- * Don't call this with single-geoms inspected!
- */
- static char *
-asx3d_inspected(LWGEOM_INSPECTED *insp)
-{
- char *x3d;
- size_t size;
-
- size = asx3d_inspected_size(insp);
- x3d = palloc(size);
- asx3d_inspected_buf(insp, x3d);
- return x3d;
-}postgis-users at postgis.refractions.net>
-
-/*
- * Returns maximum size of rendered pointarray in bytes.
- */
- static size_t
-pointArray_X3Dsize(POINTARRAY *pa)
-{
- return TYPE_NDIMS(pa->dims) * pa->npoints *
- (SHOW_DIGS + (TYPE_NDIMS(pa->dims) - 1));
-}
-
- static size_t
-pointArray_toX3D(POINTARRAY *pa, char *output)
-{
- int i;
- char *ptr;
-
- ptr = output;
-
- if ( ! TYPE_HASZ(pa->dims) )
- {
- for (i=0; i<pa->npoints; i++)
- {
- POINT2D pt;
- getPoint2d_p(pa, i, &pt);
- if ( i ) ptr += sprintf(ptr, " ");
- ptr += sprintf(ptr, "%.*g %.*g 0",
- precision, pt.x,
- precision, pt.y);
- }
- }
- else
- {
- for (i=0; i<pa->npoints; i++)
- {
- POINT4D pt;
- getPoint4d_p(pa, i, &pt);
- if ( i ) ptr += sprintf(ptr, " ");
- ptr += sprintf(ptr, "%.*g %.*g %.*g",
- precision, pt.x,
- precision, pt.y,
- precision, pt.z);
- }
- }
-
- return ptr-output;
-}
-
-/**********************************************************************
- * $Log$
- **********************************************************************/
diff -Nu lwgeom/lwpostgis.sql.in ../postgis-svn/lwgeom/lwpostgis.sql.in
--- lwgeom/lwpostgis.sql.in 2007-04-03 17:14:37.000000000 +0200
+++ ../postgis-svn/lwgeom/lwpostgis.sql.in 2006-12-15
11:48:56.000000000 +0100
@@ -3096,23 +3096,6 @@
AS 'SELECT AsUKML(transform($1,4326))'
LANGUAGE 'SQL' _IMMUTABLE_STRICT; -- WITH (isstrict,iscachable);
-
------------------------------------------------------------------------
--- X3D OUTPUT
------------------------------------------------------------------------
--- AsX3D(geom, faces, precision)
-CREATE OR REPLACE FUNCTION AsX3D(geometry, integer[], int4)
- RETURNS TEXT
- AS '@MODULE_FILENAME@','LWGEOM_asX3D'
- LANGUAGE 'C' _IMMUTABLE_STRICT; -- WITH (isstrict,iscachable);
-
--- AsX3D(geom, faces) / precision=15
-CREATE OR REPLACE FUNCTION AsX3D(geometry, integer[])
- RETURNS TEXT
- AS '@MODULE_FILENAME@','LWGEOM_asX3D'
- LANGUAGE 'C' _IMMUTABLE_STRICT; -- WITH (isstrict,iscachable);
-
-
------------------------------------------------------------------------
-- OGC defined
------------------------------------------------------------------------
@@ -3742,3 +3725,4 @@
---------------------------------------------------------------
COMMIT;
+
diff -Nu lwgeom/Makefile ../postgis-svn/lwgeom/Makefile
--- lwgeom/Makefile 2007-04-03 17:12:32.000000000 +0200
+++ ../postgis-svn/lwgeom/Makefile 2006-12-15 11:48:56.000000000 +0100
@@ -84,7 +84,7 @@
SA_OBJS=measures.o box2d.o ptarray.o lwgeom_api.o lwgeom.o lwpoint.o
lwline.o lwpoly.o lwmpoint.o lwmline.o lwmpoly.o lwcollection.o
$(GEOS_WRAPPER) $(JTS_WRAPPER) wktunparse.o lwgparse.o wktparse.tab.o
lex.yy.o vsprintf.o
-OBJS=$(SA_OBJS) liblwgeom.o lwgeom_pg.o lwgeom_debug.o lwgeom_spheroid.o
lwgeom_ogc.o lwgeom_functions_analytic.o $(JTS_OBJ) lwgeom_inout.o
lwgeom_estimate.o lwgeom_functions_basic.o lwgeom_gist.o lwgeom_btree.o
lwgeom_transform.o stringBuffer.o lwgeom_box.o lwgeom_box3d.o
lwgeom_box2dfloat4.o lwgeom_chip.o lwgeom_svg.o lwgeom_gml.o lwgeom_kml.o
lwgeom_x3d.o lwgeom_triggers.o lwgeom_dump.o lwgeom_functions_lrs.o
long_xact.o lwcurve.o lwcompound.o lwcurvepoly.o lwmcurve.o lwmsurface.o
lwgeom_sqlmm.o
+OBJS=$(SA_OBJS) liblwgeom.o lwgeom_pg.o lwgeom_debug.o lwgeom_spheroid.o
lwgeom_ogc.o lwgeom_functions_analytic.o $(JTS_OBJ) lwgeom_inout.o
lwgeom_estimate.o lwgeom_functions_basic.o lwgeom_gist.o lwgeom_btree.o
lwgeom_transform.o stringBuffer.o lwgeom_box.o lwgeom_box3d.o
lwgeom_box2dfloat4.o lwgeom_chip.o lwgeom_svg.o lwgeom_gml.o lwgeom_kml.o
lwgeom_triggers.o lwgeom_dump.o lwgeom_functions_lrs.o long_xact.o lwcurve.o
lwcompound.o lwcurvepoly.o lwmcurve.o lwmsurface.o lwgeom_sqlmm.o
#OTHERS=y.output lex.yy.c wktparse.tab.c wktparse.tab.h lwpostgis.sql
OTHERS=y.output postgis_geos_version.h
--
Olivier Courtin
Camptocamp France SAS
_______________________________________________
postgis-users mailing list
postgis-users at postgis.refractions.net
http://postgis.refractions.net/mailman/listinfo/postgis-users
More information about the postgis-users
mailing list