Datum geography_out(PG_FUNCTION_ARGS) { LWGEOM *lwgeom = NULL; GSERIALIZED *g = NULL; char *hexwkb; g = (GSERIALIZED*)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); lwgeom = lwgeom_from_gserialized(g); hexwkb = lwgeom_to_hexwkb(lwgeom, WKB_EXTENDED, 0); lwgeom_free(lwgeom); PG_RETURN_CSTRING(hexwkb); }
Datum LWGEOM_out(PG_FUNCTION_ARGS) { GSERIALIZED *geom = (GSERIALIZED*)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); LWGEOM *lwgeom; char *hexwkb; size_t hexwkb_size; lwgeom = lwgeom_from_gserialized(geom); hexwkb = lwgeom_to_hexwkb(lwgeom, WKB_EXTENDED, &hexwkb_size); lwgeom_free(lwgeom); PG_RETURN_CSTRING(hexwkb); }
Datum LWGEOM_asHEXEWKB(PG_FUNCTION_ARGS) { GSERIALIZED *geom = (GSERIALIZED*)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); LWGEOM *lwgeom; char *hexwkb; size_t hexwkb_size; uint8_t variant = 0; text *result; text *type; size_t text_size; /* If user specified endianness, respect it */ if ( (PG_NARGS()>1) && (!PG_ARGISNULL(1)) ) { type = PG_GETARG_TEXT_P(1); if ( ! strncmp(VARDATA(type), "xdr", 3) || ! strncmp(VARDATA(type), "XDR", 3) ) { variant = variant | WKB_XDR; } else { variant = variant | WKB_NDR; } } /* Create WKB hex string */ lwgeom = lwgeom_from_gserialized(geom); hexwkb = lwgeom_to_hexwkb(lwgeom, variant | WKB_EXTENDED, &hexwkb_size); lwgeom_free(lwgeom); /* Prepare the PgSQL text return type */ text_size = hexwkb_size - 1 + VARHDRSZ; result = palloc(text_size); memcpy(VARDATA(result), hexwkb, hexwkb_size - 1); SET_VARSIZE(result, text_size); /* Clean up and return */ pfree(hexwkb); PG_FREE_IF_COPY(geom, 0); PG_RETURN_TEXT_P(result); }
Datum LWGEOM_to_text(PG_FUNCTION_ARGS) { GSERIALIZED *geom = (GSERIALIZED*)PG_DETOAST_DATUM(PG_GETARG_DATUM(0)); LWGEOM *lwgeom; char *hexwkb; size_t hexwkb_size; text *result; /* Generate WKB hex text */ lwgeom = lwgeom_from_gserialized(geom); hexwkb = lwgeom_to_hexwkb(lwgeom, WKB_EXTENDED, &hexwkb_size); lwgeom_free(lwgeom); /* Copy into text obect */ result = cstring2text(hexwkb); pfree(hexwkb); /* Clean up and return */ PG_FREE_IF_COPY(geom, 0); PG_RETURN_TEXT_P(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; }
/** * @brief Generate an allocated geometry string for shapefile object obj using the state parameters */ int GenerateLineStringGeometry(SHPLOADERSTATE *state, SHPObject *obj, char **geometry) { LWGEOM **lwmultilinestrings; LWGEOM *lwgeom = NULL; POINT4D point4d; int dims = 0; int u, v, start_vertex, end_vertex; char *mem; size_t mem_length; FLAGS_SET_Z(dims, state->has_z); FLAGS_SET_M(dims, state->has_m); if (state->config->simple_geometries == 1 && obj->nParts > 1) { snprintf(state->message, SHPLOADERMSGLEN, _("We have a Multilinestring with %d parts, can't use -S switch!"), obj->nParts); return SHPLOADERERR; } /* Allocate memory for our array of LWLINEs and our dynptarrays */ lwmultilinestrings = malloc(sizeof(LWPOINT *) * obj->nParts); /* We need an array of pointers to each of our sub-geometries */ for (u = 0; u < obj->nParts; u++) { /* Create a ptarray containing the line points */ POINTARRAY *pa = ptarray_construct_empty(state->has_z, state->has_m, obj->nParts); /* Set the start/end vertices depending upon whether this is a MULTILINESTRING or not */ if ( u == obj->nParts-1 ) end_vertex = obj->nVertices; else end_vertex = obj->panPartStart[u + 1]; start_vertex = obj->panPartStart[u]; for (v = start_vertex; v < end_vertex; v++) { /* Generate the point */ point4d.x = obj->padfX[v]; point4d.y = obj->padfY[v]; if (state->has_z) point4d.z = obj->padfZ[v]; if (state->has_m) point4d.m = obj->padfM[v]; ptarray_append_point(pa, &point4d, LW_FALSE); } /* Generate the LWLINE */ lwmultilinestrings[u] = lwline_as_lwgeom(lwline_construct(state->from_srid, NULL, pa)); } /* If using MULTILINESTRINGs then generate the serialized collection, otherwise just a single LINESTRING */ if (state->config->simple_geometries == 0) { lwgeom = lwcollection_as_lwgeom(lwcollection_construct(MULTILINETYPE, state->from_srid, NULL, obj->nParts, lwmultilinestrings)); } else { lwgeom = lwmultilinestrings[0]; lwfree(lwmultilinestrings); } 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); /* Return the string - everything ok */ *geometry = mem; return SHPLOADEROK; }
/** * @brief Generate an allocated geometry string for shapefile object obj using the state parameters * if "force_multi" is true, single points will instead be created as multipoints with a single vertice. */ int GeneratePointGeometry(SHPLOADERSTATE *state, SHPObject *obj, char **geometry, int force_multi) { LWGEOM **lwmultipoints; LWGEOM *lwgeom = NULL; POINT4D point4d; int dims = 0; int u; char *mem; size_t mem_length; FLAGS_SET_Z(dims, state->has_z); FLAGS_SET_M(dims, state->has_m); /* Allocate memory for our array of LWPOINTs and our dynptarrays */ lwmultipoints = malloc(sizeof(LWPOINT *) * obj->nVertices); /* We need an array of pointers to each of our sub-geometries */ for (u = 0; u < obj->nVertices; u++) { /* Create a ptarray containing a single point */ POINTARRAY *pa = ptarray_construct_empty(state->has_z, state->has_m, 1); /* Generate the point */ point4d.x = obj->padfX[u]; point4d.y = obj->padfY[u]; if (state->has_z) point4d.z = obj->padfZ[u]; if (state->has_m) point4d.m = obj->padfM[u]; /* Add in the point! */ ptarray_append_point(pa, &point4d, LW_TRUE); /* Generate the LWPOINT */ lwmultipoints[u] = lwpoint_as_lwgeom(lwpoint_construct(state->from_srid, NULL, pa)); } /* If we have more than 1 vertex then we are working on a MULTIPOINT and so generate a MULTIPOINT rather than a POINT */ if ((obj->nVertices > 1) || force_multi) { lwgeom = lwcollection_as_lwgeom(lwcollection_construct(MULTIPOINTTYPE, state->from_srid, NULL, obj->nVertices, lwmultipoints)); } else { lwgeom = lwmultipoints[0]; lwfree(lwmultipoints); } if (state->config->use_wkt) { mem = lwgeom_to_wkt(lwgeom, WKT_EXTENDED, WKT_PRECISION, &mem_length); } else { mem = lwgeom_to_hexwkb(lwgeom, WKB_EXTENDED, &mem_length); } if ( !mem ) { snprintf(state->message, SHPLOADERMSGLEN, "unable to write geometry"); return SHPLOADERERR; } /* Free all of the allocated items */ lwgeom_free(lwgeom); /* Return the string - everything ok */ *geometry = mem; return SHPLOADEROK; }
void polyhedralsurface_parse(void) { LWGEOM *geom; GSERIALIZED *g; char *tmp; cu_error_msg_reset(); /* Because i don't trust that much prior tests... ;) */ /* 2 dims */ geom = lwgeom_from_wkt("POLYHEDRALSURFACE(((0 1,2 3,4 5,0 1)))", LW_PARSER_CHECK_NONE); CU_ASSERT_EQUAL(strlen(cu_error_msg), 0); CU_ASSERT_EQUAL(geom->type, POLYHEDRALSURFACETYPE); tmp = lwgeom_to_hexwkb(geom, WKB_NDR | WKB_EXTENDED, 0); CU_ASSERT_STRING_EQUAL("010F00000001000000010300000001000000040000000000000000000000000000000000F03F00000000000000400000000000000840000000000000104000000000000014400000000000000000000000000000F03F", tmp); lwfree(tmp); tmp = lwgeom_to_ewkt(geom); CU_ASSERT_STRING_EQUAL("POLYHEDRALSURFACE(((0 1,2 3,4 5,0 1)))", tmp); lwfree(tmp); lwgeom_free(geom); /* 3DM */ geom = lwgeom_from_wkt("POLYHEDRALSURFACEM(((0 1 2,3 4 5,6 7 8,0 1 2)))", LW_PARSER_CHECK_NONE); CU_ASSERT_EQUAL(strlen(cu_error_msg), 0); CU_ASSERT_EQUAL(geom->type, POLYHEDRALSURFACETYPE); tmp = lwgeom_to_ewkt(geom); CU_ASSERT_STRING_EQUAL("POLYHEDRALSURFACEM(((0 1 2,3 4 5,6 7 8,0 1 2)))", tmp); lwfree(tmp); tmp = lwgeom_to_hexwkb(geom, WKB_NDR | WKB_EXTENDED, 0); CU_ASSERT_STRING_EQUAL("010F00004001000000010300004001000000040000000000000000000000000000000000F03F000000000000004000000000000008400000000000001040000000000000144000000000000018400000000000001C4000000000000020400000000000000000000000000000F03F0000000000000040", tmp); lwfree(tmp); lwgeom_free(geom); /* ERROR: a missing Z values */ geom = lwgeom_from_wkt("POLYHEDRALSURFACE(((0 1 2,3 4 5,6 7,0 1 2)))", LW_PARSER_CHECK_NONE); CU_ASSERT_STRING_EQUAL("can not mix dimensionality in a geometry", cu_error_msg); cu_error_msg_reset(); lwgeom_free(geom); /* 1 face with 1 interior ring */ geom = lwgeom_from_wkt("POLYHEDRALSURFACE(((0 1 2,3 4 5,6 7 8,0 1 2),(9 10 11,12 13 14,15 16 17,9 10 11)))", LW_PARSER_CHECK_NONE); CU_ASSERT_EQUAL(strlen(cu_error_msg), 0); CU_ASSERT_EQUAL(geom->type, POLYHEDRALSURFACETYPE); tmp = lwgeom_to_ewkt(geom); CU_ASSERT_STRING_EQUAL("POLYHEDRALSURFACE(((0 1 2,3 4 5,6 7 8,0 1 2),(9 10 11,12 13 14,15 16 17,9 10 11)))", tmp); lwfree(tmp); tmp = lwgeom_to_hexwkb(geom, WKB_NDR | WKB_EXTENDED, 0); CU_ASSERT_STRING_EQUAL("010F00008001000000010300008002000000040000000000000000000000000000000000F03F000000000000004000000000000008400000000000001040000000000000144000000000000018400000000000001C4000000000000020400000000000000000000000000000F03F00000000000000400400000000000000000022400000000000002440000000000000264000000000000028400000000000002A400000000000002C400000000000002E4000000000000030400000000000003140000000000000224000000000000024400000000000002640", tmp); lwfree(tmp); lwgeom_free(geom); /* ERROR: non closed rings */ geom = lwgeom_from_wkt("POLYHEDRALSURFACE(((0 1 2,3 4 5,6 7 8,0 0 2)))", LW_PARSER_CHECK_ALL); CU_ASSERT_STRING_EQUAL("geometry contains non-closed rings", cu_error_msg); cu_error_msg_reset(); lwgeom_free(geom); /* ERROR: non closed face in Z dim */ geom = lwgeom_from_wkt("POLYHEDRALSURFACE(((0 1 2,3 4 5,6 7 8,0 1 3)))", LW_PARSER_CHECK_ALL); CU_ASSERT_STRING_EQUAL("geometry contains non-closed rings", cu_error_msg); cu_error_msg_reset(); lwgeom_free(geom); /* ERROR: non closed face in Z dim, with a 4D geom */ geom = lwgeom_from_wkt("POLYHEDRALSURFACE(((0 1 2 3,4 5 6 7,8 9 10 11,0 1 3 3)))", LW_PARSER_CHECK_ALL); CU_ASSERT_STRING_EQUAL("geometry contains non-closed rings", cu_error_msg); cu_error_msg_reset(); lwgeom_free(geom); /* ERROR: only 3 points in a face */ geom = lwgeom_from_wkt("POLYHEDRALSURFACE(((0 1 2,3 4 5,0 1 2)))", LW_PARSER_CHECK_ALL); CU_ASSERT_STRING_EQUAL("geometry requires more points", cu_error_msg); cu_error_msg_reset(); lwgeom_free(geom); /* EMPTY face */ geom = lwgeom_from_wkt("POLYHEDRALSURFACE EMPTY", LW_PARSER_CHECK_NONE); CU_ASSERT_EQUAL(strlen(cu_error_msg), 0); CU_ASSERT_EQUAL(geom->type, POLYHEDRALSURFACETYPE); tmp = (char *)lwgeom_to_wkb(geom, WKB_HEX | WKB_ISO | WKB_NDR, 0); CU_ASSERT_STRING_EQUAL("010F00000000000000", tmp); lwfree(tmp); tmp = lwgeom_to_ewkt(geom); CU_ASSERT_STRING_EQUAL("POLYHEDRALSURFACE EMPTY", tmp); lwfree(tmp); lwgeom_free(geom); /* A simple tetrahedron */ geom = lwgeom_from_wkt("POLYHEDRALSURFACE(((0 0 0,0 0 1,0 1 0,0 0 0)),((0 0 0,0 1 0,1 0 0,0 0 0)),((0 0 0,1 0 0,0 0 1,0 0 0)),((1 0 0,0 1 0,0 0 1,1 0 0)))", LW_PARSER_CHECK_NONE); CU_ASSERT_EQUAL(strlen(cu_error_msg), 0); CU_ASSERT_EQUAL(geom->type, POLYHEDRALSURFACETYPE); CU_ASSERT_EQUAL(geom->srid, SRID_UNKNOWN); tmp = lwgeom_to_ewkt(geom); CU_ASSERT_STRING_EQUAL("POLYHEDRALSURFACE(((0 0 0,0 0 1,0 1 0,0 0 0)),((0 0 0,0 1 0,1 0 0,0 0 0)),((0 0 0,1 0 0,0 0 1,0 0 0)),((1 0 0,0 1 0,0 0 1,1 0 0)))", tmp); lwfree(tmp); tmp = lwgeom_to_hexwkb(geom, WKB_NDR | WKB_EXTENDED, 0); CU_ASSERT_STRING_EQUAL("010F000080040000000103000080010000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F03F0000000000000000000000000000F03F0000000000000000000000000000000000000000000000000000000000000000010300008001000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000F03F0000000000000000000000000000F03F0000000000000000000000000000000000000000000000000000000000000000000000000000000001030000800100000004000000000000000000000000000000000000000000000000000000000000000000F03F0000000000000000000000000000000000000000000000000000000000000000000000000000F03F00000000000000000000000000000000000000000000000001030000800100000004000000000000000000F03F000000000000000000000000000000000000000000000000000000000000F03F000000000000000000000000000000000000000000000000000000000000F03F000000000000F03F00000000000000000000000000000000", tmp); lwfree(tmp); lwgeom_free(geom); /* A 4D tetrahedron */ geom = lwgeom_from_wkt("POLYHEDRALSURFACE(((0 0 0 0,0 0 1 0,0 1 0 2,0 0 0 0)),((0 0 0 0,0 1 0 0,1 0 0 4,0 0 0 0)),((0 0 0 0,1 0 0 0,0 0 1 6,0 0 0 0)),((1 0 0 0,0 1 0 0,0 0 1 0,1 0 0 0)))", LW_PARSER_CHECK_NONE); CU_ASSERT_EQUAL(strlen(cu_error_msg), 0); CU_ASSERT_EQUAL(geom->type, POLYHEDRALSURFACETYPE); CU_ASSERT_EQUAL(FLAGS_GET_M(geom->flags), 1); CU_ASSERT_EQUAL(geom->srid, SRID_UNKNOWN); tmp = lwgeom_to_ewkt(geom); CU_ASSERT_STRING_EQUAL("POLYHEDRALSURFACE(((0 0 0 0,0 0 1 0,0 1 0 2,0 0 0 0)),((0 0 0 0,0 1 0 0,1 0 0 4,0 0 0 0)),((0 0 0 0,1 0 0 0,0 0 1 6,0 0 0 0)),((1 0 0 0,0 1 0 0,0 0 1 0,1 0 0 0)))", tmp); lwfree(tmp); tmp = lwgeom_to_hexwkb(geom, WKB_NDR | WKB_EXTENDED, 0); CU_ASSERT_STRING_EQUAL("010F0000C00400000001030000C00100000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F03F00000000000000000000000000000000000000000000F03F00000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000001030000C0010000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F03F00000000000000000000000000000000000000000000F03F000000000000000000000000000000000000000000001040000000000000000000000000000000000000000000000000000000000000000001030000C001000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000F03F00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F03F0000000000001840000000000000000000000000000000000000000000000000000000000000000001030000C00100000004000000000000000000F03F0000000000000000000000000000000000000000000000000000000000000000000000000000F03F0000000000000000000000000000000000000000000000000000000000000000000000000000F03F0000000000000000000000000000F03F000000000000000000000000000000000000000000000000", tmp); lwfree(tmp); lwgeom_free(geom); /* explicit SRID */ geom = lwgeom_from_wkt("SRID=4326;POLYHEDRALSURFACE(((0 0 0,0 0 1,0 1 0,0 0 0)),((0 0 0,0 1 0,1 0 0,0 0 0)),((0 0 0,1 0 0,0 0 1,0 0 0)),((1 0 0,0 1 0,0 0 1,1 0 0)))", LW_PARSER_CHECK_NONE); CU_ASSERT_EQUAL(strlen(cu_error_msg), 0); CU_ASSERT_EQUAL(geom->type, POLYHEDRALSURFACETYPE); CU_ASSERT_EQUAL(geom->srid, 4326); tmp = lwgeom_to_ewkt(geom); CU_ASSERT_STRING_EQUAL("SRID=4326;POLYHEDRALSURFACE(((0 0 0,0 0 1,0 1 0,0 0 0)),((0 0 0,0 1 0,1 0 0,0 0 0)),((0 0 0,1 0 0,0 0 1,0 0 0)),((1 0 0,0 1 0,0 0 1,1 0 0)))", tmp); lwfree(tmp); tmp = lwgeom_to_hexwkb(geom, WKB_NDR | WKB_EXTENDED, 0); CU_ASSERT_STRING_EQUAL("010F0000A0E6100000040000000103000080010000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000F03F0000000000000000000000000000F03F0000000000000000000000000000000000000000000000000000000000000000010300008001000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000F03F0000000000000000000000000000F03F0000000000000000000000000000000000000000000000000000000000000000000000000000000001030000800100000004000000000000000000000000000000000000000000000000000000000000000000F03F0000000000000000000000000000000000000000000000000000000000000000000000000000F03F00000000000000000000000000000000000000000000000001030000800100000004000000000000000000F03F000000000000000000000000000000000000000000000000000000000000F03F000000000000000000000000000000000000000000000000000000000000F03F000000000000F03F00000000000000000000000000000000", tmp); lwfree(tmp); lwgeom_free(geom); /* geography support */ geom = lwgeom_from_wkt("POLYHEDRALSURFACE(((0 1 2,3 4 5,6 7 8,0 1 2)))", LW_PARSER_CHECK_NONE); g = gserialized_from_lwgeom(geom, 1, 0); CU_ASSERT_EQUAL(gserialized_get_type(g), POLYHEDRALSURFACETYPE); lwgeom_free(geom); lwfree(g); }