0024920: Invalid result of Pipe construction
[occt.git] / src / BRepFill / BRepFill_ShapeLaw.cxx
1 // Created on: 1998-08-17
2 // Created by: Philippe MANGIN
3 // Copyright (c) 1998-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 #include <BRepFill_ShapeLaw.ixx>
18
19 #include <BRepTools_WireExplorer.hxx>
20 #include <BRep_Tool.hxx>
21 #include <BRepAdaptor_Curve.hxx>
22 #include <BRepLProp.hxx>
23 #include <TopExp.hxx>
24 #include <TopoDS.hxx>
25 #include <TopoDS_Vertex.hxx>
26
27 #include <Geom_Curve.hxx>
28 #include <Geom_Line.hxx>
29 #include <Geom_TrimmedCurve.hxx>
30 #include <Geom_BSplineCurve.hxx>
31 #include <GeomFill_UniformSection.hxx>
32 #include <GeomFill_EvolvedSection.hxx>
33 #include <GeomFill_HArray1OfSectionLaw.hxx>
34 #include <GeomConvert_CompCurveToBSplineCurve.hxx>
35
36 #include <TColgp_HArray1OfPnt.hxx>
37 #include <TColStd_HArray1OfReal.hxx>
38 #include <TColStd_HArray1OfInteger.hxx>
39
40 #include <Precision.hxx>
41 #include <BRepBuilderAPI_Transform.hxx>
42
43
44 //=======================================================================
45 //function : Create
46 //purpose  : Process the case of Vertex by constructing a line
47 //           with the vertex in the origin
48 //=======================================================================
49 BRepFill_ShapeLaw::BRepFill_ShapeLaw(const TopoDS_Vertex& V,
50                                          const Standard_Boolean Build) 
51                              : vertex(Standard_True),
52                                myShape(V)
53 {
54   TheLaw.Nullify();
55   uclosed = Standard_False;
56   vclosed = Standard_True; // constant law
57   myEdges =  new (TopTools_HArray1OfShape) (1, 1);
58   myEdges->SetValue(1, V);
59
60   if (Build) {
61     myLaws = new (GeomFill_HArray1OfSectionLaw) (1, 1); 
62 //    gp_Pnt Origine;
63     gp_Dir D(1,0,0); //Following the normal
64     Handle(Geom_Line) L = new (Geom_Line)(BRep_Tool::Pnt(V), D);
65     Standard_Real Last =  2*BRep_Tool::Tolerance(V)+Precision::PConfusion();
66     Handle(Geom_TrimmedCurve) TC = new (Geom_TrimmedCurve) (L, 0, Last);
67
68     myLaws->ChangeValue(1) = 
69       new (GeomFill_UniformSection)(TC);
70   }
71 }
72
73 //=======================================================================
74 //function : Create
75 //purpose  : Wire
76 //=======================================================================
77
78 BRepFill_ShapeLaw::BRepFill_ShapeLaw(const TopoDS_Wire& W,
79                                          const Standard_Boolean Build) 
80                                         : vertex(Standard_False),
81                                           myShape(W)
82                                           
83
84 {
85   TheLaw.Nullify();
86   Init(Build);
87 }
88
89 //=======================================================================
90 //function : Create
91 //purpose  : Evolutive Wire
92 //=======================================================================
93
94 BRepFill_ShapeLaw::BRepFill_ShapeLaw(const TopoDS_Wire& W,
95                                      const Handle(Law_Function)& L,
96                                      const Standard_Boolean Build) 
97                                         : vertex(Standard_False),
98                                           myShape(W)
99
100 {
101   TheLaw = L;
102   Init(Build);
103 }
104
105 //=======================================================================
106 //function : Init
107 //purpose  : Case of the wire : Create a table of GeomFill_SectionLaw
108 //=======================================================================
109 void BRepFill_ShapeLaw::Init(const Standard_Boolean Build)
110 {
111   vclosed = Standard_True;
112   BRepTools_WireExplorer wexp;
113   TopoDS_Edge E;
114   Standard_Integer NbEdge,ii;
115   Standard_Real First, Last;
116   TopoDS_Wire W;
117   W = TopoDS::Wire(myShape);
118
119   for (NbEdge=0, wexp.Init(W); wexp.More(); wexp.Next()) {
120     E = wexp.Current();
121     if( !E.IsNull() && !BRep_Tool::Degenerated(E)) {
122       Handle(Geom_Curve) C = BRep_Tool::Curve(E,First,Last);
123       if( !C.IsNull() ) {
124         NbEdge++;
125       }
126     }
127   }
128   
129   myLaws  = new GeomFill_HArray1OfSectionLaw (1, NbEdge);
130   myEdges = new TopTools_HArray1OfShape      (1, NbEdge);
131
132   ii = 1;
133   
134   for(wexp.Init(W); wexp.More(); wexp.Next()) {
135     E = wexp.Current();
136     if ( !E.IsNull() && !BRep_Tool::Degenerated(wexp.Current())) {
137       Handle(Geom_Curve) C = BRep_Tool::Curve(E,First,Last);
138       if( !C.IsNull() ) {
139         myEdges->SetValue(ii, E);
140         if(Build) {
141           //Handle(Geom_Curve) C = BRep_Tool::Curve(E,First,Last);
142           if (E.Orientation() == TopAbs_REVERSED) {
143             Standard_Real aux;
144             Handle(Geom_Curve) CBis;
145             CBis = C->Reversed(); // To avoid the deterioration of the topology
146             aux = C->ReversedParameter(First);
147             First = C->ReversedParameter(Last);
148             Last = aux;
149             C = CBis;
150           }
151
152           Standard_Boolean IsReallyClosed = E.Closed();
153           //IFV - some checking when closed flag is wrong
154           if(IsReallyClosed) {
155             TopoDS_Vertex V1, V2;
156             TopExp::Vertices(E, V1, V2);
157             if(V1.IsNull() || V2.IsNull()) {
158               IsReallyClosed = Standard_False;
159             }
160             else {
161               IsReallyClosed = V1.IsSame(V2);
162             }
163           }
164           if (IsReallyClosed &&
165               Abs(C->FirstParameter() - First) > Precision::PConfusion())
166             IsReallyClosed = Standard_False; //trimmed curve differs
167
168           if ((ii>1) || !IsReallyClosed ) { // Trim C
169             Handle(Geom_TrimmedCurve) TC = new Geom_TrimmedCurve(C,First, Last);
170             C = TC;
171           }
172           // otherwise preserve the integrity of the curve
173           if (TheLaw.IsNull()) {
174             myLaws->ChangeValue(ii) = new GeomFill_UniformSection(C);
175           }
176           else {
177             myLaws->ChangeValue(ii) = new GeomFill_EvolvedSection(C, TheLaw);
178           }
179         }
180         ii++;
181       }
182     }
183   }
184
185 //  cout << "new law" << endl;
186
187   //  Is the law closed by U ?
188   uclosed = W.Closed();
189   if (!uclosed) {
190     // if not sure about the flag, make check
191     TopoDS_Edge Edge1, Edge2;
192     TopoDS_Vertex V1,V2;
193     Edge1 = TopoDS::Edge (myEdges->Value(myEdges->Length()));
194     Edge2 = TopoDS::Edge (myEdges->Value(1));
195
196     if( Edge1.Orientation() == TopAbs_REVERSED) {
197       V1 = TopExp::FirstVertex(Edge1);
198     }
199     else {
200       V1 = TopExp::LastVertex(Edge1);
201     }
202
203     if ( Edge2.Orientation() == TopAbs_REVERSED) {
204       V2 = TopExp::LastVertex(Edge2);
205     }
206     else {
207       V2 = TopExp::FirstVertex(Edge2);
208     } 
209     if (V1.IsSame(V2)) {
210       uclosed = Standard_True;
211     }
212     else {
213       BRepAdaptor_Curve Curve1(Edge1);
214       BRepAdaptor_Curve Curve2(Edge2);
215       Standard_Real U1 = BRep_Tool::Parameter(V1,Edge1);
216       Standard_Real U2 = BRep_Tool::Parameter(V2,Edge2);
217       Standard_Real Eps = BRep_Tool::Tolerance(V2) + 
218                           BRep_Tool::Tolerance(V1);
219       
220       uclosed = Curve1.Value(U1).IsEqual(Curve2.Value(U2), Eps);
221     }
222   } 
223 }
224
225
226 //=======================================================================
227 //function : IsVertex
228 //purpose  :
229 //=======================================================================
230  Standard_Boolean BRepFill_ShapeLaw::IsVertex() const
231 {
232   return vertex;
233 }
234
235 //=======================================================================
236 //function : IsConstant
237 //purpose  :
238 //=======================================================================
239  Standard_Boolean BRepFill_ShapeLaw::IsConstant() const
240 {
241   return TheLaw.IsNull();
242 }
243
244 //=======================================================================
245 //function : Vertex
246 //purpose  : 
247 //=======================================================================
248  TopoDS_Vertex 
249  BRepFill_ShapeLaw::Vertex(const Standard_Integer Index, 
250                            const Standard_Real Param) const
251
252   TopoDS_Edge E;
253   TopoDS_Vertex V; 
254   if (Index <= myEdges->Length()) {
255     E =  TopoDS::Edge(myEdges->Value(Index));
256     if (E.Orientation() == TopAbs_REVERSED) 
257        V = TopExp::LastVertex(E);
258     else V = TopExp::FirstVertex(E);
259   }
260   else if (Index == myEdges->Length()+1) {
261     E =  TopoDS::Edge(myEdges->Value(Index-1));
262     if (E.Orientation() == TopAbs_REVERSED) 
263       V = TopExp::FirstVertex(E);
264     else V = TopExp::LastVertex(E);
265   }
266
267   if (!TheLaw.IsNull()) {    
268     gp_Trsf T;
269     T.SetScale(gp_Pnt(0, 0, 0), TheLaw->Value(Param));
270     //TopLoc_Location L(T);
271     //V.Move(L);
272     V = TopoDS::Vertex(BRepBuilderAPI_Transform(V, T));
273   }
274   return V;
275 }
276
277
278 ///=======================================================================
279 //function : VertexTol
280 //purpose  : Evaluate the hole between 2 edges of the section
281 //=======================================================================
282  Standard_Real BRepFill_ShapeLaw::VertexTol(const Standard_Integer Index,
283                                               const Standard_Real Param) const
284 {
285   Standard_Real Tol = Precision::Confusion();
286   Standard_Integer I1, I2;
287   if ( (Index==0) || (Index==myEdges->Length()) ) {
288     if (!uclosed) return Tol; //The least possible error
289     I1 = myEdges->Length();
290     I2 = 1;
291   }
292   else {
293     I1 = Index;
294     I2 = I1 +1;
295   } 
296
297   Handle(GeomFill_SectionLaw) Loi;
298   Standard_Integer NbPoles,  NbKnots, Degree;
299   Handle(TColgp_HArray1OfPnt) Poles;
300   Handle(TColStd_HArray1OfReal) Knots, Weigth;
301   Handle(TColStd_HArray1OfInteger) Mults;
302   Handle(Geom_BSplineCurve) BS;
303   gp_Pnt PFirst;
304
305   Loi = myLaws->Value(I1);
306   Loi->SectionShape( NbPoles,  NbKnots, Degree);
307   Poles = new (TColgp_HArray1OfPnt) (1, NbPoles);
308   Weigth = new  (TColStd_HArray1OfReal) (1, NbPoles);
309   Loi->D0(Param, Poles->ChangeArray1(), Weigth->ChangeArray1());
310   Knots = new  (TColStd_HArray1OfReal) (1, NbKnots);
311   Loi->Knots(Knots->ChangeArray1());
312   Mults = new (TColStd_HArray1OfInteger) (1, NbKnots);
313   Loi->Mults(Mults->ChangeArray1());
314   BS = new (Geom_BSplineCurve) (Poles->Array1(), 
315                                 Weigth->Array1(), 
316                                 Knots->Array1(), 
317                                 Mults->Array1(), 
318                                 Degree,
319                                 Loi->IsUPeriodic());
320   PFirst = BS->Value( Knots->Value(Knots->Length()) );
321
322   Loi = myLaws->Value(I2);
323   Loi->SectionShape( NbPoles,  NbKnots, Degree);
324   Poles = new (TColgp_HArray1OfPnt) (1, NbPoles);
325   Weigth = new  (TColStd_HArray1OfReal) (1, NbPoles);
326   Loi->D0(Param, Poles->ChangeArray1(), Weigth->ChangeArray1());
327   Knots = new  (TColStd_HArray1OfReal) (1, NbKnots);
328   Loi->Knots(Knots->ChangeArray1());
329   Mults = new (TColStd_HArray1OfInteger) (1, NbKnots);
330   Loi->Mults(Mults->ChangeArray1());
331   BS = new (Geom_BSplineCurve) (Poles->Array1(), 
332                                 Weigth->Array1(), 
333                                 Knots->Array1(), 
334                                 Mults->Array1(), 
335                                 Degree,
336                                 Loi->IsUPeriodic());
337   Tol += PFirst.Distance(BS->Value( Knots->Value(1)));
338   return Tol;
339 }
340
341 //=======================================================================
342 //function : ConcatenedLaw
343 //purpose  : 
344 //=======================================================================
345
346  Handle(GeomFill_SectionLaw) BRepFill_ShapeLaw::ConcatenedLaw() const
347 {
348   Handle(GeomFill_SectionLaw) Law;
349   if (myLaws->Length() == 1) 
350     return myLaws->Value(1);
351   else {
352     TopoDS_Wire W;
353     TopoDS_Vertex V;
354     W = TopoDS::Wire(myShape);
355     if(!W.IsNull()) {
356       //  Concatenation of edges
357       Standard_Integer ii;
358       Standard_Real epsV, f, l;
359       Standard_Boolean Bof;
360       Handle(Geom_Curve) Composite;
361       Handle(Geom_TrimmedCurve) TC;
362       Composite = BRep_Tool::Curve(Edge(1), f, l);
363       TC = new (Geom_TrimmedCurve)(Composite, f, l);
364       GeomConvert_CompCurveToBSplineCurve Concat(TC); 
365   
366       for (ii=2, Bof=Standard_True; ii<=myEdges->Length() && Bof; ii++){
367         Composite = BRep_Tool::Curve(Edge(ii),f, l);
368         TC = new (Geom_TrimmedCurve)(Composite, f, l);
369         Bof = TopExp::CommonVertex(Edge(ii-1), Edge(ii), V);
370         if (Bof) {epsV = BRep_Tool::Tolerance(V);}
371         else epsV = 10*Precision::PConfusion();
372         Bof = Concat.Add(TC, epsV, Standard_True, 
373                          Standard_False, 20);
374         if (!Bof) Bof = Concat.Add(TC, 200*epsV,
375                                    Standard_True, Standard_False, 20);
376 #if DEB
377         if (!Bof) 
378           cout << "BRepFill_ShapeLaw::ConcatenedLaw INCOMPLET !!!" 
379           << endl;
380 #endif
381       }
382       Composite = Concat.BSplineCurve();
383
384       if (TheLaw.IsNull()) {
385         Law = new (GeomFill_UniformSection)(Composite);
386       }
387       else {
388         Law = new (GeomFill_EvolvedSection)(Composite, TheLaw);
389       }
390     }
391   }
392   return Law;
393 }
394
395 //=======================================================================
396 //function : Continuity
397 //purpose  : 
398 //=======================================================================
399  GeomAbs_Shape BRepFill_ShapeLaw::Continuity(const Standard_Integer Index,
400                                                const Standard_Real TolAngular) const
401 {
402  
403   TopoDS_Edge Edge1, Edge2;
404   if ( (Index==0) || (Index==myEdges->Length()) ) {
405     if (!uclosed) return GeomAbs_C0; //The least possible error
406     
407     Edge1 = TopoDS::Edge (myEdges->Value(myEdges->Length()));
408     Edge2 = TopoDS::Edge (myEdges->Value(1));
409   }
410   else {
411     Edge1 = TopoDS::Edge (myEdges->Value(Index));
412     Edge2 = TopoDS::Edge (myEdges->Value(Index+1));
413   } 
414   
415   TopoDS_Vertex V1,V2; //common vertex
416   TopoDS_Vertex vv1, vv2, vv3, vv4;
417   TopExp::Vertices(Edge1, vv1, vv2);
418   TopExp::Vertices(Edge2, vv3, vv4);
419   if (vv1.IsSame(vv3))
420   { V1 = vv1; V2 = vv3; }
421   else if (vv1.IsSame(vv4))
422   { V1 = vv1; V2 = vv4; }
423   else if (vv2.IsSame(vv3))
424   { V1 = vv2; V2 = vv3; }
425   else
426   { V1 = vv2; V2 = vv4; }
427
428  Standard_Real U1 = BRep_Tool::Parameter(V1,Edge1);
429  Standard_Real U2 = BRep_Tool::Parameter(V2,Edge2);
430  BRepAdaptor_Curve Curve1(Edge1);
431  BRepAdaptor_Curve Curve2(Edge2);
432  Standard_Real Eps = BRep_Tool::Tolerance(V2) +
433                      BRep_Tool::Tolerance(V1);
434  GeomAbs_Shape cont;
435  cont = BRepLProp::Continuity(Curve1,Curve2,U1,U2, Eps, TolAngular);
436
437  return cont;
438 }
439
440 //=======================================================================
441 //function : D0
442 //purpose  : 
443 //=======================================================================
444  void BRepFill_ShapeLaw::D0(const Standard_Real U, TopoDS_Shape& S)
445 {
446   S = myShape;
447   if (!TheLaw.IsNull()) {
448     gp_Trsf T;
449     T.SetScale(gp_Pnt(0, 0, 0), TheLaw->Value(U));
450     //TopLoc_Location L(T);
451     //S.Move(L);
452     S = BRepBuilderAPI_Transform(S, T);
453   }
454