Implement revolve groups.

pull/441/head
phkahler 2019-04-14 16:05:50 -04:00 committed by whitequark
parent 3d80062b66
commit 5df53fc59e
9 changed files with 352 additions and 68 deletions

View File

@ -5,6 +5,7 @@ Changelog
---
New sketch features:
* New group, revolve.
* Extrude, lathe, translate and rotate groups can use the "assembly"
boolean operation, to increase performance.
* The solid model of extrude and lathe groups can be suppressed,

View File

@ -106,6 +106,7 @@ const MenuEntry Menu[] = {
{ 1, NULL, Command::NONE, 0, KN, NULL },
{ 1, N_("E&xtrude"), Command::GROUP_EXTRUDE, S|'x', KN, mGrp },
{ 1, N_("&Lathe"), Command::GROUP_LATHE, S|'l', KN, mGrp },
{ 1, N_("Re&volve"), Command::GROUP_REVOLVE, S|'v', KN, mGrp },
{ 1, NULL, Command::NONE, 0, KN, NULL },
{ 1, N_("Link / Assemble..."), Command::GROUP_LINK, S|'i', KN, mGrp },
{ 1, N_("Link Recent"), Command::GROUP_RECENT, 0, KN, mGrp },

View File

@ -184,6 +184,30 @@ void Group::MenuGroup(Command id, Platform::Path linkFile) {
g.name = C_("group-name", "lathe");
break;
case Command::GROUP_REVOLVE:
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 = SK.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 revolve group. This group can "
"be created with:\n\n"
" * a point and a line segment or normal "
"(revolved about an axis parallel to line / "
"normal, through point)\n"
" * a line segment (revolved about line segment)\n"));
return;
}
g.type = Type::REVOLVE;
g.opA = SS.GW.activeGroup;
g.valA = 2;
g.subtype = Subtype::ONE_SIDED;
g.name = C_("group-name", "revolve");
break;
case Command::GROUP_ROT: {
if(gs.points == 1 && gs.n == 1 && SS.GW.LockedInWorkplane()) {
g.predef.origin = gs.point[0];
@ -344,7 +368,7 @@ std::string Group::DescriptionString() {
void Group::Activate() {
if(type == Type::EXTRUDE || type == Type::LINKED || type == Type::LATHE ||
type == Type::TRANSLATE || type == Type::ROTATE) {
type == Type::REVOLVE || type == Type::TRANSLATE || type == Type::ROTATE) {
SS.GW.showFaces = true;
} else {
SS.GW.showFaces = false;
@ -482,11 +506,61 @@ void Group::Generate(IdList<Entity,hEntity> *entity,
CopyAs::NUMERIC);
MakeLatheCircles(entity, param, he, axis_pos, axis_dir, ai);
MakeLatheSurfacesSelectable(entity, he, axis_dir);
ai++;
}
return;
}
case Type::REVOLVE: {
// this was borrowed from LATHE and ROTATE
Vector axis_pos = SK.GetEntity(predef.origin)->PointGetNum();
Vector axis_dir = SK.GetEntity(predef.entityB)->VectorGetNum();
// The center of rotation
AddParam(param, h.param(0), axis_pos.x);
AddParam(param, h.param(1), axis_pos.y);
AddParam(param, h.param(2), axis_pos.z);
// The rotation quaternion
AddParam(param, h.param(3), 30 * PI / 180);
AddParam(param, h.param(4), axis_dir.x);
AddParam(param, h.param(5), axis_dir.y);
AddParam(param, h.param(6), axis_dir.z);
int n = 2;
int ai = 1;
for(i = 0; i < entity->n; i++) {
Entity *e = &(entity->elem[i]);
if(e->group.v != opA.v)
continue;
e->CalculateNumerical(/*forExport=*/false);
hEntity he = e->h;
CopyEntity(entity, SK.GetEntity(predef.origin), 0, ai, NO_PARAM, NO_PARAM,
NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM, CopyAs::NUMERIC);
for(a = 0; a < 2; a++) {
if(e->group.v != opA.v)
continue;
e->CalculateNumerical(false);
CopyEntity(entity, e, a * 2 - (subtype == Subtype::ONE_SIDED ? 0 : (n - 1)),
(a == (n - 1)) ? REMAP_LATHE_END : REMAP_LATHE_START, h.param(0),
h.param(1), h.param(2), h.param(3), h.param(4), h.param(5),
h.param(6), CopyAs::N_ROT_AA);
}
// Arcs are not generated for revolve groups, for now, because our current arc
// entity is not chiral, and dragging a revolve may break the arc by inverting it.
// MakeLatheCircles(entity, param, he, axis_pos, axis_dir, ai);
MakeLatheSurfacesSelectable(entity, he, axis_dir);
ai++;
}
return;
}
case Type::TRANSLATE: {
// inherit meshCombine from source group
Group *srcg = SK.GetGroup(opA);
@ -596,7 +670,7 @@ void Group::GenerateEquations(IdList<Equation,hEquation> *l) {
Expr::From(h.param(5)),
Expr::From(h.param(6)) };
AddEq(l, (q.Magnitude())->Minus(Expr::From(1)), 0);
} else if(type == Type::ROTATE) {
} else if(type == Type::ROTATE || type == Type::REVOLVE) {
// The axis and center of rotation are specified numerically
#define EC(x) (Expr::From(x))
#define EP(x) (Expr::From(h.param(x)))
@ -729,7 +803,14 @@ void Group::MakeLatheCircles(IdList<Entity,hEntity> *el, IdList<Param,hParam> *p
el->Add(&n);
en.normal = n.h;
el->Add(&en);
} else if(ep->type == Entity::Type::LINE_SEGMENT) {
}
}
void Group::MakeLatheSurfacesSelectable(IdList<Entity, hEntity> *el, hEntity in, Vector axis) {
Entity *ep = SK.GetEntity(in);
Entity en = {};
if(ep->type == Entity::Type::LINE_SEGMENT) {
// An axis-perpendicular line gets revolved to form a face.
Vector a = SK.GetEntity(ep->point[0])->PointGetNum();
Vector b = SK.GetEntity(ep->point[1])->PointGetNum();

View File

@ -191,7 +191,7 @@ void Group::GenerateShellAndMesh() {
// Don't attempt a lathe or extrusion unless the source section is good:
// planar and not self-intersecting.
bool haveSrc = true;
if(type == Type::EXTRUDE || type == Type::LATHE) {
if(type == Type::EXTRUDE || type == Type::LATHE || type == Type::REVOLVE) {
Group *src = SK.GetGroup(opA);
if(src->polyError.how != PolyError::GOOD) {
haveSrc = false;
@ -293,6 +293,27 @@ void Group::GenerateShellAndMesh() {
for(sbls = sblss->l.First(); sbls; sbls = sblss->l.NextAfter(sbls)) {
thisShell.MakeFromRevolutionOf(sbls, pt, axis, color, this);
}
} else if(type == Type::REVOLVE && haveSrc) {
Group *src = SK.GetGroup(opA);
double anglef = SK.GetParam(h.param(3))->val * 4; // why the 4 is needed?
double angles = 0.0;
if(subtype != Subtype::ONE_SIDED) {
anglef *= 0.5;
angles = -anglef;
}
Vector pt = SK.GetEntity(predef.origin)->PointGetNum(),
axis = SK.GetEntity(predef.entityB)->VectorGetNum();
axis = axis.WithMagnitude(1);
SBezierLoopSetSet *sblss = &(src->bezierLoops);
SBezierLoopSet *sbls;
for(sbls = sblss->l.First(); sbls; sbls = sblss->l.NextAfter(sbls)) {
if(fabs(anglef - angles) < 2 * PI) {
thisShell.MakeFromHelicalRevolutionOf(sbls, pt, axis, color, this, angles, anglef);
} else {
thisShell.MakeFromRevolutionOf(sbls, pt, axis, color, this);
}
}
} else if(type == Type::LINKED) {
// The imported shell or mesh are copied over, with the appropriate
// transformation applied. We also must remap the face entities.
@ -466,6 +487,7 @@ bool Group::IsMeshGroup() {
switch(type) {
case Group::Type::EXTRUDE:
case Group::Type::LATHE:
case Group::Type::REVOLVE:
case Group::Type::ROTATE:
case Group::Type::TRANSLATE:
return true;

View File

@ -136,6 +136,7 @@ public:
DRAWING_WORKPLANE = 5001,
EXTRUDE = 5100,
LATHE = 5101,
REVOLVE = 5102,
ROTATE = 5200,
TRANSLATE = 5201,
LINKED = 5300
@ -258,6 +259,7 @@ public:
hEntity Remap(hEntity in, int copyNumber);
void MakeExtrusionLines(EntityList *el, hEntity in);
void MakeLatheCircles(IdList<Entity,hEntity> *el, IdList<Param,hParam> *param, hEntity in, Vector pt, Vector axis, int ai);
void MakeLatheSurfacesSelectable(IdList<Entity, hEntity> *el, hEntity in, Vector axis);
void MakeExtrusionTopBottomFaces(EntityList *el, hEntity pt);
void CopyEntity(EntityList *el,
Entity *ep, int timesApplied, int remap,

View File

@ -63,18 +63,19 @@ bool SSurface::IsCylinder(Vector *axis, Vector *center, double *r,
return true;
}
SSurface SSurface::FromRevolutionOf(SBezier *sb, Vector pt, Vector axis,
double thetas, double thetaf)
{
// Create a surface patch by revolving and possibly translating a curve.
// Works for sections up to but not including 180 degrees.
SSurface SSurface::FromRevolutionOf(SBezier *sb, Vector pt, Vector axis, double thetas,
double thetaf, double dists,
double distf) { // s is start, f is finish
SSurface ret = {};
ret.degm = sb->deg;
ret.degn = 2;
double dtheta = fabs(WRAP_SYMMETRIC(thetaf - thetas, 2*PI));
double w = cos(dtheta / 2);
// We now wish to revolve the curve about the z axis
// Revolve the curve about the z axis
int i;
for(i = 0; i <= ret.degm; i++) {
Vector p = sb->ctrl[i];
@ -82,32 +83,26 @@ SSurface SSurface::FromRevolutionOf(SBezier *sb, Vector pt, Vector axis,
Vector ps = p.RotatedAbout(pt, axis, thetas),
pf = p.RotatedAbout(pt, axis, thetaf);
Vector ct;
// The middle control point should be at the intersection of the tangents at ps and pf.
// This is equivalent but works for 0 <= angle < 180 degrees.
Vector mid = ps.Plus(pf).ScaledBy(0.5);
Vector c = ps.ClosestPointOnLine(pt, axis);
Vector ct = mid.Minus(c).ScaledBy(1 / (w * w)).Plus(c);
// not sure this is needed
if(ps.Equals(pf)) {
// Degenerate case: a control point lies on the axis of revolution,
// so we get three coincident control points.
ct = ps;
} else {
// Normal case, the control point sweeps out a circle.
Vector c = ps.ClosestPointOnLine(pt, axis);
Vector rs = ps.Minus(c),
rf = pf.Minus(c);
Vector ts = axis.Cross(rs),
tf = axis.Cross(rf);
ct = Vector::AtIntersectionOfLines(ps, ps.Plus(ts),
pf, pf.Plus(tf),
NULL, NULL, NULL);
ps = c;
ct = c;
pf = c;
}
ret.ctrl[i][0] = ps;
ret.ctrl[i][1] = ct;
ret.ctrl[i][2] = pf;
// moving along the axis can create hilical surfaces (or straight extrusion if
// thetas==thetaf)
ret.ctrl[i][0] = ps.Plus(axis.ScaledBy(dists));
ret.ctrl[i][1] = ct.Plus(axis.ScaledBy((dists + distf) / 2));
ret.ctrl[i][2] = pf.Plus(axis.ScaledBy(distf));
ret.weight[i][0] = sb->weight[i];
ret.weight[i][1] = sb->weight[i]*cos(dtheta/2);
ret.weight[i][1] = sb->weight[i] * w;
ret.weight[i][2] = sb->weight[i];
}
@ -611,20 +606,11 @@ void SShell::MakeFromExtrusionOf(SBezierLoopSet *sbls, Vector t0, Vector t1, Rgb
}
}
typedef struct {
hSSurface d[4];
} Revolved;
void SShell::MakeFromRevolutionOf(SBezierLoopSet *sbls, Vector pt, Vector axis, RgbaColor color, Group *group)
bool SShell::CheckNormalAxisRelationship(SBezierLoopSet *sbls, Vector pt, Vector axis)
// Check that the direction of revolution ends up parallel to the normal of
// the sketch, on the side of the axis where the sketch is.
{
SBezierLoop *sbl;
int i0 = surface.n, i;
// Normalize the axis direction so that the direction of revolution
// ends up parallel to the normal of the sketch, on the side of the
// axis where the sketch is.
Vector pto;
double md = VERY_NEGATIVE;
for(sbl = sbls->l.First(); sbl; sbl = sbls->l.NextAfter(sbl)) {
@ -634,11 +620,11 @@ void SShell::MakeFromRevolutionOf(SBezierLoopSet *sbls, Vector pt, Vector axis,
// if we choose a point that lies on the axis, for example.
// (And our surface will be self-intersecting if the sketch
// spans the axis, so don't worry about that.)
for(i = 0; i <= sb->deg; i++) {
for(int i = 0; i <= sb->deg; i++) {
Vector p = sb->ctrl[i];
double d = p.DistanceToLine(pt, axis);
if(d > md) {
md = d;
md = d;
pto = p;
}
}
@ -647,7 +633,195 @@ void SShell::MakeFromRevolutionOf(SBezierLoopSet *sbls, Vector pt, Vector axis,
Vector ptc = pto.ClosestPointOnLine(pt, axis),
up = (pto.Minus(ptc)).WithMagnitude(1),
vp = (sbls->normal).Cross(up);
if(vp.Dot(axis) < 0) {
return (vp.Dot(axis) < 0);
}
typedef struct {
hSSurface d[100];
} Revolved;
// sketch must not contain the axis of revolution as a non-construction line for helix
void SShell::MakeFromHelicalRevolutionOf(SBezierLoopSet *sbls, Vector pt, Vector axis,
RgbaColor color, Group *group, double angles,
double anglef) {
int i0 = surface.n; // number of pre-existing surfaces
SBezierLoop *sbl;
// for testing - hard code the axial distance, and number of sections.
// distance will need to be parameters in the future.
double dist = 0;
int sections = fabs(anglef - angles) / (PI / 2) + 1;
if(sections > 99) {
sections = 99;
}
double wedge = (anglef - angles) / sections;
double dists = 0; // start distance
double distf = dist; // finish distance
if(CheckNormalAxisRelationship(sbls, pt, axis) ^ (wedge < 0)) {
swap(angles, anglef);
swap(dists, distf);
dist = -dist;
wedge = -wedge;
}
// Define a coordinate system to contain the original sketch, and get
// a bounding box in that csys
Vector n = sbls->normal.ScaledBy(-1);
Vector u = n.Normal(0), v = n.Normal(1);
Vector orig = sbls->point;
double umax = 1e-10, umin = 1e10;
sbls->GetBoundingProjd(u, orig, &umin, &umax);
double vmax = 1e-10, vmin = 1e10;
sbls->GetBoundingProjd(v, orig, &vmin, &vmax);
// and now fix things up so that all u and v lie between 0 and 1
orig = orig.Plus(u.ScaledBy(umin));
orig = orig.Plus(v.ScaledBy(vmin));
u = u.ScaledBy(umax - umin);
v = v.ScaledBy(vmax - vmin);
// So we can now generate the end caps of the extrusion within
// a translated and rotated (and maybe mirrored) version of that csys.
SSurface s0, s1;
s0 = SSurface::FromPlane(orig.RotatedAbout(pt, axis, angles).Plus(axis.ScaledBy(dists)),
u.RotatedAbout(axis, angles), v.RotatedAbout(axis, angles));
s0.color = color;
s1 = SSurface::FromPlane(
orig.Plus(u).RotatedAbout(pt, axis, anglef).Plus(axis.ScaledBy(distf)),
u.ScaledBy(-1).RotatedAbout(axis, anglef), v.RotatedAbout(axis, anglef));
s1.color = color;
hSSurface hs0 = surface.AddAndAssignId(&s0), hs1 = surface.AddAndAssignId(&s1);
// Now we actually build and trim the swept surfaces. One loop at a time.
for(sbl = sbls->l.First(); sbl; sbl = sbls->l.NextAfter(sbl)) {
int i, j;
SBezier *sb;
List<Revolved> hsl = {};
// This is where all the NURBS are created and Remapped to the generating curve
for(sb = sbl->l.First(); sb; sb = sbl->l.NextAfter(sb)) {
Revolved revs;
for(j = 0; j < sections; j++) {
if((dist == 0) && sb->deg == 1 &&
(sb->ctrl[0]).DistanceToLine(pt, axis) < LENGTH_EPS &&
(sb->ctrl[1]).DistanceToLine(pt, axis) < LENGTH_EPS) {
// This is a line on the axis of revolution; it does
// not contribute a surface.
revs.d[j].v = 0;
} else {
SSurface ss = SSurface::FromRevolutionOf(
sb, pt, axis, angles + (wedge)*j, angles + (wedge) * (j + 1),
dists + j * dist / sections, dists + (j + 1) * dist / sections);
ss.color = color;
if(sb->entity != 0) {
hEntity he;
he.v = sb->entity;
hEntity hface = group->Remap(he, Group::REMAP_LINE_TO_FACE);
if(SK.entity.FindByIdNoOops(hface) != NULL) {
ss.face = hface.v;
}
}
revs.d[j] = surface.AddAndAssignId(&ss);
}
}
hsl.Add(&revs);
}
// Still the same loop. Need to create trim curves
for(i = 0; i < sbl->l.n; i++) {
Revolved revs = hsl.elem[i], revsp = hsl.elem[WRAP(i - 1, sbl->l.n)];
sb = &(sbl->l.elem[i]);
// we generate one more curve than we did surfaces
for(j = 0; j <= sections; j++) {
SCurve sc;
Quaternion qs = Quaternion::From(axis, angles + wedge * j);
// we want Q*(x - p) + p = Q*x + (p - Q*p)
Vector ts =
pt.Minus(qs.Rotate(pt)).Plus(axis.ScaledBy(dists + j * dist / sections));
// If this input curve generated a surface, then trim that
// surface with the rotated version of the input curve.
if(revs.d[0].v) { // not d[j] because crash on j==sections
sc = {};
sc.isExact = true;
sc.exact = sb->TransformedBy(ts, qs, 1.0);
(sc.exact).MakePwlInto(&(sc.pts));
// the surfaces already exist so trim with this curve
if(j < sections) {
sc.surfA = revs.d[j];
} else {
sc.surfA = hs1; // end cap
}
if(j > 0) {
sc.surfB = revs.d[j - 1];
} else {
sc.surfB = hs0; // staring cap
}
hSCurve hcb = curve.AddAndAssignId(&sc);
STrimBy stb;
stb = STrimBy::EntireCurve(this, hcb, /*backwards=*/true);
(surface.FindById(sc.surfA))->trim.Add(&stb);
stb = STrimBy::EntireCurve(this, hcb, /*backwards=*/false);
(surface.FindById(sc.surfB))->trim.Add(&stb);
} else if(j == 0) { // curve was on the rotation axis and is shared by the end caps.
sc = {};
sc.isExact = true;
sc.exact = sb->TransformedBy(ts, qs, 1.0);
(sc.exact).MakePwlInto(&(sc.pts));
sc.surfA = hs1; // end cap
sc.surfB = hs0; // staring cap
hSCurve hcb = curve.AddAndAssignId(&sc);
STrimBy stb;
stb = STrimBy::EntireCurve(this, hcb, /*backwards=*/true);
(surface.FindById(sc.surfA))->trim.Add(&stb);
stb = STrimBy::EntireCurve(this, hcb, /*backwards=*/false);
(surface.FindById(sc.surfB))->trim.Add(&stb);
}
// And if this input curve and the one after it both generated
// surfaces, then trim both of those by the appropriate
// curve based on the control points.
if((j < sections) && revs.d[j].v && revsp.d[j].v) {
SSurface *ss = surface.FindById(revs.d[j]);
sc = {};
sc.isExact = true;
sc.exact = SBezier::From(ss->ctrl[0][0], ss->ctrl[0][1], ss->ctrl[0][2]);
sc.exact.weight[1] = ss->weight[0][1];
(sc.exact).MakePwlInto(&(sc.pts));
sc.surfA = revs.d[j];
sc.surfB = revsp.d[j];
hSCurve hcc = curve.AddAndAssignId(&sc);
STrimBy stb;
stb = STrimBy::EntireCurve(this, hcc, /*backwards=*/false);
(surface.FindById(sc.surfA))->trim.Add(&stb);
stb = STrimBy::EntireCurve(this, hcc, /*backwards=*/true);
(surface.FindById(sc.surfB))->trim.Add(&stb);
}
}
}
hsl.Clear();
}
if(dist == 0) {
MakeFirstOrderRevolvedSurfaces(pt, axis, i0);
}
}
void SShell::MakeFromRevolutionOf(SBezierLoopSet *sbls, Vector pt, Vector axis, RgbaColor color,
Group *group) {
int i0 = surface.n; // number of pre-existing surfaces
SBezierLoop *sbl;
if(CheckNormalAxisRelationship(sbls, pt, axis)) {
axis = axis.ScaledBy(-1);
}
@ -668,9 +842,8 @@ void SShell::MakeFromRevolutionOf(SBezierLoopSet *sbls, Vector pt, Vector axis,
// not contribute a surface.
revs.d[j].v = 0;
} else {
SSurface ss = SSurface::FromRevolutionOf(sb, pt, axis,
(PI/2)*j,
(PI/2)*(j+1));
SSurface ss = SSurface::FromRevolutionOf(sb, pt, axis, (PI / 2) * j,
(PI / 2) * (j + 1), 0.0, 0.0);
ss.color = color;
if(sb->entity != 0) {
hEntity he;
@ -747,6 +920,12 @@ void SShell::MakeFromRevolutionOf(SBezierLoopSet *sbls, Vector pt, Vector axis,
hsl.Clear();
}
MakeFirstOrderRevolvedSurfaces(pt, axis, i0);
}
void SShell::MakeFirstOrderRevolvedSurfaces(Vector pt, Vector axis, int i0) {
int i;
for(i = i0; i < surface.n; i++) {
SSurface *srf = &(surface.elem[i]);
@ -823,9 +1002,7 @@ void SShell::MakeFromRevolutionOf(SBezierLoopSet *sbls, Vector pt, Vector axis,
continue;
}
}
}
}
void SShell::MakeFromCopyOf(SShell *a) {
@ -896,4 +1073,3 @@ void SShell::Clear() {
}
curve.Clear();
}

View File

@ -282,8 +282,8 @@ public:
Point2d cached;
static SSurface FromExtrusionOf(SBezier *spc, Vector t0, Vector t1);
static SSurface FromRevolutionOf(SBezier *sb, Vector pt, Vector axis,
double thetas, double thetaf);
static SSurface FromRevolutionOf(SBezier *sb, Vector pt, Vector axis, double thetas,
double thetaf, double dists, double distf);
static SSurface FromPlane(Vector pt, Vector u, Vector v);
static SSurface FromTransformationOf(SSurface *a, Vector t, Quaternion q,
double scale,
@ -376,9 +376,12 @@ public:
void MakeFromExtrusionOf(SBezierLoopSet *sbls, Vector t0, Vector t1,
RgbaColor color);
bool CheckNormalAxisRelationship(SBezierLoopSet *sbls, Vector pt, Vector axis);
void MakeFromRevolutionOf(SBezierLoopSet *sbls, Vector pt, Vector axis,
RgbaColor color, Group *group);
void MakeFromHelicalRevolutionOf(SBezierLoopSet *sbls, Vector pt, Vector axis, RgbaColor color,
Group *group, double angles, double anglef);
void MakeFirstOrderRevolvedSurfaces(Vector pt, Vector axis, int i0);
void MakeFromUnionOf(SShell *a, SShell *b);
void MakeFromDifferenceOf(SShell *a, SShell *b);
void MakeFromBoolean(SShell *a, SShell *b, SSurface::CombineAs type);

View File

@ -304,14 +304,15 @@ void TextWindow::ShowGroupInfo() {
if(g->type == Group::Type::LATHE) {
Printf(true, " %Ftlathe plane sketch");
} else if(g->type == Group::Type::EXTRUDE || g->type == Group::Type::ROTATE ||
g->type == Group::Type::TRANSLATE)
{
g->type == Group::Type::TRANSLATE || g->type == Group::Type::REVOLVE) {
if(g->type == Group::Type::EXTRUDE) {
s = "extrude plane sketch";
} else if(g->type == Group::Type::TRANSLATE) {
s = "translate original sketch";
} else if(g->type == Group::Type::ROTATE) {
s = "rotate original sketch";
} else if(g->type == Group::Type::REVOLVE) {
s = "revolve original sketch";
}
Printf(true, " %Ft%s%E", s);
@ -362,10 +363,8 @@ void TextWindow::ShowGroupInfo() {
}
Printf(false, "");
if(g->type == Group::Type::EXTRUDE ||
g->type == Group::Type::LATHE ||
g->type == Group::Type::LINKED)
{
if(g->type == Group::Type::EXTRUDE || g->type == Group::Type::LATHE ||
g->type == Group::Type::REVOLVE || g->type == Group::Type::LINKED) {
bool un = (g->meshCombine == Group::CombineAs::UNION);
bool diff = (g->meshCombine == Group::CombineAs::DIFFERENCE);
bool asy = (g->meshCombine == Group::CombineAs::ASSEMBLE);
@ -384,9 +383,8 @@ void TextWindow::ShowGroupInfo() {
Group::CombineAs::ASSEMBLE,
(asy ? RADIO_TRUE : RADIO_FALSE));
if(g->type == Group::Type::EXTRUDE ||
g->type == Group::Type::LATHE)
{
if(g->type == Group::Type::EXTRUDE || g->type == Group::Type::LATHE ||
g->type == Group::Type::REVOLVE) {
Printf(false,
"%Bd %Ftcolor %E%Bz %Bd (%@, %@, %@) %f%D%Lf%Fl[change]%E",
&g->color,
@ -397,9 +395,8 @@ void TextWindow::ShowGroupInfo() {
&TextWindow::ScreenOpacity);
}
if(g->type == Group::Type::EXTRUDE ||
g->type == Group::Type::LATHE ||
g->type == Group::Type::LINKED) {
if(g->type == Group::Type::EXTRUDE || g->type == Group::Type::LATHE ||
g->type == Group::Type::REVOLVE || g->type == Group::Type::LINKED) {
Printf(false, " %Fd%f%LP%s suppress this group's solid model",
&TextWindow::ScreenChangeGroupOption,
g->suppress ? CHECK_TRUE : CHECK_FALSE);

View File

@ -126,6 +126,7 @@ enum class Command : uint32_t {
GROUP_WRKPL,
GROUP_EXTRUDE,
GROUP_LATHE,
GROUP_REVOLVE,
GROUP_ROT,
GROUP_TRANS,
GROUP_LINK,