Add preliminary lathe (solid of revolution) support. I'm generating
just the mesh, no derived entities (but I suppose that I could turn all points into circles). And fix some bugs where equations didn't get unique IDs, and make it possible to lock on to the group's workplane automatically, if you press W while free in 3d with no workplane selected. [git-p4: depot-paths = "//depot/solvespace/": change = 1780]
This commit is contained in:
parent
dc15d667e3
commit
8498a99588
1
Makefile
1
Makefile
|
@ -41,6 +41,7 @@ clean:
|
||||||
|
|
||||||
$(OBJDIR)/solvespace.exe: $(SSOBJS) $(W32OBJS) $(FREEZE)
|
$(OBJDIR)/solvespace.exe: $(SSOBJS) $(W32OBJS) $(FREEZE)
|
||||||
@$(CC) $(DEFINES) $(CFLAGS) -Fe$(OBJDIR)/solvespace.exe $(SSOBJS) $(W32OBJS) $(FREEZE) $(LIBS)
|
@$(CC) $(DEFINES) $(CFLAGS) -Fe$(OBJDIR)/solvespace.exe $(SSOBJS) $(W32OBJS) $(FREEZE) $(LIBS)
|
||||||
|
editbin /nologo /STACK:8388608 $(OBJDIR)/solvespace.exe
|
||||||
@echo solvespace.exe
|
@echo solvespace.exe
|
||||||
|
|
||||||
$(SSOBJS): $(@B).cpp $(HEADERS)
|
$(SSOBJS): $(@B).cpp $(HEADERS)
|
||||||
|
|
|
@ -673,8 +673,8 @@ void Constraint::Generate(IdList<Equation,hEquation> *l) {
|
||||||
Expr *au, *av, *bu, *bv;
|
Expr *au, *av, *bu, *bv;
|
||||||
ea->PointGetExprsInWorkplane(plane->h, &au, &av);
|
ea->PointGetExprsInWorkplane(plane->h, &au, &av);
|
||||||
eb->PointGetExprsInWorkplane(plane->h, &bu, &bv);
|
eb->PointGetExprsInWorkplane(plane->h, &bu, &bv);
|
||||||
AddEq(l, au->Minus(bu), 0);
|
AddEq(l, au->Minus(bu), 1);
|
||||||
AddEq(l, av->Minus(bv), 1);
|
AddEq(l, av->Minus(bv), 2);
|
||||||
} else {
|
} else {
|
||||||
Entity *plane = SS.GetEntity(entityA);
|
Entity *plane = SS.GetEntity(entityA);
|
||||||
Entity *a = SS.GetEntity(ptA);
|
Entity *a = SS.GetEntity(ptA);
|
||||||
|
@ -717,10 +717,10 @@ void Constraint::Generate(IdList<Equation,hEquation> *l) {
|
||||||
|
|
||||||
if(type == SYMMETRIC_HORIZ) {
|
if(type == SYMMETRIC_HORIZ) {
|
||||||
AddEq(l, av->Minus(bv), 0);
|
AddEq(l, av->Minus(bv), 0);
|
||||||
AddEq(l, au->Plus(bu), 0);
|
AddEq(l, au->Plus(bu), 1);
|
||||||
} else {
|
} else {
|
||||||
AddEq(l, au->Minus(bu), 0);
|
AddEq(l, au->Minus(bu), 0);
|
||||||
AddEq(l, av->Plus(bv), 0);
|
AddEq(l, av->Plus(bv), 1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
2
dsc.h
2
dsc.h
|
@ -53,7 +53,9 @@ public:
|
||||||
Vector Cross(Vector b);
|
Vector Cross(Vector b);
|
||||||
double Dot(Vector b);
|
double Dot(Vector b);
|
||||||
Vector Normal(int which);
|
Vector Normal(int which);
|
||||||
|
Vector RotatedAbout(Vector orig, Vector axis, double theta);
|
||||||
Vector RotatedAbout(Vector axis, double theta);
|
Vector RotatedAbout(Vector axis, double theta);
|
||||||
|
double DistanceToLine(Vector p0, Vector dp);
|
||||||
double Magnitude(void);
|
double Magnitude(void);
|
||||||
Vector WithMagnitude(double s);
|
Vector WithMagnitude(double s);
|
||||||
Vector ScaledBy(double s);
|
Vector ScaledBy(double s);
|
||||||
|
|
|
@ -38,16 +38,17 @@ const GraphicsWindow::MenuEntry GraphicsWindow::menu[] = {
|
||||||
{ 1, "Dimensions in &Inches", MNU_UNITS_INCHES, 0, mView },
|
{ 1, "Dimensions in &Inches", MNU_UNITS_INCHES, 0, mView },
|
||||||
{ 1, "Dimensions in &Millimeters", MNU_UNITS_MM, 0, mView },
|
{ 1, "Dimensions in &Millimeters", MNU_UNITS_MM, 0, mView },
|
||||||
|
|
||||||
{ 0, "&New Feature", 0, 0, NULL },
|
{ 0, "&New Group", 0, 0, NULL },
|
||||||
{ 1, "&Drawing in 3d\tShift+Ctrl+D", MNU_GROUP_3D, 'D'|S|C, mGrp },
|
{ 1, "&Drawing in 3d\tShift+Ctrl+D", MNU_GROUP_3D, 'D'|S|C, mGrp },
|
||||||
{ 1, "Drawing in Workplane\tShift+Ctrl+W", MNU_GROUP_WRKPL, 'W'|S|C, mGrp },
|
{ 1, "Drawing in Workplane\tShift+Ctrl+W", MNU_GROUP_WRKPL, 'W'|S|C, mGrp },
|
||||||
{ 1, NULL, 0, NULL },
|
{ 1, NULL, 0, NULL },
|
||||||
{ 1, "Step &Translating\tShift+Ctrl+R", MNU_GROUP_TRANS, 'T'|S|C,mGrp },
|
{ 1, "Step &Translating\tShift+Ctrl+R", MNU_GROUP_TRANS, 'T'|S|C,mGrp },
|
||||||
{ 1, "Step &Rotating\tShift+Ctrl+T", MNU_GROUP_ROT, 'R'|S|C,mGrp },
|
{ 1, "Step &Rotating\tShift+Ctrl+T", MNU_GROUP_ROT, 'R'|S|C,mGrp },
|
||||||
{ 1, NULL, 0, 0, NULL },
|
{ 1, NULL, 0, 0, NULL },
|
||||||
{ 1, "Extrusion\tShift+Ctrl+X", MNU_GROUP_EXTRUDE, 'X'|S|C,mGrp },
|
{ 1, "Extrude\tShift+Ctrl+X", MNU_GROUP_EXTRUDE, 'X'|S|C,mGrp },
|
||||||
|
{ 1, "Lathe\tShift+Ctrl+L", MNU_GROUP_LATHE, 'L'|S|C,mGrp },
|
||||||
{ 1, NULL, 0, 0, NULL },
|
{ 1, NULL, 0, 0, NULL },
|
||||||
{ 1, "Import...\tShift+Ctrl+I", MNU_GROUP_IMPORT, 'I'|S|C,mGrp },
|
{ 1, "Import / Assemble...\tShift+Ctrl+I", MNU_GROUP_IMPORT, 'I'|S|C,mGrp },
|
||||||
{11, "Import Recent", MNU_GROUP_RECENT, 0, mGrp },
|
{11, "Import Recent", MNU_GROUP_RECENT, 0, mGrp },
|
||||||
|
|
||||||
{ 0, "&Request", 0, NULL },
|
{ 0, "&Request", 0, NULL },
|
||||||
|
@ -379,9 +380,14 @@ void GraphicsWindow::MenuRequest(int id) {
|
||||||
switch(id) {
|
switch(id) {
|
||||||
case MNU_SEL_WORKPLANE: {
|
case MNU_SEL_WORKPLANE: {
|
||||||
SS.GW.GroupSelection();
|
SS.GW.GroupSelection();
|
||||||
|
Group *g = SS.GetGroup(SS.GW.activeGroup);
|
||||||
|
|
||||||
if(SS.GW.gs.n == 1 && SS.GW.gs.workplanes == 1) {
|
if(SS.GW.gs.n == 1 && SS.GW.gs.workplanes == 1) {
|
||||||
SS.GetGroup(SS.GW.activeGroup)->activeWorkplane =
|
// A user-selected workplane
|
||||||
SS.GW.gs.entity[0];
|
g->activeWorkplane = SS.GW.gs.entity[0];
|
||||||
|
} else if(g->type == Group::DRAWING_WORKPLANE) {
|
||||||
|
// The group's default workplane
|
||||||
|
g->activeWorkplane = g->h.entity(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!SS.GW.LockedInWorkplane()) {
|
if(!SS.GW.LockedInWorkplane()) {
|
||||||
|
|
37
group.cpp
37
group.cpp
|
@ -81,6 +81,24 @@ void Group::MenuGroup(int id) {
|
||||||
g.name.strcpy("extrude");
|
g.name.strcpy("extrude");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case GraphicsWindow::MNU_GROUP_LATHE:
|
||||||
|
if(gs.points == 1 && gs.vectors == 1 && gs.n == 2) {
|
||||||
|
g.predef.origin = gs.point[0];
|
||||||
|
g.predef.entityB = gs.vector[0];
|
||||||
|
} else if(gs.lineSegments == 1 && gs.n == 1) {
|
||||||
|
g.predef.origin = SS.GetEntity(gs.entity[0])->point[0];
|
||||||
|
g.predef.entityB = gs.entity[0];
|
||||||
|
// since a line segment is a vector
|
||||||
|
} else {
|
||||||
|
Error("Bad selection for new lathe group.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
g.type = LATHE;
|
||||||
|
g.opA = SS.GW.activeGroup;
|
||||||
|
g.color = RGB(100, 100, 100);
|
||||||
|
g.name.strcpy("lathe");
|
||||||
|
break;
|
||||||
|
|
||||||
case GraphicsWindow::MNU_GROUP_ROT: {
|
case GraphicsWindow::MNU_GROUP_ROT: {
|
||||||
Vector n;
|
Vector n;
|
||||||
if(gs.points == 1 && gs.n == 1 && SS.GW.LockedInWorkplane()) {
|
if(gs.points == 1 && gs.n == 1 && SS.GW.LockedInWorkplane()) {
|
||||||
|
@ -128,17 +146,20 @@ void Group::MenuGroup(int id) {
|
||||||
}
|
}
|
||||||
SS.UndoRemember();
|
SS.UndoRemember();
|
||||||
SS.group.AddAndAssignId(&g);
|
SS.group.AddAndAssignId(&g);
|
||||||
if(g.type == IMPORTED) {
|
Group *gg = SS.GetGroup(g.h);
|
||||||
|
|
||||||
|
if(gg->type == IMPORTED) {
|
||||||
SS.ReloadAllImported();
|
SS.ReloadAllImported();
|
||||||
}
|
}
|
||||||
|
gg->clean = false;
|
||||||
|
SS.GW.activeGroup = gg->h;
|
||||||
SS.GenerateAll();
|
SS.GenerateAll();
|
||||||
SS.GW.activeGroup = g.h;
|
if(gg->type == DRAWING_WORKPLANE) {
|
||||||
if(g.type == DRAWING_WORKPLANE) {
|
gg->activeWorkplane = gg->h.entity(0);
|
||||||
SS.GetGroup(g.h)->activeWorkplane = g.h.entity(0);
|
|
||||||
}
|
}
|
||||||
SS.GetGroup(g.h)->Activate();
|
gg->Activate();
|
||||||
SS.GW.AnimateOntoWorkplane();
|
SS.GW.AnimateOntoWorkplane();
|
||||||
TextWindow::ScreenSelectGroup(0, g.h.v);
|
TextWindow::ScreenSelectGroup(0, gg->h.v);
|
||||||
SS.later.showTW = true;
|
SS.later.showTW = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,6 +283,10 @@ void Group::Generate(IdList<Entity,hEntity> *entity,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case LATHE: {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case TRANSLATE: {
|
case TRANSLATE: {
|
||||||
// The translation vector
|
// The translation vector
|
||||||
AddParam(param, h.param(0), gp.x);
|
AddParam(param, h.param(0), gp.x);
|
||||||
|
|
|
@ -110,6 +110,51 @@ void Group::GenerateMesh(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
edges.Clear();
|
edges.Clear();
|
||||||
|
} else if(type == LATHE) {
|
||||||
|
SEdgeList edges;
|
||||||
|
ZERO(&edges);
|
||||||
|
int a, i;
|
||||||
|
|
||||||
|
Group *src = SS.GetGroup(opA);
|
||||||
|
(src->poly).MakeEdgesInto(&edges);
|
||||||
|
|
||||||
|
STriMeta meta = { 0, color };
|
||||||
|
Vector orig = SS.GetEntity(predef.origin)->PointGetNum();
|
||||||
|
Vector axis = SS.GetEntity(predef.entityB)->VectorGetNum();
|
||||||
|
axis = axis.WithMagnitude(1);
|
||||||
|
|
||||||
|
int n = 20;
|
||||||
|
for(a = 0; a <= n; a++) {
|
||||||
|
double thetai = (2*PI*WRAP(a-1, n))/n, thetaf = (2*PI*a)/n;
|
||||||
|
for(i = 0; i < edges.l.n; i++) {
|
||||||
|
SEdge *edge = &(edges.l.elem[i]);
|
||||||
|
|
||||||
|
double da = (edge->a).DistanceToLine(orig, axis);
|
||||||
|
double db = (edge->b).DistanceToLine(orig, axis);
|
||||||
|
|
||||||
|
Vector ai = (edge->a).RotatedAbout(orig, axis, thetai);
|
||||||
|
Vector bi = (edge->b).RotatedAbout(orig, axis, thetai);
|
||||||
|
Vector af = (edge->a).RotatedAbout(orig, axis, thetaf);
|
||||||
|
Vector bf = (edge->b).RotatedAbout(orig, axis, thetaf);
|
||||||
|
|
||||||
|
Vector ab = (edge->b).Minus(edge->a);
|
||||||
|
Vector out = ((src->poly).normal).Cross(ab);
|
||||||
|
out = out.RotatedAbout(axis, thetai);
|
||||||
|
|
||||||
|
STriangle quad1 = STriangle::From(meta, ai, bi, af),
|
||||||
|
quad2 = STriangle::From(meta, af, bi, bf);
|
||||||
|
Vector n1 = quad1.Normal(), n2 = quad2.Normal();
|
||||||
|
Vector n = (n1.Magnitude() > n2.Magnitude()) ? n1 : n2;
|
||||||
|
if(n.Dot(out) < 0) {
|
||||||
|
quad1.FlipNormal();
|
||||||
|
quad2.FlipNormal();
|
||||||
|
}
|
||||||
|
// If one of the endpoints lies on the axis of rotation,
|
||||||
|
// then the quad is just a single triangle
|
||||||
|
if(da >= LENGTH_EPS) outm.AddTriangle(&quad1);
|
||||||
|
if(db >= LENGTH_EPS) outm.AddTriangle(&quad2);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if(type == IMPORTED) {
|
} else if(type == IMPORTED) {
|
||||||
// Triangles are just copied over, with the appropriate transformation
|
// Triangles are just copied over, with the appropriate transformation
|
||||||
// applied.
|
// applied.
|
||||||
|
@ -175,7 +220,7 @@ void Group::Draw(void) {
|
||||||
// to show or hide just this with the "show solids" flag.
|
// to show or hide just this with the "show solids" flag.
|
||||||
|
|
||||||
int specColor;
|
int specColor;
|
||||||
if(type != EXTRUDE && type != IMPORTED) {
|
if(type != EXTRUDE && type != IMPORTED && type != LATHE) {
|
||||||
specColor = RGB(25, 25, 25); // force the color to something dim
|
specColor = RGB(25, 25, 25); // force the color to something dim
|
||||||
} else {
|
} else {
|
||||||
specColor = -1; // use the model color
|
specColor = -1; // use the model color
|
||||||
|
|
|
@ -29,6 +29,10 @@ bool STriangle::ContainsPointProjd(Vector n, Vector p) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void STriangle::FlipNormal(void) {
|
||||||
|
SWAP(Vector, a, b);
|
||||||
|
}
|
||||||
|
|
||||||
STriangle STriangle::From(STriMeta meta, Vector a, Vector b, Vector c) {
|
STriangle STriangle::From(STriMeta meta, Vector a, Vector b, Vector c) {
|
||||||
STriangle tr = { 0, meta, a, b, c };
|
STriangle tr = { 0, meta, a, b, c };
|
||||||
return tr;
|
return tr;
|
||||||
|
|
|
@ -113,6 +113,7 @@ public:
|
||||||
|
|
||||||
static STriangle From(STriMeta meta, Vector a, Vector b, Vector c);
|
static STriangle From(STriMeta meta, Vector a, Vector b, Vector c);
|
||||||
Vector Normal(void);
|
Vector Normal(void);
|
||||||
|
void FlipNormal(void);
|
||||||
bool ContainsPoint(Vector p);
|
bool ContainsPoint(Vector p);
|
||||||
bool ContainsPointProjd(Vector n, Vector p);
|
bool ContainsPointProjd(Vector n, Vector p);
|
||||||
};
|
};
|
||||||
|
|
9
sketch.h
9
sketch.h
|
@ -80,10 +80,11 @@ public:
|
||||||
|
|
||||||
static const int DRAWING_3D = 5000;
|
static const int DRAWING_3D = 5000;
|
||||||
static const int DRAWING_WORKPLANE = 5001;
|
static const int DRAWING_WORKPLANE = 5001;
|
||||||
static const int EXTRUDE = 5010;
|
static const int EXTRUDE = 5100;
|
||||||
static const int ROTATE = 5020;
|
static const int LATHE = 5101;
|
||||||
static const int TRANSLATE = 5030;
|
static const int ROTATE = 5200;
|
||||||
static const int IMPORTED = 6000;
|
static const int TRANSLATE = 5201;
|
||||||
|
static const int IMPORTED = 5300;
|
||||||
int type;
|
int type;
|
||||||
|
|
||||||
hGroup opA;
|
hGroup opA;
|
||||||
|
|
|
@ -640,6 +640,9 @@ void TextWindow::ShowGroupInfo(void) {
|
||||||
&TextWindow::ScreenChangeOneOrTwoSides,
|
&TextWindow::ScreenChangeOneOrTwoSides,
|
||||||
(!one ? "" : "two sides"), (!one ? "two sides" : ""));
|
(!one ? "" : "two sides"), (!one ? "two sides" : ""));
|
||||||
}
|
}
|
||||||
|
if(g->type == Group::LATHE) {
|
||||||
|
Printf(true, "%FtLATHE");
|
||||||
|
}
|
||||||
|
|
||||||
if(g->type == Group::ROTATE || g->type == Group::TRANSLATE) {
|
if(g->type == Group::ROTATE || g->type == Group::TRANSLATE) {
|
||||||
int times = (int)(g->exprA->Eval());
|
int times = (int)(g->exprA->Eval());
|
||||||
|
@ -648,7 +651,10 @@ void TextWindow::ShowGroupInfo(void) {
|
||||||
g->h.v, &TextWindow::ScreenChangeExprA);
|
g->h.v, &TextWindow::ScreenChangeExprA);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(g->type == Group::EXTRUDE || g->type == Group::IMPORTED) {
|
if(g->type == Group::EXTRUDE ||
|
||||||
|
g->type == Group::LATHE ||
|
||||||
|
g->type == Group::IMPORTED)
|
||||||
|
{
|
||||||
bool un = (g->meshCombine == Group::COMBINE_AS_UNION);
|
bool un = (g->meshCombine == Group::COMBINE_AS_UNION);
|
||||||
bool diff = (g->meshCombine == Group::COMBINE_AS_DIFFERENCE);
|
bool diff = (g->meshCombine == Group::COMBINE_AS_DIFFERENCE);
|
||||||
bool asy = (g->meshCombine == Group::COMBINE_AS_ASSEMBLE);
|
bool asy = (g->meshCombine == Group::COMBINE_AS_ASSEMBLE);
|
||||||
|
|
1
ui.h
1
ui.h
|
@ -151,6 +151,7 @@ public:
|
||||||
MNU_GROUP_3D,
|
MNU_GROUP_3D,
|
||||||
MNU_GROUP_WRKPL,
|
MNU_GROUP_WRKPL,
|
||||||
MNU_GROUP_EXTRUDE,
|
MNU_GROUP_EXTRUDE,
|
||||||
|
MNU_GROUP_LATHE,
|
||||||
MNU_GROUP_ROT,
|
MNU_GROUP_ROT,
|
||||||
MNU_GROUP_TRANS,
|
MNU_GROUP_TRANS,
|
||||||
MNU_GROUP_IMPORT,
|
MNU_GROUP_IMPORT,
|
||||||
|
|
11
util.cpp
11
util.cpp
|
@ -281,6 +281,12 @@ Vector Vector::Normal(int which) {
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vector Vector::RotatedAbout(Vector orig, Vector axis, double theta) {
|
||||||
|
Vector r = this->Minus(orig);
|
||||||
|
r = r.RotatedAbout(axis, theta);
|
||||||
|
return r.Plus(orig);
|
||||||
|
}
|
||||||
|
|
||||||
Vector Vector::RotatedAbout(Vector axis, double theta) {
|
Vector Vector::RotatedAbout(Vector axis, double theta) {
|
||||||
double c = cos(theta);
|
double c = cos(theta);
|
||||||
double s = sin(theta);
|
double s = sin(theta);
|
||||||
|
@ -304,6 +310,11 @@ Vector Vector::RotatedAbout(Vector axis, double theta) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double Vector::DistanceToLine(Vector p0, Vector dp) {
|
||||||
|
double m = dp.Magnitude();
|
||||||
|
return ((this->Minus(p0)).Cross(dp)).Magnitude() / m;
|
||||||
|
}
|
||||||
|
|
||||||
double Vector::Magnitude(void) {
|
double Vector::Magnitude(void) {
|
||||||
return sqrt(x*x + y*y + z*z);
|
return sqrt(x*x + y*y + z*z);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,6 @@
|
||||||
STL check for meshes, and T intersection removal
|
STL check for meshes, and T intersection removal
|
||||||
STL export
|
STL export
|
||||||
better triangle combining (Simplify()) for meshes
|
better triangle combining (Simplify()) for meshes
|
||||||
solids of revolution
|
|
||||||
investigate slowdown with large number of entities
|
|
||||||
DXF export
|
DXF export
|
||||||
compress file format (binary?)
|
compress file format (binary?)
|
||||||
partitioned subsystems in the solver
|
partitioned subsystems in the solver
|
||||||
|
@ -13,4 +11,5 @@ TTF font text
|
||||||
display with proper formatting/units
|
display with proper formatting/units
|
||||||
more measurements
|
more measurements
|
||||||
reference dimensions (just to look at, no equations)
|
reference dimensions (just to look at, no equations)
|
||||||
|
some kind of rounding
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user