/* * Creates a 2D (xy) multipoint object in SpatiaLite * * first is a gaiaPointPtr to the first point in a linked list of points. * All of the points given to the function are 2D (xy) points. There will be at least 1 point in the list. * * Returns a geometry collection containing the created multipoint object. */ static gaiaGeomCollPtr geoJSON_multipoint_xy (struct geoJson_data *p_data, gaiaPointPtr first) { gaiaPointPtr p = first; gaiaPointPtr p_n; gaiaGeomCollPtr geom = NULL; /* If no pointers are given, return. */ if (first == NULL) return NULL; /* Creates and allocates a geometry collection containing a multipoint. */ geom = gaiaAllocGeomColl (); if (geom == NULL) return NULL; geoJsonMapDynAlloc (p_data, GEOJSON_DYN_GEOMETRY, geom); geom->DeclaredType = GAIA_MULTIPOINT; /* For every 2D (xy) point, add it to the geometry collection. */ while (p != NULL) { gaiaAddPointToGeomColl (geom, p->X, p->Y); p_n = p->Next; geoJsonMapDynClean (p_data, p); gaiaFreePoint (p); p = p_n; } return geom; }
static gaiaGeomCollPtr gaiaGeoJsonGeometryFromLinestring (struct geoJson_data *p_data, gaiaLinestringPtr line, int srid) { /* builds a GEOMETRY containing a LINESTRING */ gaiaGeomCollPtr geom = NULL; gaiaLinestringPtr line2; int iv; double x; double y; geom = gaiaAllocGeomColl (); geoJsonMapDynAlloc (p_data, GEOJSON_DYN_GEOMETRY, geom); geom->DeclaredType = GAIA_LINESTRING; geom->Srid = srid; line2 = gaiaAddLinestringToGeomColl (geom, line->Points); for (iv = 0; iv < line2->Points; iv++) { /* sets the POINTS for the exterior ring */ gaiaGetPoint (line->Coords, iv, &x, &y); gaiaSetPoint (line2->Coords, iv, x, y); } geoJsonMapDynClean (p_data, line); gaiaFreeLinestring (line); return geom; }
static void add_linestring_to_geometry (struct gml_params *params, gaiaDynamicLinePtr dyn_line) { /* adding a LINESTRING to current Geometry */ int iv = 0; gaiaPointPtr pt; gaiaLinestringPtr line; if (params->geometry == NULL) params->geometry = gaiaAllocGeomColl (); pt = dyn_line->First; while (pt) { /* counting how many POINTs are there */ iv++; pt = pt->Next; } line = gaiaAddLinestringToGeomColl (params->geometry, iv); iv = 0; pt = dyn_line->First; while (pt) { /* inserting any POINT into LINESTRING */ gaiaSetPoint (line->Coords, iv, pt->X, pt->Y); iv++; pt = pt->Next; } gaiaFreeDynamicLine (dyn_line); }
GAIAGEO_DECLARE gaiaGeomCollPtr gaiaCriticalPointFromGEOSmsg_r (const void *p_cache) { /* / Attempts to return a Point Geometry extracted from the latest GEOS / error / warning message */ double x; double y; gaiaGeomCollPtr geom; const char *msg; struct splite_internal_cache *cache = (struct splite_internal_cache *) p_cache; if (cache == NULL) return NULL; if (cache->magic1 == SPATIALITE_CACHE_MAGIC1 || cache->magic2 == SPATIALITE_CACHE_MAGIC2) ; else return NULL; msg = cache->gaia_geos_error_msg; if (msg == NULL) msg = cache->gaia_geos_warning_msg; if (msg == NULL) return NULL; if (!check_geos_critical_point (msg, &x, &y)) return NULL; geom = gaiaAllocGeomColl (); gaiaAddPointToGeomColl (geom, x, y); return geom; }
static gaiaGeomCollPtr kml_build_geometry (struct kml_data *p_data, kmlNodePtr tree) { /* attempting to build a geometry from KML nodes */ gaiaGeomCollPtr geom; gaiaGeomCollPtr result; int geom_type; kmlNodePtr next; if (tree == NULL) return NULL; geom_type = guessKmlGeometryType (tree); if (geom_type == GAIA_KML_UNKNOWN) { /* unsupported main geometry type */ return NULL; } /* creating the main geometry */ geom = gaiaAllocGeomColl (); switch (geom_type) { /* parsing KML nodes accordingly with declared KML type */ case GAIA_KML_POINT: geom->DeclaredType = GAIA_POINT; if (!kml_parse_point (p_data, geom, tree->Next, &next)) goto error; break; case GAIA_KML_LINESTRING: geom->DeclaredType = GAIA_LINESTRING; if (!kml_parse_linestring (p_data, geom, tree->Next, &next)) goto error; break; case GAIA_KML_POLYGON: geom->DeclaredType = GAIA_POLYGON; if (!kml_parse_polygon (p_data, geom, tree->Next, &next)) goto error; if (next != NULL) goto error; break; case GAIA_KML_MULTIGEOMETRY: geom->DeclaredType = GAIA_GEOMETRYCOLLECTION; if (!kml_parse_multi_geometry (p_data, geom, tree->Next)) goto error; break; }; /* attempting to build the final geometry */ result = kml_validate_geometry (p_data, geom); if (result == NULL) goto error; kml_free_geom_chain (geom); return result; error: kml_free_geom_chain (geom); return NULL; }
/* * See geomColl_xy for description. * * The only difference between this function and geomColl_xy is that the 'declaredType' field of the structs * in the linked list for this function will only contain the following types: * * GAIA_POINTZ, GAIA_LINESTRINGZ, GAIA_POLYGONZ, * GAIA_MULTIPOINTZ, GAIA_MULTILINESTRINGZ, GAIA_MULTIPOLYGONZ */ static gaiaGeomCollPtr geoJSON_geomColl_xyz (struct geoJson_data *p_data, gaiaGeomCollPtr first) { gaiaGeomCollPtr geom = gaiaAllocGeomColl (); if (geom == NULL) return NULL; geoJsonMapDynAlloc (p_data, GEOJSON_DYN_GEOMETRY, geom); geom->DeclaredType = GAIA_GEOMETRYCOLLECTION; geom->DimensionModel = GAIA_XY_Z; geoJSON_geomColl_common (p_data, first, geom); return geom; }
static gaiaGeomCollPtr gaiaGeoJsonGeometryFromPoint (struct geoJson_data *p_data, gaiaPointPtr point, int srid) { /* builds a GEOMETRY containing a POINT */ gaiaGeomCollPtr geom = NULL; geom = gaiaAllocGeomColl (); geoJsonMapDynAlloc (p_data, GEOJSON_DYN_GEOMETRY, geom); geom->DeclaredType = GAIA_POINT; geom->Srid = srid; gaiaAddPointToGeomColl (geom, point->X, point->Y); geoJsonMapDynClean (p_data, point); gaiaFreePoint (point); return geom; }
int main (int argc, char *argv[]) { #ifndef OMIT_GEOS /* only if GEOS is supported */ gaiaGeomCollPtr result; void *resultVoid; int returnValue = 0; /* Common setup */ gaiaGeomCollPtr emptyGeometry = gaiaAllocGeomColl(); /* Tests start here */ /* null input test */ result = gaiaFromGeos_XY ( (const void*) NULL ); if (result != NULL) { fprintf(stderr, "bad result at %s:%i\n", __FILE__, __LINE__); returnValue = -1; goto exit; } resultVoid = gaiaToGeos ((gaiaGeomCollPtr)NULL); if (resultVoid != NULL) { fprintf(stderr, "bad result at %s:%i\n", __FILE__, __LINE__); returnValue = -2; goto exit; } /* unknown type geometry collection */ resultVoid = gaiaToGeos ( emptyGeometry ); if (resultVoid != NULL) { fprintf(stderr, "bad result at %s:%i\n", __FILE__, __LINE__); returnValue = -3; goto exit; } /* Cleanup and exit */ exit: gaiaFreeGeomColl (emptyGeometry); return returnValue; #endif /* end GEOS conditional */ return 0; }
static void add_point_to_geometry (struct gml_params *params, gaiaDynamicLinePtr dyn_line) { /* adding a POINT to current Geometry */ gaiaPointPtr pt; if (params->geometry == NULL) params->geometry = gaiaAllocGeomColl (); pt = dyn_line->First; while (pt) { /* inserting any POINT */ gaiaAddPointToGeomColl (params->geometry, pt->X, pt->Y); pt = pt->Next; } gaiaFreeDynamicLine (dyn_line); }
GAIAGEO_DECLARE gaiaGeomCollPtr gaiaExtractPointsFromGeomColl (gaiaGeomCollPtr geom) { /* extracts any POINT from a GeometryCollection */ gaiaGeomCollPtr result; gaiaPointPtr pt; int pts = 0; if (!geom) return NULL; pt = geom->FirstPoint; while (pt) { pts++; pt = pt->Next; } if (!pts) return NULL; if (geom->DimensionModel == GAIA_XY_Z_M) result = gaiaAllocGeomCollXYZM (); else if (geom->DimensionModel == GAIA_XY_Z) result = gaiaAllocGeomCollXYZ (); else if (geom->DimensionModel == GAIA_XY_M) result = gaiaAllocGeomCollXYM (); else result = gaiaAllocGeomColl (); pt = geom->FirstPoint; while (pt) { if (geom->DimensionModel == GAIA_XY_Z_M) gaiaAddPointToGeomCollXYZM (result, pt->X, pt->Y, pt->Z, pt->M); else if (geom->DimensionModel == GAIA_XY_Z) gaiaAddPointToGeomCollXYZ (result, pt->X, pt->Y, pt->Z); else if (geom->DimensionModel == GAIA_XY_M) gaiaAddPointToGeomCollXYM (result, pt->X, pt->Y, pt->M); else gaiaAddPointToGeomColl (result, pt->X, pt->Y); pt = pt->Next; } result->Srid = geom->Srid; result->DeclaredType = GAIA_MULTIPOINT; return result; }
GAIAGEO_DECLARE gaiaGeomCollPtr gaiaCriticalPointFromGEOSmsg (void) { /* / Attempts to return a Point Geometry extracted from the latest GEOS / error / warning message */ double x; double y; gaiaGeomCollPtr geom; const char *msg = gaia_geos_error_msg; if (msg == NULL) msg = gaia_geos_warning_msg; if (msg == NULL) return NULL; if (!check_geos_critical_point (msg, &x, &y)) return NULL; geom = gaiaAllocGeomColl (); gaiaAddPointToGeomColl (geom, x, y); return geom; }
static gaiaGeomCollPtr geoJSON_buildGeomFromPolygonSrid (struct geoJson_data *p_data, gaiaPolygonPtr polygon, int *srid) { gaiaGeomCollPtr geom = NULL; /* If no pointers are given, return. */ if (polygon == NULL) { return NULL; } /* Creates and allocates a geometry collection containing a multipoint. */ switch (polygon->DimensionModel) { case GAIA_XY: geom = gaiaAllocGeomColl (); break; case GAIA_XY_Z: geom = gaiaAllocGeomCollXYZ (); break; } if (geom == NULL) { return NULL; } geoJsonMapDynAlloc (p_data, GEOJSON_DYN_GEOMETRY, geom); geom->DeclaredType = GAIA_POLYGON; geom->Srid = *srid; /* Stores the location of the first and last polygons in the linked list. */ geom->FirstPolygon = polygon; while (polygon != NULL) { geoJsonMapDynClean (p_data, polygon); geom->LastPolygon = polygon; polygon = polygon->Next; } return geom; }
/* * Creates a geometry collection containing 2D (xy) polygons. * * Parameter first is a gaiaPolygonPtr to the first polygon in a linked list of polygons which should * be added to the collection. All of the polygons in the list must be 2D (xy) polygons. There must be * at least 1 polygon in the list. * * Returns a pointer to the created geometry collection of 2D polygons. The geometry must have * FirstPolygon pointing to the first polygon in the list pointed by first and LastPolygon pointing * to the last element of the same list. DimensionModel must be GAIA_XY and DimensionType must * be GAIA_TYPE_POLYGON. * */ static gaiaGeomCollPtr geoJSON_multipolygon_xy (struct geoJson_data *p_data, gaiaPolygonPtr first) { gaiaPolygonPtr p = first; gaiaPolygonPtr p_n; int i = 0; gaiaPolygonPtr new_polyg; gaiaRingPtr i_ring; gaiaRingPtr o_ring; gaiaGeomCollPtr geom = gaiaAllocGeomColl (); geoJsonMapDynAlloc (p_data, GEOJSON_DYN_GEOMETRY, geom); geom->DeclaredType = GAIA_MULTIPOLYGON; while (p) { i_ring = p->Exterior; new_polyg = gaiaAddPolygonToGeomColl (geom, i_ring->Points, p->NumInteriors); o_ring = new_polyg->Exterior; gaiaCopyRingCoords (o_ring, i_ring); for (i = 0; i < new_polyg->NumInteriors; i++) { i_ring = p->Interiors + i; o_ring = gaiaAddInteriorRing (new_polyg, i, i_ring->Points); gaiaCopyRingCoords (o_ring, i_ring); } p_n = p->Next; geoJsonMapDynClean (p_data, p); gaiaFreePolygon (p); p = p_n; } return geom; }
static gaiaGeomCollPtr geoJSON_multilinestring_xy (struct geoJson_data *p_data, gaiaLinestringPtr first) { gaiaLinestringPtr p = first; gaiaLinestringPtr p_n; gaiaLinestringPtr new_line; gaiaGeomCollPtr a = gaiaAllocGeomColl (); geoJsonMapDynAlloc (p_data, GEOJSON_DYN_GEOMETRY, a); a->DeclaredType = GAIA_MULTILINESTRING; a->DimensionModel = GAIA_XY; 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 void vbbox_read_row (VirtualBBoxCursorPtr cursor) { /* trying to read a row from the BoundingBox real-table */ struct splite_internal_cache *cache = (struct splite_internal_cache *) cursor->pVtab->p_cache; sqlite3_stmt *stmt; int ret; int ic; int icx; const char *text; const unsigned char *blob; int size; sqlite3_int64 pk; double minx; double miny; double maxx; double maxy; int srid; char ok_minx = 'N'; char ok_miny = 'N'; char ok_maxx = 'N'; char ok_maxy = 'N'; char ok_srid = 'N'; stmt = cursor->stmt; sqlite3_bind_int64 (stmt, 1, cursor->current_row); ret = sqlite3_step (stmt); if (ret == SQLITE_ROW) { pk = sqlite3_column_int64 (stmt, 0); if (sqlite3_column_type (stmt, 1) == SQLITE_FLOAT) { minx = sqlite3_column_double (stmt, 1); ok_minx = 'Y'; } if (sqlite3_column_type (stmt, 2) == SQLITE_FLOAT) { miny = sqlite3_column_double (stmt, 2); ok_miny = 'Y'; } if (sqlite3_column_type (stmt, 3) == SQLITE_FLOAT) { maxx = sqlite3_column_double (stmt, 3); ok_maxx = 'Y'; } if (sqlite3_column_type (stmt, 4) == SQLITE_FLOAT) { maxy = sqlite3_column_double (stmt, 4); ok_maxy = 'Y'; } if (sqlite3_column_type (stmt, 5) == SQLITE_INTEGER) { srid = sqlite3_column_int (stmt, 5); ok_srid = 'Y'; } if (cursor->pVtab->BBoxGeom) gaiaFreeGeomColl (cursor->pVtab->BBoxGeom); cursor->pVtab->BBoxGeom = NULL; if (ok_minx == 'Y' && ok_miny == 'Y' && ok_maxx == 'Y' && ok_maxy == 'Y') { gaiaGeomCollPtr geom = gaiaAllocGeomColl (); gaiaPolygonPtr pg = gaiaAddPolygonToGeomColl (geom, 5, 0); gaiaRingPtr rng = pg->Exterior; gaiaSetPoint (rng->Coords, 0, minx, miny); gaiaSetPoint (rng->Coords, 1, maxx, miny); gaiaSetPoint (rng->Coords, 2, maxx, maxy); gaiaSetPoint (rng->Coords, 3, minx, maxy); gaiaSetPoint (rng->Coords, 4, minx, miny); if (ok_srid == 'Y') { if (cursor->pVtab->ForceWGS84) { /* converting to WGS84 long-lat */ gaiaGeomCollPtr geom2 = NULL; char *proj_from = NULL; char *proj_to = NULL; geom->Srid = srid; getProjParams (cursor->pVtab->db, srid, &proj_from); getProjParams (cursor->pVtab->db, 4326, &proj_to); if (proj_to == NULL || proj_from == NULL) geom2 = NULL; else #ifndef OMIT_PROJ /* including PROJ.4 */ if (cache != NULL) geom2 = gaiaTransform_r (cache, geom, proj_from, proj_to); else geom2 = gaiaTransform (geom, proj_from, proj_to); #endif /* end including PROJ.4 */ geom2 = NULL; if (geom2 != NULL) geom2->Srid = 4326; cursor->pVtab->BBoxGeom = geom2; gaiaFreeGeomColl (geom); if (proj_from) free (proj_from); if (proj_to) free (proj_to); } else { geom->Srid = srid; cursor->pVtab->BBoxGeom = geom; } } else { geom->Srid = cursor->pVtab->Srid; cursor->pVtab->BBoxGeom = geom; } } icx = 5; for (ic = 0; ic < cursor->pVtab->nColumns; ic++) { if (*(cursor->pVtab->Visible + ic) != 'Y') continue; icx++; switch (sqlite3_column_type (stmt, icx)) { case SQLITE_INTEGER: value_set_int (*(cursor->pVtab->Value + ic), sqlite3_column_int64 (stmt, icx)); break; case SQLITE_FLOAT: value_set_double (*(cursor->pVtab->Value + ic), sqlite3_column_double (stmt, icx)); break; case SQLITE_TEXT: text = (char *) sqlite3_column_text (stmt, icx); size = sqlite3_column_bytes (stmt, icx); value_set_text (*(cursor->pVtab->Value + ic), text, size); break; case SQLITE_BLOB: blob = sqlite3_column_blob (stmt, icx); size = sqlite3_column_bytes (stmt, icx); value_set_blob (*(cursor->pVtab->Value + ic), blob, size); break; case SQLITE_NULL: default: value_set_null (*(cursor->pVtab->Value + ic)); break; }; } } else { /* an error occurred */ cursor->eof = 1; return; } cursor->eof = 0; cursor->current_row = pk; }
static gaiaGeomCollPtr gaiaTransformCommon (projCtx handle, gaiaGeomCollPtr org, char *proj_from, char *proj_to) { /* creates a new GEOMETRY reprojecting coordinates from the original one */ int ib; int cnt; int i; double *xx; double *yy; double *zz; double *mm = NULL; double x; double y; double z = 0.0; double m = 0.0; int error = 0; int from_angle; int to_angle; gaiaPointPtr pt; gaiaLinestringPtr ln; gaiaLinestringPtr dst_ln; gaiaPolygonPtr pg; gaiaPolygonPtr dst_pg; gaiaRingPtr rng; gaiaRingPtr dst_rng; projPJ from_cs; projPJ to_cs; gaiaGeomCollPtr dst; if (handle != NULL) { from_cs = pj_init_plus_ctx (handle, proj_from); to_cs = pj_init_plus_ctx (handle, proj_to); } else { from_cs = pj_init_plus (proj_from); to_cs = pj_init_plus (proj_to); } if (!from_cs) { if (to_cs) pj_free (to_cs); return NULL; } if (!to_cs) { pj_free (from_cs); return NULL; } if (org->DimensionModel == GAIA_XY_Z) dst = gaiaAllocGeomCollXYZ (); else if (org->DimensionModel == GAIA_XY_M) dst = gaiaAllocGeomCollXYM (); else if (org->DimensionModel == GAIA_XY_Z_M) dst = gaiaAllocGeomCollXYZM (); else dst = gaiaAllocGeomColl (); /* setting up projection parameters */ from_angle = gaiaIsLongLat (proj_from); to_angle = gaiaIsLongLat (proj_to); cnt = 0; pt = org->FirstPoint; while (pt) { /* counting POINTs */ cnt++; pt = pt->Next; } if (cnt) { /* reprojecting POINTs */ xx = malloc (sizeof (double) * cnt); yy = malloc (sizeof (double) * cnt); zz = malloc (sizeof (double) * cnt); if (org->DimensionModel == GAIA_XY_M || org->DimensionModel == GAIA_XY_Z_M) mm = malloc (sizeof (double) * cnt); i = 0; pt = org->FirstPoint; while (pt) { /* inserting points to be converted in temporary arrays */ if (from_angle) { xx[i] = gaiaDegsToRads (pt->X); yy[i] = gaiaDegsToRads (pt->Y); } else { xx[i] = pt->X; yy[i] = pt->Y; } if (org->DimensionModel == GAIA_XY_Z || org->DimensionModel == GAIA_XY_Z_M) zz[i] = pt->Z; else zz[i] = 0.0; if (org->DimensionModel == GAIA_XY_M || org->DimensionModel == GAIA_XY_Z_M) mm[i] = pt->M; i++; pt = pt->Next; } /* applying reprojection */ if (pj_transform (from_cs, to_cs, cnt, 0, xx, yy, zz) == 0) { /* inserting the reprojected POINTs in the new GEOMETRY */ for (i = 0; i < cnt; i++) { if (to_angle) { x = gaiaRadsToDegs (xx[i]); y = gaiaRadsToDegs (yy[i]); } else { x = xx[i]; y = yy[i]; } if (org->DimensionModel == GAIA_XY_Z || org->DimensionModel == GAIA_XY_Z_M) z = zz[i]; else z = 0.0; if (org->DimensionModel == GAIA_XY_M || org->DimensionModel == GAIA_XY_Z_M) m = mm[i]; else m = 0.0; if (dst->DimensionModel == GAIA_XY_Z) gaiaAddPointToGeomCollXYZ (dst, x, y, z); else if (dst->DimensionModel == GAIA_XY_M) gaiaAddPointToGeomCollXYM (dst, x, y, m); else if (dst->DimensionModel == GAIA_XY_Z_M) gaiaAddPointToGeomCollXYZM (dst, x, y, z, m); else gaiaAddPointToGeomColl (dst, x, y); } } else error = 1; free (xx); free (yy); free (zz); if (org->DimensionModel == GAIA_XY_M || org->DimensionModel == GAIA_XY_Z_M) free (mm); } if (error) goto stop; ln = org->FirstLinestring; while (ln) { /* reprojecting LINESTRINGs */ cnt = ln->Points; xx = malloc (sizeof (double) * cnt); yy = malloc (sizeof (double) * cnt); zz = malloc (sizeof (double) * cnt); if (ln->DimensionModel == GAIA_XY_M || ln->DimensionModel == GAIA_XY_Z_M) mm = malloc (sizeof (double) * cnt); for (i = 0; i < cnt; i++) { /* inserting points to be converted in temporary arrays */ if (ln->DimensionModel == GAIA_XY_Z) { gaiaGetPointXYZ (ln->Coords, i, &x, &y, &z); } else if (ln->DimensionModel == GAIA_XY_M) { gaiaGetPointXYM (ln->Coords, i, &x, &y, &m); } else if (ln->DimensionModel == GAIA_XY_Z_M) { gaiaGetPointXYZM (ln->Coords, i, &x, &y, &z, &m); } else { gaiaGetPoint (ln->Coords, i, &x, &y); } if (from_angle) { xx[i] = gaiaDegsToRads (x); yy[i] = gaiaDegsToRads (y); } else { xx[i] = x; yy[i] = y; } if (ln->DimensionModel == GAIA_XY_Z || ln->DimensionModel == GAIA_XY_Z_M) zz[i] = z; else zz[i] = 0.0; if (ln->DimensionModel == GAIA_XY_M || ln->DimensionModel == GAIA_XY_Z_M) mm[i] = m; } /* applying reprojection */ if (pj_transform (from_cs, to_cs, cnt, 0, xx, yy, zz) == 0) { /* inserting the reprojected LINESTRING in the new GEOMETRY */ dst_ln = gaiaAddLinestringToGeomColl (dst, cnt); for (i = 0; i < cnt; i++) { /* setting LINESTRING points */ if (to_angle) { x = gaiaRadsToDegs (xx[i]); y = gaiaRadsToDegs (yy[i]); } else { x = xx[i]; y = yy[i]; } if (ln->DimensionModel == GAIA_XY_Z || ln->DimensionModel == GAIA_XY_Z_M) z = zz[i]; else z = 0.0; if (ln->DimensionModel == GAIA_XY_M || ln->DimensionModel == GAIA_XY_Z_M) m = mm[i]; else m = 0.0; if (dst_ln->DimensionModel == GAIA_XY_Z) { gaiaSetPointXYZ (dst_ln->Coords, i, x, y, z); } else if (dst_ln->DimensionModel == GAIA_XY_M) { gaiaSetPointXYM (dst_ln->Coords, i, x, y, m); } else if (dst_ln->DimensionModel == GAIA_XY_Z_M) { gaiaSetPointXYZM (dst_ln->Coords, i, x, y, z, m); } else { gaiaSetPoint (dst_ln->Coords, i, x, y); } } } else error = 1; free (xx); free (yy); free (zz); if (ln->DimensionModel == GAIA_XY_M || ln->DimensionModel == GAIA_XY_Z_M) free (mm); if (error) goto stop; ln = ln->Next; } pg = org->FirstPolygon; while (pg) { /* reprojecting POLYGONs */ rng = pg->Exterior; cnt = rng->Points; dst_pg = gaiaAddPolygonToGeomColl (dst, cnt, pg->NumInteriors); xx = malloc (sizeof (double) * cnt); yy = malloc (sizeof (double) * cnt); zz = malloc (sizeof (double) * cnt); if (rng->DimensionModel == GAIA_XY_M || rng->DimensionModel == GAIA_XY_Z_M) mm = malloc (sizeof (double) * cnt); for (i = 0; i < cnt; i++) { /* inserting points to be converted in temporary arrays [EXTERIOR RING] */ if (rng->DimensionModel == GAIA_XY_Z) { gaiaGetPointXYZ (rng->Coords, i, &x, &y, &z); } else if (rng->DimensionModel == GAIA_XY_M) { gaiaGetPointXYM (rng->Coords, i, &x, &y, &m); } else if (rng->DimensionModel == GAIA_XY_Z_M) { gaiaGetPointXYZM (rng->Coords, i, &x, &y, &z, &m); } else { gaiaGetPoint (rng->Coords, i, &x, &y); } if (from_angle) { xx[i] = gaiaDegsToRads (x); yy[i] = gaiaDegsToRads (y); } else { xx[i] = x; yy[i] = y; } if (rng->DimensionModel == GAIA_XY_Z || rng->DimensionModel == GAIA_XY_Z_M) zz[i] = z; else zz[i] = 0.0; if (rng->DimensionModel == GAIA_XY_M || rng->DimensionModel == GAIA_XY_Z_M) mm[i] = m; } /* applying reprojection */ if (pj_transform (from_cs, to_cs, cnt, 0, xx, yy, zz) == 0) { /* inserting the reprojected POLYGON in the new GEOMETRY */ dst_rng = dst_pg->Exterior; for (i = 0; i < cnt; i++) { /* setting EXTERIOR RING points */ if (to_angle) { x = gaiaRadsToDegs (xx[i]); y = gaiaRadsToDegs (yy[i]); } else { x = xx[i]; y = yy[i]; } if (rng->DimensionModel == GAIA_XY_Z || rng->DimensionModel == GAIA_XY_Z_M) z = zz[i]; else z = 0.0; if (rng->DimensionModel == GAIA_XY_M || rng->DimensionModel == GAIA_XY_Z_M) m = mm[i]; else m = 0.0; if (dst_rng->DimensionModel == GAIA_XY_Z) { gaiaSetPointXYZ (dst_rng->Coords, i, x, y, z); } else if (dst_rng->DimensionModel == GAIA_XY_M) { gaiaSetPointXYM (dst_rng->Coords, i, x, y, m); } else if (dst_rng->DimensionModel == GAIA_XY_Z_M) { gaiaSetPointXYZM (dst_rng->Coords, i, x, y, z, m); } else { gaiaSetPoint (dst_rng->Coords, i, x, y); } } } else error = 1; free (xx); free (yy); free (zz); if (rng->DimensionModel == GAIA_XY_M || rng->DimensionModel == GAIA_XY_Z_M) free (mm); if (error) goto stop; for (ib = 0; ib < pg->NumInteriors; ib++) { /* processing INTERIOR RINGS */ rng = pg->Interiors + ib; cnt = rng->Points; xx = malloc (sizeof (double) * cnt); yy = malloc (sizeof (double) * cnt); zz = malloc (sizeof (double) * cnt); if (rng->DimensionModel == GAIA_XY_M || rng->DimensionModel == GAIA_XY_Z_M) mm = malloc (sizeof (double) * cnt); for (i = 0; i < cnt; i++) { /* inserting points to be converted in temporary arrays [INTERIOR RING] */ if (rng->DimensionModel == GAIA_XY_Z) { gaiaGetPointXYZ (rng->Coords, i, &x, &y, &z); } else if (rng->DimensionModel == GAIA_XY_M) { gaiaGetPointXYM (rng->Coords, i, &x, &y, &m); } else if (rng->DimensionModel == GAIA_XY_Z_M) { gaiaGetPointXYZM (rng->Coords, i, &x, &y, &z, &m); } else { gaiaGetPoint (rng->Coords, i, &x, &y); } if (from_angle) { xx[i] = gaiaDegsToRads (x); yy[i] = gaiaDegsToRads (y); } else { xx[i] = x; yy[i] = y; } if (rng->DimensionModel == GAIA_XY_Z || rng->DimensionModel == GAIA_XY_Z_M) zz[i] = z; else zz[i] = 0.0; if (rng->DimensionModel == GAIA_XY_M || rng->DimensionModel == GAIA_XY_Z_M) mm[i] = m; } /* applying reprojection */ if (pj_transform (from_cs, to_cs, cnt, 0, xx, yy, zz) == 0) { /* inserting the reprojected POLYGON in the new GEOMETRY */ dst_rng = gaiaAddInteriorRing (dst_pg, ib, cnt); for (i = 0; i < cnt; i++) { /* setting INTERIOR RING points */ if (to_angle) { x = gaiaRadsToDegs (xx[i]); y = gaiaRadsToDegs (yy[i]); } else { x = xx[i]; y = yy[i]; } if (rng->DimensionModel == GAIA_XY_Z || rng->DimensionModel == GAIA_XY_Z_M) z = zz[i]; else z = 0.0; if (rng->DimensionModel == GAIA_XY_M || rng->DimensionModel == GAIA_XY_Z_M) m = mm[i]; else m = 0.0; if (dst_rng->DimensionModel == GAIA_XY_Z) { gaiaSetPointXYZ (dst_rng->Coords, i, x, y, z); } else if (dst_rng->DimensionModel == GAIA_XY_M) { gaiaSetPointXYM (dst_rng->Coords, i, x, y, m); } else if (dst_rng->DimensionModel == GAIA_XY_Z_M) { gaiaSetPointXYZM (dst_rng->Coords, i, x, y, z, m); } else { gaiaSetPoint (dst_rng->Coords, i, x, y); } } } else error = 1; free (xx); free (yy); free (zz); if (rng->DimensionModel == GAIA_XY_M || rng->DimensionModel == GAIA_XY_Z_M) free (mm); if (error) goto stop; } pg = pg->Next; } /* destroying the PROJ4 params */ stop: pj_free (from_cs); pj_free (to_cs); if (error) { /* some error occurred */ gaiaPointPtr pP; gaiaPointPtr pPn; gaiaLinestringPtr pL; gaiaLinestringPtr pLn; gaiaPolygonPtr pA; gaiaPolygonPtr pAn; pP = dst->FirstPoint; while (pP != NULL) { pPn = pP->Next; gaiaFreePoint (pP); pP = pPn; } pL = dst->FirstLinestring; while (pL != NULL) { pLn = pL->Next; gaiaFreeLinestring (pL); pL = pLn; } pA = dst->FirstPolygon; while (pA != NULL) { pAn = pA->Next; gaiaFreePolygon (pA); pA = pAn; } dst->FirstPoint = NULL; dst->LastPoint = NULL; dst->FirstLinestring = NULL; dst->LastLinestring = NULL; dst->FirstPolygon = NULL; dst->LastPolygon = NULL; } if (dst) { gaiaMbrGeometry (dst); dst->DeclaredType = org->DeclaredType; } return dst; }
GAIAGEO_DECLARE gaiaGeomCollPtr gaiaMakeEllipse (double cx, double cy, double x_axis, double y_axis, double step) { /* return a Linestring approximating an Ellipse */ gaiaDynamicLinePtr dyn; double x; double y; double angle = 0.0; int points = 0; gaiaPointPtr pt; gaiaGeomCollPtr geom; gaiaLinestringPtr ln; int iv = 0; if (step < 0.0) step *= -1.0; if (step == 0.0) step = 10.0; if (step < 0.1) step = 0.1; if (step > 45.0) step = 45.0; if (x_axis < 0.0) x_axis *= -1.0; if (y_axis < 0.0) y_axis *= -1.0; dyn = gaiaAllocDynamicLine (); while (angle < 360.0) { double rads = angle * .0174532925199432958; x = cx + (x_axis * cos (rads)); y = cy + (y_axis * sin (rads)); gaiaAppendPointToDynamicLine (dyn, x, y); angle += step; } /* closing the ellipse */ gaiaAppendPointToDynamicLine (dyn, dyn->First->X, dyn->First->Y); pt = dyn->First; while (pt) { /* counting how many points */ points++; pt = pt->Next; } if (points == 0) { gaiaFreeDynamicLine (dyn); return NULL; } geom = gaiaAllocGeomColl (); ln = gaiaAddLinestringToGeomColl (geom, points); pt = dyn->First; while (pt) { /* setting Vertices */ gaiaSetPoint (ln->Coords, iv, pt->X, pt->Y); iv++; pt = pt->Next; } gaiaFreeDynamicLine (dyn); return geom; }
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; }
GAIAGEO_DECLARE gaiaGeomCollPtr gaiaMakeEllipticArc (double cx, double cy, double x_axis, double y_axis, double start, double stop, double step) { /* return a Linestring approximating an Elliptic Arc */ gaiaDynamicLinePtr dyn; double x; double y; double angle; double rads; int points = 0; gaiaPointPtr pt; gaiaGeomCollPtr geom; gaiaLinestringPtr ln; int iv = 0; if (step < 0.0) step *= -1.0; if (step == 0.0) step = 10.0; if (step < 0.1) step = 0.1; if (step > 45.0) step = 45.0; if (x_axis < 0.0) x_axis *= -1.0; if (y_axis < 0.0) y_axis *= -1.0; /* normalizing Start/Stop angles */ while (start >= 360.0) start -= 360.0; while (start <= -720.0) start += 360; while (stop >= 360.0) stop -= 360.0; while (stop <= -720.0) stop += 360; if (start < 0.0) start = 360.0 + start; if (stop < 0.0) stop = 360.0 + stop; if (start > stop) stop += 360.0; dyn = gaiaAllocDynamicLine (); angle = start; while (angle < stop) { rads = angle * .0174532925199432958; x = cx + (x_axis * cos (rads)); y = cy + (y_axis * sin (rads)); gaiaAppendPointToDynamicLine (dyn, x, y); angle += step; } /* closing the arc */ rads = stop * .0174532925199432958; x = cx + (x_axis * cos (rads)); y = cy + (y_axis * sin (rads)); if (x != dyn->Last->X || y != dyn->Last->Y) gaiaAppendPointToDynamicLine (dyn, x, y); pt = dyn->First; while (pt) { /* counting how many points */ points++; pt = pt->Next; } if (points == 0) { gaiaFreeDynamicLine (dyn); return NULL; } geom = gaiaAllocGeomColl (); ln = gaiaAddLinestringToGeomColl (geom, points); pt = dyn->First; while (pt) { /* setting Vertices */ gaiaSetPoint (ln->Coords, iv, pt->X, pt->Y); iv++; pt = pt->Next; } gaiaFreeDynamicLine (dyn); return geom; }
GAIAGEO_DECLARE gaiaGeomCollPtr gaiaExtractPolygonsFromGeomColl (gaiaGeomCollPtr geom) { /* extracts any POLYGON from a GeometryCollection */ gaiaGeomCollPtr result; gaiaPolygonPtr pg; gaiaPolygonPtr new_pg; gaiaRingPtr rng; gaiaRingPtr new_rng; int pgs = 0; int iv; int ib; double x; double y; double z; double m; if (!geom) return NULL; pg = geom->FirstPolygon; while (pg) { pgs++; pg = pg->Next; } if (!pgs) return NULL; if (geom->DimensionModel == GAIA_XY_Z_M) result = gaiaAllocGeomCollXYZM (); else if (geom->DimensionModel == GAIA_XY_Z) result = gaiaAllocGeomCollXYZ (); else if (geom->DimensionModel == GAIA_XY_M) result = gaiaAllocGeomCollXYM (); else result = gaiaAllocGeomColl (); pg = geom->FirstPolygon; while (pg) { rng = pg->Exterior; new_pg = gaiaAddPolygonToGeomColl (result, rng->Points, pg->NumInteriors); new_rng = new_pg->Exterior; for (iv = 0; iv < rng->Points; iv++) { if (rng->DimensionModel == GAIA_XY_Z_M) { gaiaGetPointXYZM (rng->Coords, iv, &x, &y, &z, &m); gaiaSetPointXYZM (new_rng->Coords, iv, x, y, z, m); } else if (rng->DimensionModel == GAIA_XY_Z) { gaiaGetPointXYZ (rng->Coords, iv, &x, &y, &z); gaiaSetPointXYZ (new_rng->Coords, iv, x, y, z); } else if (rng->DimensionModel == GAIA_XY_M) { gaiaGetPointXYM (rng->Coords, iv, &x, &y, &m); gaiaSetPointXYM (new_rng->Coords, iv, x, y, m); } else { gaiaGetPoint (rng->Coords, iv, &x, &y); gaiaSetPoint (new_rng->Coords, iv, x, y); } } for (ib = 0; ib < pg->NumInteriors; ib++) { rng = pg->Interiors + ib; new_rng = gaiaAddInteriorRing (new_pg, ib, rng->Points); for (iv = 0; iv < rng->Points; iv++) { if (rng->DimensionModel == GAIA_XY_Z_M) { gaiaGetPointXYZM (rng->Coords, iv, &x, &y, &z, &m); gaiaSetPointXYZM (new_rng->Coords, iv, x, y, z, m); } else if (rng->DimensionModel == GAIA_XY_Z) { gaiaGetPointXYZ (rng->Coords, iv, &x, &y, &z); gaiaSetPointXYZ (new_rng->Coords, iv, x, y, z); } else if (rng->DimensionModel == GAIA_XY_M) { gaiaGetPointXYM (rng->Coords, iv, &x, &y, &m); gaiaSetPointXYM (new_rng->Coords, iv, x, y, m); } else { gaiaGetPoint (rng->Coords, iv, &x, &y); gaiaSetPoint (new_rng->Coords, iv, x, y); } } } pg = pg->Next; } result->Srid = geom->Srid; result->DeclaredType = GAIA_MULTIPOLYGON; return result; }
GAIAGEO_DECLARE gaiaGeomCollPtr gaiaExtractLinestringsFromGeomColl (gaiaGeomCollPtr geom) { /* extracts any LINESTRING from a GeometryCollection */ gaiaGeomCollPtr result; gaiaLinestringPtr ln; gaiaLinestringPtr new_ln; int lns = 0; int iv; double x; double y; double z; double m; if (!geom) return NULL; ln = geom->FirstLinestring; while (ln) { lns++; ln = ln->Next; } if (!lns) return NULL; if (geom->DimensionModel == GAIA_XY_Z_M) result = gaiaAllocGeomCollXYZM (); else if (geom->DimensionModel == GAIA_XY_Z) result = gaiaAllocGeomCollXYZ (); else if (geom->DimensionModel == GAIA_XY_M) result = gaiaAllocGeomCollXYM (); else result = gaiaAllocGeomColl (); ln = geom->FirstLinestring; while (ln) { new_ln = gaiaAddLinestringToGeomColl (result, ln->Points); for (iv = 0; iv < ln->Points; iv++) { if (ln->DimensionModel == GAIA_XY_Z_M) { gaiaGetPointXYZM (ln->Coords, iv, &x, &y, &z, &m); gaiaSetPointXYZM (new_ln->Coords, iv, x, y, z, m); } else if (ln->DimensionModel == GAIA_XY_Z) { gaiaGetPointXYZ (ln->Coords, iv, &x, &y, &z); gaiaSetPointXYZ (new_ln->Coords, iv, x, y, z); } else if (ln->DimensionModel == GAIA_XY_M) { gaiaGetPointXYM (ln->Coords, iv, &x, &y, &m); gaiaSetPointXYM (new_ln->Coords, iv, x, y, m); } else { gaiaGetPoint (ln->Coords, iv, &x, &y); gaiaSetPoint (new_ln->Coords, iv, x, y); } } ln = ln->Next; } result->Srid = geom->Srid; result->DeclaredType = GAIA_MULTILINESTRING; return result; }
static void polygon_set_up (struct gml_params *params) { /* setting up the latest Polygon (if any) */ int iv; int ib; int interiors; struct gml_rings_list *rg; gaiaDynamicLinePtr dyn_line; gaiaPointPtr pt; gaiaPolygonPtr pg; gaiaRingPtr ring; if (params->polygon.exterior == NULL) return; if (params->geometry == NULL) params->geometry = gaiaAllocGeomColl (); /* preliminary recognition */ dyn_line = params->polygon.exterior; iv = 0; pt = dyn_line->First; while (pt) { /* counting how many POINTs are into the Exterior Ring */ iv++; pt = pt->Next; } interiors = 0; rg = params->polygon.first; while (rg) { /* counting how many Interior Rings are there */ interiors++; rg = rg->next; } pg = gaiaAddPolygonToGeomColl (params->geometry, iv, interiors); /* setting up the Exterior Ring */ ring = pg->Exterior; iv = 0; dyn_line = params->polygon.exterior; pt = dyn_line->First; while (pt) { /* inserting any POINT into the Exterior Ring */ gaiaSetPoint (ring->Coords, iv, pt->X, pt->Y); iv++; pt = pt->Next; } ib = 0; rg = params->polygon.first; while (rg) { /* setting up any Interior Ring */ dyn_line = params->polygon.exterior; iv = 0; pt = dyn_line->First; while (pt) { /* counting how many POINTs are into the Interior Ring */ iv++; pt = pt->Next; } ring = gaiaAddInteriorRing (pg, ib, iv); iv = 0; pt = dyn_line->First; while (pt) { /* inserting any POINT into the Interior Ring */ gaiaSetPoint (ring->Coords, iv, pt->X, pt->Y); iv++; pt = pt->Next; } rg = rg->next; ib++; } }
int main (int argc, char *argv[]) { int ret; sqlite3 *handle; sqlite3_stmt *stmt; char sql[256]; char *err_msg = NULL; double x; double y; int pk; int ix; int iy; gaiaGeomCollPtr geo = NULL; unsigned char *blob; int blob_size; int i; char **results; int n_rows; int n_columns; char *count; clock_t t0; clock_t t1; void *cache; if (argc != 2) { fprintf (stderr, "usage: %s test_db_path\n", argv[0]); return -1; } /* trying to connect the test DB: - this demo is intended to create a new, empty database */ ret = sqlite3_open_v2 (argv[1], &handle, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL); if (ret != SQLITE_OK) { printf ("cannot open '%s': %s\n", argv[1], sqlite3_errmsg (handle)); sqlite3_close (handle); return -1; } cache = spatialite_alloc_connection (); spatialite_init_ex (handle, cache, 0); /* showing the SQLite version */ printf ("SQLite version: %s\n", sqlite3_libversion ()); /* showing the SpatiaLite version */ printf ("SpatiaLite version: %s\n", spatialite_version ()); printf ("\n\n"); /* we are supposing this one is an empty database, so we have to create the Spatial Metadata */ strcpy (sql, "SELECT InitSpatialMetadata(1)"); ret = sqlite3_exec (handle, sql, NULL, NULL, &err_msg); if (ret != SQLITE_OK) { /* an error occurred */ printf ("InitSpatialMetadata() error: %s\n", err_msg); sqlite3_free (err_msg); goto abort; } /* now we can create the test table for simplicity we'll define only one column, the primary key */ strcpy (sql, "CREATE TABLE test ("); strcat (sql, "PK INTEGER NOT NULL PRIMARY KEY)"); ret = sqlite3_exec (handle, sql, NULL, NULL, &err_msg); if (ret != SQLITE_OK) { /* an error occurred */ printf ("CREATE TABLE 'test' error: %s\n", err_msg); sqlite3_free (err_msg); goto abort; } /* ... we'll add a Geometry column of POINT type to the test table */ strcpy (sql, "SELECT AddGeometryColumn('test', 'geom', 3003, 'POINT', 2)"); ret = sqlite3_exec (handle, sql, NULL, NULL, &err_msg); if (ret != SQLITE_OK) { /* an error occurred */ printf ("AddGeometryColumn() error: %s\n", err_msg); sqlite3_free (err_msg); goto abort; } /* and finally we'll enable this geo-column to have a Spatial Index based on R*Tree */ strcpy (sql, "SELECT CreateSpatialIndex('test', 'geom')"); ret = sqlite3_exec (handle, sql, NULL, NULL, &err_msg); if (ret != SQLITE_OK) { /* an error occurred */ printf ("CreateSpatialIndex() error: %s\n", err_msg); sqlite3_free (err_msg); goto abort; } printf ("\nnow we are going to insert 1 million POINTs; wait, please ...\n\n"); t0 = clock (); /* beginning a transaction *** this step is absolutely critical *** the SQLite engine is a TRANSACTIONAL one the whole batch of INSERTs has to be performed as an unique transaction, otherwise performance will be surely very poor */ strcpy (sql, "BEGIN"); ret = sqlite3_exec (handle, sql, NULL, NULL, &err_msg); if (ret != SQLITE_OK) { /* an error occurred */ printf ("BEGIN error: %s\n", err_msg); sqlite3_free (err_msg); goto abort; } /* preparing to populate the test table we'll use a Prepared Statement we can reuse in order to insert each row */ strcpy (sql, "INSERT INTO test (pk, geom) VALUES (?, ?)"); ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &stmt, NULL); if (ret != SQLITE_OK) { /* an error occurred */ printf ("INSERT SQL error: %s\n", sqlite3_errmsg (handle)); goto abort; } pk = 0; for (ix = 0; ix < 1000; ix++) { x = 1000000.0 + (ix * 10.0); for (iy = 0; iy < 1000; iy++) { /* this double loop will insert 1 million rows into the the test table */ y = 4000000.0 + (iy * 10.0); pk++; if ((pk % 25000) == 0) { t1 = clock (); printf ("insert row: %d\t\t[elapsed time: %1.3f]\n", pk, (double) (t1 - t0) / CLOCKS_PER_SEC); } /* preparing the geometry to insert */ geo = gaiaAllocGeomColl (); geo->Srid = 3003; gaiaAddPointToGeomColl (geo, x, y); /* transforming this geometry into the SpatiaLite BLOB format */ gaiaToSpatiaLiteBlobWkb (geo, &blob, &blob_size); /* we can now destroy the geometry object */ gaiaFreeGeomColl (geo); /* resetting Prepared Statement and bindings */ sqlite3_reset (stmt); sqlite3_clear_bindings (stmt); /* binding parameters to Prepared Statement */ sqlite3_bind_int64 (stmt, 1, pk); sqlite3_bind_blob (stmt, 2, blob, blob_size, free); /* performing actual row insert */ ret = sqlite3_step (stmt); if (ret == SQLITE_DONE || ret == SQLITE_ROW) ; else { /* an unexpected error occurred */ printf ("sqlite3_step() error: %s\n", sqlite3_errmsg (handle)); sqlite3_finalize (stmt); goto abort; } } } /* we have now to finalize the query [memory cleanup] */ sqlite3_finalize (stmt); /* committing the transaction *** this step is absolutely critical *** if we don't confirm the still pending transaction, any update will be lost */ strcpy (sql, "COMMIT"); ret = sqlite3_exec (handle, sql, NULL, NULL, &err_msg); if (ret != SQLITE_OK) { /* an error occurred */ printf ("COMMIT error: %s\n", err_msg); sqlite3_free (err_msg); goto abort; } /* now we'll optimize the table */ strcpy (sql, "ANALYZE test"); ret = sqlite3_exec (handle, sql, NULL, NULL, &err_msg); if (ret != SQLITE_OK) { /* an error occurred */ printf ("ANALYZE error: %s\n", err_msg); sqlite3_free (err_msg); goto abort; } for (ix = 0; ix < 3; ix++) { printf ("\nperforming test#%d - not using Spatial Index\n", ix); /* now we'll perform the spatial query WITHOUT using the Spatial Index we'll loop 3 times in order to avoid buffering-caching side effects */ strcpy (sql, "SELECT Count(*) FROM test "); strcat (sql, "WHERE MbrWithin(geom, BuildMbr("); strcat (sql, "1000400.5, 4000400.5, "); strcat (sql, "1000450.5, 4000450.5))"); t0 = clock (); ret = sqlite3_get_table (handle, sql, &results, &n_rows, &n_columns, &err_msg); if (ret != SQLITE_OK) { /* an error occurred */ printf ("NoSpatialIndex SQL error: %s\n", err_msg); sqlite3_free (err_msg); goto abort; } count = ""; for (i = 1; i <= n_rows; i++) { count = results[(i * n_columns) + 0]; } t1 = clock (); printf ("Count(*) = %d\t\t[elapsed time: %1.4f]\n", atoi (count), (double) (t1 - t0) / CLOCKS_PER_SEC); /* we can now free the table results */ sqlite3_free_table (results); } for (ix = 0; ix < 3; ix++) { printf ("\nperforming test#%d - using the R*Tree Spatial Index\n", ix); /* now we'll perform the spatial query USING the R*Tree Spatial Index we'll loop 3 times in order to avoid buffering-caching side effects */ strcpy (sql, "SELECT Count(*) FROM test "); strcat (sql, "WHERE MbrWithin(geom, BuildMbr("); strcat (sql, "1000400.5, 4000400.5, "); strcat (sql, "1000450.5, 4000450.5)) AND ROWID IN ("); strcat (sql, "SELECT pkid FROM idx_test_geom WHERE "); strcat (sql, "xmin > 1000400.5 AND "); strcat (sql, "xmax < 1000450.5 AND "); strcat (sql, "ymin > 4000400.5 AND "); strcat (sql, "ymax < 4000450.5)"); /* YES, this query is a very unhappy one the idea is simply to simulate exactly the same conditions as above */ t0 = clock (); ret = sqlite3_get_table (handle, sql, &results, &n_rows, &n_columns, &err_msg); if (ret != SQLITE_OK) { /* an error occurred */ printf ("SpatialIndex SQL error: %s\n", err_msg); sqlite3_free (err_msg); goto abort; } count = ""; for (i = 1; i <= n_rows; i++) { count = results[(i * n_columns) + 0]; } t1 = clock (); printf ("Count(*) = %d\t\t[elapsed time: %1.4f]\n", atoi (count), (double) (t1 - t0) / CLOCKS_PER_SEC); /* we can now free the table results */ sqlite3_free_table (results); } /* disconnecting the test DB */ ret = sqlite3_close (handle); if (ret != SQLITE_OK) { printf ("close() error: %s\n", sqlite3_errmsg (handle)); return -1; } spatialite_cleanup_ex (cache); printf ("\n\nsample successfully terminated\n"); return 0; abort: sqlite3_close (handle); spatialite_cleanup_ex (cache); spatialite_shutdown(); return -1; }
static int kml_parse_polygon (struct kml_data *p_data, gaiaGeomCollPtr geom, kmlNodePtr node, kmlNodePtr * next_n) { /* parsing a <Polygon> */ int interior; int has_z; int inners; int outers; int points; int iv; int ib = 0; gaiaGeomCollPtr pg; gaiaGeomCollPtr last_g; gaiaPolygonPtr new_pg; gaiaRingPtr ring; gaiaDynamicLinePtr dyn; gaiaPointPtr pt; gaiaDynamicLinePtr exterior_ring; kmlNodePtr next; kmlDynamicRingPtr dyn_rng; kmlDynamicPolygonPtr dyn_pg = kml_alloc_dyn_polygon (p_data); kmlNodePtr n = node; while (n) { /* looping on rings */ if (strcmp (n->Tag, "Polygon") == 0) { *next_n = n->Next; break; } dyn = kml_parse_ring (n, &interior, &has_z, &next); if (dyn == NULL) goto error; if (kml_count_dyn_points (dyn) < 4) { /* cannot be a valid ring */ goto error; } /* checking if the ring is closed */ if (has_z) { if (dyn->First->X == dyn->Last->X && dyn->First->Y == dyn->Last->Y && dyn->First->Z == dyn->Last->Z) ; else goto error; } else { if (dyn->First->X == dyn->Last->X && dyn->First->Y == dyn->Last->Y) ; else goto error; } kml_add_polygon_ring (dyn_pg, dyn, interior, has_z); n = next; } /* ok, KML nodes match as expected */ inners = 0; outers = 0; has_z = 1; dyn_rng = dyn_pg->first; while (dyn_rng) { /* verifying the rings collection */ if (dyn_rng->has_z == 0) has_z = 0; if (dyn_rng->interior) inners++; else { outers++; points = kml_count_dyn_points (dyn_rng->ring); exterior_ring = dyn_rng->ring; } dyn_rng = dyn_rng->next; } if (outers != 1) /* no exterior ring declared */ goto error; if (has_z) { pg = gaiaAllocGeomCollXYZ (); kmlMapDynAlloc (p_data, KML_DYN_GEOM, pg); new_pg = gaiaAddPolygonToGeomColl (pg, points, inners); /* initializing the EXTERIOR RING */ ring = new_pg->Exterior; pt = exterior_ring->First; iv = 0; while (pt) { gaiaSetPointXYZ (ring->Coords, iv, pt->X, pt->Y, pt->Z); iv++; pt = pt->Next; } dyn_rng = dyn_pg->first; while (dyn_rng) { /* initializing any INTERIOR RING */ if (dyn_rng->interior == 0) { dyn_rng = dyn_rng->next; continue; } points = kml_count_dyn_points (dyn_rng->ring); ring = gaiaAddInteriorRing (new_pg, ib, points); ib++; pt = dyn_rng->ring->First; iv = 0; while (pt) { gaiaSetPointXYZ (ring->Coords, iv, pt->X, pt->Y, pt->Z); iv++; pt = pt->Next; } dyn_rng = dyn_rng->next; } } else { pg = gaiaAllocGeomColl (); kmlMapDynAlloc (p_data, KML_DYN_GEOM, pg); new_pg = gaiaAddPolygonToGeomColl (pg, points, inners); /* initializing the EXTERIOR RING */ ring = new_pg->Exterior; pt = exterior_ring->First; iv = 0; while (pt) { gaiaSetPoint (ring->Coords, iv, pt->X, pt->Y); iv++; pt = pt->Next; } dyn_rng = dyn_pg->first; while (dyn_rng) { /* initializing any INTERIOR RING */ if (dyn_rng->interior == 0) { dyn_rng = dyn_rng->next; continue; } points = kml_count_dyn_points (dyn_rng->ring); ring = gaiaAddInteriorRing (new_pg, ib, points); ib++; pt = dyn_rng->ring->First; iv = 0; while (pt) { gaiaSetPoint (ring->Coords, iv, pt->X, pt->Y); iv++; pt = pt->Next; } dyn_rng = dyn_rng->next; } } last_g = geom; while (1) { /* searching the last Geometry within chain */ if (last_g->Next == NULL) break; last_g = last_g->Next; } last_g->Next = pg; kml_free_dyn_polygon (dyn_pg); return 1; error: kml_free_dyn_polygon (dyn_pg); return 0; }
static int kml_parse_linestring (struct kml_data *p_data, gaiaGeomCollPtr geom, kmlNodePtr node, kmlNodePtr * next) { /* parsing a <LineString> */ gaiaGeomCollPtr ln; gaiaGeomCollPtr last; gaiaLinestringPtr new_ln; gaiaPointPtr pt; int iv; int has_z = 1; int points = 0; gaiaDynamicLinePtr dyn = gaiaAllocDynamicLine (); kmlMapDynAlloc (p_data, KML_DYN_DYNLINE, dyn); if (strcmp (node->Tag, "coordinates") == 0) { /* parsing a KML <LineString> */ if (!kml_parse_coordinates (node->Coordinates, dyn, &has_z)) goto error; node = node->Next; if (node == NULL) goto error; if (strcmp (node->Tag, "coordinates") == 0) ; else goto error; node = node->Next; if (node == NULL) goto error; if (strcmp (node->Tag, "LineString") == 0) ; else goto error; *next = node->Next; } /* ok, KML nodes match as expected */ points = kml_count_dyn_points (dyn); if (points < 2) goto error; if (has_z) { ln = gaiaAllocGeomCollXYZ (); kmlMapDynAlloc (p_data, KML_DYN_GEOM, ln); new_ln = gaiaAddLinestringToGeomColl (ln, points); pt = dyn->First; iv = 0; while (pt) { gaiaSetPointXYZ (new_ln->Coords, iv, pt->X, pt->Y, pt->Z); iv++; pt = pt->Next; } } else { ln = gaiaAllocGeomColl (); kmlMapDynAlloc (p_data, KML_DYN_GEOM, ln); new_ln = gaiaAddLinestringToGeomColl (ln, points); pt = dyn->First; iv = 0; while (pt) { gaiaSetPoint (new_ln->Coords, iv, pt->X, pt->Y); iv++; pt = pt->Next; } } last = geom; while (1) { /* searching the last Geometry within chain */ if (last->Next == NULL) break; last = last->Next; } last->Next = ln; gaiaFreeDynamicLine (dyn); return 1; error: gaiaFreeDynamicLine (dyn); return 0; }
GAIAGEO_DECLARE gaiaGeomCollPtr gaiaLinearize (gaiaGeomCollPtr geom, int force_multi) { /* attempts to rearrange a generic Geometry into a (multi)linestring */ int pts = 0; int lns = 0; gaiaGeomCollPtr result; gaiaPointPtr pt; gaiaLinestringPtr ln; gaiaLinestringPtr new_ln; gaiaPolygonPtr pg; gaiaRingPtr rng; int iv; int ib; double x; double y; double m; double z; if (!geom) return NULL; pt = geom->FirstPoint; while (pt) { pts++; pt = pt->Next; } ln = geom->FirstLinestring; while (ln) { lns++; ln = ln->Next; } if (pts || lns) return NULL; if (geom->DimensionModel == GAIA_XY_Z_M) result = gaiaAllocGeomCollXYZM (); else if (geom->DimensionModel == GAIA_XY_Z) result = gaiaAllocGeomCollXYZ (); else if (geom->DimensionModel == GAIA_XY_M) result = gaiaAllocGeomCollXYM (); else result = gaiaAllocGeomColl (); result->Srid = geom->Srid; if (force_multi) result->DeclaredType = GAIA_MULTILINESTRING; pg = geom->FirstPolygon; while (pg) { /* dissolving any POLYGON as simple LINESTRINGs (rings) */ rng = pg->Exterior; new_ln = gaiaAddLinestringToGeomColl (result, rng->Points); for (iv = 0; iv < rng->Points; iv++) { /* copying the EXTERIOR RING as LINESTRING */ if (geom->DimensionModel == GAIA_XY_Z_M) { gaiaGetPointXYZM (rng->Coords, iv, &x, &y, &z, &m); gaiaSetPointXYZM (new_ln->Coords, iv, x, y, z, m); } else if (geom->DimensionModel == GAIA_XY_Z) { gaiaGetPointXYZ (rng->Coords, iv, &x, &y, &z); gaiaSetPointXYZ (new_ln->Coords, iv, x, y, z); } else if (geom->DimensionModel == GAIA_XY_M) { gaiaGetPointXYM (rng->Coords, iv, &x, &y, &m); gaiaSetPointXYM (new_ln->Coords, iv, x, y, m); } else { gaiaGetPoint (rng->Coords, iv, &x, &y); gaiaSetPoint (new_ln->Coords, iv, x, y); } } for (ib = 0; ib < pg->NumInteriors; ib++) { rng = pg->Interiors + ib; new_ln = gaiaAddLinestringToGeomColl (result, rng->Points); for (iv = 0; iv < rng->Points; iv++) { /* copying an INTERIOR RING as LINESTRING */ if (geom->DimensionModel == GAIA_XY_Z_M) { gaiaGetPointXYZM (rng->Coords, iv, &x, &y, &z, &m); gaiaSetPointXYZM (new_ln->Coords, iv, x, y, z, m); } else if (geom->DimensionModel == GAIA_XY_Z) { gaiaGetPointXYZ (rng->Coords, iv, &x, &y, &z); gaiaSetPointXYZ (new_ln->Coords, iv, x, y, z); } else if (geom->DimensionModel == GAIA_XY_M) { gaiaGetPointXYM (rng->Coords, iv, &x, &y, &m); gaiaSetPointXYM (new_ln->Coords, iv, x, y, m); } else { gaiaGetPoint (rng->Coords, iv, &x, &y); gaiaSetPoint (new_ln->Coords, iv, x, y); } } } pg = pg->Next; } if (result->FirstLinestring == NULL) { gaiaFreeGeomColl (result); return NULL; } return result; }
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 gaiaDissolvePoints (gaiaGeomCollPtr geom) { /* attempts to dissolve a Geometry into points */ gaiaGeomCollPtr result; gaiaPointPtr pt; gaiaLinestringPtr ln; gaiaPolygonPtr pg; gaiaRingPtr rng; int iv; int ib; double x; double y; double z; double m; if (!geom) return NULL; if (geom->DimensionModel == GAIA_XY_Z_M) result = gaiaAllocGeomCollXYZM (); else if (geom->DimensionModel == GAIA_XY_Z) result = gaiaAllocGeomCollXYZ (); else if (geom->DimensionModel == GAIA_XY_M) result = gaiaAllocGeomCollXYM (); else result = gaiaAllocGeomColl (); pt = geom->FirstPoint; while (pt) { if (geom->DimensionModel == GAIA_XY_Z_M) gaiaAddPointToGeomCollXYZM (result, pt->X, pt->Y, pt->Z, pt->M); else if (geom->DimensionModel == GAIA_XY_Z) gaiaAddPointToGeomCollXYZ (result, pt->X, pt->Y, pt->Z); else if (geom->DimensionModel == GAIA_XY_M) gaiaAddPointToGeomCollXYM (result, pt->X, pt->Y, pt->M); else gaiaAddPointToGeomColl (result, pt->X, pt->Y); pt = pt->Next; } ln = geom->FirstLinestring; while (ln) { for (iv = 0; iv < ln->Points; iv++) { if (ln->DimensionModel == GAIA_XY_Z_M) { gaiaGetPointXYZM (ln->Coords, iv, &x, &y, &z, &m); } else if (ln->DimensionModel == GAIA_XY_Z) { gaiaGetPointXYZ (ln->Coords, iv, &x, &y, &z); } else if (ln->DimensionModel == GAIA_XY_M) { gaiaGetPointXYM (ln->Coords, iv, &x, &y, &m); } else { gaiaGetPoint (ln->Coords, iv, &x, &y); } if (geom->DimensionModel == GAIA_XY_Z_M) gaiaAddPointToGeomCollXYZM (result, x, y, z, m); else if (geom->DimensionModel == GAIA_XY_Z) gaiaAddPointToGeomCollXYZ (result, x, y, z); else if (geom->DimensionModel == GAIA_XY_M) gaiaAddPointToGeomCollXYM (result, x, y, m); else gaiaAddPointToGeomColl (result, x, y); } ln = ln->Next; } pg = geom->FirstPolygon; while (pg) { rng = pg->Exterior; for (iv = 0; iv < rng->Points; iv++) { /* exterior Ring */ if (rng->DimensionModel == GAIA_XY_Z_M) { gaiaGetPointXYZM (rng->Coords, iv, &x, &y, &z, &m); } else if (rng->DimensionModel == GAIA_XY_Z) { gaiaGetPointXYZ (rng->Coords, iv, &x, &y, &z); } else if (rng->DimensionModel == GAIA_XY_M) { gaiaGetPointXYM (rng->Coords, iv, &x, &y, &m); } else { gaiaGetPoint (rng->Coords, iv, &x, &y); } if (geom->DimensionModel == GAIA_XY_Z_M) gaiaAddPointToGeomCollXYZM (result, x, y, z, m); else if (geom->DimensionModel == GAIA_XY_Z) gaiaAddPointToGeomCollXYZ (result, x, y, z); else if (geom->DimensionModel == GAIA_XY_M) gaiaAddPointToGeomCollXYM (result, x, y, m); else gaiaAddPointToGeomColl (result, x, y); } for (ib = 0; ib < pg->NumInteriors; ib++) { rng = pg->Interiors + ib; for (iv = 0; iv < rng->Points; iv++) { /* interior Ring */ if (rng->DimensionModel == GAIA_XY_Z_M) { gaiaGetPointXYZM (rng->Coords, iv, &x, &y, &z, &m); } else if (rng->DimensionModel == GAIA_XY_Z) { gaiaGetPointXYZ (rng->Coords, iv, &x, &y, &z); } else if (rng->DimensionModel == GAIA_XY_M) { gaiaGetPointXYM (rng->Coords, iv, &x, &y, &m); } else { gaiaGetPoint (rng->Coords, iv, &x, &y); } if (geom->DimensionModel == GAIA_XY_Z_M) gaiaAddPointToGeomCollXYZM (result, x, y, z, m); else if (geom->DimensionModel == GAIA_XY_Z) gaiaAddPointToGeomCollXYZ (result, x, y, z); else if (geom->DimensionModel == GAIA_XY_M) gaiaAddPointToGeomCollXYM (result, x, y, m); else gaiaAddPointToGeomColl (result, x, y); } } pg = pg->Next; } result->Srid = geom->Srid; return result; }
static int kml_parse_point (struct kml_data *p_data, gaiaGeomCollPtr geom, kmlNodePtr node, kmlNodePtr * next) { /* parsing a <Point> */ double x; double y; double z; int has_z; gaiaGeomCollPtr pt; gaiaGeomCollPtr last; if (strcmp (node->Tag, "coordinates") == 0) { /* parsing a KML <Point> */ if (!kml_parse_point_v2 (node->Coordinates, &x, &y, &z, &has_z)) return 0; node = node->Next; if (node == NULL) return 0; if (strcmp (node->Tag, "coordinates") == 0) ; else return 0; node = node->Next; if (node == NULL) return 0; if (strcmp (node->Tag, "Point") == 0) ; else return 0; *next = node->Next; goto ok; } return 0; ok: /* ok, KML nodes match as expected */ if (has_z) { pt = gaiaAllocGeomCollXYZ (); kmlMapDynAlloc (p_data, KML_DYN_GEOM, pt); gaiaAddPointToGeomCollXYZ (pt, x, y, z); } else { pt = gaiaAllocGeomColl (); kmlMapDynAlloc (p_data, KML_DYN_GEOM, pt); gaiaAddPointToGeomColl (pt, x, y); } last = geom; while (1) { /* searching the last Geometry within chain */ if (last->Next == NULL) break; last = last->Next; } last->Next = pt; return 1; }
GAIAGEO_DECLARE gaiaGeomCollPtr gaiaTriangularGrid (gaiaGeomCollPtr geom, double origin_x, double origin_y, double size, int edges_only) { /* creating a regular grid [Triangular cells] */ double min_x; double min_y; double max_x; double max_y; double base_x; double base_y; double x1; double y1; double x2; double y2; double x3; double y3; double x4; double y4; int count = 0; int odd_even = 0; gaiaPolygonPtr pg; gaiaRingPtr rng; gaiaLinestringPtr ln; gaiaGeomCollPtr result = NULL; gaiaGeomCollPtr item = NULL; if (size <= 0.0) return NULL; result = gaiaAllocGeomColl (); result->Srid = geom->Srid; get_grid_bbox (geom, &min_x, &min_y, &max_x, &max_y); get_grid_base (min_x, min_y, origin_x, origin_y, size, &base_x, &base_y); while (base_y < max_y) { /* looping on grid rows */ if (odd_even) x1 = base_x - (size / 2.0); else x1 = base_x; y1 = base_y; x2 = x1 + size; y2 = y1; x3 = x1 + (size / 2.0); y3 = y1 + (size * sin (3.14159265358979323846 / 3.0)); x4 = x3 + size; y4 = y3; while (x1 < max_x) { /* looping on grid columns */ item = gaiaAllocGeomColl (); pg = gaiaAddPolygonToGeomColl (item, 4, 0); rng = pg->Exterior; gaiaSetPoint (rng->Coords, 0, x1, y1); gaiaSetPoint (rng->Coords, 1, x2, y2); gaiaSetPoint (rng->Coords, 2, x3, y3); gaiaSetPoint (rng->Coords, 3, x1, y1); gaiaMbrGeometry (item); if (gaiaGeomCollIntersects (geom, item) == 1) { /* ok, inserting a valid cell [pointing upside] */ count++; if (edges_only) { /* multilinestring */ ln = gaiaAddLinestringToGeomColl (result, 2); gaiaSetPoint (ln->Coords, 0, x1, y1); gaiaSetPoint (ln->Coords, 1, x2, y2); ln = gaiaAddLinestringToGeomColl (result, 2); gaiaSetPoint (ln->Coords, 0, x2, y2); gaiaSetPoint (ln->Coords, 1, x3, y3); ln = gaiaAddLinestringToGeomColl (result, 2); gaiaSetPoint (ln->Coords, 0, x3, y3); gaiaSetPoint (ln->Coords, 1, x1, y1); } else { /* polygon */ pg = gaiaAddPolygonToGeomColl (result, 4, 0); rng = pg->Exterior; gaiaSetPoint (rng->Coords, 0, x1, y1); gaiaSetPoint (rng->Coords, 1, x2, y2); gaiaSetPoint (rng->Coords, 2, x3, y3); gaiaSetPoint (rng->Coords, 3, x1, y1); } } gaiaFreeGeomColl (item); item = gaiaAllocGeomColl (); pg = gaiaAddPolygonToGeomColl (item, 4, 0); rng = pg->Exterior; gaiaSetPoint (rng->Coords, 0, x3, y3); gaiaSetPoint (rng->Coords, 1, x2, y2); gaiaSetPoint (rng->Coords, 2, x4, y4); gaiaSetPoint (rng->Coords, 3, x3, y3); gaiaMbrGeometry (item); if (gaiaGeomCollIntersects (geom, item) == 1) { /* ok, inserting a valid cell [pointing downside] */ count++; if (edges_only) { /* multilinestring */ ln = gaiaAddLinestringToGeomColl (result, 2); gaiaSetPoint (ln->Coords, 0, x1, y1); gaiaSetPoint (ln->Coords, 1, x2, y2); ln = gaiaAddLinestringToGeomColl (result, 2); gaiaSetPoint (ln->Coords, 0, x2, y2); gaiaSetPoint (ln->Coords, 1, x3, y3); ln = gaiaAddLinestringToGeomColl (result, 2); gaiaSetPoint (ln->Coords, 0, x3, y3); gaiaSetPoint (ln->Coords, 1, x1, y1); } else { /* polygon */ pg = gaiaAddPolygonToGeomColl (result, 4, 0); rng = pg->Exterior; gaiaSetPoint (rng->Coords, 0, x3, y3); gaiaSetPoint (rng->Coords, 1, x2, y2); gaiaSetPoint (rng->Coords, 2, x4, y4); gaiaSetPoint (rng->Coords, 3, x3, y3); } } gaiaFreeGeomColl (item); x1 += size; x2 += size; x3 += size; x4 += size; } base_y += (size * sin (3.14159265358979323846 / 3.0)); if (odd_even) odd_even = 0; else odd_even = 1; } /* final check */ if (!count) { /* empty grid */ gaiaFreeGeomColl (result); return NULL; } if (!edges_only) { result->DeclaredType = GAIA_MULTIPOLYGON; return result; } item = result; result = gaiaUnaryUnion (item); gaiaFreeGeomColl (item); result->Srid = geom->Srid; result->DeclaredType = GAIA_LINESTRING; return result; }