23#include <QApplication>
29QgsModelArrowItem::QgsModelArrowItem( QgsModelComponentGraphicItem *startItem, Qt::Edge startEdge,
int startIndex,
bool startIsOutgoing, Marker startMarker,
30 QgsModelComponentGraphicItem *endItem, Qt::Edge endEdge,
int endIndex,
bool endIsIncoming, Marker endMarker )
32 , mStartItem( startItem )
33 , mStartEdge( startEdge )
34 , mStartIndex( startIndex )
35 , mStartIsOutgoing( startIsOutgoing )
36 , mStartMarker( startMarker )
39 , mEndIndex( endIndex )
40 , mEndIsIncoming( endIsIncoming )
41 , mEndMarker( endMarker )
43 setCacheMode( QGraphicsItem::DeviceCoordinateCache );
44 setFlag( QGraphicsItem::ItemIsSelectable,
false );
45 mColor = QApplication::palette().color( QPalette::WindowText );
46 mColor.setAlpha( 150 );
47 setPen( QPen( mColor, 8, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin ) );
48 setZValue( QgsModelGraphicsScene::ArrowLink );
51 connect( mStartItem, &QgsModelComponentGraphicItem::updateArrowPaths,
this, &QgsModelArrowItem::updatePath );
52 connect( mStartItem, &QgsModelComponentGraphicItem::repaintArrows,
this, [ = ] { update(); } );
53 connect( mEndItem, &QgsModelComponentGraphicItem::updateArrowPaths,
this, &QgsModelArrowItem::updatePath );
54 connect( mEndItem, &QgsModelComponentGraphicItem::repaintArrows,
this, [ = ] { update(); } );
57QgsModelArrowItem::QgsModelArrowItem( QgsModelComponentGraphicItem *startItem, Qt::Edge startEdge,
int startIndex, Marker startMarker, QgsModelComponentGraphicItem *endItem, Marker endMarker )
58 : QgsModelArrowItem( startItem, startEdge, startIndex, true, startMarker, endItem, Qt::LeftEdge, -1, true, endMarker )
62QgsModelArrowItem::QgsModelArrowItem( QgsModelComponentGraphicItem *startItem, Marker startMarker, QgsModelComponentGraphicItem *endItem, Qt::Edge endEdge,
int endIndex, Marker endMarker )
63 : QgsModelArrowItem( startItem, Qt::LeftEdge, -1, true, startMarker, endItem, endEdge, endIndex, true, endMarker )
67QgsModelArrowItem::QgsModelArrowItem( QgsModelComponentGraphicItem *startItem, Marker startMarker, QgsModelComponentGraphicItem *endItem, Marker endMarker )
68 : QgsModelArrowItem( startItem, Qt::LeftEdge, -1, true, startMarker, endItem, Qt::LeftEdge, -1, true, endMarker )
73void QgsModelArrowItem::paint( QPainter *painter,
const QStyleOptionGraphicsItem *, QWidget * )
75 QColor color = mColor;
77 if ( mStartItem->state() == QgsModelComponentGraphicItem::Selected || mEndItem->state() == QgsModelComponentGraphicItem::Selected )
78 color.setAlpha( 220 );
79 else if ( mStartItem->state() == QgsModelComponentGraphicItem::Hover || mEndItem->state() == QgsModelComponentGraphicItem::Hover )
80 color.setAlpha( 150 );
88 painter->setBrush( color );
89 painter->setRenderHint( QPainter::Antialiasing );
92 switch ( mStartMarker )
95 painter->drawEllipse( mStartPoint, 3.0, 3.0 );
97 case Marker::ArrowHead:
98 drawArrowHead( painter, mStartPoint, path().pointAtPercent( 0.0 ) - path().pointAtPercent( 0.05 ) );
102 switch ( mEndMarker )
105 painter->drawEllipse( mEndPoint, 3.0, 3.0 );
107 case Marker::ArrowHead:
108 drawArrowHead( painter, mEndPoint, path().pointAtPercent( 1.0 ) - path().pointAtPercent( 0.95 ) );
112 painter->setBrush( Qt::NoBrush );
113 painter->drawPath( path() );
116void QgsModelArrowItem::drawArrowHead( QPainter *painter,
const QPointF &position,
const QPointF &vector )
118 const float angle = atan2( vector.y(), vector.x() ) * 180.0 / M_PI;
119 painter->translate( position );
120 painter->rotate(
angle );
122 arrowHead << QPointF( 0, 0 ) << QPointF( -6, 4 ) << QPointF( -6, -4 ) << QPointF( 0, 0 );
123 painter->drawPolygon( arrowHead );
124 painter->rotate( -
angle );
125 painter->translate( -position );
128void QgsModelArrowItem::setPenStyle( Qt::PenStyle style )
136void QgsModelArrowItem::updatePath()
138 QList< QPointF > controlPoints;
142 bool hasStartPt =
false;
143 if ( mStartIndex != -1 )
145 startPt = mStartItem->linkPoint( mStartEdge, mStartIndex, !mStartIsOutgoing );
149 bool hasEndPt =
false;
150 if ( mEndIndex != -1 )
152 endPt = mEndItem->linkPoint( mEndEdge, mEndIndex, mEndIsIncoming );
161 pt = mStartItem->calculateAutomaticLinkPoint( mEndItem, startEdge );
163 pt = mStartItem->calculateAutomaticLinkPoint( endPt + mEndItem->pos(), startEdge );
165 controlPoints.append( pt );
167 controlPoints.append( bezierPointForCurve( pt, startEdge, !mStartIsOutgoing ) );
171 mStartPoint = mStartItem->pos() + startPt;
172 controlPoints.append( mStartItem->pos() + startPt );
173 controlPoints.append( bezierPointForCurve( mStartItem->pos() + startPt, mStartEdge == Qt::BottomEdge ? Qt::RightEdge : Qt::LeftEdge, !mStartIsOutgoing ) );
181 pt = mEndItem->calculateAutomaticLinkPoint( mStartItem, endEdge );
183 pt = mEndItem->calculateAutomaticLinkPoint( startPt + mStartItem->pos(), endEdge );
185 controlPoints.append( bezierPointForCurve( pt, endEdge, mEndIsIncoming ) );
186 controlPoints.append( pt );
191 mEndPoint = mEndItem->pos() + endPt ;
192 controlPoints.append( bezierPointForCurve( mEndItem->pos() + endPt, mEndEdge == Qt::BottomEdge ? Qt::RightEdge : Qt::LeftEdge, mEndIsIncoming ) );
193 controlPoints.append( mEndItem->pos() + endPt );
197 path.moveTo( controlPoints.at( 0 ) );
198 path.cubicTo( controlPoints.at( 1 ), controlPoints.at( 2 ), controlPoints.at( 3 ) );
202QPointF QgsModelArrowItem::bezierPointForCurve(
const QPointF &point, Qt::Edge edge,
bool incoming )
const
207 return point + QPointF( incoming ? -50 : 50, 0 );
210 return point + QPointF( incoming ? -50 : 50, 0 );
213 return point + QPointF( 0, incoming ? -30 : 30 );
216 return point + QPointF( 0, incoming ? -30 : 30 );
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)