Files
uLib/src/Math/ContainerBox.h
2026-03-23 12:55:09 +00:00

227 lines
7.4 KiB
C++

/*//////////////////////////////////////////////////////////////////////////////
// CMT Cosmic Muon Tomography project //////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
Copyright (c) 2014, Universita' degli Studi di Padova, INFN sez. di Padova
All rights reserved
Authors: Andrea Rigoni Garola < andrea.rigoni@pd.infn.it >
------------------------------------------------------------------
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3.0 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library.
//////////////////////////////////////////////////////////////////////////////*/
#ifndef U_CONTAINERBOX_H
#define U_CONTAINERBOX_H
#include "Geometry.h"
#include "Core/Object.h"
#include "Core/Property.h"
#include "Math/Dense.h"
#include "Math/Transform.h"
#include <utility>
namespace uLib {
/**
* @brief Represents an oriented bounding box (OBB) within a hierarchical
* transformation system.
*
* ContainerBox inherits from AffineTransform, which defines its parent
* coordinate system. It contains an internal local transformation (m_LocalT)
* that defines the box's specific origin and size relative to its own
* coordinate system.
*/
class ContainerBox : public AffineTransform, public Object {
typedef AffineTransform BaseClass;
public:
////////////////////////////////////////////////////////////////////////////
// PROPERTIES //
Property<float> Width;
Property<float> Height;
Property<float> Depth;
virtual const char * GetClassName() const { return "ContainerBox"; }
/**
* @brief Default constructor.
* Initializes the local transformation with this instance as its parent.
*/
ContainerBox()
: m_LocalT(this), // BaseClass is Parent of m_LocalTransform
Width(this, "Width", 1.0f),
Height(this, "Height", 1.0f),
Depth(this, "Depth", 1.0f) {
Object::connect(&Width, &Property<float>::PropertyChanged, this, &ContainerBox::SyncSize);
Object::connect(&Height, &Property<float>::PropertyChanged, this, &ContainerBox::SyncSize);
Object::connect(&Depth, &Property<float>::PropertyChanged, this, &ContainerBox::SyncSize);
}
/**
* @brief Constructor with size.
* @param size The size vector.
*/
ContainerBox(const Vector3f &size)
: m_LocalT(this),
Width(this, "Width", size(0)),
Height(this, "Height", size(1)),
Depth(this, "Depth", size(2)) {
Object::connect(&Width, &Property<float>::PropertyChanged, this, &ContainerBox::SyncSize);
Object::connect(&Height, &Property<float>::PropertyChanged, this, &ContainerBox::SyncSize);
Object::connect(&Depth, &Property<float>::PropertyChanged, this, &ContainerBox::SyncSize);
}
/**
* @brief Copy constructor.
* @param copy The ContainerBox instance to copy from.
*/
ContainerBox(const ContainerBox &copy)
: m_LocalT(this), // BaseClass is Parent of m_LocalTransform
AffineTransform(copy),
Width(this, "Width", copy.Width),
Height(this, "Height", copy.Height),
Depth(this, "Depth", copy.Depth) {
Object::connect(&Width, &Property<float>::PropertyChanged, this, &ContainerBox::SyncSize);
Object::connect(&Height, &Property<float>::PropertyChanged, this, &ContainerBox::SyncSize);
Object::connect(&Depth, &Property<float>::PropertyChanged, this, &ContainerBox::SyncSize);
this->SetOrigin(copy.GetOrigin());
}
/**
* @brief Sets the box origin relative to its coordinate system.
* @param v The origin position vector.
*/
void SetOrigin(const Vector3f &v) { m_LocalT.SetPosition(v); }
/**
* @brief Gets the box origin relative to its coordinate system.
* @return The origin position vector.
*/
Vector3f GetOrigin() const { return m_LocalT.GetPosition(); }
/**
* @brief Sets the size of the box.
* Re-initializes the local transformation and applies the new scale.
* @param v The size vector (width, height, depth).
*/
void SetSize(const Vector3f &v) {
Width = v(0);
Height = v(1);
Depth = v(2);
Vector3f pos = this->GetOrigin();
m_LocalT = AffineTransform(this); // regenerate local transform
m_LocalT.Scale(v);
m_LocalT.SetPosition(pos);
}
/**
* @brief Gets the current size (scale) of the box.
* @return The size vector.
*/
Vector3f GetSize() const {
Vector3f s = this->GetScale();
Vector3f ls = m_LocalT.GetScale();
return Vector3f(s(0) * ls(0), s(1) * ls(1), s(2) * ls(2));
}
/**
* @brief Swaps two local axes of the box.
* @param first Index of the first axis (0=X, 1=Y, 2=Z).
* @param second Index of the second axis (0=X, 1=Y, 2=Z).
*/
void FlipLocalAxes(int first, int second) {
m_LocalT.FlipAxes(first, second);
}
/**
* @brief Returns the world transformation matrix of the box's volume.
* @return A 4x4 transformation matrix.
*/
Matrix4f GetWorldMatrix() const { return m_LocalT.GetWorldMatrix(); }
/**
* @brief Returns the local transformation matrix of the box's volume.
* @return A 4x4 transformation matrix.
*/
Matrix4f GetLocalMatrix() const { return m_LocalT.GetMatrix(); }
/**
* @brief Transforms a point from box-local space to world space.
* @param v The local point (4D homogeneous vector).
* @return The transformed point in world space.
*/
Vector4f GetWorldPoint(const Vector4f &v) const {
return m_LocalT.GetWorldMatrix() * v;
}
/**
* @brief Transforms a point from box-local space coordinates to world space.
* @param x X coordinate in local space.
* @param y Y coordinate in local space.
* @param z Z coordinate in local space.
* @return The transformed point in world space.
*/
Vector4f GetWorldPoint(const float x, const float y, const float z) {
return this->GetWorldPoint(Vector4f(x, y, z, 1));
}
/**
* @brief Transforms a point from world space to box-local space.
* @param v The world point (4D homogeneous vector).
* @return The transformed point in box-local space.
*/
Vector4f GetLocalPoint(const Vector4f &v) const {
return m_LocalT.GetWorldMatrix().inverse() * v;
}
/**
* @brief Transforms a point from world space coordinates to box-local space.
* @param x X coordinate in world space.
* @param y Y coordinate in world space.
* @param z Z coordinate in world space.
* @return The transformed point in box-local space.
*/
Vector4f GetLocalPoint(const float x, const float y, const float z) {
return this->GetLocalPoint(Vector4f(x, y, z, 1));
}
/** Translate using transformation chain */
using BaseClass::Translate;
/** Rotate using transformation chain */
using BaseClass::Rotate;
/** Scale using transformation chain */
using BaseClass::Scale;
signals:
// signal to emit when the box is updated //
virtual void Updated() override { ULIB_SIGNAL_EMIT(ContainerBox::Updated); }
private:
void SyncSize() {
this->SetSize(Vector3f(Width, Height, Depth));
}
AffineTransform m_LocalT;
};
} // namespace uLib
#endif // CONTAINERBOX_H