0030747: Modeling Algorithms - 2d Curves concatenator doesn't properly process closed...
[occt.git] / src / Geom2dConvert / Geom2dConvert_CompCurveToBSplineCurve.cxx
CommitLineData
b311480e 1// Created on: 1997-04-29
2// Created by: Stagiaire Francois DUMONT
3// Copyright (c) 1997-1999 Matra Datavision
973c2be1 4// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 5//
973c2be1 6// This file is part of Open CASCADE Technology software library.
b311480e 7//
d5f74e42 8// This library is free software; you can redistribute it and/or modify it under
9// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 10// by the Free Software Foundation, with special exception defined in the file
11// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12// distribution for complete text of the license and disclaimer of any warranty.
b311480e 13//
973c2be1 14// Alternatively, this file may be used under the terms of Open CASCADE
15// commercial license or contractual agreement.
b311480e 16
7fd59977 17
42cf5bc1 18#include <Geom2d_BoundedCurve.hxx>
7fd59977 19#include <Geom2d_BSplineCurve.hxx>
20#include <Geom2dConvert.hxx>
42cf5bc1 21#include <Geom2dConvert_CompCurveToBSplineCurve.hxx>
7fd59977 22#include <gp_Pnt2d.hxx>
42cf5bc1 23#include <gp_Vec2d.hxx>
7fd59977 24#include <Precision.hxx>
42cf5bc1 25#include <TColgp_Array1OfPnt2d.hxx>
26#include <TColStd_Array1OfInteger.hxx>
27#include <TColStd_Array1OfReal.hxx>
7fd59977 28
b514beda 29//=======================================================================
30//function : constructor
31//purpose :
32//=======================================================================
33Geom2dConvert_CompCurveToBSplineCurve::Geom2dConvert_CompCurveToBSplineCurve (const Convert_ParameterisationType theParameterisation)
34: myTol (Precision::Confusion()),
35 myType (theParameterisation)
36{
37 //
38}
7fd59977 39
b514beda 40//=======================================================================
41//function : constructor
42//purpose :
43//=======================================================================
7fd59977 44Geom2dConvert_CompCurveToBSplineCurve::
45Geom2dConvert_CompCurveToBSplineCurve(const Handle(Geom2d_BoundedCurve)& BasisCurve,
46 const Convert_ParameterisationType Parameterisation) :
47 myTol(Precision::Confusion()),
48 myType(Parameterisation)
49{
50 Handle(Geom2d_BSplineCurve) Bs =
51 Handle(Geom2d_BSplineCurve)::DownCast(BasisCurve);
52 if (!Bs.IsNull()) {
53 myCurve = Handle(Geom2d_BSplineCurve)::DownCast(BasisCurve->Copy());
54 }
55 else {
56 myCurve = Geom2dConvert::CurveToBSplineCurve (BasisCurve, myType);
57 }
58}
59
60//=======================================================================
61//function : Add
b514beda 62//purpose :
7fd59977 63//=======================================================================
64
65Standard_Boolean Geom2dConvert_CompCurveToBSplineCurve::
66Add(const Handle(Geom2d_BoundedCurve)& NewCurve,
67 const Standard_Real Tolerance,
68 const Standard_Boolean After)
69{
b514beda 70 // conversion
71 Handle(Geom2d_BSplineCurve) Bs = Handle(Geom2d_BSplineCurve)::DownCast (NewCurve);
72 if (!Bs.IsNull())
73 {
74 Bs = Handle(Geom2d_BSplineCurve)::DownCast (NewCurve->Copy());
7fd59977 75 }
b514beda 76 else
77 {
7fd59977 78 Bs = Geom2dConvert::CurveToBSplineCurve (NewCurve, myType);
79 }
b514beda 80 if (myCurve.IsNull())
81 {
82 myCurve = Bs;
83 return Standard_True;
84 }
85
86 myTol = Tolerance;
eb78d737 87 const Standard_Real aSqTol = Tolerance * Tolerance;
7fd59977 88
89 Standard_Integer LBs = Bs->NbPoles(), LCb = myCurve->NbPoles();
eb78d737 90 Standard_Real d1 = myCurve->Pole(1).SquareDistance(Bs->Pole(1));
91 Standard_Real d2 = myCurve->Pole(1).SquareDistance(Bs->Pole(LBs));
92
93 Standard_Boolean isBeforeReversed = (myCurve->Pole(1).SquareDistance(Bs->Pole(1)) < aSqTol) && (d1 < d2);
94 Standard_Boolean isBefore = (myCurve->Pole(1).SquareDistance(Bs->Pole(LBs)) < aSqTol) || isBeforeReversed;
95
96 d1 = myCurve->Pole(LCb).SquareDistance(Bs->Pole(1));
97 d2 = myCurve->Pole(LCb).SquareDistance(Bs->Pole(LBs));
98
99 Standard_Boolean isAfterReversed = (myCurve->Pole(LCb).SquareDistance(Bs->Pole(LBs)) < aSqTol) && (d2 < d1);
100 Standard_Boolean isAfter = (myCurve->Pole(LCb).SquareDistance(Bs->Pole(1)) < aSqTol) || isAfterReversed;
7fd59977 101
eb78d737 102 // myCurve and NewCurve together form a closed curve
103 if (isBefore && isAfter)
104 {
105 if (After)
106 {
107 isBefore = Standard_False;
7fd59977 108 }
eb78d737 109 else
110 {
111 isAfter = Standard_False;
7fd59977 112 }
113 }
eb78d737 114 if (isAfter)
115 {
116 if (isAfterReversed)
117 {
118 Bs->Reverse();
7fd59977 119 }
eb78d737 120 Add(myCurve, Bs, Standard_True);
121 return Standard_True;
122
123 }
124 else if (isBefore)
125 {
126 if (isBeforeReversed)
127 {
128 Bs->Reverse();
7fd59977 129 }
eb78d737 130 Add(Bs, myCurve, Standard_False);
131 return Standard_True;
132 }
133
7fd59977 134 return Standard_False;
135}
136
b514beda 137//=======================================================================
138//function : Add
139//purpose :
140//=======================================================================
141
7fd59977 142void Geom2dConvert_CompCurveToBSplineCurve::Add(
143 Handle(Geom2d_BSplineCurve)& FirstCurve,
144 Handle(Geom2d_BSplineCurve)& SecondCurve,
145 const Standard_Boolean After)
146{
147// Harmonisation des degres.
148 Standard_Integer Deg = Max(FirstCurve->Degree(), SecondCurve->Degree());
149 if (FirstCurve->Degree() < Deg) { FirstCurve->IncreaseDegree(Deg); }
150 if (SecondCurve->Degree() < Deg) { SecondCurve->IncreaseDegree(Deg); }
151
152// Declarationd
153 Standard_Real L1, L2, U_de_raccord;
154 Standard_Integer ii, jj;
155 Standard_Real Ratio=1, Ratio1, Ratio2, Delta1, Delta2;
156 Standard_Integer NbP1 = FirstCurve->NbPoles(), NbP2 = SecondCurve->NbPoles();
157 Standard_Integer NbK1 = FirstCurve->NbKnots(), NbK2 = SecondCurve->NbKnots();
158 TColStd_Array1OfReal Noeuds (1, NbK1+NbK2-1);
159 TColgp_Array1OfPnt2d Poles (1, NbP1+ NbP2-1);
160 TColStd_Array1OfReal Poids (1, NbP1+ NbP2-1);
161 TColStd_Array1OfInteger Mults (1, NbK1+NbK2-1);
162
163 // Ratio de reparametrisation (C1 si possible)
164 L1 = FirstCurve->DN(FirstCurve->LastParameter(), 1).Magnitude();
165 L2 = SecondCurve->DN(SecondCurve->FirstParameter(), 1). Magnitude();
166
167 if ( (L1 > Precision::Confusion()) && (L2 > Precision::Confusion()) ) {
168 Ratio = L1 / L2;
169 }
170 if ( (Ratio < Precision::Confusion()) || (Ratio > 1/Precision::Confusion()) ) {Ratio = 1;}
171
172 if (After) {
173// On ne bouge pas la premiere courbe
174 Ratio1 = 1;
175 Delta1 = 0;
176 Ratio2 = 1/Ratio;
177 Delta2 = Ratio2*SecondCurve->Knot(1) - FirstCurve->Knot(NbK1);
178 U_de_raccord = FirstCurve->LastParameter();
179 }
180 else {
181// On ne bouge pas la seconde courbe
182 Ratio1 = Ratio;
183 Delta1 = Ratio1*FirstCurve->Knot(NbK1) - SecondCurve->Knot(1);
184 Ratio2 = 1;
185 Delta2 = 0;
186 U_de_raccord = SecondCurve->FirstParameter();
187 }
188
189// Les Noeuds
190
191 for (ii=1; ii<NbK1; ii++) {
192 Noeuds(ii) = Ratio1*FirstCurve->Knot(ii) - Delta1;
193 Mults(ii) = FirstCurve->Multiplicity(ii);
194 }
195 Noeuds(NbK1) = U_de_raccord;
196 Mults(NbK1) = FirstCurve->Degree();
197 for (ii=2, jj=NbK1+1; ii<=NbK2; ii++, jj++) {
198 Noeuds(jj) = Ratio2*SecondCurve->Knot(ii) - Delta2;
199 Mults(jj) = SecondCurve->Multiplicity(ii);
200 }
201 Ratio = FirstCurve->Weight(NbP1) ;
202 Ratio /= SecondCurve->Weight(1) ;
203// Les Poles et Poids
204 for (ii=1; ii<NbP1; ii++) {
205 Poles(ii) = FirstCurve->Pole(ii);
206 Poids(ii) = FirstCurve->Weight(ii);
207 }
208 for (ii=1, jj=NbP1; ii<=NbP2; ii++, jj++) {
209 Poles(jj) = SecondCurve->Pole(ii);
210//
211// attentiion les poids ne se raccord pas forcement C0
212// d'ou Ratio
213//
214 Poids(jj) = Ratio * SecondCurve->Weight(ii);
215 }
216
217// Creation de la BSpline
218 myCurve = new (Geom2d_BSplineCurve) (Poles, Poids, Noeuds, Mults, Deg);
219
220// Reduction eventuelle de la multiplicite
221 Standard_Boolean Ok = Standard_True;
222 Standard_Integer M = Mults(NbK1);
223 while ( (M>0) && Ok) {
224 M--;
225 Ok = myCurve->RemoveKnot(NbK1, M, myTol);
226 }
227}
228
b514beda 229//=======================================================================
230//function : BSplineCurve
231//purpose :
232//=======================================================================
7fd59977 233
234Handle(Geom2d_BSplineCurve) Geom2dConvert_CompCurveToBSplineCurve::BSplineCurve() const
235{
b514beda 236 return myCurve;
237}
238
239//=======================================================================
240//function : Clear
241//purpose :
242//=======================================================================
243
244void Geom2dConvert_CompCurveToBSplineCurve::Clear()
245{
246 myCurve.Nullify();
7fd59977 247}