From 01885736e6f6ab838ac438e54e0495438c03cf59 Mon Sep 17 00:00:00 2001 From: Jonathan Westhues Date: Fri, 2 May 2008 19:33:35 -0800 Subject: [PATCH] Fix my rotation-matrix-to-quaternion code: it broke when the diagonal elements of the matrix summed to -1. Now it's ugly, but I think that it's correct. And add a command to flip the view to the other side, which is what started my problems. And tweak display of H and V and M for constraints: put them in the constraint plane, so that they're stationary as you rotate around. [git-p4: depot-paths = "//depot/solvespace/": change = 1704] --- drawconstraint.cpp | 11 +++++++++-- entity.cpp | 2 +- graphicswin.cpp | 10 ++++++++++ ui.h | 1 + util.cpp | 38 +++++++++++++++++++++++++++++++++----- 5 files changed, 54 insertions(+), 8 deletions(-) diff --git a/drawconstraint.cpp b/drawconstraint.cpp index 73783c5..84d69a4 100644 --- a/drawconstraint.cpp +++ b/drawconstraint.cpp @@ -159,12 +159,19 @@ void Constraint::DrawOrGetDistance(Vector *labelPos) { case HORIZONTAL: case VERTICAL: if(entityA.v) { + Vector r, u, n; + if(workplane.v == Entity::FREE_IN_3D.v) { + r = gr; u = gu; n = gn; + } else { + SS.GetEntity(workplane)->WorkplaneGetBasisVectors(&r, &u); + n = r.Cross(u); + } // For "at midpoint", this branch is always taken. Entity *e = SS.GetEntity(entityA); Vector a = SS.GetEntity(e->point[0])->PointGetCoords(); Vector b = SS.GetEntity(e->point[1])->PointGetCoords(); Vector m = (a.ScaledBy(0.5)).Plus(b.ScaledBy(0.5)); - Vector offset = (a.Minus(b)).Cross(gn); + Vector offset = (a.Minus(b)).Cross(n); offset = offset.WithMagnitude(13/SS.GW.scale); // Draw midpoint constraint on other side of line, so that // a line can be midpoint and horizontal at same time. @@ -173,7 +180,7 @@ void Constraint::DrawOrGetDistance(Vector *labelPos) { if(dogd.drawing) { glPushMatrix(); glxTranslatev(m.Plus(offset)); - glxOntoWorkplane(gr, gu); + glxOntoWorkplane(r, u); glxWriteTextRefCenter( (type == HORIZONTAL) ? "H" : ( (type == VERTICAL) ? "V" : ( diff --git a/entity.cpp b/entity.cpp index 18c76b6..920029c 100644 --- a/entity.cpp +++ b/entity.cpp @@ -238,7 +238,7 @@ void Entity::LineDrawOrGetDistance(Vector a, Vector b) { // anything else at the "same" depth in the z-buffer, so that it // goes in front of the shaded stuff. Vector n = SS.GW.projRight.Cross(SS.GW.projUp); - n = n.WithMagnitude(1.2/SS.GW.scale); + n = n.WithMagnitude(3/SS.GW.scale); glBegin(GL_LINE_STRIP); glxVertex3v(a.Plus(n)); glxVertex3v(b.Plus(n)); diff --git a/graphicswin.cpp b/graphicswin.cpp index b79de78..5369880 100644 --- a/graphicswin.cpp +++ b/graphicswin.cpp @@ -31,6 +31,7 @@ const GraphicsWindow::MenuEntry GraphicsWindow::menu[] = { { 1, "Zoom &In\t+", MNU_ZOOM_IN, '+', mView }, { 1, "Zoom &Out\t-", MNU_ZOOM_OUT, '-', mView }, { 1, "Zoom To &Fit\tF", MNU_ZOOM_TO_FIT, 'F', mView }, +{ 1, "Onto Othe&r Side\tCtrl+O", MNU_OTHER_SIDE, 'R'|C, mView }, { 1, NULL, 0, NULL }, { 1, "Show Text &Window\tTab", MNU_SHOW_TEXT_WND, '\t', mView }, { 1, NULL, 0, NULL }, @@ -185,6 +186,15 @@ void GraphicsWindow::MenuView(int id) { case MNU_ZOOM_TO_FIT: break; + case MNU_OTHER_SIDE: { + Quaternion quatf = Quaternion::MakeFrom( + SS.GW.projRight.ScaledBy(-1), SS.GW.projUp.ScaledBy(1)); + Vector ru = quatf.RotationU(); + Vector rv = quatf.RotationV(); + SS.GW.AnimateOnto(quatf, SS.GW.offset); + break; + } + case MNU_SHOW_TEXT_WND: SS.GW.showTextWindow = !SS.GW.showTextWindow; SS.GW.EnsureValidActives(); diff --git a/ui.h b/ui.h index 5e949a5..ef9871d 100644 --- a/ui.h +++ b/ui.h @@ -91,6 +91,7 @@ public: MNU_ZOOM_IN, MNU_ZOOM_OUT, MNU_ZOOM_TO_FIT, + MNU_OTHER_SIDE, MNU_SHOW_TEXT_WND, MNU_UNITS_INCHES, MNU_UNITS_MM, diff --git a/util.cpp b/util.cpp index 8c5f774..8875bf9 100644 --- a/util.cpp +++ b/util.cpp @@ -37,11 +37,37 @@ Quaternion Quaternion::MakeFrom(Vector u, Vector v) Vector n = u.Cross(v); Quaternion q; - q.a = 0.5*sqrt(1 + u.x + v.y + n.z); - q.b = (1/(4*(q.a)))*(v.z - n.y); - q.c = (1/(4*(q.a)))*(n.x - u.z); - q.d = (1/(4*(q.a)))*(u.y - v.x); - return q; + double s, tr = 1 + u.x + v.y + n.z; + if(tr > 1e-4) { + s = 2*sqrt(tr); + q.a = s/4; + q.b = (v.z - n.y)/s; + q.c = (n.x - u.z)/s; + q.d = (u.y - v.x)/s; + } else { + double m = max(u.x, max(v.y, n.z)); + if(m == u.x) { + s = 2*sqrt(1 + u.x - v.y - n.z); + q.a = (v.z - n.y)/s; + q.b = s/4; + q.c = (u.y + v.x)/s; + q.d = (n.x + u.z)/s; + } else if(m == v.y) { + s = 2*sqrt(1 - u.x + v.y - n.z); + q.a = (n.x - u.z)/s; + q.b = (u.y + v.x)/s; + q.c = s/4; + q.d = (v.z + n.y)/s; + } else if(m == n.z) { + s = 2*sqrt(1 - u.x - v.y + n.z); + q.a = (u.y - v.x)/s; + q.b = (n.x + u.z)/s; + q.c = (v.z + n.y)/s; + q.d = s/4; + } else oops(); + } + + return q.WithMagnitude(1); } Quaternion Quaternion::Plus(Quaternion y) { @@ -194,6 +220,8 @@ Vector Vector::RotatedAbout(Vector axis, double theta) { double c = cos(theta); double s = sin(theta); + axis = axis.WithMagnitude(1); + Vector r; r.x = (x)*(c + (1 - c)*(axis.x)*(axis.x)) +