Warnings on vc14 were eliminated
[occt.git] / src / LocOpe / LocOpe_Gluer.cxx
1 // Created on: 1996-01-30
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
18 #include <BRep_Builder.hxx>
19 #include <BRep_Tool.hxx>
20 #include <BRepExtrema_ExtPF.hxx>
21 #include <Extrema_ExtPS.hxx>
22 #include <Geom2d_Curve.hxx>
23 #include <Geom_Surface.hxx>
24 #include <GeomAdaptor_Surface.hxx>
25 #include <gp_Pnt2d.hxx>
26 #include <gp_Vec.hxx>
27 #include <LocOpe.hxx>
28 #include <LocOpe_Generator.hxx>
29 #include <LocOpe_GluedShape.hxx>
30 #include <LocOpe_Gluer.hxx>
31 #include <LocOpe_Spliter.hxx>
32 #include <LocOpe_WiresOnShape.hxx>
33 #include <Precision.hxx>
34 #include <Standard_ConstructionError.hxx>
35 #include <Standard_NoSuchObject.hxx>
36 #include <StdFail_NotDone.hxx>
37 #include <TopExp.hxx>
38 #include <TopExp_Explorer.hxx>
39 #include <TopoDS.hxx>
40 #include <TopoDS_Edge.hxx>
41 #include <TopoDS_Face.hxx>
42 #include <TopoDS_Shape.hxx>
43 #include <TopoDS_Vertex.hxx>
44 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
45 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
46 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
47 #include <TopTools_IndexedMapOfShape.hxx>
48 #include <TopTools_ListIteratorOfListOfShape.hxx>
49
50 static TopAbs_Orientation GetOrientation(const TopoDS_Face&,
51                                          const TopoDS_Face&);
52
53
54 static Standard_Boolean Contains(const TopTools_ListOfShape&,
55                                  const TopoDS_Shape&);
56
57
58 //=======================================================================
59 //function : Init
60 //purpose  : 
61 //=======================================================================
62
63 void LocOpe_Gluer::Init(const TopoDS_Shape& Sbase,
64                         const TopoDS_Shape& Snew)
65 {
66   mySb = Sbase;
67   mySn = Snew;
68   myMapEF.Clear();
69   myMapEE.Clear();
70   myDescF.Clear();
71   myDone = Standard_False;
72   myOri  = TopAbs_INTERNAL;
73   myOpe  = LocOpe_INVALID;
74 }
75   
76
77 //=======================================================================
78 //function : Bind
79 //purpose  : 
80 //=======================================================================
81
82 void LocOpe_Gluer::Bind(const TopoDS_Face& Fnew,
83                         const TopoDS_Face& Fbase)
84 {
85   TopExp_Explorer exp(mySn,TopAbs_FACE);
86
87   for (; exp.More(); exp.Next()) {
88     if (exp.Current().IsSame(Fnew)) {
89       break;
90     }
91   }
92   if (!exp.More()) {
93     throw Standard_ConstructionError();
94   }
95
96   TopoDS_Shape aLocalFace =  Fnew.Oriented(exp.Current().Orientation());
97   TopoDS_Face Fnor = TopoDS::Face(aLocalFace);
98 //  TopoDS_Face Fnor = TopoDS::Face(Fnew.Oriented(exp.Current().Orientation()));
99
100   for (exp.Init(mySb,TopAbs_FACE); exp.More(); exp.Next()) {
101     if (exp.Current().IsSame(Fbase)) {
102       break;
103     }
104   }
105   if (!exp.More()) {
106     throw Standard_ConstructionError();
107   }
108
109   aLocalFace = Fbase.Oriented(exp.Current().Orientation());
110   TopoDS_Face Fbor = TopoDS::Face(aLocalFace);
111 //  TopoDS_Face Fbor = TopoDS::Face(Fbase.Oriented(exp.Current().Orientation()));
112   TopAbs_Orientation Ori = GetOrientation(Fnor,Fbor);
113
114   if (myOri == TopAbs_INTERNAL) {
115     myOri = Ori; 
116     if (myOri == TopAbs_REVERSED) {
117       mySn.Reverse();
118       myOpe = LocOpe_CUT;
119     }
120     else {
121       myOpe = LocOpe_FUSE;
122     }
123   }
124   else if (Ori != TopAbs_FORWARD) {
125     myOpe = LocOpe_INVALID;
126   }
127
128   for (exp.Init(Fnor, TopAbs_EDGE); exp.More(); exp.Next()) {
129     const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
130 //    if (!myMapEF.IsBound(edg)) {
131 //      myMapEF.Bind(edg,Fbor);
132     if (!myMapEF.Contains(edg)) {
133       myMapEF.Add(edg,Fbor);
134     }
135 //    else if (!myMapEF(edg).IsSame(Fbor)) {
136     else if (!myMapEF.FindFromKey(edg).IsSame(Fbor)) {
137 //      myMapEF.UnBind(edg); // edg sur 2 face. a binder avec l`edge commun
138       myMapEF.ChangeFromKey(edg).Nullify();
139       // edg sur 2 face. a binder avec l`edge commun
140     }
141   }
142 //  myMapEF.Bind(Fnor,Fbor);
143   myMapEF.Add(Fnor,Fbor);
144 }
145
146
147 //=======================================================================
148 //function : Bind
149 //purpose  : 
150 //=======================================================================
151
152 void LocOpe_Gluer::Bind(const TopoDS_Edge& Enew,
153                         const TopoDS_Edge& Ebase)
154 {
155   if (myMapEE.IsBound(Enew) && !myMapEE(Enew).IsSame(Ebase)) {
156     throw Standard_ConstructionError();
157   }
158   myMapEE.Bind(Enew,Ebase);
159 }
160
161
162 //=======================================================================
163 //function : Perform
164 //purpose  : 
165 //=======================================================================
166
167 void LocOpe_Gluer::Perform()
168 {
169   Standard_Integer ind ;
170   if (myDone) {
171     return;
172   }
173   if (mySb.IsNull() || mySn.IsNull() || 
174       myMapEF.IsEmpty() || myOpe ==LocOpe_INVALID) {
175     throw Standard_ConstructionError();
176   }
177
178   Handle(LocOpe_WiresOnShape) theWOnS = new LocOpe_WiresOnShape(mySb);
179   Handle(LocOpe_GluedShape)  theGS   = new LocOpe_GluedShape(mySn);
180
181   Standard_Integer lmap = myMapEF.Extent();
182
183   for ( ind = 1; ind <= lmap; ind++) {
184     TopoDS_Shape S = myMapEF.FindKey(ind);
185     if (S.ShapeType() == TopAbs_EDGE) {
186       TopoDS_Shape S2 = myMapEF(ind);
187       if (!S2.IsNull()) {
188         theWOnS->Bind(TopoDS::Edge(S), TopoDS::Face(S2));
189       }
190     }
191     else { // TopAbs_FACE
192       theGS->GlueOnFace(TopoDS::Face(S));
193     }
194   }
195   
196   TopTools_DataMapIteratorOfDataMapOfShapeShape itm(myMapEE);
197   for (; itm.More(); itm.Next()) {
198     theWOnS->Bind(TopoDS::Edge(itm.Key()), TopoDS::Edge(itm.Value()));
199   }
200   
201   theWOnS->BindAll();
202   
203   if (!theWOnS->IsDone()) {
204     return;
205   }
206
207   LocOpe_Spliter theSplit(mySb);
208   theSplit.Perform(theWOnS);
209   if (!theSplit.IsDone()) {
210     return;
211   }
212   // Mise a jour des descendants
213 //  for (TopExp_Explorer exp(mySb,TopAbs_FACE); exp.More(); exp.Next()) {
214   TopExp_Explorer exp(mySb,TopAbs_FACE) ;
215   for ( ; exp.More(); exp.Next()) {
216     myDescF.Bind(exp.Current(),theSplit.DescendantShapes(exp.Current()));
217   }
218
219   for (exp.Init(mySn,TopAbs_FACE); exp.More(); exp.Next()) {
220     TopTools_ListOfShape thelist;
221     myDescF.Bind(exp.Current(), thelist);
222     if (Contains(theGS->OrientedFaces(),exp.Current())) {
223       myDescF(exp.Current()).Append(exp.Current());
224     }
225   }
226
227   LocOpe_Generator theGen(theSplit.ResultingShape());
228   theGen.Perform(theGS);
229
230   myDone = theGen.IsDone();
231   if (myDone) {
232     myRes = theGen.ResultingShape();
233
234     AddEdges();
235
236     // Mise a jour des descendants
237     TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itd;
238     for (itd.Initialize(myDescF);
239          itd.More(); 
240          itd.Next()) {
241       TopTools_ListOfShape newDesc;
242       TopTools_ListIteratorOfListOfShape itl;
243       for (itl.Initialize(itd.Value());
244            itl.More();
245            itl.Next()) {
246         TopTools_ListIteratorOfListOfShape itl2
247           (theGen.DescendantFace(TopoDS::Face(itl.Value())));
248         for (; itl2.More(); itl2.Next()) {
249           const TopoDS_Face& descface =TopoDS::Face(itl2.Value());
250           if (!descface.IsNull()) { // sinon la face a disparu
251             newDesc.Append(descface);
252           }
253         }
254       }
255       myDescF(itd.Key()) = newDesc;
256     }
257   }
258
259   // recodage des regularites
260   TopTools_IndexedDataMapOfShapeListOfShape theMapEF1, theMapEF2;
261   TopExp::MapShapesAndAncestors(mySn,TopAbs_EDGE,TopAbs_FACE,theMapEF1);
262   TopExp::MapShapesAndAncestors(myRes,TopAbs_EDGE,TopAbs_FACE,theMapEF2);
263   
264   for (ind = 1; ind <= theMapEF1.Extent(); ind++) {
265     const TopoDS_Edge& edg = TopoDS::Edge(theMapEF1.FindKey(ind));
266     const TopTools_ListOfShape& LL = theMapEF1(ind);
267     if (LL.Extent() == 2) {
268       const TopoDS_Face& fac1 = TopoDS::Face(LL.First());
269       const TopoDS_Face& fac2 = TopoDS::Face(LL.Last());
270       GeomAbs_Shape thecont = BRep_Tool::Continuity(edg,fac1,fac2);
271       if (thecont >= GeomAbs_G1) {
272         // on essaie de recoder
273         Standard_Integer ind2 = theMapEF2.FindIndex(edg);
274         if (ind2 != 0) {
275           const TopTools_ListOfShape& LL2 = theMapEF2(ind2);
276           if (LL2.Extent() == 2) {
277             const TopoDS_Face& ff1 = TopoDS::Face(LL2.First());
278             const TopoDS_Face& ff2 = TopoDS::Face(LL2.Last());
279             if ((ff1.IsSame(fac1) && ff2.IsSame(fac2)) ||
280                 (ff1.IsSame(fac2) && ff2.IsSame(fac1))) {
281
282             }
283             else {
284               BRep_Builder B;
285               B.Continuity(edg, ff1,ff2,thecont);
286             }
287           }
288         }
289       } 
290     }
291   }  
292   //creation de la liste d`edge
293   theWOnS->InitEdgeIterator();
294   while(theWOnS->MoreEdge()) {
295     TopoDS_Edge edg = theWOnS->Edge();
296     for (ind = 1; ind <= theMapEF2.Extent(); ind++) {
297       const TopoDS_Edge& edg1 = TopoDS::Edge(theMapEF2.FindKey(ind));
298       if(edg1.IsSame(edg)) {
299         myEdges.Append(edg); 
300         // recodage eventuel des regularites sur cet edge
301         const TopTools_ListOfShape& L = theMapEF2(ind);
302         if (L.Extent() == 2) {
303           const TopoDS_Face& fac1 = TopoDS::Face(L.First());
304           const TopoDS_Face& fac2 = TopoDS::Face(L.Last());
305           if(LocOpe::TgtFaces(edg, fac1, fac2))  {
306             myTgtEdges.Append(edg);
307             GeomAbs_Shape thecont = BRep_Tool::Continuity(edg,fac1,fac2);
308             if (thecont < GeomAbs_G1) {
309               BRep_Builder B;
310               B.Continuity(edg, fac1,fac2,GeomAbs_G1);
311             }
312           }      
313         }
314       }
315     }
316     theWOnS->NextEdge();
317   }
318
319       // recodage eventuel des regularites sur cet edge
320 }
321
322
323
324
325 //=======================================================================
326 //function : DescendantFaces
327 //purpose  : 
328 //=======================================================================
329
330 const TopTools_ListOfShape& LocOpe_Gluer::DescendantFaces
331    (const TopoDS_Face& F) const
332 {
333   if (!myDone) {throw StdFail_NotDone();}
334   if (myDescF.IsBound(F))
335     return myDescF(F);
336   static TopTools_ListOfShape nullList;
337   return nullList;
338 }
339
340
341
342 //=======================================================================
343 //function : GetOrientation
344 //purpose  : 
345 //=======================================================================
346
347 static TopAbs_Orientation GetOrientation(const TopoDS_Face& Fn,
348                                          const TopoDS_Face& Fb)
349 {
350
351   Handle(Geom_Surface) Sn,Sb;
352   Sn = BRep_Tool::Surface(Fn);
353   Sb = BRep_Tool::Surface(Fb);
354   
355
356   // Find a point on Sb
357   TopExp_Explorer exp;
358   Standard_Real f,l;
359   gp_Pnt2d ptvtx;
360   gp_Pnt pvt;
361   gp_Vec d1u,d1v, n1,n2;
362
363
364   for (exp.Init(Fn,TopAbs_EDGE); exp.More(); exp.Next()) {
365     const TopoDS_Edge& edg = TopoDS::Edge(exp.Current());
366     Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(edg,Fn,f,l);
367     if (Precision::IsNegativeInfinite(f) && 
368         Precision::IsPositiveInfinite(l)) {
369       f = -100.;
370       l = 100.;
371     }
372     else if (Precision::IsNegativeInfinite(f)) {
373       f = l-200.;
374     }
375     else if (Precision::IsPositiveInfinite(l)) {
376       l = f+200.;
377     }
378     Standard_Real deltau = (l-f)/20.;
379     for (Standard_Integer i=1; i<=21; i++) {
380       C2d->D0(f+(i-1)*deltau,ptvtx);
381       Sn->D1(ptvtx.X(),ptvtx.Y(),pvt,d1u,d1v);
382       n1 = d1u.Crossed(d1v);
383       if (n1.Magnitude() > Precision::Confusion() ) {
384         n1.Normalize();
385         if (Fn.Orientation() == TopAbs_REVERSED) {
386           n1.Reverse();
387         }
388         
389         // Projection sur Sb
390         GeomAdaptor_Surface GAS(Sb);
391         Standard_Real TolU = GAS.UResolution(Precision::Confusion());
392         Standard_Real TolV = GAS.VResolution(Precision::Confusion());
393         Extrema_ExtPS dist(pvt,GAS,TolU,TolV);
394         if (dist.IsDone()) {
395           Standard_Real dist2min = RealLast();
396           Standard_Integer jmin = 0;
397           for (Standard_Integer j=1; j<=dist.NbExt(); j++) {
398             if (dist.SquareDistance(j)<dist2min) {
399               jmin = j;
400               dist2min = dist.SquareDistance(j);
401             }
402           }
403           if (jmin != 0) {
404             Standard_Real uu,vv;
405             dist.Point(jmin).Parameter(uu,vv);
406             Sb->D1(uu,vv,pvt,d1u,d1v);
407             n2 = d1u.Crossed(d1v);
408             if (n2.Magnitude() > Precision::Confusion()) {
409               n2.Normalize();
410               if (Fb.Orientation() == TopAbs_REVERSED) {
411                 n2.Reverse();
412               }
413               if (n1.Dot(n2) > 0.) {
414                 return TopAbs_REVERSED;
415               }
416               return TopAbs_FORWARD;
417             }
418           }
419         }
420       }
421     }
422   }
423   return TopAbs_INTERNAL;
424 }
425
426
427 //=======================================================================
428 //function : GetOrientation
429 //purpose  : 
430 //=======================================================================
431
432 static Standard_Boolean Contains(const TopTools_ListOfShape& L,
433                                  const TopoDS_Shape& S)
434 {
435   TopTools_ListIteratorOfListOfShape it;
436   for (it.Initialize(L);
437        it.More();
438        it.Next()) {
439     if (it.Value().IsSame(S)) {
440       return Standard_True;
441     }
442   }
443   return Standard_False;
444 }
445
446
447
448
449
450 //=======================================================================
451 //function : AddEdges
452 //purpose  : 
453 //=======================================================================
454
455 void LocOpe_Gluer::AddEdges()
456 {
457   TopExp_Explorer exp, expsb;
458   exp.Init(mySn, TopAbs_EDGE);
459
460   TopLoc_Location Loc;
461 //  Standard_Real l, f;
462   TopTools_IndexedMapOfShape MapV, MapFPrism, MapE;
463   TopExp_Explorer vexp;
464   Standard_Integer flag, i;
465
466   TopExp::MapShapes(mySn, TopAbs_FACE, MapFPrism);
467
468   for (expsb.Init(myRes, TopAbs_FACE); expsb.More(); expsb.Next()) {
469     if (!MapFPrism.Contains(expsb.Current())) {
470       MapV.Clear();
471       TopExp::MapShapes(expsb.Current(), TopAbs_VERTEX, MapV);
472       TopExp::MapShapes(expsb.Current(), TopAbs_EDGE, MapE);
473       for(exp.Init(mySn, TopAbs_EDGE); exp.More(); exp.Next()) {
474         TopoDS_Edge e = TopoDS::Edge(exp.Current());
475         if (MapE.Contains(e)) continue;
476         flag = 0;
477         vexp.Init(e, TopAbs_VERTEX);
478         for(; vexp.More(); vexp.Next()) {
479           TopoDS_Vertex v = TopoDS::Vertex(vexp.Current());
480           if (MapV.Contains(v)) { 
481             flag = 1;
482           }
483         }
484         if (flag == 1) {
485           
486           vexp.Init(e, TopAbs_VERTEX);
487           BRepExtrema_ExtPF ext;
488           ext.Initialize(TopoDS::Face(expsb.Current()));
489           flag = 0;
490           for(; vexp.More(); vexp.Next()) {
491             TopoDS_Vertex v = TopoDS::Vertex(vexp.Current());
492             if (!MapV.Contains(v)) { 
493               ext.Perform(v, TopoDS::Face(expsb.Current()));
494               if (!ext.IsDone() || ext.NbExt() == 0) { flag = 0; break;}
495               else {
496                 Standard_Real dist2min = ext.SquareDistance(1);
497                 for (i = 2; i <= ext.NbExt(); i++) {
498                   dist2min = Min(dist2min, ext.SquareDistance(i));
499                 }
500                 if (dist2min >= BRep_Tool::Tolerance(v) * BRep_Tool::Tolerance(v)) {
501                   flag = 0;
502                   break;
503                 }
504                 else flag = 1;
505               }
506             }
507             else flag = 1;
508           }       
509           if (flag == 1) {
510
511           }
512         }
513       }
514     }  
515   }
516
517
518 }
519