27#include <QStyleOptionGraphicsItem>
62 mPolygon = polygon.translated( -topLeft );
65void QgsLayoutNodesItem::init()
69 setCacheMode( QGraphicsItem::NoCache );
79 painter->setPen( Qt::NoPen );
80 painter->setBrush( Qt::NoBrush );
86 if ( mDrawNodes &&
layout()->renderContext().isPreviewRender() )
93 return std::sqrt( std::pow( pt1.x() - pt2.x(), 2 ) + std::pow( pt1.y() - pt2.y(), 2 ) );
100 const QPointF start = mapFromScene( pt );
101 double minDistance = std::numeric_limits<double>::max();
102 const double maxDistance = ( checkArea ) ? radius : minDistance;
106 for (
int i = 0; i !=
mPolygon.size(); i++ )
109 const QPointF pt1 =
mPolygon.at( i );
115 const double coef = ( pt2.y() - pt1.y() ) / ( pt2.x() - pt1.x() );
116 const double b = pt1.y() - coef * pt1.x();
118 double distance = std::numeric_limits<double>::max();
119 if ( std::isinf( coef ) )
120 distance = std::fabs( pt1.x() - start.x() );
123 const double coef2 = ( -1 / coef );
124 const double b2 = start.y() - coef2 * start.x();
127 if ( std::isinf( coef2 ) )
129 distance = std::fabs( pt1.y() - start.y() );
130 inter.setX( start.x() );
131 inter.setY( pt1.y() );
135 const double interx = ( b - b2 ) / ( coef2 - coef );
136 const double intery = interx * coef2 + b2;
137 inter.setX( interx );
138 inter.setY( intery );
145 const double length4 = length1 + length2;
147 if ( std::fabs( length3 - length4 ) < std::numeric_limits<float>::epsilon() )
151 if ( distance < minDistance && distance < maxDistance )
153 minDistance = distance;
160 rc =
_addNode( idx, start, maxDistance );
174 QVariantMap properties;
175 properties.insert( QStringLiteral(
"name" ), QStringLiteral(
"cross" ) );
176 properties.insert( QStringLiteral(
"color_border" ), QStringLiteral(
"red" ) );
178 std::unique_ptr<QgsMarkerSymbol> symbol;
180 symbol->setSize( rectSize );
181 symbol->setAngle( 45 );
184 for (
const QPointF pt : std::as_const(
mPolygon ) )
188 if ( mSelectedNode >= 0 && mSelectedNode <
mPolygon.size() )
189 drawSelectedNode( context );
196 QVariantMap properties;
197 properties.insert( QStringLiteral(
"name" ), QStringLiteral(
"square" ) );
198 properties.insert( QStringLiteral(
"color" ), QStringLiteral(
"0, 0, 0, 0" ) );
199 properties.insert( QStringLiteral(
"color_border" ), QStringLiteral(
"blue" ) );
200 properties.insert( QStringLiteral(
"width_border" ), QStringLiteral(
"4" ) );
202 std::unique_ptr<QgsMarkerSymbol> symbol;
204 symbol->setSize( rectSize );
212 const bool searchInRadius,
213 const double radius )
const
215 const QPointF pt = mapFromScene( node );
216 double nearestDistance = std::numeric_limits<double>::max();
217 const double maxDistance = ( searchInRadius ) ? radius : nearestDistance;
222 for (
const QPointF polyPt : std::as_const(
mPolygon ) )
225 if ( distance < nearestDistance && distance < maxDistance )
227 nearestDistance = distance;
240 if ( index >= 0 && index <
mPolygon.size() )
242 position = mapToScene(
mPolygon.at( index ) );
264 if ( index >= 0 && index <
mPolygon.size() )
266 const QPointF nodeItem = mapFromScene( pt );
267 mPolygon.replace( index, nodeItem );
280 const QDomElement styleSymbolElem = itemElem.firstChildElement( QStringLiteral(
"symbol" ) );
281 if ( !styleSymbolElem.isNull() )
286 const QDomNodeList nodesList = itemElem.elementsByTagName( QStringLiteral(
"node" ) );
287 for (
int i = 0; i < nodesList.size(); i++ )
289 const QDomElement nodeElem = nodesList.at( i ).toElement();
291 newPt.setX( nodeElem.attribute( QStringLiteral(
"x" ) ).toDouble() );
292 newPt.setY( nodeElem.attribute( QStringLiteral(
"y" ) ).toDouble() );
314 trans = trans.scale( ratioX, ratioY );
323 if ( index >= 0 && index <
mPolygon.size() )
325 mSelectedNode = index;
335 const QRectF br =
mPolygon.boundingRect();
337 const QPointF topLeft = mapToScene( br.topLeft() );
342 mPolygon.translate( -br.topLeft().x(), -br.topLeft().y() );
352 prepareGeometryChange();
362 QDomElement nodesElem = doc.createElement( QStringLiteral(
"nodes" ) );
363 for (
const QPointF pt : std::as_const(
mPolygon ) )
365 QDomElement nodeElem = doc.createElement( QStringLiteral(
"node" ) );
366 nodeElem.setAttribute( QStringLiteral(
"x" ), QString::number( pt.x() ) );
367 nodeElem.setAttribute( QStringLiteral(
"y" ), QString::number( pt.y() ) );
368 nodesElem.appendChild( nodeElem );
370 elem.appendChild( nodesElem );
Contains settings and helpers relating to a render of a QgsLayoutItem.
QgsRenderContext & renderContext()
Returns a reference to the context's render context.
double viewScaleFactor() const
Returns the current view zoom (scale factor).
Base class for graphical items within a QgsLayout.
virtual void setFrameEnabled(bool drawFrame)
Sets whether this item has a frame drawn around it or not.
void sizePositionChanged()
Emitted when the item's size or position changes.
void clipPathChanged()
Emitted when the item's clipping path has changed.
void attemptSetSceneRect(const QRectF &rect, bool includesFrame=false)
Attempts to update the item's position and size to match the passed rect in layout coordinates.
void setBackgroundEnabled(bool drawBackground)
Sets whether this item has a background drawn under it or not.
virtual void updateBoundingRect()
Called when the bounding rect of the item should recalculated.
virtual bool _removeNode(int nodeIndex)=0
Method called in removeNode.
QPolygonF nodes() const
Returns the nodes the shape consists of.
double mMaxSymbolBleed
Max symbol bleed.
virtual void _writeXmlStyle(QDomDocument &doc, QDomElement &elmt, const QgsReadWriteContext &context) const =0
Method called in writeXml.
QRectF mCurrentRectangle
Current bounding rectangle of shape.
bool readPropertiesFromElement(const QDomElement &element, const QDomDocument &document, const QgsReadWriteContext &context) override
Sets item state from a DOM element.
bool setSelectedNode(int index)
Selects a node by index.
bool writePropertiesToElement(QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context) const override
Stores item state within an XML DOM element.
void updateSceneRect()
Update the current scene rectangle for this item.
virtual void _readXmlStyle(const QDomElement &elmt, const QgsReadWriteContext &context)=0
Method called in readXml.
bool removeNode(int index)
Remove a node with specified index from the shape.
QRectF boundingRect() const override
double computeDistance(QPointF pt1, QPointF pt2) const
Compute an euclidean distance between 2 nodes.
bool nodePosition(int index, QPointF &position) const
Gets the position of a node in scene coordinates.
bool addNode(QPointF point, bool checkArea=true, double radius=10)
Add a node in current shape.
bool moveNode(int index, QPointF node)
Moves a node to a new position.
double estimatedFrameBleed() const override
Returns the estimated amount the item's frame bleeds outside the item's actual rectangle.
void draw(QgsLayoutItemRenderContext &context) override
Draws the item's contents using the specified item render context.
virtual void _draw(QgsLayoutItemRenderContext &context, const QStyleOptionGraphicsItem *itemStyle=nullptr)=0
Method called in paint.
QgsLayoutNodesItem(QgsLayout *layout)
Constructor for QgsLayoutNodesItem, attached to the specified layout.
virtual bool _addNode(int nodeIndex, QPointF newNode, double radius)=0
Method called in addNode.
void rescaleToFitBoundingBox()
Rescale the current shape according to the item's bounding box.
void setNodes(const QPolygonF &nodes)
Sets the nodes the shape consists of.
QPolygonF mPolygon
Shape's nodes.
int nodeAtPosition(QPointF point, bool searchInRadius=true, double radius=10) const
Search for the nearest node in the shape within a maximal area.
const QgsLayout * layout() const
Returns the layout the object is attached to.
void changed()
Emitted when the object's properties change.
Base class for layouts, which can contain items such as maps, labels, scalebars, etc.
static QgsMarkerSymbol * createSimple(const QVariantMap &properties)
Create a marker symbol with one symbol layer: SimpleMarker with specified properties.
The class is used as a container of context for various read/write operations on other objects.
void setForceVectorOutput(bool force)
Sets whether rendering operations should use vector operations instead of any faster raster shortcuts...
QPainter * painter()
Returns the destination QPainter for the render operation.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)