Beispiel #1
0
ERL_NIF_TERM
geom_to_eterm_polygon_coords(ErlNifEnv *env, const GEOSGeometry *geom)
{
    unsigned int inner_num, i;
    const GEOSGeometry *outer, *inner;
    const GEOSCoordSequence *coords_seq;
    ERL_NIF_TERM coords;
    ERL_NIF_TERM *rings;

    inner_num = GEOSGetNumInteriorRings(geom);
    // all rings, outer + inner
    rings = malloc(sizeof(ERL_NIF_TERM)*inner_num+1);

    outer = GEOSGetExteriorRing(geom);
    coords_seq = GEOSGeom_getCoordSeq(outer);
    rings[0] = GEOSCoordSequence_to_eterm_list(env, coords_seq,
        GEOSGetNumCoordinates(outer));

    for (i=0; i<inner_num; i++) {
        inner = GEOSGetInteriorRingN(geom, i);
        coords_seq = GEOSGeom_getCoordSeq(inner);
        rings[i+1] = GEOSCoordSequence_to_eterm_list(env,
            coords_seq, GEOSGetNumCoordinates(inner));
    }
    coords = enif_make_list_from_array(env, rings, inner_num+1);
    free(rings);
    return coords;
}
    static size_t
asgeojson_multipolygon_size(GEOSGeom mpoly, char *srs, bbox3D *bbox, int precision)
{
    GEOSGeom poly;
    int size;
    int i, j, ngeoms = GEOSGetNumGeometries(mpoly);

    size = sizeof("{'type':'MultiPolygon',");
    if (srs) size += asgeojson_srs_size(srs);
    if (bbox) size += asgeojson_bbox_size(GEOS_getWKBOutputDims(mpoly) == 3, precision);
    size += sizeof("'coordinates':[]}");

    for (i=0; i < ngeoms; i++)
    {
        int nrings;
        poly = (GEOSGeom ) GEOSGetGeometryN(mpoly, i);
        nrings = GEOSGetNumInteriorRings(poly);
        for (j=0 ; j <nrings ; j++)
        {
            size += points_geojson_size(*(GEOSGeom*)GEOSGetInteriorRingN(poly, j), precision);
            size += sizeof("[]");
        }
        size += sizeof("[]");
    }
    size += sizeof(",") * i;
    size += sizeof("]}");

    return size;
}
    static size_t
asgeojson_multipolygon_buf(GEOSGeom mpoly, char *srs, char *output, bbox3D *bbox, int precision)
{
    GEOSGeom poly;
    int i, j, ngeoms = GEOSGetNumGeometries(mpoly);
    char *ptr=output;

    ptr += sprintf(ptr, "{\"type\":\"MultiPolygon\",");
    if (srs) ptr += asgeojson_srs_buf(ptr, srs);
    if (bbox) ptr += asgeojson_bbox_buf(ptr, bbox, GEOS_getWKBOutputDims(mpoly) == 3, precision);
    ptr += sprintf(ptr, "\"coordinates\":[");
    for (i=0; i<ngeoms; i++)
    {
        int nrings; 
        if (i) ptr += sprintf(ptr, ",");
        ptr += sprintf(ptr, "[");
        poly = (GEOSGeom ) GEOSGetGeometryN(mpoly, i);
        nrings = GEOSGetNumInteriorRings(poly);
        for (j=0 ; j < nrings ; j++)
        {
            if (j) ptr += sprintf(ptr, ",");
            ptr += sprintf(ptr, "[");
            ptr += points_to_geojson(*(GEOSGeom*)GEOSGetInteriorRingN(poly, j), ptr, precision);
            ptr += sprintf(ptr, "]");
        }
        ptr += sprintf(ptr, "]");
    }
    ptr += sprintf(ptr, "]}");

    return (ptr - output);
}
Beispiel #4
0
/* Find holes of each face */
static void
findFaceHoles(Face** faces, int nfaces)
{
  int i, j, h;

  /* We sort by envelope area so that we know holes are only
   * after their shells */
  qsort(faces, nfaces, sizeof(Face*), compare_by_envarea);
  for (i=0; i<nfaces; ++i) {
    Face* f = faces[i];
    int nholes = GEOSGetNumInteriorRings(f->geom);
    LWDEBUGF(2, "Scanning face %d with env area %g and %d holes", i, f->envarea, nholes);
    for (h=0; h<nholes; ++h) {
      const GEOSGeometry *hole = GEOSGetInteriorRingN(f->geom, h);
      LWDEBUGF(2, "Looking for hole %d/%d of face %d among %d other faces", h+1, nholes, i, nfaces-i-1);
      for (j=i+1; j<nfaces; ++j) {
        Face* f2 = faces[j];
        if ( f2->parent ) continue; /* hole already assigned */
        const GEOSGeometry *f2er = GEOSGetExteriorRing(f2->geom); 
        /* TODO: can be optimized as the ring would have the
         *       same vertices, possibly in different order.
         *       maybe comparing number of points could already be
         *       useful.
         */
        if ( GEOSEquals(f2er, hole) ) {
          LWDEBUGF(2, "Hole %d/%d of face %d is face %d", h+1, nholes, i, j);
          f2->parent = f;
          break;
        }
      }
    }
  }
}
Beispiel #5
0
static shapeObj *msGEOSGeometry2Shape_polygon(GEOSGeom g)
{
  shapeObj *shape=NULL;
  lineObj line;
  int numPoints, numRings;
  int i, j;

  GEOSCoordSeq coords;
  GEOSGeom ring;

  if(!g) return NULL;

  shape = (shapeObj *) malloc(sizeof(shapeObj));
  msInitShape(shape);
  shape->type = MS_SHAPE_POLYGON;
  shape->geometry = (GEOSGeom) g;

  /* exterior ring */
  ring = (GEOSGeom) GEOSGetExteriorRing(g);
  numPoints = GEOSGetNumCoordinates(ring);
  coords = (GEOSCoordSeq) GEOSGeom_getCoordSeq(ring);
  
  line.point = (pointObj *) malloc(sizeof(pointObj)*numPoints);
  line.numpoints = numPoints;

  for(i=0; i<numPoints; i++) {
    GEOSCoordSeq_getX(coords, i, &(line.point[i].x));
    GEOSCoordSeq_getY(coords, i, &(line.point[i].y));
    /* GEOSCoordSeq_getZ(coords, i, &(line.point[i].z)); */    
  }
  msAddLineDirectly(shape, &line);

  /* interior rings */
  numRings = GEOSGetNumInteriorRings(g);
  for(j=0; j<numRings; j++) {
    ring = (GEOSGeom) GEOSGetInteriorRingN(g, j);
    if(GEOSisRing(ring) != 1) continue; /* skip it */

    numPoints = GEOSGetNumCoordinates(ring);
    coords = (GEOSCoordSeq) GEOSGeom_getCoordSeq(ring);

    line.point = (pointObj *) malloc(sizeof(pointObj)*numPoints);
    line.numpoints = numPoints;

    for(i=0; i<numPoints; i++) {
      GEOSCoordSeq_getX(coords, i, &(line.point[i].x));
      GEOSCoordSeq_getY(coords, i, &(line.point[i].y));
      /* GEOSCoordSeq_getZ(coords, i, &(line.point[i].z)); */
    }
    msAddLineDirectly(shape, &line);
  }

  msComputeBounds(shape); 

  return shape;
}
Beispiel #6
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_poly_size(GEOSGeom poly, char *srs, bbox3D *bbox, int precision)
{
    size_t size;
    int i, nrings = GEOSGetNumInteriorRings(poly);

    size = sizeof("{\"type\":\"Polygon\",");
    if (srs) size += asgeojson_srs_size(srs);
    if (bbox) size += asgeojson_bbox_size(GEOS_getWKBOutputDims(poly) == 3, precision);
    size += sizeof("\"coordinates\":[");
    for (i=0; i<nrings; i++)
    {
        size += points_geojson_size(*(GEOSGeom*)GEOSGetInteriorRingN(poly, i), precision);
        size += sizeof("[]");
    }
    size += sizeof(",") * i;
    size += sizeof("]}");

    return size;
}
    static size_t
asgeojson_poly_buf(GEOSGeom poly, char *srs, char *output, bbox3D *bbox, int precision)
{
    int i, nrings = GEOSGetNumInteriorRings(poly);
    char *ptr=output;

    ptr += sprintf(ptr, "{\"type\":\"Polygon\",");
    if (srs) ptr += asgeojson_srs_buf(ptr, srs);
    if (bbox) ptr += asgeojson_bbox_buf(ptr, bbox, GEOS_getWKBOutputDims(poly) == 3, precision);
    ptr += sprintf(ptr, "\"coordinates\":[");
    for (i=0; i<nrings; i++)
    {
        if (i) ptr += sprintf(ptr, ",");
        ptr += sprintf(ptr, "[");
        ptr += points_to_geojson(*(GEOSGeom*) GEOSGetInteriorRingN(poly, i), ptr, precision);
        ptr += sprintf(ptr, "]");
    }
    ptr += sprintf(ptr, "]}");

    return (ptr-output);
}
Beispiel #9
0
static YAP_Bool make_polygon_to_term (geometry_t geometry,
                                        const char * functor_name,
                                        YAP_Term *term)
{
  int n;
  geometry_t ring;
  sequence_t sequence;
  YAP_Functor functor;
  unsigned int size;
  YAP_Term head;

  assert (term != NULL);
  *term = YAP_MkAtomTerm (YAP_LookupAtom ("[]"));
  size = GEOSGetNumInteriorRings (geometry);
  for (n = size - 1; n >= 0; n --)
    {
      ring = (geometry_t) GEOSGetInteriorRingN (geometry, n);
      sequence = (sequence_t) GEOSGeom_getCoordSeq (ring);
      if ((sequence == NULL)
          || (point_list_to_term (sequence, &head) == FALSE))
        return (FALSE);
      *term = YAP_MkPairTerm (head, *term);
    }
  /* Exterior ring always exists. */
  ring = (geometry_t) GEOSGetExteriorRing (geometry);
  if (ring == NULL)
    return (FALSE);
  sequence = (sequence_t) GEOSGeom_getCoordSeq (ring);
  if ((sequence == NULL)
      || (point_list_to_term (sequence, &head) == FALSE))
    return (FALSE);
  *term = YAP_MkPairTerm (head, *term);

  if (functor_name != NULL)
    {
      functor = YAP_MkFunctor (YAP_LookupAtom (NAME_POLYGON), 1);
      *term = YAP_MkApplTerm (functor, 1, term);
    }
  return (TRUE);
}
Beispiel #10
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;

	}

}
Beispiel #11
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;
}
Beispiel #12
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;
}