1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.geometry.euclidean.oned;
18
19 import java.util.Comparator;
20 import java.util.function.UnaryOperator;
21
22 import org.apache.commons.geometry.core.internal.SimpleTupleFormat;
23 import org.apache.commons.geometry.euclidean.EuclideanVector;
24 import org.apache.commons.geometry.euclidean.EuclideanVectorSum;
25 import org.apache.commons.geometry.euclidean.internal.Vectors;
26 import org.apache.commons.numbers.core.Precision;
27
28
29
30
31 public class Vector1D extends EuclideanVector<Vector1D> {
32
33
34 public static final Vector1D ZERO = new Vector1D(0.0);
35
36
37 public static final Vector1D NaN = new Vector1D(Double.NaN);
38
39
40 public static final Vector1D POSITIVE_INFINITY =
41 new Vector1D(Double.POSITIVE_INFINITY);
42
43
44 public static final Vector1D NEGATIVE_INFINITY =
45 new Vector1D(Double.NEGATIVE_INFINITY);
46
47
48
49
50
51 public static final Comparator<Vector1D> COORDINATE_ASCENDING_ORDER = (a, b) -> {
52 int cmp = 0;
53
54 if (a != null && b != null) {
55 cmp = Double.compare(a.getX(), b.getX());
56 } else if (a != null) {
57 cmp = -1;
58 } else if (b != null) {
59 cmp = 1;
60 }
61
62 return cmp;
63 };
64
65
66 private final double x;
67
68
69
70
71 private Vector1D(final double x) {
72 this.x = x;
73 }
74
75
76
77
78
79 public double getX() {
80 return x;
81 }
82
83
84 @Override
85 public int getDimension() {
86 return 1;
87 }
88
89
90 @Override
91 public boolean isNaN() {
92 return Double.isNaN(x);
93 }
94
95
96 @Override
97 public boolean isInfinite() {
98 return !isNaN() && Double.isInfinite(x);
99 }
100
101
102 @Override
103 public boolean isFinite() {
104 return Double.isFinite(x);
105 }
106
107
108 @Override
109 public Vector1D vectorTo(final Vector1D v) {
110 return v.subtract(this);
111 }
112
113
114 @Override
115 public Unit directionTo(final Vector1D v) {
116 return vectorTo(v).normalize();
117 }
118
119
120 @Override
121 public Vector1D lerp(final Vector1D p, final double t) {
122 return Sum.create()
123 .addScaled(1.0 - t, this)
124 .addScaled(t, p).get();
125 }
126
127
128 @Override
129 public Vector1D getZero() {
130 return ZERO;
131 }
132
133
134 @Override
135 public double norm() {
136 return Vectors.norm(x);
137 }
138
139
140 @Override
141 public double normSq() {
142 return Vectors.normSq(x);
143 }
144
145
146 @Override
147 public Vector1D withNorm(final double magnitude) {
148 getCheckedNorm();
149 return (x > 0.0) ? new Vector1D(magnitude) : new Vector1D(-magnitude);
150 }
151
152
153 @Override
154 public Vector1D add(final Vector1D v) {
155 return new Vector1D(x + v.x);
156 }
157
158
159 @Override
160 public Vector1D add(final double factor, final Vector1D v) {
161 return new Vector1D(x + (factor * v.x));
162 }
163
164
165 @Override
166 public Vector1D subtract(final Vector1D v) {
167 return new Vector1D(x - v.x);
168 }
169
170
171 @Override
172 public Vector1D subtract(final double factor, final Vector1D v) {
173 return new Vector1D(x - (factor * v.x));
174 }
175
176
177 @Override
178 public Vector1D negate() {
179 return new Vector1D(-x);
180 }
181
182
183 @Override
184 public Unit normalize() {
185 return Unit.from(x);
186 }
187
188
189 @Override
190 public Unit normalizeOrNull() {
191 return Unit.tryCreateNormalized(x, false);
192 }
193
194
195 @Override
196 public Vector1D multiply(final double a) {
197 return new Vector1D(a * x);
198 }
199
200
201 @Override
202 public double distance(final Vector1D v) {
203 return Vectors.norm(x - v.x);
204 }
205
206
207 @Override
208 public double distanceSq(final Vector1D v) {
209 return Vectors.normSq(x - v.x);
210 }
211
212
213 @Override
214 public double dot(final Vector1D v) {
215 return x * v.x;
216 }
217
218
219
220
221
222 @Override
223 public double angle(final Vector1D v) {
224
225 getCheckedNorm();
226 v.getCheckedNorm();
227
228 final double sig1 = Math.signum(x);
229 final double sig2 = Math.signum(v.x);
230
231
232 return (sig1 == sig2) ? 0.0 : Math.PI;
233 }
234
235
236
237
238
239
240 public Vector1D transform(final UnaryOperator<Vector1D> fn) {
241 return fn.apply(this);
242 }
243
244
245 @Override
246 public boolean eq(final Vector1D vec, final Precision.DoubleEquivalence precision) {
247 return precision.eq(x, vec.x);
248 }
249
250
251
252
253
254
255
256 @Override
257 public int hashCode() {
258 if (isNaN()) {
259 return 857;
260 }
261 return 403 * Double.hashCode(x);
262 }
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283 @Override
284 public boolean equals(final Object other) {
285 if (this == other) {
286 return true;
287 }
288 if (other instanceof Vector1D) {
289 final Vector1D rhs = (Vector1D) other;
290 if (rhs.isNaN()) {
291 return this.isNaN();
292 }
293
294 return Double.compare(x, rhs.x) == 0;
295 }
296 return false;
297 }
298
299
300 @Override
301 public String toString() {
302 return SimpleTupleFormat.getDefault().format(x);
303 }
304
305
306
307
308
309 public static Vector1D of(final double x) {
310 return new Vector1D(x);
311 }
312
313
314
315
316
317
318
319 public static Vector1D parse(final String str) {
320 return SimpleTupleFormat.getDefault().parse(str, Vector1D::new);
321 }
322
323
324
325
326
327 public static final class Unit extends Vector1D {
328
329 public static final Unit PLUS = new Unit(1d);
330
331 public static final Unit MINUS = new Unit(-1d);
332
333
334
335
336
337 private Unit(final double x) {
338 super(x);
339 }
340
341
342 @Override
343 public double norm() {
344 return 1;
345 }
346
347
348 @Override
349 public double normSq() {
350 return 1;
351 }
352
353
354 @Override
355 public Unit normalize() {
356 return this;
357 }
358
359
360 @Override
361 public Unit normalizeOrNull() {
362 return this;
363 }
364
365
366 @Override
367 public Vector1D withNorm(final double mag) {
368 return multiply(mag);
369 }
370
371
372 @Override
373 public Vector1D negate() {
374 return this == PLUS ? MINUS : PLUS;
375 }
376
377
378
379
380
381
382 public static Unit from(final double x) {
383 return tryCreateNormalized(x, true);
384 }
385
386
387
388
389
390
391 public static Unit from(final Vector1D v) {
392 return v instanceof Unit ?
393 (Unit) v :
394 from(v.getX());
395 }
396
397
398
399
400
401
402
403
404
405
406 private static Unit tryCreateNormalized(final double x, final boolean throwOnFailure) {
407 final double norm = Vectors.norm(x);
408
409 if (Vectors.isRealNonZero(norm)) {
410 return x > 0 ? PLUS : MINUS;
411 } else if (throwOnFailure) {
412 throw Vectors.illegalNorm(norm);
413 }
414 return null;
415 }
416 }
417
418
419
420
421
422
423
424 public static final class Sum extends EuclideanVectorSum<Vector1D> {
425
426
427 private final org.apache.commons.numbers.core.Sum xsum;
428
429
430
431
432 Sum(final Vector1D initial) {
433 this.xsum = org.apache.commons.numbers.core.Sum.of(initial.x);
434 }
435
436
437 @Override
438 public Sum add(final Vector1D vec) {
439 xsum.add(vec.x);
440 return this;
441 }
442
443
444 @Override
445 public Sum addScaled(final double scale, final Vector1D vec) {
446 xsum.addProduct(scale, vec.x);
447 return this;
448 }
449
450
451 @Override
452 public Vector1D get() {
453 return Vector1D.of(xsum.getAsDouble());
454 }
455
456
457
458
459 public static Sum create() {
460 return new Sum(Vector1D.ZERO);
461 }
462
463
464
465
466
467 public static Sum of(final Vector1D initial) {
468 return new Sum(initial);
469 }
470
471
472
473
474
475
476 public static Sum of(final Vector1D first, final Vector1D... more) {
477 final Sum s = new Sum(first);
478 for (final Vector1D v : more) {
479 s.add(v);
480 }
481 return s;
482 }
483 }
484 }