0030480: Visualization - Clear of Select3D_SensitiveGroup does not update internal...
[occt.git] / src / LocOpe / LocOpe_Pipe.cxx
1 // Created on: 1996-09-04
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 <BSplCLib.hxx>
21 #include <Geom_BSplineCurve.hxx>
22 #include <Geom_Curve.hxx>
23 #include <Geom_Plane.hxx>
24 #include <Geom_RectangularTrimmedSurface.hxx>
25 #include <Geom_Surface.hxx>
26 #include <GeomConvert.hxx>
27 #include <gp_Pln.hxx>
28 #include <LocOpe.hxx>
29 #include <LocOpe_BuildShape.hxx>
30 #include <LocOpe_Pipe.hxx>
31 #include <Precision.hxx>
32 #include <Standard_DomainError.hxx>
33 #include <Standard_NoSuchObject.hxx>
34 #include <TColgp_Array1OfPnt.hxx>
35 #include <TColStd_Array1OfInteger.hxx>
36 #include <TColStd_Array1OfReal.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_Wire.hxx>
44 #include <TopTools_DataMapOfShapeListOfShape.hxx>
45 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
46 #include <TopTools_ListIteratorOfListOfShape.hxx>
47 #include <TopTools_MapIteratorOfMapOfShape.hxx>
48 #include <TopTools_MapOfShape.hxx>
49
50 static TopAbs_Orientation Orientation(const TopoDS_Shape&,
51                                       const TopoDS_Shape&);
52
53
54 //=======================================================================
55 //function : LocOpe_Pipe
56 //purpose  : 
57 //=======================================================================
58
59 LocOpe_Pipe::LocOpe_Pipe(const TopoDS_Wire& Spine,
60                          const TopoDS_Shape& Profile) : 
61            myPipe(Spine,Profile)
62 {
63
64   TopoDS_Shape Result = myPipe.Shape();
65
66   // On enleve les faces generees par les edges de connexite du profile,
67   // et on fusionne les plans si possible
68
69   TopTools_IndexedDataMapOfShapeListOfShape theEFMap;
70   TopExp::MapShapesAndAncestors(Profile,TopAbs_EDGE,TopAbs_FACE,theEFMap);
71   TopExp_Explorer exp;
72   TopTools_ListOfShape Empty;
73   TopTools_ListIteratorOfListOfShape it;
74
75   TopTools_ListOfShape goodfaces;
76
77   for (Standard_Integer i=1; i<=theEFMap.Extent(); i++) { 
78     const TopoDS_Edge& edgpr = TopoDS::Edge(theEFMap.FindKey(i));
79     myMap.Bind(edgpr,Empty);
80     if (theEFMap(i).Extent() >= 2) {
81       // on ne prend pas les faces generees
82     }
83     else {
84       TopTools_MapOfShape MapFac; // on mappe les plans generes par cet edge
85       for (exp.Init(Spine,TopAbs_EDGE); exp.More(); exp.Next()) {
86         const TopoDS_Edge& edgsp = TopoDS::Edge(exp.Current());
87         TopoDS_Face resfac = myPipe.Face(edgsp,edgpr);
88         if (!resfac.IsNull()) {
89           Handle(Geom_Surface) P = BRep_Tool::Surface(resfac);
90           if (P->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
91             P = Handle(Geom_RectangularTrimmedSurface)::DownCast(P)->BasisSurface();
92           }
93           if (P->DynamicType() == STANDARD_TYPE(Geom_Plane)) {
94             MapFac.Add(resfac);
95           }
96           else {
97             myMap(edgpr).Append(resfac);
98             goodfaces.Append(resfac);
99           }
100         }
101       }
102       
103       // Chercher les composantes connexes sur cet ensemble de faces., avec meme
104       // support geometrique
105
106       TopTools_MapIteratorOfMapOfShape itm(MapFac);
107       if (MapFac.Extent() <= 1) { // un seul plan. Rien a faire
108         if (MapFac.Extent() == 1) {
109           myMap(edgpr).Append(itm.Key());
110           goodfaces.Append(itm.Key());
111         }
112         continue;
113       }
114       
115       while (MapFac.Extent() >= 2) {
116         itm.Reset();
117         TopTools_ListOfShape FacFuse;
118         TopoDS_Face FaceRef = TopoDS::Face(itm.Key());
119         FacFuse.Append(FaceRef);
120         Handle(Geom_Surface) P = BRep_Tool::Surface(FaceRef);
121         if (P->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
122           P = Handle(Geom_RectangularTrimmedSurface)::DownCast(P)->BasisSurface();
123         }
124         gp_Pln Plref = Handle(Geom_Plane)::DownCast(P)->Pln();
125         
126         for (itm.Next(); itm.More(); itm.Next()) {
127           P = BRep_Tool::Surface(TopoDS::Face(itm.Key()));
128           if (P->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
129             P = Handle(Geom_RectangularTrimmedSurface)::DownCast(P)->BasisSurface();
130           }
131           gp_Pln Pl = Handle(Geom_Plane)::DownCast(P)->Pln();
132           if (Pl.Axis().IsParallel(Plref.Axis(),Precision::Angular()) &&
133               Plref.Contains(Pl.Location(),Precision::Confusion())) {
134             FacFuse.Append(itm.Key());
135           }
136         }
137         
138         // FacFuse contient des faces de meme support. Il faut en faire 
139         // des composantes connexes
140         
141         while (FacFuse.Extent() >= 2) {
142           FaceRef = TopoDS::Face(FacFuse.First());
143           // Recuperer l'orientation
144           TopAbs_Orientation orref = Orientation(FaceRef,Result);
145           P = BRep_Tool::Surface(FaceRef);
146           if (P->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
147             P = Handle(Geom_RectangularTrimmedSurface)::DownCast(P)->BasisSurface();
148           }
149           Plref = Handle(Geom_Plane)::DownCast(P)->Pln();
150           gp_Dir Dirref(Plref.Axis().Direction());
151           if ((Plref.Direct() && orref == TopAbs_REVERSED) ||
152               (!Plref.Direct() && orref == TopAbs_FORWARD)) {
153             Dirref.Reverse();
154           }
155           
156           TopTools_MapOfShape MapEd;
157           for (exp.Init(FaceRef.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
158                exp.More(); exp.Next()) {
159             MapEd.Add(exp.Current());
160           }
161           
162           MapFac.Remove(FaceRef);
163           FacFuse.RemoveFirst(); // on enleve FaceRef
164           Standard_Boolean FaceToFuse = Standard_False;
165           Standard_Boolean MoreFound;
166           
167           
168           do {
169             MoreFound = Standard_False;
170             for (it.Initialize(FacFuse); it.More(); it.Next()) {
171               for (exp.Init(it.Value(),TopAbs_EDGE);
172                    exp.More(); exp.Next()) {
173                 if (MapEd.Contains(exp.Current())) {
174                   FaceToFuse = Standard_True;
175                   MoreFound = Standard_True;
176                   break;
177                 }
178               }
179               if (exp.More()) {
180                 break;
181               }
182             }
183             if (MoreFound) {
184               const TopoDS_Face& fac = TopoDS::Face(it.Value());
185               TopAbs_Orientation orrelat = Orientation(fac,Result);
186               Handle(Geom_Surface) OtherP = BRep_Tool::Surface(fac);
187               if (OtherP->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
188                 OtherP = Handle(Geom_RectangularTrimmedSurface)::
189                 DownCast(OtherP)->BasisSurface();
190               }
191               gp_Pln Pl = Handle(Geom_Plane)::DownCast(OtherP)->Pln();
192               gp_Dir Dirpl(Pl.Axis().Direction());
193               if ((Pl.Direct() && orrelat == TopAbs_REVERSED) ||
194             (!Plref.Direct() && orrelat == TopAbs_FORWARD)) {
195                 Dirpl.Reverse();
196               }
197               if (Dirpl.Dot(Dirref) > 0) {
198                 orrelat = TopAbs_FORWARD;
199               }
200               else {
201                 orrelat = TopAbs_REVERSED;
202               }
203               for (exp.Init(fac.Oriented(orrelat),TopAbs_EDGE);
204                    exp.More(); exp.Next()) {
205                 if (!MapEd.Add(exp.Current())) {
206                   MapEd.Remove(exp.Current());
207                 }
208               }     
209               MapFac.Remove(fac);
210               FacFuse.Remove(it);
211             }
212           } while (MoreFound);
213           
214           if (FaceToFuse) {
215             TopoDS_Face NewFace;
216             BRep_Builder B;
217             B.MakeFace(NewFace,P,BRep_Tool::Tolerance(FaceRef));
218             TopoDS_Wire NewWire;
219             B.MakeWire(NewWire);
220             for (TopTools_MapIteratorOfMapOfShape itm2(MapEd);
221                  itm2.More(); itm2.Next()) {
222               B.Add(NewWire,itm2.Key());
223             }
224             exp.Init(FaceRef.Oriented(TopAbs_FORWARD),TopAbs_WIRE);
225             NewWire.Orientation(exp.Current().Orientation());
226             B.Add(NewFace,NewWire);
227             myMap(edgpr).Append(NewFace);
228             goodfaces.Append(NewFace);
229           }
230         }
231         if (FacFuse.Extent() == 1) {
232           MapFac.Remove(FacFuse.First());
233           myMap(edgpr).Append(FacFuse.First());
234           goodfaces.Append(FacFuse.First());
235         }
236       }
237     }
238   }
239
240   for (exp.Init(myPipe.FirstShape(),TopAbs_FACE); exp.More(); exp.Next()) {
241     goodfaces.Append(exp.Current());
242   }
243   for (exp.Init(myPipe.LastShape(),TopAbs_FACE); exp.More(); exp.Next()) {
244     goodfaces.Append(exp.Current());
245   }
246
247   LocOpe_BuildShape BS(goodfaces);
248   myRes = BS.Shape();
249 }
250
251
252 //=======================================================================
253 //function : Shape
254 //purpose  : 
255 //=======================================================================
256
257 const TopoDS_Shape& LocOpe_Pipe::Shape () const
258 {
259   return myRes;
260 }
261
262
263 //=======================================================================
264 //function : Shapes
265 //purpose  : 
266 //=======================================================================
267
268 const TopTools_ListOfShape& LocOpe_Pipe::Shapes (const TopoDS_Shape& S)
269 {
270   TopAbs_ShapeEnum typS = S.ShapeType();
271   if (typS != TopAbs_EDGE && typS != TopAbs_VERTEX) {
272     throw Standard_DomainError();
273   }
274 //  for (TopExp_Explorer exp(myPipe.Profile(),typS); exp.More(); exp.Next()) {
275   TopExp_Explorer exp(myPipe.Profile(),typS) ;
276   for ( ; exp.More(); exp.Next()) {
277     if (exp.Current().IsSame(S)) {
278       break;
279     }
280   }
281   if (!exp.More()) {
282     throw Standard_NoSuchObject();
283   }
284
285   myGShap.Clear();
286   if (typS == TopAbs_VERTEX) {
287     const TopoDS_Vertex& VProfile = TopoDS::Vertex(S);
288     for (exp.Init(myPipe.Spine(),TopAbs_EDGE); exp.More(); exp.Next()) {
289       const TopoDS_Edge& edsp = TopoDS::Edge(exp.Current());
290       TopoDS_Edge resed = myPipe.Edge(edsp,VProfile);
291       if (!resed.IsNull()) {
292         myGShap.Append(resed);
293       }
294     }
295     return myGShap;
296   }
297   // TopAbs_EDGE
298   const TopoDS_Edge& EProfile = TopoDS::Edge(S);
299   return myMap(EProfile);
300 }
301
302
303 //=======================================================================
304 //function : GetCurves
305 //purpose  : 
306 //=======================================================================
307
308 const TColGeom_SequenceOfCurve& 
309     LocOpe_Pipe::Curves(const TColgp_SequenceOfPnt& Spt) 
310 {
311
312   myCrvs.Clear();
313   TopTools_MapOfShape Map;
314
315   Standard_Integer i , j , k , Nbpnt = Spt.Length();
316   Standard_Real p1,p2;
317 //  gp_Pnt ptbid;
318
319   for ( i = 1; i <= Nbpnt; i++) {
320     gp_Pnt P1 = Spt(i);
321     Standard_Integer MaxDeg = 0;
322     TColGeom_SequenceOfCurve seq;
323     TopoDS_Wire W = myPipe.PipeLine(P1);
324     
325     TopExp_Explorer ex(W, TopAbs_EDGE);
326     for (; ex.More(); ex.Next()) {
327       Handle(Geom_Curve) C1 = BRep_Tool::Curve(TopoDS::Edge(ex.Current()), p1, p2);
328       Handle(Geom_BSplineCurve) C = GeomConvert::CurveToBSplineCurve (C1);
329       if (C.IsNull()) {
330         continue;
331       }
332       MaxDeg = Max(MaxDeg,C->Degree());
333       P1 = C->Value(p2);
334       if (p1 != C->FirstParameter() || p2 != C->LastParameter()) {
335         C->Segment(p1,p2);
336       }
337       Standard_Integer Nbkn = C->NbKnots();
338       TColStd_Array1OfReal Tkn(1,Nbkn);
339       C->Knots(Tkn);
340       BSplCLib::Reparametrize(seq.Length(),seq.Length()+1,Tkn);
341       C->SetKnots(Tkn);
342       seq.Append(C);
343     }
344
345     Handle(Geom_Curve) newC;
346     Standard_Integer Nbkn=0 ,Nbp=0;
347     Standard_Integer Nbcurv = seq.Length();
348     if (Nbcurv == 0) {
349       myCrvs.Append(newC);
350       continue;
351     }
352
353     Handle(Geom_BSplineCurve) Bsp;
354     for (j=1; j<=Nbcurv; j++) {
355       Bsp = Handle(Geom_BSplineCurve)::DownCast(seq(j));
356       Bsp->IncreaseDegree(MaxDeg);
357       Nbp += Bsp->NbPoles();
358       Nbkn += Bsp->NbKnots();
359     }
360     Nbp  -= Nbcurv-1;
361     Nbkn -= Nbcurv-1;
362     TColStd_Array1OfReal Tkn(1,Nbkn);
363     TColStd_Array1OfInteger Tmu(1,Nbkn);
364     TColgp_Array1OfPnt Tpol(1,Nbp);
365     Standard_Integer Ik=0,Ip=0;
366
367     Bsp = Handle(Geom_BSplineCurve)::DownCast(seq(1));
368     for ( k = 1; k<= Bsp->NbPoles(); k++) {
369       Ip++;
370       Tpol(Ip) = Bsp->Pole(k);
371     }
372     for (k = 1; k<= Bsp->NbKnots(); k++) {
373       Ik++;
374       Tkn(Ik) = Bsp->Knot(k);
375       Tmu(Ik) = Bsp->Multiplicity(k);
376     }
377     Tmu(Ik)--;
378     
379     for (j=2; j<=Nbcurv; j++) {
380       Bsp = Handle(Geom_BSplineCurve)::DownCast(seq(j));
381       for (k = 2; k<= Bsp->NbPoles(); k++) {
382         Ip++;
383         Tpol(Ip) = Bsp->Pole(k);
384       }
385       for (k = 2; k<= Bsp->NbKnots(); k++) {
386         Ik++;
387         Tkn(Ik) = Bsp->Knot(k);
388         Tmu(Ik) = Bsp->Multiplicity(k);
389       }
390       Tmu(Ik)--;
391     }
392     Tmu(Ik)++;
393     newC = new Geom_BSplineCurve(Tpol,Tkn,Tmu,MaxDeg);
394     myCrvs.Append(newC);
395   }
396
397   return myCrvs;
398 }
399
400
401 //=======================================================================
402 //function : Orientation
403 //purpose  : static, not member
404 //=======================================================================
405
406 static TopAbs_Orientation Orientation(const TopoDS_Shape& Sub,
407                                      const TopoDS_Shape& S)
408 {
409   TopExp_Explorer exp;
410   for (exp.Init(S,Sub.ShapeType()); exp.More(); exp.Next()) {
411     if (exp.Current().IsSame(Sub)) {
412       return exp.Current().Orientation();
413     }
414   }
415   throw Standard_NoSuchObject();
416 }
417
418
419 //=======================================================================
420 //function : BarycCurve
421 //purpose  : 
422 //=======================================================================
423
424 Handle(Geom_Curve) LocOpe_Pipe::BarycCurve() 
425 {
426   Standard_Integer j , k ;
427
428   gp_Pnt bar(0., 0., 0.);
429   TColgp_SequenceOfPnt spt;
430   TopoDS_Shape Base = FirstShape();
431   LocOpe::SampleEdges(Base, spt);
432   for (Standard_Integer jj=1;jj<=spt.Length(); jj++) {
433     const gp_Pnt& pvt = spt(jj);
434     bar.ChangeCoord() += pvt.XYZ();
435   }
436   bar.ChangeCoord().Divide(spt.Length());
437
438   Standard_Real p1,p2;
439 //  gp_Pnt ptbid;
440   gp_Pnt P1 = bar;
441
442   Standard_Integer MaxDeg = 0;
443   TColGeom_SequenceOfCurve seq;  
444   TopoDS_Wire W = myPipe.PipeLine(P1);
445   
446   TopExp_Explorer ex(W, TopAbs_EDGE);
447   for (; ex.More(); ex.Next()) {
448     Handle(Geom_Curve) C1 = BRep_Tool::Curve(TopoDS::Edge(ex.Current()), p1, p2);
449     Handle(Geom_BSplineCurve) C = GeomConvert::CurveToBSplineCurve (C1);
450
451     if (C.IsNull()) {
452       continue;
453     }
454     MaxDeg = Max(MaxDeg,C->Degree());
455     P1 = C->Value(p2);
456     if (p1 != C->FirstParameter() || p2 != C->LastParameter()) {
457       C->Segment(p1,p2);
458     }
459     Standard_Integer Nbkn = C->NbKnots();
460     TColStd_Array1OfReal Tkn(1,Nbkn);
461     C->Knots(Tkn);
462     BSplCLib::Reparametrize(seq.Length(),seq.Length()+1,Tkn);
463       C->SetKnots(Tkn);
464     seq.Append(C);
465   }
466   Handle(Geom_Curve) newC;
467   Standard_Integer Nbkn=0 ,Nbp=0;
468   Standard_Integer Nbcurv = seq.Length();
469   if (Nbcurv == 0) {
470     myCrvs.Append(newC);
471   }
472   Handle(Geom_BSplineCurve) Bsp;
473   for ( j=1; j<=Nbcurv; j++) {
474     Bsp = Handle(Geom_BSplineCurve)::DownCast(seq(j));
475     Bsp->IncreaseDegree(MaxDeg);
476     Nbp += Bsp->NbPoles();
477     Nbkn += Bsp->NbKnots();
478   }
479   Nbp  -= Nbcurv-1;
480   Nbkn -= Nbcurv-1;
481   TColStd_Array1OfReal Tkn(1,Nbkn);
482   TColStd_Array1OfInteger Tmu(1,Nbkn);
483   TColgp_Array1OfPnt Tpol(1,Nbp);
484   Standard_Integer Ik=0,Ip=0;
485
486   Bsp = Handle(Geom_BSplineCurve)::DownCast(seq(1));
487   for ( k = 1; k<= Bsp->NbPoles(); k++) {
488     Ip++;
489     Tpol(Ip) = Bsp->Pole(k);
490   }
491   for (k = 1; k<= Bsp->NbKnots(); k++) {
492     Ik++;
493     Tkn(Ik) = Bsp->Knot(k);
494     Tmu(Ik) = Bsp->Multiplicity(k);
495   }
496   Tmu(Ik)--;
497   
498   for (j=2; j<=Nbcurv; j++) {
499     Bsp = Handle(Geom_BSplineCurve)::DownCast(seq(j));
500     for (k = 2; k<= Bsp->NbPoles(); k++) {
501       Ip++;
502         Tpol(Ip) = Bsp->Pole(k);
503     }
504       for (k = 2; k<= Bsp->NbKnots(); k++) {
505         Ik++;
506         Tkn(Ik) = Bsp->Knot(k);
507         Tmu(Ik) = Bsp->Multiplicity(k);
508       }
509     Tmu(Ik)--;
510   }
511   Tmu(Ik)++;
512   newC = new Geom_BSplineCurve(Tpol,Tkn,Tmu,MaxDeg);
513
514   return newC;
515 }
516
517