Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-28 09:19:36

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_ParentExplorer_HeaderFile
0015 #define _BRepGraph_ParentExplorer_HeaderFile
0016 
0017 #include <BRepGraph.hxx>
0018 #include <BRepGraphInc_Definition.hxx>
0019 #include <BRepGraphInc_Instance.hxx>
0020 #include <BRepGraphInc_Reference.hxx>
0021 #include <NCollection_BaseAllocator.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 Upward occurrence-aware parent traversal for BRepGraph.
0030 //! @see BRepGraph class comment "Iterator guide" for choosing between iterator types.
0031 //!
0032 //! Enumerates all ancestor nodes reachable from a starting node.
0033 //! Traversal is path-aware: when the same definition is reached through multiple
0034 //! occurrence paths, each path contributes its own parent sequence with its own
0035 //! accumulated location and orientation.
0036 //!
0037 //! The traversal follows the actual graph structure transparently - every node
0038 //! kind is visited as a distinct entity (no hidden collapses):
0039 //!   Vertex -> Edge,  Edge -> CoEdge,  CoEdge -> Wire,  Wire -> Face,
0040 //!   Face -> Shell,  Shell -> Solid,  Solid -> CompSolid/Compound,
0041 //!   topology root -> Occurrence, Product child -> Occurrence,
0042 //!   Occurrence -> parent Product.
0043 //!
0044 //! ## Traversal modes
0045 //! - **Recursive**: walks the full ancestor chain to the graph roots.
0046 //!   Without target kind, all ancestors are emitted.
0047 //!   With target kind, only matching ancestors are emitted but intermediate
0048 //!   levels are traversed to reach them.
0049 //! - **DirectParents**: yields only the immediate parents of the starting node.
0050 //!   No ascent into grandparents.  With target kind, only parents
0051 //!   matching the kind are returned.
0052 class BRepGraph_ParentExplorer
0053 {
0054 public:
0055   DEFINE_STANDARD_ALLOC
0056 
0057   //! Relationship kind between Current() and CurrentChild().
0058   enum class LinkKind
0059   {
0060     None,       //!< No current branch step.
0061     Reference,  //!< Current() owns CurrentChild() through a RefId.
0062     Structural, //!< Current() reaches CurrentChild() through a structural non-ref link.
0063   };
0064 
0065   //! Upward traversal strategy.
0066   enum class TraversalMode
0067   {
0068     Recursive,     //!< Walk the full ancestor chain to the graph roots.
0069     DirectParents, //!< Yields only the immediate parents of the starting node.
0070   };
0071 
0072   //! Consolidated configuration for the explorer.
0073   //!
0074   //! The `Config`-based constructor is the preferred idiom: new options can be
0075   //! added as fields without additional constructor overloads.
0076   //!
0077   //! @code
0078   //!   BRepGraph_ParentExplorer::Config aConfig;
0079   //!   aConfig.Mode       = BRepGraph_ParentExplorer::TraversalMode::DirectParents;
0080   //!   aConfig.TargetKind = BRepGraph_NodeId::Kind::Shell;
0081   //!   for (auto [id, loc, ori] : BRepGraph_ParentExplorer(aGraph, aNode, aConfig)) { ... }
0082   //! @endcode
0083   struct Config
0084   {
0085     TraversalMode Mode = TraversalMode::Recursive;
0086     std::optional<BRepGraph_NodeId::Kind>
0087       TargetKind;                                    //!< Emit only this kind (no value = emit all).
0088     std::optional<BRepGraph_NodeId::Kind> AvoidKind; //!< Do not ascend through this kind.
0089     bool EmitAvoidKind = false;                      //!< Emit matching avoid-kind ancestors once.
0090   };
0091 
0092   //! Preferred long-term constructor: all tuning knobs in `Config`.
0093   //! @param[in] theGraph  graph to walk
0094   //! @param[in] theNode   starting node whose ancestors are explored
0095   //! @param[in] theConfig traversal configuration
0096   Standard_EXPORT BRepGraph_ParentExplorer(const BRepGraph&       theGraph,
0097                                            const BRepGraph_NodeId theNode,
0098                                            const Config&          theConfig);
0099 
0100   //! Explore all parents of the starting node.
0101   //! @param[in] theGraph graph to walk
0102   //! @param[in] theNode  starting node whose ancestors are explored
0103   Standard_EXPORT BRepGraph_ParentExplorer(const BRepGraph&       theGraph,
0104                                            const BRepGraph_NodeId theNode);
0105 
0106   //! Explore parents of the starting node using the given traversal mode.
0107   //! @param[in] theGraph graph to walk
0108   //! @param[in] theNode  starting node whose ancestors are explored
0109   //! @param[in] theMode  traversal strategy (recursive or direct parents)
0110   Standard_EXPORT BRepGraph_ParentExplorer(const BRepGraph&       theGraph,
0111                                            const BRepGraph_NodeId theNode,
0112                                            TraversalMode          theMode);
0113 
0114   //! Explore all parents while pruning branches at the avoid kind.
0115   //! @param[in] theGraph        graph to walk
0116   //! @param[in] theNode         starting node whose ancestors are explored
0117   //! @param[in] theAvoidKind    node kind to avoid ascending through
0118   //! @param[in] theEmitAvoidKind if true, emit matching avoid-kind ancestors once
0119   //! @param[in] theMode         traversal strategy
0120   Standard_EXPORT BRepGraph_ParentExplorer(
0121     const BRepGraph&                             theGraph,
0122     const BRepGraph_NodeId                       theNode,
0123     const std::optional<BRepGraph_NodeId::Kind>& theAvoidKind,
0124     bool                                         theEmitAvoidKind,
0125     TraversalMode                                theMode = TraversalMode::Recursive);
0126 
0127   //! Explore only parents of the given kind.
0128   //! @param[in] theGraph     graph to walk
0129   //! @param[in] theNode      starting node whose ancestors are explored
0130   //! @param[in] theTargetKind kind of nodes to emit
0131   Standard_EXPORT BRepGraph_ParentExplorer(const BRepGraph&       theGraph,
0132                                            const BRepGraph_NodeId theNode,
0133                                            BRepGraph_NodeId::Kind theTargetKind);
0134 
0135   //! Explore only parents of the given kind using the given traversal mode.
0136   //! @param[in] theGraph     graph to walk
0137   //! @param[in] theNode      starting node whose ancestors are explored
0138   //! @param[in] theTargetKind kind of nodes to emit
0139   //! @param[in] theMode      traversal strategy
0140   Standard_EXPORT BRepGraph_ParentExplorer(const BRepGraph&       theGraph,
0141                                            const BRepGraph_NodeId theNode,
0142                                            BRepGraph_NodeId::Kind theTargetKind,
0143                                            TraversalMode          theMode);
0144 
0145   //! Explore parents of the given kind while pruning branches at the avoid kind.
0146   //! @param[in] theGraph        graph to walk
0147   //! @param[in] theNode         starting node whose ancestors are explored
0148   //! @param[in] theTargetKind   kind of nodes to emit
0149   //! @param[in] theAvoidKind    node kind to avoid ascending through
0150   //! @param[in] theEmitAvoidKind if true, emit matching avoid-kind ancestors once
0151   //! @param[in] theMode         traversal strategy
0152   Standard_EXPORT BRepGraph_ParentExplorer(
0153     const BRepGraph&                             theGraph,
0154     const BRepGraph_NodeId                       theNode,
0155     BRepGraph_NodeId::Kind                       theTargetKind,
0156     const std::optional<BRepGraph_NodeId::Kind>& theAvoidKind,
0157     bool                                         theEmitAvoidKind,
0158     TraversalMode                                theMode = TraversalMode::Recursive);
0159 
0160   //! Returns the traversal configuration this explorer was constructed with.
0161   //! Read-only - configuration is fixed for the lifetime of the explorer.
0162   [[nodiscard]] const Config& GetConfig() const { return myConfig; }
0163 
0164   //! True if another matching parent is available.
0165   [[nodiscard]] bool More() const { return myHasMore; }
0166 
0167   //! Advance to the next matching parent.
0168   Standard_EXPORT void Next();
0169 
0170   //! Current matching ancestor node with accumulated location and orientation.
0171   [[nodiscard]] BRepGraphInc::NodeInstance Current() const
0172   {
0173     if (myHasMore)
0174     {
0175       return {myCurrent, myLocation, myOrientation};
0176     }
0177     return {};
0178   }
0179 
0180   //! Returns the immediate child of Current() on the currently emitted branch.
0181   //! Returns invalid NodeId when no current ancestor is available.
0182   [[nodiscard]] Standard_EXPORT BRepGraph_NodeId CurrentChild() const;
0183 
0184   //! Returns how Current() is linked to CurrentChild().
0185   [[nodiscard]] Standard_EXPORT LinkKind CurrentLinkKind() const;
0186 
0187   //! Returns the exact parent-owned RefId linking Current() to CurrentChild(),
0188   //! when that branch step is represented by a reference entry.
0189   //!
0190   //! Some upward steps are structural and therefore have no parent-owned ref
0191   //! entry even though the parent itself is still emitted by the explorer.
0192   //! In those cases this method returns an invalid RefId, for example for
0193   //! CoEdge->Edge and Occurrence->Product/topology-root.
0194   [[nodiscard]] Standard_EXPORT BRepGraph_RefId CurrentRef() const;
0195 
0196   //! Accumulated location at the starting node of the current branch.
0197   [[nodiscard]] Standard_EXPORT const TopLoc_Location& LeafLocation() const;
0198 
0199   //! Accumulated orientation at the starting node of the current branch.
0200   [[nodiscard]] Standard_EXPORT TopAbs_Orientation LeafOrientation() const;
0201 
0202   //! True if Current() is the explicit root node of the current branch.
0203   [[nodiscard]] Standard_EXPORT bool IsCurrentBranchRoot() const;
0204 
0205   //! Returns an STL-compatible iterator for range-based for loops.
0206   NCollection_ForwardRangeIterator<BRepGraph_ParentExplorer> begin()
0207   {
0208     return NCollection_ForwardRangeIterator<BRepGraph_ParentExplorer>(this);
0209   }
0210 
0211   //! Returns a sentinel marking the end of iteration.
0212   NCollection_ForwardRangeSentinel end() const { return NCollection_ForwardRangeSentinel{}; }
0213 
0214 private:
0215   struct StackFrame
0216   {
0217     BRepGraph_NodeId   Node;
0218     uint32_t           NextParentIdx = 0;
0219     int                StepToChild   = -1;
0220     BRepGraph_RefId    RefToChild;
0221     TopLoc_Location    AccLocation;
0222     TopAbs_Orientation AccOrientation = TopAbs_FORWARD;
0223   };
0224 
0225   Standard_EXPORT void startTraversal();
0226   Standard_EXPORT void advance();
0227   Standard_EXPORT bool emitNextFromCurrentBranch();
0228   Standard_EXPORT void backtrackAfterBranchEmission();
0229   Standard_EXPORT bool nextParentFrame(StackFrame& theChild, StackFrame& theParent) const;
0230   Standard_EXPORT void prepareCurrentBranch();
0231   Standard_EXPORT void applyTransition(const BRepGraph_NodeId theParent,
0232                                        const BRepGraph_NodeId theChild,
0233                                        const int              theStepToChild,
0234                                        const BRepGraph_RefId  theRefToChild,
0235                                        TopLoc_Location&       theLocation,
0236                                        TopAbs_Orientation&    theOrientation) const;
0237 
0238   [[nodiscard]] Standard_EXPORT int branchRootFrame() const;
0239 
0240   Standard_EXPORT bool findNthOccurrenceWrapper(const BRepGraph_NodeId     theNode,
0241                                                 const uint32_t             theOrdinal,
0242                                                 BRepGraph_OccurrenceId&    theOccurrence,
0243                                                 BRepGraph_OccurrenceRefId& theOccurrenceRef) const;
0244 
0245   Standard_EXPORT int findOccurrenceStep(
0246     const BRepGraph_ProductId    theParentProduct,
0247     const BRepGraph_OccurrenceId theOccurrence,
0248     BRepGraph_OccurrenceRefId*   theOccurrenceRef = nullptr) const;
0249   Standard_EXPORT int findCompoundChildStep(const BRepGraph_CompoundId theParent,
0250                                             const BRepGraph_NodeId     theChild) const;
0251   Standard_EXPORT int findCompSolidSolidStep(const BRepGraph_CompSolidId theParent,
0252                                              const BRepGraph_SolidId     theChild) const;
0253   Standard_EXPORT int findSolidChildStep(const BRepGraph_SolidId theParent,
0254                                          const BRepGraph_NodeId  theChild) const;
0255   Standard_EXPORT int findShellChildStep(const BRepGraph_ShellId theParent,
0256                                          const BRepGraph_NodeId  theChild) const;
0257   Standard_EXPORT int findFaceChildStep(const BRepGraph_FaceId theParent,
0258                                         const BRepGraph_NodeId theChild) const;
0259   Standard_EXPORT int findWireCoEdgeStep(const BRepGraph_WireId   theParent,
0260                                          const BRepGraph_CoEdgeId theChild) const;
0261   Standard_EXPORT int findEdgeVertexStep(const BRepGraph_EdgeId   theParent,
0262                                          const BRepGraph_VertexId theChild) const;
0263 
0264   //! Try compound parents, then occurrence parents for the given node.
0265   //! Returns true and fills theParent if a match is found at theRemainingIdx.
0266   //! Returns false if no compound/occurrence parent exists at that index.
0267   Standard_EXPORT bool nextCompoundOrOccurrenceParent(BRepGraph_NodeId theNode,
0268                                                       uint32_t         theRemainingIdx,
0269                                                       StackFrame&      theParent) const;
0270 
0271   static std::optional<BRepGraph_NodeId::Kind> normalizeAvoidKind(
0272     const BRepGraph_NodeId                       theNode,
0273     const std::optional<BRepGraph_NodeId::Kind>& theTargetKind,
0274     const std::optional<BRepGraph_NodeId::Kind>& theAvoidKind);
0275 
0276   static bool canContainTarget(BRepGraph_NodeId::Kind theParentKind,
0277                                BRepGraph_NodeId::Kind theTargetKind);
0278 
0279   Standard_EXPORT void pushFrame(const StackFrame& theFrame);
0280   Standard_EXPORT void popFrame();
0281 
0282   [[nodiscard]] bool matchesAvoid(const BRepGraph_NodeId theNode) const
0283   {
0284     return myConfig.AvoidKind.has_value() && theNode.NodeKind == *myConfig.AvoidKind;
0285   }
0286 
0287   [[nodiscard]] bool shouldEmit(const BRepGraph_NodeId theNode) const
0288   {
0289     const bool isAvoid = matchesAvoid(theNode);
0290     const bool isFind =
0291       !myConfig.TargetKind.has_value() || theNode.NodeKind == *myConfig.TargetKind;
0292     return myConfig.EmitAvoidKind ? (isFind || isAvoid) : (isFind && !isAvoid);
0293   }
0294 
0295   StackFrame& topFrame() { return myStack[myStackTop]; }
0296 
0297   const StackFrame& topFrame() const { return myStack[myStackTop]; }
0298 
0299   Standard_EXPORT TopLoc_Location    stepLocation(const BRepGraph_NodeId theParent,
0300                                                   const int              theRefIdx) const;
0301   Standard_EXPORT TopAbs_Orientation stepOrientation(const BRepGraph_NodeId theParent,
0302                                                      const int              theRefIdx) const;
0303 
0304 private:
0305   static constexpr int THE_INLINE_STACK_SIZE = 16;
0306 
0307   const BRepGraph* myGraph = nullptr;
0308   BRepGraph_NodeId myNode;
0309   Config           myConfig; //!< Traversal configuration - single source of truth.
0310 
0311   NCollection_LocalArray<StackFrame, THE_INLINE_STACK_SIZE> myStack;
0312   int                                                       myStackTop     = -1;
0313   int                                                       myEmitIndex    = -1;
0314   int                                                       myCurrentFrame = -1;
0315 
0316   BRepGraph_NodeId   myCurrent;
0317   TopLoc_Location    myLocation;
0318   TopAbs_Orientation myOrientation = TopAbs_FORWARD;
0319   bool               myHasMore     = false;
0320 };
0321 
0322 #endif // _BRepGraph_ParentExplorer_HeaderFile