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);
}
示例#2
0
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;
      }
}
示例#3
0
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;
}
示例#5
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;
      }
}
示例#6
0
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;
      }
}
示例#7
0
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;
}
示例#8
0
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;
}
示例#9
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;
}
示例#10
0
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;
}
示例#11
0
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;
}
示例#13
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;
}
示例#14
0
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;
}
示例#15
0
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;
}
示例#16
0
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;
}
示例#17
0
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;
}
示例#18
0
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;
      }
}
示例#19
0
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;
}