-
Notifications
You must be signed in to change notification settings - Fork 33
/
Copy pathboolean_crosses.dart
140 lines (131 loc) · 4.48 KB
/
boolean_crosses.dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
import 'package:turf/src/invariant.dart';
import '../../helpers.dart';
import '../line_intersect.dart';
import '../polygon_to_line.dart';
import 'boolean_point_in_polygon.dart';
import 'boolean_point_on_line.dart';
/// [booleanCrosses] returns [true] if the intersection results in a geometry whose
/// dimension is one less than the maximum dimension of the two source geometries
/// and the intersection set is interior to both source geometries.
/// [booleanCrosses] returns [true] for only [MultiPoint]/[Polygon], [MultiPoint]/[LineString],
/// [LineString]/[LineString], [LineString]/[Polygon], and [LineString]/[MultiPolygon] comparisons.
/// Other comparisons are not supported as they are outside the OpenGIS Simple
/// [Feature]s spec and may give unexpected results.
/// example:
/// ```dart
/// var line1 = LineString(coordinates: [
/// Position.of([-2, 2]),
/// Position.of([4, 2])
/// ]);
/// var line2 = LineString(coordinates: [
/// Position.of([1, 1]),
/// Position.of([1, 2]),
/// Position.of([1, 3]),
/// Position.of([1, 4])
/// ]);
/// var cross = booleanCrosses(line1, line2);
/// //=true
/// ```
bool booleanCrosses(GeoJSONObject feature1, GeoJSONObject feature2) {
var geom1 = getGeom(feature1);
var geom2 = getGeom(feature2);
var exception = Exception("$geom2 is not supported");
if (geom1 is MultiPoint) {
if (geom2 is LineString) {
return _doMultiPointAndLineStringCross(geom1, geom2);
} else if (geom2 is Polygon) {
return _doesMultiPointCrossPoly(geom1, geom2);
} else {
throw exception;
}
} else if (geom1 is LineString) {
if (geom2 is MultiPoint) {
// An inverse operation
return _doMultiPointAndLineStringCross(geom2, geom1);
} else if (geom2 is LineString) {
return _doLineStringsCross(geom1, geom2);
} else if (geom2 is Polygon) {
return _doLineStringAndPolygonCross(geom1, geom2);
} else {
throw exception;
}
} else if (geom1 is Polygon) {
if (geom2 is MultiPoint) {
// An inverse operation
return _doesMultiPointCrossPoly(geom2, geom1);
} else if (geom2 is LineString) {
// An inverse operation
return _doLineStringAndPolygonCross(geom2, geom1);
} else {
throw exception;
}
} else {
throw exception;
}
}
bool _doMultiPointAndLineStringCross(
MultiPoint multiPoint, LineString lineString) {
var foundIntPoint = false;
var foundExtPoint = false;
var pointLength = multiPoint.coordinates.length;
var i = 0;
while (i < pointLength && !foundIntPoint && !foundExtPoint) {
for (var i2 = 0; i2 < lineString.coordinates.length - 1; i2++) {
var incEndVertices = true;
if (i2 == 0 || i2 == lineString.coordinates.length - 2) {
incEndVertices = false;
}
if (isPointOnLineSegmentCrossesVariant(
lineString.coordinates[i2],
lineString.coordinates[i2 + 1],
multiPoint.coordinates[i],
incEndVertices)) {
foundIntPoint = true;
} else {
foundExtPoint = true;
}
}
i++;
}
return foundIntPoint && foundExtPoint;
}
bool _doLineStringsCross(LineString lineString1, LineString lineString2) {
var doLinesIntersect = lineIntersect(lineString1, lineString2);
if (doLinesIntersect.features.isNotEmpty) {
for (var i = 0; i < lineString1.coordinates.length - 1; i++) {
for (var i2 = 0; i2 < lineString2.coordinates.length - 1; i2++) {
var incEndVertices = true;
if (i2 == 0 || i2 == lineString2.coordinates.length - 2) {
incEndVertices = false;
}
if (isPointOnLineSegmentCrossesVariant(
lineString1.coordinates[i],
lineString1.coordinates[i + 1],
lineString2.coordinates[i2],
incEndVertices)) {
return true;
}
}
}
}
return false;
}
bool _doLineStringAndPolygonCross(LineString lineString, Polygon polygon) {
Feature line = polygonToLine(polygon) as Feature;
var doLinesIntersect = lineIntersect(lineString, line);
if (doLinesIntersect.features.isNotEmpty) return true;
return false;
}
bool _doesMultiPointCrossPoly(MultiPoint multiPoint, Polygon polygon) {
var foundIntPoint = false;
var foundExtPoint = false;
var pointLength = multiPoint.coordinates.length;
for (var i = 0; i < pointLength && (!foundIntPoint || !foundExtPoint); i++) {
if (booleanPointInPolygon(multiPoint.coordinates[i], polygon)) {
foundIntPoint = true;
} else {
foundExtPoint = true;
}
}
return foundExtPoint && foundIntPoint;
}