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_RefId_HeaderFile
0015 #define _BRepGraph_RefId_HeaderFile
0016 
0017 #include <Standard_Assert.hxx>
0018 #include <Standard_HashUtils.hxx>
0019 
0020 #include <cstddef>
0021 #include <cstdint>
0022 #include <functional>
0023 #include <limits>
0024 #include <utility>
0025 
0026 class BRepGraph;
0027 
0028 //! Lightweight typed index into a per-kind reference vector inside BRepGraph.
0029 //!
0030 //! The pair (Kind, Index) forms a unique reference identifier within one graph
0031 //! instance. Default-constructed RefId has Index = UINT32_MAX (invalid).
0032 struct BRepGraph_RefId
0033 {
0034   //! Enumeration of supported topology reference kinds.
0035   enum class Kind : int
0036   {
0037     Shell      = 0, //!< Shell reference entries (usage of shell definitions)
0038     Face       = 1, //!< Face reference entries (usage of face definitions)
0039     Wire       = 2, //!< Wire reference entries (usage of wire definitions)
0040     Vertex     = 3, //!< Vertex reference entries (usage of vertex definitions)
0041     Solid      = 4, //!< Solid reference entries (usage of solid definitions)
0042     Child      = 5, //!< Generic child references (usage of mixed node definitions)
0043     Occurrence = 6  //!< Occurrence references (usage of occurrence definitions)
0044   };
0045 
0046   //! True if the kind value is one of the supported reference kinds.
0047   static bool IsValidKind(const Kind theKind)
0048   {
0049     switch (theKind)
0050     {
0051       case Kind::Shell:
0052       case Kind::Face:
0053       case Kind::Wire:
0054       case Kind::Vertex:
0055       case Kind::Solid:
0056       case Kind::Child:
0057       case Kind::Occurrence:
0058         return true;
0059     }
0060     return false;
0061   }
0062 
0063   //! @brief Compile-time typed wrapper around BRepGraph_RefId.
0064   //!
0065   //! Provides compile-time kind safety similarly to BRepGraph_NodeId::Typed.
0066   template <Kind TheKind>
0067   struct Typed
0068   {
0069     static constexpr uint32_t THE_START_INDEX   = 0u;
0070     static constexpr uint32_t THE_INVALID_INDEX = std::numeric_limits<uint32_t>::max();
0071 
0072     uint32_t Index;
0073 
0074     Typed()
0075         : Index(THE_INVALID_INDEX)
0076     {
0077     }
0078 
0079     explicit Typed(const uint32_t theIdx)
0080         : Index(theIdx)
0081     {
0082     }
0083 
0084     //! Construct from an untyped reference id of the same kind.
0085     explicit Typed(const BRepGraph_RefId theRefId)
0086         : Typed(FromRefId(theRefId))
0087     {
0088     }
0089 
0090     template <Kind OtherKind, typename std::enable_if_t<OtherKind != TheKind, int> = 0>
0091     Typed(const Typed<OtherKind>&) = delete;
0092 
0093     //! First valid id in a dense per-kind sequence.
0094     [[nodiscard]] static Typed Start() { return Typed(THE_START_INDEX); }
0095 
0096     //! Invalid sentinel id.
0097     [[nodiscard]] static Typed Invalid() { return Typed(); }
0098 
0099     [[nodiscard]] bool IsValid() const
0100     {
0101       return BRepGraph_RefId::IsValidKind(TheKind) && Index != THE_INVALID_INDEX;
0102     }
0103 
0104     //! True if this id points to an allocated slot within [0, theMaxCount).
0105     //! UINT32_MAX (invalid sentinel) always fails this check for any realistic count.
0106     [[nodiscard]] bool IsValid(const uint32_t theMaxCount) const
0107     {
0108       return IsValid() && Index < theMaxCount;
0109     }
0110 
0111     template <typename CountProviderT>
0112     [[nodiscard]] auto IsValidIn(const CountProviderT& theProvider) const
0113       -> decltype(theProvider.Nb(), bool())
0114     {
0115       return IsValid(theProvider.Nb());
0116     }
0117 
0118     template <typename CountProviderT>
0119     [[nodiscard]] auto IsValidIn(const CountProviderT& theProvider) const
0120       -> decltype(theProvider.Size(), bool())
0121     {
0122       return IsValid(static_cast<uint32_t>(theProvider.Size()));
0123     }
0124 
0125     operator BRepGraph_RefId() const { return BRepGraph_RefId(TheKind, Index); }
0126 
0127     static Typed FromRefId(const BRepGraph_RefId theRefId)
0128     {
0129       Standard_ASSERT_RETURN(theRefId.RefKind == TheKind, "RefId kind mismatch", Typed());
0130       if (!theRefId.IsValid())
0131       {
0132         return Typed();
0133       }
0134       return Typed(theRefId.Index);
0135     }
0136 
0137     bool operator==(const Typed& theOther) const { return Index == theOther.Index; }
0138 
0139     bool operator!=(const Typed& theOther) const { return Index != theOther.Index; }
0140 
0141     bool operator<(const Typed& theOther) const { return Index < theOther.Index; }
0142 
0143     bool operator<=(const Typed& theOther) const { return Index <= theOther.Index; }
0144 
0145     bool operator>(const Typed& theOther) const { return Index > theOther.Index; }
0146 
0147     bool operator>=(const Typed& theOther) const { return Index >= theOther.Index; }
0148 
0149     //! Pre-increment (++id).
0150     Typed& operator++()
0151     {
0152       Standard_ASSERT_VOID(Index != THE_INVALID_INDEX, "pre-increment on invalid id");
0153       ++Index;
0154       return *this;
0155     }
0156 
0157     //! Post-increment (id++).
0158     Typed operator++(int)
0159     {
0160       Standard_ASSERT_VOID(Index != THE_INVALID_INDEX, "post-increment on invalid id");
0161       Typed aPrev = *this;
0162       ++Index;
0163       return aPrev;
0164     }
0165 
0166     //! Advance by offset.
0167     [[nodiscard]] Typed operator+(const uint32_t theOffset) const
0168     {
0169       return Typed(Index + theOffset);
0170     }
0171 
0172     //! Retreat by offset.
0173     [[nodiscard]] Typed operator-(const uint32_t theOffset) const
0174     {
0175       Standard_ASSERT_VOID(Index != THE_INVALID_INDEX && Index >= theOffset,
0176                            "retreat underflows index");
0177       return Typed(Index - theOffset);
0178     }
0179 
0180     bool operator==(const BRepGraph_RefId& theOther) const
0181     {
0182       return theOther.RefKind == TheKind && theOther.Index == Index;
0183     }
0184 
0185     bool operator!=(const BRepGraph_RefId& theOther) const { return !(*this == theOther); }
0186 
0187     friend bool operator==(const BRepGraph_RefId& theLhs, const Typed& theRhs)
0188     {
0189       return theRhs == theLhs;
0190     }
0191 
0192     friend bool operator!=(const BRepGraph_RefId& theLhs, const Typed& theRhs)
0193     {
0194       return theRhs != theLhs;
0195     }
0196 
0197     //! Return true if this reference entry has been soft-removed in the given graph.
0198     [[nodiscard]] bool IsRemoved(const BRepGraph& theGraph) const
0199     {
0200       return BRepGraph_RefId(*this).IsRemoved(theGraph);
0201     }
0202 
0203     //! Return true if this reference entry has an active owner in the given graph.
0204     [[nodiscard]] bool IsOwned(const BRepGraph& theGraph) const
0205     {
0206       return BRepGraph_RefId(*this).IsOwned(theGraph);
0207     }
0208   };
0209 
0210   static bool IsTopologyRefKind(const Kind theKind)
0211   {
0212     return IsValidKind(theKind) && theKind >= Kind::Shell && theKind <= Kind::Child;
0213   }
0214 
0215   static constexpr uint32_t THE_START_INDEX   = 0u;
0216   static constexpr uint32_t THE_INVALID_INDEX = std::numeric_limits<uint32_t>::max();
0217 
0218   Kind     RefKind;
0219   uint32_t Index;
0220 
0221   BRepGraph_RefId()
0222       : RefKind(Kind::Shell),
0223         Index(THE_INVALID_INDEX)
0224   {
0225   }
0226 
0227   BRepGraph_RefId(const Kind theKind, const uint32_t theIdx)
0228       : RefKind(theKind),
0229         Index(theIdx)
0230   {
0231   }
0232 
0233   //! First valid id in a dense sequence for the specified kind.
0234   [[nodiscard]] static BRepGraph_RefId Start(const Kind theKind)
0235   {
0236     return BRepGraph_RefId(theKind, THE_START_INDEX);
0237   }
0238 
0239   //! Invalid sentinel id for the specified kind.
0240   [[nodiscard]] static BRepGraph_RefId Invalid(const Kind theKind = Kind::Shell)
0241   {
0242     return BRepGraph_RefId(theKind, THE_INVALID_INDEX);
0243   }
0244 
0245   [[nodiscard]] bool IsValid() const { return IsValidKind(RefKind) && Index != THE_INVALID_INDEX; }
0246 
0247   //! True if this id points to an allocated slot within [0, theMaxCount).
0248   //! UINT32_MAX (invalid sentinel) always fails this check for any realistic count.
0249   [[nodiscard]] bool IsValid(const uint32_t theMaxCount) const
0250   {
0251     return IsValid() && Index < theMaxCount;
0252   }
0253 
0254   template <typename CountProviderT>
0255   [[nodiscard]] auto IsValidIn(const CountProviderT& theProvider) const
0256     -> decltype(theProvider.Nb(), bool())
0257   {
0258     return IsValid(theProvider.Nb());
0259   }
0260 
0261   template <typename CountProviderT>
0262   [[nodiscard]] auto IsValidIn(const CountProviderT& theProvider) const
0263     -> decltype(theProvider.Size(), bool())
0264   {
0265     return IsValid(static_cast<uint32_t>(theProvider.Size()));
0266   }
0267 
0268   bool operator==(const BRepGraph_RefId& theOther) const
0269   {
0270     return RefKind == theOther.RefKind && Index == theOther.Index;
0271   }
0272 
0273   bool operator!=(const BRepGraph_RefId& theOther) const { return !(*this == theOther); }
0274 
0275   bool operator<(const BRepGraph_RefId& theOther) const
0276   {
0277     if (RefKind != theOther.RefKind)
0278     {
0279       return static_cast<int>(RefKind) < static_cast<int>(theOther.RefKind);
0280     }
0281     return Index < theOther.Index;
0282   }
0283 
0284   //! Pre-increment (++id).
0285   BRepGraph_RefId& operator++()
0286   {
0287     Standard_ASSERT_VOID(Index != THE_INVALID_INDEX, "pre-increment on invalid id");
0288     ++Index;
0289     return *this;
0290   }
0291 
0292   //! Post-increment (id++).
0293   BRepGraph_RefId operator++(int)
0294   {
0295     Standard_ASSERT_VOID(Index != THE_INVALID_INDEX, "post-increment on invalid id");
0296     BRepGraph_RefId aPrev = *this;
0297     ++Index;
0298     return aPrev;
0299   }
0300 
0301   //! Advance by offset.
0302   [[nodiscard]] BRepGraph_RefId operator+(const uint32_t theOffset) const
0303   {
0304     return BRepGraph_RefId(RefKind, Index + theOffset);
0305   }
0306 
0307   //! Retreat by offset.
0308   [[nodiscard]] BRepGraph_RefId operator-(const uint32_t theOffset) const
0309   {
0310     Standard_ASSERT_VOID(Index != THE_INVALID_INDEX && Index >= theOffset,
0311                          "retreat underflows index");
0312     return BRepGraph_RefId(RefKind, Index - theOffset);
0313   }
0314 
0315   //! Dispatch a generic ref id to a callable taking the matching typed ref id.
0316   template <typename FuncT>
0317   static auto Visit(const BRepGraph_RefId theRefId, FuncT&& theFunc)
0318     -> decltype(std::forward<FuncT>(theFunc)(Typed<Kind::Shell>()))
0319   {
0320     switch (theRefId.RefKind)
0321     {
0322       case Kind::Shell:
0323         return std::forward<FuncT>(theFunc)(Typed<Kind::Shell>::FromRefId(theRefId));
0324       case Kind::Face:
0325         return std::forward<FuncT>(theFunc)(Typed<Kind::Face>::FromRefId(theRefId));
0326       case Kind::Wire:
0327         return std::forward<FuncT>(theFunc)(Typed<Kind::Wire>::FromRefId(theRefId));
0328       case Kind::Vertex:
0329         return std::forward<FuncT>(theFunc)(Typed<Kind::Vertex>::FromRefId(theRefId));
0330       case Kind::Solid:
0331         return std::forward<FuncT>(theFunc)(Typed<Kind::Solid>::FromRefId(theRefId));
0332       case Kind::Child:
0333         return std::forward<FuncT>(theFunc)(Typed<Kind::Child>::FromRefId(theRefId));
0334       case Kind::Occurrence:
0335         return std::forward<FuncT>(theFunc)(Typed<Kind::Occurrence>::FromRefId(theRefId));
0336     }
0337 
0338     Standard_ASSERT_VOID(false, "BRepGraph_RefId::Visit: unhandled Kind");
0339     return std::forward<FuncT>(theFunc)(Typed<Kind::Shell>());
0340   }
0341 
0342   //! Return true if this reference entry has been soft-removed in the given graph.
0343   [[nodiscard]] Standard_EXPORT bool IsRemoved(const BRepGraph& theGraph) const;
0344 
0345   //! Return true if this reference entry has an active owner in the given graph.
0346   [[nodiscard]] Standard_EXPORT bool IsOwned(const BRepGraph& theGraph) const;
0347 };
0348 
0349 using BRepGraph_ShellRefId      = BRepGraph_RefId::Typed<BRepGraph_RefId::Kind::Shell>;
0350 using BRepGraph_FaceRefId       = BRepGraph_RefId::Typed<BRepGraph_RefId::Kind::Face>;
0351 using BRepGraph_WireRefId       = BRepGraph_RefId::Typed<BRepGraph_RefId::Kind::Wire>;
0352 using BRepGraph_VertexRefId     = BRepGraph_RefId::Typed<BRepGraph_RefId::Kind::Vertex>;
0353 using BRepGraph_SolidRefId      = BRepGraph_RefId::Typed<BRepGraph_RefId::Kind::Solid>;
0354 using BRepGraph_ChildRefId      = BRepGraph_RefId::Typed<BRepGraph_RefId::Kind::Child>;
0355 using BRepGraph_OccurrenceRefId = BRepGraph_RefId::Typed<BRepGraph_RefId::Kind::Occurrence>;
0356 
0357 template <>
0358 struct std::hash<BRepGraph_RefId>
0359 {
0360   size_t operator()(const BRepGraph_RefId& theId) const noexcept
0361   {
0362     size_t aCombination[2];
0363     aCombination[0] = opencascade::hash(static_cast<int>(theId.RefKind));
0364     aCombination[1] = opencascade::hash(theId.Index);
0365     return opencascade::hashBytes(aCombination, sizeof(aCombination));
0366   }
0367 };
0368 
0369 template <BRepGraph_RefId::Kind TheKind>
0370 struct std::hash<BRepGraph_RefId::Typed<TheKind>>
0371 {
0372   size_t operator()(const BRepGraph_RefId::Typed<TheKind>& theId) const noexcept
0373   {
0374     return std::hash<BRepGraph_RefId>{}(static_cast<BRepGraph_RefId>(theId));
0375   }
0376 };
0377 
0378 #endif // _BRepGraph_RefId_HeaderFile