Add point-line distance, point-plane distance, and point-on-circle
constraints. And generate the constraint equations for entities (e.g., that our unit quaternions have magnitude one). Numerical troubles there, but it sort of works. Also some stuff to draw projection lines with projected constraints, and to auto-insert more constraints as you draw. [git-p4: depot-paths = "//depot/solvespace/": change = 1711]
This commit is contained in:
parent
328a946cc4
commit
e11da119f0
|
@ -13,26 +13,21 @@ hConstraint Constraint::AddConstraint(Constraint *c) {
|
|||
return c->h;
|
||||
}
|
||||
|
||||
void Constraint::ConstrainCoincident(hEntity ptA, hEntity ptB) {
|
||||
void Constraint::Constrain(int type, hEntity ptA, hEntity ptB, hEntity entityA)
|
||||
{
|
||||
Constraint c;
|
||||
memset(&c, 0, sizeof(c));
|
||||
c.group = SS.GW.activeGroup;
|
||||
c.workplane = SS.GW.activeWorkplane;
|
||||
c.type = POINTS_COINCIDENT;
|
||||
c.type = type;
|
||||
c.ptA = ptA;
|
||||
c.ptB = ptB;
|
||||
c.entityA = entityA;
|
||||
AddConstraint(&c);
|
||||
}
|
||||
|
||||
void Constraint::ConstrainHorizVert(bool horiz, hEntity ls) {
|
||||
Constraint c;
|
||||
memset(&c, 0, sizeof(c));
|
||||
c.group = SS.GW.activeGroup;
|
||||
c.workplane = SS.GW.activeWorkplane;
|
||||
if(c.workplane.v == Entity::FREE_IN_3D.v) oops();
|
||||
c.type = (horiz ? HORIZONTAL : VERTICAL);
|
||||
c.entityA = ls;
|
||||
AddConstraint(&c);
|
||||
void Constraint::ConstrainCoincident(hEntity ptA, hEntity ptB) {
|
||||
Constrain(POINTS_COINCIDENT, ptA, ptB, Entity::NO_ENTITY);
|
||||
}
|
||||
|
||||
void Constraint::MenuConstrain(int id) {
|
||||
|
@ -55,6 +50,14 @@ void Constraint::MenuConstrain(int id) {
|
|||
Entity *e = SS.GetEntity(gs.entity[0]);
|
||||
c.ptA = e->point[0];
|
||||
c.ptB = e->point[1];
|
||||
} else if(gs.workplanes == 1 && gs.points == 1 && gs.n == 2) {
|
||||
c.type = PT_PLANE_DISTANCE;
|
||||
c.ptA = gs.point[0];
|
||||
c.entityA = gs.entity[0];
|
||||
} else if(gs.lineSegments == 1 && gs.points == 1 && gs.n == 2) {
|
||||
c.type = PT_LINE_DISTANCE;
|
||||
c.ptA = gs.point[0];
|
||||
c.entityA = gs.entity[0];
|
||||
} else if(gs.circlesOrArcs == 1 && gs.n == 1) {
|
||||
c.type = DIAMETER;
|
||||
c.entityA = gs.entity[0];
|
||||
|
@ -90,6 +93,10 @@ void Constraint::MenuConstrain(int id) {
|
|||
c.type = PT_ON_LINE;
|
||||
c.ptA = gs.point[0];
|
||||
c.entityA = gs.entity[0];
|
||||
} else if(gs.points == 1 && gs.circlesOrArcs == 1 && gs.n == 2) {
|
||||
c.type = PT_ON_CIRCLE;
|
||||
c.ptA = gs.point[0];
|
||||
c.entityA = gs.entity[0];
|
||||
} else {
|
||||
Error("Bad selection for on point / curve / plane constraint.");
|
||||
return;
|
||||
|
@ -329,6 +336,17 @@ void Constraint::Generate(IdList<Equation,hEquation> *l) {
|
|||
AddEq(l, Distance(workplane, ptA, ptB)->Minus(exprA), 0);
|
||||
break;
|
||||
|
||||
case PT_LINE_DISTANCE:
|
||||
AddEq(l,
|
||||
PointLineDistance(workplane, ptA, entityA)->Minus(exprA), 0);
|
||||
break;
|
||||
|
||||
case PT_PLANE_DISTANCE: {
|
||||
ExprVector pt = SS.GetEntity(ptA)->PointGetExprs();
|
||||
AddEq(l, (PointPlaneDistance(pt, entityA))->Minus(exprA), 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case EQUAL_LENGTH_LINES: {
|
||||
Entity *a = SS.GetEntity(entityA);
|
||||
Entity *b = SS.GetEntity(entityB);
|
||||
|
@ -390,6 +408,14 @@ void Constraint::Generate(IdList<Equation,hEquation> *l) {
|
|||
}
|
||||
break;
|
||||
|
||||
case PT_ON_CIRCLE: {
|
||||
Entity *circle = SS.GetEntity(entityA);
|
||||
hEntity center = circle->point[0];
|
||||
Expr *radius = SS.GetEntity(circle->distance)->DistanceGetExpr();
|
||||
AddEq(l, Distance(workplane, ptA, center)->Minus(radius), 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case AT_MIDPOINT:
|
||||
if(workplane.v == Entity::FREE_IN_3D.v) {
|
||||
Entity *ln = SS.GetEntity(entityA);
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
bool Constraint::HasLabel(void) {
|
||||
switch(type) {
|
||||
case PT_LINE_DISTANCE:
|
||||
case PT_PLANE_DISTANCE:
|
||||
case PT_PT_DISTANCE:
|
||||
case DIAMETER:
|
||||
return true;
|
||||
|
@ -55,6 +57,15 @@ void Constraint::DoLabel(Vector ref, Vector *labelPos, Vector gr, Vector gu) {
|
|||
}
|
||||
}
|
||||
|
||||
void Constraint::DoProjectedPoint(Vector *r) {
|
||||
Vector p = r->ProjectInto(workplane);
|
||||
glLineStipple(4, 0x5555);
|
||||
glEnable(GL_LINE_STIPPLE);
|
||||
LineDrawOrGetDistance(p, *r);
|
||||
glDisable(GL_LINE_STIPPLE);
|
||||
*r = p;
|
||||
}
|
||||
|
||||
void Constraint::DrawOrGetDistance(Vector *labelPos) {
|
||||
if(!SS.GW.showConstraints) return;
|
||||
Group *g = SS.GetGroup(group);
|
||||
|
@ -76,6 +87,11 @@ void Constraint::DrawOrGetDistance(Vector *labelPos) {
|
|||
Vector ap = SS.GetEntity(ptA)->PointGetNum();
|
||||
Vector bp = SS.GetEntity(ptB)->PointGetNum();
|
||||
|
||||
if(workplane.v != Entity::FREE_IN_3D.v) {
|
||||
DoProjectedPoint(&ap);
|
||||
DoProjectedPoint(&bp);
|
||||
}
|
||||
|
||||
Vector ref = ((ap.Plus(bp)).ScaledBy(0.5)).Plus(disp.offset);
|
||||
|
||||
Vector ab = ap.Minus(bp);
|
||||
|
@ -92,6 +108,52 @@ void Constraint::DrawOrGetDistance(Vector *labelPos) {
|
|||
break;
|
||||
}
|
||||
|
||||
case PT_PLANE_DISTANCE: {
|
||||
Vector pt = SS.GetEntity(ptA)->PointGetNum();
|
||||
Entity *plane = SS.GetEntity(entityA);
|
||||
Vector n = plane->Normal()->NormalN();
|
||||
Vector p = plane->WorkplaneGetOffset();
|
||||
double d = (p.Minus(pt)).Dot(n);
|
||||
|
||||
Vector closest = pt.Plus(n.WithMagnitude(d));
|
||||
LineDrawOrGetDistance(pt, closest);
|
||||
|
||||
Vector ref = ((closest.Plus(pt)).ScaledBy(0.5)).Plus(disp.offset);
|
||||
DoLabel(ref, labelPos, gr, gu);
|
||||
break;
|
||||
}
|
||||
|
||||
case PT_LINE_DISTANCE: {
|
||||
Vector pt = SS.GetEntity(ptA)->PointGetNum();
|
||||
Entity *line = SS.GetEntity(entityA);
|
||||
Vector lA = SS.GetEntity(line->point[0])->PointGetNum();
|
||||
Vector lB = SS.GetEntity(line->point[1])->PointGetNum();
|
||||
|
||||
if(workplane.v != Entity::FREE_IN_3D.v) {
|
||||
lA = lA.ProjectInto(workplane);
|
||||
lB = lB.ProjectInto(workplane);
|
||||
DoProjectedPoint(&pt);
|
||||
}
|
||||
|
||||
Vector lAB = (lA.Minus(lB)).WithMagnitude(1);
|
||||
Vector closest;
|
||||
// lA, lB, and pt define a plane; the min distance is in
|
||||
// that plane, so calculate its normal
|
||||
Vector pn = (pt.Minus(lA)).Cross(lAB);
|
||||
// The minimum distance line is in that plane, perpendicular
|
||||
// to the line
|
||||
Vector n = pn.Cross(lAB);
|
||||
|
||||
// Calculate the actual distance
|
||||
double d = (lAB.Cross(lA.Minus(pt))).Magnitude();
|
||||
closest = pt.Plus(n.WithMagnitude(d));
|
||||
|
||||
LineDrawOrGetDistance(pt, closest);
|
||||
Vector ref = ((closest.Plus(pt)).ScaledBy(0.5)).Plus(disp.offset);
|
||||
DoLabel(ref, labelPos, gr, gu);
|
||||
break;
|
||||
}
|
||||
|
||||
case DIAMETER: {
|
||||
Entity *circle = SS.GetEntity(entityA);
|
||||
Vector center = SS.GetEntity(circle->point[0])->PointGetNum();
|
||||
|
@ -142,6 +204,7 @@ void Constraint::DrawOrGetDistance(Vector *labelPos) {
|
|||
break;
|
||||
}
|
||||
|
||||
case PT_ON_CIRCLE:
|
||||
case PT_ON_LINE:
|
||||
case PT_IN_PLANE: {
|
||||
double s = 7/SS.GW.scale;
|
||||
|
|
3
dsc.h
3
dsc.h
|
@ -6,6 +6,8 @@ typedef unsigned long DWORD;
|
|||
typedef unsigned char BYTE;
|
||||
|
||||
class Vector;
|
||||
class Point2d;
|
||||
class hEntity;
|
||||
|
||||
class Quaternion {
|
||||
public:
|
||||
|
@ -45,6 +47,7 @@ public:
|
|||
double Magnitude(void);
|
||||
Vector WithMagnitude(double s);
|
||||
Vector ScaledBy(double s);
|
||||
Vector ProjectInto(hEntity wrkpl);
|
||||
};
|
||||
|
||||
class Point2d {
|
||||
|
|
24
entity.cpp
24
entity.cpp
|
@ -5,6 +5,10 @@ char *Entity::DescriptionString(void) {
|
|||
return r->DescriptionString();
|
||||
}
|
||||
|
||||
bool Entity::IsCircle(void) {
|
||||
return (type == CIRCLE);
|
||||
}
|
||||
|
||||
bool Entity::IsWorkplane(void) {
|
||||
return (type == WORKPLANE);
|
||||
}
|
||||
|
@ -526,3 +530,23 @@ void Entity::DrawOrGetDistance(int order) {
|
|||
}
|
||||
}
|
||||
|
||||
void Entity::AddEq(IdList<Equation,hEquation> *l, Expr *expr, int index) {
|
||||
Equation eq;
|
||||
eq.e = expr;
|
||||
eq.h = h.equation(index);
|
||||
l->Add(&eq);
|
||||
}
|
||||
|
||||
void Entity::GenerateEquations(IdList<Equation,hEquation> *l) {
|
||||
switch(type) {
|
||||
case NORMAL_IN_3D: {
|
||||
ExprQuaternion q = NormalGetExprs();
|
||||
AddEq(l, (q.Magnitude())->Minus(Expr::FromConstant(1)), 0);
|
||||
break;
|
||||
}
|
||||
default:;
|
||||
// Most entities do not generate equations.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
7
expr.cpp
7
expr.cpp
|
@ -117,6 +117,13 @@ ExprVector ExprQuaternion::RotationN(void) {
|
|||
return n;
|
||||
}
|
||||
|
||||
Expr *ExprQuaternion::Magnitude(void) {
|
||||
return ((w ->Square())->Plus(
|
||||
(vx->Square())->Plus(
|
||||
(vy->Square())->Plus(
|
||||
(vz->Square())))))->Sqrt();
|
||||
}
|
||||
|
||||
Expr *Expr::FromParam(hParam p) {
|
||||
Expr *r = AllocExpr();
|
||||
r->op = PARAM;
|
||||
|
|
2
expr.h
2
expr.h
|
@ -141,6 +141,8 @@ public:
|
|||
ExprVector RotationU(void);
|
||||
ExprVector RotationV(void);
|
||||
ExprVector RotationN(void);
|
||||
|
||||
Expr *Magnitude(void);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
1
file.cpp
1
file.cpp
|
@ -86,6 +86,7 @@ const SolveSpace::SaveTable SolveSpace::SAVED[] = {
|
|||
{ 'e', "Entity.numNormal.vx", 'f', &(SS.sv.e.numNormal.vx) },
|
||||
{ 'e', "Entity.numNormal.vy", 'f', &(SS.sv.e.numNormal.vy) },
|
||||
{ 'e', "Entity.numNormal.vz", 'f', &(SS.sv.e.numNormal.vz) },
|
||||
{ 'e', "Entity.numDistance", 'f', &(SS.sv.e.numDistance) },
|
||||
|
||||
{ 'c', "Constraint.h.v", 'x', &(SS.sv.c.h.v) },
|
||||
{ 'c', "Constraint.type", 'd', &(SS.sv.c.type) },
|
||||
|
|
|
@ -658,11 +658,43 @@ hRequest GraphicsWindow::AddRequest(int type) {
|
|||
r.workplane = activeWorkplane;
|
||||
r.type = type;
|
||||
SS.request.AddAndAssignId(&r);
|
||||
SS.GenerateAll(solving == SOLVE_ALWAYS);
|
||||
|
||||
// We must regenerate the parameters, so that the code that tries to
|
||||
// place this request's entities where the mouse is can do so. But
|
||||
// we mustn't try to solve until reasonable values have been supplied
|
||||
// for these new parameters, or else we'll get a numerical blowup.
|
||||
SS.GenerateAll(false);
|
||||
|
||||
return r.h;
|
||||
}
|
||||
|
||||
bool GraphicsWindow::ConstrainPointByHovered(hEntity pt) {
|
||||
if(!hover.entity.v) return false;
|
||||
|
||||
Entity *e = SS.GetEntity(hover.entity);
|
||||
if(e->IsPoint()) {
|
||||
Constraint::ConstrainCoincident(e->h, pt);
|
||||
return true;
|
||||
}
|
||||
if(e->IsWorkplane()) {
|
||||
Constraint::Constrain(Constraint::PT_IN_PLANE,
|
||||
pt, Entity::NO_ENTITY, e->h);
|
||||
return true;
|
||||
}
|
||||
if(e->IsCircle()) {
|
||||
Constraint::Constrain(Constraint::PT_ON_CIRCLE,
|
||||
pt, Entity::NO_ENTITY, e->h);
|
||||
return true;
|
||||
}
|
||||
if(e->type == Entity::LINE_SEGMENT) {
|
||||
Constraint::Constrain(Constraint::PT_ON_LINE,
|
||||
pt, Entity::NO_ENTITY, e->h);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void GraphicsWindow::MouseLeftDown(double mx, double my) {
|
||||
if(GraphicsEditControlIsVisible()) return;
|
||||
|
||||
|
@ -676,10 +708,6 @@ void GraphicsWindow::MouseLeftDown(double mx, double my) {
|
|||
v = v.Plus(projRight.ScaledBy(mx/scale));
|
||||
v = v.Plus(projUp.ScaledBy(my/scale));
|
||||
|
||||
#define MAYBE_PLACE(p) \
|
||||
if(hover.entity.v && SS.GetEntity((p))->IsPoint()) { \
|
||||
Constraint::ConstrainCoincident(hover.entity, (p)); \
|
||||
}
|
||||
hRequest hr;
|
||||
switch(pending.operation) {
|
||||
case MNU_DATUM_POINT:
|
||||
|
@ -694,7 +722,7 @@ void GraphicsWindow::MouseLeftDown(double mx, double my) {
|
|||
case MNU_LINE_SEGMENT:
|
||||
hr = AddRequest(Request::LINE_SEGMENT);
|
||||
SS.GetEntity(hr.entity(1))->PointForceTo(v);
|
||||
MAYBE_PLACE(hr.entity(1));
|
||||
ConstrainPointByHovered(hr.entity(1));
|
||||
|
||||
ClearSelection(); hover.Clear();
|
||||
|
||||
|
@ -717,7 +745,10 @@ void GraphicsWindow::MouseLeftDown(double mx, double my) {
|
|||
SS.GetEntity(lns[i].entity(2))->PointForceTo(v);
|
||||
}
|
||||
for(i = 0; i < 4; i++) {
|
||||
Constraint::ConstrainHorizVert((i % 2)==0, lns[i].entity(0));
|
||||
Constraint::Constrain(
|
||||
(i % 2) ? Constraint::HORIZONTAL : Constraint::VERTICAL,
|
||||
Entity::NO_ENTITY, Entity::NO_ENTITY,
|
||||
lns[i].entity(0));
|
||||
}
|
||||
|
||||
pending.operation = DRAGGING_NEW_POINT;
|
||||
|
@ -730,7 +761,7 @@ void GraphicsWindow::MouseLeftDown(double mx, double my) {
|
|||
SS.GetEntity(hr.entity(1))->PointForceTo(v);
|
||||
SS.GetEntity(hr.entity(32))->NormalForceTo(
|
||||
Quaternion::MakeFrom(SS.GW.projRight, SS.GW.projUp));
|
||||
MAYBE_PLACE(hr.entity(1));
|
||||
ConstrainPointByHovered(hr.entity(1));
|
||||
|
||||
ClearSelection(); hover.Clear();
|
||||
|
||||
|
@ -747,7 +778,7 @@ void GraphicsWindow::MouseLeftDown(double mx, double my) {
|
|||
SS.GetEntity(hr.entity(2))->PointForceTo(v);
|
||||
SS.GetEntity(hr.entity(3))->PointForceTo(v);
|
||||
SS.GetEntity(hr.entity(4))->PointForceTo(v);
|
||||
MAYBE_PLACE(hr.entity(1));
|
||||
ConstrainPointByHovered(hr.entity(1));
|
||||
|
||||
ClearSelection(); hover.Clear();
|
||||
|
||||
|
@ -761,7 +792,7 @@ void GraphicsWindow::MouseLeftDown(double mx, double my) {
|
|||
SS.GetEntity(hr.entity(1))->PointForceTo(v);
|
||||
SS.GetEntity(hr.entity(32))->NormalForceTo(
|
||||
Quaternion::MakeFrom(SS.GW.projRight, SS.GW.projUp));
|
||||
MAYBE_PLACE(hr.entity(1));
|
||||
ConstrainPointByHovered(hr.entity(1));
|
||||
|
||||
ClearSelection(); hover.Clear();
|
||||
ClearPending();
|
||||
|
@ -774,15 +805,12 @@ void GraphicsWindow::MouseLeftDown(double mx, double my) {
|
|||
break;
|
||||
|
||||
case DRAGGING_NEW_CUBIC_POINT:
|
||||
if(hover.entity.v && SS.GetEntity(hover.entity)->IsPoint()) {
|
||||
Constraint::ConstrainCoincident(pending.point, hover.entity);
|
||||
}
|
||||
ConstrainPointByHovered(pending.point);
|
||||
ClearPending();
|
||||
break;
|
||||
|
||||
case DRAGGING_NEW_LINE_POINT: {
|
||||
if(hover.entity.v && SS.GetEntity(hover.entity)->IsPoint()) {
|
||||
Constraint::ConstrainCoincident(pending.point, hover.entity);
|
||||
if(ConstrainPointByHovered(pending.point)) {
|
||||
ClearPending();
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "solvespace.h"
|
||||
|
||||
const hEntity Entity::FREE_IN_3D = { 0 };
|
||||
const hEntity Entity::NO_ENTITY = { 0 };
|
||||
|
||||
const hGroup Group::HGROUP_REFERENCES = { 1 };
|
||||
const hRequest Request::HREQUEST_REFERENCE_XY = { 1 };
|
||||
|
|
89
sketch.h
89
sketch.h
|
@ -41,6 +41,7 @@ public:
|
|||
|
||||
inline bool isFromRequest(void);
|
||||
inline hRequest request(void);
|
||||
inline hEquation equation(int i);
|
||||
};
|
||||
class hParam {
|
||||
public:
|
||||
|
@ -153,6 +154,7 @@ public:
|
|||
hEntity h;
|
||||
|
||||
static const hEntity FREE_IN_3D;
|
||||
static const hEntity NO_ENTITY;
|
||||
|
||||
static const int POINT_IN_3D = 2000;
|
||||
static const int POINT_IN_2D = 2001;
|
||||
|
@ -201,6 +203,8 @@ public:
|
|||
// times to apply the transformation.
|
||||
int timesApplied;
|
||||
|
||||
bool IsCircle(void);
|
||||
|
||||
bool HasDirection(void);
|
||||
ExprVector GetDirection(void);
|
||||
|
||||
|
@ -253,6 +257,9 @@ public:
|
|||
double GetDistance(Point2d mp);
|
||||
void GenerateEdges(SEdgeList *el);
|
||||
|
||||
void AddEq(IdList<Equation,hEquation> *l, Expr *expr, int index);
|
||||
void GenerateEquations(IdList<Equation,hEquation> *l);
|
||||
|
||||
char *DescriptionString(void);
|
||||
};
|
||||
|
||||
|
@ -270,31 +277,6 @@ public:
|
|||
};
|
||||
|
||||
|
||||
inline hEntity hGroup::entity(int i)
|
||||
{ hEntity r; r.v = 0x80000000 | (v << 16) | i; return r; }
|
||||
inline hParam hGroup::param(int i)
|
||||
{ hParam r; r.v = 0x80000000 | (v << 16) | i; return r; }
|
||||
|
||||
inline bool hRequest::IsFromReferences(void) {
|
||||
if(v == Request::HREQUEST_REFERENCE_XY.v) return true;
|
||||
if(v == Request::HREQUEST_REFERENCE_YZ.v) return true;
|
||||
if(v == Request::HREQUEST_REFERENCE_ZX.v) return true;
|
||||
return false;
|
||||
}
|
||||
inline hEntity hRequest::entity(int i)
|
||||
{ hEntity r; r.v = (v << 16) | i; return r; }
|
||||
inline hParam hRequest::param(int i)
|
||||
{ hParam r; r.v = (v << 16) | i; return r; }
|
||||
|
||||
inline bool hEntity::isFromRequest(void)
|
||||
{ if(v & 0x80000000) return false; else return true; }
|
||||
inline hRequest hEntity::request(void)
|
||||
{ hRequest r; r.v = (v >> 16); return r; }
|
||||
|
||||
inline hRequest hParam::request(void)
|
||||
{ hRequest r; r.v = (v >> 16); return r; }
|
||||
|
||||
|
||||
class hConstraint {
|
||||
public:
|
||||
DWORD v;
|
||||
|
@ -304,18 +286,20 @@ public:
|
|||
|
||||
class Constraint {
|
||||
public:
|
||||
static const int USER_EQUATION = 10;
|
||||
static const int POINTS_COINCIDENT = 20;
|
||||
static const int PT_PT_DISTANCE = 30;
|
||||
static const int PT_LINE_DISTANCE = 31;
|
||||
static const int PT_IN_PLANE = 40;
|
||||
static const int PT_ON_LINE = 41;
|
||||
static const int EQUAL_LENGTH_LINES = 50;
|
||||
static const int SYMMETRIC = 60;
|
||||
static const int AT_MIDPOINT = 70;
|
||||
static const int HORIZONTAL = 80;
|
||||
static const int VERTICAL = 81;
|
||||
static const int DIAMETER = 90;
|
||||
static const int USER_EQUATION = 10;
|
||||
static const int POINTS_COINCIDENT = 20;
|
||||
static const int PT_PT_DISTANCE = 30;
|
||||
static const int PT_LINE_DISTANCE = 31;
|
||||
static const int PT_PLANE_DISTANCE = 32;
|
||||
static const int PT_IN_PLANE = 40;
|
||||
static const int PT_ON_LINE = 41;
|
||||
static const int EQUAL_LENGTH_LINES = 50;
|
||||
static const int SYMMETRIC = 60;
|
||||
static const int AT_MIDPOINT = 70;
|
||||
static const int HORIZONTAL = 80;
|
||||
static const int VERTICAL = 81;
|
||||
static const int DIAMETER = 90;
|
||||
static const int PT_ON_CIRCLE = 100;
|
||||
|
||||
int tag;
|
||||
hConstraint h;
|
||||
|
@ -353,6 +337,7 @@ public:
|
|||
void DrawOrGetDistance(Vector *labelPos);
|
||||
double EllipticalInterpolation(double rx, double ry, double theta);
|
||||
void DoLabel(Vector ref, Vector *labelPos, Vector gr, Vector gu);
|
||||
void DoProjectedPoint(Vector *p);
|
||||
|
||||
double GetDistance(Point2d mp);
|
||||
Vector GetLabelPos(void);
|
||||
|
@ -371,7 +356,7 @@ public:
|
|||
static ExprVector PointInThreeSpace(hEntity workplane, Expr *u, Expr *v);
|
||||
|
||||
static void ConstrainCoincident(hEntity ptA, hEntity ptB);
|
||||
static void ConstrainHorizVert(bool horiz, hEntity lineSegment);
|
||||
static void Constrain(int type, hEntity ptA, hEntity ptB, hEntity entityA);
|
||||
};
|
||||
|
||||
class hEquation {
|
||||
|
@ -387,6 +372,34 @@ public:
|
|||
Expr *e;
|
||||
};
|
||||
|
||||
|
||||
inline hEntity hGroup::entity(int i)
|
||||
{ hEntity r; r.v = 0x80000000 | (v << 16) | i; return r; }
|
||||
inline hParam hGroup::param(int i)
|
||||
{ hParam r; r.v = 0x80000000 | (v << 16) | i; return r; }
|
||||
|
||||
inline bool hRequest::IsFromReferences(void) {
|
||||
if(v == Request::HREQUEST_REFERENCE_XY.v) return true;
|
||||
if(v == Request::HREQUEST_REFERENCE_YZ.v) return true;
|
||||
if(v == Request::HREQUEST_REFERENCE_ZX.v) return true;
|
||||
return false;
|
||||
}
|
||||
inline hEntity hRequest::entity(int i)
|
||||
{ hEntity r; r.v = (v << 16) | i; return r; }
|
||||
inline hParam hRequest::param(int i)
|
||||
{ hParam r; r.v = (v << 16) | i; return r; }
|
||||
|
||||
inline bool hEntity::isFromRequest(void)
|
||||
{ if(v & 0x80000000) return false; else return true; }
|
||||
inline hRequest hEntity::request(void)
|
||||
{ hRequest r; r.v = (v >> 16); return r; }
|
||||
inline hEquation hEntity::equation(int i)
|
||||
{ if(i != 0) oops(); hEquation r; r.v = v | 0x80000000; return r; }
|
||||
|
||||
inline hRequest hParam::request(void)
|
||||
{ hRequest r; r.v = (v >> 16); return r; }
|
||||
|
||||
|
||||
inline hEquation hConstraint::equation(int i)
|
||||
{ hEquation r; r.v = (v << 16) | i; return r; }
|
||||
|
||||
|
|
|
@ -127,6 +127,13 @@ bool SolveSpace::SolveGroup(hGroup hg) {
|
|||
|
||||
c->Generate(&(sys.eq));
|
||||
}
|
||||
// And the equations from entities
|
||||
for(i = 0; i < entity.n; i++) {
|
||||
Entity *e = &(entity.elem[i]);
|
||||
if(e->group.v != hg.v) continue;
|
||||
|
||||
e->GenerateEquations(&(sys.eq));
|
||||
}
|
||||
|
||||
bool r = sys.Solve();
|
||||
FreeAllTemporary();
|
||||
|
|
16
system.cpp
16
system.cpp
|
@ -70,6 +70,17 @@ bool System::IsDragged(hParam p) {
|
|||
}
|
||||
}
|
||||
}
|
||||
if(SS.GW.pending.circle.v) {
|
||||
Entity *circ = SS.entity.FindByIdNoOops(SS.GW.pending.circle);
|
||||
if(circ) {
|
||||
Entity *dist = SS.GetEntity(circ->distance);
|
||||
switch(dist->type) {
|
||||
case Entity::DISTANCE:
|
||||
if(p.v == (dist->param[0].v)) return true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -358,7 +369,10 @@ bool System::Solve(void) {
|
|||
for(i = 0; i < eq.n; i++) {
|
||||
dbp(" %.3f = %s = 0", eq.elem[i].e->Eval(), eq.elem[i].e->Print());
|
||||
}
|
||||
dbp("%d parameters", param.n); */
|
||||
dbp("%d parameters", param.n);
|
||||
for(i = 0; i < param.n; i++) {
|
||||
dbp(" param %08x at %.3f", param.elem[i].h.v, param.elem[i].val);
|
||||
} */
|
||||
|
||||
param.ClearTags();
|
||||
eq.ClearTags();
|
||||
|
|
1
ui.h
1
ui.h
|
@ -196,6 +196,7 @@ public:
|
|||
// The constraint that is being edited with the on-screen textbox.
|
||||
hConstraint constraintBeingEdited;
|
||||
|
||||
bool ConstrainPointByHovered(hEntity pt);
|
||||
hRequest AddRequest(int type);
|
||||
|
||||
// The current selection.
|
||||
|
|
14
util.cpp
14
util.cpp
|
@ -262,6 +262,19 @@ Vector Vector::WithMagnitude(double v) {
|
|||
}
|
||||
}
|
||||
|
||||
Vector Vector::ProjectInto(hEntity wrkpl) {
|
||||
Entity *w = SS.GetEntity(wrkpl);
|
||||
Vector u = w->Normal()->NormalU();
|
||||
Vector v = w->Normal()->NormalV();
|
||||
Vector p0 = w->WorkplaneGetOffset();
|
||||
|
||||
Vector f = this->Minus(p0);
|
||||
double up = f.Dot(u);
|
||||
double vp = f.Dot(v);
|
||||
|
||||
return p0.Plus((u.ScaledBy(up)).Plus(v.ScaledBy(vp)));
|
||||
}
|
||||
|
||||
Point2d Point2d::Plus(Point2d b) {
|
||||
Point2d r;
|
||||
r.x = x + b.x;
|
||||
|
@ -322,3 +335,4 @@ double Point2d::DistanceToLine(Point2d p0, Point2d dp, bool segment) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user