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
32 public final class ReverseRay extends LineConvexSubset {
33
34
35 private final Vector2D endPoint;
36
37
38
39
40
41
42 ReverseRay(final Line line, final Vector2D endPoint) {
43 super(line);
44
45 this.endPoint = endPoint;
46 }
47
48
49
50
51
52 @Override
53 public boolean isFull() {
54 return false;
55 }
56
57
58
59
60
61 @Override
62 public boolean isInfinite() {
63 return true;
64 }
65
66
67
68
69
70 @Override
71 public boolean isFinite() {
72 return false;
73 }
74
75
76
77
78
79 @Override
80 public double getSize() {
81 return Double.POSITIVE_INFINITY;
82 }
83
84
85
86
87
88 @Override
89 public Vector2D getCentroid() {
90 return null;
91 }
92
93
94
95
96
97 @Override
98 public Vector2D getStartPoint() {
99 return null;
100 }
101
102
103
104
105
106 @Override
107 public double getSubspaceStart() {
108 return Double.NEGATIVE_INFINITY;
109 }
110
111
112 @Override
113 public Vector2D getEndPoint() {
114 return endPoint;
115 }
116
117
118 @Override
119 public double getSubspaceEnd() {
120 return getLine().abscissa(endPoint);
121 }
122
123
124
125
126
127 @Override
128 public Bounds2D getBounds() {
129 return null;
130 }
131
132
133 @Override
134 public ReverseRay transform(final Transform<Vector2D> transform) {
135 final Line tLine = getLine().transform(transform);
136 final Vector2D tEnd = transform.apply(getEndPoint());
137
138 return new ReverseRay(tLine, tEnd);
139 }
140
141
142 @Override
143 public Ray reverse() {
144 return new Ray(getLine().reverse(), endPoint);
145 }
146
147
148 @Override
149 public String toString() {
150 final StringBuilder sb = new StringBuilder();
151 sb.append(getClass().getSimpleName())
152 .append("[direction= ")
153 .append(getLine().getDirection())
154 .append(", endPoint= ")
155 .append(getEndPoint())
156 .append(']');
157
158 return sb.toString();
159 }
160
161
162 @Override
163 RegionLocation classifyAbscissa(final double abscissa) {
164 final int cmp = getPrecision().compare(abscissa, getSubspaceEnd());
165 if (cmp < 0) {
166 return RegionLocation.INSIDE;
167 } else if (cmp == 0) {
168 return RegionLocation.BOUNDARY;
169 }
170
171 return RegionLocation.OUTSIDE;
172 }
173
174
175 @Override
176 double closestAbscissa(final double abscissa) {
177 return Math.min(getSubspaceEnd(), abscissa);
178 }
179
180
181 @Override
182 protected Split<LineConvexSubset> splitOnIntersection(final Line splitter, final Vector2D intersection) {
183 final Line line = getLine();
184 final Precision.DoubleEquivalence splitterPrecision = splitter.getPrecision();
185
186 final int endCmp = splitterPrecision.compare(splitter.offset(endPoint), 0.0);
187 final boolean pointsTowardPlus = splitter.getOffsetDirection().dot(line.getDirection()) >= 0.0;
188
189 if (pointsTowardPlus && endCmp < 1) {
190
191 return new Split<>(this, null);
192 } else if (!pointsTowardPlus && endCmp > -1) {
193
194 return new Split<>(null, this);
195 }
196
197
198 final Segment splitSeg = new Segment(line, intersection, endPoint);
199 final ReverseRay splitRevRay = new ReverseRay(line, intersection);
200
201 final LineConvexSubset minus = (endCmp > 0) ? splitRevRay : splitSeg;
202 final LineConvexSubset plus = (endCmp > 0) ? splitSeg : splitRevRay;
203
204 return new Split<>(minus, plus);
205 }
206 }