FS#2592 - Draw > Circle > Circle2TP: Missing solutions with circles
Andrew,
Related topic: https://www.qcad.org/rsforum/viewtopic.php?f=32&t=10960
This special case of the Apollonius’ problem has generally up to 4 solutions.
Type 7: https://en.wikipedia.org/wiki/Special_cases_of_Apollonius%27_problem
Several test revealed that there are quite a few solutions missing.
See: CT2-limitations.dxf .. Layer: Expected Solutions .. Points displayed in Mode 35
First I adapted the code of Apollonius.getSolutionsPCC for each unsupported or incomplete case. It looked over-complicated even when simplified.
After a while I discovered that the origin of the flaws is:
- ShapeAlgorithms.getTangents(...); ... See FS#2588
- Apollonius.getCommonTangents(...); ... See FS#2589
getTangents() results differ depending the order of the circle shapes.
getCommonTangents() may fail all together.
Concentric or nested circles are excluded.
Typically both resources don’t return a tangent line for the case:
- Where circles touch internally/externally.
- A line and a circle shape.
That last is somewhat special ... We enter the realm of infinity. We know that some inversions of circles may result in an endless line or better: A circle with infinite radius.
The tangents of an endless line and a circle are 2 parallels that are tangent to the circle.
These two parallel lines are considered to be tangent at infinity.
And then it doesn’t matter how far apart the line and the circle are.
The code for Apollonius.getSolutionsPCC can then be simplified drastically.
All solutions (⩽4) in about 10 functional lines of code.
Based on an enhanced algorithm that returns all possible tangent shapes.
/**
* \author Andrew Mustun, CVH © 2024
* \return Solutions for circles (<=4) that are tangential to the two given circles
* and the given point.
*/
Apollonius.getSolutionsPCC = function(point, circle1, circle2) {
if (!isPointShape(point) ||
!isCircleShape(circle1) ||
!isCircleShape(circle2)) {
return []; // Empty, no solutions
}
// Relative sized inversion circle (FS#2590):
var rInv = circle1.getRadius();
if (circle2.radius > circle1.radius) {
rInv = circle2.getRadius();
}
var inversionCircle = new RCircle(point.getPosition(), rInv);
// Construct inversion shapes:
var c1Inverse = Apollonius.getInverseShape(circle1, inversionCircle);
var c2Inverse = Apollonius.getInverseShape(circle2, inversionCircle);
// Get all tangent shapes for given inversion shapes:
// Exploits an enhanced algorithm by CVH
var tangents = Apollonius.getAllTangents(c1Inverse, c2Inverse);
// Return the re-inversion of all tangents (0-4 solutions):
return Apollonius.getInverseShapes(tangents, inversionCircle);
};
There is the rare case that one of the solutions is a line (Circle with R=infinte).
But that is filtered out in Circle2TP.js
I included the above code as a js file: Apollonius.getSolutionsPCC.js
I also re-included the adapted tangents code ( FS#2589 ): Apollonius.getAllTangents.js
Regards,
CVH
Loading...
Available keyboard shortcuts
- Alt + ⇧ Shift + l Login Dialog / Logout
- Alt + ⇧ Shift + a Add new task
- Alt + ⇧ Shift + m My searches
- Alt + ⇧ Shift + t focus taskid search
Tasklist
- o open selected task
- j move cursor down
- k move cursor up
Task Details
- n Next task
- p Previous task
- Alt + ⇧ Shift + e ↵ Enter Edit this task
- Alt + ⇧ Shift + w watch task
- Alt + ⇧ Shift + y Close Task
Task Editing
- Alt + ⇧ Shift + s save task