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