#include <QCoreApplication>#include <cmath>#include <QTransform>#include <QDebug>QRectF getArcBoundingRect(const QPointF &p1, const QPointF &p2, const QPointF ¢er){ QTransform centerTranslate = QTransform::fromTranslate(-center.x(), -center.y()); //в систему координат центра кривизны QPointF pp1 = centerTranslate.map(p1); QPointF pp2 = centerTranslate.map(p2); // можно выкинуть, если не нужна проверка на равенство радиусов { qreal radius1 = std::hypot(pp1.x(), pp1.y()); qreal radius2 = std::hypot(pp2.x(), pp2.y()); if (!qFuzzyCompare(radius1, radius2)) { qCritical() << Q_FUNC_INFO << " radius1 != radius2"; return QRectF(); } } qreal radius = std::hypot(pp1.x(), pp1.y());; QPointF topLeft = QPointF(qMin(pp1.x(), pp2.x()), qMax(pp1.y(), pp2.y())); QPointF bottomRight = QPointF(qMax(pp1.x(), pp2.x()), qMin(pp1.y(), pp2.y())); if (pp1.x() * pp2.x() < 0) { if(topLeft.y() > 0){ topLeft.ry() = qMax(topLeft.y(), radius); } if(bottomRight.y() < 0){ bottomRight.ry() = qMin(bottomRight.y(), -radius); } } if (pp1.y() * pp2.y() < 0) { if(topLeft.x() < 0){ topLeft.rx() = qMin(topLeft.x(), -radius); } if(bottomRight.x() > 0){ bottomRight.rx() = qMax(bottomRight.x(), radius); } } // в исходную систему координат auto defaultTransform = centerTranslate.inverted(); topLeft = defaultTransform.map(topLeft); bottomRight = defaultTransform.map(bottomRight); return QRectF(topLeft, bottomRight);}int main(int argc, char *argv[]){ QCoreApplication a(argc, argv); qDebug() << getArcBoundingRect(QPointF(3, -5), QPointF(5, -3), QPointF(2,-2)); return a.exec();}
from PyQt5.QtCore import *from PyQt5.QtGui import QTransformfrom math import hypotdef getArcBoundingRect(p1, p2, center): centerTranslate = QTransform.fromTranslate(-center.x(), -center.y()) pp1 = QPointF(centerTranslate.map(p1)) pp2 = QPointF(centerTranslate.map(p2)) #Проверка на равенство радиусов radius1 = hypot(pp1.x(), pp1.y()) radius2 = hypot(pp2.x(), pp2.y()) if not qFuzzyCompare(radius1, radius2): qCritical(" radius1 != radius2") #return QRectF() radius = hypot(pp1.x(), pp1.y()) topLeft = QPointF(min(pp1.x(), pp2.x()), max(pp1.y(), pp2.y())) bottomRight = QPointF(max(pp1.x(), pp2.x()), min(pp1.y(), pp2.y())) if (pp1.x() * pp2.x() < 0): if (topLeft.y() > 0): topLeft.ry = max(topLeft.y(), radius) if (bottomRight.y() < 0): bottomRight.ry = min(bottomRight.y(), -radius) if (pp1.y() * pp2.y() < 0): if (topLeft.x() < 0): topLeft.rx = min(topLeft.x(), -radius) if(bottomRight.x() > 0): bottomRight.rx = max(bottomRight.x(), radius) #В исходную систему координат defaultTransform = centerTranslate.inverted() topLeft = defaultTransform.map(topLeft) bottomRight = defaultTransform.map(bottomRight) return QRectF(topLeft, bottomRight)i = 20.0j = -5.0aX = 6.31aY = 5.773bX = 20.53bY = 19.836a = QPointF(aX, aY)b = QPointF(bX, bY)c = QPointF(aX + i, aY + j)print(getArcBoundingRect(a, b, c))
path = QPainterPath() path.arcTo(50, 50, 150, 60, 180, 90) self.ui.graphicsView.scene.addPath(path)