"Professional CMake" book suggest the following: "Targets should build successfully with or without compiler support for precompiled headers. It should be considered an optimization, not a requirement. In particular, do not explicitly include a precompile header (e.g. stdafx.h) in the source code, let CMake force-include an automatically generated precompile header on the compiler command line instead. This is more portable across the major compilers and is likely to be easier to maintain. It will also avoid warnings being generated from certain code checking tools like iwyu (include what you use)." Therefore, removed the "#include <PreCompiled.h>" from sources, also there is no need for the "#ifdef _PreComp_" anymore
2689 lines
88 KiB
C++
2689 lines
88 KiB
C++
/***************************************************************************
|
|
* 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 *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
#include <memory>
|
|
#include <sstream>
|
|
|
|
#include <Geom_TrimmedCurve.hxx>
|
|
|
|
#include <App/Document.h>
|
|
#include <Base/AxisPy.h>
|
|
#include <Base/QuantityPy.h>
|
|
#include <Base/Tools.h>
|
|
#include <Base/VectorPy.h>
|
|
#include <Mod/Part/App/Geometry.h>
|
|
#include <Mod/Part/App/LinePy.h>
|
|
|
|
#include "PythonConverter.h"
|
|
|
|
// inclusion of the generated files (generated out of SketchObjectSFPy.xml)
|
|
#include "SketchObjectPy.h"
|
|
|
|
#include "SketchObjectPy.cpp"
|
|
|
|
// other python types
|
|
#include "ConstraintPy.h"
|
|
#include "GeometryFacadePy.h"
|
|
#include "SketchAnalysis.h"
|
|
|
|
|
|
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::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;
|
|
}
|