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