static void clean_geometry (struct gml_params *params) { /* cleaning up temporary Geometry struct */ if (params->geometry) gaiaFreeGeomColl (params->geometry); params->geometry = NULL; clean_polygon (params); }
static void kml_free_geom_chain (gaiaGeomCollPtr geom) { /* deleting a chain of preliminary geometries */ gaiaGeomCollPtr gn; while (geom) { gn = geom->Next; gaiaFreeGeomColl (geom); geom = gn; } }
static void free_table (VirtualBBoxPtr p_vt) { /* memory cleanup; freeing the virtual table struct */ int i; if (!p_vt) return; if (p_vt->table) sqlite3_free (p_vt->table); if (p_vt->Column) { for (i = 0; i < p_vt->nColumns; i++) { if (*(p_vt->Column + i)) sqlite3_free (*(p_vt->Column + i)); } sqlite3_free (p_vt->Column); } if (p_vt->Type) { for (i = 0; i < p_vt->nColumns; i++) { if (*(p_vt->Type + i)) sqlite3_free (*(p_vt->Type + i)); } sqlite3_free (p_vt->Type); } if (p_vt->Visible) sqlite3_free (p_vt->Visible); if (p_vt->Value) { for (i = 0; i < p_vt->nColumns; i++) { if (*(p_vt->Value + i)) value_free (*(p_vt->Value + i)); } sqlite3_free (p_vt->Value); } if (p_vt->MinX) sqlite3_free (p_vt->MinX); if (p_vt->MinY) sqlite3_free (p_vt->MinY); if (p_vt->MaxX) sqlite3_free (p_vt->MaxX); if (p_vt->MaxY) sqlite3_free (p_vt->MaxY); if (p_vt->ColSrid) sqlite3_free (p_vt->ColSrid); if (p_vt->BBoxGeom) gaiaFreeGeomColl (p_vt->BBoxGeom); sqlite3_free (p_vt); }
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 kmlCleanMapDynAlloc (struct kml_data *p_data, int clean_all) { /* cleaning the dynamic allocations map */ int i; struct kml_dyn_block *pn; struct kml_dyn_block *p = p_data->kml_first_dyn_block; while (p) { if (clean_all) { for (i = 0; i < KML_DYN_BLOCK; i++) { /* deleting Geometry objects */ switch (p->type[i]) { case KML_DYN_DYNLINE: gaiaFreeDynamicLine ((gaiaDynamicLinePtr) (p->ptr[i])); break; case KML_DYN_GEOM: gaiaFreeGeomColl ((gaiaGeomCollPtr) (p->ptr[i])); break; case KML_DYN_DYNPG: kml_free_dyn_polygon ((kmlDynamicPolygonPtr) (p->ptr[i])); break; case KML_DYN_NODE: kml_free_node ((kmlNodePtr) (p->ptr[i])); break; case KML_DYN_COORD: kml_free_coord ((kmlCoordPtr) (p->ptr[i])); break; case KML_DYN_ATTRIB: kml_free_attrib ((kmlAttrPtr) (p->ptr[i])); break; }; } } /* deleting the map block */ pn = p->next; free (p); p = pn; } }
static void geoJsonCleanMapDynAlloc (struct geoJson_data *p_data, int clean_all) { /* cleaning the dynamic allocations map */ int i; struct geoJson_dyn_block *pn; struct geoJson_dyn_block *p = p_data->geoJson_first_dyn_block; while (p) { if (clean_all) { for (i = 0; i < GEOJSON_DYN_BLOCK; i++) { /* deleting Geometry objects */ switch (p->type[i]) { case GEOJSON_DYN_POINT: gaiaFreePoint ((gaiaPointPtr) (p->ptr[i])); break; case GEOJSON_DYN_LINESTRING: gaiaFreeLinestring ((gaiaLinestringPtr) (p->ptr[i])); break; case GEOJSON_DYN_POLYGON: gaiaFreePolygon ((gaiaPolygonPtr) (p->ptr[i])); break; case GEOJSON_DYN_RING: gaiaFreeRing ((gaiaRingPtr) (p->ptr[i])); break; case GEOJSON_DYN_GEOMETRY: gaiaFreeGeomColl ((gaiaGeomCollPtr) (p->ptr[i])); break; }; } } /* deleting the map block */ pn = p->next; free (p); p = pn; } }
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; }
GAIAGEO_DECLARE int gaiaExportDxf (gaiaDxfWriterPtr dxf, sqlite3 * db_handle, const char *sql, const char *layer_col_name, const char *geom_col_name, const char *label_col_name, const char *text_height_col_name, const char *text_rotation_col_name, gaiaGeomCollPtr geom_filter) { /* exporting a complex DXF by executing an arbitrary SQL query */ sqlite3_stmt *stmt = NULL; int ret; int params; int first_row = 1; int layer_col = -1; int geom_col = -1; int label_col = -1; int text_height_col = -1; int text_rotation_col = -1; int i; unsigned char *p_blob; const unsigned char *blob; int len; const char *layer; const char *label = NULL; gaiaGeomCollPtr geom; gaiaDxfExportPtr aux = NULL; gaiaDxfExportLayerPtr lyr; if (dxf == NULL) return 0; if (dxf->error) return 0; if (dxf->out == NULL) return 0; if (db_handle == NULL) return 0; if (sql == NULL) return 0; if (layer_col_name == NULL) return 0; if (geom_col_name == NULL) return 0; /* attempting to create the SQL prepared statement */ ret = sqlite3_prepare_v2 (db_handle, sql, strlen (sql), &stmt, NULL); if (ret != SQLITE_OK) { spatialite_e ("exportDXF - CREATE STATEMENT error: %s\n", sqlite3_errmsg (db_handle)); goto stop; } params = sqlite3_bind_parameter_count (stmt); if (params > 0 && geom_filter != NULL) { /* parameter binding - Spatial Filter */ sqlite3_reset (stmt); sqlite3_clear_bindings (stmt); for (i = 1; i <= params; i++) { gaiaToSpatiaLiteBlobWkb (geom_filter, &p_blob, &len); ret = sqlite3_bind_blob (stmt, i, p_blob, len, free); if (ret != SQLITE_OK) { spatialite_e ("exportDXF - parameter BIND error: %s\n", sqlite3_errmsg (db_handle)); goto stop; } } } /* pass #1 - sniffing the result set */ while (1) { /* scrolling the result set rows */ ret = sqlite3_step (stmt); if (ret == SQLITE_DONE) break; /* end of result set */ if (ret == SQLITE_ROW) { if (first_row) { /* this one is the first row of the resultset */ for (i = 0; i < sqlite3_column_count (stmt); i++) { /* attempting to identify the resultset columns */ if (strcasecmp (layer_col_name, sqlite3_column_name (stmt, i)) == 0) layer_col = i; if (strcasecmp (geom_col_name, sqlite3_column_name (stmt, i)) == 0) geom_col = i; if (label_col_name != NULL) { if (strcasecmp (label_col_name, sqlite3_column_name (stmt, i)) == 0) label_col = i; } if (text_height_col_name != NULL) { if (strcasecmp (text_height_col_name, sqlite3_column_name (stmt, i)) == 0) text_height_col = i; } if (text_rotation_col_name != NULL) { if (strcasecmp (text_rotation_col_name, sqlite3_column_name (stmt, i)) == 0) text_rotation_col = i; } } if (layer_col < 0) { spatialite_e ("exportDXF - Layer Column not found into the resultset\n"); goto stop; } if (geom_col < 0) { spatialite_e ("exportDXF - Geometry Column not found into the resultset\n"); goto stop; } first_row = 0; aux = alloc_aux_exporter (); } layer = (const char *) sqlite3_column_text (stmt, layer_col); blob = sqlite3_column_blob (stmt, geom_col); len = sqlite3_column_bytes (stmt, geom_col); geom = gaiaFromSpatiaLiteBlobWkb (blob, len); if (geom) { update_aux_exporter (aux, layer, geom); gaiaFreeGeomColl (geom); } } } /* pass #2 - exporting the DXF file */ gaiaDxfWriteHeader (dxf, aux->minx, aux->miny, 0, aux->maxx, aux->maxy, 0); gaiaDxfWriteTables (dxf); lyr = aux->first; while (lyr != NULL) { gaiaDxfWriteLayer (dxf, lyr->layer_name); lyr = lyr->next; } gaiaDxfWriteEndSection (dxf); gaiaDxfWriteEntities (dxf); sqlite3_reset (stmt); while (1) { /* scrolling the result set rows */ int ival; double height = 10.0; double rotation = 0.0; ret = sqlite3_step (stmt); if (ret == SQLITE_DONE) break; /* end of result set */ if (ret == SQLITE_ROW) { layer = (const char *) sqlite3_column_text (stmt, layer_col); if (label_col >= 0) label = (const char *) sqlite3_column_text (stmt, label_col); if (text_height_col >= 0) { if (sqlite3_column_type (stmt, text_height_col) == SQLITE_INTEGER) { ival = sqlite3_column_int (stmt, text_height_col); height = ival; } if (sqlite3_column_type (stmt, text_height_col) == SQLITE_FLOAT) height = sqlite3_column_double (stmt, text_height_col); } if (text_rotation_col >= 0) { if (sqlite3_column_type (stmt, text_rotation_col) == SQLITE_INTEGER) { ival = sqlite3_column_int (stmt, text_rotation_col); rotation = ival; } if (sqlite3_column_type (stmt, text_height_col) == SQLITE_FLOAT) rotation = sqlite3_column_double (stmt, text_rotation_col); } blob = sqlite3_column_blob (stmt, geom_col); len = sqlite3_column_bytes (stmt, geom_col); geom = gaiaFromSpatiaLiteBlobWkb (blob, len); if (geom) { gaiaDxfWriteGeometry (dxf, layer, label, height, rotation, geom); gaiaFreeGeomColl (geom); } } } gaiaDxfWriteEndSection (dxf); gaiaDxfWriteFooter (dxf); sqlite3_finalize (stmt); if (aux != NULL) destroy_aux_exporter (aux); return dxf->count; stop: if (stmt != NULL) sqlite3_finalize (stmt); if (aux != NULL) destroy_aux_exporter (aux); return 0; }
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; }
int main (int argc, char *argv[]) { int ret; sqlite3 *handle; sqlite3_stmt *stmt; gaiaGeomCollPtr geom; char sql[256]; int i; int ic; char **results; int n_rows; int n_columns; char *err_msg = NULL; int len; char *table_name; char **p_geotables = NULL; int n_geotables = 0; int row_no; const void *blob; int blob_size; int geom_type; double measure; 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 was designed in order to connect the standard TEST-2.3.SQLITE sample DB - but you can try to use any SQLite/SpatiaLite DB at your will Please notice: we'll establish a READ ONLY connection */ ret = sqlite3_open_v2 (argv[1], &handle, SQLITE_OPEN_READONLY, NULL); if (ret != SQLITE_OK) { printf ("cannot open '%s': %s\n", argv[1], sqlite3_errmsg (handle)); sqlite3_close (handle); return -1; } /* VERY IMPORTANT: you must initialize the SpatiaLite extension [and related] BEFORE attempting to perform any other SQLite call ========================================================== Please note: starting since 4.1.0 this is completely canged: - a separate memory block (internal cache) is required by each single connection - allocating/freeing this block falls under the responsibility of the program handling the connection - in multithreaded programs a connection can never be share by different threads; the internal-cache block must be allocated by the same thread holding the connection */ 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"); /* SQL query #1 we'll retrieve GEOMETRY tables from Spatial Metadata we are assuming this query will return only few rows, so this time we'll use the sqlite3_get_table() interface this interface is very simple to use the result set is returned as a rectangular array [rows/columns] allocated in a temporary memory storage so, this interface is well suited for small sized result sets, but performs badly when accessing a large sized resul set as a side effect, each column value is returned as text, and isn't possible at all to retrieve true column types (INTEGER, FLOAT ...) */ strcpy (sql, "SELECT DISTINCT f_table_name FROM geometry_columns ORDER BY 1"); ret = sqlite3_get_table (handle, sql, &results, &n_rows, &n_columns, &err_msg); if (ret != SQLITE_OK) { /* some error occurred */ printf ("query#1 SQL error: %s\n", err_msg); sqlite3_free (err_msg); goto abort; } if (n_rows > 1) { /* first row always contains column names and is meaningless in this context */ n_geotables = n_rows; /* allocating a dynamic pointer array to store geotable names */ p_geotables = malloc (sizeof (char *) * n_geotables); for (i = 1; i <= n_rows; i++) { /* now we'll fetch one row at each time [and we have only one column to fetch] this one is is a simplified demo; but when writing a real application you always must check for NULL values !!!! */ table_name = results[(i * n_columns) + 0]; /* and we'll store each geotable name into the dynamic pointer array */ len = strlen (table_name); p_geotables[i - 1] = malloc (len + 1); strcpy (p_geotables[i - 1], table_name); } /* we can now free the table results */ sqlite3_free_table (results); } for (i = 0; i < n_geotables; i++) { /* now we'll scan each geotable we've found in Spatial Metadata */ printf ("========= table '%s' ========================\n", p_geotables[i]); /* SQL query #2 we'll retrieve any column from the current geotable we are assuming this query will return lots of rows, so we have to use sqlite3_prepare_v2() interface this interface is a more complex one, but is well suited in order to access huge sized result sets and true value type control is supported */ sprintf (sql, "SELECT * FROM %s", p_geotables[i]); ret = sqlite3_prepare_v2 (handle, sql, strlen (sql), &stmt, NULL); if (ret != SQLITE_OK) { /* some error occurred */ printf ("query#2 SQL error: %s\n", sqlite3_errmsg (handle)); goto abort; } /* the sqlite3_prepare_v2() call simply parses the SQL statement, checking for syntax validity, allocating internal structs etc but no result set row is really yet available */ /* we'll now save the #columns within the result set */ n_columns = sqlite3_column_count (stmt); row_no = 0; while (1) { /* this is an infinite loop, intended to fetch any row */ /* we are now trying to fetch the next available row */ ret = sqlite3_step (stmt); if (ret == SQLITE_DONE) { /* there are no more rows to fetch - we can stop looping */ break; } if (ret == SQLITE_ROW) { /* ok, we've just fetched a valid row to process */ row_no++; printf ("row #%d\n", row_no); for (ic = 0; ic < n_columns; ic++) { /* and now we'll fetch column values for each column we'll then get: - the column name - a column value, that can be of type: SQLITE_NULL, SQLITE_INTEGER, SQLITE_FLOAT, SQLITE_TEXT or SQLITE_BLOB, according to internal DB storage type */ printf ("\t%-10s = ", sqlite3_column_name (stmt, ic)); switch (sqlite3_column_type (stmt, ic)) { case SQLITE_NULL: printf ("NULL"); break; case SQLITE_INTEGER: printf ("%d", sqlite3_column_int (stmt, ic)); break; case SQLITE_FLOAT: printf ("%1.4f", sqlite3_column_double (stmt, ic)); break; case SQLITE_TEXT: printf ("'%s'", sqlite3_column_text (stmt, ic)); break; case SQLITE_BLOB: blob = sqlite3_column_blob (stmt, ic); blob_size = sqlite3_column_bytes (stmt, ic); /* checking if this BLOB actually is a GEOMETRY */ geom = gaiaFromSpatiaLiteBlobWkb (blob, blob_size); if (!geom) { /* for sure this one is not a GEOMETRY */ printf ("BLOB [%d bytes]", blob_size); } else { geom_type = gaiaGeometryType (geom); if (geom_type == GAIA_UNKNOWN) printf ("EMPTY or NULL GEOMETRY"); else { char *geom_name; if (geom_type == GAIA_POINT) geom_name = "POINT"; if (geom_type == GAIA_LINESTRING) geom_name = "LINESTRING"; if (geom_type == GAIA_POLYGON) geom_name = "POLYGON"; if (geom_type == GAIA_MULTIPOINT) geom_name = "MULTIPOINT"; if (geom_type == GAIA_MULTILINESTRING) geom_name = "MULTILINESTRING"; if (geom_type == GAIA_MULTIPOLYGON) geom_name = "MULTIPOLYGON"; if (geom_type == GAIA_GEOMETRYCOLLECTION) geom_name = "GEOMETRYCOLLECTION"; printf ("%s SRID=%d", geom_name, geom->Srid); if (geom_type == GAIA_LINESTRING || geom_type == GAIA_MULTILINESTRING) { #ifndef OMIT_GEOS /* GEOS is required */ gaiaGeomCollLength (geom, &measure); printf (" length=%1.2f", measure); #else printf (" length=?? [no GEOS support available]"); #endif /* GEOS enabled/disabled */ } if (geom_type == GAIA_POLYGON || geom_type == GAIA_MULTIPOLYGON) { #ifndef OMIT_GEOS /* GEOS is required */ gaiaGeomCollArea (geom, &measure); printf (" area=%1.2f", measure); #else printf ("area=?? [no GEOS support available]"); #endif /* GEOS enabled/disabled */ } } /* we have now to free the GEOMETRY */ gaiaFreeGeomColl (geom); } break; }; printf ("\n"); } if (row_no >= 5) { /* we'll exit the loop after the first 5 rows - this is only a demo :-) */ break; } } else { /* some 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); printf ("\n\n"); } /* disconnecting the test DB */ ret = sqlite3_close (handle); if (ret != SQLITE_OK) { printf ("close() error: %s\n", sqlite3_errmsg (handle)); return -1; } /* freeing the internal-cache memory block */ spatialite_cleanup_ex (cache); printf ("\n\nsample successfully terminated\n"); /* we have to free the dynamic pointer array used to store geotable names */ for (i = 0; i < n_geotables; i++) { /* freeing each tablename */ free (p_geotables[i]); } free (p_geotables); spatialite_shutdown(); return 0; abort: sqlite3_close (handle); /* freeing the internal-cache memory block */ spatialite_cleanup_ex (cache); if (p_geotables) { /* we have to free the dynamic pointer array used to store geotable names */ for (i = 0; i < n_geotables; i++) { /* freeing each tablename */ free (p_geotables[i]); } free (p_geotables); } spatialite_shutdown(); return -1; }
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 int vspidx_filter (sqlite3_vtab_cursor * pCursor, int idxNum, const char *idxStr, int argc, sqlite3_value ** argv) { /* setting up a cursor filter */ char *db_prefix = NULL; char *table_name = NULL; char *geom_column; char *xtable = NULL; char *xgeom = NULL; char *idx_name; char *idx_nameQ; char *sql_statement; gaiaGeomCollPtr geom = NULL; int ok_table = 0; int ok_geom = 0; const unsigned char *blob; int size; int exists; int ret; sqlite3_stmt *stmt; float minx; float miny; float maxx; float maxy; double tic; double tic2; VirtualSpatialIndexCursorPtr cursor = (VirtualSpatialIndexCursorPtr) pCursor; VirtualSpatialIndexPtr spidx = (VirtualSpatialIndexPtr) cursor->pVtab; if (idxStr) idxStr = idxStr; /* unused arg warning suppression */ cursor->eof = 1; if (idxNum == 1 && argc == 3) { /* retrieving the Table/Column/MBR params */ if (sqlite3_value_type (argv[0]) == SQLITE_TEXT) { char *tn = (char *) sqlite3_value_text (argv[0]); vspidx_parse_table_name (tn, &db_prefix, &table_name); ok_table = 1; } if (sqlite3_value_type (argv[1]) == SQLITE_TEXT) { geom_column = (char *) sqlite3_value_text (argv[1]); ok_geom = 1; } if (sqlite3_value_type (argv[2]) == SQLITE_BLOB) { blob = sqlite3_value_blob (argv[2]); size = sqlite3_value_bytes (argv[2]); geom = gaiaFromSpatiaLiteBlobWkb (blob, size); } if (ok_table && ok_geom && geom) ; else { /* invalid args */ goto stop; } } if (idxNum == 2 && argc == 2) { /* retrieving the Table/MBR params */ if (sqlite3_value_type (argv[0]) == SQLITE_TEXT) { char *tn = (char *) sqlite3_value_text (argv[0]); vspidx_parse_table_name (tn, &db_prefix, &table_name); ok_table = 1; } if (sqlite3_value_type (argv[1]) == SQLITE_BLOB) { blob = sqlite3_value_blob (argv[1]); size = sqlite3_value_bytes (argv[1]); geom = gaiaFromSpatiaLiteBlobWkb (blob, size); } if (ok_table && geom) ; else { /* invalid args */ goto stop; } } /* checking if the corresponding R*Tree exists */ if (ok_geom) exists = vspidx_check_rtree (spidx->db, db_prefix, table_name, geom_column, &xtable, &xgeom); else exists = vspidx_find_rtree (spidx->db, db_prefix, table_name, &xtable, &xgeom); if (!exists) goto stop; /* building the RTree query */ idx_name = sqlite3_mprintf ("idx_%s_%s", xtable, xgeom); idx_nameQ = gaiaDoubleQuotedSql (idx_name); if (db_prefix == NULL) { sql_statement = sqlite3_mprintf ("SELECT pkid FROM \"%s\" WHERE " "xmin <= ? AND xmax >= ? AND ymin <= ? AND ymax >= ?", idx_nameQ); } else { char *quoted_db = gaiaDoubleQuotedSql (db_prefix); sql_statement = sqlite3_mprintf ("SELECT pkid FROM \"%s\".\"%s\" WHERE " "xmin <= ? AND xmax >= ? AND ymin <= ? AND ymax >= ?", quoted_db, idx_nameQ); free (quoted_db); } free (idx_nameQ); sqlite3_free (idx_name); ret = sqlite3_prepare_v2 (spidx->db, sql_statement, strlen (sql_statement), &stmt, NULL); sqlite3_free (sql_statement); if (ret != SQLITE_OK) goto stop; /* binding stmt params [MBR] */ gaiaMbrGeometry (geom); /* adjusting the MBR so to compensate for DOUBLE/FLOAT truncations */ minx = (float) (geom->MinX); miny = (float) (geom->MinY); maxx = (float) (geom->MaxX); maxy = (float) (geom->MaxY); tic = fabs (geom->MinX - minx); tic2 = fabs (geom->MinY - miny); if (tic2 > tic) tic = tic2; tic2 = fabs (geom->MaxX - maxx); if (tic2 > tic) tic = tic2; tic2 = fabs (geom->MaxY - maxy); if (tic2 > tic) tic = tic2; tic *= 2.0; sqlite3_bind_double (stmt, 1, geom->MaxX + tic); sqlite3_bind_double (stmt, 2, geom->MinX - tic); sqlite3_bind_double (stmt, 3, geom->MaxY + tic); sqlite3_bind_double (stmt, 4, geom->MinY - tic); cursor->stmt = stmt; cursor->eof = 0; /* fetching the first ResultSet's row */ ret = sqlite3_step (cursor->stmt); if (ret == SQLITE_ROW) cursor->CurrentRowId = sqlite3_column_int64 (cursor->stmt, 0); else cursor->eof = 1; stop: if (geom) gaiaFreeGeomColl (geom); if (xtable) free (xtable); if (xgeom) free (xgeom); if (db_prefix) free (db_prefix); if (table_name) free (table_name); return SQLITE_OK; }
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 int check_extended (void *cache, const char *path, int mode) { /* validating an XML Sample */ FILE *fl; int sz = 0; int rd; unsigned char *xml = NULL; int iso; int style; int svg; unsigned char *p_result = NULL; int len; char *file_id = NULL; char *parent_id = NULL; char *title = NULL; char *abstract = NULL; unsigned char *geom_blob; int geom_size; gaiaGeomCollPtr geom; /* loading the XMLDocument */ fl = fopen (path, "rb"); if (!fl) { fprintf (stderr, "cannot open \"%s\"\n", path); return 0; } if (fseek (fl, 0, SEEK_END) == 0) sz = ftell (fl); xml = malloc (sz); rewind (fl); rd = fread (xml, 1, sz, fl); if (rd != sz) { fprintf (stderr, "read error \"%s\"\n", path); return 0; } fclose (fl); /* simple parsing without validation */ gaiaXmlToBlob (cache, xml, rd, 1, NULL, &p_result, &len, NULL, NULL); if (p_result == NULL) { fprintf (stderr, "unable to parse \"%s\"\n", path); return 0; } /* checking the payload type */ iso = gaiaIsIsoMetadataXmlBlob (p_result, len); style = gaiaIsSldSeRasterStyleXmlBlob (p_result, len); style = gaiaIsSldSeVectorStyleXmlBlob (p_result, len); svg = gaiaIsSvgXmlBlob (p_result, len); if (mode == ISO_METADATA && iso && !style && !svg) ; else if (mode == SLD_SE_STYLE && !iso && style && !svg) ; else if (mode == SVG && !iso && !style && svg) ; else { fprintf (stderr, "mismatching type: \"%s\" iso=%d style=%d svg=%d\n", path, iso, style, svg); return 0; } /* testing ISO Metadata attributes */ file_id = gaiaXmlBlobGetFileId (p_result, len); parent_id = gaiaXmlBlobGetParentId (p_result, len); title = gaiaXmlBlobGetTitle (p_result, len); abstract = gaiaXmlBlobGetAbstract (p_result, len); gaiaXmlBlobGetGeometry (p_result, len, &geom_blob, &geom_size); if (mode == ISO_METADATA) { /* verifying ISO Metadata attributes */ if (file_id == NULL) { fprintf (stderr, "unexpected NULL FileIdentifier in \"%s\"\n", path); return 0; } if (strcmp (file_id, "029097fd-2ef2-487c-a5ca-6ec7a3dbac53") != 0) { fprintf (stderr, "unexpected FileIdentifier in \"%s\" [%s]\n", path, file_id); return 0; } if (parent_id == NULL) { fprintf (stderr, "unexpected NULL ParentIdentifier in \"%s\"\n", path); return 0; } if (strcmp (parent_id, "024027fd-3ef2-487c-a8ca-6ec8a3dfac57") != 0) { fprintf (stderr, "unexpected ParentIdentifier in \"%s\" [%s]\n", path, parent_id); return 0; } if (title == NULL) { fprintf (stderr, "unexpected NULL Title in \"%s\"\n", path); return 0; } if (strcmp (title, "Image2000 Product 1 (nl2) Multispectral") != 0) { fprintf (stderr, "unexpected Title in \"%s\" [%s]\n", path, title); return 0; } if (abstract == NULL) { fprintf (stderr, "unexpected NULL Abstract in \"%s\"\n", path); return 0; } if (strcmp (abstract, "IMAGE2000 product 1 individual orthorectified scenes.") != 0) { fprintf (stderr, "unexpected Abstract in \"%s\" [%s]\n", path, abstract); return 0; } if (geom_blob == NULL) { fprintf (stderr, "unexpected NULL Geometry in \"%s\"\n", path); return 0; } geom = gaiaFromSpatiaLiteBlobWkb (geom_blob, geom_size); if (geom == NULL) { fprintf (stderr, "unexpected invalid Geometry in \"%s\"\n", path); return 0; } if (geom->Srid != 4326) { fprintf (stderr, "unexpected Geometry SRID in \"%s\" [%d]\n", path, geom->Srid); return 0; } if (geom->DeclaredType != GAIA_MULTIPOLYGON) { fprintf (stderr, "unexpected Geometry Type in \"%s\" [%d]\n", path, geom->DeclaredType); return 0; } if (geom->MinX != 3.93000000) { fprintf (stderr, "unexpected Geometry MinX in \"%s\" [%1.8f]\n", path, geom->MinX); return 0; } if (geom->MinY != 52.10000000) { fprintf (stderr, "unexpected Geometry MinY in \"%s\" [%1.8f]\n", path, geom->MinY); return 0; } if (geom->MaxX != 7.57000000) { fprintf (stderr, "unexpected Geometry MaxX in \"%s\" [%1.8f]\n", path, geom->MaxX); return 0; } if (geom->MaxY != 54.10000000) { fprintf (stderr, "unexpected Geometry MaxY in \"%s\" [%1.8f]\n", path, geom->MaxY); return 0; } gaiaFreeGeomColl (geom); } else { /* not ISO Metadata */ if (strcmp (path, "stazioni_se.xml") == 0) { if (strcmp (title, "Railway Stations - blue star") != 0) { fprintf (stderr, "unexpected Title in \"%s\"\n", path); return 0; } if (strcmp (abstract, "a simple SE Point Symbolizer") != 0) { fprintf (stderr, "unexpected Abstract in \"%s\"\n", path); return 0; } } else { if (title != NULL) { fprintf (stderr, "unexpected Title in \"%s\"\n", path); return 0; } if (abstract != NULL) { fprintf (stderr, "unexpected Abstract in \"%s\"\n", path); return 0; } } } free (p_result); free (xml); if (file_id) free (file_id); if (parent_id) free (parent_id); if (title) free (title); if (abstract) free (abstract); if (geom_blob) free (geom_blob); return 1; }
static int check_mline_gpx (sqlite3 * handle, void *cache, const char *path) { /* parsing an XML Sample */ FILE *fl; int sz = 0; int rd; unsigned char *xml = NULL; int uncompressed_sz; unsigned char *p_result = NULL; gaiaGeomCollPtr geom; gaiaLinestringPtr ln; double x; double y; double z; double m; /* loading the XMLDocument */ fl = fopen (path, "rb"); if (!fl) { fprintf (stderr, "cannot open \"%s\"\n", path); return 0; } if (fseek (fl, 0, SEEK_END) == 0) sz = ftell (fl); xml = malloc (sz); rewind (fl); rd = fread (xml, 1, sz, fl); if (rd != sz) { fprintf (stderr, "read error \"%s\"\n", path); return 0; } fclose (fl); /* parsing the GPX document (no validation / not compressed) */ gaiaXmlToBlob (cache, xml, rd, 0, NULL, &p_result, &uncompressed_sz, NULL, NULL); if (p_result == NULL) { fprintf (stderr, "unable to parse(gpx)\"%s\"\n", path); return 0; } geom = gaiaXmlBlobMLineFromGPX (p_result, uncompressed_sz, handle); if (geom == NULL) { fprintf (stderr, "XB_MLineFromGPX: unexpected failure \"%s\"\n", path); return 0; } if (geom->Srid != 4326) { fprintf (stderr, "XB_MLineFromGPX: invalid SRID (%d) \"%s\"\n", geom->Srid, path); return 0; } ln = geom->FirstLinestring; if (ln == NULL) { fprintf (stderr, "XB_MLineFromGPX: not a Linestring \"%s\"\n", path); return 0; } if (ln->Points < 5) { fprintf (stderr, "XB_MLineFromGPX: too few points \"%s\"\n", path); return 0; } gaiaGetPointXYZM (ln->Coords, 4, &x, &y, &z, &m); if (strcmp (path, "Gpx-sample.gpx") == 0) { if (x != 37.808177) { fprintf (stderr, "XB_MLineFromGPX: unexpected X=%f \"%s\"\n", x, path); return 0; } if (y != 55.753587) { fprintf (stderr, "XB_MLineFromGPX: unexpected Y=%f \"%s\"\n", y, path); return 0; } if (z != 135.0) { fprintf (stderr, "XB_MLineFromGPX: unexpected Z=%f \"%s\"\n", z, path); return 0; } if (m < 2454970.667060 || m > 2454970.667061) { fprintf (stderr, "XB_MLineFromGPX: unexpected M=%f \"%s\"\n", m, path); return 0; } } else { if (x != -25.1959200) { fprintf (stderr, "XB_MLineFromGPX: unexpected X=%f \"%s\"\n", x, path); return 0; } if (y != 37.7710900) { fprintf (stderr, "XB_MLineFromGPX: unexpected Y=%f \"%s\"\n", y, path); return 0; } if (z != 0.0) { fprintf (stderr, "XB_MLineFromGPX: unexpected Z=%f \"%s\"\n", z, path); return 0; } if (m != 1721059.50) { fprintf (stderr, "XB_MLineFromGPX: unexpected M=%f \"%s\"\n", m, path); return 0; } } gaiaFreeGeomColl (geom); free (p_result); free (xml); return 1; }
GAIAGEO_DECLARE gaiaGeomCollPtr gaiaSnapToGrid (gaiaGeomCollPtr geom, double origin_x, double origin_y, double origin_z, double origin_m, double size_x, double size_y, double size_z, double size_m) { /* creating a Geometry snapped to a regular Grid */ gaiaGeomCollPtr result; int pts = 0; int lns = 0; int pgs = 0; gaiaPointPtr pt; gaiaLinestringPtr ln; gaiaPolygonPtr pg; if (!geom) return NULL; /* creating the output Geometry */ if (geom->DimensionModel == GAIA_XY_Z) result = gaiaAllocGeomCollXYZ (); else if (geom->DimensionModel == GAIA_XY_M) result = gaiaAllocGeomCollXYM (); else if (geom->DimensionModel == GAIA_XY_Z_M) result = gaiaAllocGeomCollXYZM (); else result = gaiaAllocGeomColl (); /* snapping elementary Geometries to the given Grid */ pt = geom->FirstPoint; while (pt) { /* snapping POINTs */ auxGridSnapPoint (geom->DimensionModel, pt, result, origin_x, origin_y, origin_z, origin_m, size_x, size_y, size_z, size_m); pt = pt->Next; } ln = geom->FirstLinestring; while (ln) { /* snapping LINESTRINGs */ auxGridSnapLinestring (ln, result, origin_x, origin_y, origin_z, origin_m, size_x, size_y, size_z, size_m); ln = ln->Next; } pg = geom->FirstPolygon; while (pg) { /* snapping POLYGONs */ auxGridSnapPolygon (pg, result, origin_x, origin_y, origin_z, origin_m, size_x, size_y, size_z, size_m); pg = pg->Next; } /* validating the output Geometry */ pt = result->FirstPoint; while (pt) { /* counting how many POINTs are there */ pts++; pt = pt->Next; } ln = result->FirstLinestring; while (ln) { /* counting how many LINESTRINGs are there */ lns++; ln = ln->Next; } pg = result->FirstPolygon; while (pg) { /* counting how many POLYGONs are there */ pgs++; pg = pg->Next; } if (pts == 0 && lns == 0 && pgs == 0) { /* empty result */ gaiaFreeGeomColl (result); return NULL; } /* final adjustment */ result->Srid = geom->Srid; if (pts == 1 && lns == 0 && pgs == 0) { if (geom->DeclaredType == GAIA_GEOMETRYCOLLECTION) result->DeclaredType = GAIA_GEOMETRYCOLLECTION; else if (geom->DeclaredType == GAIA_MULTIPOINT) result->DeclaredType = GAIA_MULTIPOINT; else result->DeclaredType = GAIA_POINT; } else if (pts == 0 && lns == 1 && pgs == 0) { if (geom->DeclaredType == GAIA_GEOMETRYCOLLECTION) result->DeclaredType = GAIA_GEOMETRYCOLLECTION; else if (geom->DeclaredType == GAIA_MULTILINESTRING) result->DeclaredType = GAIA_MULTILINESTRING; else result->DeclaredType = GAIA_LINESTRING; } else if (pts == 0 && lns == 0 && pgs == 1) { if (geom->DeclaredType == GAIA_GEOMETRYCOLLECTION) result->DeclaredType = GAIA_GEOMETRYCOLLECTION; else if (geom->DeclaredType == GAIA_MULTIPOLYGON) result->DeclaredType = GAIA_MULTIPOLYGON; else result->DeclaredType = GAIA_POLYGON; } else if (pts > 1 && lns == 0 && pgs == 0) { if (geom->DeclaredType == GAIA_GEOMETRYCOLLECTION) result->DeclaredType = GAIA_GEOMETRYCOLLECTION; else result->DeclaredType = GAIA_MULTIPOINT; } else if (pts == 0 && lns > 1 && pgs == 0) { if (geom->DeclaredType == GAIA_GEOMETRYCOLLECTION) result->DeclaredType = GAIA_GEOMETRYCOLLECTION; else result->DeclaredType = GAIA_MULTILINESTRING; } else if (pts == 0 && lns == 0 && pgs > 1) { if (geom->DeclaredType == GAIA_GEOMETRYCOLLECTION) result->DeclaredType = GAIA_GEOMETRYCOLLECTION; else result->DeclaredType = GAIA_MULTIPOLYGON; } else result->DeclaredType = GAIA_GEOMETRYCOLLECTION; return result; }
gaiaGeomCollPtr gaiaParseGeoJSON (const unsigned char *dirty_buffer) { void *pParser = ParseAlloc (malloc); /* Linked-list of token values */ geoJsonFlexToken *tokens = malloc (sizeof (geoJsonFlexToken)); /* Pointer to the head of the list */ geoJsonFlexToken *head = tokens; int yv; yyscan_t scanner; struct geoJson_data str_data; /* initializing the helper structs */ str_data.geoJson_line = 1; str_data.geoJson_col = 1; str_data.geoJson_parse_error = 0; str_data.geoJson_first_dyn_block = NULL; str_data.geoJson_last_dyn_block = NULL; str_data.result = NULL; /* initializing the scanner state */ GeoJsonlex_init_extra (&str_data, &scanner); tokens->Next = NULL; GeoJson_scan_string ((char *) dirty_buffer, scanner); /* / Keep tokenizing until we reach the end / yylex() will return the next matching Token for us. */ while ((yv = yylex (scanner)) != 0) { if (yv == -1) { str_data.geoJson_parse_error = 1; break; } tokens->Next = malloc (sizeof (geoJsonFlexToken)); tokens->Next->Next = NULL; tokens->Next->value = str_data.GeoJsonLval.dval; /* Pass the token to the wkt parser created from lemon */ Parse (pParser, yv, &(tokens->Next->value), &str_data); tokens = tokens->Next; } /* This denotes the end of a line as well as the end of the parser */ Parse (pParser, GEOJSON_NEWLINE, 0, &str_data); ParseFree (pParser, free); GeoJsonlex_destroy (scanner); /* Assigning the token as the end to avoid seg faults while cleaning */ tokens->Next = NULL; geoJSON_cleanup (head); if (str_data.geoJson_parse_error) { if (str_data.result) { /* if a Geometry-result has been produced, the stack is already cleaned */ gaiaFreeGeomColl (str_data.result); geoJsonCleanMapDynAlloc (&str_data, 0); } else { /* otherwise we are required to clean the stack */ geoJsonCleanMapDynAlloc (&str_data, 1); } return NULL; } geoJsonCleanMapDynAlloc (&str_data, 0); if (str_data.result == NULL) return NULL; if (!geoJsonCheckValidity (str_data.result)) { gaiaFreeGeomColl (str_data.result); return NULL; } gaiaMbrGeometry (str_data.result); return str_data.result; }
static void geoJSON_geomColl_common (struct geoJson_data *p_data, gaiaGeomCollPtr org, gaiaGeomCollPtr dst) { /* / helper function: xfers entities between the Origin and Destination / Sandro Furieri: 2010 October 12 */ gaiaGeomCollPtr p = org; gaiaGeomCollPtr p_n; gaiaPointPtr pt; gaiaPointPtr pt_n; gaiaLinestringPtr ln; gaiaLinestringPtr ln_n; gaiaPolygonPtr pg; gaiaPolygonPtr pg_n; while (p) { pt = p->FirstPoint; while (pt) { pt_n = pt->Next; pt->Next = NULL; if (dst->FirstPoint == NULL) dst->FirstPoint = pt; if (dst->LastPoint != NULL) dst->LastPoint->Next = pt; dst->LastPoint = pt; pt = pt_n; } ln = p->FirstLinestring; while (ln) { ln_n = ln->Next; ln->Next = NULL; if (dst->FirstLinestring == NULL) dst->FirstLinestring = ln; if (dst->LastLinestring != NULL) dst->LastLinestring->Next = ln; dst->LastLinestring = ln; ln = ln_n; } pg = p->FirstPolygon; while (pg) { pg_n = pg->Next; pg->Next = NULL; if (dst->FirstPolygon == NULL) dst->FirstPolygon = pg; if (dst->LastPolygon != NULL) dst->LastPolygon->Next = pg; dst->LastPolygon = pg; pg = pg_n; } p_n = p->Next; p->FirstPoint = NULL; p->LastPoint = NULL; p->FirstLinestring = NULL; p->LastLinestring = NULL; p->FirstPolygon = NULL; p->LastPolygon = NULL; geoJsonMapDynClean (p_data, p); gaiaFreeGeomColl (p); p = p_n; } }
static int vknn_filter (sqlite3_vtab_cursor * pCursor, int idxNum, const char *idxStr, int argc, sqlite3_value ** argv) { /* setting up a cursor filter */ char *db_prefix = NULL; char *table_name = NULL; char *geom_column = NULL; char *xtable = NULL; char *xgeom = NULL; char *xgeomQ; char *xtableQ; char *idx_name; char *idx_nameQ; char *sql_statement; gaiaGeomCollPtr geom = NULL; int ok_table = 0; int ok_geom = 0; int ok_max = 0; int max_items = 3; int is_geographic; const unsigned char *blob; int size; int exists; int ret; sqlite3_stmt *stmt = NULL; sqlite3_stmt *stmt_dist = NULL; sqlite3_stmt *stmt_rect = NULL; VirtualKnnCursorPtr cursor = (VirtualKnnCursorPtr) pCursor; VirtualKnnPtr knn = (VirtualKnnPtr) cursor->pVtab; VKnnContextPtr vknn_context = knn->knn_ctx; if (idxStr) idxStr = idxStr; /* unused arg warning suppression */ cursor->eof = 1; if (idxStr) idxStr = idxStr; /* unused arg warning suppression */ cursor->eof = 1; if (idxNum == 1 && argc == 3) { /* retrieving the Table/Column/Geometry params */ if (sqlite3_value_type (argv[0]) == SQLITE_TEXT) { char *tn = (char *) sqlite3_value_text (argv[0]); vknn_parse_table_name (tn, &db_prefix, &table_name); ok_table = 1; } if (sqlite3_value_type (argv[1]) == SQLITE_TEXT) { geom_column = (char *) sqlite3_value_text (argv[1]); ok_geom = 1; } if (sqlite3_value_type (argv[2]) == SQLITE_BLOB) { blob = sqlite3_value_blob (argv[2]); size = sqlite3_value_bytes (argv[2]); geom = gaiaFromSpatiaLiteBlobWkb (blob, size); } if (ok_table && ok_geom && geom) ; else { /* invalid args */ goto stop; } } if (idxNum == 2 && argc == 2) { /* retrieving the Table/Geometry params */ if (sqlite3_value_type (argv[0]) == SQLITE_TEXT) { char *tn = (char *) sqlite3_value_text (argv[0]); vknn_parse_table_name (tn, &db_prefix, &table_name); ok_table = 1; } if (sqlite3_value_type (argv[1]) == SQLITE_BLOB) { blob = sqlite3_value_blob (argv[1]); size = sqlite3_value_bytes (argv[1]); geom = gaiaFromSpatiaLiteBlobWkb (blob, size); } if (ok_table && geom) ; else { /* invalid args */ goto stop; } } if (idxNum == 3 && argc == 4) { /* retrieving the Table/Column/Geometry/MaxItems params */ if (sqlite3_value_type (argv[0]) == SQLITE_TEXT) { char *tn = (char *) sqlite3_value_text (argv[0]); vknn_parse_table_name (tn, &db_prefix, &table_name); ok_table = 1; } if (sqlite3_value_type (argv[1]) == SQLITE_TEXT) { geom_column = (char *) sqlite3_value_text (argv[1]); ok_geom = 1; } if (sqlite3_value_type (argv[2]) == SQLITE_BLOB) { blob = sqlite3_value_blob (argv[2]); size = sqlite3_value_bytes (argv[2]); geom = gaiaFromSpatiaLiteBlobWkb (blob, size); } if (sqlite3_value_type (argv[3]) == SQLITE_INTEGER) { max_items = sqlite3_value_int (argv[3]); if (max_items > 1024) max_items = 1024; if (max_items < 1) max_items = 1; ok_max = 1; } if (ok_table && ok_geom && geom && ok_max) ; else { /* invalid args */ goto stop; } } if (idxNum == 4 && argc == 3) { /* retrieving the Table/Geometry/MaxItems params */ if (sqlite3_value_type (argv[0]) == SQLITE_TEXT) { char *tn = (char *) sqlite3_value_text (argv[0]); vknn_parse_table_name (tn, &db_prefix, &table_name); ok_table = 1; } if (sqlite3_value_type (argv[1]) == SQLITE_BLOB) { blob = sqlite3_value_blob (argv[1]); size = sqlite3_value_bytes (argv[1]); geom = gaiaFromSpatiaLiteBlobWkb (blob, size); } if (sqlite3_value_type (argv[2]) == SQLITE_INTEGER) { max_items = sqlite3_value_int (argv[2]); if (max_items > 1024) max_items = 1024; if (max_items < 1) max_items = 1; ok_max = 1; } if (ok_table && geom && ok_max) ; else { /* invalid args */ goto stop; } } /* checking if the corresponding R*Tree exists */ if (ok_geom) exists = vknn_check_rtree (knn->db, db_prefix, table_name, geom_column, &xtable, &xgeom, &is_geographic); else exists = vknn_find_rtree (knn->db, db_prefix, table_name, &xtable, &xgeom, &is_geographic); if (!exists) goto stop; /* building the Distance query */ xgeomQ = gaiaDoubleQuotedSql (xgeom); xtableQ = gaiaDoubleQuotedSql (xtable); if (is_geographic) sql_statement = sqlite3_mprintf ("SELECT ST_Distance(?, \"%s\", 1) FROM \"%s\" WHERE rowid = ?", xgeomQ, xtableQ); else sql_statement = sqlite3_mprintf ("SELECT ST_Distance(?, \"%s\") FROM \"%s\" WHERE rowid = ?", xgeomQ, xtableQ); free (xgeomQ); free (xtableQ); ret = sqlite3_prepare_v2 (knn->db, sql_statement, strlen (sql_statement), &stmt_dist, NULL); sqlite3_free (sql_statement); if (ret != SQLITE_OK) goto stop; /* building the RTree MBR Distance query */ sql_statement = "SELECT ST_Distance(?, BuildMbr(?, ?, ?, ?))"; ret = sqlite3_prepare_v2 (knn->db, sql_statement, strlen (sql_statement), &stmt_rect, NULL); if (ret != SQLITE_OK) goto stop; /* installing the R*Tree query callback */ gaiaMbrGeometry (geom); vknn_init_context (vknn_context, xtable, xgeom, geom, max_items, stmt_dist, stmt_rect); gaiaFreeGeomColl (geom); geom = NULL; /* releasing ownership on geom */ stmt_dist = NULL; /* releasing ownership on stmt_dist */ stmt_rect = NULL; /* releasing ownership on stmt_rect */ sqlite3_rtree_query_callback (knn->db, "knn_position", vknn_query_callback, vknn_context, NULL); /* building the RTree query */ idx_name = sqlite3_mprintf ("idx_%s_%s", xtable, xgeom); idx_nameQ = gaiaDoubleQuotedSql (idx_name); if (db_prefix == NULL) { sql_statement = sqlite3_mprintf ("SELECT pkid FROM \"%s\" WHERE pkid MATCH knn_position(1)", idx_nameQ); } else { char *quoted_db = gaiaDoubleQuotedSql (db_prefix); sql_statement = sqlite3_mprintf ("SELECT pkid FROM \"%s\".\"%s\" WHERE pkid MATCH knn_position(1)", quoted_db, idx_nameQ); free (quoted_db); } free (idx_nameQ); sqlite3_free (idx_name); ret = sqlite3_prepare_v2 (knn->db, sql_statement, strlen (sql_statement), &stmt, NULL); sqlite3_free (sql_statement); if (ret != SQLITE_OK) goto stop; vknn_context->curr_level = -1; while (vknn_context->curr_level != 0) { /* querying the R*Tree: step #1 tree MBRs */ sqlite3_step (stmt); if (vknn_context->curr_level == -1) break; /* found an empty R*Tree, preasumably */ vknn_context->curr_level -= 1; } if (vknn_context->curr_level == 0) { /* querying the R*Tree: step #2 features */ sqlite3_step (stmt); } if (vknn_context->curr_items == 0) cursor->eof = 1; else cursor->eof = 0; cursor->CurrentIndex = 0; stop: if (geom) gaiaFreeGeomColl (geom); if (xtable) free (xtable); if (xgeom) free (xgeom); if (db_prefix) free (db_prefix); if (table_name) free (table_name); if (stmt != NULL) sqlite3_finalize (stmt); if (stmt_dist != NULL) sqlite3_finalize (stmt_dist); if (stmt_rect != NULL) sqlite3_finalize (stmt_rect); return SQLITE_OK; }