/*////////////////////////////////////////////////////////////////////////////// // 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 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 Width; Property Height; Property 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::PropertyChanged, this, &ContainerBox::SyncSize); Object::connect(&Height, &Property::PropertyChanged, this, &ContainerBox::SyncSize); Object::connect(&Depth, &Property::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::PropertyChanged, this, &ContainerBox::SyncSize); Object::connect(&Height, &Property::PropertyChanged, this, &ContainerBox::SyncSize); Object::connect(&Depth, &Property::PropertyChanged, this, &ContainerBox::SyncSize); } /** * @brief Copy constructor. * @param copy The ContainerBox instance to copy from. */ ContainerBox(const ContainerBox ©) : 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::PropertyChanged, this, &ContainerBox::SyncSize); Object::connect(&Height, &Property::PropertyChanged, this, &ContainerBox::SyncSize); Object::connect(&Depth, &Property::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