/* * Returns a geometry collection containing the created multilinestring object (?). * Creates a geometry collection containing 3D (xyz) linestrings. * Parameter first is a gaiaLinestringPtr to the first linestring in a linked list of linestrings which should be added to the * collection. All of the *linestrings in the list must be 3D (xyz) linestrings. There must be at least 1 linestring in the list. * Returns a pointer to the created geometry collection of 3D linestrings. The geometry must have FirstLinestring pointing to the * first linestring in the *list pointed by first and LastLinestring pointing to the last element of the same list. DimensionModel * must be GAIA_XYZ and DimensionType must be *GAIA_TYPE_LINESTRING. */ static gaiaGeomCollPtr geoJSON_multilinestring_xyz (struct geoJson_data *p_data, gaiaLinestringPtr first) { gaiaLinestringPtr p = first; gaiaLinestringPtr p_n; gaiaLinestringPtr new_line; gaiaGeomCollPtr a = gaiaAllocGeomCollXYZ (); geoJsonMapDynAlloc (p_data, GEOJSON_DYN_GEOMETRY, a); a->DeclaredType = GAIA_MULTILINESTRING; a->DimensionModel = GAIA_XY_Z; while (p) { new_line = gaiaAddLinestringToGeomColl (a, p->Points); gaiaCopyLinestringCoords (new_line, p); p_n = p->Next; geoJsonMapDynClean (p_data, p); gaiaFreeLinestring (p); p = p_n; } return a; }
static gaiaGeomCollPtr kml_validate_geometry (struct kml_data *p_data, gaiaGeomCollPtr chain) { int xy = 0; int xyz = 0; int pts = 0; int lns = 0; int pgs = 0; gaiaPointPtr pt; gaiaLinestringPtr ln; gaiaPolygonPtr pg; gaiaPointPtr save_pt = NULL; gaiaLinestringPtr save_ln = NULL; gaiaPolygonPtr save_pg = NULL; gaiaRingPtr i_ring; gaiaRingPtr o_ring; int ib; gaiaGeomCollPtr g; gaiaGeomCollPtr geom; g = chain; while (g) { if (g != chain) { if (g->DimensionModel == GAIA_XY) xy++; if (g->DimensionModel == GAIA_XY_Z) xyz++; } pt = g->FirstPoint; while (pt) { pts++; save_pt = pt; pt = pt->Next; } ln = g->FirstLinestring; while (ln) { lns++; save_ln = ln; ln = ln->Next; } pg = g->FirstPolygon; while (pg) { pgs++; save_pg = pg; pg = pg->Next; } g = g->Next; } if (pts == 1 && lns == 0 && pgs == 0) { /* POINT */ if (xy > 0) { /* 2D [XY] */ geom = gaiaAllocGeomColl (); kmlMapDynAlloc (p_data, KML_DYN_GEOM, pg); if (chain->DeclaredType == GAIA_GEOMETRYCOLLECTION) geom->DeclaredType = GAIA_MULTIPOINT; else geom->DeclaredType = GAIA_POINT; gaiaAddPointToGeomColl (geom, save_pt->X, save_pt->Y); return geom; } else { /* 3D [XYZ] */ geom = gaiaAllocGeomCollXYZ (); kmlMapDynAlloc (p_data, KML_DYN_GEOM, pg); if (chain->DeclaredType == GAIA_GEOMETRYCOLLECTION) geom->DeclaredType = GAIA_MULTIPOINT; else geom->DeclaredType = GAIA_POINT; gaiaAddPointToGeomCollXYZ (geom, save_pt->X, save_pt->Y, save_pt->Z); return geom; } } if (pts == 0 && lns == 1 && pgs == 0) { /* LINESTRING */ if (xy > 0) { /* 2D [XY] */ geom = gaiaAllocGeomColl (); kmlMapDynAlloc (p_data, KML_DYN_GEOM, pg); } else { /* 3D [XYZ] */ geom = gaiaAllocGeomCollXYZ (); kmlMapDynAlloc (p_data, KML_DYN_GEOM, pg); } if (chain->DeclaredType == GAIA_GEOMETRYCOLLECTION) geom->DeclaredType = GAIA_MULTILINESTRING; else geom->DeclaredType = GAIA_LINESTRING; ln = gaiaAddLinestringToGeomColl (geom, save_ln->Points); gaiaCopyLinestringCoords (ln, save_ln); return geom; } if (pts == 0 && lns == 0 && pgs == 1) { /* POLYGON */ if (xy > 0) { /* 2D [XY] */ geom = gaiaAllocGeomColl (); kmlMapDynAlloc (p_data, KML_DYN_GEOM, pg); } else { /* 3D [XYZ] */ geom = gaiaAllocGeomCollXYZ (); kmlMapDynAlloc (p_data, KML_DYN_GEOM, pg); } if (chain->DeclaredType == GAIA_GEOMETRYCOLLECTION) geom->DeclaredType = GAIA_MULTIPOLYGON; else geom->DeclaredType = GAIA_POLYGON; i_ring = save_pg->Exterior; pg = gaiaAddPolygonToGeomColl (geom, i_ring->Points, save_pg->NumInteriors); o_ring = pg->Exterior; gaiaCopyRingCoords (o_ring, i_ring); for (ib = 0; ib < save_pg->NumInteriors; ib++) { i_ring = save_pg->Interiors + ib; o_ring = gaiaAddInteriorRing (pg, ib, i_ring->Points); gaiaCopyRingCoords (o_ring, i_ring); } return geom; } if (pts >= 1 && lns == 0 && pgs == 0) { /* MULTIPOINT */ if (xy > 0) { /* 2D [XY] */ geom = gaiaAllocGeomColl (); kmlMapDynAlloc (p_data, KML_DYN_GEOM, pg); geom->DeclaredType = GAIA_MULTIPOINT; g = chain; while (g) { pt = g->FirstPoint; while (pt) { gaiaAddPointToGeomColl (geom, pt->X, pt->Y); pt = pt->Next; } g = g->Next; } return geom; } else { /* 3D [XYZ] */ geom = gaiaAllocGeomCollXYZ (); kmlMapDynAlloc (p_data, KML_DYN_GEOM, pg); geom->DeclaredType = GAIA_MULTIPOINT; g = chain; while (g) { pt = g->FirstPoint; while (pt) { gaiaAddPointToGeomCollXYZ (geom, pt->X, pt->Y, pt->Z); pt = pt->Next; } g = g->Next; } return geom; } } if (pts == 0 && lns >= 1 && pgs == 0) { /* MULTILINESTRING */ if (xy > 0) { /* 2D [XY] */ geom = gaiaAllocGeomColl (); kmlMapDynAlloc (p_data, KML_DYN_GEOM, pg); geom->DeclaredType = GAIA_MULTILINESTRING; g = chain; while (g) { ln = g->FirstLinestring; while (ln) { save_ln = gaiaAddLinestringToGeomColl (geom, ln->Points); gaiaCopyLinestringCoords (save_ln, ln); ln = ln->Next; } g = g->Next; } return geom; } else { /* 3D [XYZ] */ geom = gaiaAllocGeomCollXYZ (); kmlMapDynAlloc (p_data, KML_DYN_GEOM, pg); geom->DeclaredType = GAIA_MULTILINESTRING; g = chain; while (g) { ln = g->FirstLinestring; while (ln) { save_ln = gaiaAddLinestringToGeomColl (geom, ln->Points); gaiaCopyLinestringCoords (save_ln, ln); ln = ln->Next; } g = g->Next; } return geom; } } if (pts == 0 && lns == 0 && pgs >= 1) { /* MULTIPOLYGON */ if (xy > 0) { /* 2D [XY] */ geom = gaiaAllocGeomColl (); kmlMapDynAlloc (p_data, KML_DYN_GEOM, pg); geom->DeclaredType = GAIA_MULTIPOLYGON; g = chain; while (g) { pg = g->FirstPolygon; while (pg) { i_ring = pg->Exterior; save_pg = gaiaAddPolygonToGeomColl (geom, i_ring->Points, pg->NumInteriors); o_ring = save_pg->Exterior; gaiaCopyRingCoords (o_ring, i_ring); for (ib = 0; ib < pg->NumInteriors; ib++) { i_ring = pg->Interiors + ib; o_ring = gaiaAddInteriorRing (save_pg, ib, i_ring->Points); gaiaCopyRingCoords (o_ring, i_ring); } pg = pg->Next; } g = g->Next; } return geom; } else { /* 3D [XYZ] */ geom = gaiaAllocGeomCollXYZ (); kmlMapDynAlloc (p_data, KML_DYN_GEOM, pg); geom->DeclaredType = GAIA_MULTIPOLYGON; g = chain; while (g) { pg = g->FirstPolygon; while (pg) { i_ring = pg->Exterior; save_pg = gaiaAddPolygonToGeomColl (geom, i_ring->Points, pg->NumInteriors); o_ring = save_pg->Exterior; gaiaCopyRingCoords (o_ring, i_ring); for (ib = 0; ib < pg->NumInteriors; ib++) { i_ring = pg->Interiors + ib; o_ring = gaiaAddInteriorRing (save_pg, ib, i_ring->Points); gaiaCopyRingCoords (o_ring, i_ring); } pg = pg->Next; } g = g->Next; } return geom; } } if ((pts + lns + pgs) > 0) { /* GEOMETRYCOLLECTION */ if (xy > 0) { /* 2D [XY] */ geom = gaiaAllocGeomColl (); kmlMapDynAlloc (p_data, KML_DYN_GEOM, pg); geom->DeclaredType = GAIA_GEOMETRYCOLLECTION; g = chain; while (g) { pt = g->FirstPoint; while (pt) { gaiaAddPointToGeomColl (geom, pt->X, pt->Y); pt = pt->Next; } ln = g->FirstLinestring; while (ln) { save_ln = gaiaAddLinestringToGeomColl (geom, ln->Points); gaiaCopyLinestringCoords (save_ln, ln); ln = ln->Next; } pg = g->FirstPolygon; while (pg) { i_ring = pg->Exterior; save_pg = gaiaAddPolygonToGeomColl (geom, i_ring->Points, pg->NumInteriors); o_ring = save_pg->Exterior; gaiaCopyRingCoords (o_ring, i_ring); for (ib = 0; ib < pg->NumInteriors; ib++) { i_ring = pg->Interiors + ib; o_ring = gaiaAddInteriorRing (save_pg, ib, i_ring->Points); gaiaCopyRingCoords (o_ring, i_ring); } pg = pg->Next; } g = g->Next; } return geom; } else { /* 3D [XYZ] */ geom = gaiaAllocGeomCollXYZ (); kmlMapDynAlloc (p_data, KML_DYN_GEOM, pg); geom->DeclaredType = GAIA_GEOMETRYCOLLECTION; g = chain; while (g) { pt = g->FirstPoint; while (pt) { gaiaAddPointToGeomCollXYZ (geom, pt->X, pt->Y, pt->Z); pt = pt->Next; } ln = g->FirstLinestring; while (ln) { save_ln = gaiaAddLinestringToGeomColl (geom, ln->Points); gaiaCopyLinestringCoords (save_ln, ln); ln = ln->Next; } pg = g->FirstPolygon; while (pg) { i_ring = pg->Exterior; save_pg = gaiaAddPolygonToGeomColl (geom, i_ring->Points, pg->NumInteriors); o_ring = save_pg->Exterior; gaiaCopyRingCoords (o_ring, i_ring); for (ib = 0; ib < pg->NumInteriors; ib++) { i_ring = pg->Interiors + ib; o_ring = gaiaAddInteriorRing (save_pg, ib, i_ring->Points); gaiaCopyRingCoords (o_ring, i_ring); } pg = pg->Next; } g = g->Next; } return geom; } } return NULL; }
GAIAGEO_DECLARE gaiaGeomCollPtr gaiaSanitize (gaiaGeomCollPtr geom) { /* / sanitizes a GEOMETRYCOLLECTION: / - repeated vertices are omitted / - ring closure is enforced anyway */ int iv; int ib; double x = 0.0; double y = 0.0; double z = 0.0; double m = 0.0; double last_x = 0.0; double last_y = 0.0; double last_z = 0.0; int points; gaiaPointPtr point; gaiaLinestringPtr line; gaiaLinestringPtr new_line; gaiaPolygonPtr polyg; gaiaPolygonPtr new_polyg; gaiaGeomCollPtr new_geom; gaiaRingPtr i_ring; gaiaRingPtr o_ring; if (!geom) return NULL; if (geom->DimensionModel == GAIA_XY_Z) new_geom = gaiaAllocGeomCollXYZ (); else if (geom->DimensionModel == GAIA_XY_M) new_geom = gaiaAllocGeomCollXYM (); else if (geom->DimensionModel == GAIA_XY_Z_M) new_geom = gaiaAllocGeomCollXYZM (); else new_geom = gaiaAllocGeomColl (); new_geom->Srid = geom->Srid; new_geom->DeclaredType = geom->DeclaredType; point = geom->FirstPoint; while (point) { /* copying POINTs */ gaiaAddPointToGeomCollXYZM (new_geom, point->X, point->Y, point->Z, point->M); point = point->Next; } line = geom->FirstLinestring; while (line) { /* sanitizing LINESTRINGs */ points = 0; for (iv = 0; iv < line->Points; iv++) { /* PASS I - checking points */ z = 0.0; m = 0.0; if (line->DimensionModel == GAIA_XY_Z) { gaiaGetPointXYZ (line->Coords, iv, &x, &y, &z); } else if (line->DimensionModel == GAIA_XY_M) { gaiaGetPointXYM (line->Coords, iv, &x, &y, &m); } else if (line->DimensionModel == GAIA_XY_Z_M) { gaiaGetPointXYZM (line->Coords, iv, &x, &y, &z, &m); } else { gaiaGetPoint (line->Coords, iv, &x, &y); } if (iv > 0) { if (last_x == x && last_y == y && last_z == z) ; else points++; } else points++; last_x = x; last_y = y; last_z = z; } if (points < 2) { /* illegal LINESTRING - copying the original one */ new_line = gaiaAddLinestringToGeomColl (new_geom, line->Points); gaiaCopyLinestringCoords (new_line, line); } else { /* valid LINESTRING - sanitizing */ new_line = gaiaAddLinestringToGeomColl (new_geom, points); points = 0; for (iv = 0; iv < line->Points; iv++) { /* PASS II - inserting points */ z = 0.0; m = 0.0; if (line->DimensionModel == GAIA_XY_Z) { gaiaGetPointXYZ (line->Coords, iv, &x, &y, &z); } else if (line->DimensionModel == GAIA_XY_M) { gaiaGetPointXYM (line->Coords, iv, &x, &y, &m); } else if (line->DimensionModel == GAIA_XY_Z_M) { gaiaGetPointXYZM (line->Coords, iv, &x, &y, &z, &m); } else { gaiaGetPoint (line->Coords, iv, &x, &y); } if (iv > 0) { if (last_x == x && last_y == y && last_z == z) ; else { if (new_line->DimensionModel == GAIA_XY_Z) { gaiaSetPointXYZ (new_line->Coords, points, x, y, z); } else if (new_line->DimensionModel == GAIA_XY_M) { gaiaSetPointXYM (new_line->Coords, points, x, y, m); } else if (new_line->DimensionModel == GAIA_XY_Z_M) { gaiaSetPointXYZM (new_line->Coords, points, x, y, z, m); } else { gaiaSetPoint (new_line->Coords, points, x, y); } points++; } } else { if (new_line->DimensionModel == GAIA_XY_Z) { gaiaSetPointXYZ (new_line->Coords, points, x, y, z); } else if (new_line->DimensionModel == GAIA_XY_M) { gaiaSetPointXYM (new_line->Coords, points, x, y, m); } else if (new_line->DimensionModel == GAIA_XY_Z_M) { gaiaSetPointXYZM (new_line->Coords, points, x, y, z, m); } else { gaiaSetPoint (new_line->Coords, points, x, y); } points++; } last_x = x; last_y = y; last_z = z; } } line = line->Next; } polyg = geom->FirstPolygon; while (polyg) { /* copying POLYGONs */ i_ring = polyg->Exterior; /* sanitizing EXTERIOR RING */ points = 0; for (iv = 0; iv < i_ring->Points; iv++) { /* PASS I - checking points */ z = 0.0; m = 0.0; if (i_ring->DimensionModel == GAIA_XY_Z) { gaiaGetPointXYZ (i_ring->Coords, iv, &x, &y, &z); } else if (i_ring->DimensionModel == GAIA_XY_M) { gaiaGetPointXYM (i_ring->Coords, iv, &x, &y, &m); } else if (i_ring->DimensionModel == GAIA_XY_Z_M) { gaiaGetPointXYZM (i_ring->Coords, iv, &x, &y, &z, &m); } else { gaiaGetPoint (i_ring->Coords, iv, &x, &y); } if (iv > 0) { if (last_x == x && last_y == y && last_z == z) ; else points++; } else points++; last_x = x; last_y = y; last_z = z; } if (last_x == x && last_y == y && last_z == z) ; else { /* forcing RING closure */ points++; } if (points < 4) { /* illegal RING - copying the original one */ new_polyg = gaiaAddPolygonToGeomColl (new_geom, i_ring->Points, polyg->NumInteriors); o_ring = new_polyg->Exterior; gaiaCopyRingCoords (o_ring, i_ring); } else { /* valid RING - sanitizing */ new_polyg = gaiaAddPolygonToGeomColl (new_geom, points, polyg->NumInteriors); o_ring = new_polyg->Exterior; points = 0; for (iv = 0; iv < i_ring->Points; iv++) { /* PASS II - inserting points */ z = 0.0; m = 0.0; if (i_ring->DimensionModel == GAIA_XY_Z) { gaiaGetPointXYZ (i_ring->Coords, iv, &x, &y, &z); } else if (i_ring->DimensionModel == GAIA_XY_M) { gaiaGetPointXYM (i_ring->Coords, iv, &x, &y, &m); } else if (i_ring->DimensionModel == GAIA_XY_Z_M) { gaiaGetPointXYZM (i_ring->Coords, iv, &x, &y, &z, &m); } else { gaiaGetPoint (i_ring->Coords, iv, &x, &y); } if (iv > 0) { if (last_x == x && last_y == y && last_z == z) ; else { if (o_ring->DimensionModel == GAIA_XY_Z) { gaiaSetPointXYZ (o_ring->Coords, points, x, y, z); } else if (o_ring->DimensionModel == GAIA_XY_M) { gaiaSetPointXYM (o_ring->Coords, points, x, y, m); } else if (o_ring->DimensionModel == GAIA_XY_Z_M) { gaiaSetPointXYZM (o_ring->Coords, points, x, y, z, m); } else { gaiaSetPoint (o_ring->Coords, points, x, y); } points++; } } else { if (o_ring->DimensionModel == GAIA_XY_Z) { gaiaSetPointXYZ (o_ring->Coords, points, x, y, z); } else if (o_ring->DimensionModel == GAIA_XY_M) { gaiaSetPointXYM (o_ring->Coords, points, x, y, m); } else if (o_ring->DimensionModel == GAIA_XY_Z_M) { gaiaSetPointXYZM (o_ring->Coords, points, x, y, z, m); } else { gaiaSetPoint (o_ring->Coords, points, x, y); } points++; } last_x = x; last_y = y; last_z = z; } } /* PASS III - forcing RING closure */ z = 0.0; m = 0.0; if (i_ring->DimensionModel == GAIA_XY_Z) { gaiaGetPointXYZ (i_ring->Coords, 0, &x, &y, &z); } else if (i_ring->DimensionModel == GAIA_XY_M) { gaiaGetPointXYM (i_ring->Coords, 0, &x, &y, &m); } else if (i_ring->DimensionModel == GAIA_XY_Z_M) { gaiaGetPointXYZM (i_ring->Coords, 0, &x, &y, &z, &m); } else { gaiaGetPoint (i_ring->Coords, 0, &x, &y); } points = o_ring->Points - 1; if (o_ring->DimensionModel == GAIA_XY_Z) { gaiaSetPointXYZ (o_ring->Coords, points, x, y, z); } else if (o_ring->DimensionModel == GAIA_XY_M) { gaiaSetPointXYM (o_ring->Coords, points, x, y, m); } else if (o_ring->DimensionModel == GAIA_XY_Z_M) { gaiaSetPointXYZM (o_ring->Coords, points, x, y, z, m); } else { gaiaSetPoint (o_ring->Coords, points, x, y); } for (ib = 0; ib < new_polyg->NumInteriors; ib++) { /* copying each INTERIOR RING [if any] */ i_ring = polyg->Interiors + ib; /* sanitizing an INTERIOR RING */ points = 0; for (iv = 0; iv < i_ring->Points; iv++) { /* PASS I - checking points */ z = 0.0; m = 0.0; if (i_ring->DimensionModel == GAIA_XY_Z) { gaiaGetPointXYZ (i_ring->Coords, iv, &x, &y, &z); } else if (i_ring->DimensionModel == GAIA_XY_M) { gaiaGetPointXYM (i_ring->Coords, iv, &x, &y, &m); } else if (i_ring->DimensionModel == GAIA_XY_Z_M) { gaiaGetPointXYZM (i_ring->Coords, iv, &x, &y, &z, &m); } else { gaiaGetPoint (i_ring->Coords, iv, &x, &y); } if (iv > 0) { if (last_x == x && last_y == y && last_z == z) ; else points++; } else points++; last_x = x; last_y = y; last_z = z; } if (last_x == x && last_y == y && last_z == z) ; else { /* forcing RING closure */ points++; } if (points < 4) { /* illegal RING - copying the original one */ o_ring = gaiaAddInteriorRing (new_polyg, ib, i_ring->Points); gaiaCopyRingCoords (o_ring, i_ring); } else { /* valid RING - sanitizing */ o_ring = gaiaAddInteriorRing (new_polyg, ib, points); points = 0; for (iv = 0; iv < i_ring->Points; iv++) { /* PASS II - inserting points */ z = 0.0; m = 0.0; if (i_ring->DimensionModel == GAIA_XY_Z) { gaiaGetPointXYZ (i_ring->Coords, iv, &x, &y, &z); } else if (i_ring->DimensionModel == GAIA_XY_M) { gaiaGetPointXYM (i_ring->Coords, iv, &x, &y, &m); } else if (i_ring->DimensionModel == GAIA_XY_Z_M) { gaiaGetPointXYZM (i_ring->Coords, iv, &x, &y, &z, &m); } else { gaiaGetPoint (i_ring->Coords, iv, &x, &y); } if (iv > 0) { if (last_x == x && last_y == y && last_z == z) ; else { if (o_ring->DimensionModel == GAIA_XY_Z) { gaiaSetPointXYZ (o_ring->Coords, points, x, y, z); } else if (o_ring->DimensionModel == GAIA_XY_M) { gaiaSetPointXYM (o_ring->Coords, points, x, y, m); } else if (o_ring->DimensionModel == GAIA_XY_Z_M) { gaiaSetPointXYZM (o_ring->Coords, points, x, y, z, m); } else { gaiaSetPoint (o_ring->Coords, points, x, y); } points++; } } else { if (o_ring->DimensionModel == GAIA_XY_Z) { gaiaSetPointXYZ (o_ring->Coords, points, x, y, z); } else if (o_ring->DimensionModel == GAIA_XY_M) { gaiaSetPointXYM (o_ring->Coords, points, x, y, m); } else if (o_ring->DimensionModel == GAIA_XY_Z_M) { gaiaSetPointXYZM (o_ring->Coords, points, x, y, z, m); } else { gaiaSetPoint (o_ring->Coords, points, x, y); } points++; } last_x = x; last_y = y; last_z = z; } /* PASS III - forcing RING closure */ z = 0.0; m = 0.0; if (i_ring->DimensionModel == GAIA_XY_Z) { gaiaGetPointXYZ (i_ring->Coords, 0, &x, &y, &z); } else if (i_ring->DimensionModel == GAIA_XY_M) { gaiaGetPointXYM (i_ring->Coords, 0, &x, &y, &m); } else if (i_ring->DimensionModel == GAIA_XY_Z_M) { gaiaGetPointXYZM (i_ring->Coords, 0, &x, &y, &z, &m); } else { gaiaGetPoint (i_ring->Coords, 0, &x, &y); } points = o_ring->Points - 1; if (o_ring->DimensionModel == GAIA_XY_Z) { gaiaSetPointXYZ (o_ring->Coords, points, x, y, z); } else if (o_ring->DimensionModel == GAIA_XY_M) { gaiaSetPointXYM (o_ring->Coords, points, x, y, m); } else if (o_ring->DimensionModel == GAIA_XY_Z_M) { gaiaSetPointXYZM (o_ring->Coords, points, x, y, z, m); } else { gaiaSetPoint (o_ring->Coords, points, x, y); } } } polyg = polyg->Next; } return new_geom; }