diff --git a/CHANGELOG.md b/CHANGELOG.md
index 80843a7b..70d58733 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -41,8 +41,8 @@ Other new features:
Bugs fixed:
* A point in 3d constrained to any line whose length is free no longer
causes the line length to collapse.
- * Curve-line constraints (in 3d) and parallel constraints (in 3d)
- are more robust.
+ * Curve-line constraints (in 3d), parallel constraints (in 3d), and
+ same orientation constraints are more robust.
2.3
---
diff --git a/src/constrainteq.cpp b/src/constrainteq.cpp
index 398c99cf..680f3a01 100644
--- a/src/constrainteq.cpp
+++ b/src/constrainteq.cpp
@@ -28,35 +28,6 @@ bool ConstraintBase::HasLabel() const {
}
}
-Expr *ConstraintBase::VectorsParallel(int eq, ExprVector a, ExprVector b) {
- ExprVector r = a.Cross(b);
- // Hairy ball theorem screws me here. There's no clean solution that I
- // know, so let's pivot on the initial numerical guess. Our caller
- // has ensured that if one of our input vectors is already known (e.g.
- // it's from a previous group), then that one's in a; so that one's
- // not going to move, and we should pivot on that one.
- double mx = fabs((a.x)->Eval());
- double my = fabs((a.y)->Eval());
- double mz = fabs((a.z)->Eval());
- // The basis vector in which the vectors have the LEAST energy is the
- // one that we should look at most (e.g. if both vectors lie in the xy
- // plane, then the z component of the cross product is most important).
- // So find the strongest component of a and b, and that's the component
- // of the cross product to ignore.
- Expr *e0, *e1;
- if(mx > my && mx > mz) {
- e0 = r.y; e1 = r.z;
- } else if(my > mz) {
- e0 = r.z; e1 = r.x;
- } else {
- e0 = r.x; e1 = r.y;
- }
-
- if(eq == 0) return e0;
- if(eq == 1) return e1; // BRANCH_ALWAYS_TAKEN
- ssassert(false, "Unexpected index of equation");
-}
-
ExprVector ConstraintBase::VectorsParallel3d(ExprVector a, ExprVector b, hParam p) {
return a.Minus(b.ScaledBy(Expr::From(p)));
}
@@ -221,6 +192,7 @@ void ConstraintBase::Generate(IdList *l) const {
// Add new parameter only when we operate in 3d space
if(workplane.v != EntityBase::FREE_IN_3D.v) break;
// fallthrough
+ case Type::SAME_ORIENTATION:
case Type::PT_ON_LINE: {
Param p = {};
p.h = h.param(0);
@@ -620,9 +592,6 @@ void ConstraintBase::GenerateEquations(IdList *l,
case Type::SAME_ORIENTATION: {
EntityBase *a = SK.GetEntity(entityA);
EntityBase *b = SK.GetEntity(entityB);
- if(b->group.v != group.v) {
- swap(a, b);
- }
ExprVector au = a->NormalExprsU(),
an = a->NormalExprsN();
@@ -630,16 +599,16 @@ void ConstraintBase::GenerateEquations(IdList *l,
bv = b->NormalExprsV(),
bn = b->NormalExprsN();
- AddEq(l, VectorsParallel(0, an, bn), 0);
- AddEq(l, VectorsParallel(1, an, bn), 1);
+ ExprVector eq = VectorsParallel3d(an, bn, h.param(0));
+ AddEq(l, eq);
Expr *d1 = au.Dot(bv);
Expr *d2 = au.Dot(bu);
// Allow either orientation for the coordinate system, depending
// on how it was drawn.
if(fabs(d1->Eval()) < fabs(d2->Eval())) {
- AddEq(l, d1, 2);
+ AddEq(l, d1, 3);
} else {
- AddEq(l, d2, 2);
+ AddEq(l, d2, 3);
}
return;
}
diff --git a/src/file.cpp b/src/file.cpp
index 1a16618d..f8a36b5a 100644
--- a/src/file.cpp
+++ b/src/file.cpp
@@ -623,6 +623,20 @@ void SolveSpaceUI::UpgradeLegacyData() {
break;
}
+ case Constraint::Type::SAME_ORIENTATION: {
+ if(AllParamsExistFor(c)) continue;
+
+ EntityBase *an = SK.GetEntity(c.entityA);
+ EntityBase *bn = SK.GetEntity(c.entityB);
+
+ ExprVector a = an->NormalExprsN();
+ ExprVector b = bn->NormalExprsN();
+
+ Param *param = SK.GetParam(c.h.param(0));
+ param->val = a.Dot(b)->Eval() / b.Dot(b)->Eval();
+ break;
+ }
+
case Constraint::Type::PARALLEL: {
if(AllParamsExistFor(c)) continue;
diff --git a/src/sketch.h b/src/sketch.h
index f6db85c8..0366b5b0 100644
--- a/src/sketch.h
+++ b/src/sketch.h
@@ -652,7 +652,6 @@ public:
static Expr *Distance(hEntity workplane, hEntity pa, hEntity pb);
static Expr *PointLineDistance(hEntity workplane, hEntity pt, hEntity ln);
static Expr *PointPlaneDistance(ExprVector p, hEntity plane);
- static Expr *VectorsParallel(int eq, ExprVector a, ExprVector b);
static ExprVector VectorsParallel3d(ExprVector a, ExprVector b, hParam p);
static ExprVector PointInThreeSpace(hEntity workplane, Expr *u, Expr *v);
diff --git a/test/constraint/same_orientation/normal.slvs b/test/constraint/same_orientation/normal.slvs
index 03211cb4..bf0888b2 100644
--- a/test/constraint/same_orientation/normal.slvs
+++ b/test/constraint/same_orientation/normal.slvs
@@ -142,6 +142,10 @@ Param.h.v.=00040040
Param.val=5.00000000000000000000
AddParam
+Param.h.v.=40000002
+Param.val=1.00000000000000000000
+AddParam
+
Request.h.v=00000001
Request.type=100
Request.group.v=00000001
diff --git a/test/constraint/same_orientation/same_group.slvs b/test/constraint/same_orientation/same_group.slvs
index a6d42d48..bd7f1958 100644
--- a/test/constraint/same_orientation/same_group.slvs
+++ b/test/constraint/same_orientation/same_group.slvs
@@ -172,6 +172,10 @@ Param.h.v.=00050040
Param.val=5.00000000000000000000
AddParam
+Param.h.v.=40000002
+Param.val=-1.00000000000000022204
+AddParam
+
Request.h.v=00000001
Request.type=100
Request.group.v=00000001