25 #include <QStyleOptionGraphicsItem> 58 const QPointF topLeft = boundingRect.topLeft();
59 mPolygon = polygon.translated( -topLeft );
62 void QgsLayoutNodesItem::init()
66 setCacheMode( QGraphicsItem::NoCache );
76 painter->setPen( Qt::NoPen );
77 painter->setBrush( Qt::NoBrush );
83 if ( mDrawNodes &&
layout()->renderContext().isPreviewRender() )
90 return std::sqrt( std::pow( pt1.x() - pt2.x(), 2 ) + std::pow( pt1.y() - pt2.y(), 2 ) );
97 const QPointF start = mapFromScene( pt );
98 double minDistance = std::numeric_limits<double>::max();
99 double maxDistance = ( checkArea ) ? radius : minDistance;
103 for (
int i = 0; i !=
mPolygon.size(); i++ )
106 const QPointF pt1 =
mPolygon.at( i );
112 const double coef = ( pt2.y() - pt1.y() ) / ( pt2.x() - pt1.x() );
113 const double b = pt1.y() - coef * pt1.x();
115 double distance = std::numeric_limits<double>::max();
116 if ( std::isinf( coef ) )
117 distance = std::fabs( pt1.x() - start.x() );
120 const double coef2 = ( -1 / coef );
121 const double b2 = start.y() - coef2 * start.x();
124 if ( std::isinf( coef2 ) )
126 distance = std::fabs( pt1.y() - start.y() );
127 inter.setX( start.x() );
128 inter.setY( pt1.y() );
132 const double interx = ( b - b2 ) / ( coef2 - coef );
133 const double intery = interx * coef2 + b2;
134 inter.setX( interx );
135 inter.setY( intery );
142 const double length4 = length1 + length2;
144 if ( std::fabs( length3 - length4 ) < std::numeric_limits<float>::epsilon() )
148 if ( distance < minDistance && distance < maxDistance )
150 minDistance = distance;
157 rc =
_addNode( idx, start, maxDistance );
171 properties.insert( QStringLiteral(
"name" ), QStringLiteral(
"cross" ) );
172 properties.insert( QStringLiteral(
"color_border" ), QStringLiteral(
"red" ) );
174 std::unique_ptr<QgsMarkerSymbol> symbol;
176 symbol->setSize( rectSize );
177 symbol->setAngle( 45 );
184 if ( mSelectedNode >= 0 && mSelectedNode < mPolygon.size() )
185 drawSelectedNode( context );
193 properties.insert( QStringLiteral(
"name" ), QStringLiteral(
"square" ) );
194 properties.insert( QStringLiteral(
"color" ), QStringLiteral(
"0, 0, 0, 0" ) );
195 properties.insert( QStringLiteral(
"color_border" ), QStringLiteral(
"blue" ) );
196 properties.insert( QStringLiteral(
"width_border" ), QStringLiteral(
"4" ) );
198 std::unique_ptr<QgsMarkerSymbol> symbol;
200 symbol->setSize( rectSize );
208 const bool searchInRadius,
209 const double radius )
const 211 const QPointF pt = mapFromScene( node );
212 double nearestDistance = std::numeric_limits<double>::max();
213 double maxDistance = ( searchInRadius ) ? radius : nearestDistance;
221 if ( distance < nearestDistance && distance < maxDistance )
223 nearestDistance = distance;
236 if ( index >= 0 && index <
mPolygon.size() )
238 position = mapToScene(
mPolygon.at( index ) );
257 if ( index >= 0 && index <
mPolygon.size() )
259 QPointF nodeItem = mapFromScene( pt );
260 mPolygon.replace( index, nodeItem );
273 QDomElement styleSymbolElem = itemElem.firstChildElement( QStringLiteral(
"symbol" ) );
274 if ( !styleSymbolElem.isNull() )
279 QDomNodeList nodesList = itemElem.elementsByTagName( QStringLiteral(
"node" ) );
280 for (
int i = 0; i < nodesList.size(); i++ )
282 QDomElement nodeElem = nodesList.at( i ).toElement();
284 newPt.setX( nodeElem.attribute( QStringLiteral(
"x" ) ).toDouble() );
285 newPt.setY( nodeElem.attribute( QStringLiteral(
"y" ) ).toDouble() );
299 const float ratioX = !
qgsDoubleNear( boundingRect.width(), 0.0 )
300 ? rect().width() / boundingRect.width() : 0;
301 const float ratioY = !
qgsDoubleNear( boundingRect.height(), 0.0 )
302 ? rect().height() / boundingRect.height() : 0;
306 trans = trans.scale( ratioX, ratioY );
314 if ( index >= 0 && index <
mPolygon.size() )
316 mSelectedNode = index;
326 const QRectF br =
mPolygon.boundingRect();
328 const QPointF topLeft = mapToScene( br.topLeft() );
333 mPolygon.translate( -br.topLeft().x(), -br.topLeft().y() );
343 prepareGeometryChange();
353 QDomElement nodesElem = doc.createElement( QStringLiteral(
"nodes" ) );
356 QDomElement nodeElem = doc.createElement( QStringLiteral(
"node" ) );
357 nodeElem.setAttribute( QStringLiteral(
"x" ), QString::number( pt.x() ) );
358 nodeElem.setAttribute( QStringLiteral(
"y" ), QString::number( pt.y() ) );
359 nodesElem.appendChild( nodeElem );
361 elem.appendChild( nodesElem );
virtual void _writeXmlStyle(QDomDocument &doc, QDomElement &elmt, const QgsReadWriteContext &context) const =0
Method called in writeXml.
double computeDistance(QPointF pt1, QPointF pt2) const
Compute an euclidian distance between 2 nodes.
void setForceVectorOutput(bool force)
The class is used as a container of context for various read/write operations on other objects...
double viewScaleFactor() const
Returns the current view zoom (scale factor).
void updateSceneRect()
Update the current scene rectangle for this item.
bool readPropertiesFromElement(const QDomElement &element, const QDomDocument &document, const QgsReadWriteContext &context) override
Sets item state from a DOM element.
Base class for graphical items within a QgsLayout.
QRectF mCurrentRectangle
Current bounding rectangle of shape.
virtual void _draw(QgsLayoutItemRenderContext &context, const QStyleOptionGraphicsItem *itemStyle=nullptr)=0
Method called in paint.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
double mMaxSymbolBleed
Max symbol bleed.
bool nodePosition(int index, QPointF &position) const
Gets the position of a node in scene coordinates.
bool writePropertiesToElement(QDomElement &element, QDomDocument &document, const QgsReadWriteContext &context) const override
Stores item state within an XML DOM element.
virtual bool _removeNode(int nodeIndex)=0
Method called in removeNode.
QPolygonF mPolygon
Shape's nodes.
virtual void updateBoundingRect()
Called when the bounding rect of the item should recalculated.
int nodeAtPosition(QPointF point, bool searchInRadius=true, double radius=10) const
Search for the nearest node in the shape within a maximal area.
QMap< QString, QString > QgsStringMap
void sizePositionChanged()
Emitted when the item's size or position changes.
const QgsLayout * layout() const
Returns the layout the object is attached to.
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...
QgsRenderContext & renderContext()
Returns a reference to the context's render context.
QgsLayoutNodesItem(QgsLayout *layout)
Constructor for QgsLayoutNodesItem, attached to the specified layout.
QRectF boundingRect() const override
Base class for layouts, which can contain items such as maps, labels, scalebars, etc.
void setNodes(const QPolygonF &nodes)
Sets the nodes the shape consists of.
bool setSelectedNode(int index)
Selects a node by index.
void setBackgroundEnabled(bool drawBackground)
Sets whether this item has a background drawn under it or not.
Contains settings and helpers relating to a render of a QgsLayoutItem.
bool removeNode(int index)
Remove a node with specified index from the shape.
double estimatedFrameBleed() const override
Returns the estimated amount the item's frame bleeds outside the item's actual rectangle.
QPainter * painter()
Returns the destination QPainter for the render operation.
QPolygonF nodes() const
Returns the nodes the shape consists of.
virtual void setFrameEnabled(bool drawFrame)
Sets whether this item has a frame drawn around it or not.
bool addNode(QPointF point, bool checkArea=true, double radius=10)
Add a node in current shape.
static QgsMarkerSymbol * createSimple(const QgsStringMap &properties)
Create a marker symbol with one symbol layer: SimpleMarker with specified properties.
bool moveNode(int index, QPointF node)
Moves a node to a new position.
void changed()
Emitted when the object's properties change.
virtual void _readXmlStyle(const QDomElement &elmt, const QgsReadWriteContext &context)=0
Method called in readXml.
virtual bool _addNode(int nodeIndex, QPointF newNode, double radius)=0
Method called in addNode.
void draw(QgsLayoutItemRenderContext &context) override
Draws the item's contents using the specified item render context.
void rescaleToFitBoundingBox()
Rescale the current shape according to the item's bounding box.