Sketcher: Fix Array/copy/move

==============================

Do not copy/array internal alignment geometry if the geometry it defines is not part of the operation. Silently ignore it.

If the reference for the operation is one such geometry (or it is the only one), then abort the operation.
This commit is contained in:
Abdullah Tahiri
2020-12-20 12:23:22 +01:00
committed by abdullahtahiriyo
parent 6aca180d7e
commit c3acfcc0a0
2 changed files with 82 additions and 30 deletions

View File

@@ -4033,6 +4033,27 @@ int SketchObject::addCopy(const std::vector<int> &geoIdList, const Base::Vector3
if(x == 0 && y == 0) { // the reference for constraining array elements is the first valid point of the first element
const Part::Geometry *geo = getGeometry(*(newgeoIdList.begin()));
auto gf = GeometryFacade::getFacade(geo);
if(gf->isInternalAligned() && !moveonly) {
// only add this geometry if the corresponding geometry it defines is also in the list.
int definedGeo = Constraint::GeoUndef;
for( auto c : Constraints.getValues()) {
if(c->Type == Sketcher::InternalAlignment && c->First == *(newgeoIdList.begin())) {
definedGeo = c->Second;
break;
}
}
if(std::find(newgeoIdList.begin(), newgeoIdList.end(), definedGeo) == newgeoIdList.end() ) {
// the first element setting the reference is an internal alignment geometry, wherein the geometry
// it defines is not part of the copy operation.
THROWM(Base::ValueError,"A move/copy/array operation on an internal alignment geometry is only possible together with the geometry it defines.")
}
}
refgeoid=*(newgeoIdList.begin());
currentrowfirstgeoid = refgeoid;
iterfirstgeoid = refgeoid;
@@ -4062,9 +4083,27 @@ int SketchObject::addCopy(const std::vector<int> &geoIdList, const Base::Vector3
Part::Geometry *geocopy;
auto gf = GeometryFacade::getFacade(geo);
if(gf->isInternalAligned() && !moveonly) {
// only add this geometry if the corresponding geometry it defines is also in the list.
int definedGeo = Constraint::GeoUndef;
for( auto c : Constraints.getValues()) {
if(c->Type == Sketcher::InternalAlignment && c->First == *it) {
definedGeo = c->Second;
break;
}
}
if(std::find(newgeoIdList.begin(), newgeoIdList.end(), definedGeo) == newgeoIdList.end() )
continue; // we should not copy internal alignment geometry, unless the element they define is also mirrored
}
// We have already cloned all geometry and constraints, we only need a copy if not moving
if(!moveonly)
geocopy = geo->copy(); // make a copy of the pointer for undo even if moving
geocopy = geo->copy();
else
geocopy = newgeoVals[*it];
@@ -4183,9 +4222,9 @@ int SketchObject::addCopy(const std::vector<int> &geoIdList, const Base::Vector3
// handle geometry constraints
for (std::vector<Constraint *>::const_iterator it = constrvals.begin(); it != constrvals.end(); ++it) {
std::vector<int>::const_iterator fit=std::find(newgeoIdList.begin(), newgeoIdList.end(), (*it)->First);
auto fit = geoIdMap.find((*it)->First);
if(fit != newgeoIdList.end()) { // if First of constraint is in geoIdList
if(fit != geoIdMap.end()) { // if First of constraint is in geoIdList
if( (*it)->Second == Constraint::GeoUndef /*&& (*it)->Third == Constraint::GeoUndef*/) {
if( ((*it)->Type != Sketcher::DistanceX && (*it)->Type != Sketcher::DistanceY ) ||
@@ -4200,7 +4239,7 @@ int SketchObject::addCopy(const std::vector<int> &geoIdList, const Base::Vector3
Constraint *constNew = (*it)->copy();
constNew->Type = Sketcher::Equal;
constNew->isDriving = true;
constNew->Second = geoIdMap[(*it)->First]; // first is already (*it->First)
constNew->Second = fit->second; // first is already (*it->First)
newconstrVals.push_back(constNew);
}
else if ((*it)->Type == Sketcher::Angle && clone){
@@ -4208,21 +4247,21 @@ int SketchObject::addCopy(const std::vector<int> &geoIdList, const Base::Vector3
Constraint *constNew = (*it)->copy();
constNew->Type = Sketcher::Parallel;
constNew->isDriving = true;
constNew->Second = geoIdMap[(*it)->First]; // first is already (*it->First)
constNew->Second = fit->second; // first is already (*it->First)
newconstrVals.push_back(constNew);
}
else {
Constraint *constNew = (*it)->copy();
constNew->First = geoIdMap[(*it)->First];
constNew->First = fit->second;
newconstrVals.push_back(constNew);
}
}
}
else { // other geoids intervene in this constraint
std::vector<int>::const_iterator sit=std::find(newgeoIdList.begin(), newgeoIdList.end(), (*it)->Second);
auto sit = geoIdMap.find((*it)->Second);
if(sit != newgeoIdList.end()) { // Second is also in the list
if(sit != geoIdMap.end()) { // Second is also in the list
if( (*it)->Third == Constraint::GeoUndef ) {
if (((*it)->Type == Sketcher::DistanceX ||
(*it)->Type == Sketcher::DistanceY ||
@@ -4232,25 +4271,25 @@ int SketchObject::addCopy(const std::vector<int> &geoIdList, const Base::Vector3
constNew->Type = Sketcher::Equal;
constNew->isDriving = true;
constNew->FirstPos = Sketcher::none;
constNew->Second = geoIdMap[(*it)->First]; // first is already (*it->First)
constNew->Second = fit->second; // first is already (*it->First)
constNew->SecondPos = Sketcher::none;
newconstrVals.push_back(constNew);
}
else {
else { // this includes InternalAlignment constraints
Constraint *constNew = (*it)->copy();
constNew->First = geoIdMap[(*it)->First];
constNew->Second = geoIdMap[(*it)->Second];
constNew->First = fit->second;
constNew->Second = sit->second;
newconstrVals.push_back(constNew);
}
}
else {
std::vector<int>::const_iterator tit=std::find(newgeoIdList.begin(), newgeoIdList.end(), (*it)->Third);
auto tit = geoIdMap.find((*it)->Third);
if(tit != newgeoIdList.end()) { // Third is also in the list
if(tit != geoIdMap.end()) { // Third is also in the list
Constraint *constNew = (*it)->copy();
constNew->First = geoIdMap[(*it)->First];
constNew->Second = geoIdMap[(*it)->Second];
constNew->Third = geoIdMap[(*it)->Third];
constNew->First = fit->second;
constNew->Second = sit->second;
constNew->Third = tit->second;
newconstrVals.push_back(constNew);
}

View File

@@ -1138,19 +1138,25 @@ PyObject* SketchObjectPy::addCopy(PyObject *args)
#endif
}
int ret = this->getSketchObjectPtr()->addCopy(geoIdList, vect, false, PyObject_IsTrue(clone) ? true : false) + 1;
try {
int ret = this->getSketchObjectPtr()->addCopy(geoIdList, vect, false, PyObject_IsTrue(clone) ? true : false) + 1;
if(ret == -1)
throw Py::TypeError("Copy operation unsuccessful!");
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));
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());
}
return Py::new_reference_to(tuple);
}
std::string error = std::string("type must be list of GeoIds, not ");
@@ -1219,11 +1225,18 @@ PyObject* SketchObjectPy::addRectangularArray(PyObject *args)
#endif
}
int ret = this->getSketchObjectPtr()->addCopy(geoIdList,vect, false, PyObject_IsTrue(clone) ? true : false,
rows, cols, PyObject_IsTrue(constraindisplacement) ? true : false, perpscale) + 1;
try {
int ret = this->getSketchObjectPtr()->addCopy(geoIdList,vect, false, PyObject_IsTrue(clone) ? true : false,
rows, cols, PyObject_IsTrue(constraindisplacement) ? true : false, perpscale) + 1;
if(ret == -1)
throw Py::TypeError("Copy operation unsuccessful!");
}
catch(const Base::ValueError & e) {
throw Py::ValueError(e.getMessage());
}
if(ret == -1)
throw Py::TypeError("Copy operation unsuccessful!");
Py_Return;
}