Download src/Mod/Sketcher/App/SketchObjectPyImp.cpp from AbdulElahGwaith/FreeCAD: direct link, hf CLI and curl.
- Browser
- Download file 87.5 kB
-
https://huggingface.co/AbdulElahGwaith/FreeCAD/resolve/main/src/Mod/Sketcher/App/SketchObjectPyImp.cpp
- Command line
-
hf download hf://AbdulElahGwaith/FreeCAD/src/Mod/Sketcher/App/SketchObjectPyImp.cpp
-
curl -L -o SketchObjectPyImp.cpp https://huggingface.co/AbdulElahGwaith/FreeCAD/resolve/main/src/Mod/Sketcher/App/SketchObjectPyImp.cpp
87.5 kB
| // SPDX-License-Identifier: LGPL-2.1-or-later | |
| /*************************************************************************** | |
| * Copyright (c) 2010 Jürgen Riegel <juergen.riegel@web.de> * | |
| * * | |
| * 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 * | |
| * * | |
| ***************************************************************************/ | |
| // inclusion of the generated files (generated out of SketchObjectSFPy.xml) | |
| // other python types | |
| using namespace Sketcher; | |
| // returns a string which represents the object e.g. when printed in python | |
| std::string SketchObjectPy::representation() const | |
| { | |
| return "<Sketcher::SketchObject>"; | |
| } | |
| PyObject* SketchObjectPy::solve(PyObject* args) | |
| { | |
| if (!PyArg_ParseTuple(args, "")) { | |
| return nullptr; | |
| } | |
| int ret = this->getSketchObjectPtr()->solve(); | |
| return Py_BuildValue("i", ret); | |
| } | |
| PyObject* SketchObjectPy::addGeometry(PyObject* args) | |
| { | |
| PyObject* pcObj; | |
| PyObject* construction; // this is an optional argument default false | |
| bool isConstruction; | |
| if (!PyArg_ParseTuple(args, "OO!", &pcObj, &PyBool_Type, &construction)) { | |
| PyErr_Clear(); | |
| if (!PyArg_ParseTuple(args, "O", &pcObj)) { | |
| return nullptr; | |
| } | |
| else { | |
| isConstruction = false; | |
| } | |
| } | |
| else { | |
| isConstruction = Base::asBoolean(construction); | |
| } | |
| if (PyObject_TypeCheck(pcObj, &(Part::GeometryPy::Type))) { | |
| Part::Geometry* geo = static_cast<Part::GeometryPy*>(pcObj)->getGeometryPtr(); | |
| int ret; | |
| // An arc created with Part.Arc will be converted into a Part.ArcOfCircle | |
| if (geo->is<Part::GeomTrimmedCurve>()) { | |
| Handle(Geom_TrimmedCurve) trim = Handle(Geom_TrimmedCurve)::DownCast(geo->handle()); | |
| Handle(Geom_Circle) circle = Handle(Geom_Circle)::DownCast(trim->BasisCurve()); | |
| Handle(Geom_Ellipse) ellipse = Handle(Geom_Ellipse)::DownCast(trim->BasisCurve()); | |
| if (!circle.IsNull()) { | |
| // create the definition struct for that geom | |
| Part::GeomArcOfCircle aoc; | |
| aoc.setHandle(trim); | |
| ret = this->getSketchObjectPtr()->addGeometry(&aoc, isConstruction); | |
| } | |
| else if (!ellipse.IsNull()) { | |
| // create the definition struct for that geom | |
| Part::GeomArcOfEllipse aoe; | |
| aoe.setHandle(trim); | |
| ret = this->getSketchObjectPtr()->addGeometry(&aoe, isConstruction); | |
| } | |
| else { | |
| std::stringstream str; | |
| str << "Unsupported geometry type: " << geo->getTypeId().getName(); | |
| PyErr_SetString(PyExc_TypeError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| } | |
| else if (geo->is<Part::GeomPoint>() || geo->is<Part::GeomCircle>() | |
| || geo->is<Part::GeomEllipse>() || geo->is<Part::GeomArcOfCircle>() | |
| || geo->is<Part::GeomArcOfEllipse>() || geo->is<Part::GeomArcOfHyperbola>() | |
| || geo->is<Part::GeomArcOfParabola>() || geo->is<Part::GeomBSplineCurve>() | |
| || geo->is<Part::GeomLineSegment>()) { | |
| ret = this->getSketchObjectPtr()->addGeometry(geo, isConstruction); | |
| } | |
| else { | |
| std::stringstream str; | |
| str << "Unsupported geometry type: " << geo->getTypeId().getName(); | |
| PyErr_SetString(PyExc_TypeError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| return Py::new_reference_to(Py::Long(ret)); | |
| } | |
| else if (PyObject_TypeCheck(pcObj, &(PyList_Type)) || PyObject_TypeCheck(pcObj, &(PyTuple_Type))) { | |
| std::vector<Part::Geometry*> geoList; | |
| std::vector<std::shared_ptr<Part::Geometry>> tmpList; | |
| Py::Sequence list(pcObj); | |
| for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) { | |
| if (PyObject_TypeCheck((*it).ptr(), &(Part::GeometryPy::Type))) { | |
| Part::Geometry* geo = static_cast<Part::GeometryPy*>((*it).ptr())->getGeometryPtr(); | |
| // An arc created with Part.Arc will be converted into a Part.ArcOfCircle | |
| if (geo->is<Part::GeomTrimmedCurve>()) { | |
| Handle(Geom_TrimmedCurve) trim = Handle(Geom_TrimmedCurve)::DownCast(geo->handle()); | |
| Handle(Geom_Circle) circle = Handle(Geom_Circle)::DownCast(trim->BasisCurve()); | |
| Handle(Geom_Ellipse) ellipse = Handle(Geom_Ellipse)::DownCast(trim->BasisCurve()); | |
| if (!circle.IsNull()) { | |
| // create the definition struct for that geom | |
| std::shared_ptr<Part::GeomArcOfCircle> aoc(new Part::GeomArcOfCircle()); | |
| aoc->setHandle(trim); | |
| geoList.push_back(aoc.get()); | |
| tmpList.push_back(aoc); | |
| } | |
| else if (!ellipse.IsNull()) { | |
| // create the definition struct for that geom | |
| std::shared_ptr<Part::GeomArcOfEllipse> aoe(new Part::GeomArcOfEllipse()); | |
| aoe->setHandle(trim); | |
| geoList.push_back(aoe.get()); | |
| tmpList.push_back(aoe); | |
| } | |
| else { | |
| std::stringstream str; | |
| str << "Unsupported geometry type: " << geo->getTypeId().getName(); | |
| PyErr_SetString(PyExc_TypeError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| } | |
| else if (geo->is<Part::GeomPoint>() || geo->is<Part::GeomCircle>() | |
| || geo->is<Part::GeomEllipse>() || geo->is<Part::GeomArcOfCircle>() | |
| || geo->is<Part::GeomArcOfEllipse>() || geo->is<Part::GeomArcOfHyperbola>() | |
| || geo->is<Part::GeomArcOfParabola>() || geo->is<Part::GeomBSplineCurve>() | |
| || geo->is<Part::GeomLineSegment>()) { | |
| geoList.push_back(geo); | |
| } | |
| else { | |
| std::stringstream str; | |
| str << "Unsupported geometry type: " << geo->getTypeId().getName(); | |
| PyErr_SetString(PyExc_TypeError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| } | |
| } | |
| int ret = this->getSketchObjectPtr()->addGeometry(geoList, isConstruction) + 1; | |
| std::size_t numGeo = geoList.size(); | |
| Py::Tuple tuple(numGeo); | |
| for (std::size_t i = 0; i < numGeo; ++i) { | |
| int geoId = ret - int(numGeo - i); | |
| tuple.setItem(i, Py::Long(geoId)); | |
| } | |
| return Py::new_reference_to(tuple); | |
| } | |
| std::string error = std::string("type must be 'Geometry' or list of 'Geometry', not "); | |
| error += pcObj->ob_type->tp_name; | |
| throw Py::TypeError(error); | |
| } | |
| PyObject* SketchObjectPy::delGeometry(PyObject* args) | |
| { | |
| int Index; | |
| PyObject* noSolve = Py_False; | |
| if (!PyArg_ParseTuple(args, "i|O!", &Index, &PyBool_Type, &noSolve)) { | |
| return nullptr; | |
| } | |
| if (this->getSketchObjectPtr()->delGeometry( | |
| Index, | |
| Base::asBoolean(noSolve) ? DeleteOption::NoSolve : DeleteOption::UpdateGeometry | |
| )) { | |
| std::stringstream str; | |
| str << "Not able to delete a geometry with the given index: " << Index; | |
| PyErr_SetString(PyExc_ValueError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| Py_Return; | |
| } | |
| PyObject* SketchObjectPy::delGeometries(PyObject* args) | |
| { | |
| PyObject* pcObj; | |
| PyObject* noSolve = Py_False; | |
| if (!PyArg_ParseTuple(args, "O|O!", &pcObj, &PyBool_Type, &noSolve)) { | |
| return nullptr; | |
| } | |
| if (PyObject_TypeCheck(pcObj, &(PyList_Type)) || PyObject_TypeCheck(pcObj, &(PyTuple_Type))) { | |
| std::vector<int> geoIdList; | |
| Py::Sequence list(pcObj); | |
| for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) { | |
| if (PyLong_Check((*it).ptr())) { | |
| geoIdList.push_back(PyLong_AsLong((*it).ptr())); | |
| } | |
| } | |
| if (this->getSketchObjectPtr()->delGeometries( | |
| geoIdList, | |
| Base::asBoolean(noSolve) ? DeleteOption::NoSolve : DeleteOption::UpdateGeometry | |
| )) { | |
| std::stringstream str; | |
| str << "Not able to delete geometries"; | |
| PyErr_SetString(PyExc_ValueError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| Py_Return; | |
| } | |
| std::string error = std::string("type must be list of GeoIds, not "); | |
| error += pcObj->ob_type->tp_name; | |
| throw Py::TypeError(error); | |
| } | |
| PyObject* SketchObjectPy::deleteAllGeometry(PyObject* args) | |
| { | |
| PyObject* noSolve = Py_False; | |
| if (!PyArg_ParseTuple(args, "|O!", &PyBool_Type, &noSolve)) { | |
| return nullptr; | |
| } | |
| if (this->getSketchObjectPtr()->deleteAllGeometry( | |
| Base::asBoolean(noSolve) ? DeleteOption::NoSolve : DeleteOption::UpdateGeometry | |
| )) { | |
| std::stringstream str; | |
| str << "Unable to delete Geometry"; | |
| PyErr_SetString(PyExc_ValueError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| Py_Return; | |
| } | |
| PyObject* SketchObjectPy::detectDegeneratedGeometries(PyObject* args) | |
| { | |
| double tolerance {}; | |
| if (!PyArg_ParseTuple(args, "d", &tolerance)) { | |
| return nullptr; | |
| } | |
| SketchAnalysis analyse(this->getSketchObjectPtr()); | |
| int count = analyse.detectDegeneratedGeometries(tolerance); | |
| return Py::new_reference_to(Py::Long(count)); | |
| } | |
| PyObject* SketchObjectPy::removeDegeneratedGeometries(PyObject* args) | |
| { | |
| double tolerance {}; | |
| if (!PyArg_ParseTuple(args, "d", &tolerance)) { | |
| return nullptr; | |
| } | |
| SketchAnalysis analyse(this->getSketchObjectPtr()); | |
| int count = analyse.removeDegeneratedGeometries(tolerance); | |
| return Py::new_reference_to(Py::Long(count)); | |
| } | |
| PyObject* SketchObjectPy::deleteAllConstraints(PyObject* args) | |
| { | |
| if (!PyArg_ParseTuple(args, "")) { | |
| return nullptr; | |
| } | |
| if (this->getSketchObjectPtr()->deleteAllConstraints()) { | |
| std::stringstream str; | |
| str << "Unable to delete Constraints"; | |
| PyErr_SetString(PyExc_ValueError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| Py_Return; | |
| } | |
| PyObject* SketchObjectPy::toggleConstruction(PyObject* args) | |
| { | |
| int Index; | |
| if (!PyArg_ParseTuple(args, "i", &Index)) { | |
| return nullptr; | |
| } | |
| if (this->getSketchObjectPtr()->toggleConstruction(Index)) { | |
| std::stringstream str; | |
| str << "Not able to toggle a geometry with the given index: " << Index; | |
| PyErr_SetString(PyExc_ValueError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| Py_Return; | |
| } | |
| PyObject* SketchObjectPy::setConstruction(PyObject* args) | |
| { | |
| int Index; | |
| PyObject* Mode; | |
| if (!PyArg_ParseTuple(args, "iO!", &Index, &PyBool_Type, &Mode)) { | |
| return nullptr; | |
| } | |
| if (this->getSketchObjectPtr()->setConstruction(Index, Base::asBoolean(Mode))) { | |
| std::stringstream str; | |
| str << "Not able to set construction mode of a geometry with the given index: " << Index; | |
| PyErr_SetString(PyExc_ValueError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| Py_Return; | |
| } | |
| PyObject* SketchObjectPy::getConstruction(PyObject* args) | |
| { | |
| int Index; | |
| if (!PyArg_ParseTuple(args, "i", &Index)) { | |
| return nullptr; | |
| } | |
| auto gf = this->getSketchObjectPtr()->getGeometryFacade(Index); | |
| if (gf) { | |
| return Py::new_reference_to(Py::Boolean(gf->getConstruction())); | |
| } | |
| std::stringstream str; | |
| str << "Not able to retrieve construction mode of a geometry with the given index: " << Index; | |
| PyErr_SetString(PyExc_ValueError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| PyObject* SketchObjectPy::addConstraint(PyObject* args) | |
| { | |
| PyObject* pcObj; | |
| if (!PyArg_ParseTuple(args, "O", &pcObj)) { | |
| return nullptr; | |
| } | |
| if (PyObject_TypeCheck(pcObj, &(Sketcher::ConstraintPy::Type))) { | |
| Sketcher::Constraint* constr = static_cast<Sketcher::ConstraintPy*>(pcObj)->getConstraintPtr(); | |
| if (!this->getSketchObjectPtr()->evaluateConstraint(constr)) { | |
| PyErr_SetString(PyExc_IndexError, "Constraint has invalid indexes"); | |
| return nullptr; | |
| } | |
| int ret = this->getSketchObjectPtr()->addConstraint(constr); | |
| // this solve is necessary because: | |
| // 1. The addition of constraint is part of a command addition | |
| // 2. This solve happens before the command is committed | |
| // 3. A constraint, may effect a geometry change (think of coincident, | |
| // a line's point moves to meet the other line's point | |
| // 4. The transaction is committed before any other solve, for example | |
| // the one of execute() triggered by a recompute (UpdateActive) is generated. | |
| // 5. Upon "undo", the constraint is removed (it was before the command was committed) | |
| // however, the geometry changed after the command was committed, so the point that | |
| // moved do not go back to the position where it was. | |
| // | |
| // N.B.: However, the solve itself may be inhibited in cases where groups of | |
| // geometry/constraints | |
| // are added together, because in that case undoing will also make the geometry | |
| // disappear. | |
| this->getSketchObjectPtr()->solve(); | |
| // if the geometry moved during the solve, then the initial solution is invalid | |
| // at this point, so a point movement may not work in cases where redundant constraints | |
| // exist. this forces recalculation of the initial solution (not a full solve) | |
| if (this->getSketchObjectPtr()->noRecomputes) { | |
| this->getSketchObjectPtr()->setUpSketch(); | |
| this->getSketchObjectPtr()->Constraints.touch(); // update solver information | |
| } | |
| return Py::new_reference_to(Py::Long(ret)); | |
| } | |
| else if (PyObject_TypeCheck(pcObj, &(PyList_Type)) || PyObject_TypeCheck(pcObj, &(PyTuple_Type))) { | |
| std::vector<Constraint*> values; | |
| Py::Sequence list(pcObj); | |
| for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) { | |
| if (PyObject_TypeCheck((*it).ptr(), &(ConstraintPy::Type))) { | |
| Constraint* con = static_cast<ConstraintPy*>((*it).ptr())->getConstraintPtr(); | |
| values.push_back(con); | |
| } | |
| } | |
| for (std::vector<Constraint*>::iterator it = values.begin(); it != values.end(); ++it) { | |
| if (!this->getSketchObjectPtr()->evaluateConstraint(*it)) { | |
| PyErr_SetString( | |
| PyExc_IndexError, | |
| QT_TRANSLATE_NOOP( | |
| "Notifications", | |
| "The constraint has invalid index information and is malformed." | |
| ) | |
| ); | |
| return nullptr; | |
| } | |
| } | |
| int ret = getSketchObjectPtr()->addConstraints(values) + 1; | |
| std::size_t numCon = values.size(); | |
| Py::Tuple tuple(numCon); | |
| for (std::size_t i = 0; i < numCon; ++i) { | |
| int conId = ret - int(numCon - i); | |
| tuple.setItem(i, Py::Long(conId)); | |
| } | |
| return Py::new_reference_to(tuple); | |
| } | |
| std::string error = std::string("type must be 'Constraint' or list of 'Constraint', not "); | |
| error += pcObj->ob_type->tp_name; | |
| throw Py::TypeError(error); | |
| } | |
| PyObject* SketchObjectPy::delConstraint(PyObject* args) | |
| { | |
| int Index; | |
| PyObject* noSolve = Py_False; | |
| if (!PyArg_ParseTuple(args, "i|O!", &Index, &PyBool_Type, &noSolve)) { | |
| return nullptr; | |
| } | |
| if (this->getSketchObjectPtr()->delConstraint( | |
| Index, | |
| Base::asBoolean(noSolve) ? DeleteOption::NoSolve : DeleteOption::UpdateGeometry | |
| )) { | |
| std::stringstream str; | |
| str << "Not able to delete a constraint with the given index: " << Index; | |
| PyErr_SetString(PyExc_ValueError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| Py_Return; | |
| } | |
| PyObject* SketchObjectPy::delConstraints(PyObject* args) | |
| { | |
| PyObject* pcObj; | |
| PyObject* updateGeometry = Py_True; | |
| PyObject* noSolve = Py_False; | |
| if (!PyArg_ParseTuple(args, "O|O!O!", &pcObj, &PyBool_Type, &updateGeometry, &PyBool_Type, &noSolve)) { | |
| return nullptr; | |
| } | |
| if (PyObject_TypeCheck(pcObj, &(PyList_Type)) || PyObject_TypeCheck(pcObj, &(PyTuple_Type))) { | |
| std::vector<int> constraintIdList; | |
| Py::Sequence list(pcObj); | |
| for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) { | |
| if (PyLong_Check((*it).ptr())) { | |
| constraintIdList.push_back(PyLong_AsLong((*it).ptr())); | |
| } | |
| } | |
| if (this->getSketchObjectPtr()->delConstraints( | |
| constraintIdList, | |
| (Base::asBoolean(updateGeometry) ? DeleteOption::UpdateGeometry : DeleteOption::NoFlag) | |
| | (Base::asBoolean(noSolve) ? DeleteOption::NoSolve : DeleteOption::NoFlag) | |
| ) | |
| == -1) { | |
| std::stringstream str; | |
| str << "Not able to delete constraints, invalid indices"; | |
| PyErr_SetString(PyExc_ValueError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| Py_Return; | |
| } | |
| std::string error = std::string("type must be list of constraint indices (int), not "); | |
| error += pcObj->ob_type->tp_name; | |
| throw Py::TypeError(error); | |
| Py_Return; | |
| } | |
| PyObject* SketchObjectPy::renameConstraint(PyObject* args) | |
| { | |
| int Index; | |
| char* utf8Name; | |
| if (!PyArg_ParseTuple(args, "iet", &Index, "utf-8", &utf8Name)) { | |
| return nullptr; | |
| } | |
| std::string Name = utf8Name; | |
| PyMem_Free(utf8Name); | |
| if (this->getSketchObjectPtr()->Constraints.getSize() <= Index) { | |
| std::stringstream str; | |
| str << "Not able to rename a constraint with the given index: " << Index; | |
| PyErr_SetString(PyExc_IndexError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| if (!Name.empty()) { | |
| if (!Sketcher::PropertyConstraintList::validConstraintName(Name)) { | |
| std::stringstream str; | |
| str << "Invalid constraint name with the given index: " << Index; | |
| PyErr_SetString(PyExc_IndexError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| const std::vector<Sketcher::Constraint*>& vals = getSketchObjectPtr()->Constraints.getValues(); | |
| for (std::size_t i = 0; i < vals.size(); ++i) { | |
| if (static_cast<int>(i) != Index && Name == vals[i]->Name) { | |
| PyErr_SetString(PyExc_ValueError, "Duplicate constraint not allowed"); | |
| return nullptr; | |
| } | |
| } | |
| } | |
| this->getSketchObjectPtr()->renameConstraint(Index, Name); | |
| Py_Return; | |
| } | |
| PyObject* SketchObjectPy::getIndexByName(PyObject* args) const | |
| { | |
| char* utf8Name; | |
| if (!PyArg_ParseTuple(args, "et", "utf-8", &utf8Name)) { | |
| return nullptr; | |
| } | |
| std::string Name = utf8Name; | |
| PyMem_Free(utf8Name); | |
| if (Name.empty()) { | |
| PyErr_SetString(PyExc_ValueError, "Passed string is empty"); | |
| return nullptr; | |
| } | |
| const std::vector<Sketcher::Constraint*>& vals = getSketchObjectPtr()->Constraints.getValues(); | |
| for (std::size_t i = 0; i < vals.size(); ++i) { | |
| if (Name == vals[i]->Name) { | |
| return Py_BuildValue("i", i); | |
| } | |
| } | |
| PyErr_SetString(PyExc_LookupError, "No such constraint found"); | |
| return nullptr; | |
| } | |
| PyObject* SketchObjectPy::setAllowUnaligned(PyObject* args) | |
| { | |
| PyObject* allowObj; | |
| if (!PyArg_ParseTuple(args, "O!", &PyBool_Type, &allowObj)) { | |
| return nullptr; | |
| } | |
| bool allow = Base::asBoolean(allowObj); | |
| this->getSketchObjectPtr()->setAllowUnaligned(allow); | |
| Py_Return; | |
| } | |
| PyObject* SketchObjectPy::carbonCopy(PyObject* args) | |
| { | |
| char* ObjectName; | |
| PyObject* construction = Py_True; | |
| if (!PyArg_ParseTuple(args, "s|O!", &ObjectName, &PyBool_Type, &construction)) { | |
| return nullptr; | |
| } | |
| Sketcher::SketchObject* skObj = this->getSketchObjectPtr(); | |
| App::DocumentObject* Obj = skObj->getDocument()->getObject(ObjectName); | |
| if (!Obj) { | |
| std::stringstream str; | |
| str << ObjectName << " does not exist in the document"; | |
| PyErr_SetString(PyExc_ValueError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| bool xinv = false, yinv = false; | |
| if (!skObj->isCarbonCopyAllowed(Obj->getDocument(), Obj, xinv, yinv)) { | |
| std::stringstream str; | |
| str << ObjectName << " is not allowed for a carbon copy operation in this sketch"; | |
| PyErr_SetString(PyExc_ValueError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| if (skObj->carbonCopy(Obj, Base::asBoolean(construction)) < 0) { | |
| std::stringstream str; | |
| str << "Not able to add the requested geometry"; | |
| PyErr_SetString(PyExc_ValueError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| Py_Return; | |
| } | |
| PyObject* SketchObjectPy::addExternal(PyObject* args) | |
| { | |
| char* ObjectName = nullptr; | |
| char* SubName = nullptr; | |
| PyObject* defining = Py_False; | |
| PyObject* intersection = Py_False; | |
| if (!PyArg_ParseTuple( | |
| args, | |
| "ss|O!O!", | |
| &ObjectName, | |
| &SubName, | |
| &PyBool_Type, | |
| &defining, | |
| &PyBool_Type, | |
| &intersection | |
| )) { | |
| return nullptr; | |
| } | |
| bool isDefining = Base::asBoolean(defining); | |
| bool isIntersection = Base::asBoolean(intersection); | |
| // get the target object for the external link | |
| Sketcher::SketchObject* skObj = this->getSketchObjectPtr(); | |
| App::DocumentObject* Obj = skObj->getDocument()->getObject(ObjectName); | |
| if (!Obj) { | |
| std::stringstream str; | |
| str << ObjectName << " does not exist in the document"; | |
| PyErr_SetString(PyExc_ValueError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| // check if this type of external geometry is allowed | |
| if (!skObj->isExternalAllowed(Obj->getDocument(), Obj)) { | |
| std::stringstream str; | |
| str << ObjectName << " is not allowed as external geometry of this sketch"; | |
| PyErr_SetString(PyExc_ValueError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| // add the external | |
| if (skObj->addExternal(Obj, SubName, isDefining, isIntersection) < 0) { | |
| std::stringstream str; | |
| str << "Not able to add external shape element " << SubName; | |
| PyErr_SetString(PyExc_ValueError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| Py_Return; | |
| } | |
| PyObject* SketchObjectPy::delExternal(PyObject* args) | |
| { | |
| int Index; | |
| if (!PyArg_ParseTuple(args, "i", &Index)) { | |
| return nullptr; | |
| } | |
| if (this->getSketchObjectPtr()->delExternal(Index)) { | |
| std::stringstream str; | |
| str << "Not able to delete an external geometry with the given index: " << Index; | |
| PyErr_SetString(PyExc_ValueError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| Py_Return; | |
| } | |
| PyObject* SketchObjectPy::delConstraintOnPoint(PyObject* args) | |
| { | |
| int Index, pos = -1; | |
| if (!PyArg_ParseTuple(args, "i|i", &Index, &pos)) { | |
| return nullptr; | |
| } | |
| if (pos >= static_cast<int>(Sketcher::PointPos::none) | |
| && pos <= static_cast<int>(Sketcher::PointPos::mid)) { | |
| // This is the whole range of valid positions | |
| if (this->getSketchObjectPtr() | |
| ->delConstraintOnPoint(Index, static_cast<Sketcher::PointPos>(pos))) { | |
| std::stringstream str; | |
| str << "Not able to delete a constraint on point with the given index: " << Index | |
| << " and position: " << pos; | |
| PyErr_SetString(PyExc_ValueError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| } | |
| else if (pos == -1) { | |
| if (this->getSketchObjectPtr()->delConstraintOnPoint(Index)) { | |
| std::stringstream str; | |
| str << "Not able to delete a constraint on point with the given index: " << Index; | |
| PyErr_SetString(PyExc_ValueError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| } | |
| else { | |
| PyErr_SetString(PyExc_ValueError, "Wrong PointPos argument"); | |
| return nullptr; | |
| } | |
| Py_Return; | |
| } | |
| PyObject* SketchObjectPy::delConstraintsToExternal() | |
| { | |
| this->getSketchObjectPtr()->delConstraintsToExternal(); | |
| Py_Return; | |
| } | |
| PyObject* SketchObjectPy::setDatum(PyObject* args) | |
| { | |
| double Datum; | |
| int Index; | |
| PyObject* object; | |
| Base::Quantity Quantity; | |
| do { | |
| // handle (int,Quantity) | |
| if (PyArg_ParseTuple(args, "iO!", &Index, &(Base::QuantityPy::Type), &object)) { | |
| Quantity = *(static_cast<Base::QuantityPy*>(object)->getQuantityPtr()); | |
| if (Quantity.getUnit() == Base::Unit::Angle) { | |
| Datum = Base::toRadians<double>(Quantity.getValue()); | |
| break; | |
| } | |
| else { | |
| Datum = Quantity.getValue(); | |
| break; | |
| } | |
| } | |
| // handle (int,double) | |
| PyErr_Clear(); | |
| if (PyArg_ParseTuple(args, "id", &Index, &Datum)) { | |
| Quantity.setValue(Datum); | |
| break; | |
| } | |
| // handle (string,Quantity) | |
| char* constrName; | |
| PyErr_Clear(); | |
| if (PyArg_ParseTuple(args, "sO!", &constrName, &(Base::QuantityPy::Type), &object)) { | |
| Quantity = *(static_cast<Base::QuantityPy*>(object)->getQuantityPtr()); | |
| if (Quantity.getUnit() == Base::Unit::Angle) { | |
| Datum = Base::toRadians<double>(Quantity.getValue()); | |
| } | |
| else { | |
| Datum = Quantity.getValue(); | |
| } | |
| int i = 0; | |
| Index = -1; | |
| const std::vector<Constraint*>& vals = this->getSketchObjectPtr()->Constraints.getValues(); | |
| for (std::vector<Constraint*>::const_iterator it = vals.begin(); it != vals.end(); | |
| ++it, ++i) { | |
| if ((*it)->Name == constrName) { | |
| Index = i; | |
| break; | |
| } | |
| } | |
| if (Index >= 0) { | |
| break; | |
| } | |
| else { | |
| std::stringstream str; | |
| str << "Invalid constraint name: '" << constrName << "'"; | |
| PyErr_SetString(PyExc_ValueError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| } | |
| // handle (string,double) | |
| PyErr_Clear(); | |
| if (PyArg_ParseTuple(args, "sd", &constrName, &Datum)) { | |
| Quantity.setValue(Datum); | |
| int i = 0; | |
| Index = -1; | |
| const std::vector<Constraint*>& vals = this->getSketchObjectPtr()->Constraints.getValues(); | |
| for (std::vector<Constraint*>::const_iterator it = vals.begin(); it != vals.end(); | |
| ++it, ++i) { | |
| if ((*it)->Name == constrName) { | |
| Index = i; | |
| break; | |
| } | |
| } | |
| if (Index >= 0) { | |
| break; | |
| } | |
| else { | |
| std::stringstream str; | |
| str << "Invalid constraint name: '" << constrName << "'"; | |
| PyErr_SetString(PyExc_ValueError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| } | |
| // error handling | |
| PyErr_SetString(PyExc_TypeError, "Wrong arguments"); | |
| return nullptr; | |
| } while (false); | |
| int err = this->getSketchObjectPtr()->setDatum(Index, Datum); | |
| if (err) { | |
| std::stringstream str; | |
| if (err == -1) { | |
| str << "Invalid constraint index: " << Index; | |
| } | |
| else if (err == -3) { | |
| str << "Cannot set the datum because the sketch contains conflicting constraints"; | |
| } | |
| else if (err == -2) { | |
| str << "Datum " << Quantity.getUserString() << " for the constraint with index " | |
| << Index << " is invalid"; | |
| } | |
| else if (err == -4) { | |
| str << "Negative datum values are not valid for the constraint with index " << Index; | |
| } | |
| else if (err == -5) { | |
| str << "Zero is not a valid datum for the constraint with index " << Index; | |
| } | |
| else if (err == -6) { | |
| str << "Cannot set the datum because of invalid geometry"; | |
| } | |
| else { | |
| str << "Unexpected problem at setting datum " << Quantity.getUserString() | |
| << " for the constraint with index " << Index; | |
| } | |
| PyErr_SetString(PyExc_ValueError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| Py_Return; | |
| } | |
| PyObject* SketchObjectPy::getDatum(PyObject* args) const | |
| { | |
| const std::vector<Constraint*>& vals = this->getSketchObjectPtr()->Constraints.getValues(); | |
| Constraint* constr = nullptr; | |
| do { | |
| int index = 0; | |
| if (PyArg_ParseTuple(args, "i", &index)) { | |
| if (index < 0 || index >= static_cast<int>(vals.size())) { | |
| PyErr_SetString(PyExc_IndexError, "index out of range"); | |
| return nullptr; | |
| } | |
| constr = vals[index]; | |
| break; | |
| } | |
| PyErr_Clear(); | |
| char* name; | |
| if (PyArg_ParseTuple(args, "s", &name)) { | |
| int id = 0; | |
| for (std::vector<Constraint*>::const_iterator it = vals.begin(); it != vals.end(); | |
| ++it, ++id) { | |
| if (Sketcher::PropertyConstraintList::getConstraintName((*it)->Name, id) == name) { | |
| constr = *it; | |
| break; | |
| } | |
| } | |
| if (!constr) { | |
| std::stringstream str; | |
| str << "Invalid constraint name: '" << name << "'"; | |
| PyErr_SetString(PyExc_NameError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| else { | |
| break; | |
| } | |
| } | |
| // error handling | |
| PyErr_SetString(PyExc_TypeError, "Wrong arguments"); | |
| return nullptr; | |
| } while (false); | |
| ConstraintType type = constr->Type; | |
| if (type != Distance && type != DistanceX && type != DistanceY && type != Radius | |
| && type != Diameter && type != Angle) { | |
| PyErr_SetString(PyExc_TypeError, "Constraint is not a datum"); | |
| return nullptr; | |
| } | |
| Base::Quantity datum; | |
| datum.setValue(constr->getValue()); | |
| if (type == Angle) { | |
| datum.setValue(Base::toDegrees<double>(datum.getValue())); | |
| datum.setUnit(Base::Unit::Angle); | |
| } | |
| else { | |
| datum.setUnit(Base::Unit::Length); | |
| } | |
| return new Base::QuantityPy(new Base::Quantity(datum)); | |
| } | |
| PyObject* SketchObjectPy::setDriving(PyObject* args) | |
| { | |
| PyObject* driving; | |
| int constrid; | |
| if (!PyArg_ParseTuple(args, "iO!", &constrid, &PyBool_Type, &driving)) { | |
| return nullptr; | |
| } | |
| if (this->getSketchObjectPtr()->setDriving(constrid, Base::asBoolean(driving))) { | |
| std::stringstream str; | |
| str << "Not able set Driving/reference for constraint with the given index: " << constrid; | |
| PyErr_SetString(PyExc_ValueError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| Py_Return; | |
| } | |
| PyObject* SketchObjectPy::setDatumsDriving(PyObject* args) | |
| { | |
| PyObject* driving; | |
| if (!PyArg_ParseTuple(args, "O!", &PyBool_Type, &driving)) { | |
| return nullptr; | |
| } | |
| if (this->getSketchObjectPtr()->setDatumsDriving(Base::asBoolean(driving))) { | |
| std::stringstream str; | |
| str << "Not able set all dimensionals driving/reference"; | |
| PyErr_SetString(PyExc_ValueError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| Py_Return; | |
| } | |
| PyObject* SketchObjectPy::moveDatumsToEnd(PyObject* args) | |
| { | |
| if (!PyArg_ParseTuple(args, "")) { | |
| return nullptr; | |
| } | |
| if (this->getSketchObjectPtr()->moveDatumsToEnd()) { | |
| std::stringstream str; | |
| str << "Not able move all dimensionals to end"; | |
| PyErr_SetString(PyExc_ValueError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| Py_Return; | |
| } | |
| PyObject* SketchObjectPy::getDriving(PyObject* args) const | |
| { | |
| int constrid; | |
| bool driving; | |
| if (!PyArg_ParseTuple(args, "i", &constrid)) { | |
| return nullptr; | |
| } | |
| if (this->getSketchObjectPtr()->getDriving(constrid, driving)) { | |
| PyErr_SetString(PyExc_ValueError, "Invalid constraint id"); | |
| return nullptr; | |
| } | |
| return Py::new_reference_to(Py::Boolean(driving)); | |
| } | |
| PyObject* SketchObjectPy::toggleDriving(PyObject* args) | |
| { | |
| int constrid; | |
| if (!PyArg_ParseTuple(args, "i", &constrid)) { | |
| return nullptr; | |
| } | |
| if (this->getSketchObjectPtr()->toggleDriving(constrid)) { | |
| std::stringstream str; | |
| str << "Not able toggle Driving for constraint with the given index: " << constrid; | |
| PyErr_SetString(PyExc_ValueError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| Py_Return; | |
| } | |
| PyObject* SketchObjectPy::setVirtualSpace(PyObject* args) | |
| { | |
| PyObject* invirtualspace; | |
| PyObject* id_or_ids; | |
| if (!PyArg_ParseTuple(args, "OO!", &id_or_ids, &PyBool_Type, &invirtualspace)) { | |
| return nullptr; | |
| } | |
| if (PyObject_TypeCheck(id_or_ids, &(PyList_Type)) | |
| || PyObject_TypeCheck(id_or_ids, &(PyTuple_Type))) { | |
| std::vector<int> constrIds; | |
| Py::Sequence list(id_or_ids); | |
| for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) { | |
| if (PyLong_Check((*it).ptr())) { | |
| constrIds.push_back(PyLong_AsLong((*it).ptr())); | |
| } | |
| } | |
| try { | |
| int ret = this->getSketchObjectPtr()->setVirtualSpace( | |
| constrIds, | |
| Base::asBoolean(invirtualspace) | |
| ); | |
| if (ret == -1) { | |
| throw Py::TypeError("Impossible to set virtual space!"); | |
| } | |
| } | |
| catch (const Base::ValueError& e) { | |
| throw Py::ValueError(e.getMessage()); | |
| } | |
| Py_Return; | |
| } | |
| else if (PyLong_Check(id_or_ids)) { | |
| if (this->getSketchObjectPtr() | |
| ->setVirtualSpace(PyLong_AsLong(id_or_ids), Base::asBoolean(invirtualspace))) { | |
| std::stringstream str; | |
| str << "Not able set virtual space for constraint with the given index: " | |
| << PyLong_AsLong(id_or_ids); | |
| PyErr_SetString(PyExc_ValueError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| Py_Return; | |
| } | |
| std::string error = std::string("type must be list of Constraint Ids, not "); | |
| error += id_or_ids->ob_type->tp_name; | |
| throw Py::TypeError(error); | |
| } | |
| PyObject* SketchObjectPy::setVisibility(PyObject* args) | |
| { | |
| PyObject* isVisible; | |
| PyObject* id_or_ids; | |
| if (!PyArg_ParseTuple(args, "OO!", &id_or_ids, &PyBool_Type, &isVisible)) { | |
| return nullptr; | |
| } | |
| if (PyObject_TypeCheck(id_or_ids, &(PyList_Type)) | |
| || PyObject_TypeCheck(id_or_ids, &(PyTuple_Type))) { | |
| std::vector<int> constrIds; | |
| Py::Sequence list(id_or_ids); | |
| for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) { | |
| if (PyLong_Check((*it).ptr())) { | |
| constrIds.push_back(PyLong_AsLong((*it).ptr())); | |
| } | |
| } | |
| try { | |
| int ret = this->getSketchObjectPtr()->setVisibility(constrIds, Base::asBoolean(isVisible)); | |
| if (ret == -1) { | |
| throw Py::TypeError("Impossible to set visibility!"); | |
| } | |
| } | |
| catch (const Base::ValueError& e) { | |
| throw Py::ValueError(e.getMessage()); | |
| } | |
| Py_Return; | |
| } | |
| else if (PyLong_Check(id_or_ids)) { | |
| if (this->getSketchObjectPtr() | |
| ->setVisibility(PyLong_AsLong(id_or_ids), Base::asBoolean(isVisible))) { | |
| std::stringstream str; | |
| str << "Not able set visibility for constraint with the given index: " | |
| << PyLong_AsLong(id_or_ids); | |
| PyErr_SetString(PyExc_ValueError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| Py_Return; | |
| } | |
| std::string error = std::string("type must be list of Constraint Ids, not "); | |
| error += id_or_ids->ob_type->tp_name; | |
| throw Py::TypeError(error); | |
| } | |
| PyObject* SketchObjectPy::getVirtualSpace(PyObject* args) | |
| { | |
| int constrid; | |
| bool invirtualspace; | |
| if (!PyArg_ParseTuple(args, "i", &constrid)) { | |
| return nullptr; | |
| } | |
| if (this->getSketchObjectPtr()->getVirtualSpace(constrid, invirtualspace)) { | |
| PyErr_SetString(PyExc_ValueError, "Invalid constraint id"); | |
| return nullptr; | |
| } | |
| return Py::new_reference_to(Py::Boolean(invirtualspace)); | |
| } | |
| PyObject* SketchObjectPy::toggleVirtualSpace(PyObject* args) | |
| { | |
| int constrid; | |
| if (!PyArg_ParseTuple(args, "i", &constrid)) { | |
| return nullptr; | |
| } | |
| if (this->getSketchObjectPtr()->toggleVirtualSpace(constrid)) { | |
| std::stringstream str; | |
| str << "Not able toggle virtual space for constraint with the given index: " << constrid; | |
| PyErr_SetString(PyExc_ValueError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| Py_Return; | |
| } | |
| PyObject* SketchObjectPy::setActive(PyObject* args) | |
| { | |
| PyObject* isactive; | |
| int constrid; | |
| if (!PyArg_ParseTuple(args, "iO!", &constrid, &PyBool_Type, &isactive)) { | |
| return nullptr; | |
| } | |
| if (this->getSketchObjectPtr()->setActive(constrid, Base::asBoolean(isactive))) { | |
| std::stringstream str; | |
| str << "Not able set active/disabled status for constraint with the given index: " | |
| << constrid; | |
| PyErr_SetString(PyExc_ValueError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| Py_Return; | |
| } | |
| PyObject* SketchObjectPy::getActive(PyObject* args) const | |
| { | |
| int constrid; | |
| bool isactive; | |
| if (!PyArg_ParseTuple(args, "i", &constrid)) { | |
| return nullptr; | |
| } | |
| if (this->getSketchObjectPtr()->getActive(constrid, isactive)) { | |
| PyErr_SetString(PyExc_ValueError, "Invalid constraint id"); | |
| return nullptr; | |
| } | |
| return Py::new_reference_to(Py::Boolean(isactive)); | |
| } | |
| PyObject* SketchObjectPy::toggleActive(PyObject* args) | |
| { | |
| int constrid; | |
| if (!PyArg_ParseTuple(args, "i", &constrid)) { | |
| return nullptr; | |
| } | |
| if (this->getSketchObjectPtr()->toggleActive(constrid)) { | |
| std::stringstream str; | |
| str << "Not able toggle on/off constraint with the given index: " << constrid; | |
| PyErr_SetString(PyExc_ValueError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| Py_Return; | |
| } | |
| PyObject* SketchObjectPy::getLabelPosition(PyObject* args) const | |
| { | |
| int constrid {}; | |
| float pos {}; | |
| if (!PyArg_ParseTuple(args, "i", &constrid)) { | |
| return nullptr; | |
| } | |
| if (this->getSketchObjectPtr()->getLabelPosition(constrid, pos)) { | |
| PyErr_SetString(PyExc_ValueError, "Invalid constraint id"); | |
| return nullptr; | |
| } | |
| return Py::new_reference_to(Py::Float(pos)); | |
| } | |
| PyObject* SketchObjectPy::setLabelPosition(PyObject* args) | |
| { | |
| int constrid {}; | |
| float pos {}; | |
| if (!PyArg_ParseTuple(args, "if", &constrid, &pos)) { | |
| return nullptr; | |
| } | |
| if (this->getSketchObjectPtr()->setLabelPosition(constrid, pos)) { | |
| PyErr_SetString(PyExc_ValueError, "Invalid constraint id"); | |
| return nullptr; | |
| } | |
| Py_Return; | |
| } | |
| PyObject* SketchObjectPy::getLabelDistance(PyObject* args) const | |
| { | |
| int constrid {}; | |
| float dist {}; | |
| if (!PyArg_ParseTuple(args, "i", &constrid)) { | |
| return nullptr; | |
| } | |
| if (this->getSketchObjectPtr()->getLabelDistance(constrid, dist)) { | |
| PyErr_SetString(PyExc_ValueError, "Invalid constraint id"); | |
| return nullptr; | |
| } | |
| return Py::new_reference_to(Py::Float(dist)); | |
| } | |
| PyObject* SketchObjectPy::setLabelDistance(PyObject* args) | |
| { | |
| int constrid {}; | |
| float dist {}; | |
| if (!PyArg_ParseTuple(args, "if", &constrid, &dist)) { | |
| return nullptr; | |
| } | |
| if (this->getSketchObjectPtr()->setLabelDistance(constrid, dist)) { | |
| PyErr_SetString(PyExc_ValueError, "Invalid constraint id"); | |
| return nullptr; | |
| } | |
| Py_Return; | |
| } | |
| PyObject* SketchObjectPy::moveGeometries(PyObject* args) | |
| { | |
| PyObject* pyList; | |
| PyObject* pcObj; | |
| int relative = 0; | |
| // Parse arguments: list of pairs, Base::VectorPy, optional relative flag | |
| if (!PyArg_ParseTuple( | |
| args, | |
| "O!O!|i", | |
| &PyList_Type, | |
| &pyList, // List of pairs (geoId, pointPos) | |
| &(Base::VectorPy::Type), | |
| &pcObj, // Target vector | |
| &relative | |
| )) { // Optional relative flag | |
| return nullptr; | |
| } | |
| // Convert Python list to std::vector<GeoElementId> | |
| std::vector<GeoElementId> geoEltIds; | |
| Py_ssize_t listSize = PyList_Size(pyList); | |
| for (Py_ssize_t i = 0; i < listSize; ++i) { | |
| PyObject* pyPair = PyList_GetItem(pyList, i); // Borrowed reference | |
| if (!PyTuple_Check(pyPair) || PyTuple_Size(pyPair) != 2) { | |
| PyErr_SetString(PyExc_ValueError, "List must contain pairs (geoId, pointPos)."); | |
| return nullptr; | |
| } | |
| int geoId = PyLong_AsLong(PyTuple_GetItem(pyPair, 0)); | |
| int pointPos = PyLong_AsLong(PyTuple_GetItem(pyPair, 1)); | |
| if (PyErr_Occurred()) { | |
| PyErr_SetString(PyExc_ValueError, "Invalid geoId or pointPos in the list."); | |
| return nullptr; | |
| } | |
| geoEltIds.emplace_back(GeoElementId(geoId, static_cast<Sketcher::PointPos>(pointPos))); | |
| } | |
| // Convert Python vector to Base::Vector3d | |
| Base::Vector3d v1 = static_cast<Base::VectorPy*>(pcObj)->value(); | |
| // Call the C++ method | |
| if (this->getSketchObjectPtr()->moveGeometries(geoEltIds, v1, (relative > 0))) { | |
| PyErr_SetString(PyExc_ValueError, "Failed to move geometries."); | |
| return nullptr; | |
| } | |
| Py_RETURN_NONE; | |
| } | |
| PyObject* SketchObjectPy::moveGeometry(PyObject* args) | |
| { | |
| PyObject* pcObj; | |
| int GeoId, PointType; | |
| int relative = 0; | |
| if (!PyArg_ParseTuple(args, "iiO!|i", &GeoId, &PointType, &(Base::VectorPy::Type), &pcObj, &relative)) { | |
| return nullptr; | |
| } | |
| Base::Vector3d v1 = static_cast<Base::VectorPy*>(pcObj)->value(); | |
| if (this->getSketchObjectPtr() | |
| ->moveGeometry(GeoId, static_cast<Sketcher::PointPos>(PointType), v1, (relative > 0))) { | |
| std::stringstream str; | |
| str << "Not able to move point with the id and type: (" << GeoId << ", " << PointType << ")"; | |
| PyErr_SetString(PyExc_ValueError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| Py_Return; | |
| } | |
| PyObject* SketchObjectPy::getGeoVertexIndex(PyObject* args) const | |
| { | |
| int index; | |
| if (!PyArg_ParseTuple(args, "i", &index)) { | |
| return nullptr; | |
| } | |
| SketchObject* obj = this->getSketchObjectPtr(); | |
| int geoId; | |
| PointPos posId; | |
| obj->getGeoVertexIndex(index, geoId, posId); | |
| Py::Tuple tuple(2); | |
| tuple.setItem(0, Py::Long(geoId)); | |
| tuple.setItem(1, Py::Long(static_cast<int>(posId))); | |
| return Py::new_reference_to(tuple); | |
| } | |
| PyObject* SketchObjectPy::getPoint(PyObject* args) const | |
| { | |
| int GeoId, PointType; | |
| if (!PyArg_ParseTuple(args, "ii", &GeoId, &PointType)) { | |
| return nullptr; | |
| } | |
| if (PointType < 0 || PointType > 3) { | |
| PyErr_SetString(PyExc_ValueError, "Invalid point type"); | |
| return nullptr; | |
| } | |
| SketchObject* obj = this->getSketchObjectPtr(); | |
| if (GeoId > obj->getHighestCurveIndex() || -GeoId > obj->getExternalGeometryCount()) { | |
| PyErr_SetString(PyExc_ValueError, "Invalid geometry Id"); | |
| return nullptr; | |
| } | |
| return new Base::VectorPy( | |
| new Base::Vector3d(obj->getPoint(GeoId, static_cast<Sketcher::PointPos>(PointType))) | |
| ); | |
| } | |
| PyObject* SketchObjectPy::getAxis(PyObject* args) const | |
| { | |
| int AxId; | |
| if (!PyArg_ParseTuple(args, "i", &AxId)) { | |
| return nullptr; | |
| } | |
| return new Base::AxisPy(new Base::Axis(this->getSketchObjectPtr()->getAxis(AxId))); | |
| } | |
| PyObject* SketchObjectPy::fillet(PyObject* args) | |
| { | |
| PyObject *pcObj1, *pcObj2; | |
| int geoId1, geoId2, posId1; | |
| int trim = true; | |
| PyObject* createCorner = Py_False; | |
| PyObject* chamfer = Py_False; | |
| double radius; | |
| // Two Lines, radius | |
| if (PyArg_ParseTuple( | |
| args, | |
| "iiO!O!d|iO!O!", | |
| &geoId1, | |
| &geoId2, | |
| &(Base::VectorPy::Type), | |
| &pcObj1, | |
| &(Base::VectorPy::Type), | |
| &pcObj2, | |
| &radius, | |
| &trim, | |
| &PyBool_Type, | |
| &createCorner, | |
| &PyBool_Type, | |
| &chamfer | |
| )) { | |
| // The i for &trim should probably have been a bool like &createCorner, but we'll leave it | |
| // an int for backward compatibility (and because python will accept a bool there anyway) | |
| Base::Vector3d v1 = static_cast<Base::VectorPy*>(pcObj1)->value(); | |
| Base::Vector3d v2 = static_cast<Base::VectorPy*>(pcObj2)->value(); | |
| if (this->getSketchObjectPtr()->fillet( | |
| geoId1, | |
| geoId2, | |
| v1, | |
| v2, | |
| radius, | |
| trim, | |
| Base::asBoolean(createCorner), | |
| Base::asBoolean(chamfer) | |
| )) { | |
| std::stringstream str; | |
| str << "Not able to fillet curves with ids : (" << geoId1 << ", " << geoId2 | |
| << ") and points (" << v1.x << ", " << v1.y << ", " << v1.z << ") & " | |
| << "(" << v2.x << ", " << v2.y << ", " << v2.z << ")"; | |
| THROWM(Base::ValueError, str.str().c_str()) | |
| return nullptr; | |
| } | |
| Py_Return; | |
| } | |
| PyErr_Clear(); | |
| // Point, radius | |
| if (PyArg_ParseTuple( | |
| args, | |
| "iid|iO!O!", | |
| &geoId1, | |
| &posId1, | |
| &radius, | |
| &trim, | |
| &PyBool_Type, | |
| &createCorner, | |
| &PyBool_Type, | |
| &chamfer | |
| )) { | |
| if (this->getSketchObjectPtr()->fillet( | |
| geoId1, | |
| static_cast<Sketcher::PointPos>(posId1), | |
| radius, | |
| trim, | |
| Base::asBoolean(createCorner), | |
| Base::asBoolean(chamfer) | |
| )) { | |
| std::stringstream str; | |
| str << "Not able to fillet point with ( geoId: " << geoId1 << ", PointPos: " << posId1 | |
| << " )"; | |
| PyErr_SetString(PyExc_ValueError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| Py_Return; | |
| } | |
| PyErr_SetString( | |
| PyExc_TypeError, | |
| "fillet() method accepts:\n" | |
| "-- int,int,Vector,Vector,float,[bool],[bool]\n" | |
| "-- int,int,float,[bool],[bool]\n" | |
| ); | |
| return nullptr; | |
| } | |
| PyObject* SketchObjectPy::trim(PyObject* args) | |
| { | |
| PyObject* pcObj; | |
| int GeoId; | |
| if (!PyArg_ParseTuple(args, "iO!", &GeoId, &(Base::VectorPy::Type), &pcObj)) { | |
| return nullptr; | |
| } | |
| Base::Vector3d v1 = static_cast<Base::VectorPy*>(pcObj)->value(); | |
| if (this->getSketchObjectPtr()->trim(GeoId, v1)) { | |
| std::stringstream str; | |
| str << "Not able to trim curve with the given index: " << GeoId; | |
| PyErr_SetString(PyExc_ValueError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| Py_Return; | |
| } | |
| PyObject* SketchObjectPy::extend(PyObject* args) | |
| { | |
| double increment; | |
| int endPoint; | |
| int GeoId; | |
| if (PyArg_ParseTuple(args, "idi", &GeoId, &increment, &endPoint)) { | |
| if (this->getSketchObjectPtr() | |
| ->extend(GeoId, increment, static_cast<Sketcher::PointPos>(endPoint))) { | |
| std::stringstream str; | |
| str << "Not able to extend geometry with id : (" << GeoId << ") for increment (" | |
| << increment << ") and point position (" << endPoint << ")"; | |
| PyErr_SetString(PyExc_ValueError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| Py_Return; | |
| } | |
| PyErr_SetString( | |
| PyExc_TypeError, | |
| "extend() method accepts:\n" | |
| "-- int,float,int\n" | |
| ); | |
| return nullptr; | |
| } | |
| PyObject* SketchObjectPy::split(PyObject* args) | |
| { | |
| PyObject* pcObj; | |
| int GeoId; | |
| if (!PyArg_ParseTuple(args, "iO!", &GeoId, &(Base::VectorPy::Type), &pcObj)) { | |
| return nullptr; | |
| } | |
| Base::Vector3d v1 = static_cast<Base::VectorPy*>(pcObj)->value(); | |
| try { | |
| if (this->getSketchObjectPtr()->split(GeoId, v1)) { | |
| std::stringstream str; | |
| str << "Not able to split curve with the given index: " << GeoId; | |
| PyErr_SetString(PyExc_ValueError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| } | |
| catch (const Base::ValueError& e) { | |
| throw Py::ValueError(e.getMessage()); | |
| } | |
| Py_Return; | |
| } | |
| PyObject* SketchObjectPy::join(PyObject* args) | |
| { | |
| int GeoId1(Sketcher::GeoEnum::GeoUndef), GeoId2(Sketcher::GeoEnum::GeoUndef); | |
| int PosId1 = static_cast<int>(Sketcher::PointPos::none), | |
| PosId2 = static_cast<int>(Sketcher::PointPos::none); | |
| int continuity = 0; | |
| if (!PyArg_ParseTuple(args, "iiii|i", &GeoId1, &PosId1, &GeoId2, &PosId2, &continuity)) { | |
| return nullptr; | |
| } | |
| if (this->getSketchObjectPtr() | |
| ->join(GeoId1, (Sketcher::PointPos)PosId1, GeoId2, (Sketcher::PointPos)PosId2, continuity)) { | |
| std::stringstream str; | |
| str << "Not able to join the curves with end points: (" << GeoId1 << ", " << PosId1 | |
| << "), (" << GeoId2 << ", " << PosId2 << ")"; | |
| PyErr_SetString(PyExc_ValueError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| Py_Return; | |
| } | |
| PyObject* SketchObjectPy::addSymmetric(PyObject* args) | |
| { | |
| PyObject* pcObj; | |
| int refGeoId; | |
| int refPosId = static_cast<int>(Sketcher::PointPos::none); | |
| if (!PyArg_ParseTuple(args, "Oi|i", &pcObj, &refGeoId, &refPosId)) { | |
| return nullptr; | |
| } | |
| if (PyObject_TypeCheck(pcObj, &(PyList_Type)) || PyObject_TypeCheck(pcObj, &(PyTuple_Type))) { | |
| std::vector<int> geoIdList; | |
| Py::Sequence list(pcObj); | |
| for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) { | |
| if (PyLong_Check((*it).ptr())) { | |
| geoIdList.push_back(PyLong_AsLong((*it).ptr())); | |
| } | |
| } | |
| int ret = this->getSketchObjectPtr() | |
| ->addSymmetric(geoIdList, refGeoId, static_cast<Sketcher::PointPos>(refPosId)) | |
| + 1; | |
| if (ret == -1) { | |
| throw Py::TypeError("Symmetric operation unsuccessful!"); | |
| } | |
| std::size_t numGeo = geoIdList.size(); | |
| Py::Tuple tuple(numGeo); | |
| for (std::size_t i = 0; i < numGeo; ++i) { | |
| int geoId = ret - int(numGeo - i); | |
| tuple.setItem(i, Py::Long(geoId)); | |
| } | |
| return Py::new_reference_to(tuple); | |
| } | |
| std::string error = std::string("type must be list of GeoIds, not "); | |
| error += pcObj->ob_type->tp_name; | |
| throw Py::TypeError(error); | |
| } | |
| PyObject* SketchObjectPy::addCopy(PyObject* args) | |
| { | |
| PyObject *pcObj, *pcVect; | |
| PyObject* clone = Py_False; | |
| if (!PyArg_ParseTuple(args, "OO!|O!", &pcObj, &(Base::VectorPy::Type), &pcVect, &PyBool_Type, &clone)) { | |
| return nullptr; | |
| } | |
| Base::Vector3d vect = static_cast<Base::VectorPy*>(pcVect)->value(); | |
| if (PyObject_TypeCheck(pcObj, &(PyList_Type)) || PyObject_TypeCheck(pcObj, &(PyTuple_Type))) { | |
| std::vector<int> geoIdList; | |
| Py::Sequence list(pcObj); | |
| for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) { | |
| if (PyLong_Check((*it).ptr())) { | |
| geoIdList.push_back(PyLong_AsLong((*it).ptr())); | |
| } | |
| } | |
| try { | |
| int ret = this->getSketchObjectPtr()->addCopy(geoIdList, vect, false, Base::asBoolean(clone)) | |
| + 1; | |
| if (ret == -1) { | |
| throw Py::TypeError("Copy operation unsuccessful!"); | |
| } | |
| std::size_t numGeo = geoIdList.size(); | |
| Py::Tuple tuple(numGeo); | |
| for (std::size_t i = 0; i < numGeo; ++i) { | |
| int geoId = ret - int(numGeo - i); | |
| tuple.setItem(i, Py::Long(geoId)); | |
| } | |
| return Py::new_reference_to(tuple); | |
| } | |
| catch (const Base::ValueError& e) { | |
| throw Py::ValueError(e.getMessage()); | |
| } | |
| } | |
| std::string error = std::string("type must be list of GeoIds, not "); | |
| error += pcObj->ob_type->tp_name; | |
| throw Py::TypeError(error); | |
| } | |
| PyObject* SketchObjectPy::addMove(PyObject* args) | |
| { | |
| PyObject *pcObj, *pcVect; | |
| if (!PyArg_ParseTuple(args, "OO!", &pcObj, &(Base::VectorPy::Type), &pcVect)) { | |
| return nullptr; | |
| } | |
| Base::Vector3d vect = static_cast<Base::VectorPy*>(pcVect)->value(); | |
| if (PyObject_TypeCheck(pcObj, &(PyList_Type)) || PyObject_TypeCheck(pcObj, &(PyTuple_Type))) { | |
| std::vector<int> geoIdList; | |
| Py::Sequence list(pcObj); | |
| for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) { | |
| if (PyLong_Check((*it).ptr())) { | |
| geoIdList.push_back(PyLong_AsLong((*it).ptr())); | |
| } | |
| } | |
| this->getSketchObjectPtr()->addCopy(geoIdList, vect, true); | |
| Py_Return; | |
| } | |
| std::string error = std::string("type must be list of GeoIds, not "); | |
| error += pcObj->ob_type->tp_name; | |
| throw Py::TypeError(error); | |
| } | |
| PyObject* SketchObjectPy::addRectangularArray(PyObject* args) | |
| { | |
| PyObject *pcObj, *pcVect; | |
| int rows, cols; | |
| double perpscale = 1.0; | |
| PyObject* constraindisplacement = Py_False; | |
| PyObject* clone = Py_False; | |
| if (!PyArg_ParseTuple( | |
| args, | |
| "OO!O!ii|O!d", | |
| &pcObj, | |
| &(Base::VectorPy::Type), | |
| &pcVect, | |
| &PyBool_Type, | |
| &clone, | |
| &rows, | |
| &cols, | |
| &PyBool_Type, | |
| &constraindisplacement, | |
| &perpscale | |
| )) { | |
| return nullptr; | |
| } | |
| Base::Vector3d vect = static_cast<Base::VectorPy*>(pcVect)->value(); | |
| if (PyObject_TypeCheck(pcObj, &(PyList_Type)) || PyObject_TypeCheck(pcObj, &(PyTuple_Type))) { | |
| std::vector<int> geoIdList; | |
| Py::Sequence list(pcObj); | |
| for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) { | |
| if (PyLong_Check((*it).ptr())) { | |
| geoIdList.push_back(PyLong_AsLong((*it).ptr())); | |
| } | |
| } | |
| try { | |
| int ret = this->getSketchObjectPtr()->addCopy( | |
| geoIdList, | |
| vect, | |
| false, | |
| Base::asBoolean(clone), | |
| rows, | |
| cols, | |
| Base::asBoolean(constraindisplacement), | |
| perpscale | |
| ) | |
| + 1; | |
| if (ret == -1) { | |
| throw Py::TypeError("Copy operation unsuccessful!"); | |
| } | |
| } | |
| catch (const Base::ValueError& e) { | |
| throw Py::ValueError(e.getMessage()); | |
| } | |
| Py_Return; | |
| } | |
| std::string error = std::string("type must be list of GeoIds, not "); | |
| error += pcObj->ob_type->tp_name; | |
| throw Py::TypeError(error); | |
| } | |
| PyObject* SketchObjectPy::removeAxesAlignment(PyObject* args) | |
| { | |
| PyObject* pcObj; | |
| if (!PyArg_ParseTuple(args, "O", &pcObj)) { | |
| return nullptr; | |
| } | |
| if (PyObject_TypeCheck(pcObj, &(PyList_Type)) || PyObject_TypeCheck(pcObj, &(PyTuple_Type))) { | |
| std::vector<int> geoIdList; | |
| Py::Sequence list(pcObj); | |
| for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) { | |
| if (PyLong_Check((*it).ptr())) { | |
| geoIdList.push_back(PyLong_AsLong((*it).ptr())); | |
| } | |
| } | |
| int ret = this->getSketchObjectPtr()->removeAxesAlignment(geoIdList) + 1; | |
| if (ret == -1) { | |
| throw Py::TypeError("Operation unsuccessful!"); | |
| } | |
| Py_Return; | |
| } | |
| std::string error = std::string("type must be list of GeoIds, not "); | |
| error += pcObj->ob_type->tp_name; | |
| throw Py::TypeError(error); | |
| } | |
| PyObject* SketchObjectPy::calculateAngleViaPoint(PyObject* args) | |
| { | |
| int GeoId1 = 0, GeoId2 = 0; | |
| double px = 0, py = 0; | |
| if (!PyArg_ParseTuple(args, "iidd", &GeoId1, &GeoId2, &px, &py)) { | |
| return nullptr; | |
| } | |
| SketchObject* obj = this->getSketchObjectPtr(); | |
| if (GeoId1 > obj->getHighestCurveIndex() || -GeoId1 > obj->getExternalGeometryCount() | |
| || GeoId2 > obj->getHighestCurveIndex() || -GeoId2 > obj->getExternalGeometryCount()) { | |
| PyErr_SetString(PyExc_ValueError, "Invalid geometry Id"); | |
| return nullptr; | |
| } | |
| double ang = obj->calculateAngleViaPoint(GeoId1, GeoId2, px, py); | |
| return Py::new_reference_to(Py::Float(ang)); | |
| } | |
| PyObject* SketchObjectPy::isPointOnCurve(PyObject* args) | |
| { | |
| int GeoId = GeoEnum::GeoUndef; | |
| double px = 0, py = 0; | |
| if (!PyArg_ParseTuple(args, "idd", &GeoId, &px, &py)) { | |
| return nullptr; | |
| } | |
| SketchObject* obj = this->getSketchObjectPtr(); | |
| if (GeoId > obj->getHighestCurveIndex() || -GeoId > obj->getExternalGeometryCount()) { | |
| PyErr_SetString(PyExc_ValueError, "Invalid geometry Id"); | |
| return nullptr; | |
| } | |
| return Py::new_reference_to(Py::Boolean(obj->isPointOnCurve(GeoId, px, py))); | |
| } | |
| PyObject* SketchObjectPy::calculateConstraintError(PyObject* args) | |
| { | |
| int ic = -1; | |
| if (!PyArg_ParseTuple(args, "i", &ic)) { | |
| return nullptr; | |
| } | |
| SketchObject* obj = this->getSketchObjectPtr(); | |
| if (ic >= obj->Constraints.getSize() || ic < 0) { | |
| PyErr_SetString(PyExc_ValueError, "Invalid constraint Id"); | |
| return nullptr; | |
| } | |
| double err = obj->calculateConstraintError(ic); | |
| return Py::new_reference_to(Py::Float(err)); | |
| } | |
| PyObject* SketchObjectPy::changeConstraintsLocking(PyObject* args) | |
| { | |
| int bLock = 0; | |
| if (!PyArg_ParseTuple(args, "i", &bLock)) { | |
| return nullptr; | |
| } | |
| SketchObject* obj = this->getSketchObjectPtr(); | |
| int naff = obj->changeConstraintsLocking((bool)bLock); | |
| return Py::new_reference_to(Py::Long(naff)); | |
| } | |
| // Deprecated | |
| PyObject* SketchObjectPy::ExposeInternalGeometry(PyObject* args) | |
| { | |
| int GeoId; | |
| if (!PyArg_ParseTuple(args, "i", &GeoId)) { | |
| return nullptr; | |
| } | |
| if (this->getSketchObjectPtr()->exposeInternalGeometry(GeoId) == -1) { | |
| std::stringstream str; | |
| str << "Object does not support internal geometry: " << GeoId; | |
| PyErr_SetString(PyExc_ValueError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| Py_Return; | |
| } | |
| // Deprecated | |
| PyObject* SketchObjectPy::DeleteUnusedInternalGeometry(PyObject* args) | |
| { | |
| int GeoId; | |
| if (!PyArg_ParseTuple(args, "i", &GeoId)) { | |
| return nullptr; | |
| } | |
| if (this->getSketchObjectPtr()->deleteUnusedInternalGeometry(GeoId) == -1) { | |
| std::stringstream str; | |
| str << "Object does not support internal geometry: " << GeoId; | |
| PyErr_SetString(PyExc_ValueError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| Py_Return; | |
| } | |
| PyObject* SketchObjectPy::exposeInternalGeometry(PyObject* args) | |
| { | |
| int GeoId; | |
| if (!PyArg_ParseTuple(args, "i", &GeoId)) { | |
| return nullptr; | |
| } | |
| if (this->getSketchObjectPtr()->exposeInternalGeometry(GeoId) == -1) { | |
| std::stringstream str; | |
| str << "Object does not support internal geometry: " << GeoId; | |
| PyErr_SetString(PyExc_ValueError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| Py_Return; | |
| } | |
| PyObject* SketchObjectPy::deleteUnusedInternalGeometry(PyObject* args) | |
| { | |
| int GeoId; | |
| if (!PyArg_ParseTuple(args, "i", &GeoId)) { | |
| return nullptr; | |
| } | |
| if (this->getSketchObjectPtr()->deleteUnusedInternalGeometry(GeoId) == -1) { | |
| std::stringstream str; | |
| str << "Object does not support internal geometry: " << GeoId; | |
| PyErr_SetString(PyExc_ValueError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| Py_Return; | |
| } | |
| PyObject* SketchObjectPy::convertToNURBS(PyObject* args) | |
| { | |
| int GeoId; | |
| if (!PyArg_ParseTuple(args, "i", &GeoId)) { | |
| return nullptr; | |
| } | |
| if (!this->getSketchObjectPtr()->convertToNURBS(GeoId)) { | |
| std::stringstream str; | |
| str << "Object does not support NURBS conversion: " << GeoId; | |
| PyErr_SetString(PyExc_ValueError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| Py_Return; | |
| } | |
| PyObject* SketchObjectPy::increaseBSplineDegree(PyObject* args) | |
| { | |
| int GeoId; | |
| int incr = 1; | |
| if (!PyArg_ParseTuple(args, "i|i", &GeoId, &incr)) { | |
| return nullptr; | |
| } | |
| if (!this->getSketchObjectPtr()->increaseBSplineDegree(GeoId, incr)) { | |
| std::stringstream str; | |
| str << "Degree increase failed for: " << GeoId; | |
| PyErr_SetString(PyExc_ValueError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| Py_Return; | |
| } | |
| PyObject* SketchObjectPy::decreaseBSplineDegree(PyObject* args) | |
| { | |
| int GeoId; | |
| int decr = 1; | |
| if (!PyArg_ParseTuple(args, "i|i", &GeoId, &decr)) { | |
| return nullptr; | |
| } | |
| bool ok = this->getSketchObjectPtr()->decreaseBSplineDegree(GeoId, decr); | |
| return Py_BuildValue("O", (ok ? Py_True : Py_False)); | |
| } | |
| PyObject* SketchObjectPy::modifyBSplineKnotMultiplicity(PyObject* args) | |
| { | |
| int GeoId; | |
| int knotIndex; | |
| int multiplicity = 1; | |
| if (!PyArg_ParseTuple(args, "ii|i", &GeoId, &knotIndex, &multiplicity)) { | |
| return nullptr; | |
| } | |
| if (!this->getSketchObjectPtr()->modifyBSplineKnotMultiplicity(GeoId, knotIndex, multiplicity)) { | |
| std::stringstream str; | |
| str << "Multiplicity modification failed for: " << GeoId; | |
| PyErr_SetString(PyExc_ValueError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| Py_Return; | |
| } | |
| PyObject* SketchObjectPy::insertBSplineKnot(PyObject* args) | |
| { | |
| int GeoId; | |
| double knotParam; | |
| int multiplicity = 1; | |
| if (!PyArg_ParseTuple(args, "id|i", &GeoId, &knotParam, &multiplicity)) { | |
| return nullptr; | |
| } | |
| if (!this->getSketchObjectPtr()->insertBSplineKnot(GeoId, knotParam, multiplicity)) { | |
| std::stringstream str; | |
| str << "Knot insertion failed for: " << GeoId; | |
| PyErr_SetString(PyExc_ValueError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| Py_Return; | |
| } | |
| PyObject* SketchObjectPy::autoconstraint(PyObject* args) | |
| { | |
| double precision = Precision::Confusion() * 1000; | |
| double angleprecision = std::numbers::pi / 8; | |
| PyObject* includeconstruction = Py_True; | |
| if (!PyArg_ParseTuple(args, "|ddO!", &precision, &angleprecision, &PyBool_Type, &includeconstruction)) { | |
| return nullptr; | |
| } | |
| if (this->getSketchObjectPtr() | |
| ->autoConstraint(precision, angleprecision, Base::asBoolean(includeconstruction))) { | |
| std::stringstream str; | |
| str << "Unable to autoconstraint"; | |
| PyErr_SetString(PyExc_ValueError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| Py_Return; | |
| } | |
| PyObject* SketchObjectPy::detectMissingPointOnPointConstraints(PyObject* args) | |
| { | |
| double precision = Precision::Confusion() * 1000; | |
| PyObject* includeconstruction = Py_True; | |
| if (!PyArg_ParseTuple(args, "|dO!", &precision, &PyBool_Type, &includeconstruction)) { | |
| return nullptr; | |
| } | |
| return Py::new_reference_to( | |
| Py::Long(this->getSketchObjectPtr()->detectMissingPointOnPointConstraints( | |
| precision, | |
| Base::asBoolean(includeconstruction) | |
| )) | |
| ); | |
| } | |
| PyObject* SketchObjectPy::detectMissingVerticalHorizontalConstraints(PyObject* args) | |
| { | |
| double angleprecision = std::numbers::pi / 8; | |
| if (!PyArg_ParseTuple(args, "|d", &angleprecision)) { | |
| return nullptr; | |
| } | |
| return Py::new_reference_to( | |
| Py::Long(this->getSketchObjectPtr()->detectMissingVerticalHorizontalConstraints(angleprecision)) | |
| ); | |
| } | |
| PyObject* SketchObjectPy::detectMissingEqualityConstraints(PyObject* args) | |
| { | |
| double precision = Precision::Confusion() * 1000; | |
| if (!PyArg_ParseTuple(args, "|d", &precision)) { | |
| return nullptr; | |
| } | |
| return Py::new_reference_to( | |
| Py::Long(this->getSketchObjectPtr()->detectMissingEqualityConstraints(precision)) | |
| ); | |
| } | |
| PyObject* SketchObjectPy::analyseMissingPointOnPointCoincident(PyObject* args) | |
| { | |
| double angleprecision = std::numbers::pi / 8; | |
| if (!PyArg_ParseTuple(args, "|d", &angleprecision)) { | |
| return nullptr; | |
| } | |
| this->getSketchObjectPtr()->analyseMissingPointOnPointCoincident(angleprecision); | |
| Py_Return; | |
| } | |
| PyObject* SketchObjectPy::makeMissingPointOnPointCoincident(PyObject* args) | |
| { | |
| PyObject* onebyone = Py_False; | |
| if (!PyArg_ParseTuple(args, "|O!", &PyBool_Type, &onebyone)) { | |
| return nullptr; | |
| } | |
| this->getSketchObjectPtr()->makeMissingPointOnPointCoincident(Base::asBoolean(onebyone)); | |
| Py_Return; | |
| } | |
| PyObject* SketchObjectPy::makeMissingVerticalHorizontal(PyObject* args) | |
| { | |
| PyObject* onebyone = Py_False; | |
| if (!PyArg_ParseTuple(args, "|O!", &PyBool_Type, &onebyone)) { | |
| return nullptr; | |
| } | |
| this->getSketchObjectPtr()->makeMissingVerticalHorizontal(Base::asBoolean(onebyone)); | |
| Py_Return; | |
| } | |
| PyObject* SketchObjectPy::makeMissingEquality(PyObject* args) | |
| { | |
| PyObject* onebyone = Py_True; | |
| if (!PyArg_ParseTuple(args, "|O!", &PyBool_Type, &onebyone)) { | |
| return nullptr; | |
| } | |
| this->getSketchObjectPtr()->makeMissingEquality(Base::asBoolean(onebyone)); | |
| Py_Return; | |
| } | |
| PyObject* SketchObjectPy::evaluateConstraints() const | |
| { | |
| bool ok = this->getSketchObjectPtr()->evaluateConstraints(); | |
| return Py::new_reference_to(Py::Boolean(ok)); | |
| } | |
| PyObject* SketchObjectPy::validateConstraints() | |
| { | |
| this->getSketchObjectPtr()->validateConstraints(); | |
| Py_Return; | |
| } | |
| PyObject* SketchObjectPy::autoRemoveRedundants(PyObject* args) | |
| { | |
| PyObject* updategeo = Py_True; | |
| if (!PyArg_ParseTuple(args, "|O!", &PyBool_Type, &updategeo)) { | |
| return nullptr; | |
| } | |
| this->getSketchObjectPtr()->autoRemoveRedundants( | |
| Base::asBoolean(updategeo) ? DeleteOption::UpdateGeometry : DeleteOption::NoFlag | |
| ); | |
| Py_Return; | |
| } | |
| PyObject* SketchObjectPy::toPythonCommands(PyObject* args) | |
| { | |
| if (!PyArg_ParseTuple(args, "")) { | |
| return nullptr; | |
| } | |
| auto sketch = this->getSketchObjectPtr(); | |
| std::string geometry = PythonConverter::convert("ActiveSketch", sketch->Geometry.getValues()); | |
| std::string constraints = PythonConverter::convert("ActiveSketch", sketch->Constraints.getValues()); | |
| auto geometrymulti = PythonConverter::multiLine(std::move(geometry)); | |
| auto constraintmulti = PythonConverter::multiLine(std::move(constraints)); | |
| size_t numelements = geometrymulti.size() + constraintmulti.size(); | |
| Py::Tuple tuple(numelements); | |
| std::size_t i = 0; | |
| for (const auto& str : geometrymulti) { | |
| tuple.setItem(i, Py::String(str)); | |
| i++; | |
| } | |
| for (const auto& str : constraintmulti) { | |
| tuple.setItem(i, Py::String(str)); | |
| i++; | |
| } | |
| return Py::new_reference_to(tuple); | |
| } | |
| Py::List SketchObjectPy::getMissingPointOnPointConstraints() const | |
| { | |
| std::vector<ConstraintIds> constraints | |
| = this->getSketchObjectPtr()->getMissingPointOnPointConstraints(); | |
| Py::List list; | |
| for (auto c : constraints) { | |
| Py::Tuple t(5); | |
| t.setItem(0, Py::Long(c.First)); | |
| t.setItem( | |
| 1, | |
| Py::Long( | |
| ((c.FirstPos == Sketcher::PointPos::none) ? 0 | |
| : (c.FirstPos == Sketcher::PointPos::start) ? 1 | |
| : (c.FirstPos == Sketcher::PointPos::end) ? 2 | |
| : 3) | |
| ) | |
| ); | |
| t.setItem(2, Py::Long(c.Second)); | |
| t.setItem( | |
| 3, | |
| Py::Long( | |
| ((c.SecondPos == Sketcher::PointPos::none) ? 0 | |
| : (c.SecondPos == Sketcher::PointPos::start) ? 1 | |
| : (c.SecondPos == Sketcher::PointPos::end) ? 2 | |
| : 3) | |
| ) | |
| ); | |
| t.setItem(4, Py::Long(c.Type)); | |
| list.append(t); | |
| } | |
| return list; | |
| } | |
| void SketchObjectPy::setMissingPointOnPointConstraints(Py::List arg) | |
| { | |
| std::vector<ConstraintIds> constraints; | |
| auto checkpos = [](Py::Tuple& t, int i) { | |
| auto checkitem = [](Py::Tuple& t, int i, int val) { | |
| return long(Py::Long(t.getItem(i))) == val; | |
| }; | |
| return ( | |
| checkitem(t, i, 0) | |
| ? Sketcher::PointPos::none | |
| : (checkitem(t, i, 1) | |
| ? Sketcher::PointPos::start | |
| : (checkitem(t, i, 2) ? Sketcher::PointPos::end : Sketcher::PointPos::mid)) | |
| ); | |
| }; | |
| for (const auto& ti : arg) { | |
| Py::Tuple t(ti); | |
| ConstraintIds c; | |
| c.First = static_cast<long>(Py::Long(t.getItem(0))); | |
| c.FirstPos = checkpos(t, 1); | |
| c.Second = static_cast<long>(Py::Long(t.getItem(2))); | |
| c.SecondPos = checkpos(t, 3); | |
| c.Type = static_cast<Sketcher::ConstraintType>(static_cast<long>(Py::Long(t.getItem(4)))); | |
| constraints.push_back(c); | |
| } | |
| this->getSketchObjectPtr()->setMissingPointOnPointConstraints(constraints); | |
| } | |
| Py::List SketchObjectPy::getMissingVerticalHorizontalConstraints() const | |
| { | |
| std::vector<ConstraintIds> constraints | |
| = this->getSketchObjectPtr()->getMissingVerticalHorizontalConstraints(); | |
| Py::List list; | |
| for (auto c : constraints) { | |
| Py::Tuple t(5); | |
| t.setItem(0, Py::Long(c.First)); | |
| t.setItem( | |
| 1, | |
| Py::Long( | |
| ((c.FirstPos == Sketcher::PointPos::none) ? 0 | |
| : (c.FirstPos == Sketcher::PointPos::start) ? 1 | |
| : (c.FirstPos == Sketcher::PointPos::end) ? 2 | |
| : 3) | |
| ) | |
| ); | |
| t.setItem(2, Py::Long(c.Second)); | |
| t.setItem( | |
| 3, | |
| Py::Long( | |
| ((c.SecondPos == Sketcher::PointPos::none) ? 0 | |
| : (c.SecondPos == Sketcher::PointPos::start) ? 1 | |
| : (c.SecondPos == Sketcher::PointPos::end) ? 2 | |
| : 3) | |
| ) | |
| ); | |
| t.setItem(4, Py::Long(c.Type)); | |
| list.append(t); | |
| } | |
| return list; | |
| } | |
| void SketchObjectPy::setMissingVerticalHorizontalConstraints(Py::List arg) | |
| { | |
| std::vector<ConstraintIds> constraints; | |
| auto checkpos = [](Py::Tuple& t, int i) { | |
| auto checkitem = [](Py::Tuple& t, int i, int val) { | |
| return long(Py::Long(t.getItem(i))) == val; | |
| }; | |
| return ( | |
| checkitem(t, i, 0) | |
| ? Sketcher::PointPos::none | |
| : (checkitem(t, i, 1) | |
| ? Sketcher::PointPos::start | |
| : (checkitem(t, i, 2) ? Sketcher::PointPos::end : Sketcher::PointPos::mid)) | |
| ); | |
| }; | |
| for (const auto& ti : arg) { | |
| Py::Tuple t(ti); | |
| ConstraintIds c; | |
| c.First = static_cast<long>(Py::Long(t.getItem(0))); | |
| c.FirstPos = checkpos(t, 1); | |
| c.Second = static_cast<long>(Py::Long(t.getItem(2))); | |
| c.SecondPos = checkpos(t, 3); | |
| c.Type = static_cast<Sketcher::ConstraintType>(static_cast<long>(Py::Long(t.getItem(4)))); | |
| constraints.push_back(c); | |
| } | |
| this->getSketchObjectPtr()->setMissingVerticalHorizontalConstraints(constraints); | |
| } | |
| Py::List SketchObjectPy::getMissingLineEqualityConstraints() const | |
| { | |
| std::vector<ConstraintIds> constraints | |
| = this->getSketchObjectPtr()->getMissingLineEqualityConstraints(); | |
| Py::List list; | |
| for (auto c : constraints) { | |
| Py::Tuple t(4); | |
| t.setItem(0, Py::Long(c.First)); | |
| t.setItem( | |
| 1, | |
| Py::Long( | |
| ((c.FirstPos == Sketcher::PointPos::none) ? 0 | |
| : (c.FirstPos == Sketcher::PointPos::start) ? 1 | |
| : (c.FirstPos == Sketcher::PointPos::end) ? 2 | |
| : 3) | |
| ) | |
| ); | |
| t.setItem(2, Py::Long(c.Second)); | |
| t.setItem( | |
| 3, | |
| Py::Long( | |
| ((c.SecondPos == Sketcher::PointPos::none) ? 0 | |
| : (c.SecondPos == Sketcher::PointPos::start) ? 1 | |
| : (c.SecondPos == Sketcher::PointPos::end) ? 2 | |
| : 3) | |
| ) | |
| ); | |
| list.append(t); | |
| } | |
| return list; | |
| } | |
| void SketchObjectPy::setMissingLineEqualityConstraints(Py::List arg) | |
| { | |
| std::vector<ConstraintIds> constraints; | |
| auto checkpos = [](Py::Tuple& t, int i) { | |
| auto checkitem = [](Py::Tuple& t, int i, int val) { | |
| return long(Py::Long(t.getItem(i))) == val; | |
| }; | |
| return ( | |
| checkitem(t, i, 0) | |
| ? Sketcher::PointPos::none | |
| : (checkitem(t, i, 1) | |
| ? Sketcher::PointPos::start | |
| : (checkitem(t, i, 2) ? Sketcher::PointPos::end : Sketcher::PointPos::mid)) | |
| ); | |
| }; | |
| for (const auto& ti : arg) { | |
| Py::Tuple t(ti); | |
| ConstraintIds c; | |
| c.First = (long)Py::Long(t.getItem(0)); | |
| c.FirstPos = checkpos(t, 1); | |
| c.Second = (long)Py::Long(t.getItem(2)); | |
| c.SecondPos = checkpos(t, 3); | |
| c.Type = Sketcher::Equal; | |
| constraints.push_back(c); | |
| } | |
| this->getSketchObjectPtr()->setMissingLineEqualityConstraints(constraints); | |
| } | |
| Py::List SketchObjectPy::getMissingRadiusConstraints() const | |
| { | |
| std::vector<ConstraintIds> constraints = this->getSketchObjectPtr()->getMissingRadiusConstraints(); | |
| Py::List list; | |
| for (auto c : constraints) { | |
| Py::Tuple t(4); | |
| t.setItem(0, Py::Long(c.First)); | |
| t.setItem( | |
| 1, | |
| Py::Long( | |
| ((c.FirstPos == Sketcher::PointPos::none) ? 0 | |
| : (c.FirstPos == Sketcher::PointPos::start) ? 1 | |
| : (c.FirstPos == Sketcher::PointPos::end) ? 2 | |
| : 3) | |
| ) | |
| ); | |
| t.setItem(2, Py::Long(c.Second)); | |
| t.setItem( | |
| 3, | |
| Py::Long( | |
| ((c.SecondPos == Sketcher::PointPos::none) ? 0 | |
| : (c.SecondPos == Sketcher::PointPos::start) ? 1 | |
| : (c.SecondPos == Sketcher::PointPos::end) ? 2 | |
| : 3) | |
| ) | |
| ); | |
| list.append(t); | |
| } | |
| return list; | |
| } | |
| void SketchObjectPy::setMissingRadiusConstraints(Py::List arg) | |
| { | |
| std::vector<ConstraintIds> constraints; | |
| auto checkpos = [](Py::Tuple& t, int i) { | |
| auto checkitem = [](Py::Tuple& t, int i, int val) { | |
| return long(Py::Long(t.getItem(i))) == val; | |
| }; | |
| return ( | |
| checkitem(t, i, 0) | |
| ? Sketcher::PointPos::none | |
| : (checkitem(t, i, 1) | |
| ? Sketcher::PointPos::start | |
| : (checkitem(t, i, 2) ? Sketcher::PointPos::end : Sketcher::PointPos::mid)) | |
| ); | |
| }; | |
| for (const auto& ti : arg) { | |
| Py::Tuple t(ti); | |
| ConstraintIds c; | |
| c.First = (long)Py::Long(t.getItem(0)); | |
| c.FirstPos = checkpos(t, 1); | |
| c.Second = (long)Py::Long(t.getItem(2)); | |
| c.SecondPos = checkpos(t, 3); | |
| c.Type = Sketcher::Equal; | |
| constraints.push_back(c); | |
| } | |
| this->getSketchObjectPtr()->setMissingRadiusConstraints(constraints); | |
| } | |
| PyObject* SketchObjectPy::getGeometryWithDependentParameters(PyObject* args) | |
| { | |
| if (!PyArg_ParseTuple(args, "")) { | |
| return nullptr; | |
| } | |
| std::vector<std::pair<int, PointPos>> geometrymap; | |
| this->getSketchObjectPtr()->getGeometryWithDependentParameters(geometrymap); | |
| Py::List list; | |
| for (auto pair : geometrymap) { | |
| Py::Tuple t(2); | |
| t.setItem(0, Py::Long(pair.first)); | |
| t.setItem( | |
| 1, | |
| Py::Long( | |
| ((pair.second == Sketcher::PointPos::none) ? 0 | |
| : (pair.second == Sketcher::PointPos::start) ? 1 | |
| : (pair.second == Sketcher::PointPos::end) ? 2 | |
| : 3) | |
| ) | |
| ); | |
| list.append(t); | |
| } | |
| return Py::new_reference_to(list); | |
| } | |
| Py::List SketchObjectPy::getOpenVertices() const | |
| { | |
| std::vector<Base::Vector3d> points = this->getSketchObjectPtr()->getOpenVertices(); | |
| Py::List list; | |
| for (auto p : points) { | |
| Py::Tuple t(3); | |
| t.setItem(0, Py::Float(p.x)); | |
| t.setItem(1, Py::Float(p.y)); | |
| t.setItem(2, Py::Float(p.z)); | |
| list.append(t); | |
| } | |
| return list; | |
| } | |
| Py::Long SketchObjectPy::getConstraintCount() const | |
| { | |
| return Py::Long(this->getSketchObjectPtr()->Constraints.getSize()); | |
| } | |
| Py::Long SketchObjectPy::getGeometryCount() const | |
| { | |
| return Py::Long(this->getSketchObjectPtr()->Geometry.getSize()); | |
| } | |
| Py::Long SketchObjectPy::getAxisCount() const | |
| { | |
| return Py::Long(this->getSketchObjectPtr()->getAxisCount()); | |
| } | |
| Py::List SketchObjectPy::getGeometryFacadeList() const | |
| { | |
| Py::List list; | |
| for (int i = 0; i < getSketchObjectPtr()->Geometry.getSize(); i++) { | |
| // we create a python copy and add it to the list | |
| std::unique_ptr<GeometryFacade> geofacade = GeometryFacade::getFacade( | |
| getSketchObjectPtr()->Geometry[i]->clone() | |
| ); | |
| geofacade->setOwner(true); | |
| Py::Object gfp = Py::Object(new GeometryFacadePy(geofacade.release()), true); | |
| list.append(gfp); | |
| } | |
| return list; | |
| } | |
| void SketchObjectPy::setGeometryFacadeList(Py::List value) | |
| { | |
| std::vector<Part::Geometry*> list; | |
| list.reserve(value.size()); | |
| for (const auto& ti : value) { | |
| if (PyObject_TypeCheck(ti.ptr(), &(GeometryFacadePy::Type))) { | |
| GeometryFacadePy* gfp = static_cast<GeometryFacadePy*>(ti.ptr()); | |
| GeometryFacade* gf = gfp->getGeometryFacadePtr(); | |
| Part::Geometry* geo = gf->getGeometry()->clone(); | |
| list.push_back(geo); | |
| } | |
| } | |
| getSketchObjectPtr()->Geometry.setValues(std::move(list)); | |
| } | |
| PyObject* SketchObjectPy::getGeometryId(PyObject* args) | |
| { | |
| int Index; | |
| if (!PyArg_ParseTuple(args, "i", &Index)) { | |
| return nullptr; | |
| } | |
| long Id; | |
| if (this->getSketchObjectPtr()->getGeometryId(Index, Id)) { | |
| std::stringstream str; | |
| str << "Not able to get geometry Id of a geometry with the given index: " << Index; | |
| PyErr_SetString(PyExc_ValueError, str.str().c_str()); | |
| Py_Return; | |
| } | |
| return Py::new_reference_to(Py::Long(Id)); | |
| } | |
| PyObject* SketchObjectPy::setGeometryId(PyObject* args) | |
| { | |
| int Index; | |
| long Id; | |
| if (!PyArg_ParseTuple(args, "il", &Index, &Id)) { | |
| return nullptr; | |
| } | |
| if (this->getSketchObjectPtr()->setGeometryId(Index, Id)) { | |
| std::stringstream str; | |
| str << "Not able to set geometry Id of a geometry with the given index: " << Index; | |
| PyErr_SetString(PyExc_ValueError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| Py_Return; | |
| } | |
| PyObject* SketchObjectPy::setGeometryIds(PyObject* args) | |
| { | |
| PyObject* pyList; | |
| // Parse arguments: list of pairs, Base::VectorPy, optional relative flag | |
| if (!PyArg_ParseTuple(args, "O!", &PyList_Type, &pyList)) { | |
| return nullptr; | |
| } | |
| // Convert Python list to std::vector<std::pair<int, long>> | |
| std::vector<std::pair<int, long>> geoIdsToIds; | |
| Py_ssize_t listSize = PyList_Size(pyList); | |
| for (Py_ssize_t i = 0; i < listSize; ++i) { | |
| PyObject* pyPair = PyList_GetItem(pyList, i); // Borrowed reference | |
| if (!PyTuple_Check(pyPair) || PyTuple_Size(pyPair) != 2) { | |
| PyErr_SetString(PyExc_ValueError, "List must contain pairs (geoId, id)."); | |
| return nullptr; | |
| } | |
| int geoId = PyLong_AsLong(PyTuple_GetItem(pyPair, 0)); | |
| long id = PyLong_AsLong(PyTuple_GetItem(pyPair, 1)); | |
| if (PyErr_Occurred()) { | |
| PyErr_SetString(PyExc_ValueError, "Invalid geoId or id in the list."); | |
| return nullptr; | |
| } | |
| geoIdsToIds.emplace_back(geoId, id); | |
| } | |
| // Call the C++ method | |
| if (this->getSketchObjectPtr()->setGeometryIds(geoIdsToIds)) { | |
| std::stringstream str; | |
| str << "Not able to set geometry Ids of geometries with the given indices: "; | |
| PyErr_SetString(PyExc_ValueError, str.str().c_str()); | |
| return nullptr; | |
| } | |
| Py_Return; | |
| } | |
| Py::Long SketchObjectPy::getDoF() const | |
| { | |
| auto dofs = this->getSketchObjectPtr()->getLastDoF(); | |
| return Py::Long(dofs); | |
| } | |
| Py::List SketchObjectPy::getConflictingConstraints() const | |
| { | |
| auto conflictinglist = this->getSketchObjectPtr()->getLastConflicting(); | |
| Py::List conflicting; | |
| for (auto cid : conflictinglist) { | |
| conflicting.append(Py::Long(cid)); | |
| } | |
| return conflicting; | |
| } | |
| Py::List SketchObjectPy::getRedundantConstraints() const | |
| { | |
| auto redundantlist = this->getSketchObjectPtr()->getLastRedundant(); | |
| Py::List redundant; | |
| for (auto cid : redundantlist) { | |
| redundant.append(Py::Long(cid)); | |
| } | |
| return redundant; | |
| } | |
| Py::List SketchObjectPy::getPartiallyRedundantConstraints() const | |
| { | |
| auto redundantlist = this->getSketchObjectPtr()->getLastPartiallyRedundant(); | |
| Py::List redundant; | |
| for (auto cid : redundantlist) { | |
| redundant.append(Py::Long(cid)); | |
| } | |
| return redundant; | |
| } | |
| Py::List SketchObjectPy::getMalformedConstraints() const | |
| { | |
| auto malformedlist = this->getSketchObjectPtr()->getLastMalformedConstraints(); | |
| Py::List malformed; | |
| for (auto cid : malformedlist) { | |
| malformed.append(Py::Long(cid)); | |
| } | |
| return malformed; | |
| } | |
| PyObject* SketchObjectPy::getCustomAttributes(const char* /*attr*/) const | |
| { | |
| return nullptr; | |
| } | |
| int SketchObjectPy::setCustomAttributes(const char* attr, PyObject* obj) | |
| { | |
| // search in PropertyList | |
| App::Property* prop = getSketchObjectPtr()->getPropertyByName(attr); | |
| if (prop) { | |
| // Read-only attributes must not be set over its Python interface | |
| short Type = getSketchObjectPtr()->getPropertyType(prop); | |
| if (Type & App::Prop_ReadOnly) { | |
| std::stringstream s; | |
| s << "Object attribute '" << attr << "' is read-only"; | |
| throw Py::AttributeError(s.str()); | |
| } | |
| prop->setPyObject(obj); | |
| if (strcmp(attr, "Geometry") == 0) { | |
| getSketchObjectPtr()->rebuildVertexIndex(); | |
| } | |
| return 1; | |
| } | |
| return 0; | |
| } | |