Download src/Mod/Sketcher/App/PythonConverter.cpp from AbdulElahGwaith/FreeCAD: direct link, hf CLI and curl.
- Browser
- Download file 36.2 kB
-
https://huggingface.co/AbdulElahGwaith/FreeCAD/resolve/main/src/Mod/Sketcher/App/PythonConverter.cpp
- Command line
-
hf download hf://AbdulElahGwaith/FreeCAD/src/Mod/Sketcher/App/PythonConverter.cpp
-
curl -L -o PythonConverter.cpp https://huggingface.co/AbdulElahGwaith/FreeCAD/resolve/main/src/Mod/Sketcher/App/PythonConverter.cpp
36.2 kB
| // SPDX-License-Identifier: LGPL-2.1-or-later | |
| /*************************************************************************** | |
| * 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 * | |
| * * | |
| ***************************************************************************/ | |
| 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") | |
| ); | |
| // clang-format off: keep line breaks for readability | |
| if ((!geo->is<Part::GeomEllipse>() | |
| || !geo->is<Part::GeomArcOfEllipse>() | |
| || !geo->is<Part::GeomArcOfHyperbola>() | |
| || !geo->is<Part::GeomArcOfParabola>() | |
| || !geo->is<Part::GeomBSplineCurve>()) && mode == Mode::CreateInternalGeometry) { | |
| command += | |
| boost::str(boost::format("exposeInternalGeometry(len(ActiveSketch.Geometry))\n")); | |
| } | |
| // clang-format on | |
| 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++; | |
| // clang-format off: keep line breaks for readability | |
| if (!geo->is<Part::GeomEllipse>() | |
| || !geo->is<Part::GeomArcOfEllipse>() | |
| || !geo->is<Part::GeomArcOfHyperbola>() | |
| || !geo->is<Part::GeomArcOfParabola>() | |
| || !geo->is<Part::GeomBSplineCurve>()) { | |
| std::string newcommand = | |
| boost::str(boost::format("exposeInternalGeometry(lastGeoId + %d)\n") % (index)); | |
| command += newcommand; | |
| } | |
| // clang-format on | |
| } | |
| } | |
| 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; | |
| } | |
| template<typename T> | |
| std::string makeSplineInfoArrayString(const std::vector<T>& rInfoVec) | |
| { | |
| std::stringstream stream; | |
| if constexpr (std::is_same_v<T, Base::Vector3d>) { | |
| for (const auto& rInfo : rInfoVec) { | |
| stream << "App.Vector(" << rInfo.x << ", " << rInfo.y << "), "; | |
| } | |
| } | |
| else { | |
| for (const auto& rInfo : rInfoVec) { | |
| stream << rInfo << ", "; | |
| } | |
| } | |
| std::string res = stream.str(); | |
| // remove last comma and add brackets | |
| int index = res.rfind(','); | |
| res.resize(index); | |
| return fmt::format("[{}]", res); | |
| ; | |
| } | |
| 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); | |
| double startAngle, endAngle; | |
| arc->getRange(startAngle, endAngle, /*emulateCCWXY=*/true); | |
| 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() % startAngle % endAngle | |
| ); | |
| 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); | |
| double startAngle, endAngle; | |
| aoe->getRange(startAngle, endAngle, /*emulateCCWXY=*/true); | |
| 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 % startAngle % endAngle | |
| ); | |
| sg.construction = Sketcher::GeometryFacade::getConstruction(geo); | |
| return sg; | |
| }}, | |
| {Part::GeomArcOfHyperbola::getClassTypeId(), | |
| [](const Part::Geometry* geo) { | |
| auto aoh = static_cast<const Part::GeomArcOfHyperbola*>(geo); | |
| double startAngle, endAngle; | |
| aoh->getRange(startAngle, endAngle, /*emulateCCWXY=*/true); | |
| 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 % startAngle | |
| % endAngle | |
| ); | |
| sg.construction = Sketcher::GeometryFacade::getConstruction(geo); | |
| return sg; | |
| }}, | |
| {Part::GeomArcOfParabola::getClassTypeId(), | |
| [](const Part::Geometry* geo) { | |
| auto aop = static_cast<const Part::GeomArcOfParabola*>(geo); | |
| double startAngle, endAngle; | |
| aop->getRange(startAngle, endAngle, /*emulateCCWXY=*/true); | |
| 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 | |
| % startAngle % endAngle | |
| ); | |
| sg.construction = Sketcher::GeometryFacade::getConstruction(geo); | |
| return sg; | |
| }}, | |
| {Part::GeomBSplineCurve::getClassTypeId(), | |
| [](const Part::Geometry* geo) { | |
| auto bSpline = static_cast<const Part::GeomBSplineCurve*>(geo); | |
| std::string controlpoints = makeSplineInfoArrayString(bSpline->getPoles()); | |
| std::string mults = makeSplineInfoArrayString(bSpline->getMultiplicities()); | |
| std::string knots = makeSplineInfoArrayString(bSpline->getKnots()); | |
| std::string weights = makeSplineInfoArrayString(bSpline->getWeights()); | |
| SingleGeometry sg; | |
| sg.creation = boost::str( | |
| boost::format("Part.BSplineCurve(%s, %s, %s, %s, %d, %s, False)") | |
| % controlpoints.c_str() % mults.c_str() % knots.c_str() | |
| % (bSpline->isPeriodic() ? "True" : "False") % bSpline->getDegree() | |
| % weights.c_str() | |
| ); | |
| 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->FirstPos == Sketcher::PointPos::none | |
| && 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->FirstPos == Sketcher::PointPos::none | |
| && 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; | |
| std::string resultStr = creator(constraint, geoId1, geoId2, geoId3); | |
| if (!constraint->isActive || !constraint->isDriving) { | |
| std::string active = constraint->isActive ? "True" : "False"; | |
| resultStr += ", " + active; | |
| if (constraint->isDimensional()) { | |
| std::string driving = constraint->isDriving ? "True" : "False"; | |
| resultStr += ", " + driving; | |
| } | |
| } | |
| resultStr += ")"; | |
| return resultStr; | |
| } | |
| std::vector<std::string> PythonConverter::multiLine(std::string&& singlestring) | |
| { | |
| std::vector<std::string> tokens; | |
| split_regex(tokens, singlestring, boost::regex("(\n)+")); | |
| return tokens; | |
| } | |