示例#1
0
bool QgsSnapIndex::SegmentSnapItem::getIntersection( const QgsPoint &p1, const QgsPoint &p2, QgsPoint &inter ) const
{
  const QgsPoint &q1 = idxFrom->point(), & q2 = idxTo->point();
  QgsVector v( p2.x() - p1.x(), p2.y() - p1.y() );
  QgsVector w( q2.x() - q1.x(), q2.y() - q1.y() );
  double vl = v.length();
  double wl = w.length();

  if ( qgsDoubleNear( vl, 0, 0.000000000001 ) || qgsDoubleNear( wl, 0, 0.000000000001 ) )
  {
    return false;
  }
  v = v / vl;
  w = w / wl;

  double d = v.y() * w.x() - v.x() * w.y();

  if ( d == 0 )
    return false;

  double dx = q1.x() - p1.x();
  double dy = q1.y() - p1.y();
  double k = ( dy * w.x() - dx * w.y() ) / d;

  inter = QgsPoint( p1.x() + v.x() * k, p1.y() + v.y() * k );

  double lambdav = QgsVector( inter.x() - p1.x(), inter.y() - p1.y() ) *  v;
  if ( lambdav < 0. + 1E-8 || lambdav > vl - 1E-8 )
    return false;

  double lambdaw = QgsVector( inter.x() - q1.x(), inter.y() - q1.y() ) * w;
  return !( lambdaw < 0. + 1E-8 || lambdaw >= wl - 1E-8 );
}
示例#2
0
bool QgsGeometryUtils::segmentIntersection( const QgsPointV2 &p1, const QgsPointV2 &p2, const QgsPointV2 &q1, const QgsPointV2 &q2, QgsPointV2 &inter, double tolerance )
{
  QgsVector v( p2.x() - p1.x(), p2.y() - p1.y() );
  QgsVector w( q2.x() - q1.x(), q2.y() - q1.y() );
  double vl = v.length();
  double wl = w.length();

  if ( qFuzzyIsNull( vl ) || qFuzzyIsNull( wl ) )
  {
    return false;
  }
  v = v / vl;
  w = w / wl;

  if ( !QgsGeometryUtils::lineIntersection( p1, v, q1, w, inter ) )
    return false;

  double lambdav = QgsVector( inter.x() - p1.x(), inter.y() - p1.y() ) *  v;
  if ( lambdav < 0. + tolerance || lambdav > vl - tolerance )
    return false;

  double lambdaw = QgsVector( inter.x() - q1.x(), inter.y() - q1.y() ) * w;
  if ( lambdaw < 0. + tolerance || lambdaw >= wl - tolerance )
    return false;

  return true;
}
QgsVector calcMotion( const QgsPoint &a, const QgsPoint &b, const QgsPoint &c,
                      double lowerThreshold, double upperThreshold )
{
  QgsVector p = a - b;
  QgsVector q = c - b;

  if ( qgsDoubleNear( p.length(), 0.0 ) || qgsDoubleNear( q.length(), 0.0 ) )
    return QgsVector( 0, 0 );

  // 2.0 is a magic number from the original JOSM source code
  double scale = 2.0 * std::min( p.length(), q.length() );

  p = p.normalized();
  q = q.normalized();
  double dotProduct = p * q;

  if ( !dotProductWithinAngleTolerance( dotProduct, lowerThreshold, upperThreshold ) )
  {
    return QgsVector( 0, 0 );
  }

  // wonderful nasty hack which has survived through JOSM -> id -> QGIS
  // to deal with almost-straight segments (angle is closer to 180 than to 90/270).
  if ( dotProduct < -M_SQRT1_2 )
    dotProduct += 1.0;

  QgsVector new_v = p + q;
  // 0.1 magic number from JOSM implementation - think this is to limit each iterative step
  return new_v.normalized() * ( 0.1 * dotProduct * scale );
}
示例#4
0
void QgsHighlight::paintPoint( QPainter *p, QgsPoint point )
{
  QPolygonF r( 5 );

  double d = mMapCanvas->extent().width() * 0.005;
  r[0] = toCanvasCoordinates( point + QgsVector( -d, -d ) ) - pos();
  r[1] = toCanvasCoordinates( point + QgsVector( d, -d ) ) - pos();
  r[2] = toCanvasCoordinates( point + QgsVector( d, d ) ) - pos();
  r[3] = toCanvasCoordinates( point + QgsVector( -d, d ) ) - pos();
  r[4] = r[0];

  p->drawPolygon( r );
}
示例#5
0
void QgsGeometryAngleCheck::collectErrors( QList<QgsGeometryCheckError *> &errors, QStringList &/*messages*/, QAtomicInt *progressCounter, const QgsFeatureIds &ids ) const
{
  const QgsFeatureIds &featureIds = ids.isEmpty() ? mFeaturePool->getFeatureIds() : ids;
  Q_FOREACH ( QgsFeatureId featureid, featureIds )
  {
    if ( progressCounter ) progressCounter->fetchAndAddRelaxed( 1 );
    QgsFeature feature;
    if ( !mFeaturePool->get( featureid, feature ) )
    {
      continue;
    }
    QgsGeometry g = feature.geometry();
    const QgsAbstractGeometry *geom = g.geometry();
    for ( int iPart = 0, nParts = geom->partCount(); iPart < nParts; ++iPart )
    {
      for ( int iRing = 0, nRings = geom->ringCount( iPart ); iRing < nRings; ++iRing )
      {
        int nVerts = QgsGeometryCheckerUtils::polyLineSize( geom, iPart, iRing );
        // Less than three points, no angles to check
        if ( nVerts < 3 )
        {
          continue;
        }
        for ( int iVert = 0; iVert < nVerts; ++iVert )
        {
          const QgsPoint &p1 = geom->vertexAt( QgsVertexId( iPart, iRing, ( iVert - 1 + nVerts ) % nVerts ) );
          const QgsPoint &p2 = geom->vertexAt( QgsVertexId( iPart, iRing, iVert ) );
          const QgsPoint &p3 = geom->vertexAt( QgsVertexId( iPart, iRing, ( iVert + 1 ) % nVerts ) );
          QgsVector v21, v23;
          try
          {
            v21 = QgsVector( p1.x() - p2.x(), p1.y() - p2.y() ).normalized();
            v23 = QgsVector( p3.x() - p2.x(), p3.y() - p2.y() ).normalized();
          }
          catch ( const QgsException & )
          {
            // Zero length vectors
            continue;
          }

          double angle = std::acos( v21 * v23 ) / M_PI * 180.0;
          if ( angle < mMinAngle )
          {
            errors.append( new QgsGeometryCheckError( this, featureid, p2, QgsVertexId( iPart, iRing, iVert ), angle ) );
          }
        }
      }
    }
  }
}
示例#6
0
void QgsHighlight::paintPoint( QPainter *p, QgsPoint point )
{
  QPolygonF r( 5 );

  if ( mLayer )
  {
    point = mMapCanvas->mapRenderer()->layerToMapCoordinates( mLayer, point );
  }

  double d = mMapCanvas->extent().width() * 0.005;
  r[0] = toCanvasCoordinates( point + QgsVector( -d, -d ) ) - pos();
  r[1] = toCanvasCoordinates( point + QgsVector( d, -d ) ) - pos();
  r[2] = toCanvasCoordinates( point + QgsVector( d, d ) ) - pos();
  r[3] = toCanvasCoordinates( point + QgsVector( -d, d ) ) - pos();
  r[4] = r[0];

  p->drawPolygon( r );
}
示例#7
0
void TestQgsRectangle::operators()
{
  QgsRectangle rect1 = QgsRectangle( 10.0, 20.0, 110.0, 220.0 );
  QgsVector v = QgsVector( 1.0, 2.0 );
  QgsRectangle rect2 = rect1 + v;
  QVERIFY( rect1 != rect2 );
  QCOMPARE( rect2.height(), rect1.height() );
  QCOMPARE( rect2.width(), rect1.width() );
  QCOMPARE( rect2.xMinimum(), 11.0 );
  QCOMPARE( rect2.yMinimum(), 22.0 );

  rect2 -= rect2.center() - rect1.center();
  QVERIFY( rect1 == rect2 );

  rect2 += v * 2.5;
  QCOMPARE( rect2.xMinimum(), 12.5 );
  QCOMPARE( rect2.yMinimum(), 25.0 );

  rect2 = rect1 - v;
  QCOMPARE( rect2.xMinimum(), 9.0 );
  QCOMPARE( rect2.yMinimum(), 18.0 );
  QCOMPARE( rect2.height(), rect1.height() );
  QCOMPARE( rect2.width(), rect1.width() );
}
示例#8
0
QgsVector QgsVector::operator*( double scalar ) const
{
  return QgsVector( mX * scalar, mY * scalar );
}
示例#9
0
QgsVector QgsVector::operator-() const
{
  return QgsVector( -mX, -mY );
}
示例#10
0
void QgsGeometryAngleCheck::fixError( QgsGeometryCheckError* error, int method, int /*mergeAttributeIndex*/, Changes &changes ) const
{
    QgsFeature feature;
    if ( !mFeaturePool->get( error->featureId(), feature ) )
    {
        error->setObsolete();
        return;
    }
    QgsAbstractGeometryV2* geometry = feature.geometry()->geometry();
    const QgsVertexId& vidx = error->vidx();

    // Check if point still exists
    if ( !vidx.isValid( geometry ) )
    {
        error->setObsolete();
        return;
    }

    // Check if error still applies
    int n = QgsGeomUtils::polyLineSize( geometry, vidx.part, vidx.ring );
    const QgsPointV2& p1 = geometry->vertexAt( QgsVertexId( vidx.part, vidx.ring, ( vidx.vertex - 1 + n ) % n ) );
    const QgsPointV2& p2 = geometry->vertexAt( vidx );
    const QgsPointV2& p3 = geometry->vertexAt( QgsVertexId( vidx.part, vidx.ring, ( vidx.vertex + 1 ) % n ) );
    QgsVector v21, v23;
    try
    {
        v21 = QgsVector( p1.x() - p2.x(), p1.y() - p2.y() ).normal();
        v23 = QgsVector( p3.x() - p2.x(), p3.y() - p2.y() ).normal();
    }
    catch ( const QgsException& )
    {
        error->setObsolete();
        return;
    }
    double angle = std::acos( v21 * v23 ) / M_PI * 180.0;
    if ( angle >= mMinAngle )
    {
        error->setObsolete();
        return;
    }

    // Fix error
    if ( method == NoChange )
    {
        error->setFixed( method );
    }
    else if ( method == DeleteNode )
    {

        if ( n <= 3 )
        {
            error->setFixFailed( tr( "Resulting geometry is degenerate" ) );
        }
        else
        {
            geometry->deleteVertex( vidx );
            mFeaturePool->updateFeature( feature );
            error->setFixed( method );
            changes[error->featureId()].append( Change( ChangeNode, ChangeRemoved, vidx ) );
        }
    }
    else
    {
        error->setFixFailed( tr( "Unknown method" ) );
    }
}
示例#11
0
QgsVector QgsVector::operator-( QgsVector other ) const
{
  return QgsVector( mX - other.mX, mY - other.mY );
}
示例#12
0
QgsVector QgsVector::operator+( QgsVector other ) const
{
  return QgsVector( mX + other.mX, mY + other.mY );
}
示例#13
0
文件: qgspoint.cpp 项目: rotulet/QGIS
QgsVector QgsVector::operator-( void ) const
{
  return QgsVector( -m_x, -m_y );
}
示例#14
0
QgsLineString *doOrthogonalize( QgsLineString *ring, int iterations, double tolerance, double lowerThreshold, double upperThreshold )
{
  double minScore = DBL_MAX;

  bool isClosed = ring->isClosed();
  int numPoints = ring->numPoints();

  std::unique_ptr< QgsLineString > best( ring->clone() );

  QVector< QgsVector > /* yep */ motions;
  motions.reserve( numPoints );

  for ( int it = 0; it < iterations; ++it )
  {
    motions.resize( 0 ); // avoid re-allocations

    // first loop through an calculate all motions
    QgsPoint a;
    QgsPoint b;
    QgsPoint c;
    for ( int i = 0; i < numPoints; ++i )
    {
      if ( isClosed && i == numPoints - 1 )
        motions << motions.at( 0 ); //closed ring, so last point follows first point motion
      else if ( !isClosed && ( i == 0 || i == numPoints - 1 ) )
      {
        b = ring->pointN( 0 );
        c = ring->pointN( 1 );
        motions << QgsVector( 0, 0 ); //non closed line, leave first/last vertex untouched
      }
      else
      {
        if ( i == 0 )
        {
          a = ring->pointN( numPoints - 1 );
          b = ring->pointN( 0 );
        }
        if ( i == numPoints - 1 )
          c = ring->pointN( 0 );
        else
          c = ring->pointN( i + 1 );

        motions << calcMotion( a, b, c, lowerThreshold, upperThreshold );
      }
      a = b;
      b = c;
    }

    // then apply them
    for ( int i = 0; i < numPoints; ++i )
    {
      ring->setXAt( i, ring->xAt( i ) + motions.at( i ).x() );
      ring->setYAt( i, ring->yAt( i ) + motions.at( i ).y() );
    }

    double newScore = squareness( ring, lowerThreshold, upperThreshold );
    if ( newScore < minScore )
    {
      best.reset( ring->clone() );
      minScore = newScore;
    }

    if ( minScore < tolerance )
      break;
  }

  delete ring;

  return best.release();
}
示例#15
0
void QgsGeometryAngleCheck::fixError( QgsGeometryCheckError *error, int method, int /*mergeAttributeIndex*/, Changes &changes ) const
{
  QgsFeature feature;
  if ( !mFeaturePool->get( error->featureId(), feature ) )
  {
    error->setObsolete();
    return;
  }
  QgsGeometry g = feature.geometry();
  QgsAbstractGeometry *geometry = g.geometry();
  QgsVertexId vidx = error->vidx();

  // Check if point still exists
  if ( !vidx.isValid( geometry ) )
  {
    error->setObsolete();
    return;
  }

  // Check if error still applies
  int n = QgsGeometryCheckerUtils::polyLineSize( geometry, vidx.part, vidx.ring );
  if ( n == 0 )
  {
    error->setObsolete();
    return;
  }
  const QgsPoint &p1 = geometry->vertexAt( QgsVertexId( vidx.part, vidx.ring, ( vidx.vertex - 1 + n ) % n ) );
  const QgsPoint &p2 = geometry->vertexAt( vidx );
  const QgsPoint &p3 = geometry->vertexAt( QgsVertexId( vidx.part, vidx.ring, ( vidx.vertex + 1 ) % n ) );
  QgsVector v21, v23;
  try
  {
    v21 = QgsVector( p1.x() - p2.x(), p1.y() - p2.y() ).normalized();
    v23 = QgsVector( p3.x() - p2.x(), p3.y() - p2.y() ).normalized();
  }
  catch ( const QgsException & )
  {
    error->setObsolete();
    return;
  }
  double angle = std::acos( v21 * v23 ) / M_PI * 180.0;
  if ( angle >= mMinAngle )
  {
    error->setObsolete();
    return;
  }

  // Fix error
  if ( method == NoChange )
  {
    error->setFixed( method );
  }
  else if ( method == DeleteNode )
  {
    if ( !QgsGeometryCheckerUtils::canDeleteVertex( geometry, vidx.part, vidx.ring ) )
    {
      error->setFixFailed( tr( "Resulting geometry is degenerate" ) );
    }
    else if ( !geometry->deleteVertex( error->vidx() ) )
    {
      error->setFixFailed( tr( "Failed to delete vertex" ) );
    }
    else
    {
      changes[error->featureId()].append( Change( ChangeNode, ChangeRemoved, vidx ) );
      if ( QgsGeometryUtils::sqrDistance2D( p1, p3 ) < QgsGeometryCheckPrecision::tolerance() * QgsGeometryCheckPrecision::tolerance()
           && QgsGeometryCheckerUtils::canDeleteVertex( geometry, vidx.part, vidx.ring ) &&
           geometry->deleteVertex( error->vidx() ) ) // error->vidx points to p3 after removing p2
      {
        changes[error->featureId()].append( Change( ChangeNode, ChangeRemoved, QgsVertexId( vidx.part, vidx.ring, ( vidx.vertex + 1 ) % n ) ) );
      }
      feature.setGeometry( g );
      mFeaturePool->updateFeature( feature );
      error->setFixed( method );
    }
  }
  else
  {
    error->setFixFailed( tr( "Unknown method" ) );
  }
}
示例#16
0
QgsVector QgsVector::operator+( const QgsVector& v ) const
{
  return QgsVector( m_x + v.m_x, m_y + v.m_y );
}
示例#17
0
QgsVector QgsVector::operator-( const QgsVector& v ) const
{
  return QgsVector( m_x - v.m_x, m_y - v.m_y );
}
示例#18
0
文件: qgspoint.cpp 项目: rotulet/QGIS
// perpendicular vector (rotated 90 degrees counter-clockwise)
QgsVector QgsVector::perpVector() const
{
  return QgsVector( -m_y, m_x );
}
示例#19
0
文件: qgspoint.cpp 项目: rotulet/QGIS
QgsVector QgsVector::operator*( double scalar ) const
{
  return QgsVector( m_x * scalar, m_y * scalar );
}
示例#20
0
QgsVector QgsVector::perpVector() const
{
  return QgsVector( -mY, mX );
}
示例#21
0
QgsVector QgsVector::rotateBy( double rot ) const
{
  double ang = atan2( mY, mX ) + rot;
  double len = length();
  return QgsVector( len * cos( ang ), len * sin( ang ) );
}
示例#22
0
QgsVector QgsVector::rotateBy( double rot ) const
{
  double theAngle = atan2( mY, mX ) + rot;
  double len = length();
  return QgsVector( len * cos( theAngle ), len * sin( theAngle ) );
}