27 #include <QSvgRenderer> 29 #include <QGraphicsPathItem> 35 createDefaultPolylineStyleSymbol();
41 createDefaultPolylineStyleSymbol();
66 if ( indexPoint == (
mPolygon.size() - 1 ) )
68 if ( distEnd < radius )
70 else if ( distStart < radius )
74 mPolygon.insert( indexPoint + 1, newPoint );
81 if ( index < 0 || index >=
mPolygon.size() )
90 int newSelectNode = index;
99 void QgsLayoutItemPolyline::createDefaultPolylineStyleSymbol()
102 properties.insert( QStringLiteral(
"color" ), QStringLiteral(
"0,0,0,255" ) );
103 properties.insert( QStringLiteral(
"width" ), QStringLiteral(
"0.3" ) );
104 properties.insert( QStringLiteral(
"capstyle" ), QStringLiteral(
"square" ) );
110 void QgsLayoutItemPolyline::refreshSymbol()
123 void QgsLayoutItemPolyline::drawStartMarker( QPainter *painter )
128 switch ( mStartMarker )
130 case MarkerMode::NoMarker:
133 case MarkerMode::ArrowHead:
137 double angle = startLine.angle();
142 case MarkerMode::SvgMarker:
146 double angle = startLine.angle();
147 drawSvgMarker( painter,
mPolygon.at( 0 ),
angle, mStartMarkerFile, mStartArrowHeadHeight );
154 void QgsLayoutItemPolyline::drawEndMarker( QPainter *painter )
159 switch ( mEndMarker )
161 case MarkerMode::NoMarker:
164 case MarkerMode::ArrowHead:
168 double angle = endLine.angle();
171 QVector2D dir = QVector2D( endLine.dx(), endLine.dy() ).normalized();
172 QPointF endPoint = endLine.p2();
173 endPoint += ( dir * 0.5 * mArrowHeadWidth ).toPointF();
175 drawArrow( painter, endPoint, angle );
178 case MarkerMode::SvgMarker:
182 double angle = endLine.angle();
183 drawSvgMarker( painter, endLine.p2(),
angle, mEndMarkerFile, mEndArrowHeadHeight );
189 void QgsLayoutItemPolyline::drawArrow( QPainter *painter, QPointF center,
double angle )
194 p.setColor( mArrowHeadStrokeColor );
195 p.setWidthF( mArrowHeadStrokeWidth );
196 painter->setPen( p );
198 b.setColor( mArrowHeadFillColor );
199 painter->setBrush( b );
201 drawArrowHead( painter, center.x(), center.y(),
angle, mArrowHeadWidth );
204 void QgsLayoutItemPolyline::updateMarkerSvgSizes()
210 void QgsLayoutItemPolyline::drawArrowHead( QPainter *p,
const double x,
const double y,
const double angle,
const double arrowHeadWidth )
215 double angleRad =
angle / 180.0 * M_PI;
216 QPointF middlePoint( x, y );
219 QPointF p1 = QPointF( -arrowHeadWidth / 2.0, arrowHeadWidth );
220 QPointF p2 = QPointF( arrowHeadWidth / 2.0, arrowHeadWidth );
222 QPointF p1Rotated, p2Rotated;
223 p1Rotated.setX( p1.x() * std::cos( angleRad ) + p1.y() * -std::sin( angleRad ) );
224 p1Rotated.setY( p1.x() * std::sin( angleRad ) + p1.y() * std::cos( angleRad ) );
225 p2Rotated.setX( p2.x() * std::cos( angleRad ) + p2.y() * -std::sin( angleRad ) );
226 p2Rotated.setY( p2.x() * std::sin( angleRad ) + p2.y() * std::cos( angleRad ) );
228 QPolygonF arrowHeadPoly;
229 arrowHeadPoly << middlePoint;
230 arrowHeadPoly << QPointF( middlePoint.x() + p1Rotated.x(), middlePoint.y() + p1Rotated.y() );
231 arrowHeadPoly << QPointF( middlePoint.x() + p2Rotated.x(), middlePoint.y() + p2Rotated.y() );
232 QPen arrowPen = p->pen();
233 arrowPen.setJoinStyle( Qt::RoundJoin );
234 QBrush arrowBrush = p->brush();
235 arrowBrush.setStyle( Qt::SolidPattern );
236 p->setPen( arrowPen );
237 p->setBrush( arrowBrush );
238 arrowBrush.setStyle( Qt::SolidPattern );
239 p->drawPolygon( arrowHeadPoly );
242 void QgsLayoutItemPolyline::drawSvgMarker( QPainter *p, QPointF point,
double angle,
const QString &markerPath,
double height )
const 247 if ( mArrowHeadWidth <= 0 || height <= 0 )
253 if ( markerPath.isEmpty() )
257 const QByteArray &svgContent =
QgsApplication::svgCache()->
svgContent( markerPath, mArrowHeadWidth, mArrowHeadFillColor, mArrowHeadStrokeColor, mArrowHeadStrokeWidth,
259 r.load( svgContent );
262 p->translate( point.x(), point.y() );
264 p->translate( -mArrowHeadWidth / 2.0, -height / 2.0 );
265 r.render( p, QRectF( 0, 0, mArrowHeadWidth, height ) );
271 if ( !
id().isEmpty() )
274 return tr(
"<Polyline>" );
282 QTransform t = QTransform::fromScale( scale, scale );
284 mPolylineStyleSymbol->startRender( context.
renderContext() );
298 mPolylineStyleSymbol.reset( QgsSymbolLayerUtils::loadSymbol<QgsLineSymbol>( elmt, context ) );
303 mPolylineStyleSymbol.reset( static_cast<QgsLineSymbol *>( symbol->
clone() ) );
321 mArrowHeadWidth = width;
322 updateMarkerSvgSizes();
331 QPainterPathStroker ps;
334 QPainterPath strokedOutline = ps.createStroke( path );
336 return strokedOutline;
342 mStartMarkerFile = path;
343 if ( path.isEmpty() || !r.load( path ) )
345 mStartArrowHeadHeight = 0;
350 QRect viewBox = r.viewBox();
351 mStartArrowHeadHeight = mArrowHeadWidth / viewBox.width() * viewBox.height();
359 mEndMarkerFile = path;
360 if ( path.isEmpty() || !r.load( path ) )
362 mEndArrowHeadHeight = 0;
367 QRect viewBox = r.viewBox();
368 mEndArrowHeadHeight = mArrowHeadWidth / viewBox.width() * viewBox.height();
375 mArrowHeadStrokeColor = color;
381 mArrowHeadFillColor = color;
387 mArrowHeadStrokeWidth = width;
394 if ( mPolylineStyleSymbol )
407 mPolylineStyleSymbol.get(),
410 elmt.appendChild( pe );
421 elmt.setAttribute( QStringLiteral(
"arrowHeadWidth" ), QString::number( mArrowHeadWidth ) );
424 elmt.setAttribute( QStringLiteral(
"outlineWidth" ), QString::number( mArrowHeadStrokeWidth ) );
425 elmt.setAttribute( QStringLiteral(
"markerMode" ), mEndMarker );
426 elmt.setAttribute( QStringLiteral(
"startMarkerMode" ), mStartMarker );
427 elmt.setAttribute( QStringLiteral(
"startMarkerFile" ), startMarkerPath );
428 elmt.setAttribute( QStringLiteral(
"endMarkerFile" ), endMarkerPath );
435 mArrowHeadWidth = elmt.attribute( QStringLiteral(
"arrowHeadWidth" ), QStringLiteral(
"2.0" ) ).toDouble();
438 mArrowHeadStrokeWidth = elmt.attribute( QStringLiteral(
"outlineWidth" ), QStringLiteral(
"1.0" ) ).toDouble();
440 QString startMarkerPath = elmt.attribute( QStringLiteral(
"startMarkerFile" ), QString() );
441 QString endMarkerPath = elmt.attribute( QStringLiteral(
"endMarkerFile" ), QString() );
460 margin += 0.5 * mArrowHeadWidth;
462 br.adjust( -margin, -margin, margin, margin );
466 prepareGeometryChange();
471 double QgsLayoutItemPolyline::computeMarkerMargin()
const 477 margin = mArrowHeadStrokeWidth / 2.0 + mArrowHeadWidth * M_SQRT2;
482 double startMarkerMargin = std::sqrt( 0.25 * ( mStartArrowHeadHeight * mStartArrowHeadHeight + mArrowHeadWidth * mArrowHeadWidth ) );
483 margin = std::max( startMarkerMargin, margin );
488 double endMarkerMargin = std::sqrt( 0.25 * ( mEndArrowHeadHeight * mEndArrowHeadHeight + mArrowHeadWidth * mArrowHeadWidth ) );
489 margin = std::max( endMarkerMargin, margin );
double arrowHeadWidth() const
Returns the width of line arrow heads in mm.
double computeDistance(QPointF pt1, QPointF pt2) const
Compute an euclidian distance between 2 nodes.
The class is used as a container of context for various read/write operations on other objects...
static QgsSvgCache * svgCache()
Returns the application's SVG cache, used for caching SVG images and handling parameter replacement w...
void setStartMarker(MarkerMode mode)
Sets the start marker mode, which controls what marker is drawn at the start of the line...
void updateSceneRect()
Update the current scene rectangle for this item.
A symbol entity for QgsStyle databases.
bool _removeNode(int nodeIndex) override
Method called in removeNode.
bool readPropertiesFromElement(const QDomElement &element, const QDomDocument &document, const QgsReadWriteContext &context) override
Sets item state from a DOM element.
void setArrowHeadWidth(double width)
Sets the width of line arrow heads in mm.
void _writeXmlStyle(QDomDocument &doc, QDomElement &elmt, const QgsReadWriteContext &context) const override
Method called in writeXml.
QRectF mCurrentRectangle
Current bounding rectangle of shape.
void setArrowHeadFillColor(const QColor &color)
Sets the color used to fill the arrow head.
static QgsLineSymbol * createSimple(const QgsStringMap &properties)
Create a line symbol with one symbol layer: SimpleLine with specified properties. ...
void setStartSvgMarkerPath(const QString &path)
Sets the path to a SVG marker to draw at the start of the line.
MarkerMode
Vertex marker mode.
An abstract layout item that provides generic methods for node based shapes such as polygon or polyli...
QString displayName() const override
Gets item display name.
double mMaxSymbolBleed
Max symbol bleed.
QPainterPath shape() const override
void setEndSvgMarkerPath(const QString &path)
Sets the path to a SVG marker to draw at the end of the line.
bool writePropertiesToElement(QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context) const override
Stores item state within an XML DOM element.
static QIcon getThemeIcon(const QString &name)
Helper to get a theme icon.
static QDomElement saveSymbol(const QString &symbolName, const QgsSymbol *symbol, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a symbol definition to XML.
QPolygonF mPolygon
Shape's nodes.
An interface for classes which can visit style entity (e.g.
void updateBoundingRect() override
QByteArray svgContent(const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth, double widthScaleFactor, double fixedAspectRatio=0, bool blocking=false)
Gets SVG content.
QgsLayoutRenderContext & renderContext()
Returns a reference to the layout's render context, which stores information relating to the current ...
QMap< QString, QString > QgsStringMap
bool _addNode(int indexPoint, QPointF newPoint, double radius) override
Method called in addNode.
double ANALYSIS_EXPORT angle(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
void setSymbol(QgsLineSymbol *symbol)
Sets the symbol used to draw the shape.
A line symbol type, for rendering LineString and MultiLineString geometries.
virtual bool visit(const QgsStyleEntityVisitorInterface::StyleLeaf &entity)
Called when the visitor will visit a style entity.
static QString encodeColor(const QColor &color)
int type() const override
QgsLineSymbol * symbol()
Returns the line symbol used to draw the shape.
void _readXmlStyle(const QDomElement &elmt, const QgsReadWriteContext &context) override
Method called in readXml.
void setArrowHeadStrokeColor(const QColor &color)
Sets the color used to draw the stroke around the arrow head.
void setEndMarker(MarkerMode mode)
Sets the end marker mode, which controls what marker is drawn at the end of the line.
void frameChanged()
Emitted if the item's frame style changes.
static QString svgSymbolPathToName(const QString &path, const QgsPathResolver &pathResolver)
Determines an SVG symbol's name from its path.
void setArrowHeadStrokeWidth(double width)
Sets the pen width in millimeters for the stroke of the arrow head.
Layout item for node based polyline shapes.
QIcon icon() const override
Returns the item's icon.
const QgsLayout * layout() const
Returns the layout the object is attached to.
double dpi() const
Returns the dpi for outputting the layout.
QgsRenderContext & renderContext()
Returns a reference to the context's render context.
bool readPropertiesFromElement(const QDomElement &element, const QDomDocument &document, const QgsReadWriteContext &context) override
Sets item state from a DOM element.
static QgsRenderContext createRenderContextForLayout(QgsLayout *layout, QPainter *painter, double dpi=-1)
Creates a render context suitable for the specified layout and painter destination.
static double estimateMaxSymbolBleed(QgsSymbol *symbol, const QgsRenderContext &context)
Returns the maximum estimated bleed for the symbol.
QString id() const
Returns the item's ID name.
Base class for layouts, which can contain items such as maps, labels, scalebars, etc.
void _draw(QgsLayoutItemRenderContext &context, const QStyleOptionGraphicsItem *itemStyle=nullptr) override
Method called in paint.
static QgsLayoutItemPolyline * create(QgsLayout *layout)
Returns a new polyline item for the specified layout.
bool setSelectedNode(int index)
Selects a node by index.
Contains settings and helpers relating to a render of a QgsLayoutItem.
const QgsPathResolver & pathResolver() const
Returns path resolver for conversion between relative and absolute paths.
bool accept(QgsStyleEntityVisitorInterface *visitor) const override
Accepts the specified style entity visitor, causing it to visit all style entities associated with th...
Contains information about the context of a rendering operation.
double convertToPainterUnits(double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale()) const
Converts a size from the specified units to painter units (pixels).
QPainter * painter()
Returns the destination QPainter for the render operation.
virtual QString uuid() const
Returns the item identification string.
QgsLayoutItemPolyline(QgsLayout *layout)
Constructor for QgsLayoutItemPolyline for the specified layout.
static QString svgSymbolNameToPath(const QString &name, const QgsPathResolver &pathResolver)
Determines an SVG symbol's path from its name.
double scaleFactor() const
Returns the scaling factor for the render to convert painter units to physical sizes.
bool writePropertiesToElement(QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context) const override
Stores item state within an XML DOM element.
Contains information relating to the style entity currently being visited.
static QColor decodeColor(const QString &str)
QgsLineSymbol * clone() const override
Returns a deep copy of this symbol.