26 #include <QSvgRenderer> 28 #include <QGraphicsPathItem> 34 createDefaultPolylineStyleSymbol();
40 createDefaultPolylineStyleSymbol();
65 if ( indexPoint == (
mPolygon.size() - 1 ) )
67 if ( distEnd < radius )
69 else if ( distStart < radius )
73 mPolygon.insert( indexPoint + 1, newPoint );
80 if ( index < 0 || index >=
mPolygon.size() )
89 int newSelectNode = index;
98 void QgsLayoutItemPolyline::createDefaultPolylineStyleSymbol()
101 properties.insert( QStringLiteral(
"color" ), QStringLiteral(
"0,0,0,255" ) );
102 properties.insert( QStringLiteral(
"width" ), QStringLiteral(
"0.3" ) );
103 properties.insert( QStringLiteral(
"capstyle" ), QStringLiteral(
"square" ) );
109 void QgsLayoutItemPolyline::refreshSymbol()
122 void QgsLayoutItemPolyline::drawStartMarker( QPainter *painter )
127 switch ( mStartMarker )
129 case MarkerMode::NoMarker:
132 case MarkerMode::ArrowHead:
136 double angle = startLine.angle();
141 case MarkerMode::SvgMarker:
145 double angle = startLine.angle();
146 drawSvgMarker( painter,
mPolygon.at( 0 ),
angle, mStartMarkerFile, mStartArrowHeadHeight );
153 void QgsLayoutItemPolyline::drawEndMarker( QPainter *painter )
158 switch ( mEndMarker )
160 case MarkerMode::NoMarker:
163 case MarkerMode::ArrowHead:
167 double angle = endLine.angle();
170 QVector2D dir = QVector2D( endLine.dx(), endLine.dy() ).normalized();
171 QPointF endPoint = endLine.p2();
172 endPoint += ( dir * 0.5 * mArrowHeadWidth ).toPointF();
174 drawArrow( painter, endPoint, angle );
177 case MarkerMode::SvgMarker:
181 double angle = endLine.angle();
182 drawSvgMarker( painter, endLine.p2(),
angle, mEndMarkerFile, mEndArrowHeadHeight );
188 void QgsLayoutItemPolyline::drawArrow( QPainter *painter, QPointF center,
double angle )
193 p.setColor( mArrowHeadStrokeColor );
194 p.setWidthF( mArrowHeadStrokeWidth );
195 painter->setPen( p );
197 b.setColor( mArrowHeadFillColor );
198 painter->setBrush( b );
200 drawArrowHead( painter, center.x(), center.y(),
angle, mArrowHeadWidth );
203 void QgsLayoutItemPolyline::updateMarkerSvgSizes()
209 void QgsLayoutItemPolyline::drawArrowHead( QPainter *p,
const double x,
const double y,
const double angle,
const double arrowHeadWidth )
214 double angleRad =
angle / 180.0 * M_PI;
215 QPointF middlePoint( x, y );
218 QPointF p1 = QPointF( -arrowHeadWidth / 2.0, arrowHeadWidth );
219 QPointF p2 = QPointF( arrowHeadWidth / 2.0, arrowHeadWidth );
221 QPointF p1Rotated, p2Rotated;
222 p1Rotated.setX( p1.x() * std::cos( angleRad ) + p1.y() * -std::sin( angleRad ) );
223 p1Rotated.setY( p1.x() * std::sin( angleRad ) + p1.y() * std::cos( angleRad ) );
224 p2Rotated.setX( p2.x() * std::cos( angleRad ) + p2.y() * -std::sin( angleRad ) );
225 p2Rotated.setY( p2.x() * std::sin( angleRad ) + p2.y() * std::cos( angleRad ) );
227 QPolygonF arrowHeadPoly;
228 arrowHeadPoly << middlePoint;
229 arrowHeadPoly << QPointF( middlePoint.x() + p1Rotated.x(), middlePoint.y() + p1Rotated.y() );
230 arrowHeadPoly << QPointF( middlePoint.x() + p2Rotated.x(), middlePoint.y() + p2Rotated.y() );
231 QPen arrowPen = p->pen();
232 arrowPen.setJoinStyle( Qt::RoundJoin );
233 QBrush arrowBrush = p->brush();
234 arrowBrush.setStyle( Qt::SolidPattern );
235 p->setPen( arrowPen );
236 p->setBrush( arrowBrush );
237 arrowBrush.setStyle( Qt::SolidPattern );
238 p->drawPolygon( arrowHeadPoly );
241 void QgsLayoutItemPolyline::drawSvgMarker( QPainter *p, QPointF point,
double angle,
const QString &markerPath,
double height )
const 246 if ( mArrowHeadWidth <= 0 || height <= 0 )
252 if ( markerPath.isEmpty() )
256 const QByteArray &svgContent =
QgsApplication::svgCache()->
svgContent( markerPath, mArrowHeadWidth, mArrowHeadFillColor, mArrowHeadStrokeColor, mArrowHeadStrokeWidth,
258 r.load( svgContent );
261 p->translate( point.x(), point.y() );
263 p->translate( -mArrowHeadWidth / 2.0, -height / 2.0 );
264 r.render( p, QRectF( 0, 0, mArrowHeadWidth, height ) );
270 if ( !
id().isEmpty() )
273 return tr(
"<Polyline>" );
281 QTransform t = QTransform::fromScale( scale, scale );
283 mPolylineStyleSymbol->startRender( context.
renderContext() );
297 mPolylineStyleSymbol.reset( QgsSymbolLayerUtils::loadSymbol<QgsLineSymbol>( elmt, context ) );
302 mPolylineStyleSymbol.reset( static_cast<QgsLineSymbol *>( symbol->
clone() ) );
320 mArrowHeadWidth = width;
321 updateMarkerSvgSizes();
330 QPainterPathStroker ps;
333 QPainterPath strokedOutline = ps.createStroke( path );
335 return strokedOutline;
341 mStartMarkerFile = path;
342 if ( path.isEmpty() || !r.load( path ) )
344 mStartArrowHeadHeight = 0;
349 QRect viewBox = r.viewBox();
350 mStartArrowHeadHeight = mArrowHeadWidth / viewBox.width() * viewBox.height();
358 mEndMarkerFile = path;
359 if ( path.isEmpty() || !r.load( path ) )
361 mEndArrowHeadHeight = 0;
366 QRect viewBox = r.viewBox();
367 mEndArrowHeadHeight = mArrowHeadWidth / viewBox.width() * viewBox.height();
374 mArrowHeadStrokeColor = color;
380 mArrowHeadFillColor = color;
386 mArrowHeadStrokeWidth = width;
394 mPolylineStyleSymbol.get(),
397 elmt.appendChild( pe );
408 elmt.setAttribute( QStringLiteral(
"arrowHeadWidth" ), QString::number( mArrowHeadWidth ) );
411 elmt.setAttribute( QStringLiteral(
"outlineWidth" ), QString::number( mArrowHeadStrokeWidth ) );
412 elmt.setAttribute( QStringLiteral(
"markerMode" ), mEndMarker );
413 elmt.setAttribute( QStringLiteral(
"startMarkerMode" ), mStartMarker );
414 elmt.setAttribute( QStringLiteral(
"startMarkerFile" ), startMarkerPath );
415 elmt.setAttribute( QStringLiteral(
"endMarkerFile" ), endMarkerPath );
422 mArrowHeadWidth = elmt.attribute( QStringLiteral(
"arrowHeadWidth" ), QStringLiteral(
"2.0" ) ).toDouble();
425 mArrowHeadStrokeWidth = elmt.attribute( QStringLiteral(
"outlineWidth" ), QStringLiteral(
"1.0" ) ).toDouble();
427 QString startMarkerPath = elmt.attribute( QStringLiteral(
"startMarkerFile" ), QString() );
428 QString endMarkerPath = elmt.attribute( QStringLiteral(
"endMarkerFile" ), QString() );
447 margin += 0.5 * mArrowHeadWidth;
449 br.adjust( -margin, -margin, margin, margin );
453 prepareGeometryChange();
458 double QgsLayoutItemPolyline::computeMarkerMargin()
const 464 margin = mArrowHeadStrokeWidth / 2.0 + mArrowHeadWidth * M_SQRT2;
469 double startMarkerMargin = std::sqrt( 0.25 * ( mStartArrowHeadHeight * mStartArrowHeadHeight + mArrowHeadWidth * mArrowHeadWidth ) );
470 margin = std::max( startMarkerMargin, margin );
475 double endMarkerMargin = std::sqrt( 0.25 * ( mEndArrowHeadHeight * mEndArrowHeadHeight + mArrowHeadWidth * mArrowHeadWidth ) );
476 margin = std::max( endMarkerMargin, margin );
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.
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...
double convertToPainterUnits(double size, QgsUnitTypes::RenderUnit unit, const QgsMapUnitScale &scale=QgsMapUnitScale()) const
Converts a size from the specified units to painter units (pixels).
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.
double scaleFactor() const
Returns the scaling factor for the render to convert painter units to physical sizes.
QPolygonF mPolygon
Shape's nodes.
void updateBoundingRect() override
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.
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.
double computeDistance(QPointF pt1, QPointF pt2) const
Compute an euclidian distance between 2 nodes.
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.
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.
Contains information about the context of a rendering operation.
QPainter * painter()
Returns the destination QPainter for the render operation.
QByteArray svgContent(const QString &path, double size, const QColor &fill, const QColor &stroke, double strokeWidth, double widthScaleFactor, double fixedAspectRatio=0)
Gets SVG content.
static QDomElement saveSymbol(const QString &symbolName, QgsSymbol *symbol, QDomDocument &doc, const QgsReadWriteContext &context)
Writes a symbol definition to XML.
const QgsPathResolver & pathResolver() const
Returns path resolver for conversion between relative and absolute paths.
QString id() const
Returns the item's ID name.
QgsLayoutItemPolyline(QgsLayout *layout)
Constructor for QgsLayoutItemPolyline for the specified layout.
const QgsLayout * layout() const
Returns the layout the object is attached to.
static QString svgSymbolNameToPath(const QString &name, const QgsPathResolver &pathResolver)
Determines an SVG symbol's path from its name.
double dpi() const
Returns the dpi for outputting the layout.
bool writePropertiesToElement(QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context) const override
Stores item state within an XML DOM element.
static QColor decodeColor(const QString &str)
double arrowHeadWidth() const
Returns the width of line arrow heads in mm.
QgsLineSymbol * clone() const override
Returns a deep copy of this symbol.