Implement revolve groups.
parent
3d80062b66
commit
5df53fc59e
|
@ -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,
|
||||
|
|
|
@ -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 },
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
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.
|
||||
// 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);
|
||||
|
||||
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);
|
||||
// not sure this is needed
|
||||
if(ps.Equals(pf)) {
|
||||
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,7 +620,7 @@ 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) {
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue