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