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