Exceptions with AT (ArcTPR.js)

If you are having problems with QCAD, post here. Please report bugs through our Bug Tracker instead.

Always attach your original DXF or DWG file and mentions your QCAD version and the platform you are on.

Moderator: andrew

Forum rules

Always indicate your operating system and QCAD version.

Attach drawing files and screenshots.

Post one question per topic.

Post Reply
CVH
Premier Member
Posts: 4955
Joined: Wed Sep 27, 2017 4:17 pm

Exceptions with AT (ArcTPR.js)

Post by CVH » Fri Dec 13, 2024 5:43 pm

Andrew,

Related topic.
Even after the recent commit there are exceptions with the AT method.

As pointed out in the German topic:
The loci of center points are circles with tangent entity radius PLUS the required radius and MINUS the required radius.
Because the subtraction may become negative we normalize the locus shapes with Math.abs(...)
When that becomes zero we omit the second locus as parallel shape.

For line based shapes as tangent entity it is not well defined what to do when the point is on the line.
In that case we must include both parallels at either side of the line.
The solutions are then 2 pairs of full circular arcs.
As is, the single solution may swap sides while moving along the line.

And as pointed out:
I don't get any solutions for ellipses (Win7, Qt5.13.2, i386, QCAD Pro)
The array of intersections between an offset fitpoint RSpline and an RCircle is always empty.
For that case we must include both offset shapes (RSplines) because the inner offset may have a weird, unexpected shape.
(Thaw layer 'Construction' in the example file)

ArcTPR-TestOfUpdate.dxf
Visible green are NOT proposed as solutions
(156.86 KiB) Downloaded 390 times

'Expected Solutions' (Dark Green) are generated with this code:
(Except the manually drawn solutions for the ellipse :wink: )

Code: Select all

...
    if (isNull(this.candidates)) {
        this.candidates = [];

// Modification by CVH
        var parallels = [];
        // Include 1-2 offsets (QSharedPointer) for lineBased:
        if (isLineBasedShape(this.shape1)) {
            // This would convert RXLine and RRay shapes:
            var line = new RLine(this.shape1.getStartPoint(), this.shape1.getEndPoint());
            // Diversify between on or not on the shape:
            if (line.isOnShape(this.pos, false)) {    // Unlimited, RS.PointTolerance
                parallels = RShape.getOffsetLines(line, this.radius, 1, RS.BothSides, RVector.invalid);
            }
            else {
                parallels = RShape.getOffsetLines(line, this.radius, 1, RS.NoSide, this.pos);
            }
        }

        // Include 1-2 offset shapes (RCircle) for arcs or circles:
        else if (isArcShape(this.shape1) || isCircleShape(this.shape1)) {
            parallels.push(new RCircle(this.shape1.getCenter(), this.radius + this.shape1.getRadius()));
            // Avoid a zero radius for the second offset, normalized:
            if (!RMath.fuzzyCompare(this.radius, this.shape1.getRadius())) {    // RS.PointTolerance
                parallels.push(new RCircle(this.shape1.getCenter(), Math.abs(this.radius - this.shape1.getRadius())));
            }
        }

        // Include both offsets (QSharedPointer) for ellipses:
        // # Issue # Not functional, ips is always empty
        else if (isEllipseShape(this.shape1)) {
            parallels = this.shape1.getOffsetShapes(this.radius, 1, RS.BothSides);
        }
// End modification by CVH

        // circle around pos:
        var circle = new RCircle(this.pos, this.radius);
...
Regards,
CVH

CVH
Premier Member
Posts: 4955
Joined: Wed Sep 27, 2017 4:17 pm

Re: Exceptions with AT (ArcTPR.js)

Post by CVH » Mon Dec 16, 2024 2:28 pm

Turns out that supporting ellipses was never functional.

An (outer) offset to an ellipse is constructed as a fit-point spline.
var ips = parallel.getIntersectionPoints(circle, false); is then always empty.

The method is broken or simply NOT implemented for fit-point splines ...
(Since before QCAD 3.27.6.0 :shock: )
:arrow: Added Bug Report FS#2620

My first remark then: The offsets to a full ellipse are NOT at all symmetrical.
The ellipse is processed for parameter t = 0 ... 2pi stepping 0.1 rads ... Hence 63 fit-points.
A point at t = pi, the opposite side on the major axis, is not defined (... 3.0 - 3.1 -?- 3.2 - 3.3 ...)
Nor are points at pi/2 or 3pi/2 defined (Minor points).
The offset in these points is so straightforward that at least these should match.

FIX: I mimicked REllipse::getOffsetShapes for t = 0 ... 360, every 3 degrees and then in rads.
Resulting in 4 equal and symmetrical quadrants.
Constructed both inner and outer once, each split in two parts to get 4 control-points splines in direct.
Circle intersections with such a type of spline is functional.

Second remark: It was never intended to include "internally tangent" and certainly not for ellipses.
var p = shape.getClosestPointOnShape(ip, false);
The closest point P, or the normal IP-P for a line or a circle is well defined.
With a circle shape, point P' will never be returned but not entirely by luck it is in the same direction as P.
=> The ArcTPR method only uses the orientation to cut up the resulting arcs.
:arrow: Added a feature request FS#2621 for the Perpendicular Snap point at the opposite side of a circle.

ArcTPR-Issue.png
ArcTPR-Issue.png (24.07 KiB) Viewed 6893 times

This is not at all functional for the other normal points A-B-C with an ellipse shape.
And then I have my reserves about the returned position of P.
Verifying if the point is on the ellipse: X²/a²+Y²/b²=1 kinda agrees but then with too much tolerance.

FIX: A far better algorithm to define the closest point on an ellipse.
For example based on Simple Method for Distance to Ellipse or trig-free modification
The result converges in a few iterations to within the limits of the floating point system.


But that doesn't fix things for "internally tangent", for normals in point A, B and/or C.
Simplistic FIX: Don't include such results.

Real FIX: Only solved satisfactorily with solving for roots of a general Quartic.
ISSUE: RMath.getBiQuadRoots(...) and other root solvers are not exposed, "Non-Scriptable".

Finding only the tangent intersections of a circle and an ellipse was also not satisfactory because of the poor results.
A normal should always be an angle bisector of the angle in regards with the ellipse foci ... Or nearly.
And as above, the point should be on the circle shape: (x-xc)²+(y-yc)²=r² AND on the ellipse shape: X²/a²+Y²/b²=1 ... Or nearly.

That didn't stop me to implement a general Quartic solver.
If IP to (A,B,C or P) was about of the intended radius then I knew where to trim the arcs correctly. :P
This time, with rather better accuracy than with any other approach.

Regards,
CVH

Post Reply

Return to “QCAD Troubleshooting and Problems”