1 package org.djunits.quantity;
2
3 import org.djunits.quantity.def.AbsQuantity;
4 import org.djunits.quantity.def.AbstractReference;
5 import org.djunits.quantity.def.Quantity;
6
7 /**
8 * Position is the absolute equivalent of Length, and can, e.g., represent an absolute offset relative to a defined origin.
9 * <p>
10 * Copyright (c) 2025-2026 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights reserved. See
11 * for project information <a href="https://djunits.org" target="_blank">https://djunits.org</a>. The DJUNITS project is
12 * distributed under a <a href="https://djunits.org/docs/license.html" target="_blank">three-clause BSD-style license</a>.
13 * @author Alexander Verbraeck
14 */
15 public class Position extends AbsQuantity<Position, Length, Position.Reference>
16 {
17 /** */
18 private static final long serialVersionUID = 600L;
19
20 /**
21 * Instantiate a Position quantity with a unit and a reference point.
22 * @param valueInUnit the length value, expressed in a length unit
23 * @param unit the length unit in which the value is expressed, relative to the reference point
24 * @param reference the reference point of this position
25 */
26 public Position(final double valueInUnit, final Length.Unit unit, final Reference reference)
27 {
28 super(new Length(valueInUnit, unit), reference);
29 }
30
31 /**
32 * Instantiate a Position instance based on an length and a reference point.
33 * @param length the length, relative to the reference point
34 * @param reference the reference point of this position
35 */
36 public Position(final Length length, final Reference reference)
37 {
38 super(length, reference);
39 }
40
41 /**
42 * Return a Position instance based on an SI value and a reference point.
43 * @param si the length si value, relative to the reference point
44 * @param reference the reference point of this position
45 * @return the Position instance based on an SI value
46 */
47 public static Position ofSi(final double si, final Reference reference)
48 {
49 return new Position(si, Length.Unit.SI, reference);
50 }
51
52 @Override
53 public Position instantiate(final Length length, final Reference reference)
54 {
55 return new Position(length, reference);
56 }
57
58 /**
59 * Returns a Position representation of a textual representation of a value with a unit. The String representation that can
60 * be parsed is the double value in the unit, followed by a localized or English abbreviation of the unit. Spaces are
61 * allowed, but not required, between the value and the unit.
62 * @param text the textual representation to parse into a Position
63 * @param reference the reference point of this position
64 * @return the Scalar representation of the value in its unit
65 * @throws IllegalArgumentException when the text cannot be parsed
66 * @throws NullPointerException when the text argument is null
67 */
68 public static Position valueOf(final String text, final Reference reference)
69 {
70 return new Position(Quantity.valueOf(text, Length.ZERO), reference);
71 }
72
73 /**
74 * Returns a Position based on a value and the textual representation of the unit, which can be localized.
75 * @param valueInUnit the value, expressed in the unit as given by unitString
76 * @param unitString the textual representation of the unit
77 * @param reference the reference point of this position
78 * @return the Scalar representation of the value in its unit
79 * @throws IllegalArgumentException when the unit cannot be parsed or is incorrect
80 * @throws NullPointerException when the unitString argument is null
81 */
82 public static Position of(final double valueInUnit, final String unitString, final Reference reference)
83 {
84 return new Position(Quantity.of(valueInUnit, unitString, Length.ZERO), reference);
85 }
86
87 @Override
88 public Length subtract(final Position other)
89 {
90 var otherRef = other.relativeTo(getReference());
91 return Length.ofSi(si() - otherRef.si()).setDisplayUnit(getDisplayUnit());
92 }
93
94 @Override
95 public Position add(final Length other)
96 {
97 return new Position(Length.ofSi(si() + other.si()).setDisplayUnit(getDisplayUnit()), getReference());
98 }
99
100 @Override
101 public Position subtract(final Length other)
102 {
103 return new Position(Length.ofSi(si() - other.si()).setDisplayUnit(getDisplayUnit()), getReference());
104 }
105
106 /**
107 * The reference class to define a reference point for the position. No references have been defined yet, since there is no
108 * "natural" origin for a position that we can include here. User-defined origins van be easily added and used.
109 */
110 public static final class Reference extends AbstractReference<Reference, Position, Length>
111 {
112 /**
113 * Define a new reference point for the position.
114 * @param id the id
115 * @param name the name or explanation
116 * @param offset the offset w.r.t. the offsetReference
117 * @param offsetReference the reference to which the offset is relative
118 */
119 public Reference(final String id, final String name, final Length offset, final Reference offsetReference)
120 {
121 super(id, name, offset, offsetReference);
122 }
123
124 /**
125 * Define a new reference point for the position.
126 * @param id the id
127 * @param name the name or explanation
128 */
129 public Reference(final String id, final String name)
130 {
131 this(id, name, Length.ZERO, null);
132 }
133
134 /**
135 * Define a new reference point for the position.
136 * @param id the id
137 * @param name the name or explanation
138 * @param offset the offset w.r.t. the offsetReference
139 * @param offsetReference the reference to which the offset is relative
140 */
141 public static void add(final String id, final String name, final Length offset, final Reference offsetReference)
142 {
143 new Reference(id, name, offset, offsetReference);
144 }
145
146 /**
147 * Define a new reference point for the position.
148 * @param id the id
149 * @param name the name or explanation
150 */
151 public static void add(final String id, final String name)
152 {
153 new Reference(id, name);
154 }
155
156 /**
157 * Get a reference point for the position, based on its id. Return null when the id could not be found.
158 * @param id the id
159 * @return the PositionReference object
160 */
161 public static Reference get(final String id)
162 {
163 return AbstractReference.get(Position.Reference.class, id);
164 }
165
166 @Override
167 public Position instantiate(final Length length)
168 {
169 return new Position(length, this);
170 }
171 }
172 }