b311480e |
1 | // Created on: 1995-10-26 |
2 | // Created by: Laurent BOURESCHE |
3 | // Copyright (c) 1995-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 | // Modified by skv - Fri Jun 18 12:52:54 2004 OCC6129 |
18 | |
7fd59977 |
19 | #include <AdvApprox_ApproxAFunction.hxx> |
42cf5bc1 |
20 | #include <BSplCLib.hxx> |
21 | #include <Geom_BSplineSurface.hxx> |
22 | #include <GeomFill_Boundary.hxx> |
23 | #include <GeomFill_BoundWithSurf.hxx> |
24 | #include <GeomFill_ConstrainedFilling.hxx> |
25 | #include <GeomFill_CoonsAlgPatch.hxx> |
7fd59977 |
26 | #include <GeomFill_DegeneratedBound.hxx> |
42cf5bc1 |
27 | #include <GeomFill_TgtField.hxx> |
7fd59977 |
28 | #include <GeomFill_TgtOnCoons.hxx> |
42cf5bc1 |
29 | #include <gp_XYZ.hxx> |
30 | #include <Law.hxx> |
31 | #include <Law_BSpFunc.hxx> |
32 | #include <Law_BSpline.hxx> |
33 | #include <Law_Linear.hxx> |
34 | #include <PLib.hxx> |
35 | #include <Standard_Failure.hxx> |
36 | #include <Standard_NotImplemented.hxx> |
37 | #include <TColgp_Array1OfPnt.hxx> |
38 | #include <TColStd_HArray1OfReal.hxx> |
7fd59977 |
39 | |
40 | #ifdef DRAW |
41 | // Pour le dessin. |
42 | #include <Draw_Appli.hxx> |
43 | #include <Draw_Display.hxx> |
44 | #include <Draw.hxx> |
45 | #include <Draw_Segment3D.hxx> |
46 | #include <Draw_Segment2D.hxx> |
47 | #include <Draw_Marker2D.hxx> |
48 | #include <Draw_ColorKind.hxx> |
49 | #include <Draw_MarkerShape.hxx> |
50 | static Standard_Boolean dodraw = 0; |
51 | static Standard_Real drawfac = 0.1; |
52 | #endif |
0797d9d3 |
53 | #ifdef OCCT_DEBUG |
7fd59977 |
54 | Standard_IMPORT void Law_draw1dcurve(const TColStd_Array1OfReal& pol, |
55 | const TColStd_Array1OfReal& knots, |
56 | const TColStd_Array1OfInteger& mults, |
57 | const Standard_Integer deg, |
58 | const gp_Vec2d& tra, |
59 | const Standard_Real scal); |
60 | Standard_IMPORT void Law_draw1dcurve(const Handle(Law_BSpline)& bs, |
61 | const gp_Vec2d& tra, |
62 | const Standard_Real scal); |
63 | |
64 | |
65 | // Pour les mesures. |
66 | #include <OSD_Chronometer.hxx> |
67 | static OSD_Chronometer totclock, parclock, appclock, cstclock; |
68 | #endif |
69 | |
70 | static Standard_Integer inqadd(const Standard_Real d1, |
71 | const Standard_Real d2, |
72 | Standard_Real* k, |
73 | Standard_Integer* m, |
74 | const Standard_Integer deg, |
75 | const Standard_Real tolk) |
76 | { |
77 | Standard_Integer nbadd = 0; |
78 | m[0] = m[1] = deg - 2; |
79 | if (d1 != 1. && d2 != 1.){ |
80 | if(Abs(d1+d2-1.) < tolk) { |
81 | k[0] = 0.5 * (d1 + 1. - d2); |
82 | nbadd = 1; |
83 | } |
84 | else{ |
85 | nbadd = 2; |
86 | k[0] = Min(d1,1. - d2); |
87 | k[1] = Max(d1,1. - d2); |
88 | } |
89 | } |
90 | else if (d1 != 1.) { |
91 | k[0] = d1; |
92 | nbadd = 1; |
93 | } |
94 | else if (d2 != 1.) { |
95 | k[0] = d2; |
96 | nbadd = 1; |
97 | } |
98 | return nbadd; |
99 | } |
100 | |
101 | static Handle(Law_Linear) mklin(const Handle(Law_Function)& func) |
102 | { |
103 | Handle(Law_Linear) fu = Handle(Law_Linear)::DownCast(func); |
104 | if(fu.IsNull()) { |
105 | fu = new Law_Linear(); |
106 | Standard_Real d,f; |
107 | func->Bounds(d,f); |
108 | fu->Set(d,func->Value(d),f,func->Value(f)); |
109 | } |
110 | return fu; |
111 | } |
112 | |
113 | static void sortbounds(const Standard_Integer nb, |
114 | Handle(GeomFill_Boundary)* bound, |
115 | Standard_Boolean* rev, |
116 | GeomFill_CornerState* stat) |
117 | { |
118 | // trier les bords (facon bourinos), |
119 | // flaguer ceux a renverser, |
120 | // flaguer les baillements au coins. |
121 | Standard_Integer i,j; |
122 | Handle(GeomFill_Boundary) temp; |
123 | rev[0] = 0; |
124 | gp_Pnt pf,pl; |
125 | gp_Pnt qf,ql; |
126 | for (i = 0; i < nb-1; i++){ |
127 | if(!rev[i]) bound[i]->Points(pf,pl); |
128 | else bound[i]->Points(pl,pf); |
129 | for (j = i+1; j <= nb-1; j++){ |
130 | bound[j]->Points(qf,ql); |
131 | // Modified by skv - Fri Jun 18 12:52:54 2004 OCC6129 Begin |
132 | Standard_Real df = qf.Distance(pl); |
133 | Standard_Real dl = ql.Distance(pl); |
134 | if (df<dl) { |
135 | if(df < stat[i+1].Gap()){ |
136 | temp = bound[i+1]; |
137 | bound[i+1] = bound[j]; |
138 | bound[j] = temp; |
139 | stat[i+1].Gap(df); |
140 | rev[i+1] = Standard_False; |
141 | } |
142 | } else { |
143 | if(dl < stat[i+1].Gap()){ |
144 | temp = bound[i+1]; |
145 | bound[i+1] = bound[j]; |
146 | bound[j] = temp; |
147 | stat[i+1].Gap(dl); |
148 | rev[i+1] = Standard_True; |
149 | } |
150 | } |
151 | // Modified by skv - Fri Jun 18 12:52:54 2004 OCC6129 End |
152 | } |
153 | } |
154 | if(!rev[nb-1]) bound[nb-1]->Points(pf,pl); |
155 | else bound[nb-1]->Points(pl,pf); |
156 | bound[0]->Points(qf,ql); |
157 | stat[0].Gap(pl.Distance(qf)); |
158 | |
159 | // flaguer les angles entre tangentes au coins et entre les normales au |
160 | // coins pour les bords contraints. |
161 | gp_Pnt pbid; |
162 | gp_Vec tgi, nori, tgn, norn; |
163 | Standard_Real fi, fn, li, ln; |
164 | for (i = 0; i < nb; i++){ |
165 | Standard_Integer next = (i+1)%nb; |
166 | if(!rev[i]) bound[i]->Bounds(fi,li); |
167 | else bound[i]->Bounds(li,fi); |
168 | bound[i]->D1(li,pbid,tgi); |
169 | if(rev[i]) tgi.Reverse(); |
170 | if(!rev[next]) bound[next]->Bounds(fn,ln); |
171 | else bound[next]->Bounds(ln,fn); |
172 | bound[next]->D1(fn,pbid,tgn); |
173 | if(rev[next]) tgn.Reverse(); |
c6541a0c |
174 | Standard_Real ang = M_PI - tgi.Angle(tgn); |
7fd59977 |
175 | stat[next].TgtAng(ang); |
176 | if(bound[i]->HasNormals() && bound[next]->HasNormals()){ |
177 | stat[next].Constraint(); |
178 | nori = bound[i]->Norm(li); |
179 | norn = bound[next]->Norm(fn); |
180 | ang = nori.Angle(norn); |
181 | stat[next].NorAng(ang); |
182 | } |
183 | } |
184 | } |
185 | static void coonscnd(const Standard_Integer nb, |
186 | Handle(GeomFill_Boundary)* bound, |
187 | Standard_Boolean* rev, |
188 | GeomFill_CornerState* stat, |
189 | // Handle(GeomFill_TgtField)* tga, |
190 | Handle(GeomFill_TgtField)* , |
191 | Standard_Real* mintg) |
192 | { |
193 | Standard_Real fact_normalization = 100.; |
194 | Standard_Integer i; |
195 | // Pour chaque coin contraint, on controle les bounds adjascents. |
196 | for(i = 0; i < nb; i++){ |
197 | if(stat[i].HasConstraint()){ |
198 | Standard_Integer ip = (i-1+nb)%nb; |
199 | Standard_Real tolang = Min(bound[ip]->Tolang(),bound[i]->Tolang()); |
200 | Standard_Real an = stat[i].NorAng(); |
201 | Standard_Boolean twist = Standard_False; |
c6541a0c |
202 | if(an >= 0.5*M_PI) { twist = Standard_True; an = M_PI-an; } |
7fd59977 |
203 | if(an > tolang) stat[i].DoKill(0.); |
204 | else{ |
205 | Standard_Real fact = 0.5*27./4; |
206 | tolang *= (Min(mintg[ip],mintg[i])*fact*fact_normalization); |
207 | gp_Vec tgp, dnorp, tgi, dnori, vbid; |
208 | gp_Pnt pbid; |
209 | Standard_Real fp,lp,fi,li; |
210 | if(!rev[ip]) bound[ip]->Bounds(fp,lp); |
211 | else bound[ip]->Bounds(lp,fp); |
212 | bound[ip]->D1(lp,pbid,tgp); |
213 | bound[ip]->D1Norm(lp,vbid,dnorp); |
214 | if(!rev[i]) bound[i]->Bounds(fi,li); |
215 | else bound[i]->Bounds(li,fi); |
216 | bound[i]->D1(fi,pbid,tgi); |
217 | bound[i]->D1Norm(fi,vbid,dnori); |
218 | Standard_Real scal1 = tgp.Dot(dnori); |
219 | Standard_Real scal2 = tgi.Dot(dnorp); |
220 | if(!twist) scal2 *= -1.; |
221 | scal1 = Abs(scal1+scal2); |
222 | if(scal1 > tolang) { |
223 | Standard_Real killfactor = tolang/scal1; |
224 | stat[i].DoKill(killfactor); |
0797d9d3 |
225 | #ifdef OCCT_DEBUG |
04232180 |
226 | std::cout<<"pb coons cnd coin : "<<i<<" fact = "<<killfactor<<std::endl; |
7fd59977 |
227 | #endif |
228 | } |
229 | } |
230 | } |
231 | } |
232 | } |
233 | static void killcorners(const Standard_Integer nb, |
234 | Handle(GeomFill_Boundary)* bound, |
235 | Standard_Boolean* rev, |
236 | Standard_Boolean* nrev, |
237 | GeomFill_CornerState* stat, |
238 | Handle(GeomFill_TgtField)* tga) |
239 | { |
240 | Standard_Integer i; |
241 | // Pour chaque bound, on controle l etat des extremites et on flingue |
242 | // eventuellement le champ tangent et les derivees du bound. |
243 | for(i = 0; i < nb; i++){ |
244 | Standard_Integer inext = (i+1)%nb; |
245 | Standard_Boolean fnul, lnul; |
246 | Standard_Real fscal, lscal; |
247 | if(!nrev[i]){ |
248 | fnul = stat[i].IsToKill(fscal); |
249 | lnul = stat[inext].IsToKill(lscal); |
250 | } |
251 | else{ |
252 | lnul = stat[i].IsToKill(lscal); |
253 | fnul = stat[inext].IsToKill(fscal); |
254 | } |
255 | if(fnul || lnul){ |
0797d9d3 |
256 | #ifdef OCCT_DEBUG |
7fd59977 |
257 | parclock.Start(); |
258 | #endif |
259 | bound[i]->Reparametrize(0.,1.,fnul,lnul,fscal,lscal,rev[i]); |
0797d9d3 |
260 | #ifdef OCCT_DEBUG |
7fd59977 |
261 | parclock.Stop(); |
262 | #endif |
263 | if(bound[i]->HasNormals() && tga[i]->IsScalable()) { |
264 | Handle(Law_BSpline) bs = Law::ScaleCub(0.,1.,fnul,lnul,fscal,lscal); |
265 | tga[i]->Scale(bs); |
266 | #ifdef DRAW |
267 | if(dodraw) Law_draw1dcurve(bs,gp_Vec2d(1.,0.),1.); |
268 | #endif |
269 | } |
270 | } |
271 | } |
272 | } |
273 | |
274 | //======================================================================= |
275 | //class : GeomFill_ConstrainedFilling_Eval |
276 | //purpose: The evaluator for curve approximation |
277 | //======================================================================= |
278 | |
279 | class GeomFill_ConstrainedFilling_Eval : public AdvApprox_EvaluatorFunction |
280 | { |
281 | public: |
282 | GeomFill_ConstrainedFilling_Eval (GeomFill_ConstrainedFilling& theTool) |
283 | : curfil(theTool) {} |
284 | |
285 | virtual void Evaluate (Standard_Integer *Dimension, |
286 | Standard_Real StartEnd[2], |
287 | Standard_Real *Parameter, |
288 | Standard_Integer *DerivativeRequest, |
289 | Standard_Real *Result, // [Dimension] |
290 | Standard_Integer *ErrorCode); |
291 | |
292 | private: |
293 | GeomFill_ConstrainedFilling& curfil; |
294 | }; |
295 | |
296 | void GeomFill_ConstrainedFilling_Eval::Evaluate (Standard_Integer *,/*Dimension*/ |
297 | Standard_Real /*StartEnd*/[2], |
298 | Standard_Real *Parameter, |
299 | Standard_Integer *DerivativeRequest, |
300 | Standard_Real *Result,// [Dimension] |
301 | Standard_Integer *ErrorCode) |
302 | { |
303 | *ErrorCode = curfil.Eval(*Parameter, *DerivativeRequest, Result[0]); |
304 | } |
305 | |
306 | //======================================================================= |
307 | //function : GeomFill_ConstrainedFilling |
308 | //purpose : |
309 | //======================================================================= |
310 | |
311 | GeomFill_ConstrainedFilling::GeomFill_ConstrainedFilling |
312 | (const Standard_Integer MaxDeg, |
313 | const Standard_Integer MaxSeg) : |
314 | degmax(MaxDeg),segmax(MaxSeg),appdone(Standard_False) |
315 | { |
316 | dom[0] = dom[1] = dom[2] = dom[3] = 1.; |
317 | } |
318 | |
319 | |
320 | //======================================================================= |
321 | //function : Init |
322 | //purpose : |
323 | //======================================================================= |
324 | |
325 | void GeomFill_ConstrainedFilling::Init(const Handle(GeomFill_Boundary)& B1, |
326 | const Handle(GeomFill_Boundary)& B2, |
327 | const Handle(GeomFill_Boundary)& B3, |
328 | const Standard_Boolean NoCheck) |
329 | { |
0797d9d3 |
330 | #ifdef OCCT_DEBUG |
7fd59977 |
331 | totclock.Reset(); |
332 | parclock.Reset(); |
333 | appclock.Reset(); |
334 | cstclock.Reset(); |
335 | totclock.Start(); |
336 | #endif |
337 | Standard_Boolean rev[3]; |
338 | rev[0] = rev[1] = rev[2] = Standard_False; |
339 | Handle(GeomFill_Boundary) bound[3]; |
340 | bound[0] = B1; bound[1] = B2; bound[2] = B3; |
341 | Standard_Integer i; |
342 | sortbounds(3,bound,rev,stcor); |
343 | |
344 | // on reoriente. |
345 | rev[2] = !rev[2]; |
346 | |
347 | // on reparamettre tout le monde entre 0. et 1. |
0797d9d3 |
348 | #ifdef OCCT_DEBUG |
7fd59977 |
349 | parclock.Start(); |
350 | #endif |
351 | for (i = 0; i <= 2; i++){ |
352 | bound[i]->Reparametrize(0.,1.,0,0,1.,1.,rev[i]); |
353 | } |
0797d9d3 |
354 | #ifdef OCCT_DEBUG |
7fd59977 |
355 | parclock.Stop(); |
356 | #endif |
357 | |
358 | // On cree le carreau algorithmique (u,(1-u)) et les champs tangents |
359 | // 1er jus. |
360 | // On cree donc le bord manquant. |
361 | gp_Pnt p1 = bound[1]->Value(1.); |
362 | gp_Pnt p2 = bound[2]->Value(1.); |
363 | gp_Pnt ppp(0.5*(p1.XYZ()+p2.XYZ())); |
364 | Standard_Real t3 = Max(bound[1]->Tol3d(),bound[2]->Tol3d()); |
365 | Handle(GeomFill_DegeneratedBound) |
366 | DB = new GeomFill_DegeneratedBound(ppp,0.,1.,t3,10.); |
367 | |
368 | ptch = new GeomFill_CoonsAlgPatch(bound[0],bound[1],DB,bound[2]); |
369 | |
370 | Handle(GeomFill_TgtField) ttgalg[3]; |
371 | if(bound[0]->HasNormals()) |
372 | ttgalg[0] = tgalg[0] = new GeomFill_TgtOnCoons(ptch,0); |
373 | if(bound[1]->HasNormals()) |
374 | ttgalg[1] = tgalg[1] = new GeomFill_TgtOnCoons(ptch,1); |
375 | if(bound[2]->HasNormals()) |
376 | ttgalg[2] = tgalg[3] = new GeomFill_TgtOnCoons(ptch,3); |
377 | |
378 | for (i = 0; i <= 3; i++){ |
379 | mig[i] = 1.; |
380 | if(!tgalg[i].IsNull()) MinTgte(i); |
381 | } |
382 | |
383 | if(!NoCheck){ |
384 | // On verifie enfin les conditions de compatibilites sur les derivees |
385 | // aux coins maintenant qu on a quelque chose a quoi les comparer. |
386 | Standard_Boolean nrev[3]; |
387 | nrev[0] = nrev[1] = 0; |
388 | nrev[2] = 1; |
389 | mig[2] = mig[3]; |
390 | coonscnd(3,bound,nrev,stcor,ttgalg,mig); |
391 | killcorners(3,bound,rev,nrev,stcor,ttgalg); |
392 | } |
393 | // on remet les coins en place (on duplique la pointe). |
394 | stcor[3] = stcor[2]; |
395 | |
396 | for (i = 0; i <= 3; i++){ |
397 | mig[i] = 1.; |
398 | if(!tgalg[i].IsNull()) { |
399 | if(!CheckTgte(i)) { |
400 | Handle(Law_Function) fu1,fu2; |
401 | ptch->Func(fu1,fu2); |
c5f3a425 |
402 | fu1 = Law::MixBnd(Handle(Law_Linear)::DownCast (fu1)); |
403 | fu2 = Law::MixBnd(Handle(Law_Linear)::DownCast (fu2)); |
7fd59977 |
404 | ptch->Func(fu1,fu2); |
405 | break; |
406 | } |
407 | } |
408 | } |
409 | |
410 | Build(); |
411 | } |
412 | |
413 | |
414 | //======================================================================= |
415 | //function : Init |
416 | //purpose : |
417 | //======================================================================= |
418 | |
419 | void GeomFill_ConstrainedFilling::Init(const Handle(GeomFill_Boundary)& B1, |
420 | const Handle(GeomFill_Boundary)& B2, |
421 | const Handle(GeomFill_Boundary)& B3, |
422 | const Handle(GeomFill_Boundary)& B4, |
423 | const Standard_Boolean NoCheck) |
424 | { |
0797d9d3 |
425 | #ifdef OCCT_DEBUG |
7fd59977 |
426 | totclock.Reset(); |
427 | parclock.Reset(); |
428 | appclock.Reset(); |
429 | cstclock.Reset(); |
430 | totclock.Start(); |
431 | #endif |
432 | Standard_Boolean rev[4]; |
433 | rev[0] = rev[1] = rev[2] = rev[3] = Standard_False; |
434 | Handle(GeomFill_Boundary) bound[4]; |
435 | bound[0] = B1; bound[1] = B2; bound[2] = B3; bound[3] = B4; |
436 | Standard_Integer i; |
437 | sortbounds(4,bound,rev,stcor); |
438 | |
439 | // on reoriente. |
440 | rev[2] = !rev[2]; |
441 | rev[3] = !rev[3]; |
442 | |
443 | // on reparamettre tout le monde entre 0. et 1. |
0797d9d3 |
444 | #ifdef OCCT_DEBUG |
7fd59977 |
445 | parclock.Start(); |
446 | #endif |
447 | for (i = 0; i <= 3; i++){ |
448 | bound[i]->Reparametrize(0.,1.,0,0,1.,1.,rev[i]); |
449 | } |
0797d9d3 |
450 | #ifdef OCCT_DEBUG |
7fd59977 |
451 | parclock.Stop(); |
452 | #endif |
453 | |
454 | // On cree le carreau algorithmique (u,(1-u)) et les champs tangents |
455 | // 1er jus. |
456 | ptch = new GeomFill_CoonsAlgPatch(bound[0],bound[1],bound[2],bound[3]); |
457 | for (i = 0; i <= 3; i++){ |
458 | if(bound[i]->HasNormals()) tgalg[i] = new GeomFill_TgtOnCoons(ptch,i); |
459 | } |
460 | // on calcule le min de chacun des champs tangents pour l evaluation |
461 | // des tolerances. |
462 | for (i = 0; i <= 3; i++){ |
463 | mig[i] = 1.; |
464 | if(!tgalg[i].IsNull()) MinTgte(i); |
465 | } |
466 | |
467 | if(!NoCheck){ |
468 | // On verifie enfin les conditions de compatibilites sur les derivees |
469 | // aux coins maintenant qu on a quelque chose a quoi les comparer. |
470 | Standard_Boolean nrev[4]; |
471 | nrev[0] = nrev[1] = 0; |
472 | nrev[2] = nrev[3] = 1; |
473 | coonscnd(4,bound,nrev,stcor,tgalg,mig); |
474 | killcorners(4,bound,rev,nrev,stcor,tgalg); |
475 | } |
476 | // On verifie les champs tangents ne changent pas de direction. |
477 | for (i = 0; i <= 3; i++){ |
478 | mig[i] = 1.; |
479 | if(!tgalg[i].IsNull()) { |
480 | if(!CheckTgte(i)) { |
481 | Handle(Law_Function) fu1,fu2; |
482 | ptch->Func(fu1,fu2); |
c5f3a425 |
483 | Handle(Law_Function) ffu1 = Law::MixBnd(Handle(Law_Linear)::DownCast (fu1)); |
484 | Handle(Law_Function) ffu2 = Law::MixBnd(Handle(Law_Linear)::DownCast (fu2)); |
7fd59977 |
485 | ptch->SetFunc(ffu1,ffu2); |
486 | break; |
487 | } |
488 | } |
489 | } |
490 | |
491 | Build(); |
492 | } |
493 | |
494 | |
495 | //======================================================================= |
496 | //function : SetDomain |
497 | //purpose : |
498 | //======================================================================= |
499 | |
500 | void GeomFill_ConstrainedFilling::SetDomain |
501 | (const Standard_Real l, const Handle(GeomFill_BoundWithSurf)& B) |
502 | { |
503 | if(B == ptch->Bound(0)) dom[0] = Min(1.,Abs(l)); |
504 | else if(B == ptch->Bound(1)) dom[1] = Min(1.,Abs(l)); |
505 | else if(B == ptch->Bound(2)) dom[2] = Min(1.,Abs(l)); |
506 | else if(B == ptch->Bound(3)) dom[3] = Min(1.,Abs(l)); |
507 | } |
508 | |
509 | |
510 | //======================================================================= |
511 | //function : ReBuild |
512 | //purpose : |
513 | //======================================================================= |
514 | |
515 | void GeomFill_ConstrainedFilling::ReBuild() |
516 | { |
9775fa61 |
517 | if(!appdone) throw Standard_Failure("GeomFill_ConstrainedFilling::ReBuild Approx non faite"); |
7fd59977 |
518 | MatchKnots(); |
519 | PerformS0(); |
520 | PerformS1(); |
521 | PerformSurface(); |
522 | } |
523 | |
524 | |
525 | //======================================================================= |
526 | //function : Boundary |
527 | //purpose : |
528 | //======================================================================= |
529 | |
530 | Handle(GeomFill_Boundary) GeomFill_ConstrainedFilling::Boundary |
531 | (const Standard_Integer I) const |
532 | { |
533 | return ptch->Bound(I); |
534 | } |
535 | |
536 | |
537 | //======================================================================= |
538 | //function : Surface |
539 | //purpose : |
540 | //======================================================================= |
541 | |
542 | Handle(Geom_BSplineSurface) GeomFill_ConstrainedFilling::Surface() const |
543 | { |
544 | return surf; |
545 | } |
546 | |
547 | |
548 | //======================================================================= |
549 | //function : Build |
550 | //purpose : |
551 | //======================================================================= |
552 | |
553 | void GeomFill_ConstrainedFilling::Build() |
554 | { |
555 | for (Standard_Integer count = 0; count < 2; count++){ |
556 | ibound[0] = count; ibound[1] = count+2; |
557 | ctr[0] = ctr[1] = nbd3 = 0; |
558 | Standard_Integer ii ; |
559 | for ( ii = 0; ii < 2; ii++){ |
560 | if (ptch->Bound(ibound[ii])->HasNormals()) { |
561 | ctr[ii] = 2; |
562 | } |
563 | else if (!ptch->Bound(ibound[ii])->IsDegenerated()){ |
564 | ctr[ii] = 1; |
565 | } |
566 | nbd3 += ctr[ii]; |
567 | } |
0797d9d3 |
568 | #ifdef OCCT_DEBUG |
7fd59977 |
569 | appclock.Start(); |
570 | #endif |
571 | if(nbd3) PerformApprox(); |
0797d9d3 |
572 | #ifdef OCCT_DEBUG |
7fd59977 |
573 | appclock.Stop(); |
574 | #endif |
575 | } |
576 | appdone = Standard_True; |
0797d9d3 |
577 | #ifdef OCCT_DEBUG |
7fd59977 |
578 | cstclock.Start(); |
579 | #endif |
580 | MatchKnots(); |
581 | PerformS0(); |
582 | PerformS1(); |
583 | PerformSurface(); |
0797d9d3 |
584 | #ifdef OCCT_DEBUG |
7fd59977 |
585 | cstclock.Stop(); |
586 | totclock.Stop(); |
587 | Standard_Real tottime, apptime, partime, csttime; |
588 | totclock.Show(tottime); |
589 | parclock.Show(partime); |
590 | appclock.Show(apptime); |
591 | cstclock.Show(csttime); |
04232180 |
592 | std::cout<<"temp total : "<<tottime<<" secondes"<<std::endl; |
593 | std::cout<<std::endl; |
594 | std::cout<<"dont"<<std::endl; |
595 | std::cout<<std::endl; |
596 | std::cout<<"reparametrage : "<<partime<<" secondes"<<std::endl; |
597 | std::cout<<"approximation : "<<apptime<<" secondes"<<std::endl; |
598 | std::cout<<"construction formelle : "<<csttime<<" secondes"<<std::endl; |
599 | std::cout<<std::endl; |
7fd59977 |
600 | #endif |
601 | } |
602 | |
603 | |
604 | //======================================================================= |
605 | //function : PerformApprox |
606 | //purpose : |
607 | //======================================================================= |
608 | |
609 | void GeomFill_ConstrainedFilling::PerformApprox() |
610 | { |
611 | Standard_Integer ii ; |
612 | Handle(TColStd_HArray1OfReal) tol3d, tol2d, tol1d; |
613 | if(nbd3) tol3d = new TColStd_HArray1OfReal(1,nbd3); |
614 | Standard_Integer i3d = 0; |
615 | for( ii = 0; ii <= 1; ii++){ |
616 | if (ctr[ii]) {tol3d->SetValue((++i3d),ptch->Bound(ibound[ii])->Tol3d());} |
617 | if(ctr[ii] == 2){ |
618 | tol3d->SetValue(++i3d,0.5* mig[ibound[ii]] * ptch->Bound(ibound[ii])->Tolang()); |
619 | } |
620 | } |
621 | Standard_Real f,l; |
622 | ptch->Bound(ibound[0])->Bounds(f,l); |
623 | |
624 | GeomFill_ConstrainedFilling_Eval ev (*this); |
625 | AdvApprox_ApproxAFunction app(0, |
626 | 0, |
627 | nbd3, |
628 | tol1d, |
629 | tol2d, |
630 | tol3d, |
631 | f, |
632 | l, |
633 | GeomAbs_C1, |
634 | degmax, |
635 | segmax, |
636 | ev); |
637 | |
638 | if (app.IsDone() || app.HasResult()){ |
639 | Standard_Integer imk = Min(ibound[0],ibound[1]); |
640 | Standard_Integer nbpol = app.NbPoles(); |
641 | degree[imk] = app.Degree(); |
642 | mults[imk] = app.Multiplicities(); |
643 | knots[imk] = app.Knots(); |
644 | i3d = 0; |
645 | for(ii = 0; ii <= 1; ii++){ |
646 | curvpol[ibound[ii]] = new TColgp_HArray1OfPnt(1,nbpol); |
647 | TColgp_Array1OfPnt& cp = curvpol[ibound[ii]]->ChangeArray1(); |
648 | if (ctr[ii]){ |
649 | app.Poles(++i3d,cp); |
650 | } |
651 | else{ |
652 | gp_Pnt ppp = ptch->Bound(ibound[ii])->Value(0.5*(f+l)); |
653 | for(Standard_Integer ij = 1; ij <= nbpol; ij++){ |
654 | cp(ij) = ppp; |
655 | } |
656 | } |
657 | if(ctr[ii] == 2){ |
658 | tgtepol[ibound[ii]] = new TColgp_HArray1OfPnt(1,nbpol); |
659 | app.Poles(++i3d,tgtepol[ibound[ii]]->ChangeArray1()); |
660 | } |
661 | } |
662 | } |
663 | } |
664 | |
665 | |
666 | //======================================================================= |
667 | //function : MatchKnots |
668 | //purpose : |
669 | //======================================================================= |
670 | |
671 | void GeomFill_ConstrainedFilling::MatchKnots() |
672 | { |
673 | // on n insere rien si les domaines valent 1. |
674 | Standard_Integer i, j, l; |
675 | Standard_Integer ind[4]; |
676 | nm[0] = mults[0]; nm[1] = mults[1]; |
677 | nk[0] = knots[0]; nk[1] = knots[1]; |
678 | ind[0] = nk[1]->Length(); ind[2] = 1; |
679 | ind[1] = 1; ind[3] = nk[0]->Length(); |
680 | ncpol[0] = curvpol[0]; ncpol[1] = curvpol[1]; |
681 | ncpol[2] = curvpol[2]; ncpol[3] = curvpol[3]; |
682 | ntpol[0] = tgtepol[0]; ntpol[1] = tgtepol[1]; |
683 | ntpol[2] = tgtepol[2]; ntpol[3] = tgtepol[3]; |
684 | Standard_Real kadd[2]; |
685 | Standard_Integer madd[2]; |
686 | Standard_Real tolk = 1./Max(10,2*knots[1]->Array1().Length()); |
687 | Standard_Integer nbadd = inqadd(dom[0],dom[2],kadd,madd,degree[1],tolk); |
688 | if(nbadd){ |
689 | TColStd_Array1OfReal addk(kadd[0],1,nbadd); |
690 | TColStd_Array1OfInteger addm(madd[0],1,nbadd); |
691 | Standard_Integer nbnp, nbnk; |
692 | if(BSplCLib::PrepareInsertKnots(degree[1],0, |
693 | knots[1]->Array1(), |
694 | mults[1]->Array1(), |
0e14656b |
695 | addk,&addm,nbnp,nbnk,tolk,0)){ |
7fd59977 |
696 | nm[1] = new TColStd_HArray1OfInteger(1,nbnk); |
697 | nk[1] = new TColStd_HArray1OfReal(1,nbnk); |
698 | ncpol[1] = new TColgp_HArray1OfPnt(1,nbnp); |
699 | ncpol[3] = new TColgp_HArray1OfPnt(1,nbnp); |
700 | BSplCLib::InsertKnots(degree[1],0, |
0e14656b |
701 | curvpol[1]->Array1(),BSplCLib::NoWeights(), |
7fd59977 |
702 | knots[1]->Array1(),mults[1]->Array1(), |
0e14656b |
703 | addk,&addm, |
704 | ncpol[1]->ChangeArray1(),BSplCLib::NoWeights(), |
7fd59977 |
705 | nk[1]->ChangeArray1(),nm[1]->ChangeArray1(), |
706 | tolk,0); |
707 | |
708 | BSplCLib::InsertKnots(degree[1],0, |
0e14656b |
709 | curvpol[3]->Array1(),BSplCLib::NoWeights(), |
7fd59977 |
710 | knots[1]->Array1(),mults[1]->Array1(), |
0e14656b |
711 | addk,&addm, |
712 | ncpol[3]->ChangeArray1(),BSplCLib::NoWeights(), |
7fd59977 |
713 | nk[1]->ChangeArray1(),nm[1]->ChangeArray1(), |
714 | tolk,0); |
715 | if(!tgtepol[1].IsNull()){ |
716 | ntpol[1] = new TColgp_HArray1OfPnt(1,nbnp); |
717 | BSplCLib::InsertKnots(degree[1],0, |
0e14656b |
718 | tgtepol[1]->Array1(),BSplCLib::NoWeights(), |
7fd59977 |
719 | knots[1]->Array1(),mults[1]->Array1(), |
0e14656b |
720 | addk,&addm, |
721 | ntpol[1]->ChangeArray1(),BSplCLib::NoWeights(), |
7fd59977 |
722 | nk[1]->ChangeArray1(),nm[1]->ChangeArray1(), |
723 | tolk,0); |
724 | } |
725 | if(!tgtepol[3].IsNull()){ |
726 | ntpol[3] = new TColgp_HArray1OfPnt(1,nbnp); |
727 | BSplCLib::InsertKnots(degree[1],0, |
0e14656b |
728 | tgtepol[3]->Array1(),BSplCLib::NoWeights(), |
7fd59977 |
729 | knots[1]->Array1(),mults[1]->Array1(), |
0e14656b |
730 | addk,&addm, |
731 | ntpol[3]->ChangeArray1(),BSplCLib::NoWeights(), |
7fd59977 |
732 | nk[1]->ChangeArray1(),nm[1]->ChangeArray1(), |
733 | tolk,0); |
734 | } |
735 | } |
736 | if(dom[0] != 1.) { |
737 | for(i = 2; i <= nbnk; i++){ |
738 | if(Abs(dom[0]-nm[1]->Value(i)) < tolk){ |
739 | ind[0] = i; |
740 | break; |
741 | } |
742 | } |
743 | } |
744 | if(dom[2] != 1.) { |
745 | for(i = 1; i < nbnk; i++){ |
746 | if(Abs(1.-dom[2]-nm[1]->Value(i)) < tolk){ |
747 | ind[2] = i; |
748 | break; |
749 | } |
750 | } |
751 | } |
752 | } |
753 | tolk = 1./Max(10.,2.*knots[0]->Array1().Length()); |
754 | nbadd = inqadd(dom[1],dom[3],kadd,madd,degree[0],tolk); |
755 | if(nbadd){ |
756 | TColStd_Array1OfReal addk(kadd[0],1,nbadd); |
757 | TColStd_Array1OfInteger addm(madd[0],1,nbadd); |
758 | Standard_Integer nbnp, nbnk; |
759 | if(BSplCLib::PrepareInsertKnots(degree[0],0, |
760 | knots[0]->Array1(), |
761 | mults[0]->Array1(), |
0e14656b |
762 | addk,&addm,nbnp,nbnk,tolk,0)){ |
7fd59977 |
763 | nm[0] = new TColStd_HArray1OfInteger(1,nbnk); |
764 | nk[0] = new TColStd_HArray1OfReal(1,nbnk); |
765 | ncpol[0] = new TColgp_HArray1OfPnt(1,nbnp); |
766 | ncpol[2] = new TColgp_HArray1OfPnt(1,nbnp); |
767 | BSplCLib::InsertKnots(degree[0],0, |
0e14656b |
768 | curvpol[0]->Array1(),BSplCLib::NoWeights(), |
7fd59977 |
769 | knots[0]->Array1(),mults[0]->Array1(), |
0e14656b |
770 | addk,&addm, |
771 | ncpol[0]->ChangeArray1(),BSplCLib::NoWeights(), |
7fd59977 |
772 | nk[0]->ChangeArray1(),nm[0]->ChangeArray1(), |
773 | tolk,0); |
774 | |
775 | BSplCLib::InsertKnots(degree[0],0, |
0e14656b |
776 | curvpol[2]->Array1(),BSplCLib::NoWeights(), |
7fd59977 |
777 | knots[0]->Array1(),mults[0]->Array1(), |
0e14656b |
778 | addk,&addm, |
779 | ncpol[2]->ChangeArray1(),BSplCLib::NoWeights(), |
7fd59977 |
780 | nk[0]->ChangeArray1(),nm[0]->ChangeArray1(), |
781 | tolk,0); |
782 | if(!tgtepol[0].IsNull()){ |
783 | ntpol[0] = new TColgp_HArray1OfPnt(1,nbnp); |
784 | BSplCLib::InsertKnots(degree[0],0, |
0e14656b |
785 | tgtepol[0]->Array1(),BSplCLib::NoWeights(), |
7fd59977 |
786 | knots[0]->Array1(),mults[0]->Array1(), |
0e14656b |
787 | addk,&addm, |
788 | ntpol[0]->ChangeArray1(),BSplCLib::NoWeights(), |
7fd59977 |
789 | nk[0]->ChangeArray1(),nm[0]->ChangeArray1(), |
790 | tolk,0); |
791 | } |
792 | if(!tgtepol[2].IsNull()){ |
793 | ntpol[2] = new TColgp_HArray1OfPnt(1,nbnp); |
794 | BSplCLib::InsertKnots(degree[0],0, |
0e14656b |
795 | tgtepol[2]->Array1(),BSplCLib::NoWeights(), |
7fd59977 |
796 | knots[0]->Array1(),mults[0]->Array1(), |
0e14656b |
797 | addk,&addm, |
798 | ntpol[2]->ChangeArray1(),BSplCLib::NoWeights(), |
7fd59977 |
799 | nk[0]->ChangeArray1(),nm[0]->ChangeArray1(), |
800 | tolk,0); |
801 | } |
802 | } |
803 | if(dom[1] != 1.) { |
804 | for(i = 2; i <= nbnk; i++){ |
805 | if(Abs(dom[1]-nm[0]->Value(i)) < tolk){ |
806 | ind[1] = i; |
807 | break; |
808 | } |
809 | } |
810 | } |
811 | if(dom[3] != 1.) { |
812 | for(i = 1; i < nbnk; i++){ |
813 | if(Abs(1.-dom[3]-nm[0]->Value(i)) < tolk){ |
814 | ind[3] = i; |
815 | break; |
816 | } |
817 | } |
818 | } |
819 | } |
820 | Handle(Law_Linear) fu = mklin(ptch->Func(0)); |
821 | ab[0] = Law::MixBnd(degree[1],nk[1]->Array1(),nm[1]->Array1(),fu); |
822 | fu = mklin(ptch->Func(1)); |
823 | ab[1] = Law::MixBnd(degree[0],nk[0]->Array1(),nm[0]->Array1(),fu); |
824 | |
825 | for(i = 0; i<2; i++){ |
826 | l = ab[i]->Length(); |
827 | ab[i+2] = new TColStd_HArray1OfReal(1,l); |
828 | for(j = 1; j <= l; j++){ |
829 | ab[i+2]->SetValue(j,1.-ab[i]->Value(j)); |
830 | } |
831 | } |
832 | pq[0] = Law::MixTgt(degree[1],nk[1]->Array1(),nm[1]->Array1(),1,ind[0]); |
833 | pq[2] = Law::MixTgt(degree[1],nk[1]->Array1(),nm[1]->Array1(),0,ind[2]); |
834 | |
835 | pq[1] = Law::MixTgt(degree[0],nk[0]->Array1(),nm[0]->Array1(),0,ind[1]); |
836 | pq[3] = Law::MixTgt(degree[0],nk[0]->Array1(),nm[0]->Array1(),1,ind[3]); |
837 | |
838 | #ifdef DRAW |
839 | if(dodraw){ |
840 | gp_Vec2d tra(0.,0.); |
841 | Standard_Real scal = 1.; |
842 | Law_draw1dcurve(ab[0]->Array1(),nk[1]->Array1(),nm[1]->Array1(),degree[1],tra,scal); |
843 | tra.SetCoord(1.,0.); |
844 | Law_draw1dcurve(ab[1]->Array1(),nk[0]->Array1(),nm[0]->Array1(),degree[0],tra,scal); |
845 | tra.SetCoord(0.,1.); |
846 | Law_draw1dcurve(ab[2]->Array1(),nk[1]->Array1(),nm[1]->Array1(),degree[1],tra,scal); |
847 | tra.SetCoord(1.,1.); |
848 | Law_draw1dcurve(ab[3]->Array1(),nk[0]->Array1(),nm[0]->Array1(),degree[0],tra,scal); |
849 | tra.SetCoord(0.,0.); |
850 | Law_draw1dcurve(pq[0]->Array1(),nk[1]->Array1(),nm[1]->Array1(),degree[1],tra,scal); |
851 | tra.SetCoord(0.,1.); |
852 | Law_draw1dcurve(pq[2]->Array1(),nk[1]->Array1(),nm[1]->Array1(),degree[1],tra,scal); |
853 | tra.SetCoord(1.,0.); |
854 | Law_draw1dcurve(pq[1]->Array1(),nk[0]->Array1(),nm[0]->Array1(),degree[0],tra,scal); |
855 | tra.SetCoord(1.,1.); |
856 | Law_draw1dcurve(pq[3]->Array1(),nk[0]->Array1(),nm[0]->Array1(),degree[0],tra,scal); |
857 | } |
858 | #endif |
859 | } |
860 | |
861 | |
862 | //======================================================================= |
863 | //function : PerformS0 |
864 | //purpose : |
865 | //======================================================================= |
866 | |
867 | void GeomFill_ConstrainedFilling::PerformS0() |
868 | { |
869 | // On construit les poles de S0 par combinaison des poles des bords, |
870 | // des poles des fonctions ab, des points c selon la formule : |
871 | // S0(i,j) = ab[0](j)*ncpol[0](i) + ab[1](i)*ncpol[1](j) |
872 | // + ab[2](j)*ncpol[2](i) + ab[3](i)*ncpol[3](j) |
873 | // - ab[3](i)*ab[0](j)*c[0] - ab[0](j)*ab[1](i)*c[1] |
874 | // - ab[1](i)*ab[2](j)*c[2] - ab[2](j)*ab[3](i)*c[3] |
875 | |
876 | Standard_Integer i, j; |
877 | Standard_Integer ni = ncpol[0]->Length(); |
878 | Standard_Integer nj = ncpol[1]->Length(); |
879 | S0 = new TColgp_HArray2OfPnt(1,ni,1,nj); |
880 | TColgp_Array2OfPnt& ss0 = S0->ChangeArray2(); |
881 | const gp_XYZ& c0 = ptch->Corner(0).Coord(); |
882 | const gp_XYZ& c1 = ptch->Corner(1).Coord(); |
883 | const gp_XYZ& c2 = ptch->Corner(2).Coord(); |
884 | const gp_XYZ& c3 = ptch->Corner(3).Coord(); |
885 | for (i = 1; i <= ni; i++){ |
886 | Standard_Real ab1 = ab[1]->Value(i); |
887 | Standard_Real ab3 = ab[3]->Value(i); |
888 | const gp_XYZ& b0 = ncpol[0]->Value(i).Coord(); |
889 | const gp_XYZ& b2 = ncpol[2]->Value(i).Coord(); |
890 | for (j = 1; j <= nj; j++){ |
891 | Standard_Real ab0 = ab[0]->Value(j); |
892 | Standard_Real ab2 = ab[2]->Value(j); |
893 | const gp_XYZ& b1 = ncpol[1]->Value(j).Coord(); |
894 | const gp_XYZ& b3 = ncpol[3]->Value(j).Coord(); |
895 | gp_XYZ polij = b0.Multiplied(ab0); |
896 | gp_XYZ temp = b1.Multiplied(ab1); |
897 | polij.Add(temp); |
898 | temp = b2.Multiplied(ab2); |
899 | polij.Add(temp); |
900 | temp = b3.Multiplied(ab3); |
901 | polij.Add(temp); |
902 | temp = c0.Multiplied(-ab3*ab0); |
903 | polij.Add(temp); |
904 | temp = c1.Multiplied(-ab0*ab1); |
905 | polij.Add(temp); |
906 | temp = c2.Multiplied(-ab1*ab2); |
907 | polij.Add(temp); |
908 | temp = c3.Multiplied(-ab2*ab3); |
909 | polij.Add(temp); |
910 | ss0(i,j).SetXYZ(polij); |
911 | } |
912 | } |
913 | } |
914 | |
915 | |
916 | //======================================================================= |
917 | //function : PerformS1 |
918 | //purpose : |
919 | //======================================================================= |
920 | |
921 | void GeomFill_ConstrainedFilling::PerformS1() |
922 | { |
923 | // on construit en temporaire les poles des champs tangents |
924 | // definis par : |
925 | // tgte[ibound](u) - d/dv (S0(u,vbound)) pour ibound = 0 ou 2 |
926 | // tgte[ibound](v) - d/du (S0(ubound,v)) pour ibound = 1 ou 3 |
927 | // sur les bords ou tgte est defini. |
928 | gp_XYZ* nt[4]; |
929 | const TColgp_Array2OfPnt& ss0 = S0->Array2(); |
930 | Standard_Integer l, i, j, k; |
931 | Standard_Integer ni = ss0.ColLength(); |
932 | Standard_Integer nj = ss0.RowLength(); |
933 | for(i = 0; i <= 3; i++){ |
934 | if(ntpol[i].IsNull()) nt[i] = 0; |
935 | else { |
936 | Standard_Real z=0; |
937 | Standard_Integer nbp = ntpol[i]->Length(); |
938 | Standard_Integer i1=0,i2=0,j1=0,j2=0; |
939 | Standard_Boolean inci=0; |
940 | nt[i] = new gp_XYZ[nbp]; |
941 | switch(i){ |
942 | case 0 : |
943 | z = - degree[1]/(nk[1]->Value(2) - nk[1]->Value(1)); |
944 | inci = Standard_True; |
945 | i1 = 1; i2 = 1; j1 = 1; j2 = 2; |
946 | break; |
947 | case 1 : |
948 | l = nk[0]->Length(); |
949 | z = - degree[0]/(nk[0]->Value(l) - nk[0]->Value(l-1)); |
950 | inci = Standard_False; |
951 | i1 = ni-1; i2 = ni; j1 = 1; j2 = 1; |
952 | break; |
953 | case 2 : |
954 | l = nk[1]->Length(); |
955 | z = - degree[1]/(nk[1]->Value(l) - nk[1]->Value(l-1)); |
956 | inci = Standard_True; |
957 | i1 = 1; i2 = 1; j1 = nj-1; j2 = nj; |
958 | break; |
959 | case 3 : |
960 | z = - degree[0]/(nk[0]->Value(2) - nk[0]->Value(1)); |
961 | inci = Standard_False; |
962 | i1 = 1; i2 = 2; j1 = 1; j2 = 1; |
963 | break; |
964 | } |
965 | for(k = 0; k < nbp; k++){ |
966 | nt[i][k] = S0->Value(i1,j1).XYZ(); |
967 | nt[i][k].Multiply(-1.); |
968 | nt[i][k].Add(S0->Value(i2,j2).XYZ()); |
969 | nt[i][k].Multiply(z); |
970 | nt[i][k].Add(ntpol[i]->Value(k+1).XYZ()); |
971 | if(inci) { i1++; i2++; } |
972 | else { j1++; j2++; } |
973 | } |
974 | } |
975 | } |
976 | // on calcul les termes correctifs pour le melange. |
977 | Standard_Real coef0 = degree[0]/(nk[0]->Value(2) - nk[0]->Value(1)); |
978 | Standard_Real coef1 = degree[1]/(nk[1]->Value(2) - nk[1]->Value(1)); |
979 | gp_XYZ vtemp, vtemp0, vtemp1; |
980 | if(nt[0] && nt[3]){ |
981 | vtemp0 = nt[0][0].Multiplied(-1.); |
982 | vtemp0.Add(nt[0][1]); |
983 | vtemp0.Multiply(coef0); |
984 | vtemp1 = nt[3][0].Multiplied(-1.); |
985 | vtemp1.Add(nt[3][1]); |
986 | vtemp1.Multiply(coef1); |
987 | vtemp = vtemp0.Added(vtemp1); |
988 | vtemp.Multiply(0.5); |
989 | v[0].SetXYZ(vtemp); |
990 | } |
991 | |
992 | Standard_Integer ln0 = nk[0]->Length(), lp0 = ncpol[0]->Length(); |
993 | coef0 = degree[0]/(nk[0]->Value(ln0) - nk[0]->Value(ln0 - 1)); |
994 | coef1 = degree[1]/(nk[1]->Value(2) - nk[1]->Value(1)); |
995 | if(nt[0] && nt[1]){ |
996 | vtemp0 = nt[0][lp0 - 2].Multiplied(-1.); |
997 | vtemp0.Add(nt[0][lp0 - 1]); |
998 | vtemp0.Multiply(coef0); |
999 | vtemp1 = nt[1][0].Multiplied(-1.); |
1000 | vtemp1.Add(nt[1][1]); |
1001 | vtemp1.Multiply(coef1); |
1002 | vtemp = vtemp0.Added(vtemp1); |
1003 | vtemp.Multiply(0.5); |
1004 | v[1].SetXYZ(vtemp); |
1005 | } |
1006 | ln0 = nk[0]->Length(); lp0 = ncpol[0]->Length(); |
1007 | Standard_Integer ln1 = nk[1]->Length(), lp1 = ncpol[1]->Length(); |
1008 | coef0 = degree[0]/(nk[0]->Value(ln0) - nk[0]->Value(ln0 - 1)); |
1009 | coef1 = degree[1]/(nk[1]->Value(ln1) - nk[1]->Value(ln1 - 1)); |
1010 | if(nt[1] && nt[2]){ |
1011 | vtemp0 = nt[2][lp0 - 2].Multiplied(-1.); |
1012 | vtemp0.Add(nt[2][lp0 - 1]); |
1013 | vtemp0.Multiply(coef0); |
1014 | vtemp1 = nt[1][lp1 - 2].Multiplied(-1.); |
1015 | vtemp1.Add(nt[1][lp1 - 1]); |
1016 | vtemp1.Multiply(coef1); |
1017 | vtemp = vtemp0.Added(vtemp1); |
1018 | vtemp.Multiply(0.5); |
1019 | v[2].SetXYZ(vtemp); |
1020 | } |
1021 | ln1 = nk[1]->Length(); lp1 = ncpol[1]->Length(); |
1022 | coef0 = degree[0]/(nk[0]->Value(2) - nk[0]->Value(1)); |
1023 | coef1 = degree[1]/(nk[1]->Value(ln1) - nk[1]->Value(ln1 - 1)); |
1024 | if(nt[2] && nt[3]){ |
1025 | vtemp0 = nt[2][0].Multiplied(-1.); |
1026 | vtemp0.Add(nt[2][1]); |
1027 | vtemp0.Multiply(coef0); |
1028 | vtemp1 = nt[3][lp1 - 2].Multiplied(-1.); |
1029 | vtemp1.Add(nt[3][lp1 - 1]); |
1030 | vtemp1.Multiply(coef1); |
1031 | vtemp = vtemp0.Added(vtemp1); |
1032 | vtemp.Multiply(0.5); |
1033 | v[3].SetXYZ(vtemp); |
1034 | } |
1035 | |
1036 | // On construit les poles de S1 par combinaison des poles des |
1037 | // champs tangents, des poles des fonctions pq, des duv au coins |
1038 | // selon la formule : |
1039 | // S1(i,j) = pq[0](j)*ntpol[0](i) + pq[1](i)*ntpol[1](j) |
1040 | // + pq[2](j)*ntpol[2](i) + pq[3](i)*ntpol[3](j) |
1041 | // - pq[3](i)*pq[0](j)*v[0] - pq[0](j)*pq[1](i)*v[1] |
1042 | // - pq[1](i)*pq[2](j)*v[2] - pq[2](j)*pq[3](i)*v[3] |
1043 | S1 = new TColgp_HArray2OfPnt(1,ni,1,nj); |
1044 | TColgp_Array2OfPnt& ss1 = S1->ChangeArray2(); |
1045 | const gp_XYZ& v0 = v[0].XYZ(); |
1046 | const gp_XYZ& v1 = v[1].XYZ(); |
1047 | const gp_XYZ& v2 = v[2].XYZ(); |
1048 | const gp_XYZ& v3 = v[3].XYZ(); |
1049 | |
1050 | for (i = 1; i <= ni; i++){ |
1051 | Standard_Real pq1=0, pq3=0; |
1052 | if(nt[1]) pq1 = -pq[1]->Value(i); |
1053 | if(nt[3]) pq3 = pq[3]->Value(i); |
1054 | gp_XYZ t0, t2; |
1055 | if(nt[0]) t0 = nt[0][i-1]; |
1056 | if(nt[2]) t2 = nt[2][i-1]; |
1057 | for (j = 1; j <= nj; j++){ |
1058 | Standard_Real pq0=0, pq2=0; |
1059 | if(nt[0]) pq0 = pq[0]->Value(j); |
1060 | if(nt[2]) pq2 = -pq[2]->Value(j); |
1061 | gp_XYZ t1, t3; |
1062 | if(nt[1]) t1 = nt[1][j-1]; |
1063 | if(nt[3]) t3 = nt[3][j-1]; |
1064 | |
1065 | gp_XYZ tpolij(0.,0.,0.), temp; |
1066 | if(nt[0]) { |
1067 | temp = t0.Multiplied(pq0); |
1068 | tpolij.Add(temp); |
1069 | } |
1070 | if(nt[1]) { |
1071 | temp = t1.Multiplied(pq1); |
1072 | tpolij.Add(temp); |
1073 | } |
1074 | if(nt[2]){ |
1075 | temp = t2.Multiplied(pq2); |
1076 | tpolij.Add(temp); |
1077 | } |
1078 | if(nt[3]){ |
1079 | temp = t3.Multiplied(pq3); |
1080 | tpolij.Add(temp); |
1081 | } |
1082 | if(nt[3] && nt[0]){ |
1083 | temp = v0.Multiplied(-pq3*pq0); |
1084 | tpolij.Add(temp); |
1085 | } |
1086 | if(nt[0] && nt[1]){ |
1087 | temp = v1.Multiplied(-pq0*pq1); |
1088 | tpolij.Add(temp); |
1089 | } |
1090 | if(nt[1] && nt[2]){ |
1091 | temp = v2.Multiplied(-pq1*pq2); |
1092 | tpolij.Add(temp); |
1093 | } |
1094 | if(nt[2] && nt[3]){ |
1095 | temp = v3.Multiplied(-pq2*pq3); |
1096 | tpolij.Add(temp); |
1097 | } |
1098 | ss1(i,j).SetXYZ(tpolij); |
1099 | } |
1100 | } |
1101 | |
1102 | // Un petit menage |
1103 | for(i = 0; i <= 3; i++){ |
1104 | if(nt[i]){ |
1105 | delete[] nt[i]; |
1106 | } |
1107 | } |
1108 | } |
1109 | |
1110 | |
1111 | //======================================================================= |
1112 | //function : PerformSurface |
1113 | //purpose : |
1114 | //======================================================================= |
1115 | |
1116 | void GeomFill_ConstrainedFilling::PerformSurface() |
1117 | { |
1118 | Standard_Integer ni = S0->ColLength(), nj = S0->RowLength(),i,j; |
1119 | TColgp_Array2OfPnt temp(1,ni,1,nj); |
1120 | const TColgp_Array2OfPnt& t0 = S0->Array2(); |
1121 | const TColgp_Array2OfPnt& t1 = S1->Array2(); |
1122 | for(i = 1; i <= ni; i++){ |
1123 | for(j = 1; j <= nj; j++){ |
1124 | temp(i,j).SetXYZ(t0(i,j).XYZ().Added(t1(i,j).XYZ())); |
1125 | } |
1126 | } |
1127 | surf = new Geom_BSplineSurface(temp, |
1128 | nk[0]->Array1(),nk[1]->Array1(), |
1129 | nm[0]->Array1(),nm[1]->Array1(), |
1130 | degree[0],degree[1]); |
1131 | } |
1132 | |
1133 | //======================================================================= |
1134 | //function : CheckTgte |
1135 | //purpose : |
1136 | //======================================================================= |
1137 | |
1138 | Standard_Boolean GeomFill_ConstrainedFilling::CheckTgte(const Standard_Integer I) |
1139 | { |
1140 | Handle(GeomFill_Boundary) bou = ptch->Bound(I); |
1141 | if(!bou->HasNormals()) return Standard_True; |
1142 | // On prend 13 points le long du bord et on verifie que le triedre |
1143 | // forme par la tangente a la courbe la normale et la tangente du |
1144 | // peigne ne change pas d orientation. |
1145 | Standard_Real ll = 1./12., pmix=0; |
1146 | for (Standard_Integer iu = 0; iu < 13; iu++){ |
1147 | Standard_Real uu = iu * ll; |
1148 | gp_Pnt pbid; |
1149 | gp_Vec tgte; |
1150 | bou->D1(uu,pbid,tgte); |
1151 | gp_Vec norm = bou->Norm(uu); |
1152 | gp_Vec vfield = tgalg[I]->Value(uu); |
1153 | if(iu == 0) pmix = vfield.Dot(tgte.Crossed(norm)); |
1154 | else { |
1155 | Standard_Real pmixcur = vfield.Dot(tgte.Crossed(norm)); |
1156 | if(pmix*pmixcur < 0.) return Standard_False; |
1157 | } |
1158 | } |
1159 | return Standard_True; |
1160 | } |
1161 | |
1162 | //======================================================================= |
1163 | //function : MinTgte |
1164 | //purpose : |
1165 | //======================================================================= |
1166 | |
1167 | void GeomFill_ConstrainedFilling::MinTgte(const Standard_Integer I) |
1168 | { |
1169 | if(!ptch->Bound(I)->HasNormals()) return; |
1170 | Standard_Real minmag = RealLast(); |
1171 | Standard_Real ll = 0.02; |
1172 | for (Standard_Integer iu = 0; iu <= 30; iu++){ |
1173 | Standard_Real uu = 0.2 + iu * ll; |
1174 | gp_Vec vv = tgalg[I]->Value(uu); |
1175 | Standard_Real temp = vv.SquareMagnitude(); |
1176 | if(temp < minmag) minmag = temp; |
1177 | } |
1178 | mig[I] = sqrt(minmag); |
1179 | } |
1180 | |
1181 | //======================================================================= |
1182 | //function : Eval |
1183 | //purpose : |
1184 | //======================================================================= |
1185 | |
1186 | Standard_Integer GeomFill_ConstrainedFilling::Eval(const Standard_Real W, |
1187 | const Standard_Integer Ord, |
1188 | Standard_Real& Result)const |
1189 | { |
1190 | Standard_Real* res = &Result; |
1191 | Standard_Integer jmp = (3 * ctr[0]); |
1192 | switch(Ord){ |
1193 | case 0 : |
1194 | if(ctr[0]){ |
1195 | ptch->Bound(ibound[0])->Value(W).Coord(res[0],res[1],res[2]); |
1196 | } |
1197 | if(ctr[0] == 2){ |
1198 | tgalg[ibound[0]]->Value(W).Coord(res[3],res[4],res[5]); |
1199 | } |
1200 | if(ctr[1]){ |
1201 | ptch->Bound(ibound[1])->Value(W).Coord(res[jmp],res[jmp+1],res[jmp+2]); |
1202 | } |
1203 | if(ctr[1] == 2){ |
1204 | tgalg[ibound[1]]->Value(W).Coord(res[jmp+3],res[jmp+4],res[jmp+5]); |
1205 | } |
1206 | break; |
1207 | case 1 : |
1208 | gp_Pnt pt; |
1209 | gp_Vec vt; |
1210 | if(ctr[0]){ |
1211 | ptch->Bound(ibound[0])->D1(W,pt,vt); |
1212 | vt.Coord(res[0],res[1],res[2]); |
1213 | } |
1214 | if(ctr[0] == 2){ |
1215 | tgalg[ibound[0]]->D1(W).Coord(res[3],res[4],res[5]); |
1216 | } |
1217 | if(ctr[1]){ |
1218 | ptch->Bound(ibound[1])->D1(W,pt,vt); |
1219 | vt.Coord(res[jmp],res[jmp+1],res[jmp+2]); |
1220 | } |
1221 | if(ctr[1] == 2){ |
1222 | tgalg[ibound[1]]->D1(W).Coord(res[jmp+3],res[jmp+4],res[jmp+5]); |
1223 | } |
1224 | break; |
1225 | } |
1226 | return 0; |
1227 | } |
1228 | |
1229 | //======================================================================= |
1230 | //function : CheckCoonsAlgPatch |
1231 | //purpose : |
1232 | //======================================================================= |
1233 | |
1234 | void GeomFill_ConstrainedFilling::CheckCoonsAlgPatch(const Standard_Integer I) |
1235 | { |
1236 | Standard_Integer nbp = 30; |
1237 | Standard_Real uu=0,duu=0,vv=0,dvv=0,ww=0,dww=0,u1,u2,v1,v2; |
1238 | surf->Bounds(u1,u2,v1,v2); |
1239 | Standard_Boolean enu = Standard_False; |
1240 | switch(I){ |
1241 | case 0: |
1242 | uu = ww = u1; |
1243 | vv = v1; |
1244 | duu = dww = (u2 - u1)/nbp; |
1245 | dvv = 0.; |
1246 | break; |
1247 | case 1: |
1248 | vv = ww = v1; |
1249 | uu = u2; |
1250 | dvv = dww = (v2 - v1)/nbp; |
1251 | duu = 0.; |
1252 | enu = Standard_True; |
1253 | break; |
1254 | case 2: |
1255 | uu = ww = u1; |
1256 | vv = v2; |
1257 | duu = dww = (u2 - u1)/nbp; |
1258 | dvv = 0.; |
1259 | break; |
1260 | case 3: |
1261 | vv = ww = v1; |
1262 | uu = u1; |
1263 | dvv = dww = (v2 - v1)/nbp; |
1264 | duu = 0.; |
1265 | enu = Standard_True; |
1266 | break; |
1267 | } |
1268 | gp_Pnt pbound; |
1269 | gp_Vec vptch; |
1270 | Handle(GeomFill_Boundary) bou = ptch->Bound(I); |
1271 | for (Standard_Integer k = 0; k <= nbp; k++){ |
1272 | pbound = bou->Value(ww); |
1273 | if(enu) vptch = ptch->D1U(uu,vv); |
1274 | else vptch = ptch->D1V(uu,vv); |
1275 | #ifdef DRAW |
1276 | gp_Pnt pp; |
1277 | Handle(Draw_Segment3D) seg; |
1278 | pp = pbound.Translated(vptch); |
1279 | seg = new Draw_Segment3D(pbound,pp,Draw_jaune); |
1280 | dout << seg; |
1281 | #endif |
1282 | uu += duu; |
1283 | vv += dvv; |
1284 | ww += dww; |
1285 | } |
1286 | } |
1287 | |
1288 | //======================================================================= |
1289 | //function : CheckTgteField |
1290 | //purpose : |
1291 | //======================================================================= |
1292 | |
1293 | void GeomFill_ConstrainedFilling::CheckTgteField(const Standard_Integer I) |
1294 | { |
1295 | if(tgalg[I].IsNull()) return; |
1296 | #ifdef DRAW |
1297 | gp_Pnt p1,p2; |
1298 | #else |
1299 | gp_Pnt p1; |
1300 | #endif |
1301 | gp_Vec d1; |
1302 | Standard_Boolean caplisse = 0; |
1303 | Standard_Real maxang = 0.,pmix=0,pmixcur; |
1304 | Handle(GeomFill_Boundary) bou = ptch->Bound(I); |
1305 | for (Standard_Integer iu = 0; iu <= 30; iu++){ |
1306 | Standard_Real uu = iu/30.; |
1307 | bou->D1(uu,p1,d1); |
1308 | gp_Vec vtg = tgalg[I]->Value(uu); |
1309 | gp_Vec vnor = bou->Norm(uu); |
1310 | gp_Vec vcros = d1.Crossed(vnor); |
1311 | vcros.Normalize(); |
1312 | if(iu == 0) pmix = vtg.Dot(vcros); |
1313 | else { |
1314 | pmixcur = vtg.Dot(vcros); |
1315 | if(pmix*pmixcur < 0.) caplisse = 1; |
1316 | } |
1317 | #ifdef DRAW |
1318 | Handle(Draw_Segment3D) seg; |
1319 | p2 = p1.Translated(vtg); |
1320 | seg = new Draw_Segment3D(p1,p2,Draw_blanc); |
1321 | dout << seg; |
1322 | p2 = p1.Translated(vnor); |
1323 | seg = new Draw_Segment3D(p1,p2,Draw_rouge); |
1324 | dout << seg; |
1325 | p2 = p1.Translated(vcros); |
1326 | seg = new Draw_Segment3D(p1,p2,Draw_jaune); |
1327 | dout << seg; |
1328 | #endif |
1329 | if(vnor.Magnitude() > 1.e-15 && vtg.Magnitude() > 1.e-15){ |
c6541a0c |
1330 | Standard_Real alpha = Abs(M_PI/2.-Abs(vnor.Angle(vtg))); |
7fd59977 |
1331 | if(Abs(alpha) > maxang) maxang = Abs(alpha); |
1332 | } |
1333 | } |
04232180 |
1334 | std::cout<<"KAlgo angle max sur bord "<<I<<" : "<<maxang<<std::endl; |
1335 | if(caplisse) std::cout<<"sur bord "<<I<<" le champ tangent change de cote!"<<std::endl; |
7fd59977 |
1336 | } |
1337 | |
1338 | |
1339 | //======================================================================= |
1340 | //function : CheckApprox |
1341 | //purpose : |
1342 | //======================================================================= |
1343 | |
1344 | void GeomFill_ConstrainedFilling::CheckApprox(const Standard_Integer I) |
1345 | { |
1346 | Standard_Boolean donor = !tgalg[I].IsNull(); |
1347 | Standard_Integer nbp = 30; |
1348 | Standard_Real maxang = 0., maxdist = 0.; |
1349 | gp_Pnt pbound, papp, pbid; |
1350 | gp_Vec vbound, vapp; |
1351 | Handle(GeomFill_Boundary) bou = ptch->Bound(I); |
1352 | for (Standard_Integer iu = 0; iu <= nbp; iu++){ |
1353 | Standard_Real uu = iu; |
1354 | uu /= nbp; |
1355 | pbound = bou->Value(uu); |
1356 | BSplCLib::D0(uu,0,degree[I%2],0,ncpol[I]->Array1(),BSplCLib::NoWeights(), |
0e14656b |
1357 | nk[I%2]->Array1(),&nm[I%2]->Array1(),papp); |
7fd59977 |
1358 | if(donor) { |
1359 | BSplCLib::D0(uu,0,degree[I%2],0,ntpol[I]->Array1(),BSplCLib::NoWeights(), |
0e14656b |
1360 | nk[I%2]->Array1(),&nm[I%2]->Array1(),pbid); |
7fd59977 |
1361 | vapp.SetXYZ(pbid.XYZ()); |
1362 | vbound = bou->Norm(uu); |
1363 | if(vapp.Magnitude() > 1.e-15 && vbound.Magnitude() > 1.e-15){ |
c6541a0c |
1364 | Standard_Real alpha = Abs(M_PI/2.-Abs(vbound.Angle(vapp))); |
7fd59977 |
1365 | if(Abs(alpha) > maxang) maxang = Abs(alpha); |
1366 | } |
1367 | #ifdef DRAW |
1368 | Handle(Draw_Segment3D) seg; |
1369 | gp_Pnt pp; |
1370 | pp = pbound.Translated(vbound); |
1371 | seg = new Draw_Segment3D(pbound,pp,Draw_blanc); |
1372 | dout << seg; |
1373 | pp = papp.Translated(vapp); |
1374 | seg = new Draw_Segment3D(papp,pp,Draw_rouge); |
1375 | dout << seg; |
1376 | #endif |
1377 | } |
1378 | if(papp.Distance(pbound) > maxdist) maxdist = papp.Distance(pbound); |
1379 | } |
04232180 |
1380 | std::cout<<"Controle approx/contrainte sur bord "<<I<<" : "<<std::endl; |
1381 | std::cout<<"Distance max : "<<maxdist<<std::endl; |
7fd59977 |
1382 | if (donor) { |
c6541a0c |
1383 | maxang = maxang*180./M_PI; |
04232180 |
1384 | std::cout<<"Angle max : "<<maxang<<" deg"<<std::endl; |
7fd59977 |
1385 | } |
1386 | } |
1387 | |
1388 | |
1389 | //======================================================================= |
1390 | //function : CheckResult |
1391 | //purpose : |
1392 | //======================================================================= |
1393 | |
1394 | void GeomFill_ConstrainedFilling::CheckResult(const Standard_Integer I) |
1395 | { |
1396 | Standard_Boolean donor = !tgalg[I].IsNull(); |
1397 | Standard_Real maxang = 0., maxdist = 0.; |
1398 | Standard_Real uu=0,duu=0,vv=0,dvv=0,ww=0,dww=0,u1,u2,v1,v2; |
1399 | surf->Bounds(u1,u2,v1,v2); |
1400 | switch(I){ |
1401 | case 0: |
1402 | uu = ww = u1; |
1403 | vv = v1; |
1404 | duu = dww = (u2 - u1)/30; |
1405 | dvv = 0.; |
1406 | break; |
1407 | case 1: |
1408 | vv = ww = v1; |
1409 | uu = u2; |
1410 | dvv = dww = (v2 - v1)/30; |
1411 | duu = 0.; |
1412 | break; |
1413 | case 2: |
1414 | uu = ww = u1; |
1415 | vv = v2; |
1416 | duu = dww = (u2 - u1)/30; |
1417 | dvv = 0.; |
1418 | break; |
1419 | case 3: |
1420 | vv = ww = v1; |
1421 | uu = u1; |
1422 | dvv = dww = (v2 - v1)/30; |
1423 | duu = 0.; |
1424 | break; |
1425 | } |
1426 | gp_Pnt pbound[31],pres[31]; |
1427 | gp_Vec vbound[31],vres[31]; |
96a95605 |
1428 | #ifdef DRAW |
7fd59977 |
1429 | Standard_Real ang[31]; |
1430 | Standard_Boolean hasang[31]; |
96a95605 |
1431 | #endif |
7fd59977 |
1432 | Handle(GeomFill_Boundary) bou = ptch->Bound(I); |
1433 | Standard_Integer k ; |
1434 | for ( k = 0; k <= 30; k++){ |
1435 | pbound[k] = bou->Value(ww); |
1436 | if(!donor) surf->D0(uu,vv,pres[k]); |
1437 | else{ |
1438 | vbound[k] = bou->Norm(ww); |
1439 | gp_Vec V1,V2; |
1440 | surf->D1(uu,vv,pres[k],V1,V2); |
1441 | vres[k] = V1.Crossed(V2); |
1442 | if(vres[k].Magnitude() > 1.e-15 && vbound[k].Magnitude() > 1.e-15){ |
1443 | Standard_Real alpha = Abs(vres[k].Angle(vbound[k])); |
c6541a0c |
1444 | alpha = Min(alpha,Abs(M_PI-alpha)); |
7fd59977 |
1445 | if(alpha > maxang) maxang = alpha; |
96a95605 |
1446 | #ifdef DRAW |
7fd59977 |
1447 | ang[k] = alpha; |
1448 | hasang[k] = 1; |
96a95605 |
1449 | #endif |
7fd59977 |
1450 | } |
96a95605 |
1451 | #ifdef DRAW |
7fd59977 |
1452 | else hasang[k] = 0; |
96a95605 |
1453 | #endif |
7fd59977 |
1454 | } |
1455 | if(pres[k].Distance(pbound[k]) > maxdist) maxdist = pres[k].Distance(pbound[k]); |
1456 | uu += duu; |
1457 | vv += dvv; |
1458 | ww += dww; |
1459 | } |
04232180 |
1460 | std::cout<<"Controle resultat/contrainte sur bord "<<I<<" : "<<std::endl; |
1461 | std::cout<<"Distance max : "<<maxdist<<std::endl; |
7fd59977 |
1462 | if (donor) { |
c6541a0c |
1463 | Standard_Real angdeg = maxang*180./M_PI; |
04232180 |
1464 | std::cout<<"Angle max : "<<angdeg<<" deg"<<std::endl; |
7fd59977 |
1465 | } |
1466 | #ifdef DRAW |
1467 | Standard_Boolean scale = maxang>1.e-10; |
1468 | for (k = 0; k <= 30; k++){ |
1469 | if(hasang[k]){ |
1470 | gp_Pnt pp; |
1471 | Handle(Draw_Segment3D) seg; |
1472 | vbound[k].Normalize(); |
1473 | if(scale) vbound[k].Multiply(1.+3.*ang[k]/maxang); |
1474 | vbound[k].Multiply(drawfac); |
1475 | pp = pbound[k].Translated(vbound[k]); |
1476 | seg = new Draw_Segment3D(pbound[k],pp,Draw_blanc); |
1477 | dout << seg; |
1478 | vres[k].Normalize(); |
1479 | if(scale) vres[k].Multiply(1.+3.*ang[k]/maxang); |
1480 | vres[k].Multiply(drawfac); |
1481 | pp = pres[k].Translated(vres[k]); |
1482 | seg = new Draw_Segment3D(pres[k],pp,Draw_rouge); |
1483 | dout << seg; |
1484 | } |
1485 | } |
1486 | #endif |
1487 | } |
1488 | |