Force the numerical guess for a normal to be exactly correct when a
same orientation constraint is applied; this makes convergence easy. And don't hover faces or constraints while dragging something. [git-p4: depot-paths = "//depot/solvespace/": change = 1798]solver
parent
ae566f0380
commit
89bb81b35c
|
@ -306,7 +306,7 @@ void Constraint::MenuConstrain(int id) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case GraphicsWindow::MNU_ORIENTED_SAME:
|
case GraphicsWindow::MNU_ORIENTED_SAME: {
|
||||||
if(gs.anyNormals == 2 && gs.n == 2) {
|
if(gs.anyNormals == 2 && gs.n == 2) {
|
||||||
c.type = SAME_ORIENTATION;
|
c.type = SAME_ORIENTATION;
|
||||||
c.entityA = gs.anyNormal[0];
|
c.entityA = gs.anyNormal[0];
|
||||||
|
@ -315,8 +315,36 @@ void Constraint::MenuConstrain(int id) {
|
||||||
Error("Bad selection for same orientation constraint.");
|
Error("Bad selection for same orientation constraint.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
AddConstraint(&c);
|
SS.UndoRemember();
|
||||||
|
|
||||||
|
Entity *nfree = SS.GetEntity(c.entityA);
|
||||||
|
Entity *nref = SS.GetEntity(c.entityB);
|
||||||
|
if(nref->group.v == SS.GW.activeGroup.v) {
|
||||||
|
SWAP(Entity *, nref, nfree);
|
||||||
|
}
|
||||||
|
if(nfree->group.v == SS.GW.activeGroup.v &&
|
||||||
|
nref ->group.v != SS.GW.activeGroup.v)
|
||||||
|
{
|
||||||
|
// nfree is free, and nref is locked (since it came from a
|
||||||
|
// previous group); so let's force nfree aligned to nref,
|
||||||
|
// and make convergence easy
|
||||||
|
Vector ru = nref ->NormalU(), rv = nref ->NormalV();
|
||||||
|
Vector fu = nfree->NormalU(), fv = nfree->NormalV();
|
||||||
|
|
||||||
|
if(fabs(fu.Dot(ru)) < fabs(fu.Dot(rv))) {
|
||||||
|
// There might be an odd*90 degree rotation about the
|
||||||
|
// normal vector; allow that, since the numerical
|
||||||
|
// constraint does
|
||||||
|
SWAP(Vector, ru, rv);
|
||||||
|
}
|
||||||
|
fu = fu.Dot(ru) > 0 ? ru : ru.ScaledBy(-1);
|
||||||
|
fv = fv.Dot(rv) > 0 ? rv : rv.ScaledBy(-1);
|
||||||
|
|
||||||
|
nfree->NormalForceTo(Quaternion::From(fu, fv));
|
||||||
|
}
|
||||||
|
AddConstraint(&c, false);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case GraphicsWindow::MNU_OTHER_ANGLE:
|
case GraphicsWindow::MNU_OTHER_ANGLE:
|
||||||
if(gs.constraints == 1 && gs.n == 0) {
|
if(gs.constraints == 1 && gs.n == 0) {
|
||||||
|
|
34
draw.cpp
34
draw.cpp
|
@ -775,7 +775,8 @@ void GraphicsWindow::HitTestMakeSelection(Point2d mp) {
|
||||||
Selection s;
|
Selection s;
|
||||||
ZERO(&s);
|
ZERO(&s);
|
||||||
|
|
||||||
// Do the entities
|
// Always do the entities; we might be dragging something that should
|
||||||
|
// be auto-constrained, and we need the hover for that.
|
||||||
for(i = 0; i < SS.entity.n; i++) {
|
for(i = 0; i < SS.entity.n; i++) {
|
||||||
Entity *e = &(SS.entity.elem[i]);
|
Entity *e = &(SS.entity.elem[i]);
|
||||||
// Don't hover whatever's being dragged.
|
// Don't hover whatever's being dragged.
|
||||||
|
@ -789,22 +790,25 @@ void GraphicsWindow::HitTestMakeSelection(Point2d mp) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Constraints
|
// The constraints and faces happen only when nothing's in progress.
|
||||||
for(i = 0; i < SS.constraint.n; i++) {
|
if(pending.operation == 0) {
|
||||||
d = SS.constraint.elem[i].GetDistance(mp);
|
// Constraints
|
||||||
if(d < 10 && d < dmin) {
|
for(i = 0; i < SS.constraint.n; i++) {
|
||||||
memset(&s, 0, sizeof(s));
|
d = SS.constraint.elem[i].GetDistance(mp);
|
||||||
s.constraint = SS.constraint.elem[i].h;
|
if(d < 10 && d < dmin) {
|
||||||
dmin = d;
|
memset(&s, 0, sizeof(s));
|
||||||
|
s.constraint = SS.constraint.elem[i].h;
|
||||||
|
dmin = d;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Faces, from the triangle mesh; these are lowest priority
|
// Faces, from the triangle mesh; these are lowest priority
|
||||||
if(s.constraint.v == 0 && s.entity.v == 0 && showShaded && showFaces) {
|
if(s.constraint.v == 0 && s.entity.v == 0 && showShaded && showFaces) {
|
||||||
SMesh *m = &((SS.GetGroup(activeGroup))->mesh);
|
SMesh *m = &((SS.GetGroup(activeGroup))->mesh);
|
||||||
DWORD v = m->FirstIntersectionWith(mp);
|
DWORD v = m->FirstIntersectionWith(mp);
|
||||||
if(v) {
|
if(v) {
|
||||||
s.entity.v = v;
|
s.entity.v = v;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue