685 lines
33 KiB
C++
685 lines
33 KiB
C++
/***************************************************************************
|
|
* Copyright (c) 2022 Abdullah Tahiri <abdullah.tahiri.yo@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 <boost/algorithm/string/regex.hpp>
|
|
#include <boost/format.hpp>
|
|
#endif // #ifndef _PreComp_
|
|
|
|
#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, Mode mode)
|
|
{
|
|
// "addGeometry(Part.LineSegment(App.Vector(%f,%f,0),App.Vector(%f,%f,0)),%s)"
|
|
|
|
std::string command;
|
|
auto sg = process(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;
|
|
}
|
|
|
|
std::string PythonConverter::convert(const Sketcher::Constraint* constraint, GeoIdMode geoIdMode)
|
|
{
|
|
// addConstraint(Sketcher.Constraint('Distance',%d,%f))
|
|
std::string command;
|
|
auto cg = process(constraint, geoIdMode);
|
|
|
|
command = boost::str(boost::format("addConstraint(%s)\n") % cg);
|
|
|
|
return command;
|
|
}
|
|
|
|
std::string PythonConverter::convert(const std::string& doc,
|
|
const std::vector<Part::Geometry*>& geos,
|
|
Mode mode)
|
|
{
|
|
if (geos.empty()) {
|
|
return std::string();
|
|
}
|
|
|
|
// Generates a list for consecutive geometries of construction type, or of normal type
|
|
auto printGeoList = [&doc](const std::string& geolist, int ngeos, bool construction) {
|
|
std::string command;
|
|
|
|
if (ngeos > 0) {
|
|
if (construction) {
|
|
command = boost::str(
|
|
boost::format("constrGeoList = []\n%s%s.addGeometry(constrGeoList,%s)\n"
|
|
"del constrGeoList\n")
|
|
% geolist % doc % "True");
|
|
}
|
|
else {
|
|
command = boost::str(
|
|
boost::format("geoList = []\n%s%s.addGeometry(geoList,%s)\ndel geoList\n")
|
|
% geolist % doc % "False");
|
|
}
|
|
}
|
|
|
|
return 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,
|
|
&printGeoList](const std::string& geolist, int ngeos, bool construction) {
|
|
auto newcommand = printGeoList(geolist, ngeos, construction);
|
|
|
|
if (command.empty()) {
|
|
command = std::move(newcommand);
|
|
}
|
|
else {
|
|
command += "\n";
|
|
command += newcommand;
|
|
}
|
|
};
|
|
|
|
std::string geolist;
|
|
int ngeos = 0;
|
|
bool currentconstruction = Sketcher::GeometryFacade::getConstruction(geos[0]);
|
|
|
|
for (auto geo : geos) {
|
|
auto sg = process(geo);
|
|
|
|
if (sg.construction != currentconstruction) {
|
|
// if it switches from construction to normal or vice versa, flush elements so far in
|
|
// order to keep order of creation
|
|
addToCommands(geolist, ngeos, currentconstruction);
|
|
|
|
geolist.clear();
|
|
ngeos = 0;
|
|
currentconstruction = sg.construction;
|
|
}
|
|
|
|
if (sg.construction) {
|
|
geolist =
|
|
boost::str(boost::format("%sconstrGeoList.append(%s)\n") % geolist % sg.creation);
|
|
}
|
|
else {
|
|
geolist = boost::str(boost::format("%sgeoList.append(%s)\n") % geolist % sg.creation);
|
|
}
|
|
|
|
ngeos++;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
std::string PythonConverter::convert(const std::string& doc,
|
|
const std::vector<Sketcher::Constraint*>& constraints,
|
|
GeoIdMode geoIdMode)
|
|
{
|
|
if (constraints.size() == 1) {
|
|
auto cg = convert(constraints[0], geoIdMode);
|
|
|
|
return boost::str(boost::format("%s.%s\n") % doc % cg);
|
|
}
|
|
|
|
std::string constraintlist = "constraintList = []";
|
|
|
|
for (auto constraint : constraints) {
|
|
auto cg = process(constraint, geoIdMode);
|
|
|
|
constraintlist =
|
|
boost::str(boost::format("%s\nconstraintList.append(%s)") % constraintlist % cg);
|
|
}
|
|
|
|
if (!constraints.empty()) {
|
|
constraintlist =
|
|
boost::str(boost::format("%s\n%s.addConstraint(constraintList)\ndel constraintList\n")
|
|
% constraintlist % doc);
|
|
}
|
|
|
|
return constraintlist;
|
|
}
|
|
|
|
PythonConverter::SingleGeometry PythonConverter::process(const Part::Geometry* geo)
|
|
{
|
|
static std::map<const Base::Type, std::function<SingleGeometry(const Part::Geometry* geo)>>
|
|
converterMap = {
|
|
{Part::GeomLineSegment::getClassTypeId(),
|
|
[](const Part::Geometry* geo) {
|
|
auto sgeo = static_cast<const Part::GeomLineSegment*>(geo);
|
|
SingleGeometry sg;
|
|
sg.creation = boost::str(
|
|
boost::format(
|
|
"Part.LineSegment(App.Vector(%f, %f, %f),App.Vector(%f, %f, %f))")
|
|
% sgeo->getStartPoint().x % sgeo->getStartPoint().y % sgeo->getStartPoint().z
|
|
% sgeo->getEndPoint().x % sgeo->getEndPoint().y % sgeo->getEndPoint().z);
|
|
sg.construction = Sketcher::GeometryFacade::getConstruction(geo);
|
|
return sg;
|
|
}},
|
|
{Part::GeomArcOfCircle::getClassTypeId(),
|
|
[](const Part::Geometry* geo) {
|
|
auto arc = static_cast<const Part::GeomArcOfCircle*>(geo);
|
|
SingleGeometry sg;
|
|
sg.creation =
|
|
boost::str(boost::format("Part.ArcOfCircle(Part.Circle(App.Vector(%f, %f, "
|
|
"%f), App.Vector(%f, %f, %f), %f), %f, %f)")
|
|
% arc->getCenter().x % arc->getCenter().y % arc->getCenter().z
|
|
% arc->getAxisDirection().x % arc->getAxisDirection().y
|
|
% arc->getAxisDirection().z % arc->getRadius()
|
|
% arc->getFirstParameter() % arc->getLastParameter());
|
|
sg.construction = Sketcher::GeometryFacade::getConstruction(geo);
|
|
return sg;
|
|
}},
|
|
{Part::GeomPoint::getClassTypeId(),
|
|
[](const Part::Geometry* geo) {
|
|
auto sgeo = static_cast<const Part::GeomPoint*>(geo);
|
|
SingleGeometry sg;
|
|
sg.creation =
|
|
boost::str(boost::format("Part.Point(App.Vector(%f, %f, %f))")
|
|
% sgeo->getPoint().x % sgeo->getPoint().y % sgeo->getPoint().z);
|
|
sg.construction = Sketcher::GeometryFacade::getConstruction(geo);
|
|
return sg;
|
|
}},
|
|
{Part::GeomEllipse::getClassTypeId(),
|
|
[](const Part::Geometry* geo) {
|
|
auto ellipse = static_cast<const Part::GeomEllipse*>(geo);
|
|
SingleGeometry sg;
|
|
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))")
|
|
% periapsis.x % periapsis.y % periapsis.z % positiveB.x
|
|
% positiveB.y % positiveB.z % center.x % center.y % center.z);
|
|
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);
|
|
SingleGeometry sg;
|
|
sg.creation = boost::str(
|
|
boost::format(
|
|
"Part.Circle(App.Vector(%f, %f, %f), App.Vector(%f, %f, %f), %f)")
|
|
% circle->getCenter().x % circle->getCenter().y % circle->getCenter().z
|
|
% circle->getAxisDirection().x % circle->getAxisDirection().y
|
|
% circle->getAxisDirection().z % circle->getRadius());
|
|
sg.construction = Sketcher::GeometryFacade::getConstruction(geo);
|
|
return sg;
|
|
}},
|
|
};
|
|
|
|
auto result = converterMap.find(geo->getTypeId());
|
|
|
|
if (result == converterMap.end()) {
|
|
THROWM(Base::ValueError, "PythonConverter: Geometry Type not supported")
|
|
}
|
|
|
|
auto creator = result->second;
|
|
|
|
return creator(geo);
|
|
}
|
|
|
|
std::string PythonConverter::process(const Sketcher::Constraint* constraint, GeoIdMode geoIdMode)
|
|
{
|
|
bool addLastIdVar = geoIdMode == GeoIdMode::AddLastGeoIdToGeoIds;
|
|
bool addLastIdVar1 = constraint->First >= 0 && addLastIdVar;
|
|
bool addLastIdVar2 = constraint->Second >= 0 && addLastIdVar;
|
|
bool addLastIdVar3 = constraint->Third >= 0 && addLastIdVar;
|
|
|
|
std::string geoId1 = (addLastIdVar1 ? "lastGeoId + " : "") + std::to_string(constraint->First);
|
|
std::string geoId2 = (addLastIdVar2 ? "lastGeoId + " : "") + std::to_string(constraint->Second);
|
|
std::string geoId3 = (addLastIdVar3 ? "lastGeoId + " : "") + std::to_string(constraint->Third);
|
|
|
|
static std::map<
|
|
const Sketcher::ConstraintType,
|
|
std::function<
|
|
std::string(const Sketcher::Constraint*, std::string&, std::string&, std::string&)>>
|
|
converterMap = {
|
|
{Sketcher::Coincident,
|
|
[](const Sketcher::Constraint* constr,
|
|
std::string& geoId1,
|
|
std::string& geoId2,
|
|
[[maybe_unused]] std::string& geoId3) {
|
|
return boost::str(
|
|
boost::format("Sketcher.Constraint('Coincident', %s, %i, %s, %i)") % geoId1
|
|
% static_cast<int>(constr->FirstPos) % geoId2
|
|
% static_cast<int>(constr->SecondPos));
|
|
}},
|
|
{Sketcher::Horizontal,
|
|
[](const Sketcher::Constraint* constr,
|
|
std::string& geoId1,
|
|
std::string& geoId2,
|
|
[[maybe_unused]] std::string& geoId3) {
|
|
if (constr->Second == GeoEnum::GeoUndef) {
|
|
return boost::str(boost::format("Sketcher.Constraint('Horizontal', %s)")
|
|
% geoId1);
|
|
}
|
|
else {
|
|
return boost::str(
|
|
boost::format("Sketcher.Constraint('Horizontal', %s, %i, %s, %i)") % geoId1
|
|
% static_cast<int>(constr->FirstPos) % geoId2
|
|
% static_cast<int>(constr->SecondPos));
|
|
}
|
|
}},
|
|
{Sketcher::Vertical,
|
|
[](const Sketcher::Constraint* constr,
|
|
std::string& geoId1,
|
|
std::string& geoId2,
|
|
[[maybe_unused]] std::string& geoId3) {
|
|
if (constr->Second == GeoEnum::GeoUndef) {
|
|
return boost::str(boost::format("Sketcher.Constraint('Vertical', %s)")
|
|
% geoId1);
|
|
}
|
|
else {
|
|
return boost::str(
|
|
boost::format("Sketcher.Constraint('Vertical', %s, %i, %s, %i)") % geoId1
|
|
% static_cast<int>(constr->FirstPos) % geoId2
|
|
% static_cast<int>(constr->SecondPos));
|
|
}
|
|
}},
|
|
{Sketcher::Block,
|
|
[]([[maybe_unused]] const Sketcher::Constraint* constr,
|
|
std::string& geoId1,
|
|
[[maybe_unused]] std::string& geoId2,
|
|
[[maybe_unused]] std::string& geoId3) {
|
|
return boost::str(boost::format("Sketcher.Constraint('Block', %s)") % geoId1);
|
|
}},
|
|
{Sketcher::Tangent,
|
|
[](const Sketcher::Constraint* constr,
|
|
std::string& geoId1,
|
|
std::string& geoId2,
|
|
[[maybe_unused]] std::string& geoId3) {
|
|
if (constr->FirstPos == Sketcher::PointPos::none) {
|
|
return boost::str(boost::format("Sketcher.Constraint('Tangent', %s, %s)")
|
|
% geoId1 % geoId2);
|
|
}
|
|
else if (constr->SecondPos == Sketcher::PointPos::none) {
|
|
return boost::str(boost::format("Sketcher.Constraint('Tangent', %s, %i, %s)")
|
|
% geoId1 % static_cast<int>(constr->FirstPos) % geoId2);
|
|
}
|
|
else {
|
|
return boost::str(
|
|
boost::format("Sketcher.Constraint('Tangent', %s, %i, %s, %i)") % geoId1
|
|
% static_cast<int>(constr->FirstPos) % geoId2
|
|
% static_cast<int>(constr->SecondPos));
|
|
}
|
|
}},
|
|
{Sketcher::Parallel,
|
|
[]([[maybe_unused]] const Sketcher::Constraint* constr,
|
|
std::string& geoId1,
|
|
std::string& geoId2,
|
|
[[maybe_unused]] std::string& geoId3) {
|
|
return boost::str(boost::format("Sketcher.Constraint('Parallel', %s, %s)") % geoId1
|
|
% geoId2);
|
|
}},
|
|
{Sketcher::Perpendicular,
|
|
[]([[maybe_unused]] const Sketcher::Constraint* constr,
|
|
std::string& geoId1,
|
|
std::string& geoId2,
|
|
[[maybe_unused]] std::string& geoId3) {
|
|
if (constr->FirstPos == Sketcher::PointPos::none) {
|
|
return boost::str(boost::format("Sketcher.Constraint('Perpendicular', %s, %s)")
|
|
% geoId1 % geoId2);
|
|
}
|
|
else if (constr->SecondPos == Sketcher::PointPos::none) {
|
|
return boost::str(
|
|
boost::format("Sketcher.Constraint('Perpendicular', %s, %i, %s)") % geoId1
|
|
% static_cast<int>(constr->FirstPos) % geoId2);
|
|
}
|
|
else {
|
|
return boost::str(
|
|
boost::format("Sketcher.Constraint('Perpendicular', %s, %i, %s, %i)")
|
|
% geoId1 % static_cast<int>(constr->FirstPos) % geoId2
|
|
% static_cast<int>(constr->SecondPos));
|
|
}
|
|
}},
|
|
{Sketcher::Equal,
|
|
[]([[maybe_unused]] const Sketcher::Constraint* constr,
|
|
std::string& geoId1,
|
|
std::string& geoId2,
|
|
[[maybe_unused]] std::string& geoId3) {
|
|
return boost::str(boost::format("Sketcher.Constraint('Equal', %s, %s)") % geoId1
|
|
% geoId2);
|
|
}},
|
|
{Sketcher::InternalAlignment,
|
|
[](const Sketcher::Constraint* constr,
|
|
std::string& geoId1,
|
|
std::string& geoId2,
|
|
[[maybe_unused]] std::string& geoId3) {
|
|
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', %s, %s)")
|
|
% constr->internalAlignmentTypeToString() % geoId1 % geoId2);
|
|
}
|
|
else if (constr->AlignmentType == EllipseFocus1
|
|
|| constr->AlignmentType == EllipseFocus2
|
|
|| constr->AlignmentType == HyperbolaFocus
|
|
|| constr->AlignmentType == ParabolaFocus) {
|
|
return boost::str(
|
|
boost::format("Sketcher.Constraint('InternalAlignment:%s', %s, %i, %s)")
|
|
% constr->internalAlignmentTypeToString() % geoId1
|
|
% static_cast<int>(constr->FirstPos) % geoId2);
|
|
}
|
|
else if (constr->AlignmentType == BSplineControlPoint) {
|
|
return boost::str(
|
|
boost::format(
|
|
"Sketcher.Constraint('InternalAlignment:%s', %s, %i, %s, %i)")
|
|
% constr->internalAlignmentTypeToString() % geoId1
|
|
% static_cast<int>(constr->FirstPos) % geoId2
|
|
% constr->InternalAlignmentIndex);
|
|
}
|
|
else if (constr->AlignmentType == BSplineKnotPoint) {
|
|
return boost::str(
|
|
boost::format("Sketcher.Constraint('InternalAlignment:%s', %s, 1, %s, %i)")
|
|
% constr->internalAlignmentTypeToString() % geoId1 % geoId2
|
|
% constr->InternalAlignmentIndex);
|
|
}
|
|
|
|
THROWM(Base::ValueError,
|
|
"PythonConverter: Constraint Alignment Type not supported")
|
|
}},
|
|
{Sketcher::Distance,
|
|
[](const Sketcher::Constraint* constr,
|
|
std::string& geoId1,
|
|
std::string& geoId2,
|
|
[[maybe_unused]] std::string& geoId3) {
|
|
if (constr->Second == GeoEnum::GeoUndef) {
|
|
return boost::str(boost::format("Sketcher.Constraint('Distance', %s, %f)")
|
|
% geoId1 % constr->getValue());
|
|
}
|
|
else if (constr->FirstPos == Sketcher::PointPos::none) {
|
|
return boost::str(boost::format("Sketcher.Constraint('Distance', %s, %s, %f)")
|
|
% geoId1 % geoId2 % constr->getValue());
|
|
}
|
|
else if (constr->SecondPos == Sketcher::PointPos::none) {
|
|
return boost::str(
|
|
boost::format("Sketcher.Constraint('Distance', %s, %i, %s, %f)") % geoId1
|
|
% static_cast<int>(constr->FirstPos) % geoId2 % constr->getValue());
|
|
}
|
|
else {
|
|
return boost::str(
|
|
boost::format("Sketcher.Constraint('Distance', %s, %i, %s, %i, %f)")
|
|
% geoId1 % static_cast<int>(constr->FirstPos) % geoId2
|
|
% static_cast<int>(constr->SecondPos) % constr->getValue());
|
|
}
|
|
}},
|
|
{Sketcher::Angle,
|
|
[](const Sketcher::Constraint* constr,
|
|
std::string& geoId1,
|
|
std::string& geoId2,
|
|
std::string& geoId3) {
|
|
if (constr->Second == GeoEnum::GeoUndef) {
|
|
return boost::str(boost::format("Sketcher.Constraint('Angle', %s, %f)")
|
|
% geoId1 % constr->getValue());
|
|
}
|
|
else if (constr->Third == GeoEnum::GeoUndef) {
|
|
if (constr->SecondPos == Sketcher::PointPos::none) {
|
|
return boost::str(boost::format("Sketcher.Constraint('Angle', %s, %s, %f)")
|
|
% geoId1 % geoId2 % constr->getValue());
|
|
}
|
|
else {
|
|
return boost::str(
|
|
boost::format("Sketcher.Constraint('Angle', %s, %i, %s, %i, %f)")
|
|
% geoId1 % static_cast<int>(constr->FirstPos) % geoId2
|
|
% static_cast<int>(constr->SecondPos) % constr->getValue());
|
|
}
|
|
}
|
|
else {
|
|
return boost::str(
|
|
boost::format("Sketcher.Constraint('AngleViaPoint', %s, %s, %s, %i, %f)")
|
|
% geoId1 % geoId2 % geoId3 % static_cast<int>(constr->ThirdPos)
|
|
% constr->getValue());
|
|
}
|
|
}},
|
|
{Sketcher::DistanceX,
|
|
[](const Sketcher::Constraint* constr,
|
|
std::string& geoId1,
|
|
std::string& geoId2,
|
|
[[maybe_unused]] std::string& geoId3) {
|
|
if (constr->Second == GeoEnum::GeoUndef) {
|
|
return boost::str(boost::format("Sketcher.Constraint('DistanceX', %s, %f)")
|
|
% geoId1 % constr->getValue());
|
|
}
|
|
else if (constr->SecondPos == Sketcher::PointPos::none) {
|
|
return boost::str(boost::format("Sketcher.Constraint('DistanceX', %s, %i, %f)")
|
|
% geoId1 % static_cast<int>(constr->FirstPos)
|
|
% constr->getValue());
|
|
}
|
|
else {
|
|
return boost::str(
|
|
boost::format("Sketcher.Constraint('DistanceX', %s, %i, %s, %i, %f)")
|
|
% geoId1 % static_cast<int>(constr->FirstPos) % geoId2
|
|
% static_cast<int>(constr->SecondPos) % constr->getValue());
|
|
}
|
|
}},
|
|
{Sketcher::DistanceY,
|
|
[](const Sketcher::Constraint* constr,
|
|
std::string& geoId1,
|
|
std::string& geoId2,
|
|
[[maybe_unused]] std::string& geoId3) {
|
|
if (constr->Second == GeoEnum::GeoUndef) {
|
|
return boost::str(boost::format("Sketcher.Constraint('DistanceY', %s, %f)")
|
|
% geoId1 % constr->getValue());
|
|
}
|
|
else if (constr->SecondPos == Sketcher::PointPos::none) {
|
|
return boost::str(boost::format("Sketcher.Constraint('DistanceY', %s, %i, %f)")
|
|
% geoId1 % static_cast<int>(constr->FirstPos)
|
|
% constr->getValue());
|
|
}
|
|
else {
|
|
return boost::str(
|
|
boost::format("Sketcher.Constraint('DistanceY', %s, %i, %s, %i, %f)")
|
|
% geoId1 % static_cast<int>(constr->FirstPos) % geoId2
|
|
% static_cast<int>(constr->SecondPos) % constr->getValue());
|
|
}
|
|
}},
|
|
{Sketcher::Radius,
|
|
[](const Sketcher::Constraint* constr,
|
|
std::string& geoId1,
|
|
[[maybe_unused]] std::string& geoId2,
|
|
[[maybe_unused]] std::string& geoId3) {
|
|
return boost::str(boost::format("Sketcher.Constraint('Radius', %s, %f)") % geoId1
|
|
% constr->getValue());
|
|
}},
|
|
{Sketcher::Diameter,
|
|
[](const Sketcher::Constraint* constr,
|
|
std::string& geoId1,
|
|
[[maybe_unused]] std::string& geoId2,
|
|
[[maybe_unused]] std::string& geoId3) {
|
|
return boost::str(boost::format("Sketcher.Constraint('Diameter', %s, %f)") % geoId1
|
|
% constr->getValue());
|
|
}},
|
|
{Sketcher::Weight,
|
|
[](const Sketcher::Constraint* constr,
|
|
std::string& geoId1,
|
|
[[maybe_unused]] std::string& geoId2,
|
|
[[maybe_unused]] std::string& geoId3) {
|
|
return boost::str(boost::format("Sketcher.Constraint('Weight', %s, %f)") % geoId1
|
|
% constr->getValue());
|
|
}},
|
|
{Sketcher::PointOnObject,
|
|
[](const Sketcher::Constraint* constr,
|
|
std::string& geoId1,
|
|
std::string& geoId2,
|
|
[[maybe_unused]] std::string& geoId3) {
|
|
return boost::str(boost::format("Sketcher.Constraint('PointOnObject', %s, %i, %s)")
|
|
% geoId1 % static_cast<int>(constr->FirstPos) % geoId2);
|
|
}},
|
|
{Sketcher::Symmetric,
|
|
[](const Sketcher::Constraint* constr,
|
|
std::string& geoId1,
|
|
std::string& geoId2,
|
|
std::string& geoId3) {
|
|
if (constr->ThirdPos == Sketcher::PointPos::none) {
|
|
return boost::str(
|
|
boost::format("Sketcher.Constraint('Symmetric', %s, %i, %s, %i, %s)")
|
|
% geoId1 % static_cast<int>(constr->FirstPos) % geoId2
|
|
% static_cast<int>(constr->SecondPos) % geoId3);
|
|
}
|
|
else {
|
|
return boost::str(
|
|
boost::format("Sketcher.Constraint('Symmetric', %s, %i, %s, %i, %s, %i)")
|
|
% geoId1 % static_cast<int>(constr->FirstPos) % geoId2
|
|
% static_cast<int>(constr->SecondPos) % geoId3
|
|
% static_cast<int>(constr->ThirdPos));
|
|
}
|
|
}},
|
|
{Sketcher::SnellsLaw,
|
|
[](const Sketcher::Constraint* constr,
|
|
std::string& geoId1,
|
|
std::string& geoId2,
|
|
std::string& geoId3) {
|
|
return boost::str(
|
|
boost::format("Sketcher.Constraint('SnellsLaw', %s, %i, %s, %i, %s, %f)")
|
|
% geoId1 % static_cast<int>(constr->FirstPos) % geoId2
|
|
% static_cast<int>(constr->SecondPos) % geoId3 % constr->getValue());
|
|
}},
|
|
};
|
|
|
|
auto result = converterMap.find(constraint->Type);
|
|
|
|
if (result == converterMap.end()) {
|
|
THROWM(Base::ValueError, "PythonConverter: Constraint Type not supported")
|
|
}
|
|
|
|
auto creator = result->second;
|
|
|
|
return creator(constraint, geoId1, geoId2, geoId3);
|
|
}
|
|
|
|
std::vector<std::string> PythonConverter::multiLine(std::string&& singlestring)
|
|
{
|
|
std::vector<std::string> tokens;
|
|
split_regex(tokens, singlestring, boost::regex("(\n)+"));
|
|
return tokens;
|
|
}
|