1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.geometry.euclidean.twod;
18
19 import org.apache.commons.geometry.core.RegionLocation;
20 import org.apache.commons.geometry.core.Transform;
21 import org.apache.commons.geometry.core.partitioning.Split;
22 import org.apache.commons.numbers.core.Precision;
23
24
25
26
27
28
29
30
31 public final class Segment extends LineConvexSubset {
32
33
34 private final Vector2D startPoint;
35
36
37 private final Vector2D endPoint;
38
39
40
41
42
43
44
45
46 Segment(final Line line, final Vector2D startPoint, final Vector2D endPoint) {
47 super(line);
48
49 this.startPoint = startPoint;
50 this.endPoint = endPoint;
51 }
52
53
54
55
56
57 @Override
58 public boolean isFull() {
59 return false;
60 }
61
62
63
64
65
66 @Override
67 public boolean isInfinite() {
68 return false;
69 }
70
71
72
73
74
75 @Override
76 public boolean isFinite() {
77 return true;
78 }
79
80
81 @Override
82 public double getSize() {
83 return startPoint.distance(endPoint);
84 }
85
86
87 @Override
88 public Vector2D getCentroid() {
89 return startPoint.lerp(endPoint, 0.5);
90 }
91
92
93 @Override
94 public Vector2D getStartPoint() {
95 return startPoint;
96 }
97
98
99 @Override
100 public double getSubspaceStart() {
101 return getLine().abscissa(startPoint);
102 }
103
104
105 @Override
106 public Vector2D getEndPoint() {
107 return endPoint;
108 }
109
110
111 @Override
112 public double getSubspaceEnd() {
113 return getLine().abscissa(endPoint);
114 }
115
116
117 @Override
118 public Bounds2D getBounds() {
119 return Bounds2D.builder()
120 .add(startPoint)
121 .add(endPoint)
122 .build();
123 }
124
125
126 @Override
127 public Segment transform(final Transform<Vector2D> transform) {
128 final Vector2D t1 = transform.apply(getStartPoint());
129 final Vector2D t2 = transform.apply(getEndPoint());
130
131 final Line tLine = getLine().transform(transform);
132
133 return new Segment(tLine, t1, t2);
134 }
135
136
137 @Override
138 public Segment reverse() {
139 return new Segment(getLine().reverse(), endPoint, startPoint);
140 }
141
142
143 @Override
144 public String toString() {
145 final StringBuilder sb = new StringBuilder();
146 sb.append(getClass().getSimpleName())
147 .append("[startPoint= ")
148 .append(getStartPoint())
149 .append(", endPoint= ")
150 .append(getEndPoint())
151 .append(']');
152
153 return sb.toString();
154 }
155
156
157 @Override
158 RegionLocation classifyAbscissa(final double abscissa) {
159 final Precision.DoubleEquivalence precision = getPrecision();
160 final int startCmp = precision.compare(abscissa, getSubspaceStart());
161 if (startCmp > 0) {
162 final int endCmp = precision.compare(abscissa, getSubspaceEnd());
163 if (endCmp < 0) {
164 return RegionLocation.INSIDE;
165 } else if (endCmp == 0) {
166 return RegionLocation.BOUNDARY;
167 }
168 } else if (startCmp == 0) {
169 return RegionLocation.BOUNDARY;
170 }
171
172 return RegionLocation.OUTSIDE;
173 }
174
175
176 @Override
177 double closestAbscissa(final double abscissa) {
178 return Math.max(getSubspaceStart(), Math.min(getSubspaceEnd(), abscissa));
179 }
180
181
182 @Override
183 Split<LineConvexSubset> splitOnIntersection(final Line splitter, final Vector2D intersection) {
184 final Line line = getLine();
185
186 final Precision.DoubleEquivalence splitterPrecision = splitter.getPrecision();
187
188 final int startCmp = splitterPrecision.compare(splitter.offset(startPoint), 0.0);
189 final int endCmp = splitterPrecision.compare(splitter.offset(endPoint), 0.0);
190
191 if (startCmp == 0 && endCmp == 0) {
192
193 return new Split<>(null, null);
194 } else if (startCmp < 1 && endCmp < 1) {
195
196 return new Split<>(this, null);
197 } else if (startCmp > -1 && endCmp > -1) {
198
199 return new Split<>(null, this);
200 }
201
202
203 final Segment startSegment = new Segment(line, startPoint, intersection);
204 final Segment endSegment = new Segment(line, intersection, endPoint);
205
206 final Segment minus = (startCmp > 0) ? endSegment : startSegment;
207 final Segment plus = (startCmp > 0) ? startSegment : endSegment;
208
209 return new Split<>(minus, plus);
210 }
211 }