25#include <QStyleOptionGraphicsItem>
60 mPolygon = polygon.translated( -topLeft );
63void QgsLayoutNodesItem::init()
67 setCacheMode( QGraphicsItem::NoCache );
77 painter->setPen( Qt::NoPen );
78 painter->setBrush( Qt::NoBrush );
84 if ( mDrawNodes &&
layout()->renderContext().isPreviewRender() )
91 return std::sqrt( std::pow( pt1.x() - pt2.x(), 2 ) + std::pow( pt1.y() - pt2.y(), 2 ) );
98 const QPointF start = mapFromScene( pt );
99 double minDistance = std::numeric_limits<double>::max();
100 const double maxDistance = ( checkArea ) ? radius : minDistance;
104 for (
int i = 0; i !=
mPolygon.size(); i++ )
107 const QPointF pt1 =
mPolygon.at( i );
113 const double coef = ( pt2.y() - pt1.y() ) / ( pt2.x() - pt1.x() );
114 const double b = pt1.y() - coef * pt1.x();
116 double distance = std::numeric_limits<double>::max();
117 if ( std::isinf( coef ) )
118 distance = std::fabs( pt1.x() - start.x() );
121 const double coef2 = ( -1 / coef );
122 const double b2 = start.y() - coef2 * start.x();
125 if ( std::isinf( coef2 ) )
127 distance = std::fabs( pt1.y() - start.y() );
128 inter.setX( start.x() );
129 inter.setY( pt1.y() );
133 const double interx = ( b - b2 ) / ( coef2 - coef );
134 const double intery = interx * coef2 + b2;
135 inter.setX( interx );
136 inter.setY( intery );
143 const double length4 = length1 + length2;
145 if ( std::fabs( length3 - length4 ) < std::numeric_limits<float>::epsilon() )
149 if ( distance < minDistance && distance < maxDistance )
151 minDistance = distance;
158 rc =
_addNode( idx, start, maxDistance );
172 QVariantMap properties;
173 properties.insert( QStringLiteral(
"name" ), QStringLiteral(
"cross" ) );
174 properties.insert( QStringLiteral(
"color_border" ), QStringLiteral(
"red" ) );
176 std::unique_ptr<QgsMarkerSymbol> symbol;
178 symbol->setSize( rectSize );
179 symbol->setAngle( 45 );
182 for (
const QPointF pt : std::as_const(
mPolygon ) )
186 if ( mSelectedNode >= 0 && mSelectedNode <
mPolygon.size() )
187 drawSelectedNode( context );
194 QVariantMap properties;
195 properties.insert( QStringLiteral(
"name" ), QStringLiteral(
"square" ) );
196 properties.insert( QStringLiteral(
"color" ), QStringLiteral(
"0, 0, 0, 0" ) );
197 properties.insert( QStringLiteral(
"color_border" ), QStringLiteral(
"blue" ) );
198 properties.insert( QStringLiteral(
"width_border" ), QStringLiteral(
"4" ) );
200 std::unique_ptr<QgsMarkerSymbol> symbol;
202 symbol->setSize( rectSize );
210 const bool searchInRadius,
211 const double radius )
const
213 const QPointF pt = mapFromScene( node );
214 double nearestDistance = std::numeric_limits<double>::max();
215 const double maxDistance = ( searchInRadius ) ? radius : nearestDistance;
220 for (
const QPointF polyPt : std::as_const(
mPolygon ) )
223 if ( distance < nearestDistance && distance < maxDistance )
225 nearestDistance = distance;
238 if ( index >= 0 && index <
mPolygon.size() )
240 position = mapToScene(
mPolygon.at( index ) );
262 if ( index >= 0 && index <
mPolygon.size() )
264 const QPointF nodeItem = mapFromScene( pt );
265 mPolygon.replace( index, nodeItem );
278 const QDomElement styleSymbolElem = itemElem.firstChildElement( QStringLiteral(
"symbol" ) );
279 if ( !styleSymbolElem.isNull() )
284 const QDomNodeList nodesList = itemElem.elementsByTagName( QStringLiteral(
"node" ) );
285 for (
int i = 0; i < nodesList.size(); i++ )
287 const QDomElement nodeElem = nodesList.at( i ).toElement();
289 newPt.setX( nodeElem.attribute( QStringLiteral(
"x" ) ).toDouble() );
290 newPt.setY( nodeElem.attribute( QStringLiteral(
"y" ) ).toDouble() );
312 trans = trans.scale( ratioX, ratioY );
321 if ( index >= 0 && index <
mPolygon.size() )
323 mSelectedNode = index;
333 const QRectF br =
mPolygon.boundingRect();
335 const QPointF topLeft = mapToScene( br.topLeft() );
340 mPolygon.translate( -br.topLeft().x(), -br.topLeft().y() );
350 prepareGeometryChange();
360 QDomElement nodesElem = doc.createElement( QStringLiteral(
"nodes" ) );
361 for (
const QPointF pt : std::as_const(
mPolygon ) )
363 QDomElement nodeElem = doc.createElement( QStringLiteral(
"node" ) );
364 nodeElem.setAttribute( QStringLiteral(
"x" ), QString::number( pt.x() ) );
365 nodeElem.setAttribute( QStringLiteral(
"y" ), QString::number( pt.y() ) );
366 nodesElem.appendChild( nodeElem );
368 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)