QgsGeometry QgsInternalGeometryEngine::densifyByDistance( double distance ) const
{
  if ( !mGeometry )
  {
    return QgsGeometry();
  }

  if ( QgsWkbTypes::geometryType( mGeometry->wkbType() ) == QgsWkbTypes::PointGeometry )
  {
    return QgsGeometry( mGeometry->clone() ); // point geometry, nothing to do
  }

  if ( const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
  {
    int numGeom = gc->numGeometries();
    QVector< QgsAbstractGeometry * > geometryList;
    geometryList.reserve( numGeom );
    for ( int i = 0; i < numGeom; ++i )
    {
      geometryList << densifyGeometry( gc->geometryN( i ), -1, distance );
    }

    QgsGeometry first = QgsGeometry( geometryList.takeAt( 0 ) );
    for ( QgsAbstractGeometry *g : qgis::as_const( geometryList ) )
    {
      first.addPart( g );
    }
    return first;
  }
  else
  {
    return QgsGeometry( densifyGeometry( mGeometry, -1, distance ) );
  }
}
示例#2
0
QgsGeometry::OperationResult QgsVectorLayerEditUtils::addPart( QgsCurve *ring, QgsFeatureId featureId )
{
  if ( !mLayer->isSpatial() )
    return QgsGeometry::AddPartSelectedGeometryNotFound;

  QgsGeometry geometry;
  bool firstPart = false;
  QgsFeature f;
  if ( !mLayer->getFeatures( QgsFeatureRequest().setFilterFid( featureId ).setSubsetOfAttributes( QgsAttributeList() ) ).nextFeature( f ) )
    return QgsGeometry::AddPartSelectedGeometryNotFound;

  if ( !f.hasGeometry() )
  {
    //no existing geometry, so adding first part to null geometry
    firstPart = true;
  }
  else
  {
    geometry = f.geometry();
  }

  QgsGeometry::OperationResult errorCode = geometry.addPart( ring, mLayer->geometryType() );
  if ( errorCode == QgsGeometry::Success )
  {
    if ( firstPart && QgsWkbTypes::isSingleType( mLayer->wkbType() )
         && mLayer->dataProvider()->doesStrictFeatureTypeCheck() )
    {
      //convert back to single part if required by layer
      geometry.convertToSingleType();
    }
    mLayer->editBuffer()->changeGeometry( featureId, geometry );
  }
  return errorCode;
}
QgsGeometry QgsInternalGeometryEngine::orthogonalize( double tolerance, int maxIterations, double angleThreshold ) const
{
  if ( !mGeometry || ( QgsWkbTypes::geometryType( mGeometry->wkbType() ) != QgsWkbTypes::LineGeometry
                       && QgsWkbTypes::geometryType( mGeometry->wkbType() ) != QgsWkbTypes::PolygonGeometry ) )
  {
    return QgsGeometry();
  }

  double lowerThreshold = std::cos( ( 90 - angleThreshold ) * M_PI / 180.00 );
  double upperThreshold = std::cos( angleThreshold * M_PI / 180.0 );

  if ( const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
  {
    int numGeom = gc->numGeometries();
    QVector< QgsAbstractGeometry * > geometryList;
    geometryList.reserve( numGeom );
    for ( int i = 0; i < numGeom; ++i )
    {
      geometryList << orthogonalizeGeom( gc->geometryN( i ), maxIterations, tolerance, lowerThreshold, upperThreshold );
    }

    QgsGeometry first = QgsGeometry( geometryList.takeAt( 0 ) );
    for ( QgsAbstractGeometry *g : qgis::as_const( geometryList ) )
    {
      first.addPart( g );
    }
    return first;
  }
  else
  {
    return QgsGeometry( orthogonalizeGeom( mGeometry, maxIterations, tolerance, lowerThreshold, upperThreshold ) );
  }
}
void QgsProjectionSelectionTreeWidget::updateBoundsPreview()
{
  QTreeWidgetItem *lvi = lstCoordinateSystems->currentItem();
  if ( !lvi || lvi->text( QgisCrsIdColumn ).isEmpty() )
    return;

  QgsCoordinateReferenceSystem currentCrs = crs();
  if ( !currentCrs.isValid() )
    return;

  QgsRectangle rect = currentCrs.bounds();
  if ( !qgsDoubleNear( rect.area(), 0.0 ) )
  {
    QgsGeometry geom;
    if ( rect.xMinimum() > rect.xMaximum() )
    {
      QgsRectangle rect1 = QgsRectangle( -180, rect.yMinimum(), rect.xMaximum(), rect.yMaximum() );
      QgsRectangle rect2 = QgsRectangle( rect.xMinimum(), rect.yMinimum(), 180, rect.yMaximum() );
      geom = QgsGeometry::fromRect( rect1 );
      geom.addPart( QgsGeometry::fromRect( rect2 ) );
    }
    else
    {
      geom = QgsGeometry::fromRect( rect );
    }
    mPreviewBand->setToGeometry( geom, nullptr );
    mPreviewBand->setColor( QColor( 255, 0, 0, 65 ) );
    QgsRectangle extent = geom.boundingBox();
    extent.scale( 1.1 );
    mAreaCanvas->setExtent( extent );
    mAreaCanvas->refresh();
    mPreviewBand->show();
    QString extentString = tr( "Extent: %1, %2, %3, %4" )
                           .arg( rect.xMinimum(), 0, 'f', 2 )
                           .arg( rect.yMinimum(), 0, 'f', 2 )
                           .arg( rect.xMaximum(), 0, 'f', 2 )
                           .arg( rect.yMaximum(), 0, 'f', 2 );
    QString proj4String = tr( "Proj4: %1" ).arg( selectedProj4String() );
    teProjection->setText( extentString + "\n" + proj4String );
  }
  else
  {
    mPreviewBand->hide();
    mAreaCanvas->zoomToFullExtent();
    QString extentString = tr( "Extent: Extent not known" );
    QString proj4String = tr( "Proj4: %1" ).arg( selectedProj4String() );
    teProjection->setText( extentString + "\n" + proj4String );
  }
}
示例#5
0
int QgsVectorLayerEditUtils::addPart( QgsCurveV2* ring, QgsFeatureId featureId )
{
  if ( !L->hasGeometryType() )
    return 6;

  QgsGeometry geometry;
  bool firstPart = false;
  if ( !cache()->geometry( featureId, geometry ) ) // maybe it's in cache
  {
    // it's not in cache: let's fetch it from layer
    QgsFeature f;
    if ( !L->getFeatures( QgsFeatureRequest().setFilterFid( featureId ).setSubsetOfAttributes( QgsAttributeList() ) ).nextFeature( f ) )
      return 6; //not found

    if ( !f.constGeometry() || f.constGeometry()->isEmpty() )
    {
      //no existing geometry, so adding first part to null geometry
      firstPart = true;
    }
    else
    {
      geometry = *f.geometry();
    }
  }

  int errorCode = geometry.addPart( ring, L->geometryType() );
  if ( errorCode == 0 )
  {
    if ( firstPart && QgsWKBTypes::isSingleType( QGis::fromOldWkbType( L->wkbType() ) )
         && L->dataProvider()->doesStrictFeatureTypeCheck() )
    {
      //convert back to single part if required by layer
      geometry.convertToSingleType();
    }
    L->editBuffer()->changeGeometry( featureId, &geometry );
  }
  return errorCode;
}
示例#6
0
int QgsVectorLayerEditUtils::addPart( const QList<QgsPoint> &points, QgsFeatureId featureId )
{
    if ( !L->hasGeometryType() )
        return 6;

    QgsGeometry geometry;
    if ( !cache()->geometry( featureId, geometry ) ) // maybe it's in cache
    {
        // it's not in cache: let's fetch it from layer
        QgsFeature f;
        if ( !L->getFeatures( QgsFeatureRequest().setFilterFid( featureId ).setSubsetOfAttributes( QgsAttributeList() ) ).nextFeature( f ) || !f.geometry() )
            return 6; //geometry not found

        geometry = *f.geometry();
    }

    int errorCode = geometry.addPart( points, L->geometryType() );
    if ( errorCode == 0 )
    {
        L->editBuffer()->changeGeometry( featureId, &geometry );
    }
    return errorCode;
}
示例#7
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;
}
示例#8
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;
}