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)
|
||||
@$(CC) $(DEFINES) $(CFLAGS) -Fe$(OBJDIR)/solvespace.exe $(SSOBJS) $(W32OBJS) $(FREEZE) $(LIBS)
|
||||
editbin /nologo /STACK:8388608 $(OBJDIR)/solvespace.exe
|
||||
@echo solvespace.exe
|
||||
|
||||
$(SSOBJS): $(@B).cpp $(HEADERS)
|
||||
|
@ -673,8 +673,8 @@ void Constraint::Generate(IdList<Equation,hEquation> *l) {
|
||||
Expr *au, *av, *bu, *bv;
|
||||
ea->PointGetExprsInWorkplane(plane->h, &au, &av);
|
||||
eb->PointGetExprsInWorkplane(plane->h, &bu, &bv);
|
||||
AddEq(l, au->Minus(bu), 0);
|
||||
AddEq(l, av->Minus(bv), 1);
|
||||
AddEq(l, au->Minus(bu), 1);
|
||||
AddEq(l, av->Minus(bv), 2);
|
||||
} else {
|
||||
Entity *plane = SS.GetEntity(entityA);
|
||||
Entity *a = SS.GetEntity(ptA);
|
||||
@ -717,10 +717,10 @@ void Constraint::Generate(IdList<Equation,hEquation> *l) {
|
||||
|
||||
if(type == SYMMETRIC_HORIZ) {
|
||||
AddEq(l, av->Minus(bv), 0);
|
||||
AddEq(l, au->Plus(bu), 0);
|
||||
AddEq(l, au->Plus(bu), 1);
|
||||
} else {
|
||||
AddEq(l, au->Minus(bu), 0);
|
||||
AddEq(l, av->Plus(bv), 0);
|
||||
AddEq(l, av->Plus(bv), 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
2
dsc.h
2
dsc.h
@ -53,7 +53,9 @@ public:
|
||||
Vector Cross(Vector b);
|
||||
double Dot(Vector b);
|
||||
Vector Normal(int which);
|
||||
Vector RotatedAbout(Vector orig, Vector axis, double theta);
|
||||
Vector RotatedAbout(Vector axis, double theta);
|
||||
double DistanceToLine(Vector p0, Vector dp);
|
||||
double Magnitude(void);
|
||||
Vector WithMagnitude(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 &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 Workplane\tShift+Ctrl+W", MNU_GROUP_WRKPL, 'W'|S|C, mGrp },
|
||||
{ 1, NULL, 0, NULL },
|
||||
{ 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, 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, "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 },
|
||||
|
||||
{ 0, "&Request", 0, NULL },
|
||||
@ -379,9 +380,14 @@ void GraphicsWindow::MenuRequest(int id) {
|
||||
switch(id) {
|
||||
case MNU_SEL_WORKPLANE: {
|
||||
SS.GW.GroupSelection();
|
||||
Group *g = SS.GetGroup(SS.GW.activeGroup);
|
||||
|
||||
if(SS.GW.gs.n == 1 && SS.GW.gs.workplanes == 1) {
|
||||
SS.GetGroup(SS.GW.activeGroup)->activeWorkplane =
|
||||
SS.GW.gs.entity[0];
|
||||
// A user-selected workplane
|
||||
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()) {
|
||||
|
37
group.cpp
37
group.cpp
@ -81,6 +81,24 @@ void Group::MenuGroup(int id) {
|
||||
g.name.strcpy("extrude");
|
||||
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: {
|
||||
Vector n;
|
||||
if(gs.points == 1 && gs.n == 1 && SS.GW.LockedInWorkplane()) {
|
||||
@ -128,17 +146,20 @@ void Group::MenuGroup(int id) {
|
||||
}
|
||||
SS.UndoRemember();
|
||||
SS.group.AddAndAssignId(&g);
|
||||
if(g.type == IMPORTED) {
|
||||
Group *gg = SS.GetGroup(g.h);
|
||||
|
||||
if(gg->type == IMPORTED) {
|
||||
SS.ReloadAllImported();
|
||||
}
|
||||
gg->clean = false;
|
||||
SS.GW.activeGroup = gg->h;
|
||||
SS.GenerateAll();
|
||||
SS.GW.activeGroup = g.h;
|
||||
if(g.type == DRAWING_WORKPLANE) {
|
||||
SS.GetGroup(g.h)->activeWorkplane = g.h.entity(0);
|
||||
if(gg->type == DRAWING_WORKPLANE) {
|
||||
gg->activeWorkplane = gg->h.entity(0);
|
||||
}
|
||||
SS.GetGroup(g.h)->Activate();
|
||||
gg->Activate();
|
||||
SS.GW.AnimateOntoWorkplane();
|
||||
TextWindow::ScreenSelectGroup(0, g.h.v);
|
||||
TextWindow::ScreenSelectGroup(0, gg->h.v);
|
||||
SS.later.showTW = true;
|
||||
}
|
||||
|
||||
@ -262,6 +283,10 @@ void Group::Generate(IdList<Entity,hEntity> *entity,
|
||||
break;
|
||||
}
|
||||
|
||||
case LATHE: {
|
||||
break;
|
||||
}
|
||||
|
||||
case TRANSLATE: {
|
||||
// The translation vector
|
||||
AddParam(param, h.param(0), gp.x);
|
||||
|
@ -110,6 +110,51 @@ void Group::GenerateMesh(void) {
|
||||
}
|
||||
}
|
||||
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) {
|
||||
// Triangles are just copied over, with the appropriate transformation
|
||||
// applied.
|
||||
@ -175,7 +220,7 @@ void Group::Draw(void) {
|
||||
// to show or hide just this with the "show solids" flag.
|
||||
|
||||
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
|
||||
} else {
|
||||
specColor = -1; // use the model color
|
||||
|
@ -29,6 +29,10 @@ bool STriangle::ContainsPointProjd(Vector n, Vector p) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void STriangle::FlipNormal(void) {
|
||||
SWAP(Vector, a, b);
|
||||
}
|
||||
|
||||
STriangle STriangle::From(STriMeta meta, Vector a, Vector b, Vector c) {
|
||||
STriangle tr = { 0, meta, a, b, c };
|
||||
return tr;
|
||||
|
@ -113,6 +113,7 @@ public:
|
||||
|
||||
static STriangle From(STriMeta meta, Vector a, Vector b, Vector c);
|
||||
Vector Normal(void);
|
||||
void FlipNormal(void);
|
||||
bool ContainsPoint(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_WORKPLANE = 5001;
|
||||
static const int EXTRUDE = 5010;
|
||||
static const int ROTATE = 5020;
|
||||
static const int TRANSLATE = 5030;
|
||||
static const int IMPORTED = 6000;
|
||||
static const int EXTRUDE = 5100;
|
||||
static const int LATHE = 5101;
|
||||
static const int ROTATE = 5200;
|
||||
static const int TRANSLATE = 5201;
|
||||
static const int IMPORTED = 5300;
|
||||
int type;
|
||||
|
||||
hGroup opA;
|
||||
|
@ -640,6 +640,9 @@ void TextWindow::ShowGroupInfo(void) {
|
||||
&TextWindow::ScreenChangeOneOrTwoSides,
|
||||
(!one ? "" : "two sides"), (!one ? "two sides" : ""));
|
||||
}
|
||||
if(g->type == Group::LATHE) {
|
||||
Printf(true, "%FtLATHE");
|
||||
}
|
||||
|
||||
if(g->type == Group::ROTATE || g->type == Group::TRANSLATE) {
|
||||
int times = (int)(g->exprA->Eval());
|
||||
@ -648,7 +651,10 @@ void TextWindow::ShowGroupInfo(void) {
|
||||
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 diff = (g->meshCombine == Group::COMBINE_AS_DIFFERENCE);
|
||||
bool asy = (g->meshCombine == Group::COMBINE_AS_ASSEMBLE);
|
||||
|
1
ui.h
1
ui.h
@ -151,6 +151,7 @@ public:
|
||||
MNU_GROUP_3D,
|
||||
MNU_GROUP_WRKPL,
|
||||
MNU_GROUP_EXTRUDE,
|
||||
MNU_GROUP_LATHE,
|
||||
MNU_GROUP_ROT,
|
||||
MNU_GROUP_TRANS,
|
||||
MNU_GROUP_IMPORT,
|
||||
|
11
util.cpp
11
util.cpp
@ -281,6 +281,12 @@ Vector Vector::Normal(int which) {
|
||||
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) {
|
||||
double c = cos(theta);
|
||||
double s = sin(theta);
|
||||
@ -304,6 +310,11 @@ Vector Vector::RotatedAbout(Vector axis, double theta) {
|
||||
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) {
|
||||
return sqrt(x*x + y*y + z*z);
|
||||
}
|
||||
|
@ -3,8 +3,6 @@
|
||||
STL check for meshes, and T intersection removal
|
||||
STL export
|
||||
better triangle combining (Simplify()) for meshes
|
||||
solids of revolution
|
||||
investigate slowdown with large number of entities
|
||||
DXF export
|
||||
compress file format (binary?)
|
||||
partitioned subsystems in the solver
|
||||
@ -13,4 +11,5 @@ TTF font text
|
||||
display with proper formatting/units
|
||||
more measurements
|
||||
reference dimensions (just to look at, no equations)
|
||||
some kind of rounding
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user