Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-16 09:03:16

0001 //------------------------------- -*- C++ -*- -------------------------------//
0002 // Copyright Celeritas contributors: see top-level COPYRIGHT file for details
0003 // SPDX-License-Identifier: (Apache-2.0 OR MIT)
0004 //---------------------------------------------------------------------------//
0005 //! \file orange/orangeinp/detail/InfixStringBuilder.hh
0006 //---------------------------------------------------------------------------//
0007 #pragma once
0008 
0009 #include <ostream>
0010 
0011 #include "corecel/cont/VariantUtils.hh"
0012 #include "orange/SenseUtils.hh"
0013 
0014 #include "../CsgTree.hh"
0015 
0016 namespace celeritas
0017 {
0018 namespace orangeinp
0019 {
0020 namespace detail
0021 {
0022 //---------------------------------------------------------------------------//
0023 /*!
0024  * Transform a CSG node into a string expression.
0025  *
0026  * The string will be a combination of:
0027  * - an \c any function for a union of all listed components
0028  * - an \c all function for an intersection of all listed components
0029  * - a \c ! negation operator applied to the left of an operation or other
0030  *   negation
0031  * - a surface ID preceded by a \c - or \c + indicating "inside" or "outside",
0032  *   respectively.
0033  *
0034  * Example of a cylindrical shell: \verbatim
0035    all(all(+0, -1, -3), !all(+0, -1, -2))
0036  * \endverbatim
0037  */
0038 class InfixStringBuilder
0039 {
0040   public:
0041     // Construct with tree and a stream to write to
0042     inline InfixStringBuilder(CsgTree const& tree, std::ostream* os);
0043 
0044     // Build from a node ID
0045     inline void operator()(NodeId const& n);
0046 
0047     //!@{
0048     //! \name Visit a node directly
0049 
0050     // Append 'true'
0051     inline void operator()(True const&);
0052     // False is never explicitly part of the node tree
0053     inline void operator()(False const&);
0054     // Append a surface ID
0055     inline void operator()(Surface const&);
0056     // Aliased nodes should never be reachable explicitly
0057     inline void operator()(Aliased const&);
0058     // Visit a negated node and append 'not'
0059     inline void operator()(Negated const&);
0060     // Visit daughter nodes and append the conjunction.
0061     inline void operator()(Joined const&);
0062     //!@}
0063 
0064   private:
0065     ContainerVisitor<CsgTree const&, NodeId> visit_node_;
0066     std::ostream* os_;
0067     bool negated_{false};
0068 };
0069 
0070 //---------------------------------------------------------------------------//
0071 // INLINE DEFINITIONS
0072 //---------------------------------------------------------------------------//
0073 /*!
0074  * Construct with a reference to an output stream.
0075  */
0076 InfixStringBuilder::InfixStringBuilder(CsgTree const& tree, std::ostream* os)
0077     : visit_node_{tree}, os_{os}
0078 {
0079     CELER_EXPECT(os_);
0080 }
0081 
0082 //---------------------------------------------------------------------------//
0083 /*!
0084  * Build from a node ID.
0085  */
0086 void InfixStringBuilder::operator()(NodeId const& n)
0087 {
0088     visit_node_(*this, n);
0089 }
0090 
0091 //---------------------------------------------------------------------------//
0092 /*!
0093  * Append the "true" token.
0094  */
0095 void InfixStringBuilder::operator()(True const&)
0096 {
0097     *os_ << (negated_ ? 'F' : 'T');
0098     negated_ = false;
0099 }
0100 
0101 //---------------------------------------------------------------------------//
0102 /*!
0103  * Explicit "False" should never be possible for a CSG cell.
0104  *
0105  * The 'false' standin is always aliased to "not true" in the CSG tree.
0106  */
0107 void InfixStringBuilder::operator()(False const&)
0108 {
0109     CELER_ASSERT_UNREACHABLE();
0110 }
0111 
0112 //---------------------------------------------------------------------------//
0113 /*!
0114  * Push a surface ID.
0115  */
0116 void InfixStringBuilder::operator()(Surface const& s)
0117 {
0118     CELER_EXPECT(s.id < logic::lbegin);
0119 
0120     static_assert(to_sense(true) == Sense::outside);
0121     *os_ << (negated_ ? '-' : '+') << s.id.unchecked_get();
0122     negated_ = false;
0123 }
0124 
0125 //---------------------------------------------------------------------------//
0126 /*!
0127  * Push an aliased node.
0128  *
0129  * Note: aliased node won't be reachable if a tree is fully simplified, *but* a
0130  * node can be printed for testing before it's simplified.
0131  */
0132 void InfixStringBuilder::operator()(Aliased const& n)
0133 {
0134     (*this)(n.node);
0135 }
0136 
0137 //---------------------------------------------------------------------------//
0138 /*!
0139  * Visit a negated node and append 'not'.
0140  */
0141 void InfixStringBuilder::operator()(Negated const& n)
0142 {
0143     if (negated_)
0144     {
0145         // Note: this won't happen for simplified expressions but can be for
0146         // testing unsimplified expressions.
0147         *os_ << '!';
0148     }
0149     negated_ = true;
0150     (*this)(n.node);
0151 }
0152 
0153 //---------------------------------------------------------------------------//
0154 /*!
0155  * Visit daughter nodes and append the conjunction.
0156  */
0157 void InfixStringBuilder::operator()(Joined const& n)
0158 {
0159     CELER_EXPECT(n.nodes.size() > 1);
0160 
0161     if (negated_)
0162     {
0163         *os_ << '!';
0164     }
0165     negated_ = false;
0166     *os_ << (n.op == op_and ? "all" : n.op == op_or ? "any" : "XXX") << '(';
0167 
0168     // Visit first node, then add conjunction for subsequent nodes
0169     auto iter = n.nodes.begin();
0170     (*this)(*iter++);
0171 
0172     while (iter != n.nodes.end())
0173     {
0174         *os_ << ", ";
0175         (*this)(*iter++);
0176     }
0177     *os_ << ')';
0178 }
0179 
0180 //---------------------------------------------------------------------------//
0181 }  // namespace detail
0182 }  // namespace orangeinp
0183 }  // namespace celeritas