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:
parent
018e8a0444
commit
10240cc1df
|
@ -181,6 +181,30 @@ void Constraint::MenuConstrain(int id) {
|
|||
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:
|
||||
SS.GenerateAll(true);
|
||||
return;
|
||||
|
@ -528,6 +552,37 @@ void Constraint::Generate(IdList<Equation,hEquation> *l) {
|
|||
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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -231,6 +231,35 @@ void Constraint::DrawOrGetDistance(Vector *labelPos) {
|
|||
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: {
|
||||
for(int i = 0; i < 2; i++) {
|
||||
Entity *e = SS.GetEntity(i == 0 ? entityA : entityB);
|
||||
|
|
46
entity.cpp
46
entity.cpp
|
@ -5,6 +5,49 @@ char *Entity::DescriptionString(void) {
|
|||
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) {
|
||||
return (type == CIRCLE);
|
||||
}
|
||||
|
@ -456,10 +499,13 @@ void Entity::DrawOrGetDistance(int order) {
|
|||
Vector mp = p.Minus(us).Plus (vs);
|
||||
|
||||
glxColor3d(0, 0.3, 0.3);
|
||||
glEnable(GL_LINE_STIPPLE);
|
||||
glLineStipple(3, 0x1111);
|
||||
LineDrawOrGetDistance(pp, pm);
|
||||
LineDrawOrGetDistance(pm, mm);
|
||||
LineDrawOrGetDistance(mm, mp);
|
||||
LineDrawOrGetDistance(mp, pp);
|
||||
glDisable(GL_LINE_STIPPLE);
|
||||
|
||||
if(dogd.drawing) {
|
||||
glPushMatrix();
|
||||
|
|
8
expr.cpp
8
expr.cpp
|
@ -53,6 +53,14 @@ Expr *ExprVector::Magnitude(void) {
|
|||
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 q;
|
||||
|
|
2
expr.h
2
expr.h
|
@ -130,6 +130,8 @@ public:
|
|||
ExprVector Cross(ExprVector b);
|
||||
ExprVector ScaledBy(Expr *s);
|
||||
Expr *Magnitude(void);
|
||||
|
||||
Vector Eval(void);
|
||||
};
|
||||
|
||||
class ExprQuaternion {
|
||||
|
|
|
@ -79,6 +79,8 @@ const GraphicsWindow::MenuEntry GraphicsWindow::menu[] = {
|
|||
{ 1, "E&qual Length / Radius\tShift+Q", MNU_EQUAL, 'Q'|S, mCon },
|
||||
{ 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, "Same O&rientation\tShift+R", MNU_ORIENTED_SAME, 'R'|S, mCon },
|
||||
{ 1, NULL, 0, NULL },
|
||||
{ 1, "Sym&bolic Equation\tShift+B", 0, 'B'|S, NULL },
|
||||
{ 1, NULL, 0, NULL },
|
||||
|
@ -627,11 +629,27 @@ void GraphicsWindow::GroupSelection(void) {
|
|||
(gs.n)++;
|
||||
|
||||
Entity *e = SS.entity.FindById(s->entity);
|
||||
// A list of points, and a list of all entities that aren't points.
|
||||
if(e->IsPoint()) {
|
||||
gs.point[(gs.points)++] = s->entity;
|
||||
} else {
|
||||
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) {
|
||||
case Entity::WORKPLANE: (gs.workplanes)++; break;
|
||||
case Entity::LINE_SEGMENT: (gs.lineSegments)++; break;
|
||||
|
|
7
sketch.h
7
sketch.h
|
@ -205,8 +205,9 @@ public:
|
|||
|
||||
bool IsCircle(void);
|
||||
|
||||
bool HasDirection(void);
|
||||
ExprVector GetDirection(void);
|
||||
bool HasVector(void);
|
||||
ExprVector VectorGetExprs(void);
|
||||
Vector VectorGetRefPoint(void);
|
||||
|
||||
// For distances
|
||||
double DistanceGetNum(void);
|
||||
|
@ -300,6 +301,8 @@ public:
|
|||
static const int VERTICAL = 81;
|
||||
static const int DIAMETER = 90;
|
||||
static const int PT_ON_CIRCLE = 100;
|
||||
static const int SAME_ORIENTATION = 110;
|
||||
static const int PARALLEL = 120;
|
||||
|
||||
int tag;
|
||||
hConstraint h;
|
||||
|
|
14
system.cpp
14
system.cpp
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
6
ui.h
6
ui.h
|
@ -119,6 +119,8 @@ public:
|
|||
MNU_AT_MIDPOINT,
|
||||
MNU_HORIZONTAL,
|
||||
MNU_VERTICAL,
|
||||
MNU_PARALLEL,
|
||||
MNU_ORIENTED_SAME,
|
||||
MNU_SOLVE_AUTO,
|
||||
MNU_SOLVE_NOW,
|
||||
} MenuId;
|
||||
|
@ -219,11 +221,15 @@ public:
|
|||
struct {
|
||||
hEntity point[MAX_SELECTED];
|
||||
hEntity entity[MAX_SELECTED];
|
||||
hEntity anyNormal[MAX_SELECTED];
|
||||
hEntity vector[MAX_SELECTED];
|
||||
int points;
|
||||
int entities;
|
||||
int workplanes;
|
||||
int lineSegments;
|
||||
int circlesOrArcs;
|
||||
int anyNormals;
|
||||
int vectors;
|
||||
int n;
|
||||
} gs;
|
||||
void GroupSelection(void);
|
||||
|
|
Loading…
Reference in New Issue
Block a user