File indexing completed on 2026-09-27 09:18:49
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
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
0029
0030
0031 class Poly_MakeLoops
0032 {
0033 public:
0034
0035 enum LinkFlag
0036 {
0037 LF_None = 0,
0038 LF_Fwd = 1,
0039 LF_Rev = 2,
0040 LF_Both = 3,
0041 LF_Reversed = 4
0042 };
0043
0044
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
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
0100 typedef NCollection_List<Link> ListOfLink;
0101 typedef ListOfLink Loop;
0102
0103
0104 class Helper
0105 {
0106 public:
0107
0108 virtual const ListOfLink& GetAdjacentLinks(int theNode) const = 0;
0109
0110
0111 virtual void OnAddLink(int , const Link& ) const {}
0112 };
0113
0114
0115
0116
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
0175
0176
0177
0178 Standard_EXPORT Poly_MakeLoops(const Helper* theHelper,
0179 const occ::handle<NCollection_BaseAllocator>& theAlloc = nullptr);
0180
0181
0182 Standard_EXPORT void Reset(const Helper* theHelper,
0183 const occ::handle<NCollection_BaseAllocator>& theAlloc = nullptr);
0184
0185
0186
0187 Standard_EXPORT void AddLink(const Link& theLink);
0188
0189
0190 Standard_EXPORT void ReplaceLink(const Link& theLink, const Link& theNewLink);
0191
0192
0193
0194
0195 Standard_EXPORT LinkFlag SetLinkOrientation(const Link& theLink, const LinkFlag theOrient);
0196
0197
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
0208 Standard_EXPORT int Perform();
0209
0210
0211 int GetNbLoops() const { return myLoops.Length(); }
0212
0213
0214 const Loop& GetLoop(int theIndex) const { return myLoops.Value(theIndex); }
0215
0216
0217 int GetNbHanging() const { return myHangIndices.Extent(); }
0218
0219
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
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
0262
0263 class gp_Dir;
0264
0265 class Poly_MakeLoops3D : public Poly_MakeLoops
0266 {
0267 public:
0268
0269 class Helper : public Poly_MakeLoops::Helper
0270 {
0271 public:
0272
0273
0274
0275
0276 virtual bool GetFirstTangent(const Link& theLink, gp_Dir& theDir) const = 0;
0277
0278
0279 virtual bool GetLastTangent(const Link& theLink, gp_Dir& theDir) const = 0;
0280
0281
0282 virtual bool GetNormal(int theNode, gp_Dir& theDir) const = 0;
0283 };
0284
0285
0286
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
0303
0304 class gp_Dir2d;
0305
0306 class Poly_MakeLoops2D : public Poly_MakeLoops
0307 {
0308 public:
0309
0310 class Helper : public Poly_MakeLoops::Helper
0311 {
0312 public:
0313
0314
0315
0316
0317 virtual bool GetFirstTangent(const Link& theLink, gp_Dir2d& theDir) const = 0;
0318
0319
0320 virtual bool GetLastTangent(const Link& theLink, gp_Dir2d& theDir) const = 0;
0321 };
0322
0323
0324
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
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 }
0365
0366 #endif