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