1 package org.djutils.draw.line;
2
3 import java.awt.geom.Point2D;
4 import java.util.Arrays;
5 import java.util.Iterator;
6 import java.util.Locale;
7
8 import org.djutils.draw.Drawable2d;
9 import org.djutils.draw.bounds.Bounds2d;
10 import org.djutils.draw.point.DirectedPoint2d;
11 import org.djutils.draw.point.Point2d;
12 import org.djutils.exceptions.Throw;
13 import org.djutils.math.AngleUtil;
14
15
16
17
18
19
20
21
22
23
24
25 public class Ray2d extends DirectedPoint2d implements Drawable2d, Ray<Ray2d, DirectedPoint2d, Point2d>
26 {
27
28
29
30
31
32
33
34 public Ray2d(final double x, final double y, final double dirZ)
35 {
36 super(x, y, dirZ);
37 }
38
39
40
41
42
43
44
45
46
47 public Ray2d(final double[] xy, final double dirZ)
48 {
49 super(xy, dirZ);
50 }
51
52
53
54
55
56
57
58
59
60 public Ray2d(final Point2D point, final double dirZ)
61 {
62 super(point, dirZ);
63 }
64
65
66
67
68
69
70
71
72 public Ray2d(final Point2d point, final double dirZ)
73 {
74 super(point, dirZ);
75 }
76
77
78
79
80
81
82
83
84
85
86
87 public Ray2d(final double x, final double y, final double throughX, final double throughY)
88 {
89 super(x, y, throughX, throughY);
90 }
91
92
93
94
95
96
97
98
99
100
101
102 public Ray2d(final Point2d point, final double throughX, final double throughY)
103 {
104 super(point, throughX, throughY);
105 }
106
107
108
109
110
111
112
113
114
115 public Ray2d(final double x, final double y, final Point2d throughPoint)
116 {
117 this(x, y, Throw.whenNull(throughPoint, "througPoint").x, throughPoint.y);
118 }
119
120
121
122
123
124
125
126
127 public Ray2d(final Point2d point, final Point2d throughPoint)
128 {
129 this(Throw.whenNull(point, "point").x, point.y, Throw.whenNull(throughPoint, "throughPoint").x, throughPoint.y);
130 }
131
132
133
134
135
136 public Ray2d(final DirectedPoint2d directedPoint)
137 {
138 this(directedPoint, directedPoint.dirZ);
139 }
140
141 @Override
142 public final double getDirZ()
143 {
144 return this.dirZ;
145 }
146
147 @Override
148 public DirectedPoint2d getEndPoint()
149 {
150 return this;
151 }
152
153 @Override
154 public int size()
155 {
156 return 2;
157 }
158
159 @Override
160 public Iterator<Point2d> iterator()
161 {
162 double cosDirZ = Math.cos(this.dirZ);
163 double sinDirZ = Math.sin(this.dirZ);
164 Point2d[] array = new Point2d[] {this, new Point2d(cosDirZ == 0 ? this.x : cosDirZ * Double.POSITIVE_INFINITY,
165 sinDirZ == 0 ? this.y : sinDirZ * Double.POSITIVE_INFINITY)};
166 return Arrays.stream(array).iterator();
167 }
168
169 @Override
170 public Bounds2d getAbsoluteBounds()
171 {
172 double cosDirZ = Math.cos(this.dirZ);
173 double sinDirZ = Math.sin(this.dirZ);
174 return new Bounds2d(cosDirZ >= 0 ? this.x : Double.NEGATIVE_INFINITY, cosDirZ <= 0 ? this.x : Double.POSITIVE_INFINITY,
175 sinDirZ >= 0 ? this.y : Double.NEGATIVE_INFINITY, sinDirZ <= 0 ? this.y : Double.POSITIVE_INFINITY);
176 }
177
178 @Override
179 public Ray2d neg()
180 {
181 return new Ray2d(-this.x, -this.y, AngleUtil.normalizeAroundZero(this.dirZ + Math.PI));
182 }
183
184 @Override
185 public Ray2d flip()
186 {
187 return new Ray2d(this.x, this.y, AngleUtil.normalizeAroundZero(this.dirZ + Math.PI));
188 }
189
190 @Override
191 public Ray2d getLocationExtended(final double position)
192 {
193 Throw.whenNaN(position, "position");
194 Throw.when(Double.isInfinite(position), IllegalArgumentException.class, "position must be finite");
195 return new Ray2d(this.x + Math.cos(this.dirZ) * position, this.y + Math.sin(this.dirZ) * position, this.dirZ);
196 }
197
198 @Override
199 public Point2d closestPointOnRay(final Point2d point)
200 {
201 Throw.whenNull(point, "point");
202 double dX = Math.cos(this.dirZ);
203 double dY = Math.sin(this.dirZ);
204 return point.closestPointOnLine(this.x, this.y, this.x + dX, this.y + dY, true, false);
205 }
206
207 @Override
208 public Point2d projectOrthogonal(final Point2d point)
209 {
210 Throw.whenNull(point, "point");
211 return point.closestPointOnLine(this.x, this.y, this.x + Math.cos(this.dirZ), this.y + Math.sin(this.dirZ), null,
212 false);
213 }
214
215 @Override
216 public Point2d projectOrthogonalExtended(final Point2d point)
217 {
218 Throw.whenNull(point, "point");
219 return point.closestPointOnLine(getX(), getY(), getX() + Math.cos(this.dirZ), getY() + Math.sin(this.dirZ), false,
220 false);
221 }
222
223 @Override
224 public double projectOrthogonalFractional(final Point2d point)
225 {
226 Throw.whenNull(point, "point");
227 return point.fractionalPositionOnLine(this.x, this.y, this.x + Math.cos(this.dirZ), this.y + Math.sin(this.dirZ), null,
228 false);
229 }
230
231 @Override
232 public double projectOrthogonalFractionalExtended(final Point2d point)
233 {
234 Throw.whenNull(point, "point");
235 return point.fractionalPositionOnLine(this.x, this.y, this.x + Math.cos(this.dirZ), this.y + Math.sin(this.dirZ), false,
236 false);
237 }
238
239 @Override
240 public String toString()
241 {
242 return toString("%f", false);
243 }
244
245 @Override
246 public String toString(final String doubleFormat, final boolean doNotIncludeClassName)
247 {
248 String format = String.format("%1$s[x=%2$s, y=%2$s, dirZ=%2%s]", doNotIncludeClassName ? "" : "Ray2d ", doubleFormat);
249 return String.format(Locale.US, format, this.x, this.y, this.dirZ);
250 }
251
252 @Override
253 public int hashCode()
254 {
255 return super.hashCode();
256 }
257
258 @Override
259 @SuppressWarnings("checkstyle:needbraces")
260 public boolean equals(final Object obj)
261 {
262 if (this == obj)
263 return true;
264 if (!super.equals(obj))
265 return false;
266 if (getClass() != obj.getClass())
267 return false;
268 return true;
269 }
270
271 }