4d1c87d0876a971d811064b2c2b0ffe110093988
[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_IndexedDataMapOfShapeListOfShape.hxx>
26 #include <TopTools_ListIteratorOfListOfShape.hxx>
27 #include <TopTools_MapIteratorOfMapOfShape.hxx>
28 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
29 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
30 #include <TopExp_Explorer.hxx>
31 #include <TopoDS_Iterator.hxx>
32 #include <TopoDS_Vertex.hxx>
33 #include <TopoDS_Edge.hxx>
34 #include <TopoDS_Wire.hxx>
35 #include <TopoDS_Face.hxx>
36
37 #include <LocOpe_BuildWires.hxx>
38
39 #include <gp_Vec2d.hxx>
40 #include <gp_Vec.hxx>
41 #include <Geom_Curve.hxx>
42 #include <GeomAPI_ProjectPointOnCurve.hxx>
43 #include <BRep_Tool.hxx>
44
45 #include <BRepTools_Substitution.hxx>
46 #include <LocOpe_SplitShape.hxx>
47
48 #include <BRep_Builder.hxx>
49
50 #include <TopoDS.hxx>
51 #include <TopExp.hxx>
52
53 #include <Standard_ConstructionError.hxx>
54
55
56 //  Modified by skv - Mon May 31 13:00:30 2004 OCC5865 Begin
57 // static void RebuildWires(TopTools_ListOfShape&);
58 static void RebuildWires(TopTools_ListOfShape&,
59                          const Handle(LocOpe_ProjectedWires)&);
60 //  Modified by skv - Mon May 31 13:00:31 2004 OCC5865 End
61
62 static void Put(const TopoDS_Shape&,
63                 TopTools_DataMapOfShapeListOfShape&);
64
65 static void Select(const TopoDS_Edge&,
66                    TopTools_ListOfShape&);
67
68
69 //=======================================================================
70 //function : Perform
71 //purpose  : 
72 //=======================================================================
73
74 void LocOpe_Spliter::Perform(const Handle(LocOpe_ProjectedWires)& PW)
75 {
76   if (myShape.IsNull()) {
77     Standard_NullObject::Raise();
78   }
79   myDone = Standard_False;
80   myMap.Clear();
81   myRes.Nullify();
82
83   Put(myShape,myMap);
84
85   TopTools_MapOfShape mapV,mapE;
86   TopTools_DataMapOfShapeShape EdgOnEdg;
87   TopTools_IndexedDataMapOfShapeListOfShape mapFE;
88   TopExp_Explorer exp,exp2;
89   
90   // 1ere etape : substitution des vertex
91
92   TopoDS_Vertex Vb;
93   TopTools_ListOfShape lsubs;
94   BRepTools_Substitution theSubs;
95   BRep_Builder BB;
96
97   for (PW->InitEdgeIterator(); PW->MoreEdge(); PW->NextEdge()) {
98     const TopoDS_Edge& edg = PW->Edge();
99     mapE.Add(edg);
100     for (exp.Init(edg,TopAbs_VERTEX); exp.More(); exp.Next()) {
101       const TopoDS_Vertex& vtx = TopoDS::Vertex(exp.Current());
102       if (!mapV.Contains(vtx)) {
103         if (PW->OnVertex(vtx,Vb)) {
104           mapV.Add(vtx);
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 DEB
128         if (lsub.Extent() != 1) {
129           Standard_ConstructionError::Raise();
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     const 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,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.Oriented(TopAbs_FORWARD),lsubs);
292     }
293     else {
294 #ifdef DEB
295       cout << "Pb pour substitution" << 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 DEB
309         if (lsub.Extent() != 1) {
310           Standard_ConstructionError::Raise();
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   myDLeft.Clear();
327   myLeft.Clear();
328   mapV.Clear();
329
330   TopTools_MapIteratorOfMapOfShape itms;
331
332   for (exp.Init(myRes, TopAbs_FACE); exp.More(); exp.Next()) {
333     const TopoDS_Face& fac = TopoDS::Face(exp.Current());
334     for (exp2.Init(fac,TopAbs_EDGE); exp2.More(); exp2.Next()) {
335       const TopoDS_Edge& edg = TopoDS::Edge(exp2.Current());
336       for (itms.Initialize(mapE); 
337            itms.More(); itms.Next()) {
338         if (itms.Key().IsSame(edg) &&
339             edg.Orientation() == itms.Key().Orientation()) {
340           break;
341         }
342       }
343       if (itms.More()) {
344         break;
345       }
346     }
347     if (exp2.More()) {
348       myDLeft.Append(fac);
349       myLeft.Append(fac);
350     }
351     else {
352       mapV.Add(fac);
353     }
354   }
355
356 /* JAG : Ne peut pas marcher
357
358   Standard_Boolean full = mapV.IsEmpty();
359   while (!full) {
360     full = Standard_True;
361     itms.Initialize(mapV);
362     const TopoDS_Face& fac = TopoDS::Face(itms.Key());
363     for (exp.Init(fac,TopAbs_EDGE); exp.More(); exp.Next()) {
364       if (!mapE.Contains(exp.Current())) {
365         for (itl.Initialize(myLeft); itl.More(); itl.Next()) {
366           const TopoDS_Face& fac2 = TopoDS::Face(itl.Value());
367           for (exp2.Init(fac2,TopAbs_EDGE); exp2.More(); exp2.Next()) {
368             if (exp2.Current().IsSame(exp.Current())) {
369               myLeft.Append(fac);
370               mapV.Remove(fac);
371               full = mapV.IsEmpty();
372               break;
373             }
374           }
375           if (exp2.More()) {
376             break;
377           }
378         }
379         if (itl.More()) {
380           break;
381         }
382       }
383     }
384   }
385 */
386
387   // Map des edges ou les connexions sont possibles
388   TopTools_MapOfShape Mapebord;
389   for (itl.Initialize(myLeft); itl.More(); itl.Next()) {
390     for (exp.Init(itl.Value(),TopAbs_EDGE); exp.More(); exp.Next()) {
391       if (!mapE.Contains(exp.Current())) {
392         if (!Mapebord.Add(exp.Current())) {
393           Mapebord.Remove(exp.Current());
394         }
395       }
396     }
397   }
398
399
400   while (Mapebord.Extent() != 0) {
401     itms.Initialize(Mapebord);
402     TopoDS_Shape edg = itms.Key();
403
404     for (itms.Initialize(mapV); itms.More(); itms.Next()) {
405       const TopoDS_Shape& fac = itms.Key();
406       for (exp.Init(fac,TopAbs_EDGE); exp.More(); exp.Next()) {
407         if (exp.Current().IsSame(edg)) {
408           break;
409         }
410       }
411       if (exp.More()) {
412         break; // face a gauche
413       }
414     }
415     if (itms.More()) {
416       TopoDS_Shape fac = itms.Key();
417       for (exp.Init(fac,TopAbs_EDGE); exp.More(); exp.Next()) {
418         if (!Mapebord.Add(exp.Current())) {
419           Mapebord.Remove(exp.Current());
420         }
421       }
422       mapV.Remove(fac);
423       myLeft.Append(fac);
424     }
425     else {
426       Mapebord.Remove(edg);
427     }
428   }
429
430   myDone = Standard_True;
431 }
432
433
434 //=======================================================================
435 //function : DescendantShapes
436 //purpose  : 
437 //=======================================================================
438
439 const TopTools_ListOfShape& LocOpe_Spliter::
440    DescendantShapes(const TopoDS_Shape& F)
441 {
442   if (!myDone) {StdFail_NotDone::Raise();}
443   if (myMap.IsBound(F))
444     return myMap(F);
445   else {
446     static TopTools_ListOfShape empty;
447     return empty;
448   }
449 }
450
451
452 //=======================================================================
453 //function : DirectLeft
454 //purpose  : 
455 //=======================================================================
456
457 const TopTools_ListOfShape& LocOpe_Spliter::DirectLeft() const
458 {
459   if (!myDone) {StdFail_NotDone::Raise();}
460   return myDLeft;
461
462 }
463
464
465 //=======================================================================
466 //function : Left
467 //purpose  : 
468 //=======================================================================
469
470 const TopTools_ListOfShape& LocOpe_Spliter::Left() const
471 {
472   if (!myDone) {StdFail_NotDone::Raise();}
473   return myLeft;
474
475 }
476
477
478 //=======================================================================
479 //function : RebuildWires
480 //purpose  : 
481 //=======================================================================
482
483 //  Modified by skv - Mon May 31 12:31:39 2004 OCC5865 Begin
484 //static void RebuildWires(TopTools_ListOfShape& ledge)
485 static void RebuildWires(TopTools_ListOfShape& ledge,
486                          const Handle(LocOpe_ProjectedWires)& PW)
487 {
488   LocOpe_BuildWires theBuild(ledge, PW);
489 //  Modified by skv - Mon May 31 12:31:40 2004 OCC5865 End
490   if (!theBuild.IsDone()) {
491     Standard_ConstructionError::Raise();
492   }
493   ledge = theBuild.Result();
494
495
496 }
497
498
499
500 //=======================================================================
501 //function : Put
502 //purpose  : 
503 //=======================================================================
504
505 static void Put(const TopoDS_Shape& S,
506                 TopTools_DataMapOfShapeListOfShape& theMap)
507 {
508   if (theMap.IsBound(S)) {
509     return;
510   }
511   TopTools_ListOfShape thelist;
512   theMap.Bind(S, thelist);
513   theMap(S).Append(S);
514   for (TopoDS_Iterator it(S); it.More(); it.Next()) {
515     Put(it.Value(),theMap);
516   }
517 }
518
519
520 //=======================================================================
521 //function : Select
522 //purpose  : 
523 //=======================================================================
524
525 static void Select(const TopoDS_Edge& Ebase,
526                    TopTools_ListOfShape& lsubs)
527 {
528
529   // Choix d`un point
530
531   Handle(Geom_Curve) C;
532   TopLoc_Location Loc;
533   Standard_Real f,l,dmin = RealLast();
534   Standard_Integer i=0,imin = 0;
535
536   C = BRep_Tool::Curve(Ebase,Loc,f,l);
537
538   if (!Loc.IsIdentity()) {
539     Handle(Geom_Geometry) GG = C->Transformed(Loc.Transformation());
540     C = *((Handle(Geom_Curve)*)&GG);
541   }
542   gp_Pnt Pt(C->Value((f+l)/2.));
543
544   GeomAPI_ProjectPointOnCurve proj;
545 //  for (TopTools_ListIteratorOfListOfShape itl(lsubs);
546   TopTools_ListIteratorOfListOfShape itl(lsubs);
547   for ( ;itl.More();itl.Next()) {
548     i++;
549     const TopoDS_Edge& edg = TopoDS::Edge(itl.Value());
550     C = BRep_Tool::Curve(edg,Loc,f,l);
551     if (!Loc.IsIdentity()) {
552       Handle(Geom_Geometry) GG = C->Transformed(Loc.Transformation());
553       C = *((Handle(Geom_Curve)*)&GG);
554     }
555     proj.Init(Pt,C,f,l);
556     if (proj.NbPoints() > 0) {
557       if (proj.LowerDistance() < dmin) {
558         imin = i;
559         dmin = proj.LowerDistance();
560       }
561     }
562   }
563   if (imin == 0) {
564     lsubs.Clear();
565   }
566   else {
567     itl.Initialize(lsubs);
568     i = 1;
569     while (i < imin) {
570       lsubs.Remove(itl);
571       i++;
572     }
573     itl.Next();
574     while (itl.More()) {
575       lsubs.Remove(itl);
576     }
577   }
578 }