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]
This commit is contained in:
parent
6042fb3e0f
commit
e2263c69c8
|
@ -69,7 +69,8 @@ void Constraint::MenuConstrain(int id) {
|
||||||
Vector n = SS.GW.projRight.Cross(SS.GW.projUp);
|
Vector n = SS.GW.projRight.Cross(SS.GW.projUp);
|
||||||
Vector a = SS.GetEntity(c.ptA)->PointGetNum();
|
Vector a = SS.GetEntity(c.ptA)->PointGetNum();
|
||||||
Vector b = SS.GetEntity(c.ptB)->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 {
|
} else {
|
||||||
c.disp.offset = Vector::MakeFrom(0, 0, 0);
|
c.disp.offset = Vector::MakeFrom(0, 0, 0);
|
||||||
}
|
}
|
||||||
|
@ -116,6 +117,21 @@ void Constraint::MenuConstrain(int id) {
|
||||||
AddConstraint(&c);
|
AddConstraint(&c);
|
||||||
break;
|
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:
|
case GraphicsWindow::MNU_AT_MIDPOINT:
|
||||||
if(gs.lineSegments == 1 && gs.points == 1 && gs.n == 2) {
|
if(gs.lineSegments == 1 && gs.points == 1 && gs.n == 2) {
|
||||||
c.type = AT_MIDPOINT;
|
c.type = AT_MIDPOINT;
|
||||||
|
@ -379,6 +395,15 @@ void Constraint::Generate(IdList<Equation,hEquation> *l) {
|
||||||
break;
|
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: {
|
case DIAMETER: {
|
||||||
Entity *circle = SS.GetEntity(entityA);
|
Entity *circle = SS.GetEntity(entityA);
|
||||||
Expr *r = (SS.GetEntity(circle->distance))->DistanceGetExpr();
|
Expr *r = (SS.GetEntity(circle->distance))->DistanceGetExpr();
|
||||||
|
|
|
@ -6,6 +6,7 @@ bool Constraint::HasLabel(void) {
|
||||||
case PT_PLANE_DISTANCE:
|
case PT_PLANE_DISTANCE:
|
||||||
case PT_PT_DISTANCE:
|
case PT_PT_DISTANCE:
|
||||||
case DIAMETER:
|
case DIAMETER:
|
||||||
|
case LENGTH_RATIO:
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -249,7 +250,7 @@ void Constraint::DrawOrGetDistance(Vector *labelPos) {
|
||||||
case PARALLEL: {
|
case PARALLEL: {
|
||||||
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);
|
||||||
Vector n = e->VectorGetExprs().Eval();
|
Vector n = e->VectorGetNum();
|
||||||
n = n.WithMagnitude(25/SS.GW.scale);
|
n = n.WithMagnitude(25/SS.GW.scale);
|
||||||
Vector u = (gn.Cross(n)).WithMagnitude(4/SS.GW.scale);
|
Vector u = (gn.Cross(n)).WithMagnitude(4/SS.GW.scale);
|
||||||
Vector p = e->VectorGetRefPoint();
|
Vector p = e->VectorGetRefPoint();
|
||||||
|
@ -260,17 +261,23 @@ void Constraint::DrawOrGetDistance(Vector *labelPos) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case LENGTH_RATIO:
|
||||||
case EQUAL_LENGTH_LINES: {
|
case EQUAL_LENGTH_LINES: {
|
||||||
|
Vector a, b;
|
||||||
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);
|
||||||
Vector a = SS.GetEntity(e->point[0])->PointGetNum();
|
a = SS.GetEntity(e->point[0])->PointGetNum();
|
||||||
Vector b = SS.GetEntity(e->point[1])->PointGetNum();
|
b = SS.GetEntity(e->point[1])->PointGetNum();
|
||||||
Vector m = (a.ScaledBy(1.0/3)).Plus(b.ScaledBy(2.0/3));
|
Vector m = (a.ScaledBy(1.0/3)).Plus(b.ScaledBy(2.0/3));
|
||||||
Vector ab = a.Minus(b);
|
Vector ab = a.Minus(b);
|
||||||
Vector n = (gn.Cross(ab)).WithMagnitude(10/SS.GW.scale);
|
Vector n = (gn.Cross(ab)).WithMagnitude(10/SS.GW.scale);
|
||||||
|
|
||||||
LineDrawOrGetDistance(m.Minus(n), m.Plus(n));
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
1
dsc.h
1
dsc.h
|
@ -52,6 +52,7 @@ public:
|
||||||
Vector ScaledBy(double s);
|
Vector ScaledBy(double s);
|
||||||
Vector ProjectInto(hEntity wrkpl);
|
Vector ProjectInto(hEntity wrkpl);
|
||||||
double DivPivoting(Vector delta);
|
double DivPivoting(Vector delta);
|
||||||
|
Vector ClosestOrtho(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
class Point2d {
|
class Point2d {
|
||||||
|
|
40
entity.cpp
40
entity.cpp
|
@ -1,8 +1,13 @@
|
||||||
#include "solvespace.h"
|
#include "solvespace.h"
|
||||||
|
|
||||||
char *Entity::DescriptionString(void) {
|
char *Entity::DescriptionString(void) {
|
||||||
|
if(h.isFromRequest()) {
|
||||||
Request *r = SS.GetRequest(h.request());
|
Request *r = SS.GetRequest(h.request());
|
||||||
return r->DescriptionString();
|
return r->DescriptionString();
|
||||||
|
} else {
|
||||||
|
Group *g = SS.GetGroup(h.group());
|
||||||
|
return g->DescriptionString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Entity::HasVector(void) {
|
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) {
|
Vector Entity::VectorGetRefPoint(void) {
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case LINE_SEGMENT:
|
case LINE_SEGMENT:
|
||||||
|
@ -111,6 +132,7 @@ bool Entity::IsPoint(void) {
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case POINT_IN_3D:
|
case POINT_IN_3D:
|
||||||
case POINT_IN_2D:
|
case POINT_IN_2D:
|
||||||
|
case POINT_N_COPY:
|
||||||
case POINT_N_TRANS:
|
case POINT_N_TRANS:
|
||||||
case POINT_N_ROT_TRANS:
|
case POINT_N_ROT_TRANS:
|
||||||
return true;
|
return true;
|
||||||
|
@ -289,6 +311,10 @@ void Entity::PointForceTo(Vector p) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case POINT_N_COPY:
|
||||||
|
// Nothing to do; it's a static copy
|
||||||
|
break;
|
||||||
|
|
||||||
default: oops();
|
default: oops();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -330,6 +356,11 @@ Vector Entity::PointGetNum(void) {
|
||||||
p = p.Plus(offset);
|
p = p.Plus(offset);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case POINT_N_COPY:
|
||||||
|
p = numPoint;
|
||||||
|
break;
|
||||||
|
|
||||||
default: oops();
|
default: oops();
|
||||||
}
|
}
|
||||||
return p;
|
return p;
|
||||||
|
@ -383,6 +414,12 @@ ExprVector Entity::PointGetExprs(void) {
|
||||||
r = orig.Plus(trans);
|
r = orig.Plus(trans);
|
||||||
break;
|
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();
|
default: oops();
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
|
@ -498,6 +535,7 @@ void Entity::DrawOrGetDistance(int order) {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(type) {
|
switch(type) {
|
||||||
|
case POINT_N_COPY:
|
||||||
case POINT_N_TRANS:
|
case POINT_N_TRANS:
|
||||||
case POINT_N_ROT_TRANS:
|
case POINT_N_ROT_TRANS:
|
||||||
case POINT_IN_3D:
|
case POINT_IN_3D:
|
||||||
|
@ -563,7 +601,7 @@ void Entity::DrawOrGetDistance(int order) {
|
||||||
Vector tip = tail.Plus(v);
|
Vector tip = tail.Plus(v);
|
||||||
LineDrawOrGetDistance(tail, tip);
|
LineDrawOrGetDistance(tail, tip);
|
||||||
|
|
||||||
v = v.WithMagnitude(12);
|
v = v.WithMagnitude(12/SS.GW.scale);
|
||||||
Vector axis = q.RotationV();
|
Vector axis = q.RotationV();
|
||||||
LineDrawOrGetDistance(tip, tip.Minus(v.RotatedAbout(axis, 0.6)));
|
LineDrawOrGetDistance(tip, tip.Minus(v.RotatedAbout(axis, 0.6)));
|
||||||
LineDrawOrGetDistance(tip, tip.Minus(v.RotatedAbout(axis, -0.6)));
|
LineDrawOrGetDistance(tip, tip.Minus(v.RotatedAbout(axis, -0.6)));
|
||||||
|
|
18
file.cpp
18
file.cpp
|
@ -13,7 +13,7 @@ void SolveSpace::NewFile(void) {
|
||||||
memset(&g, 0, sizeof(g));
|
memset(&g, 0, sizeof(g));
|
||||||
g.visible = true;
|
g.visible = true;
|
||||||
g.name.strcpy("#references");
|
g.name.strcpy("#references");
|
||||||
g.type = Group::DRAWING;
|
g.type = Group::DRAWING_3D;
|
||||||
g.h = Group::HGROUP_REFERENCES;
|
g.h = Group::HGROUP_REFERENCES;
|
||||||
group.Add(&g);
|
group.Add(&g);
|
||||||
|
|
||||||
|
@ -50,7 +50,17 @@ const SolveSpace::SaveTable SolveSpace::SAVED[] = {
|
||||||
{ 'g', "Group.name", 'N', &(SS.sv.g.name) },
|
{ 'g', "Group.name", 'N', &(SS.sv.g.name) },
|
||||||
{ 'g', "Group.opA.v", 'x', &(SS.sv.g.opA.v) },
|
{ 'g', "Group.opA.v", 'x', &(SS.sv.g.opA.v) },
|
||||||
{ 'g', "Group.opB.v", 'x', &(SS.sv.g.opB.v) },
|
{ 'g', "Group.opB.v", 'x', &(SS.sv.g.opB.v) },
|
||||||
{ 'g', "Group.solveOrder", 'd', &(SS.sv.g.solveOrder) },
|
{ '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.visible", 'b', &(SS.sv.g.visible) },
|
||||||
{ 'g', "Group.remap", 'M', &(SS.sv.g.remap) },
|
{ 'g', "Group.remap", 'M', &(SS.sv.g.remap) },
|
||||||
|
|
||||||
|
@ -264,16 +274,20 @@ bool SolveSpace::LoadFromFile(char *filename) {
|
||||||
LoadUsingTable(key, val);
|
LoadUsingTable(key, val);
|
||||||
} else if(strcmp(line, "AddGroup")==0) {
|
} else if(strcmp(line, "AddGroup")==0) {
|
||||||
SS.group.Add(&(sv.g));
|
SS.group.Add(&(sv.g));
|
||||||
|
memset(&(sv.g), 0, sizeof(sv.g));
|
||||||
} else if(strcmp(line, "AddParam")==0) {
|
} else if(strcmp(line, "AddParam")==0) {
|
||||||
// params are regenerated, but we want to preload the values
|
// params are regenerated, but we want to preload the values
|
||||||
// for initial guesses
|
// for initial guesses
|
||||||
SS.param.Add(&(sv.p));
|
SS.param.Add(&(sv.p));
|
||||||
|
memset(&(sv.p), 0, sizeof(sv.p));
|
||||||
} else if(strcmp(line, "AddEntity")==0) {
|
} else if(strcmp(line, "AddEntity")==0) {
|
||||||
// entities are regenerated
|
// entities are regenerated
|
||||||
} else if(strcmp(line, "AddRequest")==0) {
|
} else if(strcmp(line, "AddRequest")==0) {
|
||||||
SS.request.Add(&(sv.r));
|
SS.request.Add(&(sv.r));
|
||||||
|
memset(&(sv.r), 0, sizeof(sv.r));
|
||||||
} else if(strcmp(line, "AddConstraint")==0) {
|
} else if(strcmp(line, "AddConstraint")==0) {
|
||||||
SS.constraint.Add(&(sv.c));
|
SS.constraint.Add(&(sv.c));
|
||||||
|
memset(&(sv.c), 0, sizeof(sv.c));
|
||||||
} else if(strcmp(line, "ñ÷åò±²³´SolveSpaceREVa")==0) {
|
} else if(strcmp(line, "ñ÷åò±²³´SolveSpaceREVa")==0) {
|
||||||
// do nothing, version string
|
// do nothing, version string
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -78,6 +78,7 @@ const GraphicsWindow::MenuEntry GraphicsWindow::menu[] = {
|
||||||
{ 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 },
|
||||||
|
{ 1, "Length Ra&tio\tShift+T", MNU_RATIO, 'T'|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, "Para&llel\tShift+L", MNU_PARALLEL, 'L'|S, mCon },
|
||||||
|
@ -97,7 +98,7 @@ void GraphicsWindow::Init(void) {
|
||||||
memset(this, 0, sizeof(*this));
|
memset(this, 0, sizeof(*this));
|
||||||
|
|
||||||
offset.x = offset.y = offset.z = 0;
|
offset.x = offset.y = offset.z = 0;
|
||||||
scale = 1;
|
scale = 5;
|
||||||
projRight.x = 1; projRight.y = projRight.z = 0;
|
projRight.x = 1; projRight.y = projRight.z = 0;
|
||||||
projUp.y = 1; projUp.z = projUp.x = 0;
|
projUp.y = 1; projUp.z = projUp.x = 0;
|
||||||
|
|
||||||
|
@ -150,10 +151,11 @@ void GraphicsWindow::AnimateOnto(Quaternion quatf, Vector offsetf) {
|
||||||
quatf = quatf.ScaledBy(-1);
|
quatf = quatf.ScaledBy(-1);
|
||||||
mp = mm;
|
mp = mm;
|
||||||
}
|
}
|
||||||
double mo = (offset0.Minus(offsetf)).Magnitude()/scale;
|
double mo = (offset0.Minus(offsetf)).Magnitude()*scale;
|
||||||
|
|
||||||
// Animate transition, unless it's a tiny move.
|
// 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();
|
SDWORD tn, t0 = GetMilliseconds();
|
||||||
double s = 0;
|
double s = 0;
|
||||||
do {
|
do {
|
||||||
|
@ -559,7 +561,7 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
|
||||||
Entity *circle = SS.GetEntity(pending.circle);
|
Entity *circle = SS.GetEntity(pending.circle);
|
||||||
Vector center = SS.GetEntity(circle->point[0])->PointGetNum();
|
Vector center = SS.GetEntity(circle->point[0])->PointGetNum();
|
||||||
Point2d c2 = ProjectPoint(center);
|
Point2d c2 = ProjectPoint(center);
|
||||||
double r = c2.DistanceTo(mp)*scale;
|
double r = c2.DistanceTo(mp)/scale;
|
||||||
SS.GetEntity(circle->distance)->DistanceForceTo(r);
|
SS.GetEntity(circle->distance)->DistanceForceTo(r);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
108
sketch.cpp
108
sketch.cpp
|
@ -24,12 +24,53 @@ void Group::MenuGroup(int id) {
|
||||||
memset(&g, 0, sizeof(g));
|
memset(&g, 0, sizeof(g));
|
||||||
g.visible = true;
|
g.visible = true;
|
||||||
|
|
||||||
|
SS.GW.GroupSelection();
|
||||||
|
#define gs (SS.GW.gs)
|
||||||
|
|
||||||
switch(id) {
|
switch(id) {
|
||||||
case GraphicsWindow::MNU_GROUP_3D:
|
case GraphicsWindow::MNU_GROUP_3D:
|
||||||
g.type = DRAWING;
|
g.type = DRAWING_3D;
|
||||||
g.name.strcpy("draw-in-3d");
|
g.name.strcpy("draw-in-3d");
|
||||||
break;
|
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:
|
case GraphicsWindow::MNU_GROUP_EXTRUDE:
|
||||||
g.type = EXTRUDE;
|
g.type = EXTRUDE;
|
||||||
g.opA = SS.GW.activeGroup;
|
g.opA = SS.GW.activeGroup;
|
||||||
|
@ -48,6 +89,13 @@ void Group::MenuGroup(int id) {
|
||||||
SS.group.AddAndAssignId(&g);
|
SS.group.AddAndAssignId(&g);
|
||||||
SS.GenerateAll(SS.GW.solving == GraphicsWindow::SOLVE_ALWAYS);
|
SS.GenerateAll(SS.GW.solving == GraphicsWindow::SOLVE_ALWAYS);
|
||||||
SS.GW.activeGroup = g.h;
|
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();
|
SS.TW.Show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,8 +116,54 @@ void Group::Generate(IdList<Entity,hEntity> *entity,
|
||||||
gn = gn.WithMagnitude(200/SS.GW.scale);
|
gn = gn.WithMagnitude(200/SS.GW.scale);
|
||||||
int i;
|
int i;
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case DRAWING:
|
case DRAWING_3D:
|
||||||
return;
|
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:
|
case EXTRUDE:
|
||||||
AddParam(param, h.param(0), gn.x);
|
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);
|
en.distance = Remap(ep->distance, a);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case Entity::POINT_N_COPY:
|
||||||
case Entity::POINT_N_TRANS:
|
case Entity::POINT_N_TRANS:
|
||||||
case Entity::POINT_N_ROT_TRANS:
|
case Entity::POINT_N_ROT_TRANS:
|
||||||
case Entity::POINT_IN_3D:
|
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();
|
if(a != 0) oops();
|
||||||
SS.entity.Add(&en);
|
SS.entity.Add(&en);
|
||||||
|
|
||||||
|
// Any operation on these lists may break existing pointers!
|
||||||
|
ep = SS.GetEntity(in);
|
||||||
|
|
||||||
hEntity np = en.h;
|
hEntity np = en.h;
|
||||||
memset(&en, 0, sizeof(en));
|
memset(&en, 0, sizeof(en));
|
||||||
en.point[0] = ep->h;
|
en.point[0] = ep->h;
|
||||||
|
@ -252,7 +350,7 @@ void Group::MakePolygons(void) {
|
||||||
(faces.elem[i]).Clear();
|
(faces.elem[i]).Clear();
|
||||||
}
|
}
|
||||||
faces.Clear();
|
faces.Clear();
|
||||||
if(type == DRAWING) {
|
if(type == DRAWING_3D || type == DRAWING_WORKPLANE) {
|
||||||
edges.l.Clear();
|
edges.l.Clear();
|
||||||
int i;
|
int i;
|
||||||
for(i = 0; i < SS.entity.n; i++) {
|
for(i = 0; i < SS.entity.n; i++) {
|
||||||
|
@ -350,7 +448,7 @@ void Group::Draw(void) {
|
||||||
} else {
|
} else {
|
||||||
int i;
|
int i;
|
||||||
glEnable(GL_LIGHTING);
|
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);
|
glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, vec);
|
||||||
for(i = 0; i < faces.n; i++) {
|
for(i = 0; i < faces.n; i++) {
|
||||||
glxFillPolygon(&(faces.elem[i]));
|
glxFillPolygon(&(faces.elem[i]));
|
||||||
|
|
23
sketch.h
23
sketch.h
|
@ -42,6 +42,7 @@ public:
|
||||||
|
|
||||||
inline bool isFromRequest(void);
|
inline bool isFromRequest(void);
|
||||||
inline hRequest request(void);
|
inline hRequest request(void);
|
||||||
|
inline hGroup group(void);
|
||||||
inline hEquation equation(int i);
|
inline hEquation equation(int i);
|
||||||
};
|
};
|
||||||
class hParam {
|
class hParam {
|
||||||
|
@ -76,19 +77,32 @@ public:
|
||||||
int tag;
|
int tag;
|
||||||
hGroup h;
|
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 EXTRUDE = 5010;
|
||||||
static const int ROTATE = 5020;
|
static const int ROTATE = 5020;
|
||||||
static const int TRANSLATE = 5030;
|
static const int TRANSLATE = 5030;
|
||||||
int type;
|
int type;
|
||||||
|
|
||||||
int solveOrder;
|
|
||||||
bool solved;
|
bool solved;
|
||||||
|
|
||||||
hGroup opA;
|
hGroup opA;
|
||||||
hGroup opB;
|
hGroup opB;
|
||||||
bool visible;
|
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;
|
SEdgeList edges;
|
||||||
SList<SPolygon> faces;
|
SList<SPolygon> faces;
|
||||||
struct {
|
struct {
|
||||||
|
@ -166,6 +180,7 @@ public:
|
||||||
static const int POINT_IN_2D = 2001;
|
static const int POINT_IN_2D = 2001;
|
||||||
static const int POINT_N_TRANS = 2010;
|
static const int POINT_N_TRANS = 2010;
|
||||||
static const int POINT_N_ROT_TRANS = 2011;
|
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_3D = 3000;
|
||||||
static const int NORMAL_IN_2D = 3001;
|
static const int NORMAL_IN_2D = 3001;
|
||||||
|
@ -215,6 +230,7 @@ public:
|
||||||
|
|
||||||
bool HasVector(void);
|
bool HasVector(void);
|
||||||
ExprVector VectorGetExprs(void);
|
ExprVector VectorGetExprs(void);
|
||||||
|
Vector VectorGetNum(void);
|
||||||
Vector VectorGetRefPoint(void);
|
Vector VectorGetRefPoint(void);
|
||||||
|
|
||||||
// For distances
|
// For distances
|
||||||
|
@ -308,6 +324,7 @@ public:
|
||||||
static const int PT_IN_PLANE = 40;
|
static const int PT_IN_PLANE = 40;
|
||||||
static const int PT_ON_LINE = 41;
|
static const int PT_ON_LINE = 41;
|
||||||
static const int EQUAL_LENGTH_LINES = 50;
|
static const int EQUAL_LENGTH_LINES = 50;
|
||||||
|
static const int LENGTH_RATIO = 51;
|
||||||
static const int SYMMETRIC = 60;
|
static const int SYMMETRIC = 60;
|
||||||
static const int AT_MIDPOINT = 70;
|
static const int AT_MIDPOINT = 70;
|
||||||
static const int HORIZONTAL = 80;
|
static const int HORIZONTAL = 80;
|
||||||
|
@ -411,6 +428,8 @@ inline bool hEntity::isFromRequest(void)
|
||||||
{ if(v & 0x80000000) return false; else return true; }
|
{ if(v & 0x80000000) return false; else return true; }
|
||||||
inline hRequest hEntity::request(void)
|
inline hRequest hEntity::request(void)
|
||||||
{ hRequest r; r.v = (v >> 16); return r; }
|
{ 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)
|
inline hEquation hEntity::equation(int i)
|
||||||
{ if(i != 0) oops(); hEquation r; r.v = v | 0x40000000; return r; }
|
{ if(i != 0) oops(); hEquation r; r.v = v | 0x40000000; return r; }
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
#define max(x, y) ((x) > (y) ? (x) : (y))
|
#define max(x, y) ((x) > (y) ? (x) : (y))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define SWAP(T, a, b) do { T temp = (a); (a) = (b); (b) = temp; } while(0)
|
||||||
|
|
||||||
#define isforname(c) (isalnum(c) || (c) == '_' || (c) == '-' || (c) == '#')
|
#define isforname(c) (isalnum(c) || (c) == '_' || (c) == '-' || (c) == '#')
|
||||||
|
|
||||||
typedef signed long SDWORD;
|
typedef signed long SDWORD;
|
||||||
|
|
12
system.cpp
12
system.cpp
|
@ -185,7 +185,6 @@ void System::SortBySensitivity(void) {
|
||||||
entryWithOrigPos[j] = j;
|
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++) {
|
for(j = 0; j < mat.n; j++) {
|
||||||
int dest = j; // we are writing to position j
|
int dest = j; // we are writing to position j
|
||||||
// And the source is whichever position ahead of us can be swapped
|
// 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) {
|
bool System::Tol(double v) {
|
||||||
return (fabs(v) < 0.001);
|
return (fabs(v) < 0.01);
|
||||||
}
|
}
|
||||||
|
|
||||||
void System::GaussJordan(void) {
|
void System::GaussJordan(void) {
|
||||||
|
@ -291,7 +290,10 @@ bool System::SolveLinearSystem(void) {
|
||||||
max = fabs(mat.A.num[ip][i]);
|
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
|
// Swap row imax with row i
|
||||||
for(jp = 0; jp < mat.n; jp++) {
|
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
|
// We've put the matrix in upper triangular form, so at this point we
|
||||||
// can solve by back-substitution.
|
// can solve by back-substitution.
|
||||||
for(i = mat.m - 1; i >= 0; i--) {
|
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];
|
temp = mat.B.num[i];
|
||||||
for(j = mat.n - 1; j > i; j--) {
|
for(j = mat.n - 1; j > i; j--) {
|
||||||
|
@ -360,7 +362,7 @@ bool System::NewtonSolve(int tag) {
|
||||||
// Check for convergence
|
// Check for convergence
|
||||||
converged = true;
|
converged = true;
|
||||||
for(i = 0; i < mat.m; i++) {
|
for(i = 0; i < mat.m; i++) {
|
||||||
if(!Tol(mat.B.num[i])) {
|
if(fabs(mat.B.num[i]) > 1e-10) {
|
||||||
converged = false;
|
converged = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
1
ui.h
1
ui.h
|
@ -117,6 +117,7 @@ public:
|
||||||
// Constrain
|
// Constrain
|
||||||
MNU_DISTANCE_DIA,
|
MNU_DISTANCE_DIA,
|
||||||
MNU_EQUAL,
|
MNU_EQUAL,
|
||||||
|
MNU_RATIO,
|
||||||
MNU_ON_ENTITY,
|
MNU_ON_ENTITY,
|
||||||
MNU_SYMMETRIC,
|
MNU_SYMMETRIC,
|
||||||
MNU_AT_MIDPOINT,
|
MNU_AT_MIDPOINT,
|
||||||
|
|
12
util.cpp
12
util.cpp
|
@ -310,6 +310,18 @@ double Vector::DivPivoting(Vector delta) {
|
||||||
} else oops();
|
} 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 Point2d::Plus(Point2d b) {
|
||||||
Point2d r;
|
Point2d r;
|
||||||
r.x = x + b.x;
|
r.x = x + b.x;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user