Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-27 09:18:49

0001 // Created on: 2009-10-22
0002 // Created by: Mikhail SAZONOV
0003 // Copyright (c) 2009-2014 OPEN CASCADE SAS
0004 //
0005 // This file is part of Open CASCADE Technology software library.
0006 //
0007 // This library is free software; you can redistribute it and/or modify it under
0008 // the terms of the GNU Lesser General Public License version 2.1 as published
0009 // by the Free Software Foundation, with special exception defined in the file
0010 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
0011 // distribution for complete text of the license and disclaimer of any warranty.
0012 //
0013 // Alternatively, this file may be used under the terms of Open CASCADE
0014 // commercial license or contractual agreement.
0015 
0016 #ifndef Poly_MakeLoops_HeaderFile
0017 #define Poly_MakeLoops_HeaderFile
0018 
0019 #include <NCollection_Sequence.hxx>
0020 #include <NCollection_IndexedMap.hxx>
0021 #include <TColStd_PackedMapOfInteger.hxx>
0022 #include <NCollection_IncAllocator.hxx>
0023 #include <NCollection_List.hxx>
0024 #include <NCollection_OccAllocator.hxx>
0025 #include <Standard_HashUtils.hxx>
0026 
0027 /**
0028  * Make loops from a set of connected links. A link is represented by
0029  * a pair of integer indices of nodes.
0030  */
0031 class Poly_MakeLoops
0032 {
0033 public:
0034   //! Orientation flags that can be attached to a link
0035   enum LinkFlag
0036   {
0037     LF_None     = 0,
0038     LF_Fwd      = 1, // forward orientation
0039     LF_Rev      = 2, // reversed orientation
0040     LF_Both     = 3, // both ways oriented
0041     LF_Reversed = 4  // means the link is reversed
0042   };
0043 
0044   //! The Link structure
0045   struct Link
0046   {
0047     int node1, node2;
0048     int flags;
0049 
0050     Link()
0051         : node1(0),
0052           node2(0),
0053           flags(0)
0054     {
0055     }
0056 
0057     Link(int theNode1, int theNode2)
0058         : node1(theNode1),
0059           node2(theNode2),
0060           flags(1)
0061     {
0062     }
0063 
0064     void Reverse() { flags ^= Poly_MakeLoops::LF_Reversed; }
0065 
0066     bool IsReversed() const { return (flags & Poly_MakeLoops::LF_Reversed) != 0; }
0067 
0068     void Nullify() { node1 = node2 = 0; }
0069 
0070     bool IsNull() const { return node1 == 0 || node2 == 0; }
0071 
0072     bool operator==(const Link& theOther) const
0073     {
0074       return (theOther.node1 == node1 && theOther.node2 == node2)
0075              || (theOther.node1 == node2 && theOther.node2 == node1);
0076     }
0077   };
0078 
0079   struct Hasher
0080   {
0081     size_t operator()(const Poly_MakeLoops::Link& theLink) const noexcept
0082     {
0083       // Combine two int values into a single hash value.
0084       int aCombination[2]{theLink.node1, theLink.node2};
0085       if (aCombination[0] > aCombination[1])
0086       {
0087         std::swap(aCombination[0], aCombination[1]);
0088       }
0089       return opencascade::hashBytes(aCombination, sizeof(aCombination));
0090     }
0091 
0092     bool operator()(const Poly_MakeLoops::Link& theLink1,
0093                     const Poly_MakeLoops::Link& theLink2) const noexcept
0094     {
0095       return theLink1 == theLink2;
0096     }
0097   };
0098 
0099   // Define the Loop as a list of links
0100   typedef NCollection_List<Link> ListOfLink;
0101   typedef ListOfLink             Loop;
0102 
0103   //! The abstract helper class
0104   class Helper
0105   {
0106   public:
0107     //! returns the links adjacent to the given node
0108     virtual const ListOfLink& GetAdjacentLinks(int theNode) const = 0;
0109 
0110     //! hook function called from AddLink in _DEBUG mode
0111     virtual void OnAddLink(int /*theNum*/, const Link& /*theLink*/) const {}
0112   };
0113 
0114   //! This class implements a heap of integers. The most effective usage
0115   //! of it is first to add there all items, and then get top item and remove
0116   //! any items till it becomes empty.
0117   class HeapOfInteger
0118   {
0119   public:
0120     HeapOfInteger(const int theNbPreAllocated = 1)
0121         : myMap(theNbPreAllocated),
0122           myIterReady(false)
0123     {
0124     }
0125 
0126     void Clear()
0127     {
0128       myMap.Clear();
0129       myIterReady = false;
0130     }
0131 
0132     void Add(const int theValue)
0133     {
0134       myMap.Add(theValue);
0135       myIterReady = false;
0136     }
0137 
0138     int Top()
0139     {
0140       if (!myIterReady)
0141       {
0142         myIter.Initialize(myMap);
0143         myIterReady = true;
0144       }
0145       return myIter.Key();
0146     }
0147 
0148     bool Contains(const int theValue) const { return myMap.Contains(theValue); }
0149 
0150     void Remove(const int theValue)
0151     {
0152       if (myIterReady && myIter.More() && myIter.Key() == theValue)
0153         myIter.Next();
0154       myMap.Remove(theValue);
0155     }
0156 
0157     bool IsEmpty()
0158     {
0159       if (!myIterReady)
0160       {
0161         myIter.Initialize(myMap);
0162         myIterReady = true;
0163       }
0164       return !myIter.More();
0165     }
0166 
0167   private:
0168     TColStd_PackedMapOfInteger           myMap;
0169     TColStd_PackedMapOfInteger::Iterator myIter;
0170     bool                                 myIterReady;
0171   };
0172 
0173 public:
0174   // PUBLIC METHODS
0175 
0176   //! Constructor. If helper is NULL then the algorithm will
0177   //! probably return a wrong result
0178   Standard_EXPORT Poly_MakeLoops(const Helper*                                 theHelper,
0179                                  const occ::handle<NCollection_BaseAllocator>& theAlloc = nullptr);
0180 
0181   //! It is to reset the algorithm to the initial state.
0182   Standard_EXPORT void Reset(const Helper*                                 theHelper,
0183                              const occ::handle<NCollection_BaseAllocator>& theAlloc = nullptr);
0184 
0185   //! Adds a link to the set. theOrient defines which orientations of the link
0186   //! are allowed.
0187   Standard_EXPORT void AddLink(const Link& theLink);
0188 
0189   //! Replace one link with another (e.g. to change order of nodes)
0190   Standard_EXPORT void ReplaceLink(const Link& theLink, const Link& theNewLink);
0191 
0192   //! Set a new value of orientation of a link already added earlier.
0193   //! It can be used with LF_None to exclude the link from consideration.
0194   //! Returns the old value of orientation.
0195   Standard_EXPORT LinkFlag SetLinkOrientation(const Link& theLink, const LinkFlag theOrient);
0196 
0197   //! Find the link stored in algo by value
0198   Standard_EXPORT Link FindLink(const Link& theLink) const;
0199 
0200   enum ResultCode
0201   {
0202     RC_LoopsDone    = 1,
0203     RC_HangingLinks = 2,
0204     RC_Failure      = 4
0205   };
0206 
0207   //! Does the work. Returns the collection of result codes
0208   Standard_EXPORT int Perform();
0209 
0210   //! Returns the number of loops in the result
0211   int GetNbLoops() const { return myLoops.Length(); }
0212 
0213   //! Returns the loop of the given index
0214   const Loop& GetLoop(int theIndex) const { return myLoops.Value(theIndex); }
0215 
0216   //! Returns the number of detected hanging chains
0217   int GetNbHanging() const { return myHangIndices.Extent(); }
0218 
0219   //! Fills in the list of hanging links
0220   Standard_EXPORT void GetHangingLinks(ListOfLink& theLinks) const;
0221 
0222 protected:
0223   virtual int chooseLeftWay(const int                    theNode,
0224                             const int                    theSegIndex,
0225                             const NCollection_List<int>& theLstIndS) const = 0;
0226 
0227   const Helper* getHelper() const { return myHelper; }
0228 
0229   Link getLink(const int theSegIndex) const
0230   {
0231     Link aLink = myMapLink(std::abs(theSegIndex));
0232     if (theSegIndex < 0)
0233       aLink.Reverse();
0234     return aLink;
0235   }
0236 #ifdef OCCT_DEBUG
0237   void showBoundaryBreaks() const;
0238 #endif
0239 
0240 private:
0241   int  findContour(int                                           theIndexS,
0242                    NCollection_IndexedMap<int>&                  theContour,
0243                    const occ::handle<NCollection_BaseAllocator>& theTempAlloc,
0244                    const occ::handle<NCollection_IncAllocator>&  theTempAlloc1) const;
0245   void acceptContour(const NCollection_IndexedMap<int>& theContour, int theStartNumber);
0246   int  getFirstNode(int theIndexS) const;
0247   int  getLastNode(int theIndexS) const;
0248   void markHangChain(int theNode, int theIndexS);
0249   bool canLinkBeTaken(int theIndexS) const;
0250 
0251   // FIELDS
0252   const Helper*                          myHelper;
0253   occ::handle<NCollection_BaseAllocator> myAlloc;
0254   NCollection_IndexedMap<Link, Hasher>   myMapLink;
0255   NCollection_Sequence<Loop>             myLoops;
0256   HeapOfInteger                          myStartIndices;
0257   TColStd_PackedMapOfInteger             myHangIndices;
0258 };
0259 
0260 /**
0261  * Implementation for 3D space
0262  */
0263 class gp_Dir;
0264 
0265 class Poly_MakeLoops3D : public Poly_MakeLoops
0266 {
0267 public:
0268   //! The abstract helper class
0269   class Helper : public Poly_MakeLoops::Helper
0270   {
0271   public:
0272     // all the following methods should return False if
0273     // it is impossible to return a valid direction
0274 
0275     //! returns the tangent vector at the first node of a link
0276     virtual bool GetFirstTangent(const Link& theLink, gp_Dir& theDir) const = 0;
0277 
0278     //! returns the tangent vector at the last node of a link
0279     virtual bool GetLastTangent(const Link& theLink, gp_Dir& theDir) const = 0;
0280 
0281     //! returns the normal to the surface at a given node
0282     virtual bool GetNormal(int theNode, gp_Dir& theDir) const = 0;
0283   };
0284 
0285   //! Constructor. If helper is NULL then the algorithm will
0286   //! probably return a wrong result
0287   Standard_EXPORT Poly_MakeLoops3D(const Helper*                                 theHelper,
0288                                    const occ::handle<NCollection_BaseAllocator>& theAlloc);
0289 
0290 protected:
0291   Standard_EXPORT int chooseLeftWay(const int                    theNode,
0292                                     const int                    theSegIndex,
0293                                     const NCollection_List<int>& theLstIndS) const override;
0294 
0295   const Helper* getHelper() const
0296   {
0297     return static_cast<const Poly_MakeLoops3D::Helper*>(Poly_MakeLoops::getHelper());
0298   }
0299 };
0300 
0301 /**
0302  * Implementation for 2D space
0303  */
0304 class gp_Dir2d;
0305 
0306 class Poly_MakeLoops2D : public Poly_MakeLoops
0307 {
0308 public:
0309   //! The abstract helper class
0310   class Helper : public Poly_MakeLoops::Helper
0311   {
0312   public:
0313     // all the following methods should return False if
0314     // it is impossible to return a valid direction
0315 
0316     //! returns the tangent vector at the first node of a link
0317     virtual bool GetFirstTangent(const Link& theLink, gp_Dir2d& theDir) const = 0;
0318 
0319     //! returns the tangent vector at the last node of a link
0320     virtual bool GetLastTangent(const Link& theLink, gp_Dir2d& theDir) const = 0;
0321   };
0322 
0323   //! Constructor. If helper is NULL then the algorithm will
0324   //! probably return a wrong result
0325   Standard_EXPORT Poly_MakeLoops2D(const bool                                    theLeftWay,
0326                                    const Helper*                                 theHelper,
0327                                    const occ::handle<NCollection_BaseAllocator>& theAlloc);
0328 
0329 protected:
0330   Standard_EXPORT int chooseLeftWay(const int                    theNode,
0331                                     const int                    theSegIndex,
0332                                     const NCollection_List<int>& theLstIndS) const override;
0333 
0334   const Helper* getHelper() const
0335   {
0336     return static_cast<const Poly_MakeLoops2D::Helper*>(Poly_MakeLoops::getHelper());
0337   }
0338 
0339 private:
0340   //! this flag says that chooseLeftWay must choose the right way instead
0341   bool myRightWay;
0342 };
0343 
0344 namespace std
0345 {
0346 template <>
0347 struct hash<Poly_MakeLoops::Link>
0348 {
0349   size_t operator()(const Poly_MakeLoops::Link& theLink) const noexcept
0350   {
0351     return Poly_MakeLoops::Hasher{}(theLink);
0352   }
0353 };
0354 
0355 template <>
0356 struct equal_to<Poly_MakeLoops::Link>
0357 {
0358   bool operator()(const Poly_MakeLoops::Link& theLink1,
0359                   const Poly_MakeLoops::Link& theLink2) const noexcept
0360   {
0361     return theLink1 == theLink2;
0362   }
0363 };
0364 } // namespace std
0365 
0366 #endif