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.
void setForceVectorOutput(bool force)
Sets whether rendering operations should use vector operations instead of any faster raster shortcuts...
QPolygonF nodes() const
Returns the nodes the shape consists of.
The class is used as a container of context for various read/write operations on other objects...
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 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.
QMap< QString, QString > QgsStringMap
void sizePositionChanged()
Emitted when the item's size or position changes.
int nodeAtPosition(QPointF point, bool searchInRadius=true, double radius=10) const
Search for the nearest node in the shape within a maximal area.
bool nodePosition(int index, QPointF &position) const
Gets the position of a node in scene coordinates.
double computeDistance(QPointF pt1, QPointF pt2) const
Compute an euclidian distance between 2 nodes.
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.
double viewScaleFactor() const
Returns the current view zoom (scale factor).
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.
const QgsLayout * layout() const
Returns the layout the object is attached to.
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.