Add horizontal and vertical constraints. Those have their own 2d/3d
issues, when the points are not all in the same coordinate system. All painful, of course. Also add continuous line drawing, and auto-constraining of line segments as I draw. [git-p4: depot-paths = "//depot/solvespace/": change = 1683]
This commit is contained in:
parent
1bf7e3deaf
commit
a8001adf33
114
constraint.cpp
114
constraint.cpp
|
@ -5,6 +5,16 @@ hConstraint Constraint::AddConstraint(Constraint *c) {
|
||||||
return c->h;
|
return c->h;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Constraint::ConstrainCoincident(hEntity ptA, hEntity ptB) {
|
||||||
|
Constraint c;
|
||||||
|
memset(&c, 0, sizeof(c));
|
||||||
|
c.group = SS.GW.activeGroup;
|
||||||
|
c.type = Constraint::POINTS_COINCIDENT;
|
||||||
|
c.ptA = ptA;
|
||||||
|
c.ptB = ptB;
|
||||||
|
SS.constraint.AddAndAssignId(&c);
|
||||||
|
}
|
||||||
|
|
||||||
void Constraint::MenuConstrain(int id) {
|
void Constraint::MenuConstrain(int id) {
|
||||||
Constraint c;
|
Constraint c;
|
||||||
memset(&c, 0, sizeof(c));
|
memset(&c, 0, sizeof(c));
|
||||||
|
@ -62,6 +72,48 @@ void Constraint::MenuConstrain(int id) {
|
||||||
AddConstraint(&c);
|
AddConstraint(&c);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case GraphicsWindow::MNU_VERTICAL:
|
||||||
|
case GraphicsWindow::MNU_HORIZONTAL: {
|
||||||
|
hEntity ha, hb;
|
||||||
|
if(gs.lineSegments == 1 && gs.n == 1) {
|
||||||
|
c.entityA = gs.entity[0];
|
||||||
|
Entity *e = SS.GetEntity(c.entityA);
|
||||||
|
ha = e->assoc[0];
|
||||||
|
hb = e->assoc[1];
|
||||||
|
} else if(gs.points == 2 && gs.n == 2) {
|
||||||
|
ha = c.ptA = gs.point[0];
|
||||||
|
hb = c.ptB = gs.point[1];
|
||||||
|
} else {
|
||||||
|
Error("Bad selection for horizontal / vertical constraint.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Entity *ea = SS.GetEntity(ha);
|
||||||
|
Entity *eb = SS.GetEntity(hb);
|
||||||
|
if(ea->csys.v == Entity::NO_CSYS.v &&
|
||||||
|
eb->csys.v == Entity::NO_CSYS.v)
|
||||||
|
{
|
||||||
|
Error("Horizontal/vertical constraint applies only to "
|
||||||
|
"entities drawn in a 2d coordinate system.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(eb->csys.v == SS.GW.activeCsys.v) {
|
||||||
|
// We are constraining two points in two different csyss; so
|
||||||
|
// we have two choices for the definitons of the coordinate
|
||||||
|
// directions. ptA's gets chosen, so make sure that's the
|
||||||
|
// active csys.
|
||||||
|
hEntity t = c.ptA;
|
||||||
|
c.ptA = c.ptB;
|
||||||
|
c.ptB = t;
|
||||||
|
}
|
||||||
|
if(id == GraphicsWindow::MNU_HORIZONTAL) {
|
||||||
|
c.type = HORIZONTAL;
|
||||||
|
} else {
|
||||||
|
c.type = VERTICAL;
|
||||||
|
}
|
||||||
|
AddConstraint(&c);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case GraphicsWindow::MNU_SOLVE_NOW:
|
case GraphicsWindow::MNU_SOLVE_NOW:
|
||||||
SS.Solve();
|
SS.Solve();
|
||||||
return;
|
return;
|
||||||
|
@ -157,24 +209,27 @@ void Constraint::Generate(IdList<Equation,hEquation> *l) {
|
||||||
AddEq(l, eab.x, 0);
|
AddEq(l, eab.x, 0);
|
||||||
AddEq(l, eab.y, 1);
|
AddEq(l, eab.y, 1);
|
||||||
AddEq(l, eab.z, 2);
|
AddEq(l, eab.z, 2);
|
||||||
} else if(a->IsPointIn3d() && !b->IsPointIn3d()) {
|
} else if(!(a->IsPointIn3d() || b->IsPointIn3d()) &&
|
||||||
// One point has 2 DOF, one has 3; write two eqs, on the
|
(a->csys.v == b->csys.v))
|
||||||
// projection of the 3 DOF point into the 2 DOF point plane.
|
{
|
||||||
ExprVector p3;
|
|
||||||
p3 = a->PointGetExprs();
|
|
||||||
Entity *csy = SS.GetEntity(b->csys);
|
|
||||||
ExprVector u, v;
|
|
||||||
csy->Csys2dGetBasisExprs(&u, &v);
|
|
||||||
AddEq(l, Expr::FromParam(b->param.h[0])->Minus(p3.Dot(u)), 0);
|
|
||||||
AddEq(l, Expr::FromParam(b->param.h[1])->Minus(p3.Dot(v)), 1);
|
|
||||||
} else if(a->csys.v == b->csys.v) {
|
|
||||||
// Both in same csys, nice.
|
// Both in same csys, nice.
|
||||||
AddEq(l, Expr::FromParam(a->param.h[0])->Minus(
|
AddEq(l, Expr::FromParam(a->param.h[0])->Minus(
|
||||||
Expr::FromParam(b->param.h[0])), 0);
|
Expr::FromParam(b->param.h[0])), 0);
|
||||||
AddEq(l, Expr::FromParam(a->param.h[1])->Minus(
|
AddEq(l, Expr::FromParam(a->param.h[1])->Minus(
|
||||||
Expr::FromParam(b->param.h[1])), 1);
|
Expr::FromParam(b->param.h[1])), 1);
|
||||||
} else {
|
} else {
|
||||||
oops();
|
// Either two 2 DOF points in different planes, or one
|
||||||
|
// 3 DOF point and one 2 DOF point. Either way, write two
|
||||||
|
// equations on the projection of a into b's plane.
|
||||||
|
ExprVector p3;
|
||||||
|
p3 = a->PointGetExprs();
|
||||||
|
Entity *csy = SS.GetEntity(b->csys);
|
||||||
|
ExprVector offset = csy->Csys2dGetOffsetExprs();
|
||||||
|
p3 = p3.Minus(offset);
|
||||||
|
ExprVector u, v;
|
||||||
|
csy->Csys2dGetBasisExprs(&u, &v);
|
||||||
|
AddEq(l, Expr::FromParam(b->param.h[0])->Minus(p3.Dot(u)), 0);
|
||||||
|
AddEq(l, Expr::FromParam(b->param.h[1])->Minus(p3.Dot(v)), 1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -188,6 +243,41 @@ void Constraint::Generate(IdList<Equation,hEquation> *l) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case HORIZONTAL:
|
||||||
|
case VERTICAL: {
|
||||||
|
hEntity ha, hb;
|
||||||
|
if(entityA.v) {
|
||||||
|
Entity *e = SS.GetEntity(entityA);
|
||||||
|
ha = e->assoc[0];
|
||||||
|
hb = e->assoc[1];
|
||||||
|
} else {
|
||||||
|
ha = ptA;
|
||||||
|
hb = ptB;
|
||||||
|
}
|
||||||
|
Entity *a = SS.GetEntity(ha);
|
||||||
|
Entity *b = SS.GetEntity(hb);
|
||||||
|
if(a->csys.v == Entity::NO_CSYS.v) {
|
||||||
|
Entity *t = a;
|
||||||
|
a = b;
|
||||||
|
b = t;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(a->csys.v == b->csys.v) {
|
||||||
|
int i = (type == HORIZONTAL) ? 1 : 0;
|
||||||
|
AddEq(l, Expr::FromParam(a->param.h[i])->Minus(
|
||||||
|
Expr::FromParam(b->param.h[i])), 0);
|
||||||
|
} else {
|
||||||
|
Entity *csy = SS.GetEntity(a->csys);
|
||||||
|
ExprVector u, v;
|
||||||
|
csy->Csys2dGetBasisExprs(&u, &v);
|
||||||
|
ExprVector norm = (type == HORIZONTAL) ? v : u;
|
||||||
|
ExprVector pa = a->PointGetExprs();
|
||||||
|
ExprVector pb = b->PointGetExprs();
|
||||||
|
AddEq(l, (pa.Minus(pb)).Dot(norm), 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default: oops();
|
default: oops();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ void Constraint::DrawOrGetDistance(Vector *labelPos) {
|
||||||
Vector gu = SS.GW.projUp;
|
Vector gu = SS.GW.projUp;
|
||||||
Vector gn = gr.Cross(gu);
|
Vector gn = gr.Cross(gu);
|
||||||
|
|
||||||
glxColor(1, 0.3, 1);
|
glxColor(1, 0.2, 1);
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case PT_PT_DISTANCE: {
|
case PT_PT_DISTANCE: {
|
||||||
Vector ap = SS.GetEntity(ptA)->PointGetCoords();
|
Vector ap = SS.GetEntity(ptA)->PointGetCoords();
|
||||||
|
@ -125,6 +125,55 @@ void Constraint::DrawOrGetDistance(Vector *labelPos) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case HORIZONTAL:
|
||||||
|
case VERTICAL:
|
||||||
|
if(entityA.v) {
|
||||||
|
Entity *e = SS.GetEntity(entityA);
|
||||||
|
Vector a = SS.GetEntity(e->assoc[0])->PointGetCoords();
|
||||||
|
Vector b = SS.GetEntity(e->assoc[1])->PointGetCoords();
|
||||||
|
Vector m = (a.ScaledBy(0.5)).Plus(b.ScaledBy(0.5));
|
||||||
|
|
||||||
|
if(dogd.drawing) {
|
||||||
|
glPushMatrix();
|
||||||
|
glxTranslatev(m);
|
||||||
|
glxOntoCsys(gr, gu);
|
||||||
|
glxWriteText(type == HORIZONTAL ? "H" : "V");
|
||||||
|
glPopMatrix();
|
||||||
|
} else {
|
||||||
|
Point2d ref = SS.GW.ProjectPoint(m);
|
||||||
|
dogd.dmin = min(dogd.dmin, ref.DistanceTo(dogd.mp)-10);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Vector a = SS.GetEntity(ptA)->PointGetCoords();
|
||||||
|
Vector b = SS.GetEntity(ptB)->PointGetCoords();
|
||||||
|
Entity *csy = SS.GetEntity(SS.GetEntity(ptA)->csys);
|
||||||
|
Vector cn = csy->Csys2dGetNormalVector();
|
||||||
|
|
||||||
|
int i;
|
||||||
|
for(i = 0; i < 2; i++) {
|
||||||
|
Vector o = (i == 0) ? a : b;
|
||||||
|
Vector d = (i == 0) ? a.Minus(b) : b.Minus(a);
|
||||||
|
Vector dp = cn.Cross(d);
|
||||||
|
d = d.WithMagnitude(14/SS.GW.scale);
|
||||||
|
Vector c = o.Minus(d);
|
||||||
|
LineDrawOrGetDistance(o, c);
|
||||||
|
d = d.WithMagnitude(3/SS.GW.scale);
|
||||||
|
dp = dp.WithMagnitude(2/SS.GW.scale);
|
||||||
|
if(dogd.drawing) {
|
||||||
|
glBegin(GL_QUADS);
|
||||||
|
glxVertex3v((c.Plus(d)).Plus(dp));
|
||||||
|
glxVertex3v((c.Minus(d)).Plus(dp));
|
||||||
|
glxVertex3v((c.Minus(d)).Minus(dp));
|
||||||
|
glxVertex3v((c.Plus(d)).Minus(dp));
|
||||||
|
glEnd();
|
||||||
|
} else {
|
||||||
|
Point2d ref = SS.GW.ProjectPoint(c);
|
||||||
|
dogd.dmin = min(dogd.dmin, ref.DistanceTo(dogd.mp)-6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default: oops();
|
default: oops();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
10
entity.cpp
10
entity.cpp
|
@ -16,6 +16,12 @@ void Entity::Csys2dGetBasisVectors(Vector *u, Vector *v) {
|
||||||
*v = quat.RotationV();
|
*v = quat.RotationV();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector Entity::Csys2dGetNormalVector(void) {
|
||||||
|
Vector u, v;
|
||||||
|
Csys2dGetBasisVectors(&u, &v);
|
||||||
|
return u.Cross(v);
|
||||||
|
}
|
||||||
|
|
||||||
void Entity::Csys2dGetBasisExprs(ExprVector *u, ExprVector *v) {
|
void Entity::Csys2dGetBasisExprs(ExprVector *u, ExprVector *v) {
|
||||||
Expr *a = Expr::FromParam(param.h[0]);
|
Expr *a = Expr::FromParam(param.h[0]);
|
||||||
Expr *b = Expr::FromParam(param.h[1]);
|
Expr *b = Expr::FromParam(param.h[1]);
|
||||||
|
@ -47,6 +53,10 @@ void Entity::Csys2dGetBasisExprs(ExprVector *u, ExprVector *v) {
|
||||||
v->z = (v->z)->Plus(two->Times(c->Times(d)));
|
v->z = (v->z)->Plus(two->Times(c->Times(d)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ExprVector Entity::Csys2dGetOffsetExprs(void) {
|
||||||
|
return SS.GetEntity(assoc[0])->PointGetExprs();
|
||||||
|
}
|
||||||
|
|
||||||
bool Entity::HasPlane(void) {
|
bool Entity::HasPlane(void) {
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case CSYS_2D:
|
case CSYS_2D:
|
||||||
|
|
|
@ -73,8 +73,8 @@ const GraphicsWindow::MenuEntry GraphicsWindow::menu[] = {
|
||||||
{ 1, "A&ngle\tShift+N", 0, 'N'|S, NULL },
|
{ 1, "A&ngle\tShift+N", 0, 'N'|S, NULL },
|
||||||
{ 1, "Other S&upplementary Angle\tShift+U", 0, 'U'|S, NULL },
|
{ 1, "Other S&upplementary Angle\tShift+U", 0, 'U'|S, NULL },
|
||||||
{ 1, NULL, 0, NULL },
|
{ 1, NULL, 0, NULL },
|
||||||
{ 1, "&Horizontal\tShift+H", 0, 'H'|S, NULL },
|
{ 1, "&Horizontal\tShift+H", MNU_HORIZONTAL, 'H'|S, mCon },
|
||||||
{ 1, "&Vertical\tShift+V", 0, 'V'|S, NULL },
|
{ 1, "&Vertical\tShift+V", MNU_VERTICAL, 'V'|S, mCon },
|
||||||
{ 1, NULL, 0, NULL },
|
{ 1, NULL, 0, NULL },
|
||||||
{ 1, "&On Point / Curve / Plane\tShift+O", MNU_ON_ENTITY, 'O'|S, mCon },
|
{ 1, "&On Point / Curve / Plane\tShift+O", MNU_ON_ENTITY, 'O'|S, mCon },
|
||||||
{ 1, "E&qual Length / Radius\tShift+Q", MNU_EQUAL, 'Q'|S, mCon },
|
{ 1, "E&qual Length / Radius\tShift+Q", MNU_EQUAL, 'Q'|S, mCon },
|
||||||
|
@ -264,6 +264,8 @@ void GraphicsWindow::MenuEdit(int id) {
|
||||||
SS.GW.ClearSelection();
|
SS.GW.ClearSelection();
|
||||||
SS.GW.pendingOperation = 0;
|
SS.GW.pendingOperation = 0;
|
||||||
SS.GW.pendingDescription = NULL;
|
SS.GW.pendingDescription = NULL;
|
||||||
|
SS.GW.pendingPoint.v = 0;
|
||||||
|
SS.GW.pendingConstraint.v = 0;
|
||||||
SS.TW.ScreenNavigation('h', 0);
|
SS.TW.ScreenNavigation('h', 0);
|
||||||
SS.TW.Show();
|
SS.TW.Show();
|
||||||
break;
|
break;
|
||||||
|
@ -360,7 +362,7 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
|
||||||
double dy = (y - orig.mouse.y) / scale;
|
double dy = (y - orig.mouse.y) / scale;
|
||||||
|
|
||||||
// When the view is locked, permit only translation (pan).
|
// When the view is locked, permit only translation (pan).
|
||||||
if(shiftDown || viewLocked) {
|
if(!(shiftDown || ctrlDown) || viewLocked) {
|
||||||
offset.x = orig.offset.x + dx*projRight.x + dy*projUp.x;
|
offset.x = orig.offset.x + dx*projRight.x + dy*projUp.x;
|
||||||
offset.y = orig.offset.y + dx*projRight.y + dy*projUp.y;
|
offset.y = orig.offset.y + dx*projRight.y + dy*projUp.y;
|
||||||
offset.z = orig.offset.z + dx*projRight.z + dy*projUp.z;
|
offset.z = orig.offset.z + dx*projRight.z + dy*projUp.z;
|
||||||
|
@ -404,7 +406,7 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
|
||||||
// Start dragging this point.
|
// Start dragging this point.
|
||||||
ClearSelection();
|
ClearSelection();
|
||||||
pendingPoint = hover.entity;
|
pendingPoint = hover.entity;
|
||||||
pendingOperation = PENDING_OPERATION_DRAGGING_POINT;
|
pendingOperation = DRAGGING_POINT;
|
||||||
}
|
}
|
||||||
} else if(hover.constraint.v &&
|
} else if(hover.constraint.v &&
|
||||||
SS.GetConstraint(hover.constraint)->HasLabel())
|
SS.GetConstraint(hover.constraint)->HasLabel())
|
||||||
|
@ -412,29 +414,28 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
|
||||||
if(dm > dmt) {
|
if(dm > dmt) {
|
||||||
ClearSelection();
|
ClearSelection();
|
||||||
pendingConstraint = hover.constraint;
|
pendingConstraint = hover.constraint;
|
||||||
pendingOperation = PENDING_OPERATION_DRAGGING_CONSTRAINT;
|
pendingOperation = DRAGGING_CONSTRAINT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if(pendingOperation == PENDING_OPERATION_DRAGGING_POINT ||
|
} else if(pendingOperation == DRAGGING_POINT ||
|
||||||
pendingOperation == PENDING_OPERATION_DRAGGING_NEW_POINT)
|
pendingOperation == DRAGGING_NEW_POINT ||
|
||||||
|
pendingOperation == DRAGGING_NEW_LINE_POINT)
|
||||||
{
|
{
|
||||||
UpdateDraggedEntity(pendingPoint, x, y);
|
UpdateDraggedEntity(pendingPoint, x, y);
|
||||||
} else if(pendingOperation == PENDING_OPERATION_DRAGGING_CONSTRAINT) {
|
} else if(pendingOperation == DRAGGING_CONSTRAINT) {
|
||||||
Constraint *c = SS.constraint.FindById(pendingConstraint);
|
Constraint *c = SS.constraint.FindById(pendingConstraint);
|
||||||
UpdateDraggedPoint(&(c->disp.offset), x, y);
|
UpdateDraggedPoint(&(c->disp.offset), x, y);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// No buttons pressed.
|
// No buttons pressed.
|
||||||
if(pendingOperation == PENDING_OPERATION_DRAGGING_NEW_POINT) {
|
if(pendingOperation == DRAGGING_NEW_POINT ||
|
||||||
|
pendingOperation == DRAGGING_NEW_LINE_POINT)
|
||||||
|
{
|
||||||
UpdateDraggedEntity(pendingPoint, x, y);
|
UpdateDraggedEntity(pendingPoint, x, y);
|
||||||
|
HitTestMakeSelection(mp);
|
||||||
} else {
|
} else {
|
||||||
// Do our usual hit testing, for the selection.
|
// Do our usual hit testing, for the selection.
|
||||||
Selection s;
|
HitTestMakeSelection(mp);
|
||||||
HitTestMakeSelection(mp, &s);
|
|
||||||
if(!s.Equals(&hover)) {
|
|
||||||
hover = s;
|
|
||||||
InvalidateGraphics();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -457,18 +458,22 @@ void GraphicsWindow::Selection::Draw(void) {
|
||||||
if(constraint.v) SS.GetConstraint(constraint)->Draw();
|
if(constraint.v) SS.GetConstraint(constraint)->Draw();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphicsWindow::HitTestMakeSelection(Point2d mp, Selection *dest) {
|
void GraphicsWindow::HitTestMakeSelection(Point2d mp) {
|
||||||
int i;
|
int i;
|
||||||
double d, dmin = 1e12;
|
double d, dmin = 1e12;
|
||||||
|
Selection s;
|
||||||
memset(dest, 0, sizeof(*dest));
|
memset(&s, 0, sizeof(s));
|
||||||
|
|
||||||
// Do the entities
|
// Do the entities
|
||||||
for(i = 0; i < SS.entity.n; i++) {
|
for(i = 0; i < SS.entity.n; i++) {
|
||||||
d = SS.entity.elem[i].GetDistance(mp);
|
Entity *e = &(SS.entity.elem[i]);
|
||||||
|
// Don't hover whatever's being dragged.
|
||||||
|
if(e->h.request().v == pendingPoint.request().v) continue;
|
||||||
|
|
||||||
|
d = e->GetDistance(mp);
|
||||||
if(d < 10 && d < dmin) {
|
if(d < 10 && d < dmin) {
|
||||||
memset(dest, 0, sizeof(*dest));
|
memset(&s, 0, sizeof(s));
|
||||||
dest->entity = SS.entity.elem[i].h;
|
s.entity = e->h;
|
||||||
dmin = d;
|
dmin = d;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -477,11 +482,16 @@ void GraphicsWindow::HitTestMakeSelection(Point2d mp, Selection *dest) {
|
||||||
for(i = 0; i < SS.constraint.n; i++) {
|
for(i = 0; i < SS.constraint.n; i++) {
|
||||||
d = SS.constraint.elem[i].GetDistance(mp);
|
d = SS.constraint.elem[i].GetDistance(mp);
|
||||||
if(d < 10 && d < dmin) {
|
if(d < 10 && d < dmin) {
|
||||||
memset(dest, 0, sizeof(*dest));
|
memset(&s, 0, sizeof(s));
|
||||||
dest->constraint = SS.constraint.elem[i].h;
|
s.constraint = SS.constraint.elem[i].h;
|
||||||
dmin = d;
|
dmin = d;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!s.Equals(&hover)) {
|
||||||
|
hover = s;
|
||||||
|
InvalidateGraphics();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GraphicsWindow::ClearSelection(void) {
|
void GraphicsWindow::ClearSelection(void) {
|
||||||
|
@ -565,17 +575,41 @@ void GraphicsWindow::MouseLeftDown(double mx, double my) {
|
||||||
hr = AddRequest(Request::LINE_SEGMENT);
|
hr = AddRequest(Request::LINE_SEGMENT);
|
||||||
SS.GetEntity(hr.entity(1))->PointForceTo(v);
|
SS.GetEntity(hr.entity(1))->PointForceTo(v);
|
||||||
|
|
||||||
pendingOperation = PENDING_OPERATION_DRAGGING_NEW_POINT;
|
pendingOperation = DRAGGING_NEW_LINE_POINT;
|
||||||
pendingPoint = hr.entity(2);
|
pendingPoint = hr.entity(2);
|
||||||
pendingDescription = "click to place next point of line";
|
pendingDescription = "click to place next point of line";
|
||||||
SS.GetEntity(pendingPoint)->PointForceTo(v);
|
SS.GetEntity(pendingPoint)->PointForceTo(v);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PENDING_OPERATION_DRAGGING_NEW_POINT:
|
case DRAGGING_NEW_POINT:
|
||||||
// The MouseMoved event has already dragged it under the cursor.
|
// The MouseMoved event has already dragged it under the cursor.
|
||||||
pendingOperation = 0;
|
pendingOperation = 0;
|
||||||
|
pendingPoint.v = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case DRAGGING_NEW_LINE_POINT: {
|
||||||
|
if(hover.entity.v && SS.GetEntity(hover.entity)->IsPoint()) {
|
||||||
|
Constraint::ConstrainCoincident(pendingPoint, hover.entity);
|
||||||
|
pendingOperation = 0;
|
||||||
|
pendingPoint.v = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Create a new line segment, so that we continue drawing.
|
||||||
|
hRequest hr = AddRequest(Request::LINE_SEGMENT);
|
||||||
|
SS.GetEntity(hr.entity(1))->PointForceTo(v);
|
||||||
|
|
||||||
|
// Constrain the line segments to share an endpoint
|
||||||
|
Constraint::ConstrainCoincident(pendingPoint, hr.entity(1));
|
||||||
|
|
||||||
|
// And drag an endpoint of the new line segment
|
||||||
|
pendingOperation = DRAGGING_NEW_LINE_POINT;
|
||||||
|
pendingPoint = hr.entity(2);
|
||||||
|
pendingDescription = "click to place next point of next line";
|
||||||
|
SS.GetEntity(pendingPoint)->PointForceTo(v);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case 0:
|
case 0:
|
||||||
default: {
|
default: {
|
||||||
pendingOperation = 0;
|
pendingOperation = 0;
|
||||||
|
@ -609,8 +643,8 @@ void GraphicsWindow::MouseLeftDown(double mx, double my) {
|
||||||
|
|
||||||
void GraphicsWindow::MouseLeftUp(double mx, double my) {
|
void GraphicsWindow::MouseLeftUp(double mx, double my) {
|
||||||
switch(pendingOperation) {
|
switch(pendingOperation) {
|
||||||
case PENDING_OPERATION_DRAGGING_POINT:
|
case DRAGGING_POINT:
|
||||||
case PENDING_OPERATION_DRAGGING_CONSTRAINT:
|
case DRAGGING_CONSTRAINT:
|
||||||
pendingOperation = 0;
|
pendingOperation = 0;
|
||||||
pendingPoint.v = 0;
|
pendingPoint.v = 0;
|
||||||
pendingConstraint.v = 0;
|
pendingConstraint.v = 0;
|
||||||
|
|
21
polygon.h
Normal file
21
polygon.h
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
|
||||||
|
#ifndef __POLYGON_H
|
||||||
|
#define __POLYGON_H
|
||||||
|
|
||||||
|
class SPolyhedron {
|
||||||
|
public:
|
||||||
|
};
|
||||||
|
|
||||||
|
class SPolygon {
|
||||||
|
public:
|
||||||
|
};
|
||||||
|
|
||||||
|
class SContour {
|
||||||
|
public:
|
||||||
|
};
|
||||||
|
|
||||||
|
class SEdgeList {
|
||||||
|
public:
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
8
sketch.h
8
sketch.h
|
@ -58,9 +58,13 @@ public:
|
||||||
int solveOrder;
|
int solveOrder;
|
||||||
bool solved;
|
bool solved;
|
||||||
|
|
||||||
|
bool visible;
|
||||||
|
|
||||||
NameStr name;
|
NameStr name;
|
||||||
|
|
||||||
char *DescriptionString(void);
|
char *DescriptionString(void);
|
||||||
|
|
||||||
|
SPolygon GetPolygon(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -140,7 +144,9 @@ public:
|
||||||
|
|
||||||
// Applies only for a CSYS_2D type
|
// Applies only for a CSYS_2D type
|
||||||
void Csys2dGetBasisVectors(Vector *u, Vector *v);
|
void Csys2dGetBasisVectors(Vector *u, Vector *v);
|
||||||
|
Vector Csys2dGetNormalVector(void);
|
||||||
void Csys2dGetBasisExprs(ExprVector *u, ExprVector *v);
|
void Csys2dGetBasisExprs(ExprVector *u, ExprVector *v);
|
||||||
|
ExprVector Csys2dGetOffsetExprs(void);
|
||||||
|
|
||||||
bool IsPoint(void);
|
bool IsPoint(void);
|
||||||
bool IsPointIn3d(void);
|
bool IsPointIn3d(void);
|
||||||
|
@ -260,6 +266,8 @@ public:
|
||||||
void ModifyToSatisfy(void);
|
void ModifyToSatisfy(void);
|
||||||
void AddEq(IdList<Equation,hEquation> *l, Expr *expr, int index);
|
void AddEq(IdList<Equation,hEquation> *l, Expr *expr, int index);
|
||||||
static Expr *Distance(hEntity pa, hEntity pb);
|
static Expr *Distance(hEntity pa, hEntity pb);
|
||||||
|
|
||||||
|
static void ConstrainCoincident(hEntity ptA, hEntity ptB);
|
||||||
};
|
};
|
||||||
|
|
||||||
class hEquation {
|
class hEquation {
|
||||||
|
|
|
@ -56,6 +56,7 @@ void MemFree(void *p);
|
||||||
|
|
||||||
|
|
||||||
#include "dsc.h"
|
#include "dsc.h"
|
||||||
|
#include "polygon.h"
|
||||||
#include "sketch.h"
|
#include "sketch.h"
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
#include "expr.h"
|
#include "expr.h"
|
||||||
|
|
11
ui.h
11
ui.h
|
@ -101,6 +101,8 @@ public:
|
||||||
MNU_DISTANCE_DIA,
|
MNU_DISTANCE_DIA,
|
||||||
MNU_EQUAL,
|
MNU_EQUAL,
|
||||||
MNU_ON_ENTITY,
|
MNU_ON_ENTITY,
|
||||||
|
MNU_HORIZONTAL,
|
||||||
|
MNU_VERTICAL,
|
||||||
MNU_SOLVE_NOW,
|
MNU_SOLVE_NOW,
|
||||||
} MenuId;
|
} MenuId;
|
||||||
typedef void MenuHandler(int id);
|
typedef void MenuHandler(int id);
|
||||||
|
@ -148,9 +150,10 @@ public:
|
||||||
|
|
||||||
// Operations that must be completed by doing something with the mouse
|
// Operations that must be completed by doing something with the mouse
|
||||||
// are noted here.
|
// are noted here.
|
||||||
static const int PENDING_OPERATION_DRAGGING_POINT = 0x0f000000;
|
static const int DRAGGING_POINT = 0x0f000000;
|
||||||
static const int PENDING_OPERATION_DRAGGING_NEW_POINT = 0x0f000001;
|
static const int DRAGGING_NEW_POINT = 0x0f000001;
|
||||||
static const int PENDING_OPERATION_DRAGGING_CONSTRAINT = 0x0f000002;
|
static const int DRAGGING_NEW_LINE_POINT = 0x0f000002;
|
||||||
|
static const int DRAGGING_CONSTRAINT = 0x0f000003;
|
||||||
hEntity pendingPoint;
|
hEntity pendingPoint;
|
||||||
hConstraint pendingConstraint;
|
hConstraint pendingConstraint;
|
||||||
int pendingOperation;
|
int pendingOperation;
|
||||||
|
@ -175,7 +178,7 @@ public:
|
||||||
Selection hover;
|
Selection hover;
|
||||||
static const int MAX_SELECTED = 32;
|
static const int MAX_SELECTED = 32;
|
||||||
Selection selection[MAX_SELECTED];
|
Selection selection[MAX_SELECTED];
|
||||||
void HitTestMakeSelection(Point2d mp, Selection *dest);
|
void HitTestMakeSelection(Point2d mp);
|
||||||
void ClearSelection(void);
|
void ClearSelection(void);
|
||||||
struct {
|
struct {
|
||||||
hEntity point[MAX_SELECTED];
|
hEntity point[MAX_SELECTED];
|
||||||
|
|
Loading…
Reference in New Issue
Block a user