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 java.io.Serializable;
20 import java.util.ArrayList;
21 import java.util.Collections;
22 import java.util.List;
23
24 import org.orekit.errors.OrekitException;
25 import org.orekit.errors.OrekitMessages;
26
27
28 /** Prototype frame that can be built from leaf to roots and later attached to a tree.
29 *
30 * <p>Regular {@link Frame} instances can be built only from a parent frame, i.e.
31 * the frames tree can be built only from root to leafs. In some cases, it may
32 * desirable to build a subset tree and attach it to the main tree after build
33 * time, which means the tree is built from leafs to root. This class allows
34 * building this subtree.</p>
35 * <p>
36 * During the build process, the {@link Frame} associated with each {@link OrphanFrame}
37 * is not available. It becomes available only once the {@link OrphanFrame} has been
38 * attached to the main tree, and at this time it can be used to compute
39 * {@link Transform transforms}.
40 * </p>
41 *
42 * @author Luc Maisonobe
43 * @since 6.0
44 */
45 public class OrphanFrame implements Serializable {
46
47 /** Serializable UID. */
48 private static final long serialVersionUID = 20130409L;
49
50 /** Instance name. */
51 private final String name;
52
53 /** Children of the frame. */
54 private final List<OrphanFrame> children;
55
56 /** Parent orphan frame. */
57 private OrphanFrame orphanParent;
58
59 /** Provider for transform from parent frame to instance. */
60 private TransformProvider provider;
61
62 /** Indicator for pseudo-inertial frames. */
63 private boolean pseudoInertial;
64
65 /** Associated frame (available only once attached to the main frames tree). */
66 private Frame frame;
67
68 /** Simple constructor.
69 * @param name name of the frame
70 */
71 public OrphanFrame(final String name) {
72 children = new ArrayList<OrphanFrame>();
73 this.name = name;
74 }
75
76 /** Add a child.
77 * <p>
78 * If a child is added after the instance has been attached, the child and
79 * all its tree will be attached immediately too.
80 * </p>
81 * @param child child to add
82 * @param transform transform from instance to child
83 * @param isPseudoInertial true if child is considered pseudo-inertial
84 * (i.e. suitable for propagating orbit)
85 */
86 public void addChild(final OrphanFrame child, final Transform transform,
87 final boolean isPseudoInertial) {
88 addChild(child, new FixedTransformProvider(transform), isPseudoInertial);
89 }
90
91 /** Add a child.
92 * <p>
93 * If a child is added after the instance has been attached, the child and
94 * all its tree will be attached immediately too.
95 * </p>
96 * @param child child to add
97 * @param transformProvider provider for transform from instance to child
98 * @param isPseudoInertial true if child is considered pseudo-inertial
99 * (i.e. suitable for propagating orbit)
100 */
101 public void addChild(final OrphanFrame child, final TransformProvider transformProvider,
102 final boolean isPseudoInertial) {
103
104 // safety check
105 if (child.orphanParent != null) {
106 throw new OrekitException(OrekitMessages.FRAME_ALREADY_ATTACHED,
107 child.name, child.orphanParent.name);
108 }
109
110 children.add(child);
111 child.orphanParent = this;
112 child.provider = transformProvider;
113 child.pseudoInertial = isPseudoInertial;
114
115 if (frame != null) {
116 // we are attaching a child after having attached the instance,
117 // we process the tree immediately
118 buildTree();
119 }
120
121 }
122
123 /** Attach the instance (and all its children down to leafs) to the main tree.
124 * @param parent parent frame to attach to
125 * @param transform transform from parent frame to instance
126 * @param isPseudoInertial true if frame is considered pseudo-inertial
127 * (i.e. suitable for propagating orbit)
128 */
129 public void attachTo(final Frame parent, final Transform transform,
130 final boolean isPseudoInertial) {
131 attachTo(parent, new FixedTransformProvider(transform), isPseudoInertial);
132 }
133
134 /** Attach the instance (and all its children down to leafs) to the main tree.
135 * @param parent parent frame to attach to
136 * @param transformProvider provider for transform from parent frame to instance
137 * @param isPseudoInertial true if frame is considered pseudo-inertial
138 * (i.e. suitable for propagating orbit)
139 */
140 public void attachTo(final Frame parent, final TransformProvider transformProvider,
141 final boolean isPseudoInertial) {
142
143 // safety check
144 if (orphanParent != null) {
145 throw new OrekitException(OrekitMessages.FRAME_ALREADY_ATTACHED,
146 name, orphanParent.name);
147 }
148
149 // set up the attach point
150 final OrphanFrame op = new OrphanFrame(parent.getName());
151 op.frame = parent;
152 op.addChild(this, transformProvider, isPseudoInertial);
153
154 }
155
156 /** Get all children of the instance.
157 * @return unmodifiable list of children
158 */
159 public List<OrphanFrame> getChildren() {
160 return Collections.unmodifiableList(children);
161 }
162
163 /** Get the associated {@link Frame frame}.
164 * @return associated frame
165 */
166 public Frame getFrame() {
167
168 // safety check
169 if (frame == null) {
170 throw new OrekitException(OrekitMessages.FRAME_NOT_ATTACHED, name);
171 }
172
173 return frame;
174
175 }
176
177 /** Recursively build the frames tree starting at instance, which is already associated.
178 */
179 private void buildTree() {
180 for (final OrphanFrame child : children) {
181
182 if (child.frame == null) {
183
184 // associate the child with a regular frame
185 child.frame = new Frame(frame, child.provider, child.name, child.pseudoInertial);
186
187 // recursively build the rest of the tree
188 child.buildTree();
189
190 }
191
192 }
193 }
194
195 /** {@inheritDoc} */
196 @Override
197 public String toString() {
198 return this.name;
199 }
200
201 }