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