Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose options parameter to @turf/boolean-intersects and @turf/booean-disjoint to add option of ignoring self intersections. #2636

Merged
merged 10 commits into from
Aug 5, 2024
Merged
9 changes: 7 additions & 2 deletions packages/turf-boolean-disjoint/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ Boolean-disjoint returns (TRUE) if the intersection of the two geometries is an

* `feature1` **([Geometry][1] | [Feature][2]\<any>)** GeoJSON Feature or Geometry
* `feature2` **([Geometry][1] | [Feature][2]\<any>)** GeoJSON Feature or Geometry
* `options` **[Object][3]** Optional parameters (optional, default `{}`)

* `options.ignoreSelfIntersections` **[boolean][4]** ignores self-intersections on input features (optional, default `false`)

### Examples

Expand All @@ -21,13 +24,15 @@ turf.booleanDisjoint(line, point);
//=true
```

Returns **[boolean][3]** true/false
Returns **[boolean][4]** true if the intersection is an empty set, false otherwise

[1]: https://tools.ietf.org/html/rfc7946#section-3.1

[2]: https://tools.ietf.org/html/rfc7946#section-3.2

[3]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean
[3]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object

[4]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean

<!-- This file is automatically generated. Please don't edit it directly. If you find an error, edit the source file of the module in question (likely index.js or index.ts), and re-run "yarn docs" from the root of the turf project. -->

Expand Down
83 changes: 61 additions & 22 deletions packages/turf-boolean-disjoint/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import { Feature, Geometry, LineString, Point, Polygon } from "geojson";
import {
Feature,
Geometry,
LineString,
Point,
Polygon,
Position,
} from "geojson";
import { booleanPointInPolygon } from "@turf/boolean-point-in-polygon";
import { lineIntersect } from "@turf/line-intersect";
import { flattenEach } from "@turf/meta";
Expand All @@ -10,7 +17,9 @@ import { polygonToLine } from "@turf/polygon-to-line";
* @name booleanDisjoint
* @param {Geometry|Feature<any>} feature1 GeoJSON Feature or Geometry
* @param {Geometry|Feature<any>} feature2 GeoJSON Feature or Geometry
* @returns {boolean} true/false
* @param {Object} [options={}] Optional parameters
* @param {boolean} [options.ignoreSelfIntersections=false] ignores self-intersections on input features
* @returns {boolean} true if the intersection is an empty set, false otherwise
* @example
* var point = turf.point([2, 2]);
* var line = turf.lineString([[1, 1], [1, 2], [1, 3], [1, 4]]);
Expand All @@ -20,15 +29,25 @@ import { polygonToLine } from "@turf/polygon-to-line";
*/
function booleanDisjoint(
feature1: Feature<any> | Geometry,
feature2: Feature<any> | Geometry
feature2: Feature<any> | Geometry,
options: {
ignoreSelfIntersections?: boolean;
} = {}
): boolean {
const ignoreSelfIntersections: boolean =
options.ignoreSelfIntersections ?? false;

let bool = true;
flattenEach(feature1, (flatten1) => {
smallsaucepan marked this conversation as resolved.
Show resolved Hide resolved
flattenEach(feature2, (flatten2) => {
if (bool === false) {
return false;
}
bool = disjoint(flatten1.geometry, flatten2.geometry);
bool = disjoint(
flatten1.geometry,
flatten2.geometry,
ignoreSelfIntersections
);
});
});
return bool;
Expand All @@ -40,11 +59,13 @@ function booleanDisjoint(
* @private
* @param {Geometry<any>} geom1 GeoJSON Geometry
* @param {Geometry<any>} geom2 GeoJSON Geometry
* @returns {boolean} true/false
* @param {boolean} ignoreSelfIntersections ignore self-intersections on input features
* @returns {boolean} true if disjoint, false otherwise
*/
function disjoint(geom1: any, geom2: any) {
function disjoint(geom1: any, geom2: any, ignoreSelfIntersections: boolean) {
switch (geom1.type) {
case "Point":
/* eslint-disable @typescript-eslint/no-unused-vars */
switch (geom2.type) {
case "Point":
return !compareCoords(geom1.coordinates, geom2.coordinates);
Expand All @@ -60,9 +81,9 @@ function disjoint(geom1: any, geom2: any) {
case "Point":
return !isPointOnLine(geom1, geom2);
case "LineString":
return !isLineOnLine(geom1, geom2);
return !isLineOnLine(geom1, geom2, ignoreSelfIntersections);
case "Polygon":
return !isLineInPoly(geom2, geom1);
return !isLineInPoly(geom2, geom1, ignoreSelfIntersections);
}
/* istanbul ignore next */
break;
Expand All @@ -71,9 +92,9 @@ function disjoint(geom1: any, geom2: any) {
case "Point":
return !booleanPointInPolygon(geom2, geom1);
case "LineString":
return !isLineInPoly(geom1, geom2);
return !isLineInPoly(geom1, geom2, ignoreSelfIntersections);
case "Polygon":
return !isPolyInPoly(geom2, geom1);
return !isPolyInPoly(geom2, geom1, ignoreSelfIntersections);
}
}
return false;
Expand All @@ -95,21 +116,33 @@ function isPointOnLine(lineString: LineString, pt: Point) {
return false;
}

function isLineOnLine(lineString1: LineString, lineString2: LineString) {
const doLinesIntersect = lineIntersect(lineString1, lineString2);
function isLineOnLine(
lineString1: LineString,
lineString2: LineString,
ignoreSelfIntersections: boolean
) {
const doLinesIntersect = lineIntersect(lineString1, lineString2, {
ignoreSelfIntersections,
});
if (doLinesIntersect.features.length > 0) {
return true;
}
return false;
}

function isLineInPoly(polygon: Polygon, lineString: LineString) {
function isLineInPoly(
polygon: Polygon,
lineString: LineString,
ignoreSelfIntersections: boolean
) {
for (const coord of lineString.coordinates) {
if (booleanPointInPolygon(coord, polygon)) {
return true;
}
}
const doLinesIntersect = lineIntersect(lineString, polygonToLine(polygon));
const doLinesIntersect = lineIntersect(lineString, polygonToLine(polygon), {
ignoreSelfIntersections,
});
if (doLinesIntersect.features.length > 0) {
return true;
}
Expand All @@ -124,9 +157,14 @@ function isLineInPoly(polygon: Polygon, lineString: LineString) {
* @private
* @param {Geometry|Feature<Polygon>} feature1 Polygon1
* @param {Geometry|Feature<Polygon>} feature2 Polygon2
* @returns {boolean} true/false
* @param {boolean} ignoreSelfIntersections ignore self-intersections on input features
* @returns {boolean} true if geom1 is in geom2, false otherwise
*/
function isPolyInPoly(feature1: Polygon, feature2: Polygon) {
function isPolyInPoly(
feature1: Polygon,
feature2: Polygon,
ignoreSelfIntersections: boolean
) {
for (const coord1 of feature1.coordinates[0]) {
if (booleanPointInPolygon(coord1, feature2)) {
return true;
Expand All @@ -139,7 +177,8 @@ function isPolyInPoly(feature1: Polygon, feature2: Polygon) {
}
const doLinesIntersect = lineIntersect(
polygonToLine(feature1),
polygonToLine(feature2)
polygonToLine(feature2),
{ ignoreSelfIntersections }
);
if (doLinesIntersect.features.length > 0) {
return true;
Expand All @@ -148,9 +187,9 @@ function isPolyInPoly(feature1: Polygon, feature2: Polygon) {
}

function isPointOnLineSegment(
lineSegmentStart: number[],
lineSegmentEnd: number[],
pt: number[]
lineSegmentStart: Position,
lineSegmentEnd: Position,
pt: Position
) {
const dxc = pt[0] - lineSegmentStart[0];
const dyc = pt[1] - lineSegmentStart[1];
Expand Down Expand Up @@ -179,9 +218,9 @@ function isPointOnLineSegment(
* @private
* @param {Position} pair1 point [x,y]
* @param {Position} pair2 point [x,y]
* @returns {boolean} true/false if coord pairs match
* @returns {boolean} true if coord pairs match, false otherwise
*/
function compareCoords(pair1: number[], pair2: number[]) {
function compareCoords(pair1: Position, pair2: Position) {
return pair1[0] === pair2[0] && pair1[1] === pair2[1];
}

Expand Down
136 changes: 136 additions & 0 deletions packages/turf-boolean-disjoint/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,139 @@ test("turf-boolean-disjoint", (t) => {
});
t.end();
});

test("turf-boolean-disjoin with ignoreSelfIntersections option", (t) => {
const selfIntersectingLineString: GeoJSON.Feature<GeoJSON.LineString> = {
type: "Feature",
properties: {},
geometry: {
type: "LineString",
coordinates: [
[1, 1],
[2, 2],
[1, 2],
[2, 1],
],
},
};

const nonIntersectingLineString: GeoJSON.Feature<GeoJSON.LineString> = {
type: "Feature",
properties: {},
geometry: {
type: "LineString",
coordinates: [
[0, 1],
[0, 0],
],
},
};

const intersectingLineString: GeoJSON.Feature<GeoJSON.LineString> = {
type: "Feature",
properties: {},
geometry: {
type: "LineString",
coordinates: [
[0, 1],
[4, 2],
],
},
};

const intersectingPolygon: GeoJSON.Feature<GeoJSON.Polygon> = {
type: "Feature",
properties: {},
geometry: {
type: "Polygon",
coordinates: [
[
[1.5, 1],
[2, 1.5],

[3, 0.5],
[1.5, 1],
],
],
},
};

const nonIntersectingPolygon: GeoJSON.Feature<GeoJSON.Polygon> = {
type: "Feature",
properties: {},
geometry: {
type: "Polygon",
coordinates: [
[
[0.5, 0],
[1, 0.5],

[2, -0.5],
[0.5, 0],
],
],
},
};

// Test without ignoringSelfIntersections option (default behavior)
let result = disjoint(selfIntersectingLineString, nonIntersectingLineString);
t.false(
result,
"[false] " +
"selfIntersectingLineString-LineString (ignoreSelfIntersections=false)"
);
result = disjoint(selfIntersectingLineString, intersectingLineString);
t.false(
result,
"[false] " +
"selfIntersectingLineString-LineString (ignoreSelfIntersections=false)"
);
result = disjoint(selfIntersectingLineString, intersectingPolygon);
t.false(
result,
"[false] " +
"selfIntersectingLineString-Polygon (ignoreSelfIntersections=false)"
);
result = disjoint(selfIntersectingLineString, nonIntersectingPolygon);
t.false(
result,
"[false] " +
"selfIntersectingLineString-Polygon (ignoreSelfIntersections=false)"
);

// Test with ignoringSelfIntersections option
result = disjoint(selfIntersectingLineString, nonIntersectingLineString, {
ignoreSelfIntersections: true,
});
t.true(
result,
"[true] " +
"selfIntersectingLineString-LineString (ignoreSelfIntersections=true)"
);
result = disjoint(selfIntersectingLineString, intersectingLineString, {
ignoreSelfIntersections: true,
});
t.false(
result,
"[false] " +
"selfIntersectingLineString-LineString (ignoreSelfIntersections=true)"
);
result = disjoint(selfIntersectingLineString, intersectingPolygon, {
ignoreSelfIntersections: true,
});
t.false(
result,
"[false] " +
"selfIntersectingLineString-Polygon (ignoreSelfIntersections=true)"
);
result = disjoint(selfIntersectingLineString, nonIntersectingPolygon, {
ignoreSelfIntersections: true,
});
t.true(
result,
"[true] " +
"selfIntersectingLineString-Polygon (ignoreSelfIntersections=true)"
);

t.end();
});
9 changes: 7 additions & 2 deletions packages/turf-boolean-intersects/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ Boolean-intersects returns (TRUE) if the intersection of the two geometries is N

* `feature1` **([Geometry][1] | [Feature][2]\<any>)** GeoJSON Feature or Geometry
* `feature2` **([Geometry][1] | [Feature][2]\<any>)** GeoJSON Feature or Geometry
* `options` **[Object][3]** Optional parameters (optional, default `{}`)

* `options.ignoreSelfIntersections` **[boolean][4]** ignores self-intersections on input features (optional, default `false`)

### Examples

Expand All @@ -30,13 +33,15 @@ point1.properties['marker-color'] = '#f00'
point2.properties['marker-color'] = '#0f0'
```

Returns **[boolean][3]** true/false
Returns **[boolean][4]** true if geometries intersect, false otherwise

[1]: https://tools.ietf.org/html/rfc7946#section-3.1

[2]: https://tools.ietf.org/html/rfc7946#section-3.2

[3]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean
[3]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object

[4]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean

<!-- This file is automatically generated. Please don't edit it directly. If you find an error, edit the source file of the module in question (likely index.js or index.ts), and re-run "yarn docs" from the root of the turf project. -->

Expand Down
Loading
Loading