transform properties
This commit is contained in:
@@ -9,7 +9,7 @@ namespace uLib {
|
|||||||
/**
|
/**
|
||||||
* @brief ObjectsContext represents a collection of Object instances.
|
* @brief ObjectsContext represents a collection of Object instances.
|
||||||
*/
|
*/
|
||||||
class ObjectsContext : public Object {
|
class ObjectsContext : virtual public Object {
|
||||||
public:
|
public:
|
||||||
ObjectsContext();
|
ObjectsContext();
|
||||||
virtual ~ObjectsContext();
|
virtual ~ObjectsContext();
|
||||||
|
|||||||
@@ -137,6 +137,11 @@ public:
|
|||||||
void serialize(Archive::hrt_iarchive & ar, const unsigned int v) override { serialize_impl(ar, v); }
|
void serialize(Archive::hrt_iarchive & ar, const unsigned int v) override { serialize_impl(ar, v); }
|
||||||
void serialize(Archive::log_archive & ar, const unsigned int v) override { serialize_impl(ar, v); }
|
void serialize(Archive::log_archive & ar, const unsigned int v) override { serialize_impl(ar, v); }
|
||||||
|
|
||||||
|
virtual void Updated() override {
|
||||||
|
PropertyBase::Updated();
|
||||||
|
this->PropertyChanged();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string m_name;
|
std::string m_name;
|
||||||
std::string m_units;
|
std::string m_units;
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ class G4Event;
|
|||||||
namespace uLib {
|
namespace uLib {
|
||||||
namespace Geant {
|
namespace Geant {
|
||||||
|
|
||||||
class EmitterPrimary : public G4VUserPrimaryGeneratorAction, public Object, public AffineTransform
|
class EmitterPrimary : public G4VUserPrimaryGeneratorAction, public AffineTransform
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ namespace uLib {
|
|||||||
*/
|
*/
|
||||||
class Assembly : public ObjectsContext, public AffineTransform {
|
class Assembly : public ObjectsContext, public AffineTransform {
|
||||||
public:
|
public:
|
||||||
|
uLibTypeMacro(Assembly, ObjectsContext, AffineTransform)
|
||||||
virtual const char *GetClassName() const override { return "Assembly"; }
|
virtual const char *GetClassName() const override { return "Assembly"; }
|
||||||
|
|
||||||
Assembly();
|
Assembly();
|
||||||
|
|||||||
@@ -44,16 +44,17 @@ namespace uLib {
|
|||||||
* that defines the box's specific origin and size relative to its own
|
* that defines the box's specific origin and size relative to its own
|
||||||
* coordinate system.
|
* coordinate system.
|
||||||
*/
|
*/
|
||||||
class ContainerBox : public AffineTransform, public Object {
|
class ContainerBox : public AffineTransform {
|
||||||
|
|
||||||
typedef AffineTransform BaseClass;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
uLibTypeMacro(ContainerBox, AffineTransform)
|
||||||
|
|
||||||
|
virtual const char * GetClassName() const override { return "ContainerBox"; }
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
// PROPERTIES //
|
// PROPERTIES //
|
||||||
Property<Vector3f> p_Size;
|
Vector3f Size;
|
||||||
Property<Vector3f> p_Origin;
|
Vector3f Origin;
|
||||||
virtual const char * GetClassName() const { return "ContainerBox"; }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Default constructor.
|
* @brief Default constructor.
|
||||||
@@ -61,10 +62,10 @@ public:
|
|||||||
*/
|
*/
|
||||||
ContainerBox()
|
ContainerBox()
|
||||||
: m_LocalT(this), // BaseClass is Parent of m_LocalTransform
|
: m_LocalT(this), // BaseClass is Parent of m_LocalTransform
|
||||||
p_Size(this, "Size", Vector3f(1.0f, 1.0f, 1.0f)),
|
Size(1.0f, 1.0f, 1.0f),
|
||||||
p_Origin(this, "Origin", Vector3f(0.0f, 0.0f, 0.0f)) {
|
Origin(0.0f, 0.0f, 0.0f) {
|
||||||
Object::connect(&p_Size, &Property<Vector3f>::PropertyChanged, this, &ContainerBox::SyncSize);
|
ULIB_ACTIVATE_PROPERTIES(*this);
|
||||||
Object::connect(&p_Origin, &Property<Vector3f>::PropertyChanged, this, &ContainerBox::SyncOrigin);
|
this->Sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -73,11 +74,10 @@ public:
|
|||||||
*/
|
*/
|
||||||
ContainerBox(const Vector3f &size)
|
ContainerBox(const Vector3f &size)
|
||||||
: m_LocalT(this),
|
: m_LocalT(this),
|
||||||
p_Size(this, "Size", size),
|
Size(size),
|
||||||
p_Origin(this, "Origin", Vector3f(0.0f, 0.0f, 0.0f)) {
|
Origin(0.0f, 0.0f, 0.0f) {
|
||||||
Object::connect(&p_Size, &Property<Vector3f>::PropertyChanged, this, &ContainerBox::SyncSize);
|
ULIB_ACTIVATE_PROPERTIES(*this);
|
||||||
Object::connect(&p_Origin, &Property<Vector3f>::PropertyChanged, this, &ContainerBox::SyncOrigin);
|
this->Sync();
|
||||||
this->SetSize(size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -85,13 +85,21 @@ public:
|
|||||||
* @param copy The ContainerBox instance to copy from.
|
* @param copy The ContainerBox instance to copy from.
|
||||||
*/
|
*/
|
||||||
ContainerBox(const ContainerBox ©)
|
ContainerBox(const ContainerBox ©)
|
||||||
: m_LocalT(copy.m_LocalT), // Copy local transform state
|
: m_LocalT(this), // Reset parent to the new object
|
||||||
AffineTransform(copy),
|
AffineTransform(copy),
|
||||||
p_Size(this, "Size", copy.p_Size),
|
Size(copy.Size),
|
||||||
p_Origin(this, "Origin", copy.p_Origin) {
|
Origin(copy.Origin) {
|
||||||
m_LocalT.SetParent(this); // Reset parent to the new object
|
ULIB_ACTIVATE_PROPERTIES(*this);
|
||||||
Object::connect(&p_Size, &Property<Vector3f>::PropertyChanged, this, &ContainerBox::SyncSize);
|
this->Sync();
|
||||||
Object::connect(&p_Origin, &Property<Vector3f>::PropertyChanged, this, &ContainerBox::SyncOrigin);
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Serialization template for property registration and persistence.
|
||||||
|
*/
|
||||||
|
template <class ArchiveT>
|
||||||
|
void serialize(ArchiveT & ar, const unsigned int version) {
|
||||||
|
ar & HRP(Size);
|
||||||
|
ar & HRP(Origin);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -99,7 +107,7 @@ public:
|
|||||||
* @param v The origin position vector.
|
* @param v The origin position vector.
|
||||||
*/
|
*/
|
||||||
void SetOrigin(const Vector3f &v) {
|
void SetOrigin(const Vector3f &v) {
|
||||||
p_Origin = v;
|
Origin = v;
|
||||||
m_LocalT.SetPosition(v);
|
m_LocalT.SetPosition(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,7 +123,7 @@ public:
|
|||||||
* @param v The size vector (width, height, depth).
|
* @param v The size vector (width, height, depth).
|
||||||
*/
|
*/
|
||||||
void SetSize(const Vector3f &v) {
|
void SetSize(const Vector3f &v) {
|
||||||
p_Size = v;
|
Size = v;
|
||||||
Vector3f pos = this->GetOrigin();
|
Vector3f pos = this->GetOrigin();
|
||||||
m_LocalT = AffineTransform(this); // regenerate local transform
|
m_LocalT = AffineTransform(this); // regenerate local transform
|
||||||
m_LocalT.Scale(v);
|
m_LocalT.Scale(v);
|
||||||
@@ -194,26 +202,27 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Translate using transformation chain */
|
/** Translate using transformation chain */
|
||||||
using BaseClass::Translate;
|
using AffineTransform::Translate;
|
||||||
|
|
||||||
/** Rotate using transformation chain */
|
/** Rotate using transformation chain */
|
||||||
using BaseClass::Rotate;
|
using AffineTransform::Rotate;
|
||||||
|
|
||||||
/** Scale using transformation chain */
|
/** Scale using transformation chain */
|
||||||
using BaseClass::Scale;
|
using AffineTransform::Scale;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
// signal to emit when the box is updated //
|
/** Signal emitted when properties change */
|
||||||
virtual void Updated() override { ULIB_SIGNAL_EMIT(ContainerBox::Updated); }
|
virtual void Updated() override {
|
||||||
|
this->Sync();
|
||||||
private slots:
|
ULIB_SIGNAL_EMIT(ContainerBox::Updated);
|
||||||
void SyncSize() {
|
|
||||||
this->SetSize(p_Size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SyncOrigin() {
|
private:
|
||||||
this->SetOrigin(p_Origin);
|
/** Synchronizes internal transformation with properties */
|
||||||
|
void Sync() {
|
||||||
|
this->SetOrigin(Origin);
|
||||||
|
this->SetSize(Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -39,10 +39,17 @@ namespace uLib {
|
|||||||
* The cylinder orientation is defined by the Axis property (0=X, 1=Y, 2=Z).
|
* The cylinder orientation is defined by the Axis property (0=X, 1=Y, 2=Z).
|
||||||
* By default, it is aligned with the Y axis (Axis=1).
|
* By default, it is aligned with the Y axis (Axis=1).
|
||||||
*/
|
*/
|
||||||
class Cylinder : public AffineTransform, public Object {
|
class Cylinder : public AffineTransform {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
uLibTypeMacro(Cylinder, Object)
|
uLibTypeMacro(Cylinder, AffineTransform)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief PROPERTIES
|
||||||
|
*/
|
||||||
|
float Radius;
|
||||||
|
float Height;
|
||||||
|
int Axis;
|
||||||
|
|
||||||
virtual const char * GetClassName() const override { return "Cylinder"; }
|
virtual const char * GetClassName() const override { return "Cylinder"; }
|
||||||
|
|
||||||
@@ -51,7 +58,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
Cylinder() : m_LocalT(this), Radius(1.0), Height(1.0), Axis(1) {
|
Cylinder() : m_LocalT(this), Radius(1.0), Height(1.0), Axis(1) {
|
||||||
ULIB_ACTIVATE_PROPERTIES(*this);
|
ULIB_ACTIVATE_PROPERTIES(*this);
|
||||||
UpdateLocalMatrix();
|
this->Sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -60,7 +67,7 @@ public:
|
|||||||
Cylinder(float radius, float height, int axis = 1)
|
Cylinder(float radius, float height, int axis = 1)
|
||||||
: m_LocalT(this), Radius(radius), Height(height), Axis(axis) {
|
: m_LocalT(this), Radius(radius), Height(height), Axis(axis) {
|
||||||
ULIB_ACTIVATE_PROPERTIES(*this);
|
ULIB_ACTIVATE_PROPERTIES(*this);
|
||||||
UpdateLocalMatrix();
|
this->Sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -69,7 +76,7 @@ public:
|
|||||||
Cylinder(const Cylinder ©)
|
Cylinder(const Cylinder ©)
|
||||||
: m_LocalT(this), AffineTransform(copy), Radius(copy.Radius), Height(copy.Height), Axis(copy.Axis) {
|
: m_LocalT(this), AffineTransform(copy), Radius(copy.Radius), Height(copy.Height), Axis(copy.Axis) {
|
||||||
ULIB_ACTIVATE_PROPERTIES(*this);
|
ULIB_ACTIVATE_PROPERTIES(*this);
|
||||||
this->UpdateLocalMatrix();
|
this->Sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -85,7 +92,7 @@ public:
|
|||||||
/** Sets the radius of the cylinder */
|
/** Sets the radius of the cylinder */
|
||||||
inline void SetRadius(float r) {
|
inline void SetRadius(float r) {
|
||||||
Radius = r;
|
Radius = r;
|
||||||
UpdateLocalMatrix();
|
this->Sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets the radius of the cylinder */
|
/** Gets the radius of the cylinder */
|
||||||
@@ -94,7 +101,7 @@ public:
|
|||||||
/** Sets the height of the cylinder */
|
/** Sets the height of the cylinder */
|
||||||
inline void SetHeight(float h) {
|
inline void SetHeight(float h) {
|
||||||
Height = h;
|
Height = h;
|
||||||
UpdateLocalMatrix();
|
this->Sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets the height of the cylinder */
|
/** Gets the height of the cylinder */
|
||||||
@@ -103,7 +110,7 @@ public:
|
|||||||
/** Sets the main axis (0=X, 1=Y, 2=Z) */
|
/** Sets the main axis (0=X, 1=Y, 2=Z) */
|
||||||
inline void SetAxis(int axis) {
|
inline void SetAxis(int axis) {
|
||||||
Axis = axis;
|
Axis = axis;
|
||||||
UpdateLocalMatrix();
|
this->Sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets the main axis */
|
/** Gets the main axis */
|
||||||
@@ -157,25 +164,33 @@ public:
|
|||||||
return Vector3f(r, theta, h);
|
return Vector3f(r, theta, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Translate using transformation chain */
|
||||||
|
using AffineTransform::Translate;
|
||||||
|
|
||||||
|
/** Rotate using transformation chain */
|
||||||
|
using AffineTransform::Rotate;
|
||||||
|
|
||||||
|
/** Scale using transformation chain */
|
||||||
|
using AffineTransform::Scale;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
/** Signal emitted when properties change */
|
/** Signal emitted when properties change */
|
||||||
virtual void Updated() override {
|
virtual void Updated() override {
|
||||||
this->UpdateLocalMatrix();
|
this->Sync();
|
||||||
ULIB_SIGNAL_EMIT(Cylinder::Updated);
|
ULIB_SIGNAL_EMIT(Cylinder::Updated);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/** Recalculates the internal local matrix based on dimensions and axis */
|
/** Synchronizes internal transformation with properties */
|
||||||
void UpdateLocalMatrix() {
|
void Sync() {
|
||||||
m_LocalT = AffineTransform(this);
|
m_LocalT = AffineTransform(this);
|
||||||
if (Axis == 0) m_LocalT.Scale(Vector3f(Height, Radius, Radius));
|
if (Axis == 0) m_LocalT.Scale(Vector3f(Height, Radius, Radius));
|
||||||
else if (Axis == 1) m_LocalT.Scale(Vector3f(Radius, Height, Radius));
|
else if (Axis == 1) m_LocalT.Scale(Vector3f(Radius, Height, Radius));
|
||||||
else m_LocalT.Scale(Vector3f(Radius, Radius, Height));
|
else m_LocalT.Scale(Vector3f(Radius, Radius, Height));
|
||||||
}
|
}
|
||||||
|
|
||||||
float Radius;
|
|
||||||
float Height;
|
private:
|
||||||
int Axis;
|
|
||||||
AffineTransform m_LocalT;
|
AffineTransform m_LocalT;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -35,10 +35,11 @@
|
|||||||
|
|
||||||
namespace uLib {
|
namespace uLib {
|
||||||
|
|
||||||
class Geometry : public AffineTransform, public Object {
|
class Geometry : public AffineTransform {
|
||||||
public:
|
public:
|
||||||
|
uLibTypeMacro(Geometry, AffineTransform)
|
||||||
|
|
||||||
virtual const char * GetClassName() const { return "Geometry"; }
|
virtual const char * GetClassName() const override { return "Geometry"; }
|
||||||
|
|
||||||
virtual Vector3f ToLinear(const Vector3f& curved_space) const {
|
virtual Vector3f ToLinear(const Vector3f& curved_space) const {
|
||||||
return curved_space;
|
return curved_space;
|
||||||
@@ -70,6 +71,7 @@ public:
|
|||||||
|
|
||||||
class CylindricalGeometry : public Geometry {
|
class CylindricalGeometry : public Geometry {
|
||||||
public:
|
public:
|
||||||
|
uLibTypeMacro(CylindricalGeometry, Geometry)
|
||||||
CylindricalGeometry() {}
|
CylindricalGeometry() {}
|
||||||
|
|
||||||
Vector3f ToLinear(const Vector3f& cylindrical) const {
|
Vector3f ToLinear(const Vector3f& cylindrical) const {
|
||||||
@@ -88,9 +90,10 @@ public:
|
|||||||
|
|
||||||
class SphericalGeometry : public Geometry {
|
class SphericalGeometry : public Geometry {
|
||||||
public:
|
public:
|
||||||
|
uLibTypeMacro(SphericalGeometry, Geometry)
|
||||||
SphericalGeometry() {}
|
SphericalGeometry() {}
|
||||||
|
|
||||||
virtual const char * GetClassName() const { return "SphericalGeometry"; }
|
virtual const char * GetClassName() const override { return "SphericalGeometry"; }
|
||||||
|
|
||||||
Vector3f ToLinear(const Vector3f& spherical) const {
|
Vector3f ToLinear(const Vector3f& spherical) const {
|
||||||
float r = spherical.x();
|
float r = spherical.x();
|
||||||
@@ -112,9 +115,10 @@ public:
|
|||||||
|
|
||||||
class ToroidalGeometry : public Geometry {
|
class ToroidalGeometry : public Geometry {
|
||||||
public:
|
public:
|
||||||
|
uLibTypeMacro(ToroidalGeometry, Geometry)
|
||||||
ToroidalGeometry(float Rtor) : m_Rtor(Rtor) {}
|
ToroidalGeometry(float Rtor) : m_Rtor(Rtor) {}
|
||||||
|
|
||||||
virtual const char * GetClassName() const { return "ToroidalGeometry"; }
|
virtual const char * GetClassName() const override { return "ToroidalGeometry"; }
|
||||||
|
|
||||||
Vector3f ToLinear(const Vector3f& toroidal) const {
|
Vector3f ToLinear(const Vector3f& toroidal) const {
|
||||||
float r = toroidal.x();
|
float r = toroidal.x();
|
||||||
|
|||||||
@@ -34,11 +34,12 @@
|
|||||||
|
|
||||||
namespace uLib {
|
namespace uLib {
|
||||||
|
|
||||||
class QuadMesh : public AffineTransform, public Object
|
class QuadMesh : public AffineTransform
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
uLibTypeMacro(QuadMesh, AffineTransform)
|
||||||
|
|
||||||
virtual const char * GetClassName() const { return "QuadMesh"; }
|
virtual const char * GetClassName() const override { return "QuadMesh"; }
|
||||||
|
|
||||||
void PrintSelf(std::ostream &o);
|
void PrintSelf(std::ostream &o);
|
||||||
|
|
||||||
|
|||||||
@@ -50,6 +50,7 @@
|
|||||||
#define U_TRANSFORM_H
|
#define U_TRANSFORM_H
|
||||||
|
|
||||||
#include <Eigen/Geometry>
|
#include <Eigen/Geometry>
|
||||||
|
#include "Math/Units.h"
|
||||||
#include "Math/Dense.h"
|
#include "Math/Dense.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -59,27 +60,65 @@ namespace uLib {
|
|||||||
///////// AFFINE TRANSFORM WRAPPER //////////////////////////////////////////
|
///////// AFFINE TRANSFORM WRAPPER //////////////////////////////////////////
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
class AffineTransform {
|
class AffineTransform : virtual public Object {
|
||||||
|
public:
|
||||||
|
uLibTypeMacro(AffineTransform, Object)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Grouped transformation parameters for property-based control.
|
||||||
|
*/
|
||||||
|
struct {
|
||||||
|
Vector3f Position = Vector3f::Zero();
|
||||||
|
Vector3f Orientation = Vector3f::Zero();
|
||||||
|
Vector3f Scale = Vector3f::Ones();
|
||||||
|
|
||||||
|
template <class ArchiveT>
|
||||||
|
void serialize(ArchiveT & ar, const unsigned int version) {
|
||||||
|
ar & HRPU(Position, "mm");
|
||||||
|
ar & HRPU(Orientation, "deg");
|
||||||
|
ar & HRP(Scale);
|
||||||
|
}
|
||||||
|
} Transform;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Eigen::Affine3f m_T;
|
Eigen::Affine3f m_T;
|
||||||
AffineTransform *m_Parent;
|
AffineTransform *m_Parent;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AffineTransform() :
|
AffineTransform() :
|
||||||
m_T(Matrix4f::Identity()),
|
m_T(Matrix4f::Identity()),
|
||||||
m_Parent(NULL)
|
m_Parent(NULL)
|
||||||
{}
|
{
|
||||||
|
ULIB_ACTIVATE_PROPERTIES(*this);
|
||||||
|
this->Sync();
|
||||||
|
}
|
||||||
|
|
||||||
virtual ~AffineTransform() {}
|
virtual ~AffineTransform() {}
|
||||||
|
|
||||||
AffineTransform(AffineTransform *parent) :
|
AffineTransform(AffineTransform *parent) :
|
||||||
m_T(Matrix4f::Identity()),
|
m_T(Matrix4f::Identity()),
|
||||||
m_Parent(parent)
|
m_Parent(parent)
|
||||||
{}
|
{
|
||||||
|
ULIB_ACTIVATE_PROPERTIES(*this);
|
||||||
|
this->Sync();
|
||||||
|
}
|
||||||
|
|
||||||
AffineTransform(const AffineTransform ©) :
|
AffineTransform(const AffineTransform ©) :
|
||||||
m_T(copy.m_T),
|
m_T(copy.m_T),
|
||||||
m_Parent(copy.m_Parent)
|
m_Parent(copy.m_Parent),
|
||||||
{}
|
Transform(copy.Transform)
|
||||||
|
{
|
||||||
|
ULIB_ACTIVATE_PROPERTIES(*this);
|
||||||
|
this->Sync();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Registration of properties in groups.
|
||||||
|
*/
|
||||||
|
template <class ArchiveT>
|
||||||
|
void serialize(ArchiveT & ar, const unsigned int version) {
|
||||||
|
ar & boost::serialization::make_nvp("Transform", Transform);
|
||||||
|
}
|
||||||
|
|
||||||
Eigen::Affine3f& GetTransform() { return m_T; }
|
Eigen::Affine3f& GetTransform() { return m_T; }
|
||||||
|
|
||||||
@@ -87,7 +126,11 @@ public:
|
|||||||
|
|
||||||
void SetParent(AffineTransform *name) { this->m_Parent = name; }
|
void SetParent(AffineTransform *name) { this->m_Parent = name; }
|
||||||
|
|
||||||
void SetMatrix (Matrix4f mat) { m_T.matrix() = mat; }
|
void SetMatrix (Matrix4f mat) {
|
||||||
|
m_T.matrix() = mat;
|
||||||
|
this->UpdatePropertiesFromMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
Matrix4f GetMatrix() const { return m_T.matrix(); }
|
Matrix4f GetMatrix() const { return m_T.matrix(); }
|
||||||
|
|
||||||
Matrix4f GetWorldMatrix() const
|
Matrix4f GetWorldMatrix() const
|
||||||
@@ -96,32 +139,51 @@ public:
|
|||||||
else return m_Parent->GetWorldMatrix() * m_T.matrix(); // T = B * A //
|
else return m_Parent->GetWorldMatrix() * m_T.matrix(); // T = B * A //
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetPosition(const Vector3f v) { this->m_T.translation() = v; }
|
void SetPosition(const Vector3f v) {
|
||||||
|
this->Transform.Position = v;
|
||||||
|
this->Sync();
|
||||||
|
}
|
||||||
|
|
||||||
Vector3f GetPosition() const { return this->m_T.translation(); }
|
Vector3f GetPosition() const { return this->Transform.Position; }
|
||||||
|
|
||||||
void SetRotation(const Matrix3f m) { this->m_T.linear() = m; }
|
void SetRotation(const Matrix3f m) {
|
||||||
|
this->m_T.linear() = m;
|
||||||
|
this->UpdatePropertiesFromMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
Matrix3f GetRotation() const { return this->m_T.rotation(); }
|
Matrix3f GetRotation() const { return this->m_T.rotation(); }
|
||||||
|
|
||||||
void Translate(const Vector3f v) { this->m_T.translate(v); }
|
void Translate(const Vector3f v) {
|
||||||
|
this->Transform.Position += v;
|
||||||
void Scale(const Vector3f v) { this->m_T.scale(v); }
|
this->Sync();
|
||||||
|
|
||||||
Vector3f GetScale() const {
|
|
||||||
return Vector3f(m_T.linear().col(0).norm(),
|
|
||||||
m_T.linear().col(1).norm(),
|
|
||||||
m_T.linear().col(2).norm());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Scale(const Vector3f v) {
|
||||||
|
this->Transform.Scale = this->Transform.Scale.cwiseProduct(v);
|
||||||
|
this->Sync();
|
||||||
|
}
|
||||||
|
|
||||||
void Rotate(const Matrix3f m) { this->m_T.rotate(m); }
|
Vector3f GetScale() const { return this->Transform.Scale; }
|
||||||
|
|
||||||
|
void SetOrientation(const Vector3f v) {
|
||||||
|
this->Transform.Orientation = v;
|
||||||
|
this->Sync();
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3f GetOrientation() const { return this->Transform.Orientation; }
|
||||||
|
|
||||||
|
|
||||||
|
void Rotate(const Matrix3f m) {
|
||||||
|
this->m_T.rotate(m);
|
||||||
|
this->UpdatePropertiesFromMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
void Rotate(const float angle, Vector3f axis)
|
void Rotate(const float angle, Vector3f axis)
|
||||||
{
|
{
|
||||||
axis.normalize(); // prehaps not necessary ( see eigens )
|
axis.normalize();
|
||||||
Eigen::AngleAxisf ax(angle,axis);
|
Eigen::AngleAxisf ax(angle,axis);
|
||||||
this->m_T.rotate(Eigen::Quaternion<float>(ax));
|
this->m_T.rotate(Eigen::Quaternion<float>(ax));
|
||||||
|
this->UpdatePropertiesFromMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Rotate(const Vector3f euler_axis) {
|
void Rotate(const Vector3f euler_axis) {
|
||||||
@@ -129,17 +191,14 @@ public:
|
|||||||
Rotate(angle,euler_axis);
|
Rotate(angle,euler_axis);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PreRotate(const Matrix3f m) { this->m_T.prerotate(m); }
|
void PreRotate(const Matrix3f m) { this->m_T.prerotate(m); this->UpdatePropertiesFromMatrix(); }
|
||||||
|
|
||||||
void QuaternionRotate(const Vector4f q)
|
void QuaternionRotate(const Vector4f q)
|
||||||
{ this->m_T.rotate(Eigen::Quaternion<float>(q)); }
|
{ this->m_T.rotate(Eigen::Quaternion<float>(q)); this->UpdatePropertiesFromMatrix(); }
|
||||||
|
|
||||||
void EulerYZYRotate(const Vector3f e) {
|
void EulerYZYRotate(const Vector3f e) {
|
||||||
Matrix3f mat;
|
this->Transform.Orientation = e;
|
||||||
mat = Eigen::AngleAxisf(e.x(), Vector3f::UnitY())
|
this->Sync();
|
||||||
* Eigen::AngleAxisf(e.y(), Vector3f::UnitZ())
|
|
||||||
* Eigen::AngleAxisf(e.z(), Vector3f::UnitY());
|
|
||||||
m_T.rotate(mat);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlipAxes(int first, int second)
|
void FlipAxes(int first, int second)
|
||||||
@@ -147,6 +206,60 @@ public:
|
|||||||
Matrix3f mat = Matrix3f::Identity();
|
Matrix3f mat = Matrix3f::Identity();
|
||||||
mat.col(first).swap(mat.col(second));
|
mat.col(first).swap(mat.col(second));
|
||||||
m_T.rotate(mat);
|
m_T.rotate(mat);
|
||||||
|
this->UpdatePropertiesFromMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Decomposes the internal matrix m_T back into Position, Orientation, and Scale properties.
|
||||||
|
*/
|
||||||
|
void UpdatePropertiesFromMatrix() {
|
||||||
|
// 1. Position
|
||||||
|
Transform.Position = m_T.translation();
|
||||||
|
|
||||||
|
// 2. Scale
|
||||||
|
Matrix3f linear = m_T.linear();
|
||||||
|
Transform.Scale(0) = linear.col(0).norm();
|
||||||
|
Transform.Scale(1) = linear.col(1).norm();
|
||||||
|
Transform.Scale(2) = linear.col(2).norm();
|
||||||
|
|
||||||
|
// 3. Rotation (Normalization removes scale)
|
||||||
|
Matrix3f rotation = linear;
|
||||||
|
if (Transform.Scale(0) > 1e-6) rotation.col(0) /= Transform.Scale(0);
|
||||||
|
if (Transform.Scale(1) > 1e-6) rotation.col(1) /= Transform.Scale(1);
|
||||||
|
if (Transform.Scale(2) > 1e-6) rotation.col(2) /= Transform.Scale(2);
|
||||||
|
|
||||||
|
// Euler YZY (indices 1, 2, 1)
|
||||||
|
Vector3f euler = rotation.eulerAngles(1, 2, 1);
|
||||||
|
Transform.Orientation = euler / CLHEP::degree;
|
||||||
|
|
||||||
|
// Notify properties
|
||||||
|
PropertyBase* p;
|
||||||
|
if ((p = this->GetProperty("Transform.Position"))) p->Updated();
|
||||||
|
if ((p = this->GetProperty("Transform.Orientation"))) p->Updated();
|
||||||
|
if ((p = this->GetProperty("Transform.Scale"))) p->Updated();
|
||||||
|
}
|
||||||
|
|
||||||
|
signals:
|
||||||
|
/** Signal emitted when properties change */
|
||||||
|
virtual void Updated() override {
|
||||||
|
this->Sync();
|
||||||
|
ULIB_SIGNAL_EMIT(AffineTransform::Updated);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
/** Synchronizes m_T with properties */
|
||||||
|
void Sync() {
|
||||||
|
m_T = Eigen::Affine3f::Identity();
|
||||||
|
m_T.translate(Transform.Position);
|
||||||
|
|
||||||
|
// Orientation (using YZY order as implied by EulerYZYRotate)
|
||||||
|
Matrix3f mat;
|
||||||
|
mat = Eigen::AngleAxisf(Transform.Orientation.x() * CLHEP::degree, Vector3f::UnitY())
|
||||||
|
* Eigen::AngleAxisf(Transform.Orientation.y() * CLHEP::degree, Vector3f::UnitZ())
|
||||||
|
* Eigen::AngleAxisf(Transform.Orientation.z() * CLHEP::degree, Vector3f::UnitY());
|
||||||
|
m_T.rotate(mat);
|
||||||
|
|
||||||
|
m_T.scale(Transform.Scale);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -37,11 +37,12 @@
|
|||||||
|
|
||||||
namespace uLib {
|
namespace uLib {
|
||||||
|
|
||||||
class TriangleMesh : public AffineTransform, public Object
|
class TriangleMesh : public AffineTransform
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
uLibTypeMacro(TriangleMesh, AffineTransform)
|
||||||
|
|
||||||
virtual const char * GetClassName() const { return "TriangleMesh"; }
|
virtual const char * GetClassName() const override { return "TriangleMesh"; }
|
||||||
|
|
||||||
void PrintSelf(std::ostream &o);
|
void PrintSelf(std::ostream &o);
|
||||||
|
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
#include <vtkVersion.h>
|
#include <vtkVersion.h>
|
||||||
#include "vtkViewport.h"
|
#include "vtkViewport.h"
|
||||||
#include "uLibVtkInterface.h"
|
#include "uLibVtkInterface.h"
|
||||||
|
#include "Math/Transform.h"
|
||||||
#include <vtkActor.h>
|
#include <vtkActor.h>
|
||||||
#include <vtkPolyDataMapper.h>
|
#include <vtkPolyDataMapper.h>
|
||||||
#include <vtkProperty.h>
|
#include <vtkProperty.h>
|
||||||
@@ -484,7 +485,7 @@ void Puppet::SetSelected(bool selected)
|
|||||||
if (!pd->m_Selectable) return;
|
if (!pd->m_Selectable) return;
|
||||||
if (pd->m_Selected == selected) return;
|
if (pd->m_Selected == selected) return;
|
||||||
pd->m_Selected = selected;
|
pd->m_Selected = selected;
|
||||||
pd->UpdateHighlight();
|
pd->UpdateHighlight();0
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Puppet::IsSelected() const
|
bool Puppet::IsSelected() const
|
||||||
@@ -498,8 +499,25 @@ void Puppet::Update()
|
|||||||
if (root) {
|
if (root) {
|
||||||
pd->ApplyAppearance(root);
|
pd->ApplyAppearance(root);
|
||||||
|
|
||||||
// Apply transformation if it's a Prop3D
|
// Handle transformation synchronization from content
|
||||||
|
if (auto* content = dynamic_cast<uLib::AffineTransform*>(GetContent())) {
|
||||||
|
pd->m_Position = content->GetPosition().cast<double>();
|
||||||
|
pd->m_Orientation = content->GetOrientation().cast<double>();
|
||||||
|
pd->m_Scale = content->GetScale().cast<double>();
|
||||||
|
|
||||||
if (auto* p3d = vtkProp3D::SafeDownCast(root)) {
|
if (auto* p3d = vtkProp3D::SafeDownCast(root)) {
|
||||||
|
vtkNew<vtkMatrix4x4> vmat;
|
||||||
|
const Matrix4f& emat = content->GetMatrix();
|
||||||
|
for(int i=0; i<4; ++i) for(int j=0; j<4; ++j) vmat->SetElement(i, j, emat(i,j));
|
||||||
|
p3d->SetUserMatrix(vmat);
|
||||||
|
|
||||||
|
// Clear base transform to avoid double-application
|
||||||
|
p3d->SetPosition(0,0,0);
|
||||||
|
p3d->SetOrientation(0,0,0);
|
||||||
|
p3d->SetScale(1,1,1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (auto* p3d = vtkProp3D::SafeDownCast(root)) {
|
||||||
p3d->SetPosition(pd->m_Position.data());
|
p3d->SetPosition(pd->m_Position.data());
|
||||||
p3d->SetOrientation(pd->m_Orientation.data());
|
p3d->SetOrientation(pd->m_Orientation.data());
|
||||||
p3d->SetScale(pd->m_Scale.data());
|
p3d->SetScale(pd->m_Scale.data());
|
||||||
@@ -539,23 +557,42 @@ void Puppet::Update()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Puppet::SyncFromVtk()
|
void Puppet::SyncFromVtk()
|
||||||
{
|
{
|
||||||
vtkProp* root = this->GetProp();
|
vtkProp* root = this->GetProp();
|
||||||
if (auto* p3d = vtkProp3D::SafeDownCast(root)) {
|
if (auto* p3d = vtkProp3D::SafeDownCast(root)) {
|
||||||
|
// Handle content synchronization if it's an AffineTransform
|
||||||
|
if (auto* content = dynamic_cast<uLib::AffineTransform*>(GetContent())) {
|
||||||
|
vtkMatrix4x4* vmat = p3d->GetUserMatrix();
|
||||||
|
if (vmat) {
|
||||||
|
Matrix4f emat;
|
||||||
|
for (int i=0; i<4; ++i)
|
||||||
|
for (int j=0; j<4; ++j)
|
||||||
|
emat(i, j) = vmat->GetElement(i, j);
|
||||||
|
content->SetMatrix(emat);
|
||||||
|
|
||||||
|
// Re-sync internal puppet properties from the now-updated content
|
||||||
|
pd->m_Position = content->GetPosition().cast<double>();
|
||||||
|
pd->m_Orientation = content->GetOrientation().cast<double>();
|
||||||
|
pd->m_Scale = content->GetScale().cast<double>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Update internal puppet properties directly from base components
|
||||||
|
// only if no content exists (old behavior)
|
||||||
double pos[3], ori[3], scale[3];
|
double pos[3], ori[3], scale[3];
|
||||||
p3d->GetPosition(pos);
|
p3d->GetPosition(pos);
|
||||||
p3d->GetOrientation(ori);
|
p3d->GetOrientation(ori);
|
||||||
p3d->GetScale(scale);
|
p3d->GetScale(scale);
|
||||||
|
|
||||||
// Update properties
|
|
||||||
for (int i=0; i<3; ++i) {
|
for (int i=0; i<3; ++i) {
|
||||||
pd->m_Position(i) = pos[i];
|
pd->m_Position(i) = pos[i];
|
||||||
pd->m_Orientation(i) = ori[i];
|
pd->m_Orientation(i) = ori[i];
|
||||||
pd->m_Scale(i) = scale[i];
|
pd->m_Scale(i) = scale[i];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Get the properties from the object
|
// Notify puppet properties updated
|
||||||
if (auto* propPos = this->GetProperty("Position")) propPos->Updated();
|
if (auto* propPos = this->GetProperty("Position")) propPos->Updated();
|
||||||
if (auto* propOri = this->GetProperty("Orientation")) propOri->Updated();
|
if (auto* propOri = this->GetProperty("Orientation")) propOri->Updated();
|
||||||
if (auto* propScale = this->GetProperty("Scale")) propScale->Updated();
|
if (auto* propScale = this->GetProperty("Scale")) propScale->Updated();
|
||||||
|
|||||||
@@ -110,17 +110,16 @@ void vtkObjectsContext::Update() {
|
|||||||
Puppet* vtkObjectsContext::CreatePuppet(uLib::Object* obj) {
|
Puppet* vtkObjectsContext::CreatePuppet(uLib::Object* obj) {
|
||||||
if (!obj) return nullptr;
|
if (!obj) return nullptr;
|
||||||
|
|
||||||
const char* className = obj->GetClassName();
|
if (auto* box = dynamic_cast<uLib::ContainerBox*>(obj)) {
|
||||||
if (std::strcmp(className, "ContainerBox") == 0) {
|
return new vtkContainerBox(box);
|
||||||
return new vtkContainerBox(static_cast<uLib::ContainerBox*>(obj));
|
} else if (auto* chamber = dynamic_cast<uLib::DetectorChamber*>(obj)) {
|
||||||
} else if (std::strcmp(className, "DetectorChamber") == 0) {
|
return new vtkDetectorChamber(chamber);
|
||||||
return new vtkDetectorChamber(static_cast<uLib::DetectorChamber*>(obj));
|
} else if (auto* cylinder = dynamic_cast<uLib::Cylinder*>(obj)) {
|
||||||
} else if (std::strcmp(className, "Cylinder") == 0) {
|
return new vtkCylinder(cylinder);
|
||||||
return new vtkCylinder(static_cast<uLib::Cylinder*>(obj));
|
} else if (auto* vox = dynamic_cast<uLib::Abstract::VoxImage*>(obj)) {
|
||||||
} else if (std::strcmp(className, "VoxImage") == 0) {
|
return new vtkVoxImage(*vox);
|
||||||
return new vtkVoxImage(*static_cast<uLib::Abstract::VoxImage*>(obj));
|
} else if (auto* assembly = dynamic_cast<uLib::Assembly*>(obj)) {
|
||||||
} else if (std::strcmp(className, "Assembly") == 0) {
|
return new Assembly(assembly);
|
||||||
return new Assembly(static_cast<uLib::Assembly*>(obj));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fallback if we don't know the exact class but it might be a context itself
|
// Fallback if we don't know the exact class but it might be a context itself
|
||||||
|
|||||||
Reference in New Issue
Block a user