From ddfc21afc16795ed51189e371dfabcb29c37e7fc Mon Sep 17 00:00:00 2001 From: wmayer Date: Tue, 28 May 2024 15:28:53 +0200 Subject: [PATCH] Sketch: Refactor SketchAnalysis Refactor detectMissingPointOnPointConstraints() --- src/Mod/Sketcher/App/SketchAnalysis.cpp | 262 ++++++++++++------------ 1 file changed, 134 insertions(+), 128 deletions(-) diff --git a/src/Mod/Sketcher/App/SketchAnalysis.cpp b/src/Mod/Sketcher/App/SketchAnalysis.cpp index b007e0b04e..527e83e529 100644 --- a/src/Mod/Sketcher/App/SketchAnalysis.cpp +++ b/src/Mod/Sketcher/App/SketchAnalysis.cpp @@ -151,10 +151,6 @@ private: struct PointConstraints { - explicit PointConstraints(std::vector& vertexIds) - : vertexIds {vertexIds} - {} - void addGeometry(const Part::Geometry* geo, int index) { if (const auto* segm = dynamic_cast(geo)) { @@ -255,8 +251,136 @@ struct PointConstraints vertexIds.push_back(id); } + std::list getMissingCoincidences(std::vector& allcoincid, + double precision) + { + std::list missingCoincidences; // Holds the list of missing coincidences + + // Sort points in geographic order + std::sort(vertexIds.begin(), vertexIds.end(), Vertex_Less(precision)); + + auto vt = vertexIds.begin(); + Vertex_EqualTo pred(precision); + + // Comparing existing constraints and find missing ones + + while (vt < vertexIds.end()) { + // Seeking for adjacent group of vertices + vt = std::adjacent_find(vt, vertexIds.end(), pred); + if (vt < vertexIds.end()) { // If one found + std::vector::iterator vn; + // Holds a single group of adjacent vertices + std::set vertexGrp; + // Extract the group of adjacent vertices + vertexGrp.insert(*vt); + for (vn = vt + 1; vn < vertexIds.end(); ++vn) { + if (pred(*vt, *vn)) { + vertexGrp.insert(*vn); + } + else { + break; + } + } + + // Holds groups of coincident vertices + std::vector> coincVertexGrps; + + // Decompose the group of adjacent vertices into groups of coincident vertices + // Going through existent coincidences + for (auto& coincidence : allcoincid) { + VertexIds v1; + VertexIds v2; + v1.GeoId = coincidence->First; + v1.PosId = coincidence->FirstPos; + v2.GeoId = coincidence->Second; + v2.PosId = coincidence->SecondPos; + + // Look if coincident vertices are in the group of adjacent ones we are + // processing + auto nv1 = vertexGrp.extract(v1); + auto nv2 = vertexGrp.extract(v2); + + // Maybe if both empty, they already have been extracted by other coincidences + // We have to check in existing coincident groups and eventually merge + if (nv1.empty() && nv2.empty()) { + std::set* tempGrp = nullptr; + for (auto it = coincVertexGrps.begin(); it < coincVertexGrps.end(); ++it) { + if ((it->find(v1) != it->end()) || (it->find(v2) != it->end())) { + if (!tempGrp) { + tempGrp = &*it; + } + else { + tempGrp->insert(it->begin(), it->end()); + coincVertexGrps.erase(it); + break; + } + } + } + continue; + } + + // Look if one of the constrained vertices is already in a group of coincident + // vertices + for (std::set& grp : coincVertexGrps) { + if ((grp.find(v1) != grp.end()) || (grp.find(v2) != grp.end())) { + // If yes add them to the existing group + if (!nv1.empty()) { + grp.insert(nv1.value()); + } + if (!nv2.empty()) { + grp.insert(nv2.value()); + } + continue; + } + } + + if (nv1.empty() || nv2.empty()) { + continue; + } + + // If no, create a new group of coincident vertices + std::set newGrp; + newGrp.insert(nv1.value()); + newGrp.insert(nv2.value()); + coincVertexGrps.push_back(newGrp); + } + + // If there are remaining vertices in the adjacent group (not in any existing + // constraint) add them as being each a separate coincident group + for (auto& lonept : vertexGrp) { + std::set newGrp; + newGrp.insert(lonept); + coincVertexGrps.push_back(newGrp); + } + + // If there is more than 1 coincident group into adjacent group, constraint(s) + // is(are) missing Virtually generate the missing constraint(s) + if (coincVertexGrps.size() > 1) { + std::vector>::iterator vn; + // Starting from the 2nd coincident group, generate a constraint between + // this group first vertex, and previous group first vertex + for (vn = coincVertexGrps.begin() + 1; vn < coincVertexGrps.end(); ++vn) { + ConstraintIds id; + id.Type = Coincident; // default point on point restriction + id.v = (vn - 1)->begin()->v; + id.First = (vn - 1)->begin()->GeoId; + id.FirstPos = (vn - 1)->begin()->PosId; + id.Second = vn->begin()->GeoId; + id.SecondPos = vn->begin()->PosId; + missingCoincidences.push_back(id); + } + } + + vt = vn; + } + } + + return missingCoincidences; + } + private: - std::vector& vertexIds; + // Holds a list of all vertices in the sketch + std::vector vertexIds; }; struct EqualityConstraints @@ -380,8 +504,7 @@ private: int SketchAnalysis::detectMissingPointOnPointConstraints(double precision, bool includeconstruction /*=true*/) { - std::vector vertexIds; // Holds a list of all vertices in the sketch - PointConstraints pointConstr(vertexIds); + PointConstraints pointConstr; // Build the list of sketch vertices const std::vector& geom = sketch->getInternalGeometry(); @@ -396,13 +519,9 @@ int SketchAnalysis::detectMissingPointOnPointConstraints(double precision, // TODO take into account single vertices ? } - // Sort points in geographic order - std::sort(vertexIds.begin(), vertexIds.end(), Vertex_Less(precision)); - - // Build a list of all coincidence in the sketch + // Build a list of all coincidences in the sketch std::vector coincidences = sketch->Constraints.getValues(); - for (auto& constraint : sketch->Constraints.getValues()) { // clang-format off if (constraint->Type == Sketcher::Coincident || @@ -414,122 +533,9 @@ int SketchAnalysis::detectMissingPointOnPointConstraints(double precision, // TODO optimizing by removing constraints not applying on vertices ? } - std::list missingCoincidences; // Holds the list of missing coincidences - - auto vt = vertexIds.begin(); - Vertex_EqualTo pred(precision); - - // Comparing existing constraints and find missing ones - - while (vt < vertexIds.end()) { - // Seeking for adjacent group of vertices - vt = std::adjacent_find(vt, vertexIds.end(), pred); - if (vt < vertexIds.end()) { // If one found - std::vector::iterator vn; - // Holds a single group of adjacent vertices - std::set vertexGrp; - // Extract the group of adjacent vertices - vertexGrp.insert(*vt); - for (vn = vt + 1; vn < vertexIds.end(); ++vn) { - if (pred(*vt, *vn)) { - vertexGrp.insert(*vn); - } - else { - break; - } - } - - // Holds groups of coincident vertices - std::vector> coincVertexGrps; - - // Decompose the group of adjacent vertices into groups of coincident vertices - // Going through existent coincidences - for (auto& coincidence : coincidences) { - VertexIds v1; - VertexIds v2; - v1.GeoId = coincidence->First; - v1.PosId = coincidence->FirstPos; - v2.GeoId = coincidence->Second; - v2.PosId = coincidence->SecondPos; - - // Look if coincident vertices are in the group of adjacent ones we are processing - auto nv1 = vertexGrp.extract(v1); - auto nv2 = vertexGrp.extract(v2); - - // Maybe if both empty, they already have been extracted by other coincidences - // We have to check in existing coincident groups and eventually merge - if (nv1.empty() && nv2.empty()) { - std::set* tempGrp = nullptr; - for (auto it = coincVertexGrps.begin(); it < coincVertexGrps.end(); ++it) { - if ((it->find(v1) != it->end()) || (it->find(v2) != it->end())) { - if (!tempGrp) { - tempGrp = &*it; - } - else { - tempGrp->insert(it->begin(), it->end()); - coincVertexGrps.erase(it); - break; - } - } - } - continue; - } - - // Look if one of the constrained vertices is already in a group of coincident - // vertices - for (std::set& grp : coincVertexGrps) { - if ((grp.find(v1) != grp.end()) || (grp.find(v2) != grp.end())) { - // If yes add them to the existing group - if (!nv1.empty()) { - grp.insert(nv1.value()); - } - if (!nv2.empty()) { - grp.insert(nv2.value()); - } - continue; - } - } - - if (nv1.empty() || nv2.empty()) { - continue; - } - - // If no, create a new group of coincident vertices - std::set newGrp; - newGrp.insert(nv1.value()); - newGrp.insert(nv2.value()); - coincVertexGrps.push_back(newGrp); - } - - // If there are remaining vertices in the adjacent group (not in any existing - // constraint) add them as being each a separate coincident group - for (auto& lonept : vertexGrp) { - std::set newGrp; - newGrp.insert(lonept); - coincVertexGrps.push_back(newGrp); - } - - // If there is more than 1 coincident group into adjacent group, constraint(s) is(are) - // missing Virtually generate the missing constraint(s) - if (coincVertexGrps.size() > 1) { - std::vector>::iterator vn; - // Starting from the 2nd coincident group, generate a constraint between - // this group first vertex, and previous group first vertex - for (vn = coincVertexGrps.begin() + 1; vn < coincVertexGrps.end(); ++vn) { - ConstraintIds id; - id.Type = Coincident; // default point on point restriction - id.v = (vn - 1)->begin()->v; - id.First = (vn - 1)->begin()->GeoId; - id.FirstPos = (vn - 1)->begin()->PosId; - id.Second = vn->begin()->GeoId; - id.SecondPos = vn->begin()->PosId; - missingCoincidences.push_back(id); - } - } - - vt = vn; - } - } + // Holds the list of missing coincidences + std::list missingCoincidences = + pointConstr.getMissingCoincidences(coincidences, precision); // Update list of missing constraints stored as member variable of sketch this->vertexConstraints.clear();