Esempio n. 1
0
BOX3D Polygon::bounds() const
{
    uint32_t numInputDims;
    BOX3D output;

    GEOSGeometry* boundary = GEOSGeom_clone_r(m_ctx, m_geom);

    // Smash out multi*
    if (GEOSGeomTypeId_r(m_ctx, m_geom) > 3)
        boundary = GEOSEnvelope_r(m_ctx, m_geom);

    GEOSGeometry const* ring = GEOSGetExteriorRing_r(m_ctx, boundary);
    GEOSCoordSequence const* coords = GEOSGeom_getCoordSeq_r(m_ctx, ring);

    GEOSCoordSeq_getDimensions_r(m_ctx, coords, &numInputDims);

    uint32_t count(0);
    GEOSCoordSeq_getSize_r(m_ctx, coords, &count);

    double x(0.0);
    double y(0.0);
    double z(0.0);
    for (unsigned i = 0; i < count; ++i)
    {
        GEOSCoordSeq_getOrdinate_r(m_ctx, coords, i, 0, &x);
        GEOSCoordSeq_getOrdinate_r(m_ctx, coords, i, 1, &y);
        if (numInputDims > 2)
            GEOSCoordSeq_getOrdinate_r(m_ctx, coords, i, 2, &z);
        output.grow(x, y, z);
    }
    GEOSGeom_destroy_r(m_ctx, boundary);

    return output;
}
Esempio n. 2
0
static VALUE method_geometry_initialize_copy(VALUE self, VALUE orig)
{
  // Clear out any existing value
  RGeo_GeometryData* self_data = RGEO_GEOMETRY_DATA_PTR(self);
  GEOSGeometry* self_geom = self_data->geom;
  if (self_geom) {
    GEOSGeom_destroy_r(self_data->geos_context, self_geom);
    self_data->geom = NULL;
    self_data->geos_context = NULL;
    self_data->factory = Qnil;
    self_data->klasses = Qnil;
  }
  
  // Copy value from orig
  const GEOSGeometry* geom = rgeo_get_geos_geometry_safe(orig);
  if (geom) {
    RGeo_GeometryData* orig_data = RGEO_GEOMETRY_DATA_PTR(orig);
    GEOSContextHandle_t orig_context = orig_data->geos_context;
    GEOSGeometry* clone_geom = GEOSGeom_clone_r(orig_context, geom);
    if (clone_geom) {
      GEOSSetSRID_r(orig_context, clone_geom, GEOSGetSRID_r(orig_context, geom));
      self_data->geom = clone_geom;
      self_data->geos_context = orig_context;
      self_data->factory = orig_data->factory;
      self_data->klasses = orig_data->klasses;
    }
  }
  return self;
}
Esempio n. 3
0
Polygon::Polygon(GEOSGeometry* g, const SpatialReference& srs,
    geos::ErrorHandler& err)
    : m_geom(GEOSGeom_clone_r(err.ctx, g))
    , m_srs(srs)
    , m_ctx(err.ctx)
{
    prepare();
}
Esempio n. 4
0
Polygon::Polygon(GEOSGeometry* g, const SpatialReference& srs,
    GEOSContextHandle_t ctx)
    : m_geom(GEOSGeom_clone_r(ctx, g))
    , m_srs(srs)
    , m_ctx(ctx)
{
    prepare();
}
Esempio n. 5
0
Polygon::Polygon(const Polygon& input)
    : m_srs(input.m_srs)
    , m_ctx(input.m_ctx)
{
    assert(input.m_geom != 0);
    m_geom = GEOSGeom_clone_r(m_ctx, input.m_geom);
    assert(m_geom != 0);
    m_prepGeom = 0;
    prepare();
}
Esempio n. 6
0
Polygon& Polygon::operator=(const Polygon& input)
{

    if (&input!= this)
    {
        m_ctx = input.m_ctx;
        m_srs = input.m_srs;
        m_geom = GEOSGeom_clone_r(m_ctx, input.m_geom);
        prepare();
    }
    return *this;


}
Esempio n. 7
0
VALUE rgeo_wrap_geos_geometry_clone(VALUE factory, const GEOSGeometry* geom, VALUE klass)
{
  VALUE result;
  GEOSGeometry* clone_geom;

  result = Qnil;
  if (geom) {
    clone_geom = GEOSGeom_clone_r(RGEO_FACTORY_DATA_PTR(factory)->geos_context, geom);
    if (clone_geom) {
      result = rgeo_wrap_geos_geometry(factory, clone_geom, klass);
    }
  }
  return result;
}
static GEOSGeometry *LWGEOM_GEOS_makeValid( const GEOSGeometry *gin, QString &errorMessage )
{
  GEOSContextHandle_t handle = QgsGeos::getGEOSHandler();

  // return what we got so far if already valid
  Q_NOWARN_UNREACHABLE_PUSH
  try
  {
    if ( GEOSisValid_r( handle, gin ) )
    {
      // It's valid at this step, return what we have
      return GEOSGeom_clone_r( handle, gin );
    }
  }
  catch ( GEOSException &e )
  {
    // I don't think should ever happen
    errorMessage = QStringLiteral( "GEOSisValid(): %1" ).arg( e.what() );
    return nullptr;
  }
  Q_NOWARN_UNREACHABLE_POP

  // make what we got valid

  switch ( GEOSGeomTypeId_r( handle, gin ) )
  {
    case GEOS_MULTIPOINT:
    case GEOS_POINT:
      // points are always valid, but we might have invalid ordinate values
      QgsDebugMsg( QStringLiteral( "PUNTUAL geometry resulted invalid to GEOS -- dunno how to clean that up" ) );
      return nullptr;

    case GEOS_LINESTRING:
      return LWGEOM_GEOS_makeValidLine( gin, errorMessage );

    case GEOS_MULTILINESTRING:
      return LWGEOM_GEOS_makeValidMultiLine( gin, errorMessage );

    case GEOS_POLYGON:
    case GEOS_MULTIPOLYGON:
      return LWGEOM_GEOS_makeValidPolygon( gin, errorMessage );

    case GEOS_GEOMETRYCOLLECTION:
      return LWGEOM_GEOS_makeValidCollection( gin, errorMessage );

    default:
      errorMessage = QStringLiteral( "ST_MakeValid: doesn't support geometry type: %1" ).arg( GEOSGeomTypeId_r( handle, gin ) );
      return nullptr;
  }
}
Esempio n. 9
0
Polygon& Polygon::operator=(const Polygon& input)
{

    if (&input!= this)
    {
        m_geoserr = input.m_geoserr;
        m_srs = input.m_srs;
        geos::GeometryDeleter geom_del(m_geoserr);
        GEOSGeomPtr p(GEOSGeom_clone_r(m_geoserr.ctx(), input.m_geom.get()), geom_del);
        m_geom.swap(p);

        prepare();
    }
    return *this;
}
static GEOSGeometry *collectFacesWithEvenAncestors( Face **faces, int nfaces )
{
  GEOSContextHandle_t handle = QgsGeos::getGEOSHandler();

  unsigned int ngeoms = 0;
  GEOSGeometry **geoms = new GEOSGeometry*[nfaces];
  for ( int i = 0; i < nfaces; ++i )
  {
    Face *f = faces[i];
    if ( countParens( f ) % 2 )
      continue; // we skip odd parents geoms
    geoms[ngeoms++] = GEOSGeom_clone_r( handle, f->geom );
  }

  GEOSGeometry *ret = GEOSGeom_createCollection_r( handle, GEOS_MULTIPOLYGON, geoms, ngeoms );
  delete [] geoms;
  return ret;
}
Esempio n. 11
0
static VALUE method_geometry_initialize_copy(VALUE self, VALUE orig)
{
  RGeo_GeometryData* self_data;
  const GEOSPreparedGeometry* prep;
  const GEOSGeometry* geom;
  RGeo_GeometryData* orig_data;
  GEOSContextHandle_t orig_context;
  GEOSGeometry* clone_geom;
  RGeo_FactoryData* factory_data;

  // Clear out any existing value
  self_data = RGEO_GEOMETRY_DATA_PTR(self);
  if (self_data->geom) {
    GEOSGeom_destroy_r(self_data->geos_context, self_data->geom);
    self_data->geom = NULL;
  }
  prep = self_data->prep;
  if (prep && prep != (GEOSPreparedGeometry*)1 && prep != (GEOSPreparedGeometry*)2) {
    GEOSPreparedGeom_destroy_r(self_data->geos_context, prep);
  }
  self_data->prep = NULL;
  self_data->geos_context = NULL;
  self_data->factory = Qnil;
  self_data->klasses = Qnil;

  // Copy value from orig
  geom = rgeo_get_geos_geometry_safe(orig);
  if (geom) {
    orig_data = RGEO_GEOMETRY_DATA_PTR(orig);
    orig_context = orig_data->geos_context;
    clone_geom = GEOSGeom_clone_r(orig_context, geom);
    if (clone_geom) {
      factory_data = RGEO_FACTORY_DATA_PTR(orig_data->factory);
      GEOSSetSRID_r(orig_context, clone_geom, GEOSGetSRID_r(orig_context, geom));
      self_data->geom = clone_geom;
      self_data->geos_context = orig_context;
      self_data->prep = factory_data && (factory_data->flags & RGEO_FACTORYFLAGS_PREPARE_HEURISTIC != 0) ?
        (GEOSPreparedGeometry*)1 : NULL;
      self_data->factory = orig_data->factory;
      self_data->klasses = orig_data->klasses;
    }
  }
  return self;
}
Esempio n. 12
0
SEXP rgeos_topologyfunc(SEXP env, SEXP obj, SEXP id, SEXP byid, p_topofunc topofunc) {

    GEOSContextHandle_t GEOShandle = getContextHandle(env);

    SEXP p4s = GET_SLOT(obj, install("proj4string"));
    GEOSGeom geom = rgeos_convert_R2geos(env, obj);
    int type = GEOSGeomTypeId_r(GEOShandle, geom);
    
    int n = 1;
    if (LOGICAL_POINTER(byid)[0] && type == GEOS_GEOMETRYCOLLECTION)
        n = GEOSGetNumGeometries_r(GEOShandle, geom);
    
    if (n < 1) error("rgeos_topologyfunc: invalid number of geometries");
    
    GEOSGeom *resgeoms = (GEOSGeom *) R_alloc((size_t) n, sizeof(GEOSGeom));
    
    for(int i=0; i<n; i++) {
        const GEOSGeometry *curgeom = (n > 1) ? (GEOSGeom) GEOSGetGeometryN_r(GEOShandle, geom, i)
                                       : geom;
        
        if (curgeom == NULL) 
            error("rgeos_topologyfunc: unable to get subgeometries");
        
        if (    topofunc == GEOSUnionCascaded_r
             && GEOSGeomTypeId_r(GEOShandle, curgeom) == GEOS_POLYGON) {
            resgeoms[i] = GEOSGeom_clone_r(GEOShandle, curgeom);
        } else {
            resgeoms[i] = topofunc(GEOShandle, curgeom);
            if (resgeoms[i] == NULL)
                error("rgeos_topologyfunc: unable to calculate");
        }
    }
    
    GEOSGeom_destroy_r(GEOShandle, geom);
    
    GEOSGeom res = (n == 1) ? resgeoms[0]
                    : GEOSGeom_createCollection_r(GEOShandle, GEOS_GEOMETRYCOLLECTION, resgeoms, (unsigned int) n);
    
    return( rgeos_convert_geos2R(env, res, p4s, id) ); // releases res
}
static GEOSGeometry *LWGEOM_GEOS_makeValidMultiLine( const GEOSGeometry *gin, QString &errorMessage )
{
  GEOSContextHandle_t handle = QgsGeos::getGEOSHandler();

  int ngeoms = GEOSGetNumGeometries_r( handle, gin );
  uint32_t nlines_alloc = ngeoms;
  QVector<GEOSGeometry *> lines;
  QVector<GEOSGeometry *> points;
  lines.reserve( nlines_alloc );
  points.reserve( ngeoms );

  for ( int i = 0; i < ngeoms; ++i )
  {
    const GEOSGeometry *g = GEOSGetGeometryN_r( handle, gin, i );
    GEOSGeometry *vg = LWGEOM_GEOS_makeValidLine( g, errorMessage );
    if ( GEOSisEmpty_r( handle, vg ) )
    {
      // we don't care about this one
      GEOSGeom_destroy_r( handle, vg );
    }
    if ( GEOSGeomTypeId_r( handle, vg ) == GEOS_POINT )
    {
      points.append( vg );
    }
    else if ( GEOSGeomTypeId_r( handle, vg ) == GEOS_LINESTRING )
    {
      lines.append( vg );
    }
    else if ( GEOSGeomTypeId_r( handle, vg ) == GEOS_MULTILINESTRING )
    {
      int nsubgeoms = GEOSGetNumGeometries_r( handle, vg );
      nlines_alloc += nsubgeoms;
      lines.reserve( nlines_alloc );
      for ( int j = 0; j < nsubgeoms; ++j )
      {
        // NOTE: ownership of the cloned geoms will be taken by final collection
        lines.append( GEOSGeom_clone_r( handle, GEOSGetGeometryN_r( handle, vg, j ) ) );
      }
    }
    else
    {
      // NOTE: return from GEOSGeomType will leak but we really don't expect this to happen
      errorMessage = QStringLiteral( "unexpected geom type returned by LWGEOM_GEOS_makeValid: %1" ).arg( GEOSGeomTypeId_r( handle, vg ) );
    }
  }

  GEOSGeometry *mpoint_out = nullptr;
  if ( points.count() )
  {
    if ( points.count() > 1 )
    {
      mpoint_out = GEOSGeom_createCollection_r( handle, GEOS_MULTIPOINT, points.data(), points.count() );
    }
    else
    {
      mpoint_out = points[0];
    }
  }

  GEOSGeometry *mline_out = nullptr;
  if ( lines.count() )
  {
    if ( lines.count() > 1 )
    {
      mline_out = GEOSGeom_createCollection_r( handle, GEOS_MULTILINESTRING, lines.data(), lines.count() );
    }
    else
    {
      mline_out = lines[0];
    }
  }

  if ( mline_out && mpoint_out )
  {
    GEOSGeometry *collection[2];
    collection[0] = mline_out;
    collection[1] = mpoint_out;
    return GEOSGeom_createCollection_r( handle, GEOS_GEOMETRYCOLLECTION, collection, 2 );
  }
  else if ( mline_out )
  {
    return mline_out;
  }
  else if ( mpoint_out )
  {
    return mpoint_out;
  }
  else
  {
    return nullptr;
  }
}
Esempio n. 14
0
SEXP rgeos_geosring2Polygon(SEXP env, GEOSGeom lr, int hole) {
    
    GEOSContextHandle_t GEOShandle = getContextHandle(env);
    int pc=0;
    
    GEOSCoordSeq s = (GEOSCoordSequence *) GEOSGeom_getCoordSeq_r(GEOShandle, lr);
    if (s == NULL) 
        error("rgeos_geosring2Polygon: CoordSeq failure");
    
    unsigned int n;
    if (GEOSCoordSeq_getSize_r(GEOShandle, s, &n) == 0)
        error("rgeos_geosring2Polygon: CoordSeq failure");
    
    // Get coordinates
    SEXP crd;
    PROTECT(crd = rgeos_crdMatFixDir(PROTECT(rgeos_CoordSeq2crdMat(env, s, FALSE, hole)), hole)); pc += 2;
    
    // Calculate area
    GEOSGeom p = GEOSGeom_createPolygon_r(GEOShandle,GEOSGeom_clone_r(GEOShandle,lr),NULL,0);
    if (p == NULL) 
        error("rgeos_geosring2Polygon: unable to create polygon");
    
    SEXP area;
    PROTECT(area = NEW_NUMERIC(1)); pc++;
    NUMERIC_POINTER(area)[0] = 0.0;
    if (!GEOSArea_r(GEOShandle, p, NUMERIC_POINTER(area)))
        error("rgeos_geosring2Polygon: area calculation failure");
    
    
    // Calculate label position
    SEXP labpt;
    PROTECT(labpt = NEW_NUMERIC(2)); pc++;
    
    GEOSGeom centroid = GEOSGetCentroid_r(GEOShandle, p);
    double xc, yc;
    rgeos_Pt2xy(env, centroid, &xc, &yc);
    
    if (!R_FINITE(xc) || !R_FINITE(yc)) {
        xc = 0.0;
        yc = 0.0;
        for(int i=0; i != n; i++) {
            xc += NUMERIC_POINTER(crd)[i];
            yc += NUMERIC_POINTER(crd)[(int) (n) +i];
        }
        
        xc /= n;
        yc /= n;
    }
    
    NUMERIC_POINTER(labpt)[0] = xc;
    NUMERIC_POINTER(labpt)[1] = yc;
    
    GEOSGeom_destroy_r(GEOShandle, centroid);
    GEOSGeom_destroy_r(GEOShandle, p);
    
    // Get ring direction
    SEXP ringDir;
    PROTECT(ringDir = NEW_INTEGER(1)); pc++;
    INTEGER_POINTER(ringDir)[0] = hole ? -1 : 1;
    
    // Get hole status
    SEXP Hole;
    PROTECT(Hole = NEW_LOGICAL(1)); pc++;
    LOGICAL_POINTER(Hole)[0] = hole;
    
    SEXP ans;
    PROTECT(ans = NEW_OBJECT(MAKE_CLASS("Polygon"))); pc++;    
    SET_SLOT(ans, install("ringDir"), ringDir);
    SET_SLOT(ans, install("labpt"), labpt);
    SET_SLOT(ans, install("area"), area);
    SET_SLOT(ans, install("hole"), Hole);
    SET_SLOT(ans, install("coords"), crd);
    
    SEXP valid;
    PROTECT(valid = SP_PREFIX(Polygon_validate_c)(ans)); pc++;
    if (!isLogical(valid)) {
        UNPROTECT(pc);
        if (isString(valid)) 
            error(CHAR(STRING_ELT(valid, 0)));
        else 
            error("invalid Polygon object");
    }
    
    UNPROTECT(pc);
    return(ans);
}
QgsLabelFeature* QgsVectorLayerDiagramProvider::registerDiagram( QgsFeature& feat, QgsRenderContext &context, QgsGeometry* obstacleGeometry )
{
  const QgsMapSettings& mapSettings = mEngine->mapSettings();

  const QgsDiagramRenderer* dr = mSettings.getRenderer();
  if ( dr )
  {
    QList<QgsDiagramSettings> settingList = dr->diagramSettings();
    if ( !settingList.isEmpty() && settingList.at( 0 ).scaleBasedVisibility )
    {
      double minScale = settingList.at( 0 ).minScaleDenominator;
      if ( minScale > 0 && context.rendererScale() < minScale )
      {
        return nullptr;
      }

      double maxScale = settingList.at( 0 ).maxScaleDenominator;
      if ( maxScale > 0 && context.rendererScale() > maxScale )
      {
        return nullptr;
      }
    }
  }

  //convert geom to geos
  QgsGeometry geom = feat.geometry();
  QgsGeometry extentGeom = QgsGeometry::fromRect( mapSettings.visibleExtent() );
  if ( !qgsDoubleNear( mapSettings.rotation(), 0.0 ) )
  {
    //PAL features are prerotated, so extent also needs to be unrotated
    extentGeom.rotate( -mapSettings.rotation(), mapSettings.visibleExtent().center() );
  }

  const GEOSGeometry* geos_geom = nullptr;
  QScopedPointer<QgsGeometry> scopedPreparedGeom;
  if ( QgsPalLabeling::geometryRequiresPreparation( geom, context, mSettings.coordinateTransform(), &extentGeom ) )
  {
    scopedPreparedGeom.reset( new QgsGeometry( QgsPalLabeling::prepareGeometry( geom, context, mSettings.coordinateTransform(), &extentGeom ) ) );
    QgsGeometry* preparedGeom = scopedPreparedGeom.data();
    if ( preparedGeom->isEmpty() )
      return nullptr;
    geos_geom = preparedGeom->asGeos();
  }
  else
  {
    geos_geom = geom.asGeos();
  }

  if ( !geos_geom )
    return nullptr; // invalid geometry

  GEOSGeometry* geomCopy = GEOSGeom_clone_r( QgsGeometry::getGEOSHandler(), geos_geom );

  const GEOSGeometry* geosObstacleGeom = nullptr;
  QScopedPointer<QgsGeometry> scopedObstacleGeom;
  if ( mSettings.isObstacle() && obstacleGeometry && QgsPalLabeling::geometryRequiresPreparation( *obstacleGeometry, context, mSettings.coordinateTransform(), &extentGeom ) )
  {
    QgsGeometry preparedObstacleGeom = QgsPalLabeling::prepareGeometry( *obstacleGeometry, context, mSettings.coordinateTransform(), &extentGeom );
    geosObstacleGeom = preparedObstacleGeom.asGeos();
  }
  else if ( mSettings.isObstacle() && obstacleGeometry )
  {
    geosObstacleGeom = obstacleGeometry->asGeos();
  }
  GEOSGeometry* geosObstacleGeomClone = nullptr;
  if ( geosObstacleGeom )
  {
    geosObstacleGeomClone = GEOSGeom_clone_r( QgsGeometry::getGEOSHandler(), geosObstacleGeom );
  }


  double diagramWidth = 0;
  double diagramHeight = 0;
  if ( dr )
  {
    QSizeF diagSize = dr->sizeMapUnits( feat, context );
    if ( diagSize.isValid() )
    {
      diagramWidth = diagSize.width();
      diagramHeight = diagSize.height();
    }
  }

  //  feature to the layer
  bool alwaysShow = mSettings.showAllDiagrams();
  int ddColX = mSettings.xPosColumn;
  int ddColY = mSettings.yPosColumn;
  double ddPosX = 0.0;
  double ddPosY = 0.0;
  bool ddPos = ( ddColX >= 0 && ddColY >= 0 );
  if ( ddPos && ! feat.attribute( ddColX ).isNull() && ! feat.attribute( ddColY ).isNull() )
  {
    bool posXOk, posYOk;
    ddPosX = feat.attribute( ddColX ).toDouble( &posXOk );
    ddPosY = feat.attribute( ddColY ).toDouble( &posYOk );
    if ( !posXOk || !posYOk )
    {
      ddPos = false;
    }
    else
    {
      QgsCoordinateTransform ct = mSettings.coordinateTransform();
      if ( ct.isValid() && !ct.isShortCircuited() )
      {
        double z = 0;
        ct.transformInPlace( ddPosX, ddPosY, z );
      }
      //data defined diagram position is always centered
      ddPosX -= diagramWidth / 2.0;
      ddPosY -= diagramHeight / 2.0;
    }
  }
  else
    ddPos = false;

  int ddColShow = mSettings.showColumn;
  if ( ddColShow >= 0 && ! feat.attribute( ddColShow ).isNull() )
  {
    bool showOk;
    bool ddShow = feat.attribute( ddColShow ).toDouble( &showOk );

    if ( showOk && ! ddShow )
      return nullptr;
  }

  QgsDiagramLabelFeature* lf = new QgsDiagramLabelFeature( feat.id(), geomCopy, QSizeF( diagramWidth, diagramHeight ) );
  lf->setHasFixedPosition( ddPos );
  lf->setFixedPosition( QgsPoint( ddPosX, ddPosY ) );
  lf->setHasFixedAngle( true );
  lf->setFixedAngle( 0 );
  lf->setAlwaysShow( alwaysShow );
  lf->setIsObstacle( mSettings.isObstacle() );
  lf->setZIndex( mSettings.getZIndex() );
  if ( geosObstacleGeomClone )
  {
    lf->setObstacleGeometry( geosObstacleGeomClone );
  }

  if ( dr )
  {
    //append the diagram attributes to lbl
    lf->setAttributes( feat.attributes() );
  }

  QgsPoint ptZero = mapSettings.mapToPixel().toMapCoordinates( 0, 0 );
  QgsPoint ptOne = mapSettings.mapToPixel().toMapCoordinates( 1, 0 );
  lf->setDistLabel( ptOne.distance( ptZero ) * mSettings.distance() );
  return lf;
}
QgsLabelFeature* QgsVectorLayerDiagramProvider::registerDiagram( QgsFeature& feat, QgsRenderContext &context )
{
  const QgsMapSettings& mapSettings = mEngine->mapSettings();

  QgsDiagramRendererV2* dr = mSettings.renderer;
  if ( dr )
  {
    QList<QgsDiagramSettings> settingList = dr->diagramSettings();
    if ( settingList.size() > 0 && settingList.at( 0 ).scaleBasedVisibility )
    {
      double minScale = settingList.at( 0 ).minScaleDenominator;
      if ( minScale > 0 && context.rendererScale() < minScale )
      {
        return 0;
      }

      double maxScale = settingList.at( 0 ).maxScaleDenominator;
      if ( maxScale > 0 && context.rendererScale() > maxScale )
      {
        return 0;
      }
    }
  }

  //convert geom to geos
  const QgsGeometry* geom = feat.constGeometry();
  QScopedPointer<QgsGeometry> extentGeom( QgsGeometry::fromRect( mapSettings.visibleExtent() ) );
  if ( !qgsDoubleNear( mapSettings.rotation(), 0.0 ) )
  {
    //PAL features are prerotated, so extent also needs to be unrotated
    extentGeom->rotate( -mapSettings.rotation(), mapSettings.visibleExtent().center() );
  }

  const GEOSGeometry* geos_geom = 0;
  QScopedPointer<QgsGeometry> preparedGeom;
  if ( QgsPalLabeling::geometryRequiresPreparation( geom, context, mSettings.ct, extentGeom.data() ) )
  {
    preparedGeom.reset( QgsPalLabeling::prepareGeometry( geom, context, mSettings.ct, extentGeom.data() ) );
    if ( !preparedGeom.data() )
      return 0;
    geos_geom = preparedGeom.data()->asGeos();
  }
  else
  {
    geos_geom = geom->asGeos();
  }

  if ( geos_geom == 0 )
  {
    return 0; // invalid geometry
  }

  GEOSGeometry* geomCopy = GEOSGeom_clone_r( QgsGeometry::getGEOSHandler(), geos_geom );

  double diagramWidth = 0;
  double diagramHeight = 0;
  if ( dr )
  {
    QSizeF diagSize = dr->sizeMapUnits( feat, context );
    if ( diagSize.isValid() )
    {
      diagramWidth = diagSize.width();
      diagramHeight = diagSize.height();
    }
  }

  //  feature to the layer
  bool alwaysShow = mSettings.showAll;
  int ddColX = mSettings.xPosColumn;
  int ddColY = mSettings.yPosColumn;
  double ddPosX = 0.0;
  double ddPosY = 0.0;
  bool ddPos = ( ddColX >= 0 && ddColY >= 0 );
  if ( ddPos )
  {
    bool posXOk, posYOk;
    ddPosX = feat.attribute( ddColX ).toDouble( &posXOk );
    ddPosY = feat.attribute( ddColY ).toDouble( &posYOk );
    if ( !posXOk || !posYOk )
    {
      ddPos = false;
    }
    else
    {
      const QgsCoordinateTransform* ct = mSettings.ct;
      if ( ct )
      {
        double z = 0;
        ct->transformInPlace( ddPosX, ddPosY, z );
      }
      //data defined diagram position is always centered
      ddPosX -= diagramWidth / 2.0;
      ddPosY -= diagramHeight / 2.0;
    }
  }

  QgsDiagramLabelFeature* lf = new QgsDiagramLabelFeature( feat.id(), geomCopy, QSizeF( diagramWidth, diagramHeight ) );
  lf->setHasFixedPosition( ddPos );
  lf->setFixedPosition( QgsPoint( ddPosX, ddPosY ) );
  lf->setHasFixedAngle( true );
  lf->setFixedAngle( 0 );
  lf->setAlwaysShow( alwaysShow );
  lf->setIsObstacle( mSettings.obstacle );

  if ( dr )
  {
    //append the diagram attributes to lbl
    lf->setAttributes( feat.attributes() );
  }

  QgsPoint ptZero = mSettings.xform->toMapCoordinates( 0, 0 );
  QgsPoint ptOne = mSettings.xform->toMapCoordinates( 1, 0 );
  lf->setDistLabel( qAbs( ptOne.x() - ptZero.x() ) * mSettings.dist );
  return lf;
}
Esempio n. 17
0
Polygon Polygon::simplify(double distance_tolerance,
    double area_tolerance) const
{
    GEOSGeometry *smoothed =
        GEOSTopologyPreserveSimplify_r(m_ctx, m_geom, distance_tolerance);
    if (!smoothed)
        throw pdal_error("Unable to simplify input geometry!");

    std::vector<GEOSGeometry*> geometries;

    int numGeom = GEOSGetNumGeometries_r(m_ctx, smoothed);
    for (int n = 0; n < numGeom; ++n)
    {
        const GEOSGeometry* m = GEOSGetGeometryN_r(m_ctx, smoothed, n);
        if (!m)
            throw pdal::pdal_error("Unable to Get GeometryN");

        const GEOSGeometry* ering = GEOSGetExteriorRing_r(m_ctx, m);
        if (!ering)
            throw pdal::pdal_error("Unable to Get Exterior Ring");

        GEOSGeometry* exterior = GEOSGeom_clone_r(m_ctx,
            GEOSGetExteriorRing_r(m_ctx, m));
        if (!exterior)
            throw pdal::pdal_error("Unable to clone exterior ring!");

        std::vector<GEOSGeometry*> keep_rings;
        int numRings = GEOSGetNumInteriorRings_r(m_ctx, m);
        for (int i = 0; i < numRings; ++i)
        {
            double area(0.0);

            const GEOSGeometry* iring =
                GEOSGetInteriorRingN_r(m_ctx, m, i);
            if (!iring)
                throw pdal::pdal_error("Unable to Get Interior Ring");

            GEOSGeometry* cring = GEOSGeom_clone_r(m_ctx, iring);
            if (!cring)
                throw pdal::pdal_error("Unable to clone interior ring!");
            GEOSGeometry* aring = GEOSGeom_createPolygon_r(m_ctx, cring,
                NULL, 0);

            int errored = GEOSArea_r(m_ctx, aring, &area);
            if (errored == 0)
                throw pdal::pdal_error("Unable to get area of ring!");
            if (area > area_tolerance)
            {
                keep_rings.push_back(cring);
            }
        }

        GEOSGeometry* p = GEOSGeom_createPolygon_r(m_ctx, exterior,
            keep_rings.data(), keep_rings.size());
        if (p == NULL) throw
            pdal::pdal_error("smooth polygon could not be created!" );
        geometries.push_back(p);
    }

    GEOSGeometry* o = GEOSGeom_createCollection_r(m_ctx, GEOS_MULTIPOLYGON,
        geometries.data(), geometries.size());
    Polygon p(o, m_srs, m_ctx);
    GEOSGeom_destroy_r(m_ctx, smoothed);
    GEOSGeom_destroy_r(m_ctx, o);

    return p;
}
Esempio n. 18
0
ErrorList topolTest::checkGaps( double tolerance, QgsVectorLayer *layer1, QgsVectorLayer *layer2, bool isExtent )
{
  Q_UNUSED( tolerance );
  Q_UNUSED( layer2 );

  int i = 0;
  ErrorList errorList;
  GEOSContextHandle_t geosctxt = QgsGeometry::getGEOSHandler();

  // could be enabled for lines and points too
  // so duplicate rule may be removed?

  if ( layer1->geometryType() != QGis::Polygon )
  {
    return errorList;
  }

  QList<FeatureLayer>::Iterator it;
  QgsGeometry* g1;

  QList<GEOSGeometry*> geomList;

  qDebug() << mFeatureList1.count() << " features in list!";
  QList<FeatureLayer>::ConstIterator FeatureListEnd = mFeatureList1.end();
  for ( it = mFeatureList1.begin(); it != FeatureListEnd; ++it )
  {
    qDebug() << "reading features-" << i;

    if ( !( ++i % 100 ) )
    {
      emit progress( i );
    }

    if ( testCancelled() )
    {
      break;
    }

    g1 = it->feature.geometry();

    if ( !g1 )
    {
      continue;
    }

    if ( !g1->asGeos() )
    {
      continue;
    }

    if ( !g1->isGeosValid() )
    {
      qDebug() << "invalid geometry found..skipping.." << it->feature.id();
      continue;
    }

    if ( g1->isMultipart() )
    {
      QgsMultiPolygon polys = g1->asMultiPolygon();
      for ( int m = 0; m < polys.count(); m++ )
      {
        QgsPolygon polygon = polys[m];

        QgsGeometry* polyGeom = QgsGeometry::fromPolygon( polygon );

        geomList.push_back( GEOSGeom_clone_r( geosctxt, polyGeom->asGeos() ) );
        delete polyGeom;
      }

    }
    else
    {
      geomList.push_back( GEOSGeom_clone_r( geosctxt, g1->asGeos() ) );
    }
  }

  GEOSGeometry** geomArray = new GEOSGeometry*[geomList.size()];
  for ( int i = 0; i < geomList.size(); ++i )
  {
    //qDebug() << "filling geometry array-" << i;
    geomArray[i] = geomList.at( i );
  }

  qDebug() << "creating geometry collection-";

  if ( geomList.size() == 0 )
  {
    //qDebug() << "geometry list is empty!";
    delete [] geomArray;
    return errorList;
  }

  GEOSGeometry* collection = 0;
  collection = GEOSGeom_createCollection_r( geosctxt, GEOS_MULTIPOLYGON, geomArray, geomList.size() );


  qDebug() << "performing cascaded union..might take time..-";
  GEOSGeometry* unionGeom = GEOSUnionCascaded_r( geosctxt, collection );
  //delete[] geomArray;

  QgsGeometry test;
  test.fromGeos( unionGeom );


  //qDebug() << "wktmerged - " << test.exportToWkt();

  QString extentWkt =  test.boundingBox().asWktPolygon();
  QgsGeometry* extentGeom = QgsGeometry::fromWkt( extentWkt );
  QgsGeometry* bufferExtent = extentGeom->buffer( 2, 3 );
  delete extentGeom;

  //qDebug() << "extent wkt - " << bufferExtent->exportToWkt();

  QgsGeometry* diffGeoms = bufferExtent->difference( &test );
  delete bufferExtent;
  if ( !diffGeoms )
  {
    qDebug() << "difference result 0-";
    return errorList;
  }

  //qDebug() << "difference gometry - " << diffGeoms->exportToWkt();

  QList<QgsGeometry*> geomColl = diffGeoms->asGeometryCollection();

  QgsGeometry* canvasExtentPoly = QgsGeometry::fromWkt( theQgsInterface->mapCanvas()->extent().asWktPolygon() );

  for ( int i = 1; i < geomColl.count() ; ++i )
  {
    QgsGeometry* conflictGeom = geomColl[i];
    if ( isExtent )
    {
      if ( canvasExtentPoly->disjoint( conflictGeom ) )
      {
        continue;
      }
      if ( canvasExtentPoly->crosses( conflictGeom ) )
      {
        conflictGeom = conflictGeom->intersection( canvasExtentPoly );
      }
    }
    QgsRectangle bBox = conflictGeom->boundingBox();
    QgsFeature feat;
    FeatureLayer ftrLayer1;
    ftrLayer1.layer = layer1;
    QList<FeatureLayer> errorFtrLayers;
    errorFtrLayers << ftrLayer1 << ftrLayer1;
    TopolErrorGaps* err = new TopolErrorGaps( bBox, conflictGeom, errorFtrLayers );
    errorList << err;
  }

  delete canvasExtentPoly;
  return errorList;
}
Esempio n. 19
0
bool QgsGeometryAnalyzer::createOffsetGeometry( QgsGeometry* geom, QgsGeometry* lineGeom, double offset )
{
  if ( !geom || !lineGeom )
  {
    return false;
  }

  QList<QgsGeometry*> inputGeomList;

  if ( geom->isMultipart() )
  {
    inputGeomList = geom->asGeometryCollection();
  }
  else
  {
    inputGeomList.push_back( geom );
  }

  QList<GEOSGeometry*> outputGeomList;
  QList<QgsGeometry*>::const_iterator inputGeomIt = inputGeomList.constBegin();
  GEOSContextHandle_t geosctxt = QgsGeometry::getGEOSHandler();
  for ( ; inputGeomIt != inputGeomList.constEnd(); ++inputGeomIt )
  {
    if ( geom->type() == QGis::Line )
    {
      //geos 3.3 needed for line offsets
#if defined(GEOS_VERSION_MAJOR) && defined(GEOS_VERSION_MINOR) && \
      ((GEOS_VERSION_MAJOR>3) || ((GEOS_VERSION_MAJOR==3) && (GEOS_VERSION_MINOR>=3)))
      GEOSGeometry* offsetGeom = GEOSOffsetCurve_r( geosctxt, ( *inputGeomIt )->asGeos(), -offset, 8 /*quadSegments*/, 0 /*joinStyle*/, 5.0 /*mitreLimit*/ );
      if ( !offsetGeom || !GEOSisValid_r( geosctxt, offsetGeom ) )
      {
        return false;
      }
      if ( !GEOSisValid_r( geosctxt, offsetGeom ) || GEOSGeomTypeId_r( geosctxt, offsetGeom ) != GEOS_LINESTRING || GEOSGeomGetNumPoints_r( geosctxt, offsetGeom ) < 1 )
      {
        GEOSGeom_destroy_r( geosctxt, offsetGeom );
        return false;
      }
      outputGeomList.push_back( offsetGeom );
#else
      outputGeomList.push_back( GEOSGeom_clone_r( geosctxt, ( *inputGeomIt )->asGeos() ) );
#endif
    }
    else if ( geom->type() == QGis::Point )
    {
      QgsPoint p = ( *inputGeomIt )->asPoint();
      p = createPointOffset( p.x(), p.y(), offset, lineGeom );
      GEOSCoordSequence* ptSeq = GEOSCoordSeq_create_r( geosctxt, 1, 2 );
      GEOSCoordSeq_setX_r( geosctxt, ptSeq, 0, p.x() );
      GEOSCoordSeq_setY_r( geosctxt, ptSeq, 0, p.y() );
      GEOSGeometry* geosPt = GEOSGeom_createPoint_r( geosctxt, ptSeq );
      outputGeomList.push_back( geosPt );
    }
  }

  if ( !geom->isMultipart() )
  {
    GEOSGeometry* outputGeom = outputGeomList.at( 0 );
    if ( outputGeom )
    {
      geom->fromGeos( outputGeom );
    }
  }
  else
  {
    GEOSGeometry** geomArray = new GEOSGeometry*[outputGeomList.size()];
    for ( int i = 0; i < outputGeomList.size(); ++i )
    {
      geomArray[i] = outputGeomList.at( i );
    }
    GEOSGeometry* collection = 0;
    if ( geom->type() == QGis::Point )
    {
      collection = GEOSGeom_createCollection_r( geosctxt, GEOS_MULTIPOINT, geomArray, outputGeomList.size() );
    }
    else if ( geom->type() == QGis::Line )
    {
      collection = GEOSGeom_createCollection_r( geosctxt, GEOS_MULTILINESTRING, geomArray, outputGeomList.size() );
    }
    geom->fromGeos( collection );
    delete[] geomArray;
  }
  return true;
}
Q_NOWARN_UNREACHABLE_PUSH
static GEOSGeometry *LWGEOM_GEOS_buildArea( const GEOSGeometry *geom_in, QString &errorMessage )
{
  GEOSContextHandle_t handle = QgsGeos::getGEOSHandler();

  GEOSGeometry *tmp = nullptr;
  GEOSGeometry *shp = nullptr;
  GEOSGeometry *geos_result = nullptr;
  int srid = GEOSGetSRID_r( handle, geom_in );

  GEOSGeometry const *vgeoms[1];
  vgeoms[0] = geom_in;
  try
  {
    geos_result = GEOSPolygonize_r( handle, vgeoms, 1 );
  }
  catch ( GEOSException &e )
  {
    errorMessage = QStringLiteral( "GEOSPolygonize(): %1" ).arg( e.what() );
    return nullptr;
  }

  // We should now have a collection
#if PARANOIA_LEVEL > 0
  if ( GEOSGeometryTypeId_r( handle, geos_result ) != COLLECTIONTYPE )
  {
    GEOSGeom_destroy_r( handle, geos_result );
    errorMessage = "Unexpected return from GEOSpolygonize";
    return nullptr;
  }
#endif

  int ngeoms = GEOSGetNumGeometries_r( handle, geos_result );

  // No geometries in collection, early out
  if ( ngeoms == 0 )
  {
    GEOSSetSRID_r( handle, geos_result, srid );
    return geos_result;
  }

  // Return first geometry if we only have one in collection,
  // to avoid the unnecessary Geometry clone below.
  if ( ngeoms == 1 )
  {
    tmp = ( GEOSGeometry * )GEOSGetGeometryN_r( handle, geos_result, 0 );
    if ( ! tmp )
    {
      GEOSGeom_destroy_r( handle, geos_result );
      return nullptr;
    }
    shp = GEOSGeom_clone_r( handle, tmp );
    GEOSGeom_destroy_r( handle, geos_result ); // only safe after the clone above
    GEOSSetSRID_r( handle, shp, srid );
    return shp;
  }

  /*
   * Polygonizer returns a polygon for each face in the built topology.
   *
   * This means that for any face with holes we'll have other faces
   * representing each hole. We can imagine a parent-child relationship
   * between these faces.
   *
   * In order to maximize the number of visible rings in output we
   * only use those faces which have an even number of parents.
   *
   * Example:
   *
   *   +---------------+
   *   |     L0        |  L0 has no parents
   *   |  +---------+  |
   *   |  |   L1    |  |  L1 is an hole of L0
   *   |  |  +---+  |  |
   *   |  |  |L2 |  |  |  L2 is an hole of L1 (which is an hole of L0)
   *   |  |  |   |  |  |
   *   |  |  +---+  |  |
   *   |  +---------+  |
   *   |               |
   *   +---------------+
   *
   * See http://trac.osgeo.org/postgis/ticket/1806
   *
   */

  // Prepare face structures for later analysis
  Face **geoms = new Face*[ngeoms];
  for ( int i = 0; i < ngeoms; ++i )
    geoms[i] = newFace( GEOSGetGeometryN_r( handle, geos_result, i ) );

  // Find faces representing other faces holes
  findFaceHoles( geoms, ngeoms );

  // Build a MultiPolygon composed only by faces with an
  // even number of ancestors
  tmp = collectFacesWithEvenAncestors( geoms, ngeoms );

  // Cleanup face structures
  for ( int i = 0; i < ngeoms; ++i )
    delFace( geoms[i] );
  delete [] geoms;

  // Faces referenced memory owned by geos_result.
  // It is safe to destroy geos_result after deleting them.
  GEOSGeom_destroy_r( handle, geos_result );

  // Run a single overlay operation to dissolve shared edges
  shp = GEOSUnionCascaded_r( handle, tmp );
  if ( !shp )
  {
    GEOSGeom_destroy_r( handle, tmp );
    return nullptr;
  }

  GEOSGeom_destroy_r( handle, tmp );

  GEOSSetSRID_r( handle, shp, srid );

  return shp;
}
Esempio n. 21
0
SEXP rgeos_convert_geos2R(SEXP env, GEOSGeom geom, SEXP p4s, SEXP id) {
    
    GEOSContextHandle_t GEOShandle = getContextHandle(env);

    int type = GEOSGeomTypeId_r(GEOShandle, geom);
    int ng = GEOSGetNumGeometries_r(GEOShandle, geom);
    if (ng == -1) error("rgeos_convert_geos2R: invalid number of subgeometries"); 
    
    if (type == GEOS_GEOMETRYCOLLECTION && ng==0 && GEOSisEmpty_r(GEOShandle,geom)) {
        GEOSGeom_destroy_r(GEOShandle, geom);
        return(R_NilValue);
    }
    
    ng = ng ? ng : 1; // Empty MULTI type geometries return size 0

    int pc=0;

    SEXP ans=NULL;
    switch(type) { // Determine appropriate conversion for the collection
        case -1:
            error("rgeos_convert_geos2R: unknown geometry type");
            break;
            
        case GEOS_POINT:
        case GEOS_MULTIPOINT:
            PROTECT( ans = rgeos_geospoint2SpatialPoints(env, geom, p4s, id, ng) ); pc++;
            break;
    
        case GEOS_LINEARRING:
            PROTECT( ans = rgeos_geosring2SpatialRings(env, geom, p4s, id, ng)); pc++;
            break;
            
        case GEOS_LINESTRING:
        case GEOS_MULTILINESTRING:
            PROTECT( ans = rgeos_geosline2SpatialLines(env, geom, p4s, id, 1) ); pc++;
            break;
    
        case GEOS_POLYGON:
        case GEOS_MULTIPOLYGON:
            PROTECT( ans = rgeos_geospolygon2SpatialPolygons(env, geom,p4s, id, 1) ); pc++;
            break;
        
        case GEOS_GEOMETRYCOLLECTION:
        {    
            
            int gctypes[] = {0,0,0,0,0,0,0,0};
            int gctypen[] = {0,0,0,0,0,0,0,0};
            int n=0;
            
            int *types = (int *) R_alloc((size_t) ng, sizeof(int));
            for (int i=0; i<ng; i++) {
                const GEOSGeometry *subgeom = GEOSGetGeometryN_r(GEOShandle, geom, i);
                if (subgeom == NULL)
                    error("rgeos_convert_geos2R: unable to retrieve subgeometry");
                
                int ns = GEOSGetNumGeometries_r(GEOShandle, subgeom);
                if (ns == -1) error("rgeos_convert_geos2R: invalid number of geometries in subgeometry");
                ns = ns ? ns : 1;
                n += ns;
                
                types[i] = GEOSGeomTypeId_r(GEOShandle, subgeom);
                if (types[i] == GEOS_GEOMETRYCOLLECTION) {
                    Rprintf("output subgeometry %d, row.name: %s\n", i,
                        CHAR(STRING_ELT(id, i)));
                    for (int ii=0; ii<ns; ii++)
                        Rprintf("subsubgeometry %d: %s\n", ii,
                            GEOSGeomType_r(GEOShandle,
                            GEOSGetGeometryN_r(GEOShandle, subgeom, ii)));
                    error("Geometry collections may not contain other geometry collections");
                }
                
                gctypes[ types[i] ] += 1; 
                gctypen[ types[i] ] += ns;
            }
            
            int isPoint = gctypes[GEOS_POINT] + gctypes[GEOS_MULTIPOINT];
            int isLine  = gctypes[GEOS_LINESTRING] + gctypes[GEOS_MULTILINESTRING];
            int isPoly  = gctypes[GEOS_POLYGON] + gctypes[GEOS_MULTIPOLYGON];
            int isRing  = gctypes[GEOS_LINEARRING];
            int isGC    = gctypes[GEOS_GEOMETRYCOLLECTION];
            
            if ( isPoint && !isLine && !isPoly && !isRing && !isGC ) {
                PROTECT( ans = rgeos_geospoint2SpatialPoints(env, geom, p4s, id, n) ); pc++;
            } else if ( isLine && !isPoint && !isPoly && !isRing && !isGC ) {
                PROTECT( ans = rgeos_geosline2SpatialLines(env, geom, p4s, id, ng) ); pc++;
            } else if ( isPoly && !isPoint && !isLine && !isRing && !isGC ) {
                PROTECT( ans = rgeos_geospolygon2SpatialPolygons(env, geom, p4s,id, ng) ); pc++;
            } else if ( isRing && !isPoint && !isLine && !isPoly && !isGC ) {
                PROTECT( ans = rgeos_geosring2SpatialRings(env, geom, p4s, id, ng) ); pc++;    
            } else {
                
                //Rprintf("isPoint: %d  isLine: %d  isPoly: %d  isRing: %d  isGC: %d\n",isPoint, isLine, isPoly, isRing, isGC);
                
                int m = MAX(MAX(MAX(isPoint,isLine),isPoly),isRing);
                if (length(id) < m) {
                    char buf[BUFSIZ];

                    PROTECT(id = NEW_CHARACTER(m)); pc++;
                    for (int i=0;i<m;i++) {
                        sprintf(buf,"%d",i);
                        SET_STRING_ELT(id, i, COPY_TO_USER_STRING(buf));
                    }
                }
                
                GEOSGeom *GCS[4];
                GCS[0] = (GEOSGeom *) R_alloc((size_t) isPoint, sizeof(GEOSGeom));
                GCS[1] = (GEOSGeom *) R_alloc((size_t) isLine,  sizeof(GEOSGeom));
                GCS[2] = (GEOSGeom *) R_alloc((size_t) isRing,  sizeof(GEOSGeom));
                GCS[3] = (GEOSGeom *) R_alloc((size_t) isPoly,  sizeof(GEOSGeom));
                
                SEXP ptID, lID, rID, pID;
                PROTECT(ptID = NEW_CHARACTER(isPoint)); pc++;
                PROTECT(lID  = NEW_CHARACTER(isLine)); pc++;
                PROTECT(rID  = NEW_CHARACTER(isRing)); pc++;
                PROTECT(pID  = NEW_CHARACTER(isPoly)); pc++;
                
                int typei[] = {0,0,0,0};
                for (int i=0; i<ng; i++) {
                    const GEOSGeometry *subgeom = GEOSGetGeometryN_r(GEOShandle, geom, i);
                    if (subgeom == NULL)
                        error("rgeos_convert_geos2R: unable to retrieve subgeometry");
                    
                    int j = -1;
                    SEXP cur_id=NULL;
                    
                    if (types[i]==GEOS_POINT || types[i]==GEOS_MULTIPOINT) {
                        j=0;
                        cur_id=ptID;
                    } else if (types[i]==GEOS_LINESTRING || types[i]==GEOS_MULTILINESTRING) {
                        j=1;
                        cur_id=lID;
                    } else if (types[i]==GEOS_LINEARRING) {
                        j=2;
                        cur_id=rID;
                    } else if (types[i]==GEOS_POLYGON || types[i]==GEOS_MULTIPOLYGON) {
                        j=3;
                        cur_id=pID;
                    }
                    
                    if (GCS[j] == NULL)
                        error("rgeos_convert_geos2R: GCS element is NULL (this should never happen).");
                    
                    GCS[j][ typei[j] ] = GEOSGeom_clone_r(GEOShandle, subgeom);
                    
                    SET_STRING_ELT(cur_id, typei[j], STRING_ELT(id,typei[j]));
                    typei[j]++;
                }         
                
                SEXP points = R_NilValue;
                SEXP lines  = R_NilValue;
                SEXP rings  = R_NilValue;
                SEXP polys  = R_NilValue;
                
                if (isPoint) {
                    GEOSGeom ptGC = GEOSGeom_createCollection_r(GEOShandle, GEOS_GEOMETRYCOLLECTION, GCS[0], (unsigned int) isPoint);
                    PROTECT( points = rgeos_convert_geos2R(env, ptGC, p4s, ptID) ); pc++;
                }
                if (isLine) {
                    GEOSGeom lGC = GEOSGeom_createCollection_r(GEOShandle, GEOS_GEOMETRYCOLLECTION, GCS[1], (unsigned int) isLine);
                    PROTECT( lines = rgeos_convert_geos2R(env, lGC, p4s, lID) ); pc++;
                }
                if (isRing) {
                    GEOSGeom rGC = GEOSGeom_createCollection_r(GEOShandle, GEOS_GEOMETRYCOLLECTION, GCS[2], (unsigned int) isRing);
                    PROTECT( rings = rgeos_convert_geos2R(env, rGC, p4s, rID) ); pc++;
                }
                if (isPoly) {
                    GEOSGeom pGC = GEOSGeom_createCollection_r(GEOShandle, GEOS_GEOMETRYCOLLECTION, GCS[3], (unsigned int) isPoly);
                    PROTECT( polys = rgeos_convert_geos2R(env, pGC, p4s, pID) ); pc++;
                }
                
                PROTECT(ans = NEW_OBJECT(MAKE_CLASS("SpatialCollections"))); pc++;
                SET_SLOT(ans, install("proj4string"), p4s);
                
                SET_SLOT(ans, install("pointobj"), points);
                SET_SLOT(ans, install("lineobj"), lines);
                SET_SLOT(ans, install("ringobj"), rings);
                SET_SLOT(ans, install("polyobj"), polys);
            
                SEXP plotOrder;
                PROTECT(plotOrder = NEW_INTEGER(4)); pc++;
                INTEGER_POINTER(plotOrder)[0] = 4;
                INTEGER_POINTER(plotOrder)[1] = 3;
                INTEGER_POINTER(plotOrder)[2] = 2;
                INTEGER_POINTER(plotOrder)[3] = 1;
                SET_SLOT(ans, install("plotOrder"), plotOrder);
                
                SEXP bbox;
                PROTECT(bbox = rgeos_geom2bbox(env, geom)); pc++;
                SET_SLOT(ans, install("bbox"), bbox);
            }
            
            break;
        }    
        default:
            error("rgeos_convert_geos2R: Unknown geometry type");
    }
    
    GEOSGeom_destroy_r(GEOShandle, geom);
    UNPROTECT(pc);
    return(ans);
}