Esempio n. 1
0
bool QgsGeometryEditUtils::deleteRing( QgsAbstractGeometryV2* geom, int ringNum, int partNum )
{
  if ( !geom || partNum < 0 )
  {
    return false;
  }

  if ( ringNum < 1 ) //cannot remove exterior ring
  {
    return false;
  }

  QgsAbstractGeometryV2* g = geom;
  QgsGeometryCollectionV2* c = dynamic_cast<QgsGeometryCollectionV2*>( geom );
  if ( c )
  {
    g = c->geometryN( partNum );
  }
  else if ( partNum > 0 )
  {
    //part num specified, but not a multi part geometry type
    return false;
  }

  QgsCurvePolygonV2* cpoly = dynamic_cast<QgsCurvePolygonV2*>( g );
  if ( !cpoly )
  {
    return false;
  }

  return cpoly->removeInteriorRing( ringNum - 1 );
}
Esempio n. 2
0
int QgsGeometryEditUtils::addRing( QgsAbstractGeometryV2* geom, QgsCurveV2* ring )
{
  if ( !ring )
  {
    return 1;
  }

  QList< QgsCurvePolygonV2* > polygonList;
  QgsCurvePolygonV2* curvePoly = dynamic_cast< QgsCurvePolygonV2* >( geom );
  QgsGeometryCollectionV2* multiGeom = dynamic_cast< QgsGeometryCollectionV2* >( geom );
  if ( curvePoly )
  {
    polygonList.append( curvePoly );
  }
  else if ( multiGeom )
  {
    for ( int i = 0; i < multiGeom->numGeometries(); ++i )
    {
      polygonList.append( dynamic_cast< QgsCurvePolygonV2* >( multiGeom->geometryN( i ) ) );
    }
  }
  else
  {
    delete ring; return 1; //not polygon / multipolygon;
  }

  //ring must be closed
  if ( !ring->isClosed() )
  {
    delete ring; return 2;
  }
  else if ( !ring->isRing() )
  {
    delete ring; return 3;
  }

  QScopedPointer<QgsGeometryEngine> ringGeom( QgsGeometry::createGeometryEngine( ring ) );
  ringGeom->prepareGeometry();

  //for each polygon, test if inside outer ring and no intersection with other interior ring
  QList< QgsCurvePolygonV2* >::iterator polyIter = polygonList.begin();
  for ( ; polyIter != polygonList.end(); ++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 ) ) )
        {
          delete ring; return 4;
        }
      }
      ( *polyIter )->addInteriorRing( ring );
      return 0; //success
    }
  }
  delete ring; return 5; //not contained in any outer ring
}
void QgsGeometryAreaCheck::collectErrors( QList<QgsGeometryCheckError*>& errors, QStringList &/*messages*/, QAtomicInt* progressCounter , const QgsFeatureIds &ids ) const
{
  const QgsFeatureIds& featureIds = ids.isEmpty() ? mFeaturePool->getFeatureIds() : ids;
  foreach ( const QgsFeatureId& featureid, featureIds )
  {
    if ( progressCounter ) progressCounter->fetchAndAddRelaxed( 1 );
    QgsFeature feature;
    if ( !mFeaturePool->get( featureid, feature ) )
    {
      continue;
    }

    QgsAbstractGeometryV2* geom = feature.geometry()->geometry();
    if ( dynamic_cast<QgsGeometryCollectionV2*>( geom ) )
    {
      QgsGeometryCollectionV2* multiGeom = static_cast<QgsGeometryCollectionV2*>( geom );
      for ( int i = 0, n = multiGeom->numGeometries(); i < n; ++i )
      {
        double value;
        if ( checkThreshold( multiGeom->geometryN( i ), value ) )
        {
          errors.append( new QgsGeometryCheckError( this, featureid, multiGeom->geometryN( i )->centroid(), QgsVertexId( i ), value, QgsGeometryCheckError::ValueArea ) );
        }
      }
    }
    else
    {
      double value;
      if ( checkThreshold( geom, value ) )
      {
        errors.append( new QgsGeometryCheckError( this, featureid, geom->centroid(), QgsVertexId( 0 ), value, QgsGeometryCheckError::ValueArea ) );
      }
    }
  }
}
Esempio n. 4
0
bool QgsGeometryEditUtils::deletePart( QgsAbstractGeometryV2* geom, int partNum )
{
  if ( !geom )
  {
    return false;
  }

  QgsGeometryCollectionV2* c = dynamic_cast<QgsGeometryCollectionV2*>( geom );
  if ( !c )
  {
    return false;
  }

  return c->removeGeometry( partNum );
}
Esempio n. 5
0
void QgsGeometryCheck::replaceFeatureGeometryPart( QgsFeature& feature, int partIdx, QgsAbstractGeometryV2* newPartGeom, Changes& changes ) const
{
  QgsAbstractGeometryV2* geom = feature.geometry()->geometry();
  if ( dynamic_cast<QgsGeometryCollectionV2*>( geom ) )
  {
    QgsGeometryCollectionV2* GeomCollection = static_cast<QgsGeometryCollectionV2*>( geom );
    GeomCollection->removeGeometry( partIdx );
    GeomCollection->addGeometry( newPartGeom );
    changes[feature.id()].append( Change( ChangeFeature, ChangeRemoved, QgsVertexId( partIdx ) ) );
    changes[feature.id()].append( Change( ChangeFeature, ChangeAdded, QgsVertexId( GeomCollection->partCount() - 1 ) ) );
  }
  else
  {
    feature.setGeometry( new QgsGeometry( newPartGeom ) );
    changes[feature.id()].append( Change( ChangeFeature, ChangeChanged ) );
  }
  mFeaturePool->updateFeature( feature );
}
Esempio n. 6
0
int QgsGeometryEditUtils::addPart( QgsAbstractGeometryV2* geom, QgsAbstractGeometryV2* part )
{
  if ( !geom )
  {
    return 1;
  }

  if ( !part )
  {
    return 2;
  }

  //multitype?
  QgsGeometryCollectionV2* geomCollection = dynamic_cast<QgsGeometryCollectionV2*>( geom );
  if ( !geomCollection )
  {
    return 1;
  }

  bool added = false;
  if ( QgsWKBTypes::flatType( geom->wkbType() ) == QgsWKBTypes::MultiSurface
       || QgsWKBTypes::flatType( geom->wkbType() ) == QgsWKBTypes::MultiPolygon )
  {
    QgsCurveV2* curve = dynamic_cast<QgsCurveV2*>( part );
    if ( curve && curve->isClosed() && curve->numPoints() >= 4 )
    {
      QgsCurvePolygonV2 *poly = nullptr;
      if ( QgsWKBTypes::flatType( curve->wkbType() ) == QgsWKBTypes::LineString )
      {
        poly = new QgsPolygonV2();
      }
      else
      {
        poly = new QgsCurvePolygonV2();
      }
      poly->setExteriorRing( curve );
      added = geomCollection->addGeometry( poly );
    }
    else if ( QgsWKBTypes::flatType( part->wkbType() ) == QgsWKBTypes::Polygon )
    {
      added = geomCollection->addGeometry( part );
    }
    else if ( QgsWKBTypes::flatType( part->wkbType() ) == QgsWKBTypes::MultiPolygon )
    {
      QgsGeometryCollectionV2 *parts = static_cast<QgsGeometryCollectionV2*>( part );

      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 );
        delete part;
        return 2;
      }

      delete part;
    }
    else
    {
      delete part;
      return 2;
    }
  }
  else
  {
    added = geomCollection->addGeometry( part );
  }
  return added ? 0 : 2;
}
void QgsGeometryTypeCheck::fixError( QgsGeometryCheckError* error, int method, int /*mergeAttributeIndex*/, Changes &changes ) const
{
  QgsFeature feature;
  if ( !mFeaturePool->get( error->featureId(), feature ) )
  {
    error->setObsolete();
    return;
  }
  QgsAbstractGeometryV2* geom = feature.geometry()->geometry();

  // Check if error still applies
  QgsWKBTypes::Type type = QgsWKBTypes::flatType( geom->wkbType() );
  if (( mAllowedTypes & ( 1 << type ) ) != 0 )
  {
    error->setObsolete();
    return;
  }

  // Fix with selected method
  if ( method == NoChange )
  {
    error->setFixed( method );
  }
  else if ( method == Convert )
  {
    // Check if corresponding single type is allowed
    if ( QgsWKBTypes::isMultiType( type ) && (( 1 << QgsWKBTypes::singleType( type ) ) & mAllowedTypes ) != 0 )
    {
      // Explode multi-type feature into single-type features
      for ( int iPart = 1, nParts = geom->partCount(); iPart < nParts; ++iPart )
      {
        QgsFeature newFeature;
        newFeature.setAttributes( feature.attributes() );
        newFeature.setGeometry( new QgsGeometry( QgsGeomUtils::getGeomPart( geom, iPart )->clone() ) );
        mFeaturePool->addFeature( newFeature );
        changes[newFeature.id()].append( Change( ChangeFeature, ChangeAdded ) );
      }
      // Recycle feature for part 0
      feature.setGeometry( new QgsGeometry( QgsGeomUtils::getGeomPart( geom, 0 ) ) );
      changes[feature.id()].append( Change( ChangeFeature, ChangeChanged ) );
    }
    // Check if corresponding multi type is allowed
    else if ( QgsWKBTypes::isSingleType( type ) && (( 1 << QgsWKBTypes::multiType( type ) ) & mAllowedTypes ) != 0 )
    {
      QgsGeometryCollectionV2* geomCollection = nullptr;
      switch ( QgsWKBTypes::multiType( type ) )
      {
        case QgsWKBTypes::MultiPoint:
        {
          geomCollection = new QgsMultiPointV2();
          break;
        }
        case QgsWKBTypes::MultiLineString:
        {
          geomCollection = new QgsMultiLineStringV2();
          break;
        }
        case QgsWKBTypes::MultiPolygon:
        {
          geomCollection = new QgsMultiPolygonV2();
          break;
        }
        case QgsWKBTypes::MultiCurve:
        {
          geomCollection = new QgsMultiCurveV2();
          break;
        }
        case QgsWKBTypes::MultiSurface:
        {
          geomCollection = new QgsMultiSurfaceV2();
          break;
        }
        default:
          break;
      }
      if ( !geomCollection )
      {
        error->setFixFailed( tr( "Unknown geometry type" ) );
      }
      else
      {
        geomCollection->addGeometry( geom->clone() );

        feature.setGeometry( new QgsGeometry( geomCollection ) );
        mFeaturePool->updateFeature( feature );
        changes[feature.id()].append( Change( ChangeFeature, ChangeChanged ) );
      }
    }
    // Delete feature
    else
    {
      mFeaturePool->deleteFeature( feature );
      changes[error->featureId()].append( Change( ChangeFeature, ChangeRemoved ) );
    }
    error->setFixed( method );
  }
  else if ( method == Delete )
  {
    mFeaturePool->deleteFeature( feature );
    error->setFixed( method );
    changes[error->featureId()].append( Change( ChangeFeature, ChangeRemoved ) );
  }
  else
  {
    error->setFixFailed( tr( "Unknown method" ) );
  }
}