0023404: Create SquareConfusion function in Precision package for speed and convenience
[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-2012 OPEN CASCADE SAS
5 //
6 // The content of this file is subject to the Open CASCADE Technology Public
7 // License Version 6.5 (the "License"). You may not use the content of this file
8 // except in compliance with the License. Please obtain a copy of the License
9 // at http://www.opencascade.org and read it completely before using this file.
10 //
11 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13 //
14 // The Original Code and all software distributed under the License is
15 // distributed on an "AS IS" basis, without warranty of any kind, and the
16 // Initial Developer hereby disclaims all such warranties, including without
17 // limitation, any warranties of merchantability, fitness for a particular
18 // purpose or non-infringement. Please see the License for the specific terms
19 // and conditions governing the rights and limitations under the License.
20
21
22
23 #include <BRepLib_MakeWire.ixx>
24 #include <BRepLib.hxx>
25 #include <TopTools_MapOfShape.hxx>
26 #include <TopTools_MapOfOrientedShape.hxx>
27 #include <TopTools_MapIteratorOfMapOfShape.hxx>
28 #include <TopTools_MapIteratorOfMapOfOrientedShape.hxx>
29 #include <TopTools_DataMapOfShapeShape.hxx>
30 #include <TopTools_ListOfShape.hxx>
31 #include <TopTools_ListIteratorOfListOfShape.hxx>
32 #include <BRep_Builder.hxx>
33 #include <TopExp.hxx>
34 #include <TopExp_Explorer.hxx>
35 #include <TopoDS.hxx>
36 #include <TopoDS_Vertex.hxx>
37 #include <TopoDS_Edge.hxx>
38 #include <TopoDS_Compound.hxx>
39 #include <BRep_Tool.hxx>
40 #include <gp_Pnt.hxx>
41 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
42
43
44 //=======================================================================
45 //function : Add
46 //purpose  : Add the list of edges to the current wire
47 //=======================================================================
48
49 void  BRepLib_MakeWire::Add(const TopTools_ListOfShape& L)
50 {
51   myError = BRepLib_WireDone;
52   if (!myShape.IsNull()) myShape.Closed(Standard_False);
53
54   if (!L.IsEmpty()) {
55     NotDone();
56     TopTools_MapOfShape mapLocale;
57     mapLocale.Assign(myVertices);
58     TopTools_DataMapOfShapeShape toCopy;
59     TopTools_ListOfShape toAdd, nlist, rlist;
60     BRep_Builder BB;
61
62     TopExp_Explorer exv;
63     TopTools_MapIteratorOfMapOfShape itMS;
64     TopTools_ListIteratorOfListOfShape itList(L);
65     for (;itList.More(); itList.Next()) {
66       const TopoDS_Edge& curEd=TopoDS::Edge(itList.Value());
67       if (!curEd.IsNull()) {
68         rlist.Clear();
69         nlist.Clear();
70         Standard_Boolean copEd=Standard_False;
71         if (myEdge.IsNull()) {
72           Add(curEd);
73           if (!VF.IsNull()) mapLocale.Add(VF);
74           if (!VL.IsNull()) mapLocale.Add(VL);
75           NotDone();
76           continue;
77         }
78         for (exv.Init(curEd, TopAbs_VERTEX); exv.More(); exv.Next()) {
79           const TopoDS_Vertex& edVer=TopoDS::Vertex(exv.Current());
80           rlist.Prepend(edVer);
81           nlist.Prepend(edVer);
82           if (!mapLocale.Contains(edVer)) {
83 #ifndef DEB
84             Standard_Boolean notYetFound = Standard_True;
85 #else
86             Standard_Boolean notYetFound;
87 #endif
88             Standard_Real gap=BRep_Tool::Tolerance(edVer);
89             gp_Pnt pVer=BRep_Tool::Pnt(edVer);
90             for (itMS.Initialize(mapLocale); itMS.More(); itMS.Next()) {
91               notYetFound=Standard_True;
92               const TopoDS_Vertex& refVer=TopoDS::Vertex(itMS.Key());
93               gap +=BRep_Tool::Tolerance(refVer);
94               if (pVer.Distance(BRep_Tool::Pnt(TopoDS::Vertex(refVer))) <= gap) {
95                 nlist.RemoveFirst();
96                 nlist.Prepend(refVer.Oriented(edVer.Orientation()));
97                 copEd=Standard_True;
98                 notYetFound=Standard_False;
99                 break;
100               }
101             }
102             if (notYetFound) mapLocale.Add(edVer);
103           }
104         }
105         if (copEd) {
106           TopoDS_Shape aLocalShape = curEd.EmptyCopied();
107           TopoDS_Edge newEd=TopoDS::Edge(aLocalShape);
108 //        TopoDS_Edge newEd=TopoDS::Edge(curEd.EmptyCopied());
109           BB.Transfert(curEd, newEd);
110           newEd.Closed(curEd.Closed());
111           TopTools_ListIteratorOfListOfShape itV(nlist);
112           for (; itV.More(); itV.Next()) {
113             BB.Add(newEd, itV.Value());
114             BB.Transfert(curEd, newEd, TopoDS::Vertex(rlist.First()), TopoDS::Vertex(itV.Value()));
115             rlist.RemoveFirst();
116           }
117           toAdd.Append(newEd);
118         }
119         else {
120           toAdd.Append(curEd);
121         }
122       }
123     }
124     if (!toAdd.IsEmpty()) {
125       TopoDS_Compound comp;
126       BB.MakeCompound(comp);
127       TopTools_MapIteratorOfMapOfOrientedShape itMOS;
128       TopTools_MapOfOrientedShape theEdges;
129       for (itList.Initialize(toAdd); itList.More(); itList.Next()) {
130         BB.Add(comp, itList.Value());
131         theEdges.Add(itList.Value());
132       }
133       TopTools_IndexedDataMapOfShapeListOfShape lesMeres;
134       TopExp::MapShapesAndAncestors(comp, TopAbs_VERTEX, TopAbs_EDGE, lesMeres);
135       TopoDS_Vertex vf, vl;
136       TopoDS_Shape theKey;
137       Standard_Boolean usedVertex;
138 #ifndef DEB
139       Standard_Boolean closedEdge = Standard_False;
140 #else
141       Standard_Boolean closedEdge;
142 #endif
143       Standard_Integer vvInd, lastInd;
144       do {
145         if (!VL.IsNull() && lesMeres.Contains(VL)) {
146           if (!VF.IsNull()) closedEdge=VF.IsSame(VL);
147           usedVertex=Standard_True;
148           for (itList.Initialize(lesMeres.FindFromKey(VL)); itList.More(); itList.Next()) {
149             if (theEdges.Contains(itList.Value())) {
150               usedVertex=Standard_False;
151               theEdges.Remove(itList.Value());
152               TopExp::Vertices(TopoDS::Edge(itList.Value()), vf,vl);
153               if (vf.IsSame(VL)) {
154                 BB.Add(myShape, itList.Value());
155                 myVertices.Add(vl);
156                 VL=vl;
157               }
158               else {
159                 if (closedEdge) {
160                   BB.Add(myShape, itList.Value());
161                   VF=vf;
162                 }
163                 else {
164                   BB.Add(myShape, itList.Value().Reversed());
165                   vf.Reverse();
166                   VL=vf;
167                 }
168                 myVertices.Add(vf);
169               }
170             }
171           }
172           if (usedVertex) {
173             lastInd=lesMeres.Extent();
174             vvInd=lesMeres.FindIndex(VL);
175             if (vvInd != lastInd) {
176               theKey=lesMeres.FindKey(lastInd);
177               nlist=lesMeres.FindFromIndex(lastInd);
178             }
179             lesMeres.RemoveLast();
180             if (vvInd != lastInd) {
181               lesMeres.Substitute(vvInd, theKey, nlist);
182             }
183           }
184         }
185         else if (!VF.IsNull() && lesMeres.Contains(VF)) {
186           usedVertex=Standard_True;
187           for (itList.Initialize(lesMeres.FindFromKey(VF)); itList.More(); itList.Next()) {
188             if (theEdges.Contains(itList.Value())) {
189               usedVertex=Standard_False;
190               theEdges.Remove(itList.Value());
191               TopExp::Vertices(TopoDS::Edge(itList.Value()), vf,vl);
192               if (vl.IsSame(VF)) {
193                 BB.Add(myShape, itList.Value());
194                 myVertices.Add(vf);
195                 VF=vf;
196               }
197               else {
198                 BB.Add(myShape, itList.Value().Reversed());
199                 vl.Reverse();
200                 myVertices.Add(vl);
201                 VF=vl;
202               }
203             }
204           }
205           if (usedVertex) {
206             lastInd=lesMeres.Extent();
207             vvInd=lesMeres.FindIndex(VF);
208             if (vvInd != lastInd) {
209               theKey=lesMeres.FindKey(lastInd);
210               nlist=lesMeres.FindFromIndex(lastInd);
211             }
212             lesMeres.RemoveLast();
213             if (vvInd != lastInd) {
214               lesMeres.Substitute(vvInd, theKey, nlist);
215             }
216           }
217         }
218         else {
219           if (theEdges.Extent()>0) {
220             Standard_Boolean noCandidat=Standard_True;
221             for (itMOS.Initialize(theEdges); itMOS.More(); itMOS.Next()) {
222               TopExp::Vertices(TopoDS::Edge(itMOS.Key()), vf,vl);
223               if (myVertices.Contains(vl)) {
224                 if (myError==BRepLib_WireDone)  myError = BRepLib_NonManifoldWire;
225                 BB.Add(myShape, itMOS.Key());
226                 myVertices.Add(vf);
227                 VF=vf;
228                 noCandidat=Standard_False;
229                 break;
230               }
231               else if (myVertices.Contains(vf)) {
232                 if (myError==BRepLib_WireDone)  myError = BRepLib_NonManifoldWire;
233                 BB.Add(myShape, itMOS.Key());
234                 myVertices.Add(vl);
235                 VL=vl;
236                 noCandidat=Standard_False;
237                 break;
238               }
239             }
240             if (noCandidat) {
241               theEdges.Clear();
242 // Some Edges are not connected to first edge and the diagnosis is as follows
243 // but the "Maker" is Done() because otherwise it is not possible to return the constructed connected part...
244               myError=BRepLib_DisconnectedWire;
245             }
246             else theEdges.Remove(itMOS.Key());
247           }
248         }
249       } while (theEdges.Extent()>0);
250     }
251   }
252
253   if (!VF.IsNull() && !VL.IsNull() && VF.IsSame(VL))
254     myShape.Closed(Standard_True);  
255   Done();
256 }