Add parallel and same orientation constraints, that work on line

segments and normals.

[git-p4: depot-paths = "//depot/solvespace/": change = 1713]
This commit is contained in:
Jonathan Westhues 2008-05-08 21:33:23 -08:00
parent 018e8a0444
commit 10240cc1df
9 changed files with 183 additions and 2 deletions

View File

@ -181,6 +181,30 @@ void Constraint::MenuConstrain(int id) {
break; break;
} }
case GraphicsWindow::MNU_ORIENTED_SAME:
if(gs.anyNormals == 2 && gs.n == 2) {
c.type = SAME_ORIENTATION;
c.entityA = gs.anyNormal[0];
c.entityB = gs.anyNormal[1];
} else {
Error("Bad selection for same orientation constraint.");
return;
}
AddConstraint(&c);
break;
case GraphicsWindow::MNU_PARALLEL:
if(gs.vectors == 2 && gs.n == 2) {
c.type = PARALLEL;
c.entityA = gs.vector[0];
c.entityB = gs.vector[1];
} else {
Error("Bad selection for parallel constraint.");
return;
}
AddConstraint(&c);
break;
case GraphicsWindow::MNU_SOLVE_NOW: case GraphicsWindow::MNU_SOLVE_NOW:
SS.GenerateAll(true); SS.GenerateAll(true);
return; return;
@ -528,6 +552,37 @@ void Constraint::Generate(IdList<Equation,hEquation> *l) {
break; break;
} }
case SAME_ORIENTATION: {
Entity *a = SS.GetEntity(entityA);
Entity *b = SS.GetEntity(entityB);
ExprVector au = a->NormalExprsU(),
av = a->NormalExprsV(),
an = a->NormalExprsN();
ExprVector bu = b->NormalExprsU(),
bv = b->NormalExprsV(),
bn = b->NormalExprsN();
AddEq(l, VectorsParallel(0, an, bn), 0);
AddEq(l, VectorsParallel(1, an, bn), 1);
AddEq(l, au.Dot(bv), 2);
break;
}
case PARALLEL: {
ExprVector a = SS.GetEntity(entityA)->VectorGetExprs();
ExprVector b = SS.GetEntity(entityB)->VectorGetExprs();
if(workplane.v == Entity::FREE_IN_3D.v) {
AddEq(l, VectorsParallel(0, a, b), 0);
AddEq(l, VectorsParallel(1, a, b), 1);
} else {
Entity *w = SS.GetEntity(workplane);
ExprVector wn = w->Normal()->NormalExprsN();
AddEq(l, (a.Cross(b)).Dot(wn), 0);
}
break;
}
default: oops(); default: oops();
} }
} }

View File

@ -231,6 +231,35 @@ void Constraint::DrawOrGetDistance(Vector *labelPos) {
break; break;
} }
case SAME_ORIENTATION: {
for(int i = 0; i < 2; i++) {
Entity *e = SS.GetEntity(i == 0 ? entityA : entityB);
Quaternion q = e->NormalGetNum();
Vector n = q.RotationN().WithMagnitude(25/SS.GW.scale);
Vector u = q.RotationU().WithMagnitude(6/SS.GW.scale);
Vector p = SS.GetEntity(e->point[0])->PointGetNum();
p = p.Plus(n.WithMagnitude(10/SS.GW.scale));
LineDrawOrGetDistance(p.Plus(u), p.Minus(u).Plus(n));
LineDrawOrGetDistance(p.Minus(u), p.Plus(u).Plus(n));
}
break;
}
case PARALLEL: {
for(int i = 0; i < 2; i++) {
Entity *e = SS.GetEntity(i == 0 ? entityA : entityB);
Vector n = e->VectorGetExprs().Eval();
n = n.WithMagnitude(25/SS.GW.scale);
Vector u = (gn.Cross(n)).WithMagnitude(4/SS.GW.scale);
Vector p = e->VectorGetRefPoint();
LineDrawOrGetDistance(p.Plus(u), p.Plus(u).Plus(n));
LineDrawOrGetDistance(p.Minus(u), p.Minus(u).Plus(n));
}
break;
}
case EQUAL_LENGTH_LINES: { case EQUAL_LENGTH_LINES: {
for(int i = 0; i < 2; i++) { for(int i = 0; i < 2; i++) {
Entity *e = SS.GetEntity(i == 0 ? entityA : entityB); Entity *e = SS.GetEntity(i == 0 ? entityA : entityB);

View File

@ -5,6 +5,49 @@ char *Entity::DescriptionString(void) {
return r->DescriptionString(); return r->DescriptionString();
} }
bool Entity::HasVector(void) {
switch(type) {
case LINE_SEGMENT:
case NORMAL_IN_3D:
case NORMAL_IN_2D:
case NORMAL_XFRMD:
return true;
default:
return false;
}
}
ExprVector Entity::VectorGetExprs(void) {
switch(type) {
case LINE_SEGMENT:
return (SS.GetEntity(point[0])->PointGetExprs()).Minus(
SS.GetEntity(point[1])->PointGetExprs());
case NORMAL_IN_3D:
case NORMAL_IN_2D:
case NORMAL_XFRMD:
return NormalExprsN();
default: oops();
}
}
Vector Entity::VectorGetRefPoint(void) {
switch(type) {
case LINE_SEGMENT:
return ((SS.GetEntity(point[0])->PointGetNum()).Plus(
SS.GetEntity(point[1])->PointGetNum())).ScaledBy(0.5);
case NORMAL_IN_3D:
case NORMAL_IN_2D:
case NORMAL_XFRMD:
return SS.GetEntity(point[0])->PointGetNum();
default: oops();
}
}
bool Entity::IsCircle(void) { bool Entity::IsCircle(void) {
return (type == CIRCLE); return (type == CIRCLE);
} }
@ -456,10 +499,13 @@ void Entity::DrawOrGetDistance(int order) {
Vector mp = p.Minus(us).Plus (vs); Vector mp = p.Minus(us).Plus (vs);
glxColor3d(0, 0.3, 0.3); glxColor3d(0, 0.3, 0.3);
glEnable(GL_LINE_STIPPLE);
glLineStipple(3, 0x1111);
LineDrawOrGetDistance(pp, pm); LineDrawOrGetDistance(pp, pm);
LineDrawOrGetDistance(pm, mm); LineDrawOrGetDistance(pm, mm);
LineDrawOrGetDistance(mm, mp); LineDrawOrGetDistance(mm, mp);
LineDrawOrGetDistance(mp, pp); LineDrawOrGetDistance(mp, pp);
glDisable(GL_LINE_STIPPLE);
if(dogd.drawing) { if(dogd.drawing) {
glPushMatrix(); glPushMatrix();

View File

@ -53,6 +53,14 @@ Expr *ExprVector::Magnitude(void) {
return r->Sqrt(); return r->Sqrt();
} }
Vector ExprVector::Eval(void) {
Vector r;
r.x = x->Eval();
r.y = y->Eval();
r.z = z->Eval();
return r;
}
ExprQuaternion ExprQuaternion::FromExprs(Expr *w, Expr *vx, Expr *vy, Expr *vz) ExprQuaternion ExprQuaternion::FromExprs(Expr *w, Expr *vx, Expr *vy, Expr *vz)
{ {
ExprQuaternion q; ExprQuaternion q;

2
expr.h
View File

@ -130,6 +130,8 @@ public:
ExprVector Cross(ExprVector b); ExprVector Cross(ExprVector b);
ExprVector ScaledBy(Expr *s); ExprVector ScaledBy(Expr *s);
Expr *Magnitude(void); Expr *Magnitude(void);
Vector Eval(void);
}; };
class ExprQuaternion { class ExprQuaternion {

View File

@ -79,6 +79,8 @@ const GraphicsWindow::MenuEntry GraphicsWindow::menu[] = {
{ 1, "E&qual Length / Radius\tShift+Q", MNU_EQUAL, 'Q'|S, mCon }, { 1, "E&qual Length / Radius\tShift+Q", MNU_EQUAL, 'Q'|S, mCon },
{ 1, "At &Midpoint\tShift+M", MNU_AT_MIDPOINT, 'M'|S, mCon }, { 1, "At &Midpoint\tShift+M", MNU_AT_MIDPOINT, 'M'|S, mCon },
{ 1, "S&ymmetric\tShift+Y", MNU_SYMMETRIC, 'Y'|S, mCon }, { 1, "S&ymmetric\tShift+Y", MNU_SYMMETRIC, 'Y'|S, mCon },
{ 1, "Para&llel\tShift+L", MNU_PARALLEL, 'L'|S, mCon },
{ 1, "Same O&rientation\tShift+R", MNU_ORIENTED_SAME, 'R'|S, mCon },
{ 1, NULL, 0, NULL }, { 1, NULL, 0, NULL },
{ 1, "Sym&bolic Equation\tShift+B", 0, 'B'|S, NULL }, { 1, "Sym&bolic Equation\tShift+B", 0, 'B'|S, NULL },
{ 1, NULL, 0, NULL }, { 1, NULL, 0, NULL },
@ -627,11 +629,27 @@ void GraphicsWindow::GroupSelection(void) {
(gs.n)++; (gs.n)++;
Entity *e = SS.entity.FindById(s->entity); Entity *e = SS.entity.FindById(s->entity);
// A list of points, and a list of all entities that aren't points.
if(e->IsPoint()) { if(e->IsPoint()) {
gs.point[(gs.points)++] = s->entity; gs.point[(gs.points)++] = s->entity;
} else { } else {
gs.entity[(gs.entities)++] = s->entity; gs.entity[(gs.entities)++] = s->entity;
} }
// And an auxiliary list of normals, including normals from
// workplanes.
if(e->IsNormal()) {
gs.anyNormal[(gs.anyNormals)++] = s->entity;
} else if(e->IsWorkplane()) {
gs.anyNormal[(gs.anyNormals)++] = e->Normal()->h;
}
// And of vectors (i.e., stuff with a direction to constrain)
if(e->HasVector()) {
gs.vector[(gs.vectors)++] = s->entity;
}
// And some aux counts too
switch(e->type) { switch(e->type) {
case Entity::WORKPLANE: (gs.workplanes)++; break; case Entity::WORKPLANE: (gs.workplanes)++; break;
case Entity::LINE_SEGMENT: (gs.lineSegments)++; break; case Entity::LINE_SEGMENT: (gs.lineSegments)++; break;

View File

@ -205,8 +205,9 @@ public:
bool IsCircle(void); bool IsCircle(void);
bool HasDirection(void); bool HasVector(void);
ExprVector GetDirection(void); ExprVector VectorGetExprs(void);
Vector VectorGetRefPoint(void);
// For distances // For distances
double DistanceGetNum(void); double DistanceGetNum(void);
@ -300,6 +301,8 @@ public:
static const int VERTICAL = 81; static const int VERTICAL = 81;
static const int DIAMETER = 90; static const int DIAMETER = 90;
static const int PT_ON_CIRCLE = 100; static const int PT_ON_CIRCLE = 100;
static const int SAME_ORIENTATION = 110;
static const int PARALLEL = 120;
int tag; int tag;
hConstraint h; hConstraint h;

View File

@ -81,6 +81,20 @@ bool System::IsDragged(hParam p) {
} }
} }
} }
if(SS.GW.pending.normal.v) {
Entity *norm = SS.entity.FindByIdNoOops(SS.GW.pending.normal);
if(norm) {
switch(norm->type) {
case Entity::NORMAL_IN_3D:
if(p.v == (norm->param[0].v)) return true;
if(p.v == (norm->param[1].v)) return true;
if(p.v == (norm->param[2].v)) return true;
if(p.v == (norm->param[3].v)) return true;
break;
// other types are locked, so not draggable
}
}
}
return false; return false;
} }

6
ui.h
View File

@ -119,6 +119,8 @@ public:
MNU_AT_MIDPOINT, MNU_AT_MIDPOINT,
MNU_HORIZONTAL, MNU_HORIZONTAL,
MNU_VERTICAL, MNU_VERTICAL,
MNU_PARALLEL,
MNU_ORIENTED_SAME,
MNU_SOLVE_AUTO, MNU_SOLVE_AUTO,
MNU_SOLVE_NOW, MNU_SOLVE_NOW,
} MenuId; } MenuId;
@ -219,11 +221,15 @@ public:
struct { struct {
hEntity point[MAX_SELECTED]; hEntity point[MAX_SELECTED];
hEntity entity[MAX_SELECTED]; hEntity entity[MAX_SELECTED];
hEntity anyNormal[MAX_SELECTED];
hEntity vector[MAX_SELECTED];
int points; int points;
int entities; int entities;
int workplanes; int workplanes;
int lineSegments; int lineSegments;
int circlesOrArcs; int circlesOrArcs;
int anyNormals;
int vectors;
int n; int n;
} gs; } gs;
void GroupSelection(void); void GroupSelection(void);