HarryStevens / geometric

A JavaScript library for doing geometry.
https://www.npmjs.com/package/geometric
MIT License
970 stars 49 forks source link

Feature Request: Avoid Rounding Errors #19

Closed sus-mharder closed 3 years ago

sus-mharder commented 3 years ago

I'm using 'geometric' in a CAD project. I lately discovered false negatives from the function pointWithLine.

I copied the function and added an epsilon test. This resolved the issue.

export function pointWithLineWithEpsilon(point: Point, line: Line, epsilon: number = 1e-10) {
    const x = cross(point, line[0], line[1]);
    return Math.abs(x) < epsilon;
}

My suggeston would be to add an optional epsilon parameter to that function, as well as functions with similar cases.

HarryStevens commented 3 years ago

@sus-mharder Thanks for this idea. Can you also provide a point and line that currently fails so that I can reproduce this?

sus-mharder commented 3 years ago

Hi. Sorry for the delay.

I picked some of the results, where the false negatives occured.

{
    "point":[-50.94850158691406,-3.027209166609623],
    "line":[[-49.69850158691406,-3.0271999835968018],[-51.19850158687358,-3.027211003212187]]
}
{
    "point":[-46.8047,-12.1569],
    "line":[[-46.2164,-12.0707],[-47.700552783102914,-12.288163827814842]]
}
{
    "point":[-45.41063565015793,-6.862901151180267],
    "line":[[-44.59149932861328,-7.436500072479248],[-45.82020378894317,-6.576101705927197]]
}
{
    "point":[-46.22977195704452,-6.289302240145567],
    "line":[[-44.59149932861328,-7.436500072479248],[-45.82020378894317,-6.576101705927197]]
}
{
    "point":[-33.12336051464081,-15.46659255027771],
    "line":[[-33.942501068115234,-14.892999649047852],[-32.713790276416105,-15.753388973924736]]
}
{
    "point":[-32.30421998684139,-16.040185433528965],
    "line":[[-33.942501068115234,-14.892999649047852],[-32.713790276416105,-15.753388973924736]]
}
{
    "point":[-33.94243496656418,-14.89300149679184],
    "line":[[-33.12329864501953,-15.46660041809082],[-34.35200310534942,-14.60620205153877]]
}
{
    "point":[-34.76157127345077,-14.319402585757139],
    "line":[[-33.12329864501953,-15.46660041809082],[-34.35200310534942,-14.60620205153877]]
}
{
    "point":[-33.94245994091034,-14.892992734909058],
    "line":[[-34.761600494384766,-14.3193998336792],[-33.53288970268564,-15.179789158556083]]
}
{
    "point":[-33.12331941311092,-15.466585618160314],
    "line":[[-34.761600494384766,-14.3193998336792],[-33.53288970268564,-15.179789158556083]]
}
{
    "point":[-34.76163738965988,-14.31940072774887],
    "line":[[-33.942501068115234,-14.892999649047852],[-35.17120552844512,-14.0326012824958]]
}
HarryStevens commented 3 years ago

Thanks Mike. I'll take a look at this as soon as possible.

HarryStevens commented 3 years ago

@sus-mharder, you can now pass an optional epsilon number to pointOnLine, pointOnPolygon, and pointWithLine. For example:


const point = [-50.94850158691406,-3.027209166609623];
const line = [[-49.69850158691406,-3.0271999835968018],[-51.19850158687358,-3.027211003212187]];

geometric.pointWithLine(point, line); // false
geometric.pointWithLine(point, line, 1e-10); // true

I've incorporated your tests into the test suite: https://github.com/HarryStevens/geometric/blob/master/test/pointOnLine-test.js#L48