PythonConverter: Extend for Hyperbola/Parabola/BSpline
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user