[postgis-users] X3D and Postgis

Olivier Courtin olivier.courtin at camptocamp.com
Tue Apr 3 09:17:19 PDT 2007


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

  From MAILER-DAEMON  Tue Apr  3 12:01:53 2007
Return-Path: <>
X-Original-To: postgis-users at postgis.refractions.net
Delivered-To: postgis-users at netnation.refractions.net
Received: from mail.inet.dk (mail99.123hotel.dk [80.160.71.178])
	by netnation.refractions.net (Postfix) with ESMTP id 9BD272C07BC
	for <postgis-users at postgis.refractions.net>;
	Tue,  3 Apr 2007 12:01:31 -0700 (PDT)
Received: from ([64.40.100.236])
	by mail.inet.dk (80.160.71.178=mail.inet.dk) with SMTP id IXE62630
	for <postgis-users at postgis.refractions.net>;
	Tue, 03 Apr 2007 21:01:30 +0200
Date: Tue, 03 Apr 2007 21:01:30 +0200
From: Martin Hoegh <mh at svaj.dk>
To: <postgis-users at postgis.refractions.net>
Message-Id: <914597935 at mail.inet.dk>
Content-Type: text/plain; charset="utf-8"
Subject: [postgis-users] Re: postgis-users Digest, Vol 54, Issue 3
X-BeenThere: postgis-users at postgis.refractions.net
X-Mailman-Version: 2.1.5
Precedence: list
Reply-To: PostGIS Users Discussion <postgis-users at postgis.refractions.net>
List-Id: PostGIS Users Discussion <postgis-users.postgis.refractions.net>
List-Unsubscribe: <http://postgis.refractions.net/mailman/listinfo/postgis-users>,
	<mailto:postgis-users-request at postgis.refractions.net?subject=unsubscribe>
List-Archive: <http://lists.refractions.net/pipermail/postgis-users>
List-Post: <mailto:postgis-users at postgis.refractions.net>
List-Help: <mailto:postgis-users-request at postgis.refractions.net?subject=help>
List-Subscribe: <http://postgis.refractions.net/mailman/listinfo/postgis-users>,
	<mailto:postgis-users-request at postgis.refractions.net?subject=subscribe>
X-List-Received-Date: Tue, 03 Apr 2007 19:01:53 -0000

Jeg er på forældreorlov indtil d. 14. maj. Mine kollegaer kan traeffes paa tlf. 98129300.

I am on parental leave until May 14. If you have any matter of urgency please do not hesitate to call my collegues on +45 98129300




More information about the postgis-users mailing list