1 // Created on: 1998-05-20
2 // Created by: Didier PIFFAULT
3 // Copyright (c) 1998-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
18 #include <BRep_Builder.hxx>
19 #include <BRep_Tool.hxx>
20 #include <BRepLib.hxx>
21 #include <BRepLib_MakeWire.hxx>
23 #include <StdFail_NotDone.hxx>
25 #include <TopExp_Explorer.hxx>
27 #include <TopoDS_Compound.hxx>
28 #include <TopoDS_Edge.hxx>
29 #include <TopoDS_Vertex.hxx>
30 #include <TopoDS_Wire.hxx>
31 #include <TopTools_DataMapOfShapeShape.hxx>
32 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
33 #include <TopTools_ListIteratorOfListOfShape.hxx>
34 #include <TopTools_ListOfShape.hxx>
35 #include <TopTools_MapIteratorOfMapOfOrientedShape.hxx>
36 #include <TopTools_MapIteratorOfMapOfShape.hxx>
37 #include <TopTools_MapOfOrientedShape.hxx>
38 #include <TopTools_MapOfShape.hxx>
39 #include <NCollection_UBTreeFiller.hxx>
40 #include <BRepBndLib.hxx>
41 #include <BRepLib_MakeVertex.hxx>
43 //=======================================================================
45 //purpose : Add the list of edges to the current wire
46 //=======================================================================
47 void BRepLib_MakeWire::Add(const TopTools_ListOfShape& L)
49 myError = BRepLib_WireDone;
50 Standard_Integer aLSize = 0;
51 Standard_Integer aRefSize = L.Size();
55 NCollection_List<NCollection_List<TopoDS_Vertex>> aGrVL;
57 TopTools_IndexedDataMapOfShapeListOfShape aMapVE;
59 CollectCoincidentVertices(L, aGrVL);
61 TopTools_DataMapOfShapeShape anO2NV;
63 CreateNewVertices(aGrVL, anO2NV);
65 TopTools_ListOfShape aNewEList;
67 CreateNewListOfEdges(L, anO2NV, aNewEList);
70 TopExp::MapShapesAndAncestors(myShape, TopAbs_VERTEX, TopAbs_EDGE, aMapVE);
72 TopTools_MapOfShape aProcessedEdges;
73 TopExp_Explorer anExp;
75 TopTools_ListOfShape anActEdges, aNeighEdges;
79 //take the first edge from the list and add it
80 const TopoDS_Edge& aFE = TopoDS::Edge(aNewEList.First());
82 aProcessedEdges.Add(aFE);
83 anActEdges.Append(aFE);
88 //existing edges are already connected
89 for (anExp.Init(myShape, TopAbs_EDGE); anExp.More(); anExp.Next())
91 const TopoDS_Shape& aCSh = anExp.Current();
92 aProcessedEdges.Add(aCSh);
93 anActEdges.Append(aCSh);
97 TopTools_ListIteratorOfListOfShape anItL1, anItL2;
99 for (anItL1.Initialize(aNewEList); anItL1.More(); anItL1.Next())
100 TopExp::MapShapesAndAncestors(anItL1.Value(), TopAbs_VERTEX, TopAbs_EDGE, aMapVE);
102 while (!anActEdges.IsEmpty())
104 anItL2.Initialize(anActEdges);
105 for (;anItL2.More(); anItL2.Next())
107 const TopoDS_Shape& aCE = anItL2.Value();
108 anExp.Init(aCE, TopAbs_VERTEX);
109 for (;anExp.More(); anExp.Next())
111 const TopoDS_Shape& aCV = anExp.Current();
112 for (anItL1.Initialize(aMapVE.FindFromKey(aCV)); anItL1.More(); anItL1.Next())
114 const TopoDS_Shape& aNE = anItL1.Value(); //neighbor edge
115 if (!aProcessedEdges.Contains(aNE))
117 Add(TopoDS::Edge(aNE), Standard_False);
118 aNeighEdges.Append(aNE);
119 aProcessedEdges.Add(aNE);
126 anActEdges.Append(aNeighEdges);
129 if (aLSize == aRefSize)
134 myError = BRepLib_DisconnectedWire;
138 //=======================================================================
141 //=======================================================================
142 Standard_Boolean BRepLib_MakeWire::BRepLib_BndBoxVertexSelector::
143 Accept (const Standard_Integer& theObj)
145 if (theObj > myMapOfShape.Extent())
146 return Standard_False;
148 const TopoDS_Vertex& aV = TopoDS::Vertex(myMapOfShape(theObj));
150 if (theObj == myVInd)
151 return Standard_False;
153 gp_Pnt aVPnt = BRep_Tool::Pnt(aV);
155 Standard_Real aTolV = BRep_Tool::Tolerance(aV);
157 Standard_Real aL = myP.SquareDistance(aVPnt);
158 Standard_Real aSTol = aTolV + myTolP;
163 myResultInd.Append(theObj);
164 return Standard_True;
167 return Standard_False;
170 //=======================================================================
171 //function : SetCurrentVertex
173 //=======================================================================
174 void BRepLib_MakeWire::BRepLib_BndBoxVertexSelector::
175 SetCurrentVertex (const gp_Pnt& theP, Standard_Real theTol,
176 Standard_Integer theVInd)
180 myVBox.Enlarge(theTol);
185 //=======================================================================
186 //function : CollectCoincidentVertices
188 //=======================================================================
189 void BRepLib_MakeWire::CollectCoincidentVertices(const TopTools_ListOfShape& theL,
190 NCollection_List<NCollection_List<TopoDS_Vertex>>& theGrVL)
192 TopTools_IndexedMapOfShape anAllV;
193 TopTools_IndexedDataMapOfShapeListOfShape aMV2EL;
195 TopExp::MapShapes(myShape, TopAbs_VERTEX, anAllV);
197 TopTools_ListIteratorOfListOfShape anItL(theL);
198 for (; anItL.More(); anItL.Next())
199 TopExp::MapShapes(anItL.Value(), TopAbs_VERTEX, anAllV);
201 //aV2CV : vertex <-> its coincident vertices
202 NCollection_DataMap<TopoDS_Vertex, NCollection_Map<TopoDS_Vertex>> aV2CV;
203 NCollection_UBTree <Standard_Integer, Bnd_Box> aTree;
204 NCollection_UBTreeFiller <Standard_Integer, Bnd_Box> aTreeFiller (aTree);
205 NCollection_Map<TopoDS_Vertex> aNonGroupedV;
207 /// add vertices from anAllV to treefiller
208 for (Standard_Integer i = 1; i <= anAllV.Extent(); i++)
210 const TopoDS_Shape& aSh = anAllV(i);
212 BRepBndLib::Add(aSh, aBB);
213 aTreeFiller.Add(i, aBB);
217 BRepLib_BndBoxVertexSelector aSelector(anAllV);
219 Standard_Integer aNbColl = 0;
220 NCollection_List<Standard_Integer>::Iterator itI;
221 for (Standard_Integer i = 1; i <= anAllV.Extent(); i++ )
223 const TopoDS_Vertex& aV = TopoDS::Vertex(anAllV(i));
224 if (myVertices.Contains(aV))
226 aSelector.SetCurrentVertex(BRep_Tool::Pnt(aV), BRep_Tool::Tolerance(aV), i );
227 aNbColl = aTree.Select(aSelector);
230 const NCollection_List<Standard_Integer>& aResInds = aSelector.GetResultInds();
231 NCollection_Map<TopoDS_Vertex>* aVM =
232 aV2CV.Bound(aV, NCollection_Map<TopoDS_Vertex>());
233 for (itI.Initialize(aResInds); itI.More(); itI.Next() )
235 const TopoDS_Vertex& aCV = TopoDS::Vertex(anAllV(itI.Value()));
237 if (myVertices.Contains(aCV))
239 if (aV2CV.IsBound(aCV))
243 aV2CV.Bound(aCV, NCollection_Map<TopoDS_Vertex>())->Add(aV);
244 aNonGroupedV.Add(aCV);
249 aNonGroupedV.Add(aV); //vertexes to be grouped; store only coincident vertices
251 aSelector.ClearResInds();
255 /// group the coincident vertices
256 NCollection_Map<TopoDS_Vertex>::Iterator itMV;
257 NCollection_List<TopoDS_Vertex> aStartV, aCurrentV, anOneGrV;
258 NCollection_List<TopoDS_Vertex>::Iterator itLV;
259 Standard_Boolean IsStartNewGroup = Standard_True;
260 while(!aNonGroupedV.IsEmpty() || !IsStartNewGroup)
261 //exit only if there are no nongrouped vertices
262 //and the last group are fully are constructed
266 //start list of vertices is empty => append one from aNonGroupedV
267 // and remove it from it (i.e. mark as grouped)
268 itMV.Initialize(aNonGroupedV);
269 const TopoDS_Vertex& aCurV = itMV.Value();
270 aStartV.Append(aCurV);
271 aNonGroupedV.Remove(aCurV);
274 for (;itLV.More();itLV.Next())
276 const TopoDS_Vertex& aSV = itLV.Value();
277 anOneGrV.Append(aSV);
278 itMV.Initialize(aV2CV(aSV));
279 for (;itMV.More();itMV.Next())
281 const TopoDS_Vertex& aCV = itMV.Value();
282 if (aNonGroupedV.Contains(aCV))
284 aCurrentV.Append(aCV);
285 aNonGroupedV.Remove(aCV);
290 aStartV.Append(aCurrentV);
291 IsStartNewGroup = aStartV.IsEmpty();
292 if (IsStartNewGroup && !anOneGrV.IsEmpty())
294 theGrVL.Append(anOneGrV);
300 //=======================================================================
301 //function : CreateNewVertices
303 //=======================================================================
304 void BRepLib_MakeWire::CreateNewVertices(const NCollection_List<NCollection_List<TopoDS_Vertex>>& theGrVL,
305 TopTools_DataMapOfShapeShape& theO2NV)
307 //map [old vertex => new vertex]
308 //note that already existing shape (i.e. the original ones)
309 //shouldnt be modified on the topological level
310 NCollection_List<NCollection_List<TopoDS_Vertex>>::Iterator itLLV;
311 NCollection_List<TopoDS_Vertex>::Iterator itLV;
314 for (;itLLV.More();itLLV.Next())
317 NCollection_List<TopoDS_Shape> aValList;
318 const NCollection_List<TopoDS_Vertex>& aVal = itLLV.Value();
319 itLV.Initialize(aVal);
320 Standard_Real aNewTol = 0;
322 for (;itLV.More();itLV.Next())
324 const TopoDS_Vertex& aVV = itLV.Value();
325 aValList.Append(aVV);
326 if (myVertices.Contains(aVV))
329 BRepLib::BoundingVertex(aValList, aNewC, aNewTol);
333 //vertices from the original shape isnt found in this group
334 //create the new vertex
335 aNewV = BRepLib_MakeVertex(aNewC);
336 aBB.UpdateVertex(aNewV, aNewTol);
339 //update already existing vertex
340 aBB.UpdateVertex(aNewV, gp_Pnt(aNewC), aNewTol);
342 //fill the map of old->new vertices
343 itLV.Initialize(aVal);
344 for (;itLV.More();itLV.Next())
346 const TopoDS_Vertex& aVV = itLV.Value();
347 theO2NV.Bind(aVV, aNewV);
352 //=======================================================================
353 //function : CreateNewListOfEdges
355 //=======================================================================
356 void BRepLib_MakeWire::CreateNewListOfEdges(const TopTools_ListOfShape& theL,
357 const TopTools_DataMapOfShapeShape& theO2NV,
358 TopTools_ListOfShape& theNewEList)
360 ///create the new list (theNewEList) from the input list L
361 Standard_Boolean IsNewEdge;
362 NCollection_List<TopoDS_Vertex> aVList;
365 TopTools_ListIteratorOfListOfShape anItL;
366 for (anItL.Initialize(theL); anItL.More(); anItL.Next())
368 IsNewEdge = Standard_False;
370 const TopoDS_Edge& aCE = TopoDS::Edge(anItL.Value());
371 exp.Init(aCE, TopAbs_VERTEX);
372 for (;exp.More(); exp.Next())
374 const TopoDS_Vertex& aVal = TopoDS::Vertex(exp.Current());
375 if (theO2NV.IsBound(aVal))
377 IsNewEdge = Standard_True;
378 //append the new vertex
379 aVList.Append(TopoDS::Vertex(theO2NV(aVal).Oriented(aVal.Orientation())));
386 TopoDS_Shape NewE = aCE.EmptyCopied();
387 NCollection_List<TopoDS_Edge>::Iterator it(aVList);
388 for (; it.More(); it.Next())
389 aBB.Add(NewE, it.Value());
390 theNewEList.Append(TopoDS::Edge(NewE));
393 theNewEList.Append(aCE);