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 java.util.ArrayList;
29 import java.util.Collection;
30
31 import math.geom2d.AffineTransform2D;
32 import math.geom2d.Angle2D;
33 import math.geom2d.Box2D;
34 import math.geom2d.Point2D;
35 import math.geom2d.Shape2D;
36 import math.geom2d.Vector2D;
37 import math.geom2d.curve.AbstractSmoothCurve2D;
38 import math.geom2d.circulinear.CirculinearCurve2DUtils;
39 import math.geom2d.circulinear.CirculinearDomain2D;
40 import math.geom2d.circulinear.CirculinearElement2D;
41 import math.geom2d.conic.CircleArc2D;
42 import math.geom2d.curve.Curve2D;
43 import math.geom2d.curve.Curve2DUtils;
44 import math.geom2d.curve.CurveArray2D;
45 import math.geom2d.curve.CurveSet2D;
46 import math.geom2d.transform.CircleInversion2D;
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 public class Line2D extends AbstractSmoothCurve2D
75 implements LinearShape2D, CirculinearElement2D, Cloneable {
76
77
78
79
80
81
82
83
84
85
86 public Point2D p1;
87
88
89
90
91 public Point2D p2;
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106 public static boolean intersects(Line2D line1, Line2D line2) {
107 Point2D e1p1 = line1.getFirstPoint();
108 Point2D e1p2 = line1.getLastPoint();
109 Point2D e2p1 = line2.getFirstPoint();
110 Point2D e2p2 = line2.getLastPoint();
111
112 boolean b1 = Point2D.ccw(e1p1, e1p2, e2p1)
113 *Point2D.ccw(e1p1, e1p2, e2p2)<=0;
114 boolean b2 = Point2D.ccw(e2p1, e2p2, e1p1)
115 *Point2D.ccw(e2p1, e2p2, e1p2)<=0;
116 return b1&&b2;
117 }
118
119
120
121
122
123 public Line2D(Point2D point1, Point2D point2) {
124 this.p1 = point1;
125 this.p2 = point2;
126 }
127
128
129 public Line2D(double x1, double y1, double x2, double y2) {
130 p1 = new Point2D(x1, y1);
131 p2 = new Point2D(x2, y2);
132 }
133
134
135
136
137
138
139
140
141
142 public static Line2D create(Point2D p1, Point2D p2) {
143 return new Line2D(p1, p2);
144 }
145
146
147
148
149
150
151
152
153
154
155 public Point2D getPoint1() {
156 return p1;
157 }
158
159
160
161
162
163
164 public Point2D getPoint2() {
165 return p2;
166 }
167
168 public double getX1() {
169 return p1.getX();
170 }
171
172 public double getY1() {
173 return p1.getY();
174 }
175
176 public double getX2() {
177 return p2.getX();
178 }
179
180 public double getY2() {
181 return p2.getY();
182 }
183
184
185
186
187
188
189
190 public Point2D getOtherPoint(Point2D point) {
191 if (point.equals(p1))
192 return p2;
193 if (point.equals(p2))
194 return p1;
195 return null;
196 }
197
198 public void setPoint1(Point2D point) {
199 p1 = point;
200 }
201
202 public void setPoint2(Point2D point) {
203 p2 = point;
204 }
205
206
207
208
209 public boolean isColinear(LinearShape2D line) {
210 return new LineSegment2D(p1, p2).isColinear(line);
211 }
212
213
214
215
216
217 public boolean isParallel(LinearShape2D line) {
218 return new LineSegment2D(p1, p2).isParallel(line);
219 }
220
221
222
223
224
225
226
227 public CirculinearDomain2D getBuffer(double dist) {
228 return CirculinearCurve2DUtils.computeBuffer(this, dist);
229 }
230
231
232
233
234 public Line2D getParallel(double d) {
235 double x0 = getX1();
236 double y0 = getY1();
237 double dx = getX2()-x0;
238 double dy = getY2()-y0;
239 double dd = Math.sqrt(dx*dx+dy*dy);
240 return new Line2D(
241 x0+dy*d/dd, y0-dx*d/dd,
242 x0+dx+dy*d/dd, y0+dy-dx*d/dd);
243 }
244
245
246
247
248 public double getLength() {
249 return p1.getDistance(p2);
250 }
251
252
253
254
255 public double getLength(double pos) {
256 double dx = p2.getX()-p1.getX();
257 double dy = p2.getY()-p1.getY();
258 return pos*Math.hypot(dx, dy);
259 }
260
261
262
263
264 public double getPosition(double length) {
265 double dx = p2.getX()-p1.getX();
266 double dy = p2.getY()-p1.getY();
267 return length/Math.hypot(dx, dy);
268 }
269
270
271
272
273 public CirculinearElement2D transform(CircleInversion2D inv) {
274
275 Point2D center = inv.getCenter();
276 double r = inv.getRadius();
277
278
279 Point2D po = new StraightLine2D(this).getProjectedPoint(center);
280 double d = this.getDistance(po);
281
282
283
284 if (Math.abs(d)<Shape2D.ACCURACY){
285 Point2D p1 = this.getFirstPoint().transform(inv);
286 Point2D p2 = this.getLastPoint().transform(inv);
287 return new LineSegment2D(p1, p2);
288 }
289
290
291 double angle = Angle2D.getHorizontalAngle(center, po);
292
293
294 double r2 = r*r/d/2;
295 Point2D c2 = Point2D.createPolar(center, r2, angle);
296
297
298 boolean direct = !this.isInside(center);
299
300
301 double theta1 = Angle2D.getHorizontalAngle(c2, p1);
302 double theta2 = Angle2D.getHorizontalAngle(c2, p2);
303
304
305 return new CircleArc2D(c2, r2, theta1, theta2, direct);
306 }
307
308
309
310
311
312
313 public double[][] getParametric() {
314 return new LineSegment2D(p1, p2).getParametric();
315 }
316
317 public double[] getCartesianEquation() {
318 return new LineSegment2D(p1, p2).getCartesianEquation();
319 }
320
321 public double[] getPolarCoefficients() {
322 return new LineSegment2D(p1, p2).getPolarCoefficients();
323 }
324
325 public double[] getSignedPolarCoefficients() {
326 return new LineSegment2D(p1, p2).getSignedPolarCoefficients();
327 }
328
329
330
331
332 public double getHorizontalAngle() {
333 return new LineSegment2D(p1, p2).getHorizontalAngle();
334 }
335
336
337
338
339 public Point2D getIntersection(LinearShape2D line) {
340 return new LineSegment2D(p1, p2).getIntersection(line);
341 }
342
343
344
345
346 public Point2D getOrigin() {
347 return p1;
348 }
349
350
351
352
353 public StraightLine2D getSupportingLine() {
354 return new StraightLine2D(p1, p2);
355 }
356
357
358
359
360 public Vector2D getVector() {
361 return new Vector2D(p1, p2);
362 }
363
364
365
366
367
368 public double getSignedDistance(java.awt.geom.Point2D p) {
369 return getSignedDistance(p.getX(), p.getY());
370 }
371
372 public double getSignedDistance(double x, double y) {
373 return new LineSegment2D(p1, p2).getSignedDistance(x, y);
374 }
375
376
377
378
379
380
381
382
383 @Override
384 public Collection<? extends Line2D> getSmoothPieces() {
385 ArrayList<Line2D> array = new ArrayList<Line2D>(1);
386 array.add(this);
387 return array;
388 }
389
390
391
392
393
394 public boolean isClosed() {
395 return false;
396 }
397
398
399
400
401
402
403
404 public double getDistance(java.awt.geom.Point2D p) {
405 return getDistance(p.getX(), p.getY());
406 }
407
408
409
410
411 public double getDistance(double x, double y) {
412 StraightLine2D support = new StraightLine2D(p1, p2);
413 Point2D proj = support.getProjectedPoint(x, y);
414 if (contains(proj))
415 return proj.distance(x, y);
416 double d1 = Math.hypot(p1.getX()-x, p1.getY()-y);
417 double d2 = Math.hypot(p2.getX()-x, p2.getY()-y);
418
419 return Math.min(d1, d2);
420 }
421
422
423
424
425
426
427
428
429 public StraightLine2D getParallel(Point2D point) {
430 return new LineSegment2D(p1, p2).getParallel(point);
431 }
432
433
434
435
436
437
438
439
440 public StraightLine2D getPerpendicular(Point2D point) {
441 return new LineSegment2D(p1, p2).getPerpendicular(point);
442 }
443
444
445
446
447
448
449
450 public CurveSet2D<? extends Line2D> clip(Box2D box) {
451
452 CurveSet2D<? extends Curve2D> set = Curve2DUtils.clipCurve(this, box);
453
454
455 CurveArray2D<Line2D> result =
456 new CurveArray2D<Line2D>(set.getCurveNumber());
457
458
459 for (Curve2D curve : set.getCurves()) {
460 if (curve instanceof Line2D)
461 result.addCurve((Line2D) curve);
462 }
463 return result;
464 }
465
466
467
468
469 public Box2D getBoundingBox() {
470 return new Box2D(p1, p2);
471 }
472
473
474
475
476 public Vector2D getTangent(double t) {
477 return new Vector2D(p1, p2);
478 }
479
480
481
482
483 public double getCurvature(double t) {
484 return 0.0;
485 }
486
487
488
489
490 public double getWindingAngle(java.awt.geom.Point2D point) {
491 return new LineSegment2D(p1, p2).getWindingAngle(point);
492 }
493
494 public boolean isInside(java.awt.geom.Point2D point) {
495 return new LineSegment2D(p1, p2).getSignedDistance(point)<0;
496 }
497
498
499
500
501
502
503
504 public double getT0() {
505 return 0.0;
506 }
507
508
509
510
511 public double getT1() {
512 return 1.0;
513 }
514
515 public Point2D getPoint(double t) {
516 if (t<0)
517 return null;
518 if (t>1)
519 return null;
520 double x = p1.getX()*(1-t) + p2.getX()*t;
521 double y = p1.getY()*(1-t) + p2.getY()*t;
522 return new Point2D(x, y);
523 }
524
525
526
527
528
529
530 @Override
531 public Point2D getFirstPoint() {
532 return p1;
533 }
534
535
536
537
538
539
540 @Override
541 public Point2D getLastPoint() {
542 return p2;
543 }
544
545
546
547
548
549
550
551
552
553
554
555 public double getPosition(java.awt.geom.Point2D point) {
556 return new LineSegment2D(p1, p2).getPosition(point);
557 }
558
559 public double project(java.awt.geom.Point2D point) {
560 return new LineSegment2D(p1, p2).project(point);
561 }
562
563
564
565
566
567 public Line2D getReverseCurve() {
568 return new Line2D(p2, p1);
569 }
570
571 @Override
572 public Collection<? extends Line2D> getContinuousCurves() {
573 return wrapCurve(this);
574 }
575
576
577
578
579
580 public Line2D getSubCurve(double t0, double t1) {
581 if(t0>t1)
582 return null;
583 t0 = Math.max(t0, getT0());
584 t1 = Math.min(t1, getT1());
585 return new Line2D(this.getPoint(t0), this.getPoint(t1));
586 }
587
588
589
590
591 public Collection<Point2D> getIntersections(LinearShape2D line) {
592 return new LineSegment2D(p1, p2).getIntersections(line);
593 }
594
595
596
597
598 public Line2D transform(AffineTransform2D trans) {
599 return new Line2D(
600 p1.transform(trans),
601 p2.transform(trans));
602 }
603
604
605
606
607
608
609
610
611 public boolean contains(double x, double y) {
612 return new LineSegment2D(p1, p2).contains(x, y);
613 }
614
615
616
617
618
619 public boolean contains(java.awt.geom.Point2D p) {
620 return contains(p.getX(), p.getY());
621 }
622
623
624
625
626 public boolean isBounded() {
627 return true;
628 }
629
630
631
632
633 public boolean isEmpty() {
634 return false;
635 }
636
637 public java.awt.geom.GeneralPath getGeneralPath() {
638 java.awt.geom.GeneralPath path = new java.awt.geom.GeneralPath();
639 path.moveTo((float) p1.getX(), (float) p1.getY());
640 path.lineTo((float) p2.getX(), (float) p2.getY());
641 return path;
642 }
643
644 public java.awt.geom.GeneralPath appendPath(java.awt.geom.GeneralPath path) {
645 path.lineTo((float) p2.getX(), (float) p2.getY());
646 return path;
647 }
648
649
650
651
652 @Override
653 public String toString() {
654 return "Line2D(" + p1 + ")-(" + p2 + ")";
655 }
656
657
658
659
660
661
662
663
664 @Override
665 public boolean equals(Object obj) {
666
667 if(!(obj instanceof Line2D))
668 return false;
669
670
671 Line2D edge = (Line2D) obj;
672 return p1.equals(edge.p1) && p2.equals(edge.p2);
673 }
674
675 @Override
676 public Line2D clone() {
677 return new Line2D(p1.clone(), p2.clone());
678 }
679 }