void QgsAnnotationItem::updateBalloon() { //first test if the point is in the frame. In that case we don't need a balloon. if ( !mMapPositionFixed || ( mOffsetFromReferencePoint.x() < 0 && ( mOffsetFromReferencePoint.x() + mFrameSize.width() ) > 0 && mOffsetFromReferencePoint.y() < 0 && ( mOffsetFromReferencePoint.y() + mFrameSize.height() ) > 0 ) ) { mBalloonSegment = -1; return; } //edge list QList<QLineF> segmentList; segmentList << segment( 0 ); segmentList << segment( 1 ); segmentList << segment( 2 ); segmentList << segment( 3 ); //find closest edge / closest edge point double minEdgeDist = DBL_MAX; int minEdgeIndex = -1; QLineF minEdge; QgsPoint minEdgePoint; QgsPoint origin( 0, 0 ); for ( int i = 0; i < 4; ++i ) { QLineF currentSegment = segmentList.at( i ); QgsPoint currentMinDistPoint; double currentMinDist = origin.sqrDistToSegment( currentSegment.x1(), currentSegment.y1(), currentSegment.x2(), currentSegment.y2(), currentMinDistPoint ); if ( currentMinDist < minEdgeDist ) { minEdgeIndex = i; minEdgePoint = currentMinDistPoint; minEdgeDist = currentMinDist; minEdge = currentSegment; } } if ( minEdgeIndex < 0 ) { return; } //make that configurable for the item double segmentPointWidth = 10; mBalloonSegment = minEdgeIndex; QPointF minEdgeEnd = minEdge.p2(); mBalloonSegmentPoint1 = QPointF( minEdgePoint.x(), minEdgePoint.y() ); if ( sqrt( minEdgePoint.sqrDist( minEdgeEnd.x(), minEdgeEnd.y() ) ) < segmentPointWidth ) { mBalloonSegmentPoint1 = pointOnLineWithDistance( minEdge.p2(), minEdge.p1(), segmentPointWidth ); } mBalloonSegmentPoint2 = pointOnLineWithDistance( mBalloonSegmentPoint1, minEdge.p2(), 10 ); }
bool QgsGeometryUtils::segmentMidPoint( const QgsPointV2& p1, const QgsPointV2& p2, QgsPointV2& result, double radius, const QgsPointV2& mousePos ) { QgsPointV2 midPoint(( p1.x() + p2.x() ) / 2.0, ( p1.y() + p2.y() ) / 2.0 ); double midDist = sqrt( sqrDistance2D( p1, midPoint ) ); if ( radius < midDist ) { return false; } double centerMidDist = sqrt( radius * radius - midDist * midDist ); double dist = radius - centerMidDist; double midDx = midPoint.x() - p1.x(); double midDy = midPoint.y() - p1.y(); //get the four possible midpoints QList<QgsPointV2> possibleMidPoints; possibleMidPoints.append( pointOnLineWithDistance( midPoint, QgsPointV2( midPoint.x() - midDy, midPoint.y() + midDx ), dist ) ); possibleMidPoints.append( pointOnLineWithDistance( midPoint, QgsPointV2( midPoint.x() - midDy, midPoint.y() + midDx ), 2 * radius - dist ) ); possibleMidPoints.append( pointOnLineWithDistance( midPoint, QgsPointV2( midPoint.x() + midDy, midPoint.y() - midDx ), dist ) ); possibleMidPoints.append( pointOnLineWithDistance( midPoint, QgsPointV2( midPoint.x() + midDy, midPoint.y() - midDx ), 2 * radius - dist ) ); //take the closest one double minDist = std::numeric_limits<double>::max(); int minDistIndex = -1; for ( int i = 0; i < possibleMidPoints.size(); ++i ) { double currentDist = sqrDistance2D( mousePos, possibleMidPoints.at( i ) ); if ( currentDist < minDist ) { minDistIndex = i; minDist = currentDist; } } if ( minDistIndex == -1 ) { return false; } result = possibleMidPoints.at( minDistIndex ); return true; }
bool QgsComposerItem::imageSizeConsideringRotation( double& width, double& height ) const { if ( qAbs( mRotation ) <= 0.0 ) //width and height stays the same if there is no rotation { return true; } double x1 = 0; double y1 = 0; double x2 = width; double y2 = 0; double x3 = width; double y3 = height; double x4 = 0; double y4 = height; double midX = width / 2.0; double midY = height / 2.0; if ( !cornerPointOnRotatedAndScaledRect( x1, y1, width, height ) ) { return false; } if ( !cornerPointOnRotatedAndScaledRect( x2, y2, width, height ) ) { return false; } if ( !cornerPointOnRotatedAndScaledRect( x3, y3, width, height ) ) { return false; } if ( !cornerPointOnRotatedAndScaledRect( x4, y4, width, height ) ) { return false; } //assume points 1 and 3 are on the rectangle boundaries. Calculate 2 and 4. double distM1 = sqrt(( x1 - midX ) * ( x1 - midX ) + ( y1 - midY ) * ( y1 - midY ) ); QPointF p2 = pointOnLineWithDistance( QPointF( midX, midY ), QPointF( x2, y2 ), distM1 ); if ( p2.x() < width && p2.x() > 0 && p2.y() < height && p2.y() > 0 ) { width = sqrt(( p2.x() - x1 ) * ( p2.x() - x1 ) + ( p2.y() - y1 ) * ( p2.y() - y1 ) ); height = sqrt(( x3 - p2.x() ) * ( x3 - p2.x() ) + ( y3 - p2.y() ) * ( y3 - p2.y() ) ); return true; } //else assume that points 2 and 4 are on the rectangle boundaries. Calculate 1 and 3 double distM2 = sqrt(( x2 - midX ) * ( x2 - midX ) + ( y2 - midY ) * ( y2 - midY ) ); QPointF p1 = pointOnLineWithDistance( QPointF( midX, midY ), QPointF( x1, y1 ), distM2 ); QPointF p3 = pointOnLineWithDistance( QPointF( midX, midY ), QPointF( x3, y3 ), distM2 ); width = sqrt(( x2 - p1.x() ) * ( x2 - p1.x() ) + ( y2 - p1.y() ) * ( y2 - p1.y() ) ); height = sqrt(( p3.x() - x2 ) * ( p3.x() - x2 ) + ( p3.y() - y2 ) * ( p3.y() - y2 ) ); return true; #if 0 double x1 = 0; double y1 = 0; double x2 = width; double y2 = 0; double x3 = width; double y3 = height; if ( !cornerPointOnRotatedAndScaledRect( x1, y1, width, height ) ) { return false; } if ( !cornerPointOnRotatedAndScaledRect( x2, y2, width, height ) ) { return false; } if ( !cornerPointOnRotatedAndScaledRect( x3, y3, width, height ) ) { return false; } width = sqrt(( x2 - x1 ) * ( x2 - x1 ) + ( y2 - y1 ) * ( y2 - y1 ) ); height = sqrt(( x3 - x2 ) * ( x3 - x2 ) + ( y3 - y2 ) * ( y3 - y2 ) ); return true; #endif //0 }