b311480e |
1 | // Created on: 1997-10-06 |
2 | // Created by: Roman BORISOV |
3 | // Copyright (c) 1997-1999 Matra Datavision |
973c2be1 |
4 | // Copyright (c) 1999-2014 OPEN CASCADE SAS |
b311480e |
5 | // |
973c2be1 |
6 | // This file is part of Open CASCADE Technology software library. |
b311480e |
7 | // |
d5f74e42 |
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 |
973c2be1 |
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. |
b311480e |
13 | // |
973c2be1 |
14 | // Alternatively, this file may be used under the terms of Open CASCADE |
15 | // commercial license or contractual agreement. |
7fd59977 |
16 | |
17 | #include <Precision.hxx> |
18 | #include <Approx_CurveOnSurface.ixx> |
19 | #include <gp_Pnt.hxx> |
20 | #include <gp_Vec.hxx> |
21 | #include <GeomAdaptor_HSurface.hxx> |
22 | #include <Adaptor3d_CurveOnSurface.hxx> |
23 | #include <TColStd_HArray1OfReal.hxx> |
24 | #include <AdvApprox_ApproxAFunction.hxx> |
25 | #include <Adaptor3d_HCurve.hxx> |
26 | #include <TColgp_Array1OfPnt.hxx> |
27 | #include <GeomAdaptor_HCurve.hxx> |
28 | #include <Geom2dAdaptor_HCurve.hxx> |
29 | #include <Adaptor3d_HCurveOnSurface.hxx> |
30 | #include <TColgp_Array1OfPnt2d.hxx> |
31 | #include <TColStd_Array1OfReal.hxx> |
32 | #include <AdvApprox_PrefAndRec.hxx> |
33 | #include <AdvApprox_DichoCutting.hxx> |
34 | |
35 | //======================================================================= |
36 | //class : Approx_CurveOnSurface_Eval |
37 | //purpose: evaluator class for approximation of both 2d and 3d curves |
38 | //======================================================================= |
39 | |
40 | class Approx_CurveOnSurface_Eval : public AdvApprox_EvaluatorFunction |
41 | { |
42 | public: |
43 | Approx_CurveOnSurface_Eval (const Handle(Adaptor3d_HCurve)& theFunc, |
44 | const Handle(Adaptor2d_HCurve2d)& theFunc2d, |
45 | Standard_Real First, Standard_Real Last) |
46 | : fonct(theFunc), fonct2d(theFunc2d) |
47 | { StartEndSav[0] = First; StartEndSav[1] = Last; } |
48 | |
49 | virtual void Evaluate (Standard_Integer *Dimension, |
50 | Standard_Real StartEnd[2], |
51 | Standard_Real *Parameter, |
52 | Standard_Integer *DerivativeRequest, |
53 | Standard_Real *Result, // [Dimension] |
54 | Standard_Integer *ErrorCode); |
55 | |
56 | private: |
57 | Handle(Adaptor3d_HCurve) fonct; |
58 | Handle(Adaptor2d_HCurve2d) fonct2d; |
59 | Standard_Real StartEndSav[2]; |
60 | }; |
61 | |
62 | void Approx_CurveOnSurface_Eval::Evaluate (Standard_Integer *Dimension, |
63 | Standard_Real StartEnd[2], |
64 | Standard_Real *Param, // Parameter at which evaluation |
65 | Standard_Integer *Order, // Derivative Request |
66 | Standard_Real *Result,// [Dimension] |
67 | Standard_Integer *ErrorCode) |
68 | { |
69 | *ErrorCode = 0; |
70 | Standard_Real par = *Param; |
71 | |
72 | // Dimension is incorrect |
73 | if (*Dimension != 5) { |
74 | *ErrorCode = 1; |
75 | } |
76 | |
77 | // Parameter is incorrect |
78 | if(StartEnd[0] != StartEndSav[0] || StartEnd[1]!= StartEndSav[1]) |
79 | { |
80 | fonct = fonct->Trim(StartEnd[0],StartEnd[1],Precision::PConfusion()); |
81 | fonct2d = fonct2d->Trim(StartEnd[0],StartEnd[1], |
82 | Precision::PConfusion()); |
83 | StartEndSav[0]=StartEnd[0]; |
84 | StartEndSav[1]=StartEnd[1]; |
85 | } |
86 | gp_Pnt pnt; |
87 | |
88 | |
89 | gp_Pnt2d pnt2d; |
90 | |
91 | switch (*Order) { |
92 | case 0: |
93 | { |
94 | fonct2d->D0(par, pnt2d); |
95 | fonct->D0(par, pnt); |
96 | Result[0] = pnt2d.X(); |
97 | Result[1] = pnt2d.Y(); |
98 | Result[2] = pnt.X(); |
99 | Result[3] = pnt.Y(); |
100 | Result[4] = pnt.Z(); |
101 | break; |
102 | } |
103 | case 1: |
104 | { |
105 | gp_Vec v1; |
106 | gp_Vec2d v21; |
107 | fonct2d->D1(par, pnt2d, v21); |
108 | fonct->D1(par,pnt, v1); |
109 | Result[0] = v21.X(); |
110 | Result[1] = v21.Y(); |
111 | Result[2] = v1.X(); |
112 | Result[3] = v1.Y(); |
113 | Result[4] = v1.Z(); |
114 | break; |
115 | } |
116 | case 2: |
117 | { |
118 | gp_Vec v1, v2; |
119 | gp_Vec2d v21, v22; |
120 | fonct2d->D2(par, pnt2d, v21, v22); |
121 | fonct->D2(par, pnt, v1, v2); |
122 | Result[0] = v22.X(); |
123 | Result[1] = v22.Y(); |
124 | Result[2] = v2.X(); |
125 | Result[3] = v2.Y(); |
126 | Result[4] = v2.Z(); |
127 | break; |
128 | } |
129 | default: |
130 | Result[0] = Result[1] = Result[2] = Result[3] = Result[4] = 0.; |
131 | *ErrorCode = 3; |
132 | break; |
133 | } |
134 | } |
135 | |
136 | //======================================================================= |
137 | //class : Approx_CurveOnSurface_Eval3d |
138 | //purpose: evaluator class for approximation of 3d curve |
139 | //======================================================================= |
140 | |
141 | class Approx_CurveOnSurface_Eval3d : public AdvApprox_EvaluatorFunction |
142 | { |
143 | public: |
144 | Approx_CurveOnSurface_Eval3d (const Handle(Adaptor3d_HCurve)& theFunc, |
145 | Standard_Real First, Standard_Real Last) |
146 | : fonct(theFunc) { StartEndSav[0] = First; StartEndSav[1] = Last; } |
147 | |
148 | virtual void Evaluate (Standard_Integer *Dimension, |
149 | Standard_Real StartEnd[2], |
150 | Standard_Real *Parameter, |
151 | Standard_Integer *DerivativeRequest, |
152 | Standard_Real *Result, // [Dimension] |
153 | Standard_Integer *ErrorCode); |
154 | |
155 | private: |
156 | Handle(Adaptor3d_HCurve) fonct; |
157 | Standard_Real StartEndSav[2]; |
158 | }; |
159 | |
160 | void Approx_CurveOnSurface_Eval3d::Evaluate (Standard_Integer *Dimension, |
161 | Standard_Real StartEnd[2], |
162 | Standard_Real *Param, // Parameter at which evaluation |
163 | Standard_Integer *Order, // Derivative Request |
164 | Standard_Real *Result,// [Dimension] |
165 | Standard_Integer *ErrorCode) |
166 | { |
167 | *ErrorCode = 0; |
168 | Standard_Real par = *Param; |
169 | |
170 | // Dimension is incorrect |
171 | if (*Dimension != 3) { |
172 | *ErrorCode = 1; |
173 | } |
174 | |
175 | // Parameter is incorrect |
176 | if(StartEnd[0] != StartEndSav[0] || StartEnd[1]!= StartEndSav[1]) |
177 | { |
178 | fonct = fonct->Trim(StartEnd[0],StartEnd[1],Precision::PConfusion()); |
179 | StartEndSav[0]=StartEnd[0]; |
180 | StartEndSav[1]=StartEnd[1]; |
181 | } |
182 | |
183 | gp_Pnt pnt; |
184 | |
185 | switch (*Order) { |
186 | case 0: |
187 | pnt = fonct->Value(par); |
188 | Result[0] = pnt.X(); |
189 | Result[1] = pnt.Y(); |
190 | Result[2] = pnt.Z(); |
191 | break; |
192 | case 1: |
193 | { |
194 | gp_Vec v1; |
195 | fonct->D1(par, pnt, v1); |
196 | Result[0] = v1.X(); |
197 | Result[1] = v1.Y(); |
198 | Result[2] = v1.Z(); |
199 | break; |
200 | } |
201 | case 2: |
202 | { |
203 | gp_Vec v1, v2; |
204 | fonct->D2(par, pnt, v1, v2); |
205 | Result[0] = v2.X(); |
206 | Result[1] = v2.Y(); |
207 | Result[2] = v2.Z(); |
208 | break; |
209 | } |
210 | default: |
211 | Result[0] = Result[1] = Result[2] = 0.; |
212 | *ErrorCode = 3; |
213 | break; |
214 | } |
215 | } |
216 | |
217 | //======================================================================= |
218 | //class : Approx_CurveOnSurface_Eval2d |
219 | //purpose: evaluator class for approximation of 2d curve |
220 | //======================================================================= |
221 | |
222 | class Approx_CurveOnSurface_Eval2d : public AdvApprox_EvaluatorFunction |
223 | { |
224 | public: |
225 | Approx_CurveOnSurface_Eval2d (const Handle(Adaptor2d_HCurve2d)& theFunc2d, |
226 | Standard_Real First, Standard_Real Last) |
227 | : fonct2d(theFunc2d) { StartEndSav[0] = First; StartEndSav[1] = Last; } |
228 | |
229 | virtual void Evaluate (Standard_Integer *Dimension, |
230 | Standard_Real StartEnd[2], |
231 | Standard_Real *Parameter, |
232 | Standard_Integer *DerivativeRequest, |
233 | Standard_Real *Result, // [Dimension] |
234 | Standard_Integer *ErrorCode); |
235 | |
236 | private: |
237 | Handle(Adaptor2d_HCurve2d) fonct2d; |
238 | Standard_Real StartEndSav[2]; |
239 | }; |
240 | |
241 | void Approx_CurveOnSurface_Eval2d::Evaluate (Standard_Integer *Dimension, |
242 | Standard_Real StartEnd[2], |
243 | Standard_Real *Param, // Parameter at which evaluation |
244 | Standard_Integer *Order, // Derivative Request |
245 | Standard_Real *Result,// [Dimension] |
246 | Standard_Integer *ErrorCode) |
247 | { |
248 | *ErrorCode = 0; |
249 | Standard_Real par = *Param; |
250 | |
251 | // Dimension is incorrect |
252 | if (*Dimension != 2) { |
253 | *ErrorCode = 1; |
254 | } |
255 | |
256 | // Parameter is incorrect |
257 | if(StartEnd[0] != StartEndSav[0] || StartEnd[1]!= StartEndSav[1]) |
258 | { |
259 | fonct2d = fonct2d->Trim(StartEnd[0],StartEnd[1],Precision::PConfusion()); |
260 | StartEndSav[0]=StartEnd[0]; |
261 | StartEndSav[1]=StartEnd[1]; |
262 | } |
263 | |
264 | gp_Pnt2d pnt; |
265 | |
266 | switch (*Order) { |
267 | case 0: |
268 | { |
269 | pnt = fonct2d->Value(par); |
270 | Result[0] = pnt.X(); |
271 | Result[1] = pnt.Y(); |
272 | break; |
273 | } |
274 | case 1: |
275 | { |
276 | gp_Vec2d v1; |
277 | fonct2d->D1(par, pnt, v1); |
278 | Result[0] = v1.X(); |
279 | Result[1] = v1.Y(); |
280 | break; |
281 | } |
282 | case 2: |
283 | { |
284 | gp_Vec2d v1, v2; |
285 | fonct2d->D2(par, pnt, v1, v2); |
286 | Result[0] = v2.X(); |
287 | Result[1] = v2.Y(); |
288 | break; |
289 | } |
290 | default: |
291 | Result[0] = Result[1] = 0.; |
292 | *ErrorCode = 3; |
293 | break; |
294 | } |
295 | } |
296 | |
297 | Approx_CurveOnSurface::Approx_CurveOnSurface(const Handle(Adaptor2d_HCurve2d)& C2D, |
298 | const Handle(Adaptor3d_HSurface)& Surf, |
299 | const Standard_Real First, |
300 | const Standard_Real Last, |
301 | const Standard_Real Tol, |
302 | const GeomAbs_Shape S, |
303 | const Standard_Integer MaxDegree, |
304 | const Standard_Integer MaxSegments, |
305 | const Standard_Boolean only3d, |
306 | const Standard_Boolean only2d) |
307 | { |
308 | myIsDone = Standard_False; |
309 | if(only3d && only2d) Standard_ConstructionError::Raise(); |
310 | GeomAbs_Shape Order = S; |
311 | |
312 | Handle( Adaptor2d_HCurve2d ) TrimmedC2D = C2D->Trim( First, Last, Precision::PConfusion() ); |
313 | |
314 | Adaptor3d_CurveOnSurface COnS( TrimmedC2D, Surf ); |
315 | Handle(Adaptor3d_HCurveOnSurface) HCOnS = new Adaptor3d_HCurveOnSurface(); |
316 | HCOnS->Set(COnS); |
317 | |
318 | Standard_Integer Num1DSS = 0, Num2DSS=0, Num3DSS=0; |
319 | Handle(TColStd_HArray1OfReal) OneDTol; |
320 | Handle(TColStd_HArray1OfReal) TwoDTolNul; |
321 | Handle(TColStd_HArray1OfReal) ThreeDTol; |
322 | |
323 | // create evaluators and choose appropriate one |
324 | Approx_CurveOnSurface_Eval3d Eval3dCvOnSurf (HCOnS, First, Last); |
325 | Approx_CurveOnSurface_Eval2d Eval2dCvOnSurf ( TrimmedC2D, First, Last); |
326 | Approx_CurveOnSurface_Eval EvalCvOnSurf (HCOnS, TrimmedC2D, First, Last); |
327 | AdvApprox_EvaluatorFunction* EvalPtr; |
328 | if ( only3d ) EvalPtr = &Eval3dCvOnSurf; |
329 | else if ( only2d ) EvalPtr = &Eval2dCvOnSurf; |
330 | else EvalPtr = &EvalCvOnSurf; |
331 | |
332 | // Initialization for 2d approximation |
333 | if(!only3d) { |
334 | Num1DSS = 2; |
335 | OneDTol = new TColStd_HArray1OfReal(1,Num1DSS); |
336 | |
337 | Standard_Real TolU, TolV; |
338 | |
339 | TolU = Surf->UResolution(Tol)/2; |
340 | TolV = Surf->VResolution(Tol)/2; |
341 | |
342 | OneDTol->SetValue(1,TolU); |
343 | OneDTol->SetValue(2,TolV); |
344 | } |
345 | |
346 | if(!only2d) { |
347 | Num3DSS=1; |
348 | ThreeDTol = new TColStd_HArray1OfReal(1,Num3DSS); |
349 | ThreeDTol->Init(Tol/2); |
350 | } |
351 | |
352 | myError2dU = 0; |
353 | myError2dV = 0; |
354 | myError3d = 0; |
355 | |
356 | Standard_Integer NbInterv_C2 = HCOnS->NbIntervals(GeomAbs_C2); |
357 | TColStd_Array1OfReal CutPnts_C2(1, NbInterv_C2 + 1); |
358 | HCOnS->Intervals(CutPnts_C2, GeomAbs_C2); |
359 | Standard_Integer NbInterv_C3 = HCOnS->NbIntervals(GeomAbs_C3); |
360 | TColStd_Array1OfReal CutPnts_C3(1, NbInterv_C3 + 1); |
361 | HCOnS->Intervals(CutPnts_C3, GeomAbs_C3); |
362 | |
363 | AdvApprox_PrefAndRec CutTool(CutPnts_C2,CutPnts_C3); |
364 | AdvApprox_ApproxAFunction aApprox (Num1DSS, Num2DSS, Num3DSS, |
365 | OneDTol, TwoDTolNul, ThreeDTol, |
366 | First, Last, Order, |
367 | MaxDegree, MaxSegments, |
368 | *EvalPtr, CutTool); |
369 | |
370 | myIsDone = aApprox.IsDone(); |
371 | myHasResult = aApprox.HasResult(); |
372 | |
373 | if (myHasResult) { |
374 | Handle(TColStd_HArray1OfReal) Knots = aApprox.Knots(); |
375 | Handle(TColStd_HArray1OfInteger) Mults = aApprox.Multiplicities(); |
376 | Standard_Integer Degree = aApprox.Degree(); |
377 | |
378 | if(!only2d) |
379 | { |
380 | TColgp_Array1OfPnt Poles(1,aApprox.NbPoles()); |
381 | aApprox.Poles(1,Poles); |
382 | myCurve3d = new Geom_BSplineCurve(Poles, Knots->Array1(), Mults->Array1(), Degree); |
383 | myError3d = aApprox.MaxError(3, 1); |
384 | } |
385 | if(!only3d) |
386 | { |
387 | TColgp_Array1OfPnt2d Poles2d(1,aApprox.NbPoles()); |
388 | TColStd_Array1OfReal Poles1dU(1,aApprox.NbPoles()); |
389 | aApprox.Poles1d(1, Poles1dU); |
390 | TColStd_Array1OfReal Poles1dV(1,aApprox.NbPoles()); |
391 | aApprox.Poles1d(2, Poles1dV); |
392 | for(Standard_Integer i = 1; i <= aApprox.NbPoles(); i++) |
393 | Poles2d.SetValue(i, gp_Pnt2d(Poles1dU.Value(i), Poles1dV.Value(i))); |
394 | myCurve2d = new Geom2d_BSplineCurve(Poles2d, Knots->Array1(), Mults->Array1(), Degree); |
395 | |
396 | myError2dU = aApprox.MaxError(1, 1); |
397 | myError2dV = aApprox.MaxError(1, 2); |
398 | } |
399 | } |
400 | |
401 | // } |
402 | |
403 | } |
404 | |
405 | Standard_Boolean Approx_CurveOnSurface::IsDone() const |
406 | { |
407 | return myIsDone; |
408 | } |
409 | |
410 | Standard_Boolean Approx_CurveOnSurface::HasResult() const |
411 | { |
412 | return myHasResult; |
413 | } |
414 | |
415 | Handle(Geom_BSplineCurve) Approx_CurveOnSurface::Curve3d() const |
416 | { |
417 | return myCurve3d; |
418 | } |
419 | |
420 | Handle(Geom2d_BSplineCurve) Approx_CurveOnSurface::Curve2d() const |
421 | { |
422 | return myCurve2d; |
423 | } |
424 | |
425 | Standard_Real Approx_CurveOnSurface::MaxError3d() const |
426 | { |
427 | return myError3d; |
428 | } |
429 | |
430 | Standard_Real Approx_CurveOnSurface::MaxError2dU() const |
431 | { |
432 | return myError2dU; |
433 | } |
434 | |
435 | Standard_Real Approx_CurveOnSurface::MaxError2dV() const |
436 | { |
437 | return myError2dV; |
438 | } |
439 | |