[postgis-devel] Backend crash with RC3 and RC4
strk at refractions.net
strk at refractions.net
Wed Mar 23 08:55:28 PST 2005
RC4 patch is attached.
--strk;
On Wed, Mar 23, 2005 at 04:38:27PM -0000, Mark Cave-Ayland wrote:
>
> > -----Original Message-----
> > From: postgis-devel-bounces at postgis.refractions.net
> > [mailto:postgis-devel-bounces at postgis.refractions.net] On
> > Behalf Of strk at refractions.net
> > Sent: 23 March 2005 16:12
> > To: 'PostGIS Development Discussion'
> > Subject: Re: [postgis-devel] Backend crash with RC3 and RC4
> >
> >
> > Well.. it was less dramatic then I tought.
> > Fix was two fold:
> > - *wrong* box3d computation for COLLECTIONS
> > - *missing* return value check from GEOMSTRY::BOX3D cast
> >
> > Upgrading people will benefit from an addBBOX(dropBBOX(the_geom))
> > update of spatial tables. And a VACUUM ANALYZE afterwards...
> >
> > I hope this won't require an RC5.... what about an RC4-2
> > win32 installer Mark ?
> >
> > --strk;
>
>
> Hi strk,
>
> Hmmm... haven't got time to do a new installer but could quickly compile and
> email Martin a new liblwgeom.dll if you could supply a patch against RC4....
>
> I would say that a crasher is definitely worth bringing out RC5, otherwise
> we get people confused as to whether they are using RC4-1 or RC4-2 (plus it
> doesn't help the Unix users). If you can send me the patch, I'll quickly
> apply and send Martin the DLL. If it works then my call would be go for RC5
> beginning of next week just to avoid confusion....
>
>
> Kind regards,
>
> Mark.
>
> ------------------------
> WebBased Ltd
> South West Technology Centre
> Tamar Science Park
> Plymouth
> PL6 8BT
>
> T: +44 (0)1752 791021
> F: +44 (0)1752 791023
> W: http://www.webbased.co.uk
>
>
> _______________________________________________
> postgis-devel mailing list
> postgis-devel at postgis.refractions.net
> http://postgis.refractions.net/mailman/listinfo/postgis-devel
-------------- next part --------------
Index: CHANGES
===================================================================
RCS file: /home/cvs/postgis/postgis/CHANGES,v
retrieving revision 1.59
retrieving revision 1.61
diff -U2 -r1.59 -r1.61
--- CHANGES 18 Mar 2005 21:04:01 -0000 1.59
+++ CHANGES 23 Mar 2005 16:24:55 -0000 1.61
@@ -1,2 +1,7 @@
+PostGIS 1.0.0
+??????????
+ - small build scripts refinements
+ - BUGFIX in box3d computation (yes, another!)
+
PostGIS 1.0.0RC4
2005/03/18
Index: doc/postgis.xml
===================================================================
RCS file: /home/cvs/postgis/postgis/doc/postgis.xml,v
retrieving revision 1.126
retrieving revision 1.127
diff -U2 -r1.126 -r1.127
--- doc/postgis.xml 4 Mar 2005 19:31:36 -0000 1.126
+++ doc/postgis.xml 21 Mar 2005 12:24:31 -0000 1.127
@@ -4402,13 +4402,15 @@
</varlistentry>
- <varlistentry>
- <term>estimated_extent([schema], table, geocolumn)</term>
- <listitem>
- <para> Return the 'estimated' extent of the given spatial table. The estimated is taken from the geometry column's statistics gathered by running VACUUM ANALYZE, and is statistically about 95% of 'real' extent. The current schema will be used if not specified. </para>
- <para>NOTE: This is only available with PostgreSQL >= 8.0.0</para>
- </listitem>
- </varlistentry>
+ <varlistentry>
+ <term>estimated_extent([schema], table, geocolumn)</term>
+ <listitem>
+ <para> Return the 'estimated' extent of the given spatial table. The estimated is taken from the geometry column's statistics. The current schema will be used if not specified.</para>
+
+ <para>For PostgreSQL>=8.0.0 statistics are gathered by VACUUM ANALYZE and resulting extent will be about 95% of the real one.</para>
+ <para>For PostgreSQL<8.0.0 statistics are gathered by update_geometry_stats() and resulting extent will be exact.</para>
+ </listitem>
+ </varlistentry>
- <varlistentry>
+ <varlistentry>
<term>find_srid(varchar,varchar,varchar)</term>
Index: jdbc2/.cvsignore
===================================================================
RCS file: /home/cvs/postgis/postgis/jdbc2/.cvsignore,v
retrieving revision 1.5
retrieving revision 1.6
diff -U2 -r1.5 -r1.6
--- jdbc2/.cvsignore 4 Mar 2005 15:22:01 -0000 1.5
+++ jdbc2/.cvsignore 21 Mar 2005 13:43:42 -0000 1.6
@@ -1,6 +1,5 @@
bin
compile
-postgis.jar
-postgis_debug.jar
+*.jar
stubbin
stubcompile
Index: lwgeom/Makefile
===================================================================
RCS file: /home/cvs/postgis/postgis/lwgeom/Makefile,v
retrieving revision 1.72
retrieving revision 1.73
diff -U2 -r1.72 -r1.73
--- lwgeom/Makefile 18 Mar 2005 12:43:23 -0000 1.72
+++ lwgeom/Makefile 21 Mar 2005 17:52:06 -0000 1.73
@@ -139,5 +139,5 @@
lwpostgis.sql: lwpostgis.sql.in
- cpp -P -traditional-cpp -DUSE_VERSION=$(USE_VERSION) $< | sed -e 's:@MODULE_FILENAME@:$(MODULE_FILENAME):g;s:@POSTGIS_VERSION@:$(POSTGIS_VERSION):g;s:@POSTGIS_SCRIPTS_VERSION@:$(SCRIPTS_VERSION):g;s/@POSTGIS_BUILD_DATE@/$(POSTGIS_BUILD_DATE)/g' | grep -v ^# > $@
+ cpp -P -traditional-cpp -DUSE_VERSION=$(USE_VERSION) $< | sed -e 's:@MODULE_FILENAME@:$(MODULE_FILENAME):g;s:@POSTGIS_VERSION@:$(POSTGIS_VERSION):g;s:@POSTGIS_SCRIPTS_VERSION@:$(SCRIPTS_VERSION):g;s/@POSTGIS_BUILD_DATE@/$(POSTGIS_BUILD_DATE)/g' | grep -v '^#' > $@
install: all installdirs install-lwgeom-lib install-lwgeom-scripts
Index: lwgeom/liblwgeom.h
===================================================================
RCS file: /home/cvs/postgis/postgis/lwgeom/liblwgeom.h,v
retrieving revision 1.42
retrieving revision 1.43
diff -U2 -r1.42 -r1.43
--- lwgeom/liblwgeom.h 18 Mar 2005 12:36:27 -0000 1.42
+++ lwgeom/liblwgeom.h 23 Mar 2005 16:23:45 -0000 1.43
@@ -597,47 +597,4 @@
extern int lwgeom_size_inspected(const LWGEOM_INSPECTED *inspected, int geom_number);
-/*
- * This structure is intended to be used for geometry collection construction.
- * Does not allow specification of collection structure
- * (serialization chooses the simpler form)
- */
-typedef struct
-{
- int SRID;
- uchar dims;
- uint32 npoints;
- uchar **points;
- uint32 nlines;
- uchar **lines;
- uint32 npolys;
- uchar **polys;
-} LWGEOM_EXPLODED;
-
-void pfree_exploded(LWGEOM_EXPLODED *exploded);
-
-// Returns a 'palloced' union of the two input exploded geoms.
-// Returns NULL if SRID or ndims do not match.
-LWGEOM_EXPLODED * lwexploded_sum(LWGEOM_EXPLODED *exp1, LWGEOM_EXPLODED *exp2);
-
-/*
- * This function recursively scan the given serialized geometry
- * and returns a list of _all_ subgeoms in it (deep-first)
- */
-extern LWGEOM_EXPLODED *lwgeom_explode(uchar *serialized);
-
-/*
- * Return the length of the serialized form corresponding
- * to this exploded structure.
- */
-extern size_t lwexploded_findlength(LWGEOM_EXPLODED *exp, int wantbbox);
-
-// Serialize an LWGEOM_EXPLODED object.
-// SRID and ndims will be taken from exploded structure.
-// wantbbox will determine result bbox.
-extern uchar *lwexploded_serialize(LWGEOM_EXPLODED *exploded, int wantbbox);
-
-// Same as lwexploded_serialize but writing to pre-allocated space
-extern void lwexploded_serialize_buf(LWGEOM_EXPLODED *exploded, int wantbbox, uchar *buf, size_t *retsize);
-
// note - for a simple type (ie. point), this will have sub_geom[0] = serialized_form.
// for multi-geomtries sub_geom[0] will be a few bytes into the serialized form
@@ -778,4 +735,5 @@
extern uint32 get_uint32(const uchar *loc);
extern int32 get_int32(const uchar *loc);
+extern void printBOX3D(BOX3D *b);
extern void printPA(POINTARRAY *pa);
extern void printLWPOINT(LWPOINT *point);
@@ -1043,5 +1001,4 @@
extern int32 lwgeom_nrings_recursive(uchar *serialized);
-extern void dump_lwexploded(LWGEOM_EXPLODED *exploded);
extern void ptarray_reverse(POINTARRAY *pa);
Index: lwgeom/lwgeom_api.c
===================================================================
RCS file: /home/cvs/postgis/postgis/lwgeom/lwgeom_api.c,v
retrieving revision 1.70
retrieving revision 1.71
diff -U2 -r1.70 -r1.71
--- lwgeom/lwgeom_api.c 18 Mar 2005 12:36:27 -0000 1.70
+++ lwgeom/lwgeom_api.c 23 Mar 2005 16:23:45 -0000 1.71
@@ -9,12 +9,8 @@
//#define PGIS_DEBUG 1
-//#define PGIS_DEBUG_EXPLODED 1
// This is an implementation of the functions defined in lwgeom.h
//forward decs
-#ifdef PGIS_DEBUG_EXPLODED
-void checkexplodedsize(uchar *srl, LWGEOM_EXPLODED *exploded, int alloced, char wantbbox);
-#endif
extern uchar *parse_lwg(const char* geometry, lwallocator allocfunc, lwreporter errfunc);
@@ -1470,9 +1466,18 @@
for (t=0; t<ngeoms; t++)
{
- if ( ! compute_serialized_box3d_p(loc, &b1) ) continue;
- if (result) nboxes += box3d_union_p(result, &b1, result);
- else {
- result = lwalloc(sizeof(BOX3D));
- memcpy(result, &b1, sizeof(BOX3D));
+ if ( compute_serialized_box3d_p(loc, &b1) )
+ {
+#ifdef PGIS_DEBUG
+ lwnotice("Geom %d have box:"); printBOX3D(&b1);
+#endif
+ if (result)
+ {
+ nboxes += box3d_union_p(result, &b1, result);
+ }
+ else
+ {
+ result = lwalloc(sizeof(BOX3D));
+ memcpy(result, &b1, sizeof(BOX3D));
+ }
}
@@ -1511,4 +1516,10 @@
+void printBOX3D(BOX3D *box)
+{
+ lwnotice("BOX3D: %g %g, %g %g", box->xmin, box->ymin,
+ box->xmax, box->ymax);
+}
+
void printPA(POINTARRAY *pa)
{
@@ -1734,620 +1745,4 @@
}
-void
-pfree_exploded(LWGEOM_EXPLODED *exploded)
-{
- if ( exploded->npoints )
- lwfree(exploded->points);
- if ( exploded->nlines )
- lwfree(exploded->lines);
- if ( exploded->npolys )
- lwfree(exploded->polys);
- lwfree(exploded);
-};
-
-/*
- * This function recursively scan the given serialized geometry
- * and returns a list of _all_ subgeoms in it (deep-first)
- */
-LWGEOM_EXPLODED *
-lwgeom_explode(uchar *serialized)
-{
- LWGEOM_INSPECTED *inspected;
- LWGEOM_EXPLODED *subexploded, *result;
- int i;
-
-#ifdef PGIS_DEBUG
- lwnotice("lwgeom_explode called");
-#endif
-
- inspected = lwgeom_inspect(serialized);
-
-
-#ifdef PGIS_DEBUG
-lwnotice("lwgeom_explode: serialized inspected");
-#endif
-
- result = lwalloc(sizeof(LWGEOM_EXPLODED));
- result->points = lwalloc(1);
- result->lines = lwalloc(1);
- result->polys = lwalloc(1);
- result->npoints = 0;
- result->nlines = 0;
- result->npolys = 0;
-
- if ( ! inspected->ngeometries )
- {
- lwfree(result->points);
- lwfree(result->lines);
- lwfree(result->polys);
- result->SRID = -1;
- result->dims = inspected->type;
- pfree_inspected(inspected);
- //lwnotice("lwgeom_explode: no geometries");
- return result;
- }
-
- result->SRID = lwgeom_getsrid(serialized);
- result->dims = inspected->type; // will use ZM only
-
- for (i=0; i<inspected->ngeometries; i++)
- {
-
- uchar *subgeom = inspected->sub_geoms[i];
- int type = lwgeom_getType(subgeom[0]);
-
- if ( type == POINTTYPE )
- {
-#ifdef PGIS_DEBUG
-lwnotice("lwgeom_explode: it's a point");
-#endif
- result->points = lwrealloc(result->points,
- (result->npoints+1)*sizeof(uchar *));
- result->points[result->npoints] = subgeom;
- result->npoints++;
- continue;
- }
-
- if ( type == LINETYPE )
- {
-#ifdef PGIS_DEBUG
-lwnotice("lwgeom_explode: it's a line");
-#endif
- result->lines = lwrealloc(result->lines,
- (result->nlines+1)*sizeof(uchar *));
- result->lines[result->nlines] = subgeom;
- result->nlines++;
- continue;
- }
-
- if ( type == POLYGONTYPE )
- {
-#ifdef PGIS_DEBUG
-lwnotice("lwgeom_explode: it's a polygon");
-#endif
- result->polys = lwrealloc(result->polys,
- (result->npolys+1)*sizeof(uchar *));
- result->polys[result->npolys] = subgeom;
- result->npolys++;
- continue;
- }
-
-#ifdef PGIS_DEBUG
- lwnotice("type of subgeom %d is %d, recursing", i, type);
-#endif
-
- // it's a multi geometry, recurse
- subexploded = lwgeom_explode(subgeom);
-
-#ifdef PGIS_DEBUG
- lwnotice("subgeom %d, exploded: %d point, %d lines, %d polys", i, subexploded->npoints, subexploded->nlines, subexploded->npolys);
-#endif
-
- // Re-allocate adding space for new exploded geoms
- // (-1 because 1 was already allocated for the collection)
- // Copy subgeom pointers from subexploded to current
- // exploded.
-
- if ( subexploded->npoints )
- {
- result->points = lwrealloc(result->points,
- sizeof(uchar *)*(result->npoints+subexploded->npoints-1));
- if ( ! result )
- lwerror("Out of virtual memory");
-
-#ifdef PGIS_DEBUG
- lwnotice("lwrealloc'ed exploded->points");
-#endif
-
- memcpy(&(result->points[result->npoints]),
- subexploded->points,
- subexploded->npoints*sizeof(uchar *));
-
-#ifdef PGIS_DEBUG
- lwnotice("memcpied exploded->points");
-#endif
-
- result->npoints += subexploded->npoints;
-
-#ifdef PGIS_DEBUG
- lwnotice("memcopied %d points from subexploded (exploded points: %d", subexploded->npoints, result->npoints);
-#endif
- }
-
- if ( subexploded->nlines )
- {
- result->lines = lwrealloc(result->lines,
- sizeof(uchar *)*
- (result->nlines+subexploded->nlines-1));
-
- memcpy(&(result->lines[result->nlines]),
- subexploded->lines,
- subexploded->nlines*sizeof(uchar *));
-
- result->nlines += subexploded->nlines;
- }
-
- if ( subexploded->npolys )
- {
- result->polys = lwrealloc(result->polys,
- sizeof(uchar *)*
- (result->npolys+subexploded->npolys-1));
-
- memcpy(&(result->polys[result->npolys]),
- subexploded->polys,
- subexploded->npolys*sizeof(uchar *));
-
- result->npolys += subexploded->npolys;
- }
-
- // release subexploded memory
- pfree_exploded(subexploded);
-
- }
-
- pfree_inspected(inspected);
-
-#ifdef PGIS_DEBUG
-lwnotice("lwgeom_explode: returning");
-#endif
-
- return result;
-}
-
-// Returns a 'lwalloced' union of the two input exploded geoms
-// Returns NULL if SRID or ndims do not match.
-LWGEOM_EXPLODED *
-lwexploded_sum(LWGEOM_EXPLODED *exp1, LWGEOM_EXPLODED *exp2)
-{
- LWGEOM_EXPLODED *expcoll;
- uchar *loc;
-
- if ( TYPE_GETZM(exp1->dims) != TYPE_GETZM(exp2->dims) )
- {
- lwerror("lwexploded_sum: can't sum mixed DIMS geoms (%d/%d)",
- TYPE_GETZM(exp1->dims), TYPE_GETZM(exp2->dims));
- return NULL;
- }
- if ( exp1->SRID != exp2->SRID )
- {
- lwerror("lwexploded_sum: can't sum mixed SRID geoms (%d/%d)",
- exp1->SRID, exp2->SRID);
- return NULL;
- }
-
- expcoll = lwalloc(sizeof(LWGEOM_EXPLODED));
-
- expcoll->npoints = exp1->npoints + exp2->npoints;
- if ( expcoll->npoints ) {
- expcoll->points = lwalloc(expcoll->npoints*sizeof(char *));
- loc = (char *)&(expcoll->points[0]);
- if ( exp1->npoints ) {
- memcpy(loc, exp1->points,
- exp1->npoints*sizeof(char *));
- loc += exp1->npoints*sizeof(char *);
- }
- if ( exp2->npoints ) {
- memcpy(loc, exp2->points,
- exp2->npoints*sizeof(char *));
- }
- }
-
- expcoll->nlines = exp1->nlines + exp2->nlines;
- if ( expcoll->nlines ) {
- expcoll->lines = lwalloc(expcoll->nlines*sizeof(char *));
- loc = (char *)&(expcoll->lines[0]);
- if ( exp1->nlines ) {
- memcpy(loc, exp1->lines,
- exp1->nlines*sizeof(char *));
- loc += exp1->nlines*sizeof(char *);
- }
- if ( exp2->nlines ) {
- memcpy(loc, exp2->lines,
- exp2->nlines*sizeof(char *));
- }
- }
-
- expcoll->npolys = exp1->npolys + exp2->npolys;
- if ( expcoll->npolys ) {
- expcoll->polys = lwalloc(expcoll->npolys*sizeof(char *));
- loc = (char *)&(expcoll->polys[0]);
- if ( exp1->npolys ) {
- memcpy(loc, exp1->polys,
- exp1->npolys*sizeof(char *));
- loc += exp1->npolys*sizeof(char *);
- }
- if ( exp2->npolys ) {
- memcpy(loc, exp2->polys,
- exp2->npolys*sizeof(char *));
- }
- }
-
- expcoll->dims = exp1->dims;
- expcoll->SRID = exp1->SRID;
-
- return expcoll;
-}
-
-/*
- * Serialized a LWGEOM_EXPLODED structure
- */
-uchar *
-lwexploded_serialize(LWGEOM_EXPLODED *exploded, int wantbbox)
-{
- size_t sizecom = 0;
- size_t size;
- uchar *result;
-
- size = lwexploded_findlength(exploded, wantbbox);
- result = lwalloc(size);
- lwexploded_serialize_buf(exploded, wantbbox, result, &sizecom);
-#ifdef PGIS_DEBUG
- lwnotice("lwexploded_serialize: findlength:%d, serialize_buf:%d", size, sizecom);
-#endif
- return result;
-}
-
-/*
- * Serialized a LWGEOM_EXPLODED structure into a
- * pre-allocated memory space.
- * Use lwexploded_findlength to know the required size
- * of the provided buffer.
- */
-void
-lwexploded_serialize_buf(LWGEOM_EXPLODED *exploded, int wantbbox,
- uchar *buf, size_t *retsize)
-{
- size_t size=0;
- int i;
- int ntypes = 0;
- int ngeoms = 0;
- uchar *loc;
- int outtype = 0;
- LWPOLY *poly;
- LWLINE *line;
- LWPOINT *point;
- BOX2DFLOAT4 *box2d;
- BOX3D *box3d;
-
- ngeoms = exploded->npoints + exploded->nlines + exploded->npolys;
-
- if ( ngeoms == 0 )
- {
- lwgeom_constructempty_buf(exploded->SRID,
- TYPE_HASZ(exploded->dims), TYPE_HASM(exploded->dims),
- buf, retsize);
- return;
- }
-
-
- // For a single geometry just set SRID and BBOX (if requested)
- if ( ngeoms == 1 )
- {
- loc = buf;
-
- if ( exploded->npoints ) {
-
- if ( wantbbox && !
- lwgeom_hasBBOX(exploded->points[0][0]) )
- {
- loc += sizeof(BOX2DFLOAT4);
- }
- point = lwpoint_deserialize(exploded->points[0]);
- point->SRID = exploded->SRID;
- lwpoint_serialize_buf(point, loc, &size);
- pfree_point(point);
- }
- else if ( exploded->nlines ) {
- if ( wantbbox && !
- lwgeom_hasBBOX(exploded->lines[0][0]) )
- {
- loc += sizeof(BOX2DFLOAT4);
- }
- line = lwline_deserialize(exploded->lines[0]);
- line->SRID = exploded->SRID;
- lwline_serialize_buf(line, loc, &size);
- pfree_line(line);
- }
- else if ( exploded->npolys ) {
- if ( wantbbox && !
- lwgeom_hasBBOX(exploded->polys[0][0]) )
- {
- loc += sizeof(BOX2DFLOAT4);
- }
- poly = lwpoly_deserialize(exploded->polys[0]);
- poly->SRID = exploded->SRID;
- lwpoly_serialize_buf(poly, loc, &size);
- pfree_polygon(poly);
-
- }
- else {
- if ( retsize ) *retsize = 0;
- return; // ERROR !!
- }
-
-
- // Now compute the bounding box and write it
- if ( wantbbox && ! lwgeom_hasBBOX(loc[0]) )
- {
- buf[0] = loc[0];
- TYPE_SETHASBBOX(buf[0], 1);
- box3d = compute_serialized_box3d(loc);
- box2d = box3d_to_box2df(box3d);
- loc = buf+1;
- memcpy(loc, box2d, sizeof(BOX2DFLOAT4));
- size += sizeof(BOX2DFLOAT4);
- }
-
- if (retsize) *retsize = size;
- return;
- }
-
- if ( exploded->npoints ) {
- ntypes++;
- outtype = (exploded->npoints>1) ? MULTIPOINTTYPE : POINTTYPE;
- }
- if ( exploded->nlines ) {
- ntypes++;
- if ( outtype ) outtype = COLLECTIONTYPE;
- else outtype = (exploded->nlines>1) ? MULTILINETYPE : LINETYPE;
- }
- if ( exploded->npolys ) {
- ntypes++;
- if ( outtype ) outtype = COLLECTIONTYPE;
- else outtype = (exploded->npolys>1) ? MULTIPOLYGONTYPE : POLYGONTYPE;
- }
-
-#ifdef PGIS_DEBUG
- lwnotice(" computed outtype: %d, ngeoms: %d", outtype, ngeoms);
-#endif
-
-
- loc = buf+1; // skip type
-
- if ( wantbbox ) loc += sizeof(BOX2DFLOAT4); // skip box
- if ( exploded->SRID != -1 ) loc += 4; // skip SRID
-
- // If we have more then one type of geom
- // write that number in the 'ngeoms' field of the
- // output serialized form (internal geoms would be multi themself).
- // Else rewind location pointer so to overwrite result type.
- if ( ntypes > 1 ) {
- memcpy(loc, &ntypes, 4);
- loc += 4;
- } else {
- loc--; // let the type be specified later.
- }
-
- if ( exploded->npoints > 1 )
- {
- loc[0] = lwgeom_makeType_full(
- TYPE_HASZ(exploded->dims), TYPE_HASM(exploded->dims),
- 0, MULTIPOINTTYPE, 0);
- loc++;
- memcpy(loc, &exploded->npoints, 4); // numpoints
- loc += 4;
- }
- // Serialize points stripping BBOX and SRID if any
- for (i=0; i<exploded->npoints; i++)
- {
- size_t subsize;
- point = lwpoint_deserialize(exploded->points[i]);
- point->SRID = -1;
- lwpoint_serialize_buf(point, loc, &subsize);
- pfree_point(point);
- loc += subsize;
- }
-
- if ( exploded->nlines > 1 )
- {
- loc[0] = lwgeom_makeType_full(
- TYPE_HASZ(exploded->dims),
- TYPE_HASM(exploded->dims),
- 0, MULTILINETYPE, 0);
- loc++;
- memcpy(loc, &exploded->nlines, 4); // numlines
- loc += 4;
- }
- // Serialize lines stripping BBOX and SRID if any
- for (i=0; i<exploded->nlines; i++)
- {
- size_t subsize;
-
- line = lwline_deserialize(exploded->lines[i]);
- if ( line == NULL )
- {
- lwerror("Error deserializing %dnt line from exploded geom", i);
- return;
- }
- line->SRID = -1;
- lwline_serialize_buf(line, loc, &subsize);
- pfree_line(line);
- loc += subsize;
- }
-
- if ( exploded->npolys > 1 )
- {
- loc[0] = lwgeom_makeType_full(
- TYPE_HASZ(exploded->dims),
- TYPE_HASM(exploded->dims),
- 0, MULTIPOLYGONTYPE, 0);
- loc++;
- memcpy(loc, &exploded->npolys, 4); // numpolys
- loc += 4;
- }
- // Serialize polys stripping BBOX and SRID if any
- for (i=0; i<exploded->npolys; i++)
- {
- size_t subsize;
-
- poly = lwpoly_deserialize(exploded->polys[i]);
- if ( poly == NULL )
- {
- lwerror("Error deserializing %dnt polygon from exploded geom", i);
- return;
- }
- poly->SRID = -1;
- lwpoly_serialize_buf(poly, loc, &subsize);
- pfree_polygon(poly);
- loc += subsize;
- }
-
- // Register now the number of written bytes
- if (retsize) *retsize = (loc-buf);
-
- // Ok. now we need to add type, SRID and bbox
- buf[0] = lwgeom_makeType_full(
- TYPE_HASZ(exploded->dims),
- TYPE_HASM(exploded->dims),
- (exploded->SRID!=-1), outtype, wantbbox);
- loc = buf+1;
-
- if ( wantbbox )
- {
- box3d = compute_serialized_box3d(buf);
- box2d = box3d_to_box2df(box3d);
- memcpy(loc, box2d, sizeof(BOX2DFLOAT4));
- loc += sizeof(BOX2DFLOAT4);
- }
-
- if ( exploded->SRID != -1 )
- {
- memcpy(loc, &(exploded->SRID), 4);
- loc += 4; // useless.. we've finished
- }
-
-#ifdef PGIS_DEBUG
- lwnotice("lwexploded_serialize finished");
- lwnotice(" type: %d", lwgeom_getType(buf[0]));
- lwnotice(" SRID: %d", lwgeom_getsrid(buf));
- if ( lwgeom_hasBBOX(buf[0]) )
- {
- {
- BOX2DFLOAT4 boxbuf;
- getbox2d_p(buf, &boxbuf);
- lwnotice(" BBOX: %f,%f %f,%f",
- boxbuf.xmin, boxbuf.ymin,
- boxbuf.xmax, boxbuf.ymax);
- }
- }
- lwnotice(" numgeoms: %d", lwgeom_getnumgeometries(buf));
-#endif
-
- return;
-}
-
-#ifdef PGIS_DEBUG_EXPLODED
-void
-checkexplodedsize(uchar *srl, LWGEOM_EXPLODED *exp, int alloced, char wantbbox)
-{
- lwnotice("exploded len: serialized:%d computed:%d alloced:%d",
- lwgeom_size(srl), lwexploded_findlength(exp, wantbbox),
- alloced);
-}
-#endif
-
-size_t
-lwexploded_findlength(LWGEOM_EXPLODED *exploded, int wantbbox)
-{
- size_t size=0;
- char ntypes=0;
- uint32 i;
-
-
- // find sum of sizes of all geoms.
- // substract size of eventually embedded SRID and BBOXes
- if ( exploded->npoints )
- {
- ntypes++;
- for (i=0; i<exploded->npoints; i++)
- {
- size += lwgeom_size_point(exploded->points[i]);
- if ( lwgeom_hasBBOX(exploded->points[i][0]) )
- size -= sizeof(BOX2DFLOAT4);
- if ( lwgeom_hasSRID(exploded->points[i][0]) )
- size -= 4;
- }
- // add multigeom header size
- if ( exploded->npoints > 1 )
- {
- size += 1; // type
- size += 4; // numgeometries
- }
- }
- if ( exploded->nlines )
- {
- ntypes++;
- for (i=0; i<exploded->nlines; i++)
- {
- size += lwgeom_size_line(exploded->lines[i]);
- if ( lwgeom_hasBBOX(exploded->lines[i][0]) )
- size -= sizeof(BOX2DFLOAT4);
- if ( lwgeom_hasSRID(exploded->lines[i][0]) )
- size -= 4;
- }
- // add multigeom header size
- if ( exploded->nlines > 1 )
- {
- size += 1; // type
- size += 4; // numgeometries
- }
- }
- if ( exploded->npolys )
- {
- ntypes++;
- for (i=0; i<exploded->npolys; i++)
- {
- size += lwgeom_size_poly(exploded->polys[i]);
- if ( lwgeom_hasBBOX(exploded->polys[i][0]) )
- size -= sizeof(BOX2DFLOAT4);
- if ( lwgeom_hasSRID(exploded->polys[i][0]) )
- size -= 4;
- }
- // add multigeom header size
- if ( exploded->npolys > 1 )
- {
- size += 1; // type
- size += 4; // numgeometries
- }
- }
-
- /* structure is empty */
- if ( ! ntypes ) return lwgeom_empty_length(exploded->SRID);
-
- /* multi-typed geom (collection), add collection header */
- if ( ntypes > 1 )
- {
- size += 1; // type
- size += 4; // numgeometries
- }
-
- /*
- * Add BBOX and SRID if required
- */
- if ( exploded->SRID != -1 ) size += 4;
- if ( wantbbox ) size += sizeof(BOX2DFLOAT4);
-
- return size;
-}
char
Index: lwgeom/lwgeom_box3d.c
===================================================================
RCS file: /home/cvs/postgis/postgis/lwgeom/lwgeom_box3d.c,v
retrieving revision 1.13
retrieving revision 1.15
diff -U2 -r1.13 -r1.15
--- lwgeom/lwgeom_box3d.c 18 Mar 2005 12:36:27 -0000 1.13
+++ lwgeom/lwgeom_box3d.c 23 Mar 2005 17:10:17 -0000 1.15
@@ -1,385 +1,389 @@
-/**********************************************************************
- *
- * BOX3D IO and conversions
- *
- **********************************************************************/
-
-#include <math.h>
-#include <float.h>
-#include <string.h>
-#include <stdio.h>
-#include <errno.h>
-
-#include "postgres.h"
-#include "fmgr.h"
-#include "utils/elog.h"
-#include "utils/geo_decls.h"
-
-#include "lwgeom_pg.h"
-#include "liblwgeom.h"
-
-
-//#define PGIS_DEBUG
-// basic implementation of BOX2D
-
-#define SHOW_DIGS_DOUBLE 15
-#define MAX_DIGS_DOUBLE (SHOW_DIGS_DOUBLE + 6 + 1 + 3 +1)
-
-//forward defs
-Datum BOX3D_in(PG_FUNCTION_ARGS);
-Datum BOX3D_out(PG_FUNCTION_ARGS);
-Datum LWGEOM_to_BOX3D(PG_FUNCTION_ARGS);
-Datum BOX3D_to_LWGEOM(PG_FUNCTION_ARGS);
-Datum BOX3D_expand(PG_FUNCTION_ARGS);
-Datum BOX3D_to_BOX2DFLOAT4(PG_FUNCTION_ARGS);
-Datum BOX3D_to_BOX(PG_FUNCTION_ARGS);
-Datum BOX3D_xmin(PG_FUNCTION_ARGS);
-Datum BOX3D_ymin(PG_FUNCTION_ARGS);
-Datum BOX3D_zmin(PG_FUNCTION_ARGS);
-Datum BOX3D_xmax(PG_FUNCTION_ARGS);
-Datum BOX3D_ymax(PG_FUNCTION_ARGS);
-Datum BOX3D_zmax(PG_FUNCTION_ARGS);
-Datum BOX3D_combine(PG_FUNCTION_ARGS);
-
-/*
- * BOX3D_in - takes a string rep of BOX3D and returns internal rep
- *
- * example:
- * "BOX3D(x1 y1 z1,x2 y2 z2)"
- * or "BOX3D(x1 y1,x2 y2)" z1 and z2 = 0.0
- *
- *
- */
-
-PG_FUNCTION_INFO_V1(BOX3D_in);
-Datum BOX3D_in(PG_FUNCTION_ARGS)
-{
- char *str = PG_GETARG_CSTRING(0);
- int nitems;
- BOX3D *box = (BOX3D *) palloc(sizeof(BOX3D));
- box->zmin = 0;
- box->zmax = 0;
-
-
-//printf( "box3d_in gets '%s'\n",str);
-
- if (strstr(str,"BOX3D(") != str )
- {
- pfree(box);
- elog(ERROR,"BOX3D parser - doesnt start with BOX3D(");
- PG_RETURN_NULL();
- }
-
- nitems = sscanf(str,"BOX3D(%le %le %le,%le %le %le)",
- &box->xmin, &box->ymin, &box->zmin,
- &box->xmax, &box->ymax, &box->zmax);
- if (nitems != 6 )
- {
- nitems = sscanf(str,"BOX3D(%le %le,%le %le)",
- &box->xmin, &box->ymin, &box->xmax, &box->ymax);
- if (nitems != 4)
- {
- pfree(box);
- elog(ERROR,"BOX3D parser - couldnt parse. It should look like: BOX3D(xmin ymin zmin,xmax ymax zmax) or BOX3D(xmin ymin,xmax ymax)");
- PG_RETURN_NULL();
- }
- }
-
- if (box->xmin > box->xmax)
- {
- float tmp = box->xmin;
- box->xmin = box->xmax;
- box->xmax = tmp;
- }
- if (box->ymin > box->ymax)
- {
- float tmp = box->ymin;
- box->ymin = box->ymax;
- box->ymax = tmp;
- }
- if (box->zmin > box->zmax)
- {
- float tmp = box->zmin;
- box->zmin = box->zmax;
- box->zmax = tmp;
- }
- PG_RETURN_POINTER(box);
-}
-
-
-/*
- * Takes an internal rep of a BOX3D and returns a string rep.
- *
- * example:
- * "BOX3D(xmin ymin zmin, xmin ymin zmin)"
- */
-PG_FUNCTION_INFO_V1(BOX3D_out);
-Datum BOX3D_out(PG_FUNCTION_ARGS)
-{
- BOX3D *bbox = (BOX3D *) PG_GETARG_POINTER(0);
- int size;
- char *result;
-
- if (bbox == NULL)
- {
- result = palloc(5);
- strcat(result,"NULL");
- PG_RETURN_CSTRING(result);
- }
-
- size = MAX_DIGS_DOUBLE*6+5+2+4+5+1;
- result = (char *) palloc(size); //double digits+ "BOX3D"+ "()" + commas +null
- sprintf(result, "BOX3D(%.15g %.15g %.15g,%.15g %.15g %.15g)",
- bbox->xmin, bbox->ymin, bbox->zmin,
- bbox->xmax,bbox->ymax,bbox->zmax);
-
- PG_RETURN_CSTRING(result);
-}
-
-PG_FUNCTION_INFO_V1(BOX3D_to_BOX2DFLOAT4);
-Datum BOX3D_to_BOX2DFLOAT4(PG_FUNCTION_ARGS)
-{
- BOX3D *in = (BOX3D *)PG_GETARG_POINTER(0);
- BOX2DFLOAT4 *out = box3d_to_box2df(in);
- PG_RETURN_POINTER(out);
-}
-
-PG_FUNCTION_INFO_V1(BOX3D_to_BOX);
-Datum BOX3D_to_BOX(PG_FUNCTION_ARGS)
-{
- BOX3D *in = (BOX3D *)PG_GETARG_POINTER(0);
- BOX2DFLOAT4 *box2d = box3d_to_box2df(in);
- BOX *box = palloc(sizeof(BOX));
-
- box2df_to_box_p(box2d, box);
- PG_RETURN_POINTER(box);
-}
-
-PG_FUNCTION_INFO_V1(BOX3D_to_LWGEOM);
-Datum BOX3D_to_LWGEOM(PG_FUNCTION_ARGS)
-{
- BOX3D *box = (BOX3D *)PG_GETARG_POINTER(0);
- POINT2D *pts = palloc(sizeof(POINT2D)*5);
- POINTARRAY *pa[1];
- LWPOLY *poly;
- int wantbbox = 0;
- PG_LWGEOM *result;
- char *ser;
-
- // Assign coordinates to POINT2D array
- pts[0].x = box->xmin; pts[0].y = box->ymin;
- pts[1].x = box->xmin; pts[1].y = box->ymax;
- pts[2].x = box->xmax; pts[2].y = box->ymax;
- pts[3].x = box->xmax; pts[3].y = box->ymin;
- pts[4].x = box->xmin; pts[4].y = box->ymin;
-
- // Construct point array
- pa[0] = palloc(sizeof(POINTARRAY));
- pa[0]->serialized_pointlist = (char *)pts;
- TYPE_SETZM(pa[0]->dims, 0, 0);
- pa[0]->npoints = 5;
-
- // Construct polygon
- poly = lwpoly_construct(-1, NULL, 1, pa);
-
- // Serialize polygon
- ser = lwpoly_serialize(poly);
-
- // Construct PG_LWGEOM
- result = PG_LWGEOM_construct(ser, -1, wantbbox);
-
- PG_RETURN_POINTER(result);
-}
-
-/* Expand given box of 'd' units in all directions */
-void
-expand_box3d(BOX3D *box, double d)
-{
- box->xmin -= d;
- box->ymin -= d;
- box->zmin -= d;
-
- box->xmax += d;
- box->ymax += d;
- box->zmax += d;
-}
-
-PG_FUNCTION_INFO_V1(BOX3D_expand);
-Datum BOX3D_expand(PG_FUNCTION_ARGS)
-{
- BOX3D *box = (BOX3D *)PG_GETARG_POINTER(0);
- double d = PG_GETARG_FLOAT8(1);
- BOX3D *result = (BOX3D *)palloc(sizeof(BOX3D));
-
- memcpy(result, box, sizeof(BOX3D));
- expand_box3d(result, d);
-
- PG_RETURN_POINTER(result);
-}
-
-/*
- * convert a PG_LWGEOM to BOX3D
- *
- * NOTE: the bounding box is *always* recomputed as the cache
- * is a box2d, not a box3d...
- *
- */
-PG_FUNCTION_INFO_V1(LWGEOM_to_BOX3D);
-Datum LWGEOM_to_BOX3D(PG_FUNCTION_ARGS)
-{
- PG_LWGEOM *lwgeom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
- BOX3D *result;
-
- result = compute_serialized_box3d(SERIALIZED_FORM(lwgeom));
-
- PG_RETURN_POINTER(result);
-}
-
-PG_FUNCTION_INFO_V1(BOX3D_xmin);
-Datum BOX3D_xmin(PG_FUNCTION_ARGS)
-{
- BOX3D *box = (BOX3D *)PG_GETARG_POINTER(0);
- PG_RETURN_FLOAT8(box->xmin);
-}
-
-PG_FUNCTION_INFO_V1(BOX3D_ymin);
-Datum BOX3D_ymin(PG_FUNCTION_ARGS)
-{
- BOX3D *box = (BOX3D *)PG_GETARG_POINTER(0);
- PG_RETURN_FLOAT8(box->ymin);
-}
-
-PG_FUNCTION_INFO_V1(BOX3D_zmin);
-Datum BOX3D_zmin(PG_FUNCTION_ARGS)
-{
- BOX3D *box = (BOX3D *)PG_GETARG_POINTER(0);
- PG_RETURN_FLOAT8(box->zmin);
-}
-
-PG_FUNCTION_INFO_V1(BOX3D_xmax);
-Datum BOX3D_xmax(PG_FUNCTION_ARGS)
-{
- BOX3D *box = (BOX3D *)PG_GETARG_POINTER(0);
- PG_RETURN_FLOAT8(box->xmax);
-}
-
-PG_FUNCTION_INFO_V1(BOX3D_ymax);
-Datum BOX3D_ymax(PG_FUNCTION_ARGS)
-{
- BOX3D *box = (BOX3D *)PG_GETARG_POINTER(0);
- PG_RETURN_FLOAT8(box->ymax);
-}
-
-PG_FUNCTION_INFO_V1(BOX3D_zmax);
-Datum BOX3D_zmax(PG_FUNCTION_ARGS)
-{
- BOX3D *box = (BOX3D *)PG_GETARG_POINTER(0);
- PG_RETURN_FLOAT8(box->zmax);
-}
-
-
-PG_FUNCTION_INFO_V1(BOX3D_combine);
-Datum BOX3D_combine(PG_FUNCTION_ARGS)
-{
- Pointer box3d_ptr = PG_GETARG_POINTER(0);
- Pointer geom_ptr = PG_GETARG_POINTER(1);
- BOX3D *a,*b;
- PG_LWGEOM *lwgeom;
- BOX3D *box, *result;
-
- if ( (box3d_ptr == NULL) && (geom_ptr == NULL) )
- {
- PG_RETURN_NULL();
- }
-
- result = (BOX3D *)palloc(sizeof(BOX3D));
-
- if (box3d_ptr == NULL)
- {
- lwgeom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
- box = compute_serialized_box3d(SERIALIZED_FORM(lwgeom));
- if ( ! box ) {
- PG_FREE_IF_COPY(lwgeom, 1);
- PG_RETURN_NULL(); // must be the empty geom
- }
- memcpy(result, box, sizeof(BOX3D));
- PG_RETURN_POINTER(result);
- }
-
- // combine_bbox(BOX3D, null) => BOX3D
- if (geom_ptr == NULL)
- {
- memcpy(result, (char *)PG_GETARG_DATUM(0), sizeof(BOX3D));
- PG_RETURN_POINTER(result);
- }
-
- lwgeom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
- box = compute_serialized_box3d(SERIALIZED_FORM(lwgeom));
- if ( ! box ) // must be the empty geom
- {
- PG_FREE_IF_COPY(lwgeom, 1);
- memcpy(result, (char *)PG_GETARG_DATUM(0), sizeof(BOX3D));
- PG_RETURN_POINTER(result);
- }
-
- a = (BOX3D *)PG_GETARG_DATUM(0);
- b = box;
-
- result->xmax = LWGEOM_Maxd(a->xmax, b->xmax);
- result->ymax = LWGEOM_Maxd(a->ymax, b->ymax);
- result->zmax = LWGEOM_Maxd(a->zmax, b->zmax);
- result->xmin = LWGEOM_Mind(a->xmin, b->xmin);
- result->ymin = LWGEOM_Mind(a->ymin, b->ymin);
- result->zmin = LWGEOM_Mind(a->zmin, b->zmin);
-
- PG_RETURN_POINTER(result);
-}
-
-PG_FUNCTION_INFO_V1(BOX3D_construct);
-Datum BOX3D_construct(PG_FUNCTION_ARGS)
-{
- PG_LWGEOM *min = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
- PG_LWGEOM *max = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
- BOX3D *result = palloc(sizeof(BOX3D));
- LWGEOM *minpoint, *maxpoint;
- POINT3DZ minp, maxp;
-
- minpoint = lwgeom_deserialize(SERIALIZED_FORM(min));
- maxpoint = lwgeom_deserialize(SERIALIZED_FORM(max));
-
- if ( TYPE_GETTYPE(minpoint->type) != POINTTYPE ||
- TYPE_GETTYPE(maxpoint->type) != POINTTYPE )
- {
- elog(ERROR, "BOX2DFLOAT4_construct: args must be points");
- PG_RETURN_NULL();
- }
-
- getPoint3dz_p(((LWPOINT *)minpoint)->point, 0, &minp);
- getPoint3dz_p(((LWPOINT *)maxpoint)->point, 0, &maxp);
-
- result->xmax = maxp.x;
- result->ymax = maxp.y;
- result->zmax = maxp.z;
-
- result->xmin = minp.x;
- result->ymin = minp.y;
- result->zmin = minp.z;
-
- PG_RETURN_POINTER(result);
-}
-
-//min(a,b)
-double LWGEOM_Mind(double a, double b)
-{
- if (a<b)
- return a;
- return b;
-}
-
-//max(a,b)
-double LWGEOM_Maxd(double a, double b)
-{
- if (b>a)
- return b;
- return a;
-}
+/**********************************************************************
+ *
+ * BOX3D IO and conversions
+ *
+ **********************************************************************/
+
+#include <math.h>
+#include <float.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include "postgres.h"
+#include "fmgr.h"
+#include "utils/elog.h"
+#include "utils/geo_decls.h"
+
+#include "lwgeom_pg.h"
+#include "liblwgeom.h"
+
+
+//#define PGIS_DEBUG
+// basic implementation of BOX2D
+
+#define SHOW_DIGS_DOUBLE 15
+#define MAX_DIGS_DOUBLE (SHOW_DIGS_DOUBLE + 6 + 1 + 3 +1)
+
+//forward defs
+Datum BOX3D_in(PG_FUNCTION_ARGS);
+Datum BOX3D_out(PG_FUNCTION_ARGS);
+Datum LWGEOM_to_BOX3D(PG_FUNCTION_ARGS);
+Datum BOX3D_to_LWGEOM(PG_FUNCTION_ARGS);
+Datum BOX3D_expand(PG_FUNCTION_ARGS);
+Datum BOX3D_to_BOX2DFLOAT4(PG_FUNCTION_ARGS);
+Datum BOX3D_to_BOX(PG_FUNCTION_ARGS);
+Datum BOX3D_xmin(PG_FUNCTION_ARGS);
+Datum BOX3D_ymin(PG_FUNCTION_ARGS);
+Datum BOX3D_zmin(PG_FUNCTION_ARGS);
+Datum BOX3D_xmax(PG_FUNCTION_ARGS);
+Datum BOX3D_ymax(PG_FUNCTION_ARGS);
+Datum BOX3D_zmax(PG_FUNCTION_ARGS);
+Datum BOX3D_combine(PG_FUNCTION_ARGS);
+
+/*
+ * BOX3D_in - takes a string rep of BOX3D and returns internal rep
+ *
+ * example:
+ * "BOX3D(x1 y1 z1,x2 y2 z2)"
+ * or "BOX3D(x1 y1,x2 y2)" z1 and z2 = 0.0
+ *
+ *
+ */
+
+PG_FUNCTION_INFO_V1(BOX3D_in);
+Datum BOX3D_in(PG_FUNCTION_ARGS)
+{
+ char *str = PG_GETARG_CSTRING(0);
+ int nitems;
+ BOX3D *box = (BOX3D *) palloc(sizeof(BOX3D));
+ box->zmin = 0;
+ box->zmax = 0;
+
+
+//printf( "box3d_in gets '%s'\n",str);
+
+ if (strstr(str,"BOX3D(") != str )
+ {
+ pfree(box);
+ elog(ERROR,"BOX3D parser - doesnt start with BOX3D(");
+ PG_RETURN_NULL();
+ }
+
+ nitems = sscanf(str,"BOX3D(%le %le %le,%le %le %le)",
+ &box->xmin, &box->ymin, &box->zmin,
+ &box->xmax, &box->ymax, &box->zmax);
+ if (nitems != 6 )
+ {
+ nitems = sscanf(str,"BOX3D(%le %le,%le %le)",
+ &box->xmin, &box->ymin, &box->xmax, &box->ymax);
+ if (nitems != 4)
+ {
+ pfree(box);
+ elog(ERROR,"BOX3D parser - couldnt parse. It should look like: BOX3D(xmin ymin zmin,xmax ymax zmax) or BOX3D(xmin ymin,xmax ymax)");
+ PG_RETURN_NULL();
+ }
+ }
+
+ if (box->xmin > box->xmax)
+ {
+ float tmp = box->xmin;
+ box->xmin = box->xmax;
+ box->xmax = tmp;
+ }
+ if (box->ymin > box->ymax)
+ {
+ float tmp = box->ymin;
+ box->ymin = box->ymax;
+ box->ymax = tmp;
+ }
+ if (box->zmin > box->zmax)
+ {
+ float tmp = box->zmin;
+ box->zmin = box->zmax;
+ box->zmax = tmp;
+ }
+ PG_RETURN_POINTER(box);
+}
+
+
+/*
+ * Takes an internal rep of a BOX3D and returns a string rep.
+ *
+ * example:
+ * "BOX3D(xmin ymin zmin, xmin ymin zmin)"
+ */
+PG_FUNCTION_INFO_V1(BOX3D_out);
+Datum BOX3D_out(PG_FUNCTION_ARGS)
+{
+ BOX3D *bbox = (BOX3D *) PG_GETARG_POINTER(0);
+ int size;
+ char *result;
+
+ if (bbox == NULL)
+ {
+ result = palloc(5);
+ strcat(result,"NULL");
+ PG_RETURN_CSTRING(result);
+ }
+
+ size = MAX_DIGS_DOUBLE*6+5+2+4+5+1;
+ result = (char *) palloc(size); //double digits+ "BOX3D"+ "()" + commas +null
+ sprintf(result, "BOX3D(%.15g %.15g %.15g,%.15g %.15g %.15g)",
+ bbox->xmin, bbox->ymin, bbox->zmin,
+ bbox->xmax,bbox->ymax,bbox->zmax);
+
+ PG_RETURN_CSTRING(result);
+}
+
+PG_FUNCTION_INFO_V1(BOX3D_to_BOX2DFLOAT4);
+Datum BOX3D_to_BOX2DFLOAT4(PG_FUNCTION_ARGS)
+{
+ BOX3D *in = (BOX3D *)PG_GETARG_POINTER(0);
+ BOX2DFLOAT4 *out = box3d_to_box2df(in);
+ PG_RETURN_POINTER(out);
+}
+
+PG_FUNCTION_INFO_V1(BOX3D_to_BOX);
+Datum BOX3D_to_BOX(PG_FUNCTION_ARGS)
+{
+ BOX3D *in = (BOX3D *)PG_GETARG_POINTER(0);
+ BOX2DFLOAT4 *box2d = box3d_to_box2df(in);
+ BOX *box = palloc(sizeof(BOX));
+
+ box2df_to_box_p(box2d, box);
+ PG_RETURN_POINTER(box);
+}
+
+PG_FUNCTION_INFO_V1(BOX3D_to_LWGEOM);
+Datum BOX3D_to_LWGEOM(PG_FUNCTION_ARGS)
+{
+ BOX3D *box = (BOX3D *)PG_GETARG_POINTER(0);
+ POINT2D *pts = palloc(sizeof(POINT2D)*5);
+ POINTARRAY *pa[1];
+ LWPOLY *poly;
+ int wantbbox = 0;
+ PG_LWGEOM *result;
+ char *ser;
+
+ // Assign coordinates to POINT2D array
+ pts[0].x = box->xmin; pts[0].y = box->ymin;
+ pts[1].x = box->xmin; pts[1].y = box->ymax;
+ pts[2].x = box->xmax; pts[2].y = box->ymax;
+ pts[3].x = box->xmax; pts[3].y = box->ymin;
+ pts[4].x = box->xmin; pts[4].y = box->ymin;
+
+ // Construct point array
+ pa[0] = palloc(sizeof(POINTARRAY));
+ pa[0]->serialized_pointlist = (char *)pts;
+ TYPE_SETZM(pa[0]->dims, 0, 0);
+ pa[0]->npoints = 5;
+
+ // Construct polygon
+ poly = lwpoly_construct(-1, NULL, 1, pa);
+
+ // Serialize polygon
+ ser = lwpoly_serialize(poly);
+
+ // Construct PG_LWGEOM
+ result = PG_LWGEOM_construct(ser, -1, wantbbox);
+
+ PG_RETURN_POINTER(result);
+}
+
+/* Expand given box of 'd' units in all directions */
+void
+expand_box3d(BOX3D *box, double d)
+{
+ box->xmin -= d;
+ box->ymin -= d;
+ box->zmin -= d;
+
+ box->xmax += d;
+ box->ymax += d;
+ box->zmax += d;
+}
+
+PG_FUNCTION_INFO_V1(BOX3D_expand);
+Datum BOX3D_expand(PG_FUNCTION_ARGS)
+{
+ BOX3D *box = (BOX3D *)PG_GETARG_POINTER(0);
+ double d = PG_GETARG_FLOAT8(1);
+ BOX3D *result = (BOX3D *)palloc(sizeof(BOX3D));
+
+ memcpy(result, box, sizeof(BOX3D));
+ expand_box3d(result, d);
+
+ PG_RETURN_POINTER(result);
+}
+
+/*
+ * convert a PG_LWGEOM to BOX3D
+ *
+ * NOTE: the bounding box is *always* recomputed as the cache
+ * is a box2d, not a box3d...
+ *
+ */
+PG_FUNCTION_INFO_V1(LWGEOM_to_BOX3D);
+Datum LWGEOM_to_BOX3D(PG_FUNCTION_ARGS)
+{
+ PG_LWGEOM *lwgeom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+ BOX3D *result;
+
+ result = compute_serialized_box3d(SERIALIZED_FORM(lwgeom));
+ if ( ! result ) PG_RETURN_NULL();
+
+ PG_RETURN_POINTER(result);
+}
+
+PG_FUNCTION_INFO_V1(BOX3D_xmin);
+Datum BOX3D_xmin(PG_FUNCTION_ARGS)
+{
+ BOX3D *box = (BOX3D *)PG_GETARG_POINTER(0);
+ PG_RETURN_FLOAT8(box->xmin);
+}
+
+PG_FUNCTION_INFO_V1(BOX3D_ymin);
+Datum BOX3D_ymin(PG_FUNCTION_ARGS)
+{
+ BOX3D *box = (BOX3D *)PG_GETARG_POINTER(0);
+ PG_RETURN_FLOAT8(box->ymin);
+}
+
+PG_FUNCTION_INFO_V1(BOX3D_zmin);
+Datum BOX3D_zmin(PG_FUNCTION_ARGS)
+{
+ BOX3D *box = (BOX3D *)PG_GETARG_POINTER(0);
+ PG_RETURN_FLOAT8(box->zmin);
+}
+
+PG_FUNCTION_INFO_V1(BOX3D_xmax);
+Datum BOX3D_xmax(PG_FUNCTION_ARGS)
+{
+ BOX3D *box = (BOX3D *)PG_GETARG_POINTER(0);
+ PG_RETURN_FLOAT8(box->xmax);
+}
+
+PG_FUNCTION_INFO_V1(BOX3D_ymax);
+Datum BOX3D_ymax(PG_FUNCTION_ARGS)
+{
+ BOX3D *box = (BOX3D *)PG_GETARG_POINTER(0);
+ PG_RETURN_FLOAT8(box->ymax);
+}
+
+PG_FUNCTION_INFO_V1(BOX3D_zmax);
+Datum BOX3D_zmax(PG_FUNCTION_ARGS)
+{
+ BOX3D *box = (BOX3D *)PG_GETARG_POINTER(0);
+ PG_RETURN_FLOAT8(box->zmax);
+}
+
+
+PG_FUNCTION_INFO_V1(BOX3D_combine);
+Datum BOX3D_combine(PG_FUNCTION_ARGS)
+{
+ Pointer box3d_ptr = PG_GETARG_POINTER(0);
+ Pointer geom_ptr = PG_GETARG_POINTER(1);
+ BOX3D *a,*b;
+ PG_LWGEOM *lwgeom;
+ BOX3D *box, *result;
+
+ if ( (box3d_ptr == NULL) && (geom_ptr == NULL) )
+ {
+ PG_RETURN_NULL();
+ }
+
+ result = (BOX3D *)palloc(sizeof(BOX3D));
+
+ if (box3d_ptr == NULL)
+ {
+ lwgeom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
+ box = compute_serialized_box3d(SERIALIZED_FORM(lwgeom));
+ if ( ! box ) {
+ PG_FREE_IF_COPY(lwgeom, 1);
+ PG_RETURN_NULL(); // must be the empty geom
+ }
+ memcpy(result, box, sizeof(BOX3D));
+ PG_RETURN_POINTER(result);
+ }
+
+ // combine_bbox(BOX3D, null) => BOX3D
+ if (geom_ptr == NULL)
+ {
+ memcpy(result, (char *)PG_GETARG_DATUM(0), sizeof(BOX3D));
+ PG_RETURN_POINTER(result);
+ }
+
+ lwgeom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
+ box = compute_serialized_box3d(SERIALIZED_FORM(lwgeom));
+ if ( ! box ) // must be the empty geom
+ {
+ PG_FREE_IF_COPY(lwgeom, 1);
+ memcpy(result, (char *)PG_GETARG_DATUM(0), sizeof(BOX3D));
+ PG_RETURN_POINTER(result);
+ }
+
+ a = (BOX3D *)PG_GETARG_DATUM(0);
+ b = box;
+
+ result->xmax = LWGEOM_Maxd(a->xmax, b->xmax);
+ result->ymax = LWGEOM_Maxd(a->ymax, b->ymax);
+ result->zmax = LWGEOM_Maxd(a->zmax, b->zmax);
+ result->xmin = LWGEOM_Mind(a->xmin, b->xmin);
+ result->ymin = LWGEOM_Mind(a->ymin, b->ymin);
+ result->zmin = LWGEOM_Mind(a->zmin, b->zmin);
+
+ PG_RETURN_POINTER(result);
+}
+
+PG_FUNCTION_INFO_V1(BOX3D_construct);
+Datum BOX3D_construct(PG_FUNCTION_ARGS)
+{
+ PG_LWGEOM *min = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+ PG_LWGEOM *max = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
+ BOX3D *result = palloc(sizeof(BOX3D));
+ LWGEOM *minpoint, *maxpoint;
+ POINT3DZ minp, maxp;
+
+ minpoint = lwgeom_deserialize(SERIALIZED_FORM(min));
+ maxpoint = lwgeom_deserialize(SERIALIZED_FORM(max));
+
+ if ( TYPE_GETTYPE(minpoint->type) != POINTTYPE ||
+ TYPE_GETTYPE(maxpoint->type) != POINTTYPE )
+ {
+ elog(ERROR, "BOX2DFLOAT4_construct: args must be points");
+ PG_RETURN_NULL();
+ }
+
+ getPoint3dz_p(((LWPOINT *)minpoint)->point, 0, &minp);
+ getPoint3dz_p(((LWPOINT *)maxpoint)->point, 0, &maxp);
+
+ result->xmax = maxp.x;
+ result->ymax = maxp.y;
+ result->zmax = maxp.z;
+
+ result->xmin = minp.x;
+ result->ymin = minp.y;
+ result->zmin = minp.z;
+
+ PG_RETURN_POINTER(result);
+}
+
+//min(a,b)
+double
+LWGEOM_Mind(double a, double b)
+{
+ if (a<b)
+ return a;
+ return b;
+}
+
+//max(a,b)
+double
+LWGEOM_Maxd(double a, double b)
+{
+ if (b>a)
+ return b;
+ return a;
+}
+
Index: regress/regress.sql
===================================================================
RCS file: /home/cvs/postgis/postgis/regress/regress.sql,v
retrieving revision 1.9
retrieving revision 1.10
diff -U2 -r1.9 -r1.10
--- regress/regress.sql 11 Mar 2005 17:47:33 -0000 1.9
+++ regress/regress.sql 23 Mar 2005 16:29:17 -0000 1.10
@@ -229,2 +229,6 @@
select '136', distance('POINT(0 0)', translate('POINT(0 0)', 5, 12, 0));
+
+select '137', box3d('GEOMETRYCOLLECTION(GEOMETRYCOLLECTION EMPTY)'::geometry);
+select '138', box3d('GEOMETRYCOLLECTION(GEOMETRYCOLLECTION EMPTY, POINT(0 0))'::geometry);
+
Index: regress/regress_expected
===================================================================
RCS file: /home/cvs/postgis/postgis/regress/regress_expected,v
retrieving revision 1.9
retrieving revision 1.10
diff -U2 -r1.9 -r1.10
--- regress/regress_expected 11 Mar 2005 17:47:33 -0000 1.9
+++ regress/regress_expected 23 Mar 2005 16:29:17 -0000 1.10
@@ -137,2 +137,4 @@
135|13
136|13
+137|
+138|BOX3D(0 0 0,0 0 0)
More information about the postgis-devel
mailing list