0024023: Revamp the OCCT Handle -- downcast (automatic)
[occt.git] / src / LocOpe / LocOpe_Spliter.cxx
1 // Created on: 1996-01-09
2 // Created by: Jacques GOUSSARD
3 // Copyright (c) 1996-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 //  Modified by skv - Mon May 31 12:34:09 2004 OCC5865
18
19 #include <LocOpe_Spliter.ixx>
20
21 //#include <LocOpe_ProjectedWires.hxx>
22
23 #include <TopTools_MapOfShape.hxx>
24 #include <TopTools_DataMapOfShapeShape.hxx>
25 #include <TopTools_IndexedMapOfShape.hxx>
26 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
27 #include <TopTools_SequenceOfShape.hxx>
28 #include <TopTools_ListIteratorOfListOfShape.hxx>
29 #include <TopTools_MapIteratorOfMapOfShape.hxx>
30 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
31 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
32 #include <TopExp_Explorer.hxx>
33 #include <TopoDS_Iterator.hxx>
34 #include <TopoDS_Vertex.hxx>
35 #include <TopoDS_Edge.hxx>
36 #include <TopoDS_Wire.hxx>
37 #include <TopoDS_Face.hxx>
38
39 #include <LocOpe_BuildWires.hxx>
40
41 #include <gp_Vec2d.hxx>
42 #include <gp_Vec.hxx>
43 #include <Geom_Curve.hxx>
44 #include <GeomAPI_ProjectPointOnCurve.hxx>
45 #include <BRep_Tool.hxx>
46
47 #include <BRepTools_Substitution.hxx>
48 #include <LocOpe_SplitShape.hxx>
49
50 #include <BRep_Builder.hxx>
51
52 #include <TopoDS.hxx>
53 #include <TopExp.hxx>
54
55 #include <Standard_ConstructionError.hxx>
56
57
58 //  Modified by skv - Mon May 31 13:00:30 2004 OCC5865 Begin
59 // static void RebuildWires(TopTools_ListOfShape&);
60 static void RebuildWires(TopTools_ListOfShape&,
61                          const Handle(LocOpe_WiresOnShape)&);
62 //  Modified by skv - Mon May 31 13:00:31 2004 OCC5865 End
63
64 static void Put(const TopoDS_Shape&,
65                 TopTools_DataMapOfShapeListOfShape&);
66
67 static void Select(const TopoDS_Edge&,
68                    TopTools_ListOfShape&);
69
70
71 //=======================================================================
72 //function : Perform
73 //purpose  : 
74 //=======================================================================
75
76 void LocOpe_Spliter::Perform(const Handle(LocOpe_WiresOnShape)& PW)
77 {
78   if (myShape.IsNull()) {
79     Standard_NullObject::Raise();
80   }
81   myDone = Standard_False;
82   myMap.Clear();
83   myRes.Nullify();
84
85   Put(myShape,myMap);
86
87   TopTools_MapOfShape mapV,mapE;
88   TopTools_DataMapOfShapeShape EdgOnEdg;
89   TopTools_IndexedDataMapOfShapeListOfShape mapFE;
90   TopExp_Explorer exp,exp2;
91   
92   // 1ere etape : substitution des vertex
93
94   TopoDS_Vertex Vb;
95   TopTools_ListOfShape lsubs;
96   BRepTools_Substitution theSubs;
97   BRep_Builder BB;
98
99   for (PW->InitEdgeIterator(); PW->MoreEdge(); PW->NextEdge()) {
100     const TopoDS_Edge& edg = PW->Edge();
101     mapE.Add(edg);
102     for (exp.Init(edg,TopAbs_VERTEX); exp.More(); exp.Next()) {
103       const TopoDS_Vertex& vtx = TopoDS::Vertex(exp.Current());
104       if (!mapV.Contains(vtx)) {
105         if (PW->OnVertex(vtx,Vb)) {
106           mapV.Add(vtx);
107           lsubs.Clear();
108           TopoDS_Vertex vsub = TopoDS::Vertex(vtx.Oriented(TopAbs_FORWARD));
109           gp_Pnt p1 = BRep_Tool::Pnt(vsub), p2 = BRep_Tool::Pnt(Vb);
110           Standard_Real d = p1.Distance(p2);
111           d = d + BRep_Tool::Tolerance(Vb);
112           BB.UpdateVertex(vsub, d);
113           lsubs.Append(vsub);
114           theSubs.Substitute(Vb.Oriented(TopAbs_FORWARD),lsubs);
115         }
116         
117       }
118     }
119   }
120
121   theSubs.Build(myShape);
122   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itdesc(myMap);
123   if (theSubs.IsCopied(myShape)) {
124     // on n`a fait que des substitutions de vertex. Donc chaque element
125     // est remplace par lui meme ou par un seul element du meme type.
126     for (; itdesc.More(); itdesc.Next()) {
127       if (theSubs.IsCopied(itdesc.Key())) {
128         const TopTools_ListOfShape& lsub = theSubs.Copy(itdesc.Key());
129 #ifdef OCCT_DEBUG
130         if (lsub.Extent() != 1) {
131           Standard_ConstructionError::Raise();
132         }
133 #endif
134         myMap(itdesc.Key()).Clear(); 
135         myMap(itdesc.Key()).Append(lsub.First()); 
136       }
137     }
138   }
139
140   myRes = myMap(myShape).First();
141   LocOpe_SplitShape theCFace(myRes);
142
143   // Adds every vertices lying on an edge of the shape, and prepares 
144   // work to rebuild wires on each face
145   TopoDS_Edge Ed;
146   Standard_Real prm;
147
148   TopTools_MapOfShape theFacesWithSection;
149   for (PW->InitEdgeIterator(); PW->MoreEdge(); PW->NextEdge()) {
150     const TopoDS_Edge& edg = PW->Edge();
151     for (exp.Init(edg,TopAbs_VERTEX); exp.More(); exp.Next()) {
152       const TopoDS_Vertex& vtx = TopoDS::Vertex(exp.Current());
153       if (!mapV.Contains(vtx)) {
154         mapV.Add(vtx);
155         if (PW->OnEdge(vtx,edg,Ed,prm)) {
156           // on devrait verifier que le vtx n`existe pas deja sur l`edge
157           if(!myMap.IsBound(Ed)) continue;
158           Ed = TopoDS::Edge(myMap(Ed).First());
159           theCFace.Add(vtx,prm,Ed);
160         }
161       }
162     }
163     TopoDS_Edge Ebis;
164     if (PW->OnEdge(Ebis)) {
165       //        Ebis = TopoDS::Edge(myMap(Ebis).First());
166       EdgOnEdg.Bind(edg,Ebis);
167     }
168     else {
169       TopoDS_Face fac = PW->OnFace();
170       if(!myMap.IsBound(fac)) continue;
171       Standard_Boolean IsFaceWithSec = PW->IsFaceWithSection(fac);
172       fac = TopoDS::Face(myMap(fac).First());
173       if (IsFaceWithSec)
174         theFacesWithSection.Add(fac);
175       if (!mapFE.Contains(fac)) {
176         TopTools_ListOfShape thelist;
177         mapFE.Add(fac, thelist);
178       }
179       mapFE.ChangeFromKey(fac).Append(edg);
180     }
181   }
182
183   // Rebuilds wires on each face of the shape
184
185   TopTools_ListIteratorOfListOfShape itl;
186   for (Standard_Integer i=1; i<=mapFE.Extent(); i++) {
187     const TopoDS_Face& fac = TopoDS::Face(mapFE.FindKey(i));
188     TopTools_ListOfShape& ledges = mapFE(i);
189 //  Modified by skv - Mon May 31 12:32:54 2004 OCC5865 Begin
190 //     RebuildWires(ledges);
191     RebuildWires(ledges, PW);
192 //  Modified by skv - Mon May 31 12:32:54 2004 OCC5865 End
193     if (theFacesWithSection.Contains(fac))
194       theCFace.Add(ledges, fac);
195     else
196       for (itl.Initialize(ledges); itl.More(); itl.Next())
197         theCFace.Add(TopoDS::Wire(itl.Value()),fac);
198   }
199
200
201   // Mise a jour des descendants
202
203   for (itdesc.Reset(); itdesc.More(); itdesc.Next()) {
204     const TopoDS_Shape& sori = itdesc.Key();
205     const TopoDS_Shape& scib = itdesc.Value().First();
206     myMap(sori) = theCFace.DescendantShapes(scib);
207   }
208
209   const TopTools_ListOfShape& lres = myMap(myShape);
210
211   TopAbs_ShapeEnum typS = myShape.ShapeType();
212   if (typS == TopAbs_FACE && lres.Extent() >=2) {
213     BRep_Builder B;
214     myRes.Nullify();
215     B.MakeShell(TopoDS::Shell(myRes));
216     myRes.Orientation(TopAbs_FORWARD);
217     for (itl.Initialize(lres); itl.More(); itl.Next()) {
218       B.Add(myRes,itl.Value().Oriented(myShape.Orientation()));
219     }
220   }
221   else if (typS == TopAbs_EDGE && lres.Extent() >=2) {
222     BRep_Builder B;
223     myRes.Nullify();
224     B.MakeWire(TopoDS::Wire(myRes));
225     myRes.Orientation(TopAbs_FORWARD);
226     for (itl.Initialize(lres); itl.More(); itl.Next()) {
227       B.Add(myRes,itl.Value().Oriented(myShape.Orientation()));
228     }
229   }
230   else {
231     if (lres.Extent() != 1) {
232       return;
233     }
234     myRes = lres.First();
235   }
236
237   theSubs.Clear();
238   for (TopTools_DataMapIteratorOfDataMapOfShapeShape itee(EdgOnEdg);
239        itee.More();
240        itee.Next()) {
241     const TopoDS_Edge& e1 = TopoDS::Edge(itee.Key());
242     // on recherche dans les descendants de e2 l`edge qui correspont a e1
243
244     TopoDS_Vertex vf1,vl1,vf2,vl2;
245     TopExp::Vertices(e1,vf1,vl1);
246     lsubs.Clear();
247     for (itl.Initialize(myMap(itee.Value()));
248          itl.More();
249          itl.Next()) {
250       const TopoDS_Edge& e2 = TopoDS::Edge(itl.Value());
251       TopExp::Vertices(e2,vf2,vl2);
252
253       if (!vl1.IsSame(vf1)) {
254         if (vf1.IsSame(vf2) && vl1.IsSame(vl2)) {
255           lsubs.Append(e2.Oriented(TopAbs_FORWARD));
256           //    break;
257         }
258         else if (vf1.IsSame(vl2) && vl1.IsSame(vf2)) {
259           lsubs.Append(e2.Oriented(TopAbs_REVERSED));
260           //    break;
261         }
262       }
263       else { // discrimination sur les tangentes
264         if (vf2.IsSame(vl2) && vl2.IsSame(vl1)) { // tout au meme point
265           TopLoc_Location Loc;
266           Standard_Real f,l;
267           gp_Pnt pbid;
268           gp_Vec v1,v2;
269           Handle(Geom_Curve) C = BRep_Tool::Curve(e1,Loc,f,l);
270           C->D1(f,pbid,v1);
271           v1.Transform(Loc.Transformation());
272
273           C = BRep_Tool::Curve(e2,Loc,f,l);
274           C->D1(f,pbid,v2);
275           v2.Transform(Loc.Transformation());
276           if (v1.Dot(v2) >0.) {
277             lsubs.Append(e2.Oriented(TopAbs_FORWARD));
278           }
279           else {
280             lsubs.Append(e2.Oriented(TopAbs_REVERSED));
281           }
282         }
283       }
284
285     }
286     if (lsubs.Extent() >= 2) { // il faut faire un choix
287       Select(e1,lsubs);
288     }
289     if (lsubs.Extent() == 1) {
290       TopoDS_Shape ebase = lsubs.First();
291       lsubs.Clear();
292       lsubs.Append(e1.Oriented(ebase.Orientation()));
293       theSubs.Substitute(ebase.Oriented(TopAbs_FORWARD),lsubs);
294     }
295     else {
296 #ifdef OCCT_DEBUG
297       cout << "Pb pour substitution" << endl;
298 #endif
299     }
300   }
301
302   theSubs.Build(myRes);
303
304   for (itdesc.Reset(); itdesc.More(); itdesc.Next()) {
305     TopTools_ListOfShape& ldesc = myMap(itdesc.Key());
306     TopTools_ListOfShape newdesc;
307     for (itl.Initialize(ldesc); itl.More(); itl.Next()) {
308       if (theSubs.IsCopied(itl.Value())) {
309         const TopTools_ListOfShape& lsub = theSubs.Copy(itl.Value());
310 #ifdef OCCT_DEBUG
311         if (lsub.Extent() != 1) {
312           Standard_ConstructionError::Raise();
313         }
314 #endif
315         newdesc.Append(lsub.First());
316       }
317       else {
318         newdesc.Append(itl.Value());
319       }
320     }
321     myMap(itdesc.Key()) = newdesc;
322   }
323   
324   if (theSubs.IsCopied(myRes)) {
325     myRes = theSubs.Copy(myRes).First();
326   }
327
328   ////remove superfluous vertices on degenerated edges
329   theSubs.Clear();
330   TopTools_IndexedMapOfShape Emap;
331   TopExp::MapShapes(myRes, TopAbs_EDGE, Emap);
332   TopTools_SequenceOfShape DegEdges;
333   Standard_Integer i, j;
334   for (i = 1; i <= Emap.Extent(); i++)
335   {
336     const TopoDS_Edge& anEdge = TopoDS::Edge(Emap(i));
337     if (BRep_Tool::Degenerated(anEdge))
338       DegEdges.Append(anEdge);
339   }
340   
341   TopTools_SequenceOfShape DegWires;
342   for (;;)
343   {
344     if (DegEdges.IsEmpty())
345       break;
346     TopoDS_Wire aDegWire;
347     BB.MakeWire(aDegWire);
348     BB.Add(aDegWire, DegEdges(1));
349     DegEdges.Remove(1);
350     TopoDS_Vertex Vfirst, Vlast;
351     for (;;)
352     {
353       TopExp::Vertices(aDegWire, Vfirst, Vlast);
354       Standard_Boolean found = Standard_False;
355       for (i = 1; i <= DegEdges.Length(); i++)
356       {
357         const TopoDS_Edge& anEdge = TopoDS::Edge(DegEdges(i));
358         TopoDS_Vertex V1, V2;
359         TopExp::Vertices(anEdge, V1, V2);
360         if (V1.IsSame(Vfirst) || V1.IsSame(Vlast) || V2.IsSame(Vfirst) || V2.IsSame(Vlast))
361         {
362           BB.Add(aDegWire, anEdge);
363           DegEdges.Remove(i);
364           found = Standard_True;
365           break;
366         }
367       }
368       if (!found)
369         break;
370     }
371     DegWires.Append(aDegWire);
372   }
373
374   for (i = 1; i <= DegWires.Length(); i++)
375   {
376     TopTools_IndexedMapOfShape Vmap;
377     TopExp::MapShapes(DegWires(i), TopAbs_VERTEX, Vmap);
378     TopTools_ListOfShape LV;
379     LV.Append(Vmap(1).Oriented(TopAbs_FORWARD));
380     for (j = 2; j <= Vmap.Extent(); j++)
381     {
382       if (!Vmap(j).IsSame(Vmap(1)))
383         theSubs.Substitute(Vmap(j), LV);
384     }
385   }
386   theSubs.Build(myRes);
387   if (theSubs.IsCopied(myRes))
388     myRes = theSubs.Copy(myRes).First();
389   ////
390
391   myDLeft.Clear();
392   myLeft.Clear();
393   mapV.Clear();
394
395   TopTools_MapIteratorOfMapOfShape itms;
396
397   for (exp.Init(myRes, TopAbs_FACE); exp.More(); exp.Next()) {
398     const TopoDS_Face& fac = TopoDS::Face(exp.Current());
399     for (exp2.Init(fac,TopAbs_EDGE); exp2.More(); exp2.Next()) {
400       const TopoDS_Edge& edg = TopoDS::Edge(exp2.Current());
401       for (itms.Initialize(mapE); 
402            itms.More(); itms.Next()) {
403         if (itms.Key().IsSame(edg) &&
404             edg.Orientation() == itms.Key().Orientation()) {
405           break;
406         }
407       }
408       if (itms.More()) {
409         break;
410       }
411     }
412     if (exp2.More()) {
413       myDLeft.Append(fac);
414       myLeft.Append(fac);
415     }
416     else {
417       mapV.Add(fac);
418     }
419   }
420
421 /* JAG : Ne peut pas marcher
422
423   Standard_Boolean full = mapV.IsEmpty();
424   while (!full) {
425     full = Standard_True;
426     itms.Initialize(mapV);
427     const TopoDS_Face& fac = TopoDS::Face(itms.Key());
428     for (exp.Init(fac,TopAbs_EDGE); exp.More(); exp.Next()) {
429       if (!mapE.Contains(exp.Current())) {
430         for (itl.Initialize(myLeft); itl.More(); itl.Next()) {
431           const TopoDS_Face& fac2 = TopoDS::Face(itl.Value());
432           for (exp2.Init(fac2,TopAbs_EDGE); exp2.More(); exp2.Next()) {
433             if (exp2.Current().IsSame(exp.Current())) {
434               myLeft.Append(fac);
435               mapV.Remove(fac);
436               full = mapV.IsEmpty();
437               break;
438             }
439           }
440           if (exp2.More()) {
441             break;
442           }
443         }
444         if (itl.More()) {
445           break;
446         }
447       }
448     }
449   }
450 */
451
452   // Map des edges ou les connexions sont possibles
453   TopTools_MapOfShape Mapebord;
454   for (itl.Initialize(myLeft); itl.More(); itl.Next()) {
455     for (exp.Init(itl.Value(),TopAbs_EDGE); exp.More(); exp.Next()) {
456       if (!mapE.Contains(exp.Current())) {
457         if (!Mapebord.Add(exp.Current())) {
458           Mapebord.Remove(exp.Current());
459         }
460       }
461     }
462   }
463
464
465   while (Mapebord.Extent() != 0) {
466     itms.Initialize(Mapebord);
467     TopoDS_Shape edg = itms.Key();
468
469     for (itms.Initialize(mapV); itms.More(); itms.Next()) {
470       const TopoDS_Shape& fac = itms.Key();
471       for (exp.Init(fac,TopAbs_EDGE); exp.More(); exp.Next()) {
472         if (exp.Current().IsSame(edg)) {
473           break;
474         }
475       }
476       if (exp.More()) {
477         break; // face a gauche
478       }
479     }
480     if (itms.More()) {
481       TopoDS_Shape fac = itms.Key();
482       for (exp.Init(fac,TopAbs_EDGE); exp.More(); exp.Next()) {
483         if (!Mapebord.Add(exp.Current())) {
484           Mapebord.Remove(exp.Current());
485         }
486       }
487       mapV.Remove(fac);
488       myLeft.Append(fac);
489     }
490     else {
491       Mapebord.Remove(edg);
492     }
493   }
494
495   myDone = Standard_True;
496 }
497
498
499 //=======================================================================
500 //function : DescendantShapes
501 //purpose  : 
502 //=======================================================================
503
504 const TopTools_ListOfShape& LocOpe_Spliter::
505    DescendantShapes(const TopoDS_Shape& F)
506 {
507   if (!myDone) {StdFail_NotDone::Raise();}
508   if (myMap.IsBound(F))
509     return myMap(F);
510   else {
511     static TopTools_ListOfShape empty;
512     return empty;
513   }
514 }
515
516
517 //=======================================================================
518 //function : DirectLeft
519 //purpose  : 
520 //=======================================================================
521
522 const TopTools_ListOfShape& LocOpe_Spliter::DirectLeft() const
523 {
524   if (!myDone) {StdFail_NotDone::Raise();}
525   return myDLeft;
526
527 }
528
529
530 //=======================================================================
531 //function : Left
532 //purpose  : 
533 //=======================================================================
534
535 const TopTools_ListOfShape& LocOpe_Spliter::Left() const
536 {
537   if (!myDone) {StdFail_NotDone::Raise();}
538   return myLeft;
539
540 }
541
542
543 //=======================================================================
544 //function : RebuildWires
545 //purpose  : 
546 //=======================================================================
547
548 //  Modified by skv - Mon May 31 12:31:39 2004 OCC5865 Begin
549 //static void RebuildWires(TopTools_ListOfShape& ledge)
550 static void RebuildWires(TopTools_ListOfShape& ledge,
551                          const Handle(LocOpe_WiresOnShape)& PW)
552 {
553   LocOpe_BuildWires theBuild(ledge, PW);
554 //  Modified by skv - Mon May 31 12:31:40 2004 OCC5865 End
555   if (!theBuild.IsDone()) {
556     Standard_ConstructionError::Raise();
557   }
558   ledge = theBuild.Result();
559
560
561 }
562
563
564
565 //=======================================================================
566 //function : Put
567 //purpose  : 
568 //=======================================================================
569
570 static void Put(const TopoDS_Shape& S,
571                 TopTools_DataMapOfShapeListOfShape& theMap)
572 {
573   if (theMap.IsBound(S)) {
574     return;
575   }
576   TopTools_ListOfShape thelist;
577   theMap.Bind(S, thelist);
578   theMap(S).Append(S);
579   for (TopoDS_Iterator it(S); it.More(); it.Next()) {
580     Put(it.Value(),theMap);
581   }
582 }
583
584
585 //=======================================================================
586 //function : Select
587 //purpose  : 
588 //=======================================================================
589
590 static void Select(const TopoDS_Edge& Ebase,
591                    TopTools_ListOfShape& lsubs)
592 {
593
594   // Choix d`un point
595
596   Handle(Geom_Curve) C;
597   TopLoc_Location Loc;
598   Standard_Real f,l,dmin = RealLast();
599   Standard_Integer i=0,imin = 0;
600
601   C = BRep_Tool::Curve(Ebase,Loc,f,l);
602
603   if (!Loc.IsIdentity()) {
604     Handle(Geom_Geometry) GG = C->Transformed(Loc.Transformation());
605     C = Handle(Geom_Curve)::DownCast (GG);
606   }
607   gp_Pnt Pt(C->Value((f+l)/2.));
608
609   GeomAPI_ProjectPointOnCurve proj;
610 //  for (TopTools_ListIteratorOfListOfShape itl(lsubs);
611   TopTools_ListIteratorOfListOfShape itl(lsubs);
612   for ( ;itl.More();itl.Next()) {
613     i++;
614     const TopoDS_Edge& edg = TopoDS::Edge(itl.Value());
615     C = BRep_Tool::Curve(edg,Loc,f,l);
616     if (!Loc.IsIdentity()) {
617       Handle(Geom_Geometry) GG = C->Transformed(Loc.Transformation());
618       C = Handle(Geom_Curve)::DownCast (GG);
619     }
620     proj.Init(Pt,C,f,l);
621     if (proj.NbPoints() > 0) {
622       if (proj.LowerDistance() < dmin) {
623         imin = i;
624         dmin = proj.LowerDistance();
625       }
626     }
627   }
628   if (imin == 0) {
629     lsubs.Clear();
630   }
631   else {
632     itl.Initialize(lsubs);
633     i = 1;
634     while (i < imin) {
635       lsubs.Remove(itl);
636       i++;
637     }
638     itl.Next();
639     while (itl.More()) {
640       lsubs.Remove(itl);
641     }
642   }
643 }