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

Implement booleanWithin #167

Merged
merged 17 commits into from
Feb 17, 2024
Merged
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ Any new benchmarks must be named `*_benchmark.dart` and reside in the
- [x] [booleanParallel](https://github.com/dartclub/turf_dart/blob/main/lib/src/booleans/boolean_parallel.dart)
- [x] [booleanPointInPolygon](https://github.com/dartclub/turf_dart/blob/main/lib/src/booleans/boolean_point_in_polygon.dart)
- [x] [booleanPointOnLine](https://github.com/dartclub/turf_dart/blob/main/lib/src/booleans/boolean_point_on_line.dart)
- [ ] booleanWithin
- [x] [booleanWithin](https://github.com/dartclub/turf_dart/blob/main/lib/src/booleans/boolean_within.dart)

### Unit Conversion

Expand All @@ -250,4 +250,4 @@ Any new benchmarks must be named `*_benchmark.dart` and reside in the
- [x] [radiansToLength](https://github.com/dartclub/turf_dart/blob/main/lib/src/helpers.dart)
- [x] [radiansToDegrees](https://github.com/dartclub/turf_dart/blob/main/lib/src/helpers.dart)
- [ ] toMercator
- [ ] toWgs84
- [ ] toWgs84
16 changes: 16 additions & 0 deletions lib/boolean.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
library turf_boolean;

export 'src/booleans/boolean_clockwise.dart';
export 'src/booleans/boolean_concave.dart';
export 'src/booleans/boolean_contains.dart';
export 'src/booleans/boolean_crosses.dart';
export 'src/booleans/boolean_disjoint.dart';
export 'src/booleans/boolean_equal.dart';
export 'src/booleans/boolean_intersects.dart';
// export 'src/booleans/boolean_overlap.dart';
export 'src/booleans/boolean_parallel.dart';
export 'src/booleans/boolean_point_in_polygon.dart';
export 'src/booleans/boolean_point_on_line.dart';
export 'src/booleans/boolean_touches.dart';
export 'src/booleans/boolean_valid.dart';
export 'src/booleans/boolean_within.dart';
130 changes: 22 additions & 108 deletions lib/src/booleans/boolean_contains.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'package:turf/turf.dart';

import 'boolean_point_in_polygon.dart';
import 'boolean_point_on_line.dart';
import 'boolean_helper.dart';

/// [booleanContains] returns [true] if the second geometry is completely contained
/// by the first geometry.
Expand All @@ -11,162 +12,75 @@ import 'boolean_point_on_line.dart';
/// [booleanContains] returns the exact opposite result of the [booleanWithin].
/// example:
/// ```dart
/// var line = LineString(coordinates: [
/// final line = LineString(coordinates: [
/// Position.of([1, 1]),
/// Position.of([1, 2]),
/// Position.of([1, 3]),
/// Position.of([1, 4])
/// ]);
/// var point = Point(coordinates: Position.of([1, 2]));
/// final point = Point(coordinates: Position.of([1, 2]));
/// booleanContains(line, point);
/// //=true
/// ```
bool booleanContains(GeoJSONObject feature1, GeoJSONObject feature2) {
var geom1 = getGeom(feature1);
var geom2 = getGeom(feature2);
final geom1 = getGeom(feature1);
final geom2 = getGeom(feature2);

var coords1 = (geom1 as GeometryType).coordinates;
var coords2 = (geom2 as GeometryType).coordinates;
final exception = Exception("{feature2 $geom2 geometry not supported}");
final coords1 = (geom1 as GeometryType).coordinates;
final coords2 = (geom2 as GeometryType).coordinates;
if (geom1 is Point) {
if (geom2 is Point) {
return coords1 == coords2;
} else {
throw exception;
throw FeatureNotSupported(geom1, geom2);
}
} else if (geom1 is MultiPoint) {
if (geom2 is Point) {
return _isPointInMultiPoint(geom1, geom2);
return isPointInMultiPoint(geom2, geom1);
} else if (geom2 is MultiPoint) {
return _isMultiPointInMultiPoint(geom1, geom2);
return isMultiPointInMultiPoint(geom2, geom1);
} else {
throw exception;
throw FeatureNotSupported(geom1, geom2);
}
} else if (geom1 is LineString) {
if (geom2 is Point) {
return booleanPointOnLine(geom2, geom1, ignoreEndVertices: true);
} else if (geom2 is LineString) {
return _isLineOnLine(geom1, geom2);
return isLineOnLine(geom2, geom1);
} else if (geom2 is MultiPoint) {
return _isMultiPointOnLine(geom1, geom2);
return isMultiPointOnLine(geom2, geom1);
} else {
throw exception;
throw FeatureNotSupported(geom1, geom2);
}
} else if (geom1 is Polygon) {
if (geom2 is Point) {
return booleanPointInPolygon((geom2).coordinates, geom1,
ignoreBoundary: true);
} else if (geom2 is LineString) {
return _isLineInPoly(geom1, geom2);
return isLineInPolygon(geom2, geom1);
} else if (geom2 is Polygon) {
return _isPolyInPoly(geom1, geom2);
} else if (geom2 is MultiPoint) {
return _isMultiPointInPoly(geom1, geom2);
return isMultiPointInPolygon(geom2, geom1);
} else {
throw exception;
throw FeatureNotSupported(geom1, geom2);
}
} else {
throw exception;
throw FeatureNotSupported(geom1, geom2);
}
}

bool _isPointInMultiPoint(MultiPoint multiPoint, Point pt) {
for (int i = 0; i < multiPoint.coordinates.length; i++) {
if ((multiPoint.coordinates[i] == pt.coordinates)) {
return true;
}
}
return false;
}

bool _isMultiPointInMultiPoint(MultiPoint multiPoint1, MultiPoint multiPoint2) {
for (Position coord2 in multiPoint2.coordinates) {
bool match = false;
for (Position coord1 in multiPoint1.coordinates) {
if (coord2 == coord1) {
match = true;
}
}
if (!match) return false;
}
return true;
}

bool _isMultiPointOnLine(LineString lineString, MultiPoint multiPoint) {
var haveFoundInteriorPoint = false;
for (var coord in multiPoint.coordinates) {
if (booleanPointOnLine(Point(coordinates: coord), lineString,
ignoreEndVertices: true)) {
haveFoundInteriorPoint = true;
}
if (!booleanPointOnLine(Point(coordinates: coord), lineString)) {
return false;
}
}
return haveFoundInteriorPoint;
}

bool _isMultiPointInPoly(Polygon polygon, MultiPoint multiPoint) {
for (var coord in multiPoint.coordinates) {
if (!booleanPointInPolygon(coord, polygon, ignoreBoundary: true)) {
return false;
}
}
return true;
}

bool _isLineOnLine(LineString lineString1, LineString lineString2) {
var haveFoundInteriorPoint = false;
for (Position coord in lineString2.coordinates) {
if (booleanPointOnLine(
Point(coordinates: coord),
lineString1,
ignoreEndVertices: true,
)) {
haveFoundInteriorPoint = true;
}
if (!booleanPointOnLine(
Point(coordinates: coord),
lineString1,
ignoreEndVertices: false,
)) {
return false;
}
}
return haveFoundInteriorPoint;
}

bool _isLineInPoly(Polygon polygon, LineString linestring) {
var polyBbox = bbox(polygon);
var lineBbox = bbox(linestring);
if (!_doBBoxesOverlap(polyBbox, lineBbox)) {
return false;
}
for (var i = 0; i < linestring.coordinates.length - 1; i++) {
var midPoint =
midpointRaw(linestring.coordinates[i], linestring.coordinates[i + 1]);
if (booleanPointInPolygon(
midPoint,
polygon,
ignoreBoundary: true,
)) {
return true;
}
}
return false;
}

/// Is Polygon2 in Polygon1
/// Only takes into account outer rings
bool _isPolyInPoly(GeoJSONObject geom1, GeoJSONObject geom2) {
var poly1Bbox = bbox(geom1);
var poly2Bbox = bbox(geom2);
final poly1Bbox = bbox(geom1);
final poly2Bbox = bbox(geom2);
if (!_doBBoxesOverlap(poly1Bbox, poly2Bbox)) {
return false;
}

for (var ring in (geom2 as GeometryType).coordinates) {
for (var coord in ring) {
for (final ring in (geom2 as GeometryType).coordinates) {
for (final coord in ring) {
if (!booleanPointInPolygon(coord, geom1)) {
return false;
}
Expand Down
Loading
Loading