![]() |
|
|||
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
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
![]() ![]() |