1 // Created on: 1996-09-23
2 // Created by: Philippe MANGIN
3 // Copyright (c) 1996-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
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.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
17 // Modified: Fri Jul 10 11:23:35 1998
18 // JCT : Add WithRatio,MinM
20 #include <Geom_BoundedCurve.hxx>
21 #include <Geom_BSplineCurve.hxx>
22 #include <GeomConvert.hxx>
23 #include <GeomConvert_CompCurveToBSplineCurve.hxx>
26 #include <Precision.hxx>
27 #include <TColgp_Array1OfPnt.hxx>
28 #include <TColStd_Array1OfInteger.hxx>
29 #include <TColStd_Array1OfReal.hxx>
31 //=======================================================================
32 //function : constructor
34 //=======================================================================
35 GeomConvert_CompCurveToBSplineCurve::GeomConvert_CompCurveToBSplineCurve (const Convert_ParameterisationType theParameterisation)
36 : myTol (Precision::Confusion()),
37 myType (theParameterisation)
42 //=======================================================================
43 //function : constructor
45 //=======================================================================
46 GeomConvert_CompCurveToBSplineCurve::
47 GeomConvert_CompCurveToBSplineCurve(const Handle(Geom_BoundedCurve)& BasisCurve,
48 const Convert_ParameterisationType Parameterisation) :
49 myTol(Precision::Confusion()),
50 myType(Parameterisation)
52 Handle(Geom_BSplineCurve) Bs =
53 Handle(Geom_BSplineCurve)::DownCast(BasisCurve);
55 myCurve = Handle(Geom_BSplineCurve)::DownCast(BasisCurve->Copy());
58 myCurve = GeomConvert::CurveToBSplineCurve (BasisCurve, myType);
62 //=======================================================================
65 //=======================================================================
67 Standard_Boolean GeomConvert_CompCurveToBSplineCurve::
68 Add(const Handle(Geom_BoundedCurve)& NewCurve,
69 const Standard_Real Tolerance,
70 const Standard_Boolean After,
71 const Standard_Boolean WithRatio,
72 const Standard_Integer MinM)
75 Handle(Geom_BSplineCurve) Bs = Handle(Geom_BSplineCurve)::DownCast (NewCurve);
78 Bs = Handle(Geom_BSplineCurve)::DownCast (NewCurve->Copy());
82 Bs = GeomConvert::CurveToBSplineCurve (NewCurve, myType);
90 Standard_Boolean avant, apres;
93 Standard_Integer LBs = Bs->NbPoles(), LCb = myCurve->NbPoles();
95 avant = (( myCurve->Pole(1).Distance(Bs->Pole(1)) < myTol)||
96 ( myCurve->Pole(1).Distance(Bs->Pole(LBs))< myTol));
97 apres = (( myCurve->Pole(LCb).Distance(Bs->Pole(1)) < myTol) ||
98 ( myCurve->Pole(LCb).Distance(Bs->Pole(LBs))< myTol));
100 // myCurve est (sera) elle fermee ?
101 if (avant && apres) { // On leve l'ambiguite
102 if (After) avant = Standard_False;
103 else apres = Standard_False;
108 if (myCurve->Pole(LCb).Distance(Bs->Pole(LBs)) < myTol) {Bs->Reverse();}
109 Add(myCurve, Bs, Standard_True, WithRatio, MinM);
110 return Standard_True;
114 if (myCurve->Pole(1).Distance(Bs->Pole(1)) < myTol) {Bs->Reverse();}
115 Add(Bs, myCurve, Standard_False, WithRatio, MinM);
116 return Standard_True;
119 return Standard_False;
122 void GeomConvert_CompCurveToBSplineCurve::Add(
123 Handle(Geom_BSplineCurve)& FirstCurve,
124 Handle(Geom_BSplineCurve)& SecondCurve,
125 const Standard_Boolean After,
126 const Standard_Boolean WithRatio,
127 const Standard_Integer MinM)
129 // Harmonisation des degres.
130 Standard_Integer Deg = Max(FirstCurve->Degree(), SecondCurve->Degree());
131 if (FirstCurve->Degree() < Deg) { FirstCurve->IncreaseDegree(Deg); }
132 if (SecondCurve->Degree() < Deg) { SecondCurve->IncreaseDegree(Deg); }
135 Standard_Real L1, L2, U_de_raccord;
136 Standard_Integer ii, jj;
137 Standard_Real Ratio=1, Ratio1, Ratio2, Delta1, Delta2;
138 Standard_Integer NbP1 = FirstCurve->NbPoles(), NbP2 = SecondCurve->NbPoles();
139 Standard_Integer NbK1 = FirstCurve->NbKnots(), NbK2 = SecondCurve->NbKnots();
140 TColStd_Array1OfReal Noeuds (1, NbK1+NbK2-1);
141 TColgp_Array1OfPnt Poles (1, NbP1+ NbP2-1);
142 TColStd_Array1OfReal Poids (1, NbP1+ NbP2-1);
143 TColStd_Array1OfInteger Mults (1, NbK1+NbK2-1);
145 // Ratio de reparametrisation (C1 si possible)
147 L1 = FirstCurve->DN(FirstCurve->LastParameter(), 1).Magnitude();
148 L2 = SecondCurve->DN(SecondCurve->FirstParameter(), 1). Magnitude();
150 if ( (L1 > Precision::Confusion()) && (L2 > Precision::Confusion()) ) {
153 if ( (Ratio < Precision::Confusion()) || (Ratio > 1/Precision::Confusion()) ) {Ratio = 1;}
157 // On ne bouge pas la premiere courbe
161 Delta2 = Ratio2*SecondCurve->Knot(1) - FirstCurve->Knot(NbK1);
162 U_de_raccord = FirstCurve->LastParameter();
165 // On ne bouge pas la seconde courbe
167 Delta1 = Ratio1*FirstCurve->Knot(NbK1) - SecondCurve->Knot(1);
170 U_de_raccord = SecondCurve->FirstParameter();
175 for (ii=1; ii<NbK1; ii++) {
176 Noeuds(ii) = Ratio1*FirstCurve->Knot(ii) - Delta1;
178 eps = Epsilon (Abs(Noeuds(ii-1)));
179 if( eps < 5.e-10 ) eps = 5.e-10;
180 if(Noeuds(ii) - Noeuds(ii-1) <= eps) {
184 Mults(ii) = FirstCurve->Multiplicity(ii);
186 Noeuds(NbK1) = U_de_raccord;
187 eps = Epsilon (Abs(Noeuds(NbK1-1)));
188 if(Noeuds(NbK1) - Noeuds(NbK1-1) <= eps) {
191 Mults(NbK1) = FirstCurve->Degree();
192 for (ii=2, jj=NbK1+1; ii<=NbK2; ii++, jj++) {
193 Noeuds(jj) = Ratio2*SecondCurve->Knot(ii) - Delta2;
194 eps = Epsilon (Abs(Noeuds(jj-1)));
195 if( eps < 5.e-10 ) eps = 5.e-10;
196 if(Noeuds(jj) - Noeuds(jj-1) <= eps) {
199 Mults(jj) = SecondCurve->Multiplicity(ii);
202 Ratio = FirstCurve->Weight(NbP1) ;
203 Ratio /= SecondCurve->Weight(1) ;
204 // Les Poles et Poids
205 for (ii=1; ii<NbP1; ii++) {
206 Poles(ii) = FirstCurve->Pole(ii);
207 Poids(ii) = FirstCurve->Weight(ii);
209 for (ii=1, jj=NbP1; ii<=NbP2; ii++, jj++) {
210 Poles(jj) = SecondCurve->Pole(ii);
212 // attentiion les poids ne se raccord pas forcement C0
215 Poids(jj) = Ratio * SecondCurve->Weight(ii);
218 // Creation de la BSpline
219 myCurve = new (Geom_BSplineCurve) (Poles, Poids, Noeuds, Mults, Deg);
221 // Reduction eventuelle de la multiplicite jusqu'a MinM
222 Standard_Boolean Ok = Standard_True;
223 Standard_Integer M = Mults(NbK1);
224 while ( (M>MinM) && Ok) {
226 Ok = myCurve->RemoveKnot(NbK1, M, myTol);
232 //=======================================================================
233 //function : BSplineCurve
235 //=======================================================================
237 Handle(Geom_BSplineCurve) GeomConvert_CompCurveToBSplineCurve::BSplineCurve() const
242 //=======================================================================
245 //=======================================================================
247 void GeomConvert_CompCurveToBSplineCurve::Clear()