Stumbled on it again while reviewing Apollonius.js for enhancements, bugs (exceptions) and so on.
A few revisions have already made it to be part of the QCAD 3.31.0 release.
A technique used is the inversion through a circle, and then larger things become tiny while small things can get very big.
At some point solutions where filtered out on not touching the referenced entities.
More pronounced when things got small or when the overall scale was coin-size or smaller.
In special in the sub unit range.
Instead of failing for small numbers I rather see it not failing in any scale unless there is a reason to or the cost is to high.
Now ... Math won't fail for no reason, simplified and streamlined there is no extra cost for Apollonius.js, the opposite is true.
RLine.getVectorTo(point) returns:
- RVector.invalid when the length of the segment is strictly less that 1.0e-6.
--> Meaning: Can not compute based on determinant, the real mathematical limit is 'not divide by zero'.
- RVector.nullVector when the point is strictly less that 1.0e-6 in 2D away from the start point.
--> Meaning: Everything within the blue circle is considered as being the start point itself
- A mathematical solution what is a vector perpendicular to the line.
--> Where things near the endpoint don't play a favorite role.
The solution is then simple ...
- When the answer is invalid there is no answer (Can be false negative).
--> Ensure that line entities are at least longer than 1.0e-6 units.
- When the X and Y coordinate are exactly zero then the point might have been very near the start point.
--> Reverse the line and try again.
- Otherwise it is a well defined point, valid ifso.
getVectorTo(point) plays a key role in many QCAD resources, I would not adapt it in the core.
For those interested or when small values/differences may play a role:
In all simplicity var v = RLine.getVectorTo(point) can be implemented as:
Code: Select all
var v = line.getVectorTo(point);
if (isValid(v) && v.x === 0.0 && v.y === 0.0) {
line.reverse();
v = line.getVectorTo(point);
}Code: Select all
var v = line.getVectorTo(point);
if (isValid(v) && v.x === 0.0 && v.y === 0.0) {
line.reverse();
v = line.getVectorTo(point);
}
pp = v.operator_add(point);
};Code: Select all
var v = line.getVectorTo(point);
if (isValid(v) && v.x === 0.0 && v.y === 0.0) {
line.reverse();
v = line.getVectorTo(point);
}
pp = v.operator_add(point);
var dist = point.getDistanceTo(pp);
};Code: Select all
( dist < RS.PointTolerance ) Code: Select all
( point.equalsFuzzy(pp) ) Remark that it is RLine.vectorTo(point, true) by default when the boolean limited is not provided.
Then the vector points directly to the nearest endpoint A or B when there is no perpendicular position on the limited segment between AB.
Regards,
CVH