LWPOLY* lwpoly_simplify(const LWPOLY *ipoly, double dist, int preserve_collapsed) { int i; LWPOLY *opoly = lwpoly_construct_empty(ipoly->srid, FLAGS_GET_Z(ipoly->flags), FLAGS_GET_M(ipoly->flags)); LWDEBUGF(2, "%s: simplifying polygon with %d rings", __func__, ipoly->nrings); if ( lwpoly_is_empty(ipoly) ) { lwpoly_free(opoly); return NULL; } for ( i = 0; i < ipoly->nrings; i++ ) { POINTARRAY *opts; int minvertices = 0; /* We'll still let holes collapse, but if we're preserving */ /* and this is a shell, we ensure it is kept */ if ( preserve_collapsed && i == 0 ) minvertices = 4; opts = ptarray_simplify(ipoly->rings[i], dist, minvertices); LWDEBUGF(3, "ring%d simplified from %d to %d points", i, ipoly->rings[i]->npoints, opts->npoints); /* Less points than are needed to form a closed ring, we can't use this */ if ( opts->npoints < 4 ) { LWDEBUGF(3, "ring%d skipped (% pts)", i, opts->npoints); ptarray_free(opts); if ( i ) continue; else break; /* Don't scan holes if shell is collapsed */ } /* Add ring to simplified polygon */ if( lwpoly_add_ring(opoly, opts) == LW_FAILURE ) { lwpoly_free(opoly); return NULL; } } LWDEBUGF(3, "simplified polygon with %d rings", ipoly->nrings); opoly->type = ipoly->type; if( lwpoly_is_empty(opoly) ) { lwpoly_free(opoly); return NULL; } return opoly; }
static void test_rect_tree_intersects_tree(void) { LWPOLY *poly1, *poly2; RECT_NODE *tree1, *tree2; int result; /* total overlap, A == B */ poly1 = (LWPOLY*)lwgeom_from_wkt("POLYGON((0 0, 3 1, 0 2, 3 3, 0 4, 3 5, 0 6, 5 6, 5 0, 0 0))", LW_PARSER_CHECK_NONE); poly2 = (LWPOLY*)lwgeom_from_wkt("POLYGON((0 0, 3 1, 0 2, 3 3, 0 4, 3 5, 0 6, 5 6, 5 0, 0 0))", LW_PARSER_CHECK_NONE); tree1 = rect_tree_new(poly1->rings[0]); tree2 = rect_tree_new(poly2->rings[0]); result = rect_tree_intersects_tree(tree1, tree2); CU_ASSERT_EQUAL(result, LW_TRUE); lwpoly_free(poly1); lwpoly_free(poly2); rect_tree_free(tree1); rect_tree_free(tree2); /* hiding between the tines of the comb */ poly1 = (LWPOLY*)lwgeom_from_wkt("POLYGON((0 0, 3 1, 0 2, 3 3, 0 4, 3 5, 0 6, 5 6, 5 0, 0 0))", LW_PARSER_CHECK_NONE); poly2 = (LWPOLY*)lwgeom_from_wkt("POLYGON((0.3 0.7, 0.3 0.8, 0.4 0.8, 0.4 0.7, 0.3 0.7))", LW_PARSER_CHECK_NONE); tree1 = rect_tree_new(poly1->rings[0]); tree2 = rect_tree_new(poly2->rings[0]); result = rect_tree_intersects_tree(tree1, tree2); CU_ASSERT_EQUAL(result, LW_FALSE); lwpoly_free(poly1); lwpoly_free(poly2); rect_tree_free(tree1); rect_tree_free(tree2); /* between the tines, but with a corner overlapping */ poly1 = (LWPOLY*)lwgeom_from_wkt("POLYGON((0 0, 3 1, 0 2, 3 3, 0 4, 3 5, 0 6, 5 6, 5 0, 0 0))", LW_PARSER_CHECK_NONE); poly2 = (LWPOLY*)lwgeom_from_wkt("POLYGON((0.3 0.7, 0.3 0.8, 0.4 0.8, 1.3 0.3, 0.3 0.7))", LW_PARSER_CHECK_NONE); tree1 = rect_tree_new(poly1->rings[0]); tree2 = rect_tree_new(poly2->rings[0]); result = rect_tree_intersects_tree(tree1, tree2); CU_ASSERT_EQUAL(result, LW_TRUE); lwpoly_free(poly1); lwpoly_free(poly2); rect_tree_free(tree1); rect_tree_free(tree2); /* Just touching the top left corner of the comb */ poly1 = (LWPOLY*)lwgeom_from_wkt("POLYGON((0 0, 3 1, 0 2, 3 3, 0 4, 3 5, 0 6, 5 6, 5 0, 0 0))", LW_PARSER_CHECK_NONE); poly2 = (LWPOLY*)lwgeom_from_wkt("POLYGON((-1 5, 0 5, 0 7, -1 7, -1 5))", LW_PARSER_CHECK_NONE); tree1 = rect_tree_new(poly1->rings[0]); tree2 = rect_tree_new(poly2->rings[0]); result = rect_tree_intersects_tree(tree1, tree2); CU_ASSERT_EQUAL(result, LW_TRUE); lwpoly_free(poly1); lwpoly_free(poly2); rect_tree_free(tree1); rect_tree_free(tree2); }
static void do_test_lwgeom_effectivearea_polys(void) { LWPOLY *the_geom; int avoid_collaps=4; /*POLYGON 1*/ the_geom = (LWPOLY*)lwgeom_from_wkt("POLYGON((10 10,12 8, 15 7, 18 7, 20 20, 15 21, 18 22, 10 30,1 99, 0 100, 10 10))", LW_PARSER_CHECK_NONE); double the_areas1[]={FLT_MAX,5,1.5,55,100,4,4,FLT_MAX,30,FLT_MAX,FLT_MAX}; do_test_lwgeom_effectivearea(the_geom->rings[0],the_areas1,avoid_collaps); lwpoly_free(the_geom); }
LWPOLY* lwpoly_grid(const LWPOLY *poly, const gridspec *grid) { LWPOLY *opoly; int ri; #if 0 /* * TODO: control this assertion * it is assumed that, since the grid size will be a pixel, * a visible ring should show at least a white pixel inside, * thus, for a square, that would be grid_xsize*grid_ysize */ double minvisiblearea = grid->xsize * grid->ysize; #endif LWDEBUGF(3, "lwpoly_grid: applying grid to polygon with %d rings", poly->nrings); opoly = lwpoly_construct_empty(poly->srid, lwgeom_has_z((LWGEOM*)poly), lwgeom_has_m((LWGEOM*)poly)); for (ri=0; ri<poly->nrings; ri++) { POINTARRAY *ring = poly->rings[ri]; POINTARRAY *newring; newring = ptarray_grid(ring, grid); /* Skip ring if not composed by at least 4 pts (3 segments) */ if ( newring->npoints < 4 ) { ptarray_free(newring); LWDEBUGF(3, "grid_polygon3d: ring%d skipped ( <4 pts )", ri); if ( ri ) continue; else break; /* this is the external ring, no need to work on holes */ } if ( ! lwpoly_add_ring(opoly, newring) ) { lwerror("lwpoly_grid, memory error"); return NULL; } } LWDEBUGF(3, "lwpoly_grid: simplified polygon with %d rings", opoly->nrings); if ( ! opoly->nrings ) { lwpoly_free(opoly); return NULL; } return opoly; }
/** * This should be rewritten to make use of the curve itself. */ double lwcurvepoly_area(const LWCURVEPOLY *curvepoly) { double area = 0.0; LWPOLY *poly; if( lwgeom_is_empty((LWGEOM*)curvepoly) ) return 0.0; poly = lwcurvepoly_segmentize(curvepoly, 32); area = lwpoly_area(poly); lwpoly_free(poly); return area; }
void lwgeom_free(LWGEOM *lwgeom) { /* There's nothing here to free... */ if( ! lwgeom ) return; LWDEBUGF(5,"freeing a %s",lwtype_name(lwgeom->type)); switch (lwgeom->type) { case POINTTYPE: lwpoint_free((LWPOINT *)lwgeom); break; case LINETYPE: lwline_free((LWLINE *)lwgeom); break; case POLYGONTYPE: lwpoly_free((LWPOLY *)lwgeom); break; case CIRCSTRINGTYPE: lwcircstring_free((LWCIRCSTRING *)lwgeom); break; case TRIANGLETYPE: lwtriangle_free((LWTRIANGLE *)lwgeom); break; case MULTIPOINTTYPE: lwmpoint_free((LWMPOINT *)lwgeom); break; case MULTILINETYPE: lwmline_free((LWMLINE *)lwgeom); break; case MULTIPOLYGONTYPE: lwmpoly_free((LWMPOLY *)lwgeom); break; case POLYHEDRALSURFACETYPE: lwpsurface_free((LWPSURFACE *)lwgeom); break; case TINTYPE: lwtin_free((LWTIN *)lwgeom); break; case CURVEPOLYTYPE: case COMPOUNDTYPE: case MULTICURVETYPE: case MULTISURFACETYPE: case COLLECTIONTYPE: lwcollection_free((LWCOLLECTION *)lwgeom); break; default: lwerror("lwgeom_free called with unknown type (%d) %s", lwgeom->type, lwtype_name(lwgeom->type)); } return; }
void lwmpoly_free(LWMPOLY *mpoly) { int i; if ( ! mpoly ) return; if ( mpoly->bbox ) lwfree(mpoly->bbox); for ( i = 0; i < mpoly->ngeoms; i++ ) if ( mpoly->geoms && mpoly->geoms[i] ) lwpoly_free(mpoly->geoms[i]); if ( mpoly->geoms ) lwfree(mpoly->geoms); lwfree(mpoly); }
void lwpsurface_free(LWPSURFACE *psurf) { int i; if ( ! psurf ) return; if ( psurf->bbox ) lwfree(psurf->bbox); for ( i = 0; i < psurf->ngeoms; i++ ) if ( psurf->geoms && psurf->geoms[i] ) lwpoly_free(psurf->geoms[i]); if ( psurf->geoms ) lwfree(psurf->geoms); lwfree(psurf); }
static void test_ptarray_isccw(void) { LWLINE *line; LWPOLY* poly; int ccw; /* clockwise rectangle */ line = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(0 0,0 10,10 10,10 0, 0 0)")); ccw = ptarray_isccw(line->points); CU_ASSERT_EQUAL(ccw, 0); lwline_free(line); /* clockwise triangle */ line = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(0 3,20 4,20 3, 0 3)")); ccw = ptarray_isccw(line->points); CU_ASSERT_EQUAL(ccw, 0); lwline_free(line); /* counterclockwise triangle */ line = lwgeom_as_lwline(lwgeom_from_text("LINESTRING(0 3,20 3,20 4, 0 3)")); ccw = ptarray_isccw(line->points); CU_ASSERT_EQUAL(ccw, 1); lwline_free(line); /* counterclockwise narrow ring (see ticket #1302) */ line = lwgeom_as_lwline(lwgeom_from_hexwkb("01020000000500000000917E9BA468294100917E9B8AEA284137894120A4682941C976BE9F8AEA2841B39ABE1FA46829415ACCC29F8AEA2841C976BE1FA4682941C976BE9F8AEA284100917E9BA468294100917E9B8AEA2841", LW_PARSER_CHECK_NONE)); ccw = ptarray_isccw(line->points); CU_ASSERT_EQUAL(ccw, 1); lwline_free(line); /* clockwise narrow ring (see ticket #1302) */ line = lwgeom_as_lwline(lwgeom_from_hexwkb("01020000000500000000917E9BA468294100917E9B8AEA2841C976BE1FA4682941C976BE9F8AEA2841B39ABE1FA46829415ACCC29F8AEA284137894120A4682941C976BE9F8AEA284100917E9BA468294100917E9B8AEA2841", LW_PARSER_CHECK_NONE)); ccw = ptarray_isccw(line->points); CU_ASSERT_EQUAL(ccw, 0); lwline_free(line); /* Clockwise narrow ring (see ticket #1302) */ poly = lwgeom_as_lwpoly(lwgeom_from_hexwkb("0103000000010000000500000000917E9BA468294100917E9B8AEA2841C976BE1FA4682941C976BE9F8AEA2841B39ABE1FA46829415ACCC29F8AEA284137894120A4682941C976BE9F8AEA284100917E9BA468294100917E9B8AEA2841", LW_PARSER_CHECK_NONE)); ccw = ptarray_isccw(poly->rings[0]); CU_ASSERT_EQUAL(ccw, 0); lwpoly_free(poly); }
void lwmpoly_free(LWMPOLY *mpoly) { int i; if( mpoly->bbox ) { lwfree(mpoly->bbox); } for ( i = 0; i < mpoly->ngeoms; i++ ) { if( mpoly->geoms[i] ) { lwpoly_free(mpoly->geoms[i]); } } if( mpoly->geoms ) { lwfree(mpoly->geoms); } lwfree(mpoly); };
static void test_rect_tree_contains_point(void) { LWPOLY *poly; POINT2D p; RECT_NODE* tree; int result; int boundary = 0; /* square */ poly = (LWPOLY*)lwgeom_from_wkt("POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))", LW_PARSER_CHECK_NONE); tree = rect_tree_new(poly->rings[0]); /* inside square */ boundary = 0; p.x = 0.5; p.y = 0.5; result = rect_tree_contains_point(tree, &p, &boundary); CU_ASSERT_NOT_EQUAL(result, 0); /* outside square */ boundary = 0; p.x = 1.5; p.y = 0.5; result = rect_tree_contains_point(tree, &p, &boundary); CU_ASSERT_EQUAL(result, 0); rect_tree_free(tree); lwpoly_free(poly); /* ziggy zaggy horizontal saw tooth polygon */ poly = (LWPOLY*)lwgeom_from_wkt("POLYGON((0 0, 1 3, 2 0, 3 3, 4 0, 4 5, 0 5, 0 0))", LW_PARSER_CHECK_NONE); tree = rect_tree_new(poly->rings[0]); /* not in, left side */ boundary = 0; p.x = -0.5; p.y = 0.5; result = rect_tree_contains_point(tree, &p, &boundary); CU_ASSERT_EQUAL(result, 0); /* not in, right side */ boundary = 0; p.x = 3.0; p.y = 1.0; result = rect_tree_contains_point(tree, &p, &boundary); CU_ASSERT_EQUAL(result, 0); /* inside */ boundary = 0; p.x = 2.0; p.y = 1.0; result = rect_tree_contains_point(tree, &p, &boundary); CU_ASSERT_NOT_EQUAL(result, 0); /* on left border */ boundary = 0; p.x = 0.0; p.y = 1.0; result = rect_tree_contains_point(tree, &p, &boundary); CU_ASSERT_EQUAL(boundary, 1); /* on right border */ boundary = 0; p.x = 4.0; p.y = 0.0; result = rect_tree_contains_point(tree, &p, &boundary); CU_ASSERT_EQUAL(boundary, 1); /* on tooth concave */ boundary = 0; p.x = 3.0; p.y = 3.0; result = rect_tree_contains_point(tree, &p, &boundary); CU_ASSERT_EQUAL(boundary, 1); /* on tooth convex */ boundary = 0; p.x = 2.0; p.y = 0.0; result = rect_tree_contains_point(tree, &p, &boundary); CU_ASSERT_EQUAL(boundary, 1); rect_tree_free(tree); lwpoly_free(poly); /* ziggy zaggy vertical saw tooth polygon */ poly = (LWPOLY*)lwgeom_from_wkt("POLYGON((0 0, 3 1, 0 2, 3 3, 0 4, 3 5, 0 6, 5 6, 5 0, 0 0))", LW_PARSER_CHECK_NONE); tree = rect_tree_new(poly->rings[0]); /* not in, left side */ boundary = 0; p.x = -0.5; p.y = 3.5; result = rect_tree_contains_point(tree, &p, &boundary); CU_ASSERT_EQUAL(result, 0); /* not in, right side */ boundary = 0; p.x = 6.0; p.y = 2.2; result = rect_tree_contains_point(tree, &p, &boundary); CU_ASSERT_EQUAL(result, 0); /* inside */ boundary = 0; p.x = 3.0; p.y = 2.0; result = rect_tree_contains_point(tree, &p, &boundary); CU_ASSERT_NOT_EQUAL(result, 0); /* on bottom border */ boundary = 0; p.x = 1.0; p.y = 0.0; result = rect_tree_contains_point(tree, &p, &boundary); CU_ASSERT_EQUAL(boundary, 1); /* on top border */ boundary = 0; p.x = 3.0; p.y = 6.0; result = rect_tree_contains_point(tree, &p, &boundary); CU_ASSERT_EQUAL(boundary, 1); /* on tooth concave */ boundary = 0; p.x = 3.0; p.y = 1.0; result = rect_tree_contains_point(tree, &p, &boundary); CU_ASSERT_EQUAL(boundary, 1); /* on tooth convex */ boundary = 0; p.x = 0.0; p.y = 2.0; result = rect_tree_contains_point(tree, &p, &boundary); CU_ASSERT_EQUAL(boundary, 1); /* on tooth convex */ boundary = 0; p.x = 0.0; p.y = 6.0; result = rect_tree_contains_point(tree, &p, &boundary); CU_ASSERT_EQUAL(boundary, 1); rect_tree_free(tree); lwpoly_free(poly); }
int main() { /* * An example to show how to call the WKT/WKB unparsers in liblwgeom */ LWGEOM_UNPARSER_RESULT lwg_unparser_result; int result; LWGEOM *lwgeom; uchar *serialized_lwgeom; DYNPTARRAY *dpa; POINT4D point4d; POINTARRAY **rings; LWPOINT *testpoint; LWLINE *testline; LWPOLY *testpoly; /* * Construct a geometry equivalent to POINT(0 51) */ dpa = dynptarray_create(10, 2); point4d.x = 0; point4d.y = 51; dynptarray_addPoint4d(dpa, &point4d, 0); testpoint = lwpoint_construct(-1, NULL, dpa->pa); /* Generate the LWGEOM from LWPOINT, then serialize it ready for the parser */ lwgeom = lwpoint_as_lwgeom(testpoint); serialized_lwgeom = lwgeom_serialize(lwgeom); /* Output the geometry in WKT and WKB */ result = serialized_lwgeom_to_ewkt(&lwg_unparser_result, serialized_lwgeom, PARSER_CHECK_ALL); printf("WKT format : %s\n", lwg_unparser_result.wkoutput); result = serialized_lwgeom_to_hexwkb(&lwg_unparser_result, serialized_lwgeom, PARSER_CHECK_ALL, NDR); printf("HEXWKB format : %s\n\n", lwg_unparser_result.wkoutput); /* Free all of the allocated items */ lwfree(lwg_unparser_result.wkoutput); lwfree(serialized_lwgeom); lwpoint_free(testpoint); lwfree(dpa); /* * Construct a geometry equivalent to LINESTRING(0 0, 2 2, 4 1) */ dpa = dynptarray_create(10, 2); point4d.x = 0; point4d.y = 0; dynptarray_addPoint4d(dpa, &point4d, 0); point4d.x = 2; point4d.y = 2; dynptarray_addPoint4d(dpa, &point4d, 0); point4d.x = 4; point4d.y = 1; dynptarray_addPoint4d(dpa, &point4d, 0); testline = lwline_construct(-1, NULL, dpa->pa); /* Generate the LWGEOM from LWLINE, then serialize it ready for the parser */ lwgeom = lwline_as_lwgeom(testline); serialized_lwgeom = lwgeom_serialize(lwgeom); /* Output the geometry in WKT and WKB */ result = serialized_lwgeom_to_ewkt(&lwg_unparser_result, serialized_lwgeom, PARSER_CHECK_ALL); printf("WKT format : %s\n", lwg_unparser_result.wkoutput); result = serialized_lwgeom_to_hexwkb(&lwg_unparser_result, serialized_lwgeom, PARSER_CHECK_ALL, NDR); printf("HEXWKB format : %s\n\n", lwg_unparser_result.wkoutput); /* Free all of the allocated items */ lwfree(lwg_unparser_result.wkoutput); lwfree(serialized_lwgeom); lwline_free(testline); lwfree(dpa); /* * Construct a geometry equivalent to POLYGON((0 0, 0 10, 10 10, 10 0, 0 0)(3 3, 3 6, 6 6, 6 3, 3 3)) */ /* Allocate memory for the rings */ rings = lwalloc(sizeof(POINTARRAY) * 2); /* Construct the first ring */ dpa = dynptarray_create(10, 2); point4d.x = 0; point4d.y = 0; dynptarray_addPoint4d(dpa, &point4d, 0); point4d.x = 0; point4d.y = 10; dynptarray_addPoint4d(dpa, &point4d, 0); point4d.x = 10; point4d.y = 10; dynptarray_addPoint4d(dpa, &point4d, 0); point4d.x = 10; point4d.y = 0; dynptarray_addPoint4d(dpa, &point4d, 0); point4d.x = 0; point4d.y = 0; dynptarray_addPoint4d(dpa, &point4d, 0); rings[0] = dpa->pa; lwfree(dpa); /* Construct the second ring */ dpa = dynptarray_create(10, 2); point4d.x = 3; point4d.y = 3; dynptarray_addPoint4d(dpa, &point4d, 0); point4d.x = 3; point4d.y = 6; dynptarray_addPoint4d(dpa, &point4d, 0); point4d.x = 6; point4d.y = 6; dynptarray_addPoint4d(dpa, &point4d, 0); point4d.x = 6; point4d.y = 3; dynptarray_addPoint4d(dpa, &point4d, 0); point4d.x = 3; point4d.y = 3; dynptarray_addPoint4d(dpa, &point4d, 0); rings[1] = dpa->pa; lwfree(dpa); testpoly = lwpoly_construct(-1, NULL, 2, rings); /* Generate the LWGEOM from LWPOLY, then serialize it ready for the parser */ lwgeom = lwpoly_as_lwgeom(testpoly); serialized_lwgeom = lwgeom_serialize(lwgeom); /* Output the geometry in WKT and WKB */ result = serialized_lwgeom_to_ewkt(&lwg_unparser_result, serialized_lwgeom, PARSER_CHECK_NONE); printf("WKT format : %s\n", lwg_unparser_result.wkoutput); result = serialized_lwgeom_to_hexwkb(&lwg_unparser_result, serialized_lwgeom, PARSER_CHECK_NONE, NDR); printf("HEXWKB format : %s\n\n", lwg_unparser_result.wkoutput); /* Free all of the allocated items */ lwfree(lwg_unparser_result.wkoutput); lwfree(serialized_lwgeom); lwpoly_free(testpoly); }
Datum BOX2D_to_LWGEOM(PG_FUNCTION_ARGS) { GBOX *box = (GBOX *)PG_GETARG_POINTER(0); POINTARRAY *pa = ptarray_construct_empty(0, 0, 5); POINT4D pt; GSERIALIZED *result; /* * Alter BOX2D cast so that a valid geometry is always * returned depending upon the size of the BOX2D. The * code makes the following assumptions: * - If the BOX2D is a single point then return a * POINT geometry * - If the BOX2D represents either a horizontal or * vertical line, return a LINESTRING geometry * - Otherwise return a POLYGON */ if ( (box->xmin == box->xmax) && (box->ymin == box->ymax) ) { /* Construct and serialize point */ LWPOINT *point = lwpoint_make2d(SRID_UNKNOWN, box->xmin, box->ymin); result = geometry_serialize(lwpoint_as_lwgeom(point)); lwpoint_free(point); } else if ( (box->xmin == box->xmax) || (box->ymin == box->ymax) ) { LWLINE *line; /* Assign coordinates to point array */ pt.x = box->xmin; pt.y = box->ymin; ptarray_append_point(pa, &pt, LW_TRUE); pt.x = box->xmax; pt.y = box->ymax; ptarray_append_point(pa, &pt, LW_TRUE); /* Construct and serialize linestring */ line = lwline_construct(SRID_UNKNOWN, NULL, pa); result = geometry_serialize(lwline_as_lwgeom(line)); lwline_free(line); } else { LWPOLY *poly; POINTARRAY **ppa = lwalloc(sizeof(POINTARRAY*)); /* Assign coordinates to point array */ pt.x = box->xmin; pt.y = box->ymin; ptarray_append_point(pa, &pt, LW_TRUE); pt.x = box->xmin; pt.y = box->ymax; ptarray_append_point(pa, &pt, LW_TRUE); pt.x = box->xmax; pt.y = box->ymax; ptarray_append_point(pa, &pt, LW_TRUE); pt.x = box->xmax; pt.y = box->ymin; ptarray_append_point(pa, &pt, LW_TRUE); pt.x = box->xmin; pt.y = box->ymin; ptarray_append_point(pa, &pt, LW_TRUE); /* Construct polygon */ ppa[0] = pa; poly = lwpoly_construct(SRID_UNKNOWN, NULL, 1, ppa); result = geometry_serialize(lwpoly_as_lwgeom(poly)); lwpoly_free(poly); } PG_RETURN_POINTER(result); }
Datum LWGEOM_interiorringn_polygon(PG_FUNCTION_ARGS) { GSERIALIZED *geom; int32 wanted_index; LWCURVEPOLY *curvepoly = NULL; LWPOLY *poly = NULL; POINTARRAY *ring; LWLINE *line; LWGEOM *lwgeom; GSERIALIZED *result; GBOX *bbox = NULL; int type; POSTGIS_DEBUG(2, "LWGEOM_interierringn_polygon called."); wanted_index = PG_GETARG_INT32(1); if ( wanted_index < 1 ) { /* elog(ERROR, "InteriorRingN: ring number is 1-based"); */ PG_RETURN_NULL(); /* index out of range */ } geom = (GSERIALIZED *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); type = gserialized_get_type(geom); if ( (type != POLYGONTYPE) && (type != CURVEPOLYTYPE) ) { elog(ERROR, "InteriorRingN: geom is not a polygon"); PG_FREE_IF_COPY(geom, 0); PG_RETURN_NULL(); } lwgeom = lwgeom_from_gserialized(geom); if( lwgeom_is_empty(lwgeom) ) { lwpoly_free(poly); PG_FREE_IF_COPY(geom, 0); PG_RETURN_NULL(); } if ( type == POLYGONTYPE) { poly = lwgeom_as_lwpoly(lwgeom_from_gserialized(geom)); /* Ok, now we have a polygon. Let's see if it has enough holes */ if ( wanted_index >= poly->nrings ) { lwpoly_free(poly); PG_FREE_IF_COPY(geom, 0); PG_RETURN_NULL(); } ring = poly->rings[wanted_index]; /* COMPUTE_BBOX==TAINTING */ if ( poly->bbox ) { bbox = lwalloc(sizeof(GBOX)); ptarray_calculate_gbox_cartesian(ring, bbox); } /* This is a LWLINE constructed by interior ring POINTARRAY */ line = lwline_construct(poly->srid, bbox, ring); result = geometry_serialize((LWGEOM *)line); lwline_release(line); lwpoly_free(poly); } else { curvepoly = lwgeom_as_lwcurvepoly(lwgeom_from_gserialized(geom)); if (wanted_index >= curvepoly->nrings) { PG_FREE_IF_COPY(geom, 0); lwgeom_release((LWGEOM *)curvepoly); PG_RETURN_NULL(); } result = geometry_serialize(curvepoly->rings[wanted_index]); lwgeom_free((LWGEOM*)curvepoly); } PG_FREE_IF_COPY(geom, 0); PG_RETURN_POINTER(result); }
/** * @brief Generate an allocated geometry string for shapefile object obj using the state parameters * * This function basically deals with the polygon case. It sorts the polys in order of outer, * inner,inner, so that inners always come after outers they are within. * */ int GeneratePolygonGeometry(SHPLOADERSTATE *state, SHPObject *obj, char **geometry) { Ring **Outer; int polygon_total, ring_total; int pi, vi; /* part index and vertex index */ int u; LWCOLLECTION *lwcollection = NULL; LWGEOM **lwpolygons; uchar *serialized_lwgeom; LWGEOM_UNPARSER_RESULT lwg_unparser_result; LWPOLY *lwpoly; DYNPTARRAY *dpas; POINTARRAY ***pas; POINT4D point4d; int dims = 0, hasz = 0, hasm = 0; int result; char *mem; /* Determine the correct dimensions: note that in hwgeom-compatible mode we cannot use the M coordinate */ if (state->wkbtype & WKBZOFFSET) hasz = 1; if (!state->config->hwgeom) if (state->wkbtype & WKBMOFFSET) hasm = 1; TYPE_SETZM(dims, hasz, hasm); polygon_total = FindPolygons(obj, &Outer); if (state->config->simple_geometries == 1 && polygon_total != 1) /* We write Non-MULTI geometries, but have several parts: */ { snprintf(state->message, SHPLOADERMSGLEN, "We have a Multipolygon with %d parts, can't use -S switch!", polygon_total); return SHPLOADERERR; } /* Allocate memory for our array of LWPOLYs */ lwpolygons = malloc(sizeof(LWPOLY *) * polygon_total); /* Allocate memory for our POINTARRAY pointers for each polygon */ pas = malloc(sizeof(POINTARRAY **) * polygon_total); /* Cycle through each individual polygon */ for (pi = 0; pi < polygon_total; pi++) { Ring *polyring; int ring_index = 0; /* Firstly count through the total number of rings in this polygon */ ring_total = 0; polyring = Outer[pi]; while (polyring) { ring_total++; polyring = polyring->next; } /* Reserve memory for the POINTARRAYs representing each ring */ pas[pi] = malloc(sizeof(POINTARRAY *) * ring_total); /* Cycle through each ring within the polygon, starting with the outer */ polyring = Outer[pi]; while (polyring) { /* Create a DYNPTARRAY containing the points making up the ring */ dpas = dynptarray_create(polyring->n, dims); for (vi = 0; vi < polyring->n; vi++) { /* Build up a point array of all the points in this ring */ point4d.x = polyring->list[vi].x; point4d.y = polyring->list[vi].y; if (state->wkbtype & WKBZOFFSET) point4d.z = polyring->list[vi].z; if (state->wkbtype & WKBMOFFSET) point4d.m = polyring->list[vi].m; dynptarray_addPoint4d(dpas, &point4d, 0); } /* Copy the POINTARRAY pointer from the DYNPTARRAY structure so we can use the LWPOLY constructor */ pas[pi][ring_index] = dpas->pa; /* Free the DYNPTARRAY structure (we don't need this part anymore as we have the reference to the internal POINTARRAY) */ lwfree(dpas); polyring = polyring->next; ring_index++; } /* Generate the LWGEOM */ lwpoly = lwpoly_construct(state->config->sr_id, NULL, ring_total, pas[pi]); lwpolygons[pi] = lwpoly_as_lwgeom(lwpoly); } /* If using MULTIPOLYGONS then generate the serialized collection, otherwise just a single POLYGON */ if (state->config->simple_geometries == 0) { lwcollection = lwcollection_construct(MULTIPOLYGONTYPE, state->config->sr_id, NULL, polygon_total, lwpolygons); /* When outputting wkt rather than wkb, we need to remove the SRID from the inner geometries */ if (state->config->hwgeom) { for (u = 0; u < pi; u++) lwpolygons[u]->SRID = -1; } serialized_lwgeom = lwgeom_serialize(lwcollection_as_lwgeom(lwcollection)); } else { serialized_lwgeom = lwgeom_serialize(lwpolygons[0]); } /* Note: lwpoly_free() currently doesn't free its serialized pointlist, so do it manually */ for (pi = 0; pi < polygon_total; pi++) { Ring *polyring = Outer[pi]; int ring_index = 0; while (polyring) { if (pas[pi][ring_index]->serialized_pointlist) lwfree(pas[pi][ring_index]->serialized_pointlist); polyring = polyring->next; ring_index++; } } ReleasePolygons(Outer, polygon_total); if (!state->config->hwgeom) result = serialized_lwgeom_to_hexwkb(&lwg_unparser_result, serialized_lwgeom, PARSER_CHECK_NONE, -1); else result = serialized_lwgeom_to_ewkt(&lwg_unparser_result, serialized_lwgeom, PARSER_CHECK_NONE); if (result) { snprintf(state->message, SHPLOADERMSGLEN, "%s", lwg_unparser_result.message); return SHPLOADERERR; } /* Allocate a string containing the resulting geometry */ mem = malloc(strlen(lwg_unparser_result.wkoutput) + 1); strcpy(mem, lwg_unparser_result.wkoutput); /* Free all of the allocated items */ lwfree(lwg_unparser_result.wkoutput); lwfree(serialized_lwgeom); /* Cycle through each polygon, freeing everything we need... */ for (u = 0; u < polygon_total; u++) lwpoly_free(lwgeom_as_lwpoly(lwpolygons[u])); /* Free the pointer arrays */ lwfree(pas); lwfree(lwpolygons); if (lwcollection) lwfree(lwcollection); /* Return the string - everything ok */ *geometry = mem; return SHPLOADEROK; }