]> granicus.if.org Git - postgis/commitdiff
segmentize2d() port and use of new LWGEOM structure.
authorSandro Santilli <strk@keybit.net>
Sun, 10 Oct 2004 20:31:23 +0000 (20:31 +0000)
committerSandro Santilli <strk@keybit.net>
Sun, 10 Oct 2004 20:31:23 +0000 (20:31 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@972 b70326c6-7e19-0410-871a-916f4a2858ee

lwgeom/TODO
lwgeom/liblwgeom.h
lwgeom/lwcollection.c
lwgeom/lwgeom.c
lwgeom/lwgeom.h
lwgeom/lwgeom_functions_basic.c
lwgeom/lwline.c
lwgeom/lwpoly.c
lwgeom/ptarray.c

index 08a1236ac836fa00345b0dc2b686447f31cdc71b..ced577fcc4136c3f6b88066097476ff87b4b4886 100644 (file)
@@ -1,4 +1,4 @@
-- port LINESTRING extension to LWGEOM
+- geometry_same implementation
 
 - WKB support in loader (canonical form is OK)
 
index 4817123a326f12f03fac360cba23fa358ed150aa..ec01664e37de217d337573adac52a69554512fb2 100644 (file)
@@ -917,7 +917,7 @@ extern double lwgeom_mindistance2d_recursive(char *lw1, char *lw2);
 extern void lwgeom_translate_recursive(char *serialized, double xoff, double yoff, double zoff);
 extern void lwgeom_translate_ptarray(POINTARRAY *pa, double xoff, double yoff, double zoff);
 extern int lwgeom_pt_inside_circle(POINT2D *p, double cx, double cy, double rad);
-extern POINTARRAY *segmentize2d_ptarray(POINTARRAY *ipa, double dist);
+extern POINTARRAY *ptarray_segmentize2d(POINTARRAY *ipa, double dist);
 extern int32 lwgeom_npoints(char *serialized);
 extern char ptarray_isccw(const POINTARRAY *pa);
 extern void lwgeom_reverse(LWGEOM *lwgeom);
@@ -990,6 +990,10 @@ extern int32 lwgeom_nrings_recursive(char *serialized);
 extern void dump_lwexploded(LWGEOM_EXPLODED *exploded);
 extern void ptarray_reverse(POINTARRAY *pa);
 
+extern LWGEOM *lwgeom_segmentize2d(LWGEOM *line, double dist);
+extern LWLINE *lwline_segmentize2d(LWLINE *line, double dist);
+extern LWPOLY *lwpoly_segmentize2d(LWPOLY *line, double dist);
+extern LWCOLLECTION *lwcollection_segmentize2d(LWCOLLECTION *coll, double dist);
 extern unsigned char   parse_hex(char *str);
 extern void deparse_hex(unsigned char str, unsigned char *result);
 extern char *parse_lwgeom_wkt(char *wkt_input);
index 4ccec4814a545dcb3657001d54bc161d73bbb691..79c9e853afded1f4113bc6d4b4422f1add863ba0 100644 (file)
@@ -258,3 +258,19 @@ lwcollection_add(const LWCOLLECTION *to, uint32 where, const LWGEOM *what)
        return (LWGEOM *)col;
 
 }
+
+LWCOLLECTION *
+lwcollection_segmentize2d(LWCOLLECTION *col, double dist)
+{
+       unsigned int i;
+       LWGEOM **newgeoms;
+
+       if ( ! col->ngeoms ) return col;
+
+       newgeoms = lwalloc(sizeof(LWGEOM *)*col->ngeoms);
+       for (i=0; i<col->ngeoms; i++)
+               newgeoms[i] = lwgeom_segmentize2d(col->geoms[i], dist);
+
+       return lwcollection_construct(col->type, col->SRID, col->bbox,
+               col->ngeoms, newgeoms);
+}
index 805bf61c086b2c4fac4c1ac6aa24200a6c3c87de..d7b76506af7cd9342b89b6ea719c5f68970b456f 100644 (file)
@@ -401,3 +401,24 @@ lwgeom_dropSRID(LWGEOM *lwgeom)
        TYPE_SETHASSRID(lwgeom->type, 0);
        lwgeom->SRID = -1;
 }
+
+LWGEOM *
+lwgeom_segmentize2d(LWGEOM *lwgeom, double dist)
+{
+       switch(TYPE_GETTYPE(lwgeom->type))
+       {
+               case LINETYPE:
+                       return (LWGEOM *)lwline_segmentize2d((LWLINE *)lwgeom,
+                               dist);
+               case POLYGONTYPE:
+                       return (LWGEOM *)lwpoly_segmentize2d((LWPOLY *)lwgeom,
+                               dist);
+               case MULTILINETYPE:
+               case MULTIPOLYGONTYPE:
+               case COLLECTIONTYPE:
+                       return (LWGEOM *)lwcollection_segmentize2d(
+                               (LWCOLLECTION *)lwgeom, dist);
+               default:
+                       return lwgeom;
+       }
+}
index 084003a9b2808dc82557e60828b46f5e09679611..cc2b62b034f5ace0cfec0591348220198127c189 100644 (file)
@@ -39,3 +39,4 @@ extern LWGEOM lwline_construct(int SRID, char wantbbox, POINTARRAY pa);
 // Spatial functions
 extern void lwgeom_reverse(LWGEOM lwgeom);
 extern void lwgeom_forceRHR(LWGEOM lwgeom);
+extern LWGEOM lwgeom_segmentize2d(LWGEOM lwgeom, double dist);
index 509c5031ac48346607c21c74109510e642e2458a..7338167337c9a341751f7ca174da0efe8ae10114 100644 (file)
@@ -2783,72 +2783,6 @@ Datum centroid(PG_FUNCTION_ARGS)
 }
 #endif // ! USE_GEOS
 
-// Returns a modified POINTARRAY so that no segment is 
-// longer then the given distance (computed using 2d).
-// Every input point is kept.
-// Z and M values for added points (if needed) are set to 0.
-POINTARRAY *
-segmentize2d_ptarray(POINTARRAY *ipa, double dist)
-{
-       double  segdist;
-       POINT4D *p1, *p2, *ip, *op;
-       POINT4D pbuf;
-       POINTARRAY *opa;
-       int maxpoints = ipa->npoints;
-       int ptsize = pointArray_ptsize(ipa);
-       int ipoff=0; // input point offset
-
-       pbuf.x = pbuf.y = pbuf.z = pbuf.m = 0;
-
-       // Initial storage
-       opa = (POINTARRAY *)lwalloc(ptsize * maxpoints);
-       opa->dims = ipa->dims;
-       opa->npoints = 0;
-       opa->serialized_pointlist = (char *)lwalloc(maxpoints*ptsize);
-
-       // Add first point
-       opa->npoints++;
-       p1 = (POINT4D *)getPoint(ipa, ipoff);
-       op = (POINT4D *)getPoint(opa, opa->npoints-1);
-       memcpy(op, p1, ptsize); 
-       ipoff++;
-
-       while (ipoff<ipa->npoints)
-       {
-               p2 = (POINT4D *)getPoint(ipa, ipoff);
-
-               segdist = distance2d_pt_pt((POINT2D *)p1, (POINT2D *)p2);
-
-               if (segdist > dist) // add an intermediate point
-               {
-                       pbuf.x = p1->x + (p2->x-p1->x)/segdist * dist;
-                       pbuf.y = p1->y + (p2->y-p1->y)/segdist * dist;
-                       // might also compute z and m if available...
-                       ip = &pbuf;
-                       p1 = ip;
-               }
-               else // copy second point
-               {
-                       ip = p2;
-                       p1 = p2;
-                       ipoff++;
-               }
-
-               // Add point
-               if ( ++(opa->npoints) > maxpoints ) {
-                       maxpoints *= 1.5;
-                       opa->serialized_pointlist = (char *)lwrealloc(
-                               opa->serialized_pointlist,
-                               maxpoints*ptsize
-                       );
-               }
-               op = (POINT4D *)getPoint(opa, opa->npoints-1);
-               memcpy(op, ip, ptsize); 
-       }
-
-       return opa;
-}
-
 // Returns a modified [multi]polygon so that no ring segment is 
 // longer then the given distance (computed using 2d).
 // Every input point is kept.
@@ -2856,43 +2790,33 @@ segmentize2d_ptarray(POINTARRAY *ipa, double dist)
 PG_FUNCTION_INFO_V1(LWGEOM_segmentize2d);
 Datum LWGEOM_segmentize2d(PG_FUNCTION_ARGS)
 {
-       PG_LWGEOM *geom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
-       double dist = PG_GETARG_FLOAT8(1);
-       PG_LWGEOM *result = NULL;
-       int type = lwgeom_getType(geom->type);
-       LWGEOM_EXPLODED *exp;
-       int i, j;
-       char *srl;
+       PG_LWGEOM *outgeom, *ingeom;
+       double dist;
+       LWGEOM *inlwgeom, *outlwgeom;
+       size_t size, retsize;
 
-       if ( (type != POLYGONTYPE) && (type != MULTIPOLYGONTYPE) )
-       {
-               elog(ERROR,"segmentize: 1st arg isnt a [multi-]polygon\n");
-               PG_RETURN_NULL();
-       }
+       ingeom = (PG_LWGEOM *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
+       dist = PG_GETARG_FLOAT8(1);
 
-       exp = lwgeom_explode(SERIALIZED_FORM(geom));
+       // Avoid deserialize/serialize steps
+       if ( (TYPE_GETTYPE(ingeom->type) == POINTTYPE) ||
+               (TYPE_GETTYPE(ingeom->type) == MULTIPOINTTYPE) )
+               PG_RETURN_POINTER(ingeom);
 
-       for (i=0; i<exp->npolys; i++)
-       {
-               LWPOLY *poly = lwpoly_deserialize(exp->polys[i]);
-               for (j=0; j<poly->nrings; j++) 
-               {
-                       POINTARRAY *ring = poly->rings[j];
-                       poly->rings[j] = segmentize2d_ptarray(ring, dist);
-               } 
-               pfree_polygon(poly);
-               exp->polys[i] = lwpoly_serialize(poly);
-       } 
+       inlwgeom = lwgeom_deserialize(SERIALIZED_FORM(ingeom));
+       outlwgeom = lwgeom_segmentize2d(inlwgeom, dist);
 
-       // Serialize exploded structure
-       srl = lwexploded_serialize(exp, lwgeom_hasBBOX(geom->type));
-       pfree_exploded(exp);
+       size = lwgeom_serialize_size(outlwgeom);
+       outgeom = palloc(size+4);
+       outgeom->size = size+4;
+       lwgeom_serialize_buf(outlwgeom, SERIALIZED_FORM(outgeom), &retsize);
 
-       // Construct return value
-       result = PG_LWGEOM_construct(srl, lwgeom_getSRID(geom),
-               lwgeom_hasBBOX(geom->type));
+       if ( size != retsize )
+       {
+               lwerror ("lwgeom_serialize_buf returned size(%d) != lwgeom_serialize_size (%d)", retsize, size);
+       }
 
-       PG_RETURN_POINTER(result);
+       PG_RETURN_POINTER(outgeom);
 }
 
 // Reverse vertex order of geometry
index d58f77cd06a1509804e7116b121b785de7a50ba3..1572992d8adab86720f64fa25a61b886ea6ad4e2 100644 (file)
@@ -358,3 +358,10 @@ lwline_reverse(LWLINE *line)
 {
        ptarray_reverse(line->points);
 }
+
+LWLINE *
+lwline_segmentize2d(LWLINE *line, double dist)
+{
+       return lwline_construct(line->SRID, line->bbox,
+               ptarray_segmentize2d(line->points, dist));
+}
index f88ca60ef5669439d8664a72064e527aa396a5f1..52807745bdcfa364a418661cea9db02a2a534967 100644 (file)
@@ -509,3 +509,18 @@ lwpoly_reverse(LWPOLY *poly)
        for (i=0; i<poly->nrings; i++)
                ptarray_reverse(poly->rings[i]);
 }
+
+LWPOLY *
+lwpoly_segmentize2d(LWPOLY *poly, double dist)
+{
+       POINTARRAY **newrings;
+       unsigned int i;
+       
+       newrings = lwalloc(sizeof(POINTARRAY *)*poly->nrings);
+       for (i=0; i<poly->nrings; i++)
+       {
+               newrings[i] = ptarray_segmentize2d(poly->rings[i], dist);
+       }
+       return lwpoly_construct(poly->SRID, poly->bbox,
+               poly->nrings, newrings);
+}
index 90100cfaa4bddabcfa46fe95cd94bcf54b1452e6..dc7e1e9e343f354c0528498b9d2aec67fb837488 100644 (file)
@@ -121,3 +121,70 @@ ptarray_compute_bbox(const POINTARRAY *pa)
 
        return result;
 }
+
+// Returns a modified POINTARRAY so that no segment is 
+// longer then the given distance (computed using 2d).
+// Every input point is kept.
+// Z and M values for added points (if needed) are set to 0.
+POINTARRAY *
+ptarray_segmentize2d(POINTARRAY *ipa, double dist)
+{
+       double  segdist;
+       POINT4D *p1, *p2, *ip, *op;
+       POINT4D pbuf;
+       POINTARRAY *opa;
+       int maxpoints = ipa->npoints;
+       int ptsize = pointArray_ptsize(ipa);
+       int ipoff=0; // input point offset
+
+       pbuf.x = pbuf.y = pbuf.z = pbuf.m = 0;
+
+       // Initial storage
+       opa = (POINTARRAY *)lwalloc(ptsize * maxpoints);
+       opa->dims = ipa->dims;
+       opa->npoints = 0;
+       opa->serialized_pointlist = (char *)lwalloc(maxpoints*ptsize);
+
+       // Add first point
+       opa->npoints++;
+       p1 = (POINT4D *)getPoint(ipa, ipoff);
+       op = (POINT4D *)getPoint(opa, opa->npoints-1);
+       memcpy(op, p1, ptsize); 
+       ipoff++;
+
+       while (ipoff<ipa->npoints)
+       {
+               p2 = (POINT4D *)getPoint(ipa, ipoff);
+
+               segdist = distance2d_pt_pt((POINT2D *)p1, (POINT2D *)p2);
+
+               if (segdist > dist) // add an intermediate point
+               {
+                       pbuf.x = p1->x + (p2->x-p1->x)/segdist * dist;
+                       pbuf.y = p1->y + (p2->y-p1->y)/segdist * dist;
+                       // might also compute z and m if available...
+                       ip = &pbuf;
+                       p1 = ip;
+               }
+               else // copy second point
+               {
+                       ip = p2;
+                       p1 = p2;
+                       ipoff++;
+               }
+
+               // Add point
+               if ( ++(opa->npoints) > maxpoints ) {
+                       maxpoints *= 1.5;
+                       opa->serialized_pointlist = (char *)lwrealloc(
+                               opa->serialized_pointlist,
+                               maxpoints*ptsize
+                       );
+               }
+               op = (POINT4D *)getPoint(opa, opa->npoints-1);
+               memcpy(op, ip, ptsize); 
+       }
+
+       return opa;
+}
+