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 }