50 lines
2.5 KiB
Diff
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;
|
|
}
|