Add a perpendicular constraint; identical to constraining a ninety

degree angle, but shows with a right angle symbol instead of a
numerical angle you can edit.

[git-p4: depot-paths = "//depot/solvespace/": change = 1819]
solver
Jonathan Westhues 2008-07-02 01:21:29 -08:00
parent 1bc68779d9
commit fd4abd5519
6 changed files with 64 additions and 3 deletions

View File

@ -31,6 +31,7 @@ char *Constraint::DescriptionString(void) {
case SAME_ORIENTATION: s = "same-orientation"; break;
case ANGLE: s = "angle"; break;
case PARALLEL: s = "parallel"; break;
case PERPENDICULAR: s = "perpendicular"; break;
case EQUAL_RADIUS: s = "eq-radius"; break;
case COMMENT: s = "comment"; break;
default: s = "???"; break;
@ -425,6 +426,18 @@ void Constraint::MenuConstrain(int id) {
AddConstraint(&c);
break;
case GraphicsWindow::MNU_PERPENDICULAR:
if(gs.vectors == 2 && gs.n == 2) {
c.type = PERPENDICULAR;
c.entityA = gs.vector[0];
c.entityB = gs.vector[1];
} else {
Error("Bad selection for perpendicular constraint.");
return;
}
AddConstraint(&c);
break;
case GraphicsWindow::MNU_COMMENT:
c.type = COMMENT;
c.comment.strcpy("NEW COMMENT -- DOUBLE-CLICK TO EDIT");
@ -942,6 +955,7 @@ void Constraint::GenerateReal(IdList<Equation,hEquation> *l) {
break;
}
case PERPENDICULAR:
case ANGLE: {
Entity *a = SS.GetEntity(entityA);
Entity *b = SS.GetEntity(entityB);
@ -965,8 +979,16 @@ void Constraint::GenerateReal(IdList<Equation,hEquation> *l) {
Expr *dot = (ua->Times(ub))->Plus(va->Times(vb));
c = dot->Div(maga->Times(magb));
}
Expr *rads = exA->Times(Expr::From(PI/180));
AddEq(l, c->Minus(rads->Cos()), 0);
if(type == ANGLE) {
// The direction cosine is equal to the cosine of the
// specified angle
Expr *rads = exA->Times(Expr::From(PI/180));
AddEq(l, c->Minus(rads->Cos()), 0);
} else {
// The dot product (and therefore the direction cosine)
// is equal to zero, perpendicular.
AddEq(l, c, 0);
}
break;
}

View File

@ -373,6 +373,43 @@ void Constraint::DrawOrGetDistance(Vector *labelPos) {
break;
}
case PERPENDICULAR: {
Vector u, v;
Vector rn, ru;
if(workplane.v == Entity::FREE_IN_3D.v) {
rn = gn;
ru = gu;
} else {
Entity *normal = SS.GetEntity(workplane)->Normal();
rn = normal->NormalN();
ru = normal->NormalV(); // ru meaning r_up, not u/v
}
for(int i = 0; i < 2; i++) {
Entity *e = SS.GetEntity(i == 0 ? entityA : entityB);
if(i == 0) {
// Calculate orientation of perpendicular sign only
// once, so that it's the same both times it's drawn
u = e->VectorGetNum();
u = u.WithMagnitude(16/SS.GW.scale);
v = (rn.Cross(u)).WithMagnitude(16/SS.GW.scale);
if(fabs(u.Dot(ru)) < fabs(v.Dot(ru))) {
SWAP(Vector, u, v);
}
if(u.Dot(ru) < 0) u = u.ScaledBy(-1);
}
Vector p = e->VectorGetRefPoint();
Vector s = p.Plus(u).Plus(v);
LineDrawOrGetDistance(s, s.Plus(v));
Vector m = s.Plus(v.ScaledBy(0.5));
LineDrawOrGetDistance(m, m.Plus(u));
}
break;
}
case PARALLEL: {
for(int i = 0; i < 2; i++) {
Entity *e = SS.GetEntity(i == 0 ? entityA : entityB);

View File

@ -86,6 +86,7 @@ const GraphicsWindow::MenuEntry GraphicsWindow::menu[] = {
{ 1, "At &Midpoint\tShift+M", MNU_AT_MIDPOINT, 'M'|S, mCon },
{ 1, "S&ymmetric\tShift+Y", MNU_SYMMETRIC, 'Y'|S, mCon },
{ 1, "Para&llel\tShift+L", MNU_PARALLEL, 'L'|S, mCon },
{ 1, "&Perpendicular\tShift+P", MNU_PERPENDICULAR, 'P'|S, mCon },
{ 1, "Same Orient&ation\tShift+A", MNU_ORIENTED_SAME, 'A'|S, mCon },
{ 1, NULL, 0, NULL },
{ 1, "Comment\tShift+C", MNU_COMMENT, 'C'|S, mCon },

View File

@ -456,6 +456,7 @@ public:
static const int SAME_ORIENTATION = 110;
static const int ANGLE = 120;
static const int PARALLEL = 121;
static const int PERPENDICULAR = 122;
static const int EQUAL_RADIUS = 130;
static const int COMMENT = 1000;

1
ui.h
View File

@ -196,6 +196,7 @@ public:
MNU_HORIZONTAL,
MNU_VERTICAL,
MNU_PARALLEL,
MNU_PERPENDICULAR,
MNU_ORIENTED_SAME,
MNU_COMMENT,
} MenuId;

View File

@ -8,7 +8,6 @@ auto-generate circles and faces when lathing
copy the section geometry to other end when sweeping
cylindrical faces
draw explicit edges
perpendicular constraint
long term