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 package math.geom2d.line;
27
28 import math.geom2d.AffineTransform2D;
29 import math.geom2d.Angle2D;
30 import math.geom2d.Box2D;
31 import math.geom2d.Point2D;
32 import math.geom2d.Shape2D;
33 import math.geom2d.Vector2D;
34 import math.geom2d.circulinear.CirculinearElement2D;
35
36
37
38
39
40
41
42 public class LineSegment2D extends AbstractLine2D
43 implements Cloneable, CirculinearElement2D {
44
45
46
47
48
49
50
51
52
53
54
55 public LineSegment2D(java.awt.geom.Point2D point1,
56 java.awt.geom.Point2D point2) {
57 this(point1.getX(), point1.getY(), point2.getX(), point2.getY());
58 }
59
60
61 public LineSegment2D(double x1, double y1, double x2, double y2) {
62 super(x1, y1, x2-x1, y2-y1);
63 }
64
65
66
67
68
69
70
71
72 public final static LineSegment2D create(Point2D p1, Point2D p2) {
73 return new LineSegment2D(p1, p2);
74 }
75
76 public final static StraightLine2D getMedian(LineSegment2D edge) {
77 return new StraightLine2D(
78 edge.x0+edge.dx*.5, edge.y0+edge.dy*.5,
79 -edge.dy, edge.dx);
80 }
81
82
83
84
85 public final static double getEdgeAngle(LineSegment2D edge1,
86 LineSegment2D edge2) {
87 double x0, y0, x1, y1, x2, y2;
88
89 if (Math.abs(edge1.x0-edge2.x0)<Shape2D.ACCURACY
90 &&Math.abs(edge1.y0-edge2.y0)<Shape2D.ACCURACY) {
91 x0 = edge1.x0;
92 y0 = edge1.y0;
93 x1 = edge1.x0+edge1.dx;
94 y1 = edge1.y0+edge1.dy;
95 x2 = edge2.x0+edge2.dx;
96 y2 = edge2.y0+edge2.dy;
97 } else if (Math.abs(edge1.x0+edge1.dx-edge2.x0)<Shape2D.ACCURACY
98 &&Math.abs(edge1.y0+edge1.dy-edge2.y0)<Shape2D.ACCURACY) {
99 x0 = edge1.x0+edge1.dx;
100 y0 = edge1.y0+edge1.dy;
101 x1 = edge1.x0;
102 y1 = edge1.y0;
103 x2 = edge2.x0+edge2.dx;
104 y2 = edge2.y0+edge2.dy;
105 } else if (Math.abs(edge1.x0+edge1.dx-edge2.x0-edge2.dx)<Shape2D.ACCURACY
106 &&Math.abs(edge1.y0+edge1.dy-edge2.y0-edge2.dy)<Shape2D.ACCURACY) {
107 x0 = edge1.x0+edge1.dx;
108 y0 = edge1.y0+edge1.dy;
109 x1 = edge1.x0;
110 y1 = edge1.y0;
111 x2 = edge2.x0;
112 y2 = edge2.y0;
113 } else if (Math.abs(edge1.x0-edge2.x0-edge2.dx)<Shape2D.ACCURACY
114 &&Math.abs(edge1.y0-edge2.y0-edge2.dy)<Shape2D.ACCURACY) {
115 x0 = edge1.x0;
116 y0 = edge1.y0;
117 x1 = edge1.x0+edge1.dx;
118 y1 = edge1.y0+edge1.dy;
119 x2 = edge2.x0;
120 y2 = edge2.y0;
121 } else {
122 return Double.NaN;
123 }
124
125 return Angle2D.getAngle(new Vector2D(x1-x0, y1-y0), new Vector2D(x2-x0,
126 y2-y0));
127 }
128
129
130
131
132
133
134
135
136
137 public final static boolean intersects(LineSegment2D edge1,
138 LineSegment2D edge2) {
139 Point2D e1p1 = edge1.getFirstPoint();
140 Point2D e1p2 = edge1.getLastPoint();
141 Point2D e2p1 = edge2.getFirstPoint();
142 Point2D e2p2 = edge2.getLastPoint();
143
144 boolean b1 = Point2D.ccw(e1p1, e1p2, e2p1)
145 *Point2D.ccw(e1p1, e1p2, e2p2)<=0;
146 boolean b2 = Point2D.ccw(e2p1, e2p2, e1p1)
147 *Point2D.ccw(e2p1, e2p2, e1p2)<=0;
148 return b1&&b2;
149 }
150
151
152
153
154
155
156
157
158
159
160
161 public Point2D getOtherPoint(Point2D point) {
162 if (point.equals(new Point2D(x0, y0)))
163 return new Point2D(x0+dx, y0+dy);
164 if (point.equals(new Point2D(x0+dx, y0+dy)))
165 return new Point2D(x0, y0);
166 return null;
167 }
168
169
170
171
172
173 public StraightLine2D getMedian() {
174
175
176 return new StraightLine2D(x0+dx*.5, y0+dy*.5, -dy, dx);
177 }
178
179
180
181
182 @Deprecated
183 public void setLineSegment(Point2D p1, Point2D p2) {
184 this.x0 = p1.getX();
185 this.y0 = p1.getY();
186 this.dx = p2.getX()-this.x0;
187 this.dy = p2.getY()-this.y0;
188 }
189
190
191
192
193 @Deprecated
194 public void setLineSegment(double x1, double y1, double x2, double y2) {
195 this.x0 = x1;
196 this.y0 = y1;
197 this.dx = x2-x1;
198 this.dy = y2-y1;
199 }
200
201
202
203
204
205
206
207 @Override
208 public double getLength() {
209 return Math.hypot(dx, dy);
210 }
211
212
213
214
215 public LineSegment2D getParallel(double d) {
216 double dd = Math.sqrt(dx*dx+dy*dy);
217 return new LineSegment2D(
218 x0+dy*d/dd, y0-dx*d/dd,
219 x0+dx+dy*d/dd, y0+dy-dx*d/dd);
220 }
221
222
223
224
225 @Override
226 public double getSignedDistance(double x, double y) {
227 Point2D proj = super.getProjectedPoint(x, y);
228 if (contains(proj))
229 return super.getSignedDistance(x, y);
230
231 double d = this.getDistance(x, y);
232 return super.getSignedDistance(x, y)>0 ? d : -d;
233 }
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286 @Override
287 public Point2D getFirstPoint() {
288 return new Point2D(x0, y0);
289 }
290
291
292
293
294
295
296 @Override
297 public Point2D getLastPoint() {
298 return new Point2D(x0+dx, y0+dy);
299 }
300
301
302
303
304 public double getT0() {
305 return 0.0;
306 }
307
308
309
310
311 public double getT1() {
312 return 1.0;
313 }
314
315 public Point2D getPoint(double t) {
316 t = Math.min(Math.max(t, 0), 1);
317 return new Point2D(x0+dx*t, y0+dy*t);
318 }
319
320
321
322
323
324 public LineSegment2D getReverseCurve() {
325 return new LineSegment2D(x0+dx, y0+dy, x0, y0);
326 }
327
328
329
330
331
332
333
334 public boolean isBounded() {
335 return true;
336 }
337
338 public boolean contains(double xp, double yp) {
339 if (!super.supportContains(xp, yp))
340 return false;
341
342
343 double t = getPositionOnLine(xp, yp);
344
345 if (t<-ACCURACY)
346 return false;
347 if (t-1>ACCURACY)
348 return false;
349
350 return true;
351 }
352
353
354
355
356 @Override
357 public double getDistance(double x, double y) {
358 Point2D proj = super.getProjectedPoint(x, y);
359 if (contains(proj))
360 return proj.distance(x, y);
361 double d1 = Math.hypot(x0-x, y0-y);
362 double d2 = Math.hypot(x0+dx-x, y0+dy-y);
363 return Math.min(d1, d2);
364 }
365
366 @Override
367 public LineSegment2D transform(AffineTransform2D trans) {
368 double[] tab = trans.getCoefficients();
369 double x1 = x0*tab[0]+y0*tab[1]+tab[2];
370 double y1 = x0*tab[3]+y0*tab[4]+tab[5];
371 double x2 = (x0+dx)*tab[0]+(y0+dy)*tab[1]+tab[2];
372 double y2 = (x0+dx)*tab[3]+(y0+dy)*tab[4]+tab[5];
373 return new LineSegment2D(x1, y1, x2, y2);
374 }
375
376 public Box2D getBoundingBox() {
377 return new Box2D(x0, x0+dx, y0, y0+dy);
378 }
379
380
381
382
383
384
385
386
387
388
389 public java.awt.geom.GeneralPath appendPath(java.awt.geom.GeneralPath path) {
390 path.lineTo((float) x0+dx, (float) y0+dy);
391 return path;
392 }
393
394
395
396
397 public java.awt.geom.GeneralPath getGeneralPath() {
398 java.awt.geom.GeneralPath path = new java.awt.geom.GeneralPath();
399 path.moveTo((float) x0, (float) y0);
400 path.lineTo((float) (x0+dx), (float) (y0+dy));
401 return path;
402 }
403
404
405
406
407 @Override
408 public String toString() {
409 return new String("LineSegment2D[(" + x0 + "," + y0 + ")-("
410 + (x0+dx) + "," + (y0+dy) + ")]");
411 }
412
413 @Override
414 public boolean equals(Object obj) {
415 if (!(obj instanceof LineSegment2D))
416 return false;
417 LineSegment2D edge = (LineSegment2D) obj;
418
419 if (Math.abs(x0-edge.x0)>Shape2D.ACCURACY)
420 return false;
421 if (Math.abs(y0-edge.y0)>Shape2D.ACCURACY)
422 return false;
423 if (Math.abs(dx-edge.dx)>Shape2D.ACCURACY)
424 return false;
425 if (Math.abs(dy-edge.dy)>Shape2D.ACCURACY)
426 return false;
427 return true;
428 }
429
430 @Override
431 public LineSegment2D clone() {
432 return new LineSegment2D(x0, y0, x0+dx, y0+dy);
433 }
434 }