]> granicus.if.org Git - postgis/commitdiff
Fixed a bug in serializedform length computation (for collection).
authorSandro Santilli <strk@keybit.net>
Mon, 23 Aug 2004 10:49:08 +0000 (10:49 +0000)
committerSandro Santilli <strk@keybit.net>
Mon, 23 Aug 2004 10:49:08 +0000 (10:49 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@717 b70326c6-7e19-0410-871a-916f4a2858ee

lwgeom/lwgeom_api.c
lwgeom/lwgeom_functions_basic.c

index 0f04f568078fc1b750bc99803b1f20dd54fcd967..12bb93930b1259a9017b93e4712e01d047886351 100644 (file)
@@ -873,13 +873,13 @@ BOX3D *lwline_findbbox(LWLINE *line)
 //find length of this serialized line
 uint32 lwline_findlength(char *serialized_line)
 {
-               int type = (unsigned char) serialized_line[0];
-               uint32 result =1;  //type
-               char *loc;
-               uint32 npoints;
+       int type = (unsigned char) serialized_line[0];
+       uint32 result =1;  //type
+       char *loc;
+       uint32 npoints;
 
-               if ( lwgeom_getType(type) != LINETYPE)
-                       elog(ERROR,"lwline_findlength::attempt to find the length of a non-line");
+       if ( lwgeom_getType(type) != LINETYPE)
+               elog(ERROR,"lwline_findlength::attempt to find the length of a non-line");
 
 
        loc = serialized_line+1;
@@ -1323,69 +1323,75 @@ BOX3D *lwpoly_findbbox(LWPOLY *poly)
 //find length of this serialized polygon
 uint32 lwpoly_findlength(char *serialized_poly)
 {
-               uint32 result = 1; // char type
-               uint32 nrings;
-               int   ndims;
-               int t;
-               unsigned char type;
-               uint32 npoints;
-               char *loc;
+       uint32 result = 1; // char type
+       uint32 nrings;
+       int   ndims;
+       int t;
+       unsigned char type;
+       uint32 npoints;
+       char *loc;
 
-               if (serialized_poly == NULL)
-                       return -9999;
+       if (serialized_poly == NULL)
+               return -9999;
 
 
-               type = (unsigned char) serialized_poly[0];
-               ndims = lwgeom_ndims(type);
+       type = (unsigned char) serialized_poly[0];
+       ndims = lwgeom_ndims(type);
 
-               if ( lwgeom_getType(type) != POLYGONTYPE)
-                       return -9999;
+       if ( lwgeom_getType(type) != POLYGONTYPE)
+               return -9999;
 
 
        loc = serialized_poly+1;
 
        if (lwgeom_hasBBOX(type))
        {
+#ifdef DEBUG
+               elog(NOTICE, "lwpoly_findlength: has bbox");
+#endif
                loc += sizeof(BOX2DFLOAT4);
                result +=sizeof(BOX2DFLOAT4);
        }
 
 
-               if ( lwgeom_hasSRID(type))
-               {
-                       loc +=4; // type + SRID
-                       result += 4;
-               }
+       if ( lwgeom_hasSRID(type))
+       {
+#ifdef DEBUG
+               elog(NOTICE, "lwpoly_findlength: has srid");
+#endif
+               loc +=4; // type + SRID
+               result += 4;
+       }
 
 
-               nrings = get_uint32(loc);
+       nrings = get_uint32(loc);
+       loc +=4;
+       result +=4;
+
+
+       for (t =0;t<nrings;t++)
+       {
+               //read in a single ring and make a PA
+               npoints = get_uint32(loc);
                loc +=4;
                result +=4;
 
-
-               for (t =0;t<nrings;t++)
+               if (ndims == 3)
                {
-                       //read in a single ring and make a PA
-                       npoints = get_uint32(loc);
-                       loc +=4;
-                       result +=4;
-
-                       if (ndims == 3)
-                       {
-                               loc += 24*npoints;
-                               result += 24*npoints;
-                       }
-                       else if (ndims == 2)
-                       {
-                               loc += 16*npoints;
-                               result += 16*npoints;
-                       }
-                       else if (ndims == 4)
-                       {
-                               loc += 32*npoints;
-                               result += 32*npoints;
-                       }
+                       loc += 24*npoints;
+                       result += 24*npoints;
+               }
+               else if (ndims == 2)
+               {
+                       loc += 16*npoints;
+                       result += 16*npoints;
                }
+               else if (ndims == 4)
+               {
+                       loc += 32*npoints;
+                       result += 32*npoints;
+               }
+       }
        return result;
 }
 
@@ -1436,25 +1442,38 @@ LWGEOM_INSPECTED *lwgeom_inspect(char *serialized_form)
                sub_geoms = (char**) palloc(sizeof(char*));
                sub_geoms[0] = serialized_form;
                result->sub_geoms = sub_geoms;
+               return result;
        }
-       else
+
+       // its a GeometryCollection or multi* geometry
+
+       if (lwgeom_hasSRID((unsigned char) serialized_form[0]) )
        {
-               if (lwgeom_hasSRID((unsigned char) serialized_form[0]) )
-               {
-                       result->SRID=  get_int32(loc);
-                       loc += 4;
-               }
-               //its a GeometryCollection or multi* geometry
-               result->ngeometries = get_uint32(loc);
-               loc +=4;
-               sub_geoms = (char**) palloc(sizeof(char*) * result->ngeometries );
-               result->sub_geoms = sub_geoms;
-               sub_geoms[0] = loc;
-               for (t=1;t<result->ngeometries; t++)
-               {
-                       int sub_length = lwgeom_seralizedformlength(sub_geoms[t-1], -1);//-1 = entire object
-                       sub_geoms[t] = sub_geoms[t-1] + sub_length;
-               }
+               result->SRID=  get_int32(loc);
+               loc += 4;
+       }
+
+       result->ngeometries = get_uint32(loc);
+       loc +=4;
+#ifdef DEBUG
+       elog(NOTICE, "lwgeom_inspect: geometry is a collection of %d elements",
+               result->ngeometries);
+#endif
+
+       sub_geoms = (char**) palloc(sizeof(char*) * result->ngeometries );
+       result->sub_geoms = sub_geoms;
+       sub_geoms[0] = loc;
+#ifdef DEBUG
+       elog(NOTICE, "subgeom[0] @ %i", sub_geoms[0]);
+#endif
+       for (t=1;t<result->ngeometries; t++)
+       {
+               int sub_length = lwgeom_seralizedformlength(sub_geoms[t-1], -1);//-1 = entire object
+               sub_geoms[t] = sub_geoms[t-1] + sub_length;
+#ifdef DEBUG
+               elog(NOTICE, "subgeom[%d] @ %i (sub_length: %d)",
+                       t, sub_geoms[t], sub_length);
+#endif
        }
 
        return result;
@@ -1858,27 +1877,57 @@ int lwgeom_seralizedformlength_simple(char *serialized_form)
        int result = 1; //"type"
 
        if (type == POINTTYPE)
+       {
+#ifdef DEBUG
+               elog(NOTICE, "lwgeom_seralizedformlength_simple: is a point");
+#endif
                return lwpoint_findlength(serialized_form);
+       }
        else if (type == LINETYPE)
+       {
+#ifdef DEBUG
+               elog(NOTICE, "lwgeom_seralizedformlength_simple: is a line");
+#endif
                return lwline_findlength(serialized_form);
+       }
        else if (type == POLYGONTYPE)
+       {
+#ifdef DEBUG
+               elog(NOTICE, "lwgeom_seralizedformlength_simple: is a polygon");
+#endif
                return lwpoly_findlength(serialized_form);
+       }
 
-       //handle all the multi* and geometrycollections the same
-           //NOTE: for a geometry collection of GC of GC of GC we will be recursing...
+       if ( type == 0 )
+       {
+               elog(ERROR, "lwgeom_seralizedformlength_simple called with unknown-typed serialized geometry");
+               return 0;
+       }
 
+       //handle all the multi* and geometrycollections the same
+       //NOTE: for a geometry collection of GC of GC of GC we will be recursing...
 
+#ifdef DEBUG
+       elog(NOTICE, "lwgeom_seralizedformlength_simple called on a geoemtry with type %d", type);
+#endif
 
        loc = serialized_form+1;
 
        if (lwgeom_hasBBOX((unsigned char) serialized_form[0]))
        {
+#ifdef DEBUG
+               elog(NOTICE, "lwgeom_seralizedformlength_simple: has bbox");
+#endif
+
                loc += sizeof(BOX2DFLOAT4);
                result +=sizeof(BOX2DFLOAT4);
        }
 
        if (lwgeom_hasSRID( (unsigned char) serialized_form[0]) )
        {
+#ifdef DEBUG
+               elog(NOTICE, "lwgeom_seralizedformlength_simple: has srid");
+#endif
                result +=4;
                loc +=4;
        }
@@ -1886,14 +1935,25 @@ int lwgeom_seralizedformlength_simple(char *serialized_form)
 
        ngeoms =  get_uint32(loc);
        loc +=4;
+       result += 4; // numgeoms
+
+#ifdef DEBUG
+       elog(NOTICE, "lwgeom_seralizedformlength_simple called on a geoemtry with %d elems (result so far: %d)", ngeoms, result);
+#endif
 
        for (t=0;t<ngeoms;t++)
        {
                sub_size = lwgeom_seralizedformlength_simple(loc);
+#ifdef DEBUG
+               elog(NOTICE, " subsize %d", sub_size);
+#endif
                loc += sub_size;
                result += sub_size;
        }
 
+#ifdef DEBUG
+       elog(NOTICE, "lwgeom_seralizedformlength_simple returning %d", result);
+#endif
        return result;
 }
 
index 76e1febf6dde7e99ac622d080d9c5c077517c5c7..c1b7e4815e4134dd1bffdde81fdfd015a60a14aa 100644 (file)
@@ -145,8 +145,16 @@ Datum combine_box2d(PG_FUNCTION_ARGS)
 PG_FUNCTION_INFO_V1(lwgeom_mem_size);
 Datum lwgeom_mem_size(PG_FUNCTION_ARGS)
 {
-       char *geom = (char *)  PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       int32 size = *((int32 *)geom);
+       LWGEOM *geom = (LWGEOM *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+       int32 size = geom->size;
+       int32 computed_size = lwgeom_seralizedformlength_simple(SERIALIZED_FORM(geom));
+       computed_size += 4; // varlena size
+       if ( size != computed_size )
+       {
+               elog(NOTICE, "varlena size (%d) != computed size+4 (%d)",
+                               size, computed_size);
+       }
+
        PG_FREE_IF_COPY(geom,0);
        PG_RETURN_INT32(size);
 }
@@ -156,8 +164,9 @@ Datum lwgeom_mem_size(PG_FUNCTION_ARGS)
  * LWGEOM object
  */
 char *
-lwgeom_summary_recursive(char *serialized)
+lwgeom_summary_recursive(char *serialized, int offset)
 {
+       static int idx = 0;
        LWGEOM_INSPECTED *inspected;
        char *result;
        char *ptr;
@@ -169,21 +178,34 @@ lwgeom_summary_recursive(char *serialized)
        result = palloc(1);
        result[0] = '\0';
 
+       if ( offset == 0 ) idx = 0;
+
        inspected = lwgeom_inspect(serialized);
+
+       if (0) {
+               size += 57;
+               result = repalloc(result,size);
+               sprintf(tmp,
+                       "Geometry (inspected) contains %i subgeoms\n",
+                       inspected->ngeometries);
+               strcat(result,tmp);
+       }
+
        //now have to do a scan of each object
        for (j=0; j<inspected->ngeometries; j++)
        {
                LWLINE *line=NULL;
                LWPOINT *point=NULL;
                LWPOLY *poly=NULL;
-               char *subgeom;
+               char *subgeom=NULL;
 
                point = lwgeom_getpoint_inspected(inspected,j);
                if (point !=NULL)
                {
                        size += 30;
                        result = repalloc(result,size);
-                       sprintf(tmp,"Object %i is a POINT()\n",j);
+                       sprintf(tmp,"Object %i is a POINT()\n",
+                               idx++);
                        strcat(result,tmp);
                        continue;
                }
@@ -193,7 +215,8 @@ lwgeom_summary_recursive(char *serialized)
                {
                        size += 57*(poly->nrings+1);
                        result = repalloc(result,size);
-                       sprintf(tmp,"Object %i is a POLYGON() with %i rings\n",j,poly->nrings);
+                       sprintf(tmp,"Object %i is a POLYGON() with %i rings\n",
+                                       idx++, poly->nrings);
                        strcat(result,tmp);
                        for (i=0; i<poly->nrings;i++)
                        {
@@ -211,7 +234,7 @@ lwgeom_summary_recursive(char *serialized)
                        result = repalloc(result,size);
                        sprintf(tmp,
                                "Object %i is a LINESTRING() with %i points\n",
-                               j, line->points->npoints);
+                               idx++, line->points->npoints);
                        strcat(result,tmp);
                        continue;
                }
@@ -219,7 +242,7 @@ lwgeom_summary_recursive(char *serialized)
                subgeom = lwgeom_getsubgeometry_inspected(inspected, j);
                if ( subgeom != NULL )
                {
-                       ptr = lwgeom_summary_recursive(subgeom);
+                       ptr = lwgeom_summary_recursive(subgeom, 1);
                        size += strlen(ptr);
                        result = repalloc(result,size);
                        strcat(result, ptr);
@@ -231,6 +254,7 @@ lwgeom_summary_recursive(char *serialized)
                }
        }
 
+       pfree_inspected(inspected);
        return result;
 }
 
@@ -242,7 +266,7 @@ Datum lwgeom_summary(PG_FUNCTION_ARGS)
        char *result;
        text *mytext;
 
-       result = lwgeom_summary_recursive(SERIALIZED_FORM(geom));
+       result = lwgeom_summary_recursive(SERIALIZED_FORM(geom), 0);
 
        // create a text obj to return
        mytext = (text *) palloc(VARHDRSZ  + strlen(result) );