Пример #1
0
bool QgsMapToolReshape::isBindingLine( QgsVectorLayer *vlayer, const QgsRectangle &bbox ) const
{
  if ( vlayer->geometryType() != QgsWkbTypes::LineGeometry )
    return false;

  bool begin = false;
  bool end = false;
  const QgsPointXY beginPoint = points().first();
  const QgsPointXY endPoint = points().last();

  QgsFeatureIterator fit = vlayer->getFeatures( QgsFeatureRequest().setFilterRect( bbox ).setSubsetOfAttributes( QgsAttributeList() ) );
  QgsFeature f;

  // check that extremities of the new line are contained by features
  while ( fit.nextFeature( f ) )
  {
    const QgsGeometry geom = f.geometry();
    if ( !geom.isNull() )
    {
      const QgsPolylineXY line = geom.asPolyline();

      if ( line.contains( beginPoint ) )
        begin = true;
      else if ( line.contains( endPoint ) )
        end = true;
    }
  }

  return end && begin;
}
Пример #2
0
std::unique_ptr<QgsLineString> QgsGeometryFactory::linestringFromPolyline( const QgsPolylineXY &polyline )
{
  QVector< double > x;
  x.reserve( polyline.size() );
  QVector< double > y;
  y.reserve( polyline.size() );
  QgsPolylineXY::const_iterator it = polyline.constBegin();
  for ( ; it != polyline.constEnd(); ++it )
  {
    x << it->x();
    y << it->y();
  }
  std::unique_ptr< QgsLineString > line = qgis::make_unique< QgsLineString >( x, y );
  return line;
}
Пример #3
0
bool QgsGeometryValidator::ringInRing( const QgsPolylineXY &inside, const QgsPolylineXY &outside )
{
  for ( int i = 0; !mStop && i < inside.size(); i++ )
  {
    if ( !pointInRing( outside, inside[i] ) )
      return false;
  }

  return true;
}
Пример #4
0
bool QgsGeometryValidator::pointInRing( const QgsPolylineXY &ring, const QgsPointXY &p )
{
  bool inside = false;
  int j = ring.size() - 1;

  for ( int i = 0; !mStop && i < ring.size(); i++ )
  {
    if ( qgsDoubleNear( ring[i].x(), p.x() ) && qgsDoubleNear( ring[i].y(), p.y() ) )
      return true;

    if ( ( ring[i].y() < p.y() && ring[j].y() >= p.y() ) ||
         ( ring[j].y() < p.y() && ring[i].y() >= p.y() ) )
    {
      if ( ring[i].x() + ( p.y() - ring[i].y() ) / ( ring[j].y() - ring[i].y() ) * ( ring[j].x() - ring[i].x() ) <= p.x() )
        inside = !inside;
    }

    j = i;
  }

  return inside;
}
Пример #5
0
// TODO: move to geometry utils
double closestSegment( const QgsPolylineXY &pl, const QgsPointXY &pt, int &vertexAfter, double epsilon )
{
  double sqrDist = std::numeric_limits<double>::max();
  const QgsPointXY *pldata = pl.constData();
  int plcount = pl.count();
  double prevX = pldata[0].x(), prevY = pldata[0].y();
  double segmentPtX, segmentPtY;
  for ( int i = 1; i < plcount; ++i )
  {
    double currentX = pldata[i].x();
    double currentY = pldata[i].y();
    double testDist = QgsGeometryUtils::sqrDistToLine( pt.x(), pt.y(), prevX, prevY, currentX, currentY, segmentPtX, segmentPtY, epsilon );
    if ( testDist < sqrDist )
    {
      sqrDist = testDist;
      vertexAfter = i;
    }
    prevX = currentX;
    prevY = currentY;
  }
  return sqrDist;
}
Пример #6
0
bool TopolError::fixSnap()
{
  bool ok;
  QgsFeature f1, f2;
  FeatureLayer fl = mFeaturePairs.at( 1 );
  ok = fl.layer->getFeatures( ( QgsFeatureRequest().setFilterFid( fl.feature.id() ) ) ).nextFeature( f2 );
  fl = mFeaturePairs.first();
  ok = ok && fl.layer->getFeatures( QgsFeatureRequest().setFilterFid( fl.feature.id() ) ).nextFeature( f1 );

  if ( !ok )
    return false;

  QgsGeometry ge = f1.geometry();

  QgsPolylineXY line = ge.asPolyline();
  QgsPolylineXY conflictLine = mConflict.asPolyline();
  line.last() = conflictLine.last();

  QgsGeometry newG = QgsGeometry::fromPolylineXY( line );
  bool ret = fl.layer->changeGeometry( f1.id(), newG );

  return ret;
}
Пример #7
0
void QgsGeometryValidator::checkRingIntersections(
  int p0, int i0, const QgsPolylineXY &ring0,
  int p1, int i1, const QgsPolylineXY &ring1 )
{
  for ( int i = 0; !mStop && i < ring0.size() - 1; i++ )
  {
    QgsVector v = ring0[i + 1] - ring0[i];

    for ( int j = 0; !mStop && j < ring1.size() - 1; j++ )
    {
      QgsVector w = ring1[j + 1] - ring1[j];

      QgsPointXY s;
      if ( intersectLines( ring0[i], v, ring1[j], w, s ) )
      {
        double d = -distLine2Point( ring0[i], v.perpVector(), s );

        if ( d >= 0 && d <= v.length() )
        {
          d = -distLine2Point( ring1[j], w.perpVector(), s );
          if ( d > 0 && d < w.length() &&
               ring0[i + 1] != ring1[j + 1] && ring0[i + 1] != ring1[j] &&
               ring0[i + 0] != ring1[j + 1] && ring0[i + 0] != ring1[j] )
          {
            QString msg = QObject::tr( "segment %1 of ring %2 of polygon %3 intersects segment %4 of ring %5 of polygon %6 at %7" )
                          .arg( i0 ).arg( i ).arg( p0 )
                          .arg( i1 ).arg( j ).arg( p1 )
                          .arg( s.toString() );
            QgsDebugMsg( msg );
            emit errorFound( QgsGeometry::Error( msg, s ) );
            mErrorCount++;
          }
        }
      }
    }
  }
}
Пример #8
0
// TODO: move to geometry utils
double distance2D( const QgsPolylineXY &coords )
{
  int np = coords.count();
  if ( np == 0 )
    return 0;

  double x0 = coords[0].x(), y0 = coords[0].y();
  double x1, y1;
  double dist = 0;
  for ( int i = 1; i < np; ++i )
  {
    x1 = coords[i].x();
    y1 = coords[i].y();
    dist += std::sqrt( ( x1 - x0 ) * ( x1 - x0 ) + ( y1 - y0 ) * ( y1 - y0 ) );
    x0 = x1;
    y0 = y1;
  }
  return dist;
}
Пример #9
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;
}
Пример #10
0
void QgsGeometryValidator::validatePolyline( int i, QgsPolylineXY line, bool ring )
{
  if ( ring )
  {
    if ( line.size() < 4 )
    {
      QString msg = QObject::tr( "ring %1 with less than four points" ).arg( i );
      QgsDebugMsg( msg );
      emit errorFound( QgsGeometry::Error( msg ) );
      mErrorCount++;
      return;
    }

    if ( line[0] != line[ line.size() - 1 ] )
    {
      QString msg = QObject::tr( "ring %1 not closed" ).arg( i );
      QgsDebugMsg( msg );
      emit errorFound( QgsGeometry::Error( msg ) );
      mErrorCount++;
      return;
    }
  }
  else if ( line.size() < 2 )
  {
    QString msg = QObject::tr( "line %1 with less than two points" ).arg( i );
    QgsDebugMsg( msg );
    emit errorFound( QgsGeometry::Error( msg ) );
    mErrorCount++;
    return;
  }

  int j = 0;
  while ( j < line.size() - 1 )
  {
    int n = 0;
    while ( j < line.size() - 1 && line[j] == line[j + 1] )
    {
      line.remove( j );
      n++;
    }

    if ( n > 0 )
    {
      QString msg = QObject::tr( "line %1 contains %n duplicate node(s) at %2", "number of duplicate nodes", n ).arg( i ).arg( j );
      QgsDebugMsg( msg );
      emit errorFound( QgsGeometry::Error( msg, line[j] ) );
      mErrorCount++;
    }

    j++;
  }

  for ( j = 0; !mStop && j < line.size() - 3; j++ )
  {
    QgsVector v = line[j + 1] - line[j];
    double vl = v.length();

    int n = ( j == 0 && ring ) ? line.size() - 2 : line.size() - 1;

    for ( int k = j + 2; !mStop && k < n; k++ )
    {
      QgsVector w = line[k + 1] - line[k];

      QgsPointXY s;
      if ( !intersectLines( line[j], v, line[k], w, s ) )
        continue;

      double d = 0.0;
      try
      {
        d = -distLine2Point( line[j], v.perpVector(), s );
      }
      catch ( QgsException &e )
      {
        Q_UNUSED( e );
        QgsDebugMsg( "Error validating: " + e.what() );
        continue;
      }
      if ( d < 0 || d > vl )
        continue;

      try
      {
        d = -distLine2Point( line[k], w.perpVector(), s );
      }
      catch ( QgsException &e )
      {
        Q_UNUSED( e );
        QgsDebugMsg( "Error validating: " + e.what() );
        continue;
      }

      if ( d <= 0 || d >= w.length() )
        continue;

      QString msg = QObject::tr( "segments %1 and %2 of line %3 intersect at %4" ).arg( j ).arg( k ).arg( i ).arg( s.toString() );
      QgsDebugMsg( msg );
      emit errorFound( QgsGeometry::Error( msg, s ) );
      mErrorCount++;
    }
  }
}
Пример #11
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;
}
Пример #12
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;
}