Skip to content

Commit bc1aa42

Browse files
committedMay 19, 2016
Merge pull request #3081 from mhugent/curve_segmentize_parameters
Curve segmentize parameters
2 parents 0078b33 + c0d12dc commit bc1aa42

34 files changed

+338
-310
lines changed
 

‎python/core/geometry/qgsabstractgeometryv2.sip

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,14 @@ class QgsAbstractGeometryV2
7070

7171
public:
7272

73+
/** Segmentation tolerance as maximum angle or maximum difference between approximation and circle*/
74+
enum SegmentationToleranceType
75+
{
76+
MaximumAngle = 0,
77+
MaximumDifference
78+
};
79+
80+
7381
QgsAbstractGeometryV2();
7482
virtual ~QgsAbstractGeometryV2();
7583
QgsAbstractGeometryV2( const QgsAbstractGeometryV2& geom );
@@ -303,8 +311,10 @@ class QgsAbstractGeometryV2
303311

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

309319
/** Returns the geometry converted to the more generic curve type.
310320
E.g. QgsLineStringV2 -> QgsCompoundCurveV2, QgsPolygonV2 -> QgsCurvePolygonV2,

‎python/core/geometry/qgscircularstringv2.sip

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,11 @@ class QgsCircularStringV2: public QgsCurveV2
5454
* @copydoc QgsCurveV2::endPoint()
5555
*/
5656
virtual QgsPointV2 endPoint() const;
57-
/**
58-
* @copydoc QgsCurveV2::curveToLine()
59-
*/
60-
virtual QgsLineStringV2* curveToLine() const;
57+
/** Returns a new line string geometry corresponding to a segmentized approximation
58+
* of the curve.
59+
* @param tolerance segmentation tolerance
60+
* @param toleranceType maximum segmentation angle or maximum difference between approximation and curve*/
61+
virtual QgsLineStringV2* curveToLine( double tolerance = M_PI_2 / 90, SegmentationToleranceType toleranceType = MaximumAngle ) const;
6162

6263
void draw( QPainter& p ) const;
6364

‎python/core/geometry/qgscompoundcurvev2.sip

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,11 @@ class QgsCompoundCurveV2: public QgsCurveV2
3434
virtual QgsPointV2 endPoint() const;
3535
virtual void points( QList<QgsPointV2>& pts ) const;
3636
virtual int numPoints() const;
37-
virtual QgsLineStringV2* curveToLine() const;
37+
/** Returns a new line string geometry corresponding to a segmentized approximation
38+
* of the curve.
39+
* @param tolerance segmentation tolerance
40+
* @param toleranceType maximum segmentation angle or maximum difference between approximation and curve*/
41+
virtual QgsLineStringV2* curveToLine( double tolerance = M_PI_2 / 90, SegmentationToleranceType toleranceType = MaximumAngle ) const;
3842

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

‎python/core/geometry/qgscurvepolygonv2.sip

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,11 @@ class QgsCurvePolygonV2: public QgsSurfaceV2
3434
int numInteriorRings() const;
3535
const QgsCurveV2* exteriorRing() const;
3636
const QgsCurveV2* interiorRing( int i ) const;
37-
virtual QgsPolygonV2* toPolygon() const;
37+
/** Returns a new polygon geometry corresponding to a segmentized approximation
38+
* of the curve.
39+
* @param tolerance segmentation tolerance
40+
* @param toleranceType maximum segmentation angle or maximum difference between approximation and curve*/
41+
virtual QgsPolygonV2* toPolygon( double tolerance = M_PI_2 / 90, SegmentationToleranceType toleranceType = MaximumAngle ) const;
3842

3943
/** Sets the exterior ring of the polygon. The CurvePolygon type will be updated to match the dimensionality
4044
* 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
6973
bool nextVertex( QgsVertexId& id, QgsPointV2& vertex ) const;
7074

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

7481
/** Returns approximate rotation angle for a vertex. Usually average angle between adjacent segments.
7582
* @param vertex the vertex id

‎python/core/geometry/qgscurvev2.sip

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,10 @@ class QgsCurveV2: public QgsAbstractGeometryV2
3232

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

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

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

7983
virtual int vertexCount( int part = 0, int ring = 0 ) const;
8084
virtual int ringCount( int part = 0 ) const;

‎python/core/geometry/qgsgeometrycollectionv2.sip

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,10 @@ class QgsGeometryCollectionV2: public QgsAbstractGeometryV2
8383

8484
bool hasCurvedSegments() const;
8585

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

8991
/** Returns approximate rotation angle for a vertex. Usually average angle between adjacent segments.
9092
* @param vertex the vertex id

‎python/core/geometry/qgslinestringv2.sip

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,11 @@ class QgsLineStringV2: public QgsCurveV2
131131
virtual double length() const;
132132
virtual QgsPointV2 startPoint() const;
133133
virtual QgsPointV2 endPoint() const;
134-
virtual QgsLineStringV2* curveToLine() const /Factory/;
134+
/** Returns a new line string geometry corresponding to a segmentized approximation
135+
* of the curve.
136+
* @param tolerance segmentation tolerance
137+
* @param toleranceType maximum segmentation angle or maximum difference between approximation and curve*/
138+
virtual QgsLineStringV2* curveToLine( double tolerance = M_PI_2 / 90, SegmentationToleranceType toleranceType = MaximumAngle ) const /Factory/;
135139

136140
int numPoints() const;
137141
void points( QList<QgsPointV2>& pt ) const;

‎python/core/qgsmapsettings.sip

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,18 @@ class QgsMapSettings
211211

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

214+
/** Sets the segmentation tolerance applied when rendering curved geometries
215+
@param tolerance the segmentation tolerance*/
216+
void setSegmentationTolerance( double tolerance );
217+
/** Gets the segmentation tolerance applied when rendering curved geometries*/
218+
double segmentationTolerance() const;
219+
/** Sets segmentation tolerance type (maximum angle or maximum difference between curve and approximation)
220+
@param type the segmentation tolerance typename*/
221+
void setSegmentationToleranceType( QgsAbstractGeometryV2::SegmentationToleranceType type );
222+
/** Gets segmentation tolerance type (maximum angle or maximum difference between curve and approximation)*/
223+
QgsAbstractGeometryV2::SegmentationToleranceType segmentationToleranceType() const;
224+
225+
214226
protected:
215227

216228
void updateDerived();

‎python/core/qgsrendercontext.sip

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,4 +177,16 @@ class QgsRenderContext
177177
* @see setFeatureFilterProvider()
178178
*/
179179
const QgsFeatureFilterProvider* featureFilterProvider() const;
180+
181+
/** Sets the segmentation tolerance applied when rendering curved geometries
182+
@param tolerance the segmentation tolerance*/
183+
void setSegmentationTolerance( double tolerance );
184+
/** Gets the segmentation tolerance applied when rendering curved geometries*/
185+
double segmentationTolerance() const;
186+
187+
/** Sets segmentation tolerance type (maximum angle or maximum difference between curve and approximation)
188+
@param type the segmentation tolerance typename*/
189+
void setSegmentationToleranceType( QgsAbstractGeometryV2::SegmentationToleranceType type );
190+
/** Gets segmentation tolerance type (maximum angle or maximum difference between curve and approximation)*/
191+
QgsAbstractGeometryV2::SegmentationToleranceType segmentationToleranceType() const;
180192
};

‎python/gui/qgsmapcanvas.sip

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,13 @@ class QgsMapCanvas : QGraphicsView
393393
*/
394394
// const QgsExpressionContextScope& expressionContextScope() const;
395395

396+
/** Sets the segmentation tolerance applied when rendering curved geometries
397+
@param tolerance the segmentation tolerance*/
398+
void setSegmentationTolerance( double tolerance );
399+
/** Sets segmentation tolerance type (maximum angle or maximum difference between curve and approximation)
400+
@param type the segmentation tolerance typename*/
401+
void setSegmentationToleranceType( QgsAbstractGeometryV2::SegmentationToleranceType type );
402+
396403
public slots:
397404

398405
/** Repaints the canvas map*/

‎src/app/qgisapp.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8641,6 +8641,9 @@ void QgisApp::showOptionsDialog( QWidget *parent, const QString& currentPage )
86418641

86428642
bool otfTransformAutoEnable = mySettings.value( "/Projections/otfTransformAutoEnable", true ).toBool();
86438643
mLayerTreeCanvasBridge->setAutoEnableCrsTransform( otfTransformAutoEnable );
8644+
8645+
mMapCanvas->setSegmentationTolerance( mySettings.value( "/qgis/segmentationTolerance", "0.01745" ).toDouble() );
8646+
mMapCanvas->setSegmentationToleranceType( QgsAbstractGeometryV2::SegmentationToleranceType( mySettings.value( "/qgis/segmentationToleranceType", "0" ).toInt() ) );
86448647
}
86458648

86468649
delete optionsDialog;

‎src/app/qgsoptions.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,23 @@ QgsOptions::QgsOptions( QWidget *parent, Qt::WindowFlags fl )
584584
mSimplifyDrawingSpinBox->setValue( mSettings->value( "/qgis/simplifyDrawingTol", QGis::DEFAULT_MAPTOPIXEL_THRESHOLD ).toFloat() );
585585
mSimplifyDrawingAtProvider->setChecked( !mSettings->value( "/qgis/simplifyLocal", true ).toBool() );
586586

587+
//segmentation tolerance type
588+
mToleranceTypeComboBox->addItem( tr( "Maximum angle" ), 0 );
589+
mToleranceTypeComboBox->addItem( tr( "Maximum difference" ), 1 );
590+
int toleranceType = mSettings->value( "/qgis/segmentationToleranceType", "0" ).toInt();
591+
int toleranceTypeIndex = mToleranceTypeComboBox->findData( toleranceType );
592+
if ( toleranceTypeIndex != -1 )
593+
{
594+
mToleranceTypeComboBox->setCurrentIndex( toleranceTypeIndex );
595+
}
596+
597+
double tolerance = mSettings->value( "/qgis/segmentationTolerance", "0.01745" ).toDouble();
598+
if ( toleranceType == 0 )
599+
{
600+
tolerance = tolerance * 180.0 / M_PI; //value shown to the user is degree, not rad
601+
}
602+
mSegmentationToleranceSpinBox->setValue( tolerance );
603+
587604
QStringList myScalesList = PROJECT_SCALES.split( ',' );
588605
myScalesList.append( "1:1" );
589606
mSimplifyMaximumScaleComboBox->updateScales( myScalesList );
@@ -1202,6 +1219,16 @@ void QgsOptions::saveOptions()
12021219
// magnification
12031220
mSettings->setValue( "/qgis/magnifier_level", doubleSpinBoxMagnifierDefault->value() );
12041221

1222+
//curve segmentation
1223+
int segmentationType = mToleranceTypeComboBox->itemData( mToleranceTypeComboBox->currentIndex() ).toInt();
1224+
mSettings->setValue( "/qgis/segmentationToleranceType", segmentationType );
1225+
double segmentationTolerance = mSegmentationToleranceSpinBox->value();
1226+
if ( segmentationType == 0 )
1227+
{
1228+
segmentationTolerance = segmentationTolerance / 180.0 * M_PI; //user sets angle tolerance in degrees, internal classes need value in rad
1229+
}
1230+
mSettings->setValue( "/qgis/segmentationTolerance", segmentationTolerance );
1231+
12051232
// project
12061233
mSettings->setValue( "/qgis/projOpenAtLaunch", mProjectOnLaunchCmbBx->currentIndex() );
12071234
mSettings->setValue( "/qgis/projOpenAtLaunchPath", mProjectOnLaunchLineEdit->text() );

‎src/core/geometry/qgsabstractgeometryv2.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,3 +244,12 @@ bool QgsAbstractGeometryV2::isEmpty() const
244244
QgsPointV2 vertex;
245245
return !nextVertex( vId, vertex );
246246
}
247+
248+
249+
QgsAbstractGeometryV2* QgsAbstractGeometryV2::segmentize( double tolerance, SegmentationToleranceType toleranceType ) const
250+
{
251+
Q_UNUSED( tolerance );
252+
Q_UNUSED( toleranceType );
253+
return clone();
254+
}
255+

‎src/core/geometry/qgsabstractgeometryv2.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,14 @@ typedef QList< QgsRingSequenceV2 > QgsCoordinateSequenceV2;
4343
class CORE_EXPORT QgsAbstractGeometryV2
4444
{
4545
public:
46+
47+
/** Segmentation tolerance as maximum angle or maximum difference between approximation and circle*/
48+
enum SegmentationToleranceType
49+
{
50+
MaximumAngle = 0,
51+
MaximumDifference
52+
};
53+
4654
QgsAbstractGeometryV2();
4755
virtual ~QgsAbstractGeometryV2();
4856
QgsAbstractGeometryV2( const QgsAbstractGeometryV2& geom );
@@ -288,8 +296,10 @@ class CORE_EXPORT QgsAbstractGeometryV2
288296

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

294304
/** Returns the geometry converted to the more generic curve type.
295305
E.g. QgsLineStringV2 -> QgsCompoundCurveV2, QgsPolygonV2 -> QgsCurvePolygonV2,

‎src/core/geometry/qgscircularstringv2.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -351,15 +351,15 @@ QgsPointV2 QgsCircularStringV2::endPoint() const
351351
return pointN( numPoints() - 1 );
352352
}
353353

354-
QgsLineStringV2* QgsCircularStringV2::curveToLine() const
354+
QgsLineStringV2* QgsCircularStringV2::curveToLine( double tolerance, SegmentationToleranceType toleranceType ) const
355355
{
356356
QgsLineStringV2* line = new QgsLineStringV2();
357357
QgsPointSequenceV2 points;
358358
int nPoints = numPoints();
359359

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

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

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

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

501506
//angles of pt1, pt2, pt3
502507
double a1 = atan2( p1.y() - centerY, p1.x() - centerX );

‎src/core/geometry/qgscircularstringv2.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,11 @@ class CORE_EXPORT QgsCircularStringV2: public QgsCurveV2
7979
* @copydoc QgsCurveV2::endPoint()
8080
*/
8181
virtual QgsPointV2 endPoint() const override;
82-
/**
83-
* @copydoc QgsCurveV2::curveToLine()
84-
*/
85-
virtual QgsLineStringV2* curveToLine() const override;
82+
/** Returns a new line string geometry corresponding to a segmentized approximation
83+
* of the curve.
84+
* @param tolerance segmentation tolerance
85+
* @param toleranceType maximum segmentation angle or maximum difference between approximation and curve*/
86+
virtual QgsLineStringV2* curveToLine( double tolerance = M_PI_2 / 90, SegmentationToleranceType toleranceType = MaximumAngle ) const override;
8687

8788
void draw( QPainter& p ) const override;
8889

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

145146
//helper methods for curveToLine
146-
void segmentize( const QgsPointV2& p1, const QgsPointV2& p2, const QgsPointV2& p3, QgsPointSequenceV2 &points ) const;
147+
void segmentize( const QgsPointV2& p1, const QgsPointV2& p2, const QgsPointV2& p3, QgsPointSequenceV2 &points, double tolerance = M_PI_2 / 90, SegmentationToleranceType toleranceType = MaximumAngle ) const;
147148
int segmentSide( const QgsPointV2& pt1, const QgsPointV2& pt3, const QgsPointV2& pt2 ) const;
148149
double interpolateArc( double angle, double a1, double a2, double a3, double zm1, double zm2, double zm3 ) const;
149150
static void arcTo( QPainterPath& path, QPointF pt1, QPointF pt2, QPointF pt3 );

‎src/core/geometry/qgscompoundcurvev2.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -357,14 +357,14 @@ int QgsCompoundCurveV2::numPoints() const
357357
return nPoints;
358358
}
359359

360-
QgsLineStringV2* QgsCompoundCurveV2::curveToLine() const
360+
QgsLineStringV2* QgsCompoundCurveV2::curveToLine( double tolerance, SegmentationToleranceType toleranceType ) const
361361
{
362362
QList< QgsCurveV2* >::const_iterator curveIt = mCurves.constBegin();
363363
QgsLineStringV2* line = new QgsLineStringV2();
364364
QgsLineStringV2* currentLine = nullptr;
365365
for ( ; curveIt != mCurves.constEnd(); ++curveIt )
366366
{
367-
currentLine = ( *curveIt )->curveToLine();
367+
currentLine = ( *curveIt )->curveToLine( tolerance, toleranceType );
368368
line->append( currentLine );
369369
delete currentLine;
370370
}

‎src/core/geometry/qgscompoundcurvev2.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,11 @@ class CORE_EXPORT QgsCompoundCurveV2: public QgsCurveV2
5858
virtual QgsPointV2 endPoint() const override;
5959
virtual void points( QgsPointSequenceV2 &pts ) const override;
6060
virtual int numPoints() const override;
61-
virtual QgsLineStringV2* curveToLine() const override;
61+
/** Returns a new line string geometry corresponding to a segmentized approximation
62+
* of the curve.
63+
* @param tolerance segmentation tolerance
64+
* @param toleranceType maximum segmentation angle or maximum difference between approximation and curve*/
65+
virtual QgsLineStringV2* curveToLine( double tolerance = M_PI_2 / 90, SegmentationToleranceType toleranceType = MaximumAngle ) const override;
6266

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

‎src/core/geometry/qgscurvepolygonv2.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -417,21 +417,21 @@ QgsPolygonV2* QgsCurvePolygonV2::surfaceToPolygon() const
417417
return polygon;
418418
}
419419

420-
QgsPolygonV2* QgsCurvePolygonV2::toPolygon() const
420+
QgsPolygonV2* QgsCurvePolygonV2::toPolygon( double tolerance, SegmentationToleranceType toleranceType ) const
421421
{
422422
if ( !mExteriorRing )
423423
{
424424
return nullptr;
425425
}
426426

427427
QgsPolygonV2* poly = new QgsPolygonV2();
428-
poly->setExteriorRing( mExteriorRing->curveToLine() );
428+
poly->setExteriorRing( mExteriorRing->curveToLine( tolerance, toleranceType ) );
429429

430430
QList<QgsCurveV2*> rings;
431431
QList<QgsCurveV2*>::const_iterator it = mInteriorRings.constBegin();
432432
for ( ; it != mInteriorRings.constEnd(); ++it )
433433
{
434-
rings.push_back(( *it )->curveToLine() );
434+
rings.push_back(( *it )->curveToLine( tolerance, toleranceType ) );
435435
}
436436
poly->setInteriorRings( rings );
437437
return poly;
@@ -765,9 +765,9 @@ bool QgsCurvePolygonV2::hasCurvedSegments() const
765765
return false;
766766
}
767767

768-
QgsAbstractGeometryV2* QgsCurvePolygonV2::segmentize() const
768+
QgsAbstractGeometryV2* QgsCurvePolygonV2::segmentize( double tolerance, SegmentationToleranceType toleranceType ) const
769769
{
770-
return toPolygon();
770+
return toPolygon( tolerance, toleranceType );
771771
}
772772

773773
double QgsCurvePolygonV2::vertexAngle( QgsVertexId vertex ) const

‎src/core/geometry/qgscurvepolygonv2.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,11 @@ class CORE_EXPORT QgsCurvePolygonV2: public QgsSurfaceV2
6060
int numInteriorRings() const;
6161
const QgsCurveV2* exteriorRing() const;
6262
const QgsCurveV2* interiorRing( int i ) const;
63-
virtual QgsPolygonV2* toPolygon() const;
63+
/** Returns a new polygon geometry corresponding to a segmentized approximation
64+
* of the curve.
65+
* @param tolerance segmentation tolerance
66+
* @param toleranceType maximum segmentation angle or maximum difference between approximation and curve*/
67+
virtual QgsPolygonV2* toPolygon( double tolerance = M_PI_2 / 90, SegmentationToleranceType toleranceType = MaximumAngle ) const;
6468

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

97101
bool hasCurvedSegments() const override;
98-
QgsAbstractGeometryV2* segmentize() const override;
102+
/** Returns a geometry without curves. Caller takes ownership
103+
* @param tolerance segmentation tolerance
104+
* @param toleranceType maximum segmentation angle or maximum difference between approximation and curve*/
105+
QgsAbstractGeometryV2* segmentize( double tolerance = M_PI_2 / 90, SegmentationToleranceType toleranceType = MaximumAngle ) const override;
99106

100107
/** Returns approximate rotation angle for a vertex. Usually average angle between adjacent segments.
101108
* @param vertex the vertex id

‎src/core/geometry/qgscurvev2.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,9 @@ bool QgsCurveV2::nextVertex( QgsVertexId& id, QgsPointV2& vertex ) const
7979
return pointAt( id.vertex, vertex, id.type );
8080
}
8181

82-
QgsCurveV2* QgsCurveV2::segmentize() const
82+
QgsCurveV2* QgsCurveV2::segmentize( double tolerance, SegmentationToleranceType toleranceType ) const
8383
{
84-
return curveToLine();
84+
return curveToLine( tolerance, toleranceType );
8585
}
8686

8787
QgsPointV2 QgsCurveV2::vertexAt( QgsVertexId id ) const

‎src/core/geometry/qgscurvev2.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,9 @@ class CORE_EXPORT QgsCurveV2: public QgsAbstractGeometryV2
6060

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

6667
/** Adds a curve to a painter path.
6768
*/
@@ -101,8 +102,10 @@ class CORE_EXPORT QgsCurveV2: public QgsAbstractGeometryV2
101102
*/
102103
virtual QgsCurveV2* reversed() const = 0;
103104

104-
/** Returns a geometry without curves. Caller takes ownership*/
105-
QgsCurveV2* segmentize() const override;
105+
/** Returns a geometry without curves. Caller takes ownership
106+
* @param tolerance segmentation tolerance
107+
* @param toleranceType maximum segmentation angle or maximum difference between approximation and curve*/
108+
QgsCurveV2* segmentize( double tolerance = M_PI_2 / 90, SegmentationToleranceType toleranceType = MaximumAngle ) const override;
106109

107110
virtual int vertexCount( int part = 0, int ring = 0 ) const override { Q_UNUSED( part ); Q_UNUSED( ring ); return numPoints(); }
108111
virtual int ringCount( int part = 0 ) const override { Q_UNUSED( part ); return numPoints() > 0 ? 1 : 0; }

‎src/core/geometry/qgsgeometrycollectionv2.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -555,7 +555,7 @@ bool QgsGeometryCollectionV2::hasCurvedSegments() const
555555
return false;
556556
}
557557

558-
QgsAbstractGeometryV2* QgsGeometryCollectionV2::segmentize() const
558+
QgsAbstractGeometryV2* QgsGeometryCollectionV2::segmentize( double tolerance, SegmentationToleranceType toleranceType ) const
559559
{
560560
QgsAbstractGeometryV2* geom = QgsGeometryFactory::geomFromWkbType( mWkbType );
561561
QgsGeometryCollectionV2* geomCollection = dynamic_cast<QgsGeometryCollectionV2*>( geom );
@@ -568,7 +568,7 @@ QgsAbstractGeometryV2* QgsGeometryCollectionV2::segmentize() const
568568
QVector< QgsAbstractGeometryV2* >::const_iterator geomIt = mGeometries.constBegin();
569569
for ( ; geomIt != mGeometries.constEnd(); ++geomIt )
570570
{
571-
geomCollection->addGeometry(( *geomIt )->segmentize() );
571+
geomCollection->addGeometry(( *geomIt )->segmentize( tolerance, toleranceType ) );
572572
}
573573
return geomCollection;
574574
}

‎src/core/geometry/qgsgeometrycollectionv2.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,10 @@ class CORE_EXPORT QgsGeometryCollectionV2: public QgsAbstractGeometryV2
107107

108108
bool hasCurvedSegments() const override;
109109

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

113115
/** Returns approximate rotation angle for a vertex. Usually average angle between adjacent segments.
114116
* @param vertex the vertex id

‎src/core/geometry/qgslinestringv2.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,8 +271,10 @@ QgsPointV2 QgsLineStringV2::endPoint() const
271271
* See details in QEP #17
272272
****************************************************************************/
273273

274-
QgsLineStringV2* QgsLineStringV2::curveToLine() const
274+
QgsLineStringV2* QgsLineStringV2::curveToLine( double tolerance, SegmentationToleranceType toleranceType ) const
275275
{
276+
Q_UNUSED( tolerance );
277+
Q_UNUSED( toleranceType );
276278
return static_cast<QgsLineStringV2*>( clone() );
277279
}
278280

‎src/core/geometry/qgslinestringv2.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,11 @@ class CORE_EXPORT QgsLineStringV2: public QgsCurveV2
157157
virtual double length() const override;
158158
virtual QgsPointV2 startPoint() const override;
159159
virtual QgsPointV2 endPoint() const override;
160-
virtual QgsLineStringV2* curveToLine() const override;
160+
/** Returns a new line string geometry corresponding to a segmentized approximation
161+
* of the curve.
162+
* @param tolerance segmentation tolerance
163+
* @param toleranceType maximum segmentation angle or maximum difference between approximation and curve*/
164+
virtual QgsLineStringV2* curveToLine( double tolerance = M_PI_2 / 90, SegmentationToleranceType toleranceType = MaximumAngle ) const override;
161165

162166
int numPoints() const override;
163167
void points( QgsPointSequenceV2 &pt ) const override;

‎src/core/qgsmapsettings.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ QgsMapSettings::QgsMapSettings()
4343
, mSelectionColor( Qt::yellow )
4444
, mFlags( Antialiasing | UseAdvancedEffects | DrawLabeling | DrawSelection )
4545
, mImageFormat( QImage::Format_ARGB32_Premultiplied )
46+
, mSegmentationTolerance( M_PI_2 / 90 )
47+
, mSegmentationToleranceType( QgsAbstractGeometryV2::MaximumAngle )
4648
, mValid( false )
4749
, mVisibleExtent()
4850
, mMapUnitsPerPixel( 1 )

‎src/core/qgsmapsettings.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <QSize>
2222
#include <QStringList>
2323

24+
#include "qgsabstractgeometryv2.h"
2425
#include "qgscoordinatereferencesystem.h"
2526
#include "qgsdatumtransformstore.h"
2627
#include "qgsmaptopixel.h"
@@ -259,6 +260,17 @@ class CORE_EXPORT QgsMapSettings
259260

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

263+
/** Sets the segmentation tolerance applied when rendering curved geometries
264+
@param tolerance the segmentation tolerance*/
265+
void setSegmentationTolerance( double tolerance ) { mSegmentationTolerance = tolerance; }
266+
/** Gets the segmentation tolerance applied when rendering curved geometries*/
267+
double segmentationTolerance() const { return mSegmentationTolerance; }
268+
/** Sets segmentation tolerance type (maximum angle or maximum difference between curve and approximation)
269+
@param type the segmentation tolerance typename*/
270+
void setSegmentationToleranceType( QgsAbstractGeometryV2::SegmentationToleranceType type ) { mSegmentationToleranceType = type; }
271+
/** Gets segmentation tolerance type (maximum angle or maximum difference between curve and approximation)*/
272+
QgsAbstractGeometryV2::SegmentationToleranceType segmentationToleranceType() const { return mSegmentationToleranceType; }
273+
262274
protected:
263275

264276
int mDpi;
@@ -285,6 +297,10 @@ class CORE_EXPORT QgsMapSettings
285297

286298
QImage::Format mImageFormat;
287299

300+
double mSegmentationTolerance;
301+
QgsAbstractGeometryV2::SegmentationToleranceType mSegmentationToleranceType;
302+
303+
288304
// derived properties
289305
bool mValid; //!< whether the actual settings are valid (set in updateDerived())
290306
QgsRectangle mVisibleExtent; //!< extent with some additional white space that matches the output aspect ratio

‎src/core/qgsrendercontext.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ QgsRenderContext::QgsRenderContext()
3535
, mLabelingEngine2( nullptr )
3636
, mGeometry( nullptr )
3737
, mFeatureFilterProvider( nullptr )
38+
, mSegmentationTolerance( M_PI_2 / 90 )
39+
, mSegmentationToleranceType( QgsAbstractGeometryV2::MaximumAngle )
3840
{
3941
mVectorSimplifyMethod.setSimplifyHints( QgsVectorSimplifyMethod::NoSimplification );
4042
}
@@ -56,6 +58,8 @@ QgsRenderContext::QgsRenderContext( const QgsRenderContext& rh )
5658
, mExpressionContext( rh.mExpressionContext )
5759
, mGeometry( rh.mGeometry )
5860
, mFeatureFilterProvider( rh.mFeatureFilterProvider ? rh.mFeatureFilterProvider->clone() : nullptr )
61+
, mSegmentationTolerance( rh.mSegmentationTolerance )
62+
, mSegmentationToleranceType( rh.mSegmentationToleranceType )
5963
{
6064
}
6165

@@ -77,6 +81,8 @@ QgsRenderContext&QgsRenderContext::operator=( const QgsRenderContext & rh )
7781
mExpressionContext = rh.mExpressionContext;
7882
mGeometry = rh.mGeometry;
7983
mFeatureFilterProvider = rh.mFeatureFilterProvider ? rh.mFeatureFilterProvider->clone() : nullptr;
84+
mSegmentationTolerance = rh.mSegmentationTolerance;
85+
mSegmentationToleranceType = rh.mSegmentationToleranceType;
8086
return *this;
8187
}
8288

@@ -127,6 +133,8 @@ QgsRenderContext QgsRenderContext::fromMapSettings( const QgsMapSettings& mapSet
127133
ctx.setScaleFactor( mapSettings.outputDpi() / 25.4 ); // = pixels per mm
128134
ctx.setRendererScale( mapSettings.scale() );
129135
ctx.setExpressionContext( mapSettings.expressionContext() );
136+
ctx.setSegmentationTolerance( mapSettings.segmentationTolerance() );
137+
ctx.setSegmentationToleranceType( mapSettings.segmentationToleranceType() );
130138

131139
//this flag is only for stopping during the current rendering progress,
132140
//so must be false at every new render operation

‎src/core/qgsrendercontext.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
#include <QColor>
2222

23+
#include "qgsabstractgeometryv2.h"
2324
#include "qgscoordinatetransform.h"
2425
#include "qgsmaptopixel.h"
2526
#include "qgsrectangle.h"
@@ -219,6 +220,18 @@ class CORE_EXPORT QgsRenderContext
219220
*/
220221
const QgsFeatureFilterProvider* featureFilterProvider() const { return mFeatureFilterProvider; }
221222

223+
/** Sets the segmentation tolerance applied when rendering curved geometries
224+
@param tolerance the segmentation tolerance*/
225+
void setSegmentationTolerance( double tolerance ) { mSegmentationTolerance = tolerance; }
226+
/** Gets the segmentation tolerance applied when rendering curved geometries*/
227+
double segmentationTolerance() const { return mSegmentationTolerance; }
228+
229+
/** Sets segmentation tolerance type (maximum angle or maximum difference between curve and approximation)
230+
@param type the segmentation tolerance typename*/
231+
void setSegmentationToleranceType( QgsAbstractGeometryV2::SegmentationToleranceType type ) { mSegmentationToleranceType = type; }
232+
/** Gets segmentation tolerance type (maximum angle or maximum difference between curve and approximation)*/
233+
QgsAbstractGeometryV2::SegmentationToleranceType segmentationToleranceType() const { return mSegmentationToleranceType; }
234+
222235
private:
223236

224237
Flags mFlags;
@@ -266,6 +279,9 @@ class CORE_EXPORT QgsRenderContext
266279
/** The feature filter provider */
267280
const QgsFeatureFilterProvider* mFeatureFilterProvider;
268281

282+
double mSegmentationTolerance;
283+
284+
QgsAbstractGeometryV2::SegmentationToleranceType mSegmentationToleranceType;
269285
};
270286

271287
Q_DECLARE_OPERATORS_FOR_FLAGS( QgsRenderContext::Flags )

‎src/core/symbology-ng/qgssymbolv2.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -724,7 +724,7 @@ void QgsSymbolV2::renderFeature( const QgsFeature& feature, QgsRenderContext& co
724724
//convert curve types to normal point/line/polygon ones
725725
if ( QgsWKBTypes::isCurvedType( geom->geometry()->wkbType() ) )
726726
{
727-
QgsAbstractGeometryV2 *g = geom->geometry()->segmentize();
727+
QgsAbstractGeometryV2 *g = geom->geometry()->segmentize( context.segmentationTolerance(), context.segmentationToleranceType() );
728728
if ( !g )
729729
{
730730
return;

‎src/gui/qgsmapcanvas.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,13 @@ QgsMapCanvas::QgsMapCanvas( QWidget * parent, const char *name )
240240
mSettings.setFlag( QgsMapSettings::DrawEditingInfo );
241241
mSettings.setFlag( QgsMapSettings::UseRenderingOptimization );
242242

243+
//segmentation parameters
244+
QSettings settings;
245+
double segmentationTolerance = settings.value( "/qgis/segmentationTolerance", "0.01745" ).toDouble();
246+
QgsAbstractGeometryV2::SegmentationToleranceType toleranceType = QgsAbstractGeometryV2::SegmentationToleranceType( settings.value( "/qgis/segmentationToleranceType", 0 ).toInt() );
247+
mSettings.setSegmentationTolerance( segmentationTolerance );
248+
mSettings.setSegmentationToleranceType( toleranceType );
249+
243250
// class that will sync most of the changes between canvas and (legacy) map renderer
244251
// it is parented to map canvas, will be deleted automatically
245252
new QgsMapCanvasRendererSync( this, mMapRenderer );
@@ -2093,3 +2100,13 @@ void QgsMapCanvas::refreshAllLayers()
20932100
// and then refresh
20942101
refresh();
20952102
}
2103+
2104+
void QgsMapCanvas::setSegmentationTolerance( double tolerance )
2105+
{
2106+
mSettings.setSegmentationTolerance( tolerance );
2107+
}
2108+
2109+
void QgsMapCanvas::setSegmentationToleranceType( QgsAbstractGeometryV2::SegmentationToleranceType type )
2110+
{
2111+
mSettings.setSegmentationToleranceType( type );
2112+
}

‎src/gui/qgsmapcanvas.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,13 @@ class GUI_EXPORT QgsMapCanvas : public QGraphicsView
462462
*/
463463
const QgsExpressionContextScope& expressionContextScope() const { return mExpressionContextScope; }
464464

465+
/** Sets the segmentation tolerance applied when rendering curved geometries
466+
@param tolerance the segmentation tolerance*/
467+
void setSegmentationTolerance( double tolerance );
468+
/** Sets segmentation tolerance type (maximum angle or maximum difference between curve and approximation)
469+
@param type the segmentation tolerance typename*/
470+
void setSegmentationToleranceType( QgsAbstractGeometryV2::SegmentationToleranceType type );
471+
465472
public slots:
466473

467474
/** Repaints the canvas map*/

‎src/ui/qgsoptionsbase.ui

Lines changed: 85 additions & 263 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)
Please sign in to comment.