示例#1
0
static bool lwcollection_make_geos_friendly( QgsGeometryCollection &g )
{
  for ( int i = 0; i < g.numGeometries(); i++ )
  {
    if ( !lwgeom_make_geos_friendly( *g.geometryN( i ) ) )
      return false;
  }

  return true;
}
示例#2
0
QgsGeometry::OperationResult QgsGeometryEditUtils::addPart( QgsAbstractGeometry *geom, std::unique_ptr<QgsAbstractGeometry> part )
{
  if ( !geom )
  {
    return QgsGeometry::InvalidBaseGeometry;
  }

  if ( !part )
  {
    return QgsGeometry::InvalidInput;
  }

  //multitype?
  QgsGeometryCollection *geomCollection = qgsgeometry_cast<QgsGeometryCollection *>( geom );
  if ( !geomCollection )
  {
    return QgsGeometry::AddPartNotMultiGeometry;
  }

  bool added = false;
  if ( QgsWkbTypes::flatType( geom->wkbType() ) == QgsWkbTypes::MultiSurface
       || QgsWkbTypes::flatType( geom->wkbType() ) == QgsWkbTypes::MultiPolygon )
  {
    QgsCurve *curve = qgsgeometry_cast<QgsCurve *>( part.get() );

    if ( curve && curve->isClosed() && curve->numPoints() >= 4 )
    {
      std::unique_ptr<QgsCurvePolygon> poly;
      if ( QgsWkbTypes::flatType( curve->wkbType() ) == QgsWkbTypes::LineString )
      {
        poly = qgis::make_unique< QgsPolygonV2 >();
      }
      else
      {
        poly = qgis::make_unique< QgsCurvePolygon >();
      }
      // Ownership is still with part, curve points to the same object and is transferred
      // to poly here.
      part.release();
      poly->setExteriorRing( curve );
      added = geomCollection->addGeometry( poly.release() );
    }
    else if ( QgsWkbTypes::flatType( part->wkbType() ) == QgsWkbTypes::Polygon )
    {
      added = geomCollection->addGeometry( part.release() );
    }
    else if ( QgsWkbTypes::flatType( part->wkbType() ) == QgsWkbTypes::MultiPolygon )
    {
      std::unique_ptr<QgsGeometryCollection> parts( static_cast<QgsGeometryCollection *>( part.release() ) );

      int i;
      int n = geomCollection->numGeometries();
      for ( i = 0; i < parts->numGeometries() && geomCollection->addGeometry( parts->geometryN( i )->clone() ); i++ )
        ;

      added = i == parts->numGeometries();
      if ( !added )
      {
        while ( geomCollection->numGeometries() > n )
          geomCollection->removeGeometry( n );
        return QgsGeometry::InvalidInput;
      }
    }
    else
    {
      return QgsGeometry::InvalidInput;
    }
  }
  else
  {
    added = geomCollection->addGeometry( part.release() );
  }
  return added ? QgsGeometry::Success : QgsGeometry::InvalidInput;
}
示例#3
0
QgsGeometry::OperationResult QgsGeometryEditUtils::addRing( QgsAbstractGeometry *geom, std::unique_ptr<QgsCurve> ring )
{
  if ( !ring )
  {
    return QgsGeometry::InvalidInput;
  }

  QList< QgsCurvePolygon * > polygonList;
  QgsCurvePolygon *curvePoly = qgsgeometry_cast< QgsCurvePolygon * >( geom );
  QgsGeometryCollection *multiGeom = qgsgeometry_cast< QgsGeometryCollection * >( geom );
  if ( curvePoly )
  {
    polygonList.append( curvePoly );
  }
  else if ( multiGeom )
  {
    polygonList.reserve( multiGeom->numGeometries() );
    for ( int i = 0; i < multiGeom->numGeometries(); ++i )
    {
      polygonList.append( qgsgeometry_cast< QgsCurvePolygon * >( multiGeom->geometryN( i ) ) );
    }
  }
  else
  {
    return QgsGeometry::InvalidInput; //not polygon / multipolygon;
  }

  //ring must be closed
  if ( !ring->isClosed() )
  {
    return QgsGeometry::AddRingNotClosed;
  }
  else if ( !ring->isRing() )
  {
    return QgsGeometry::AddRingNotValid;
  }

  std::unique_ptr<QgsGeometryEngine> ringGeom( QgsGeometry::createGeometryEngine( ring.get() ) );
  ringGeom->prepareGeometry();

  //for each polygon, test if inside outer ring and no intersection with other interior ring
  QList< QgsCurvePolygon * >::const_iterator polyIter = polygonList.constBegin();
  for ( ; polyIter != polygonList.constEnd(); ++polyIter )
  {
    if ( ringGeom->within( *polyIter ) )
    {
      //check if disjoint with other interior rings
      int nInnerRings = ( *polyIter )->numInteriorRings();
      for ( int i = 0; i < nInnerRings; ++i )
      {
        if ( !ringGeom->disjoint( ( *polyIter )->interiorRing( i ) ) )
        {
          return QgsGeometry::AddRingCrossesExistingRings;
        }
      }

      //make sure dimensionality of ring matches geometry
      if ( QgsWkbTypes::hasZ( geom->wkbType() ) )
        ring->addZValue( 0 );
      if ( QgsWkbTypes::hasM( geom->wkbType() ) )
        ring->addMValue( 0 );

      ( *polyIter )->addInteriorRing( ring.release() );
      return QgsGeometry::Success; //success
    }
  }
  return QgsGeometry::AddRingNotInExistingFeature; //not contained in any outer ring
}