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