1   /* Contributed in the public domain.
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.geometry.euclidean.threed.FieldRotation;
21  import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
22  import org.hipparchus.geometry.euclidean.threed.Line;
23  import org.hipparchus.geometry.euclidean.threed.Rotation;
24  import org.hipparchus.geometry.euclidean.threed.RotationConvention;
25  import org.hipparchus.geometry.euclidean.threed.Vector3D;
26  import org.orekit.time.AbsoluteDate;
27  import org.orekit.time.TimeStamped;
28  
29  /**
30   * A transform that only includes translation and rotation. It is static in the
31   * sense that no rates thereof are included.
32   *
33   * @author Evan Ward
34   * @see Transform
35   * @since 11.2
36   */
37  public interface StaticTransform extends TimeStamped {
38  
39      /**
40       * Get the identity static transform.
41       *
42       * @return identity transform.
43       */
44      static StaticTransform getIdentity() {
45          return Transform.IDENTITY;
46      }
47  
48      /**
49       * Transform a position vector (including translation effects).
50       *
51       * @param position vector to transform
52       * @return transformed position
53       */
54      default Vector3D transformPosition(final Vector3D position) {
55          return getRotation().applyTo(getTranslation().add(position));
56      }
57  
58      /**
59       * Transform a position vector (including translation effects).
60       *
61       * @param position vector to transform
62       * @param <T>      the type of the field elements
63       * @return transformed position
64       */
65      default  <T extends CalculusFieldElement<T>> FieldVector3D<T> transformPosition(
66              final FieldVector3D<T> position) {
67          return FieldRotation.applyTo(getRotation(), position.add(getTranslation()));
68      }
69  
70      /**
71       * Transform a vector (ignoring translation effects).
72       *
73       * @param vector vector to transform
74       * @return transformed vector
75       */
76      default  Vector3D transformVector(final Vector3D vector) {
77          return getRotation().applyTo(vector);
78      }
79  
80      /**
81       * Transform a vector (ignoring translation effects).
82       *
83       * @param vector vector to transform
84       * @param <T>    the type of the field elements
85       * @return transformed vector
86       */
87      default <T extends CalculusFieldElement<T>> FieldVector3D<T> transformVector(
88              final FieldVector3D<T> vector) {
89          return FieldRotation.applyTo(getRotation(), vector);
90      }
91  
92      /**
93       * Transform a line.
94       *
95       * @param line to transform
96       * @return transformed line
97       */
98      default Line transformLine(final Line line) {
99          final Vector3D transformedP0 = transformPosition(line.getOrigin());
100         final Vector3D transformedD  = transformVector(line.getDirection());
101         return Line.fromDirection(transformedP0, transformedD, line.getTolerance());
102     }
103 
104     /**
105      * Get the underlying elementary translation.
106      * <p>A transform can be uniquely represented as an elementary
107      * translation followed by an elementary rotation. This method returns this
108      * unique elementary translation.</p>
109      *
110      * @return underlying elementary translation
111      */
112     Vector3D getTranslation();
113 
114     /**
115      * Get the underlying elementary rotation.
116      * <p>A transform can be uniquely represented as an elementary
117      * translation followed by an elementary rotation. This method returns this
118      * unique elementary rotation.</p>
119      *
120      * @return underlying elementary rotation
121      */
122     Rotation getRotation();
123 
124     /**
125      * Get the inverse transform of the instance.
126      *
127      * @return inverse transform of the instance
128      */
129     StaticTransform getInverse();
130 
131     /**
132      * Build a transform by combining two existing ones.
133      * <p>
134      * Note that the dates of the two existing transformed are <em>ignored</em>,
135      * and the combined transform date is set to the date supplied in this
136      * constructor without any attempt to shift the raw transforms. This is a
137      * design choice allowing user full control of the combination.
138      * </p>
139      *
140      * @param date   date of the transform
141      * @param first  first transform applied
142      * @param second second transform applied
143      * @return the newly created static transform that has the same effect as
144      * applying {@code first}, then {@code second}.
145      * @see #of(AbsoluteDate, Vector3D, Rotation)
146      */
147     static StaticTransform compose(final AbsoluteDate date,
148                                    final StaticTransform first,
149                                    final StaticTransform second) {
150         return of(date,
151                 compositeTranslation(first, second),
152                 compositeRotation(first, second));
153     }
154 
155     /**
156      * Compute a composite translation.
157      *
158      * @param first  first applied transform
159      * @param second second applied transform
160      * @return translation part of the composite transform
161      */
162     static Vector3D compositeTranslation(
163             final StaticTransform first,
164             final StaticTransform second) {
165         final Vector3D p1 = first.getTranslation();
166         final Rotation r1 = first.getRotation();
167         final Vector3D p2 = second.getTranslation();
168 
169         return p1.add(r1.applyInverseTo(p2));
170     }
171 
172     /**
173      * Compute a composite rotation.
174      *
175      * @param first  first applied transform
176      * @param second second applied transform
177      * @return rotation part of the composite transform
178      */
179     static Rotation compositeRotation(final StaticTransform first,
180                                       final StaticTransform second) {
181         final Rotation r1 = first.getRotation();
182         final Rotation r2 = second.getRotation();
183         return r1.compose(r2, RotationConvention.FRAME_TRANSFORM);
184 
185     }
186 
187     /**
188      * Create a new static transform from a rotation and zero translation.
189      *
190      * @param date     of translation.
191      * @param rotation to apply after the translation. That is after translating
192      *                 applying this rotation produces positions expressed in
193      *                 the new frame.
194      * @return the newly created static transform.
195      * @see #of(AbsoluteDate, Vector3D, Rotation)
196      */
197     static StaticTransform of(final AbsoluteDate date,
198                               final Rotation rotation) {
199         return of(date, Vector3D.ZERO, rotation);
200     }
201 
202     /**
203      * Create a new static transform from a translation and rotation.
204      *
205      * @param date        of translation.
206      * @param translation to apply, expressed in the old frame. That is, the
207      *                    opposite of the coordinates of the new origin in the
208      *                    old frame.
209      * @return the newly created static transform.
210      * @see #of(AbsoluteDate, Vector3D, Rotation)
211      */
212     static StaticTransform of(final AbsoluteDate date,
213                               final Vector3D translation) {
214         return of(date, translation, Rotation.IDENTITY);
215     }
216 
217     /**
218      * Create a new static transform from a translation and rotation.
219      *
220      * @param date        of translation.
221      * @param translation to apply, expressed in the old frame. That is, the
222      *                    opposite of the coordinates of the new origin in the
223      *                    old frame.
224      * @param rotation    to apply after the translation. That is after
225      *                    translating applying this rotation produces positions
226      *                    expressed in the new frame.
227      * @return the newly created static transform.
228      * @see #compose(AbsoluteDate, StaticTransform, StaticTransform)
229      * @see #of(AbsoluteDate, Rotation)
230      * @see #of(AbsoluteDate, Vector3D)
231      */
232     static StaticTransform of(final AbsoluteDate date,
233                               final Vector3D translation,
234                               final Rotation rotation) {
235         return new StaticTransform() {
236 
237             @Override
238             public StaticTransform getInverse() {
239                 final Rotation r = getRotation();
240                 final Vector3D rp = r.applyTo(getTranslation());
241                 final Vector3D pInv = rp.negate();
242                 return StaticTransform.of(date, pInv, rotation.revert());
243             }
244 
245             @Override
246             public AbsoluteDate getDate() {
247                 return date;
248             }
249 
250             @Override
251             public Vector3D getTranslation() {
252                 return translation;
253             }
254 
255             @Override
256             public Rotation getRotation() {
257                 return rotation;
258             }
259 
260         };
261     }
262 
263 }