PythonConverter: Extend for Hyperbola/Parabola/BSpline

This commit is contained in:
Paddle
2023-11-16 11:58:47 +01:00
committed by abdullahtahiriyo
parent aa901520b5
commit 30e2a109e6
6 changed files with 168 additions and 20 deletions

View File

@@ -2957,6 +2957,18 @@ Base::Vector3d GeomArcOfEllipse::getMajorAxisDir() const
return Base::Vector3d(xdir.X(), xdir.Y(), xdir.Z());
}
/*!
* \brief GeomArcOfEllipse::getMinorAxisDir
* \return the direction vector (unit-length) of minor axis of the ellipse.
*/
Base::Vector3d GeomArcOfEllipse::getMinorAxisDir() const
{
Handle(Geom_Ellipse) c = Handle(Geom_Ellipse)::DownCast(myCurve->BasisCurve());
assert(!c.IsNull());
gp_Dir ydir = c->YAxis().Direction();
return Base::Vector3d(ydir.X(), ydir.Y(), ydir.Z());
}
/*!
* \brief GeomArcOfEllipse::setMajorAxisDir Rotates the ellipse in its plane, so
* that its major axis is as close as possible to the provided direction.
@@ -3387,6 +3399,18 @@ Base::Vector3d GeomArcOfHyperbola::getMajorAxisDir() const
return Base::Vector3d(xdir.X(), xdir.Y(), xdir.Z());
}
/*!
* \brief GeomArcOfHyperbola::getMinorAxisDir
* \return the direction vector (unit-length) of minor axis of the hyperbola.
*/
Base::Vector3d GeomArcOfHyperbola::getMinorAxisDir() const
{
Handle(Geom_Hyperbola) c = Handle(Geom_Hyperbola)::DownCast( myCurve->BasisCurve() );
assert(!c.IsNull());
gp_Dir ydir = c->YAxis().Direction();
return Base::Vector3d(ydir.X(), ydir.Y(), ydir.Z());
}
/*!
* \brief GeomArcOfHyperbola::setMajorAxisDir Rotates the hyperbola in its plane, so
* that its major axis is as close as possible to the provided direction.

View File

@@ -568,6 +568,7 @@ public:
void setMinorRadius(double Radius);
Base::Vector3d getMajorAxisDir() const;
void setMajorAxisDir(Base::Vector3d newdir);
Base::Vector3d getMinorAxisDir() const;
void getRange(double& u, double& v, bool emulateCCWXY) const override;
void setRange(double u, double v, bool emulateCCWXY) override;
@@ -630,6 +631,7 @@ public:
void setMinorRadius(double Radius);
Base::Vector3d getMajorAxisDir() const;
void setMajorAxisDir(Base::Vector3d newdir);
Base::Vector3d getMinorAxisDir() const;
void getRange(double& u, double& v, bool emulateCCWXY) const override;
void setRange(double u, double v, bool emulateCCWXY) override;

View File

@@ -619,6 +619,12 @@ std::string ConstraintPy::representation() const
case ParabolaFocus:
result << "'InternalAlignment:ParabolaFocus'>";
break;
case BSplineControlPoint:
result << "'InternalAlignment:BSplineControlPoint'>";
break;
case BSplineKnotPoint:
result << "'InternalAlignment:BSplineKnotPoint'>";
break;
default:
result << "'InternalAlignment:?'>";
break;

View File

@@ -29,13 +29,14 @@
#include <Base/Exception.h>
#include <Mod/Sketcher/App/Constraint.h>
#include <Mod/Sketcher/App/GeometryFacade.h>
#include <Mod/Sketcher/App/SketchObject.h>
#include "PythonConverter.h"
using namespace Sketcher;
std::string PythonConverter::convert(const Part::Geometry* geo)
std::string PythonConverter::convert(const Part::Geometry* geo, Mode mode)
{
// "addGeometry(Part.LineSegment(App.Vector(%f,%f,0),App.Vector(%f,%f,0)),%s)"
@@ -45,6 +46,16 @@ std::string PythonConverter::convert(const Part::Geometry* geo)
command = boost::str(boost::format("addGeometry(%s,%s)\n") % sg.creation
% (sg.construction ? "True" : "False"));
if ((geo->getTypeId() != Part::GeomEllipse::getClassTypeId()
|| geo->getTypeId() != Part::GeomArcOfEllipse::getClassTypeId()
|| geo->getTypeId() != Part::GeomArcOfHyperbola::getClassTypeId()
|| geo->getTypeId() != Part::GeomArcOfParabola::getClassTypeId()
|| geo->getTypeId() != Part::GeomBSplineCurve::getClassTypeId())
&& mode == Mode::CreateInternalGeometry) {
command +=
boost::str(boost::format("exposeInternalGeometry(len(ActiveSketch.Geometry))\n"));
}
return command;
}
@@ -60,7 +71,8 @@ std::string PythonConverter::convert(const Sketcher::Constraint* constraint)
}
std::string PythonConverter::convert(const std::string& doc,
const std::vector<Part::Geometry*>& geos)
const std::vector<Part::Geometry*>& geos,
Mode mode)
{
if (geos.empty()) {
return std::string();
@@ -87,7 +99,7 @@ std::string PythonConverter::convert(const std::string& doc,
return command;
};
std::string command;
std::string command = boost::str(boost::format("lastGeoId = len(ActiveSketch.Geometry)\n"));
// Adds a list of consecutive geometries of a same construction type to the generating command
auto addToCommands = [&command,
@@ -133,6 +145,22 @@ std::string PythonConverter::convert(const std::string& doc,
addToCommands(geolist, ngeos, currentconstruction);
int index = 0;
if (mode == Mode::CreateInternalGeometry) {
for (auto geo : geos) {
index++;
if (geo->getTypeId() != Part::GeomEllipse::getClassTypeId()
|| geo->getTypeId() != Part::GeomArcOfEllipse::getClassTypeId()
|| geo->getTypeId() != Part::GeomArcOfHyperbola::getClassTypeId()
|| geo->getTypeId() != Part::GeomArcOfParabola::getClassTypeId()
|| geo->getTypeId() != Part::GeomBSplineCurve::getClassTypeId()) {
std::string newcommand =
boost::str(boost::format("exposeInternalGeometry(lastGeoId + %d)\n") % (index));
command += newcommand;
}
}
}
return command;
}
@@ -206,11 +234,9 @@ PythonConverter::SingleGeometry PythonConverter::process(const Part::Geometry* g
[](const Part::Geometry* geo) {
auto ellipse = static_cast<const Part::GeomEllipse*>(geo);
SingleGeometry sg;
auto periapsis =
ellipse->getCenter() + ellipse->getMajorAxisDir() * ellipse->getMajorRadius();
auto positiveB =
ellipse->getCenter() + ellipse->getMinorAxisDir() * ellipse->getMinorRadius();
auto center = ellipse->getCenter();
auto periapsis = center + ellipse->getMajorAxisDir() * ellipse->getMajorRadius();
auto positiveB = center + ellipse->getMinorAxisDir() * ellipse->getMinorRadius();
sg.creation =
boost::str(boost::format("Part.Ellipse(App.Vector(%f, %f, %f), App.Vector(%f, "
"%f, %f), App.Vector(%f, %f, %f))")
@@ -219,6 +245,77 @@ PythonConverter::SingleGeometry PythonConverter::process(const Part::Geometry* g
sg.construction = Sketcher::GeometryFacade::getConstruction(geo);
return sg;
}},
{Part::GeomArcOfEllipse::getClassTypeId(),
[](const Part::Geometry* geo) {
auto aoe = static_cast<const Part::GeomArcOfEllipse*>(geo);
SingleGeometry sg;
auto center = aoe->getCenter();
auto periapsis = center + aoe->getMajorAxisDir() * aoe->getMajorRadius();
auto positiveB = center + aoe->getMinorAxisDir() * aoe->getMinorRadius();
sg.creation = boost::str(
boost::format(
"Part.ArcOfEllipse(Part.Ellipse(App.Vector(%f, %f, %f), App.Vector(%f, "
"%f, %f), App.Vector(%f, %f, %f)), %f, %f)")
% periapsis.x % periapsis.y % periapsis.z % positiveB.x % positiveB.y
% positiveB.z % center.x % center.y % center.z % aoe->getFirstParameter()
% aoe->getLastParameter());
sg.construction = Sketcher::GeometryFacade::getConstruction(geo);
return sg;
}},
{Part::GeomArcOfHyperbola::getClassTypeId(),
[](const Part::Geometry* geo) {
auto aoh = static_cast<const Part::GeomArcOfHyperbola*>(geo);
SingleGeometry sg;
auto center = aoh->getCenter();
auto majAxisPoint = center + aoh->getMajorAxisDir() * aoh->getMajorRadius();
auto minAxisPoint = center + aoh->getMinorAxisDir() * aoh->getMinorRadius();
sg.creation = boost::str(
boost::format("Part.ArcOfHyperbola(Part.Hyperbola(App.Vector(%f, %f, %f), "
"App.Vector(%f, %f, %f), App.Vector(%f, %f, %f)), %f, %f)")
% majAxisPoint.x % majAxisPoint.y % majAxisPoint.z % minAxisPoint.x
% minAxisPoint.y % minAxisPoint.z % center.x % center.y % center.z
% aoh->getFirstParameter() % aoh->getLastParameter());
sg.construction = Sketcher::GeometryFacade::getConstruction(geo);
return sg;
}},
{Part::GeomArcOfParabola::getClassTypeId(),
[](const Part::Geometry* geo) {
auto aop = static_cast<const Part::GeomArcOfParabola*>(geo);
SingleGeometry sg;
auto focus = aop->getFocus();
auto axisPoint = aop->getCenter();
sg.creation = boost::str(
boost::format("Part.ArcOfParabola(Part.Parabola(App.Vector(%f, %f, %f), "
"App.Vector(%f, %f, %f), App.Vector(0, 0, 1)), %f, %f)")
% focus.x % focus.y % focus.z % axisPoint.x % axisPoint.y % axisPoint.z
% aop->getFirstParameter() % aop->getLastParameter());
sg.construction = Sketcher::GeometryFacade::getConstruction(geo);
return sg;
}},
{Part::GeomBSplineCurve::getClassTypeId(),
[](const Part::Geometry* geo) {
auto bSpline = static_cast<const Part::GeomBSplineCurve*>(geo);
std::stringstream stream;
std::vector<Base::Vector3d> poles = bSpline->getPoles();
for (auto& pole : poles) {
stream << "App.Vector(" << pole.x << "," << pole.y << "),";
}
std::string controlpoints = stream.str();
// remove last comma and add brackets
int index = controlpoints.rfind(',');
controlpoints.resize(index);
controlpoints.insert(0, 1, '[');
controlpoints.append(1, ']');
SingleGeometry sg;
sg.creation =
boost::str(boost::format("Part.BSplineCurve (%s,None,None,%s,%d,None,False)")
% controlpoints.c_str() % (bSpline->isPeriodic() ? "True" : "False")
% bSpline->getDegree());
sg.construction = Sketcher::GeometryFacade::getConstruction(geo);
return sg;
}},
{Part::GeomCircle::getClassTypeId(),
[](const Part::Geometry* geo) {
auto circle = static_cast<const Part::GeomCircle*>(geo);
@@ -336,21 +433,26 @@ std::string PythonConverter::process(const Sketcher::Constraint* constraint)
}},
{Sketcher::InternalAlignment,
[](const Sketcher::Constraint* constr) {
if (constr->InternalAlignmentIndex == EllipseMajorDiameter
|| constr->InternalAlignmentIndex == EllipseMinorDiameter) {
if (constr->AlignmentType == EllipseMajorDiameter
|| constr->AlignmentType == EllipseMinorDiameter
|| constr->AlignmentType == HyperbolaMajor
|| constr->AlignmentType == HyperbolaMinor
|| constr->AlignmentType == ParabolaFocalAxis) {
return boost::str(
boost::format("Sketcher.Constraint('InternalAlignment:%s', %i, %i)")
% constr->internalAlignmentTypeToString() % constr->First
% constr->Second);
}
else if (constr->InternalAlignmentIndex == EllipseFocus1
|| constr->InternalAlignmentIndex == EllipseFocus2) {
else if (constr->AlignmentType == EllipseFocus1
|| constr->AlignmentType == EllipseFocus2
|| constr->AlignmentType == HyperbolaFocus
|| constr->AlignmentType == ParabolaFocus) {
return boost::str(
boost::format("Sketcher.Constraint('InternalAlignment:%s', %i, %i, %i)")
% constr->internalAlignmentTypeToString() % constr->First
% static_cast<int>(constr->FirstPos) % constr->Second);
}
else if (constr->InternalAlignmentIndex == BSplineControlPoint) {
else if (constr->AlignmentType == BSplineControlPoint) {
return boost::str(
boost::format(
"Sketcher.Constraint('InternalAlignment:%s', %i, %i, %i, %i)")
@@ -358,6 +460,12 @@ std::string PythonConverter::process(const Sketcher::Constraint* constraint)
% static_cast<int>(constr->FirstPos) % constr->Second
% constr->InternalAlignmentIndex);
}
else if (constr->AlignmentType == BSplineKnotPoint) {
return boost::str(
boost::format("Sketcher.Constraint('InternalAlignment:%s', %i, 1, %i, %i)")
% constr->internalAlignmentTypeToString() % constr->First % constr->Second
% constr->InternalAlignmentIndex);
}
THROWM(Base::ValueError,
"PythonConverter: Constraint Alignment Type not supported")

View File

@@ -43,7 +43,6 @@ class Constraint;
class SketcherExport PythonConverter
{
class SingleGeometry
{
public:
@@ -52,14 +51,22 @@ class SketcherExport PythonConverter
};
public:
enum class Mode
{
CreateInternalGeometry,
OmitInternalGeometry
};
explicit PythonConverter() = delete;
~PythonConverter() = delete;
/// Convert a geometry into the string representing the command creating it
static std::string convert(const Part::Geometry* geo);
static std::string convert(const Part::Geometry* geo, Mode mode = Mode::CreateInternalGeometry);
/// Convert a vector of geometries into the string representing the command creating them
static std::string convert(const std::string& doc, const std::vector<Part::Geometry*>& geos);
static std::string convert(const std::string& doc,
const std::vector<Part::Geometry*>& geos,
Mode mode = Mode::CreateInternalGeometry);
static std::string convert(const Sketcher::Constraint* constraint);

View File

@@ -1110,11 +1110,12 @@ protected:
void commandAddShapeGeometryAndConstraints()
{
auto shapeGeometry = toPointerVector(ShapeGeometry);
Gui::Command::doCommand(
Gui::Command::Doc,
Sketcher::PythonConverter::convert(Gui::Command::getObjectCmd(sketchgui->getObject()),
shapeGeometry)
.c_str());
Gui::Command::doCommand(Gui::Command::Doc,
Sketcher::PythonConverter::convert(
Gui::Command::getObjectCmd(sketchgui->getObject()),
shapeGeometry,
Sketcher::PythonConverter::Mode::OmitInternalGeometry)
.c_str());
auto shapeConstraints = toPointerVector(ShapeConstraints);
Gui::Command::doCommand(