0024157: Parallelization of assembly part of BO
[occt.git] / src / ShapeAnalysis / ShapeAnalysis_FreeBounds.cxx
1 // Created on: 1998-04-27
2 // Created by: Roman LYGIN
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 // Modified:    Thu Sep 17 12:27:58 1998
22 // 25.12.98 pdn transmission from BRepTools_Sewing to BRepBuilderAPI_Sewing
23 //szv#4 S4163
24 // 11.01.00 svv #1: porting on DEC  
25
26 #include <ShapeAnalysis_FreeBounds.ixx>
27
28 #include <BRep_Builder.hxx>
29 #include <BRep_Tool.hxx>
30 #include <BRepBuilderAPI_Sewing.hxx>
31
32 #include <Precision.hxx>
33
34 #include <TopoDS.hxx>
35 #include <TopoDS_Vertex.hxx>
36 #include <TopoDS_Wire.hxx>
37 #include <TopoDS_Edge.hxx>
38 #include <TopoDS_Iterator.hxx>
39
40 #include <TColStd_Array1OfBoolean.hxx>
41 #include <TColStd_Array1OfInteger.hxx>
42 #include <TColStd_SequenceOfInteger.hxx>
43
44 #include <ShapeExtend_WireData.hxx>
45 #include <ShapeExtend_Explorer.hxx>
46 #include <ShapeBuild_Vertex.hxx>
47 #include <ShapeBuild_Edge.hxx>
48 #include <ShapeAnalysis.hxx>
49 #include <ShapeAnalysis_Edge.hxx>
50 #include <ShapeAnalysis_Wire.hxx>
51 #include <ShapeAnalysis_Shell.hxx>
52
53 #include <gp_Pnt.hxx> //ied_modif_for_compil_Nov-19-1998
54 #include <TopExp_Explorer.hxx>
55 #include <TopTools_MapOfShape.hxx>
56 #include <TopTools_MapIteratorOfMapOfShape.hxx>
57 #include <TopoDS_Shell.hxx>
58 #include <ShapeAnalysis_BoxBndTree.hxx>
59 #include <NCollection_UBTreeFiller.hxx>
60 #include <TColStd_ListIteratorOfListOfInteger.hxx>
61 #include <TopTools_HArray1OfShape.hxx>
62 #include <TopExp.hxx>
63
64 //=======================================================================
65 //function : ShapeAnalysis_FreeBounds
66 //purpose  : Empty constructor
67 //=======================================================================
68
69 ShapeAnalysis_FreeBounds::ShapeAnalysis_FreeBounds() {}
70
71 //=======================================================================
72 //function : ShapeAnalysis_FreeBounds
73 //purpose  : 
74 //=======================================================================
75
76 ShapeAnalysis_FreeBounds::ShapeAnalysis_FreeBounds(const TopoDS_Shape& shape,
77                                                    const Standard_Real toler,
78                                                    const Standard_Boolean splitclosed,
79                                                    const Standard_Boolean splitopen) :
80        myTolerance (toler), myShared (Standard_False),
81        mySplitClosed (splitclosed), mySplitOpen (splitopen)
82 {
83   BRepBuilderAPI_Sewing Sew(toler, Standard_False, Standard_False);
84   for (TopoDS_Iterator S (shape); S.More(); S.Next()) Sew.Add(S.Value());
85   Sew.Perform();
86   //
87   // Extract free edges.
88   //
89   Standard_Integer nbedge = Sew.NbFreeEdges();
90   Handle(TopTools_HSequenceOfShape) edges = new TopTools_HSequenceOfShape;
91   Handle(TopTools_HSequenceOfShape) wires;
92   TopoDS_Edge anEdge;
93   for (Standard_Integer iedge = 1 ; iedge <= nbedge ; iedge++) {
94     anEdge = TopoDS::Edge (Sew.FreeEdge(iedge));
95     if ( !BRep_Tool::Degenerated(anEdge) ) edges->Append (anEdge);
96   }
97   //
98   // Chainage.
99   //
100   ConnectEdgesToWires (edges, toler, Standard_False, wires);
101   DispatchWires (wires, myWires, myEdges);
102   SplitWires ();
103   
104   return ;
105 }
106
107 //=======================================================================
108 //function : ShapeAnalysis_FreeBounds
109 //purpose  : 
110 //=======================================================================
111
112 ShapeAnalysis_FreeBounds::ShapeAnalysis_FreeBounds(const TopoDS_Shape& shape,
113                                                    const Standard_Boolean splitclosed,
114                                                    const Standard_Boolean splitopen,
115                                                    const Standard_Boolean checkinternaledges) :
116        myTolerance (0.), myShared (Standard_True),
117        mySplitClosed (splitclosed), mySplitOpen (splitopen)
118 {
119   TopoDS_Shell aTmpShell;
120   BRep_Builder aB;
121   aB.MakeShell(aTmpShell);
122   for(TopExp_Explorer aExpFace(shape,TopAbs_FACE);aExpFace.More(); aExpFace.Next())
123     aB.Add(aTmpShell,aExpFace.Current());
124   
125   ShapeAnalysis_Shell sas;
126   sas.CheckOrientedShells (aTmpShell, Standard_True, checkinternaledges);
127   
128   if (sas.HasFreeEdges()) {
129     ShapeExtend_Explorer see;
130     Handle(TopTools_HSequenceOfShape) edges = see.SeqFromCompound (sas.FreeEdges(), Standard_False);
131   
132     Handle(TopTools_HSequenceOfShape) wires;
133     ConnectEdgesToWires (edges, Precision::Confusion(), Standard_True, wires);
134     DispatchWires (wires, myWires, myEdges);
135     SplitWires ();
136   }
137   
138   
139 }
140
141 //=======================================================================
142 //function : ConnectEdgesToWires
143 //purpose  : 
144 //=======================================================================
145
146  void ShapeAnalysis_FreeBounds::ConnectEdgesToWires(Handle(TopTools_HSequenceOfShape)& edges,
147                                                     const Standard_Real toler,
148                                                     const Standard_Boolean shared,
149                                                     Handle(TopTools_HSequenceOfShape)& wires) 
150 {
151   Handle(TopTools_HSequenceOfShape) iwires = new TopTools_HSequenceOfShape;
152   BRep_Builder B;
153   
154   Standard_Integer i; // svv #1
155   for (i = 1; i <= edges->Length(); i++) {
156     TopoDS_Wire wire;
157     B.MakeWire (wire);
158     B.Add (wire, edges->Value (i));
159     iwires->Append (wire);
160   }
161
162   ConnectWiresToWires (iwires, toler, shared, wires);
163
164   for (i = 1; i <= edges->Length(); i++)
165     if (iwires->Value(i).Orientation() == TopAbs_REVERSED)
166       edges->ChangeValue(i).Reverse();
167 }
168
169 //=======================================================================
170 //function : ConnectWiresToWires
171 //purpose  : 
172 //=======================================================================
173
174  void ShapeAnalysis_FreeBounds::ConnectWiresToWires(Handle(TopTools_HSequenceOfShape)& iwires,
175                                                     const Standard_Real toler,
176                                                     const Standard_Boolean shared,
177                                                     Handle(TopTools_HSequenceOfShape)& owires) 
178 {
179   TopTools_DataMapOfShapeShape map;
180   ConnectWiresToWires (iwires, toler, shared, owires, map);
181 }
182
183 //=======================================================================
184 //function : ConnectWiresToWires
185 //purpose  : 
186 //=======================================================================
187
188  void ShapeAnalysis_FreeBounds::ConnectWiresToWires(Handle(TopTools_HSequenceOfShape)& iwires,
189                                                     const Standard_Real toler,
190                                                     const Standard_Boolean shared,
191                                                     Handle(TopTools_HSequenceOfShape)& owires,
192                                                     TopTools_DataMapOfShapeShape& vertices) 
193 {
194   if (iwires.IsNull() || !iwires->Length()) return;
195   Handle(TopTools_HArray1OfShape) arrwires = new TopTools_HArray1OfShape(1, iwires->Length());
196   //amv
197   Standard_Integer i;
198   for (i = 1; i <= arrwires->Length(); i++)
199     arrwires->SetValue(i, iwires->Value(i));
200   owires = new TopTools_HSequenceOfShape;
201   Standard_Real tolerance = Max (toler, Precision::Confusion());
202   
203   Handle(ShapeExtend_WireData)
204     sewd = new ShapeExtend_WireData (TopoDS::Wire (arrwires->Value (1)));
205
206   Handle(ShapeAnalysis_Wire) saw = new ShapeAnalysis_Wire;
207   saw->Load (sewd);
208   saw->SetPrecision (tolerance);
209
210   ShapeAnalysis_BoxBndTree aBBTree;
211   NCollection_UBTreeFiller <Standard_Integer, Bnd_Box> aTreeFiller(aBBTree);
212   ShapeAnalysis_BoxBndTreeSelector aSel(arrwires, shared);
213   aSel.LoadList(1);
214  
215   for (Standard_Integer inbW = 2; inbW <= arrwires->Length(); inbW++){
216     TopoDS_Wire trW = TopoDS::Wire (arrwires->Value (inbW));
217     Bnd_Box aBox;
218     TopoDS_Vertex trV1, trV2;
219     ShapeAnalysis::FindBounds (trW, trV1, trV2);
220     gp_Pnt trP1 = BRep_Tool::Pnt(trV1);
221     gp_Pnt trP2 = BRep_Tool::Pnt(trV2);
222     aBox.Set(trP1);
223     aBox.Add(trP2);
224     aBox.SetGap(tolerance);
225     aTreeFiller.Add(inbW, aBox);
226   }
227   Standard_Integer nbFill;
228   nbFill = aTreeFiller.Fill();
229   Standard_Integer nsel;
230   
231   ShapeAnalysis_Edge sae; //szv#4:S4163:12Mar99 moved
232   Standard_Boolean done = Standard_False;
233   
234   while (!done) {
235     Standard_Boolean found = Standard_False, tail = Standard_False, direct = Standard_False;
236     Standard_Integer lwire=0;
237     aSel.SetStop();
238     Bnd_Box FVBox, LVBox;
239     TopoDS_Vertex Vf, Vl;
240     Vf = sae.FirstVertex(sewd->Edge(1));
241     Vl = sae.LastVertex(sewd->Edge(sewd->NbEdges()));
242     gp_Pnt pf, pl;
243     pf = BRep_Tool::Pnt(Vf);
244     pl = BRep_Tool::Pnt(Vl);
245     FVBox.Set(pf);
246     FVBox.SetGap(tolerance);
247     LVBox.Set(pl);
248     LVBox.SetGap(tolerance);
249     
250     aSel.DefineBoxes(FVBox, LVBox);
251     
252     if (shared)
253       aSel.DefineVertexes(Vf,Vl);
254     else{
255       aSel.DefinePnt(pf,pl);
256       aSel.SetTolerance(tolerance);
257     }
258     
259     nsel = aBBTree.Select(aSel);
260     
261     if (nsel != 0 && !aSel.LastCheckStatus(ShapeExtend_FAIL)) {
262       found = Standard_True;
263       lwire = aSel.GetNb();
264       tail    = aSel.LastCheckStatus (ShapeExtend_DONE1) ||
265                 aSel.LastCheckStatus (ShapeExtend_DONE2);
266       direct  = aSel.LastCheckStatus (ShapeExtend_DONE1) ||
267                 aSel.LastCheckStatus (ShapeExtend_DONE3);
268       aSel.LoadList(lwire);
269     }
270     
271     if (found) {
272       if (!direct) arrwires->ChangeValue(lwire).Reverse();
273       TopoDS_Wire aCurW = TopoDS::Wire (arrwires->Value (lwire));
274       Handle(ShapeExtend_WireData) acurwd = 
275         new ShapeExtend_WireData ( TopoDS::Wire (arrwires->Value (lwire)));
276       sewd->Add (acurwd, (tail ? 0 : 1));
277     }
278     else {
279       //making wire
280       //1.providing connection (see ShapeFix_Wire::FixConnected())
281       //Standard_Integer i; // svv #1
282       for (/*Standard_Integer*/ i = 1; i <= saw->NbEdges(); i++) {
283         if (saw->CheckConnected (i)) {
284           Standard_Integer n2 = i;
285           Standard_Integer n1 = (n2 > 1 ? n2 - 1 : saw->NbEdges());
286           TopoDS_Edge E1 = sewd->Edge(n1);
287           TopoDS_Edge E2 = sewd->Edge(n2);
288   
289           TopoDS_Vertex Vprev, Vfol, V; //connection vertex
290           Vprev = sae.LastVertex (E1);
291           Vfol = sae.FirstVertex (E2);
292
293           if (saw->LastCheckStatus (ShapeExtend_DONE1)) //absolutely confused
294             V = Vprev;
295           else {
296             ShapeBuild_Vertex sbv; 
297             V = sbv.CombineVertex (Vprev, Vfol);
298           }
299           vertices.Bind (Vprev, V);
300           vertices.Bind (Vfol, V);
301
302           //replace vertices to a new one
303           ShapeBuild_Edge sbe;
304           if (saw->NbEdges() < 2)
305             sewd->Set (sbe.CopyReplaceVertices (E2, V, V), n2);
306           else {
307             sewd->Set (sbe.CopyReplaceVertices (E2, V, TopoDS_Vertex()), n2);
308             if (!saw->LastCheckStatus (ShapeExtend_DONE1))
309               sewd->Set (sbe.CopyReplaceVertices (E1, TopoDS_Vertex(), V), n1);
310           }
311         }
312       }
313
314       //2.making wire
315       TopoDS_Wire wire = sewd->Wire();
316       if (!saw->CheckConnected (1) && saw->LastCheckStatus (ShapeExtend_OK))
317         wire.Closed (Standard_True);
318       owires->Append (wire);
319       sewd->Clear();
320         
321       // Recherche de la premier edge non traitee pour un autre wire.
322       //Searching for first edge for next wire
323       lwire = -1;
324       for (/*Standard_Integer*/ i = 1 ; i <= arrwires->Length() && lwire == -1; i++)
325         if (!aSel.ContWire(i)) lwire = i; //szv#4:S4163:12Mar99 optimized
326
327       if (lwire == -1) done = 1;
328       else {
329         sewd->Add (TopoDS::Wire (arrwires->Value (lwire)));
330         aSel.LoadList(lwire);
331       }
332     }
333   }
334   for ( /*Standard_Integer*/ i = 1; i <= iwires->Length(); i++)
335     iwires->SetValue (i, arrwires->Value(i));
336 }
337
338 static void SplitWire(const TopoDS_Wire& wire,
339                       const Standard_Real toler,
340                       const Standard_Boolean shared,
341                       Handle(TopTools_HSequenceOfShape)& closed,
342                       Handle(TopTools_HSequenceOfShape)& open) 
343 {
344   closed = new TopTools_HSequenceOfShape;
345   open   = new TopTools_HSequenceOfShape;
346   Standard_Real tolerance = Max (toler, Precision::Confusion());
347
348   BRep_Builder B;
349   ShapeAnalysis_Edge sae;
350   
351   Handle(ShapeExtend_WireData) sewd = new ShapeExtend_WireData (wire);
352   Standard_Integer nbedges = sewd->NbEdges();
353
354   //ConnectedEdgeSequence - list of indices of connected edges to build a wire
355   TColStd_SequenceOfInteger ces;
356   //statuses - array of flags describing the edge:
357   //0-free, 1-in CES, 2-already in wire,
358   //3-no closed wire can be produced starting at this edge
359   TColStd_Array1OfInteger statuses (1, nbedges); 
360   statuses.Init (0);
361
362   //building closed wires
363   Standard_Integer i; // svv #1
364   for (i = 1; i <= nbedges; i++)
365     if (statuses.Value (i) == 0) {
366       ces.Append (i); statuses.SetValue (i, 1); //putting into CES
367       Standard_Boolean SearchBackward = Standard_True;
368
369       for(;;) {
370         Standard_Integer ei = ces.Last(); //ei-edge index, number of current edge analyzed for connection
371         Standard_Boolean found;
372         TopoDS_Edge edge;
373         TopoDS_Vertex lvertex;
374         gp_Pnt lpoint;
375
376         //searching for connection in ces
377         if (SearchBackward) {
378           SearchBackward = Standard_False;
379           found = Standard_False;
380           edge = sewd->Edge (ces.Last());
381           lvertex = sae.LastVertex (edge);
382           lpoint = BRep_Tool::Pnt (lvertex);
383           Standard_Integer j; // svv #1
384           for (j = ces.Length(); (j >= 1) && !found; j--) {
385             TopoDS_Vertex fv = sae.FirstVertex (sewd->Edge (ces.Value (j)) );
386             gp_Pnt fp = BRep_Tool::Pnt (fv);
387             if ((shared && lvertex.IsSame (fv)) ||
388                 (!shared && lpoint.IsEqual (fp, tolerance)))
389               found = Standard_True;
390           }
391
392           if (found) {
393             j++;//because of decreasing last iteration
394             //making closed wire
395             TopoDS_Wire wire1;
396             B.MakeWire (wire1);
397             for (Standard_Integer cesindex = j; cesindex <= ces.Length(); cesindex++) {
398               B.Add (wire1, sewd->Edge (ces.Value (cesindex)));
399               statuses.SetValue (ces.Value (cesindex), 2);
400             }
401             wire1.Closed (Standard_True);
402             closed->Append (wire1);
403             ces.Remove (j, ces.Length());
404             if (ces.IsEmpty()) break;
405           }
406         }
407     
408         //searching for connection among free edges
409         found = Standard_False;
410         ei = ces.Last();
411         edge = sewd->Edge (ces.Last());
412         lvertex = sae.LastVertex (edge);
413         lpoint = BRep_Tool::Pnt (lvertex);
414         Standard_Integer j; // svv #1
415         for (j = 1; (j <= nbedges) && !found; j++)
416           if (statuses.Value (j) == 0) {
417             TopoDS_Vertex fv = sae.FirstVertex (sewd->Edge (j));
418             gp_Pnt fp = BRep_Tool::Pnt (fv);
419             if ((shared && lvertex.IsSame (fv)) ||
420                 (!shared && lpoint.IsEqual (fp, tolerance)))
421               found = Standard_True;
422           }
423
424         if (found) {
425           j--;//because of last iteration
426           ces.Append (j); statuses.SetValue (j, 1);//putting into CES
427           SearchBackward = Standard_True;
428           continue;
429         }
430         
431         //no edges found - mark the branch as open (use status 3)
432         statuses.SetValue (ces.Last(), 3);
433         ces.Remove (ces.Length());
434         if (ces.IsEmpty()) break;
435       }
436     }
437   
438   //building open wires
439   Handle(TopTools_HSequenceOfShape) edges = new TopTools_HSequenceOfShape;
440   for (i = 1; i <= nbedges; i++)
441     if (statuses.Value (i) != 2) edges->Append (sewd->Edge(i));
442
443   ShapeAnalysis_FreeBounds::ConnectEdgesToWires (edges, toler, shared, open);
444 }
445
446  void ShapeAnalysis_FreeBounds::SplitWires(const Handle(TopTools_HSequenceOfShape)& wires,
447                                            const Standard_Real toler,
448                                            const Standard_Boolean shared,
449                                            Handle(TopTools_HSequenceOfShape)& closed,
450                                            Handle(TopTools_HSequenceOfShape)& open) 
451 {
452   closed = new TopTools_HSequenceOfShape;
453   open   = new TopTools_HSequenceOfShape;
454
455   for (Standard_Integer i = 1; i <= wires->Length(); i++) {
456     Handle(TopTools_HSequenceOfShape) tmpclosed, tmpopen;
457     SplitWire (TopoDS::Wire (wires->Value (i)), toler, shared, tmpclosed, tmpopen);
458     closed->Append (tmpclosed);
459     open->Append (tmpopen);
460   }
461 }
462
463 //=======================================================================
464 //function : DispatchWires
465 //purpose  : 
466 //=======================================================================
467
468  void ShapeAnalysis_FreeBounds::DispatchWires(const Handle(TopTools_HSequenceOfShape)& wires,
469                                               TopoDS_Compound& closed,
470                                               TopoDS_Compound& open)
471 {
472   BRep_Builder B;
473   if (closed.IsNull()) B.MakeCompound (closed);
474   if (open.IsNull())  B.MakeCompound (open);
475   if (wires.IsNull()) return;
476
477   for (Standard_Integer iw = 1 ; iw <= wires->Length(); iw++)
478     if ( wires->Value (iw).Closed() )
479       B.Add (closed, wires->Value (iw));
480     else
481       B.Add (open, wires->Value (iw));
482 }
483
484 //=======================================================================
485 //function : SplitWires
486 //purpose  : Splits compounds of closed (myWires) and open (myEdges) wires
487 //           into small closed wires according to fields mySplitClosed and
488 //           mySplitOpen and rebuilds compounds
489 //=======================================================================
490
491  void ShapeAnalysis_FreeBounds::SplitWires()
492 {
493   if (!mySplitClosed && !mySplitOpen) return; //nothing to do
494
495   ShapeExtend_Explorer see;
496   Handle(TopTools_HSequenceOfShape) closedwires, cw1, cw2,
497                                     openwires,   ow1, ow2;
498   closedwires = see.SeqFromCompound (myWires, Standard_False);
499   openwires   = see.SeqFromCompound (myEdges, Standard_False);
500   
501   if (mySplitClosed) SplitWires (closedwires, myTolerance, myShared, cw1, ow1);
502   else {cw1 = closedwires; ow1 = new TopTools_HSequenceOfShape;}
503
504   if (mySplitOpen) SplitWires (openwires, myTolerance, myShared, cw2, ow2);
505   else {cw2 = new TopTools_HSequenceOfShape; ow2 = openwires;}
506   
507   closedwires = cw1; closedwires->Append (cw2);
508   openwires = ow1;   openwires->Append (ow2);
509
510   //szv#4:S4163:12Mar99 SGI warns
511   TopoDS_Shape compWires = see.CompoundFromSeq (closedwires);
512   TopoDS_Shape compEdges = see.CompoundFromSeq (openwires);
513   myWires = TopoDS::Compound (compWires);
514   myEdges = TopoDS::Compound (compEdges);
515 }