|
||||
File indexing completed on 2025-01-18 10:05:55
0001 //----------------------------------*-C++-*----------------------------------// 0002 // Copyright 2024 UT-Battelle, LLC, and other Celeritas developers. 0003 // See the top-level COPYRIGHT file for details. 0004 // SPDX-License-Identifier: (Apache-2.0 OR MIT) 0005 //---------------------------------------------------------------------------// 0006 //! \file orange/orangeinp/detail/InfixStringBuilder.hh 0007 //---------------------------------------------------------------------------// 0008 #pragma once 0009 0010 #include <ostream> 0011 0012 #include "corecel/cont/VariantUtils.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 // Append 'true' 0050 inline void operator()(True const&); 0051 // False is never explicitly part of the node tree 0052 inline void operator()(False const&); 0053 // Append a surface ID 0054 inline void operator()(Surface const&); 0055 // Aliased nodes should never be reachable explicitly 0056 inline void operator()(Aliased const&); 0057 // Visit a negated node and append 'not' 0058 inline void operator()(Negated const&); 0059 // Visit daughter nodes and append the conjunction. 0060 inline void operator()(Joined const&); 0061 //!@} 0062 0063 private: 0064 ContainerVisitor<CsgTree const&, NodeId> visit_node_; 0065 std::ostream* os_; 0066 bool negated_{false}; 0067 }; 0068 0069 //---------------------------------------------------------------------------// 0070 // INLINE DEFINITIONS 0071 //---------------------------------------------------------------------------// 0072 /*! 0073 * Construct with a reference to an output stream. 0074 */ 0075 InfixStringBuilder::InfixStringBuilder(CsgTree const& tree, std::ostream* os) 0076 : visit_node_{tree}, os_{os} 0077 { 0078 CELER_EXPECT(os_); 0079 } 0080 0081 //---------------------------------------------------------------------------// 0082 /*! 0083 * Build from a node ID. 0084 */ 0085 void InfixStringBuilder::operator()(NodeId const& n) 0086 { 0087 visit_node_(*this, n); 0088 } 0089 0090 //---------------------------------------------------------------------------// 0091 /*! 0092 * Append the "true" token. 0093 */ 0094 void InfixStringBuilder::operator()(True const&) 0095 { 0096 *os_ << (negated_ ? 'F' : 'T'); 0097 negated_ = false; 0098 } 0099 0100 //---------------------------------------------------------------------------// 0101 /*! 0102 * Explicit "False" should never be possible for a CSG cell. 0103 * 0104 * The 'false' standin is always aliased to "not true" in the CSG tree. 0105 */ 0106 void InfixStringBuilder::operator()(False const&) 0107 { 0108 CELER_ASSERT_UNREACHABLE(); 0109 } 0110 0111 //---------------------------------------------------------------------------// 0112 /*! 0113 * Push a surface ID. 0114 */ 0115 void InfixStringBuilder::operator()(Surface const& s) 0116 { 0117 CELER_EXPECT(s.id < logic::lbegin); 0118 0119 static_assert(to_sense(true) == Sense::outside); 0120 *os_ << (negated_ ? '-' : '+') << s.id.unchecked_get(); 0121 negated_ = false; 0122 } 0123 0124 //---------------------------------------------------------------------------// 0125 /*! 0126 * Push an aliased node. 0127 * 0128 * Note: aliased node won't be reachable if a tree is fully simplified, *but* a 0129 * node can be printed for testing before it's simplified. 0130 */ 0131 void InfixStringBuilder::operator()(Aliased const& n) 0132 { 0133 (*this)(n.node); 0134 } 0135 0136 //---------------------------------------------------------------------------// 0137 /*! 0138 * Visit a negated node and append 'not'. 0139 */ 0140 void InfixStringBuilder::operator()(Negated const& n) 0141 { 0142 if (negated_) 0143 { 0144 // Note: this won't happen for simplified expressions but can be for 0145 // testing unsimplified expressions. 0146 *os_ << '!'; 0147 } 0148 negated_ = true; 0149 (*this)(n.node); 0150 } 0151 0152 //---------------------------------------------------------------------------// 0153 /*! 0154 * Visit daughter nodes and append the conjunction. 0155 */ 0156 void InfixStringBuilder::operator()(Joined const& n) 0157 { 0158 CELER_EXPECT(n.nodes.size() > 1); 0159 0160 if (negated_) 0161 { 0162 *os_ << '!'; 0163 } 0164 negated_ = false; 0165 *os_ << (n.op == op_and ? "all" : n.op == op_or ? "any" : "XXX") << '('; 0166 0167 // Visit first node, then add conjunction for subsequent nodes 0168 auto iter = n.nodes.begin(); 0169 (*this)(*iter++); 0170 0171 while (iter != n.nodes.end()) 0172 { 0173 *os_ << ", "; 0174 (*this)(*iter++); 0175 } 0176 *os_ << ')'; 0177 } 0178 0179 //---------------------------------------------------------------------------// 0180 } // namespace detail 0181 } // namespace orangeinp 0182 } // 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 |