Surface: Various fixes

This commit is contained in:
tomate44
2022-08-18 14:58:05 +02:00
committed by wwmayer
parent e0034bed61
commit 6ec601dade
11 changed files with 1047 additions and 0 deletions

View File

@@ -30,6 +30,9 @@
#include "FeatureGeomFillSurface.h"
#include "FeatureExtend.h"
#include "FeatureSections.h"
#include "Blending/BlendPointPy.h"
#include "Blending/BlendCurvePy.h"
#include "Blending/FeatureBlendCurve.h"
#include <Base/Interpreter.h>
#include <Base/Parameter.h>
@@ -78,6 +81,9 @@ PyMOD_INIT_FUNC(Surface)
Surface::GeomFillSurface ::init();
Surface::Extend ::init();
Surface::Sections ::init();
Surface::BlendPoint ::init();
Surface::BlendCurve ::init();
Surface::FeatureBlendCurve ::init();
PyMOD_Return(mod);
}

View File

@@ -0,0 +1,171 @@
/***************************************************************************
* Copyright (c) 2022 Matteo Grellier <matteogrellier@gmail.com> *
* *
* *
* 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"
#ifndef _PreComp_
#include <BSplCLib.hxx>
#include <Geom_BezierCurve.hxx>
#include <Precision.hxx>
#include <Standard_Version.hxx>
#include <TColStd_Array1OfReal.hxx>
#include <TColgp_Array1OfPnt.hxx>
#include <gp_Pnt.hxx>
#include <math_Gauss.hxx>
#include <math_Matrix.hxx>
#endif
#include <Base/Vector3D.h>
#include <Mod/Part/App/Geometry.h>
#include "Blending/BlendCurve.h"
#include "Blending/BlendCurvePy.h"
using namespace Surface;
BlendCurve::BlendCurve()
{
}
BlendCurve::BlendCurve(std::vector<BlendPoint> blendPointsList)
{
// Retrieve number of blendPoints and push them into blendPoints.
int nb_pts = blendPointsList.size();
if (nb_pts > 2) {
throw Base::ValueError("Not implemented");
}
else if (nb_pts < 2) {
throw Base::ValueError("Need two points for working");
}
blendPoints = blendPointsList;
}
BlendCurve::~BlendCurve()
{
}
Handle(Geom_BezierCurve) BlendCurve::compute()
{
int nb_pts = blendPoints.size();
try {
// Uniform Parametrization
TColStd_Array1OfReal params(1, nb_pts);
for (int i = 0; i < nb_pts; ++i) {
params(i + 1) = (double)i / ((double)nb_pts - 1);
}
int num_poles = 0;
for (int i = 0; i < nb_pts; ++i) {
num_poles += blendPoints[i].nbVectors();
}
Handle(Geom_BezierCurve) curve;
if (num_poles > (curve->MaxDegree()+1))// use Geom_BezierCurve max degree
Standard_Failure::Raise("number of constraints exceeds bezier curve capacity");
TColStd_Array1OfReal knots(1, 2 * num_poles);
for (int i = 1; i <= num_poles; ++i) {
knots(i) = params(1);
knots(num_poles + i) = params(nb_pts);
}
math_Matrix OCCmatrix(1, num_poles, 1, num_poles, 0.0);
math_Vector res_x(1, num_poles, 0.0);
math_Vector res_y(1, num_poles, 0.0);
math_Vector res_z(1, num_poles, 0.0);
int row_idx = 1;
int cons_idx = 1;
for (int i = 0; i < nb_pts; ++i) {
math_Matrix bezier_eval(1, blendPoints[i].nbVectors(), 1, num_poles, 0.0);
Standard_Integer first_non_zero;
BSplCLib::EvalBsplineBasis(blendPoints[i].nbVectors() - 1, num_poles, knots, params(cons_idx), first_non_zero, bezier_eval, Standard_False);
int idx2 = 1;
for (int it2 = 0; it2 < blendPoints[i].nbVectors(); ++it2) {
OCCmatrix.SetRow(row_idx, bezier_eval.Row(idx2));
Base::Vector3d pnt = blendPoints[i].vectors[it2];
res_x(row_idx) = pnt.x;
res_y(row_idx) = pnt.y;
res_z(row_idx) = pnt.z;
idx2++;
row_idx++;
}
cons_idx++;
}
math_Gauss gauss(OCCmatrix);
gauss.Solve(res_x);
if (!gauss.IsDone())
Standard_Failure::Raise("Failed to solve equations");
gauss.Solve(res_y);
if (!gauss.IsDone())
Standard_Failure::Raise("Failed to solve equations");
gauss.Solve(res_z);
if (!gauss.IsDone())
Standard_Failure::Raise("Failed to solve equations");
TColgp_Array1OfPnt poles(1, num_poles);
for (int idx = 1; idx <= num_poles; ++idx) {
poles.SetValue(idx, gp_Pnt(res_x(idx), res_y(idx), res_z(idx)));
}
Handle(Geom_BezierCurve) bezier = new Geom_BezierCurve(poles);
return bezier;
}
catch (Standard_Failure &e) {
PyErr_SetString(PyExc_Exception, "Failed to compute bezier curve");
}
return nullptr;
}
void BlendCurve::setSize(int i, double f, bool relative)
{
double size = f;
try {
if (relative) {
double nb_poles = blendPoints.front().nbVectors() + blendPoints[1].nbVectors();
Base::Vector3d diff = blendPoints[1].vectors[0] - blendPoints[0].vectors[0];
size = size * diff.Length() / nb_poles;
}
blendPoints[i].setSize(size);
}
catch (Standard_Failure &e) {
PyErr_SetString(PyExc_Exception, e.GetMessageString());
}
}
unsigned int BlendCurve::getMemSize(void) const
{
return 1;
}
PyObject *BlendCurve::getPyObject(void)
{
return new BlendCurvePy(new BlendCurve(blendPoints));
}
void BlendCurve::Save(Base::Writer & /*writer*/) const
{
throw Base::NotImplementedError("BlendCurve::Save");
}
void BlendCurve::Restore(Base::XMLReader & /*reader*/)
{
throw Base::NotImplementedError("BlendCurve::Restore");
}

View File

@@ -0,0 +1,76 @@
/***************************************************************************
* Copyright (c) 2022 Matteo Grellier <matteogrellier@gmail.com> *
* *
* 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 *
* *
***************************************************************************/
#ifndef BLEND_CURVE_H
#define BLEND_CURVE_H
#include <Geom_BezierCurve.hxx>
// #include <Mod/Part/App/Geometry.h>
// #include <App/PropertyLinks.h>
// #include <App/PropertyStandard.h>
// #include <App/PropertyUnits.h>
// #include <Base/Persistence.h>
// #include <Mod/Part/App/PartFeature.h>
#include <Mod/Surface/SurfaceGlobal.h>
#include <Mod/Surface/App/Blending/BlendPoint.h>
namespace Surface
{
/*!
* Create a BezierCurve interpolating a list of BlendPoints
*/
class SurfaceExport BlendCurve: public Base::Persistence
{
public:
std::vector<BlendPoint> blendPoints;
BlendCurve();
/*!
* Constructor
*\param std::vector<BlendPoint>
*/
BlendCurve(std::vector<BlendPoint> blendPointsList);
virtual ~BlendCurve();
/*!
* Perform the interpolate algorithm
*\return the BezierCurve
*/
Handle(Geom_BezierCurve) compute();
/*!
* Set the size of the first derivative of a BlendPoint
*\param int index of the BlendPoint to modify
*\param double new size
*\param bool interpret new size relative to chordlength
*/
void setSize(int, double, bool);
virtual PyObject *getPyObject(void);
// Persistence implementer ---------------------
virtual unsigned int getMemSize(void) const;
virtual void Save(Base::Writer & /*writer*/) const;
virtual void Restore(Base::XMLReader & /*reader*/);
};
}// namespace Surface
#endif

View File

@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<GenerateModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="generateMetaModel_Module.xsd">
<PythonExport
Father="PersistencePy"
FatherInclude="Base/PersistencePy.h"
FatherNamespace="Base"
Name="BlendCurvePy"
PythonName="Surface.BlendCurve"
Twin="BlendCurve"
TwinPointer="BlendCurve"
Include="Mod/Surface/App/Blending/BlendCurve.h"
Namespace="Surface"
Constructor="true"
Delete="true">
<Documentation>
</Documentation>
<Documentation>
<Author Licence="LGPL" Name="Mattéo Grellier" EMail="matteogrellier@gmail.com" />
<UserDocu>
Create a BlendCurve that interpolate a list of BlendPoints.
curve = BlendCurve([BlendPoint1, BlendPoint2])
curve = BlendCurve(BlendPoint1, BlendPoint2)
</UserDocu>
</Documentation>
<Methode Name="compute">
<Documentation>
<UserDocu>
Return the BezierCurve that interpolate the input BlendPoints.
</UserDocu>
</Documentation>
</Methode>
<Methode Name="setSize">
<Documentation>
<UserDocu>
Set the tangent size of the blendpoint at given index.
If relative is true, the size is considered relative to the distance between the two blendpoints.
myBlendCurve.setSize(idx, size, relative)
</UserDocu>
</Documentation>
</Methode>
</PythonExport>
</GenerateModel>

View File

@@ -0,0 +1,119 @@
///***************************************************************************
// * Copyright (c) 2022 Matteo Grellier <matteogrellier@gmail.com> *
// * *
// * 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"
#ifndef _PreComp_
#include <TColStd_Array1OfReal.hxx>
#include <TColgp_Array1OfPnt.hxx>
#endif
#include "Blending/BlendCurvePy.h"
#include "Blending/BlendPointPy.h"
// #include "Mod/Part/App/Geometry.h"
// #include <Base/GeometryPyCXX.h>
#include <Base/VectorPy.h>
#include <Mod/Part/App/BezierCurvePy.h>
#include "Blending/BlendCurvePy.cpp"
using namespace Surface;
std::string BlendCurvePy::representation(void) const
{
return "BlendCurve";
}
PyObject *BlendCurvePy::PyMake(struct _typeobject *, PyObject *, PyObject *)// Python wrapper
{
// create a new instance of BlendCurvePy
return new BlendCurvePy(new BlendCurve);
}
int BlendCurvePy::PyInit(PyObject *args, PyObject * /*kwds*/)
{
PyObject *plist;
if (PyArg_ParseTuple(args, "O", &plist)) {
Py::Sequence list(plist);
if (list.size() != 2) {
PyErr_SetString(PyExc_TypeError, "Currently BlendCurve need exactly 2 BlendPoints");
return -1;
}
std::vector<BlendPoint> bpList;
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
Py::Object obj(*it);
if (PyObject_TypeCheck(obj.ptr(), &BlendPointPy::Type)) {
BlendPoint *geom = static_cast<BlendPointPy *>(obj.ptr())->getBlendPointPtr();
bpList.emplace_back(*geom);
}
}
this->getBlendCurvePtr()->blendPoints = bpList;
return 0;
}
PyErr_Clear();
PyObject *b1;
PyObject *b2;
std::vector<BlendPoint> bpList;
if (PyArg_ParseTuple(args, "O!O!", &(Surface::BlendPointPy::Type), &b1, &(Surface::BlendPointPy::Type), &b2)) {
BlendPoint *geom1 = static_cast<BlendPointPy *>(b1)->getBlendPointPtr();
BlendPoint *geom2 = static_cast<BlendPointPy *>(b2)->getBlendPointPtr();
bpList.emplace_back(*geom1);
bpList.emplace_back(*geom2);
this->getBlendCurvePtr()->blendPoints = bpList;
return 0;
}
return -1;
}
PyObject *BlendCurvePy::compute(PyObject * /*args*/)
{
BlendCurve *bc = getBlendCurvePtr();
Handle(Geom_BezierCurve) gc = bc->compute();
return new Part::BezierCurvePy(new Part::GeomBezierCurve(gc));
}
PyObject *BlendCurvePy::setSize(PyObject *args)
{
int i;
double size;
PyObject* relative = Py_True;
if (!PyArg_ParseTuple(args, "idO!", &i, &size, &PyBool_Type, &relative)) {
return nullptr;
}
try {
getBlendCurvePtr()->setSize(i, size, Base::asBoolean(relative));
}
catch (Standard_Failure &e) {
PyErr_SetString(PyExc_Exception, e.GetMessageString());
return nullptr;
}
Py_Return;
}
PyObject *BlendCurvePy::getCustomAttributes(const char * /*attr*/) const
{
return nullptr;
}
int BlendCurvePy::setCustomAttributes(const char * /*attr*/, PyObject * /*obj*/)
{
return 0;
}

View File

@@ -0,0 +1,101 @@
/***************************************************************************
* Copyright (c) 2022 Matteo Grellier <matteogrellier@gmail.com> *
* *
* *
* 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"
#ifndef _PreComp_
#include <Base/Persistence.h>
#include <Base/Vector3D.h>
#include <Precision.hxx>
#include <Standard_Version.hxx>
#include <TopoDS.hxx>
#include <gp_Pnt.hxx>
#endif
#include "Blending/BlendPoint.h"
#include "Blending/BlendPointPy.h"
using namespace Surface;
BlendPoint::BlendPoint(std::vector<Base::Vector3d> vectorList)
{
for (size_t i = 0; i < vectorList.size(); i++) {
vectors.emplace_back(vectorList[i]);
}
}
BlendPoint::BlendPoint()
{
vectors.emplace_back(Base::Vector3d(0, 0, 0));
}
BlendPoint::~BlendPoint()
{
}
void BlendPoint::multiply(double f)
{
for (int i = 0; i < nbVectors(); i++) {
vectors[i] *= Pow(f, i);
}
}
void BlendPoint::setSize(double f)
{
if (nbVectors() > 1) {
double il = vectors[1].Length();
if (il > Precision::Confusion()) {
multiply(f / il);
}
}
}
int BlendPoint::getContinuity()
{
return vectors.size() - 1;
}
int BlendPoint::nbVectors()
{
return vectors.size();
}
PyObject *BlendPoint::getPyObject(void)
{
return new BlendPointPy(new BlendPoint(vectors));
}
void BlendPoint::Save(Base::Writer & /*writer*/) const
{
throw Base::NotImplementedError("BlendPoint::Save");
}
void BlendPoint::Restore(Base::XMLReader & /*reader*/)
{
throw Base::NotImplementedError("BlendPoint::Restore");
}
unsigned int BlendPoint::getMemSize(void) const
{
// do we need to loop on the vectors list ?
return sizeof(vectors) * sizeof(vectors.front());
}

View File

@@ -0,0 +1,83 @@
/***************************************************************************
* Copyright (c) 2014 Matteo Grellier <matteogrellier@gmail.com> *
* *
* 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 *
* *
***************************************************************************/
#ifndef BLEND_POINT_H
#define BLEND_POINT_H
#include <App/PropertyLinks.h>
#include <App/PropertyStandard.h>
#include <App/PropertyUnits.h>
#include <Base/Persistence.h>
#include <Mod/Part/App/PartFeature.h>
#include <Mod/Surface/SurfaceGlobal.h>
#include <Mod/Part/App/FeaturePartSpline.h>
namespace Surface
{
/*!
* Create a list of vectors formed by a point and some derivatives
* obtained from a curve or surface
*/
class SurfaceExport BlendPoint: public Base::Persistence
{
public:
std::vector<Base::Vector3d> vectors;
BlendPoint();
/*!
* Constructor
*\param std::vector<Base::Vector3d>
*/
BlendPoint(std::vector<Base::Vector3d> vectorList);
virtual ~BlendPoint();
/*!
* Scale the blendpoint vectors
*\param double scaling factor
*/
void multiply(double f);
/*!
* Resize the blendpoint vectors
* by setting the size of the first derivative
*\param double new size
*/
void setSize(double f);
/*!
*\return continuity of this BlendPoint
*/
int getContinuity();
/*!
*\return Number of vectors of this BlendPoint
*/
int nbVectors();
virtual PyObject *getPyObject(void);
// Persistence implementer ---------------------
virtual unsigned int getMemSize(void) const;
virtual void Save(Base::Writer & /*writer*/) const;
virtual void Restore(Base::XMLReader & /*reader*/);
private:
};
}// namespace Surface
#endif

View File

@@ -0,0 +1,57 @@
<?xml version="1.0" encoding="utf-8"?>
<GenerateModel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="generateMetaModel_Module.xsd">
<PythonExport
Father="PersistencePy"
FatherInclude="Base/PersistencePy.h"
FatherNamespace="Base"
Name="BlendPointPy"
PythonName="Surface.BlendPoint"
Twin="BlendPoint"
TwinPointer="BlendPoint"
Include="Mod/Surface/App/Blending/BlendPoint.h"
Namespace="Surface"
Constructor="true"
Delete="true">
<Documentation>
</Documentation>
<Documentation>
<Author Licence="LGPL" Name="Mattéo Grellier" EMail="matteogrellier@gmail.com" />
<UserDocu>
Create BlendPoint from a point and some derivatives.
myBlendPoint = BlendPoint([Point, D1, D2, ..., DN])
BlendPoint can also be constructed from an edge
myBlendPoint = BlendPoint(Edge, parameter = float, continuity = int)
</UserDocu>
</Documentation>
<Attribute Name="Vectors" ReadOnly="true">
<Documentation>
<UserDocu>The list of vectors of this BlendPoint.</UserDocu>
</Documentation>
<Parameter Name="vectors" Type="List"/>
</Attribute>
<Methode Name="getSize" Const="true">
<Documentation>
<UserDocu>
Return BlendPoint first derivative length.
</UserDocu>
</Documentation>
</Methode>
<Methode Name="setSize">
<Documentation>
<UserDocu>
Resizes the BlendPoint vectors,
by setting the lenght of the first derivative.
theBlendPoint.setSize(new_size)
</UserDocu>
</Documentation>
</Methode>
<Methode Name="setvectors">
<Documentation>
<UserDocu>
Set the vectors of BlendPoint.
BlendPoint.setvectors([Point, D1, D2, ..., DN])
</UserDocu>
</Documentation>
</Methode>
</PythonExport>
</GenerateModel>

View File

@@ -0,0 +1,194 @@
///***************************************************************************
// * Copyright (c) 2022 Matteo Grellier <matteogrellier@gmail.com> *
// * *
// * 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"
#ifndef _PreComp_
#include <BRepAdaptor_Curve.hxx>
#include <TColStd_Array1OfReal.hxx>
#include <TColgp_Array1OfPnt.hxx>
#include <TopoDS.hxx>
#endif
#include <Base/GeometryPyCXX.h>
#include <Base/VectorPy.h>
#include <Mod/Part/App/TopoShapePy.h>
#include "Blending/BlendPoint.h"
#include "Blending/BlendPointPy.h"
#include "Blending/BlendPointPy.cpp"
using namespace Surface;
std::string BlendPointPy::representation(void) const
{
Base::Vector3d bp = getBlendPointPtr()->vectors[0];
std::stringstream str;
str << "G" << getBlendPointPtr()->getContinuity()
<< " BlendPoint at (" << bp.x << ", " << bp.y << ", " << bp.z << "), ";
return str.str();
}
PyObject *BlendPointPy::PyMake(struct _typeobject *, PyObject *, PyObject *)// Python wrapper
{
// create a new instance of BlendPointPy
return new BlendPointPy(new BlendPoint);
}
int BlendPointPy::PyInit(PyObject* args, PyObject*)
{
PyObject *plist;
std::vector<Base::Vector3d> vecs;
if (PyArg_ParseTuple(args, "O", &plist)) {
Py::Sequence list(plist);
if (list.size() == 0) {
vecs.emplace_back(Base::Vector3d(0, 0, 0));
}
else {
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
Py::Vector v(*it);
Base::Vector3d vec = v.toVector();
vecs.emplace_back(vec);
}
}
this->getBlendPointPtr()->vectors = vecs;
return 0;
}
PyErr_Clear();
if (PyArg_ParseTuple(args, "")) {
vecs.emplace_back(Base::Vector3d(0, 0, 0));
this->getBlendPointPtr()->vectors = vecs;
return 0;
}
double param;
int cont;
PyObject *pcObj;
PyErr_Clear();
// Create a curve with an edge, parameter and continiuity.
if (PyArg_ParseTuple(args, "O!di", &(Part::TopoShapePy::Type), &pcObj, &param, &cont)) {
try {
gp_Pnt Pt;
TopoDS_Shape shape = static_cast<Part::TopoShapePy *>(pcObj)->getTopoShapePtr()->getShape();
const TopoDS_Edge &e = TopoDS::Edge(shape);
BRepAdaptor_Curve adapt(e);
adapt.D0(param, Pt);
Base::Vector3d bv(Pt.X(), Pt.Y(), Pt.Z());
vecs.emplace_back(bv);
for (int i = 1; i <= cont; i++) {
gp_Vec v1 = adapt.DN(param, i);
Base::Vector3d bbv1(v1.X(), v1.Y(), v1.Z());
vecs.emplace_back(bbv1);
}
this->getBlendPointPtr()->vectors = vecs;
return 0;
}
catch (const std::exception &e) {
std::cerr << e.what() << '\n';
return -1;
}
}
return -1;
}
PyObject *BlendPointPy::setSize(PyObject *args)
{
double size = 1.0;
if (!PyArg_ParseTuple(args, "d", &size))
return nullptr;
try {
getBlendPointPtr()->setSize(size);
Py_Return;
}
catch (Standard_Failure &e) {
PyErr_SetString(PyExc_Exception, "Failed to set size");
return nullptr;
}
}
PyObject *BlendPointPy::getSize(PyObject *args)
{
if (!PyArg_ParseTuple(args, ""))
return nullptr;
int nb = getBlendPointPtr()->nbVectors();
if (nb >= 2) {
double bpTangentLength = getBlendPointPtr()->vectors[1].Length();
return Py_BuildValue("d", bpTangentLength);
}
return nullptr;
}
Py::List BlendPointPy::getVectors() const
{
try {
BlendPoint *bp = getBlendPointPtr();
std::vector<Base::Vector3d> p = bp->vectors;
Py::List vecs;
for (size_t i = 0; i < p.size(); i++) {
Base::VectorPy *vec = new Base::VectorPy(Base::Vector3d(
p[i].x, p[i].y, p[i].z));
vecs.append(Py::asObject(vec));
}
return vecs;
}
catch (Standard_Failure &e) {
PyErr_SetString(PyExc_RuntimeError,
e.GetMessageString());
return Py::List();
}
}
PyObject *BlendPointPy::setvectors(PyObject *args)
{
BlendPoint *bp = getBlendPointPtr();
PyObject *plist;
if (!PyArg_ParseTuple(args, "O", &plist)) {
PyErr_SetString(PyExc_TypeError, "List of vectors required.");
return nullptr;
}
try {
Py::Sequence list(plist);
std::vector<Base::Vector3d> vecs;
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
Py::Vector v(*it);
Base::Vector3d pole = v.toVector();
vecs.emplace_back(pole);
}
bp->vectors = vecs;
Py_Return;
}
catch (Standard_Failure &e) {
PyErr_SetString(PyExc_RuntimeError, e.GetMessageString());
}
return nullptr;
}
PyObject *BlendPointPy::getCustomAttributes(const char * /*attr*/) const
{
return nullptr;
}
int BlendPointPy::setCustomAttributes(const char * /*attr*/, PyObject * /*obj*/)
{
return 0;
}

View File

@@ -0,0 +1,181 @@
/***************************************************************************
* Copyright (c) 2022 Matteo Grellier <matteogrellier@gmail.com> *
* *
* *
* 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"
#ifndef _PreComp_
#include <BRepAdaptor_Curve.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <Base/Tools.h>
#include <Geom_Curve.hxx>
#include <Precision.hxx>
#include <Standard_Version.hxx>
#include <TopoDS.hxx>
#include <gp_Pnt.hxx>
#endif
#include "FeatureBlendCurve.h"
#include "Mod/Surface/App/Blending/BlendCurve.h"
#include "Mod/Surface/App/Blending/BlendPoint.h"
using namespace Surface;
const App::PropertyFloatConstraint::Constraints StartParameterConstraint = {0.0, 1.0, 0.05};
const App::PropertyFloatConstraint::Constraints EndParameterConstraint = {0.0, 1.0, 0.05};
const App::PropertyIntegerConstraint::Constraints StartContinuityConstraint = {0, 25, 1};
const App::PropertyIntegerConstraint::Constraints EndContinuityConstraint = {0, 25, 1};
PROPERTY_SOURCE(Surface::FeatureBlendCurve, Part::Spline)
FeatureBlendCurve::FeatureBlendCurve() : lockOnChangeMutex(false)
{
ADD_PROPERTY_TYPE(StartEdge, (nullptr), "FirstEdge", App::Prop_None, "");
ADD_PROPERTY_TYPE(StartContinuity, (2), "FirstEdge", App::Prop_None, "");
StartContinuity.setConstraints(&StartContinuityConstraint);
ADD_PROPERTY_TYPE(StartParameter, (0.0f), "FirstEdge", App::Prop_None, "");
StartParameter.setConstraints(&StartParameterConstraint);
ADD_PROPERTY_TYPE(StartSize, (1.0f), "FirstEdge", App::Prop_None, "");
ADD_PROPERTY_TYPE(EndEdge, (nullptr), "SecondEdge", App::Prop_None, "");
ADD_PROPERTY_TYPE(EndContinuity, (2), "SecondEdge", App::Prop_None, "");
EndContinuity.setConstraints(&EndContinuityConstraint);
ADD_PROPERTY_TYPE(EndParameter, (0.0f), "SecondEdge", App::Prop_None, "");
EndParameter.setConstraints(&EndParameterConstraint);
ADD_PROPERTY_TYPE(EndSize, (1.0f), "SecondEdge", App::Prop_None, "");
Handle(Geom_BezierCurve) maxDegreeCurve;
maxDegree = maxDegreeCurve->MaxDegree();
}
short FeatureBlendCurve::mustExecute() const
{
if (StartEdge.isTouched())
return 1;
if (StartParameter.isTouched())
return 1;
if (StartContinuity.isTouched())
return 1;
if (StartSize.isTouched())
return 1;
if (EndEdge.isTouched())
return 1;
if (EndParameter.isTouched())
return 1;
if (EndContinuity.isTouched())
return 1;
if (EndSize.isTouched())
return 1;
return 0;
}
BlendPoint FeatureBlendCurve::GetBlendPoint(App::PropertyLinkSub &link, App::PropertyFloatConstraint &param, App::PropertyIntegerConstraint &continuity)
{
auto linked = link.getValue();
TopoDS_Shape axEdge;
if (link.getSubValues().size() > 0 && link.getSubValues()[0].length() > 0) {
axEdge = Feature::getTopoShape(linked, link.getSubValues()[0].c_str(), true /*need element*/).getShape();
}
else {
axEdge = Feature::getShape(linked);
}
if (axEdge.IsNull())
throw Base::ValueError("DirLink shape is null");
if (axEdge.ShapeType() != TopAbs_EDGE)
throw Base::TypeError("DirLink shape is not an edge");
const TopoDS_Edge &e = TopoDS::Edge(axEdge);
BRepAdaptor_Curve adapt(e);
double fp = adapt.FirstParameter();
double lp = adapt.LastParameter();
double RealPar = RelativeToRealParameters(param.getValue(), fp, lp);
std::vector<Base::Vector3d> constraints;
gp_Pnt Pt;
adapt.D0(RealPar, Pt);
Base::Vector3d bv(Pt.X(), Pt.Y(), Pt.Z());
constraints.emplace_back(bv);
for (int i = 1; i <= continuity.getValue(); i++) {
gp_Vec v1 = adapt.DN(RealPar, i);
Base::Vector3d bbv1(v1.X(), v1.Y(), v1.Z());
constraints.emplace_back(bbv1);
}
BlendPoint bp(constraints);
return bp;
}
App::DocumentObjectExecReturn *FeatureBlendCurve::execute(void)
{
BlendPoint bp1 = GetBlendPoint(StartEdge, StartParameter, StartContinuity);
BlendPoint bp2 = GetBlendPoint(EndEdge, EndParameter, EndContinuity);
std::vector<BlendPoint> blendPointsList;
blendPointsList.emplace_back(bp1);
blendPointsList.emplace_back(bp2);
BlendCurve curve(blendPointsList);
curve.setSize(0, StartSize.getValue(), true);
curve.setSize(1, EndSize.getValue(), true);
Handle(Geom_BezierCurve) bc(curve.compute());
BRepBuilderAPI_MakeEdge mkEdge(bc);
Shape.setValue(mkEdge.Edge());
return StdReturn;
}
double FeatureBlendCurve::RelativeToRealParameters(double relativeValue, double fp, double lp)
{
return fp + relativeValue * (lp - fp);
}
void FeatureBlendCurve::onChanged(const App::Property *prop)
{
// using a mutex and lock to protect a recursive calling when setting the new values
if (lockOnChangeMutex)
return;
Base::StateLocker lock(lockOnChangeMutex);
if (prop == &StartContinuity) {
auto changedStartProp = dynamic_cast<const App::PropertyInteger *>(prop);
if (changedStartProp->getValue() > (maxDegree - 2 - EndContinuity.getValue())) {
StartContinuity.setValue(maxDegree - 2 - EndContinuity.getValue());
}
}
else if (prop == &EndContinuity) {
auto changedEndProp = dynamic_cast<const App::PropertyInteger *>(prop);
if (changedEndProp->getValue() > (maxDegree - 2 - StartContinuity.getValue())) {
EndContinuity.setValue(maxDegree - 2 - StartContinuity.getValue());
}
}
Part::Spline::onChanged(prop);
}

View File

@@ -16,6 +16,23 @@ set(Surface_LIBS
Part
)
SET(BlendingPy_SRCS
Blending/BlendPointPy.xml
Blending/BlendPointPyImp.cpp
Blending/BlendCurvePy.xml
Blending/BlendCurvePyImp.cpp
)
SOURCE_GROUP("Blending" FILES ${BlendingPy_SRCS})
SET(Blending_SRCS
Blending/FeatureBlendCurve.cpp
Blending/FeatureBlendCurve.h
Blending/BlendPoint.cpp
Blending/BlendPoint.h
Blending/BlendCurve.cpp
Blending/BlendCurve.h
)
SET(Surface_SRCS
AppSurface.cpp
PreCompiled.cpp