1// Copyright (c) 1995-1999 Matra Datavision
2// Copyright (c) 1999-2014 OPEN CASCADE SAS
3//
4// This file is part of Open CASCADE Technology software library.
5//
6// This library is free software; you can redistribute it and/or modify it under
7// the terms of the GNU Lesser General Public License version 2.1 as published
8// by the Free Software Foundation, with special exception defined in the file
9// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10// distribution for complete text of the license and disclaimer of any warranty.
11//
12// Alternatively, this file may be used under the terms of Open CASCADE
13// commercial license or contractual agreement.
14
15#include <AppDef_MultiLine.hxx>
16#include <AppDef_MultiPointConstraint.hxx>
17#include <AppParCurves_MultiBSpCurve.hxx>
18#include <AppParCurves_MultiCurve.hxx>
19#include <AppDef_BSplineCompute.hxx>
20#include <AppDef_Compute.hxx>
21#include <AppParCurves_Constraint.hxx>
22#include <Approx_MCurvesToBSpCurve.hxx>
23#include <TColgp_Array1OfPnt.hxx>
24#include <TColgp_Array1OfPnt2d.hxx>
25#include <TColgp_Array1OfVec.hxx>
26#include <TColgp_Array1OfVec2d.hxx>
27#include <gp_Vec.hxx>
28#include <gp_Vec2d.hxx>
29#include <gp_Pnt.hxx>
30#include <gp_Pnt2d.hxx>
31#include <math_Vector.hxx>
32#include <BSplCLib.hxx>
33
34#include <StdFail_NotDone.hxx>
35#include <AppParCurves_HArray1OfConstraintCouple.hxx>
36#include <AppDef_Variational.hxx>
37
38static   Standard_Boolean scal = 1;
39
40Standard_EXPORT Standard_Boolean AppBlend_GetContextSplineApprox();
41Standard_EXPORT Standard_Boolean AppBlend_GetContextApproxWithNoTgt();
42
43//  modified by EAP (Edward AGAPOV) Fri Jan 4 2002, bug OCC9
44//  --- keep pipe parametrized like path
45
46
47//=======================================================================
48//function : AppBlend_AppSurf
49//purpose  :
50//=======================================================================
51
52AppBlend_AppSurf::AppBlend_AppSurf ()
53: done(Standard_False),
54  dmin(0),
55  dmax(0),
56  tol3d(0.0),
57  tol2d(0.0),
58  nbit(0),
59  udeg(0),
60  vdeg(0),
61  knownp(Standard_False),
62  tol3dreached(0.0),
63  tol2dreached(0.0),
64  paramtype(Approx_ChordLength),
65  continuity(GeomAbs_C2)
66{
67  critweights[0]=0.4;
68  critweights[1]=0.2;
69  critweights[2]=0.4;
70}
71
72
73//=======================================================================
74//function : AppBlend_AppSurf
75//purpose  :
76//=======================================================================
77
78AppBlend_AppSurf::AppBlend_AppSurf (const Standard_Integer Degmin,
79				    const Standard_Integer Degmax,
80				    const Standard_Real Tol3d,
81				    const Standard_Real Tol2d,
82				    const Standard_Integer NbIt,
83				    const Standard_Boolean KnownParameters)
84: done(Standard_False),
85  dmin(Degmin),
86  dmax(Degmax),
87  tol3d(Tol3d),
88  tol2d(Tol2d),
89  nbit(NbIt),
90  udeg(0),
91  vdeg(0),
92  knownp(KnownParameters),
93  tol3dreached(0.0),
94  tol2dreached(0.0),
95  paramtype(Approx_ChordLength),
96  continuity(GeomAbs_C2)
97{
98  critweights[0]=0.4;
99  critweights[1]=0.2;
100  critweights[2]=0.4;
101}
102
103//=======================================================================
104//function : Init
105//purpose  :
106//=======================================================================
107
108void AppBlend_AppSurf::Init (const Standard_Integer Degmin,
109			     const Standard_Integer Degmax,
110			     const Standard_Real Tol3d,
111			     const Standard_Real Tol2d,
112			     const Standard_Integer NbIt,
113			     const Standard_Boolean KnownParameters)
114{
115  done  = Standard_False;
116  dmin  = Degmin;
117  dmax  = Degmax;
118  tol3d = Tol3d;
119  tol2d = Tol2d;
120  nbit  = NbIt;
121  knownp = KnownParameters;
122  continuity = GeomAbs_C2;
123  paramtype = Approx_ChordLength;
124  critweights[0]=0.4;
125  critweights[1]=0.2;
126  critweights[2]=0.4;
127}
128
129//=======================================================================
130//function : CriteriumWeight
131//purpose  : returns the Weights associed  to the criterium used in
132//           the  optimization.
133//=======================================================================
134//
135void AppBlend_AppSurf::CriteriumWeight(Standard_Real& W1, Standard_Real& W2, Standard_Real& W3) const
136{
137  W1 = critweights[0];
138  W2 = critweights[1];
139  W3 = critweights[2] ;
140}
141//=======================================================================
142//function : SetCriteriumWeight
143//purpose  :
144//=======================================================================
145
146void AppBlend_AppSurf::SetCriteriumWeight(const Standard_Real W1, const Standard_Real W2, const Standard_Real W3)
147{
148  if (W1 < 0 || W2 < 0 || W3 < 0 ) throw Standard_DomainError();
149  critweights[0] = W1;
150  critweights[1] = W2;
151  critweights[2] = W3;
152}
153//=======================================================================
154//function : SetContinuity
155//purpose  :
156//=======================================================================
157
158void AppBlend_AppSurf::SetContinuity (const GeomAbs_Shape TheCont)
159{
160  continuity = TheCont;
161}
162
163//=======================================================================
164//function : Continuity
165//purpose  :
166//=======================================================================
167
168GeomAbs_Shape AppBlend_AppSurf::Continuity () const
169{
170  return continuity;
171}
172
173//=======================================================================
174//function : SetParType
175//purpose  :
176//=======================================================================
177
178void AppBlend_AppSurf::SetParType (const Approx_ParametrizationType ParType)
179{
180  paramtype = ParType;
181}
182
183//=======================================================================
184//function : ParType
185//purpose  :
186//=======================================================================
187
188Approx_ParametrizationType AppBlend_AppSurf::ParType () const
189{
190  return paramtype;
191}
192
193
194//=======================================================================
195//function : Perform
196//purpose  :
197//=======================================================================
198
199void AppBlend_AppSurf::Perform(const Handle(TheLine)& Lin,
200			       TheSectionGenerator& F,
201			       const Standard_Boolean SpApprox)
202
203{
204  InternalPerform(Lin, F, SpApprox, Standard_False);
205}
206
207//=======================================================================
208//function : PerformSmoothing
209//purpose  :
210//=======================================================================
211
212void AppBlend_AppSurf::PerformSmoothing(const Handle(TheLine)& Lin,
213					  TheSectionGenerator& F)
214
215{
216  InternalPerform(Lin, F, Standard_True, Standard_True);
217}
218
219//=======================================================================
220//function : InternalPerform
221//purpose  :
222//=======================================================================
223
224void AppBlend_AppSurf::InternalPerform(const Handle(TheLine)& Lin,
225				       TheSectionGenerator& F,
226				       const Standard_Boolean SpApprox,
227				       const Standard_Boolean UseSmoothing)
228
229{
230  done = Standard_False;
231  if (Lin.IsNull()) {return;}
232  Standard_Integer i,j,k,NbPoint;
233  Standard_Integer NbUPoles,NbUKnots,NbPoles2d,NbVPoles;
234  Standard_Boolean withderiv;
235  AppParCurves_Constraint Cfirst,Clast;
236
237  Standard_Real mytol3d,mytol2d;
238  gp_XYZ newDv;
239
240  seqPoles2d.Clear();
241
242  NbPoint=Lin->NbPoints();
243  AppDef_MultiPointConstraint multP;
244  AppDef_MultiLine multL(NbPoint);
245
246  F.GetShape(NbUPoles,NbUKnots,udeg,NbPoles2d);
247
248  tabUKnots  = new TColStd_HArray1OfReal (1,NbUKnots);
249  tabUMults  = new TColStd_HArray1OfInteger (1,NbUKnots);
250
251  F.Knots(tabUKnots->ChangeArray1());
252  F.Mults(tabUMults->ChangeArray1());
253
254  TColgp_Array1OfPnt tabAppP(1,NbUPoles);
255  TColgp_Array1OfVec tabAppV(1,NbUPoles);
256
257  TColgp_Array1OfPnt2d tabP2d(1,Max(1,NbPoles2d));
258  TColgp_Array1OfVec2d tabV2d(1,Max(1,NbPoles2d));
259
260  TColStd_Array1OfReal tabW(1,NbUPoles),tabDW(1,NbUPoles);
261
262  TColgp_Array1OfPnt2d tabAppP2d(1,NbPoles2d+NbUPoles); // points2d + poids
263  TColgp_Array1OfVec2d tabAppV2d(1,NbPoles2d+NbUPoles);
264
265
266  AppParCurves_MultiBSpCurve multC;
267
268//  Standard_Boolean SpApprox = Standard_False;
269
270  withderiv = F.Section(Lin->Point(1),tabAppP,tabAppV,tabP2d,tabV2d,
271			tabW,tabDW);
272
273  if(AppBlend_GetContextApproxWithNoTgt()) withderiv = Standard_False;
274
275  for (j=1; j<=NbPoles2d; j++) {
276    tabAppP2d(j) = tabP2d(j);
277    if (withderiv) {
278      tabAppV2d(j) = tabV2d(j);
279    }
280  }
281  for (j=1; j<=NbUPoles; j++) {
282    // pour les courbes rationnelles il faut multiplier les poles par
283    // leurs poids respectifs
284    if (withderiv) {
285      tabAppV2d(NbPoles2d+j).SetCoord(tabDW(j),0.);
286      newDv.SetLinearForm(tabDW(j),tabAppP(j).XYZ(),tabW(j),tabAppV(j).XYZ());
287      tabAppV(j).SetXYZ(newDv);
288    }
289    tabAppP(j).SetXYZ(tabAppP(j).XYZ() * tabW(j));
290    tabAppP2d(NbPoles2d+j).SetCoord(tabW(j),0.);
291  }
292
293  if (withderiv) {
294    multP = AppDef_MultiPointConstraint(tabAppP,tabAppP2d,tabAppV,tabAppV2d);
295    Cfirst = AppParCurves_TangencyPoint;
296  }
297  else {
298    multP = AppDef_MultiPointConstraint(tabAppP,tabAppP2d);
299    Cfirst = AppParCurves_PassPoint;
300  }
301  multL.SetValue(1,multP);
302
303  for (i=2; i<=NbPoint-1; i++) {
304    if (SpApprox) {
305      F.Section(Lin->Point(i),tabAppP,tabP2d,tabW);
306      for (j=1; j<=NbPoles2d; j++) {
307	tabAppP2d(j) = tabP2d(j);
308      }
309      for (j=1; j<=NbUPoles; j++) {
310	// pour les courbes rationnelles il faut multiplier les poles par
311	// leurs poids respectifs
312	tabAppP(j).SetXYZ(tabAppP(j).XYZ() * tabW(j));
313	tabAppP2d(NbPoles2d+j).SetCoord(tabW(j),0.);
314      }
315      multP = AppDef_MultiPointConstraint(tabAppP,tabAppP2d);
316      multL.SetValue(i,multP);
317    }
318// ***********************
319    else {
320      withderiv = F.Section(Lin->Point(i),tabAppP,tabAppV,tabP2d,tabV2d,
321			    tabW,tabDW);
322      if(AppBlend_GetContextApproxWithNoTgt()) withderiv = Standard_False;
323
324      for (j=1; j<=NbPoles2d; j++) {
325	tabAppP2d(j) = tabP2d(j);
326	if (withderiv) {
327	  tabAppV2d(j) = tabV2d(j);
328	}
329      }
330      for (j=1; j<=NbUPoles; j++) {
331	// pour les courbes rationnelles il faut multiplier les poles par
332	// leurs poids respectifs
333	if (withderiv) {
334	  tabAppV2d(NbPoles2d+j).SetCoord(tabDW(j),0.);
335	  newDv.SetLinearForm(tabDW(j),tabAppP(j).XYZ(),tabW(j),tabAppV(j).XYZ());
336	  tabAppV(j).SetXYZ(newDv);
337	}
338	tabAppP(j).SetXYZ(tabAppP(j).XYZ() * tabW(j));
339	tabAppP2d(NbPoles2d+j).SetCoord(tabW(j),0.);
340      }
341      if (withderiv) {
342	multP = AppDef_MultiPointConstraint(tabAppP,tabAppP2d,tabAppV,tabAppV2d);
343      }
344      else {
345	multP = AppDef_MultiPointConstraint(tabAppP,tabAppP2d);
346      }
347      multL.SetValue(i,multP);
348    }
349// ******************************
350  }
351
352  withderiv = F.Section(Lin->Point(NbPoint),tabAppP,tabAppV,tabP2d,tabV2d,
353			tabW,tabDW);
354  if(AppBlend_GetContextApproxWithNoTgt()) withderiv = Standard_False;
355
356  for (j=1; j<=NbPoles2d; j++) {
357    tabAppP2d(j) = tabP2d(j);
358    if (withderiv) {
359      tabAppV2d(j) = tabV2d(j);
360    }
361  }
362  for (j=1; j<=NbUPoles; j++) {
363    // pour les courbes rationnelles il faut multiplier les poles par
364    // leurs poids respectifs
365    if (withderiv) {
366      tabAppV2d(NbPoles2d+j).SetCoord(tabDW(j),0.);
367      newDv.SetLinearForm(tabDW(j),tabAppP(j).XYZ(),tabW(j),tabAppV(j).XYZ());
368      tabAppV(j).SetXYZ(newDv);
369    }
370    tabAppP(j).SetXYZ(tabAppP(j).XYZ() * tabW(j));
371    tabAppP2d(NbPoles2d+j).SetCoord(tabW(j),0.);
372  }
373
374  if (withderiv) {
375    multP = AppDef_MultiPointConstraint(tabAppP,tabAppP2d,tabAppV,tabAppV2d);
376    Clast = AppParCurves_TangencyPoint;
377  }
378  else {
379    multP = AppDef_MultiPointConstraint(tabAppP,tabAppP2d);
380    Clast = AppParCurves_PassPoint;
381  }
382  multL.SetValue(NbPoint,multP);
383
384  //IFV 04.06.07 occ13904
385  if(NbPoint == 2) {
386    dmin = 1;
387    if(Cfirst == AppParCurves_PassPoint && Clast == AppParCurves_PassPoint) {
388      dmax = 1;
389    }
390  }
391
392
393  if (!SpApprox) {
394    AppDef_Compute theapprox (dmin,dmax,tol3d,tol2d,nbit, Standard_True, paramtype);
395    if (knownp) {
396      math_Vector theParams(1,NbPoint);
397
398      // On recale les parametres entre 0 et 1.
399      theParams(1) = 0.;
400      theParams(NbPoint) = 1.;
401      Standard_Real Uf = F.Parameter(Lin->Point(1));
402      Standard_Real Ul = F.Parameter(Lin->Point(NbPoint))-Uf;
403      for (i=2; i<NbPoint; i++) {
404	theParams(i) = (F.Parameter(Lin->Point(i))-Uf)/Ul;
405      }
406      AppDef_Compute theAppDef(theParams,dmin,dmax,tol3d,tol2d,nbit,
407				 Standard_True, Standard_True);
408      theapprox = theAppDef;
409    }
410    theapprox.SetConstraints(Cfirst,Clast);
411    theapprox.Perform(multL);
412
413    Standard_Real TheTol3d, TheTol2d;
414    mytol3d = mytol2d = 0.0;
415    for (Standard_Integer Index=1; Index<=theapprox.NbMultiCurves(); Index++) {
416      theapprox.Error(Index, TheTol3d, TheTol2d);
417      mytol3d = Max(TheTol3d, mytol3d);
418      mytol2d = Max(TheTol2d, mytol2d);
419    }
420#ifdef OCCT_DEBUG
421    std::cout << " Tolerances obtenues  --> 3d : "<< mytol3d << std::endl;
422    std::cout << "                      --> 2d : "<< mytol2d << std::endl;
423#endif
424    multC = theapprox.SplineValue();
425  }
426
427  else {
428    if(!UseSmoothing) {
429      Standard_Boolean UseSquares = Standard_False;
430      if(nbit == 0) UseSquares = Standard_True;
431      AppDef_BSplineCompute theapprox (dmin,dmax,tol3d,tol2d,nbit,Standard_True, paramtype,
432				       UseSquares);
433      if(continuity == GeomAbs_C0) {
434	theapprox.SetContinuity(0);
435      }
436      if(continuity == GeomAbs_C1) {
437	theapprox.SetContinuity(1);
438      }
439      else if(continuity == GeomAbs_C2) {
440	theapprox.SetContinuity(2);
441      }
442      else {
443	theapprox.SetContinuity(3);
444      }
445
446      theapprox.SetConstraints(Cfirst,Clast);
447
448      if (knownp) {
449	math_Vector theParams(1,NbPoint);
450	// On recale les parametres entre 0 et 1.
451	theParams(1) = 0.;
452	theParams(NbPoint) = 1.;
453	Standard_Real Uf = F.Parameter(Lin->Point(1));
454	Standard_Real Ul = F.Parameter(Lin->Point(NbPoint))-Uf;
455	for (i=2; i<NbPoint; i++) {
456	  theParams(i) = (F.Parameter(Lin->Point(i))-Uf)/Ul;
457	}
458
459	theapprox.Init(dmin,dmax,tol3d,tol2d,nbit,Standard_True,
460		       Approx_IsoParametric,Standard_True);
461	theapprox.SetParameters(theParams);
462      }
463      theapprox.Perform(multL);
464      theapprox.Error(mytol3d,mytol2d);
465#ifdef OCCT_DEBUG
466      std::cout << " Tolerances obtenues  --> 3d : "<< mytol3d << std::endl;
467      std::cout << "                      --> 2d : "<< mytol2d << std::endl;
468#endif
469      tol3dreached = mytol3d;
470      tol2dreached = mytol2d;
471      multC = theapprox.Value();
472    }
473    else {
474      //Variational algo
475      Handle(AppParCurves_HArray1OfConstraintCouple) TABofCC =
476	new AppParCurves_HArray1OfConstraintCouple(1, NbPoint);
477      AppParCurves_Constraint  Constraint=AppParCurves_NoConstraint;
478
479      for(i = 1; i <= NbPoint; ++i) {
480	AppParCurves_ConstraintCouple ACC(i,Constraint);
481	TABofCC->SetValue(i,ACC);
482      }
483
484      TABofCC->ChangeValue(1).SetConstraint(Cfirst);
485      TABofCC->ChangeValue(NbPoint).SetConstraint(Clast);
486
487      AppDef_Variational Variation(multL, 1, NbPoint, TABofCC);
488
489//===================================
490      Standard_Integer theMaxSegments = 1000;
491      Standard_Boolean theWithMinMax = Standard_False;
492      Standard_Boolean theWithCutting = Standard_True;
493//===================================
494
495      Variation.SetMaxDegree(dmax);
496      Variation.SetContinuity(continuity);
497      Variation.SetMaxSegment(theMaxSegments);
498
499      Variation.SetTolerance(tol3d);
500      Variation.SetWithMinMax(theWithMinMax);
501      Variation.SetWithCutting(theWithCutting);
502      Variation.SetNbIterations(nbit);
503
504      Variation.SetCriteriumWeight(critweights[0], critweights[1], critweights[2]);
505
506      if(!Variation.IsCreated()) {
507	return;
508      }
509
510      if(Variation.IsOverConstrained()) {
511	return;
512      }
513
514      try {
515	Variation.Approximate();
516      }
517      catch (Standard_Failure const&) {
518	return;
519      }
520
521      if(!Variation.IsDone()) {
522	return;
523      }
524
525      mytol3d = Variation.MaxError();
526      mytol2d = 0.;
527#ifdef OCCT_DEBUG
528      std::cout << " Tolerances obtenues  --> 3d : "<< mytol3d << std::endl;
529      std::cout << "                      --> 2d : "<< mytol2d << std::endl;
530#endif
531      tol3dreached = mytol3d;
532      tol2dreached = mytol2d;
533      multC = Variation.Value();
534    }
535  }
536
537  vdeg = multC.Degree();
538  NbVPoles = multC.NbPoles();
539
540  tabPoles   = new TColgp_HArray2OfPnt (1,NbUPoles,1,NbVPoles);
541  tabWeights = new TColStd_HArray2OfReal (1,NbUPoles,1,NbVPoles);
542  tabVKnots  = new TColStd_HArray1OfReal (multC.Knots().Lower(),
543					  multC.Knots().Upper());
544  tabVKnots->ChangeArray1() = multC.Knots();
545
546  if (knownp && !UseSmoothing) {
547    BSplCLib::Reparametrize(F.Parameter(Lin->Point(1)),
548			    F.Parameter(Lin->Point(NbPoint)),
549			    tabVKnots->ChangeArray1());
550  }
551
552  tabVMults  = new TColStd_HArray1OfInteger (multC.Multiplicities().Lower(),
553					     multC.Multiplicities().Upper());
554  tabVMults->ChangeArray1() = multC.Multiplicities();
555
556
557  TColgp_Array1OfPnt newtabP(1,NbVPoles);
558  Handle(TColgp_HArray1OfPnt2d) newtabP2d =
559    new TColgp_HArray1OfPnt2d(1,NbVPoles);
560  for (j=1; j <=NbUPoles; j++) {
561    multC.Curve(j,newtabP);
562    multC.Curve(j+NbUPoles+NbPoles2d,newtabP2d->ChangeArray1());
563    for (k=1; k<=NbVPoles; k++) {
564      // pour les courbes rationnelles il faut maintenant diviser
565      // les poles par leurs poids respectifs
566      tabPoles->ChangeValue(j,k).SetXYZ(newtabP(k).XYZ()/newtabP2d->Value(k).X());
567      Standard_Real aWeight = newtabP2d->Value(k).X();
568      if (aWeight < gp::Resolution()) {
569        done = Standard_False;
570        return;
571      }
572      tabWeights->SetValue(j,k,aWeight);
573    }
574  }
575
576  for (j=1; j<=NbPoles2d; j++) {
577    newtabP2d = new TColgp_HArray1OfPnt2d(1,NbVPoles);
578    multC.Curve(NbUPoles+j,newtabP2d->ChangeArray1());
579    seqPoles2d.Append(newtabP2d);
580  }
581
582  done = Standard_True;
583}
584
585
586//=======================================================================
587//function : Perform
588//purpose  :
589//=======================================================================
590
591void AppBlend_AppSurf::Perform(const Handle(TheLine)& Lin,
592			       TheSectionGenerator& F,
593			       const Standard_Integer NbMaxP)
594{
595  done = Standard_False;
596  if (Lin.IsNull()) {return;}
597  Standard_Integer i,j,k;
598  Standard_Integer NbUPoles,NbUKnots,NbPoles2d,NbVPoles;
599  Standard_Boolean withderiv;
600  AppParCurves_Constraint Cfirst=AppParCurves_NoConstraint,Clast=AppParCurves_NoConstraint;
601
602  Standard_Real mytol3d = 0.0, mytol2d = 0.0;
603  gp_XYZ newDv;
604
605  seqPoles2d.Clear();
606
607  Standard_Integer NbPointTot = Lin->NbPoints();
608
609  F.GetShape(NbUPoles,NbUKnots,udeg,NbPoles2d);
610
611  tabUKnots  = new TColStd_HArray1OfReal (1,NbUKnots);
612  tabUMults  = new TColStd_HArray1OfInteger (1,NbUKnots);
613
614  F.Knots(tabUKnots->ChangeArray1());
615  F.Mults(tabUMults->ChangeArray1());
616
617  TColgp_Array1OfPnt tabAppP(1,NbUPoles);
618  TColgp_Array1OfVec tabAppV(1,NbUPoles);
619  Standard_Real X,Y,Z,DX,DY,DZ;
620  X = Y = Z = RealLast();
621  DX = DY = DZ = RealFirst();
622
623  TColgp_Array1OfPnt2d tabP2d(1,Max(1,NbPoles2d));
624  TColgp_Array1OfVec2d tabV2d(1,Max(1,NbPoles2d));
625  TColStd_Array1OfReal X2d(1,Max(1,NbPoles2d));X2d.Init(RealLast());
626  TColStd_Array1OfReal Y2d(1,Max(1,NbPoles2d));Y2d.Init(RealLast());
627  TColStd_Array1OfReal DX2d(1,Max(1,NbPoles2d));DX2d.Init(RealFirst());
628  TColStd_Array1OfReal DY2d(1,Max(1,NbPoles2d));DY2d.Init(RealFirst());
629
630  TColStd_Array1OfReal tabW(1,NbUPoles),tabDW(1,NbUPoles);
631
632  TColgp_Array1OfPnt2d tabAppP2d(1,NbPoles2d+NbUPoles); // points2d + poids
633  TColgp_Array1OfVec2d tabAppV2d(1,NbPoles2d+NbUPoles);
634
635  // On calcule les boites de chaque ligne (box for all lines)
636  for(i = 1; i <= NbPointTot; i++){
637    F.Section(Lin->Point(i),tabAppP,tabAppV,tabP2d,tabV2d,tabW,tabDW);
638    Standard_Real x,y,z;
639    for (j = 1; j <= NbUPoles; j++)
640    {
641      tabAppP(j).Coord(x,y,z);
642      if(x < X)  { X  = x; }
643      if(x > DX) { DX = x; }
644      if(y < Y)  { Y  = y; }
645      if(y > DY) { DY = y; }
646      if(z < Z)  { Z  = z; }
647      if(z > DZ) { DZ = z; }
648    }
649    for (j = 1; j <= NbPoles2d; j++)
650    {
651      tabP2d(j).Coord(x,y);
652      if(x < X2d (j)) { X2d (j) = x; }
653      if(x > DX2d(j)) { DX2d(j) = x; }
654      if(y < Y2d (j)) { Y2d (j) = y; }
655      if(y > DY2d(j)) { DY2d(j) = y; }
656    }
657  }
658  // On calcule pour chaque ligne la transformation vers 0 1.
659  Standard_Real seuil = 1000.*tol3d;
660  Standard_Real seuil2d = 1000.*tol2d;
661  if((DX - X) < seuil ){ DX = 1.; X = 0.; }
662  else{ DX = 1./(DX - X); X *= -DX; }
663  if((DY - Y) < seuil){ DY = 1.; Y = 0.; }
664  else{ DY = 1./(DY - Y); Y *= -DY; }
665  if((DZ - Z) < seuil){ DZ = 1.; Z = 0.; }
666  else{ DZ = 1./(DZ - Z); Z *= -DZ; }
667  for(j = 1; j <= NbPoles2d; j++){
668    if((DX2d(j) - X2d(j)) < seuil2d){ DX2d(j) = 1.; X2d(j) = 0.; }
669    else{ DX2d(j) = 1./(DX2d(j) - X2d(j)); X2d(j) *= -DX2d(j); }
670    if((DY2d(j) - Y2d(j)) < seuil2d){ DY2d(j) = 1.; Y2d(j) = 0.; }
671    else{ DY2d(j) = 1./(DY2d(j) - Y2d(j)); Y2d(j) *= -DY2d(j); }
672  }
673  if(!scal){
674    DX = 1.; X = 0.;
675    DY = 1.; Y = 0.;
676    DZ = 1.; Z = 0.;
677    for(j = 1; j <= NbPoles2d; j++){
678      DX2d(j) = 1.; X2d(j) = 0.;
679      DY2d(j) = 1.; Y2d(j) = 0.;
680    }
681  }
682//  modified by eap Thu Jan  3 14:45:22 2002 ___BEGIN___
683  // Keep "inter-troncons" parameters, not only first and last
684//  Standard_Real Ufirst=0,Ulast=0;
685  TColStd_SequenceOfReal aParamSeq;
686   if (knownp) {
687//     Ufirst = F.Parameter(Lin->Point(1));
688//     Ulast = F.Parameter(Lin->Point(NbPointTot));
689     aParamSeq.Append( F.Parameter (Lin->Point(1)) );
690  }
691//  modified by EAP Thu Jan  3 14:45:41 2002 ___END___
692
693  Approx_MCurvesToBSpCurve concat;
694
695  //On calcule le nombre de troncons.
696  Standard_Integer nbtronc = NbPointTot/NbMaxP;
697  Standard_Integer reste = NbPointTot - (nbtronc * NbMaxP);
698  // On regarde si il faut prendre un troncon de plus.
699  Standard_Integer nmax = NbMaxP;
700  if(nbtronc > 0 && reste > 0){
701    nmax = NbPointTot/(nbtronc + 1);
702    if(nmax > (2*NbMaxP)/3) {
703      nbtronc++;
704      reste = NbPointTot - (nbtronc * nmax);
705    }
706    else nmax = NbMaxP;
707  }
708  else if(nbtronc == 0){
709    nbtronc = 1;
710    nmax = reste;
711    reste = 0;
712  }
713
714  // Approximate each "troncon" with nb of Bezier's using AppDef_Compute
715  // and concat them into BSpline with Approx_MCurvesToBSpCurve
716
717  TColStd_Array1OfInteger troncsize(1,nbtronc);
718  TColStd_Array1OfInteger troncstart(1,nbtronc);
719
720  Standard_Integer rab = reste/nbtronc + 1;
721  Standard_Integer start = 1;
722  Standard_Integer itronc ;
723  for( itronc = 1; itronc <= nbtronc; itronc++){
724    troncstart(itronc) = start;
725    Standard_Integer rabrab = Min(rab,reste);
726    if(reste > 0){ reste -= rabrab; }
727    troncsize(itronc) = nmax + rabrab + 1;
728    start += (nmax + rabrab);
729  }
730  troncsize(nbtronc) = troncsize(nbtronc) - 1;
731  for(itronc = 1; itronc <= nbtronc; itronc++){
732    Standard_Integer NbPoint = troncsize(itronc);
733    Standard_Integer StPoint = troncstart(itronc);
734    AppDef_MultiPointConstraint multP;
735    AppDef_MultiLine multL(NbPoint);
736
737    for (i=1; i<=NbPoint; i++) {
738      Standard_Integer iLin = StPoint + i - 1;
739      Standard_Real x,y,z;
740      withderiv = F.Section(Lin->Point(iLin),tabAppP,tabAppV,tabP2d,tabV2d,
741			    tabW,tabDW);
742      if(AppBlend_GetContextApproxWithNoTgt()) withderiv = Standard_False;
743
744      for (j=1; j<=NbPoles2d; j++) {
745	tabP2d(j).Coord(x,y);
746	tabAppP2d(j).SetCoord(DX2d(j)*x+X2d(j),DY2d(j)*y+Y2d(j));
747	if (withderiv) {
748	  tabV2d(j).Coord(x,y);
749	  tabAppV2d(j).SetCoord(DX2d(j)*x,DY2d(j)*y);
750	}
751      }
752      for (j=1; j<=NbUPoles; j++) {
753	// pour les courbes rationnelles il faut multiplier les poles par
754	// leurs poids respectifs
755	if (withderiv) {
756	  tabAppV2d(NbPoles2d+j).SetCoord(tabDW(j),0.);
757	  newDv.SetLinearForm(tabDW(j),tabAppP(j).XYZ(),tabW(j),tabAppV(j).XYZ());
758	  tabAppV(j).SetCoord(DX*newDv.X(),DY*newDv.Y(),DZ*newDv.Z());
759	}
760	tabAppP(j).SetXYZ(tabAppP(j).XYZ() * tabW(j));
761	tabAppP2d(NbPoles2d+j).SetCoord(tabW(j),0.);
762	tabAppP(j).Coord(x,y,z);
763	tabAppP(j).SetCoord(DX*x+X,DY*y+Y,DZ*z+Z);
764      }
765      if (withderiv) {
766	multP = AppDef_MultiPointConstraint(tabAppP,tabAppP2d,tabAppV,tabAppV2d);
767	if(i == 1) Cfirst = AppParCurves_TangencyPoint;
768	else if(i == NbPoint) Clast = AppParCurves_TangencyPoint;
769      }
770      else {
771	multP = AppDef_MultiPointConstraint(tabAppP,tabAppP2d);
772	if(i == 1) Cfirst = AppParCurves_PassPoint;
773	else if(i == NbPoint) Clast = AppParCurves_PassPoint;
774      }
775      multL.SetValue(i,multP);
776    }
777
778
779  //IFV 04.06.07 occ13904
780    if(NbPoint == 2) {
781      dmin = 1;
782      if(Cfirst == AppParCurves_PassPoint && Clast == AppParCurves_PassPoint) {
783	dmax = 1;
784      }
785    }
786
787//  modified by EAP Thu Jan  3 15:44:13 2002 ___BEGIN___
788    Standard_Real Ufloc=0., Ulloc=0.;
789    AppDef_Compute theapprox (dmin,dmax,tol3d,tol2d,nbit);
790    if (knownp) {
791      math_Vector theParams(1,NbPoint);
792      // On recale les parametres entre 0 et 1.
793      /*Standard_Real*/ Ufloc = F.Parameter(Lin->Point(StPoint));
794      /*Standard_Real*/ Ulloc = F.Parameter(Lin->Point(StPoint+NbPoint-1));
795//  modified by EAP Thu Jan  3 15:45:17 2002 ___END___
796      for (i=1; i <= NbPoint; i++) {
797	Standard_Integer iLin = StPoint + i - 1;
798	theParams(i) = (F.Parameter(Lin->Point(iLin))-Ufloc)/(Ulloc - Ufloc);
799      }
800      AppDef_Compute theAppDef1(theParams,dmin,dmax,tol3d,tol2d,nbit, Standard_True,Standard_True);
801      theapprox = theAppDef1;
802    }
803    theapprox.SetConstraints(Cfirst,Clast);
804    theapprox.Perform(multL);
805
806//  modified by EAP Thu Jan  3 16:00:43 2002 ___BEGIN___
807    // To know internal parameters if multicurve is approximated by several Bezier's
808    TColStd_SequenceOfReal aPoleDistSeq;
809    Standard_Real aWholeDist=0;
810//  modified by EAP Thu Jan  3 16:45:48 2002 ___END___
811    Standard_Real TheTol3d, TheTol2d;
812    for (Standard_Integer Index=1; Index<=theapprox.NbMultiCurves(); Index++) {
813      AppParCurves_MultiCurve& mucu = theapprox.ChangeValue(Index);
814      theapprox.Error(Index, TheTol3d, TheTol2d);
815      mytol3d = Max(TheTol3d/DX, mytol3d);
816      mytol3d = Max(TheTol3d/DY, mytol3d);
817      mytol3d = Max(TheTol3d/DZ, mytol3d);
818      for(j = 1; j <= NbUPoles; j++){
819	mucu.Transform(j,
820		       -X/DX,1./DX,
821		       -Y/DY,1./DY,
822		       -Z/DZ,1./DZ);
823      }
824      for(j = 1; j <= NbPoles2d; j++){
825	mucu.Transform2d(j + NbUPoles,
826			 -X2d(j)/DX2d(j),1./DX2d(j),
827			 -Y2d(j)/DY2d(j),1./DY2d(j));
828	mytol2d = Max(TheTol2d/DX2d(j), mytol2d);
829	mytol2d = Max(TheTol2d/DY2d(j), mytol2d);
830      }
831      concat.Append(mucu);
832
833//  modified by EAP Thu Jan  3 15:45:23 2002 ___BEGIN___
834      if (knownp && theapprox.NbMultiCurves() > 1)
835      {
836	gp_Pnt aFirstPole = mucu.Pole(Index, 1);
837	gp_Pnt aLastPole  = mucu.Pole(Index, mucu.NbPoles());
838	aPoleDistSeq.Append (aFirstPole.Distance(aLastPole));
839	aWholeDist += aPoleDistSeq.Last();
840      }
841    }
842    if (knownp)
843    {
844      Standard_Integer iDist;
845      Standard_Real iU = Ufloc;
846      for (iDist=1; iDist<aPoleDistSeq.Length(); iDist++)
847      {
848	iU += aPoleDistSeq(iDist) / aWholeDist * (Ulloc - Ufloc);
849	//cout << "Internal: " << iU << endl;
850	aParamSeq.Append(iU);
851      }
852      aParamSeq.Append(Ulloc);
853    }
854//  modified by EAP Thu Jan  3 15:45:27 2002 ___END___
855  }
856#ifdef OCCT_DEBUG
857  std::cout << "   Tolerances obtenues  --> 3d : "<< mytol3d << std::endl;
858  std::cout << "                        --> 2d : "<< mytol2d << std::endl;
859#endif
860  tol3dreached = mytol3d;
861  tol2dreached = mytol2d;
862  concat.Perform();
863  const AppParCurves_MultiBSpCurve& multC = concat.Value();
864  vdeg = multC.Degree();
865  NbVPoles = multC.NbPoles();
866
867  tabPoles   = new TColgp_HArray2OfPnt (1,NbUPoles,1,NbVPoles);
868  tabWeights = new TColStd_HArray2OfReal (1,NbUPoles,1,NbVPoles);
869  tabVKnots  = new TColStd_HArray1OfReal (multC.Knots().Lower(),
870					  multC.Knots().Upper());
871  tabVKnots->ChangeArray1() = multC.Knots();
872
873  if (knownp) {
874//  modified by EAP Fri Jan  4 12:07:30 2002 ___BEGIN___
875    if (aParamSeq.Length() != tabVKnots->Length())
876    {
877      BSplCLib::Reparametrize(F.Parameter(Lin->Point(1)),
878			      F.Parameter(Lin->Point(Lin->NbPoints())),
879			      tabVKnots->ChangeArray1()
880			      );
881#ifdef OCCT_DEBUG
882      std::cout << "Warning: AppBlend_AppSurf::Perform(), bad length of aParamSeq: " <<
883	aParamSeq.Length() << " instead of " << tabVKnots->Length() << std::endl;
884#endif
885    }
886    else
887    {
888      Standard_Integer iKnot, iTabKnot = tabVKnots->Lower();
889      for (iKnot=1; iKnot<=aParamSeq.Length(); iKnot++, iTabKnot++)
890      {
891	//cout << "Replace " << tabVKnots->Value(iTabKnot) << " with " << aParamSeq(iKnot) << endl;
892	tabVKnots->SetValue(iTabKnot, aParamSeq(iKnot));
893      }
894    }
895//  modified by EAP Fri Jan  4 12:07:35 2002 ___END___
896  }
897
898  tabVMults  = new TColStd_HArray1OfInteger (multC.Multiplicities().Lower(),
899					     multC.Multiplicities().Upper());
900  tabVMults->ChangeArray1() = multC.Multiplicities();
901
902
903  TColgp_Array1OfPnt newtabP(1,NbVPoles);
904  Handle(TColgp_HArray1OfPnt2d) newtabP2d =
905    new TColgp_HArray1OfPnt2d(1,NbVPoles);
906  for (j=1; j <=NbUPoles; j++) {
907    multC.Curve(j,newtabP);
908    multC.Curve(j+NbUPoles+NbPoles2d,newtabP2d->ChangeArray1());
909    for (k=1; k<=NbVPoles; k++) {
910      // pour les courbes rationnelles il faut maintenant diviser
911      // les poles par leurs poids respectifs
912      tabPoles->ChangeValue(j,k).SetXYZ(newtabP(k).XYZ()/newtabP2d->Value(k).X());
913      Standard_Real aWeight = newtabP2d->Value(k).X();
914      if (aWeight < gp::Resolution()) {
915        done = Standard_False;
916        return;
917      }
918      tabWeights->SetValue(j,k,aWeight);
919    }
920  }
921
922  for (j=1; j<=NbPoles2d; j++) {
923    newtabP2d = new TColgp_HArray1OfPnt2d(1,NbVPoles);
924    multC.Curve(NbUPoles+j,newtabP2d->ChangeArray1());
925    seqPoles2d.Append(newtabP2d);
926  }
927
928  done = Standard_True;
929}
930
931
932//=======================================================================
933//function : SurfShape
934//purpose  :
935//=======================================================================
936
937void AppBlend_AppSurf::SurfShape (Standard_Integer& UDegree,
938				  Standard_Integer& VDegree,
939				  Standard_Integer& NbUPoles,
940				  Standard_Integer& NbVPoles,
941				  Standard_Integer& NbUKnots,
942				  Standard_Integer& NbVKnots) const
943{
944  if (!done) {throw StdFail_NotDone();}
945  UDegree  = udeg;
946  VDegree  = vdeg;
947  NbUPoles = tabPoles->ColLength();
948  NbVPoles = tabPoles->RowLength();
949  NbUKnots = tabUKnots->Length();
950  NbVKnots = tabVKnots->Length();
951}
952
953
954void AppBlend_AppSurf::Surface(TColgp_Array2OfPnt& TPoles,
955			       TColStd_Array2OfReal& TWeights,
956			       TColStd_Array1OfReal& TUKnots,
957			       TColStd_Array1OfReal& TVKnots,
958			       TColStd_Array1OfInteger& TUMults,
959			       TColStd_Array1OfInteger& TVMults) const
960
961{
962  if (!done) {throw StdFail_NotDone();}
963  TPoles   = tabPoles->Array2();
964  TWeights = tabWeights->Array2();
965  TUKnots  = tabUKnots->Array1();
966  TUMults  = tabUMults->Array1();
967  TVKnots  = tabVKnots->Array1();
968  TVMults  = tabVMults->Array1();
969}
970
971//=======================================================================
972//function : Curves2dShape
973//purpose  :
974//=======================================================================
975
976void AppBlend_AppSurf::Curves2dShape(Standard_Integer& Degree,
977				     Standard_Integer& NbPoles,
978				     Standard_Integer& NbKnots) const
979{
980  if (!done) {throw StdFail_NotDone();}
981  if (seqPoles2d.Length() == 0) {throw Standard_DomainError();}
982  Degree = vdeg;
983  NbPoles = tabPoles->ColLength();
984  NbKnots = tabVKnots->Length();
985}
986
987//=======================================================================
988//function : Curve2d
989//purpose  :
990//=======================================================================
991
992void AppBlend_AppSurf::Curve2d(const Standard_Integer Index,
993			       TColgp_Array1OfPnt2d& TPoles,
994			       TColStd_Array1OfReal& TKnots,
995			       TColStd_Array1OfInteger& TMults) const
996{
997  if (!done) {throw StdFail_NotDone();}
998  if (seqPoles2d.Length() == 0) {throw Standard_DomainError();}
999  TPoles = seqPoles2d(Index)->Array1();
1000  TKnots  = tabVKnots->Array1();
1001  TMults  = tabVMults->Array1();
1002}
1003
1004//=======================================================================
1005//function : TolCurveOnSurf
1006//purpose  :
1007//=======================================================================
1008
1009Standard_Real AppBlend_AppSurf::TolCurveOnSurf(const Standard_Integer) const
1010{
1011  return tol3dreached; //On ne s'embete pas !!
1012}
1013
1014
1015
1016