java-topology/defects/solvespace-0001/patch/solvespace-0001-arc-constraint-scan.patch

50 lines
2.5 KiB
Diff

# UNDF: UNDF-2026-000001160
# UNDF:
--- a/src/entity.cpp
+++ b/src/entity.cpp
@@ -938,6 +938,28 @@ void EntityBase::GenerateEquations(IdList<Equation,hEquation> *l) const {
switch(type) {
+
+// Helper: build a set of (ptA,ptB) handle pairs for POINTS_COINCIDENT constraints
+// in a given group. Used by ARC_OF_CIRCLE to check endpoint coincidence in O(1).
+// This is computed once per GenerateEquations call by callers that iterate many entities.
+
case Type::NORMAL_IN_3D: {
ExprQuaternion q = NormalGetExprs();
AddEq(l, (q.Magnitude())->Minus(Expr::From(1)), 0);
break;
}
case Type::ARC_OF_CIRCLE: {
if(SK.GetEntity(point[0])->type != Type::POINT_IN_2D) break;
- auto it = std::find_if(SK.constraint.begin(), SK.constraint.end(),
- [&](ConstraintBase const &con) {
- return (con.group == group) &&
- (con.type == Constraint::Type::POINTS_COINCIDENT) &&
- ((con.ptA == point[1] && con.ptB == point[2]) ||
- (con.ptA == point[2] && con.ptB == point[1]));
- });
- if(it != SK.constraint.end()) {
+ // Build set of coincident-endpoint pairs for this group on first arc
+ // encountered, then reuse for subsequent arcs in the same call.
+ // Key: pack two uint32_t handles into one uint64_t, store both orderings.
+ using PairSet = std::unordered_set<uint64_t>;
+ static thread_local PairSet coincidentCache;
+ static thread_local hGroup cacheGroup = { 0 };
+ if(cacheGroup.v != group.v) {
+ coincidentCache.clear();
+ cacheGroup = group;
+ for(const ConstraintBase &con : SK.constraint) {
+ if(con.group.v != group.v) continue;
+ if(con.type != Constraint::Type::POINTS_COINCIDENT) continue;
+ uint64_t ab = ((uint64_t)con.ptA.v << 32) | con.ptB.v;
+ uint64_t ba = ((uint64_t)con.ptB.v << 32) | con.ptA.v;
+ coincidentCache.insert(ab);
+ coincidentCache.insert(ba);
+ }
+ }
+ uint64_t key = ((uint64_t)point[1].v << 32) | point[2].v;
+ if(coincidentCache.count(key)) {
break;
}