From 3581d9b9ec1d71b9749d9a5e44da68f741c94ae5 Mon Sep 17 00:00:00 2001 From: Jonathan Westhues Date: Tue, 28 Apr 2009 18:42:44 -0800 Subject: [PATCH] Construct surfaces of revolution from lathe groups, although we're not triangulating them correctly yet. [git-p4: depot-paths = "//depot/solvespace/": change = 1950] --- dsc.h | 1 + groupmesh.cpp | 5 +- srf/surface.cpp | 136 ++++++++++++++++++++++++++++++++++++++++++++++++ srf/surface.h | 4 ++ util.cpp | 11 ++++ 5 files changed, 155 insertions(+), 2 deletions(-) diff --git a/dsc.h b/dsc.h index 425d678..1ba704d 100644 --- a/dsc.h +++ b/dsc.h @@ -21,6 +21,7 @@ public: static Quaternion From(double w, double vx, double vy, double vz); static Quaternion From(hParam w, hParam vx, hParam vy, hParam vz); static Quaternion From(Vector u, Vector v); + static Quaternion From(Vector axis, double dtheta); Quaternion Plus(Quaternion b); Quaternion Minus(Quaternion b); diff --git a/groupmesh.cpp b/groupmesh.cpp index 232fa80..c0140a1 100644 --- a/groupmesh.cpp +++ b/groupmesh.cpp @@ -185,10 +185,11 @@ void Group::GenerateShellAndMesh(void) { } else if(type == LATHE) { Group *src = SK.GetGroup(opA); - Vector orig = SK.GetEntity(predef.origin)->PointGetNum(); - Vector axis = SK.GetEntity(predef.entityB)->VectorGetNum(); + Vector pt = SK.GetEntity(predef.origin)->PointGetNum(), + axis = SK.GetEntity(predef.entityB)->VectorGetNum(); axis = axis.WithMagnitude(1); + thisShell.MakeFromRevolutionOf(&(src->bezierLoopSet), pt, axis, color); } else if(type == IMPORTED) { // Triangles are just copied over, with the appropriate transformation // applied. diff --git a/srf/surface.cpp b/srf/surface.cpp index ca50834..eff0b6f 100644 --- a/srf/surface.cpp +++ b/srf/surface.cpp @@ -62,6 +62,48 @@ bool SSurface::IsCylinder(Vector *axis, Vector *center, double *r, return true; } +SSurface SSurface::FromRevolutionOf(SBezier *sb, Vector pt, Vector axis, + double thetas, double thetaf) +{ + SSurface ret; + ZERO(&ret); + ret.degm = sb->deg; + ret.degn = 2; + + double dtheta = fabs(WRAP_SYMMETRIC(thetaf - thetas, 2*PI)); + + // We now wish to revolve the curve about the z axis + int i; + for(i = 0; i <= ret.degm; i++) { + Vector p = sb->ctrl[i]; + + Vector ps = p.RotatedAbout(pt, axis, thetas), + pf = p.RotatedAbout(pt, axis, thetaf); + + Vector c = ps.ClosestPointOnLine(pt, axis); + + Vector rs = ps.Minus(c), + rf = pf.Minus(c); + + Vector ts = axis.Cross(rs), + tf = axis.Cross(rf); + + Vector ct = Vector::AtIntersectionOfLines(ps, ps.Plus(ts), + pf, pf.Plus(tf), + NULL, NULL, NULL); + + ret.ctrl[i][0] = ps; + ret.ctrl[i][1] = ct; + ret.ctrl[i][2] = pf; + + ret.weight[i][0] = sb->weight[i]; + ret.weight[i][1] = sb->weight[i]*cos(dtheta/2); + ret.weight[i][2] = sb->weight[i]; + } + + return ret; +} + SSurface SSurface::FromPlane(Vector pt, Vector u, Vector v) { SSurface ret; ZERO(&ret); @@ -430,6 +472,100 @@ void SShell::MakeFromExtrusionOf(SBezierLoopSet *sbls, Vector t0, Vector t1, } } + +void SShell::MakeFromRevolutionOf(SBezierLoopSet *sbls, Vector pt, Vector axis, + int color) +{ + ZERO(this); + + // 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 = sbls->point, + ptc = pto.ClosestPointOnLine(pt, axis), + up = (pto.Minus(ptc)).WithMagnitude(1), + vp = (sbls->normal).Cross(up); + + if(vp.Dot(axis) < 0) { + axis = axis.ScaledBy(-1); + } + + SBezierLoop *sbl; + for(sbl = sbls->l.First(); sbl; sbl = sbls->l.NextAfter(sbl)) { + int i, j; + SBezier *sb, *prev; + + typedef struct { + hSSurface d[4]; + } Revolved; + List hsl; + ZERO(&hsl); + + for(sb = sbl->l.First(); sb; sb = sbl->l.NextAfter(sb)) { + Revolved revs; + for(j = 0; j < 4; j++) { + SSurface ss = SSurface::FromRevolutionOf(sb, pt, axis, + (PI/2)*j, + (PI/2)*(j+1)); + ss.color = color; + revs.d[j] = surface.AddAndAssignId(&ss); + } + hsl.Add(&revs); + } + + 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]); + prev = &(sbl->l.elem[WRAP(i-1, sbl->l.n)]); + + for(j = 0; j < 4; j++) { + Quaternion qs = Quaternion::From(axis, (PI/2)*j); + // we want Q*(x - p) + p = Q*x + (p - Q*p) + Vector ts = pt.Minus(qs.Rotate(pt)); + + SCurve sc; + ZERO(&sc); + sc.isExact = true; + sc.exact = sb->TransformedBy(ts, qs); + (sc.exact).MakePwlInto(&(sc.pts)); + sc.surfA = revs.d[j]; + sc.surfB = revs.d[WRAP(j-1, 4)]; + + hSCurve hcb = curve.AddAndAssignId(&sc); + + STrimBy stb; + stb = STrimBy::EntireCurve(this, hcb, true); + (surface.FindById(sc.surfA))->trim.Add(&stb); + stb = STrimBy::EntireCurve(this, hcb, false); + (surface.FindById(sc.surfB))->trim.Add(&stb); + + SSurface *ss = surface.FindById(sc.surfA); + + ZERO(&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); + + stb = STrimBy::EntireCurve(this, hcc, false); + (surface.FindById(sc.surfA))->trim.Add(&stb); + stb = STrimBy::EntireCurve(this, hcc, true); + (surface.FindById(sc.surfB))->trim.Add(&stb); + } + } + + hsl.Clear(); + } +} + void SShell::MakeFromCopyOf(SShell *a) { MakeFromTransformationOf(a, Vector::From(0, 0, 0), Quaternion::IDENTITY); } diff --git a/srf/surface.h b/srf/surface.h index 3003265..332f246 100644 --- a/srf/surface.h +++ b/srf/surface.h @@ -201,6 +201,8 @@ public: SBspUv *bsp; static SSurface FromExtrusionOf(SBezier *spc, Vector t0, Vector t1); + static SSurface FromRevolutionOf(SBezier *sb, Vector pt, Vector axis, + double thetas, double thetaf); static SSurface FromPlane(Vector pt, Vector u, Vector v); static SSurface FromTransformationOf(SSurface *a, Vector t, Quaternion q, bool includingTrims); @@ -265,6 +267,8 @@ public: void MakeFromExtrusionOf(SBezierLoopSet *sbls, Vector t0, Vector t1, int color); + void MakeFromRevolutionOf(SBezierLoopSet *sbls, Vector pt, Vector axis, + int color); void MakeFromUnionOf(SShell *a, SShell *b); void MakeFromDifferenceOf(SShell *a, SShell *b); diff --git a/util.cpp b/util.cpp index 58c4c00..7ea23b7 100644 --- a/util.cpp +++ b/util.cpp @@ -120,6 +120,17 @@ Quaternion Quaternion::From(hParam w, hParam vx, hParam vy, hParam vz) { return q; } +Quaternion Quaternion::From(Vector axis, double dtheta) { + Quaternion q; + double c = cos(dtheta / 2), s = sin(dtheta / 2); + axis = axis.WithMagnitude(s); + q.w = c; + q.vx = axis.x; + q.vy = axis.y; + q.vz = axis.z; + return q; +} + Quaternion Quaternion::From(Vector u, Vector v) { Vector n = u.Cross(v);