- ArcOfEllipse enhancement: Tangency ArcOfEllipse to ArcOfEllipse or ArcOfCircle by selecting end/starting points... - Minor bug corrections (Thanks DeepSOIC) - ExposeInternalGeometry python command - DeleteUnusedInternalGeometry python command - On deletion of an Ellipse/ArcOfEllipse all further unconstrained internal geometry is also deleted. - This cleans up the code by eliminating code repetition in the creation methods. - Major bug fix for autoconstraints for ellipse and arc of ellipse creation (for both creation methods) - Major bug fix Start and Endpoint constraints of an arc of ellipse where not taking into account that Sketcher arcs are always CCW, so they have to be exchanged if we convert a CW arc into a CCW arc. Sketcher: General bug fix: Tangency wrongly suggested What? ===== - On creation of a shape autoconstraints are suggested. - Tangent autoconstraint was suggested even with lines perpendicular to the tangency direction Reproduce ========= - Make a circle on the origin and move the mouse along the X axis, it will suggest a tangency that is impossible - Click on the axis and no circle will be created Solution ======== - The SeekConstraint now can use the parameter dir to give a direction that is substantially perpendicular to the expected tangency, so that if an object having a direction (a line) is hit, a tangency will not be suggested if within around 6 degrees of being parallel. - Additionally, if such a line is an X,Y axis of the sketch, tangency will only be suggested if the direction is within 6 degrees of being perpendicular (i.e. it is almost tangent already while sketching). - This difference is due to the fact that an X or Y axis can not "move" to meet the object under creation, whereas a line can.
676 lines
24 KiB
C++
676 lines
24 KiB
C++
/***************************************************************************
|
|
* Copyright (c) Jürgen Riegel (juergen.riegel@web.de) 2010 *
|
|
* *
|
|
* This file is part of the FreeCAD CAx development system. *
|
|
* *
|
|
* This library is free software; you can redistribute it and/or *
|
|
* modify it under the terms of the GNU Library General Public *
|
|
* License as published by the Free Software Foundation; either *
|
|
* version 2 of the License, or (at your option) any later version. *
|
|
* *
|
|
* This library is distributed in the hope that it will be useful, *
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
* GNU Library General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the GNU Library General Public *
|
|
* License along with this library; see the file COPYING.LIB. If not, *
|
|
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
|
* Suite 330, Boston, MA 02111-1307, USA *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
#include "PreCompiled.h"
|
|
#ifndef _PreComp_
|
|
# include <sstream>
|
|
# include <Geom_TrimmedCurve.hxx>
|
|
#endif
|
|
|
|
#include <boost/shared_ptr.hpp>
|
|
|
|
#include <Mod/Sketcher/App/SketchObject.h>
|
|
#include <Mod/Part/App/LinePy.h>
|
|
#include <Mod/Part/App/Geometry.h>
|
|
#include <Base/GeometryPyCXX.h>
|
|
#include <Base/VectorPy.h>
|
|
#include <Base/AxisPy.h>
|
|
#include <Base/Tools.h>
|
|
#include <Base/QuantityPy.h>
|
|
#include <App/Document.h>
|
|
#include <CXX/Objects.hxx>
|
|
|
|
// inclusion of the generated files (generated out of SketchObjectSFPy.xml)
|
|
#include "SketchObjectPy.h"
|
|
#include "SketchObjectPy.cpp"
|
|
// other python types
|
|
#include "ConstraintPy.h"
|
|
|
|
using namespace Sketcher;
|
|
|
|
// returns a string which represents the object e.g. when printed in python
|
|
std::string SketchObjectPy::representation(void) const
|
|
{
|
|
return "<Sketcher::SketchObject>";
|
|
}
|
|
|
|
|
|
PyObject* SketchObjectPy::solve(PyObject *args)
|
|
{
|
|
if (!PyArg_ParseTuple(args, ""))
|
|
return 0;
|
|
int ret = this->getSketchObjectPtr()->solve();
|
|
return Py_BuildValue("i", ret);
|
|
}
|
|
|
|
PyObject* SketchObjectPy::addGeometry(PyObject *args)
|
|
{
|
|
PyObject *pcObj;
|
|
if (!PyArg_ParseTuple(args, "O", &pcObj))
|
|
return 0;
|
|
|
|
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->getTypeId() == Part::GeomTrimmedCurve::getClassTypeId()) {
|
|
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);
|
|
}
|
|
else if (!ellipse.IsNull()) {
|
|
// create the definition struct for that geom
|
|
Part::GeomArcOfEllipse aoe;
|
|
aoe.setHandle(trim);
|
|
ret = this->getSketchObjectPtr()->addGeometry(&aoe);
|
|
}
|
|
else {
|
|
std::stringstream str;
|
|
str << "Unsupported geometry type: " << geo->getTypeId().getName();
|
|
PyErr_SetString(PyExc_TypeError, str.str().c_str());
|
|
return 0;
|
|
}
|
|
}
|
|
else if (geo->getTypeId() == Part::GeomPoint::getClassTypeId() ||
|
|
geo->getTypeId() == Part::GeomCircle::getClassTypeId() ||
|
|
geo->getTypeId() == Part::GeomEllipse::getClassTypeId() ||
|
|
geo->getTypeId() == Part::GeomArcOfCircle::getClassTypeId() ||
|
|
geo->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId() ||
|
|
geo->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
|
|
ret = this->getSketchObjectPtr()->addGeometry(geo);
|
|
}
|
|
else {
|
|
std::stringstream str;
|
|
str << "Unsupported geometry type: " << geo->getTypeId().getName();
|
|
PyErr_SetString(PyExc_TypeError, str.str().c_str());
|
|
return 0;
|
|
}
|
|
return Py::new_reference_to(Py::Int(ret));
|
|
}
|
|
else if (PyObject_TypeCheck(pcObj, &(PyList_Type)) ||
|
|
PyObject_TypeCheck(pcObj, &(PyTuple_Type))) {
|
|
std::vector<Part::Geometry *> geoList;
|
|
std::vector<boost::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->getTypeId() == Part::GeomTrimmedCurve::getClassTypeId()) {
|
|
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
|
|
boost::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
|
|
boost::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 0;
|
|
}
|
|
}
|
|
else if (geo->getTypeId() == Part::GeomPoint::getClassTypeId() ||
|
|
geo->getTypeId() == Part::GeomCircle::getClassTypeId() ||
|
|
geo->getTypeId() == Part::GeomEllipse::getClassTypeId() ||
|
|
geo->getTypeId() == Part::GeomArcOfCircle::getClassTypeId() ||
|
|
geo->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId() ||
|
|
geo->getTypeId() == Part::GeomLineSegment::getClassTypeId()) {
|
|
geoList.push_back(geo);
|
|
}
|
|
else {
|
|
std::stringstream str;
|
|
str << "Unsupported geometry type: " << geo->getTypeId().getName();
|
|
PyErr_SetString(PyExc_TypeError, str.str().c_str());
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
int ret = this->getSketchObjectPtr()->addGeometry(geoList) + 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::Int(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;
|
|
if (!PyArg_ParseTuple(args, "i", &Index))
|
|
return 0;
|
|
|
|
if (this->getSketchObjectPtr()->delGeometry(Index)) {
|
|
std::stringstream str;
|
|
str << "Not able to delete a geometry with the given index: " << Index;
|
|
PyErr_SetString(PyExc_ValueError, str.str().c_str());
|
|
return 0;
|
|
}
|
|
|
|
Py_Return;
|
|
}
|
|
|
|
PyObject* SketchObjectPy::toggleConstruction(PyObject *args)
|
|
{
|
|
int Index;
|
|
if (!PyArg_ParseTuple(args, "i", &Index))
|
|
return 0;
|
|
|
|
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 0;
|
|
}
|
|
|
|
Py_Return;
|
|
}
|
|
|
|
PyObject* SketchObjectPy::setConstruction(PyObject *args)
|
|
{
|
|
int Index;
|
|
PyObject *Mode;
|
|
if (!PyArg_ParseTuple(args, "iO!", &Index, &PyBool_Type, &Mode))
|
|
return 0;
|
|
|
|
if (this->getSketchObjectPtr()->setConstruction(Index, PyObject_IsTrue(Mode) ? true : false)) {
|
|
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 0;
|
|
}
|
|
|
|
Py_Return;
|
|
}
|
|
|
|
PyObject* SketchObjectPy::addConstraint(PyObject *args)
|
|
{
|
|
PyObject *pcObj;
|
|
if (!PyArg_ParseTuple(args, "O", &pcObj))
|
|
return 0;
|
|
|
|
if (PyObject_TypeCheck(pcObj, &(Sketcher::ConstraintPy::Type))) {
|
|
Sketcher::Constraint *constr = static_cast<Sketcher::ConstraintPy*>(pcObj)->getConstraintPtr();
|
|
int ret = this->getSketchObjectPtr()->addConstraint(constr);
|
|
this->getSketchObjectPtr()->solve();
|
|
return Py::new_reference_to(Py::Int(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);
|
|
}
|
|
}
|
|
|
|
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::Int(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;
|
|
if (!PyArg_ParseTuple(args, "i", &Index))
|
|
return 0;
|
|
|
|
if (this->getSketchObjectPtr()->delConstraint(Index)) {
|
|
std::stringstream str;
|
|
str << "Not able to delete a constraint with the given index: " << Index;
|
|
PyErr_SetString(PyExc_ValueError, str.str().c_str());
|
|
return 0;
|
|
}
|
|
|
|
Py_Return;
|
|
}
|
|
|
|
PyObject* SketchObjectPy::renameConstraint(PyObject *args)
|
|
{
|
|
int Index;
|
|
char* Name;
|
|
if (!PyArg_ParseTuple(args, "is", &Index, &Name))
|
|
return 0;
|
|
|
|
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 0;
|
|
}
|
|
|
|
Constraint* copy = this->getSketchObjectPtr()->Constraints[Index]->clone();
|
|
copy->Name = Name;
|
|
this->getSketchObjectPtr()->Constraints.set1Value(Index, copy);
|
|
delete copy;
|
|
|
|
Py_Return;
|
|
}
|
|
|
|
PyObject* SketchObjectPy::addExternal(PyObject *args)
|
|
{
|
|
char *ObjectName;
|
|
char *SubName;
|
|
if (!PyArg_ParseTuple(args, "ss:Give an object and subelement name", &ObjectName,&SubName))
|
|
return 0;
|
|
|
|
// get the target object for the external link
|
|
App::DocumentObject * Obj = this->getSketchObjectPtr()->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 0;
|
|
}
|
|
// check if it belongs to the sketch support
|
|
if (this->getSketchObjectPtr()->Support.getValue() != Obj) {
|
|
std::stringstream str;
|
|
str << ObjectName << "is not supported by this sketch";
|
|
PyErr_SetString(PyExc_ValueError, str.str().c_str());
|
|
return 0;
|
|
}
|
|
|
|
// add the external
|
|
if (this->getSketchObjectPtr()->addExternal(Obj,SubName) < 0) {
|
|
std::stringstream str;
|
|
str << "Not able to add external shape element";
|
|
PyErr_SetString(PyExc_ValueError, str.str().c_str());
|
|
return 0;
|
|
}
|
|
|
|
Py_Return;
|
|
}
|
|
|
|
PyObject* SketchObjectPy::delExternal(PyObject *args)
|
|
{
|
|
int Index;
|
|
if (!PyArg_ParseTuple(args, "i", &Index))
|
|
return 0;
|
|
|
|
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 0;
|
|
}
|
|
|
|
Py_Return;
|
|
}
|
|
|
|
PyObject* SketchObjectPy::delConstraintOnPoint(PyObject *args)
|
|
{
|
|
int Index;
|
|
if (!PyArg_ParseTuple(args, "i", &Index))
|
|
return 0;
|
|
|
|
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 0;
|
|
}
|
|
|
|
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 0;
|
|
}
|
|
}
|
|
|
|
// 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 0;
|
|
}
|
|
}
|
|
|
|
// error handling
|
|
PyErr_SetString(PyExc_TypeError, "Wrong arguments");
|
|
return 0;
|
|
}
|
|
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 " << (const char*)Quantity.getUserString().toUtf8() << " 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
|
|
str << "Unexpected problem at setting datum " << (const char*)Quantity.getUserString().toUtf8() << " for the constraint with index " << Index;
|
|
PyErr_SetString(PyExc_ValueError, str.str().c_str());
|
|
return 0;
|
|
}
|
|
|
|
Py_Return;
|
|
}
|
|
|
|
PyObject* SketchObjectPy::movePoint(PyObject *args)
|
|
{
|
|
PyObject *pcObj;
|
|
int GeoId, PointType;
|
|
int relative=0;
|
|
|
|
if (!PyArg_ParseTuple(args, "iiO!|i", &GeoId, &PointType, &(Base::VectorPy::Type), &pcObj, &relative))
|
|
return 0;
|
|
|
|
Base::Vector3d v1 = static_cast<Base::VectorPy*>(pcObj)->value();
|
|
|
|
if (this->getSketchObjectPtr()->movePoint(GeoId,(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 0;
|
|
}
|
|
|
|
Py_Return;
|
|
|
|
}
|
|
|
|
PyObject* SketchObjectPy::getPoint(PyObject *args)
|
|
{
|
|
int GeoId, PointType;
|
|
if (!PyArg_ParseTuple(args, "ii", &GeoId, &PointType))
|
|
return 0;
|
|
|
|
if (PointType < 0 || PointType > 3) {
|
|
PyErr_SetString(PyExc_ValueError, "Invalid point type");
|
|
return 0;
|
|
}
|
|
|
|
SketchObject* obj = this->getSketchObjectPtr();
|
|
if (GeoId > obj->getHighestCurveIndex() || -GeoId > obj->getExternalGeometryCount()) {
|
|
PyErr_SetString(PyExc_ValueError, "Invalid geometry Id");
|
|
return 0;
|
|
}
|
|
|
|
return new Base::VectorPy(new Base::Vector3d(obj->getPoint(GeoId,(Sketcher::PointPos)PointType)));
|
|
}
|
|
|
|
PyObject* SketchObjectPy::getAxis(PyObject *args)
|
|
{
|
|
int AxId;
|
|
if (!PyArg_ParseTuple(args, "i", &AxId))
|
|
return 0;
|
|
|
|
return new Base::AxisPy(new Base::Axis(this->getSketchObjectPtr()->getAxis(AxId)));
|
|
}
|
|
|
|
PyObject* SketchObjectPy::fillet(PyObject *args)
|
|
{
|
|
PyObject *pcObj1, *pcObj2;
|
|
int geoId1, geoId2, posId1, trim=1;
|
|
double radius;
|
|
|
|
// Two Lines, radius
|
|
if (PyArg_ParseTuple(args, "iiO!O!d|i", &geoId1, &geoId2, &(Base::VectorPy::Type), &pcObj1, &(Base::VectorPy::Type), &pcObj2, &radius, &trim)) {
|
|
|
|
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?true:false)) {
|
|
std::stringstream str;
|
|
str << "Not able to fillet lineSegments with ids : (" << geoId1 << ", " << geoId2 << ") and points (" << v1.x << ", " << v1.y << ", " << v1.z << ") & "
|
|
<< "(" << v2.x << ", " << v2.y << ", " << v2.z << ")";
|
|
PyErr_SetString(PyExc_ValueError, str.str().c_str());
|
|
return 0;
|
|
}
|
|
Py_Return;
|
|
}
|
|
|
|
PyErr_Clear();
|
|
// Point, radius
|
|
if (PyArg_ParseTuple(args, "iid|i", &geoId1, &posId1, &radius, &trim)) {
|
|
if (this->getSketchObjectPtr()->fillet(geoId1, (Sketcher::PointPos) posId1, radius, trim?true:false)) {
|
|
std::stringstream str;
|
|
str << "Not able to fillet point with ( geoId: " << geoId1 << ", PointPos: " << posId1 << " )";
|
|
PyErr_SetString(PyExc_ValueError, str.str().c_str());
|
|
return 0;
|
|
}
|
|
Py_Return;
|
|
}
|
|
|
|
PyErr_SetString(PyExc_TypeError, "fillet() method accepts:\n"
|
|
"-- int,int,Vector,Vector,float,[int]\n"
|
|
"-- int,int,float,[int]\n");
|
|
return 0;
|
|
}
|
|
|
|
PyObject* SketchObjectPy::trim(PyObject *args)
|
|
{
|
|
PyObject *pcObj;
|
|
int GeoId;
|
|
|
|
if (!PyArg_ParseTuple(args, "iO!", &GeoId, &(Base::VectorPy::Type), &pcObj))
|
|
return 0;
|
|
|
|
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 0;
|
|
}
|
|
|
|
Py_Return;
|
|
|
|
}
|
|
|
|
PyObject* SketchObjectPy::ExposeInternalGeometry(PyObject *args)
|
|
{
|
|
int GeoId;
|
|
|
|
if (!PyArg_ParseTuple(args, "i", &GeoId))
|
|
return 0;
|
|
|
|
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 0;
|
|
}
|
|
|
|
Py_Return;
|
|
}
|
|
|
|
PyObject* SketchObjectPy::DeleteUnusedInternalGeometry(PyObject *args)
|
|
{
|
|
int GeoId;
|
|
|
|
if (!PyArg_ParseTuple(args, "i", &GeoId))
|
|
return 0;
|
|
|
|
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 0;
|
|
}
|
|
|
|
Py_Return;
|
|
}
|
|
|
|
Py::Int SketchObjectPy::getConstraintCount(void) const
|
|
{
|
|
return Py::Int(this->getSketchObjectPtr()->Constraints.getSize());
|
|
}
|
|
|
|
Py::Int SketchObjectPy::getGeometryCount(void) const
|
|
{
|
|
return Py::Int(this->getSketchObjectPtr()->Geometry.getSize());
|
|
}
|
|
|
|
Py::Int SketchObjectPy::getAxisCount(void) const
|
|
{
|
|
return Py::Int(this->getSketchObjectPtr()->getAxisCount());
|
|
}
|
|
|
|
PyObject *SketchObjectPy::getCustomAttributes(const char* /*attr*/) const
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
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;
|
|
}
|