Skip to content
Permalink
Browse files

Merge pull request #3081 from mhugent/curve_segmentize_parameters

Curve segmentize parameters
  • Loading branch information
mhugent committed May 19, 2016
2 parents 0078b33 + c0d12dc commit bc1aa42f858056bf2309488320267e15ae6b54ab
Showing with 338 additions and 310 deletions.
  1. +11 −1 python/core/geometry/qgsabstractgeometryv2.sip
  2. +5 −4 python/core/geometry/qgscircularstringv2.sip
  3. +5 −1 python/core/geometry/qgscompoundcurvev2.sip
  4. +9 −2 python/core/geometry/qgscurvepolygonv2.sip
  5. +7 −3 python/core/geometry/qgscurvev2.sip
  6. +4 −2 python/core/geometry/qgsgeometrycollectionv2.sip
  7. +5 −1 python/core/geometry/qgslinestringv2.sip
  8. +12 −0 python/core/qgsmapsettings.sip
  9. +12 −0 python/core/qgsrendercontext.sip
  10. +7 −0 python/gui/qgsmapcanvas.sip
  11. +3 −0 src/app/qgisapp.cpp
  12. +27 −0 src/app/qgsoptions.cpp
  13. +9 −0 src/core/geometry/qgsabstractgeometryv2.cpp
  14. +11 −1 src/core/geometry/qgsabstractgeometryv2.h
  15. +9 −4 src/core/geometry/qgscircularstringv2.cpp
  16. +6 −5 src/core/geometry/qgscircularstringv2.h
  17. +2 −2 src/core/geometry/qgscompoundcurvev2.cpp
  18. +5 −1 src/core/geometry/qgscompoundcurvev2.h
  19. +5 −5 src/core/geometry/qgscurvepolygonv2.cpp
  20. +9 −2 src/core/geometry/qgscurvepolygonv2.h
  21. +2 −2 src/core/geometry/qgscurvev2.cpp
  22. +7 −4 src/core/geometry/qgscurvev2.h
  23. +2 −2 src/core/geometry/qgsgeometrycollectionv2.cpp
  24. +4 −2 src/core/geometry/qgsgeometrycollectionv2.h
  25. +3 −1 src/core/geometry/qgslinestringv2.cpp
  26. +5 −1 src/core/geometry/qgslinestringv2.h
  27. +2 −0 src/core/qgsmapsettings.cpp
  28. +16 −0 src/core/qgsmapsettings.h
  29. +8 −0 src/core/qgsrendercontext.cpp
  30. +16 −0 src/core/qgsrendercontext.h
  31. +1 −1 src/core/symbology-ng/qgssymbolv2.cpp
  32. +17 −0 src/gui/qgsmapcanvas.cpp
  33. +7 −0 src/gui/qgsmapcanvas.h
  34. +85 −263 src/ui/qgsoptionsbase.ui
@@ -70,6 +70,14 @@ class QgsAbstractGeometryV2

public:

/** Segmentation tolerance as maximum angle or maximum difference between approximation and circle*/
enum SegmentationToleranceType
{
MaximumAngle = 0,
MaximumDifference
};


QgsAbstractGeometryV2();
virtual ~QgsAbstractGeometryV2();
QgsAbstractGeometryV2( const QgsAbstractGeometryV2& geom );
@@ -303,8 +311,10 @@ class QgsAbstractGeometryV2

/** Returns a version of the geometry without curves. Caller takes ownership of
* the returned geometry.
* @param tolerance segmentation tolerance
* @param toleranceType maximum segmentation angle or maximum difference between approximation and curve
*/
virtual QgsAbstractGeometryV2* segmentize() const /Factory/;
virtual QgsAbstractGeometryV2* segmentize( double tolerance = M_PI_2 / 90, SegmentationToleranceType toleranceType = MaximumAngle ) const /Factory/;

/** Returns the geometry converted to the more generic curve type.
E.g. QgsLineStringV2 -> QgsCompoundCurveV2, QgsPolygonV2 -> QgsCurvePolygonV2,
@@ -54,10 +54,11 @@ class QgsCircularStringV2: public QgsCurveV2
* @copydoc QgsCurveV2::endPoint()
*/
virtual QgsPointV2 endPoint() const;
/**
* @copydoc QgsCurveV2::curveToLine()
*/
virtual QgsLineStringV2* curveToLine() const;
/** Returns a new line string geometry corresponding to a segmentized approximation
* of the curve.
* @param tolerance segmentation tolerance
* @param toleranceType maximum segmentation angle or maximum difference between approximation and curve*/
virtual QgsLineStringV2* curveToLine( double tolerance = M_PI_2 / 90, SegmentationToleranceType toleranceType = MaximumAngle ) const;

void draw( QPainter& p ) const;

@@ -34,7 +34,11 @@ class QgsCompoundCurveV2: public QgsCurveV2
virtual QgsPointV2 endPoint() const;
virtual void points( QList<QgsPointV2>& pts ) const;
virtual int numPoints() const;
virtual QgsLineStringV2* curveToLine() const;
/** Returns a new line string geometry corresponding to a segmentized approximation
* of the curve.
* @param tolerance segmentation tolerance
* @param toleranceType maximum segmentation angle or maximum difference between approximation and curve*/
virtual QgsLineStringV2* curveToLine( double tolerance = M_PI_2 / 90, SegmentationToleranceType toleranceType = MaximumAngle ) const;

/** Returns the number of curves in the geometry.
*/
@@ -34,7 +34,11 @@ class QgsCurvePolygonV2: public QgsSurfaceV2
int numInteriorRings() const;
const QgsCurveV2* exteriorRing() const;
const QgsCurveV2* interiorRing( int i ) const;
virtual QgsPolygonV2* toPolygon() const;
/** Returns a new polygon geometry corresponding to a segmentized approximation
* of the curve.
* @param tolerance segmentation tolerance
* @param toleranceType maximum segmentation angle or maximum difference between approximation and curve*/
virtual QgsPolygonV2* toPolygon( double tolerance = M_PI_2 / 90, SegmentationToleranceType toleranceType = MaximumAngle ) const;

/** Sets the exterior ring of the polygon. The CurvePolygon type will be updated to match the dimensionality
* of the exterior ring. For instance, setting a 2D exterior ring on a 3D CurvePolygon will drop the z dimension
@@ -69,7 +73,10 @@ class QgsCurvePolygonV2: public QgsSurfaceV2
bool nextVertex( QgsVertexId& id, QgsPointV2& vertex ) const;

bool hasCurvedSegments() const;
QgsAbstractGeometryV2* segmentize() const /Factory/;
/** Returns a geometry without curves. Caller takes ownership
* @param tolerance segmentation tolerance
* @param toleranceType maximum segmentation angle or maximum difference between approximation and curve*/
QgsAbstractGeometryV2* segmentize( double tolerance = M_PI_2 / 90, SegmentationToleranceType toleranceType = MaximumAngle ) const /Factory/;

/** Returns approximate rotation angle for a vertex. Usually average angle between adjacent segments.
* @param vertex the vertex id
@@ -32,8 +32,10 @@ class QgsCurveV2: public QgsAbstractGeometryV2

/** Returns a new line string geometry corresponding to a segmentized approximation
* of the curve.
* @param tolerance segmentation tolerance
* @param toleranceType maximum segmentation angle or maximum difference between approximation and curve
*/
virtual QgsLineStringV2* curveToLine() const = 0;
virtual QgsLineStringV2* curveToLine( double tolerance = M_PI_2 / 90, SegmentationToleranceType toleranceType = MaximumAngle ) const = 0;

/** Adds a curve to a painter path.
*/
@@ -73,8 +75,10 @@ class QgsCurveV2: public QgsAbstractGeometryV2
*/
virtual QgsCurveV2* reversed() const = 0 /Factory/;

/** Returns a geometry without curves. Caller takes ownership*/
virtual QgsCurveV2* segmentize() const /Factory/;
/** Returns a geometry without curves. Caller takes ownership
* @param tolerance segmentation tolerance
* @param toleranceType maximum segmentation angle or maximum difference between approximation and curve*/
virtual QgsCurveV2* segmentize( double tolerance = M_PI_2 / 90, SegmentationToleranceType toleranceType = MaximumAngle ) const /Factory/;

virtual int vertexCount( int part = 0, int ring = 0 ) const;
virtual int ringCount( int part = 0 ) const;
@@ -83,8 +83,10 @@ class QgsGeometryCollectionV2: public QgsAbstractGeometryV2

bool hasCurvedSegments() const;

/** Returns a geometry without curves. Caller takes ownership*/
QgsAbstractGeometryV2* segmentize() const;
/** Returns a geometry without curves. Caller takes ownership
* @param tolerance segmentation tolerance
* @param toleranceType maximum segmentation angle or maximum difference between approximation and curve*/
QgsAbstractGeometryV2* segmentize( double tolerance = M_PI_2 / 90, SegmentationToleranceType toleranceType = MaximumAngle ) const;

/** Returns approximate rotation angle for a vertex. Usually average angle between adjacent segments.
* @param vertex the vertex id
@@ -131,7 +131,11 @@ class QgsLineStringV2: public QgsCurveV2
virtual double length() const;
virtual QgsPointV2 startPoint() const;
virtual QgsPointV2 endPoint() const;
virtual QgsLineStringV2* curveToLine() const /Factory/;
/** Returns a new line string geometry corresponding to a segmentized approximation
* of the curve.
* @param tolerance segmentation tolerance
* @param toleranceType maximum segmentation angle or maximum difference between approximation and curve*/
virtual QgsLineStringV2* curveToLine( double tolerance = M_PI_2 / 90, SegmentationToleranceType toleranceType = MaximumAngle ) const /Factory/;

int numPoints() const;
void points( QList<QgsPointV2>& pt ) const;
@@ -211,6 +211,18 @@ class QgsMapSettings

void writeXML( QDomNode& theNode, QDomDocument& theDoc );

/** Sets the segmentation tolerance applied when rendering curved geometries
@param tolerance the segmentation tolerance*/
void setSegmentationTolerance( double tolerance );
/** Gets the segmentation tolerance applied when rendering curved geometries*/
double segmentationTolerance() const;
/** Sets segmentation tolerance type (maximum angle or maximum difference between curve and approximation)
@param type the segmentation tolerance typename*/
void setSegmentationToleranceType( QgsAbstractGeometryV2::SegmentationToleranceType type );
/** Gets segmentation tolerance type (maximum angle or maximum difference between curve and approximation)*/
QgsAbstractGeometryV2::SegmentationToleranceType segmentationToleranceType() const;


protected:

void updateDerived();
@@ -177,4 +177,16 @@ class QgsRenderContext
* @see setFeatureFilterProvider()
*/
const QgsFeatureFilterProvider* featureFilterProvider() const;

/** Sets the segmentation tolerance applied when rendering curved geometries
@param tolerance the segmentation tolerance*/
void setSegmentationTolerance( double tolerance );
/** Gets the segmentation tolerance applied when rendering curved geometries*/
double segmentationTolerance() const;

/** Sets segmentation tolerance type (maximum angle or maximum difference between curve and approximation)
@param type the segmentation tolerance typename*/
void setSegmentationToleranceType( QgsAbstractGeometryV2::SegmentationToleranceType type );
/** Gets segmentation tolerance type (maximum angle or maximum difference between curve and approximation)*/
QgsAbstractGeometryV2::SegmentationToleranceType segmentationToleranceType() const;
};
@@ -393,6 +393,13 @@ class QgsMapCanvas : QGraphicsView
*/
// const QgsExpressionContextScope& expressionContextScope() const;

/** Sets the segmentation tolerance applied when rendering curved geometries
@param tolerance the segmentation tolerance*/
void setSegmentationTolerance( double tolerance );
/** Sets segmentation tolerance type (maximum angle or maximum difference between curve and approximation)
@param type the segmentation tolerance typename*/
void setSegmentationToleranceType( QgsAbstractGeometryV2::SegmentationToleranceType type );

public slots:

/** Repaints the canvas map*/
@@ -8641,6 +8641,9 @@ void QgisApp::showOptionsDialog( QWidget *parent, const QString& currentPage )

bool otfTransformAutoEnable = mySettings.value( "/Projections/otfTransformAutoEnable", true ).toBool();
mLayerTreeCanvasBridge->setAutoEnableCrsTransform( otfTransformAutoEnable );

mMapCanvas->setSegmentationTolerance( mySettings.value( "/qgis/segmentationTolerance", "0.01745" ).toDouble() );
mMapCanvas->setSegmentationToleranceType( QgsAbstractGeometryV2::SegmentationToleranceType( mySettings.value( "/qgis/segmentationToleranceType", "0" ).toInt() ) );
}

delete optionsDialog;
@@ -584,6 +584,23 @@ QgsOptions::QgsOptions( QWidget *parent, Qt::WindowFlags fl )
mSimplifyDrawingSpinBox->setValue( mSettings->value( "/qgis/simplifyDrawingTol", QGis::DEFAULT_MAPTOPIXEL_THRESHOLD ).toFloat() );
mSimplifyDrawingAtProvider->setChecked( !mSettings->value( "/qgis/simplifyLocal", true ).toBool() );

//segmentation tolerance type
mToleranceTypeComboBox->addItem( tr( "Maximum angle" ), 0 );
mToleranceTypeComboBox->addItem( tr( "Maximum difference" ), 1 );
int toleranceType = mSettings->value( "/qgis/segmentationToleranceType", "0" ).toInt();
int toleranceTypeIndex = mToleranceTypeComboBox->findData( toleranceType );
if ( toleranceTypeIndex != -1 )
{
mToleranceTypeComboBox->setCurrentIndex( toleranceTypeIndex );
}

double tolerance = mSettings->value( "/qgis/segmentationTolerance", "0.01745" ).toDouble();
if ( toleranceType == 0 )
{
tolerance = tolerance * 180.0 / M_PI; //value shown to the user is degree, not rad
}
mSegmentationToleranceSpinBox->setValue( tolerance );

QStringList myScalesList = PROJECT_SCALES.split( ',' );
myScalesList.append( "1:1" );
mSimplifyMaximumScaleComboBox->updateScales( myScalesList );
@@ -1202,6 +1219,16 @@ void QgsOptions::saveOptions()
// magnification
mSettings->setValue( "/qgis/magnifier_level", doubleSpinBoxMagnifierDefault->value() );

//curve segmentation
int segmentationType = mToleranceTypeComboBox->itemData( mToleranceTypeComboBox->currentIndex() ).toInt();
mSettings->setValue( "/qgis/segmentationToleranceType", segmentationType );
double segmentationTolerance = mSegmentationToleranceSpinBox->value();
if ( segmentationType == 0 )
{
segmentationTolerance = segmentationTolerance / 180.0 * M_PI; //user sets angle tolerance in degrees, internal classes need value in rad
}
mSettings->setValue( "/qgis/segmentationTolerance", segmentationTolerance );

// project
mSettings->setValue( "/qgis/projOpenAtLaunch", mProjectOnLaunchCmbBx->currentIndex() );
mSettings->setValue( "/qgis/projOpenAtLaunchPath", mProjectOnLaunchLineEdit->text() );
@@ -244,3 +244,12 @@ bool QgsAbstractGeometryV2::isEmpty() const
QgsPointV2 vertex;
return !nextVertex( vId, vertex );
}


QgsAbstractGeometryV2* QgsAbstractGeometryV2::segmentize( double tolerance, SegmentationToleranceType toleranceType ) const
{
Q_UNUSED( tolerance );
Q_UNUSED( toleranceType );
return clone();
}

@@ -43,6 +43,14 @@ typedef QList< QgsRingSequenceV2 > QgsCoordinateSequenceV2;
class CORE_EXPORT QgsAbstractGeometryV2
{
public:

/** Segmentation tolerance as maximum angle or maximum difference between approximation and circle*/
enum SegmentationToleranceType
{
MaximumAngle = 0,
MaximumDifference
};

QgsAbstractGeometryV2();
virtual ~QgsAbstractGeometryV2();
QgsAbstractGeometryV2( const QgsAbstractGeometryV2& geom );
@@ -288,8 +296,10 @@ class CORE_EXPORT QgsAbstractGeometryV2

/** Returns a version of the geometry without curves. Caller takes ownership of
* the returned geometry.
* @param tolerance segmentation tolerance
* @param toleranceType maximum segmentation angle or maximum difference between approximation and curve
*/
virtual QgsAbstractGeometryV2* segmentize() const { return clone(); }
virtual QgsAbstractGeometryV2* segmentize( double tolerance = M_PI_2 / 90, SegmentationToleranceType toleranceType = MaximumAngle ) const;

/** Returns the geometry converted to the more generic curve type.
E.g. QgsLineStringV2 -> QgsCompoundCurveV2, QgsPolygonV2 -> QgsCurvePolygonV2,
@@ -351,15 +351,15 @@ QgsPointV2 QgsCircularStringV2::endPoint() const
return pointN( numPoints() - 1 );
}

QgsLineStringV2* QgsCircularStringV2::curveToLine() const
QgsLineStringV2* QgsCircularStringV2::curveToLine( double tolerance, SegmentationToleranceType toleranceType ) const
{
QgsLineStringV2* line = new QgsLineStringV2();
QgsPointSequenceV2 points;
int nPoints = numPoints();

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

line->setPoints( points );
@@ -473,7 +473,7 @@ void QgsCircularStringV2::setPoints( const QgsPointSequenceV2 &points )
}
}

void QgsCircularStringV2::segmentize( const QgsPointV2& p1, const QgsPointV2& p2, const QgsPointV2& p3, QgsPointSequenceV2 &points ) const
void QgsCircularStringV2::segmentize( const QgsPointV2& p1, const QgsPointV2& p2, const QgsPointV2& p3, QgsPointSequenceV2 &points, double tolerance, SegmentationToleranceType toleranceType ) const
{
//adapted code from postgis
double radius = 0;
@@ -496,7 +496,12 @@ void QgsCircularStringV2::segmentize( const QgsPointV2& p1, const QgsPointV2& p2
clockwise = true;
}

double increment = fabs( M_PI_2 / 90 ); //one segment per degree
double increment = tolerance; //one segment per degree
if ( toleranceType == QgsAbstractGeometryV2::MaximumDifference )
{
double halfAngle = acos( -tolerance / radius + 1 );
increment = 2 * halfAngle;
}

//angles of pt1, pt2, pt3
double a1 = atan2( p1.y() - centerY, p1.x() - centerX );
@@ -79,10 +79,11 @@ class CORE_EXPORT QgsCircularStringV2: public QgsCurveV2
* @copydoc QgsCurveV2::endPoint()
*/
virtual QgsPointV2 endPoint() const override;
/**
* @copydoc QgsCurveV2::curveToLine()
*/
virtual QgsLineStringV2* curveToLine() const override;
/** Returns a new line string geometry corresponding to a segmentized approximation
* of the curve.
* @param tolerance segmentation tolerance
* @param toleranceType maximum segmentation angle or maximum difference between approximation and curve*/
virtual QgsLineStringV2* curveToLine( double tolerance = M_PI_2 / 90, SegmentationToleranceType toleranceType = MaximumAngle ) const override;

void draw( QPainter& p ) const override;

@@ -143,7 +144,7 @@ class CORE_EXPORT QgsCircularStringV2: public QgsCurveV2
QVector<double> mM;

//helper methods for curveToLine
void segmentize( const QgsPointV2& p1, const QgsPointV2& p2, const QgsPointV2& p3, QgsPointSequenceV2 &points ) const;
void segmentize( const QgsPointV2& p1, const QgsPointV2& p2, const QgsPointV2& p3, QgsPointSequenceV2 &points, double tolerance = M_PI_2 / 90, SegmentationToleranceType toleranceType = MaximumAngle ) const;
int segmentSide( const QgsPointV2& pt1, const QgsPointV2& pt3, const QgsPointV2& pt2 ) const;
double interpolateArc( double angle, double a1, double a2, double a3, double zm1, double zm2, double zm3 ) const;
static void arcTo( QPainterPath& path, QPointF pt1, QPointF pt2, QPointF pt3 );
@@ -357,14 +357,14 @@ int QgsCompoundCurveV2::numPoints() const
return nPoints;
}

QgsLineStringV2* QgsCompoundCurveV2::curveToLine() const
QgsLineStringV2* QgsCompoundCurveV2::curveToLine( double tolerance, SegmentationToleranceType toleranceType ) const
{
QList< QgsCurveV2* >::const_iterator curveIt = mCurves.constBegin();
QgsLineStringV2* line = new QgsLineStringV2();
QgsLineStringV2* currentLine = nullptr;
for ( ; curveIt != mCurves.constEnd(); ++curveIt )
{
currentLine = ( *curveIt )->curveToLine();
currentLine = ( *curveIt )->curveToLine( tolerance, toleranceType );
line->append( currentLine );
delete currentLine;
}
@@ -58,7 +58,11 @@ class CORE_EXPORT QgsCompoundCurveV2: public QgsCurveV2
virtual QgsPointV2 endPoint() const override;
virtual void points( QgsPointSequenceV2 &pts ) const override;
virtual int numPoints() const override;
virtual QgsLineStringV2* curveToLine() const override;
/** Returns a new line string geometry corresponding to a segmentized approximation
* of the curve.
* @param tolerance segmentation tolerance
* @param toleranceType maximum segmentation angle or maximum difference between approximation and curve*/
virtual QgsLineStringV2* curveToLine( double tolerance = M_PI_2 / 90, SegmentationToleranceType toleranceType = MaximumAngle ) const override;

/** Returns the number of curves in the geometry.
*/

0 comments on commit bc1aa42

Please sign in to comment.
You can’t perform that action at this time.