Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:04:38

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