345 const QPointF &
p1 = radius1 < radius2 ? point2 : point1;
346 const QPointF &
p2 = radius1 < radius2 ? point1 : point2;
347 const qreal &
r1 = radius1 < radius2 ? radius2 : radius1;
348 const qreal &
r2 = radius1 < radius2 ? radius1 : radius2;
349 const QPointF deltaP1P2 =
p2 -
p1;
350 const qreal deltaR1R2 =
r1 -
r2;
351 QPointF tangentPointP11, tangentPointP12, tangentPointP21, tangentPointP22;
355 const qreal deltaP1P2Length = std::sqrt(deltaP1P2.x() * deltaP1P2.x() + deltaP1P2.y() * deltaP1P2.y());
356 const QPointF deltaP1P2Normalized = deltaP1P2 / deltaP1P2Length;
357 tangentPointP11 =
p1 + QPointF(deltaP1P2Normalized.y(), -deltaP1P2Normalized.x()) *
r1;
358 tangentPointP12 =
p1 + QPointF(-deltaP1P2Normalized.y(), deltaP1P2Normalized.x()) *
r1;
359 tangentPointP21 =
p2 + QPointF(deltaP1P2Normalized.y(), -deltaP1P2Normalized.x()) *
r2;
360 tangentPointP22 =
p2 + QPointF(-deltaP1P2Normalized.y(), deltaP1P2Normalized.x()) *
r2;
363 const QPointF tangentIntersectionPoint(
364 (
p2.x() *
r1 -
p1.x() *
r2) / deltaR1R2,
365 (
p2.y() *
r1 -
p1.y() *
r2) / deltaR1R2
367 auto f = [](qreal t1, qreal t2, qreal t3, qreal t4, qreal
sign) -> qreal
369 return (t1 +
sign * t2) / t3 + t4;
372 const qreal r1Squared =
r1 *
r1;
373 const QPointF deltaP1TangentIntersectionPoint = tangentIntersectionPoint -
p1;
374 const qreal deltaP1TangentIntersectionPointLengthSquared =
375 deltaP1TangentIntersectionPoint.x() * deltaP1TangentIntersectionPoint.x() +
376 deltaP1TangentIntersectionPoint.y() * deltaP1TangentIntersectionPoint.y();
377 const QPointF t11 = r1Squared * deltaP1TangentIntersectionPoint;
378 const QPointF t12 =
r1 * deltaP1TangentIntersectionPoint * std::sqrt(deltaP1TangentIntersectionPointLengthSquared - r1Squared);
379 tangentPointP11 = QPointF(
380 f(t11.x(), t12.y(), deltaP1TangentIntersectionPointLengthSquared,
p1.x(), 1.0),
381 f(t11.y(), t12.x(), deltaP1TangentIntersectionPointLengthSquared,
p1.y(), -1.0)
383 tangentPointP12 = QPointF(
384 f(t11.x(), t12.y(), deltaP1TangentIntersectionPointLengthSquared,
p1.x(), -1.0),
385 f(t11.y(), t12.x(), deltaP1TangentIntersectionPointLengthSquared,
p1.y(), 1.0)
389 const qreal r2Squared =
r2 *
r2;
390 const QPointF deltaP2TangentIntersectionPoint = tangentIntersectionPoint -
p2;
391 const qreal deltaP2TangentIntersectionPointLengthSquared =
392 deltaP2TangentIntersectionPoint.x() * deltaP2TangentIntersectionPoint.x() +
393 deltaP2TangentIntersectionPoint.y() * deltaP2TangentIntersectionPoint.y();
394 const QPointF t11 = r2Squared * deltaP2TangentIntersectionPoint;
395 const QPointF t12 =
r2 * deltaP2TangentIntersectionPoint * std::sqrt(deltaP2TangentIntersectionPointLengthSquared - r2Squared);
396 tangentPointP21 = QPointF(
397 f(t11.x(), t12.y(), deltaP2TangentIntersectionPointLengthSquared,
p2.x(), 1.0),
398 f(t11.y(), t12.x(), deltaP2TangentIntersectionPointLengthSquared,
p2.y(), -1.0)
400 tangentPointP22 = QPointF(
401 f(t11.x(), t12.y(), deltaP2TangentIntersectionPointLengthSquared,
p2.x(), -1.0),
402 f(t11.y(), t12.x(), deltaP2TangentIntersectionPointLengthSquared,
p2.y(), 1.0)
408 path.setFillRule(Qt::WindingFill);
409 path.moveTo(tangentPointP11);
410 path.lineTo(tangentPointP21);
411 path.lineTo(tangentPointP22);
412 path.lineTo(tangentPointP12);
414 path.addEllipse(point2, radius2, radius2);