28QLineF
segment(
int index, QRectF rect,
double radius )
30 const int yMultiplier = rect.height() < 0 ? -1 : 1;
34 return QLineF( rect.left() + radius, rect.top(), rect.right() - radius, rect.top() );
36 return QLineF( rect.right(), rect.top() + yMultiplier * radius, rect.right(), rect.bottom() - yMultiplier * radius );
38 return QLineF( rect.right() - radius, rect.bottom(), rect.left() + radius, rect.bottom() );
40 return QLineF( rect.left(), rect.bottom() - yMultiplier * radius, rect.left(), rect.top() + yMultiplier * radius );
53 int balloonSegment = -1;
54 QPointF balloonSegmentPoint1;
55 QPointF balloonSegmentPoint2;
57 const bool invertedY = rect.height() < 0;
59 cornerRadius = std::min( cornerRadius, std::min( std::fabs( rect.height() ), rect.width() ) / 2.0 );
62 if ( rect.contains( origin.
toQPointF() ) )
69 QList<QLineF> segmentList;
70 segmentList <<
segment( 0, rect, cornerRadius );
71 segmentList <<
segment( 1, rect, cornerRadius );
72 segmentList <<
segment( 2, rect, cornerRadius );
73 segmentList <<
segment( 3, rect, cornerRadius );
76 double minEdgeDist = std::numeric_limits<double>::max();
77 int minEdgeIndex = -1;
81 for (
int i = 0; i < 4; ++i )
83 QLineF currentSegment = segmentList.at( i );
85 double currentMinDist = origin.
sqrDistToSegment( currentSegment.x1(), currentSegment.y1(), currentSegment.x2(), currentSegment.y2(), currentMinDistPoint );
86 bool isPreferredSegment =
false;
90 const double angle = fmod( origin.
azimuth( currentMinDistPoint ) + 360.0, 360.0 );
91 if ( angle < 45 || angle > 315 )
92 isPreferredSegment = i == 0;
93 else if ( angle < 135 )
94 isPreferredSegment = i == 3;
95 else if ( angle < 225 )
96 isPreferredSegment = i == 2;
98 isPreferredSegment = i == 1;
100 else if ( currentMinDist < minEdgeDist )
101 isPreferredSegment =
true;
103 if ( isPreferredSegment )
106 minEdgePoint = currentMinDistPoint;
107 minEdgeDist = currentMinDist;
108 minEdge = currentSegment;
112 if ( minEdgeIndex >= 0 )
114 balloonSegment = minEdgeIndex;
115 QPointF minEdgeEnd = minEdge.p2();
116 balloonSegmentPoint1 = QPointF( minEdgePoint.
x(), minEdgePoint.
y() );
118 const double segmentLength = minEdge.length();
119 const double clampedWedgeWidth = std::clamp( wedgeWidth, 0.0, segmentLength );
120 if ( std::sqrt( minEdgePoint.
sqrDist( minEdgeEnd.x(), minEdgeEnd.y() ) ) < clampedWedgeWidth )
125 balloonSegmentPoint1 = QPointF( x, y );
132 balloonSegmentPoint2 = QPointF( x, y );
140 for (
int i = 0; i < 4; ++i )
142 QLineF currentSegment =
segment( i, rect, cornerRadius );
145 p0 = currentSegment.p1();
146 path.moveTo( currentSegment.p1() );
151 path.arcTo( std::min( p1.x(), currentSegment.p1().x() ), std::min( p1.y(), currentSegment.p1().y() ), cornerRadius, cornerRadius, i == 1 ? -90 : ( i == 2 ? 0 : 90 ), 90 );
153 path.arcTo( std::min( p1.x(), currentSegment.p1().x() ), std::min( p1.y(), currentSegment.p1().y() ), cornerRadius, cornerRadius, i == 1 ? 90 : ( i == 2 ? 0 : -90 ), -90 );
156 if ( i == balloonSegment )
158 path.lineTo( balloonSegmentPoint1 );
160 path.lineTo( balloonSegmentPoint2 );
163 p1 = currentSegment.p2();
168 path.arcTo( std::min( p1.x(), p0.x() ), std::min( p1.y(), p0.y() ), cornerRadius, cornerRadius, 180, 90 );
170 path.arcTo( std::min( p1.x(), p0.x() ), std::min( p1.y(), p0.y() ), cornerRadius, cornerRadius, -180, -90 );
static void pointOnLineWithDistance(double x1, double y1, double x2, double y2, double distance, double &x, double &y, double *z1=nullptr, double *z2=nullptr, double *z=nullptr, double *m1=nullptr, double *m2=nullptr, double *m=nullptr)
Calculates the point a specified distance from (x1, y1) toward a second point (x2,...