c20aec9e017bb88293e54539e1d700c38f17e0a5
[occt.git] / src / Approx / Approx_Curve3d.cxx
1 // File:        Approx_Curve3d.cxx
2 // Created:     Thu Aug 20 18:33:15 1998
3 // Author:      Philippe MANGIN
4 //              <pmn@sgi29>
5
6 #include <Approx_Curve3d.ixx>
7 #include <gp_Pnt.hxx>
8 #include <gp_Vec.hxx>
9 #include <GeomAdaptor_HCurve.hxx>
10 #include <TColStd_HArray1OfReal.hxx>
11 #include <AdvApprox_PrefAndRec.hxx>
12 #include <AdvApprox_ApproxAFunction.hxx>
13 #include <TColgp_Array1OfPnt.hxx>
14 #include <Precision.hxx>
15
16 //=======================================================================
17 //class : Approx_Curve3d_Eval
18 //purpose: evaluator class for approximation
19 //=======================================================================
20
21 class Approx_Curve3d_Eval : public AdvApprox_EvaluatorFunction
22 {
23  public:
24   Approx_Curve3d_Eval (const Handle(Adaptor3d_HCurve)& theFunc, 
25                        Standard_Real First, Standard_Real Last)
26     : fonct(theFunc) { StartEndSav[0] = First; StartEndSav[1] = Last; }
27   
28   virtual void Evaluate (Standard_Integer *Dimension,
29                          Standard_Real     StartEnd[2],
30                          Standard_Real    *Parameter,
31                          Standard_Integer *DerivativeRequest,
32                          Standard_Real    *Result, // [Dimension]
33                          Standard_Integer *ErrorCode);
34   
35  private:
36   Handle(Adaptor3d_HCurve) fonct;
37   Standard_Real StartEndSav[2];
38 };
39
40 void Approx_Curve3d_Eval::Evaluate (Standard_Integer *Dimension,
41                                     Standard_Real     StartEnd[2],
42                                     Standard_Real    *Param, // Parameter at which evaluation
43                                     Standard_Integer *Order, // Derivative Request
44                                     Standard_Real    *Result,// [Dimension]
45                                     Standard_Integer *ErrorCode)
46 {
47   *ErrorCode = 0;
48   Standard_Real par = *Param;
49
50 // Dimension is incorrect
51   if (*Dimension!=3) {
52     *ErrorCode = 1;
53   }
54
55   if(StartEnd[0] != StartEndSav[0] || StartEnd[1]!= StartEndSav[1]) 
56     {
57       fonct = fonct->Trim(StartEnd[0],StartEnd[1],Precision::PConfusion());
58       StartEndSav[0]=StartEnd[0];
59       StartEndSav[1]=StartEnd[1];
60     }
61
62   gp_Pnt pnt;
63   gp_Vec v1, v2;
64
65   switch (*Order) {
66   case 0:
67     pnt = fonct->Value(par);
68     Result[0] = pnt.X();
69     Result[1] = pnt.Y();
70     Result[2] = pnt.Z();
71     break;
72   case 1:
73     fonct->D1(par, pnt, v1);
74     Result[0] = v1.X();
75     Result[1] = v1.Y();
76     Result[2] = v1.Z();
77     break;
78   case 2:
79     fonct->D2(par, pnt, v1, v2);
80     Result[0] = v2.X();
81     Result[1] = v2.Y();
82     Result[2] = v2.Z();
83     break;
84   default:
85     Result[0] = Result[1] = Result[2] = 0.;
86     *ErrorCode = 3;
87     break;
88   }
89 }
90
91 Approx_Curve3d::Approx_Curve3d(const Handle(Adaptor3d_HCurve)& Curve,
92                                                  const Standard_Real Tol3d,
93                                                  const GeomAbs_Shape Order,
94                                                  const Standard_Integer MaxSegments,
95                                                  const Standard_Integer MaxDegree)
96 {
97   // Initialisation of input parameters of AdvApprox
98
99   Standard_Integer Num1DSS=0, Num2DSS=0, Num3DSS=1;
100   Handle(TColStd_HArray1OfReal) OneDTolNul, TwoDTolNul; 
101   Handle(TColStd_HArray1OfReal) ThreeDTol  = 
102     new TColStd_HArray1OfReal(1,Num3DSS);
103   ThreeDTol->Init(Tol3d); 
104
105   Standard_Real First = Curve->FirstParameter();
106   Standard_Real Last  = Curve->LastParameter();
107
108   Standard_Integer NbInterv_C2 = Curve->NbIntervals(GeomAbs_C2);
109   TColStd_Array1OfReal CutPnts_C2(1, NbInterv_C2+1);
110   Curve->Intervals(CutPnts_C2,GeomAbs_C2);
111   Standard_Integer NbInterv_C3 = Curve->NbIntervals(GeomAbs_C3);
112   TColStd_Array1OfReal CutPnts_C3(1, NbInterv_C3+1);
113   Curve->Intervals(CutPnts_C3,GeomAbs_C3);
114  
115   AdvApprox_PrefAndRec CutTool(CutPnts_C2,CutPnts_C3);
116
117   myMaxError = 0;
118
119   Approx_Curve3d_Eval ev (Curve, First, Last);
120   AdvApprox_ApproxAFunction aApprox (Num1DSS, Num2DSS, Num3DSS, 
121                                      OneDTolNul, TwoDTolNul, ThreeDTol,
122                                      First, Last, Order,
123                                      MaxDegree, MaxSegments,
124                                      ev, CutTool);
125
126   myIsDone = aApprox.IsDone();
127   myHasResult = aApprox.HasResult();
128
129   if (myHasResult) {
130     TColgp_Array1OfPnt Poles(1,aApprox.NbPoles());
131     aApprox.Poles(1,Poles);
132     Handle(TColStd_HArray1OfReal)    Knots = aApprox.Knots();
133     Handle(TColStd_HArray1OfInteger) Mults = aApprox.Multiplicities();
134     Standard_Integer Degree = aApprox.Degree();
135     myBSplCurve = new Geom_BSplineCurve(Poles, Knots->Array1(), Mults->Array1(), Degree);
136     myMaxError = aApprox.MaxError(3, 1);
137   } 
138 }
139
140  Handle(Geom_BSplineCurve) Approx_Curve3d::Curve() const
141 {
142   return myBSplCurve;
143 }
144
145  Standard_Boolean Approx_Curve3d::IsDone() const
146 {
147   return myIsDone; 
148 }
149
150  Standard_Boolean Approx_Curve3d::HasResult() const
151 {
152   return myHasResult; 
153 }
154
155  Standard_Real Approx_Curve3d::MaxError() const
156 {
157   return myMaxError;
158 }
159
160  void Approx_Curve3d::Dump(Standard_OStream& o) const
161 {
162   o << "******* Dump of ApproxCurve *******" << endl;
163   o << "*******Degree     " << Curve()->Degree() << endl;
164   o << "*******NbSegments " << Curve()->NbKnots() - 1 << endl;
165   o << "*******Error      " << MaxError() << endl;
166 }