d211b635ec2b558bfcdcf11484fb0e141078771c
[occt.git] / src / BOP / BOP_WireEdgeSet.cxx
1 // Created on: 1993-06-17
2 // Created by: Jean Yves LEBEY
3 // Copyright (c) 1993-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 // modified by NIZNHY-PKV 
22
23 #include <BOP_WireEdgeSet.ixx>
24
25 #include <Standard_ProgramError.hxx>
26
27 #include <Precision.hxx>
28
29 #include <gp_Vec.hxx>
30 #include <gp_Vec2d.hxx>
31 #include <gp_Pnt2d.hxx>
32 #include <gp_Dir2d.hxx>
33
34 #include <Geom2d_Curve.hxx>
35 #include <Geom2d_Line.hxx>
36 #include <Geom_Curve.hxx>
37 #include <Geom_Surface.hxx>
38 #include <GeomAbs_SurfaceType.hxx>
39 #include <GeomAbs_CurveType.hxx>
40 #include <GeomAPI_ProjectPointOnSurf.hxx>
41
42 #include <BRep_Tool.hxx>
43 #include <BRepAdaptor_Surface.hxx>
44 #include <BRepAdaptor_Curve.hxx>
45
46 #include <TopoDS.hxx>
47 #include <TopAbs.hxx>
48 #include <TopExp_Explorer.hxx>
49
50 #include <BOPTools_Tools2D.hxx>
51
52 // modified by NIZHNY-MKK  Fri May 30 10:18:01 2003.BEGIN
53 #include <TopTools_IndexedMapOfShape.hxx>
54 #include <TopExp.hxx>
55 #include <BOPTools_Tools3D.hxx>
56
57 static void GetOrientationVOnE(const TopoDS_Shape& V,
58                                const TopoDS_Shape& E1,
59                                const TopoDS_Shape& E2,
60                                TopAbs_Orientation& o1,
61                                TopAbs_Orientation& o2);
62 // modified by NIZHNY-MKK  Fri May 30 10:18:03 2003.END
63
64 //=======================================================================
65 //function : BOP_WireEdgeSet::BOP_WireEdgeSet
66 //purpose  : 
67 //=======================================================================
68   BOP_WireEdgeSet::BOP_WireEdgeSet()
69 :
70   BOP_ShapeSet(TopAbs_VERTEX)
71 {
72 }
73 //=======================================================================
74 //function : BOP_WireEdgeSet::BOP_WireEdgeSet
75 //purpose  : 
76 //=======================================================================
77   BOP_WireEdgeSet::BOP_WireEdgeSet(const TopoDS_Face& F)
78
79   BOP_ShapeSet(TopAbs_VERTEX),
80   myFace(F)
81 {
82 }
83
84 //=======================================================================
85 //function : Initialize
86 //purpose  : 
87 //=======================================================================
88   void BOP_WireEdgeSet::Initialize(const TopoDS_Face& F)
89 {
90   myFace=F;
91 }
92
93 //=======================================================================
94 //function : AddShape
95 //purpose  : 
96 //=======================================================================
97   void BOP_WireEdgeSet::AddShape(const TopoDS_Shape& S)
98 {
99   ProcessAddShape(S);
100 }
101
102 //=======================================================================
103 //function : AddStartElement
104 //purpose  : 
105 //=======================================================================
106   void BOP_WireEdgeSet::AddStartElement(const TopoDS_Shape& S)
107 {
108   ProcessAddStartElement(S);
109 }
110
111 //=======================================================================
112 //function : AddElement
113 //purpose  : 
114 //=======================================================================
115   void BOP_WireEdgeSet::AddElement(const TopoDS_Shape& S)
116 {
117   BOP_ShapeSet::AddElement(S);
118 }
119
120 //=======================================================================
121 //function : InitNeighbours
122 //purpose  : 
123 //=======================================================================
124   void  BOP_WireEdgeSet::InitNeighbours(const TopoDS_Shape& E)
125 {
126   mySubShapeExplorer.Init(E,mySubShapeType);
127   myCurrentShape = E;
128
129   FindNeighbours();
130 }
131
132
133 //=======================================================================
134 //function : FindNeighbours
135 //purpose  : 
136 //=======================================================================
137   void BOP_WireEdgeSet::FindNeighbours()
138 {
139   while (mySubShapeExplorer.More()) {
140     
141     // l = list of edges neighbour of edge myCurrentShape trough
142     // the vertex mySubShapeExplorer.Current(), which is a vertex of the
143     // edge myCurrentShape.
144     const TopoDS_Shape& V = mySubShapeExplorer.Current();
145     
146     const TopTools_ListOfShape & l = 
147       MakeNeighboursList(myCurrentShape, V);
148
149     // myIncidentShapesIter iterates on the neighbour edges of the edge
150     // given as InitNeighbours() argument (this edge has been stored 
151     // in the field myCurrentShape).
152
153     myIncidentShapesIter.Initialize(l);
154     if (myIncidentShapesIter.More()) {
155       break;
156     }
157     else{
158       mySubShapeExplorer.Next();
159     }
160   }
161 }
162
163 //=======================================================================
164 //function : MakeNeighboursList
165 //purpose  : find edges connected to Earg by Varg 
166 //=======================================================================
167   const TopTools_ListOfShape & BOP_WireEdgeSet::MakeNeighboursList(const TopoDS_Shape& Earg,
168                                                                    const TopoDS_Shape& Varg)
169 {
170   const TopoDS_Edge&   E = TopoDS::Edge(Earg);
171   const TopoDS_Vertex& V = TopoDS::Vertex(Varg);
172
173   const TopTools_ListOfShape& l = mySubShapeMap.FindFromKey(Varg);
174
175   Standard_Integer nclosing = NbClosingShapes(l);
176   if (nclosing) { 
177     // build myCurrentShapeNeighbours = 
178     // edge list made of connected shapes to Earg through Varg
179     myCurrentShapeNeighbours.Clear();
180     
181     Standard_Integer iapp = 0;
182     for (TopTools_ListIteratorOfListOfShape it(l); it.More(); it.Next()) {
183       iapp++;
184       const TopoDS_Shape& curn = it.Value(); // current neighbour
185       Standard_Boolean k = VertexConnectsEdgesClosing(Varg, Earg, curn);
186       if (k) {
187         myCurrentShapeNeighbours.Append(curn);
188       }
189     }
190
191     Standard_Integer newn = NbClosingShapes(myCurrentShapeNeighbours);
192     if (newn >= 2 ) {
193
194       const TopoDS_Face& F = myFace;
195       // several sewing edges connected to E by V such as :
196       // orientation of V in E # orientation of V in its edges.
197       // one leaves among the connected sewing edges,
198       // only edge A that checks tg(E) ^ tg(A) > 0
199
200       TopAbs_Orientation Eori;
201       gp_Vec2d d1E; gp_Pnt2d pE;
202       Standard_Real fiE, laE, tolpc, parE;
203       
204       parE = BRep_Tool::Parameter(V,E);
205       
206       Handle(Geom2d_Curve) PCE;
207       BOPTools_Tools2D::CurveOnSurface(E, F, PCE, fiE, laE, tolpc, Standard_False);
208
209       if (!PCE.IsNull()){
210         PCE->D1(parE, pE, d1E);
211       }
212       else  {
213         LocalD1 (F, E, V, pE, d1E);
214       }
215
216       Eori = E.Orientation();
217       if (Eori == TopAbs_REVERSED) {
218         d1E.Reverse();
219       }
220
221       TopTools_ListIteratorOfListOfShape lclo(myCurrentShapeNeighbours);
222       Standard_Integer rang = 0;
223       while (lclo.More()) {
224         rang++;
225
226         if ( ! IsClosed(lclo.Value()) ) {
227           lclo.Next();
228           continue;
229         }
230
231         const TopoDS_Edge& EE = TopoDS::Edge(lclo.Value());
232         Standard_Real parEE,  fiEE, laEE, tolpcc;
233         gp_Vec2d d1EE; gp_Pnt2d pEE;
234         
235         parEE = BRep_Tool::Parameter(V,EE);
236         
237         Handle(Geom2d_Curve) PCEE;
238         BOPTools_Tools2D::CurveOnSurface (EE, F, PCEE, fiEE, laEE, tolpcc, Standard_False);//
239         //
240         if (!PCEE.IsNull()) {
241           PCEE->D1(parEE,pEE,d1EE);
242         
243         }
244         else {
245           LocalD1(F, EE, V, pEE, d1EE);
246         }
247
248         TopAbs_Orientation EEori = EE.Orientation();
249         if (EEori == TopAbs_REVERSED) d1EE.Reverse();
250
251         Standard_Real cross = d1E.Crossed(d1EE);
252         TopAbs_Orientation oVE,oVEE;
253
254         // modified by NIZHNY-MKK  Fri May 30 10:17:10 2003.BEGIN
255         GetOrientationVOnE(V,E,EE,oVE,oVEE);
256 //      VertexConnectsEdges(V,E,EE,oVE,oVEE);
257         // modified by NIZHNY-MKK  Fri May 30 10:17:13 2003.END
258
259         Standard_Boolean t2 = ( (cross > 0) && oVE == TopAbs_REVERSED ) ||
260                               ( (cross < 0) && oVE == TopAbs_FORWARD );
261
262         if ( t2 ) { //-- t1
263           // this is proper IsClosed, only it is preserved among IsClosed 
264           lclo.Next();
265         }
266         else {
267           // edge IsClosed is suspended
268           myCurrentShapeNeighbours.Remove(lclo);
269         }
270       }// end of while (lclo.More())
271     }// end of if (newn >= 2 )
272     return myCurrentShapeNeighbours;
273   }// end of if (nclosing)
274
275   else {
276     return l;
277   }
278 } // MakeNeighoursList
279
280 //=======================================================================
281 //function : VertexConnectsEdges
282 //purpose  : 
283 //=======================================================================
284   Standard_Boolean BOP_WireEdgeSet::VertexConnectsEdges(const TopoDS_Shape& V,
285                                                         const TopoDS_Shape& E1,
286                                                         const TopoDS_Shape& E2,
287                                                         TopAbs_Orientation& o1,
288                                                         TopAbs_Orientation& o2) const
289 {
290   TopExp_Explorer ex1, ex2;
291   ex1.Init(E1,TopAbs_VERTEX);
292   for(; ex1.More(); ex1.Next()) {
293     
294     if (V.IsSame(ex1.Current())) {
295       ex2.Init(E2,TopAbs_VERTEX);
296       for(; ex2.More(); ex2.Next()) {
297         
298         if (V.IsSame(ex2.Current())) {
299           o1 = ex1.Current().Orientation();
300           o2 = ex2.Current().Orientation();
301           if ( o1 != o2 ) {
302             return Standard_True;
303           }
304         }
305       }
306     }
307   }
308   return Standard_False;
309 }
310
311
312 //=======================================================================
313 //function : VertexConnectEdgesClosing
314 //purpose  : 
315 //=======================================================================
316   Standard_Boolean BOP_WireEdgeSet::VertexConnectsEdgesClosing(const TopoDS_Shape& V, 
317                                                                const TopoDS_Shape& E1, 
318                                                                const TopoDS_Shape& E2) const
319 {
320 //  Let S the set of incident edges on vertex V.
321 //  S contains at least one closed edge on the periodic face to build.
322 // (the face implied in closing test of edge is myFace)
323 //  E1,E2 are S shapes (sharing V).
324 //  
325 //  if E1 and E2 are not closed : edges are NOT connected
326 //  if E1 or E2 is/are closed :
327 //    if V changes of relative orientation between E1,E2 : edges are connected
328 //    else : edges are NOT connected
329 //  
330 //  example with E1 NOT closed, E2 closed :
331 //
332 //  E1 FORWARD, V REVERSED on E1 
333 //  E2 FORWARD, V FORWARD on E2       --> edges are connected
334 //
335 //  E1 FORWARD, V REVERSED on E1 
336 //  E2 REVERSED, V FORWARD on E2      --> edges are NOT connected
337 //-----------------------------------------------------------------------
338
339   Standard_Boolean c1 = IsClosed(E1);
340   Standard_Boolean c2 = IsClosed(E2);
341
342   Standard_Boolean testconnect = c1 || c2;
343   Standard_Boolean resu = Standard_False;
344   TopAbs_Orientation o1,o2;
345
346   // SSCONNEX = False ==> E2 is  selected to create as many 
347   // (default)           faces as there are components connected in UV.
348   // SSCONNEX = True ==> the entire edge E2 sharing V with E1 is taken
349   //                     so that orientation(V/E1) # orientation(V/E2)
350   //                     ==> face of part and other sewings
351   if ((c1 && c2)) {
352     Standard_Boolean u1 = c1 ? IsUClosed(E1) : Standard_False; 
353     Standard_Boolean v1 = c1 ? IsVClosed(E1) : Standard_False; 
354     Standard_Boolean u2 = c2 ? IsUClosed(E2) : Standard_False; 
355     Standard_Boolean v2 = c2 ? IsVClosed(E2) : Standard_False; 
356     Standard_Boolean uvdiff = (u1 && v2) || (u2 && v1);
357     testconnect = uvdiff;
358   }
359
360   if (testconnect) {
361     resu = VertexConnectsEdges(V,E1,E2,o1,o2);
362   }
363   else { 
364     // cto 012 O2 sewing edge of cylindric face
365     // chain of components split ON and OUT of the same orientation
366     TopAbs_Orientation oe1 = E1.Orientation();
367     TopAbs_Orientation oe2 = E2.Orientation();
368     Standard_Boolean iseq = E1.IsEqual(E2);
369     if ( (c1 && c2) && (oe1 == oe2) && (!iseq) ) {
370       resu = VertexConnectsEdges(V,E1,E2,o1,o2);
371     }
372   }
373   return resu;
374 }
375
376 //=======================================================================
377 //function : NbClosingShapes
378 //purpose  : 
379 //=======================================================================
380   Standard_Integer BOP_WireEdgeSet::NbClosingShapes(const TopTools_ListOfShape & L) const
381 {
382   Standard_Integer n = 0;
383   TopTools_ListIteratorOfListOfShape it(L);
384   for ( ; it.More(); it.Next()) {
385     const TopoDS_Shape& S = it.Value();
386     if ( IsClosed(S) ) {
387       n++;
388     }
389   }
390   return n;
391 }
392
393 //=======================================================================
394 //function : LocalD1
395 //purpose  : 
396 //=======================================================================
397   void BOP_WireEdgeSet::LocalD1(const TopoDS_Face&  F,
398                                 const TopoDS_Edge&  E,
399                                 const TopoDS_Vertex& V,
400                                 gp_Pnt2d& ,//pE, 
401                                 gp_Vec2d& d1E) const
402 {
403   TopLoc_Location Loc;
404   Standard_Real parE, fiE, laE, u, v;
405   
406   parE = BRep_Tool::Parameter(V,E);
407    
408   Handle(Geom_Curve) CE = BRep_Tool::Curve(E, Loc, fiE, laE);
409   CE = Handle(Geom_Curve)::DownCast(CE->Transformed(Loc.Transformation()));
410   
411   gp_Pnt p3dE; gp_Vec d3dE;
412   CE->D1(parE, p3dE, d3dE);
413   
414   Handle(Geom_Surface) S = BRep_Tool::Surface(F);
415   GeomAPI_ProjectPointOnSurf proj(p3dE,S);
416  
417   proj.LowerDistanceParameters(u,v);
418   gp_Pnt bid; 
419   gp_Vec d1u,d1v;
420   S->D1(u,v,bid,d1u,d1v);
421   u = d3dE.Dot(d1u);
422   v = d3dE.Dot(d1v);
423   d1E.SetCoord(u,v);
424 }
425
426 //=======================================================================
427 //function : IsClosed
428 //purpose  : 
429 //=======================================================================
430   Standard_Boolean BOP_WireEdgeSet::IsClosed(const TopoDS_Shape& E) const
431 {
432   const TopoDS_Edge& EE = TopoDS::Edge(E);
433   Standard_Boolean closed = BRep_Tool::IsClosed(EE,myFace);
434
435   // modified by NIZHNY-MKK  Wed May 12 15:44:10 2004.BEGIN
436   if(closed) {
437     TopoDS_Edge aE1, aE2;
438     BOPTools_Tools3D::GetSeam (myFace, aE1, aE2);
439
440     if(aE1.IsNull() || aE2.IsNull()) {
441       closed = Standard_False;
442     }
443   }
444   // modified by NIZHNY-MKK  Wed May 12 15:44:14 2004.END
445
446   return closed;
447 }
448
449 //=======================================================================
450 //function : IsUVISO
451 //purpose  : 
452 //=======================================================================
453   void BOP_WireEdgeSet::IsUVISO(const TopoDS_Edge& E,
454                                 const TopoDS_Face& F,
455                                 Standard_Boolean& uiso,
456                                 Standard_Boolean& viso) 
457 {
458   uiso = viso = Standard_False;
459   Standard_Real fE, lE,tolpc;
460   
461   Handle(Geom2d_Curve) PC;
462   BOPTools_Tools2D::CurveOnSurface (E, F, PC, fE, lE, tolpc, Standard_False);//
463   
464   if (PC.IsNull()) {
465     Standard_ProgramError::Raise("BOP_WireEdgeSet::IsUVISO");
466   }
467   
468   Handle(Standard_Type) TheType = PC->DynamicType();
469   if (TheType == STANDARD_TYPE(Geom2d_Line)) {
470     const Handle(Geom2d_Line)& HL = *((Handle(Geom2d_Line)*)&PC);
471     const gp_Dir2d&  D = HL->Direction();
472     Standard_Real    tol = Precision::Angular();
473     if      (D.IsParallel(gp_Dir2d(0.,1.),tol)) {
474       uiso = Standard_True;
475     }    
476     else if (D.IsParallel(gp_Dir2d(1.,0.),tol)) {
477       viso = Standard_True;
478     }
479   }
480 }
481
482 //=======================================================================
483 //function : IsUClosed
484 //purpose  : 
485 //=======================================================================
486   Standard_Boolean BOP_WireEdgeSet::IsUClosed(const TopoDS_Shape& E) const
487 {
488   const TopoDS_Edge& EE = TopoDS::Edge(E);
489
490   Standard_Boolean bid, closed;
491   IsUVISO(EE, myFace, closed, bid);
492   return closed;
493 }
494
495
496 //=======================================================================
497 //function : IsVClosed
498 //purpose  : 
499 //=======================================================================
500   Standard_Boolean BOP_WireEdgeSet::IsVClosed(const TopoDS_Shape& E) const
501 {
502   const TopoDS_Edge& EE = TopoDS::Edge(E);
503
504   Standard_Boolean bid, closed;
505   IsUVISO (EE, myFace, bid, closed);
506   return closed;
507 }
508
509 //=======================================================================
510 //function : Face
511 //purpose  : 
512 //=======================================================================
513   const TopoDS_Face& BOP_WireEdgeSet::Face() const 
514 {
515   return myFace;
516 }
517 //=======================================================================
518 //function : BOP_Tools::KeptTwice
519 //purpose  : 
520 //=======================================================================
521   Standard_Boolean BOP_WireEdgeSet::KeptTwice (const TopoDS_Edge& aSpEF2) const
522                                          
523
524 {
525   Standard_Integer iCnt=0;
526
527   const TopTools_ListOfShape& aWESList=StartElements();
528
529   TopTools_ListIteratorOfListOfShape anIt(aWESList);
530   for (; anIt.More(); anIt.Next()) {
531     const TopoDS_Shape& aSS=anIt.Value();
532     if (aSpEF2.IsSame(aSS)) {
533       iCnt++;
534       if (iCnt > 1) {
535         return Standard_True;
536       }
537     }
538   }
539  return Standard_False;
540 }
541 //=======================================================================
542 //function : BOP_Tools::RemoveEdgeFromWES
543 //purpose  : 
544 //=======================================================================
545   void BOP_WireEdgeSet::RemoveEdgeFromWES(const TopoDS_Edge& aSpEF2)
546                                     
547 {
548   TopTools_ListOfShape aTmpList;
549   aTmpList=StartElements();
550   
551   ClearContents();
552
553   TopTools_ListIteratorOfListOfShape anIt(aTmpList);
554   for (; anIt.More(); anIt.Next()) {
555     const TopoDS_Shape& aSS=anIt.Value();
556     if (!aSpEF2.IsEqual(aSS)) {
557       AddStartElement(aSS);
558     }
559   }
560 }
561
562
563 // modified by NIZHNY-MKK  Fri May 30 10:18:38 2003.BEGIN
564 void GetOrientationVOnE(const TopoDS_Shape& V,
565                         const TopoDS_Shape& E1,
566                         const TopoDS_Shape& E2,
567                         TopAbs_Orientation& o1,
568                         TopAbs_Orientation& o2) {
569   TopTools_IndexedMapOfShape aMap;
570
571   TopExp::MapShapes(E1, TopAbs_VERTEX, aMap);
572   TopExp::MapShapes(E2, TopAbs_VERTEX, aMap);
573
574   if(aMap.Extent() > 1) {
575     TopExp_Explorer ex1, ex2;
576     ex1.Init(E1,TopAbs_VERTEX);
577
578     for(; ex1.More(); ex1.Next()) {
579     
580       if (V.IsSame(ex1.Current())) {
581         ex2.Init(E2,TopAbs_VERTEX);
582
583         for(; ex2.More(); ex2.Next()) {
584
585           if (V.IsSame(ex2.Current())) {
586             o1 = ex1.Current().Orientation();
587             o2 = ex2.Current().Orientation();
588
589             if ( o1 != o2 ) {
590               return;
591             }
592           }
593         }
594       }
595     }
596   }
597   else {
598     TopoDS_Shape VV = V;
599
600     if(E1.Orientation() == TopAbs_REVERSED)
601       VV.Reverse();
602     o1 = VV.Orientation();
603     VV.Reverse();
604     o2 = VV.Orientation();
605   }
606   return;
607 }
608 // modified by NIZHNY-MKK  Fri May 30 10:18:40 2003.END