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 * Get the inverse transform of the instance in static form (without rates).
133 * This enables to create a purely static inverse, as inheritors such as {@link Transform} may
134 * have a relatively computationally-heavy #getInverse() method.
135 *
136 * @return inverse static transform of the instance
137 * @since 12.1
138 */
139 default StaticTransform getStaticInverse() {
140 final Rotation rotation = getRotation();
141 return StaticTransform.of(getDate(), rotation.applyTo(getTranslation()).negate(), rotation.revert());
142 }
143
144 /**
145 * Build a transform by combining two existing ones.
146 * <p>
147 * Note that the dates of the two existing transformed are <em>ignored</em>,
148 * and the combined transform date is set to the date supplied in this
149 * constructor without any attempt to shift the raw transforms. This is a
150 * design choice allowing user full control of the combination.
151 * </p>
152 *
153 * @param date date of the transform
154 * @param first first transform applied
155 * @param second second transform applied
156 * @return the newly created static transform that has the same effect as
157 * applying {@code first}, then {@code second}.
158 * @see #of(AbsoluteDate, Vector3D, Rotation)
159 */
160 static StaticTransform compose(final AbsoluteDate date,
161 final StaticTransform first,
162 final StaticTransform second) {
163 return of(date,
164 compositeTranslation(first, second),
165 compositeRotation(first, second));
166 }
167
168 /**
169 * Compute a composite translation.
170 *
171 * @param first first applied transform
172 * @param second second applied transform
173 * @return translation part of the composite transform
174 */
175 static Vector3D compositeTranslation(
176 final StaticTransform first,
177 final StaticTransform second) {
178 final Vector3D p1 = first.getTranslation();
179 final Rotation r1 = first.getRotation();
180 final Vector3D p2 = second.getTranslation();
181
182 return p1.add(r1.applyInverseTo(p2));
183 }
184
185 /**
186 * Compute a composite rotation.
187 *
188 * @param first first applied transform
189 * @param second second applied transform
190 * @return rotation part of the composite transform
191 */
192 static Rotation compositeRotation(final StaticTransform first,
193 final StaticTransform second) {
194 final Rotation r1 = first.getRotation();
195 final Rotation r2 = second.getRotation();
196 return r1.compose(r2, RotationConvention.FRAME_TRANSFORM);
197
198 }
199
200 /**
201 * Create a new static transform from a rotation and zero translation.
202 *
203 * @param date of translation.
204 * @param rotation to apply after the translation. That is after translating
205 * applying this rotation produces positions expressed in
206 * the new frame.
207 * @return the newly created static transform.
208 * @see #of(AbsoluteDate, Vector3D, Rotation)
209 */
210 static StaticTransform of(final AbsoluteDate date,
211 final Rotation rotation) {
212 return of(date, Vector3D.ZERO, rotation);
213 }
214
215 /**
216 * Create a new static transform from a translation and rotation.
217 *
218 * @param date of translation.
219 * @param translation to apply, expressed in the old frame. That is, the
220 * opposite of the coordinates of the new origin in the
221 * old frame.
222 * @return the newly created static transform.
223 * @see #of(AbsoluteDate, Vector3D, Rotation)
224 */
225 static StaticTransform of(final AbsoluteDate date,
226 final Vector3D translation) {
227 return of(date, translation, Rotation.IDENTITY);
228 }
229
230 /**
231 * Create a new static transform from a translation and rotation.
232 *
233 * @param date of translation.
234 * @param translation to apply, expressed in the old frame. That is, the
235 * opposite of the coordinates of the new origin in the
236 * old frame.
237 * @param rotation to apply after the translation. That is after
238 * translating applying this rotation produces positions
239 * expressed in the new frame.
240 * @return the newly created static transform.
241 * @see #compose(AbsoluteDate, StaticTransform, StaticTransform)
242 * @see #of(AbsoluteDate, Rotation)
243 * @see #of(AbsoluteDate, Vector3D)
244 */
245 static StaticTransform of(final AbsoluteDate date,
246 final Vector3D translation,
247 final Rotation rotation) {
248 return new StaticTransform() {
249
250 @Override
251 public StaticTransform getInverse() {
252 final Rotation r = getRotation();
253 final Vector3D rp = r.applyTo(getTranslation());
254 final Vector3D pInv = rp.negate();
255 return StaticTransform.of(date, pInv, rotation.revert());
256 }
257
258 @Override
259 public AbsoluteDate getDate() {
260 return date;
261 }
262
263 @Override
264 public Vector3D getTranslation() {
265 return translation;
266 }
267
268 @Override
269 public Rotation getRotation() {
270 return rotation;
271 }
272
273 };
274 }
275
276 }