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