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