[Sketcher] Refactor SketchObject::migrateSketch()

Manipulate some if-else statements, for loops, and possibly replace them with
std algorithms.
This commit is contained in:
Ajinkya Dahale
2024-08-22 22:41:31 +05:30
parent 169a10c7d2
commit 585ce5ec03

View File

@@ -10814,60 +10814,64 @@ void SketchObject::onSketchRestore()
}
}
// clang-format on
void SketchObject::migrateSketch()
{
bool noextensions = false;
for (const auto& g : getInternalGeometry())
// no extension - legacy file
if (!g->hasExtension(SketchGeometryExtension::getClassTypeId()))
noextensions = true;
const auto& allGeoms = getInternalGeometry();
bool noextensions = std::ranges::any_of(allGeoms, [](const auto& geo) {
return !geo->hasExtension(SketchGeometryExtension::getClassTypeId());
});
if (noextensions) {
for (auto c : Constraints.getValues()) {
for (const auto& c : Constraints.getValues()) {
addGeometryState(c);
// Convert B-Spline controlpoints radius/diameter constraints to Weight constraints
if (c->Type == InternalAlignment && c->AlignmentType == BSplineControlPoint) {
int circlegeoid = c->First;
int bsplinegeoid = c->Second;
if (c->Type != InternalAlignment || c->AlignmentType != BSplineControlPoint) {
continue;
}
auto bsp = static_cast<const Part::GeomBSplineCurve*>(getGeometry(bsplinegeoid));
int circleGeoId = c->First;
int bSplineGeoId = c->Second;
std::vector<double> weights = bsp->getWeights();
auto bsp = static_cast<const Part::GeomBSplineCurve*>(getGeometry(bSplineGeoId));
for (auto ccp : Constraints.getValues()) {
if ((ccp->Type == Radius || ccp->Type == Diameter)
&& ccp->First == circlegeoid) {
if (c->InternalAlignmentIndex < int(weights.size())) {
ccp->Type = Weight;
ccp->setValue(weights[c->InternalAlignmentIndex]);
}
}
std::vector<double> weights = bsp->getWeights();
if (!(c->InternalAlignmentIndex < int(weights.size()))) {
continue;
}
for (auto& ccp : Constraints.getValues()) {
if ((ccp->Type == Radius || ccp->Type == Diameter) && ccp->First == circleGeoId) {
ccp->Type = Weight;
ccp->setValue(weights[c->InternalAlignmentIndex]);
}
}
}
// Construction migration to extension
for (auto g : Geometry.getValues()) {
if (g->hasExtension(Part::GeometryMigrationExtension::getClassTypeId())) {
auto ext = std::static_pointer_cast<Part::GeometryMigrationExtension>(
g->getExtension(Part::GeometryMigrationExtension::getClassTypeId()).lock());
if (ext->testMigrationType(Part::GeometryMigrationExtension::Construction)) {
// at this point IA geometry is already migrated
auto gf = GeometryFacade::getFacade(g);
bool oldconstr = ext->getConstruction();
if (g->is<Part::GeomPoint>() && !gf->isInternalAligned())
oldconstr = true;
GeometryFacade::setConstruction(g, oldconstr);
}
g->deleteExtension(Part::GeometryMigrationExtension::getClassTypeId());
for (auto& g : Geometry.getValues()) {
if (!g->hasExtension(Part::GeometryMigrationExtension::getClassTypeId())) {
continue;
}
auto ext = std::static_pointer_cast<Part::GeometryMigrationExtension>(
g->getExtension(Part::GeometryMigrationExtension::getClassTypeId()).lock());
if (!ext->testMigrationType(Part::GeometryMigrationExtension::Construction)) {
continue;
}
// at this point IA geometry is already migrated
auto gf = GeometryFacade::getFacade(g);
bool oldConstr =
ext->getConstruction() || (g->is<Part::GeomPoint>() && !gf->isInternalAligned());
GeometryFacade::setConstruction(g, oldConstr);
g->deleteExtension(Part::GeometryMigrationExtension::getClassTypeId());
}
}
@@ -10875,124 +10879,128 @@ void SketchObject::migrateSketch()
auto constraints = Constraints.getValues();
auto geometries = getInternalGeometry();
bool parabolaFound = std::ranges::any_of(geometries, &Part::Geometry::is<Part::GeomArcOfParabola>);
bool parabolaFound =
std::ranges::any_of(geometries, &Part::Geometry::is<Part::GeomArcOfParabola>);
if (parabolaFound) {
bool focalaxisfound = std::ranges::any_of(constraints, [](auto& c) {
return c->Type == InternalAlignment && c->AlignmentType == ParabolaFocalAxis;
});
if (!parabolaFound) {
return;
}
// There are parabolas and there isn't an IA axis. (1) there are no axis or (2) there is a
// legacy construction line
if (!focalaxisfound) {
// maps parabola geoid to focusgeoid
std::map<int, int> parabolageoid2focusgeoid;
auto focalAxisFound = std::ranges::any_of(constraints, [](auto c) {
return c->Type == InternalAlignment && c->AlignmentType == ParabolaFocalAxis;
});
// populate parabola and focus geoids
for (const auto& c : constraints) {
if (c->Type == InternalAlignment && c->AlignmentType == ParabolaFocus) {
parabolageoid2focusgeoid[c->Second] = {c->First};
}
}
if (focalAxisFound) {
return;
}
// maps axis geoid to parabolageoid
std::map<int, int> axisgeoid2parabolageoid;
// There are parabolas and there isn't an IA axis. (1) there are no axis or (2) there is a
// legacy construction line
// populate axis geoid
for (const auto& [parabolageoid, focusgeoid] : parabolageoid2focusgeoid) {
// look for a line from focusgeoid:start to Geoid:mid_external
std::vector<int> focusgeoidlistgeoidlist;
std::vector<PointPos> focusposidlist;
getDirectlyCoincidentPoints(
focusgeoid, Sketcher::PointPos::start, focusgeoidlistgeoidlist, focusposidlist);
// maps parabola geoid to focusGeoId
std::map<int, int> parabolaGeoId2FocusGeoId;
std::vector<int> parabgeoidlistgeoidlist;
std::vector<PointPos> parabposidlist;
getDirectlyCoincidentPoints(parabolageoid,
Sketcher::PointPos::mid,
parabgeoidlistgeoidlist,
parabposidlist);
if (!focusgeoidlistgeoidlist.empty() && !parabgeoidlistgeoidlist.empty()) {
std::size_t i, j;
for (i = 0; i < focusgeoidlistgeoidlist.size(); i++) {
for (j = 0; j < parabgeoidlistgeoidlist.size(); j++) {
if (focusgeoidlistgeoidlist[i] == parabgeoidlistgeoidlist[j]) {
axisgeoid2parabolageoid[focusgeoidlistgeoidlist[i]] = parabolageoid;
}
}
}
}
}
std::vector<Constraint*> newconstraints;
newconstraints.reserve(constraints.size());
for (const auto& c : constraints) {
if (c->Type != Coincident) {
newconstraints.push_back(c);
}
else {
auto axismajorcoincidentfound = std::ranges::any_of(axisgeoid2parabolageoid,
[&](const auto& pair) {
auto parabolageoid = pair.second;
auto axisgeoid = pair.first;
return (c->First == axisgeoid && c->Second == parabolageoid
&& c->SecondPos == PointPos::mid)
|| (c->Second == axisgeoid && c->First == parabolageoid
&& c->FirstPos == PointPos::mid);
});
if (axismajorcoincidentfound) {
// we skip this coincident, the other coincident on axis will be substituted
// by internal geometry constraint
continue;
}
auto focuscoincidentfound =
std::ranges::find_if(axisgeoid2parabolageoid,
[&](const auto& pair) {
auto parabolageoid = pair.second;
auto axisgeoid = pair.first;
auto focusgeoid = parabolageoid2focusgeoid[parabolageoid];
return (c->First == axisgeoid && c->Second == focusgeoid
&& c->SecondPos == PointPos::start)
|| (c->Second == axisgeoid && c->First == focusgeoid
&& c->FirstPos == PointPos::start);
});
if (focuscoincidentfound != axisgeoid2parabolageoid.end()) {
Sketcher::Constraint* newConstr = new Sketcher::Constraint();
newConstr->Type = Sketcher::InternalAlignment;
newConstr->AlignmentType = Sketcher::ParabolaFocalAxis;
newConstr->First = focuscoincidentfound->first;// axis geoid
newConstr->FirstPos = Sketcher::PointPos::none;
newConstr->Second = focuscoincidentfound->second;// parabola geoid
newConstr->SecondPos = Sketcher::PointPos::none;
newconstraints.push_back(newConstr);
addGeometryState(newConstr);
// we skip the coincident, as we have substituted it by internal geometry
// constraint
continue;
}
newconstraints.push_back(c);
}
}
Constraints.setValues(std::move(newconstraints));
Base::Console().critical(
this->getFullName(),
QT_TRANSLATE_NOOP("Notifications",
"Parabolas were migrated. Migrated files won't open in previous "
"versions of FreeCAD!!\n"));
// populate parabola and focus geoids
for (const auto& c : constraints) {
if (c->Type == InternalAlignment && c->AlignmentType == ParabolaFocus) {
parabolaGeoId2FocusGeoId[c->Second] = {c->First};
}
}
// maps axis geoid to parabolaGeoId
std::map<int, int> axisGeoId2ParabolaGeoId;
// populate axis geoid
for (const auto& [parabolaGeoId, focusGeoId] : parabolaGeoId2FocusGeoId) {
// look for a line from focusGeoId:start to Geoid:mid_external
std::vector<int> focusGeoIdListGeoIdList;
std::vector<PointPos> focusPosIdList;
getDirectlyCoincidentPoints(focusGeoId,
Sketcher::PointPos::start,
focusGeoIdListGeoIdList,
focusPosIdList);
std::vector<int> parabGeoIdListGeoIdList;
std::vector<PointPos> parabposidlist;
getDirectlyCoincidentPoints(parabolaGeoId,
Sketcher::PointPos::mid,
parabGeoIdListGeoIdList,
parabposidlist);
for (const auto& parabGeoIdListGeoId : parabGeoIdListGeoIdList) {
auto iterParabolaGeoId =
std::ranges::find(focusGeoIdListGeoIdList, parabGeoIdListGeoId);
if (iterParabolaGeoId != focusGeoIdListGeoIdList.end()) {
axisGeoId2ParabolaGeoId[*iterParabolaGeoId] = parabolaGeoId;
}
}
}
std::vector<Constraint*> newConstraints;
newConstraints.reserve(constraints.size());
for (const auto& c : constraints) {
if (c->Type != Coincident) {
newConstraints.push_back(c);
continue;
}
auto axisMajorCoincidentFound =
std::ranges::any_of(axisGeoId2ParabolaGeoId, [&](const auto& pair) {
auto parabolaGeoId = pair.second;
auto axisgeoid = pair.first;
return (c->First == axisgeoid && c->Second == parabolaGeoId
&& c->SecondPos == PointPos::mid)
|| (c->Second == axisgeoid && c->First == parabolaGeoId
&& c->FirstPos == PointPos::mid);
});
if (axisMajorCoincidentFound) {
// we skip this coincident, the other coincident on axis will be substituted
// by internal geometry constraint
continue;
}
auto focusCoincidentFound =
std::ranges::find_if(axisGeoId2ParabolaGeoId, [&](const auto& pair) {
auto parabolaGeoId = pair.second;
auto axisgeoid = pair.first;
auto focusGeoId = parabolaGeoId2FocusGeoId[parabolaGeoId];
return (c->First == axisgeoid && c->Second == focusGeoId
&& c->SecondPos == PointPos::start)
|| (c->Second == axisgeoid && c->First == focusGeoId
&& c->FirstPos == PointPos::start);
});
if (focusCoincidentFound != axisGeoId2ParabolaGeoId.end()) {
auto* newConstr = new Sketcher::Constraint();
newConstr->Type = Sketcher::InternalAlignment;
newConstr->AlignmentType = Sketcher::ParabolaFocalAxis;
newConstr->First = focusCoincidentFound->first; // axis geoid
newConstr->FirstPos = Sketcher::PointPos::none;
newConstr->Second = focusCoincidentFound->second; // parabola geoid
newConstr->SecondPos = Sketcher::PointPos::none;
newConstraints.push_back(newConstr);
addGeometryState(newConstr);
// we skip the coincident, as we have substituted it by internal geometry
// constraint
continue;
}
newConstraints.push_back(c);
}
Constraints.setValues(std::move(newConstraints));
Base::Console().critical(
this->getFullName(),
QT_TRANSLATE_NOOP("Notifications",
"Parabolas were migrated. Migrated files won't open in previous "
"versions of FreeCAD!!\n"));
}
// clang-format off
void SketchObject::getGeoVertexIndex(int VertexId, int& GeoId, PointPos& PosId) const
{