Skip to content

Commit

Permalink
Sketcher: New Features: Python copy and array commands
Browse files Browse the repository at this point in the history
======================================================

Two new python commands (no UI yet).

Copy: Copies the geoids in a list by a displacement given by a Vector3d:

App.ActiveDocument.Sketch001.addCopy([0,1,2,3,4,5],App.Vector(150,150,0))

Array: Copies the geoids in a list cols times in the displacement vector
direction and rows times in the perpendicular to the displacement vector:

App.ActiveDocument.Sketch001.addArray([0,1,2,3,4,5], App.Vector(150,150,0),3,4)

N.B.: You need to recompute or solve to update the view

App.ActiveDocument.recompute()

or

App.ActiveDocument.Sketch001.solve()
  • Loading branch information
abdullahtahiriyo authored and wwmayer committed Aug 30, 2015
1 parent 359e9a5 commit 3eb8f21
Show file tree
Hide file tree
Showing 4 changed files with 216 additions and 1 deletion.
132 changes: 132 additions & 0 deletions src/Mod/Sketcher/App/SketchObject.cpp
Expand Up @@ -2004,6 +2004,138 @@ int SketchObject::addSymmetric(const std::vector<int> &geoIdList, int refGeoId,
return Geometry.getSize()-1;
}

int SketchObject::addCopy(const std::vector<int> &geoIdList, const Base::Vector3d& displacement, int csize/*=2*/, int rsize/*=1*/)
{
const std::vector< Part::Geometry * > &geovals = getInternalGeometry();
std::vector< Part::Geometry * > newgeoVals(geovals);

const std::vector< Constraint * > &constrvals = this->Constraints.getValues();
std::vector< Constraint * > newconstrVals(constrvals);

int cgeoid = getHighestCurveIndex()+1;

std::map<int, int> geoIdMap;

Base::Vector3d perpendicularDisplacement = Base::Vector3d(displacement.y,-displacement.x,0);

int x,y;

for (y=0;y<rsize;y++) {
for (x=0;x<csize;x++) {
if(x == 0 && y == 0)
continue; // the first element is already in place

for (std::vector<int>::const_iterator it = geoIdList.begin(); it != geoIdList.end(); ++it) {
const Part::Geometry *geo = getGeometry(*it);
Part::Geometry *geosym = geo->clone();

// Handle Geometry
if(geosym->getTypeId() == Part::GeomLineSegment::getClassTypeId()){
Part::GeomLineSegment *geosymline = static_cast<Part::GeomLineSegment *>(geosym);
Base::Vector3d sp = geosymline->getStartPoint();
Base::Vector3d ep = geosymline->getEndPoint();

geosymline->setPoints(sp+double(x)*displacement+double(y)*perpendicularDisplacement,
ep+double(x)*displacement+double(y)*perpendicularDisplacement);
}
else if(geosym->getTypeId() == Part::GeomCircle::getClassTypeId()){
Part::GeomCircle *geosymcircle = static_cast<Part::GeomCircle *>(geosym);
Base::Vector3d cp = geosymcircle->getCenter();

geosymcircle->setCenter(cp+double(x)*displacement+double(y)*perpendicularDisplacement);
}
else if(geosym->getTypeId() == Part::GeomArcOfCircle::getClassTypeId()){
Part::GeomArcOfCircle *geoaoc = static_cast<Part::GeomArcOfCircle *>(geosym);
Base::Vector3d cp = geoaoc->getCenter();
Base::Vector3d scp = cp+double(x)*displacement+double(y)*perpendicularDisplacement;

geoaoc->setCenter(scp);
}
else if(geosym->getTypeId() == Part::GeomEllipse::getClassTypeId()){
Part::GeomEllipse *geosymellipse = static_cast<Part::GeomEllipse *>(geosym);
Base::Vector3d cp = geosymellipse->getCenter();
Base::Vector3d scp = cp+double(x)*displacement+double(y)*perpendicularDisplacement;

geosymellipse->setCenter(scp);
}
else if(geosym->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId()){
Part::GeomArcOfEllipse *geosymaoe = static_cast<Part::GeomArcOfEllipse *>(geosym);
Base::Vector3d cp = geosymaoe->getCenter();
Base::Vector3d scp = cp+double(x)*displacement+double(y)*perpendicularDisplacement;

geosymaoe->setCenter(scp);
}
else if(geosym->getTypeId() == Part::GeomPoint::getClassTypeId()){
Part::GeomPoint *geosympoint = static_cast<Part::GeomPoint *>(geosym);
Base::Vector3d cp = geosympoint->getPoint();

geosympoint->setPoint(cp+double(x)*displacement+double(y)*perpendicularDisplacement);
}
else {
Base::Console().Error("Unsupported Geometry!! Just copying it.\n");
}

newgeoVals.push_back(geosym);
geoIdMap.insert(std::make_pair(*it, cgeoid));
cgeoid++;
}

// handle constraints
for (std::vector<Constraint *>::const_iterator it = constrvals.begin(); it != constrvals.end(); ++it) {

std::vector<int>::const_iterator fit=std::find(geoIdList.begin(), geoIdList.end(), (*it)->First);

if(fit != geoIdList.end()) { // if First of constraint is in geoIdList

if( (*it)->Second == Constraint::GeoUndef /*&& (*it)->Third == Constraint::GeoUndef*/) {
Constraint *constNew = (*it)->clone();
constNew->First = geoIdMap[(*it)->First];
newconstrVals.push_back(constNew);
}
else { // other geoids intervene in this constraint

std::vector<int>::const_iterator sit=std::find(geoIdList.begin(), geoIdList.end(), (*it)->Second);

if(sit != geoIdList.end()) { // Second is also in the list

if( (*it)->Third == Constraint::GeoUndef ) {
Constraint *constNew = (*it)->clone();
constNew->First = geoIdMap[(*it)->First];
constNew->Second = geoIdMap[(*it)->Second];
newconstrVals.push_back(constNew);
}
else {
std::vector<int>::const_iterator tit=std::find(geoIdList.begin(), geoIdList.end(), (*it)->Third);

if(tit != geoIdList.end()) { // Third is also in the list
Constraint *constNew = (*it)->clone();
constNew->First = geoIdMap[(*it)->First];
constNew->Second = geoIdMap[(*it)->Second];
constNew->Third = geoIdMap[(*it)->Third];

newconstrVals.push_back(constNew);
}
}
}
}
}
}


geoIdMap.clear(); // after each creation reset map so that the key-value is univoque
}
}

Geometry.setValues(newgeoVals);
Constraints.acceptGeometry(getCompleteGeometry());
rebuildVertexIndex();

if( newconstrVals.size() > constrvals.size() )
Constraints.setValues(newconstrVals);

return Geometry.getSize()-1;

}

int SketchObject::ExposeInternalGeometry(int GeoId)
{
Expand Down
2 changes: 2 additions & 0 deletions src/Mod/Sketcher/App/SketchObject.h
Expand Up @@ -152,6 +152,8 @@ class SketcherExport SketchObject : public Part::Part2DObject
int trim(int geoId, const Base::Vector3d& point);
/// adds symmetric geometric elements with respect to the refGeoId (line or point)
int addSymmetric(const std::vector<int> &geoIdList, int refGeoId, Sketcher::PointPos refPosId=Sketcher::none);
/// adds a copy of the geometric elements displaced by the displacement vector
int addCopy(const std::vector<int> &geoIdList, const Base::Vector3d& displacement, int csize=2, int rsize=1);
/// Exposes all internal geometry of an object supporting internal geometry
/*!
* \return -1 on error
Expand Down
12 changes: 11 additions & 1 deletion src/Mod/Sketcher/App/SketchObjectPy.xml
Expand Up @@ -136,7 +136,17 @@
<Documentation>
<UserDocu>add a symmetric geometric objects to the sketch with respect to a reference point or line</UserDocu>
</Documentation>
</Methode>
</Methode>
<Methode Name="addCopy">
<Documentation>
<UserDocu>add a copy of geometric objects to the sketch displaced by a vector3d</UserDocu>
</Documentation>
</Methode>
<Methode Name="addArray">
<Documentation>
<UserDocu>add an array of size cols by rows where each element is a copy of the selected geometric objects displaced by a vector3d in the cols direction and by a vector perpendicular to it in the rows direction</UserDocu>
</Documentation>
</Methode>
<Methode Name="ExposeInternalGeometry">
<Documentation>
<UserDocu>Exposes all internal geometry of an object supporting internal geometry</UserDocu>
Expand Down
71 changes: 71 additions & 0 deletions src/Mod/Sketcher/App/SketchObjectPyImp.cpp
Expand Up @@ -792,6 +792,77 @@ PyObject* SketchObjectPy::addSymmetric(PyObject *args)
}


PyObject* SketchObjectPy::addCopy(PyObject *args)
{
PyObject *pcObj, *pcVect;

if (!PyArg_ParseTuple(args, "OO!", &pcObj, &(Base::VectorPy::Type), &pcVect))
return 0;

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 (PyInt_Check((*it).ptr()))
geoIdList.push_back(PyInt_AsLong((*it).ptr()));
}

int ret = this->getSketchObjectPtr()->addCopy(geoIdList,vect) + 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::Int(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::addArray(PyObject *args)
{
PyObject *pcObj, *pcVect;
int rows,cols;

if (!PyArg_ParseTuple(args, "OO!ii", &pcObj, &(Base::VectorPy::Type), &pcVect,&rows,&cols))
return 0;

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 (PyInt_Check((*it).ptr()))
geoIdList.push_back(PyInt_AsLong((*it).ptr()));
}

int ret = this->getSketchObjectPtr()->addCopy(geoIdList,vect,rows,cols) + 1;

if(ret == -1)
throw Py::TypeError("Copy 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;
Expand Down

0 comments on commit 3eb8f21

Please sign in to comment.