1 /* Copyright 2002-2025 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 * Override methods for speed.
45 *
46 * @param <T> type of the elements
47 * @param field field used by default
48 * @return identity transform.
49 */
50 static <T extends CalculusFieldElement<T>> FieldStaticTransform<T> getIdentity(final Field<T> field) {
51 return new FieldStaticTransform<T>() {
52 @Override
53 public FieldVector3D<T> getTranslation() {
54 return FieldVector3D.getZero(field);
55 }
56
57 @Override
58 public FieldRotation<T> getRotation() {
59 return FieldRotation.getIdentity(field);
60 }
61
62 @Override
63 public FieldStaticTransform<T> getStaticInverse() {
64 return getInverse();
65 }
66
67 @Override
68 public FieldStaticTransform<T> getInverse() {
69 return this;
70 }
71
72 @Override
73 public AbsoluteDate getDate() {
74 return AbsoluteDate.ARBITRARY_EPOCH;
75 }
76
77 @Override
78 public FieldVector3D<T> transformVector(final FieldVector3D<T> vector) {
79 return new FieldVector3D<>(vector.getX(), vector.getY(), vector.getZ());
80 }
81
82 @Override
83 public FieldVector3D<T> transformVector(final Vector3D vector) {
84 return new FieldVector3D<>(field, vector);
85 }
86
87 @Override
88 public FieldVector3D<T> transformPosition(final FieldVector3D<T> position) {
89 return transformVector(position);
90 }
91
92 @Override
93 public FieldVector3D<T> transformPosition(final Vector3D position) {
94 return transformVector(position);
95 }
96 };
97 }
98
99 /**
100 * Transform a position vector (including translation effects).
101 *
102 * @param position vector to transform
103 * @return transformed position
104 */
105 default FieldVector3D<T> transformPosition(final Vector3D position) {
106 return getRotation().applyTo(getTranslation().add(position));
107 }
108
109 /**
110 * Transform a position vector (including translation effects).
111 *
112 * @param position vector to transform
113 * @return transformed position
114 */
115 default FieldVector3D<T> transformPosition(final FieldVector3D<T> position) {
116 return getRotation().applyTo(getTranslation().add(position));
117 }
118
119 /**
120 * Transform a vector (ignoring translation effects).
121 *
122 * @param vector vector to transform
123 * @return transformed vector
124 */
125 default FieldVector3D<T> transformVector(final Vector3D vector) {
126 return getRotation().applyTo(vector);
127 }
128
129 /**
130 * Transform a vector (ignoring translation effects).
131 *
132 * @param vector vector to transform
133 * @return transformed vector
134 */
135 default FieldVector3D<T> transformVector(final FieldVector3D<T> vector) {
136 return getRotation().applyTo(vector);
137 }
138
139 /**
140 * Transform a line.
141 *
142 * @param line to transform
143 * @return transformed line
144 */
145 default FieldLine<T> transformLine(final Line line) {
146 final FieldVector3D<T> transformedP0 = transformPosition(line.getOrigin());
147 final FieldVector3D<T> transformedP1 = transformPosition(line.pointAt(1.0e6));
148 return new FieldLine<>(transformedP0, transformedP1, line.getTolerance());
149 }
150
151 /**
152 * Transform a line.
153 *
154 * @param line to transform
155 * @return transformed line
156 */
157 default FieldLine<T> transformLine(final FieldLine<T> line) {
158 final FieldVector3D<T> transformedP0 = transformPosition(line.getOrigin());
159 final FieldVector3D<T> transformedP1 = transformPosition(line.pointAt(1.0e6));
160 return new FieldLine<>(transformedP0, transformedP1, line.getTolerance());
161 }
162
163 /** Get the Field date.
164 * This default implementation is there so that no API is broken by a minor release.
165 * It is overloaded by native inheritors and shall be removed in the next major release.
166 * @return Field date attached to the object
167 * @since 12.1
168 */
169 default FieldAbsoluteDate<T> getFieldDate() {
170 return new FieldAbsoluteDate<>(getTranslation().getX().getField(), getDate());
171 }
172
173 /**
174 * Get the underlying elementary translation.
175 * <p>A transform can be uniquely represented as an elementary
176 * translation followed by an elementary rotation. This method returns this
177 * unique elementary translation.</p>
178 *
179 * @return underlying elementary translation
180 */
181 FieldVector3D<T> getTranslation();
182
183 /**
184 * Get the underlying elementary rotation.
185 * <p>A transform can be uniquely represented as an elementary
186 * translation followed by an elementary rotation. This method returns this
187 * unique elementary rotation.</p>
188 *
189 * @return underlying elementary rotation
190 */
191 FieldRotation<T> getRotation();
192
193 /**
194 * Get the inverse transform of the instance.
195 *
196 * @return inverse transform of the instance
197 */
198 FieldStaticTransform<T> getInverse();
199
200 /**
201 * Get the inverse transform of the instance in static form (without rates).
202 * This enables to create a purely static inverse, as inheritors such as {@link FieldTransform} may
203 * have a relatively computationally-heavy #getInverse() method.
204 *
205 * @return inverse static transform of the instance
206 * @since 12.1
207 */
208 default FieldStaticTransform<T> getStaticInverse() {
209 final FieldVector3D<T> negatedTranslation = getTranslation().negate();
210 final FieldRotation<T> rotation = getRotation();
211 return FieldStaticTransform.of(getFieldDate(), rotation.applyTo(negatedTranslation), rotation.revert());
212 }
213
214 /**
215 * Build a transform by combining two existing ones.
216 * <p>
217 * Note that the dates of the two existing transformed are <em>ignored</em>,
218 * and the combined transform date is set to the date supplied in this
219 * constructor without any attempt to shift the raw transforms. This is a
220 * design choice allowing user full control of the combination.
221 * </p>
222 *
223 * @param <T> type of the elements
224 * @param date date of the transform
225 * @param first first transform applied
226 * @param second second transform applied
227 * @return the newly created static transform that has the same effect as
228 * applying {@code first}, then {@code second}.
229 * @see #of(FieldAbsoluteDate, FieldVector3D, FieldRotation)
230 */
231 static <T extends CalculusFieldElement<T>> FieldStaticTransform<T> compose(final FieldAbsoluteDate<T> date,
232 final FieldStaticTransform<T> first,
233 final FieldStaticTransform<T> second) {
234 return of(date,
235 compositeTranslation(first, second),
236 compositeRotation(first, second));
237 }
238
239 /**
240 * Compute a composite translation.
241 *
242 * @param first first applied transform
243 * @param second second applied transform
244 * @param <T> the type of the field elements
245 * @return translation part of the composite transform
246 */
247 static <T extends CalculusFieldElement<T>> FieldVector3D<T> compositeTranslation(final FieldStaticTransform<T> first,
248 final FieldStaticTransform<T> second) {
249
250 final FieldVector3D<T> p1 = first.getTranslation();
251 final FieldRotation<T> r1 = first.getRotation();
252 final FieldVector3D<T> p2 = second.getTranslation();
253
254 return p1.add(r1.applyInverseTo(p2));
255
256 }
257
258 /**
259 * Compute a composite rotation.
260 *
261 * @param first first applied transform
262 * @param second second applied transform
263 * @param <T> the type of the field elements
264 * @return rotation part of the composite transform
265 */
266 static <T extends CalculusFieldElement<T>> FieldRotation<T> compositeRotation(final FieldStaticTransform<T> first,
267 final FieldStaticTransform<T> second) {
268 final FieldRotation<T> r1 = first.getRotation();
269 final FieldRotation<T> r2 = second.getRotation();
270 return r1.compose(r2, RotationConvention.FRAME_TRANSFORM);
271 }
272
273 /**
274 * Create a new static transform from a rotation and zero translation.
275 *
276 * @param <T> type of the elements
277 * @param date of translation.
278 * @param rotation to apply after the translation. That is after translating
279 * applying this rotation produces positions expressed in
280 * the new frame.
281 * @return the newly created static transform.
282 * @see #of(FieldAbsoluteDate, FieldVector3D, FieldRotation)
283 */
284 static <T extends CalculusFieldElement<T>> FieldStaticTransform<T> of(final FieldAbsoluteDate<T> date,
285 final FieldRotation<T> rotation) {
286 return of(date, FieldVector3D.getZero(date.getField()), rotation);
287 }
288
289 /**
290 * Create a new static transform from a translation and rotation.
291 *
292 * @param <T> type of the elements
293 * @param date of translation.
294 * @param translation to apply, expressed in the old frame. That is, the
295 * opposite of the coordinates of the new origin in the
296 * old frame.
297 * @return the newly created static transform.
298 * @see #of(FieldAbsoluteDate, FieldVector3D, FieldRotation)
299 */
300 static <T extends CalculusFieldElement<T>> FieldStaticTransform<T> of(final FieldAbsoluteDate<T> date,
301 final FieldVector3D<T> translation) {
302 return of(date, translation, FieldRotation.getIdentity(date.getField()));
303 }
304
305 /**
306 * Create a new static transform from an {@link FieldAbsoluteDate} and a {@link StaticTransform}.
307 *
308 * @param <T> type of the elements
309 * @param date of translation.
310 * @param staticTransform to apply
311 * @return the newly created static transform.
312 * @see #of(FieldAbsoluteDate, FieldVector3D, FieldRotation)
313 */
314 static <T extends CalculusFieldElement<T>> FieldStaticTransform<T> of(final FieldAbsoluteDate<T> date,
315 final StaticTransform staticTransform) {
316 return of(date,
317 new FieldVector3D<>(date.getField(), staticTransform.getTranslation()),
318 new FieldRotation<>(date.getField(), staticTransform.getRotation()));
319 }
320
321 /**
322 * Create a new static transform from a translation and rotation.
323 *
324 * @param <T> type of the elements
325 * @param date of translation.
326 * @param translation to apply, expressed in the old frame. That is, the
327 * opposite of the coordinates of the new origin in the
328 * old frame.
329 * @param rotation to apply after the translation. That is after
330 * translating applying this rotation produces positions
331 * expressed in the new frame.
332 * @return the newly created static transform.
333 * @see #compose(FieldAbsoluteDate, FieldStaticTransform, FieldStaticTransform)
334 * @see #of(FieldAbsoluteDate, FieldRotation)
335 * @see #of(FieldAbsoluteDate, FieldVector3D)
336 */
337 static <T extends CalculusFieldElement<T>> FieldStaticTransform<T> of(final FieldAbsoluteDate<T> date,
338 final FieldVector3D<T> translation,
339 final FieldRotation<T> rotation) {
340 return new FieldStaticTransform<T>() {
341
342 @Override
343 public FieldStaticTransform<T> getInverse() {
344 final FieldRotation<T> r = getRotation();
345 final FieldVector3D<T> rp = r.applyTo(getTranslation());
346 final FieldVector3D<T> pInv = rp.negate();
347 return FieldStaticTransform.of(date, pInv, rotation.revert());
348 }
349
350 @Override
351 public AbsoluteDate getDate() {
352 return date.toAbsoluteDate();
353 }
354
355 @Override
356 public FieldAbsoluteDate<T> getFieldDate() {
357 return date;
358 }
359
360 @Override
361 public FieldVector3D<T> getTranslation() {
362 return translation;
363 }
364
365 @Override
366 public FieldRotation<T> getRotation() {
367 return rotation;
368 }
369
370 };
371 }
372
373 }