Example #1
0
std::unique_ptr<QgsMultiLineString> QgsGeometryFactory::fromMultiPolylineXY( const QgsMultiPolylineXY &multiline )
{
  std::unique_ptr< QgsMultiLineString > mLine = qgis::make_unique< QgsMultiLineString >();
  for ( int i = 0; i < multiline.size(); ++i )
  {
    mLine->addGeometry( fromPolylineXY( multiline.at( i ) ).release() );
  }
  return mLine;
}
Example #2
0
ErrorList topolTest::checkPseudos( QgsVectorLayer *layer1, QgsVectorLayer *layer2, bool isExtent )
{
  Q_UNUSED( layer2 );

  int i = 0;
  ErrorList errorList;
  QgsFeature f;

  if ( layer1->geometryType() != QgsWkbTypes::LineGeometry )
  {
    return errorList;
  }

  QList<FeatureLayer>::iterator it;

  qDebug() << mFeatureList1.count();

  QgsPointXY startPoint;
  QgsPointXY endPoint;

  std::multimap<QgsPointXY, QgsFeatureId, PointComparer> endVerticesMap;

  for ( it = mFeatureList1.begin(); it != mFeatureList1.end(); ++it )
  {
    if ( !( ++i % 100 ) )
      emit progress( i );

    if ( testCanceled() )
      break;

    QgsGeometry g1 = it->feature.geometry();

    if ( g1.isNull() )
    {
      QgsMessageLog::logMessage( tr( "Skipping invalid first geometry in pseudo line test." ), tr( "Topology plugin" ) );
      continue;
    }

    if ( !_canExportToGeos( g1 ) )
    {
      QgsMessageLog::logMessage( tr( "Failed to import first geometry into GEOS in pseudo line test." ), tr( "Topology plugin" ) );
      continue;
    }

    if ( g1.isMultipart() )
    {
      QgsMultiPolylineXY lines = g1.asMultiPolyline();
      for ( int m = 0; m < lines.count(); m++ )
      {
        QgsPolylineXY line = lines[m];
        startPoint = line[0];
        endPoint = line[line.size() - 1];

        endVerticesMap.insert( std::pair<QgsPointXY, QgsFeatureId>( startPoint, it->feature.id() ) );
        endVerticesMap.insert( std::pair<QgsPointXY, QgsFeatureId>( endPoint, it->feature.id() ) );

      }
    }
    else
    {
      QgsPolylineXY polyline = g1.asPolyline();
      startPoint = polyline[0];
      endPoint = polyline[polyline.size() - 1];
      endVerticesMap.insert( std::pair<QgsPointXY, QgsFeatureId>( startPoint, it->feature.id() ) );
      endVerticesMap.insert( std::pair<QgsPointXY, QgsFeatureId>( endPoint, it->feature.id() ) );
    }
  }


  QgsGeometry canvasExtentPoly = QgsGeometry::fromWkt( qgsInterface->mapCanvas()->extent().asWktPolygon() );


  for ( std::multimap<QgsPointXY, QgsFeatureId, PointComparer>::iterator pointIt = endVerticesMap.begin(), end = endVerticesMap.end(); pointIt != end; pointIt = endVerticesMap.upper_bound( pointIt->first ) )
  {
    QgsPointXY p = pointIt->first;
    QgsFeatureId k = pointIt->second;

    size_t repetitions = endVerticesMap.count( p );

    if ( repetitions == 2 )
    {
      QgsGeometry conflictGeom = QgsGeometry::fromPointXY( p );

      if ( isExtent )
      {
        if ( canvasExtentPoly.disjoint( conflictGeom ) )
        {
          continue;
        }
      }

      QgsRectangle bBox = conflictGeom.boundingBox();
      QgsFeature feat;

      FeatureLayer ftrLayer1;
      //need to fetch attributes?? being safe side by fetching..
      layer1->getFeatures( QgsFeatureRequest().setFilterFid( k ) ).nextFeature( feat );
      ftrLayer1.feature = feat;
      ftrLayer1.layer = layer1;

      QList<FeatureLayer> errorFtrLayers;
      errorFtrLayers << ftrLayer1 << ftrLayer1;

      TopolErrorPseudos *err = new TopolErrorPseudos( bBox, conflictGeom, errorFtrLayers );
      errorList << err;

    }
  }
  return errorList;
}
QgsGeometry QgsMapToolDeletePart::partUnderPoint( QPoint point, QgsFeatureId &fid, int &partNum )
{
  QgsFeature f;
  QgsGeometry geomPart;

  switch ( vlayer->geometryType() )
  {
    case QgsWkbTypes::PointGeometry:
    case QgsWkbTypes::LineGeometry:
    {
      QgsPointLocator::Match match = mCanvas->snappingUtils()->snapToCurrentLayer( point, QgsPointLocator::Types( QgsPointLocator::Vertex | QgsPointLocator::Edge ) );
      if ( !match.isValid() )
        return geomPart;

      int snapVertex = match.vertexIndex();
      vlayer->getFeatures( QgsFeatureRequest().setFilterFid( match.featureId() ) ).nextFeature( f );
      QgsGeometry g = f.geometry();
      if ( !g.isMultipart() )
      {
        fid = match.featureId();
        return QgsGeometry::fromPointXY( match.point() );
      }
      else if ( QgsWkbTypes::geometryType( g.wkbType() ) == QgsWkbTypes::PointGeometry )
      {
        fid = match.featureId();
        partNum = snapVertex;
        return QgsGeometry::fromPointXY( match.point() );
      }
      else if ( QgsWkbTypes::geometryType( g.wkbType() ) == QgsWkbTypes::LineGeometry )
      {
        QgsMultiPolylineXY mline = g.asMultiPolyline();
        for ( int part = 0; part < mline.count(); part++ )
        {
          if ( snapVertex < mline[part].count() )
          {
            fid = match.featureId();
            partNum = part;
            return QgsGeometry::fromPolylineXY( mline[part] );
          }
          snapVertex -= mline[part].count();
        }
      }
      break;
    }
    case QgsWkbTypes::PolygonGeometry:
    {
      QgsPointLocator::Match match = mCanvas->snappingUtils()->snapToCurrentLayer( point, QgsPointLocator::Area );
      if ( !match.isValid() )
        return geomPart;

      vlayer->getFeatures( QgsFeatureRequest().setFilterFid( match.featureId() ) ).nextFeature( f );
      QgsGeometry g = f.geometry();
      if ( g.isNull() )
        return geomPart;

      QgsPointXY layerCoords = toLayerCoordinates( vlayer, point );

      if ( !g.isMultipart() )
      {
        fid = f.id();
        return geomPart;
      }
      QgsMultiPolygonXY mpolygon = g.asMultiPolygon();
      for ( int part = 0; part < mpolygon.count(); part++ ) // go through the polygons
      {
        const QgsPolygonXY &polygon = mpolygon[part];
        QgsGeometry partGeo = QgsGeometry::fromPolygonXY( polygon );
        if ( partGeo.contains( &layerCoords ) )
        {
          fid = f.id();
          partNum = part;
          return partGeo;
        }
      }
      break;
    }
    default:
    {
      break;
    }
  }
  return geomPart;
}
Example #4
0
void QgsMapToolOffsetCurve::prepareGeometry( const QgsPointLocator::Match &match, QgsFeature &snappedFeature )
{
  QgsVectorLayer *vl = match.layer();
  if ( !vl )
  {
    return;
  }

  mOriginalGeometry = QgsGeometry();
  mManipulatedGeometry = QgsGeometry();
  mModifiedPart = -1;
  mModifiedRing = -1;

  //assign feature part by vertex number (snap to vertex) or by before vertex number (snap to segment)
  QgsGeometry geom = snappedFeature.geometry();
  if ( geom.isNull() )
  {
    return;
  }
  mOriginalGeometry = geom;

  QgsWkbTypes::Type geomType = geom.wkbType();
  if ( QgsWkbTypes::geometryType( geomType ) == QgsWkbTypes::LineGeometry )
  {
    if ( !match.hasEdge() )
    {
      return;
    }
    if ( !geom.isMultipart() )
    {
      mManipulatedGeometry = geom;
    }
    else
    {
      int vertex = match.vertexIndex();
      QgsVertexId vertexId;
      geom.vertexIdFromVertexNr( vertex, vertexId );
      mModifiedPart = vertexId.part;

      QgsMultiPolylineXY multiLine = geom.asMultiPolyline();
      mManipulatedGeometry = QgsGeometry::fromPolylineXY( multiLine.at( mModifiedPart ) );
    }
  }
  else if ( QgsWkbTypes::geometryType( geomType ) == QgsWkbTypes::PolygonGeometry )
  {
    if ( !match.hasEdge() && match.hasArea() )
    {
      if ( !geom.isMultipart() )
      {
        mManipulatedGeometry = geom;
      }
      else
      {
        // get the correct part
        QgsMultiPolygonXY mpolygon = geom.asMultiPolygon();
        for ( int part = 0; part < mpolygon.count(); part++ ) // go through the polygons
        {
          const QgsPolygonXY &polygon = mpolygon[part];
          QgsGeometry partGeo = QgsGeometry::fromPolygonXY( polygon );
          const QgsPointXY layerCoords = match.point();
          if ( partGeo.contains( &layerCoords ) )
          {
            mModifiedPart = part;
            mManipulatedGeometry = partGeo;
          }
        }
      }
    }
    else if ( match.hasEdge() )
    {
      int vertex = match.vertexIndex();
      QgsVertexId vertexId;
      geom.vertexIdFromVertexNr( vertex, vertexId );
      QgsDebugMsg( QStringLiteral( "%1" ).arg( vertexId.ring ) );

      if ( !geom.isMultipart() )
      {
        QgsPolygonXY poly = geom.asPolygon();
        // if has rings
        if ( poly.count() > 0 )
        {
          mModifiedRing = vertexId.ring;
          mManipulatedGeometry = QgsGeometry::fromPolygonXY( QgsPolygonXY() << poly.at( mModifiedRing ) );
        }
        else
        {
          mManipulatedGeometry = QgsGeometry::fromPolygonXY( poly );
        }

      }
      else
      {
        mModifiedPart = vertexId.part;
        // get part, get ring
        QgsMultiPolygonXY multiPoly = geom.asMultiPolygon();
        // if has rings
        if ( multiPoly.at( mModifiedPart ).count() > 0 )
        {
          mModifiedRing = vertexId.ring;
          mManipulatedGeometry = QgsGeometry::fromPolygonXY( QgsPolygonXY() << multiPoly.at( mModifiedPart ).at( mModifiedRing ) );
        }
        else
        {
          mManipulatedGeometry = QgsGeometry::fromPolygonXY( multiPoly.at( mModifiedPart ) );
        }
      }
    }
  }
}
Example #5
0
void QgsMapToolOffsetCurve::applyOffset( double offset, Qt::KeyboardModifiers modifiers )
{
  if ( !mLayer || offset == 0.0 )
  {
    cancel();
    notifyNotVectorLayer();
    return;
  }

  updateGeometryAndRubberBand( offset );

  // no modification
  if ( !mGeometryModified )
  {
    mLayer->destroyEditCommand();
    cancel();
    return;
  }

  if ( mModifiedPart >= 0 )
  {
    QgsGeometry geometry;
    int partIndex = 0;
    QgsWkbTypes::Type geomType = mOriginalGeometry.wkbType();
    if ( QgsWkbTypes::geometryType( geomType ) == QgsWkbTypes::LineGeometry )
    {
      QgsMultiPolylineXY newMultiLine;
      QgsMultiPolylineXY multiLine = mOriginalGeometry.asMultiPolyline();
      QgsMultiPolylineXY::const_iterator it = multiLine.constBegin();
      for ( ; it != multiLine.constEnd(); ++it )
      {
        if ( partIndex == mModifiedPart )
        {
          newMultiLine.append( mModifiedGeometry.asPolyline() );
        }
        else
        {
          newMultiLine.append( *it );
        }
        partIndex++;
      }
      geometry = QgsGeometry::fromMultiPolylineXY( newMultiLine );
    }
    else
    {
      QgsMultiPolygonXY newMultiPoly;
      const QgsMultiPolygonXY multiPoly = mOriginalGeometry.asMultiPolygon();
      QgsMultiPolygonXY::const_iterator multiPolyIt = multiPoly.constBegin();
      for ( ; multiPolyIt != multiPoly.constEnd(); ++multiPolyIt )
      {
        if ( partIndex == mModifiedPart )
        {
          if ( mModifiedGeometry.isMultipart() )
          {
            // not a ring
            if ( mModifiedRing <= 0 )
            {
              // part became mulitpolygon, that means discard original rings from the part
              newMultiPoly += mModifiedGeometry.asMultiPolygon();
            }
            else
            {
              // ring became multipolygon, oh boy!
              QgsPolygonXY newPoly;
              int ringIndex = 0;
              QgsPolygonXY::const_iterator polyIt = multiPolyIt->constBegin();
              for ( ; polyIt != multiPolyIt->constEnd(); ++polyIt )
              {
                if ( ringIndex == mModifiedRing )
                {
                  const QgsMultiPolygonXY ringParts = mModifiedGeometry.asMultiPolygon();
                  QgsPolygonXY newRings;
                  QgsMultiPolygonXY::const_iterator ringIt = ringParts.constBegin();
                  for ( ; ringIt != ringParts.constEnd(); ++ringIt )
                  {
                    // the different parts of the new rings cannot have rings themselves
                    newRings.append( ringIt->at( 0 ) );
                  }
                  newPoly += newRings;
                }
                else
                {
                  newPoly.append( *polyIt );
                }
                ringIndex++;
              }
              newMultiPoly.append( newPoly );
            }
          }
          else
          {
            // original part had no ring
            if ( mModifiedRing == -1 )
            {
              newMultiPoly.append( mModifiedGeometry.asPolygon() );
            }
            else
            {
              QgsPolygonXY newPoly;
              int ringIndex = 0;
              QgsPolygonXY::const_iterator polyIt = multiPolyIt->constBegin();
              for ( ; polyIt != multiPolyIt->constEnd(); ++polyIt )
              {
                if ( ringIndex == mModifiedRing )
                {
                  newPoly.append( mModifiedGeometry.asPolygon().at( 0 ) );
                }
                else
                {
                  newPoly.append( *polyIt );
                }
                ringIndex++;
              }
              newMultiPoly.append( newPoly );
            }
          }
        }
        else
        {
          newMultiPoly.append( *multiPolyIt );
        }
        partIndex++;
      }
      geometry = QgsGeometry::fromMultiPolygonXY( newMultiPoly );
    }
    geometry.convertToMultiType();
    mModifiedGeometry = geometry;
  }
  else if ( mModifiedRing >= 0 )
  {
    // original geometry had some rings
    if ( mModifiedGeometry.isMultipart() )
    {
      // not a ring
      if ( mModifiedRing == 0 )
      {
        // polygon became mulitpolygon, that means discard original rings from the part
        // keep the modified geometry as is
      }
      else
      {
        QgsPolygonXY newPoly;
        const QgsPolygonXY poly = mOriginalGeometry.asPolygon();

        // ring became multipolygon, oh boy!
        int ringIndex = 0;
        QgsPolygonXY::const_iterator polyIt = poly.constBegin();
        for ( ; polyIt != poly.constEnd(); ++polyIt )
        {
          if ( ringIndex == mModifiedRing )
          {
            QgsMultiPolygonXY ringParts = mModifiedGeometry.asMultiPolygon();
            QgsPolygonXY newRings;
            QgsMultiPolygonXY::const_iterator ringIt = ringParts.constBegin();
            for ( ; ringIt != ringParts.constEnd(); ++ringIt )
            {
              // the different parts of the new rings cannot have rings themselves
              newRings.append( ringIt->at( 0 ) );
            }
            newPoly += newRings;
          }
          else
          {
            newPoly.append( *polyIt );
          }
          ringIndex++;
        }
        mModifiedGeometry = QgsGeometry::fromPolygonXY( newPoly );
      }
    }
    else
    {
      // simple case where modified geom is a polygon (not multi)
      QgsPolygonXY newPoly;
      const QgsPolygonXY poly = mOriginalGeometry.asPolygon();

      int ringIndex = 0;
      QgsPolygonXY::const_iterator polyIt = poly.constBegin();
      for ( ; polyIt != poly.constEnd(); ++polyIt )
      {
        if ( ringIndex == mModifiedRing )
        {
          newPoly.append( mModifiedGeometry.asPolygon().at( 0 ) );
        }
        else
        {
          newPoly.append( *polyIt );
        }
        ringIndex++;
      }
      mModifiedGeometry = QgsGeometry::fromPolygonXY( newPoly );
    }
  }

  if ( !mModifiedGeometry.isGeosValid() )
  {
    emit messageEmitted( tr( "Generated geometry is not valid." ), Qgis::Critical );
    // no cancel, continue editing.
    return;
  }

  mLayer->beginEditCommand( tr( "Offset curve" ) );

  bool editOk;
  if ( !mCtrlHeldOnFirstClick && !( modifiers & Qt::ControlModifier ) )
  {
    editOk = mLayer->changeGeometry( mModifiedFeature, mModifiedGeometry );
  }
  else
  {
    QgsFeature f;
    f.setGeometry( mModifiedGeometry );

    //add empty values for all fields (allows inserting attribute values via the feature form in the same session)
    QgsAttributes attrs( mLayer->fields().count() );
    const QgsFields &fields = mLayer->fields();
    for ( int idx = 0; idx < fields.count(); ++idx )
    {
      attrs[idx] = QVariant();
    }
    f.setAttributes( attrs );
    editOk = mLayer->addFeature( f );
  }

  if ( editOk )
  {
    mLayer->endEditCommand();
  }
  else
  {
    mLayer->destroyEditCommand();
    emit messageEmitted( QStringLiteral( "Could not apply offset" ), Qgis::Critical );
  }

  deleteRubberBandAndGeometry();
  deleteUserInputWidget();
  mLayer->triggerRepaint();
  mLayer = nullptr;
}
Example #6
0
int QgsVectorLayerEditUtils::addTopologicalPoints( const QgsGeometry &geom )
{
  if ( !mLayer->isSpatial() )
    return 1;

  if ( geom.isNull() )
  {
    return 1;
  }

  int returnVal = 0;

  QgsWkbTypes::Type wkbType = geom.wkbType();

  switch ( QgsWkbTypes::geometryType( wkbType ) )
  {
    //line
    case QgsWkbTypes::LineGeometry:
    {
      if ( !QgsWkbTypes::isMultiType( wkbType ) )
      {
        QgsPolylineXY line = geom.asPolyline();
        QgsPolylineXY::const_iterator line_it = line.constBegin();
        for ( ; line_it != line.constEnd(); ++line_it )
        {
          if ( addTopologicalPoints( *line_it ) != 0 )
          {
            returnVal = 2;
          }
        }
      }
      else
      {
        QgsMultiPolylineXY multiLine = geom.asMultiPolyline();
        QgsPolylineXY currentPolyline;

        for ( int i = 0; i < multiLine.size(); ++i )
        {
          QgsPolylineXY::const_iterator line_it = currentPolyline.constBegin();
          for ( ; line_it != currentPolyline.constEnd(); ++line_it )
          {
            if ( addTopologicalPoints( *line_it ) != 0 )
            {
              returnVal = 2;
            }
          }
        }
      }
      break;
    }

    case QgsWkbTypes::PolygonGeometry:
    {
      if ( !QgsWkbTypes::isMultiType( wkbType ) )
      {
        QgsPolygonXY polygon = geom.asPolygon();
        QgsPolylineXY currentRing;

        for ( int i = 0; i < polygon.size(); ++i )
        {
          currentRing = polygon.at( i );
          QgsPolylineXY::const_iterator line_it = currentRing.constBegin();
          for ( ; line_it != currentRing.constEnd(); ++line_it )
          {
            if ( addTopologicalPoints( *line_it ) != 0 )
            {
              returnVal = 2;
            }
          }
        }
      }
      else
      {
        QgsMultiPolygonXY multiPolygon = geom.asMultiPolygon();
        QgsPolygonXY currentPolygon;
        QgsPolylineXY currentRing;

        for ( int i = 0; i < multiPolygon.size(); ++i )
        {
          currentPolygon = multiPolygon.at( i );
          for ( int j = 0; j < currentPolygon.size(); ++j )
          {
            currentRing = currentPolygon.at( j );
            QgsPolylineXY::const_iterator line_it = currentRing.constBegin();
            for ( ; line_it != currentRing.constEnd(); ++line_it )
            {
              if ( addTopologicalPoints( *line_it ) != 0 )
              {
                returnVal = 2;
              }
            }
          }
        }
      }
      break;
    }

    case QgsWkbTypes::PointGeometry:
    case QgsWkbTypes::UnknownGeometry:
    case QgsWkbTypes::NullGeometry:
      break;
  }
  return returnVal;
}
Example #7
0
ErrorList topolTest::checkSegmentLength( double tolerance, QgsVectorLayer *layer1, QgsVectorLayer *layer2, bool isExtent )
{
  Q_UNUSED( layer1 );
  Q_UNUSED( layer2 );
  Q_UNUSED( isExtent );

  int i = 0;
  ErrorList errorList;
  QgsFeature f;


  QList<FeatureLayer>::iterator it;

  QgsPolygonXY pol;

  QgsMultiPolygonXY mpol;
  QgsPolylineXY segm;
  QgsPolylineXY ls;
  QgsMultiPolylineXY mls;
  QList<FeatureLayer> fls;
  TopolErrorShort *err = nullptr;
  double distance;

  for ( it = mFeatureList1.begin(); it != mFeatureList1.end(); ++it )
  {
    if ( !( ++i % 100 ) )
    {
      emit progress( i );
    }

    if ( testCanceled() )
    {
      break;
    }

    QgsGeometry g1 = it->feature.geometry();


    // switching by type here, because layer can contain both single and multi version geometries
    switch ( g1.wkbType() )
    {
      case QgsWkbTypes::LineString:
      case QgsWkbTypes::LineString25D:
        ls = g1.asPolyline();


        for ( int i = 1; i < ls.size(); ++i )
        {
          distance = std::sqrt( ls[i - 1].sqrDist( ls[i] ) );
          if ( distance < tolerance )
          {
            fls.clear();
            fls << *it << *it;
            segm.clear();
            segm << ls[i - 1] << ls[i];
            QgsGeometry conflict = QgsGeometry::fromPolylineXY( segm );
            err = new TopolErrorShort( g1.boundingBox(), conflict, fls );
            //err = new TopolErrorShort(g1->boundingBox(), QgsGeometry::fromPolyline(segm), fls);
            errorList << err;
            //break on getting the first error
            break;
          }
        }
        break;

      case QgsWkbTypes::Polygon:
      case QgsWkbTypes::Polygon25D:
        pol = g1.asPolygon();

        for ( int i = 0; i < pol.size(); ++i )
        {
          for ( int j = 1; j < pol[i].size(); ++j )
          {
            distance = std::sqrt( pol[i][j - 1].sqrDist( pol[i][j] ) );
            if ( distance < tolerance )
            {
              fls.clear();
              fls << *it << *it;
              segm.clear();
              segm << pol[i][j - 1] << pol[i][j];
              QgsGeometry conflict = QgsGeometry::fromPolylineXY( segm );
              err = new TopolErrorShort( g1.boundingBox(), conflict, fls );
              errorList << err;
              //break on getting the first error
              break;
            }
          }
        }

        break;

      case QgsWkbTypes::MultiLineString:
      case QgsWkbTypes::MultiLineString25D:
        mls = g1.asMultiPolyline();

        for ( int k = 0; k < mls.size(); ++k )
        {
          QgsPolylineXY &ls = mls[k];
          for ( int i = 1; i < ls.size(); ++i )
          {
            distance = std::sqrt( ls[i - 1].sqrDist( ls[i] ) );
            if ( distance < tolerance )
            {
              fls.clear();
              fls << *it << *it;
              segm.clear();
              segm << ls[i - 1] << ls[i];
              QgsGeometry conflict = QgsGeometry::fromPolylineXY( segm );
              err = new TopolErrorShort( g1.boundingBox(), conflict, fls );
              errorList << err;
              //break on getting the first error
              break;
            }
          }
        }
        break;

      case QgsWkbTypes::MultiPolygon:
      case QgsWkbTypes::MultiPolygon25D:
        mpol = g1.asMultiPolygon();

        for ( int k = 0; k < mpol.size(); ++k )
        {
          QgsPolygonXY &pol = mpol[k];
          for ( int i = 0; i < pol.size(); ++i )
          {
            for ( int j = 1; j < pol[i].size(); ++j )
            {
              distance = pol[i][j - 1].sqrDist( pol[i][j] );
              if ( distance < tolerance )
              {
                fls.clear();
                fls << *it << *it;
                segm.clear();
                segm << pol[i][j - 1] << pol[i][j];
                QgsGeometry conflict = QgsGeometry::fromPolylineXY( segm );
                err = new TopolErrorShort( g1.boundingBox(), conflict, fls );
                errorList << err;
                //break on getting the first error
                break;
              }
            }
          }
        }
        break;

      default:
        continue;
    }
  }

  return errorList;
}
Example #8
0
void QgsGeometryValidator::run()
{
  mErrorCount = 0;
  switch ( mMethod )
  {
    case QgsGeometry::ValidatorGeos:
    {
      char *r = nullptr;
      geos::unique_ptr g0( mGeometry.exportToGeos() );
      GEOSContextHandle_t handle = QgsGeometry::getGEOSHandler();
      if ( !g0 )
      {
        emit errorFound( QgsGeometry::Error( QObject::tr( "GEOS error: could not produce geometry for GEOS (check log window)" ) ) );
      }
      else
      {
        GEOSGeometry *g1 = nullptr;
        char res = GEOSisValidDetail_r( handle, g0.get(), GEOSVALID_ALLOW_SELFTOUCHING_RING_FORMING_HOLE, &r, &g1 );
        if ( res != 1 )
        {
          if ( g1 )
          {
            const GEOSCoordSequence *cs = GEOSGeom_getCoordSeq_r( handle, g1 );

            unsigned int n;
            if ( GEOSCoordSeq_getSize_r( handle, cs, &n ) && n == 1 )
            {
              double x, y;
              GEOSCoordSeq_getX_r( handle, cs, 0, &x );
              GEOSCoordSeq_getY_r( handle, cs, 0, &y );
              emit errorFound( QgsGeometry::Error( QObject::tr( "GEOS error: %1" ).arg( r ), QgsPointXY( x, y ) ) );
              mErrorCount++;
            }

            GEOSGeom_destroy_r( handle, g1 );
          }
          else
          {
            emit errorFound( QgsGeometry::Error( QObject::tr( "GEOS error: %1" ).arg( r ) ) );
            mErrorCount++;
          }

          GEOSFree_r( handle, r );
        }
      }

      break;
    }

    case QgsGeometry::ValidatorQgisInternal:
    {
      QgsWkbTypes::Type flatType = QgsWkbTypes::flatType( mGeometry.wkbType() );
      //if ( flatType == QgsWkbTypes::Point || flatType == QgsWkbTypes::MultiPoint )
      //    break;
      if ( flatType == QgsWkbTypes::LineString )
      {
        validatePolyline( 0, mGeometry.asPolyline() );
      }
      else if ( flatType == QgsWkbTypes::MultiLineString )
      {
        QgsMultiPolylineXY mp = mGeometry.asMultiPolyline();
        for ( int i = 0; !mStop && i < mp.size(); i++ )
          validatePolyline( i, mp[i] );
      }
      else if ( flatType == QgsWkbTypes::Polygon )
      {
        validatePolygon( 0, mGeometry.asPolygon() );
      }
      else if ( flatType == QgsWkbTypes::MultiPolygon )
      {
        QgsMultiPolygonXY mp = mGeometry.asMultiPolygon();
        for ( int i = 0; !mStop && i < mp.size(); i++ )
        {
          validatePolygon( i, mp[i] );
        }

        for ( int i = 0; !mStop && i < mp.size(); i++ )
        {
          if ( mp[i].isEmpty() )
          {
            emit errorFound( QgsGeometry::Error( QObject::tr( "polygon %1 has no rings" ).arg( i ) ) );
            mErrorCount++;
            continue;
          }

          for ( int j = i + 1;  !mStop && j < mp.size(); j++ )
          {
            if ( mp[j].isEmpty() )
              continue;

            if ( ringInRing( mp[i][0], mp[j][0] ) )
            {
              emit errorFound( QgsGeometry::Error( QObject::tr( "polygon %1 inside polygon %2" ).arg( i ).arg( j ) ) );
              mErrorCount++;
            }
            else if ( ringInRing( mp[j][0], mp[i][0] ) )
            {
              emit errorFound( QgsGeometry::Error( QObject::tr( "polygon %1 inside polygon %2" ).arg( j ).arg( i ) ) );
              mErrorCount++;
            }
            else
            {
              checkRingIntersections( i, 0, mp[i][0], j, 0, mp[j][0] );
            }
          }
        }
      }

      else if ( flatType == QgsWkbTypes::Unknown )
      {
        QgsDebugMsg( QObject::tr( "Unknown geometry type" ) );
        emit errorFound( QgsGeometry::Error( QObject::tr( "Unknown geometry type %1" ).arg( mGeometry.wkbType() ) ) );
        mErrorCount++;
      }

      if ( mStop )
      {
        emit errorFound( QgsGeometry::Error( QObject::tr( "Geometry validation was aborted." ) ) );
      }
      else if ( mErrorCount > 0 )
      {
        emit errorFound( QgsGeometry::Error( QObject::tr( "Geometry has %1 errors." ).arg( mErrorCount ) ) );
      }
#if 0
      else
      {
        emit errorFound( QgsGeometry::Error( QObject::tr( "Geometry is valid." ) ) );
      }
#endif
      break;
    }
  }
}
Example #9
0
QgsGeometry QgsMapToolDeletePart::partUnderPoint( QPoint point, QgsFeatureId &fid, int &partNum )
{
  QgsFeature f;
  QgsGeometry geomPart;

  switch ( vlayer->geometryType() )
  {
    case QgsWkbTypes::PointGeometry:
    case QgsWkbTypes::LineGeometry:
    {
      QgsPointLocator::Match match = mCanvas->snappingUtils()->snapToCurrentLayer( point, QgsPointLocator::Types( QgsPointLocator::Vertex | QgsPointLocator::Edge ) );
      if ( !match.isValid() )
        return geomPart;

      int snapVertex = match.vertexIndex();
      vlayer->getFeatures( QgsFeatureRequest().setFilterFid( match.featureId() ) ).nextFeature( f );
      QgsGeometry g = f.geometry();
      if ( !g.isMultipart() )
      {
        fid = match.featureId();
        return QgsGeometry::fromPointXY( match.point() );
      }
      if ( g.wkbType() == QgsWkbTypes::MultiPoint || g.wkbType() == QgsWkbTypes::MultiPoint25D )
      {
        fid = match.featureId();
        partNum = snapVertex;
        return QgsGeometry::fromPointXY( match.point() );
      }
      if ( g.wkbType() == QgsWkbTypes::MultiLineString || g.wkbType() == QgsWkbTypes::MultiLineString25D )
      {
        QgsMultiPolylineXY mline = g.asMultiPolyline();
        for ( int part = 0; part < mline.count(); part++ )
        {
          if ( snapVertex < mline[part].count() )
          {
            fid = match.featureId();
            partNum = part;
            return QgsGeometry::fromPolylineXY( mline[part] );
          }
          snapVertex -= mline[part].count();
        }
      }
      break;
    }
    case QgsWkbTypes::PolygonGeometry:
    {
      QgsPointXY layerCoords = toLayerCoordinates( vlayer, point );
      double searchRadius = QgsTolerance::vertexSearchRadius( mCanvas->currentLayer(), mCanvas->mapSettings() );
      QgsRectangle selectRect( layerCoords.x() - searchRadius, layerCoords.y() - searchRadius,
                               layerCoords.x() + searchRadius, layerCoords.y() + searchRadius );
      QgsFeatureIterator fit = vlayer->getFeatures( QgsFeatureRequest().setFilterRect( selectRect ) );
      fit.nextFeature( f );
      QgsGeometry g = f.geometry();
      if ( g.isNull() )
        return geomPart;
      if ( !g.isMultipart() )
      {
        fid = f.id();
        return geomPart;
      }
      QgsMultiPolygonXY mpolygon = g.asMultiPolygon();
      for ( int part = 0; part < mpolygon.count(); part++ ) // go through the polygons
      {
        const QgsPolygonXY &polygon = mpolygon[part];
        QgsGeometry partGeo = QgsGeometry::fromPolygonXY( polygon );
        if ( partGeo.contains( &layerCoords ) )
        {
          fid = f.id();
          partNum = part;
          return partGeo;
        }
      }
      break;
    }
    default:
    {
      break;
    }
  }
  return geomPart;
}