Find a memory corruption! I was getting a pointer into the entity
list, and then adding a new entity to that list, and then looking at that pointer again. Not okay; the add operation might have forced a realloc. I have to watch for that. And add a "distance ratio" constraint, plus a new kind of group that comes with its own workplane. The workplane is not solved for; it's generated explicitly in terms of elements that are already solved. [git-p4: depot-paths = "//depot/solvespace/": change = 1716]solver
parent
6042fb3e0f
commit
e2263c69c8
|
@ -69,7 +69,8 @@ void Constraint::MenuConstrain(int id) {
|
|||
Vector n = SS.GW.projRight.Cross(SS.GW.projUp);
|
||||
Vector a = SS.GetEntity(c.ptA)->PointGetNum();
|
||||
Vector b = SS.GetEntity(c.ptB)->PointGetNum();
|
||||
c.disp.offset = n.Cross(a.Minus(b)).WithMagnitude(50);
|
||||
c.disp.offset = n.Cross(a.Minus(b));
|
||||
c.disp.offset = (c.disp.offset).WithMagnitude(50/SS.GW.scale);
|
||||
} else {
|
||||
c.disp.offset = Vector::MakeFrom(0, 0, 0);
|
||||
}
|
||||
|
@ -116,6 +117,21 @@ void Constraint::MenuConstrain(int id) {
|
|||
AddConstraint(&c);
|
||||
break;
|
||||
|
||||
case GraphicsWindow::MNU_RATIO:
|
||||
if(gs.lineSegments == 2 && gs.n == 2) {
|
||||
c.type = LENGTH_RATIO;
|
||||
c.entityA = gs.entity[0];
|
||||
c.entityB = gs.entity[1];
|
||||
} else {
|
||||
Error("Bad selection for length ratio constraint.");
|
||||
return;
|
||||
}
|
||||
|
||||
c.exprA = Expr::FromString("0")->DeepCopyKeep();
|
||||
c.ModifyToSatisfy();
|
||||
AddConstraint(&c);
|
||||
break;
|
||||
|
||||
case GraphicsWindow::MNU_AT_MIDPOINT:
|
||||
if(gs.lineSegments == 1 && gs.points == 1 && gs.n == 2) {
|
||||
c.type = AT_MIDPOINT;
|
||||
|
@ -379,6 +395,15 @@ void Constraint::Generate(IdList<Equation,hEquation> *l) {
|
|||
break;
|
||||
}
|
||||
|
||||
case LENGTH_RATIO: {
|
||||
Entity *a = SS.GetEntity(entityA);
|
||||
Entity *b = SS.GetEntity(entityB);
|
||||
Expr *la = Distance(workplane, a->point[0], a->point[1]);
|
||||
Expr *lb = Distance(workplane, b->point[0], b->point[1]);
|
||||
AddEq(l, (la->Div(lb))->Minus(exprA), 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case DIAMETER: {
|
||||
Entity *circle = SS.GetEntity(entityA);
|
||||
Expr *r = (SS.GetEntity(circle->distance))->DistanceGetExpr();
|
||||
|
|
|
@ -6,6 +6,7 @@ bool Constraint::HasLabel(void) {
|
|||
case PT_PLANE_DISTANCE:
|
||||
case PT_PT_DISTANCE:
|
||||
case DIAMETER:
|
||||
case LENGTH_RATIO:
|
||||
return true;
|
||||
|
||||
default:
|
||||
|
@ -249,7 +250,7 @@ void Constraint::DrawOrGetDistance(Vector *labelPos) {
|
|||
case PARALLEL: {
|
||||
for(int i = 0; i < 2; i++) {
|
||||
Entity *e = SS.GetEntity(i == 0 ? entityA : entityB);
|
||||
Vector n = e->VectorGetExprs().Eval();
|
||||
Vector n = e->VectorGetNum();
|
||||
n = n.WithMagnitude(25/SS.GW.scale);
|
||||
Vector u = (gn.Cross(n)).WithMagnitude(4/SS.GW.scale);
|
||||
Vector p = e->VectorGetRefPoint();
|
||||
|
@ -260,17 +261,23 @@ void Constraint::DrawOrGetDistance(Vector *labelPos) {
|
|||
break;
|
||||
}
|
||||
|
||||
case LENGTH_RATIO:
|
||||
case EQUAL_LENGTH_LINES: {
|
||||
Vector a, b;
|
||||
for(int i = 0; i < 2; i++) {
|
||||
Entity *e = SS.GetEntity(i == 0 ? entityA : entityB);
|
||||
Vector a = SS.GetEntity(e->point[0])->PointGetNum();
|
||||
Vector b = SS.GetEntity(e->point[1])->PointGetNum();
|
||||
a = SS.GetEntity(e->point[0])->PointGetNum();
|
||||
b = SS.GetEntity(e->point[1])->PointGetNum();
|
||||
Vector m = (a.ScaledBy(1.0/3)).Plus(b.ScaledBy(2.0/3));
|
||||
Vector ab = a.Minus(b);
|
||||
Vector n = (gn.Cross(ab)).WithMagnitude(10/SS.GW.scale);
|
||||
|
||||
LineDrawOrGetDistance(m.Minus(n), m.Plus(n));
|
||||
}
|
||||
if(type == LENGTH_RATIO) {
|
||||
Vector ref = ((a.Plus(b)).ScaledBy(0.5)).Plus(disp.offset);
|
||||
DoLabel(ref, labelPos, gr, gu);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
1
dsc.h
1
dsc.h
|
@ -52,6 +52,7 @@ public:
|
|||
Vector ScaledBy(double s);
|
||||
Vector ProjectInto(hEntity wrkpl);
|
||||
double DivPivoting(Vector delta);
|
||||
Vector ClosestOrtho(void);
|
||||
};
|
||||
|
||||
class Point2d {
|
||||
|
|
44
entity.cpp
44
entity.cpp
|
@ -1,8 +1,13 @@
|
|||
#include "solvespace.h"
|
||||
|
||||
char *Entity::DescriptionString(void) {
|
||||
Request *r = SS.GetRequest(h.request());
|
||||
return r->DescriptionString();
|
||||
if(h.isFromRequest()) {
|
||||
Request *r = SS.GetRequest(h.request());
|
||||
return r->DescriptionString();
|
||||
} else {
|
||||
Group *g = SS.GetGroup(h.group());
|
||||
return g->DescriptionString();
|
||||
}
|
||||
}
|
||||
|
||||
bool Entity::HasVector(void) {
|
||||
|
@ -35,6 +40,22 @@ ExprVector Entity::VectorGetExprs(void) {
|
|||
}
|
||||
}
|
||||
|
||||
Vector Entity::VectorGetNum(void) {
|
||||
switch(type) {
|
||||
case LINE_SEGMENT:
|
||||
return (SS.GetEntity(point[0])->PointGetNum()).Minus(
|
||||
SS.GetEntity(point[1])->PointGetNum());
|
||||
|
||||
case NORMAL_IN_3D:
|
||||
case NORMAL_IN_2D:
|
||||
case NORMAL_N_COPY:
|
||||
case NORMAL_N_ROT:
|
||||
return NormalN();
|
||||
|
||||
default: oops();
|
||||
}
|
||||
}
|
||||
|
||||
Vector Entity::VectorGetRefPoint(void) {
|
||||
switch(type) {
|
||||
case LINE_SEGMENT:
|
||||
|
@ -111,6 +132,7 @@ bool Entity::IsPoint(void) {
|
|||
switch(type) {
|
||||
case POINT_IN_3D:
|
||||
case POINT_IN_2D:
|
||||
case POINT_N_COPY:
|
||||
case POINT_N_TRANS:
|
||||
case POINT_N_ROT_TRANS:
|
||||
return true;
|
||||
|
@ -289,6 +311,10 @@ void Entity::PointForceTo(Vector p) {
|
|||
break;
|
||||
}
|
||||
|
||||
case POINT_N_COPY:
|
||||
// Nothing to do; it's a static copy
|
||||
break;
|
||||
|
||||
default: oops();
|
||||
}
|
||||
}
|
||||
|
@ -330,6 +356,11 @@ Vector Entity::PointGetNum(void) {
|
|||
p = p.Plus(offset);
|
||||
break;
|
||||
}
|
||||
|
||||
case POINT_N_COPY:
|
||||
p = numPoint;
|
||||
break;
|
||||
|
||||
default: oops();
|
||||
}
|
||||
return p;
|
||||
|
@ -383,6 +414,12 @@ ExprVector Entity::PointGetExprs(void) {
|
|||
r = orig.Plus(trans);
|
||||
break;
|
||||
}
|
||||
case POINT_N_COPY:
|
||||
r.x = Expr::FromConstant(numPoint.x);
|
||||
r.y = Expr::FromConstant(numPoint.y);
|
||||
r.z = Expr::FromConstant(numPoint.z);
|
||||
break;
|
||||
|
||||
default: oops();
|
||||
}
|
||||
return r;
|
||||
|
@ -498,6 +535,7 @@ void Entity::DrawOrGetDistance(int order) {
|
|||
}
|
||||
|
||||
switch(type) {
|
||||
case POINT_N_COPY:
|
||||
case POINT_N_TRANS:
|
||||
case POINT_N_ROT_TRANS:
|
||||
case POINT_IN_3D:
|
||||
|
@ -563,7 +601,7 @@ void Entity::DrawOrGetDistance(int order) {
|
|||
Vector tip = tail.Plus(v);
|
||||
LineDrawOrGetDistance(tail, tip);
|
||||
|
||||
v = v.WithMagnitude(12);
|
||||
v = v.WithMagnitude(12/SS.GW.scale);
|
||||
Vector axis = q.RotationV();
|
||||
LineDrawOrGetDistance(tip, tip.Minus(v.RotatedAbout(axis, 0.6)));
|
||||
LineDrawOrGetDistance(tip, tip.Minus(v.RotatedAbout(axis, -0.6)));
|
||||
|
|
128
file.cpp
128
file.cpp
|
@ -13,7 +13,7 @@ void SolveSpace::NewFile(void) {
|
|||
memset(&g, 0, sizeof(g));
|
||||
g.visible = true;
|
||||
g.name.strcpy("#references");
|
||||
g.type = Group::DRAWING;
|
||||
g.type = Group::DRAWING_3D;
|
||||
g.h = Group::HGROUP_REFERENCES;
|
||||
group.Add(&g);
|
||||
|
||||
|
@ -45,66 +45,76 @@ void SolveSpace::NewFile(void) {
|
|||
|
||||
|
||||
const SolveSpace::SaveTable SolveSpace::SAVED[] = {
|
||||
{ 'g', "Group.h.v", 'x', &(SS.sv.g.h.v) },
|
||||
{ 'g', "Group.type", 'd', &(SS.sv.g.type) },
|
||||
{ 'g', "Group.name", 'N', &(SS.sv.g.name) },
|
||||
{ 'g', "Group.opA.v", 'x', &(SS.sv.g.opA.v) },
|
||||
{ 'g', "Group.opB.v", 'x', &(SS.sv.g.opB.v) },
|
||||
{ 'g', "Group.solveOrder", 'd', &(SS.sv.g.solveOrder) },
|
||||
{ 'g', "Group.visible", 'b', &(SS.sv.g.visible) },
|
||||
{ 'g', "Group.remap", 'M', &(SS.sv.g.remap) },
|
||||
{ 'g', "Group.h.v", 'x', &(SS.sv.g.h.v) },
|
||||
{ 'g', "Group.type", 'd', &(SS.sv.g.type) },
|
||||
{ 'g', "Group.name", 'N', &(SS.sv.g.name) },
|
||||
{ 'g', "Group.opA.v", 'x', &(SS.sv.g.opA.v) },
|
||||
{ 'g', "Group.opB.v", 'x', &(SS.sv.g.opB.v) },
|
||||
{ 'g', "Group.wrkpl.type", 'd', &(SS.sv.g.wrkpl.type) },
|
||||
{ 'g', "Group.wrkpl.q.w", 'f', &(SS.sv.g.wrkpl.q.w) },
|
||||
{ 'g', "Group.wrkpl.q.vx", 'f', &(SS.sv.g.wrkpl.q.vx) },
|
||||
{ 'g', "Group.wrkpl.q.vy", 'f', &(SS.sv.g.wrkpl.q.vy) },
|
||||
{ 'g', "Group.wrkpl.q.vz", 'f', &(SS.sv.g.wrkpl.q.vz) },
|
||||
{ 'g', "Group.wrkpl.origin.v", 'x', &(SS.sv.g.wrkpl.origin.v) },
|
||||
{ 'g', "Group.wrkpl.entityB.v", 'x', &(SS.sv.g.wrkpl.entityB.v)},
|
||||
{ 'g', "Group.wrkpl.entityC.v", 'x', &(SS.sv.g.wrkpl.entityC.v)},
|
||||
{ 'g', "Group.wrkpl.swapUV", 'b', &(SS.sv.g.wrkpl.swapUV) },
|
||||
{ 'g', "Group.wrkpl.negateU", 'b', &(SS.sv.g.wrkpl.negateU) },
|
||||
{ 'g', "Group.wrkpl.negateV", 'b', &(SS.sv.g.wrkpl.negateV) },
|
||||
{ 'g', "Group.visible", 'b', &(SS.sv.g.visible) },
|
||||
{ 'g', "Group.remap", 'M', &(SS.sv.g.remap) },
|
||||
|
||||
{ 'p', "Param.h.v.", 'x', &(SS.sv.p.h.v) },
|
||||
{ 'p', "Param.val", 'f', &(SS.sv.p.val) },
|
||||
{ 'p', "Param.h.v.", 'x', &(SS.sv.p.h.v) },
|
||||
{ 'p', "Param.val", 'f', &(SS.sv.p.val) },
|
||||
|
||||
{ 'r', "Request.h.v", 'x', &(SS.sv.r.h.v) },
|
||||
{ 'r', "Request.type", 'd', &(SS.sv.r.type) },
|
||||
{ 'r', "Request.workplane.v", 'x', &(SS.sv.r.workplane.v) },
|
||||
{ 'r', "Request.group.v", 'x', &(SS.sv.r.group.v) },
|
||||
{ 'r', "Request.name", 'N', &(SS.sv.r.name) },
|
||||
{ 'r', "Request.construction", 'b', &(SS.sv.r.construction) },
|
||||
{ 'r', "Request.h.v", 'x', &(SS.sv.r.h.v) },
|
||||
{ 'r', "Request.type", 'd', &(SS.sv.r.type) },
|
||||
{ 'r', "Request.workplane.v", 'x', &(SS.sv.r.workplane.v) },
|
||||
{ 'r', "Request.group.v", 'x', &(SS.sv.r.group.v) },
|
||||
{ 'r', "Request.name", 'N', &(SS.sv.r.name) },
|
||||
{ 'r', "Request.construction", 'b', &(SS.sv.r.construction) },
|
||||
|
||||
{ 'e', "Entity.h.v", 'x', &(SS.sv.e.h.v) },
|
||||
{ 'e', "Entity.type", 'd', &(SS.sv.e.type) },
|
||||
{ 'e', "Entity.group.v", 'x', &(SS.sv.e.group.v) },
|
||||
{ 'e', "Entity.construction", 'b', &(SS.sv.e.construction) },
|
||||
{ 'e', "Entity.param[0].v", 'x', &(SS.sv.e.param[0].v) },
|
||||
{ 'e', "Entity.param[1].v", 'x', &(SS.sv.e.param[1].v) },
|
||||
{ 'e', "Entity.param[2].v", 'x', &(SS.sv.e.param[2].v) },
|
||||
{ 'e', "Entity.param[3].v", 'x', &(SS.sv.e.param[3].v) },
|
||||
{ 'e', "Entity.param[4].v", 'x', &(SS.sv.e.param[4].v) },
|
||||
{ 'e', "Entity.param[5].v", 'x', &(SS.sv.e.param[5].v) },
|
||||
{ 'e', "Entity.param[6].v", 'x', &(SS.sv.e.param[6].v) },
|
||||
{ 'e', "Entity.point[0].v", 'x', &(SS.sv.e.point[0].v) },
|
||||
{ 'e', "Entity.point[1].v", 'x', &(SS.sv.e.point[1].v) },
|
||||
{ 'e', "Entity.point[2].v", 'x', &(SS.sv.e.point[2].v) },
|
||||
{ 'e', "Entity.point[3].v", 'x', &(SS.sv.e.point[3].v) },
|
||||
{ 'e', "Entity.normal.v", 'x', &(SS.sv.e.normal.v) },
|
||||
{ 'e', "Entity.distance.v", 'x', &(SS.sv.e.distance.v) },
|
||||
{ 'e', "Entity.workplane.v", 'x', &(SS.sv.e.workplane.v) },
|
||||
{ 'e', "Entity.numPoint.x", 'f', &(SS.sv.e.numPoint.x) },
|
||||
{ 'e', "Entity.numPoint.y", 'f', &(SS.sv.e.numPoint.y) },
|
||||
{ 'e', "Entity.numPoint.z", 'f', &(SS.sv.e.numPoint.z) },
|
||||
{ 'e', "Entity.numNormal.w", 'f', &(SS.sv.e.numNormal.w) },
|
||||
{ '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) },
|
||||
{ 'e', "Entity.h.v", 'x', &(SS.sv.e.h.v) },
|
||||
{ 'e', "Entity.type", 'd', &(SS.sv.e.type) },
|
||||
{ 'e', "Entity.group.v", 'x', &(SS.sv.e.group.v) },
|
||||
{ 'e', "Entity.construction", 'b', &(SS.sv.e.construction) },
|
||||
{ 'e', "Entity.param[0].v", 'x', &(SS.sv.e.param[0].v) },
|
||||
{ 'e', "Entity.param[1].v", 'x', &(SS.sv.e.param[1].v) },
|
||||
{ 'e', "Entity.param[2].v", 'x', &(SS.sv.e.param[2].v) },
|
||||
{ 'e', "Entity.param[3].v", 'x', &(SS.sv.e.param[3].v) },
|
||||
{ 'e', "Entity.param[4].v", 'x', &(SS.sv.e.param[4].v) },
|
||||
{ 'e', "Entity.param[5].v", 'x', &(SS.sv.e.param[5].v) },
|
||||
{ 'e', "Entity.param[6].v", 'x', &(SS.sv.e.param[6].v) },
|
||||
{ 'e', "Entity.point[0].v", 'x', &(SS.sv.e.point[0].v) },
|
||||
{ 'e', "Entity.point[1].v", 'x', &(SS.sv.e.point[1].v) },
|
||||
{ 'e', "Entity.point[2].v", 'x', &(SS.sv.e.point[2].v) },
|
||||
{ 'e', "Entity.point[3].v", 'x', &(SS.sv.e.point[3].v) },
|
||||
{ 'e', "Entity.normal.v", 'x', &(SS.sv.e.normal.v) },
|
||||
{ 'e', "Entity.distance.v", 'x', &(SS.sv.e.distance.v) },
|
||||
{ 'e', "Entity.workplane.v", 'x', &(SS.sv.e.workplane.v) },
|
||||
{ 'e', "Entity.numPoint.x", 'f', &(SS.sv.e.numPoint.x) },
|
||||
{ 'e', "Entity.numPoint.y", 'f', &(SS.sv.e.numPoint.y) },
|
||||
{ 'e', "Entity.numPoint.z", 'f', &(SS.sv.e.numPoint.z) },
|
||||
{ 'e', "Entity.numNormal.w", 'f', &(SS.sv.e.numNormal.w) },
|
||||
{ '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) },
|
||||
{ 'c', "Constraint.group.v", 'x', &(SS.sv.c.group.v) },
|
||||
{ 'c', "Constraint.workplane.v", 'x', &(SS.sv.c.workplane.v) },
|
||||
{ 'c', "Constraint.exprA", 'E', &(SS.sv.c.exprA) },
|
||||
{ 'c', "Constraint.exprB", 'E', &(SS.sv.c.exprB) },
|
||||
{ 'c', "Constraint.ptA.v", 'x', &(SS.sv.c.ptA.v) },
|
||||
{ 'c', "Constraint.ptB.v", 'x', &(SS.sv.c.ptB.v) },
|
||||
{ 'c', "Constraint.ptC.v", 'x', &(SS.sv.c.ptC.v) },
|
||||
{ 'c', "Constraint.entityA.v", 'x', &(SS.sv.c.entityA.v) },
|
||||
{ 'c', "Constraint.entityB.v", 'x', &(SS.sv.c.entityB.v) },
|
||||
{ 'c', "Constraint.disp.offset.x", 'f', &(SS.sv.c.disp.offset.x)},
|
||||
{ 'c', "Constraint.disp.offset.y", 'f', &(SS.sv.c.disp.offset.y)},
|
||||
{ 'c', "Constraint.disp.offset.z", 'f', &(SS.sv.c.disp.offset.z)},
|
||||
{ 'c', "Constraint.h.v", 'x', &(SS.sv.c.h.v) },
|
||||
{ 'c', "Constraint.type", 'd', &(SS.sv.c.type) },
|
||||
{ 'c', "Constraint.group.v", 'x', &(SS.sv.c.group.v) },
|
||||
{ 'c', "Constraint.workplane.v", 'x', &(SS.sv.c.workplane.v) },
|
||||
{ 'c', "Constraint.exprA", 'E', &(SS.sv.c.exprA) },
|
||||
{ 'c', "Constraint.exprB", 'E', &(SS.sv.c.exprB) },
|
||||
{ 'c', "Constraint.ptA.v", 'x', &(SS.sv.c.ptA.v) },
|
||||
{ 'c', "Constraint.ptB.v", 'x', &(SS.sv.c.ptB.v) },
|
||||
{ 'c', "Constraint.ptC.v", 'x', &(SS.sv.c.ptC.v) },
|
||||
{ 'c', "Constraint.entityA.v", 'x', &(SS.sv.c.entityA.v) },
|
||||
{ 'c', "Constraint.entityB.v", 'x', &(SS.sv.c.entityB.v) },
|
||||
{ 'c', "Constraint.disp.offset.x", 'f', &(SS.sv.c.disp.offset.x) },
|
||||
{ 'c', "Constraint.disp.offset.y", 'f', &(SS.sv.c.disp.offset.y) },
|
||||
{ 'c', "Constraint.disp.offset.z", 'f', &(SS.sv.c.disp.offset.z) },
|
||||
|
||||
{ 0, NULL, NULL, NULL },
|
||||
};
|
||||
|
@ -264,16 +274,20 @@ bool SolveSpace::LoadFromFile(char *filename) {
|
|||
LoadUsingTable(key, val);
|
||||
} else if(strcmp(line, "AddGroup")==0) {
|
||||
SS.group.Add(&(sv.g));
|
||||
memset(&(sv.g), 0, sizeof(sv.g));
|
||||
} else if(strcmp(line, "AddParam")==0) {
|
||||
// params are regenerated, but we want to preload the values
|
||||
// for initial guesses
|
||||
SS.param.Add(&(sv.p));
|
||||
memset(&(sv.p), 0, sizeof(sv.p));
|
||||
} else if(strcmp(line, "AddEntity")==0) {
|
||||
// entities are regenerated
|
||||
} else if(strcmp(line, "AddRequest")==0) {
|
||||
SS.request.Add(&(sv.r));
|
||||
memset(&(sv.r), 0, sizeof(sv.r));
|
||||
} else if(strcmp(line, "AddConstraint")==0) {
|
||||
SS.constraint.Add(&(sv.c));
|
||||
memset(&(sv.c), 0, sizeof(sv.c));
|
||||
} else if(strcmp(line, "ñ÷åò±²³´SolveSpaceREVa")==0) {
|
||||
// do nothing, version string
|
||||
} else {
|
||||
|
|
|
@ -78,6 +78,7 @@ const GraphicsWindow::MenuEntry GraphicsWindow::menu[] = {
|
|||
{ 1, NULL, 0, NULL },
|
||||
{ 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, "Length Ra&tio\tShift+T", MNU_RATIO, 'T'|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 },
|
||||
|
@ -97,7 +98,7 @@ void GraphicsWindow::Init(void) {
|
|||
memset(this, 0, sizeof(*this));
|
||||
|
||||
offset.x = offset.y = offset.z = 0;
|
||||
scale = 1;
|
||||
scale = 5;
|
||||
projRight.x = 1; projRight.y = projRight.z = 0;
|
||||
projUp.y = 1; projUp.z = projUp.x = 0;
|
||||
|
||||
|
@ -150,10 +151,11 @@ void GraphicsWindow::AnimateOnto(Quaternion quatf, Vector offsetf) {
|
|||
quatf = quatf.ScaledBy(-1);
|
||||
mp = mm;
|
||||
}
|
||||
double mo = (offset0.Minus(offsetf)).Magnitude()/scale;
|
||||
double mo = (offset0.Minus(offsetf)).Magnitude()*scale;
|
||||
|
||||
// Animate transition, unless it's a tiny move.
|
||||
SDWORD dt = (mp < 0.01 && mo < 10) ? (-20) : (SDWORD)(100 + 1000*mp);
|
||||
SDWORD dt = (mp < 0.01 && mo < 10) ? (-20) :
|
||||
(SDWORD)(100 + 1000*mp + 0.4*mo);
|
||||
SDWORD tn, t0 = GetMilliseconds();
|
||||
double s = 0;
|
||||
do {
|
||||
|
@ -559,7 +561,7 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
|
|||
Entity *circle = SS.GetEntity(pending.circle);
|
||||
Vector center = SS.GetEntity(circle->point[0])->PointGetNum();
|
||||
Point2d c2 = ProjectPoint(center);
|
||||
double r = c2.DistanceTo(mp)*scale;
|
||||
double r = c2.DistanceTo(mp)/scale;
|
||||
SS.GetEntity(circle->distance)->DistanceForceTo(r);
|
||||
break;
|
||||
}
|
||||
|
|
108
sketch.cpp
108
sketch.cpp
|
@ -24,12 +24,53 @@ void Group::MenuGroup(int id) {
|
|||
memset(&g, 0, sizeof(g));
|
||||
g.visible = true;
|
||||
|
||||
SS.GW.GroupSelection();
|
||||
#define gs (SS.GW.gs)
|
||||
|
||||
switch(id) {
|
||||
case GraphicsWindow::MNU_GROUP_3D:
|
||||
g.type = DRAWING;
|
||||
g.type = DRAWING_3D;
|
||||
g.name.strcpy("draw-in-3d");
|
||||
break;
|
||||
|
||||
case GraphicsWindow::MNU_GROUP_WRKPL:
|
||||
g.type = DRAWING_WORKPLANE;
|
||||
g.name.strcpy("draw-in-plane");
|
||||
if(gs.points == 1 && gs.n == 1) {
|
||||
g.wrkpl.type = WORKPLANE_BY_POINT_ORTHO;
|
||||
|
||||
Vector u = SS.GW.projRight, v = SS.GW.projUp;
|
||||
u = u.ClosestOrtho();
|
||||
v = v.Minus(u.ScaledBy(v.Dot(u)));
|
||||
v = v.ClosestOrtho();
|
||||
|
||||
g.wrkpl.q = Quaternion::MakeFrom(u, v);
|
||||
g.wrkpl.origin = gs.point[0];
|
||||
} else if(gs.points == 1 && gs.lineSegments == 2 && gs.n == 3) {
|
||||
g.wrkpl.type = WORKPLANE_BY_LINE_SEGMENTS;
|
||||
|
||||
g.wrkpl.origin = gs.point[0];
|
||||
g.wrkpl.entityB = gs.entity[0];
|
||||
g.wrkpl.entityC = gs.entity[1];
|
||||
|
||||
Vector ut = SS.GetEntity(g.wrkpl.entityB)->VectorGetNum();
|
||||
Vector vt = SS.GetEntity(g.wrkpl.entityC)->VectorGetNum();
|
||||
ut = ut.WithMagnitude(1);
|
||||
vt = vt.WithMagnitude(1);
|
||||
|
||||
if(fabs(SS.GW.projUp.Dot(vt)) < fabs(SS.GW.projUp.Dot(ut))) {
|
||||
SWAP(Vector, ut, vt);
|
||||
g.wrkpl.swapUV = true;
|
||||
}
|
||||
if(SS.GW.projRight.Dot(ut) < 0) g.wrkpl.negateU = true;
|
||||
if(SS.GW.projUp. Dot(vt) < 0) g.wrkpl.negateV = true;
|
||||
} else {
|
||||
Error("Bad selection for new drawing in workplane.");
|
||||
return;
|
||||
}
|
||||
SS.GW.ClearSelection();
|
||||
break;
|
||||
|
||||
case GraphicsWindow::MNU_GROUP_EXTRUDE:
|
||||
g.type = EXTRUDE;
|
||||
g.opA = SS.GW.activeGroup;
|
||||
|
@ -48,6 +89,13 @@ void Group::MenuGroup(int id) {
|
|||
SS.group.AddAndAssignId(&g);
|
||||
SS.GenerateAll(SS.GW.solving == GraphicsWindow::SOLVE_ALWAYS);
|
||||
SS.GW.activeGroup = g.h;
|
||||
if(g.type == DRAWING_WORKPLANE) {
|
||||
SS.GW.activeWorkplane = g.h.entity(0);
|
||||
Entity *e = SS.GetEntity(SS.GW.activeWorkplane);
|
||||
Quaternion quatf = e->Normal()->NormalGetNum();
|
||||
Vector offsetf = (e->WorkplaneGetOffset()).ScaledBy(-1);
|
||||
SS.GW.AnimateOnto(quatf, offsetf);
|
||||
}
|
||||
SS.TW.Show();
|
||||
}
|
||||
|
||||
|
@ -68,8 +116,54 @@ void Group::Generate(IdList<Entity,hEntity> *entity,
|
|||
gn = gn.WithMagnitude(200/SS.GW.scale);
|
||||
int i;
|
||||
switch(type) {
|
||||
case DRAWING:
|
||||
return;
|
||||
case DRAWING_3D:
|
||||
break;
|
||||
|
||||
case DRAWING_WORKPLANE: {
|
||||
Quaternion q;
|
||||
if(wrkpl.type == WORKPLANE_BY_LINE_SEGMENTS) {
|
||||
Vector u = SS.GetEntity(wrkpl.entityB)->VectorGetNum();
|
||||
Vector v = SS.GetEntity(wrkpl.entityC)->VectorGetNum();
|
||||
u = u.WithMagnitude(1);
|
||||
Vector n = u.Cross(v);
|
||||
v = (n.Cross(u)).WithMagnitude(1);
|
||||
|
||||
if(wrkpl.swapUV) SWAP(Vector, u, v);
|
||||
if(wrkpl.negateU) u = u.ScaledBy(-1);
|
||||
if(wrkpl.negateV) v = v.ScaledBy(-1);
|
||||
q = Quaternion::MakeFrom(u, v);
|
||||
} else if(wrkpl.type == WORKPLANE_BY_POINT_ORTHO) {
|
||||
// Already given, numerically.
|
||||
q = wrkpl.q;
|
||||
} else oops();
|
||||
|
||||
Entity normal;
|
||||
memset(&normal, 0, sizeof(normal));
|
||||
normal.type = Entity::NORMAL_N_COPY;
|
||||
normal.numNormal = q;
|
||||
normal.point[0] = h.entity(2);
|
||||
normal.group = h;
|
||||
normal.h = h.entity(1);
|
||||
entity->Add(&normal);
|
||||
|
||||
Entity point;
|
||||
memset(&point, 0, sizeof(point));
|
||||
point.type = Entity::POINT_N_COPY;
|
||||
point.numPoint = SS.GetEntity(wrkpl.origin)->PointGetNum();
|
||||
point.group = h;
|
||||
point.h = h.entity(2);
|
||||
entity->Add(&point);
|
||||
|
||||
Entity wp;
|
||||
memset(&wp, 0, sizeof(wp));
|
||||
wp.type = Entity::WORKPLANE;
|
||||
wp.normal = normal.h;
|
||||
wp.point[0] = point.h;
|
||||
wp.group = h;
|
||||
wp.h = h.entity(0);
|
||||
entity->Add(&wp);
|
||||
break;
|
||||
}
|
||||
|
||||
case EXTRUDE:
|
||||
AddParam(param, h.param(0), gn.x);
|
||||
|
@ -179,6 +273,7 @@ void Group::CopyEntity(hEntity in, int a, hParam dx, hParam dy, hParam dz,
|
|||
en.distance = Remap(ep->distance, a);
|
||||
break;
|
||||
|
||||
case Entity::POINT_N_COPY:
|
||||
case Entity::POINT_N_TRANS:
|
||||
case Entity::POINT_N_ROT_TRANS:
|
||||
case Entity::POINT_IN_3D:
|
||||
|
@ -205,6 +300,9 @@ void Group::CopyEntity(hEntity in, int a, hParam dx, hParam dy, hParam dz,
|
|||
if(a != 0) oops();
|
||||
SS.entity.Add(&en);
|
||||
|
||||
// Any operation on these lists may break existing pointers!
|
||||
ep = SS.GetEntity(in);
|
||||
|
||||
hEntity np = en.h;
|
||||
memset(&en, 0, sizeof(en));
|
||||
en.point[0] = ep->h;
|
||||
|
@ -252,7 +350,7 @@ void Group::MakePolygons(void) {
|
|||
(faces.elem[i]).Clear();
|
||||
}
|
||||
faces.Clear();
|
||||
if(type == DRAWING) {
|
||||
if(type == DRAWING_3D || type == DRAWING_WORKPLANE) {
|
||||
edges.l.Clear();
|
||||
int i;
|
||||
for(i = 0; i < SS.entity.n; i++) {
|
||||
|
@ -350,7 +448,7 @@ void Group::Draw(void) {
|
|||
} else {
|
||||
int i;
|
||||
glEnable(GL_LIGHTING);
|
||||
GLfloat vec[] = { 0, 0, 0.5, 1.0 };
|
||||
GLfloat vec[] = { 0.3f, 0.3f, 0.3f, 1.0 };
|
||||
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, vec);
|
||||
for(i = 0; i < faces.n; i++) {
|
||||
glxFillPolygon(&(faces.elem[i]));
|
||||
|
|
23
sketch.h
23
sketch.h
|
@ -42,6 +42,7 @@ public:
|
|||
|
||||
inline bool isFromRequest(void);
|
||||
inline hRequest request(void);
|
||||
inline hGroup group(void);
|
||||
inline hEquation equation(int i);
|
||||
};
|
||||
class hParam {
|
||||
|
@ -76,19 +77,32 @@ public:
|
|||
int tag;
|
||||
hGroup h;
|
||||
|
||||
static const int DRAWING = 5000;
|
||||
static const int DRAWING_3D = 5000;
|
||||
static const int DRAWING_WORKPLANE = 5001;
|
||||
static const int EXTRUDE = 5010;
|
||||
static const int ROTATE = 5020;
|
||||
static const int TRANSLATE = 5030;
|
||||
int type;
|
||||
|
||||
int solveOrder;
|
||||
bool solved;
|
||||
|
||||
hGroup opA;
|
||||
hGroup opB;
|
||||
bool visible;
|
||||
|
||||
static const int WORKPLANE_BY_POINT_ORTHO = 6000;
|
||||
static const int WORKPLANE_BY_LINE_SEGMENTS = 6001;
|
||||
struct {
|
||||
int type;
|
||||
Quaternion q;
|
||||
hEntity origin;
|
||||
hEntity entityB;
|
||||
hEntity entityC;
|
||||
bool swapUV;
|
||||
bool negateU;
|
||||
bool negateV;
|
||||
} wrkpl;
|
||||
|
||||
SEdgeList edges;
|
||||
SList<SPolygon> faces;
|
||||
struct {
|
||||
|
@ -166,6 +180,7 @@ public:
|
|||
static const int POINT_IN_2D = 2001;
|
||||
static const int POINT_N_TRANS = 2010;
|
||||
static const int POINT_N_ROT_TRANS = 2011;
|
||||
static const int POINT_N_COPY = 2012;
|
||||
|
||||
static const int NORMAL_IN_3D = 3000;
|
||||
static const int NORMAL_IN_2D = 3001;
|
||||
|
@ -215,6 +230,7 @@ public:
|
|||
|
||||
bool HasVector(void);
|
||||
ExprVector VectorGetExprs(void);
|
||||
Vector VectorGetNum(void);
|
||||
Vector VectorGetRefPoint(void);
|
||||
|
||||
// For distances
|
||||
|
@ -308,6 +324,7 @@ public:
|
|||
static const int PT_IN_PLANE = 40;
|
||||
static const int PT_ON_LINE = 41;
|
||||
static const int EQUAL_LENGTH_LINES = 50;
|
||||
static const int LENGTH_RATIO = 51;
|
||||
static const int SYMMETRIC = 60;
|
||||
static const int AT_MIDPOINT = 70;
|
||||
static const int HORIZONTAL = 80;
|
||||
|
@ -411,6 +428,8 @@ 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 hGroup hEntity::group(void)
|
||||
{ hGroup r; r.v = (v >> 16) & 0x3fff; return r; }
|
||||
inline hEquation hEntity::equation(int i)
|
||||
{ if(i != 0) oops(); hEquation r; r.v = v | 0x40000000; return r; }
|
||||
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
#define max(x, y) ((x) > (y) ? (x) : (y))
|
||||
#endif
|
||||
|
||||
#define SWAP(T, a, b) do { T temp = (a); (a) = (b); (b) = temp; } while(0)
|
||||
|
||||
#define isforname(c) (isalnum(c) || (c) == '_' || (c) == '-' || (c) == '#')
|
||||
|
||||
typedef signed long SDWORD;
|
||||
|
|
12
system.cpp
12
system.cpp
|
@ -185,7 +185,6 @@ void System::SortBySensitivity(void) {
|
|||
entryWithOrigPos[j] = j;
|
||||
}
|
||||
|
||||
#define SWAP(T, a, b) do { T temp = (a); (a) = (b); (b) = temp; } while(0)
|
||||
for(j = 0; j < mat.n; j++) {
|
||||
int dest = j; // we are writing to position j
|
||||
// And the source is whichever position ahead of us can be swapped
|
||||
|
@ -208,7 +207,7 @@ void System::SortBySensitivity(void) {
|
|||
}
|
||||
|
||||
bool System::Tol(double v) {
|
||||
return (fabs(v) < 0.001);
|
||||
return (fabs(v) < 0.01);
|
||||
}
|
||||
|
||||
void System::GaussJordan(void) {
|
||||
|
@ -291,7 +290,10 @@ bool System::SolveLinearSystem(void) {
|
|||
max = fabs(mat.A.num[ip][i]);
|
||||
}
|
||||
}
|
||||
if(fabs(max) < 1e-12) return false;
|
||||
// Don't give up on a singular matrix unless it's really bad; the
|
||||
// assumption code is responsible for identifying that condition,
|
||||
// so we're not responsible for reporting that error.
|
||||
if(fabs(max) < 1e-20) return false;
|
||||
|
||||
// Swap row imax with row i
|
||||
for(jp = 0; jp < mat.n; jp++) {
|
||||
|
@ -317,7 +319,7 @@ bool System::SolveLinearSystem(void) {
|
|||
// We've put the matrix in upper triangular form, so at this point we
|
||||
// can solve by back-substitution.
|
||||
for(i = mat.m - 1; i >= 0; i--) {
|
||||
if(fabs(mat.A.num[i][i]) < 1e-10) return false;
|
||||
if(fabs(mat.A.num[i][i]) < 1e-20) return false;
|
||||
|
||||
temp = mat.B.num[i];
|
||||
for(j = mat.n - 1; j > i; j--) {
|
||||
|
@ -360,7 +362,7 @@ bool System::NewtonSolve(int tag) {
|
|||
// Check for convergence
|
||||
converged = true;
|
||||
for(i = 0; i < mat.m; i++) {
|
||||
if(!Tol(mat.B.num[i])) {
|
||||
if(fabs(mat.B.num[i]) > 1e-10) {
|
||||
converged = false;
|
||||
break;
|
||||
}
|
||||
|
|
1
ui.h
1
ui.h
|
@ -117,6 +117,7 @@ public:
|
|||
// Constrain
|
||||
MNU_DISTANCE_DIA,
|
||||
MNU_EQUAL,
|
||||
MNU_RATIO,
|
||||
MNU_ON_ENTITY,
|
||||
MNU_SYMMETRIC,
|
||||
MNU_AT_MIDPOINT,
|
||||
|
|
12
util.cpp
12
util.cpp
|
@ -310,6 +310,18 @@ double Vector::DivPivoting(Vector delta) {
|
|||
} else oops();
|
||||
}
|
||||
|
||||
Vector Vector::ClosestOrtho(void) {
|
||||
double m = max(fabs(x), max(fabs(y), fabs(z)));
|
||||
|
||||
if(m == fabs(x)) {
|
||||
return MakeFrom((x > 0) ? 1 : -1, 0, 0);
|
||||
} else if(m == fabs(y)) {
|
||||
return MakeFrom(0, (y > 0) ? 1 : -1, 0);
|
||||
} else if(m == fabs(z)) {
|
||||
return MakeFrom(0, 0, (z > 0) ? 1 : -1);
|
||||
} else oops();
|
||||
}
|
||||
|
||||
Point2d Point2d::Plus(Point2d b) {
|
||||
Point2d r;
|
||||
r.x = x + b.x;
|
||||
|
|
Loading…
Reference in New Issue