/*************************************************************************** * Copyright (c) 2022 Abdullah Tahiri * * * * 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 #endif // #ifndef _PreComp_ #include #include #include #include #include "PythonConverter.h" using namespace Sketcher; std::string PythonConverter::convert(const Part::Geometry * geo) { // "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")); return command; } std::string PythonConverter::convert(const Sketcher::Constraint * constraint) { // addConstraint(Sketcher.Constraint('Distance',%d,%f)) std::string command; auto cg = process(constraint); command = boost::str(boost::format("addConstraint(%s)\n") % cg); return command; } std::string PythonConverter::convert(const std::string & doc, const std::vector & geos) { std::string geolist = "geoList = []\n"; std::string constrgeolist = "constrGeoList = []\n"; int ngeo = 0, nconstr = 0; for(auto geo : geos) { auto sg = process(geo); if (sg.construction) { constrgeolist = boost::str(boost::format("%s\nconstrGeoList.append(%s)\n") % constrgeolist % sg.creation); nconstr++; } else { geolist = boost::str(boost::format("%s\ngeoList.append(%s)\n") % geolist % sg.creation); ngeo++; } } if(ngeo > 0) { geolist = boost::str(boost::format("%s\n%s.addGeometry(geoList,%s)\ndel geoList\n") % geolist % doc % "False"); } if(nconstr > 0) { constrgeolist = boost::str(boost::format("%s\n%s.addGeometry(constrGeoList,%s)\ndel constrGeoList") % constrgeolist % doc % "True"); } std::string command; if(ngeo > 0 && nconstr > 0) command = geolist + constrgeolist; else if (ngeo > 0) command = std::move(geolist); else if (nconstr > 0) command = std::move(constrgeolist); return command; } std::string PythonConverter::convert(const std::string & doc, const std::vector & constraints) { if(constraints.size() == 1) { auto cg = convert(constraints[0]); return boost::str(boost::format("%s.%s\n") % doc % cg); } std::string constraintlist = "constraintList = []"; for(auto constraint : constraints) { auto cg = process(constraint); 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> converterMap = { { Part::GeomLineSegment::getClassTypeId(), [](const Part::Geometry * geo){ auto sgeo = static_cast(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(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(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(geo); SingleGeometry sg; auto periapsis = ellipse->getCenter() + ellipse->getMajorAxisDir() * ellipse->getMajorRadius(); auto positiveB = ellipse->getCenter() + ellipse->getMinorAxisDir() * ellipse->getMinorRadius(); auto center = ellipse->getCenter(); 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::GeomCircle::getClassTypeId(), [](const Part::Geometry * geo){ auto circle = static_cast(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) { static std::map> converterMap = { { Sketcher::Coincident, [](const Sketcher::Constraint * constr){ return boost::str(boost::format("Sketcher.Constraint('Coincident', %i, %i, %i, %i)") % constr->First % static_cast(constr->FirstPos) % constr->Second % static_cast(constr->SecondPos)); }}, { Sketcher::Horizontal, [](const Sketcher::Constraint * constr){ if(constr->Second == GeoEnum::GeoUndef) { return boost::str(boost::format("Sketcher.Constraint('Horizontal', %i)") % constr->First); } else { return boost::str(boost::format("Sketcher.Constraint('Horizontal', %i, %i, %i, %i)") % constr->First % static_cast(constr->FirstPos) % constr->Second % static_cast(constr->SecondPos)); } }}, { Sketcher::Vertical, [](const Sketcher::Constraint * constr){ if(constr->Second == GeoEnum::GeoUndef) { return boost::str(boost::format("Sketcher.Constraint('Vertical', %i)") % constr->First); } else { return boost::str(boost::format("Sketcher.Constraint('Vertical', %i, %i, %i, %i)") % constr->First % static_cast(constr->FirstPos) % constr->Second % static_cast(constr->SecondPos)); } }}, { Sketcher::Block, [](const Sketcher::Constraint * constr){ return boost::str(boost::format("Sketcher.Constraint('Block', %i)") % constr->First); }}, { Sketcher::Tangent, [](const Sketcher::Constraint * constr){ if(constr->FirstPos == Sketcher::PointPos::none) { return boost::str(boost::format("Sketcher.Constraint('Tangent', %i, %i)") % constr->First % constr->Second); } else if(constr->SecondPos == Sketcher::PointPos::none){ return boost::str(boost::format("Sketcher.Constraint('Tangent', %i, %i, %i)") % constr->First % static_cast(constr->FirstPos) % constr->Second); } else { return boost::str(boost::format("Sketcher.Constraint('Tangent', %i, %i, %i, %i)") % constr->First % static_cast(constr->FirstPos) % constr->Second % static_cast(constr->SecondPos)); } }}, { Sketcher::Parallel, [](const Sketcher::Constraint * constr){ return boost::str(boost::format("Sketcher.Constraint('Parallel', %i, %i)") % constr->First % constr->Second); }}, { Sketcher::Perpendicular, [](const Sketcher::Constraint * constr){ if(constr->FirstPos == Sketcher::PointPos::none) { return boost::str(boost::format("Sketcher.Constraint('Perpendicular', %i, %i)") % constr->First % constr->Second); } else if(constr->SecondPos == Sketcher::PointPos::none){ return boost::str(boost::format("Sketcher.Constraint('Perpendicular', %i, %i, %i)") % constr->First % static_cast(constr->FirstPos) % constr->Second); } else { return boost::str(boost::format("Sketcher.Constraint('Perpendicular', %i, %i, %i, %i)") % constr->First % static_cast(constr->FirstPos) % constr->Second % static_cast(constr->SecondPos)); } }}, { Sketcher::Equal, [](const Sketcher::Constraint * constr){ return boost::str(boost::format("Sketcher.Constraint('Equal', %i, %i)") % constr->First % constr->Second); }}, { Sketcher::InternalAlignment, [](const Sketcher::Constraint * constr){ if(constr->InternalAlignmentIndex == EllipseMajorDiameter || constr->InternalAlignmentIndex == EllipseMinorDiameter) { 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) { return boost::str(boost::format("Sketcher.Constraint('InternalAlignment:%s', %i, %i, %i)") % constr->internalAlignmentTypeToString() % constr->First % static_cast(constr->FirstPos) % constr->Second); } else if(constr->InternalAlignmentIndex == BSplineControlPoint) { return boost::str(boost::format("Sketcher.Constraint('InternalAlignment:%s', %i, %i, %i, %i)") % constr->internalAlignmentTypeToString() % constr->First % static_cast(constr->FirstPos) % constr->Second % constr->InternalAlignmentIndex); } THROWM(Base::ValueError, "PythonConverter: Constraint Alignment Type not supported") }}, { Sketcher::Distance, [](const Sketcher::Constraint * constr){ if(constr->Second == GeoEnum::GeoUndef){ return boost::str(boost::format("Sketcher.Constraint('Distance', %i, %f)") % constr->First % constr->getValue()); } else if(constr->SecondPos == Sketcher::PointPos::none){ return boost::str(boost::format("Sketcher.Constraint('Distance', %i, %i, %i, %f)") % constr->First % static_cast(constr->FirstPos) % constr->Second % constr->getValue()); } else { return boost::str(boost::format("Sketcher.Constraint('Distance', %i, %i, %i, %i, %f)") % constr->First % static_cast(constr->FirstPos) % constr->Second % static_cast(constr->SecondPos) % constr->getValue()); } }}, { Sketcher::Angle, [](const Sketcher::Constraint * constr){ if(constr->Second == GeoEnum::GeoUndef) { return boost::str(boost::format("Sketcher.Constraint('Angle', %i, %f)") % constr->First % constr->getValue()); } else if(constr->SecondPos == Sketcher::PointPos::none){ return boost::str(boost::format("Sketcher.Constraint('Angle', %i, %i, %f)") % constr->First % constr->Second % constr->getValue()); } else { return boost::str(boost::format("Sketcher.Constraint('Angle', %i, %i, %i, %i, %f)") % constr->First % static_cast(constr->FirstPos) % constr->Second % static_cast(constr->SecondPos) % constr->getValue()); } }}, { Sketcher::DistanceX, [](const Sketcher::Constraint * constr){ if(constr->Second == GeoEnum::GeoUndef) { return boost::str(boost::format("Sketcher.Constraint('DistanceX', %i, %f)") % constr->First % constr->getValue()); } else if(constr->SecondPos == Sketcher::PointPos::none){ return boost::str(boost::format("Sketcher.Constraint('DistanceX', %i, %i, %f)") % constr->First % static_cast(constr->FirstPos) % constr->getValue()); } else { return boost::str(boost::format("Sketcher.Constraint('DistanceX', %i, %i, %i, %i, %f)") % constr->First % static_cast(constr->FirstPos) % constr->Second % static_cast(constr->SecondPos) % constr->getValue()); } }}, { Sketcher::DistanceY, [](const Sketcher::Constraint * constr){ if(constr->Second == GeoEnum::GeoUndef) { return boost::str(boost::format("Sketcher.Constraint('DistanceY', %i, %f)") % constr->First % constr->getValue()); } else if(constr->SecondPos == Sketcher::PointPos::none){ return boost::str(boost::format("Sketcher.Constraint('DistanceY', %i, %i, %f)") % constr->First % static_cast(constr->FirstPos) % constr->getValue()); } else { return boost::str(boost::format("Sketcher.Constraint('DistanceY', %i, %i, %i, %i, %f)") % constr->First % static_cast(constr->FirstPos) % constr->Second % static_cast(constr->SecondPos) % constr->getValue()); } }}, { Sketcher::Radius, [](const Sketcher::Constraint * constr){ return boost::str(boost::format("Sketcher.Constraint('Radius', %i, %f)") % constr->First % constr->getValue()); }}, { Sketcher::Diameter, [](const Sketcher::Constraint * constr){ return boost::str(boost::format("Sketcher.Constraint('Diameter', %i, %f)") % constr->First % constr->getValue()); }}, { Sketcher::Weight, [](const Sketcher::Constraint * constr){ return boost::str(boost::format("Sketcher.Constraint('Weight', %i, %f)") % constr->First % constr->getValue()); }}, { Sketcher::PointOnObject, [](const Sketcher::Constraint * constr){ return boost::str(boost::format("Sketcher.Constraint('PointOnObject', %i, %i, %i)") % constr->First % static_cast(constr->FirstPos) % constr->Second); }}, { Sketcher::Symmetric, [](const Sketcher::Constraint * constr){ if(constr->ThirdPos==Sketcher::PointPos::none) { return boost::str(boost::format("Sketcher.Constraint('Symmetric', %i, %i, %i, %i, %i)") % constr->First % static_cast(constr->FirstPos) % constr->Second % static_cast(constr->SecondPos) % constr->Third); } else { return boost::str(boost::format("Sketcher.Constraint('Symmetric', %i, %i, %i, %i, %i, %i)") % constr->First % static_cast(constr->FirstPos) % constr->Second % static_cast(constr->SecondPos) % constr->Third % static_cast(constr->ThirdPos)); } }}, { Sketcher::SnellsLaw, [](const Sketcher::Constraint * constr){ return boost::str(boost::format("Sketcher.Constraint('SnellsLaw', %i, %i, %i, %i, %i, %f)") % constr->First % static_cast(constr->FirstPos) % constr->Second % static_cast(constr->SecondPos) % constr->Third % 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); }