Ejemplo n.º 1
0
void QgsPolygonV2::setExteriorRing( QgsCurve *ring )
{
  if ( !ring )
  {
    return;
  }

  if ( ring->hasCurvedSegments() )
  {
    //need to segmentize ring as polygon does not support curves
    QgsCurve *line = ring->segmentize();
    delete ring;
    ring = line;
  }

  QgsLineString *lineString = qgsgeometry_cast< QgsLineString *>( ring );
  if ( lineString && !lineString->isClosed() )
  {
    lineString->close();
  }

  mExteriorRing.reset( ring );

  //set proper wkb type
  setZMTypeFromSubGeometry( ring, QgsWkbTypes::Polygon );

  //match dimensionality for rings
  for ( QgsCurve *ring : qgis::as_const( mInteriorRings ) )
  {
    ring->convertTo( mExteriorRing->wkbType() );
  }

  clearCache();
}
Ejemplo n.º 2
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 );
  }
}
Ejemplo n.º 3
0
void QgsPolygonV2::addInteriorRing( QgsCurve *ring )
{
  if ( !ring )
    return;

  if ( ring->hasCurvedSegments() )
  {
    //can't add a curved ring to a QgsPolygonV2
    QgsLineString *segmented = ring->curveToLine();
    delete ring;
    ring = segmented;
  }

  QgsLineString *lineString = qgsgeometry_cast< QgsLineString *>( ring );
  if ( lineString && !lineString->isClosed() )
  {
    lineString->close();
  }

  if ( mWkbType == QgsWkbTypes::Polygon25D )
  {
    ring->convertTo( QgsWkbTypes::LineString25D );
    mInteriorRings.append( ring );
  }
  else
  {
    QgsCurvePolygon::addInteriorRing( ring );
  }
  clearCache();
}
Ejemplo n.º 4
0
// Need NO or >1 points. Duplicate first if only one.
static bool lwline_make_geos_friendly( QgsLineString &line )
{
  if ( line.numPoints() == 1 ) // 0 is fine, 2 is fine
  {
    line.addVertex( line.startPoint() );
  }
  return true;
}
Ejemplo n.º 5
0
QDomElement QgsCircularString::asGML2( QDomDocument &doc, int precision, const QString &ns ) const
{
  // GML2 does not support curves
  QgsLineString *line = curveToLine();
  QDomElement gml = line->asGML2( doc, precision, ns );
  delete line;
  return gml;
}
Ejemplo n.º 6
0
QString QgsCircularString::asJSON( int precision ) const
{
  // GeoJSON does not support curves
  QgsLineString *line = curveToLine();
  QString json = line->asJSON( precision );
  delete line;
  return json;
}
Ejemplo n.º 7
0
void QgsMapToolCapture::setPoints( const QVector<QgsPointXY> &pointList )
{
  QgsLineString *line = new QgsLineString( pointList );
  mCaptureCurve.clear();
  mCaptureCurve.addCurve( line );
  mSnappingMatches.clear();
  for ( int i = 0; i < line->length(); ++i )
    mSnappingMatches.append( QgsPointLocator::Match() );
}
Ejemplo n.º 8
0
void QgsTriangle::setExteriorRing( QgsCurve *ring )
{
  if ( !ring )
  {
    return;
  }

  if ( ring->hasCurvedSegments() )
  {
    //need to segmentize ring as polygon does not support curves
    QgsCurve *line = ring->segmentize();
    delete ring;
    ring = line;
  }

  if ( ( ring->numPoints() > 4 ) || ( ring->numPoints() < 3 ) )
  {
    delete ring;
    return;
  }
  else if ( ring->numPoints() == 4 )
  {
    if ( !ring->isClosed() )
    {
      delete ring;
      return;
    }
  }
  else if ( ring->numPoints() == 3 )
  {
    if ( ring->isClosed() )
    {
      delete ring;
      return;
    }
    QgsLineString *lineString = static_cast< QgsLineString *>( ring );
    if ( !lineString->isClosed() )
    {
      lineString->close();
    }
    ring = lineString;
  }

  if ( !validateGeom( ring->vertexAt( QgsVertexId( 0, 0, 0 ) ), ring->vertexAt( QgsVertexId( 0, 0, 1 ) ), ring->vertexAt( QgsVertexId( 0, 0, 2 ) ) ) )
  {
    delete ring;
    return;
  }

  mExteriorRing.reset( ring );

  //set proper wkb type
  setZMTypeFromSubGeometry( ring, QgsWkbTypes::Triangle );

  clearCache();
}
Ejemplo n.º 9
0
QgsLineString *QgsCompoundCurve::curveToLine( double tolerance, SegmentationToleranceType toleranceType ) const
{
  QgsLineString *line = new QgsLineString();
  std::unique_ptr< QgsLineString > currentLine;
  for ( const QgsCurve *curve : mCurves )
  {
    currentLine.reset( curve->curveToLine( tolerance, toleranceType ) );
    line->append( currentLine.get() );
  }
  return line;
}
Ejemplo n.º 10
0
int QgsVectorLayerEditUtils::addRing( const QList<QgsPoint>& ring, const QgsFeatureIds& targetFeatureIds, QgsFeatureId* modifiedFeatureId )
{
  QgsLineString* ringLine = new QgsLineString();
  QgsPointSequence ringPoints;
  QList<QgsPoint>::const_iterator ringIt = ring.constBegin();
  for ( ; ringIt != ring.constEnd(); ++ringIt )
  {
    ringPoints.append( QgsPointV2( ringIt->x(), ringIt->y() ) );
  }
  ringLine->setPoints( ringPoints );
  return addRing( ringLine, targetFeatureIds,  modifiedFeatureId );
}
Ejemplo n.º 11
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 );
}
Ejemplo n.º 12
0
QgsLineString *QgsCircularString::curveToLine( double tolerance, SegmentationToleranceType toleranceType ) const
{
  QgsLineString *line = new QgsLineString();
  QgsPointSequence points;
  int nPoints = numPoints();

  for ( int i = 0; i < ( nPoints - 2 ) ; i += 2 )
  {
    segmentize( pointN( i ), pointN( i + 1 ), pointN( i + 2 ), points, tolerance, toleranceType );
  }

  line->setPoints( points );
  return line;
}
Ejemplo n.º 13
0
QgsLineString *QgsLineString::reversed() const
{
  QgsLineString *copy = clone();
  std::reverse( copy->mX.begin(), copy->mX.end() );
  std::reverse( copy->mY.begin(), copy->mY.end() );
  if ( copy->is3D() )
  {
    std::reverse( copy->mZ.begin(), copy->mZ.end() );
  }
  if ( copy->isMeasure() )
  {
    std::reverse( copy->mM.begin(), copy->mM.end() );
  }
  return copy;
}
Ejemplo n.º 14
0
bool QgsTriangle::fromWkb( QgsConstWkbPtr &wkbPtr )
{
  clear();
  if ( !wkbPtr )
  {
    return false;
  }

  QgsWkbTypes::Type type = wkbPtr.readHeader();
  if ( QgsWkbTypes::flatType( type ) != QgsWkbTypes::Triangle )
  {
    return false;
  }
  mWkbType = type;

  QgsWkbTypes::Type ringType;
  switch ( mWkbType )
  {
    case QgsWkbTypes::TriangleZ:
      ringType = QgsWkbTypes::LineStringZ;
      break;
    case QgsWkbTypes::TriangleM:
      ringType = QgsWkbTypes::LineStringM;
      break;
    case QgsWkbTypes::TriangleZM:
      ringType = QgsWkbTypes::LineStringZM;
      break;
    default:
      ringType = QgsWkbTypes::LineString;
      break;
  }

  int nRings;
  wkbPtr >> nRings;
  if ( nRings > 1 )
  {
    return false;
  }

  QgsLineString *line = new QgsLineString();
  line->fromWkbPoints( ringType, wkbPtr );
  if ( !mExteriorRing )
  {
    mExteriorRing = line;
  }

  return true;
}
Ejemplo n.º 15
0
int QgsMapToolCapture::addCurve( QgsCurve *c )
{
  if ( !c )
  {
    return 1;
  }

  if ( !mRubberBand )
  {
    mRubberBand = createRubberBand( mCaptureMode == CapturePolygon ? QgsWkbTypes::PolygonGeometry : QgsWkbTypes::LineGeometry );
  }

  QgsLineString *lineString = c->curveToLine();
  QgsPointSequence linePoints;
  lineString->points( linePoints );
  delete lineString;
  QgsPointSequence::const_iterator ptIt = linePoints.constBegin();
  for ( ; ptIt != linePoints.constEnd(); ++ptIt )
  {
    mRubberBand->addPoint( QgsPointXY( ptIt->x(), ptIt->y() ) );
  }

  if ( !mTempRubberBand )
  {
    mTempRubberBand = createRubberBand( mCaptureMode == CapturePolygon ? QgsWkbTypes::PolygonGeometry : QgsWkbTypes::LineGeometry, true );
  }
  else
  {
    mTempRubberBand->reset();
  }
  QgsPoint endPt = c->endPoint();
  mTempRubberBand->addPoint( QgsPointXY( endPt.x(), endPt.y() ) ); //add last point of c

  //transform back to layer CRS in case map CRS and layer CRS are different
  QgsVectorLayer *vlayer = qobject_cast<QgsVectorLayer *>( mCanvas->currentLayer() );
  QgsCoordinateTransform ct = mCanvas->mapSettings().layerTransform( vlayer );
  if ( ct.isValid() )
  {
    c->transform( ct, QgsCoordinateTransform::ReverseTransform );
  }
  mCaptureCurve.addCurve( c );
  for ( int i = 0; i < c->length(); ++i )
    mSnappingMatches.append( QgsPointLocator::Match() );

  return 0;
}
Ejemplo n.º 16
0
QString QgsMultiSurface::asJSON( int precision ) const
{
  // GeoJSON does not support curves
  QString json = QStringLiteral( "{\"type\": \"MultiPolygon\", \"coordinates\": [" );
  Q_FOREACH ( const QgsAbstractGeometry *geom, mGeometries )
  {
    if ( dynamic_cast<const QgsSurface*>( geom ) )
    {
      json += '[';

      QgsPolygonV2* polygon = static_cast<const QgsSurface*>( geom )->surfaceToPolygon();

      QgsLineString* exteriorLineString = polygon->exteriorRing()->curveToLine();
      QgsPointSequence exteriorPts;
      exteriorLineString->points( exteriorPts );
      json += QgsGeometryUtils::pointsToJSON( exteriorPts, precision ) + ", ";
      delete exteriorLineString;

      for ( int i = 0, n = polygon->numInteriorRings(); i < n; ++i )
      {
        QgsLineString* interiorLineString = polygon->interiorRing( i )->curveToLine();
        QgsPointSequence interiorPts;
        interiorLineString->points( interiorPts );
        json += QgsGeometryUtils::pointsToJSON( interiorPts, precision ) + ", ";
        delete interiorLineString;
      }
      if ( json.endsWith( QLatin1String( ", " ) ) )
      {
        json.chop( 2 ); // Remove last ", "
      }

      delete polygon;

      json += QLatin1String( "], " );
    }
  }
  if ( json.endsWith( QLatin1String( ", " ) ) )
  {
    json.chop( 2 ); // Remove last ", "
  }
  json += QLatin1String( "] }" );
  return json;
}
Ejemplo n.º 17
0
static bool ring_make_geos_friendly( QgsCurve *ring )
{
  if ( ring->nCoordinates() == 0 )
    return false;

  // earlier we allowed in only geometries with straight segments
  QgsLineString *linestring = qgsgeometry_cast<QgsLineString *>( ring );

  // close the ring if not already closed (2d only)

  QgsPoint p1 = linestring->startPoint(), p2 = linestring->endPoint();
  if ( p1.x() != p2.x() || p1.y() != p2.y() )
    linestring->addVertex( p1 );

  // must have at least 4 coordinates to be accepted by GEOS

  while ( linestring->nCoordinates() < 4 )
    linestring->addVertex( p1 );

  return true;
}
Ejemplo n.º 18
0
bool QgsCompoundCurve::deleteVertex( QgsVertexId position )
{
  QVector< QPair<int, QgsVertexId> > curveIds = curveVertexId( position );
  if ( curveIds.size() == 1 )
  {
    if ( !mCurves.at( curveIds.at( 0 ).first )->deleteVertex( curveIds.at( 0 ).second ) )
    {
      clearCache(); //bbox may have changed
      return false;
    }
    if ( mCurves.at( curveIds.at( 0 ).first )->numPoints() == 0 )
    {
      removeCurve( curveIds.at( 0 ).first );
    }
  }
  else if ( curveIds.size() == 2 )
  {
    Q_ASSERT( curveIds.at( 1 ).first == curveIds.at( 0 ).first + 1 );
    Q_ASSERT( curveIds.at( 0 ).second.vertex == mCurves.at( curveIds.at( 0 ).first )->numPoints() - 1 );
    Q_ASSERT( curveIds.at( 1 ).second.vertex == 0 );
    QgsPoint startPoint = mCurves.at( curveIds.at( 0 ).first ) ->startPoint();
    QgsPoint endPoint = mCurves.at( curveIds.at( 1 ).first ) ->endPoint();
    if ( QgsWkbTypes::flatType( mCurves.at( curveIds.at( 0 ).first )->wkbType() ) == QgsWkbTypes::LineString &&
         QgsWkbTypes::flatType( mCurves.at( curveIds.at( 1 ).first )->wkbType() ) == QgsWkbTypes::CircularString &&
         mCurves.at( curveIds.at( 1 ).first )->numPoints() > 3 )
    {
      QgsPoint intermediatePoint;
      QgsVertexId::VertexType type;
      mCurves.at( curveIds.at( 1 ).first ) ->pointAt( 2, intermediatePoint, type );
      mCurves.at( curveIds.at( 0 ).first )->moveVertex(
        QgsVertexId( 0, 0, mCurves.at( curveIds.at( 0 ).first )->numPoints() - 1 ), intermediatePoint );
    }
    else if ( !mCurves.at( curveIds.at( 0 ).first )->deleteVertex( curveIds.at( 0 ).second ) )
    {
      clearCache(); //bbox may have changed
      return false;
    }
    if ( QgsWkbTypes::flatType( mCurves.at( curveIds.at( 0 ).first )->wkbType() ) == QgsWkbTypes::CircularString &&
         mCurves.at( curveIds.at( 0 ).first )->numPoints() > 0 &&
         QgsWkbTypes::flatType( mCurves.at( curveIds.at( 1 ).first )->wkbType() ) == QgsWkbTypes::LineString )
    {
      QgsPoint intermediatePoint = mCurves.at( curveIds.at( 0 ).first ) ->endPoint();
      mCurves.at( curveIds.at( 1 ).first )->moveVertex( QgsVertexId( 0, 0, 0 ), intermediatePoint );
    }
    else if ( !mCurves.at( curveIds.at( 1 ).first )->deleteVertex( curveIds.at( 1 ).second ) )
    {
      clearCache(); //bbox may have changed
      return false;
    }
    if ( mCurves.at( curveIds.at( 0 ).first )->numPoints() == 0 &&
         mCurves.at( curveIds.at( 1 ).first )->numPoints() != 0 )
    {
      mCurves.at( curveIds.at( 1 ).first )->moveVertex( QgsVertexId( 0, 0, 0 ), startPoint );
      removeCurve( curveIds.at( 0 ).first );
    }
    else if ( mCurves.at( curveIds.at( 0 ).first )->numPoints() != 0 &&
              mCurves.at( curveIds.at( 1 ).first )->numPoints() == 0 )
    {
      mCurves.at( curveIds.at( 0 ).first )->moveVertex(
        QgsVertexId( 0, 0, mCurves.at( curveIds.at( 0 ).first )->numPoints() - 1 ), endPoint );
      removeCurve( curveIds.at( 1 ).first );
    }
    else if ( mCurves.at( curveIds.at( 0 ).first )->numPoints() == 0 &&
              mCurves.at( curveIds.at( 1 ).first )->numPoints() == 0 )
    {
      removeCurve( curveIds.at( 1 ).first );
      removeCurve( curveIds.at( 0 ).first );
      QgsLineString *line = new QgsLineString();
      line->insertVertex( QgsVertexId( 0, 0, 0 ), startPoint );
      line->insertVertex( QgsVertexId( 0, 0, 1 ), endPoint );
      mCurves.insert( curveIds.at( 0 ).first, line );
    }
    else
    {
      QgsPoint endPointOfFirst = mCurves.at( curveIds.at( 0 ).first ) ->endPoint();
      QgsPoint startPointOfSecond = mCurves.at( curveIds.at( 1 ).first ) ->startPoint();
      if ( endPointOfFirst != startPointOfSecond )
      {
        QgsLineString *line = new QgsLineString();
        line->insertVertex( QgsVertexId( 0, 0, 0 ), endPointOfFirst );
        line->insertVertex( QgsVertexId( 0, 0, 1 ), startPointOfSecond );
        mCurves.insert( curveIds.at( 1 ).first, line );
      }
    }
  }

  bool success = !curveIds.isEmpty();
  if ( success )
  {
    clearCache(); //bbox changed
  }
  return success;
}
Ejemplo n.º 19
-1
void QgsCompoundCurve::addVertex( const QgsPoint &pt )
{
  if ( mCurves.isEmpty() || mWkbType == QgsWkbTypes::Unknown )
  {
    setZMTypeFromSubGeometry( &pt, QgsWkbTypes::CompoundCurve );
  }

  //is last curve QgsLineString
  QgsCurve *lastCurve = nullptr;
  if ( !mCurves.isEmpty() )
  {
    lastCurve = mCurves.at( mCurves.size() - 1 );
  }

  QgsLineString *line = nullptr;
  if ( !lastCurve || QgsWkbTypes::flatType( lastCurve->wkbType() ) != QgsWkbTypes::LineString )
  {
    line = new QgsLineString();
    mCurves.append( line );
    if ( lastCurve )
    {
      line->addVertex( lastCurve->endPoint() );
    }
    lastCurve = line;
  }
  else //create new QgsLineString* with point in it
  {
    line = static_cast<QgsLineString *>( lastCurve );
  }
  line->addVertex( pt );
  clearCache();
}