add support of Hermite curves
This commit is contained in:
parent
761d684c79
commit
18a5ff83b1
|
@ -75,6 +75,7 @@
|
|||
#include "ArcOfHyperbolaPy.h"
|
||||
#include "BezierCurvePy.h"
|
||||
#include "BSplineCurvePy.h"
|
||||
#include "HermiteCurvePy.h"
|
||||
#include "HyperbolaPy.h"
|
||||
#include "OffsetCurvePy.h"
|
||||
#include "ParabolaPy.h"
|
||||
|
@ -200,6 +201,7 @@ PyMODINIT_FUNC initPart()
|
|||
Base::Interpreter().addType(&Part::ArcOfHyperbolaPy ::Type,partModule,"ArcOfHyperbola");
|
||||
Base::Interpreter().addType(&Part::BezierCurvePy ::Type,partModule,"BezierCurve");
|
||||
Base::Interpreter().addType(&Part::BSplineCurvePy ::Type,partModule,"BSplineCurve");
|
||||
Base::Interpreter().addType(&Part::HermiteCurvePy ::Type,partModule,"HermiteCurve");
|
||||
Base::Interpreter().addType(&Part::OffsetCurvePy ::Type,partModule,"OffsetCurve");
|
||||
|
||||
Base::Interpreter().addType(&Part::PlanePy ::Type,partModule,"Plane");
|
||||
|
@ -320,6 +322,7 @@ PyMODINIT_FUNC initPart()
|
|||
Part::GeomCurve ::init();
|
||||
Part::GeomBezierCurve ::init();
|
||||
Part::GeomBSplineCurve ::init();
|
||||
Part::GeomHermiteCurve ::init();
|
||||
Part::GeomCircle ::init();
|
||||
Part::GeomArcOfCircle ::init();
|
||||
Part::GeomArcOfEllipse ::init();
|
||||
|
|
|
@ -56,6 +56,7 @@ generate_from_xml(LinePy)
|
|||
generate_from_xml(PointPy)
|
||||
generate_from_xml(BezierCurvePy)
|
||||
generate_from_xml(BSplineCurvePy)
|
||||
generate_from_xml(HermiteCurvePy)
|
||||
generate_from_xml(PlanePy)
|
||||
generate_from_xml(ConePy)
|
||||
generate_from_xml(CylinderPy)
|
||||
|
@ -194,6 +195,8 @@ SET(Python_SRCS
|
|||
BezierCurvePyImp.cpp
|
||||
BSplineCurvePy.xml
|
||||
BSplineCurvePyImp.cpp
|
||||
HermiteCurvePy.xml
|
||||
HermiteCurvePyImp.cpp
|
||||
PlanePy.xml
|
||||
PlanePyImp.cpp
|
||||
ConePy.xml
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
# include <Geom_RectangularTrimmedSurface.hxx>
|
||||
# include <Geom_SurfaceOfRevolution.hxx>
|
||||
# include <Geom_SurfaceOfLinearExtrusion.hxx>
|
||||
# include <GeomAPI_Interpolate.hxx>
|
||||
# include <GeomConvert.hxx>
|
||||
# include <GeomConvert_CompCurveToBSplineCurve.hxx>
|
||||
# include <GeomLProp_CLProps.hxx>
|
||||
|
@ -70,8 +71,11 @@
|
|||
# include <gp_Torus.hxx>
|
||||
# include <Standard_Real.hxx>
|
||||
# include <Standard_Version.hxx>
|
||||
# include <Standard_ConstructionError.hxx>
|
||||
# include <TColgp_Array1OfPnt.hxx>
|
||||
# include <TColgp_Array2OfPnt.hxx>
|
||||
# include <TColgp_HArray1OfPnt.hxx>
|
||||
# include <TColStd_HArray1OfBoolean.hxx>
|
||||
# include <TColStd_Array1OfReal.hxx>
|
||||
# include <TColStd_Array1OfInteger.hxx>
|
||||
# include <gp.hxx>
|
||||
|
@ -103,6 +107,7 @@
|
|||
#include "ArcOfParabolaPy.h"
|
||||
#include "BezierCurvePy.h"
|
||||
#include "BSplineCurvePy.h"
|
||||
#include "HermiteCurvePy.h"
|
||||
#include "HyperbolaPy.h"
|
||||
#include "ArcOfHyperbolaPy.h"
|
||||
#include "OffsetCurvePy.h"
|
||||
|
@ -467,6 +472,148 @@ PyObject *GeomBezierCurve::getPyObject(void)
|
|||
|
||||
// -------------------------------------------------
|
||||
|
||||
TYPESYSTEM_SOURCE(Part::GeomHermiteCurve,Part::GeomCurve);
|
||||
|
||||
GeomHermiteCurve::GeomHermiteCurve()
|
||||
{
|
||||
std::vector<gp_Pnt> p;
|
||||
p.push_back(gp_Pnt(0.0,0.0,0.0));
|
||||
p.push_back(gp_Pnt(1.0,0.0,0.0));
|
||||
|
||||
std::vector<gp_Vec> t;
|
||||
t.push_back(gp_Vec(1,0,0));
|
||||
t.push_back(gp_Vec(1,0,0));
|
||||
|
||||
compute(p, t);
|
||||
}
|
||||
|
||||
GeomHermiteCurve::GeomHermiteCurve(const std::vector<gp_Pnt>& p,
|
||||
const std::vector<gp_Vec>& t)
|
||||
{
|
||||
compute(p, t);
|
||||
}
|
||||
|
||||
GeomHermiteCurve::~GeomHermiteCurve()
|
||||
{
|
||||
}
|
||||
|
||||
void GeomHermiteCurve::interpolate(const std::vector<gp_Pnt>& p,
|
||||
const std::vector<gp_Vec>& t)
|
||||
{
|
||||
if (p.size() < 2)
|
||||
Standard_ConstructionError::Raise();
|
||||
if (p.size() != t.size())
|
||||
Standard_ConstructionError::Raise();
|
||||
|
||||
compute(p, t);
|
||||
}
|
||||
|
||||
void GeomHermiteCurve::getCardinalSplineTangents(const std::vector<gp_Pnt>& p,
|
||||
const std::vector<double>& c,
|
||||
std::vector<gp_Vec>& t) const
|
||||
{
|
||||
// https://de.wikipedia.org/wiki/Kubisch_Hermitescher_Spline#Cardinal_Spline
|
||||
if (p.size() < 2)
|
||||
Standard_ConstructionError::Raise();
|
||||
if (p.size() != c.size())
|
||||
Standard_ConstructionError::Raise();
|
||||
|
||||
t.resize(p.size());
|
||||
if (p.size() == 2) {
|
||||
t[0] = gp_Vec(p[0], p[1]);
|
||||
t[1] = gp_Vec(p[0], p[1]);
|
||||
}
|
||||
else {
|
||||
std::size_t e = p.size() - 1;
|
||||
|
||||
for (std::size_t i = 1; i < e; i++) {
|
||||
gp_Vec v = gp_Vec(p[i-1], p[i+1]);
|
||||
double f = 0.5 * (1-c[i]);
|
||||
v.Scale(f);
|
||||
t[i] = v;
|
||||
}
|
||||
|
||||
t[0] = t[1];
|
||||
t[t.size()-1] = t[t.size()-2];
|
||||
}
|
||||
}
|
||||
|
||||
void GeomHermiteCurve::getCardinalSplineTangents(const std::vector<gp_Pnt>& p, double c,
|
||||
std::vector<gp_Vec>& t) const
|
||||
{
|
||||
// https://de.wikipedia.org/wiki/Kubisch_Hermitescher_Spline#Cardinal_Spline
|
||||
if (p.size() < 2)
|
||||
Standard_ConstructionError::Raise();
|
||||
|
||||
t.resize(p.size());
|
||||
if (p.size() == 2) {
|
||||
t[0] = gp_Vec(p[0], p[1]);
|
||||
t[1] = gp_Vec(p[0], p[1]);
|
||||
}
|
||||
else {
|
||||
std::size_t e = p.size() - 1;
|
||||
double f = 0.5 * (1-c);
|
||||
|
||||
for (std::size_t i = 1; i < e; i++) {
|
||||
gp_Vec v = gp_Vec(p[i-1], p[i+1]);
|
||||
v.Scale(f);
|
||||
t[i] = v;
|
||||
}
|
||||
|
||||
t[0] = t[1];
|
||||
t[t.size()-1] = t[t.size()-2];
|
||||
}
|
||||
}
|
||||
|
||||
const Handle_Geom_Geometry& GeomHermiteCurve::handle() const
|
||||
{
|
||||
return myCurve;
|
||||
}
|
||||
|
||||
void GeomHermiteCurve::compute(const std::vector<gp_Pnt>& p,
|
||||
const std::vector<gp_Vec>& t)
|
||||
{
|
||||
double tol3d = Precision::Approximation();
|
||||
Handle_TColgp_HArray1OfPnt pts = new TColgp_HArray1OfPnt(1, p.size());
|
||||
for (std::size_t i=0; i<p.size(); i++) {
|
||||
pts->SetValue(i+1, p[i]);
|
||||
}
|
||||
|
||||
TColgp_Array1OfVec tgs(1, t.size());
|
||||
Handle_TColStd_HArray1OfBoolean fgs = new TColStd_HArray1OfBoolean(1, t.size());
|
||||
for (std::size_t i=0; i<p.size(); i++) {
|
||||
tgs.SetValue(i+1, t[i]);
|
||||
fgs->SetValue(i+1, Standard_True);
|
||||
}
|
||||
|
||||
GeomAPI_Interpolate interpolate(pts, Standard_False, tol3d);
|
||||
interpolate.Load(tgs, fgs);
|
||||
interpolate.Perform();
|
||||
this->myCurve = interpolate.Curve();
|
||||
|
||||
this->poles = p;
|
||||
this->tangents = t;
|
||||
}
|
||||
|
||||
Geometry *GeomHermiteCurve::clone(void) const
|
||||
{
|
||||
GeomHermiteCurve *newCurve = new GeomHermiteCurve(poles, tangents);
|
||||
newCurve->Construction = this->Construction;
|
||||
return newCurve;
|
||||
}
|
||||
|
||||
// Persistence implementer
|
||||
unsigned int GeomHermiteCurve::getMemSize (void) const {assert(0); return 0;/* not implemented yet */}
|
||||
void GeomHermiteCurve::Save (Base::Writer &/*writer*/) const {assert(0); /* not implemented yet */}
|
||||
void GeomHermiteCurve::Restore (Base::XMLReader &/*reader*/) {assert(0); /* not implemented yet */}
|
||||
|
||||
PyObject *GeomHermiteCurve::getPyObject(void)
|
||||
{
|
||||
return new HermiteCurvePy(static_cast<GeomHermiteCurve*>(this->clone()));
|
||||
}
|
||||
|
||||
// -------------------------------------------------
|
||||
|
||||
TYPESYSTEM_SOURCE(Part::GeomBSplineCurve,Part::GeomCurve);
|
||||
|
||||
GeomBSplineCurve::GeomBSplineCurve()
|
||||
|
|
|
@ -52,7 +52,10 @@
|
|||
#include <TopoDS_Shape.hxx>
|
||||
#include <gp_Ax1.hxx>
|
||||
#include <gp_Dir.hxx>
|
||||
#include <gp_Pnt.hxx>
|
||||
#include <gp_Vec.hxx>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include <Base/Persistence.h>
|
||||
#include <Base/Vector3D.h>
|
||||
|
||||
|
@ -150,6 +153,57 @@ private:
|
|||
Handle_Geom_BezierCurve myCurve;
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief The GeomHermiteCurve class
|
||||
* The GeomHermiteCurve describes a cubic Hermite spline.
|
||||
* @note Since OpenCascade doesn't directly support Hermite splines
|
||||
* the returned curve will be a B-Spline curve.
|
||||
*/
|
||||
class PartExport GeomHermiteCurve : public GeomCurve
|
||||
{
|
||||
TYPESYSTEM_HEADER();
|
||||
public:
|
||||
GeomHermiteCurve();
|
||||
GeomHermiteCurve(const std::vector<gp_Pnt>&, const std::vector<gp_Vec>&);
|
||||
virtual ~GeomHermiteCurve();
|
||||
virtual Geometry *clone(void) const;
|
||||
/*!
|
||||
* Set the poles and tangents for the cubic Hermite spline
|
||||
*/
|
||||
void interpolate(const std::vector<gp_Pnt>&, const std::vector<gp_Vec>&);
|
||||
/*!
|
||||
* Compute the tangents for a Cardinal spline using the
|
||||
* the cubic Hermite spline. It uses the method for Cardinal splines.
|
||||
*/
|
||||
void getCardinalSplineTangents(const std::vector<gp_Pnt>&,
|
||||
const std::vector<double>&,
|
||||
std::vector<gp_Vec>&) const;
|
||||
/*!
|
||||
* Compute the tangents for a Cardinal spline using the
|
||||
* the cubic Hermite spline. It uses the method for Cardinal splines.
|
||||
* It uses the same parameter for each tangent.
|
||||
*/
|
||||
void getCardinalSplineTangents(const std::vector<gp_Pnt>&, double,
|
||||
std::vector<gp_Vec>&) const;
|
||||
|
||||
// Persistence implementer ---------------------
|
||||
virtual unsigned int getMemSize (void) const;
|
||||
virtual void Save (Base::Writer &/*writer*/) const;
|
||||
virtual void Restore(Base::XMLReader &/*reader*/);
|
||||
// Base implementer ----------------------------
|
||||
virtual PyObject *getPyObject(void);
|
||||
|
||||
const Handle_Geom_Geometry& handle() const;
|
||||
|
||||
private:
|
||||
void compute(const std::vector<gp_Pnt>&, const std::vector<gp_Vec>&);
|
||||
|
||||
private:
|
||||
Handle_Geom_BSplineCurve myCurve;
|
||||
std::vector<gp_Pnt> poles;
|
||||
std::vector<gp_Vec> tangents;
|
||||
};
|
||||
|
||||
class PartExport GeomBSplineCurve : public GeomCurve
|
||||
{
|
||||
TYPESYSTEM_HEADER();
|
||||
|
|
30
src/Mod/Part/App/HermiteCurvePy.xml
Normal file
30
src/Mod/Part/App/HermiteCurvePy.xml
Normal file
|
@ -0,0 +1,30 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<GenerateModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="generateMetaModel_Module.xsd">
|
||||
<PythonExport
|
||||
Father="GeometryCurvePy"
|
||||
Name="HermiteCurvePy"
|
||||
Twin="GeomHermiteCurve"
|
||||
TwinPointer="GeomHermiteCurve"
|
||||
Include="Mod/Part/App/Geometry.h"
|
||||
Namespace="Part"
|
||||
FatherInclude="Mod/Part/App/GeometryCurvePy.h"
|
||||
FatherNamespace="Part"
|
||||
Constructor="true">
|
||||
<Documentation>
|
||||
<Author Licence="LGPL" Name="Werner Mayer" EMail="wmayer@users.sourceforge.net" />
|
||||
<UserDocu>
|
||||
Describes a Hermite curve
|
||||
</UserDocu>
|
||||
</Documentation>
|
||||
<Methode Name="interpolate" Keyword="true">
|
||||
<Documentation>
|
||||
<UserDocu>Set the poles and tangents to compute the Hermite curve.</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="getCardinalSplineTangents" Keyword="true">
|
||||
<Documentation>
|
||||
<UserDocu>Compute the tangents for a Cardinal spline</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
</PythonExport>
|
||||
</GenerateModel>
|
155
src/Mod/Part/App/HermiteCurvePyImp.cpp
Normal file
155
src/Mod/Part/App/HermiteCurvePyImp.cpp
Normal file
|
@ -0,0 +1,155 @@
|
|||
/***************************************************************************
|
||||
* Copyright (c) 2016 Werner Mayer <wmayer[at]users.sourceforge.net> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Library General Public *
|
||||
* License as published by the Free Software Foundation; either *
|
||||
* version 2 of the License, or (at your option) any later version. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU Library General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Library General Public *
|
||||
* License along with this library; see the file COPYING.LIB. If not, *
|
||||
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
||||
* Suite 330, Boston, MA 02111-1307, USA *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#include "PreCompiled.h"
|
||||
|
||||
#include "Geometry.h"
|
||||
#include <Base/GeometryPyCXX.h>
|
||||
|
||||
#include <Mod/Part/App/BSplineCurvePy.h>
|
||||
#include <Mod/Part/App/HermiteCurvePy.h>
|
||||
#include <Mod/Part/App/HermiteCurvePy.cpp>
|
||||
|
||||
using namespace Part;
|
||||
|
||||
// returns a string which represents the object e.g. when printed in python
|
||||
std::string HermiteCurvePy::representation(void) const
|
||||
{
|
||||
return std::string("<GeomHermiteCurve object>");
|
||||
}
|
||||
|
||||
PyObject *HermiteCurvePy::PyMake(struct _typeobject *, PyObject *, PyObject *) // Python wrapper
|
||||
{
|
||||
// create a new instance of HermiteCurvePy and the Twin object
|
||||
return new HermiteCurvePy(new GeomHermiteCurve);
|
||||
}
|
||||
|
||||
// constructor method
|
||||
int HermiteCurvePy::PyInit(PyObject* /*args*/, PyObject* /*kwd*/)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
PyObject* HermiteCurvePy::interpolate(PyObject *args, PyObject *kwds)
|
||||
{
|
||||
PyObject* pts;
|
||||
PyObject* tgs;
|
||||
|
||||
static char* kwds_interp1[] = {"Points", "Tangents", NULL};
|
||||
if (PyArg_ParseTupleAndKeywords(args, kwds, "OO",kwds_interp1, &pts, &tgs)) {
|
||||
Py::Sequence list(pts);
|
||||
std::vector<gp_Pnt> interpPoints;
|
||||
interpPoints.reserve(list.size());
|
||||
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
|
||||
Py::Vector v(*it);
|
||||
Base::Vector3d pnt = v.toVector();
|
||||
interpPoints.push_back(gp_Pnt(pnt.x,pnt.y,pnt.z));
|
||||
}
|
||||
Py::Sequence list2(tgs);
|
||||
std::vector<gp_Vec> interpTangents;
|
||||
interpTangents.reserve(list2.size());
|
||||
for (Py::Sequence::iterator it = list2.begin(); it != list2.end(); ++it) {
|
||||
Py::Vector v(*it);
|
||||
Base::Vector3d vec = v.toVector();
|
||||
interpTangents.push_back(gp_Vec(vec.x,vec.y,vec.z));
|
||||
}
|
||||
|
||||
GeomHermiteCurve* hermite = this->getGeomHermiteCurvePtr();
|
||||
hermite->interpolate(interpPoints, interpTangents);
|
||||
Handle_Geom_BSplineCurve aBSpline = Handle_Geom_BSplineCurve::DownCast
|
||||
(hermite->handle());
|
||||
return new BSplineCurvePy(new GeomBSplineCurve(aBSpline));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
PyObject* HermiteCurvePy::getCardinalSplineTangents(PyObject *args, PyObject *kwds)
|
||||
{
|
||||
PyObject* pts;
|
||||
PyObject* tgs;
|
||||
double parameter;
|
||||
|
||||
static char* kwds_interp1[] = {"Points", "Parameter", NULL};
|
||||
if (PyArg_ParseTupleAndKeywords(args, kwds, "Od",kwds_interp1, &pts, ¶meter)) {
|
||||
Py::Sequence list(pts);
|
||||
std::vector<gp_Pnt> interpPoints;
|
||||
interpPoints.reserve(list.size());
|
||||
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
|
||||
Py::Vector v(*it);
|
||||
Base::Vector3d pnt = v.toVector();
|
||||
interpPoints.push_back(gp_Pnt(pnt.x,pnt.y,pnt.z));
|
||||
}
|
||||
|
||||
GeomHermiteCurve* hermite = this->getGeomHermiteCurvePtr();
|
||||
std::vector<gp_Vec> tangents;
|
||||
hermite->getCardinalSplineTangents(interpPoints, parameter, tangents);
|
||||
|
||||
Py::List vec;
|
||||
for (gp_Vec it : tangents)
|
||||
vec.append(Py::Vector(Base::Vector3d(it.X(), it.Y(), it.Z())));
|
||||
return Py::new_reference_to(vec);
|
||||
}
|
||||
|
||||
PyErr_Clear();
|
||||
static char* kwds_interp2[] = {"Points", "Parameters", NULL};
|
||||
if (PyArg_ParseTupleAndKeywords(args, kwds, "OO",kwds_interp2, &pts, &tgs)) {
|
||||
Py::Sequence list(pts);
|
||||
std::vector<gp_Pnt> interpPoints;
|
||||
interpPoints.reserve(list.size());
|
||||
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
|
||||
Py::Vector v(*it);
|
||||
Base::Vector3d pnt = v.toVector();
|
||||
interpPoints.push_back(gp_Pnt(pnt.x,pnt.y,pnt.z));
|
||||
}
|
||||
|
||||
Py::Sequence list2(tgs);
|
||||
std::vector<double> parameters;
|
||||
parameters.reserve(list2.size());
|
||||
for (Py::Sequence::iterator it = list2.begin(); it != list2.end(); ++it) {
|
||||
Py::Float p(*it);
|
||||
parameters.push_back(static_cast<double>(p));
|
||||
}
|
||||
|
||||
GeomHermiteCurve* hermite = this->getGeomHermiteCurvePtr();
|
||||
std::vector<gp_Vec> tangents;
|
||||
hermite->getCardinalSplineTangents(interpPoints, parameters, tangents);
|
||||
|
||||
Py::List vec;
|
||||
for (gp_Vec it : tangents)
|
||||
vec.append(Py::Vector(Base::Vector3d(it.X(), it.Y(), it.Z())));
|
||||
return Py::new_reference_to(vec);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
PyObject *HermiteCurvePy::getCustomAttributes(const char* /*attr*/) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int HermiteCurvePy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/)
|
||||
{
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user