203 lines
6.2 KiB
C++
203 lines
6.2 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_CYLINDER_H
|
|
#define U_CYLINDER_H
|
|
|
|
#include "Geometry.h"
|
|
#include "Core/Object.h"
|
|
#include "Math/Dense.h"
|
|
#include "Math/Transform.h"
|
|
|
|
namespace uLib {
|
|
|
|
/**
|
|
* @brief Represents a cylindrical volume.
|
|
*
|
|
* 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).
|
|
*/
|
|
class Cylinder : public TRS {
|
|
|
|
uLibTypeMacro(Cylinder, TRS)
|
|
ULIB_DECLARE_PROPERTIES(Cylinder)
|
|
|
|
public:
|
|
|
|
/**
|
|
* @brief PROPERTIES
|
|
*/
|
|
float Radius;
|
|
float Height;
|
|
int Axis;
|
|
|
|
|
|
|
|
/**
|
|
* @brief Default constructor. Aligns with Y by default.
|
|
*/
|
|
Cylinder() : m_LocalT(this), Radius(1.0), Height(1.0), Axis(1) {
|
|
this->Sync();
|
|
}
|
|
|
|
/**
|
|
* @brief Constructor with radius and height.
|
|
*/
|
|
Cylinder(float radius, float height, int axis = 1)
|
|
: m_LocalT(this), Radius(radius), Height(height), Axis(axis) {
|
|
this->Sync();
|
|
}
|
|
|
|
/**
|
|
* @brief Copy constructor.
|
|
*/
|
|
Cylinder(const Cylinder ©)
|
|
: m_LocalT(this), TRS(copy), Radius(copy.Radius), Height(copy.Height), Axis(copy.Axis) {
|
|
this->Sync();
|
|
}
|
|
|
|
/**
|
|
* @brief Serialization template for property registration and persistence.
|
|
*/
|
|
template <class ArchiveT>
|
|
void serialize(ArchiveT & ar, const unsigned int version) {
|
|
ar & HRP(Radius);
|
|
ar & HRP(Height);
|
|
ar & boost::serialization::make_hrp_enum("Axis", Axis, {"X", "Y", "Z"});
|
|
ar & NVP("TRS", boost::serialization::base_object<TRS>(*this));
|
|
}
|
|
|
|
/** Sets the radius of the cylinder */
|
|
inline void SetRadius(float r) {
|
|
Radius = r;
|
|
this->Sync();
|
|
}
|
|
|
|
/** Gets the radius of the cylinder */
|
|
inline float GetRadius() const { return Radius; }
|
|
|
|
/** Sets the height of the cylinder */
|
|
inline void SetHeight(float h) {
|
|
Height = h;
|
|
this->Sync();
|
|
}
|
|
|
|
/** Gets the height of the cylinder */
|
|
inline float GetHeight() const { return Height; }
|
|
|
|
/** Sets the main axis (0=X, 1=Y, 2=Z) */
|
|
inline void SetAxis(int axis) {
|
|
Axis = axis;
|
|
this->Sync();
|
|
}
|
|
|
|
/** Gets the main axis */
|
|
inline int GetAxis() const { return Axis; }
|
|
|
|
/**
|
|
* @brief Returns the world transformation matrix.
|
|
*/
|
|
Matrix4f GetWorldMatrix() const { return m_LocalT.GetWorldMatrix(); }
|
|
|
|
/**
|
|
* @brief Returns the local transformation matrix.
|
|
*/
|
|
Matrix4f GetLocalMatrix() const { return m_LocalT.GetMatrix(); }
|
|
|
|
/**
|
|
* @brief Transforms local cylindrical coordinates to world space.
|
|
* @param r Local radius.
|
|
* @param theta Local angle in radians (around main axis).
|
|
* @param h Local height along main axis.
|
|
*/
|
|
inline Vector4f GetWorldPoint(float r, float theta, float h) const {
|
|
Vector3f p;
|
|
if (Axis == 0) p = Vector3f(h, r * std::cos(theta), r * std::sin(theta));
|
|
else if (Axis == 1) p = Vector3f(r * std::cos(theta), h, r * std::sin(theta));
|
|
else p = Vector3f(r * std::cos(theta), r * std::sin(theta), h);
|
|
|
|
return AffineTransform::GetWorldMatrix() * Vector4f(p.x(), p.y(), p.z(), 1.0f);
|
|
}
|
|
|
|
/**
|
|
* @brief Transforms a world point to cylindrical local space.
|
|
* @return Vector3f(r, theta, h)
|
|
*/
|
|
inline Vector3f GetCylindricalLocal(const Vector4f &world_v) const {
|
|
Vector4f local_v = AffineTransform::GetWorldMatrix().inverse() * world_v;
|
|
float r, theta, h;
|
|
if (Axis == 0) {
|
|
h = local_v.x();
|
|
r = std::sqrt(local_v.y() * local_v.y() + local_v.z() * local_v.z());
|
|
theta = std::atan2(local_v.z(), local_v.y());
|
|
} else if (Axis == 1) {
|
|
h = local_v.y();
|
|
r = std::sqrt(local_v.x() * local_v.x() + local_v.z() * local_v.z());
|
|
theta = std::atan2(local_v.z(), local_v.x());
|
|
} else {
|
|
h = local_v.z();
|
|
r = std::sqrt(local_v.x() * local_v.x() + local_v.y() * local_v.y());
|
|
theta = std::atan2(local_v.y(), local_v.x());
|
|
}
|
|
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:
|
|
/** Signal emitted when properties change */
|
|
virtual void Updated() override {
|
|
// 1. Synchronize local cylinder part (Radius/Height/Axis -> m_LocalT)
|
|
this->Sync();
|
|
|
|
// 2. Synchronize TRS part (position/rotation/scaling -> m_T) and emit signal
|
|
this->TRS::Updated();
|
|
}
|
|
|
|
private:
|
|
/** Synchronizes internal transformation with properties */
|
|
void Sync() {
|
|
m_LocalT = AffineTransform(this);
|
|
if (Axis == 0) m_LocalT.Scale(Vector3f(Height, Radius, Radius));
|
|
else if (Axis == 1) m_LocalT.Scale(Vector3f(Radius, Height, Radius));
|
|
else m_LocalT.Scale(Vector3f(Radius, Radius, Height));
|
|
}
|
|
|
|
|
|
private:
|
|
AffineTransform m_LocalT;
|
|
};
|
|
|
|
} // namespace uLib
|
|
|
|
#endif // U_CYLINDER_H
|