Skip to content

Commit

Permalink
Add transformed object construction (#1128)
Browse files Browse the repository at this point in the history
* Add transformed shape
* Fix single-precision casting
* Add docs
  • Loading branch information
sethrj committed Mar 1, 2024
1 parent 2f8cc5e commit 507f55c
Show file tree
Hide file tree
Showing 9 changed files with 434 additions and 10 deletions.
1 change: 1 addition & 0 deletions src/orange/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ list(APPEND SOURCES
orangeinp/CsgTypes.cc
orangeinp/CsgTreeUtils.cc
orangeinp/Shape.cc
orangeinp/Transformed.cc
orangeinp/detail/BoundingZone.cc
orangeinp/detail/ConvexSurfaceState.cc
orangeinp/detail/CsgUnitBuilder.cc
Expand Down
45 changes: 45 additions & 0 deletions src/orange/orangeinp/Transformed.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
//----------------------------------*-C++-*----------------------------------//
// Copyright 2024 UT-Battelle, LLC, and other Celeritas developers.
// See the top-level COPYRIGHT file for details.
// SPDX-License-Identifier: (Apache-2.0 OR MIT)
//---------------------------------------------------------------------------//
//! \file orange/orangeinp/Transformed.cc
//---------------------------------------------------------------------------//
#include "Transformed.hh"

#include "detail/CsgUnitBuilder.hh"
#include "detail/VolumeBuilder.hh"

namespace celeritas
{
namespace orangeinp
{
//---------------------------------------------------------------------------//
/*!
* Construct with daughter object and transform.
*
* The input transform should *not* be "no transform" because that would be
* silly.
*/
Transformed::Transformed(SPConstObject obj, VariantTransform&& transform)
: obj_{std::move(obj)}, transform_{std::move(transform)}
{
CELER_EXPECT(obj_);
CELER_EXPECT(!transform_.valueless_by_exception());
CELER_EXPECT(!std::holds_alternative<NoTransformation>(transform_));
}

//---------------------------------------------------------------------------//
/*!
* Construct a volume from this transformed shape.
*/
NodeId Transformed::build(VolumeBuilder& vb) const
{
// Apply the transform through the life of this object
auto scoped_transform = vb.make_scoped_transform(transform_);
return obj_->build(vb);
}

//---------------------------------------------------------------------------//
} // namespace orangeinp
} // namespace celeritas
41 changes: 41 additions & 0 deletions src/orange/orangeinp/Transformed.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//----------------------------------*-C++-*----------------------------------//
// Copyright 2024 UT-Battelle, LLC, and other Celeritas developers.
// See the top-level COPYRIGHT file for details.
// SPDX-License-Identifier: (Apache-2.0 OR MIT)
//---------------------------------------------------------------------------//
//! \file orange/orangeinp/Transformed.hh
//---------------------------------------------------------------------------//
#pragma once

#include "orange/transform/VariantTransform.hh"

#include "ObjectInterface.hh"

namespace celeritas
{
namespace orangeinp
{
//---------------------------------------------------------------------------//
/*!
* Build a translated or transformed object.
*/
class Transformed final : public ObjectInterface
{
public:
// Construct with daughter object and transform
Transformed(SPConstObject obj, VariantTransform&& transform);

//! Get the user-provided label
std::string_view label() const final { return obj_->label(); }

// Construct a volume from this object
NodeId build(VolumeBuilder&) const final;

private:
SPConstObject obj_;
VariantTransform transform_;
};

//---------------------------------------------------------------------------//
} // namespace orangeinp
} // namespace celeritas
18 changes: 16 additions & 2 deletions src/orange/orangeinp/detail/CsgUnitBuilder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
//---------------------------------------------------------------------------//
#include "CsgUnitBuilder.hh"

#include "corecel/io/Logger.hh"
#include "corecel/io/StreamableVariant.hh"
#include "orange/transform/TransformIO.hh"

namespace celeritas
{
namespace orangeinp
Expand Down Expand Up @@ -43,7 +47,7 @@ void CsgUnitBuilder::insert_region(NodeId n,

auto&& [iter, inserted]
= unit_->regions.insert({n, CsgUnit::Region{bzone, trans_id}});
if (!inserted)
if (CELERITAS_DEBUG && !inserted)
{
// The existing bounding zone *SHOULD BE IDENTICAL*.
// For now this is a rough check...
Expand All @@ -53,7 +57,17 @@ void CsgUnitBuilder::insert_region(NodeId n,
== static_cast<bool>(existing.bounds.interior));
CELER_ASSERT(static_cast<bool>(bzone.exterior)
== static_cast<bool>(existing.bounds.exterior));
CELER_ASSERT(trans_id == existing.transform_id);
if (trans_id != existing.transform_id)
{
// TODO: we need to implement transform soft equivalence
// and simplification
CELER_LOG(warning)
<< "While re-inserting region for node " << n.get()
<< ": existing transform "
<< StreamableVariant{this->transform(existing.transform_id)}
<< " differs from new transform "
<< StreamableVariant{this->transform(trans_id)};
}
}
}

Expand Down
65 changes: 63 additions & 2 deletions src/orange/orangeinp/detail/VolumeBuilder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,25 +25,86 @@ namespace detail
VolumeBuilder::VolumeBuilder(CsgUnitBuilder* ub) : ub_{ub}
{
CELER_EXPECT(ub_);
ub_->insert_transform(NoTransformation{});
this->push_transform(NoTransformation{});
CELER_ENSURE(transforms_.size() == 1);
}

//---------------------------------------------------------------------------//
/*!
* Access the local-to-global transform during construction.
*/
VariantTransform const& VolumeBuilder::local_transform() const
{
CELER_EXPECT(!transforms_.empty());
return ub_->transform(transforms_.back());
}

//-------------------------------------------------------------------------//
/*!
* Add a region to the CSG tree.
*/
NodeId
VolumeBuilder::insert_region(Metadata&& md, Joined&& j, BoundingZone&& bzone)
{
auto node_id = ub_->insert_csg(std::move(j)).first;
ub_->insert_region(node_id, std::move(bzone), TransformId{0});
CELER_ASSERT(!transforms_.empty());
ub_->insert_region(node_id, std::move(bzone), transforms_.back());

// Always add metadata
ub_->insert_md(node_id, std::move(md));

return node_id;
}

//---------------------------------------------------------------------------//
/*!
* Apply a transform within this scope.
*/
[[nodiscard]] PopVBTransformOnDestruct
VolumeBuilder::make_scoped_transform(VariantTransform const& t)
{
// Apply the current local transform to get a new local transform, and add
// it to the stack
this->push_transform(apply_transform(this->local_transform(), t));

// Return the helper class that will pop the last transform
CELER_ENSURE(transforms_.size() > 1);
return PopVBTransformOnDestruct(this);
}

//---------------------------------------------------------------------------//
// PRIVATE METHODS
//---------------------------------------------------------------------------//
/*!
* Add a new variant transform.
*/
void VolumeBuilder::push_transform(VariantTransform&& vt)
{
auto trans_id = ub_->insert_transform(std::move(vt));
transforms_.push_back(trans_id);
}

//---------------------------------------------------------------------------//
/*!
* Pop the last transform, used only by PopVBTransformOnDestruct.
*/
void VolumeBuilder::pop_transform()
{
CELER_EXPECT(transforms_.size() > 1);

transforms_.pop_back();
}

//---------------------------------------------------------------------------//
/*!
* Construct with a volume builder pointer.
*/
PopVBTransformOnDestruct::PopVBTransformOnDestruct(VolumeBuilder* vb) : vb_{vb}
{
CELER_EXPECT(vb_);
CELER_EXPECT(vb_->transforms_.size() > 1);
}

//---------------------------------------------------------------------------//
} // namespace detail
} // namespace orangeinp
Expand Down
74 changes: 70 additions & 4 deletions src/orange/orangeinp/detail/VolumeBuilder.hh
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ namespace orangeinp
{
namespace detail
{
//---------------------------------------------------------------------------//
class CsgUnitBuilder;
struct BoundingZone;
class PopVBTransformOnDestruct;

//---------------------------------------------------------------------------//
/*!
Expand All @@ -28,6 +30,11 @@ struct BoundingZone;
* This class maintains a stack of transforms used by nested objects. It
* ultimately returns a node ID corresponding to the CSG node (and bounding box
* etc.) of the constructed object.
*
* To add a transform, store the result of \c make_scoped_transform within a
* scoping block (generally the calling function). The resulting RAII class
* prevents an imbalance from manual calls to "push" and "pop". For an example
* usage, see \c celeritas::orangeinp::Transformed::build .
*/
class VolumeBuilder
{
Expand All @@ -38,24 +45,83 @@ class VolumeBuilder
//!@}

public:
// Construct with unit builder and volume name
// Construct with unit builder (and volume name??)
explicit VolumeBuilder(CsgUnitBuilder* ub);

//// ACCESSORS ////

//!@{
//! Access the unit builder for construction
CsgUnitBuilder const& unit_builder() const { return *ub_; }
CsgUnitBuilder& unit_builder() { return *ub_; }
//!@}

//! Access the local-to-global transform during construction
VariantTransform const& local_transform() const { return local_trans_; }
// Access the local-to-global transform during construction
VariantTransform const& local_transform() const;

//// MUTATORS ////

// Add a region to the CSG tree
NodeId insert_region(Metadata&& md, Joined&& j, BoundingZone&& bzone);

// Apply a transform within this scope
[[nodiscard]] PopVBTransformOnDestruct
make_scoped_transform(VariantTransform const& t);

private:
//// DATA ////

CsgUnitBuilder* ub_;
VariantTransform local_trans_; //!< DUMMY for now
std::vector<TransformId> transforms_;

//// PRIVATE METHODS ////

// Add a new variant transform
void push_transform(VariantTransform&& vt);

// Pop the last transform, used only by PopVBTransformOnDestruct
void pop_transform();

//// FRIENDS ////

friend class PopVBTransformOnDestruct;
};

//---------------------------------------------------------------------------//
//! Implementation-only RAII helper class for VolumeBuilder (detail detail)
class PopVBTransformOnDestruct
{
private:
friend class VolumeBuilder;

// Construct with a volume builder pointer
explicit PopVBTransformOnDestruct(VolumeBuilder* vb);

public:
//! Capture the pointer when move constructed
PopVBTransformOnDestruct(PopVBTransformOnDestruct&& other)
: vb_(std::exchange(other.vb_, nullptr))
{
}

//! Capture the pointer when move assigned
PopVBTransformOnDestruct& operator=(PopVBTransformOnDestruct&& other)
{
vb_ = std::exchange(other.vb_, nullptr);
return *this;
}

//! Call pop when we own the pointer and go out of scope
~PopVBTransformOnDestruct()
{
if (vb_)
{
vb_->pop_transform();
}
}

private:
VolumeBuilder* vb_{nullptr};
};

//---------------------------------------------------------------------------//
Expand Down
4 changes: 2 additions & 2 deletions src/orange/transform/detail/TransformTransformer.hh
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ namespace detail
\mathbf{T}' = \mathbf{T}_A \mathbf{T}_B
* \f]
* where \f$\mathbf{T}_A\f$ is the constructor argument
* (the operator itself), \b T_B is the argument passed to the call operator,
* and the \f$\mathbf{T}'\f$ is the return value.
* (the operator itself), \f$\mathbf{T}_b\f$ is the argument passed to the call
* operator, and the \f$\mathbf{T}'\f$ is the return value.
* The new transform has rotation
* \f[
\mathbf{R}' = \mathbf{R}_A\mathbf{R}_B
Expand Down
1 change: 1 addition & 0 deletions test/orange/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ celeritas_add_test(orangeinp/ConvexSurfaceBuilder.test.cc)
celeritas_add_test(orangeinp/CsgTree.test.cc)
celeritas_add_test(orangeinp/CsgTreeUtils.test.cc)
celeritas_add_test(orangeinp/Shape.test.cc)
celeritas_add_test(orangeinp/Transformed.test.cc)

celeritas_add_test(orangeinp/detail/BoundingZone.test.cc)
celeritas_add_test(orangeinp/detail/LocalSurfaceInserter.test.cc)
Expand Down

0 comments on commit 507f55c

Please sign in to comment.