|
|
|||
File indexing completed on 2026-09-28 09:19:34
0001 // Copyright (c) 2026 OPEN CASCADE SAS 0002 // 0003 // This file is part of Open CASCADE Technology software library. 0004 // 0005 // This library is free software; you can redistribute it and/or modify it under 0006 // the terms of the GNU Lesser General Public License version 2.1 as published 0007 // by the Free Software Foundation, with special exception defined in the file 0008 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT 0009 // distribution for complete text of the license and disclaimer of any warranty. 0010 // 0011 // Alternatively, this file may be used under the terms of Open CASCADE 0012 // commercial license or contractual agreement. 0013 0014 #ifndef _BRepGraph_ChildExplorer_HeaderFile 0015 #define _BRepGraph_ChildExplorer_HeaderFile 0016 0017 #include <BRepGraph.hxx> 0018 #include <BRepGraphInc_Definition.hxx> 0019 #include <BRepGraphInc_Instance.hxx> 0020 #include <BRepGraphInc_Reference.hxx> 0021 #include <BRepGraph_UsagePath.hxx> 0022 #include <NCollection_ForwardRange.hxx> 0023 #include <NCollection_LocalArray.hxx> 0024 #include <TopAbs_Orientation.hxx> 0025 #include <TopLoc_Location.hxx> 0026 0027 #include <optional> 0028 0029 //! @brief Stack-based lazy downward hierarchy walker for BRepGraph with inline 0030 //! location/orientation accumulation. 0031 //! @see BRepGraph class comment "Iterator guide" for choosing between iterator types. 0032 //! 0033 //! Walks the graph hierarchy from a root node down to entities of a target kind, 0034 //! yielding one occurrence at a time via a depth-first stack. Location and 0035 //! orientation are composed incrementally during the walk, making 0036 //! Current().Location and Current().Orientation O(1) per call. 0037 //! 0038 //! The traversal follows the actual graph structure transparently - every node 0039 //! kind is visited as a distinct entity (no hidden collapses): 0040 //! Compound -> children, CompSolid -> Solids, Solid -> Shells, 0041 //! Shell -> Faces, Face -> Wires (+direct Vertices), Wire -> CoEdges, 0042 //! CoEdge -> Edge, Edge -> Vertices, 0043 //! Product -> Occurrences, Occurrence -> Product/topology-root. 0044 //! 0045 //! Unlike flat definition traversal by typed ids, BRepGraph_ChildExplorer visits 0046 //! each occurrence. If Edge[5] is reachable through Face[0] and Face[1], 0047 //! it is visited twice with different accumulated transforms. 0048 //! 0049 //! ## Traversal modes 0050 //! - **Recursive**: depth-first walk through the full subgraph. 0051 //! Without target kind, all descendant nodes are emitted. 0052 //! With target kind, only matching nodes are emitted but intermediate 0053 //! levels are traversed to reach them. 0054 //! - **DirectChildren**: yields only the immediate children of the root. 0055 //! No descent into grandchildren. With target kind, only children 0056 //! matching the kind are returned. 0057 class BRepGraph_ChildExplorer 0058 { 0059 public: 0060 DEFINE_STANDARD_ALLOC 0061 0062 //! Relationship kind between Current() and CurrentParent(). 0063 enum class LinkKind 0064 { 0065 None, //!< No current incoming link (e.g. root/self match). 0066 Reference, //!< Current() is reached through a parent-owned RefId. 0067 Structural, //!< Current() is reached through a structural non-ref link. 0068 }; 0069 0070 //! Downward traversal strategy. 0071 enum class TraversalMode 0072 { 0073 Recursive, //!< Depth-first walk through the full subgraph. 0074 DirectChildren, //!< Yields only the immediate children of the root. 0075 }; 0076 0077 //! Consolidated configuration for the explorer. 0078 //! 0079 //! The `Config`-based constructor is the preferred idiom: new options can be 0080 //! added as fields without additional constructor overloads. 0081 //! 0082 //! @code 0083 //! BRepGraph_ChildExplorer::Config aConfig; 0084 //! aConfig.Mode = BRepGraph_ChildExplorer::TraversalMode::DirectChildren; 0085 //! aConfig.TargetKind = BRepGraph_NodeId::Kind::Face; 0086 //! aConfig.StartLoc = aParentLocation; 0087 //! aConfig.StartOri = TopAbs_REVERSED; 0088 //! for (auto [id, loc, ori] : BRepGraph_ChildExplorer(aGraph, aRoot, aConfig)) { ... } 0089 //! @endcode 0090 struct Config 0091 { 0092 TraversalMode Mode = TraversalMode::Recursive; 0093 std::optional<BRepGraph_NodeId::Kind> 0094 TargetKind; //!< Emit only this kind (no value = emit all). 0095 std::optional<BRepGraph_NodeId::Kind> AvoidKind; //!< Do not descend into this kind. 0096 bool EmitAvoidKind = 0097 false; //!< Emit matching avoid-kind nodes once before skipping their subtree. 0098 bool AccumulateLocation = true; //!< Compose Location down the walk. 0099 bool AccumulateOrientation = true; //!< Compose Orientation down the walk. 0100 TopLoc_Location StartLoc; //!< Initial accumulated location. 0101 TopAbs_Orientation StartOri = TopAbs_FORWARD; //!< Initial accumulated orientation. 0102 }; 0103 0104 //! Preferred long-term constructor: all tuning knobs in `Config`. 0105 //! @param[in] theGraph graph to walk 0106 //! @param[in] theRoot root node where the walk begins 0107 //! @param[in] theConfig traversal configuration (mode, target kind, avoid kind, etc.) 0108 Standard_EXPORT BRepGraph_ChildExplorer(const BRepGraph& theGraph, 0109 const BRepGraph_NodeId theRoot, 0110 const Config& theConfig); 0111 0112 //! Explore all descendants of the root node using recursive traversal. 0113 //! @param[in] theGraph graph to walk 0114 //! @param[in] theRoot root node where the walk begins 0115 Standard_EXPORT BRepGraph_ChildExplorer(const BRepGraph& theGraph, 0116 const BRepGraph_NodeId theRoot); 0117 0118 //! Explore descendants of the root node using the given traversal mode. 0119 //! @param[in] theGraph graph to walk 0120 //! @param[in] theRoot root node where the walk begins 0121 //! @param[in] theMode traversal strategy (recursive or direct children) 0122 Standard_EXPORT BRepGraph_ChildExplorer(const BRepGraph& theGraph, 0123 const BRepGraph_NodeId theRoot, 0124 TraversalMode theMode); 0125 0126 //! Explore descendants while pruning branches at the avoid kind. 0127 //! @param[in] theGraph graph to walk 0128 //! @param[in] theRoot root node where the walk begins 0129 //! @param[in] theAvoidKind node kind to avoid descending into 0130 //! @param[in] theEmitAvoidKind if true, emit matching avoid-kind nodes once before skipping 0131 //! @param[in] theMode traversal strategy 0132 Standard_EXPORT BRepGraph_ChildExplorer(const BRepGraph& theGraph, 0133 const BRepGraph_NodeId theRoot, 0134 const std::optional<BRepGraph_NodeId::Kind>& theAvoidKind, 0135 bool theEmitAvoidKind, 0136 TraversalMode theMode = TraversalMode::Recursive); 0137 0138 //! Explore only descendants of the given target kind. 0139 //! @param[in] theGraph graph to walk 0140 //! @param[in] theRoot root node where the walk begins 0141 //! @param[in] theTargetKind kind of nodes to emit 0142 Standard_EXPORT BRepGraph_ChildExplorer(const BRepGraph& theGraph, 0143 const BRepGraph_NodeId theRoot, 0144 BRepGraph_NodeId::Kind theTargetKind); 0145 0146 //! Explore only descendants of the given target kind using the given traversal mode. 0147 //! @param[in] theGraph graph to walk 0148 //! @param[in] theRoot root node where the walk begins 0149 //! @param[in] theTargetKind kind of nodes to emit 0150 //! @param[in] theMode traversal strategy 0151 Standard_EXPORT BRepGraph_ChildExplorer(const BRepGraph& theGraph, 0152 const BRepGraph_NodeId theRoot, 0153 BRepGraph_NodeId::Kind theTargetKind, 0154 TraversalMode theMode); 0155 0156 //! Explore descendants of the given target kind while pruning branches at the avoid kind. 0157 //! @param[in] theGraph graph to walk 0158 //! @param[in] theRoot root node where the walk begins 0159 //! @param[in] theTargetKind kind of nodes to emit 0160 //! @param[in] theAvoidKind node kind to avoid descending into 0161 //! @param[in] theEmitAvoidKind if true, emit matching avoid-kind nodes once before skipping 0162 //! @param[in] theMode traversal strategy 0163 Standard_EXPORT BRepGraph_ChildExplorer(const BRepGraph& theGraph, 0164 const BRepGraph_NodeId theRoot, 0165 BRepGraph_NodeId::Kind theTargetKind, 0166 const std::optional<BRepGraph_NodeId::Kind>& theAvoidKind, 0167 bool theEmitAvoidKind, 0168 TraversalMode theMode = TraversalMode::Recursive); 0169 0170 //! Explore only descendants of the given target kind starting from a product. 0171 //! @param[in] theGraph graph to walk 0172 //! @param[in] theProduct product whose occurrences and topology are explored 0173 //! @param[in] theTargetKind kind of nodes to emit 0174 Standard_EXPORT BRepGraph_ChildExplorer(const BRepGraph& theGraph, 0175 const BRepGraph_ProductId theProduct, 0176 BRepGraph_NodeId::Kind theTargetKind); 0177 0178 //! Disambiguates non-product typed ids from the ProductId-specific overload 0179 //! family above and keeps them on the generic NodeId traversal path. 0180 //! @param[in] theGraph graph to walk 0181 //! @param[in] theRoot typed root node where the walk begins 0182 //! @param[in] theTargetKind kind of nodes to emit 0183 template <BRepGraph_NodeId::Kind TheKind, 0184 typename std::enable_if_t<TheKind != BRepGraph_NodeId::Kind::Product, int> = 0> 0185 BRepGraph_ChildExplorer(const BRepGraph& theGraph, 0186 const BRepGraph_NodeId::Typed<TheKind> theRoot, 0187 BRepGraph_NodeId::Kind theTargetKind) 0188 : BRepGraph_ChildExplorer(theGraph, BRepGraph_NodeId(theRoot), theTargetKind) 0189 { 0190 } 0191 0192 //! Explore only descendants of the given target kind starting from a product, 0193 //! using the given traversal mode. 0194 //! @param[in] theGraph graph to walk 0195 //! @param[in] theProduct product whose occurrences and topology are explored 0196 //! @param[in] theTargetKind kind of nodes to emit 0197 //! @param[in] theMode traversal strategy 0198 Standard_EXPORT BRepGraph_ChildExplorer(const BRepGraph& theGraph, 0199 const BRepGraph_ProductId theProduct, 0200 BRepGraph_NodeId::Kind theTargetKind, 0201 TraversalMode theMode); 0202 0203 //! Disambiguates non-product typed ids from the ProductId-specific overload 0204 //! family above and keeps them on the generic NodeId traversal path. 0205 //! @param[in] theGraph graph to walk 0206 //! @param[in] theRoot typed root node where the walk begins 0207 //! @param[in] theTargetKind kind of nodes to emit 0208 //! @param[in] theMode traversal strategy 0209 template <BRepGraph_NodeId::Kind TheKind, 0210 typename std::enable_if_t<TheKind != BRepGraph_NodeId::Kind::Product, int> = 0> 0211 BRepGraph_ChildExplorer(const BRepGraph& theGraph, 0212 const BRepGraph_NodeId::Typed<TheKind> theRoot, 0213 BRepGraph_NodeId::Kind theTargetKind, 0214 TraversalMode theMode) 0215 : BRepGraph_ChildExplorer(theGraph, BRepGraph_NodeId(theRoot), theTargetKind, theMode) 0216 { 0217 } 0218 0219 //! Explore only descendants of the given target kind with explicit location/orientation control. 0220 //! @param[in] theGraph graph to walk 0221 //! @param[in] theRoot root node where the walk begins 0222 //! @param[in] theTargetKind kind of nodes to emit 0223 //! @param[in] theCumLoc if true, accumulate location down the walk 0224 //! @param[in] theCumOri if true, accumulate orientation down the walk 0225 //! @param[in] theMode traversal strategy 0226 Standard_EXPORT BRepGraph_ChildExplorer(const BRepGraph& theGraph, 0227 const BRepGraph_NodeId theRoot, 0228 BRepGraph_NodeId::Kind theTargetKind, 0229 bool theCumLoc, 0230 bool theCumOri, 0231 TraversalMode theMode = TraversalMode::Recursive); 0232 0233 //! Explore only descendants of the given target kind starting from a product, 0234 //! with explicit location/orientation control. 0235 //! @param[in] theGraph graph to walk 0236 //! @param[in] theProduct product whose occurrences and topology are explored 0237 //! @param[in] theTargetKind kind of nodes to emit 0238 //! @param[in] theCumLoc if true, accumulate location down the walk 0239 //! @param[in] theCumOri if true, accumulate orientation down the walk 0240 //! @param[in] theMode traversal strategy 0241 Standard_EXPORT BRepGraph_ChildExplorer(const BRepGraph& theGraph, 0242 const BRepGraph_ProductId theProduct, 0243 BRepGraph_NodeId::Kind theTargetKind, 0244 bool theCumLoc, 0245 bool theCumOri, 0246 TraversalMode theMode = TraversalMode::Recursive); 0247 0248 //! Disambiguates non-product typed ids from the ProductId-specific overload 0249 //! family above and keeps them on the generic NodeId traversal path. 0250 //! @param[in] theGraph graph to walk 0251 //! @param[in] theRoot typed root node where the walk begins 0252 //! @param[in] theTargetKind kind of nodes to emit 0253 //! @param[in] theCumLoc if true, accumulate location down the walk 0254 //! @param[in] theCumOri if true, accumulate orientation down the walk 0255 //! @param[in] theMode traversal strategy 0256 template <BRepGraph_NodeId::Kind TheKind, 0257 typename std::enable_if_t<TheKind != BRepGraph_NodeId::Kind::Product, int> = 0> 0258 BRepGraph_ChildExplorer(const BRepGraph& theGraph, 0259 const BRepGraph_NodeId::Typed<TheKind> theRoot, 0260 BRepGraph_NodeId::Kind theTargetKind, 0261 bool theCumLoc, 0262 bool theCumOri, 0263 TraversalMode theMode = TraversalMode::Recursive) 0264 : BRepGraph_ChildExplorer(theGraph, 0265 BRepGraph_NodeId(theRoot), 0266 theTargetKind, 0267 theCumLoc, 0268 theCumOri, 0269 theMode) 0270 { 0271 } 0272 0273 //! Explore only descendants of the given target kind with an explicit initial transform. 0274 //! @param[in] theGraph graph to walk 0275 //! @param[in] theRoot root node where the walk begins 0276 //! @param[in] theTargetKind kind of nodes to emit 0277 //! @param[in] theStartLoc initial accumulated location 0278 //! @param[in] theStartOri initial accumulated orientation 0279 //! @param[in] theMode traversal strategy 0280 Standard_EXPORT BRepGraph_ChildExplorer(const BRepGraph& theGraph, 0281 const BRepGraph_NodeId theRoot, 0282 BRepGraph_NodeId::Kind theTargetKind, 0283 const TopLoc_Location& theStartLoc, 0284 TopAbs_Orientation theStartOri, 0285 TraversalMode theMode = TraversalMode::DirectChildren); 0286 0287 //! Returns the traversal configuration this explorer was constructed with. 0288 //! Read-only - configuration is fixed for the lifetime of the explorer. 0289 [[nodiscard]] const Config& GetConfig() const { return myConfig; } 0290 0291 //! True if another matching descendant is available. 0292 [[nodiscard]] bool More() const { return myHasMore; } 0293 0294 //! Advance to the next matching descendant. 0295 Standard_EXPORT void Next(); 0296 0297 //! Current matching descendant node with accumulated location and orientation. 0298 [[nodiscard]] BRepGraphInc::NodeInstance Current() const 0299 { 0300 return {myCurrent, myLocation, myOrientation}; 0301 } 0302 0303 //! Returns the immediate parent of Current() in the explored path. 0304 //! Returns invalid NodeId when Current() is the root/self match. 0305 [[nodiscard]] Standard_EXPORT BRepGraph_NodeId CurrentParent() const; 0306 0307 //! Returns how Current() is linked from CurrentParent(). 0308 [[nodiscard]] Standard_EXPORT LinkKind CurrentLinkKind() const; 0309 0310 //! Returns the exact parent-owned RefId for Current(), when the current step 0311 //! is represented by a reference entry. Returns invalid RefId for structural 0312 //! links without a dedicated ref entry such as CoEdge->Edge, 0313 //! Occurrence->Product/topology-root. 0314 [[nodiscard]] Standard_EXPORT BRepGraph_RefId CurrentRef() const; 0315 0316 //! Returns the explicit concrete traversal path from the explorer root to Current(). 0317 [[nodiscard]] Standard_EXPORT BRepGraph_UsagePath CurrentUsagePath() const; 0318 0319 //! Returns the accumulated location at the most recent ancestor of the given kind. 0320 //! @param[in] theKind node kind to search for in the ancestor chain 0321 //! @return accumulated location at the matching ancestor 0322 [[nodiscard]] Standard_EXPORT TopLoc_Location 0323 LocationOf(const BRepGraph_NodeId::Kind theKind) const; 0324 0325 //! Returns the node id of the most recent ancestor of the given kind. 0326 //! @param[in] theKind node kind to search for in the ancestor chain 0327 //! @return node id of the matching ancestor 0328 [[nodiscard]] Standard_EXPORT BRepGraph_NodeId NodeOf(const BRepGraph_NodeId::Kind theKind) const; 0329 0330 //! Returns the accumulated location at the given stack level. 0331 //! @param[in] theLevel zero-based stack depth (0 = root) 0332 //! @return accumulated location at the specified level 0333 [[nodiscard]] Standard_EXPORT TopLoc_Location LocationAt(const int theLevel) const; 0334 0335 //! Returns the node id at the given stack level. 0336 //! @param[in] theLevel zero-based stack depth (0 = root) 0337 //! @return node id at the specified level 0338 [[nodiscard]] Standard_EXPORT BRepGraph_NodeId NodeAt(const int theLevel) const; 0339 0340 //! Number of valid ancestor frames currently on the stack (excluding the 0341 //! sentinel below the root). O(1); avoids the O(depth^2) NodeAt(i) walk used 0342 //! to compute container priority in selection-mode building. 0343 [[nodiscard]] int Depth() const noexcept { return myStackTop < 0 ? 0 : myStackTop + 1; } 0344 0345 //! Returns an STL-compatible iterator for range-based for loops. 0346 NCollection_ForwardRangeIterator<BRepGraph_ChildExplorer> begin() 0347 { 0348 return NCollection_ForwardRangeIterator<BRepGraph_ChildExplorer>(this); 0349 } 0350 0351 //! Returns a sentinel marking the end of iteration. 0352 NCollection_ForwardRangeSentinel end() const { return NCollection_ForwardRangeSentinel{}; } 0353 0354 private: 0355 struct StackFrame 0356 { 0357 BRepGraph_NodeId Node; 0358 uint32_t NextChildIdx = 0; 0359 int StepFromParent = -1; 0360 BRepGraph_RefId Ref; //!< RefId resolved at push time (O(1) in CurrentRef) 0361 TopLoc_Location AccLocation; 0362 TopAbs_Orientation AccOrientation = TopAbs_FORWARD; 0363 }; 0364 0365 Standard_EXPORT void advance(); 0366 0367 void startTraversal(const TopLoc_Location& theStartLoc, TopAbs_Orientation theStartOri); 0368 0369 static std::optional<BRepGraph_NodeId::Kind> normalizeAvoidKind( 0370 const std::optional<BRepGraph_NodeId::Kind>& theAvoidKind, 0371 const std::optional<BRepGraph_NodeId::Kind>& theTargetKind); 0372 0373 static bool canContainTarget(BRepGraph_NodeId::Kind theParentKind, 0374 BRepGraph_NodeId::Kind theTargetKind); 0375 0376 static bool canHaveChildren(BRepGraph_NodeId::Kind theNodeKind); 0377 0378 void setCurrentFromFrame(const int theFrameIndex); 0379 0380 [[nodiscard]] bool shouldDescendFromCurrent() const; 0381 0382 [[nodiscard]] bool matchesTarget(const BRepGraph_NodeId theNode) const 0383 { 0384 return myConfig.TargetKind.has_value() && theNode.NodeKind == *myConfig.TargetKind; 0385 } 0386 0387 [[nodiscard]] bool matchesAvoid(const BRepGraph_NodeId theNode) const 0388 { 0389 return myConfig.AvoidKind.has_value() && theNode.NodeKind == *myConfig.AvoidKind; 0390 } 0391 0392 [[nodiscard]] bool shouldEmit(const BRepGraph_NodeId theNode) const 0393 { 0394 const bool isAvoid = matchesAvoid(theNode); 0395 const bool isFind = 0396 !myConfig.TargetKind.has_value() || theNode.NodeKind == *myConfig.TargetKind; 0397 return myConfig.EmitAvoidKind ? (isFind || isAvoid) : (isFind && !isAvoid); 0398 } 0399 0400 void pushFrame(const StackFrame& theFrame); 0401 0402 void popFrame(); 0403 0404 StackFrame& topFrame() { return myStack[myStackTop]; } 0405 0406 const StackFrame& topFrame() const { return myStack[myStackTop]; } 0407 0408 static constexpr int THE_INLINE_STACK_SIZE = 16; 0409 0410 const BRepGraph* myGraph = nullptr; 0411 BRepGraph_NodeId myRoot; 0412 Config myConfig; //!< Traversal configuration - single source of truth. 0413 0414 NCollection_LocalArray<StackFrame, THE_INLINE_STACK_SIZE> myStack; 0415 int myStackTop = -1; 0416 int myCurrentFrame = -1; 0417 0418 BRepGraph_NodeId myCurrent; 0419 TopLoc_Location myLocation; 0420 TopAbs_Orientation myOrientation = TopAbs_FORWARD; 0421 bool myHasMore = false; 0422 }; 0423 0424 #endif // _BRepGraph_ChildExplorer_HeaderFile
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|