void QgsSelectedFeature::validateGeometry( QgsGeometry *g )
{
  QSettings settings;
  if ( settings.value( "/qgis/digitizing/validate_geometries", 1 ).toInt() == 0 )
    return;

  if ( !g )
    g = mGeometry;

  mTip.clear();

  if ( mValidator )
  {
    mValidator->stop();
    mValidator->wait();
    mValidator->deleteLater();
    mValidator = 0;
  }

  mGeomErrors.clear();
  while ( !mGeomErrorMarkers.isEmpty() )
  {
    QgsVertexMarker *vm = mGeomErrorMarkers.takeFirst();
    QgsDebugMsg( "deleting " + vm->toolTip() );
    delete vm;
  }

  mValidator = new QgsGeometryValidator( g );
  connect( mValidator, SIGNAL( errorFound( QgsGeometry::Error ) ), this, SLOT( addError( QgsGeometry::Error ) ) );
  connect( mValidator, SIGNAL( finished() ), this, SLOT( validationFinished() ) );
  mValidator->start();

  QStatusBar *sb = QgisApp::instance()->statusBar();
  sb->showMessage( tr( "Validation started." ) );
}
void QgsGeometryValidator::validateGeometry( const QgsGeometry *g, QList<QgsGeometry::Error> &errors )
{
  QgsGeometryValidator *gv = new QgsGeometryValidator( g, &errors );
  connect( gv, SIGNAL( errorFound( QgsGeometry::Error ) ), gv, SLOT( addError( QgsGeometry::Error ) ) );
  gv->run();
  gv->wait();
}
void QgsGeometryValidator::validatePolygon( int idx, const QgsPolygon &polygon )
{
  // check if holes are inside polygon
  for ( int i = 1; !mStop && i < polygon.size(); i++ )
  {
    if ( !ringInRing( polygon[i], polygon[0] ) )
    {
      QString msg = QObject::tr( "ring %1 of polygon %2 not in exterior ring" ).arg( i ).arg( idx );
      QgsDebugMsg( msg );
      emit errorFound( QgsGeometry::Error( msg ) );
      mErrorCount++;
    }
  }

  // check holes for intersections
  for ( int i = 1; !mStop && i < polygon.size(); i++ )
  {
    for ( int j = i + 1; !mStop && j < polygon.size(); j++ )
    {
      checkRingIntersections( idx, i, polygon[i], idx, j, polygon[j] );
    }
  }

  // check if rings are self-intersecting
  for ( int i = 0; !mStop && i < polygon.size(); i++ )
  {
    validatePolyline( i, polygon[i], true );
  }
}
void SatelliteModel::updateDemoData()
{
    static bool flag = true;
    QList<QGeoSatelliteInfo> satellites;
    if (flag) {
        for (int i = 0; i<5; i++) {
            QGeoSatelliteInfo info;
            info.setSatelliteIdentifier(i);
            info.setSignalStrength(20 + 20*i);
            satellites.append(info);
        }
    } else {
        for (int i = 0; i<9; i++) {
            QGeoSatelliteInfo info;
            info.setSatelliteIdentifier(i*2);
            info.setSignalStrength(20 + 10*i);
            satellites.append(info);
        }
    }


    satellitesInViewUpdated(satellites);
    flag ? satellitesInUseUpdated(QList<QGeoSatelliteInfo>() << satellites.at(2))
         : satellitesInUseUpdated(QList<QGeoSatelliteInfo>() << satellites.at(3));
    flag = !flag;

    emit errorFound(flag);

    if (isSingleRequest() && !singleRequestServed) {
        singleRequestServed = true;
        setRunning(false);
    }
}
void QgsMapToolCapture::validateGeometry()
{
  QSettings settings;
  if ( settings.value( "/qgis/digitizing/validate_geometries", 1 ).toInt() == 0 )
    return;

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

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

  QgsGeometry *g = 0;

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

  if ( !g )
    return;

  mValidator = new QgsGeometryValidator( g );
  connect( mValidator, SIGNAL( errorFound( QgsGeometry::Error ) ), this, SLOT( addError( QgsGeometry::Error ) ) );
  connect( mValidator, SIGNAL( finished() ), this, SLOT( validationFinished() ) );
  mValidator->start();

  QStatusBar *sb = QgisApp::instance()->statusBar();
  sb->showMessage( tr( "Validation started." ) );
  delete g;
}
void QgsMapToolCapture::validateGeometry()
{
  QSettings settings;
  if ( settings.value( "/qgis/digitizing/validate_geometries", 1 ).toInt() == 0 )
    return;

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

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

  QgsGeometry *g = 0;

  switch ( mCaptureMode )
  {
    case CaptureNone:
    case CapturePoint:
      return;
    case CaptureLine:
      if ( mCaptureList.size() < 2 )
        return;
      g = QgsGeometry::fromPolyline( mCaptureList.toVector() );
      break;
    case CapturePolygon:
      if ( mCaptureList.size() < 3 )
        return;
      g = QgsGeometry::fromPolygon( QgsPolygon() << ( QgsPolyline() << mCaptureList.toVector() << mCaptureList[0] ) );
      break;
  }

  if ( !g )
    return;

  mValidator = new QgsGeometryValidator( g );
  connect( mValidator, SIGNAL( errorFound( QgsGeometry::Error ) ), this, SLOT( addError( QgsGeometry::Error ) ) );
  connect( mValidator, SIGNAL( finished() ), this, SLOT( validationFinished() ) );
  mValidator->start();

  QStatusBar *sb = QgisApp::instance()->statusBar();
  sb->showMessage( tr( "Validation started." ) );
}
void QgsGeometryValidator::checkRingIntersections(
  int p0, int i0, const QgsPolyline &ring0,
  int p1, int i1, const QgsPolyline &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];

      QgsPoint 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++;
          }
        }
      }
    }
  }
}
void QgsGeometryValidator::validatePolyline( int i, QgsPolyline 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];

      QgsPoint 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++;
    }
  }
}
void QgsGeometryValidator::run()
{
  mErrorCount = 0;
  QSettings settings;
  if ( settings.value( QStringLiteral( "/qgis/digitizing/validate_geometries" ), 1 ).toInt() == 2 )
  {
    char *r = nullptr;
    const GEOSGeometry *g0 = mG.asGeos();
    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;
      if ( GEOSisValidDetail_r( handle, g0, GEOSVALID_ALLOW_SELFTOUCHING_RING_FORMING_HOLE, &r, &g1 ) != 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 ), QgsPoint( 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 );
      }
    }

    return;
  }

  QgsDebugMsg( "validation thread started." );

  QgsWkbTypes::Type flatType = QgsWkbTypes::flatType( mG.wkbType() );
  //if ( flatType == QgsWkbTypes::Point || flatType == QgsWkbTypes::MultiPoint )
  //    break;
  if ( flatType == QgsWkbTypes::LineString )
  {
    validatePolyline( 0, mG.asPolyline() );
  }
  else if ( flatType == QgsWkbTypes::MultiLineString )
  {
    QgsMultiPolyline mp = mG.asMultiPolyline();
    for ( int i = 0; !mStop && i < mp.size(); i++ )
      validatePolyline( i, mp[i] );
  }
  else if ( flatType == QgsWkbTypes::Polygon )
  {
    validatePolygon( 0, mG.asPolygon() );
  }
  else if ( flatType == QgsWkbTypes::MultiPolygon )
  {
    QgsMultiPolygon mp = mG.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( mG.wkbType() ) ) );
    mErrorCount++;
  }

  QgsDebugMsg( "validation finished." );

  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
}
void SatelliteModel::error(QGeoSatelliteInfoSource::Error error)
{
    emit errorFound((int)error);
}
Exemple #11
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;
    }
  }
}