add assembly
This commit is contained in:
146
src/Math/Assembly.cpp
Normal file
146
src/Math/Assembly.cpp
Normal file
@@ -0,0 +1,146 @@
|
||||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
// 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 >
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
#include "Math/Assembly.h"
|
||||
#include "Math/ContainerBox.h"
|
||||
#include "Math/Cylinder.h"
|
||||
|
||||
#include <limits>
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
|
||||
namespace uLib {
|
||||
|
||||
Assembly::Assembly()
|
||||
: ObjectsContext(),
|
||||
AffineTransform(),
|
||||
m_BBoxMin(Vector3f::Zero()),
|
||||
m_BBoxMax(Vector3f::Zero()),
|
||||
m_ShowBoundingBox(false),
|
||||
m_GroupSelection(true) {}
|
||||
|
||||
Assembly::Assembly(const Assembly ©)
|
||||
: ObjectsContext(copy),
|
||||
AffineTransform(copy),
|
||||
m_BBoxMin(copy.m_BBoxMin),
|
||||
m_BBoxMax(copy.m_BBoxMax),
|
||||
m_ShowBoundingBox(copy.m_ShowBoundingBox),
|
||||
m_GroupSelection(copy.m_GroupSelection) {}
|
||||
|
||||
Assembly::~Assembly() {}
|
||||
|
||||
void Assembly::AddObject(Object *obj) {
|
||||
if (auto *at = dynamic_cast<AffineTransform *>(obj)) {
|
||||
at->SetParent(this);
|
||||
}
|
||||
ObjectsContext::AddObject(obj);
|
||||
}
|
||||
|
||||
void Assembly::RemoveObject(Object *obj) {
|
||||
if (auto *at = dynamic_cast<AffineTransform *>(obj)) {
|
||||
if (at->GetParent() == this)
|
||||
at->SetParent(nullptr);
|
||||
}
|
||||
ObjectsContext::RemoveObject(obj);
|
||||
}
|
||||
|
||||
void Assembly::ComputeBoundingBox() {
|
||||
const auto &objects = this->GetObjects();
|
||||
if (objects.empty()) {
|
||||
m_BBoxMin = Vector3f::Zero();
|
||||
m_BBoxMax = Vector3f::Zero();
|
||||
return;
|
||||
}
|
||||
|
||||
float inf = std::numeric_limits<float>::max();
|
||||
m_BBoxMin = Vector3f(inf, inf, inf);
|
||||
m_BBoxMax = Vector3f(-inf, -inf, -inf);
|
||||
|
||||
Matrix4f invAsm = this->GetWorldMatrix().inverse();
|
||||
|
||||
for (Object *obj : objects) {
|
||||
if (auto *box = dynamic_cast<ContainerBox *>(obj)) {
|
||||
// ContainerBox: wm is matrix from unit cube [0,1] to assembly base
|
||||
Matrix4f m = invAsm * box->GetWorldMatrix();
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
float x = (i & 1) ? 1.0f : 0.0f;
|
||||
float y = (i & 2) ? 1.0f : 0.0f;
|
||||
float z = (i & 4) ? 1.0f : 0.0f;
|
||||
Vector4f corner = m * Vector4f(x, y, z, 1.0f);
|
||||
for (int a = 0; a < 3; ++a) {
|
||||
m_BBoxMin(a) = std::min(m_BBoxMin(a), corner(a));
|
||||
m_BBoxMax(a) = std::max(m_BBoxMax(a), corner(a));
|
||||
}
|
||||
}
|
||||
} else if (auto *cyl = dynamic_cast<Cylinder *>(obj)) {
|
||||
// Cylinder: centered [-1, 1] radial, [-0.5, 0.5] height
|
||||
Matrix4f m = invAsm * cyl->GetWorldMatrix();
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
float x = (i & 1) ? 1.0f : -1.0f;
|
||||
float y = (i & 2) ? 0.5f : -0.5f;
|
||||
float z = (i & 4) ? 1.0f : -1.0f;
|
||||
Vector4f corner = m * Vector4f(x, y, z, 1.0f);
|
||||
for (int a = 0; a < 3; ++a) {
|
||||
m_BBoxMin(a) = std::min(m_BBoxMin(a), corner(a));
|
||||
m_BBoxMax(a) = std::max(m_BBoxMax(a), corner(a));
|
||||
}
|
||||
}
|
||||
} else if (auto *subAsm = dynamic_cast<Assembly *>(obj)) {
|
||||
// Recursive AABB for nested assemblies
|
||||
subAsm->ComputeBoundingBox();
|
||||
Vector3f subMin, subMax;
|
||||
subAsm->GetBoundingBox(subMin, subMax);
|
||||
Matrix4f m = invAsm * subAsm->GetWorldMatrix();
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
float x = (i & 1) ? subMax(0) : subMin(0);
|
||||
float y = (i & 2) ? subMax(1) : subMin(1);
|
||||
float z = (i & 4) ? subMax(2) : subMin(2);
|
||||
Vector4f corner = m * Vector4f(x, y, z, 1.0f);
|
||||
for (int a = 0; a < 3; ++a) {
|
||||
m_BBoxMin(a) = std::min(m_BBoxMin(a), corner(a));
|
||||
m_BBoxMax(a) = std::max(m_BBoxMax(a), corner(a));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Assembly::GetBoundingBox(Vector3f &bbMin, Vector3f &bbMax) const {
|
||||
bbMin = m_BBoxMin;
|
||||
bbMax = m_BBoxMax;
|
||||
}
|
||||
|
||||
ContainerBox Assembly::GetBoundingBoxAsContainer() const {
|
||||
ContainerBox bb;
|
||||
Vector3f size = m_BBoxMax - m_BBoxMin;
|
||||
bb.SetSize(size);
|
||||
bb.SetPosition(m_BBoxMin);
|
||||
return bb;
|
||||
}
|
||||
|
||||
void Assembly::SetShowBoundingBox(bool show) {
|
||||
m_ShowBoundingBox = show;
|
||||
this->Updated();
|
||||
}
|
||||
|
||||
bool Assembly::GetShowBoundingBox() const {
|
||||
return m_ShowBoundingBox;
|
||||
}
|
||||
|
||||
void Assembly::SetGroupSelection(bool group) {
|
||||
m_GroupSelection = group;
|
||||
}
|
||||
|
||||
bool Assembly::GetGroupSelection() const {
|
||||
return m_GroupSelection;
|
||||
}
|
||||
|
||||
} // namespace uLib
|
||||
109
src/Math/Assembly.h
Normal file
109
src/Math/Assembly.h
Normal file
@@ -0,0 +1,109 @@
|
||||
/*//////////////////////////////////////////////////////////////////////////////
|
||||
// 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_ASSEMBLY_H
|
||||
#define U_ASSEMBLY_H
|
||||
|
||||
#include "Core/ObjectsContext.h"
|
||||
#include "Math/ContainerBox.h"
|
||||
#include "Math/Transform.h"
|
||||
|
||||
namespace uLib {
|
||||
|
||||
/**
|
||||
* @brief Assembly groups geometric objects (ContainerBox, Cylinder, etc.)
|
||||
* under a common transformation.
|
||||
*
|
||||
* Assembly derives from ObjectsContext so objects can be added/removed
|
||||
* dynamically. It also inherits AffineTransform to provide a group-level
|
||||
* transformation that is applied on top of each child's own transform.
|
||||
*
|
||||
* A bounding box is automatically computed from all contained objects and
|
||||
* can be queried or shown/hidden through the VTK puppet.
|
||||
*/
|
||||
class Assembly : public ObjectsContext, public AffineTransform {
|
||||
public:
|
||||
virtual const char *GetClassName() const override { return "Assembly"; }
|
||||
|
||||
Assembly();
|
||||
Assembly(const Assembly ©);
|
||||
virtual ~Assembly();
|
||||
|
||||
virtual void AddObject(Object* obj) override;
|
||||
virtual void RemoveObject(Object* obj) override;
|
||||
|
||||
/**
|
||||
* @brief Recomputes the axis-aligned bounding box enclosing all children.
|
||||
* Stores the result internally.
|
||||
*/
|
||||
void ComputeBoundingBox();
|
||||
|
||||
/**
|
||||
* @brief Returns the bounding box as min/max corners (in assembly-local
|
||||
* coordinates).
|
||||
*/
|
||||
void GetBoundingBox(Vector3f &bbMin, Vector3f &bbMax) const;
|
||||
|
||||
/**
|
||||
* @brief Returns the bounding box as a ContainerBox (positioned
|
||||
* at bbMin, sized bbMax-bbMin, parented to this transform).
|
||||
*/
|
||||
ContainerBox GetBoundingBoxAsContainer() const;
|
||||
|
||||
/**
|
||||
* @brief Controls whether the bounding box wireframe should be shown
|
||||
* in the viewer (used by the VTK puppet).
|
||||
*/
|
||||
void SetShowBoundingBox(bool show);
|
||||
bool GetShowBoundingBox() const;
|
||||
|
||||
/**
|
||||
* @brief Controls selection behavior.
|
||||
* If true (default), clicking any child within the assembly will select
|
||||
* the assembly itself. If false, individual children can be picked.
|
||||
*/
|
||||
void SetGroupSelection(bool group);
|
||||
bool GetGroupSelection() const;
|
||||
|
||||
signals:
|
||||
virtual void Updated() override {
|
||||
if (m_InUpdated) return; // break signal recursion
|
||||
m_InUpdated = true;
|
||||
this->ComputeBoundingBox();
|
||||
ULIB_SIGNAL_EMIT(Assembly::Updated);
|
||||
m_InUpdated = false;
|
||||
}
|
||||
|
||||
private:
|
||||
Vector3f m_BBoxMin;
|
||||
Vector3f m_BBoxMax;
|
||||
bool m_ShowBoundingBox;
|
||||
bool m_GroupSelection;
|
||||
bool m_InUpdated = false;
|
||||
};
|
||||
|
||||
} // namespace uLib
|
||||
|
||||
#endif // U_ASSEMBLY_H
|
||||
@@ -1,6 +1,7 @@
|
||||
|
||||
set(HEADERS ContainerBox.h
|
||||
Cylinder.h
|
||||
Assembly.h
|
||||
Dense.h
|
||||
Geometry.h
|
||||
Transform.h
|
||||
@@ -33,6 +34,7 @@ set(SOURCES VoxRaytracer.cpp
|
||||
VoxImage.cpp
|
||||
TriangleMesh.cpp
|
||||
QuadMesh.cpp
|
||||
Assembly.cpp
|
||||
Dense.cpp
|
||||
Structured2DGrid.cpp
|
||||
Structured4DGrid.cpp
|
||||
|
||||
@@ -69,6 +69,8 @@ public:
|
||||
m_Parent(NULL)
|
||||
{}
|
||||
|
||||
virtual ~AffineTransform() {}
|
||||
|
||||
AffineTransform(AffineTransform *parent) :
|
||||
m_T(Matrix4f::Identity()),
|
||||
m_Parent(parent)
|
||||
|
||||
Reference in New Issue
Block a user