Esempio n. 1
0
int QgsVectorLayerEditUtils::addRing( const QList<QgsPoint>& ring )
{
    if ( !L->hasGeometryType() )
        return 5;

    int addRingReturnCode = 5; //default: return code for 'ring not inserted'
    double xMin, yMin, xMax, yMax;
    QgsRectangle bBox;

    if ( boundingBoxFromPointList( ring, xMin, yMin, xMax, yMax ) == 0 )
    {
        bBox.setXMinimum( xMin );
        bBox.setYMinimum( yMin );
        bBox.setXMaximum( xMax );
        bBox.setYMaximum( yMax );
    }
    else
    {
        return 3; //ring not valid
    }

    QgsFeatureIterator fit = L->getFeatures( QgsFeatureRequest().setFilterRect( bBox ).setFlags( QgsFeatureRequest::ExactIntersect ) );

    QgsFeature f;
    while ( fit.nextFeature( f ) )
    {
        addRingReturnCode = f.geometry()->addRing( ring );
        if ( addRingReturnCode == 0 )
        {
            L->editBuffer()->changeGeometry( f.id(), f.geometry() );

            //setModified( true, true );
            break;
        }
    }

    return addRingReturnCode;
}
Esempio n. 2
0
int QgsVectorLayerEditUtils::splitFeatures( const QList<QgsPoint>& splitLine, bool topologicalEditing )
{
  if ( !L->hasGeometryType() )
    return 4;

  QgsFeatureList newFeatures; //store all the newly created features
  double xMin, yMin, xMax, yMax;
  QgsRectangle bBox; //bounding box of the split line
  int returnCode = 0;
  int splitFunctionReturn; //return code of QgsGeometry::splitGeometry
  int numberOfSplittedFeatures = 0;

  QgsFeatureIterator features;
  const QgsFeatureIds selectedIds = L->selectedFeaturesIds();

  if ( selectedIds.size() > 0 ) //consider only the selected features if there is a selection
  {
    features = L->selectedFeaturesIterator();
  }
  else //else consider all the feature that intersect the bounding box of the split line
  {
    if ( boundingBoxFromPointList( splitLine, xMin, yMin, xMax, yMax ) == 0 )
    {
      bBox.setXMinimum( xMin ); bBox.setYMinimum( yMin );
      bBox.setXMaximum( xMax ); bBox.setYMaximum( yMax );
    }
    else
    {
      return 1;
    }

    if ( bBox.isEmpty() )
    {
      //if the bbox is a line, try to make a square out of it
      if ( bBox.width() == 0.0 && bBox.height() > 0 )
      {
        bBox.setXMinimum( bBox.xMinimum() - bBox.height() / 2 );
        bBox.setXMaximum( bBox.xMaximum() + bBox.height() / 2 );
      }
      else if ( bBox.height() == 0.0 && bBox.width() > 0 )
      {
        bBox.setYMinimum( bBox.yMinimum() - bBox.width() / 2 );
        bBox.setYMaximum( bBox.yMaximum() + bBox.width() / 2 );
      }
      else
      {
        //If we have a single point, we still create a non-null box
        double bufferDistance = 0.000001;
        if ( L->crs().geographicFlag() )
          bufferDistance = 0.00000001;
        bBox.setXMinimum( bBox.xMinimum() - bufferDistance );
        bBox.setXMaximum( bBox.xMaximum() + bufferDistance );
        bBox.setYMinimum( bBox.yMinimum() - bufferDistance );
        bBox.setYMaximum( bBox.yMaximum() + bufferDistance );
      }
    }

    features = L->getFeatures( QgsFeatureRequest().setFilterRect( bBox ).setFlags( QgsFeatureRequest::ExactIntersect ) );
  }

  QgsFeature feat;
  while ( features.nextFeature( feat ) )
  {
    if ( !feat.constGeometry() )
    {
      continue;
    }
    QList<QgsGeometry*> newGeometries;
    QList<QgsPoint> topologyTestPoints;
    QgsGeometry* newGeometry = 0;
    splitFunctionReturn = feat.geometry()->splitGeometry( splitLine, newGeometries, topologicalEditing, topologyTestPoints );
    if ( splitFunctionReturn == 0 )
    {
      //change this geometry
      L->editBuffer()->changeGeometry( feat.id(), feat.geometry() );

      //insert new features
      for ( int i = 0; i < newGeometries.size(); ++i )
      {
        newGeometry = newGeometries.at( i );
        QgsFeature newFeature;
        newFeature.setGeometry( newGeometry );

        //use default value where possible for primary key (e.g. autoincrement),
        //and use the value from the original (split) feature if not primary key
        QgsAttributes newAttributes = feat.attributes();
        Q_FOREACH ( int pkIdx, L->dataProvider()->pkAttributeIndexes() )
        {
          const QVariant defaultValue = L->dataProvider()->defaultValue( pkIdx );
          if ( !defaultValue.isNull() )
          {
            newAttributes[ pkIdx ] = defaultValue;
          }
          else //try with NULL
          {
            newAttributes[ pkIdx ] = QVariant();
          }
        }

        newFeature.setAttributes( newAttributes );

        newFeatures.append( newFeature );
      }

      if ( topologicalEditing )
      {
        QList<QgsPoint>::const_iterator topol_it = topologyTestPoints.constBegin();
        for ( ; topol_it != topologyTestPoints.constEnd(); ++topol_it )
        {
          addTopologicalPoints( *topol_it );
        }
      }
      ++numberOfSplittedFeatures;
    }
    else if ( splitFunctionReturn > 1 ) //1 means no split but also no error
int QgsVectorLayerEditUtils::splitFeatures( const QList<QgsPoint>& splitLine, bool topologicalEditing )
{
  if ( !L->hasGeometryType() )
    return 4;

  QgsFeatureList newFeatures; //store all the newly created features
  double xMin, yMin, xMax, yMax;
  QgsRectangle bBox; //bounding box of the split line
  int returnCode = 0;
  int splitFunctionReturn; //return code of QgsGeometry::splitGeometry
  int numberOfSplittedFeatures = 0;

  QgsFeatureList featureList;
  const QgsFeatureIds selectedIds = L->selectedFeaturesIds();

  if ( selectedIds.size() > 0 ) //consider only the selected features if there is a selection
  {
    featureList = L->selectedFeatures();
  }
  else //else consider all the feature that intersect the bounding box of the split line
  {
    if ( boundingBoxFromPointList( splitLine, xMin, yMin, xMax, yMax ) == 0 )
    {
      bBox.setXMinimum( xMin ); bBox.setYMinimum( yMin );
      bBox.setXMaximum( xMax ); bBox.setYMaximum( yMax );
    }
    else
    {
      return 1;
    }

    if ( bBox.isEmpty() )
    {
      //if the bbox is a line, try to make a square out of it
      if ( bBox.width() == 0.0 && bBox.height() > 0 )
      {
        bBox.setXMinimum( bBox.xMinimum() - bBox.height() / 2 );
        bBox.setXMaximum( bBox.xMaximum() + bBox.height() / 2 );
      }
      else if ( bBox.height() == 0.0 && bBox.width() > 0 )
      {
        bBox.setYMinimum( bBox.yMinimum() - bBox.width() / 2 );
        bBox.setYMaximum( bBox.yMaximum() + bBox.width() / 2 );
      }
      else
      {
        return 2;
      }
    }

    QgsFeatureIterator fit = L->getFeatures( QgsFeatureRequest().setFilterRect( bBox ).setFlags( QgsFeatureRequest::ExactIntersect ) );

    QgsFeature f;
    while ( fit.nextFeature( f ) )
      featureList << QgsFeature( f );
  }

  QgsFeatureList::iterator select_it = featureList.begin();
  for ( ; select_it != featureList.end(); ++select_it )
  {
    if ( !select_it->geometry() )
    {
      continue;
    }
    QList<QgsGeometry*> newGeometries;
    QList<QgsPoint> topologyTestPoints;
    QgsGeometry* newGeometry = 0;
    splitFunctionReturn = select_it->geometry()->splitGeometry( splitLine, newGeometries, topologicalEditing, topologyTestPoints );
    if ( splitFunctionReturn == 0 )
    {
      //change this geometry
      L->editBuffer()->changeGeometry( select_it->id(), select_it->geometry() );

      //insert new features
      for ( int i = 0; i < newGeometries.size(); ++i )
      {
        newGeometry = newGeometries.at( i );
        QgsFeature newFeature;
        newFeature.setGeometry( newGeometry );

        //use default value where possible (primary key issue), otherwise the value from the original (split) feature
        QgsAttributes newAttributes = select_it->attributes();
        QVariant defaultValue;
        for ( int j = 0; j < newAttributes.count(); ++j )
        {
          defaultValue = L->dataProvider()->defaultValue( j );
          if ( !defaultValue.isNull() )
          {
            newAttributes[ j ] = defaultValue;
          }
        }

        newFeature.setAttributes( newAttributes );

        newFeatures.append( newFeature );
      }

      if ( topologicalEditing )
      {
        QList<QgsPoint>::const_iterator topol_it = topologyTestPoints.constBegin();
        for ( ; topol_it != topologyTestPoints.constEnd(); ++topol_it )
        {
          addTopologicalPoints( *topol_it );
        }
      }
      ++numberOfSplittedFeatures;
    }
    else if ( splitFunctionReturn > 1 ) //1 means no split but also no error
    {
      returnCode = splitFunctionReturn;
    }
  }

  if ( numberOfSplittedFeatures == 0 && selectedIds.size() > 0 )
  {
    //There is a selection but no feature has been split.
    //Maybe user forgot that only the selected features are split
    returnCode = 4;
  }


  //now add the new features to this vectorlayer
  L->editBuffer()->addFeatures( newFeatures );

  return returnCode;
}
Esempio n. 4
0
int QgsVectorLayerEditUtils::splitParts( const QList<QgsPoint>& splitLine, bool topologicalEditing )
{
  if ( !L->hasGeometryType() )
    return 4;

  double xMin, yMin, xMax, yMax;
  QgsRectangle bBox; //bounding box of the split line
  int returnCode = 0;
  int splitFunctionReturn; //return code of QgsGeometry::splitGeometry
  int numberOfSplittedParts = 0;

  QgsFeatureIterator fit;

  if ( L->selectedFeatureCount() > 0 ) //consider only the selected features if there is a selection
  {
    fit = L->selectedFeaturesIterator();
  }
  else //else consider all the feature that intersect the bounding box of the split line
  {
    if ( boundingBoxFromPointList( splitLine, xMin, yMin, xMax, yMax ) == 0 )
    {
      bBox.setXMinimum( xMin );
      bBox.setYMinimum( yMin );
      bBox.setXMaximum( xMax );
      bBox.setYMaximum( yMax );
    }
    else
    {
      return 1;
    }

    if ( bBox.isEmpty() )
    {
      //if the bbox is a line, try to make a square out of it
      if ( bBox.width() == 0.0 && bBox.height() > 0 )
      {
        bBox.setXMinimum( bBox.xMinimum() - bBox.height() / 2 );
        bBox.setXMaximum( bBox.xMaximum() + bBox.height() / 2 );
      }
      else if ( bBox.height() == 0.0 && bBox.width() > 0 )
      {
        bBox.setYMinimum( bBox.yMinimum() - bBox.width() / 2 );
        bBox.setYMaximum( bBox.yMaximum() + bBox.width() / 2 );
      }
      else
      {
        //If we have a single point, we still create a non-null box
        double bufferDistance = 0.000001;
        if ( L->crs().isGeographic() )
          bufferDistance = 0.00000001;
        bBox.setXMinimum( bBox.xMinimum() - bufferDistance );
        bBox.setXMaximum( bBox.xMaximum() + bufferDistance );
        bBox.setYMinimum( bBox.yMinimum() - bufferDistance );
        bBox.setYMaximum( bBox.yMaximum() + bufferDistance );
      }
    }

    fit = L->getFeatures( QgsFeatureRequest().setFilterRect( bBox ).setFlags( QgsFeatureRequest::ExactIntersect ) );
  }

  int addPartRet = 0;

  QgsFeature feat;
  while ( fit.nextFeature( feat ) )
  {
    QList<QgsGeometry> newGeometries;
    QList<QgsPoint> topologyTestPoints;
    QgsGeometry featureGeom = feat.geometry();
    splitFunctionReturn = featureGeom.splitGeometry( splitLine, newGeometries, topologicalEditing, topologyTestPoints );
    if ( splitFunctionReturn == 0 )
    {
      //add new parts
      if ( !newGeometries.isEmpty() )
        featureGeom.convertToMultiType();

      for ( int i = 0; i < newGeometries.size(); ++i )
      {
        addPartRet = featureGeom.addPart( newGeometries.at( i ) );
        if ( addPartRet )
          break;
      }

      // For test only: Exception already thrown here...
      // feat.geometry()->asWkb();

      if ( !addPartRet )
      {
        L->editBuffer()->changeGeometry( feat.id(), featureGeom );
      }
      else
      {
        // Test addPartRet
        switch ( addPartRet )
        {
          case 1:
            QgsDebugMsg( "Not a multipolygon" );
            break;

          case 2:
            QgsDebugMsg( "Not a valid geometry" );
            break;

          case 3:
            QgsDebugMsg( "New polygon ring" );
            break;
        }
      }
      L->editBuffer()->changeGeometry( feat.id(), featureGeom );

      if ( topologicalEditing )
      {
        QList<QgsPoint>::const_iterator topol_it = topologyTestPoints.constBegin();
        for ( ; topol_it != topologyTestPoints.constEnd(); ++topol_it )
        {
          addTopologicalPoints( *topol_it );
        }
      }
      ++numberOfSplittedParts;
    }
    else if ( splitFunctionReturn > 1 ) //1 means no split but also no error
    {
      returnCode = splitFunctionReturn;
    }
  }

  if ( numberOfSplittedParts == 0 && L->selectedFeatureCount() > 0  && returnCode == 0 )
  {
    //There is a selection but no feature has been split.
    //Maybe user forgot that only the selected features are split
    returnCode = 4;
  }

  return returnCode;
}
Esempio n. 5
0
int QgsVectorLayerEditUtils::splitFeatures( const QList<QgsPoint>& splitLine, bool topologicalEditing )
{
  if ( !L->hasGeometryType() )
    return 4;

  QgsFeatureList newFeatures; //store all the newly created features
  double xMin, yMin, xMax, yMax;
  QgsRectangle bBox; //bounding box of the split line
  int returnCode = 0;
  int splitFunctionReturn; //return code of QgsGeometry::splitGeometry
  int numberOfSplittedFeatures = 0;

  QgsFeatureIterator features;
  const QgsFeatureIds selectedIds = L->selectedFeatureIds();

  if ( !selectedIds.isEmpty() ) //consider only the selected features if there is a selection
  {
    features = L->selectedFeaturesIterator();
  }
  else //else consider all the feature that intersect the bounding box of the split line
  {
    if ( boundingBoxFromPointList( splitLine, xMin, yMin, xMax, yMax ) == 0 )
    {
      bBox.setXMinimum( xMin );
      bBox.setYMinimum( yMin );
      bBox.setXMaximum( xMax );
      bBox.setYMaximum( yMax );
    }
    else
    {
      return 1;
    }

    if ( bBox.isEmpty() )
    {
      //if the bbox is a line, try to make a square out of it
      if ( bBox.width() == 0.0 && bBox.height() > 0 )
      {
        bBox.setXMinimum( bBox.xMinimum() - bBox.height() / 2 );
        bBox.setXMaximum( bBox.xMaximum() + bBox.height() / 2 );
      }
      else if ( bBox.height() == 0.0 && bBox.width() > 0 )
      {
        bBox.setYMinimum( bBox.yMinimum() - bBox.width() / 2 );
        bBox.setYMaximum( bBox.yMaximum() + bBox.width() / 2 );
      }
      else
      {
        //If we have a single point, we still create a non-null box
        double bufferDistance = 0.000001;
        if ( L->crs().isGeographic() )
          bufferDistance = 0.00000001;
        bBox.setXMinimum( bBox.xMinimum() - bufferDistance );
        bBox.setXMaximum( bBox.xMaximum() + bufferDistance );
        bBox.setYMinimum( bBox.yMinimum() - bufferDistance );
        bBox.setYMaximum( bBox.yMaximum() + bufferDistance );
      }
    }

    features = L->getFeatures( QgsFeatureRequest().setFilterRect( bBox ).setFlags( QgsFeatureRequest::ExactIntersect ) );
  }

  QgsFeature feat;
  while ( features.nextFeature( feat ) )
  {
    if ( !feat.hasGeometry() )
    {
      continue;
    }
    QList<QgsGeometry> newGeometries;
    QList<QgsPoint> topologyTestPoints;
    QgsGeometry featureGeom = feat.geometry();
    splitFunctionReturn = featureGeom.splitGeometry( splitLine, newGeometries, topologicalEditing, topologyTestPoints );
    if ( splitFunctionReturn == 0 )
    {
      //change this geometry
      L->editBuffer()->changeGeometry( feat.id(), featureGeom );

      //insert new features
      for ( int i = 0; i < newGeometries.size(); ++i )
      {
        QgsFeature f = QgsVectorLayerUtils::createFeature( L, newGeometries.at( i ), feat.attributes().toMap() );
        L->editBuffer()->addFeature( f );
      }

      if ( topologicalEditing )
      {
        QList<QgsPoint>::const_iterator topol_it = topologyTestPoints.constBegin();
        for ( ; topol_it != topologyTestPoints.constEnd(); ++topol_it )
        {
          addTopologicalPoints( *topol_it );
        }
      }
      ++numberOfSplittedFeatures;
    }
    else if ( splitFunctionReturn > 1 ) //1 means no split but also no error
    {
      returnCode = splitFunctionReturn;
    }
  }

  if ( numberOfSplittedFeatures == 0 && !selectedIds.isEmpty() )
  {
    //There is a selection but no feature has been split.
    //Maybe user forgot that only the selected features are split
    returnCode = 4;
  }

  return returnCode;
}
Esempio n. 6
0
QgsGeometry::OperationResult QgsVectorLayerEditUtils::splitParts( const QVector<QgsPointXY> &splitLine, bool topologicalEditing )
{
  if ( !mLayer->isSpatial() )
    return QgsGeometry::InvalidBaseGeometry;

  double xMin, yMin, xMax, yMax;
  QgsRectangle bBox; //bounding box of the split line
  QgsGeometry::OperationResult returnCode = QgsGeometry::OperationResult::Success;
  QgsGeometry::OperationResult splitFunctionReturn; //return code of QgsGeometry::splitGeometry
  int numberOfSplitParts = 0;

  QgsFeatureIterator fit;

  if ( mLayer->selectedFeatureCount() > 0 ) //consider only the selected features if there is a selection
  {
    fit = mLayer->getSelectedFeatures();
  }
  else //else consider all the feature that intersect the bounding box of the split line
  {
    if ( boundingBoxFromPointList( splitLine, xMin, yMin, xMax, yMax ) )
    {
      bBox.setXMinimum( xMin );
      bBox.setYMinimum( yMin );
      bBox.setXMaximum( xMax );
      bBox.setYMaximum( yMax );
    }
    else
    {
      return QgsGeometry::OperationResult::InvalidInputGeometryType;
    }

    if ( bBox.isEmpty() )
    {
      //if the bbox is a line, try to make a square out of it
      if ( bBox.width() == 0.0 && bBox.height() > 0 )
      {
        bBox.setXMinimum( bBox.xMinimum() - bBox.height() / 2 );
        bBox.setXMaximum( bBox.xMaximum() + bBox.height() / 2 );
      }
      else if ( bBox.height() == 0.0 && bBox.width() > 0 )
      {
        bBox.setYMinimum( bBox.yMinimum() - bBox.width() / 2 );
        bBox.setYMaximum( bBox.yMaximum() + bBox.width() / 2 );
      }
      else
      {
        //If we have a single point, we still create a non-null box
        double bufferDistance = 0.000001;
        if ( mLayer->crs().isGeographic() )
          bufferDistance = 0.00000001;
        bBox.setXMinimum( bBox.xMinimum() - bufferDistance );
        bBox.setXMaximum( bBox.xMaximum() + bufferDistance );
        bBox.setYMinimum( bBox.yMinimum() - bufferDistance );
        bBox.setYMaximum( bBox.yMaximum() + bufferDistance );
      }
    }

    fit = mLayer->getFeatures( QgsFeatureRequest().setFilterRect( bBox ).setFlags( QgsFeatureRequest::ExactIntersect ) );
  }

  QgsGeometry::OperationResult addPartRet = QgsGeometry::OperationResult::Success;

  QgsFeature feat;
  while ( fit.nextFeature( feat ) )
  {
    QVector<QgsGeometry> newGeometries;
    QVector<QgsPointXY> topologyTestPoints;
    QgsGeometry featureGeom = feat.geometry();
    splitFunctionReturn = featureGeom.splitGeometry( splitLine, newGeometries, topologicalEditing, topologyTestPoints );
    if ( splitFunctionReturn == 0 )
    {
      //add new parts
      if ( !newGeometries.isEmpty() )
        featureGeom.convertToMultiType();

      for ( int i = 0; i < newGeometries.size(); ++i )
      {
        addPartRet = featureGeom.addPart( newGeometries.at( i ) );
        if ( addPartRet )
          break;
      }

      // For test only: Exception already thrown here...
      // feat.geometry()->asWkb();

      if ( !addPartRet )
      {
        mLayer->editBuffer()->changeGeometry( feat.id(), featureGeom );
      }

      if ( topologicalEditing )
      {
        QVector<QgsPointXY>::const_iterator topol_it = topologyTestPoints.constBegin();
        for ( ; topol_it != topologyTestPoints.constEnd(); ++topol_it )
        {
          addTopologicalPoints( *topol_it );
        }
      }
      ++numberOfSplitParts;
    }
    else if ( splitFunctionReturn != QgsGeometry::OperationResult::Success && splitFunctionReturn != QgsGeometry::OperationResult::NothingHappened )
    {
      returnCode = splitFunctionReturn;
    }
  }

  if ( numberOfSplitParts == 0 && mLayer->selectedFeatureCount() > 0  && returnCode == QgsGeometry::Success )
  {
    //There is a selection but no feature has been split.
    //Maybe user forgot that only the selected features are split
    returnCode = QgsGeometry::OperationResult::NothingHappened;
  }

  return returnCode;
}