Loading files
f2929057eThis file is pinned to the selected release. Download the original to open it in your design tool.
// Created on: 1997-04-29
// Created by: Stagiaire Francois DUMONT
// Copyright (c) 1997-1999 Matra Datavision
// Copyright (c) 1999-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <Geom2d_BoundedCurve.hxx>
#include <Geom2d_BSplineCurve.hxx>
#include <Geom2dConvert.hxx>
#include <Geom2dConvert_CompCurveToBSplineCurve.hxx>
#include <gp_Pnt2d.hxx>
#include <gp_Vec2d.hxx>
#include <Precision.hxx>
#include <NCollection_Array1.hxx>
#include <Standard_Integer.hxx>
//=================================================================================================
Geom2dConvert_CompCurveToBSplineCurve::Geom2dConvert_CompCurveToBSplineCurve(
const Convert_ParameterisationType theParameterisation)
: myTol(Precision::Confusion()),
myType(theParameterisation)
{
}
//=================================================================================================
Geom2dConvert_CompCurveToBSplineCurve::Geom2dConvert_CompCurveToBSplineCurve(
const occ::handle<Geom2d_BoundedCurve>& BasisCurve,
const Convert_ParameterisationType Parameterisation)
: myTol(Precision::Confusion()),
myType(Parameterisation)
{
occ::handle<Geom2d_BSplineCurve> Bs = occ::down_cast<Geom2d_BSplineCurve>(BasisCurve);
if (!Bs.IsNull())
{
myCurve = occ::down_cast<Geom2d_BSplineCurve>(BasisCurve->Copy());
}
else
{
myCurve = Geom2dConvert::CurveToBSplineCurve(BasisCurve, myType);
}
}
//=================================================================================================
bool Geom2dConvert_CompCurveToBSplineCurve::Add(const occ::handle<Geom2d_BoundedCurve>& NewCurve,
const double Tolerance,
const bool After)
{
// conversion
occ::handle<Geom2d_BSplineCurve> Bs = occ::down_cast<Geom2d_BSplineCurve>(NewCurve);
if (!Bs.IsNull())
{
Bs = occ::down_cast<Geom2d_BSplineCurve>(NewCurve->Copy());
}
else
{
Bs = Geom2dConvert::CurveToBSplineCurve(NewCurve, myType);
}
if (myCurve.IsNull())
{
myCurve = Bs;
return true;
}
myTol = Tolerance;
const double aSqTol = Tolerance * Tolerance;
int LBs = Bs->NbPoles(), LCb = myCurve->NbPoles();
double d1 = myCurve->Pole(1).SquareDistance(Bs->Pole(1));
double d2 = myCurve->Pole(1).SquareDistance(Bs->Pole(LBs));
bool isBeforeReversed = (myCurve->Pole(1).SquareDistance(Bs->Pole(1)) < aSqTol) && (d1 < d2);
bool isBefore = (myCurve->Pole(1).SquareDistance(Bs->Pole(LBs)) < aSqTol) || isBeforeReversed;
d1 = myCurve->Pole(LCb).SquareDistance(Bs->Pole(1));
d2 = myCurve->Pole(LCb).SquareDistance(Bs->Pole(LBs));
bool isAfterReversed = (myCurve->Pole(LCb).SquareDistance(Bs->Pole(LBs)) < aSqTol) && (d2 < d1);
bool isAfter = (myCurve->Pole(LCb).SquareDistance(Bs->Pole(1)) < aSqTol) || isAfterReversed;
// myCurve and NewCurve together form a closed curve
if (isBefore && isAfter)
{
if (After)
{
isBefore = false;
}
else
{
isAfter = false;
}
}
if (isAfter)
{
if (isAfterReversed)
{
Bs->Reverse();
}
Add(myCurve, Bs, true);
return true;
}
else if (isBefore)
{
if (isBeforeReversed)
{
Bs->Reverse();
}
Add(Bs, myCurve, false);
return true;
}
return false;
}
//=================================================================================================
void Geom2dConvert_CompCurveToBSplineCurve::Add(occ::handle<Geom2d_BSplineCurve>& FirstCurve,
occ::handle<Geom2d_BSplineCurve>& SecondCurve,
const bool After)
{
// Harmonize the degrees.
int Deg = std::max(FirstCurve->Degree(), SecondCurve->Degree());
if (FirstCurve->Degree() < Deg)
{
FirstCurve->IncreaseDegree(Deg);
}
if (SecondCurve->Degree() < Deg)
{
SecondCurve->IncreaseDegree(Deg);
}
// Declarations
double L1, L2, U_de_raccord;
int ii, jj;
double Ratio = 1, Ratio1, Ratio2, Delta1, Delta2;
int NbP1 = FirstCurve->NbPoles(), NbP2 = SecondCurve->NbPoles();
int NbK1 = FirstCurve->NbKnots(), NbK2 = SecondCurve->NbKnots();
NCollection_Array1<double> Noeuds(1, NbK1 + NbK2 - 1);
NCollection_Array1<gp_Pnt2d> Poles(1, NbP1 + NbP2 - 1);
NCollection_Array1<double> Poids(1, NbP1 + NbP2 - 1);
NCollection_Array1<int> Mults(1, NbK1 + NbK2 - 1);
// Reparameterization ratio (C1 if possible)
L1 = FirstCurve->DN(FirstCurve->LastParameter(), 1).Magnitude();
L2 = SecondCurve->DN(SecondCurve->FirstParameter(), 1).Magnitude();
if ((L1 > Precision::Confusion()) && (L2 > Precision::Confusion()))
{
Ratio = L1 / L2;
}
if ((Ratio < Precision::Confusion()) || (Ratio > 1 / Precision::Confusion()))
{
Ratio = 1;
}
if (After)
{
// Do not move the first curve
Ratio1 = 1;
Delta1 = 0;
Ratio2 = 1 / Ratio;
Delta2 = Ratio2 * SecondCurve->Knot(1) - FirstCurve->Knot(NbK1);
U_de_raccord = FirstCurve->LastParameter();
}
else
{
// Do not move the second curve
Ratio1 = Ratio;
Delta1 = Ratio1 * FirstCurve->Knot(NbK1) - SecondCurve->Knot(1);
Ratio2 = 1;
Delta2 = 0;
U_de_raccord = SecondCurve->FirstParameter();
}
// The Knots
for (ii = 1; ii < NbK1; ii++)
{
Noeuds(ii) = Ratio1 * FirstCurve->Knot(ii) - Delta1;
Mults(ii) = FirstCurve->Multiplicity(ii);
}
Noeuds(NbK1) = U_de_raccord;
Mults(NbK1) = FirstCurve->Degree();
for (ii = 2, jj = NbK1 + 1; ii <= NbK2; ii++, jj++)
{
Noeuds(jj) = Ratio2 * SecondCurve->Knot(ii) - Delta2;
Mults(jj) = SecondCurve->Multiplicity(ii);
}
Ratio = FirstCurve->Weight(NbP1);
Ratio /= SecondCurve->Weight(1);
// The Poles and Weights
for (ii = 1; ii < NbP1; ii++)
{
Poles(ii) = FirstCurve->Pole(ii);
Poids(ii) = FirstCurve->Weight(ii);
}
for (ii = 1, jj = NbP1; ii <= NbP2; ii++, jj++)
{
Poles(jj) = SecondCurve->Pole(ii);
//
// Note: the weights may not necessarily connect with C0 continuity,
// hence the use of Ratio
//
Poids(jj) = Ratio * SecondCurve->Weight(ii);
}
// Create the BSpline
myCurve = new (Geom2d_BSplineCurve)(Poles, Poids, Noeuds, Mults, Deg);
// Optionally reduce multiplicity
bool Ok = true;
int M = Mults(NbK1);
while ((M > 0) && Ok)
{
M--;
Ok = myCurve->RemoveKnot(NbK1, M, myTol);
}
}
//=================================================================================================
occ::handle<Geom2d_BSplineCurve> Geom2dConvert_CompCurveToBSplineCurve::BSplineCurve() const
{
return myCurve;
}
//=================================================================================================
void Geom2dConvert_CompCurveToBSplineCurve::Clear()
{
myCurve.Nullify();
}