forked from celeritas-project/celeritas
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add CSG operations on objects (celeritas-project#1130)
- Loading branch information
Showing
12 changed files
with
772 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
//----------------------------------*-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/CsgObject.cc | ||
//---------------------------------------------------------------------------// | ||
#include "CsgObject.hh" | ||
|
||
#include <utility> | ||
|
||
#include "detail/CsgUnitBuilder.hh" | ||
#include "detail/VolumeBuilder.hh" | ||
|
||
namespace celeritas | ||
{ | ||
namespace orangeinp | ||
{ | ||
//---------------------------------------------------------------------------// | ||
// NEGATED | ||
//---------------------------------------------------------------------------// | ||
/*! | ||
* Construct with the object to negate and an empty name. | ||
*/ | ||
NegatedObject::NegatedObject(SPConstObject obj) | ||
: NegatedObject{{}, std::move(obj)} | ||
{ | ||
} | ||
|
||
//---------------------------------------------------------------------------// | ||
/*! | ||
* Construct with a name and object. | ||
*/ | ||
NegatedObject::NegatedObject(std::string&& label, SPConstObject obj) | ||
: label_{std::move(label)}, obj_{std::move(obj)} | ||
{ | ||
CELER_EXPECT(obj_); | ||
} | ||
|
||
//---------------------------------------------------------------------------// | ||
/*! | ||
* Construct a volume from this object. | ||
*/ | ||
NodeId NegatedObject::build(VolumeBuilder& vb) const | ||
{ | ||
// Build object to be negated | ||
auto daughter_id = obj_->build(vb); | ||
// Add the new region (or anti-region) | ||
return vb.insert_region(Label{label_}, Negated{daughter_id}); | ||
} | ||
|
||
//---------------------------------------------------------------------------// | ||
// JOIN_OBJECTS | ||
//---------------------------------------------------------------------------// | ||
template<OperatorToken Op> | ||
constexpr OperatorToken JoinObjects<Op>::op_token; | ||
|
||
//---------------------------------------------------------------------------// | ||
/*! | ||
* Construct with a name and a vector of objects. | ||
*/ | ||
template<OperatorToken Op> | ||
JoinObjects<Op>::JoinObjects(std::string&& label, VecObject&& objects) | ||
: label_{std::move(label)}, objects_{std::move(objects)} | ||
{ | ||
CELER_EXPECT(!label_.empty()); | ||
CELER_EXPECT(std::all_of( | ||
objects_.begin(), objects_.end(), [](SPConstObject const& obj) { | ||
return static_cast<bool>(obj); | ||
})); | ||
CELER_EXPECT(!objects_.empty()); | ||
} | ||
|
||
//---------------------------------------------------------------------------// | ||
/*! | ||
* Construct a volume from the joined objets. | ||
*/ | ||
template<OperatorToken Op> | ||
NodeId JoinObjects<Op>::build(VolumeBuilder& vb) const | ||
{ | ||
// Vector of nodes and cumulative bounding zone being built | ||
std::vector<NodeId> nodes; | ||
for (auto const& obj : objects_) | ||
{ | ||
// Construct the daughter CSG node | ||
auto daughter_id = obj->build(vb); | ||
nodes.push_back(daughter_id); | ||
} | ||
|
||
// Add the combined region | ||
return vb.insert_region(Label{label_}, Joined{op_token, std::move(nodes)}); | ||
} | ||
|
||
//---------------------------------------------------------------------------// | ||
// FREE FUNCTIONS | ||
//---------------------------------------------------------------------------// | ||
/*! | ||
* Make a new object that is the second object subtracted from the first. | ||
* | ||
* This just takes the intersection the first object and the negated second: | ||
* \verbatim A - B <=> A & ~B \endverbatim | ||
*/ | ||
std::shared_ptr<AllObjects const> | ||
make_subtraction(std::string&& label, | ||
std::shared_ptr<ObjectInterface const> const& minuend, | ||
std::shared_ptr<ObjectInterface const> const& subtrahend) | ||
{ | ||
CELER_EXPECT(!label.empty()); | ||
CELER_EXPECT(minuend && subtrahend); | ||
|
||
return std::make_shared<AllObjects>( | ||
std::move(label), | ||
AllObjects::VecObject{ | ||
{minuend, std::make_shared<NegatedObject>(subtrahend)}}); | ||
} | ||
|
||
//---------------------------------------------------------------------------// | ||
/*! | ||
* Make a combination of possibly negated objects. | ||
* | ||
* The Region Definition Vector is the SCALE way for defining media, | ||
* boundaries, etc. It must not be empty. | ||
*/ | ||
std::shared_ptr<AllObjects const> make_rdv( | ||
std::string&& label, | ||
std::vector<std::pair<Sense, std::shared_ptr<ObjectInterface const>>>&& inp) | ||
{ | ||
CELER_EXPECT(!label.empty()); | ||
CELER_EXPECT(!inp.empty()); | ||
|
||
AllObjects::VecObject objects; | ||
for (auto&& [sense, obj] : std::move(inp)) | ||
{ | ||
CELER_EXPECT(obj); | ||
// Negate 'outside' objects | ||
if (sense == Sense::outside) | ||
{ | ||
obj = std::make_shared<NegatedObject>(obj); | ||
} | ||
objects.push_back(std::move(obj)); | ||
} | ||
|
||
return std::make_shared<AllObjects>(std::move(label), std::move(objects)); | ||
} | ||
|
||
//---------------------------------------------------------------------------// | ||
// EXPLICIT INSTANTIATION | ||
//---------------------------------------------------------------------------// | ||
|
||
template class JoinObjects<op_and>; | ||
template class JoinObjects<op_or>; | ||
|
||
//---------------------------------------------------------------------------// | ||
} // namespace orangeinp | ||
} // namespace celeritas |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
//----------------------------------*-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/CsgObject.hh | ||
//! \brief CSG operations on Object instances: negation, union, intersection | ||
//---------------------------------------------------------------------------// | ||
#pragma once | ||
|
||
#include <string> | ||
#include <vector> | ||
|
||
#include "ObjectInterface.hh" | ||
|
||
namespace celeritas | ||
{ | ||
namespace orangeinp | ||
{ | ||
//---------------------------------------------------------------------------// | ||
/*! | ||
* Everywhere *but* the embedded object. | ||
*/ | ||
class NegatedObject : public ObjectInterface | ||
{ | ||
public: | ||
// Construct with the object to negate and an empty name | ||
explicit NegatedObject(SPConstObject obj); | ||
|
||
// Construct with a name and object | ||
NegatedObject(std::string&& label, SPConstObject obj); | ||
|
||
//! Get the user-provided label | ||
std::string_view label() const final { return label_; } | ||
|
||
// Construct a volume from this object | ||
NodeId build(VolumeBuilder&) const final; | ||
|
||
private: | ||
std::string label_; | ||
SPConstObject obj_; | ||
}; | ||
|
||
//---------------------------------------------------------------------------// | ||
/*! | ||
* Join all of the given objects with an intersection or union. | ||
*/ | ||
template<OperatorToken Op> | ||
class JoinObjects : public ObjectInterface | ||
{ | ||
static_assert(Op == op_and || Op == op_or); | ||
|
||
public: | ||
//!@{ | ||
//! \name Type aliases | ||
using VecObject = std::vector<SPConstObject>; | ||
//!@} | ||
|
||
//! Operation joining the daughters ("and" or "or") | ||
static constexpr OperatorToken op_token = Op; | ||
|
||
public: | ||
// Construct with a label and vector of objects | ||
JoinObjects(std::string&& label, VecObject&& objects); | ||
|
||
//! Access the vector of daughter objects | ||
VecObject const& daughters() const { return objects_; } | ||
|
||
//! Get the user-provided label | ||
std::string_view label() const final { return label_; } | ||
|
||
// Construct a volume from this object | ||
NodeId build(VolumeBuilder&) const final; | ||
|
||
private: | ||
std::string label_; | ||
VecObject objects_; | ||
}; | ||
|
||
//---------------------------------------------------------------------------// | ||
// TYPE ALIASES | ||
//---------------------------------------------------------------------------// | ||
|
||
//! Union of the given objects | ||
using AnyObjects = JoinObjects<op_or>; | ||
//! Intersection of the given objects | ||
using AllObjects = JoinObjects<op_and>; | ||
|
||
//---------------------------------------------------------------------------// | ||
// FREE FUNCTIONS | ||
//---------------------------------------------------------------------------// | ||
|
||
// Make a new object that is the second object subtracted from the first | ||
std::shared_ptr<AllObjects const> | ||
make_subtraction(std::string&& label, | ||
std::shared_ptr<ObjectInterface const> const& minuend, | ||
std::shared_ptr<ObjectInterface const> const& subtrahend); | ||
|
||
// Make a combination of possibly negated objects | ||
std::shared_ptr<AllObjects const> make_rdv( | ||
std::string&& label, | ||
std::vector<std::pair<Sense, std::shared_ptr<ObjectInterface const>>>&&); | ||
|
||
//---------------------------------------------------------------------------// | ||
} // namespace orangeinp | ||
} // namespace celeritas |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.