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 }