8a065f5b7ec0cf747896e99b3dd0a77c7de9e391
[occt.git] / src / BRepLib / BRepLib_MakeWire_1.cxx
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
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
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.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17
18 #include <BRep_Builder.hxx>
19 #include <BRep_Tool.hxx>
20 #include <BRepLib.hxx>
21 #include <BRepLib_MakeWire.hxx>
22 #include <gp_Pnt.hxx>
23 #include <StdFail_NotDone.hxx>
24 #include <TopExp.hxx>
25 #include <TopExp_Explorer.hxx>
26 #include <TopoDS.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
40 //=======================================================================
41 //function : Add
42 //purpose  : Add the list of edges to the current wire
43 //=======================================================================
44 void  BRepLib_MakeWire::Add(const TopTools_ListOfShape& L)
45 {
46   myError = BRepLib_WireDone;
47   if (!myShape.IsNull()) myShape.Closed(Standard_False);
48
49   if (!L.IsEmpty()) {
50     NotDone();
51     TopTools_MapOfShape mapLocale;
52     mapLocale.Assign(myVertices);
53     TopTools_DataMapOfShapeShape toCopy;
54     TopTools_ListOfShape toAdd, nlist, rlist;
55     BRep_Builder BB;
56
57     TopExp_Explorer exv;
58     TopTools_MapIteratorOfMapOfShape itMS;
59     TopTools_ListIteratorOfListOfShape itList(L);
60     for (;itList.More(); itList.Next()) {
61       const TopoDS_Edge& curEd=TopoDS::Edge(itList.Value());
62       if (!curEd.IsNull()) {
63         rlist.Clear();
64         nlist.Clear();
65         Standard_Boolean copEd=Standard_False;
66         if (myEdge.IsNull()) {
67           Add(curEd);
68           if (!VF.IsNull()) mapLocale.Add(VF);
69           if (!VL.IsNull()) mapLocale.Add(VL);
70           NotDone();
71           continue;
72         }
73         for (exv.Init(curEd, TopAbs_VERTEX); exv.More(); exv.Next()) {
74           const TopoDS_Vertex& edVer=TopoDS::Vertex(exv.Current());
75           rlist.Prepend(edVer);
76           nlist.Prepend(edVer);
77           if (!mapLocale.Contains(edVer)) {
78             Standard_Boolean notYetFound = Standard_True;
79             Standard_Real gap=BRep_Tool::Tolerance(edVer);
80             gp_Pnt pVer=BRep_Tool::Pnt(edVer);
81             for (itMS.Initialize(mapLocale); itMS.More(); itMS.Next()) {
82               notYetFound=Standard_True;
83               const TopoDS_Vertex& refVer=TopoDS::Vertex(itMS.Key());
84               gap +=BRep_Tool::Tolerance(refVer);
85               if (pVer.Distance(BRep_Tool::Pnt(TopoDS::Vertex(refVer))) <= gap) {
86                 nlist.RemoveFirst();
87                 nlist.Prepend(refVer.Oriented(edVer.Orientation()));
88                 copEd=Standard_True;
89                 notYetFound=Standard_False;
90                 break;
91               }
92             }
93             if (notYetFound) mapLocale.Add(edVer);
94           }
95         }
96         if (copEd) {
97           TopoDS_Shape aLocalShape = curEd.EmptyCopied();
98           TopoDS_Edge newEd=TopoDS::Edge(aLocalShape);
99 //        TopoDS_Edge newEd=TopoDS::Edge(curEd.EmptyCopied());
100           BB.Transfert(curEd, newEd);
101           TopTools_ListIteratorOfListOfShape itV(nlist);
102           for (; itV.More(); itV.Next()) {
103             BB.Add(newEd, itV.Value());
104             BB.Transfert(curEd, newEd, TopoDS::Vertex(rlist.First()), TopoDS::Vertex(itV.Value()));
105             rlist.RemoveFirst();
106           }
107           toAdd.Append(newEd);
108         }
109         else {
110           toAdd.Append(curEd);
111         }
112       }
113     }
114     if (!toAdd.IsEmpty()) {
115       TopoDS_Compound comp;
116       BB.MakeCompound(comp);
117       TopTools_MapIteratorOfMapOfOrientedShape itMOS;
118       TopTools_MapOfOrientedShape theEdges;
119       for (itList.Initialize(toAdd); itList.More(); itList.Next()) {
120         BB.Add(comp, itList.Value());
121         theEdges.Add(itList.Value());
122       }
123       TopTools_IndexedDataMapOfShapeListOfShape lesMeres;
124       TopExp::MapShapesAndAncestors(comp, TopAbs_VERTEX, TopAbs_EDGE, lesMeres);
125       TopoDS_Vertex vf, vl;
126       TopoDS_Shape theKey;
127       Standard_Boolean usedVertex;
128       Standard_Boolean closedEdge = Standard_False;
129       Standard_Integer vvInd, lastInd;
130       do {
131         if (!VL.IsNull() && lesMeres.Contains(VL)) {
132           if (!VF.IsNull()) closedEdge=VF.IsSame(VL);
133           usedVertex=Standard_True;
134           for (itList.Initialize(lesMeres.FindFromKey(VL)); itList.More(); itList.Next()) {
135             if (theEdges.Contains(itList.Value())) {
136               usedVertex=Standard_False;
137               theEdges.Remove(itList.Value());
138               TopExp::Vertices(TopoDS::Edge(itList.Value()), vf,vl);
139               if (vf.IsSame(VL)) {
140                 BB.Add(myShape, itList.Value());
141                 myVertices.Add(vl);
142                 VL=vl;
143               }
144               else {
145                 if (closedEdge) {
146                   BB.Add(myShape, itList.Value());
147                   VF=vf;
148                 }
149                 else {
150                   BB.Add(myShape, itList.Value().Reversed());
151                   vf.Reverse();
152                   VL=vf;
153                 }
154                 myVertices.Add(vf);
155               }
156             }
157           }
158           if (usedVertex) {
159             lastInd=lesMeres.Extent();
160             vvInd=lesMeres.FindIndex(VL);
161             if (vvInd != lastInd) {
162               theKey=lesMeres.FindKey(lastInd);
163               nlist=lesMeres.FindFromIndex(lastInd);
164             }
165             lesMeres.RemoveLast();
166             if (vvInd != lastInd) {
167               lesMeres.Substitute(vvInd, theKey, nlist);
168             }
169           }
170         }
171         else if (!VF.IsNull() && lesMeres.Contains(VF)) {
172           usedVertex=Standard_True;
173           for (itList.Initialize(lesMeres.FindFromKey(VF)); itList.More(); itList.Next()) {
174             if (theEdges.Contains(itList.Value())) {
175               usedVertex=Standard_False;
176               theEdges.Remove(itList.Value());
177               TopExp::Vertices(TopoDS::Edge(itList.Value()), vf,vl);
178               if (vl.IsSame(VF)) {
179                 BB.Add(myShape, itList.Value());
180                 myVertices.Add(vf);
181                 VF=vf;
182               }
183               else {
184                 BB.Add(myShape, itList.Value().Reversed());
185                 vl.Reverse();
186                 myVertices.Add(vl);
187                 VF=vl;
188               }
189             }
190           }
191           if (usedVertex) {
192             lastInd=lesMeres.Extent();
193             vvInd=lesMeres.FindIndex(VF);
194             if (vvInd != lastInd) {
195               theKey=lesMeres.FindKey(lastInd);
196               nlist=lesMeres.FindFromIndex(lastInd);
197             }
198             lesMeres.RemoveLast();
199             if (vvInd != lastInd) {
200               lesMeres.Substitute(vvInd, theKey, nlist);
201             }
202           }
203         }
204         else {
205           if (theEdges.Extent()>0) {
206             Standard_Boolean noCandidat=Standard_True;
207             for (itMOS.Initialize(theEdges); itMOS.More(); itMOS.Next()) {
208               TopExp::Vertices(TopoDS::Edge(itMOS.Key()), vf,vl);
209               if (myVertices.Contains(vl)) {
210                 if (myError==BRepLib_WireDone)  myError = BRepLib_NonManifoldWire;
211                 BB.Add(myShape, itMOS.Key());
212                 myVertices.Add(vf);
213                 VF=vf;
214                 noCandidat=Standard_False;
215                 break;
216               }
217               else if (myVertices.Contains(vf)) {
218                 if (myError==BRepLib_WireDone)  myError = BRepLib_NonManifoldWire;
219                 BB.Add(myShape, itMOS.Key());
220                 myVertices.Add(vl);
221                 VL=vl;
222                 noCandidat=Standard_False;
223                 break;
224               }
225             }
226             if (noCandidat) {
227               theEdges.Clear();
228 // Some Edges are not connected to first edge and the diagnosis is as follows
229 // but the "Maker" is Done() because otherwise it is not possible to return the constructed connected part...
230               myError=BRepLib_DisconnectedWire;
231             }
232             else theEdges.Remove(itMOS.Key());
233           }
234         }
235       } while (theEdges.Extent()>0);
236     }
237   }
238
239   if (!VF.IsNull() && !VL.IsNull() && VF.IsSame(VL))
240     myShape.Closed(Standard_True);  
241   Done();
242 }