Skip to content
Permalink
Browse files
Use proper arcs when converting geometries to painter paths
  • Loading branch information
nyalldawson committed Nov 16, 2021
1 parent eb223fd commit 0cfee7f0338d7f0e2ce68ef333b2f75ef4661da1
Showing with 25 additions and 27 deletions.
  1. +14 −24 src/core/geometry/qgscircularstring.cpp
  2. +9 −0 src/core/geometry/qgscompoundcurve.cpp
  3. +2 −3 tests/src/python/test_qgsgeometry.py
  4. BIN tests/testdata/control_images/geometry/expected_circularstring/expected_circularstring_mask.png
  5. BIN tests/testdata/control_images/geometry/expected_compoundcurve/expected_compoundcurve_mask.png
  6. BIN ...ontrol_images/geometry/expected_compoundcurve_aspolygon/expected_compoundcurve_aspolygon_mask.png
  7. BIN .../testdata/control_images/geometry_path/expected_circular_string/expected_circular_string_mask.png
  8. BIN ...es/geometry_path/expected_collection_circular_string/expected_collection_circular_string_mask.png
  9. BIN ...ages/geometry_path/expected_collection_compound_curve/expected_collection_compound_curve_mask.png
  10. BIN ...images/geometry_path/expected_collection_curve_polygon/expected_collection_curve_polygon_mask.png
  11. BIN tests/testdata/control_images/geometry_path/expected_compound_curve/expected_compound_curve_mask.png
  12. BIN ...l_images/geometry_path/expected_compoundcurve_with_line/expected_compoundcurve_with_line_mask.png
  13. BIN tests/testdata/control_images/geometry_path/expected_curve_polygon/expected_curve_polygon_mask.png
  14. BIN ...epolygon_circularstring_interiorrings/expected_curvepolygon_circularstring_interiorrings_mask.png
  15. BIN tests/testdata/control_images/geometry_path/expected_multicurve/expected_multicurve_mask.png
  16. BIN ...eometry_path/expected_multicurvepolygon_with_rings/expected_multicurvepolygon_with_rings_mask.png
@@ -1156,6 +1156,19 @@ void QgsCircularString::transform( const QTransform &t, double zTranslate, doubl
}
}

void arcTo( QPainterPath &path, QPointF pt1, QPointF pt2, QPointF pt3 )
{
double centerX, centerY, radius;
QgsGeometryUtils::circleCenterRadius( QgsPoint( pt1.x(), pt1.y() ), QgsPoint( pt2.x(), pt2.y() ), QgsPoint( pt3.x(), pt3.y() ),
radius, centerX, centerY );

double p1Angle = QgsGeometryUtils::ccwAngle( pt1.y() - centerY, pt1.x() - centerX );
double sweepAngle = QgsGeometryUtils::sweepAngle( centerX, centerY, pt1.x(), pt1.y(), pt2.x(), pt2.y(), pt3.x(), pt3.y() );

double diameter = 2 * radius;
path.arcTo( centerX - radius, centerY - radius, diameter, diameter, -p1Angle, -sweepAngle );
}

void QgsCircularString::addToPainterPath( QPainterPath &path ) const
{
int nPoints = numPoints();
@@ -1171,15 +1184,7 @@ void QgsCircularString::addToPainterPath( QPainterPath &path ) const

for ( int i = 0; i < ( nPoints - 2 ) ; i += 2 )
{
QgsPointSequence pt;
QgsGeometryUtils::segmentizeArc( QgsPoint( mX[i], mY[i] ), QgsPoint( mX[i + 1], mY[i + 1] ), QgsPoint( mX[i + 2], mY[i + 2] ), pt );
for ( int j = 1; j < pt.size(); ++j )
{
path.lineTo( pt.at( j ).x(), pt.at( j ).y() );
}
#if 0
//arcTo( path, QPointF( mX[i], mY[i] ), QPointF( mX[i + 1], mY[i + 1] ), QPointF( mX[i + 2], mY[i + 2] ) );
#endif
arcTo( path, QPointF( mX[i], mY[i] ), QPointF( mX[i + 1], mY[i + 1] ), QPointF( mX[i + 2], mY[i + 2] ) );
}

//if number of points is even, connect to last point with straight line (even though the circular string is not valid)
@@ -1189,21 +1194,6 @@ void QgsCircularString::addToPainterPath( QPainterPath &path ) const
}
}

#if 0
void QgsCircularString::arcTo( QPainterPath &path, QPointF pt1, QPointF pt2, QPointF pt3 )
{
double centerX, centerY, radius;
QgsGeometryUtils::circleCenterRadius( QgsPoint( pt1.x(), pt1.y() ), QgsPoint( pt2.x(), pt2.y() ), QgsPoint( pt3.x(), pt3.y() ),
radius, centerX, centerY );

double p1Angle = QgsGeometryUtils::ccwAngle( pt1.y() - centerY, pt1.x() - centerX );
double sweepAngle = QgsGeometryUtils::sweepAngle( centerX, centerY, pt1.x(), pt1.y(), pt2.x(), pt2.y(), pt3.x(), pt3.y() );

double diameter = 2 * radius;
path.arcTo( centerX - radius, centerY - radius, diameter, diameter, p1Angle, sweepAngle );
}
#endif

void QgsCircularString::drawAsPolygon( QPainter &p ) const
{
draw( p );
@@ -727,8 +727,13 @@ void QgsCompoundCurve::transform( const QTransform &t, double zTranslate, double
void QgsCompoundCurve::addToPainterPath( QPainterPath &path ) const
{
QPainterPath pp;

for ( const QgsCurve *curve : mCurves )
{
if ( curve != mCurves.at( 0 ) && pp.currentPosition() != curve->startPoint().toQPointF() )
{
pp.lineTo( curve->startPoint().toQPointF() );
}
curve->addToPainterPath( pp );
}
path.addPath( pp );
@@ -739,6 +744,10 @@ void QgsCompoundCurve::drawAsPolygon( QPainter &p ) const
QPainterPath pp;
for ( const QgsCurve *curve : mCurves )
{
if ( curve != mCurves.at( 0 ) && pp.currentPosition() != curve->startPoint().toQPointF() )
{
pp.lineTo( curve->startPoint().toQPointF() );
}
curve->addToPainterPath( pp );
}
p.drawPath( pp );
@@ -6734,7 +6734,7 @@ def testGeometryDraw(self):
geom = QgsGeometry.fromWkt(test['wkt'])
self.assertTrue(geom and not geom.isNull(), 'Could not create geometry {}'.format(test['wkt']))
rendered_image = self.renderGeometry(geom, test['use_pen'])
assert self.imageCheck(test['name'], test['reference_image'], rendered_image)
self.assertTrue(self.imageCheck(test['name'], test['reference_image'], rendered_image), test['name'])

if hasattr(geom.constGet(), 'addToPainterPath'):
# also check using painter path
@@ -6743,11 +6743,10 @@ def testGeometryDraw(self):

if 'as_polygon_reference_image' in test:
rendered_image = self.renderGeometry(geom, False, True)
assert self.imageCheck(test['name'] + '_aspolygon', test['as_polygon_reference_image'], rendered_image)
self.assertTrue(self.imageCheck(test['name'] + '_aspolygon', test['as_polygon_reference_image'], rendered_image), test['name'] + '_aspolygon')

def testGeometryAsQPainterPath(self):
'''Tests conversion of different geometries to QPainterPath, including bad/odd geometries.'''

empty_multipolygon = QgsMultiPolygon()
empty_multipolygon.addGeometry(QgsPolygon())
empty_polygon = QgsPolygon()
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

0 comments on commit 0cfee7f

Please sign in to comment.