Esempio n. 1
0
shapeObj *msGEOSGeometry2Shape(GEOSGeom g)
{
  int type;

  if(!g) 
    return NULL; /* a NULL geometry generates a NULL shape */

  type = GEOSGeomTypeId(g);
  switch(type) {
  case GEOS_POINT:
    return msGEOSGeometry2Shape_point(g);
    break;
  case GEOS_MULTIPOINT:
    return msGEOSGeometry2Shape_multipoint(g);
    break;
  case GEOS_LINESTRING:
    return msGEOSGeometry2Shape_line(g);
    break;
  case GEOS_MULTILINESTRING:
    return msGEOSGeometry2Shape_multiline(g);
    break;
  case GEOS_POLYGON:
    return msGEOSGeometry2Shape_polygon(g);
    break;
  case GEOS_MULTIPOLYGON:
    return msGEOSGeometry2Shape_multipolygon(g);
    break;
  default:
    if (!GEOSisEmpty(g))
        msSetError(MS_GEOSERR, "Unsupported GEOS geometry type (%d).", "msGEOSGeometry2Shape()", type);
    return NULL;
  }
}
Esempio n. 2
0
void Geometry::ApplyPointTransformation(PointTransformer *t)
{
    GEOSGeometry    *g      = this->geos_geom_;
    GEOSGeometry    *ng     = NULL;
    int             gtype   = GEOSGeomTypeId(g);
    int             gcount  = GEOSGetNumGeometries(g);
    
    if (gcount == 1) {
        ng = ApplyPointTransformationToSingleGeometry(t, g);
    }
    else {
        GEOSGeometry **coll = new GEOSGeometry *[gcount];
    
        try {
            for (int i = 0; i < gcount; i++) {
                coll[i] = ApplyPointTransformationToSingleGeometry(t, GEOSGetGeometryN(g, i));
            }
        }
        catch (TransformerException ex) {
            // free up our memory before we pass this up.
            delete coll;
            throw ex;
        }

        ng = GEOSGeom_createCollection(gtype, coll, gcount);
        delete coll;
    }
    
    if (ng != NULL) {
        GEOSGeom_destroy(this->geos_geom_);
        this->geos_geom_ = ng;
    }
}
Esempio n. 3
0
    struct GridPointDataListIterator * readPoints(
        const struct PlaceSpecification * ps, GEOSGeom location,
        enum InterpolationType interpolation, int interpolationParam, FileId dataId)
    {
        const BaseDataReader & dataReader = BaseDataReader::getInstance(* ps);

        GridPointDataListIterator * ret = NULL;
        try
        {
            if ( ! location )
            {
                //AllPointsReader reader(dataReader);
                //struct GridPointDataList * list = reader.read(dataId);

                // On NULL geometries we won't return anything
                struct GridPointDataList * list = GridPointDataListNew(0);
                ret = GridPointDataListIteratorNew(list);
            }
            else
            {
                int geometryType = GEOSGeomTypeId(location);
                if (geometryType == GEOS_POINT)
                {
                    SinglePointReader reader(dataReader);

                    GridPointDataList * list = reader.read(location, interpolation, interpolationParam, dataId);
                    ret = GridPointDataListIteratorNew(list);
                }
                else if ((geometryType == GEOS_POLYGON)||
                         (geometryType == GEOS_MULTIPOLYGON))
                {
                    PolygonReader reader(dataReader);
                    GridPointDataList * list = reader.read(location, interpolation, dataId);
                    ret = GridPointDataListIteratorNew(list);
                }
                else
                    throw std::runtime_error("This geometry type is not supported");
            }
        }
        catch (std::exception & e)
        {
            if ( ret )
                GridPointDataListDelete(ret->list, false);
            ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), errmsg(e.what())));
        }
        catch (...)
        {
            // This should never happen, but just in case...
            if ( ret )
                GridPointDataListDelete(ret->list, false);
            ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), "Unknown error when fetching point data. Please tell someone about this"));
        }

        return ret;
    }
Esempio n. 4
0
YAP_Bool geometry_to_term (geometry_t geometry, YAP_Term *term)
{
  geometry_type_t type;
  unsigned int n, size;

  assert (term != NULL);
  type = GEOSGeomTypeId (geometry);
  size = sizeof (translate) / sizeof (struct type_name_arity);
  for (n = 0; n < size; n ++)
    if (translate[n].geos_type == type)
      return (translate[n].procedure_export (geometry, term));

  return (FALSE);
}
Esempio n. 5
0
static void _get_envelope(GEOSGeometry* geometry,Rect* rect)
{
	unsigned int num_pnt;
	GEOSGeometry* env;
	const GEOSGeometry* ring;
	const GEOSCoordSequence* seq;
	double x,y;
	unsigned int loop=0;
	assert(rect != 0);
	assert(geometry != 0);
	rect->minX = rect->minY = rect->maxX = rect->maxY = 0;

	if(GEOSGeomTypeId(geometry) == GEOS_POINT)
	{
		GEOSGeomGetX(geometry,&x);
		GEOSGeomGetY(geometry,&y);
		rect->minX = rect->maxX = x;
		rect->minY = rect->maxY = y;
		return;
	}

	env = GEOSEnvelope(geometry);
	ring = GEOSGetExteriorRing(env);
	seq	 =	GEOSGeom_getCoordSeq(ring);
	GEOSCoordSeq_getSize(seq,&num_pnt);

	if(num_pnt == 0 || num_pnt > 5)return;

	GEOSCoordSeq_getX(seq,0,&x);
	GEOSCoordSeq_getY(seq,0,&y);

	rect->minX = rect->maxX = x;
	rect->minY = rect->maxY = y;

	for(loop=1;loop<num_pnt;loop++)
	{
		GEOSCoordSeq_getX(seq,loop,&x);
		GEOSCoordSeq_getY(seq,loop,&y);
		
		if(x > rect->maxX) rect->maxX = x;
		if(x < rect->minX) rect->minX = x;

		if(y > rect->maxY) rect->maxY = y;
		if(y < rect->minY) rect->minY = y;
	}

	GEOSGeom_destroy(env);
}
Esempio n. 6
0
//LinkedList<const geos::geom::Geometry*> * unmulti (geos::geom::Geometry *the_geom){
  LinkedList<const GEOSGeometry*> * unmulti( GEOSGeometry *the_geom )
  {

    //LinkedList<const geos::geom::Geometry*> *queue = new  LinkedList<const geos::geom::Geometry*>(ptrGeomEq);
    //LinkedList<const geos::geom::Geometry*> *final_queue = new  LinkedList<const geos::geom::Geometry*>(ptrGeomEq);
    LinkedList<const GEOSGeometry*> *queue = new  LinkedList<const GEOSGeometry*> ( ptrGeomEq );
    LinkedList<const GEOSGeometry*> *final_queue = new  LinkedList<const GEOSGeometry*> ( ptrGeomEq );

    //const geos::geom::Geometry *geom;
    const GEOSGeometry *geom;

    queue->push_back( the_geom );
    int nGeom;
    int i;

    while ( queue->size() > 0 )
    {
      geom = queue->pop_front();
      switch ( GEOSGeomTypeId( geom ) )
      {
          //case geos::geom::GEOS_MULTIPOINT:
          //case geos::geom::GEOS_MULTILINESTRING:
          //case geos::geom::GEOS_MULTIPOLYGON:
        case GEOS_MULTIPOINT:
        case GEOS_MULTILINESTRING:
        case GEOS_MULTIPOLYGON:
          nGeom = GEOSGetNumGeometries( geom );
          for ( i = 0; i < nGeom; i++ )
          {
            queue->push_back( GEOSGetGeometryN( geom, i ) );
          }
          break;
        case GEOS_POINT:
        case GEOS_LINESTRING:
        case GEOS_POLYGON:
          final_queue->push_back( geom );
          break;
        default:
          delete final_queue;
          final_queue = NULL;
      }
    }
    delete queue;

    return final_queue;
  }
Esempio n. 7
0
GEOSGeometry *Geometry::ApplyPointTransformationToSingleGeometry(PointTransformer *t, const GEOSGeometry *g)
{
    int             gtype   = GEOSGeomTypeId(g);
    GEOSGeometry    *ng     = NULL;
    
    if (gtype == GEOS_POINT || gtype == GEOS_LINESTRING || gtype == GEOS_LINEARRING) {
        const GEOSCoordSequence *seq =  GEOSGeom_getCoordSeq(g);
        GEOSCoordSequence       *nseq = ApplyPointTransformationToCoordSequence(t, seq);
        
        // this is silly -- GEOS really needs a shortcut for this
        if (gtype == GEOS_POINT) {
            ng = GEOSGeom_createPoint(nseq);
        }
        if (gtype == GEOS_LINESTRING) {
            ng = GEOSGeom_createLineString(nseq);
        }
        if (gtype == GEOS_LINEARRING) {
            ng = GEOSGeom_createLinearRing(nseq);
        }
    }
    else if (gtype == GEOS_POLYGON) {
        int                 ircnt   = GEOSGetNumInteriorRings(g);
        const GEOSGeometry  *ext    = GEOSGetExteriorRing(g);
        GEOSGeometry        *next   = ApplyPointTransformationToSingleGeometry(t, ext);
        GEOSGeometry        **rings = NULL;
        
        if (ircnt > 0) {
            // This shares a lot in common with the code below in ApplyPointTransformation,
            // refactor into a single method?
            rings = new GEOSGeometry *[ircnt];
            
            for (int i = 0; i < ircnt; i++) {
                rings[i] = ApplyPointTransformationToSingleGeometry(t, GEOSGetInteriorRingN(g, i));
            }
        }
        
        ng = GEOSGeom_createPolygon(next, rings, ircnt);
        
        if (rings) {
            delete rings;
        }
    }
    
    return ng;
}
static size_t
asgeojson_geom_buf(GEOSGeom geom, char *output, bbox3D *bbox, int precision)
{
    int type = GEOSGeomTypeId(geom)+1;
    char *ptr=output;

    switch (type)
    {
        case wkbPoint_mdb:
            ptr += asgeojson_point_buf(geom, NULL, ptr, bbox, precision);
            break;

        case wkbLineString_mdb:
            ptr += asgeojson_line_buf(geom, NULL, ptr, bbox, precision);
            break;

        case wkbPolygon_mdb:
            ptr += asgeojson_poly_buf(geom, NULL, ptr, bbox, precision);
            break;

        case wkbMultiPoint_mdb:
            ptr += asgeojson_multipoint_buf(geom, NULL, ptr, bbox, precision);
            break;

        case wkbMultiLineString_mdb:
            ptr += asgeojson_multiline_buf(geom, NULL, ptr, bbox, precision);
            break;

        case wkbMultiPolygon_mdb:
            ptr += asgeojson_multipolygon_buf(geom, NULL, ptr, bbox, precision);
            break;

        default:
            if (bbox)
                GDKfree(bbox);
            assert(0);
    }

    return (ptr-output);
}
    static size_t
asgeojson_geom_size(GEOSGeom geom, bbox3D *bbox, int precision)
{
    int type = GEOSGeomTypeId(geom)+1;
    size_t size = 0;

    switch (type)
    {
        case wkbPoint_mdb:
            size = asgeojson_point_size(geom, NULL, bbox, precision);
            break;

        case wkbLineString_mdb:
            size = asgeojson_line_size(geom, NULL, bbox, precision);
            break;

        case wkbPolygon_mdb:
            size = asgeojson_poly_size(geom, NULL, bbox, precision);
            break;

        case wkbMultiPoint_mdb:
            size = asgeojson_multipoint_size(geom, NULL, bbox, precision);
            break;

        case wkbMultiLineString_mdb:
            size = asgeojson_multiline_size(geom, NULL, bbox, precision);
            break;

        case wkbMultiPolygon_mdb:
            size = asgeojson_multipolygon_size(geom, NULL, bbox, precision);
            break;

        default:
            assert(0);
            size = 0;
    }

    return size;
}
Esempio n. 10
0
void geo_y(sqlite3_context *context,int argc,sqlite3_value **argv)
{
	if(argc == 1 && sqlite3_value_type(argv[0]) == SQLITE_BLOB)
	{ 
		GEOSGeometry* geometry;
		const void* data = sqlite3_value_blob(argv[0]);
		size_t data_size = sqlite3_value_bytes(argv[0]);

		_init_geos();
		geometry = _geo_from_wkb((const unsigned char*)data,data_size);
		if(geometry != 0)
		{
			if(GEOSGeomTypeId(geometry) == GEOS_POINT)
			{
				double y;
				GEOSGeomGetY(geometry,&y);
				sqlite3_result_double(context,y);
			}
		}
		GEOSGeom_destroy(geometry);
		finishGEOS();
	}
}
char*
geom_to_geojson(GEOSGeom geom, char *srs, int precision, int has_bbox)
{
    int type = GEOSGeomTypeId(geom)+1;
    bbox3D *bbox;

    if ( precision > OUT_MAX_DOUBLE_PRECISION ) precision = OUT_MAX_DOUBLE_PRECISION;

    if (has_bbox) 
    {
        bbox3DFromGeos(&bbox, geom);
    }		

    switch (type)
    {
        case wkbPoint_mdb:
            return asgeojson_point(geom, srs, bbox, precision);
        case wkbLineString_mdb:
            return asgeojson_line(geom, srs, bbox, precision);
        case wkbPolygon_mdb:
            return asgeojson_poly(geom, srs, bbox, precision);
        case wkbMultiPoint_mdb:
            return asgeojson_multipoint(geom, srs, bbox, precision);
        case wkbMultiLineString_mdb:
            return asgeojson_multiline(geom, srs, bbox, precision);
        case wkbMultiPolygon_mdb:
            return asgeojson_multipolygon(geom, srs, bbox, precision);
        case wkbGeometryCollection_mdb:
            return asgeojson_collection(geom, srs, bbox, precision);
        default:
            assert(0);
            return NULL;
    }

    return NULL;
}
Esempio n. 12
0
static ERL_NIF_TERM
geom_to_eterm(ErlNifEnv *env, const GEOSGeometry *geom)
{
    ERL_NIF_TERM coords;
    int type = GEOSGeomTypeId(geom);

    switch(type) {
    case GEOS_POINT:
        if (GEOSisEmpty(geom)) {
            coords = enif_make_list(env, 0);
        }
        else {
            coords = geom_to_eterm_point_coords(env, geom);
        }
        return enif_make_tuple2(env, enif_make_atom(env, "Point"), coords);
    case GEOS_LINESTRING:
        if (GEOSisEmpty(geom)) {
            coords = enif_make_list(env, 0);
        }
        else {
            coords = geom_to_eterm_linestring_coords(env, geom);
        }
        return enif_make_tuple2(env, enif_make_atom(env, "LineString"),
            coords);
    case GEOS_POLYGON:
        if (GEOSisEmpty(geom)) {
            coords = enif_make_list(env, 0);
        }
        else {
            coords = geom_to_eterm_polygon_coords(env, geom);
        }
        return enif_make_tuple2(env, enif_make_atom(env, "Polygon"), coords);
    case GEOS_MULTIPOINT:
        if (GEOSisEmpty(geom)) {
            coords = enif_make_list(env, 0);
        }
        else {
            coords = geom_to_eterm_multi_coords(env, geom,
                geom_to_eterm_point_coords);
        }
        return enif_make_tuple2(env, enif_make_atom(env, "MultiPoint"),
            coords);
    case GEOS_MULTILINESTRING:
        if (GEOSisEmpty(geom)) {
            coords = enif_make_list(env, 0);
        }
        else {
            coords = geom_to_eterm_multi_coords(env, geom,
                geom_to_eterm_linestring_coords);
        }
        return enif_make_tuple2(env, enif_make_atom(env, "MultiLineString"),
            coords);
    case GEOS_MULTIPOLYGON:
        if (GEOSisEmpty(geom)) {
            coords = enif_make_list(env, 0);
        }
        else {
            coords = geom_to_eterm_multi_coords(env, geom,
                geom_to_eterm_polygon_coords);
        }
        return enif_make_tuple2(env, enif_make_atom(env, "MultiPolygon"),
            coords);
    case GEOS_GEOMETRYCOLLECTION:
        if (GEOSisEmpty(geom)) {
            coords = enif_make_list(env, 0);
        }
        else {
            coords = geom_to_eterm_multi_coords(env, geom, geom_to_eterm);
        }
        return enif_make_tuple2(env, enif_make_atom(env, "GeometryCollection"),
            coords);
    }
    return -1;
}
Esempio n. 13
0
/* Initializes and uses GEOS internally */
static LWGEOM*
lwpoly_split_by_line(const LWPOLY* lwpoly_in, const LWLINE* blade_in)
{
	LWCOLLECTION* out;
	GEOSGeometry* g1;
	GEOSGeometry* g2;
	GEOSGeometry* g1_bounds;
	GEOSGeometry* polygons;
	const GEOSGeometry *vgeoms[1];
	int i,n;
	int hasZ = FLAGS_GET_Z(lwpoly_in->flags);


	/* Possible outcomes:
	 *
	 *  1. The line does not split the polygon
	 *      -> Return a collection with single element
	 *  2. The line does split the polygon
	 *      -> Return a collection of all elements resulting from the split
	 */

	initGEOS(lwgeom_geos_error, lwgeom_geos_error);

	g1 = LWGEOM2GEOS((LWGEOM*)lwpoly_in, 0);
	if ( NULL == g1 )
	{
		lwerror("LWGEOM2GEOS: %s", lwgeom_geos_errmsg);
		return NULL;
	}
	g1_bounds = GEOSBoundary(g1);
	if ( NULL == g1_bounds )
	{
		GEOSGeom_destroy(g1);
		lwerror("GEOSBoundary: %s", lwgeom_geos_errmsg);
		return NULL;
	}

	g2 = LWGEOM2GEOS((LWGEOM*)blade_in, 0);
	if ( NULL == g2 )
	{
		GEOSGeom_destroy(g1);
		GEOSGeom_destroy(g1_bounds);
		lwerror("LWGEOM2GEOS: %s", lwgeom_geos_errmsg);
		return NULL;
	}

	vgeoms[0] = GEOSUnion(g1_bounds, g2);
	if ( NULL == vgeoms[0] )
	{
		GEOSGeom_destroy(g1);
		GEOSGeom_destroy(g2);
		GEOSGeom_destroy(g1_bounds);
		lwerror("GEOSUnion: %s", lwgeom_geos_errmsg);
		return NULL;
	}

	polygons = GEOSPolygonize(vgeoms, 1);
	if ( NULL == polygons )
	{
		GEOSGeom_destroy(g1);
		GEOSGeom_destroy(g2);
		GEOSGeom_destroy(g1_bounds);
		GEOSGeom_destroy((GEOSGeometry*)vgeoms[0]);
		lwerror("GEOSPolygonize: %s", lwgeom_geos_errmsg);
		return NULL;
	}

#if PARANOIA_LEVEL > 0
	if ( GEOSGeomTypeId(polygons) != COLLECTIONTYPE )
	{
		GEOSGeom_destroy(g1);
		GEOSGeom_destroy(g2);
		GEOSGeom_destroy(g1_bounds);
		GEOSGeom_destroy((GEOSGeometry*)vgeoms[0]);
		GEOSGeom_destroy(polygons);
		lwerror("%s [%s] Unexpected return from GEOSpolygonize", __FILE__, __LINE__);
		return 0;
	}
#endif

	/* We should now have all polygons, just skip
	 * the ones which are in holes of the original
	 * geometries and return the rest in a collection
	 */
	n = GEOSGetNumGeometries(polygons);
	out = lwcollection_construct_empty(COLLECTIONTYPE, lwpoly_in->srid,
				     hasZ, 0);
	/* Allocate space for all polys */
	out->geoms = lwrealloc(out->geoms, sizeof(LWGEOM*)*n);
	assert(0 == out->ngeoms);
	for (i=0; i<n; ++i)
	{
		GEOSGeometry* pos; /* point on surface */
		const GEOSGeometry* p = GEOSGetGeometryN(polygons, i);
		int contains;

		pos = GEOSPointOnSurface(p);
		if ( ! pos )
		{
			GEOSGeom_destroy(g1);
			GEOSGeom_destroy(g2);
			GEOSGeom_destroy(g1_bounds);
			GEOSGeom_destroy((GEOSGeometry*)vgeoms[0]);
			GEOSGeom_destroy(polygons);
			lwerror("GEOSPointOnSurface: %s", lwgeom_geos_errmsg);
			return NULL;
		}

		contains = GEOSContains(g1, pos);
		if ( 2 == contains )
		{
			GEOSGeom_destroy(g1);
			GEOSGeom_destroy(g2);
			GEOSGeom_destroy(g1_bounds);
			GEOSGeom_destroy((GEOSGeometry*)vgeoms[0]);
			GEOSGeom_destroy(polygons);
			GEOSGeom_destroy(pos);
			lwerror("GEOSContains: %s", lwgeom_geos_errmsg);
			return NULL;
		}

		GEOSGeom_destroy(pos);

		if ( 0 == contains )
		{
			/* Original geometry doesn't contain
			 * a point in this ring, must be an hole
			 */
			continue;
		}

		out->geoms[out->ngeoms++] = GEOS2LWGEOM(p, hasZ);
	}

	GEOSGeom_destroy(g1);
	GEOSGeom_destroy(g2);
	GEOSGeom_destroy(g1_bounds);
	GEOSGeom_destroy((GEOSGeometry*)vgeoms[0]);
	GEOSGeom_destroy(polygons);

	return (LWGEOM*)out;
}
Esempio n. 14
0
  bool Layer::registerFeature( const char *geom_id, PalGeometry *userGeom, double label_x, double label_y, const char* labelText,
                               double labelPosX, double labelPosY, bool fixedPos, double angle, bool fixedAngle,
                               int xQuadOffset, int yQuadOffset, double xOffset, double yOffset )
  {
    if ( !geom_id || label_x < 0 || label_y < 0 )
      return false;

    modMutex->lock();

    if ( hashtable->find( geom_id ) )
    {
      modMutex->unlock();
      //A feature with this id already exists. Don't throw an exception as sometimes,
      //the same feature is added twice (dateline split with otf-reprojection)
      return false;
    }

    // Split MULTI GEOM and Collection in simple geometries
    GEOSGeometry *the_geom = userGeom->getGeosGeometry();

    Feature* f = new Feature( this, geom_id, userGeom, label_x, label_y );
    if ( fixedPos )
    {
      f->setFixedPosition( labelPosX, labelPosY );
    }
    if ( xQuadOffset != 0 || yQuadOffset != 0 )
    {
      f->setQuadOffset( xQuadOffset, yQuadOffset );
    }
    if ( xOffset != 0.0 || yOffset != 0.0 )
    {
      f->setPosOffset( xOffset, yOffset );
    }
    if ( fixedAngle )
    {
      f->setFixedAngle( angle );
    }
    // use layer-level defined rotation, but not if position fixed
    if ( !fixedPos && angle != 0.0 )
    {
      f->setFixedAngle( angle );
    }

    bool first_feat = true;

    double geom_size = -1, biggest_size = -1;
    FeaturePart* biggest_part = NULL;

    // break the (possibly multi-part) geometry into simple geometries
    LinkedList <const GEOSGeometry*> *simpleGeometries = unmulti( the_geom );
    if ( simpleGeometries == NULL ) // unmulti() failed?
    {
      modMutex->unlock();
      throw InternalException::UnknownGeometry();
    }

    while ( simpleGeometries->size() > 0 )
    {
      const GEOSGeometry* geom = simpleGeometries->pop_front();

      // ignore invalid geometries (e.g. polygons with self-intersecting rings)
      if ( GEOSisValid( geom ) != 1 ) // 0=invalid, 1=valid, 2=exception
      {
        std::cerr << "ignoring invalid feature " << geom_id << std::endl;
        continue;
      }

      int type = GEOSGeomTypeId( geom );

      if ( type != GEOS_POINT && type != GEOS_LINESTRING && type != GEOS_POLYGON )
      {
        modMutex->unlock();
        throw InternalException::UnknownGeometry();
      }

      FeaturePart* fpart = new FeaturePart( f, geom );

      // ignore invalid geometries
      if (( type == GEOS_LINESTRING && fpart->nbPoints < 2 ) ||
          ( type == GEOS_POLYGON && fpart->nbPoints < 3 ) )
      {
        delete fpart;
        continue;
      }

      // polygons: reorder coordinates
      if ( type == GEOS_POLYGON && reorderPolygon( fpart->nbPoints, fpart->x, fpart->y ) != 0 )
      {
        delete fpart;
        continue;
      }

      if ( mode == LabelPerFeature && ( type == GEOS_POLYGON || type == GEOS_LINESTRING ) )
      {
        if ( type == GEOS_LINESTRING )
          GEOSLength( geom, &geom_size );
        else if ( type == GEOS_POLYGON )
          GEOSArea( geom, &geom_size );

        if ( geom_size > biggest_size )
        {
          biggest_size = geom_size;
          delete biggest_part; // safe with NULL part
          biggest_part = fpart;
        }
        continue; // don't add the feature part now, do it later
        // TODO: we should probably add also other parts to act just as obstacles
      }

      // feature part is ready!
      addFeaturePart( fpart, labelText );

      first_feat = false;
    }
    delete simpleGeometries;

    userGeom->releaseGeosGeometry( the_geom );

    modMutex->unlock();

    // if using only biggest parts...
    if (( mode == LabelPerFeature || f->fixedPosition() ) && biggest_part != NULL )
    {
      addFeaturePart( biggest_part, labelText );
      first_feat = false;
    }

    // add feature to layer if we have added something
    if ( !first_feat )
    {
      features->push_back( f );
      hashtable->insertItem( geom_id, f );
    }
    else
    {
      delete f;
    }

    return !first_feat; // true if we've added something
  }
Esempio n. 15
0
static gaiaGeomCollPtr
fromGeosGeometry (const GEOSGeometry * geos, const int dimension_model)
{
/* converting a GEOS Geometry into a GAIA Geometry */
    int type;
    int itemType;
    unsigned int dims;
    int iv;
    int ib;
    int it;
    int sub_it;
    int nItems;
    int nSubItems;
    int holes;
    unsigned int points;
    double x;
    double y;
    double z;
    const GEOSCoordSequence *cs;
    const GEOSGeometry *geos_ring;
    const GEOSGeometry *geos_item;
    const GEOSGeometry *geos_sub_item;
    gaiaGeomCollPtr gaia = NULL;
    gaiaLinestringPtr ln;
    gaiaPolygonPtr pg;
    gaiaRingPtr rng;
    if (!geos)
	return NULL;
    type = GEOSGeomTypeId (geos);
    switch (type)
      {
      case GEOS_POINT:
	  if (dimension_model == GAIA_XY_Z)
	      gaia = gaiaAllocGeomCollXYZ ();
	  else if (dimension_model == GAIA_XY_M)
	      gaia = gaiaAllocGeomCollXYM ();
	  else if (dimension_model == GAIA_XY_Z_M)
	      gaia = gaiaAllocGeomCollXYZM ();
	  else
	      gaia = gaiaAllocGeomColl ();
	  gaia->DeclaredType = GAIA_POINT;
	  gaia->Srid = GEOSGetSRID (geos);
	  cs = GEOSGeom_getCoordSeq (geos);
	  GEOSCoordSeq_getDimensions (cs, &dims);
	  if (dims == 3)
	    {
		GEOSCoordSeq_getX (cs, 0, &x);
		GEOSCoordSeq_getY (cs, 0, &y);
		GEOSCoordSeq_getZ (cs, 0, &z);
	    }
	  else
	    {
		GEOSCoordSeq_getX (cs, 0, &x);
		GEOSCoordSeq_getY (cs, 0, &y);
		z = 0.0;
	    }
	  if (dimension_model == GAIA_XY_Z)
	      gaiaAddPointToGeomCollXYZ (gaia, x, y, z);
	  else if (dimension_model == GAIA_XY_M)
	      gaiaAddPointToGeomCollXYM (gaia, x, y, 0.0);
	  else if (dimension_model == GAIA_XY_Z_M)
	      gaiaAddPointToGeomCollXYZM (gaia, x, y, z, 0.0);
	  else
	      gaiaAddPointToGeomColl (gaia, x, y);
	  break;
      case GEOS_LINESTRING:
	  if (dimension_model == GAIA_XY_Z)
	      gaia = gaiaAllocGeomCollXYZ ();
	  else if (dimension_model == GAIA_XY_M)
	      gaia = gaiaAllocGeomCollXYM ();
	  else if (dimension_model == GAIA_XY_Z_M)
	      gaia = gaiaAllocGeomCollXYZM ();
	  else
	      gaia = gaiaAllocGeomColl ();
	  gaia->DeclaredType = GAIA_LINESTRING;
	  gaia->Srid = GEOSGetSRID (geos);
	  cs = GEOSGeom_getCoordSeq (geos);
	  GEOSCoordSeq_getDimensions (cs, &dims);
	  GEOSCoordSeq_getSize (cs, &points);
	  ln = gaiaAddLinestringToGeomColl (gaia, points);
	  for (iv = 0; iv < (int) points; iv++)
	    {
		if (dims == 3)
		  {
		      GEOSCoordSeq_getX (cs, iv, &x);
		      GEOSCoordSeq_getY (cs, iv, &y);
		      GEOSCoordSeq_getZ (cs, iv, &z);
		  }
		else
		  {
		      GEOSCoordSeq_getX (cs, iv, &x);
		      GEOSCoordSeq_getY (cs, iv, &y);
		      z = 0.0;
		  }
		if (dimension_model == GAIA_XY_Z)
		  {
		      gaiaSetPointXYZ (ln->Coords, iv, x, y, z);
		  }
		else if (dimension_model == GAIA_XY_M)
		  {
		      gaiaSetPointXYM (ln->Coords, iv, x, y, 0.0);
		  }
		else if (dimension_model == GAIA_XY_Z_M)
		  {
		      gaiaSetPointXYZM (ln->Coords, iv, x, y, z, 0.0);
		  }
		else
		  {
		      gaiaSetPoint (ln->Coords, iv, x, y);
		  }
	    }
	  break;
      case GEOS_POLYGON:
	  if (dimension_model == GAIA_XY_Z)
	      gaia = gaiaAllocGeomCollXYZ ();
	  else if (dimension_model == GAIA_XY_M)
	      gaia = gaiaAllocGeomCollXYM ();
	  else if (dimension_model == GAIA_XY_Z_M)
	      gaia = gaiaAllocGeomCollXYZM ();
	  else
	      gaia = gaiaAllocGeomColl ();
	  gaia->DeclaredType = GAIA_POLYGON;
	  gaia->Srid = GEOSGetSRID (geos);
	  /* exterior ring */
	  holes = GEOSGetNumInteriorRings (geos);
	  geos_ring = GEOSGetExteriorRing (geos);
	  cs = GEOSGeom_getCoordSeq (geos_ring);
	  GEOSCoordSeq_getDimensions (cs, &dims);
	  GEOSCoordSeq_getSize (cs, &points);
	  pg = gaiaAddPolygonToGeomColl (gaia, points, holes);
	  rng = pg->Exterior;
	  for (iv = 0; iv < (int) points; iv++)
	    {
		if (dims == 3)
		  {
		      GEOSCoordSeq_getX (cs, iv, &x);
		      GEOSCoordSeq_getY (cs, iv, &y);
		      GEOSCoordSeq_getZ (cs, iv, &z);
		  }
		else
		  {
		      GEOSCoordSeq_getX (cs, iv, &x);
		      GEOSCoordSeq_getY (cs, iv, &y);
		      z = 0.0;
		  }
		if (dimension_model == GAIA_XY_Z)
		  {
		      gaiaSetPointXYZ (rng->Coords, iv, x, y, z);
		  }
		else if (dimension_model == GAIA_XY_M)
		  {
		      gaiaSetPointXYM (rng->Coords, iv, x, y, 0.0);
		  }
		else if (dimension_model == GAIA_XY_Z_M)
		  {
		      gaiaSetPointXYZM (rng->Coords, iv, x, y, z, 0.0);
		  }
		else
		  {
		      gaiaSetPoint (rng->Coords, iv, x, y);
		  }
	    }
	  for (ib = 0; ib < holes; ib++)
	    {
		/* interior rings */
		geos_ring = GEOSGetInteriorRingN (geos, ib);
		cs = GEOSGeom_getCoordSeq (geos_ring);
		GEOSCoordSeq_getDimensions (cs, &dims);
		GEOSCoordSeq_getSize (cs, &points);
		rng = gaiaAddInteriorRing (pg, ib, points);
		for (iv = 0; iv < (int) points; iv++)
		  {
		      if (dims == 3)
			{
			    GEOSCoordSeq_getX (cs, iv, &x);
			    GEOSCoordSeq_getY (cs, iv, &y);
			    GEOSCoordSeq_getZ (cs, iv, &z);
			}
		      else
			{
			    GEOSCoordSeq_getX (cs, iv, &x);
			    GEOSCoordSeq_getY (cs, iv, &y);
			    z = 0.0;
			}
		      if (dimension_model == GAIA_XY_Z)
			{
			    gaiaSetPointXYZ (rng->Coords, iv, x, y, z);
			}
		      else if (dimension_model == GAIA_XY_M)
			{
			    gaiaSetPointXYM (rng->Coords, iv, x, y, 0.0);
			}
		      else if (dimension_model == GAIA_XY_Z_M)
			{
			    gaiaSetPointXYZM (rng->Coords, iv, x, y, z, 0.0);
			}
		      else
			{
			    gaiaSetPoint (rng->Coords, iv, x, y);
			}
		  }
	    }
	  break;
      case GEOS_MULTIPOINT:
      case GEOS_MULTILINESTRING:
      case GEOS_MULTIPOLYGON:
      case GEOS_GEOMETRYCOLLECTION:
	  if (dimension_model == GAIA_XY_Z)
	      gaia = gaiaAllocGeomCollXYZ ();
	  else if (dimension_model == GAIA_XY_M)
	      gaia = gaiaAllocGeomCollXYM ();
	  else if (dimension_model == GAIA_XY_Z_M)
	      gaia = gaiaAllocGeomCollXYZM ();
	  else
	      gaia = gaiaAllocGeomColl ();
	  if (type == GEOS_MULTIPOINT)
	      gaia->DeclaredType = GAIA_MULTIPOINT;
	  else if (type == GEOS_MULTILINESTRING)
	      gaia->DeclaredType = GAIA_MULTILINESTRING;
	  else if (type == GEOS_MULTIPOLYGON)
	      gaia->DeclaredType = GAIA_MULTIPOLYGON;
	  else
	      gaia->DeclaredType = GAIA_GEOMETRYCOLLECTION;
	  gaia->Srid = GEOSGetSRID (geos);
	  nItems = GEOSGetNumGeometries (geos);
	  for (it = 0; it < nItems; it++)
	    {
		/* looping on elementaty geometries */
		geos_item = GEOSGetGeometryN (geos, it);
		itemType = GEOSGeomTypeId (geos_item);
		switch (itemType)
		  {
		  case GEOS_POINT:
		      cs = GEOSGeom_getCoordSeq (geos_item);
		      GEOSCoordSeq_getDimensions (cs, &dims);
		      if (dims == 3)
			{
			    GEOSCoordSeq_getX (cs, 0, &x);
			    GEOSCoordSeq_getY (cs, 0, &y);
			    GEOSCoordSeq_getZ (cs, 0, &z);
			}
		      else
			{
			    GEOSCoordSeq_getX (cs, 0, &x);
			    GEOSCoordSeq_getY (cs, 0, &y);
			    z = 0.0;
			}
		      if (dimension_model == GAIA_XY_Z)
			  gaiaAddPointToGeomCollXYZ (gaia, x, y, z);
		      else if (dimension_model == GAIA_XY_M)
			  gaiaAddPointToGeomCollXYM (gaia, x, y, 0.0);
		      else if (dimension_model == GAIA_XY_Z_M)
			  gaiaAddPointToGeomCollXYZM (gaia, x, y, z, 0.0);
		      else
			  gaiaAddPointToGeomColl (gaia, x, y);
		      break;
		  case GEOS_LINESTRING:
		      cs = GEOSGeom_getCoordSeq (geos_item);
		      GEOSCoordSeq_getDimensions (cs, &dims);
		      GEOSCoordSeq_getSize (cs, &points);
		      ln = gaiaAddLinestringToGeomColl (gaia, points);
		      for (iv = 0; iv < (int) points; iv++)
			{
			    if (dims == 3)
			      {
				  GEOSCoordSeq_getX (cs, iv, &x);
				  GEOSCoordSeq_getY (cs, iv, &y);
				  GEOSCoordSeq_getZ (cs, iv, &z);
			      }
			    else
			      {
				  GEOSCoordSeq_getX (cs, iv, &x);
				  GEOSCoordSeq_getY (cs, iv, &y);
				  z = 0.0;
			      }
			    if (dimension_model == GAIA_XY_Z)
			      {
				  gaiaSetPointXYZ (ln->Coords, iv, x, y, z);
			      }
			    else if (dimension_model == GAIA_XY_M)
			      {
				  gaiaSetPointXYM (ln->Coords, iv, x, y, 0.0);
			      }
			    else if (dimension_model == GAIA_XY_Z_M)
			      {
				  gaiaSetPointXYZM (ln->Coords, iv, x, y, z,
						    0.0);
			      }
			    else
			      {
				  gaiaSetPoint (ln->Coords, iv, x, y);
			      }
			}
		      break;
		  case GEOS_MULTILINESTRING:
		      nSubItems = GEOSGetNumGeometries (geos_item);
		      for (sub_it = 0; sub_it < nSubItems; sub_it++)
			{
			    /* looping on elementaty geometries */
			    geos_sub_item =
				GEOSGetGeometryN (geos_item, sub_it);
			    cs = GEOSGeom_getCoordSeq (geos_sub_item);
			    GEOSCoordSeq_getDimensions (cs, &dims);
			    GEOSCoordSeq_getSize (cs, &points);
			    ln = gaiaAddLinestringToGeomColl (gaia, points);
			    for (iv = 0; iv < (int) points; iv++)
			      {
				  if (dims == 3)
				    {
					GEOSCoordSeq_getX (cs, iv, &x);
					GEOSCoordSeq_getY (cs, iv, &y);
					GEOSCoordSeq_getZ (cs, iv, &z);
				    }
				  else
				    {
					GEOSCoordSeq_getX (cs, iv, &x);
					GEOSCoordSeq_getY (cs, iv, &y);
					z = 0.0;
				    }
				  if (dimension_model == GAIA_XY_Z)
				    {
					gaiaSetPointXYZ (ln->Coords, iv, x, y,
							 z);
				    }
				  else if (dimension_model == GAIA_XY_M)
				    {
					gaiaSetPointXYM (ln->Coords, iv, x, y,
							 0.0);
				    }
				  else if (dimension_model == GAIA_XY_Z_M)
				    {
					gaiaSetPointXYZM (ln->Coords, iv, x, y,
							  z, 0.0);
				    }
				  else
				    {
					gaiaSetPoint (ln->Coords, iv, x, y);
				    }
			      }
			}
		      break;
		  case GEOS_POLYGON:
		      /* exterior ring */
		      holes = GEOSGetNumInteriorRings (geos_item);
		      geos_ring = GEOSGetExteriorRing (geos_item);
		      cs = GEOSGeom_getCoordSeq (geos_ring);
		      GEOSCoordSeq_getDimensions (cs, &dims);
		      GEOSCoordSeq_getSize (cs, &points);
		      pg = gaiaAddPolygonToGeomColl (gaia, points, holes);
		      rng = pg->Exterior;
		      for (iv = 0; iv < (int) points; iv++)
			{
			    if (dims == 3)
			      {
				  GEOSCoordSeq_getX (cs, iv, &x);
				  GEOSCoordSeq_getY (cs, iv, &y);
				  GEOSCoordSeq_getZ (cs, iv, &z);
			      }
			    else
			      {
				  GEOSCoordSeq_getX (cs, iv, &x);
				  GEOSCoordSeq_getY (cs, iv, &y);
				  z = 0.0;
			      }
			    if (dimension_model == GAIA_XY_Z)
			      {
				  gaiaSetPointXYZ (rng->Coords, iv, x, y, z);
			      }
			    else if (dimension_model == GAIA_XY_M)
			      {
				  gaiaSetPointXYM (rng->Coords, iv, x, y, 0.0);
			      }
			    else if (dimension_model == GAIA_XY_Z_M)
			      {
				  gaiaSetPointXYZM (rng->Coords, iv, x, y, z,
						    0.0);
			      }
			    else
			      {
				  gaiaSetPoint (rng->Coords, iv, x, y);
			      }
			}
		      for (ib = 0; ib < holes; ib++)
			{
			    /* interior rings */
			    geos_ring = GEOSGetInteriorRingN (geos_item, ib);
			    cs = GEOSGeom_getCoordSeq (geos_ring);
			    GEOSCoordSeq_getDimensions (cs, &dims);
			    GEOSCoordSeq_getSize (cs, &points);
			    rng = gaiaAddInteriorRing (pg, ib, points);
			    for (iv = 0; iv < (int) points; iv++)
			      {
				  if (dims == 3)
				    {
					GEOSCoordSeq_getX (cs, iv, &x);
					GEOSCoordSeq_getY (cs, iv, &y);
					GEOSCoordSeq_getZ (cs, iv, &z);
				    }
				  else
				    {
					GEOSCoordSeq_getX (cs, iv, &x);
					GEOSCoordSeq_getY (cs, iv, &y);
					z = 0.0;
				    }
				  if (dimension_model == GAIA_XY_Z)
				    {
					gaiaSetPointXYZ (rng->Coords, iv, x, y,
							 z);
				    }
				  else if (dimension_model == GAIA_XY_M)
				    {
					gaiaSetPointXYM (rng->Coords, iv, x, y,
							 0.0);
				    }
				  else if (dimension_model == GAIA_XY_Z_M)
				    {
					gaiaSetPointXYZM (rng->Coords, iv, x, y,
							  z, 0.0);
				    }
				  else
				    {
					gaiaSetPoint (rng->Coords, iv, x, y);
				    }
			      }
			}
		      break;
		  };
	    }
	  break;
      };
    return gaia;
}
Esempio n. 16
0
static int geom2ring(GEOSGeometry *geom, struct Map_info *Out,
                     struct Map_info *Buf,
                     struct spatial_index *si,
		     struct line_cats *Cats,
		     struct buf_contours **arr_bc,
		     int *buffers_count, int *arr_bc_alloc)
{
    int i, nrings, ngeoms, line_id;
    const GEOSGeometry *geom2;
    struct bound_box bbox;
    static struct line_pnts *Points = NULL;
    static struct line_cats *BCats = NULL;
    struct buf_contours *p = *arr_bc;

    G_debug(3, "geom2ring(): GEOS %s", GEOSGeomType(geom));

    if (!Points)
	Points = Vect_new_line_struct();
    if (!BCats)
	BCats = Vect_new_cats_struct();

    if (GEOSGeomTypeId(geom) == GEOS_LINESTRING ||
        GEOSGeomTypeId(geom) == GEOS_LINEARRING) {

	if (!ring2pts(geom, Points))
	    return 0;

	Vect_write_line(Out, GV_BOUNDARY, Points, BCats);
	line_id = Vect_write_line(Buf, GV_BOUNDARY, Points, Cats);
	/* add buffer to spatial index */
	Vect_get_line_box(Buf, line_id, &bbox);
	Vect_spatial_index_add_item(si, *buffers_count, &bbox);
	p[*buffers_count].outer = line_id;

	p[*buffers_count].inner_count = 0;
	*buffers_count += 1;
	if (*buffers_count >= *arr_bc_alloc) {
	    *arr_bc_alloc += 100;
	    p = G_realloc(p, *arr_bc_alloc * sizeof(struct buf_contours));
	    *arr_bc = p;
	}
    }
    else if (GEOSGeomTypeId(geom) == GEOS_POLYGON) {
	geom2 = GEOSGetExteriorRing(geom);
	if (!ring2pts(geom2, Points))
	    return 0;

	Vect_write_line(Out, GV_BOUNDARY, Points, BCats);
	line_id = Vect_write_line(Buf, GV_BOUNDARY, Points, Cats);
	/* add buffer to spatial index */
	Vect_get_line_box(Buf, line_id, &bbox);
	Vect_spatial_index_add_item(si, *buffers_count, &bbox);
	p[*buffers_count].outer = line_id;
	p[*buffers_count].inner_count = 0;

	nrings = GEOSGetNumInteriorRings(geom);
	
	if (nrings > 0) {

	    p[*buffers_count].inner_count = nrings;
	    p[*buffers_count].inner = G_malloc(nrings * sizeof(int));

	    for (i = 0; i < nrings; i++) {
		geom2 = GEOSGetInteriorRingN(geom, i);
		if (!ring2pts(geom2, Points)) {
		    G_fatal_error(_("Corrupt GEOS geometry"));
		}
		Vect_write_line(Out, GV_BOUNDARY, Points, BCats);
		line_id = Vect_write_line(Buf, GV_BOUNDARY, Points, BCats);
		p[*buffers_count].inner[i] = line_id;
	    }
	}
	*buffers_count += 1;
	if (*buffers_count >= *arr_bc_alloc) {
	    *arr_bc_alloc += 100;
	    p = G_realloc(p, *arr_bc_alloc * sizeof(struct buf_contours));
	    *arr_bc = p;
	}
    }
    else if (GEOSGeomTypeId(geom) == GEOS_MULTILINESTRING ||
             GEOSGeomTypeId(geom) == GEOS_MULTIPOLYGON ||
	     GEOSGeomTypeId(geom) == GEOS_GEOMETRYCOLLECTION) {

	G_debug(3, "GEOS %s", GEOSGeomType(geom));

	ngeoms = GEOSGetNumGeometries(geom);
	for (i = 0; i < ngeoms; i++) {
	    geom2 = GEOSGetGeometryN(geom, i);
	    geom2ring((GEOSGeometry *)geom2, Out, Buf, si, Cats,
	              arr_bc, buffers_count, arr_bc_alloc);
	}
    }
    else
	G_fatal_error(_("Unknown GEOS geometry type"));

    return 1;
}
void VertexSnapper::editGeometry( MyGEOSGeom *geom, GEOSCoordSequence *coord )
{
    // edit geometry according to coord -> GeometryEditor and GeometryEditorOperation/interface classes ??????

    qDebug("VertexSnapper::editGeometry: ENTERING EDIT GEOMETRY");

    // new geometry
    GEOSGeometry *newGeom = NULL;
    GEOSGeometry *ring = NULL;

    // change geometry according to its type  // NOTE: improve this according to http://trac.osgeo.org/geos/browser/trunk/tests/geostest/geostest.c - fineGrainedReconstructionTest
    int type = GEOSGeomTypeId( geom->getGEOSGeom() );
    switch ( type )
    {
        case GEOS_POINT:
            newGeom = GEOSGeom_createPoint( coord );
            break;
        case GEOS_LINESTRING:
            newGeom = GEOSGeom_createLineString( coord );
            break;
        case GEOS_LINEARRING:
            newGeom = GEOSGeom_createLinearRing( coord );
            break;
        case GEOS_POLYGON:
            ring = GEOSGeom_createLinearRing( coord ); // NOTE: Fails if polygon has holes
            newGeom = GEOSGeom_createPolygon( ring, NULL, 0 );
            break;
        case GEOS_MULTIPOINT:
            newGeom = GEOSGeom_createEmptyCollection(4);
            qDebug("VertexSnapper::editGeometry: Multi geometry is not supported yet.");
            break;
        case GEOS_MULTILINESTRING:
            newGeom = GEOSGeom_createEmptyCollection(5);
            qDebug("VertexSnapper::editGeometry: Multi geometry is not supported yet.");
            break;
        case GEOS_MULTIPOLYGON:
            newGeom = GEOSGeom_createEmptyCollection(6);
            qDebug("VertexSnapper::editGeometry: Multi geometry is not supported yet.");
            break;
        case GEOS_GEOMETRYCOLLECTION:
            newGeom = GEOSGeom_createEmptyCollection(7);
            qDebug("VertexSnapper::editGeometry: Multi geometry is not supported yet.");
            break;
        default:
            qDebug("VertexSnapper::editGeometry: Unknown geometry type.");
    }


    // return edited geometry
    geom->setGEOSGeom( newGeom );


    if( GEOSisEmpty( geom->getGEOSGeom() ) )
        qDebug("VertexSnapper::editGeometry: Geom is empty.");

    if( GEOSisValid( geom->getGEOSGeom() ) )
        qDebug("VertexSnapper::editGeometry: Geom is valid.");


    //GEOSGeom_destroy(newGeom);


} // void VertexSnapper::editGeometry( MyGEOSGeom &geom, CoordinateSequence &coord )
Esempio n. 18
0
/* Return an LWGEOM from a Geometry */
LWGEOM *
GEOS2LWGEOM(const GEOSGeometry *geom, char want3d)
{
	int type = GEOSGeomTypeId(geom) ;
	int hasZ;
	int SRID = GEOSGetSRID(geom);

	/* GEOS's 0 is equivalent to our unknown as for SRID values */
	if ( SRID == 0 ) SRID = SRID_UNKNOWN;

	if ( want3d )
	{
		hasZ = GEOSHasZ(geom);
		if ( ! hasZ )
		{
			LWDEBUG(3, "Geometry has no Z, won't provide one");

			want3d = 0;
		}
	}

/*
	if ( GEOSisEmpty(geom) )
	{
		return (LWGEOM*)lwcollection_construct_empty(COLLECTIONTYPE, SRID, want3d, 0);
	}
*/

	switch (type)
	{
		const GEOSCoordSequence *cs;
		POINTARRAY *pa, **ppaa;
		const GEOSGeometry *g;
		LWGEOM **geoms;
		uint32_t i, ngeoms;

	case GEOS_POINT:
		LWDEBUG(4, "lwgeom_from_geometry: it's a Point");
		cs = GEOSGeom_getCoordSeq(geom);
		if ( GEOSisEmpty(geom) )
		  return (LWGEOM*)lwpoint_construct_empty(SRID, want3d, 0);
		pa = ptarray_from_GEOSCoordSeq(cs, want3d);
		return (LWGEOM *)lwpoint_construct(SRID, NULL, pa);

	case GEOS_LINESTRING:
	case GEOS_LINEARRING:
		LWDEBUG(4, "lwgeom_from_geometry: it's a LineString or LinearRing");
		if ( GEOSisEmpty(geom) )
		  return (LWGEOM*)lwline_construct_empty(SRID, want3d, 0);

		cs = GEOSGeom_getCoordSeq(geom);
		pa = ptarray_from_GEOSCoordSeq(cs, want3d);
		return (LWGEOM *)lwline_construct(SRID, NULL, pa);

	case GEOS_POLYGON:
		LWDEBUG(4, "lwgeom_from_geometry: it's a Polygon");
		if ( GEOSisEmpty(geom) )
		  return (LWGEOM*)lwpoly_construct_empty(SRID, want3d, 0);
		ngeoms = GEOSGetNumInteriorRings(geom);
		ppaa = lwalloc(sizeof(POINTARRAY *)*(ngeoms+1));
		g = GEOSGetExteriorRing(geom);
		cs = GEOSGeom_getCoordSeq(g);
		ppaa[0] = ptarray_from_GEOSCoordSeq(cs, want3d);
		for (i=0; i<ngeoms; i++)
		{
			g = GEOSGetInteriorRingN(geom, i);
			cs = GEOSGeom_getCoordSeq(g);
			ppaa[i+1] = ptarray_from_GEOSCoordSeq(cs,
			                                      want3d);
		}
		return (LWGEOM *)lwpoly_construct(SRID, NULL,
		                                  ngeoms+1, ppaa);

	case GEOS_MULTIPOINT:
	case GEOS_MULTILINESTRING:
	case GEOS_MULTIPOLYGON:
	case GEOS_GEOMETRYCOLLECTION:
		LWDEBUG(4, "lwgeom_from_geometry: it's a Collection or Multi");

		ngeoms = GEOSGetNumGeometries(geom);
		geoms = NULL;
		if ( ngeoms )
		{
			geoms = lwalloc(sizeof(LWGEOM *)*ngeoms);
			for (i=0; i<ngeoms; i++)
			{
				g = GEOSGetGeometryN(geom, i);
				geoms[i] = GEOS2LWGEOM(g, want3d);
			}
		}
		return (LWGEOM *)lwcollection_construct(type,
		                                        SRID, NULL, ngeoms, geoms);

	default:
		lwerror("GEOS2LWGEOM: unknown geometry type: %d", type);
		return NULL;

	}

}