QCAD Bugtracker

  • Status Assigned
  • Percent Complete
    0%
  • Task Type Bug Report
  • Category QCAD (main)
  • Assigned To
    Andrew
  • Operating System All
  • Severity Very Low
  • Priority Very Low
  • Reported Version 3.28.2
  • Due in Version Undecided
  • Due Date Undecided
  • Votes 1
    • CVH (25.10.2023)
  • Private
Attached to Project: QCAD Bugtracker
Opened by CVH - 25.10.2023

FS#2497 - Draw > Circle > 3 Tangents (CT3) fails in some cases with 3 circles

Andrew,

See attachment with example:

Solution included on layer ‘Solution’.

Regards,
CVH

26.10.2023 : A task closure has been requested. Reason for request: Problem solved, enhancements for Apollonius.getSolutionsCCC included
Admin
Andrew commented on 25.10.2023 14:52

This is a complex problem. QCAD uses the Apollonius algorithm and an alternative algorithm to come up with as many solutions as possible. However, it is a best effort type algorithm. There are very likely other scenarios where not all solution can be found (hence "no solution found").

CVH commented on 25.10.2023 15:40

There is but one solution inside the area of interest and its mirror.
Both their centers are on the Centerline.
There are indeed four more outside area of interest.

I am coding the locus of equidistant points between:
- 2 Points ⇒ RXline (Too easy ;-))
- Point vs Line segment ⇒ Up to 4 shapes (2 Quadratic RSpline's, 2RRay's)
- Point vs Arc segment ... Circle ⇒ ... Includes Hyperbola and former
- 2 Line segments ⇒ Up to 6 shapes (2 RLine's, 2 Quadratic RSpline's, 2RRay's)
- 2 Arc segments ... Circles ⇒ ... Includes Hyperbola and former

Work in process, the hyperbola is fairly good approximated by a cubic RSpline.
Fairly good but I store the coefficients of the implicit conic equation.
Regards,
CVH

CVH commented on 26.10.2023 09:35

Reviewing Apollonius.getSolutionsCCC
I read: special case: at least two circles are concentric: no solution:

When two circles are concentric there are an infinite amount of circles with radius rx=abs(r1-r2)/2 tangent to both.
The locus of the center points is itself a circle with r1+(r1-r2)/2.
All intersections of the locus and circles with radius r3-rx or r3+rx are solutions for centers of tangent circles with radius rx.

Simply a question to enhance Apollonius.getSolutionsCCC

If all three are concentric with different radii then there is no solution.
If 2 of them have the same radii then there are infinite solutions.

Regards,
CVH

CVH commented on 26.10.2023 12:52

Andrew,

I replaced in Apollonius.getSolutionsCCC:

    // special case: at least two circles are concentric: no solution:
    if (c1.center.equalsFuzzy(c2.center) ||
        c1.center.equalsFuzzy(c3.center) ||
        c2.center.equalsFuzzy(c3.center)) {

        return [];
    }

With the code below with good and stable results.

    // special case: at least two circles are concentric: no solution:
    // # Enhanced by CVH #
    // Verify if circle 1 is concentric with circle 2:
    if (c1.center.equalsFuzzy(c2.center)) {
        if (c1.center.equalsFuzzy(c3.center)) {
            // Failed: 3 concentric circles
            return [];    // No or infinite solutions
        }
        var rDiff = c1.getRadius() - c2.getRadius();
        var locus = c1.clone();
        circle1 = c3.clone();
    }
    // Verify if circle 1 is concentric with circle 3:
    else if (c1.center.equalsFuzzy(c3.center)) {
        if (c1.center.equalsFuzzy(c2.center)) {
            // Failed: 3 concentric circles
            return [];    // No or infinite solutions
        }
        var rDiff = c1.getRadius() - c3.getRadius();
        var locus = c1.clone();
        circle1 = c2.clone();
    }
    // Verify if circle 2 is concentric with circle 3:
    else if (c2.center.equalsFuzzy(c3.center)) {
        if (c2.center.equalsFuzzy(c1.center)) {
            // Failed: 3 concentric circles
            return [];    // No or infinite solutions
        }
        var rDiff = c2.getRadius() - c3.getRadius();
        var locus = c2.clone();
        circle1 = c1.clone();
    }

    // Handle two concentric circles:
    if (!isNull(locus)) {
        if (!isNumber(rDiff)) {
            return [];    // No solutions
        }
        if (RMath.fuzzyCompare(rDiff, 0.0)) {
            return [];    // Infinite solutions
        }

        // Get intersections of two concentric with the other circle and the locus:
        locus.setRadius(locus.getRadius() - rDiff / 2);
        circle1.setRadius(circle1.getRadius() - Math.abs(rDiff / 2));
        circle2 = circle1.clone();
        circle2.setRadius(circle1.getRadius() + Math.abs(rDiff));
        var ips = locus.getIntersectionPoints(circle1);
        ips = ips.concat(locus.getIntersectionPoints(circle2));

        // If any, create tangent circles at intersections;
        if (ips.length === 0) {
            return [];    // No solutions
        }
        for (var i=0; i<ips.length; i++) {
            ret.push(new RCircle(ips[i], Math.abs(rDiff / 2)));
        }

        ret = Apollonius.removeDuplicates(ret);    // Most likely none
        return ret;
    }
CVH commented on 12.11.2023 16:12

Newer art see PM Sat Nov 04, 2023 9:41 am
Avoid negative radii for intersections of locus/circle:

      // Get intersections of two concentric with the other circle and the locus:
      locus.setRadius(locus.getRadius() - rDiff / 2);
      circle1.setRadius(circle1.getRadius() + Math.abs(rDiff / 2));
      var ips = locus.getIntersectionPoints(circle1);
      circle1.setRadius(circle1.getRadius() - Math.abs(rDiff));
      // Avoid inversion through the center with negative radii:
      if (circle1.getRadius() > 0) {
          ips = ips.concat(locus.getIntersectionPoints(circle1));
      }

Regards,
CVH

Loading...

Available keyboard shortcuts

Tasklist

Task Details

Task Editing