1 package org.opentrafficsim.core.geometry;
2
3 import java.awt.geom.Line2D;
4 import java.awt.geom.Path2D;
5 import java.awt.geom.Point2D;
6 import java.awt.geom.Rectangle2D;
7 import java.util.ArrayList;
8 import java.util.Arrays;
9 import java.util.List;
10
11 import com.vividsolutions.jts.geom.Coordinate;
12 import com.vividsolutions.jts.geom.Geometry;
13 import com.vividsolutions.jts.geom.LineString;
14
15
16
17
18
19
20
21
22
23
24
25 public class OTSShape extends OTSLine3D
26 {
27
28 private static final long serialVersionUID = 20160331;
29
30
31 private Path2D shape = null;
32
33
34
35
36
37
38
39 public OTSShape(final OTSPoint3D... points) throws OTSGeometryException
40 {
41 super(points);
42 }
43
44
45
46
47
48
49
50 public OTSShape(final Coordinate[] coordinates) throws OTSGeometryException
51 {
52 super(coordinates);
53 }
54
55
56
57
58
59
60
61 public OTSShape(final LineString lineString) throws OTSGeometryException
62 {
63 super(lineString);
64 }
65
66
67
68
69
70
71
72 public OTSShape(final Geometry geometry) throws OTSGeometryException
73 {
74 super(geometry);
75 }
76
77
78
79
80
81
82
83 public OTSShape(final List<OTSPoint3D> pointList) throws OTSGeometryException
84 {
85 super(pointList);
86 }
87
88
89
90
91
92
93
94 public OTSShape(final Path2D path) throws OTSGeometryException
95 {
96 super(path);
97 }
98
99
100
101
102 public final Path2D getShape()
103 {
104 if (this.shape == null)
105 {
106 calculateShape();
107 }
108 return this.shape;
109 }
110
111
112
113
114 private void calculateShape()
115 {
116 this.shape = new Path2D.Double();
117 this.shape.moveTo(getPoints()[0].x, getPoints()[0].y);
118 for (int i = 1; i < getPoints().length; i++)
119 {
120 this.shape.lineTo(getPoints()[i].x, getPoints()[i].y);
121 }
122 this.shape.closePath();
123 }
124
125
126
127
128
129 public final boolean contains(final OTSPoint3D point)
130 {
131 return getShape().contains(point.x, point.y);
132 }
133
134
135
136
137
138
139
140
141 public final boolean contains(final Rectangle2D rectangle)
142 {
143 return getShape().contains(rectangle);
144 }
145
146
147
148
149
150 public final boolean intersects(final OTSShape otsShape)
151 {
152
153 if (!getEnvelope().intersects(otsShape.getEnvelope()))
154 {
155 return false;
156 }
157
158
159 for (OTSPoint3D p : getPoints())
160 {
161 if (otsShape.contains(p))
162 {
163 return true;
164 }
165 }
166
167
168 for (OTSPoint3D p : otsShape.getPoints())
169 {
170 if (contains(p))
171 {
172 return true;
173 }
174 }
175
176
177 for (int i = 0; i < getPoints().length - 1; i++)
178 {
179 Line2D.Double line1 = new Line2D.Double(this.getPoints()[i].getPoint2D(), this.getPoints()[i + 1].getPoint2D());
180 for (int j = 0; j < otsShape.getPoints().length - 1; j++)
181 {
182 Line2D.Double line2 =
183 new Line2D.Double(otsShape.getPoints()[j].getPoint2D(), otsShape.getPoints()[j + 1].getPoint2D());
184
185 if (line1.intersectsLine(line2))
186 {
187 double p1x = line1.getX1(), p1y = line1.getY1(), d1x = line1.getX2() - p1x, d1y = line1.getY2() - p1y;
188 double p2x = line2.getX1(), p2y = line2.getY1(), d2x = line2.getX2() - p2x, d2y = line2.getY2() - p2y;
189
190 double det = d2x * d1y - d2y * d1x;
191 if (det == 0)
192 {
193
194
195
196
197
198
199 Point2D p1s = line1.getP1(), p1e = line1.getP2(), p2s = line2.getP1(), p2e = line2.getP2();
200 if ((p1s.equals(p2s) && p1e.equals(p2e)) || (p1s.equals(p2e) && p1e.equals(p2s)))
201 {
202 return true;
203 }
204 if (p1s.equals(p2s) && line1.ptLineDist(p2e) > 0 && line2.ptLineDist(p1e) > 0)
205 {
206 return true;
207 }
208 if (p1e.equals(p2e) && line1.ptLineDist(p2s) > 0 && line2.ptLineDist(p1s) > 0)
209 {
210 return true;
211 }
212 if (p1s.equals(p2e) && line1.ptLineDist(p2s) > 0 && line2.ptLineDist(p1e) > 0)
213 {
214 return true;
215 }
216 if (p1e.equals(p2s) && line1.ptLineDist(p2e) > 0 && line2.ptLineDist(p1s) > 0)
217 {
218 return true;
219 }
220 }
221 else
222 {
223 double z = (d2x * (p2y - p1y) + d2y * (p1x - p2x)) / det;
224 if (Math.abs(z) < 10.0 * Math.ulp(1.0) || Math.abs(z - 1.0) < 10.0 * Math.ulp(1.0))
225 {
226 return true;
227 }
228 }
229
230 }
231 }
232 }
233 return false;
234 }
235
236
237
238
239
240
241
242 public static OTSShape createAndCleanOTSShape(final OTSPoint3D[] points) throws OTSGeometryException
243 {
244 if (points.length < 2)
245 {
246 throw new OTSGeometryException("Degenerate OTSLine3D; has " + points.length + " point"
247 + (points.length != 1 ? "s" : ""));
248 }
249 return createAndCleanOTSShape(new ArrayList<>(Arrays.asList(points)));
250 }
251
252
253
254
255
256
257
258
259 public static OTSShape createAndCleanOTSShape(final List<OTSPoint3D> pointList) throws OTSGeometryException
260 {
261
262 int i = 1;
263 while (i < pointList.size())
264 {
265 if (pointList.get(i - 1).equals(pointList.get(i)))
266 {
267 pointList.remove(i);
268 }
269 else
270 {
271 i++;
272 }
273 }
274 return new OTSShape(pointList);
275 }
276
277
278
279
280
281
282 public static void main(final String[] args) throws OTSGeometryException
283 {
284 OTSShape s1 = new OTSShape(new OTSPoint3D(0, 0), new OTSPoint3D(10, 0), new OTSPoint3D(10, 10), new OTSPoint3D(0, 10));
285 OTSShape s2 = new OTSShape(new OTSPoint3D(5, 5), new OTSPoint3D(15, 5), new OTSPoint3D(15, 15), new OTSPoint3D(5, 15));
286 System.out.println("s1.intersect(s2): " + s1.intersects(s2));
287 System.out.println("s1.intersect(s1): " + s1.intersects(s1));
288 OTSShape s3 =
289 new OTSShape(new OTSPoint3D(25, 25), new OTSPoint3D(35, 25), new OTSPoint3D(35, 35), new OTSPoint3D(25, 35));
290 System.out.println("s1.intersect(s3): " + s1.intersects(s3));
291 }
292
293
294 @Override
295 public final String toString()
296 {
297 return "OTSShape [shape=" + this.shape + "]";
298 }
299 }