Files
create/src/Mod/Sketcher/App/SketchObjectPyImp.cpp
DeepSOIC 3838bddcdb AngleViaPoint Constraint
AngleViaPoint: fixes in UI routines + new messages

Goofed undo message in tangency via point is fixed.
Forgotten updateActive, clearSelection have been added.
New more informative error messages for tangent constraint.

AngleViaPoint: using it instead of via line tangency

* replaced the helper construction line for ellipse-to-ellipse and
similar tangency with a point. Using tangent-via-point there
* deleted tangency via line for point-to-point on
(cherry picked from commit 9e3fa8c8de0f49c0ef3c978e015eb905358dbdd9)

AngleViaPoint: internal/external tangency locking

*Added automatic tangency type lockdown for all new constraints (only
for point-wise tangency).
Tangency type is stored in the constraint datum field, as an angle value
shifted by Pi/2 (to be able to treat 0.0 as undefined type).
Added ability to switch the tangency by setting datum value from python
(can be abused by passing arbitrary angle).
Further simplified the tangency related code in Sketch.cpp.

AngleViaPoint: added license to Geo.cpp

AngleViaPoint: renames in Constraints.cpp/.h

Changed some names to increase self-explanatoryness:
bool "remapped" renamed to "pvecChangedFlag"
"ReconstructEverything()" renamed to "ReconstructGeomPointers()"

AngleViaPoint: renames in Constraints.cpp/.h

Changed some names to increase self-explanatoryness:
bool "remapped" renamed to "pvecChangedFlag"
"ReconstructEverything()" renamed to "ReconstructGeomPointers()"

AngleViaPoint: using for endpoint perpendicularity

+ direction lockdown, just as with tangency.
+ quite a lot of old code is gone because of that

AngleViaPoint: perp-ty UI routine made similar to tangent

(Git has made a very messy diff.)
The changes are:
* Perpendicularity-via-point (3-element selection) support added.
* Endpoint-to-curve and endpoint-to-endpoint supports all shape
combinations.
* a bit of code cleanup and clarifications.

AngleViaPoint: placement of perpendicular icon in 3d view

AngleViaPoint: fix: allow setDatum of perpendicular constraint

AngleViaPoint: fix: centers of ellipses are not endpoints

isSimpleVertex used to return false for centers of ellipses and arcs of
ellipses, which made them being accepted for point-to-point tangency.
Should be fixed forever, mo more changes are expected to be necessary
for new types of geometry.

AngleViaPoint: precalc with OCC (work in progress)

Work in progress (not yet working).
Using OCC's tangent to replace implementation of
SketchObject::calculateAngleViaPoint.

AngleViaPoint: fix math: normal now points inwards, where it was intended initially and goofed up.

AngleViaPoint: adding comments to the code

AngleViaPoint: using GeomCurve::closestParameterToBasicCurve for angle precalculation

AngleViaPoint: Py method: changeConstraintsLocking

changeConstraintsLocking(True) - locks/re-locks all lockable
tangency/perpendicularity constraints of the sketch (applicable to
existing sketches).
changeConstraintsLocking(False) - removes locking information from
lockable constraints

AngleViaPoint: final SketchObject::calculateAngleViaPoint

Now, finally, using OCC functionality (thanks Abdullah!), without
composing temporary Sketch object.
2015-01-02 11:48:29 +01:00

822 lines
29 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();
if (!this->getSketchObjectPtr()->evaluateConstraint(constr)) {
PyErr_SetString(PyExc_IndexError, "Constraint has invalid indexes");
return 0;
}
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);
}
}
for (std::vector<Constraint*>::iterator it = values.begin(); it != values.end(); ++it) {
if (!this->getSketchObjectPtr()->evaluateConstraint(*it)) {
PyErr_SetString(PyExc_IndexError, "Constraint has invalid indexes");
return 0;
}
}
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::getDatum(PyObject *args)
{
const std::vector<Constraint*>& vals = this->getSketchObjectPtr()->Constraints.getValues();
Constraint* constr = 0;
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 0;
}
constr = vals[index];
break;
}
PyErr_Clear();
char* name;
if (PyArg_ParseTuple(args,"s", &name)) {
int id = 1;
for (std::vector<Constraint*>::const_iterator it = vals.begin(); it != vals.end(); ++it, ++id) {
std::string constrName = (*it)->Name;
if (constrName.empty()) {
std::stringstream str;
str << "Constraint" << id;
constrName = str.str();
}
if (constrName == name) {
constr = *it;
break;
}
}
if (!constr) {
std::stringstream str;
str << "Invalid constraint name: '" << name << "'";
PyErr_SetString(PyExc_NameError, str.str().c_str());
return 0;
}
else {
break;
}
}
// error handling
PyErr_SetString(PyExc_TypeError, "Wrong arguments");
return 0;
}
while (false);
ConstraintType type = constr->Type;
if (type != Distance &&
type != DistanceX &&
type != DistanceY &&
type != Radius &&
type != Angle) {
PyErr_SetString(PyExc_TypeError, "Constraint is not a datum");
return 0;
}
Base::Quantity datum;
datum.setValue(constr->Value);
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::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::calculateAngleViaPoint(PyObject *args)
{
int GeoId1=0, GeoId2=0;
double px=0, py=0;
if (!PyArg_ParseTuple(args, "iidd", &GeoId1, &GeoId2, &px, &py))
return 0;
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 0;
}
double ang = obj->calculateAngleViaPoint(GeoId1, GeoId2, px, py);
return Py::new_reference_to(Py::Float(ang));
}
PyObject* SketchObjectPy::isPointOnCurve(PyObject *args)
{
int GeoId=Constraint::GeoUndef;
double px=0, py=0;
if (!PyArg_ParseTuple(args, "idd", &GeoId, &px, &py))
return 0;
SketchObject* obj = this->getSketchObjectPtr();
if (GeoId > obj->getHighestCurveIndex() || -GeoId > obj->getExternalGeometryCount()) {
PyErr_SetString(PyExc_ValueError, "Invalid geometry Id");
return 0;
}
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 0;
SketchObject* obj = this->getSketchObjectPtr();
if (ic >= obj->Constraints.getSize() || ic < 0) {
PyErr_SetString(PyExc_ValueError, "Invalid constraint Id");
return 0;
}
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 0;
SketchObject* obj = this->getSketchObjectPtr();
int naff = obj->changeConstraintsLocking((bool)bLock);
return Py::new_reference_to(Py::Int(naff));
}
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;
}