[Sketcher] Fix "toggle internal geo" on multi-selection

Some deleted GeoIds can stay in selection and GeoIds can change as some objects
are deleted.
This commit is contained in:
Ajinkya Dahale
2022-03-08 18:20:35 -05:00
committed by abdullahtahiriyo
parent b0d19d28d7
commit 76029a5b2d

View File

@@ -983,50 +983,67 @@ void CmdSketcherRestoreInternalAlignmentGeometry::activated(int iMsg)
getSelection().clearSelection();
// Return GeoId of the SubName only if it is an edge
auto getEdgeGeoId = [&Obj](const std::string& SubName) {
int GeoId;
Sketcher::PointPos PosId;
getIdsFromName(SubName, Obj, GeoId, PosId);
if (PosId == Sketcher::PointPos::none)
return GeoId;
else
return (int)GeoEnum::GeoUndef;
};
// Tells if the geometry with given GeoId has internal geometry
auto noInternalGeo = [&Obj](const auto& GeoId) {
const Part::Geometry *geo = Obj->getGeometry(GeoId);
bool hasInternalGeo = geo &&
(geo->getTypeId() == Part::GeomEllipse::getClassTypeId() ||
geo->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId() ||
geo->getTypeId() == Part::GeomArcOfHyperbola::getClassTypeId() ||
geo->getTypeId() == Part::GeomArcOfParabola::getClassTypeId() ||
geo->getTypeId() == Part::GeomBSplineCurve::getClassTypeId());
return !hasInternalGeo; // so it's removed
};
std::vector<int> SubGeoIds(SubNames.size());
std::transform(SubNames.begin(), SubNames.end(), SubGeoIds.begin(), getEdgeGeoId);
// Handle highest GeoIds first to minimize GeoIds changing
// TODO: this might not completely resolve GeoIds changing
std::sort(SubGeoIds.begin(), SubGeoIds.end(), std::greater<int>());
// Keep unique
SubGeoIds.erase(std::unique(SubGeoIds.begin(), SubGeoIds.end()), SubGeoIds.end());
// Only for supported types and keep unique
SubGeoIds.erase(std::remove_if(SubGeoIds.begin(), SubGeoIds.end(), noInternalGeo),
SubGeoIds.end());
// go through the selected subelements
for (std::vector<std::string>::const_iterator it=SubNames.begin(); it != SubNames.end(); ++it) {
// only handle edges
if ((it->size() > 4 && it->substr(0,4) == "Edge") ||
(it->size() > 12 && it->substr(0,12) == "ExternalEdge")) {
int GeoId;
if (it->substr(0,4) == "Edge")
GeoId = std::atoi(it->substr(4,4000).c_str()) - 1;
else
GeoId = -std::atoi(it->substr(12,4000).c_str()) - 2;
for (const auto& GeoId : SubGeoIds) {
int currentgeoid = Obj->getHighestCurveIndex();
const Part::Geometry *geo = Obj->getGeometry(GeoId);
// Only for supported types
if (geo->getTypeId() == Part::GeomEllipse::getClassTypeId() ||
geo->getTypeId() == Part::GeomArcOfEllipse::getClassTypeId() ||
geo->getTypeId() == Part::GeomArcOfHyperbola::getClassTypeId() ||
geo->getTypeId() == Part::GeomArcOfParabola::getClassTypeId() ||
geo->getTypeId() == Part::GeomBSplineCurve::getClassTypeId()) {
try {
Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Exposing Internal Geometry"));
Gui::cmdAppObjectArgs(Obj, "exposeInternalGeometry(%d)", GeoId);
int currentgeoid = Obj->getHighestCurveIndex();
int aftergeoid = Obj->getHighestCurveIndex();
try {
Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Exposing Internal Geometry"));
Gui::cmdAppObjectArgs(Obj, "exposeInternalGeometry(%d)", GeoId);
int aftergeoid = Obj->getHighestCurveIndex();
if(aftergeoid == currentgeoid) { // if we did not expose anything, deleteunused
Gui::cmdAppObjectArgs(Obj, "deleteUnusedInternalGeometry(%d)", GeoId);
}
}
catch (const Base::Exception& e) {
Base::Console().Error("%s\n", e.what());
Gui::Command::abortCommand();
tryAutoRecomputeIfNotSolve(static_cast<Sketcher::SketchObject *>(Obj));
return;
}
Gui::Command::commitCommand();
tryAutoRecomputeIfNotSolve(static_cast<Sketcher::SketchObject *>(Obj));
if(aftergeoid == currentgeoid) { // if we did not expose anything, deleteunused
Gui::cmdAppObjectArgs(Obj, "deleteUnusedInternalGeometry(%d)", GeoId);
}
}
catch (const Base::Exception& e) {
Base::Console().Error("%s\n", e.what());
Gui::Command::abortCommand();
tryAutoRecomputeIfNotSolve(static_cast<Sketcher::SketchObject *>(Obj));
return;
}
Gui::Command::commitCommand();
tryAutoRecomputeIfNotSolve(static_cast<Sketcher::SketchObject *>(Obj));
}
}