Пример #1
0
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 ) );
  }
}
QgsGeometry QgsGeometryAnalyzer::locateBetweenMeasures( double fromMeasure, double toMeasure, const QgsGeometry& lineGeom )
{
  if ( lineGeom.isEmpty() )
  {
    return QgsGeometry();
  }

  QgsMultiPolyline resultGeom;

  //need to go with WKB and z coordinate until QgsGeometry supports M values
  QByteArray wkb( lineGeom.exportToWkb() );
  QgsConstWkbPtr wkbPtr( wkb );
  wkbPtr.readHeader();

  QgsWkbTypes::Type wkbType = lineGeom.wkbType();
  if ( wkbType != QgsWkbTypes::LineString25D && wkbType != QgsWkbTypes::MultiLineString25D )
  {
    return QgsGeometry();
  }

  if ( wkbType == QgsWkbTypes::LineString25D )
  {
    locateBetweenWkbString( wkbPtr, resultGeom, fromMeasure, toMeasure );
  }
  else if ( wkbType == QgsWkbTypes::MultiLineString25D )
  {
    int nLines;
    wkbPtr >> nLines;
    for ( int i = 0; i < nLines; ++i )
    {
      wkbPtr.readHeader();
      wkbPtr = locateBetweenWkbString( wkbPtr, resultGeom, fromMeasure, toMeasure );
    }
  }
Пример #3
0
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 ) );
  }
}
Пример #4
0
static bool _check_intersecting_rings( const QgsPolygon &polygon )
{
  // At this point we assume that input polygons are valid according to the OGC definition.
  // This means e.g. no duplicate points, polygons are simple (no butterfly shaped polygon with self-intersection),
  // internal rings are inside exterior rings, rings do not cross each other, no dangles.

  // There is however an issue with polygons where rings touch:
  //  +---+
  //  |   |
  //  | +-+-+
  //  | | | |
  //  | +-+ |
  //  |     |
  //  +-----+
  // This is a valid polygon with one exterior and one interior ring that touch at one point,
  // but poly2tri library does not allow interior rings touch each other or exterior ring.
  // TODO: Handle the situation better - rather than just detecting the problem, try to fix
  // it by converting touching rings into one ring.

  if ( polygon.numInteriorRings() > 0 )
  {
    QList<QgsGeometry> geomRings;
    geomRings << QgsGeometry( polygon.exteriorRing()->clone() );
    for ( int i = 0; i < polygon.numInteriorRings(); ++i )
      geomRings << QgsGeometry( polygon.interiorRing( i )->clone() );

    for ( int i = 0; i < geomRings.count(); ++i )
      for ( int j = i + 1; j < geomRings.count(); ++j )
      {
        if ( geomRings[i].intersects( geomRings[j] ) )
          return false;
      }
  }
  return true;
}
Пример #5
0
//! Generalize the WKB-geometry using the BBOX of the original geometry
static QgsGeometry generalizeWkbGeometryByBoundingBox(
  QgsWkbTypes::Type wkbType,
  const QgsAbstractGeometry& geometry,
  const QgsRectangle &envelope )
{
  unsigned int geometryType = QgsWkbTypes::singleType( QgsWkbTypes::flatType( wkbType ) );

  // If the geometry is already minimal skip the generalization
  int minimumSize = geometryType == QgsWkbTypes::LineString ? 2 : 5;

  if ( geometry.nCoordinates() <= minimumSize )
  {
    return QgsGeometry( geometry.clone() );
  }

  const double x1 = envelope.xMinimum();
  const double y1 = envelope.yMinimum();
  const double x2 = envelope.xMaximum();
  const double y2 = envelope.yMaximum();

  // Write the generalized geometry
  if ( geometryType == QgsWkbTypes::LineString )
  {
    QgsLineString* lineString = new QgsLineString();
    lineString->addVertex( QgsPointV2( x1, y1 ) );
    lineString->addVertex( QgsPointV2( x2, y2 ) );
    return QgsGeometry( lineString );
  }
  else
  {
    return QgsGeometry::fromRect( envelope );
  }
}
Пример #6
0
void QgsMapToolCapture::validateGeometry()
{
  QgsSettings settings;
  if ( settings.value( QStringLiteral( "qgis/digitizing/validate_geometries" ), 1 ).toInt() == 0 )
    return;

  if ( mValidator )
  {
    mValidator->deleteLater();
    mValidator = nullptr;
  }

  mGeomErrors.clear();
  while ( !mGeomErrorMarkers.isEmpty() )
  {
    delete mGeomErrorMarkers.takeFirst();
  }

  QgsGeometry geom;

  switch ( mCaptureMode )
  {
    case CaptureNone:
    case CapturePoint:
      return;
    case CaptureLine:
      if ( size() < 2 )
        return;
      geom = QgsGeometry( mCaptureCurve.curveToLine() );
      break;
    case CapturePolygon:
      if ( size() < 3 )
        return;
      QgsLineString *exteriorRing = mCaptureCurve.curveToLine();
      exteriorRing->close();
      QgsPolygon *polygon = new QgsPolygon();
      polygon->setExteriorRing( exteriorRing );
      geom = QgsGeometry( polygon );
      break;
  }

  if ( geom.isNull() )
    return;

  QgsGeometry::ValidationMethod method = QgsGeometry::ValidatorQgisInternal;
  if ( settings.value( QStringLiteral( "qgis/digitizing/validate_geometries" ), 1 ).toInt() == 2 )
    method = QgsGeometry::ValidatorGeos;
  mValidator = new QgsGeometryValidator( geom, nullptr, method );
  connect( mValidator, &QgsGeometryValidator::errorFound, this, &QgsMapToolCapture::addError );
  mValidator->start();
  QgsDebugMsgLevel( QStringLiteral( "Validation started" ), 4 );
}
Пример #7
0
QgsGeometry QgsInternalGeometryEngine::extrude( double x, double y ) const
{
  QVector<QgsLineString *> linesToProcess;

  const QgsMultiCurve *multiCurve = qgsgeometry_cast< const QgsMultiCurve * >( mGeometry );
  if ( multiCurve )
  {
    for ( int i = 0; i < multiCurve->partCount(); ++i )
    {
      linesToProcess << static_cast<QgsLineString *>( multiCurve->geometryN( i )->clone() );
    }
  }

  const QgsCurve *curve = qgsgeometry_cast< const QgsCurve * >( mGeometry );
  if ( curve )
  {
    linesToProcess << static_cast<QgsLineString *>( curve->segmentize() );
  }

  std::unique_ptr<QgsMultiPolygon> multipolygon( linesToProcess.size() > 1 ? new QgsMultiPolygon() : nullptr );
  QgsPolygon *polygon = nullptr;

  if ( !linesToProcess.empty() )
  {
    std::unique_ptr< QgsLineString > secondline;
    for ( QgsLineString *line : qgis::as_const( linesToProcess ) )
    {
      QTransform transform = QTransform::fromTranslate( x, y );

      secondline.reset( line->reversed() );
      secondline->transform( transform );

      line->append( secondline.get() );
      line->addVertex( line->pointN( 0 ) );

      polygon = new QgsPolygon();
      polygon->setExteriorRing( line );

      if ( multipolygon )
        multipolygon->addGeometry( polygon );
    }

    if ( multipolygon )
      return QgsGeometry( multipolygon.release() );
    else
      return QgsGeometry( polygon );
  }

  return QgsGeometry();
}
Пример #8
0
QgsGeometry QgsTransectSample::closestMultilineElement( const QgsPoint& pt, const QgsGeometry& multiLine )
{
  if ( !multiLine || ( multiLine.wkbType() != QgsWkbTypes::MultiLineString
                       && multiLine.wkbType() != QgsWkbTypes::MultiLineString25D ) )
  {
    return QgsGeometry();
  }

  double minDist = DBL_MAX;
  double currentDist = 0;
  QgsGeometry currentLine;
  QgsGeometry closestLine;
  QgsGeometry pointGeom = QgsGeometry::fromPoint( pt );

  QgsMultiPolyline multiPolyline = multiLine.asMultiPolyline();
  QgsMultiPolyline::const_iterator it = multiPolyline.constBegin();
  for ( ; it != multiPolyline.constEnd(); ++it )
  {
    currentLine = QgsGeometry::fromPolyline( *it );
    currentDist = pointGeom.distance( currentLine );
    if ( currentDist < minDist )
    {
      minDist = currentDist;
      closestLine = currentLine;
    }
  }

  return closestLine;
}
Пример #9
0
QVariantMap QgsDissolveAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
{
  return processCollection( parameters, context, feedback, [ & ]( const QVector< QgsGeometry > &parts )->QgsGeometry
  {
    QgsGeometry result( QgsGeometry::unaryUnion( parts ) );
    if ( QgsWkbTypes::geometryType( result.wkbType() ) == QgsWkbTypes::LineGeometry )
      result = result.mergeLines();
    // Geos may fail in some cases, let's try a slower but safer approach
    // See: https://issues.qgis.org/issues/20591 - Dissolve tool failing to produce outputs
    if ( ! result.lastError().isEmpty() && parts.count() >  2 )
    {
      if ( feedback->isCanceled() )
        return result;

      feedback->pushDebugInfo( QObject::tr( "GEOS exception: taking the slower route ..." ) );
      result = QgsGeometry();
      for ( const auto &p : parts )
      {
        result = QgsGeometry::unaryUnion( QVector< QgsGeometry >() << result << p );
        if ( QgsWkbTypes::geometryType( result.wkbType() ) == QgsWkbTypes::LineGeometry )
          result = result.mergeLines();
        if ( feedback->isCanceled() )
          return result;
      }
    }
    if ( ! result.lastError().isEmpty() )
    {
      feedback->reportError( result.lastError(), true );
      if ( result.isEmpty() )
        throw QgsProcessingException( QObject::tr( "The algorithm returned no output." ) );
    }
    return result;
  }, 10000 );
}
Пример #10
0
QgsAtlasComposition::QgsAtlasComposition( QgsComposition* composition )
    : mComposition( composition )
    , mEnabled( false )
    , mHideCoverage( false )
    , mFilenamePattern( "'output_'||$feature" )
    , mCoverageLayer( 0 )
    , mSingleFile( false )
    , mSortFeatures( false )
    , mSortAscending( true )
    , mCurrentFeatureNo( 0 )
    , mFilterFeatures( false )
{

  // declare special columns with a default value
  QgsExpression::setSpecialColumn( "$page", QVariant(( int )1 ) );
  QgsExpression::setSpecialColumn( "$feature", QVariant(( int )0 ) );
  QgsExpression::setSpecialColumn( "$numpages", QVariant(( int )1 ) );
  QgsExpression::setSpecialColumn( "$numfeatures", QVariant(( int )0 ) );
  QgsExpression::setSpecialColumn( "$atlasfeatureid", QVariant(( int )0 ) );
  QgsExpression::setSpecialColumn( "$atlasfeature", QVariant::fromValue( QgsFeature() ) );
  QgsExpression::setSpecialColumn( "$atlasgeometry", QVariant::fromValue( QgsGeometry() ) );

  //listen out for layer removal
  connect( QgsMapLayerRegistry::instance(), SIGNAL( layersWillBeRemoved( QStringList ) ), this, SLOT( removeLayers( QStringList ) ) );
}
void QgsRelationEditorWidget::addFeature()
{
  QgsAttributeMap keyAttrs;

  const QgsVectorLayerTools* vlTools = mEditorContext.vectorLayerTools();

  if ( mNmRelation.isValid() )
  {
    // n:m Relation: first let the user create a new feature on the other table
    // and autocreate a new linking feature.
    QgsFeature f;
    if ( vlTools->addFeature( mNmRelation.referencedLayer(), QgsAttributeMap(), QgsGeometry(), &f ) )
    {
      QgsFeature flink( mRelation.referencingLayer()->fields() ); // Linking feature

      flink.setAttribute( mRelation.fieldPairs().at( 0 ).first, mFeature.attribute( mRelation.fieldPairs().at( 0 ).second ) );
      flink.setAttribute( mNmRelation.referencingFields().at( 0 ), f.attribute( mNmRelation.referencedFields().at( 0 ) ) );

      mRelation.referencingLayer()->addFeature( flink );

      updateUi();
    }
  }
  else
  {
    QgsFields fields = mRelation.referencingLayer()->fields();

    Q_FOREACH ( const QgsRelation::FieldPair& fieldPair, mRelation.fieldPairs() )
    {
      keyAttrs.insert( fields.indexFromName( fieldPair.referencingField() ), mFeature.attribute( fieldPair.referencedField() ) );
    }

    vlTools->addFeature( mDualView->masterModel()->layer(), keyAttrs );
  }
}
Пример #12
0
QgsGeometry QgsAtlasComposition::currentGeometry( const QgsCoordinateReferenceSystem& crs ) const
{
  if ( !mCoverageLayer || !mCurrentFeature.isValid() || !mCurrentFeature.hasGeometry() )
  {
    return QgsGeometry();
  }

  if ( !crs.isValid() )
  {
    // no projection, return the native geometry
    return mCurrentFeature.geometry();
  }

  QMap<long, QgsGeometry>::const_iterator it = mGeometryCache.constFind( crs.srsid() );
  if ( it != mGeometryCache.constEnd() )
  {
    // we have it in cache, return it
    return it.value();
  }

  if ( mCoverageLayer->crs() == crs )
  {
    return mCurrentFeature.geometry();
  }

  QgsGeometry transformed = mCurrentFeature.geometry();
  transformed.transform( QgsCoordinateTransformCache::instance()->transform( mCoverageLayer->crs().authid(), crs.authid() ) );
  mGeometryCache[crs.srsid()] = transformed;
  return transformed;
}
Пример #13
0
bool QgsGeometryCheckerResultTab::exportErrorsDo( const QString& file )
{
  QList< QPair<QString, QString> > attributes;
  attributes.append( qMakePair( QString( "FeatureID" ), QString( "String;10;" ) ) );
  attributes.append( qMakePair( QString( "ErrorDesc" ), QString( "String;80;" ) ) );

  QLibrary ogrLib( QgsProviderRegistry::instance()->library( "ogr" ) );
  if ( !ogrLib.load() )
  {
    return false;
  }
  typedef bool ( *createEmptyDataSourceProc )( const QString&, const QString&, const QString&, Qgis::WkbType, const QList< QPair<QString, QString> >&, const QgsCoordinateReferenceSystem& );
  createEmptyDataSourceProc createEmptyDataSource = ( createEmptyDataSourceProc ) cast_to_fptr( ogrLib.resolve( "createEmptyDataSource" ) );
  if ( !createEmptyDataSource )
  {
    return false;
  }
  if ( !createEmptyDataSource( file, "ESRI Shapefile", mFeaturePool->getLayer()->dataProvider()->encoding(), Qgis::WKBPoint, attributes, mFeaturePool->getLayer()->crs() ) )
  {
    return false;
  }
  QgsVectorLayer* layer = new QgsVectorLayer( file, QFileInfo( file ).baseName(), "ogr" );
  if ( !layer->isValid() )
  {
    delete layer;
    return false;
  }

  int fieldFeatureId = layer->fieldNameIndex( "FeatureID" );
  int fieldErrDesc = layer->fieldNameIndex( "ErrorDesc" );
  for ( int row = 0, nRows = ui.tableWidgetErrors->rowCount(); row < nRows; ++row )
  {
    QgsGeometryCheckError* error = ui.tableWidgetErrors->item( row, 0 )->data( Qt::UserRole ).value<QgsGeometryCheckError*>();

    QgsFeature f( layer->fields() );
    f.setAttribute( fieldFeatureId, error->featureId() );
    f.setAttribute( fieldErrDesc, error->description() );
    f.setGeometry( QgsGeometry( error->location().clone() ) );
    layer->dataProvider()->addFeatures( QgsFeatureList() << f );
  }

  // Remove existing layer with same uri
  QStringList toRemove;
  Q_FOREACH ( QgsMapLayer* maplayer, QgsMapLayerRegistry::instance()->mapLayers() )
  {
    if ( dynamic_cast<QgsVectorLayer*>( maplayer ) &&
         static_cast<QgsVectorLayer*>( maplayer )->dataProvider()->dataSourceUri() == layer->dataProvider()->dataSourceUri() )
    {
      toRemove.append( maplayer->id() );
    }
  }
  if ( !toRemove.isEmpty() )
  {
    QgsMapLayerRegistry::instance()->removeMapLayers( toRemove );
  }

  QgsMapLayerRegistry::instance()->addMapLayers( QList<QgsMapLayer*>() << layer );
  return true;
}
Пример #14
0
Qt3DRender::QGeometryRenderer *QgsLine3DSymbolEntityNode::renderer( const Qgs3DMapSettings &map, const QgsLine3DSymbol &symbol, const QgsVectorLayer *layer, const QgsFeatureRequest &request )
{
  QgsPointXY origin( map.origin().x(), map.origin().y() );

  // TODO: configurable
  int nSegments = 4;
  QgsGeometry::EndCapStyle endCapStyle = QgsGeometry::CapRound;
  QgsGeometry::JoinStyle joinStyle = QgsGeometry::JoinStyleRound;
  double mitreLimit = 0;

  QList<QgsPolygon *> polygons;
  QgsFeature f;
  QgsFeatureIterator fi = layer->getFeatures( request );
  while ( fi.nextFeature( f ) )
  {
    if ( f.geometry().isNull() )
      continue;

    QgsGeometry geom = f.geometry();

    // segmentize curved geometries if necessary
    if ( QgsWkbTypes::isCurvedType( geom.constGet()->wkbType() ) )
      geom = QgsGeometry( geom.constGet()->segmentize() );

    const QgsAbstractGeometry *g = geom.constGet();

    QgsGeos engine( g );
    QgsAbstractGeometry *buffered = engine.buffer( symbol.width() / 2., nSegments, endCapStyle, joinStyle, mitreLimit ); // factory

    if ( QgsWkbTypes::flatType( buffered->wkbType() ) == QgsWkbTypes::Polygon )
    {
      QgsPolygon *polyBuffered = static_cast<QgsPolygon *>( buffered );
      Qgs3DUtils::clampAltitudes( polyBuffered, symbol.altitudeClamping(), symbol.altitudeBinding(), symbol.height(), map );
      polygons.append( polyBuffered );
    }
    else if ( QgsWkbTypes::flatType( buffered->wkbType() ) == QgsWkbTypes::MultiPolygon )
    {
      QgsMultiPolygon *mpolyBuffered = static_cast<QgsMultiPolygon *>( buffered );
      for ( int i = 0; i < mpolyBuffered->numGeometries(); ++i )
      {
        QgsAbstractGeometry *partBuffered = mpolyBuffered->geometryN( i );
        Q_ASSERT( QgsWkbTypes::flatType( partBuffered->wkbType() ) == QgsWkbTypes::Polygon );
        QgsPolygon *polyBuffered = static_cast<QgsPolygon *>( partBuffered )->clone(); // need to clone individual geometry parts
        Qgs3DUtils::clampAltitudes( polyBuffered, symbol.altitudeClamping(), symbol.altitudeBinding(), symbol.height(), map );
        polygons.append( polyBuffered );
      }
      delete buffered;
    }
  }

  mGeometry = new QgsTessellatedPolygonGeometry;
  mGeometry->setPolygons( polygons, origin, symbol.extrusionHeight() );

  Qt3DRender::QGeometryRenderer *renderer = new Qt3DRender::QGeometryRenderer;
  renderer->setGeometry( mGeometry );

  return renderer;
}
Пример #15
0
static bool _check_intersecting_rings( const QgsPolygon &polygon )
{
  QList<QgsGeometry> geomRings;
  geomRings << QgsGeometry( polygon.exteriorRing()->clone() );
  for ( int i = 0; i < polygon.numInteriorRings(); ++i )
    geomRings << QgsGeometry( polygon.interiorRing( i )->clone() );

  // we need to make sure that the polygon has no rings with self-intersection: that may
  // crash the tessellator. The original geometry maybe have been valid and the self-intersection
  // was introduced when transforming to a new base (in a rare case when all points are not in the same plane)

  for ( int i = 0; i < geomRings.count(); ++i )
  {
    if ( !geomRings[i].isSimple() )
      return false;
  }

  // At this point we assume that input polygons are valid according to the OGC definition.
  // This means e.g. no duplicate points, polygons are simple (no butterfly shaped polygon with self-intersection),
  // internal rings are inside exterior rings, rings do not cross each other, no dangles.

  // There is however an issue with polygons where rings touch:
  //  +---+
  //  |   |
  //  | +-+-+
  //  | | | |
  //  | +-+ |
  //  |     |
  //  +-----+
  // This is a valid polygon with one exterior and one interior ring that touch at one point,
  // but poly2tri library does not allow interior rings touch each other or exterior ring.
  // TODO: Handle the situation better - rather than just detecting the problem, try to fix
  // it by converting touching rings into one ring.

  if ( polygon.numInteriorRings() > 0 )
  {
    for ( int i = 0; i < geomRings.count(); ++i )
      for ( int j = i + 1; j < geomRings.count(); ++j )
      {
        if ( geomRings[i].intersects( geomRings[j] ) )
          return false;
      }
  }
  return true;
}
Пример #16
0
QgsGeometry QgsMeshCalculatorDialog::maskGeometry() const
{
  QgsVectorLayer *mask_layer = qobject_cast<QgsVectorLayer *> ( cboLayerMask->currentLayer() );
  if ( mask_layer )
  {
    return maskGeometry( mask_layer );
  }
  return QgsGeometry();
}
Пример #17
0
QgsGeometry QgsTransectSample::findBaselineGeometry( const QVariant& strataId )
{
  if ( !mBaselineLayer )
  {
    return QgsGeometry();
  }

  QgsFeatureIterator baseLineIt = mBaselineLayer->getFeatures( QgsFeatureRequest().setSubsetOfAttributes( QStringList( mBaselineStrataId ), mBaselineLayer->fields() ) );
  QgsFeature fet;

  while ( baseLineIt.nextFeature( fet ) ) //todo: cache this in case there are many baslines
  {
    if ( strataId == fet.attribute( mBaselineStrataId ) || mShareBaseline )
    {
      return fet.geometry();
    }
  }
  return QgsGeometry();
}
Пример #18
0
QgsGeometry QgsOgrUtils::ogrGeometryToQgsGeometry( OGRGeometryH geom )
{
  if ( !geom )
    return QgsGeometry();

  // get the wkb representation
  int memorySize = OGR_G_WkbSize( geom );
  unsigned char *wkb = new unsigned char[memorySize];
  OGR_G_ExportToWkb( geom, ( OGRwkbByteOrder ) QgsApplication::endian(), wkb );

  QgsGeometry g;
  g.fromWkb( wkb, memorySize );
  return g;
}
void QgsZonalStatistics::statisticsFromPreciseIntersection( void* band, const QgsGeometry& poly, int pixelOffsetX,
    int pixelOffsetY, int nCellsX, int nCellsY, double cellSizeX, double cellSizeY, const QgsRectangle& rasterBBox, FeatureStats &stats )
{
  stats.reset();

  double currentY = rasterBBox.yMaximum() - pixelOffsetY * cellSizeY - cellSizeY / 2;
  float* pixelData = ( float * ) CPLMalloc( sizeof( float ) );
  QgsGeometry pixelRectGeometry;

  double hCellSizeX = cellSizeX / 2.0;
  double hCellSizeY = cellSizeY / 2.0;
  double pixelArea = cellSizeX * cellSizeY;
  double weight = 0;

  for ( int row = 0; row < nCellsY; ++row )
  {
    double currentX = rasterBBox.xMinimum() + cellSizeX / 2.0 + pixelOffsetX * cellSizeX;
    for ( int col = 0; col < nCellsX; ++col )
    {
      if ( GDALRasterIO( band, GF_Read, pixelOffsetX + col, pixelOffsetY + row, nCellsX, 1, pixelData, 1, 1, GDT_Float32, 0, 0 ) != CE_None )
      {
        QgsDebugMsg( "Raster IO Error" );
      }

      if ( !validPixel( *pixelData ) )
        continue;

      pixelRectGeometry = QgsGeometry::fromRect( QgsRectangle( currentX - hCellSizeX, currentY - hCellSizeY, currentX + hCellSizeX, currentY + hCellSizeY ) );
      if ( !pixelRectGeometry.isEmpty() )
      {
        //intersection
        QgsGeometry intersectGeometry = pixelRectGeometry.intersection( poly );
        if ( !intersectGeometry.isEmpty() )
        {
          double intersectionArea = intersectGeometry.area();
          if ( intersectionArea >= 0.0 )
          {
            weight = intersectionArea / pixelArea;
            stats.addValue( *pixelData, weight );
          }
        }
        pixelRectGeometry = QgsGeometry();
      }
      currentX += cellSizeX;
    }
    currentY -= cellSizeY;
  }
  CPLFree( pixelData );
}
Пример #20
0
void QgsZonalStatistics::statisticsFromPreciseIntersection( const QgsGeometry &poly, int pixelOffsetX,
    int pixelOffsetY, int nCellsX, int nCellsY, double cellSizeX, double cellSizeY, const QgsRectangle &rasterBBox, FeatureStats &stats )
{
  stats.reset();

  double currentY = rasterBBox.yMaximum() - pixelOffsetY * cellSizeY - cellSizeY / 2;
  QgsGeometry pixelRectGeometry;

  double hCellSizeX = cellSizeX / 2.0;
  double hCellSizeY = cellSizeY / 2.0;
  double pixelArea = cellSizeX * cellSizeY;
  double weight = 0;

  QgsRectangle featureBBox = poly.boundingBox().intersect( &rasterBBox );
  QgsRectangle intersectBBox = rasterBBox.intersect( &featureBBox );

  QgsRasterBlock *block = mRasterProvider->block( mRasterBand, intersectBBox, nCellsX, nCellsY );
  for ( int i = 0; i < nCellsY; ++i )
  {
    double currentX = rasterBBox.xMinimum() + cellSizeX / 2.0 + pixelOffsetX * cellSizeX;
    for ( int j = 0; j < nCellsX; ++j )
    {
      if ( !validPixel( block->value( i, j ) ) )
      {
        continue;
      }

      pixelRectGeometry = QgsGeometry::fromRect( QgsRectangle( currentX - hCellSizeX, currentY - hCellSizeY, currentX + hCellSizeX, currentY + hCellSizeY ) );
      if ( !pixelRectGeometry.isNull() )
      {
        //intersection
        QgsGeometry intersectGeometry = pixelRectGeometry.intersection( poly );
        if ( !intersectGeometry.isNull() )
        {
          double intersectionArea = intersectGeometry.area();
          if ( intersectionArea >= 0.0 )
          {
            weight = intersectionArea / pixelArea;
            stats.addValue( block->value( i, j ), weight );
          }
        }
        pixelRectGeometry = QgsGeometry();
      }
      currentX += cellSizeX;
    }
    currentY -= cellSizeY;
  }
  delete block;
}
QgsVectorLayerUndoCommandChangeGeometry::QgsVectorLayerUndoCommandChangeGeometry( QgsVectorLayerEditBuffer *buffer, QgsFeatureId fid, const QgsGeometry &newGeom )
  : QgsVectorLayerUndoCommand( buffer )
  , mFid( fid )
  , mNewGeom( newGeom )
{
  if ( FID_IS_NEW( mFid ) )
  {
    QgsFeatureMap::const_iterator it = mBuffer->mAddedFeatures.constFind( mFid );
    Q_ASSERT( it != mBuffer->mAddedFeatures.constEnd() );
    mOldGeom = ( it.value().geometry() );
  }
  else
  {
    mOldGeom = mBuffer->mChangedGeometries.value( mFid, QgsGeometry() );
  }
}
Пример #22
0
void QgsBufferedLine3DSymbolHandler::processFeature( QgsFeature &f, const Qgs3DRenderContext &context )
{
  if ( f.geometry().isNull() )
    return;

  LineData &out = mSelectedIds.contains( f.id() ) ? outSelected : outNormal;

  QgsGeometry geom = f.geometry();

  // segmentize curved geometries if necessary
  if ( QgsWkbTypes::isCurvedType( geom.constGet()->wkbType() ) )
    geom = QgsGeometry( geom.constGet()->segmentize() );

  const QgsAbstractGeometry *g = geom.constGet();

  // TODO: configurable
  const int nSegments = 4;
  const QgsGeometry::EndCapStyle endCapStyle = QgsGeometry::CapRound;
  const QgsGeometry::JoinStyle joinStyle = QgsGeometry::JoinStyleRound;
  const double mitreLimit = 0;

  QgsGeos engine( g );
  QgsAbstractGeometry *buffered = engine.buffer( mSymbol.width() / 2., nSegments, endCapStyle, joinStyle, mitreLimit ); // factory

  if ( QgsWkbTypes::flatType( buffered->wkbType() ) == QgsWkbTypes::Polygon )
  {
    QgsPolygon *polyBuffered = static_cast<QgsPolygon *>( buffered );
    Qgs3DUtils::clampAltitudes( polyBuffered, mSymbol.altitudeClamping(), mSymbol.altitudeBinding(), mSymbol.height(), context.map() );
    out.polygons.append( polyBuffered );
    out.fids.append( f.id() );
  }
  else if ( QgsWkbTypes::flatType( buffered->wkbType() ) == QgsWkbTypes::MultiPolygon )
  {
    QgsMultiPolygon *mpolyBuffered = static_cast<QgsMultiPolygon *>( buffered );
    for ( int i = 0; i < mpolyBuffered->numGeometries(); ++i )
    {
      QgsAbstractGeometry *partBuffered = mpolyBuffered->geometryN( i );
      Q_ASSERT( QgsWkbTypes::flatType( partBuffered->wkbType() ) == QgsWkbTypes::Polygon );
      QgsPolygon *polyBuffered = static_cast<QgsPolygon *>( partBuffered )->clone(); // need to clone individual geometry parts
      Qgs3DUtils::clampAltitudes( polyBuffered, mSymbol.altitudeClamping(), mSymbol.altitudeBinding(), mSymbol.height(), context.map() );
      out.polygons.append( polyBuffered );
      out.fids.append( f.id() );
    }
    delete buffered;
  }
}
Пример #23
0
QgsAtlasComposition::QgsAtlasComposition( QgsComposition* composition ) :
    mComposition( composition ),
    mEnabled( false ),
    mHideCoverage( false ), mFilenamePattern( "'output_'||$feature" ),
    mCoverageLayer( 0 ), mSingleFile( false ),
    mSortFeatures( false ), mSortAscending( true ), mCurrentFeatureNo( 0 ),
    mFilterFeatures( false ), mFeatureFilter( "" )
{

  // declare special columns with a default value
  QgsExpression::setSpecialColumn( "$page", QVariant(( int )1 ) );
  QgsExpression::setSpecialColumn( "$feature", QVariant(( int )0 ) );
  QgsExpression::setSpecialColumn( "$numpages", QVariant(( int )1 ) );
  QgsExpression::setSpecialColumn( "$numfeatures", QVariant(( int )0 ) );
  QgsExpression::setSpecialColumn( "$atlasfeatureid", QVariant(( int )0 ) );
  QgsExpression::setSpecialColumn( "$atlasgeometry", QVariant::fromValue( QgsGeometry() ) );
}
Пример #24
0
bool QgsVectorLayerUndoCommandChangeGeometry::mergeWith( const QUndoCommand *other )
{
  if ( other->id() != id() )
    return false;

  const QgsVectorLayerUndoCommandChangeGeometry *merge = dynamic_cast<const QgsVectorLayerUndoCommandChangeGeometry *>( other );
  if ( !merge )
    return false;

  if ( merge->mFid != mFid )
    return false;

  mNewGeom = merge->mNewGeom;
  merge->mNewGeom = QgsGeometry();

  return true;
}
Пример #25
0
QgsGeometry QgsInternalGeometryEngine::poleOfInaccessibility( double precision, double *distanceFromBoundary ) const
{
  if ( distanceFromBoundary )
    *distanceFromBoundary = DBL_MAX;

  if ( !mGeometry || mGeometry->isEmpty() )
    return QgsGeometry();

  if ( precision <= 0 )
    return QgsGeometry();

  if ( const QgsGeometryCollection *gc = qgsgeometry_cast< const QgsGeometryCollection *>( mGeometry ) )
  {
    int numGeom = gc->numGeometries();
    double maxDist = 0;
    QgsPoint bestPoint;
    bool found = false;
    for ( int i = 0; i < numGeom; ++i )
    {
      const QgsSurface *surface = qgsgeometry_cast< const QgsSurface * >( gc->geometryN( i ) );
      if ( !surface )
        continue;

      found = true;
      double dist = DBL_MAX;
      QgsPoint p = surfacePoleOfInaccessibility( surface, precision, dist );
      if ( dist > maxDist )
      {
        maxDist = dist;
        bestPoint = p;
      }
    }

    if ( !found )
      return QgsGeometry();

    if ( distanceFromBoundary )
      *distanceFromBoundary = maxDist;
    return QgsGeometry( new QgsPoint( bestPoint ) );
  }
  else
  {
    const QgsSurface *surface = qgsgeometry_cast< const QgsSurface * >( mGeometry );
    if ( !surface )
      return QgsGeometry();

    double dist = DBL_MAX;
    QgsPoint p = surfacePoleOfInaccessibility( surface, precision, dist );
    if ( distanceFromBoundary )
      *distanceFromBoundary = dist;
    return QgsGeometry( new QgsPoint( p ) );
  }
}
Пример #26
0
QgsGeometry QgsDelimitedTextProvider::geomFromWkt( QString &sWkt, bool wktHasPrefixRegexp )
{
  QgsGeometry geom;
  try
  {
    if ( wktHasPrefixRegexp )
    {
      sWkt.remove( WktPrefixRegexp );
    }

    geom = QgsGeometry::fromWkt( sWkt );
  }
  catch ( ... )
  {
    geom = QgsGeometry();
  }
  return geom;
}
Пример #27
0
QgsVectorLayerUndoCommandChangeGeometry::QgsVectorLayerUndoCommandChangeGeometry( QgsVectorLayerEditBuffer* buffer, QgsFeatureId fid, const QgsGeometry& newGeom )
    : QgsVectorLayerUndoCommand( buffer )
    , mFid( fid )
    , mNewGeom( newGeom )
{
  if ( FID_IS_NEW( mFid ) )
  {
    QgsFeatureMap::const_iterator it = mBuffer->mAddedFeatures.constFind( mFid );
    Q_ASSERT( it != mBuffer->mAddedFeatures.constEnd() );
    mOldGeom = ( it.value().geometry() );
  }
  else
  {
    bool changedAlready = mBuffer->mChangedGeometries.contains( mFid );
    QgsGeometry geom;
    bool cachedGeom = cache()->geometry( mFid, geom );
    mOldGeom = ( changedAlready && cachedGeom ) ? geom : QgsGeometry();
  }
}
Пример #28
0
    void testNullGeometries()
    {
      QgsVectorLayer *vlNullGeom = new QgsVectorLayer( "Polygon", "x", "memory" );
      QgsFeature ff( 0 );
      ff.setGeometry( QgsGeometry() );
      QgsFeatureList flist;
      flist << ff;
      vlNullGeom->dataProvider()->addFeatures( flist );

      QgsPointLocator loc( vlNullGeom, QgsCoordinateReferenceSystem(), nullptr );

      QgsPointLocator::Match m1 = loc.nearestVertex( QgsPointXY( 2, 2 ), std::numeric_limits<double>::max() );
      QVERIFY( !m1.isValid() );

      QgsPointLocator::Match m2 = loc.nearestEdge( QgsPointXY( 2, 2 ), std::numeric_limits<double>::max() );
      QVERIFY( !m2.isValid() );

      delete vlNullGeom;
    }
void QgsGeometryMultipartCheck::fixError( const QMap<QString, QgsFeaturePool *> &featurePools, QgsGeometryCheckError *error, int method, const QMap<QString, int> & /*mergeAttributeIndices*/, Changes &changes ) const
{
  QgsFeaturePool *featurePool = featurePools[ error->layerId() ];
  QgsFeature feature;
  if ( !featurePool->getFeature( error->featureId(), feature ) )
  {
    error->setObsolete();
    return;
  }
  QgsGeometry featureGeom = feature.geometry();
  const QgsAbstractGeometry *geom = featureGeom.constGet();

  // Check if error still applies
  if ( geom->partCount() > 1 || !QgsWkbTypes::isMultiType( geom->wkbType() ) )
  {
    error->setObsolete();
    return;
  }

  // Fix error
  if ( method == NoChange )
  {
    error->setFixed( method );
  }
  else if ( method == ConvertToSingle )
  {
    feature.setGeometry( QgsGeometry( QgsGeometryCheckerUtils::getGeomPart( geom, 0 )->clone() ) );
    featurePool->updateFeature( feature );
    error->setFixed( method );
    changes[error->layerId()][feature.id()].append( Change( ChangeFeature, ChangeChanged ) );
  }
  else if ( method == RemoveObject )
  {
    featurePool->deleteFeature( feature.id() );
    error->setFixed( method );
    changes[error->layerId()][feature.id()].append( Change( ChangeFeature, ChangeRemoved ) );
  }
  else
  {
    error->setFixFailed( tr( "Unknown method" ) );
  }
}
Пример #30
0
void QgsGeometryCheck::replaceFeatureGeometryPart( const QString &layerId, QgsFeature &feature, int partIdx, QgsAbstractGeometry *newPartGeom, Changes &changes ) const
{
  QgsFeaturePool *featurePool = mContext->featurePools[layerId];
  QgsGeometry featureGeom = feature.geometry();
  QgsAbstractGeometry *geom = featureGeom.get();
  if ( QgsGeometryCollection *geomCollection = dynamic_cast< QgsGeometryCollection *>( geom ) )
  {
    geomCollection->removeGeometry( partIdx );
    geomCollection->addGeometry( newPartGeom );
    changes[layerId][feature.id()].append( Change( ChangePart, ChangeRemoved, QgsVertexId( partIdx ) ) );
    changes[layerId][feature.id()].append( Change( ChangePart, ChangeAdded, QgsVertexId( geomCollection->partCount() - 1 ) ) );
    feature.setGeometry( featureGeom );
  }
  else
  {
    feature.setGeometry( QgsGeometry( newPartGeom ) );
    changes[layerId][feature.id()].append( Change( ChangeFeature, ChangeChanged ) );
  }
  featurePool->updateFeature( feature );
}