1 /* Copyright 2002-2024 CS GROUP
2 * Licensed to CS GROUP (CS) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * CS licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.orekit.frames;
18
19 import org.hipparchus.CalculusFieldElement;
20 import org.hipparchus.Field;
21 import org.hipparchus.geometry.euclidean.threed.FieldLine;
22 import org.hipparchus.geometry.euclidean.threed.FieldRotation;
23 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
24 import org.hipparchus.geometry.euclidean.threed.Line;
25 import org.hipparchus.geometry.euclidean.threed.RotationConvention;
26 import org.hipparchus.geometry.euclidean.threed.Vector3D;
27 import org.orekit.time.AbsoluteDate;
28 import org.orekit.time.FieldAbsoluteDate;
29 import org.orekit.time.TimeStamped;
30
31 /**
32 * A transform that only includes translation and rotation. It is static in the
33 * sense that no rates thereof are included.
34 *
35 * @param <T> the type of the field elements
36 * @author Bryan Cazabonne
37 * @see FieldTransform
38 * @since 12.0
39 */
40 public interface FieldStaticTransform<T extends CalculusFieldElement<T>> extends TimeStamped {
41
42 /**
43 * Get the identity static transform.
44 *
45 * @param <T> type of the elements
46 * @param field field used by default
47 * @return identity transform.
48 */
49 static <T extends CalculusFieldElement<T>> FieldStaticTransform<T> getIdentity(final Field<T> field) {
50 return FieldTransform.getIdentity(field);
51 }
52
53 /**
54 * Transform a position vector (including translation effects).
55 *
56 * @param position vector to transform
57 * @return transformed position
58 */
59 default FieldVector3D<T> transformPosition(final Vector3D position) {
60 return getRotation().applyTo(getTranslation().add(position));
61 }
62
63 /**
64 * Transform a position vector (including translation effects).
65 *
66 * @param position vector to transform
67 * @return transformed position
68 */
69 default FieldVector3D<T> transformPosition(final FieldVector3D<T> position) {
70 return getRotation().applyTo(position.add(getTranslation()));
71 }
72
73 /**
74 * Transform a vector (ignoring translation effects).
75 *
76 * @param vector vector to transform
77 * @return transformed vector
78 */
79 default FieldVector3D<T> transformVector(final Vector3D vector) {
80 return getRotation().applyTo(vector);
81 }
82
83 /**
84 * Transform a vector (ignoring translation effects).
85 *
86 * @param vector vector to transform
87 * @return transformed vector
88 */
89 default FieldVector3D<T> transformVector(final FieldVector3D<T> vector) {
90 return getRotation().applyTo(vector);
91 }
92
93 /**
94 * Transform a line.
95 *
96 * @param line to transform
97 * @return transformed line
98 */
99 default FieldLine<T> transformLine(final Line line) {
100 final FieldVector3D<T> transformedP0 = transformPosition(line.getOrigin());
101 final FieldVector3D<T> transformedP1 = transformPosition(line.pointAt(1.0e6));
102 return new FieldLine<>(transformedP0, transformedP1, line.getTolerance());
103 }
104
105 /**
106 * Transform a line.
107 *
108 * @param line to transform
109 * @return transformed line
110 */
111 default FieldLine<T> transformLine(final FieldLine<T> line) {
112 final FieldVector3D<T> transformedP0 = transformPosition(line.getOrigin());
113 final FieldVector3D<T> transformedP1 = transformPosition(line.pointAt(1.0e6));
114 return new FieldLine<>(transformedP0, transformedP1, line.getTolerance());
115 }
116
117 /** Get the Field date.
118 * This default implementation is there so that no API is broken by a minor release.
119 * It is overloaded by native inheritors and shall be removed in the next major release.
120 * @return Field date attached to the object
121 * @since 12.1
122 */
123 default FieldAbsoluteDate<T> getFieldDate() {
124 return new FieldAbsoluteDate<>(getTranslation().getX().getField(), getDate());
125 }
126
127 /**
128 * Get the underlying elementary translation.
129 * <p>A transform can be uniquely represented as an elementary
130 * translation followed by an elementary rotation. This method returns this
131 * unique elementary translation.</p>
132 *
133 * @return underlying elementary translation
134 */
135 FieldVector3D<T> getTranslation();
136
137 /**
138 * Get the underlying elementary rotation.
139 * <p>A transform can be uniquely represented as an elementary
140 * translation followed by an elementary rotation. This method returns this
141 * unique elementary rotation.</p>
142 *
143 * @return underlying elementary rotation
144 */
145 FieldRotation<T> getRotation();
146
147 /**
148 * Get the inverse transform of the instance.
149 *
150 * @return inverse transform of the instance
151 */
152 FieldStaticTransform<T> getInverse();
153
154 /**
155 * Get the inverse transform of the instance in static form (without rates).
156 * This enables to create a purely static inverse, as inheritors such as {@link FieldTransform} may
157 * have a relatively computationally-heavy #getInverse() method.
158 *
159 * @return inverse static transform of the instance
160 * @since 12.1
161 */
162 default FieldStaticTransform<T> getStaticInverse() {
163 final FieldVector3D<T> negatedTranslation = getTranslation().negate();
164 final FieldRotation<T> rotation = getRotation();
165 return FieldStaticTransform.of(getFieldDate(), rotation.applyTo(negatedTranslation), rotation.revert());
166 }
167
168 /**
169 * Build a transform by combining two existing ones.
170 * <p>
171 * Note that the dates of the two existing transformed are <em>ignored</em>,
172 * and the combined transform date is set to the date supplied in this
173 * constructor without any attempt to shift the raw transforms. This is a
174 * design choice allowing user full control of the combination.
175 * </p>
176 *
177 * @param <T> type of the elements
178 * @param date date of the transform
179 * @param first first transform applied
180 * @param second second transform applied
181 * @return the newly created static transform that has the same effect as
182 * applying {@code first}, then {@code second}.
183 * @see #of(FieldAbsoluteDate, FieldVector3D, FieldRotation)
184 */
185 static <T extends CalculusFieldElement<T>> FieldStaticTransform<T> compose(final FieldAbsoluteDate<T> date,
186 final FieldStaticTransform<T> first,
187 final FieldStaticTransform<T> second) {
188 return of(date,
189 compositeTranslation(first, second),
190 compositeRotation(first, second));
191 }
192
193 /**
194 * Compute a composite translation.
195 *
196 * @param first first applied transform
197 * @param second second applied transform
198 * @param <T> the type of the field elements
199 * @return translation part of the composite transform
200 */
201 static <T extends CalculusFieldElement<T>> FieldVector3D<T> compositeTranslation(final FieldStaticTransform<T> first,
202 final FieldStaticTransform<T> second) {
203
204 final FieldVector3D<T> p1 = first.getTranslation();
205 final FieldRotation<T> r1 = first.getRotation();
206 final FieldVector3D<T> p2 = second.getTranslation();
207
208 return p1.add(r1.applyInverseTo(p2));
209
210 }
211
212 /**
213 * Compute a composite rotation.
214 *
215 * @param first first applied transform
216 * @param second second applied transform
217 * @param <T> the type of the field elements
218 * @return rotation part of the composite transform
219 */
220 static <T extends CalculusFieldElement<T>> FieldRotation<T> compositeRotation(final FieldStaticTransform<T> first,
221 final FieldStaticTransform<T> second) {
222 final FieldRotation<T> r1 = first.getRotation();
223 final FieldRotation<T> r2 = second.getRotation();
224 return r1.compose(r2, RotationConvention.FRAME_TRANSFORM);
225 }
226
227 /**
228 * Create a new static transform from a rotation and zero translation.
229 *
230 * @param <T> type of the elements
231 * @param date of translation.
232 * @param rotation to apply after the translation. That is after translating
233 * applying this rotation produces positions expressed in
234 * the new frame.
235 * @return the newly created static transform.
236 * @see #of(FieldAbsoluteDate, FieldVector3D, FieldRotation)
237 */
238 static <T extends CalculusFieldElement<T>> FieldStaticTransform<T> of(final FieldAbsoluteDate<T> date,
239 final FieldRotation<T> rotation) {
240 return of(date, FieldVector3D.getZero(date.getField()), rotation);
241 }
242
243 /**
244 * Create a new static transform from a translation and rotation.
245 *
246 * @param <T> type of the elements
247 * @param date of translation.
248 * @param translation to apply, expressed in the old frame. That is, the
249 * opposite of the coordinates of the new origin in the
250 * old frame.
251 * @return the newly created static transform.
252 * @see #of(FieldAbsoluteDate, FieldVector3D, FieldRotation)
253 */
254 static <T extends CalculusFieldElement<T>> FieldStaticTransform<T> of(final FieldAbsoluteDate<T> date,
255 final FieldVector3D<T> translation) {
256 return of(date, translation, FieldRotation.getIdentity(date.getField()));
257 }
258
259 /**
260 * Create a new static transform from an {@link FieldAbsoluteDate} and a {@link StaticTransform}.
261 *
262 * @param <T> type of the elements
263 * @param date of translation.
264 * @param staticTransform to apply
265 * @return the newly created static transform.
266 * @see #of(FieldAbsoluteDate, FieldVector3D, FieldRotation)
267 */
268 static <T extends CalculusFieldElement<T>> FieldStaticTransform<T> of(final FieldAbsoluteDate<T> date,
269 final StaticTransform staticTransform) {
270 return of(date,
271 new FieldVector3D<>(date.getField(), staticTransform.getTranslation()),
272 new FieldRotation<>(date.getField(), staticTransform.getRotation()));
273 }
274
275 /**
276 * Create a new static transform from a translation and rotation.
277 *
278 * @param <T> type of the elements
279 * @param date of translation.
280 * @param translation to apply, expressed in the old frame. That is, the
281 * opposite of the coordinates of the new origin in the
282 * old frame.
283 * @param rotation to apply after the translation. That is after
284 * translating applying this rotation produces positions
285 * expressed in the new frame.
286 * @return the newly created static transform.
287 * @see #compose(FieldAbsoluteDate, FieldStaticTransform, FieldStaticTransform)
288 * @see #of(FieldAbsoluteDate, FieldRotation)
289 * @see #of(FieldAbsoluteDate, FieldVector3D)
290 */
291 static <T extends CalculusFieldElement<T>> FieldStaticTransform<T> of(final FieldAbsoluteDate<T> date,
292 final FieldVector3D<T> translation,
293 final FieldRotation<T> rotation) {
294 return new FieldStaticTransform<T>() {
295
296 @Override
297 public FieldStaticTransform<T> getInverse() {
298 final FieldRotation<T> r = getRotation();
299 final FieldVector3D<T> rp = r.applyTo(getTranslation());
300 final FieldVector3D<T> pInv = rp.negate();
301 return FieldStaticTransform.of(date, pInv, rotation.revert());
302 }
303
304 @Override
305 public AbsoluteDate getDate() {
306 return date.toAbsoluteDate();
307 }
308
309 @Override
310 public FieldAbsoluteDate<T> getFieldDate() {
311 return date;
312 }
313
314 @Override
315 public FieldVector3D<T> getTranslation() {
316 return translation;
317 }
318
319 @Override
320 public FieldRotation<T> getRotation() {
321 return rotation;
322 }
323
324 };
325 }
326
327 }