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