RayZaler 0.1
The free opto-mechanical simulation framework
ReferenceFrame.h
1//
2// Copyright (c) 2024 Gonzalo José Carracedo Carballal
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU Lesser General Public License as
6// published by the Free Software Foundation, either version 3 of the
7// License, or (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful, but
10// WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU Lesser General Public License for more details.
13//
14// You should have received a copy of the GNU Lesser General Public
15// License along with this program. If not, see
16// <http://www.gnu.org/licenses/>
17//
18
19#ifndef REFERENCEFRAME_H
20#define REFERENCEFRAME_H
21
22#include <string>
23#include <Vector.h>
24#include <Matrix.h>
25#include <map>
26#include <vector>
27#include <list>
28#include <cstdint>
29
30#define RZ_REF_FRAME_WORLD_ID 0x0
31#define RZ_REF_FRAME_ROTATION_ID 0x1000
32#define RZ_REF_FRAME_TRANSLATION_ID 0x1001
33#define RZ_REF_FRAME_TRIPOD_ID 0x1002
34
35namespace RZ{
36 struct NamedVector {
37 std::string name;
38 Vec3 relative; // Relative to the owner
39 Vec3 absolute; // Global
40 };
41
42 //
43 // The global center and orientation are mandatory. After recalculate(), these
44 // must be available. How the global center and orientation is calculated is
45 // completely upon the implementaion of the ReferenceFrame. For instance:
46 //
47 // - We may have a GlobalFrame. The center is always (0, 0, 0) and its
48 // orientation is the identity.
49 // - We may have a RotatedFrame. This would have a pointer to its base frame.
50 // The implementation of recalculate() would look up the center and rotation
51 // axis of its parent, and calculate the new center and orientation. Its
52 // center would be that of the parent but rotated around the rotation center.
53 // The same would apply to the orientation matrix.
54 // - We may also have a CrossProduct frame. This would be calculated from
55 // two previous vectors, etc. In this case, we would have either one
56 // or two dependencies. Maybe assume two different parents?
57 //
58
60 std::string m_name;
61 Vec3 m_center; // Global, calculated
62 Matrix3 m_orientation; // Global, calculated
63 bool m_calculated = false;
64 ReferenceFrame *m_parent = nullptr;
65 int m_parentIndex = -1;
66
67 std::vector<NamedVector> m_axes;
68 std::vector<NamedVector> m_points;
69
70 std::map<std::string, int> m_nameToAxis;
71 std::map<std::string, int> m_nameToPoint;
72
73 // When adding axes and points, these caches get cleared.
74 std::map<std::string, Vec3 *> m_nameToAxisCache;
75 std::map<std::string, Vec3 *> m_nameToPointCache;
76
77 std::vector<ReferenceFrame *> m_children; // Dependents
78
79 void recalculateVectors();
80
81 protected:
82 uint32_t m_typeId = 0;
83
84 ReferenceFrame(std::string const &);
85 ReferenceFrame(std::string const &, ReferenceFrame *);
86
87 void addChild(ReferenceFrame *);
88 void removeChild(ReferenceFrame *);
89
90 virtual void recalculateFrame() = 0;
91
92 void setCenter(Vec3 const &);
93 void setOrientation(Matrix3 const &);
94
95 public:
96 virtual ~ReferenceFrame();
97
98 // These are added by the dependants or elements. Let us say that
99 // this frame was used to create a rotated frame around certain axis
100 // defined in this frame. In this case, the dependent would have
101 // called addAxis("new_frame.rot_axis", ...) and addPoint("new_frame.rot_center")
102 // upon us. This axis and point would belong to us, and we would be in
103 // charge not only of recalculating them, but on calling recalculate()
104 // on the children that needed this.
105 inline bool
106 isCalculated() const
107 {
108 return m_calculated;
109 }
110
111 inline ReferenceFrame *
112 parent() const
113 {
114 return m_parent;
115 }
116
117 inline std::string
118 name() const
119 {
120 return m_name;
121 }
122
123 inline Vec3
124 eX() const
125 {
126 return m_orientation.t().rows[0];
127 }
128
129 inline Vec3
130 eY() const
131 {
132 return m_orientation.t().rows[1];
133 }
134
135 inline Vec3
136 eZ() const
137 {
138 return m_orientation.t().rows[2];
139 }
140
141 inline uint32_t
142 typeId() const
143 {
144 return m_typeId;
145 }
146
147 inline const char *
148 typeString() const
149 {
150 switch (m_typeId) {
151 case RZ_REF_FRAME_WORLD_ID:
152 return "World";
153 case RZ_REF_FRAME_ROTATION_ID:
154 return "Rotation";
155 case RZ_REF_FRAME_TRANSLATION_ID:
156 return "Translation";
157 case RZ_REF_FRAME_TRIPOD_ID:
158 return "Tripod";
159 }
160
161 return nullptr;
162 }
163
164 inline Vec3
165 toRelative(Vec3 const &absv) const
166 {
167 return m_orientation.t() * (absv - getCenter());
168 }
169
170 inline Vec3
171 fromRelative(Vec3 const &relv) const
172 {
173 return m_orientation * relv + getCenter();
174 }
175
176 inline Vec3
177 toRelativeVec(Vec3 const &absv) const
178 {
179 return m_orientation.t() * absv;
180 }
181
182 inline Vec3
183 fromRelativeVec(Vec3 const &relv) const
184 {
185 return m_orientation * relv;
186 }
187
188 int replaceAxis(std::string const &, Vec3 const &);
189 int replacePoint(std::string const &, Point3 const &);
190
191 int addAxis(std::string const &, Vec3 const &); // Relative (to this)
192 int addPoint(std::string const &, Point3 const &); // Relative (to this)
193
194 void recalculate(); // Recalculate this and all children
195 void recalculateChildren(); // Recalculate children only
196 const Matrix3 &getOrientation() const; // Global
197 const Point3 &getCenter() const; // Global
198
199 int getAxisIndex(std::string const &) const;
200 int getPointIndex(std::string const &) const;
201
202 const Vec3 *getAxis(std::string const &); // Global
203 const Point3 *getPoint(std::string const &); // Global
204
205 const Vec3 *getAxis(std::string const &) const; // Global
206 const Point3 *getPoint(std::string const &) const; // Global
207
208 const Vec3 *getAxis(int) const; // Global
209 const Point3 *getPoint(int) const; // Global
210
211 Vec3 *getAxis(int); // Global
212 Point3 *getPoint(int); // Global
213
214 friend class WorldFrame;
215 };
216}
217
218#endif // REFERENCEFRAME_H
Definition: ReferenceFrame.h:59
Definition: WorldFrame.h:25
Definition: Matrix.h:48
Definition: ReferenceFrame.h:36
Definition: Vector.h:66