LWGEOM * lwgeom_construct_empty(uint8_t type, int srid, char hasz, char hasm) { switch(type) { case POINTTYPE: return lwpoint_as_lwgeom(lwpoint_construct_empty(srid, hasz, hasm)); case LINETYPE: return lwline_as_lwgeom(lwline_construct_empty(srid, hasz, hasm)); case POLYGONTYPE: return lwpoly_as_lwgeom(lwpoly_construct_empty(srid, hasz, hasm)); case CURVEPOLYTYPE: return lwcurvepoly_as_lwgeom(lwcurvepoly_construct_empty(srid, hasz, hasm)); case CIRCSTRINGTYPE: return lwcircstring_as_lwgeom(lwcircstring_construct_empty(srid, hasz, hasm)); case TRIANGLETYPE: return lwtriangle_as_lwgeom(lwtriangle_construct_empty(srid, hasz, hasm)); case COMPOUNDTYPE: case MULTIPOINTTYPE: case MULTILINETYPE: case MULTIPOLYGONTYPE: case COLLECTIONTYPE: return lwcollection_as_lwgeom(lwcollection_construct_empty(type, srid, hasz, hasm)); default: lwerror("lwgeom_construct_empty: unsupported geometry type: %s", lwtype_name(type)); return NULL; } }
LWGEOM* wkt_parser_polygon_finalize(LWGEOM *poly, char *dimensionality) { uint8_t flags = wkt_dimensionality(dimensionality); int flagdims = FLAGS_NDIMS(flags); LWDEBUG(4,"entered"); /* Null input implies empty return */ if( ! poly ) return lwpoly_as_lwgeom(lwpoly_construct_empty(SRID_UNKNOWN, FLAGS_GET_Z(flags), FLAGS_GET_M(flags))); /* If the number of dimensions are not consistent, we have a problem. */ if( flagdims > 2 ) { if ( flagdims != FLAGS_NDIMS(poly->flags) ) { lwgeom_free(poly); SET_PARSER_ERROR(PARSER_ERROR_MIXDIMS); return NULL; } /* Harmonize the flags in the sub-components with the wkt flags */ if( LW_FAILURE == wkt_parser_set_dims(poly, flags) ) { lwgeom_free(poly); SET_PARSER_ERROR(PARSER_ERROR_OTHER); return NULL; } } return poly; }
LWGEOM* lwgeom_force_dims(const LWGEOM *geom, int hasz, int hasm) { switch(geom->type) { case POINTTYPE: return lwpoint_as_lwgeom(lwpoint_force_dims((LWPOINT*)geom, hasz, hasm)); case CIRCSTRINGTYPE: case LINETYPE: case TRIANGLETYPE: return lwline_as_lwgeom(lwline_force_dims((LWLINE*)geom, hasz, hasm)); case POLYGONTYPE: return lwpoly_as_lwgeom(lwpoly_force_dims((LWPOLY*)geom, hasz, hasm)); case COMPOUNDTYPE: case CURVEPOLYTYPE: case MULTICURVETYPE: case MULTISURFACETYPE: case MULTIPOINTTYPE: case MULTILINETYPE: case MULTIPOLYGONTYPE: case POLYHEDRALSURFACETYPE: case TINTYPE: case COLLECTIONTYPE: return lwcollection_as_lwgeom(lwcollection_force_dims((LWCOLLECTION*)geom, hasz, hasm)); default: lwerror("lwgeom_force_2d: unsupported geom type: %s", lwtype_name(geom->type)); return NULL; } }
/** * MULTIPOLYGON */ static LWCOLLECTION* lwmultipoly_from_twkb_state(twkb_parse_state *s) { int ngeoms, i; LWGEOM *geom = NULL; LWCOLLECTION *col = lwcollection_construct_empty(s->lwtype, SRID_UNKNOWN, s->has_z, s->has_m); LWDEBUG(2,"Entering lwmultipolygon_from_twkb_state"); if ( s->is_empty ) return col; /* Read number of geometries */ ngeoms = twkb_parse_state_uvarint(s); LWDEBUGF(4,"Number of geometries %d",ngeoms); /* It has an idlist, we need to skip that */ if ( s->has_idlist ) { for ( i = 0; i < ngeoms; i++ ) twkb_parse_state_varint_skip(s); } for ( i = 0; i < ngeoms; i++ ) { geom = lwpoly_as_lwgeom(lwpoly_from_twkb_state(s)); if ( lwcollection_add_lwgeom(col, geom) == NULL ) { lwerror("Unable to add geometry (%p) to collection (%p)", geom, col); return NULL; } } return col; }
LWPOLY * lwpoly_construct_envelope(int srid, double x1, double y1, double x2, double y2) { POINT4D p1, p2, p3, p4; LWPOLY *poly; p1.x = x1; p1.y = y1; p2.x = x1; p2.y = y2; p3.x = x2; p3.y = y2; p4.x = x2; p4.y = y1; poly = lwpoly_construct_rectangle(0, 0, &p1, &p2, &p3, &p4); lwgeom_set_srid(lwpoly_as_lwgeom(poly), srid); lwgeom_add_bbox(lwpoly_as_lwgeom(poly)); return poly; }
LWGEOM* wkt_parser_polygon_new(POINTARRAY *pa, char dimcheck) { LWPOLY *poly = NULL; LWDEBUG(4,"entered"); /* No pointarray is a problem */ if( ! pa ) { SET_PARSER_ERROR(PARSER_ERROR_OTHER); return NULL; } poly = lwpoly_construct_empty(SRID_UNKNOWN, FLAGS_GET_Z(pa->flags), FLAGS_GET_M(pa->flags)); /* Error out if we can't build this polygon. */ if( ! poly ) { SET_PARSER_ERROR(PARSER_ERROR_OTHER); return NULL; } wkt_parser_polygon_add_ring(lwpoly_as_lwgeom(poly), pa, dimcheck); return lwpoly_as_lwgeom(poly); }
void lwpoly_release(LWPOLY *lwpoly) { lwgeom_release(lwpoly_as_lwgeom(lwpoly)); }
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); }
/** * @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 */ LWGEOM **lwpolygons; LWGEOM *lwgeom; POINT4D point4d; int dims = 0; char *mem; size_t mem_length; FLAGS_SET_Z(dims, state->has_z); FLAGS_SET_M(dims, state->has_m); 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); /* Cycle through each individual polygon */ for (pi = 0; pi < polygon_total; pi++) { LWPOLY *lwpoly = lwpoly_construct_empty(state->from_srid, state->has_z, state->has_m); 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; } /* Cycle through each ring within the polygon, starting with the outer */ polyring = Outer[pi]; while (polyring) { /* Create a POINTARRAY containing the points making up the ring */ POINTARRAY *pa = ptarray_construct_empty(state->has_z, state->has_m, polyring->n); 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->has_z) point4d.z = polyring->list[vi].z; if (state->has_m) point4d.m = polyring->list[vi].m; ptarray_append_point(pa, &point4d, LW_TRUE); } /* Copy the POINTARRAY pointer so we can use the LWPOLY constructor */ lwpoly_add_ring(lwpoly, pa); polyring = polyring->next; ring_index++; } /* Generate the LWGEOM */ 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) { lwgeom = lwcollection_as_lwgeom(lwcollection_construct(MULTIPOLYGONTYPE, state->from_srid, NULL, polygon_total, lwpolygons)); } else { lwgeom = lwpolygons[0]; lwfree(lwpolygons); } if (!state->config->use_wkt) mem = lwgeom_to_hexwkb(lwgeom, WKB_EXTENDED, &mem_length); else mem = lwgeom_to_wkt(lwgeom, WKT_EXTENDED, WKT_PRECISION, &mem_length); if ( !mem ) { snprintf(state->message, SHPLOADERMSGLEN, "unable to write geometry"); return SHPLOADERERR; } /* Free all of the allocated items */ lwgeom_free(lwgeom); /* Free the linked list of rings */ ReleasePolygons(Outer, polygon_total); /* Return the string - everything ok */ *geometry = mem; return SHPLOADEROK; }
Datum BOX3D_to_LWGEOM(PG_FUNCTION_ARGS) { BOX3D *box = (BOX3D *)PG_GETARG_POINTER(0); POINTARRAY *pa; GSERIALIZED *result; POINT4D pt; /** * Alter BOX3D cast so that a valid geometry is always * returned depending upon the size of the BOX3D. The * code makes the following assumptions: * - If the BOX3D is a single point then return a * POINT geometry * - If the BOX3D represents either a horizontal or * vertical line, return a LINESTRING geometry * - Otherwise return a POLYGON */ pa = ptarray_construct_empty(0, 0, 5); if ( (box->xmin == box->xmax) && (box->ymin == box->ymax) ) { LWPOINT *lwpt = lwpoint_construct(SRID_UNKNOWN, NULL, pa); pt.x = box->xmin; pt.y = box->ymin; ptarray_append_point(pa, &pt, LW_TRUE); result = geometry_serialize(lwpoint_as_lwgeom(lwpt)); } else if (box->xmin == box->xmax || box->ymin == box->ymax) { LWLINE *lwline = lwline_construct(SRID_UNKNOWN, NULL, pa); 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); result = geometry_serialize(lwline_as_lwgeom(lwline)); } else { LWPOLY *lwpoly = lwpoly_construct(SRID_UNKNOWN, NULL, 1, &pa); 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); result = geometry_serialize(lwpoly_as_lwgeom(lwpoly)); } gserialized_set_srid(result, box->srid); 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; }