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