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 
LocOpe_Pipe(const TopoDS_Wire & Spine,const TopoDS_Shape & Profile)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 
Shape() const257 const TopoDS_Shape& LocOpe_Pipe::Shape () const
258 {
259   return myRes;
260 }
261 
262 
263 //=======================================================================
264 //function : Shapes
265 //purpose  :
266 //=======================================================================
267 
Shapes(const TopoDS_Shape & S)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&
Curves(const TColgp_SequenceOfPnt & Spt)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 
Orientation(const TopoDS_Shape & Sub,const TopoDS_Shape & S)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 
Handle(Geom_Curve)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 
518