Skip to content

booleanEqual check does not properly handle precision #2530

@solarissmoke

Description

@solarissmoke

Turf version: 6.5.0/7.0.0a

The way booleanEqual check handles precision is incorrect. The following example illustrates the problem:

const point1 = {"type": "Point", "coordinates": [100.55719328, 23.0365925]}
const point2 = {"type": "Point", "coordinates": [100.55719327926636, 23.03659249995325]}

booleanEqual(point1, point2, {precision: 7})   // returns true
booleanEqual(point1, point2, {precision: 6})   // returns false !

This is incorrect. If two points are equal to a precision of 7, then by definition they must be equal to a precision of 6 as well. The problem here arises from the underlying implementation of GeojsonEquality, which uses toFixed to round the coordinates. The problem is that this introduces rounding errors that then cause the equality check to fail:

const a = 23.0365925;
const b = 23.03659249995325;

a.toFixed(6) // returns "23.036593"
b.toFixed(6) // returns "23.036592" 

a.toFixed(7) // returns "23.0365925"
b.toFixed(7) // returns "23.0365925" 

a.toFixed(6) === b.toFixed(6) // returns false
a.toFixed(7) === b.toFixed(7) // returns true

I think the correct behaviour here is not to use toFixed() but to check that both values fall within the acceptable precision, e.g., like this:

Math.abs(a - b) < (10**-6) // returns true, as expected
Math.abs(a - b) < (10**-7) // returns true, as expected

Which likely needs to be fixed upstream in GeojsonEquality (I've filed a bug there too), or that logic replaced entirely in turf.

My suggestion is to drop the dependency on geojson-equality and implement it afresh here, which will allow updating the implementation to use typescript - more than happy to make a PR if the maintainers here agree.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions