30 : QPaintEngine( QPaintEngine::AllFeatures )
31 , mUsePathStroker( usePathStroker )
37 mStrokedPathsSegments = segments;
42 mSimplifyTolerance = tolerance;
57 return QPaintEngine::User;
62 if ( mUsePathStroker && state.state().testFlag( QPaintEngine::DirtyFlag::DirtyPen ) )
71 QgsDebugError( QStringLiteral(
"QgsGeometryPaintEngine does not support drawImage method" ) );
77 QgsDebugError( QStringLiteral(
"QgsGeometryPaintEngine does not support drawPixmap method" ) );
83 QgsDebugError( QStringLiteral(
"QgsGeometryPaintEngine does not support drawTiledPixmap method" ) );
90 if ( transform.isIdentity() )
92 for (
int i = 0; i < lineCount; ++i, ++lines )
95 QVector<double> {
static_cast< double >( lines->x1() ),
static_cast< double >( lines->x2() ) },
96 QVector<double> {
static_cast< double >( lines->y1() ),
static_cast< double >( lines->y2() ) } )
102 for (
int i = 0; i < lineCount; ++i, ++lines )
104 double x1 = lines->x1();
105 double x2 = lines->x2();
106 double y1 = lines->y1();
107 double y2 = lines->y2();
109 double tx1, tx2, ty1, ty2;
110 transform.map( x1, y1, &tx1, &ty1 );
111 transform.map( x2, y2, &tx2, &ty2 );
114 QVector<double> { tx1, tx2 },
115 QVector<double> { ty1, ty2 } )
123 if ( mUsePathStroker )
126 QPaintEngine::drawLines( lines, lineCount );
130 const QTransform transform = painter()->combinedTransform();
137 if ( mUsePathStroker )
140 QPaintEngine::drawLines( lines, lineCount );
144 const QTransform transform = painter()->combinedTransform();
153 if ( transform.isIdentity() )
155 for (
int i = 0; i < pointCount; ++i, ++points )
158 static_cast< double >( points->y() ) ) );
163 for (
int i = 0; i < pointCount; ++i, ++points )
165 double x = points->x();
166 double y = points->y();
169 transform.map( x, y, &tx, &ty );
178 const QTransform transform = painter()->combinedTransform();
184 const QTransform transform = painter()->combinedTransform();
192 if ( transform.isIdentity() )
194 for (
int i = 0; i < rectCount; ++i, ++rects )
197 QVector<double> {
static_cast< double >( rects->left() ),
198 static_cast< double >( rects->right() ),
199 static_cast< double >( rects->right() ),
200 static_cast< double >( rects->left() ),
201 static_cast< double>( rects->left() )
203 QVector<double> {
static_cast< double >( rects->bottom() ),
204 static_cast< double >( rects->bottom() ),
205 static_cast< double >( rects->top() ),
206 static_cast< double >( rects->top() ),
207 static_cast< double >( rects->bottom() )
214 for (
int i = 0; i < rectCount; ++i, ++rects )
216 const double left = rects->left();
217 const double right = rects->right();
218 const double top = rects->top();
219 const double bottom = rects->bottom();
221 double bottomLeftX, bottomLeftY, bottomRightX, bottomRightY, topLeftX, topLeftY, topRightX, topRightY;
222 transform.map( left, bottom, &bottomLeftX, &bottomLeftY );
223 transform.map( right, bottom, &bottomRightX, &bottomRightY );
224 transform.map( left, top, &topLeftX, &topLeftY );
225 transform.map( right, top, &topRightX, &topRightY );
228 QVector<double> { bottomLeftX, bottomRightX, topRightX, topLeftX, bottomLeftX },
229 QVector<double> { bottomLeftY, bottomRightY, topRightY, topLeftY, bottomLeftY } );
237 const QTransform transform = painter()->combinedTransform();
243 const QTransform transform = painter()->combinedTransform();
252 x.resize( pointCount );
253 y.resize( pointCount );
254 double *xData = x.data();
255 double *yData = y.data();
257 if ( transform.isIdentity() )
259 for (
int i = 0; i < pointCount; ++i, ++points )
261 *xData++ = points->x();
262 *yData++ = points->y();
267 for (
int i = 0; i < pointCount; ++i, ++points )
269 const double x = points->x();
270 const double y = points->y();
272 transform.map( x, y, &tx, &ty );
281 case QPaintEngine::PolylineMode:
282 if ( simplifyTolerance > 0 )
288 case QPaintEngine::OddEvenMode:
289 case QPaintEngine::WindingMode:
290 case QPaintEngine::ConvexMode:
291 if ( simplifyTolerance > 0 )
301 if ( mUsePathStroker && mode == PolygonDrawMode::PolylineMode )
304 if ( pointCount > 0 )
307 path.moveTo( *points++ );
308 for (
int i = 1; i < pointCount; ++i )
310 path.lineTo( *points++ );
317 const QTransform transform = painter()->combinedTransform();
318 drawPolygonImp( transform, mGeometry, points, pointCount, mode, mSimplifyTolerance );
324 if ( mUsePathStroker )
327 if ( pointCount > 0 )
330 path.moveTo( *points++ );
331 for (
int i = 1; i < pointCount; ++i )
333 path.lineTo( *points++ );
340 const QTransform transform = painter()->combinedTransform();
341 drawPolygonImp( transform, mGeometry, points, pointCount, mode, mSimplifyTolerance );
347 std::unique_ptr< QgsAbstractGeometry > buffered;
348 if ( mSimplifyTolerance > 0 )
355 const double preBufferedSimplificationFactor = mSimplifyTolerance * 0.75;
356 std::unique_ptr< QgsLineString > simplified( line->
simplifyByDistance( preBufferedSimplificationFactor ) );
358 buffered.reset(
geos.buffer( penWidth / 2, mStrokedPathsSegments, endCapStyle, joinStyle, miterLimit ) );
363 buffered.reset(
geos.buffer( penWidth / 2, mStrokedPathsSegments, endCapStyle, joinStyle, miterLimit ) );
370 buffered->transform( *matrix );
372 if (
QgsGeometryCollection *bufferedCollection = qgsgeometry_cast< QgsGeometryCollection * >( buffered.get() ) )
374 if ( mSimplifyTolerance > 0 )
376 for (
auto it = bufferedCollection->const_parts_begin(); it != bufferedCollection->const_parts_end(); ++it )
378 mGeometry.
addGeometry( ( *it )->simplifyByDistance( mSimplifyTolerance ) );
383 mGeometry.
addGeometries( bufferedCollection->takeGeometries() );
388 if ( mSimplifyTolerance > 0 )
390 mGeometry.
addGeometry( buffered->simplifyByDistance( mSimplifyTolerance ) );
400void QgsGeometryPaintEngine::addSubpathGeometries(
const QPainterPath &path,
const QTransform &matrix )
402 if ( path.isEmpty() )
405 const bool transformIsIdentity = matrix.isIdentity();
409 const double penWidth = mPen.widthF() <= 0 ? 1 : mPen.widthF();
410 const double miterLimit = mPen.miterLimit();
412 QVector< double > currentX;
413 QVector< double > currentY;
414 const int count = path.elementCount();
417 std::vector< std::unique_ptr< QgsPolygon > > queuedPolygons;
419 for (
int i = 0; i < count; ++i )
421 const QPainterPath::Element &e = path.elementAt( i );
424 case QPainterPath::MoveToElement:
426 if ( currentX.size() > 1 )
428 auto line = std::make_unique< QgsLineString >( currentX, currentY );
429 if ( mUsePathStroker )
431 addStrokedLine( line.get(), penWidth, endCapStyle, joinStyle, miterLimit, transformIsIdentity ?
nullptr : &matrix );
435 if ( !transformIsIdentity )
438 if ( mSimplifyTolerance > 0 )
440 queuedPolygons.emplace_back( std::make_unique< QgsPolygon >( line->
simplifyByDistance( mSimplifyTolerance ) ) );
445 queuedPolygons.emplace_back( std::make_unique< QgsPolygon >( line.release() ) );
450 if ( !transformIsIdentity )
452 if ( mSimplifyTolerance > 0 )
463 currentX.resize( 0 );
464 currentY.resize( 0 );
466 currentX.reserve( 16 );
467 currentY.reserve( 16 );
473 case QPainterPath::LineToElement:
480 case QPainterPath::CurveToElement:
482 Q_ASSERT( path.elementAt( i + 1 ).type == QPainterPath::CurveToDataElement );
483 Q_ASSERT( path.elementAt( i + 2 ).type == QPainterPath::CurveToDataElement );
485 const double x1 = path.elementAt( i - 1 ).x;
486 const double y1 = path.elementAt( i - 1 ).y;
488 const double x3 = path.elementAt( i + 1 ).x;
489 const double y3 = path.elementAt( i + 1 ).y;
491 const double x4 = path.elementAt( i + 2 ).x;
492 const double y4 = path.elementAt( i + 2 ).y;
501 currentX << bezier->xVector();
502 currentY << bezier->yVector();
507 case QPainterPath::CurveToDataElement:
508 Q_ASSERT( !
"addSubpathGeometries(), bad element type" );
513 if ( currentX.size() > 1 )
515 auto line = std::make_unique< QgsLineString >( currentX, currentY );
516 if ( mUsePathStroker )
518 addStrokedLine( line.get(), penWidth, endCapStyle, joinStyle, miterLimit, transformIsIdentity ?
nullptr : &matrix );
522 if ( !transformIsIdentity )
524 if ( mSimplifyTolerance > 0 )
526 queuedPolygons.emplace_back( std::make_unique< QgsPolygon >( line->
simplifyByDistance( mSimplifyTolerance ) ) );
531 queuedPolygons.emplace_back( std::make_unique< QgsPolygon >( line.release() ) );
536 if ( !transformIsIdentity )
538 if ( mSimplifyTolerance > 0 )
550 if ( queuedPolygons.empty() )
556 tempMultiPolygon.
reserve(
static_cast< int >( queuedPolygons.size() ) );
557 for (
auto &part : queuedPolygons )
563 QgsGeos geosCollection( &tempMultiPolygon );
568 for (
auto it = g->const_parts_begin(); it != g->const_parts_end(); ++it )
576 const QTransform transform = painter()->combinedTransform();
577 addSubpathGeometries( path, transform );
587 mPaintEngine = std::make_unique<QgsGeometryPaintEngine>( usePathStroker );
593 mPaintEngine->setStrokedPathSegments( segments );
599 mPaintEngine->setSimplificationTolerance( tolerance );
604 return mPaintEngine.get();
615 val =
static_cast< int >( mPaintEngine->geometry().boundingBox().width() );
618 val =
static_cast< int >( mPaintEngine->geometry().boundingBox().height() );
627 case PdmPhysicalDpiX:
631 case PdmPhysicalDpiY:
640 case PdmDevicePixelRatio:
643 case PdmDevicePixelRatioScaled:
644 val =
static_cast< int >( 1 * QPaintDevice::devicePixelRatioFScale() );
648 qWarning(
"QPicture::metric: Invalid metric command" );
655 return mPaintEngine->geometry();
661 QPainter painter( &device );
662 painter.drawPath( path );
JoinStyle
Join styles for buffers.
EndCapStyle
End cap styles for buffers.
@ Linework
Combines all rings into a set of noded lines and then extracts valid polygons from that linework.
Abstract base class for all geometries.
virtual QgsAbstractGeometry * clone() const =0
Clones the geometry by performing a deep copy.
void reserve(int size)
Attempts to allocate memory for at least size geometries.
virtual bool addGeometries(const QVector< QgsAbstractGeometry * > &geometries)
Adds a list of geometries to the collection, transferring ownership to the collection.
virtual bool addGeometry(QgsAbstractGeometry *g)
Adds a geometry and takes ownership. Returns true in case of success.
int numGeometries() const
Returns the number of geometries within the collection.
A paint device which converts everything renderer to a QgsGeometry representation of the rendered sha...
QgsGeometryPaintDevice(bool usePathStroker=false)
Constructor for QgsGeometryPaintDevice.
void setStrokedPathSegments(int segments)
Sets the number of segments to use when drawing stroked paths with a rounded pen.
int metric(PaintDeviceMetric metric) const override
void setSimplificationTolerance(double tolerance)
Sets a simplification tolerance (in painter units) to use for on-the-fly simplification of geometries...
QPaintEngine * paintEngine() const override
static QgsGeometry painterPathToGeometry(const QPainterPath &path)
Converts a painter path to a QgsGeometry.
const QgsAbstractGeometry & geometry() const
Returns the rendered geometry.
void setSimplificationTolerance(double tolerance)
Sets a simplification tolerance (in painter units) to use for on-the-fly simplification of geometries...
void drawImage(const QRectF &rectangle, const QImage &image, const QRectF &sr, Qt::ImageConversionFlags flags=Qt::AutoColor) final
void drawRects(const QRectF *rects, int rectCount) final
void drawPolygon(const QPointF *points, int pointCount, QPaintEngine::PolygonDrawMode mode) final
void drawPixmap(const QRectF &, const QPixmap &, const QRectF &) final
void drawPoints(const QPointF *points, int pointCount) final
bool begin(QPaintDevice *) final
QgsGeometryPaintEngine(bool usePathStroker=false)
Constructor for QgsGeometryPaintEngine.
void drawLines(const QLineF *lines, int lineCount) final
QPaintEngine::Type type() const final
void drawTiledPixmap(const QRectF &rect, const QPixmap &pixmap, const QPointF &p) final
void updateState(const QPaintEngineState &) final
void drawPath(const QPainterPath &path) final
void setStrokedPathSegments(int segments)
Sets the number of segments to use when drawing stroked paths with a rounded pen.
A geometry is the spatial representation of a feature.
Does vector analysis using the GEOS library and handles import, export, and exception handling.
Line string geometry type, with support for z-dimension and m-values.
static std::unique_ptr< QgsLineString > fromBezierCurve(const QgsPoint &start, const QgsPoint &controlPoint1, const QgsPoint &controlPoint2, const QgsPoint &end, int segments=30)
Returns a new linestring created by segmentizing the bezier curve between start and end,...
bool isClosed() const override
Returns true if the curve is closed.
QgsLineString * simplifyByDistance(double tolerance) const override
Simplifies the geometry by applying the Douglas Peucker simplification by distance algorithm.
void transform(const QgsCoordinateTransform &ct, Qgis::TransformDirection d=Qgis::TransformDirection::Forward, bool transformZ=false) override
Transforms the geometry using a coordinate transform.
Multi polygon geometry collection.
bool addGeometry(QgsAbstractGeometry *g) override
Adds a geometry and takes ownership. Returns true in case of success.
static int qtDefaultDpiY()
Returns the default Qt vertical DPI.
static int qtDefaultDpiX()
Returns the default Qt horizontal DPI.
Point geometry type, with support for z-dimension and m-values.
static Qgis::EndCapStyle penCapStyleToEndCapStyle(Qt::PenCapStyle style)
Converts a Qt pen cap style to a QGIS end cap style.
static Qgis::JoinStyle penJoinStyleToJoinStyle(Qt::PenJoinStyle style)
Converts a Qt pen joinstyle to a QGIS join style.
Contains geos related utilities and functions.
void drawPointsImp(const QTransform &transform, QgsGeometryCollection &geometry, const T *points, int pointCount)
void drawRectsImp(const QTransform &transform, QgsGeometryCollection &geometry, const T *rects, int rectCount)
void drawLinesImp(const QTransform &transform, QgsGeometryCollection &geometry, const T *lines, int lineCount)
void drawPolygonImp(const QTransform &transform, QgsGeometryCollection &geometry, const T *points, int pointCount, QPaintEngine::PolygonDrawMode mode, double simplifyTolerance)
#define QgsDebugError(str)