Remove old sweep/helical sweep code for meshes, and add some

untested stuff to start making exact surface shells.

[git-p4: depot-paths = "//depot/solvespace/": change = 1896]
This commit is contained in:
Jonathan Westhues 2009-01-16 21:28:49 -08:00
parent f904c0fbee
commit 7a874c20c0
4 changed files with 120 additions and 159 deletions

View File

@ -200,153 +200,6 @@ void Group::GenerateMeshForStepAndRepeat(void) {
thisMesh.Clear();
}
void Group::GenerateMeshForSweep(bool helical,
Vector axisp, Vector axis, Vector onHelix)
{
STriMeta meta = { 0, color };
int a, i;
// The closed section that will be swept along the curve
Group *section = SS.GetGroup(helical ? opA : opB);
SEdgeList edges;
ZERO(&edges);
(section->poly).MakeEdgesInto(&edges);
// The trajectory along which the section will be swept
SContour traj;
ZERO(&traj);
if(helical) {
double r0 = onHelix.DistanceToLine(axisp, axis);
int n = (int)(SS.CircleSides(r0)*valA) + 4;
Vector origin = onHelix.ClosestPointOnLine(axisp, axis);
Vector u = (onHelix.Minus(origin)).WithMagnitude(1);
Vector v = (axis.Cross(u)).WithMagnitude(1);
for(i = 0; i <= n; i++) {
double turns = (i*valA)/n;
double theta = turns*2*PI;
double r = r0 + turns*valC;
if(subtype == LEFT_HANDED) theta = -theta;
Vector p = origin.Plus(
u.ScaledBy(r*cos(theta)).Plus(
v.ScaledBy(r*sin(theta)).Plus(
axis.WithMagnitude(turns*valB))));
traj.AddPoint(p);
}
} else {
GetTrajectory(opA, &traj, &(section->poly));
}
if(traj.l.n <= 0) {
edges.Clear();
return; // no trajectory, nothing to do
}
// Initial offset/orientation determined by first pwl in trajectory
Vector origRef = traj.l.elem[0].p;
Vector origNormal = (traj.l.elem[1].p).Minus(origRef);
origNormal = origNormal.WithMagnitude(1);
Vector oldRef = origRef, oldNormal = origNormal;
Vector oldU, oldV;
if(helical) {
oldU = axis.WithMagnitude(1);
oldV = (oldNormal.Cross(oldU)).WithMagnitude(1);
// numerical fixup, since pwl segment isn't exactly tangent...
oldU = (oldV.Cross(oldNormal)).WithMagnitude(1);
} else {
oldU = oldNormal.Normal(0);
oldV = oldNormal.Normal(1);
}
// The endcap at the start of the curve
SPolygon cap;
ZERO(&cap);
edges.l.ClearTags();
edges.AssemblePolygon(&cap, NULL);
cap.normal = cap.ComputeNormal();
if(oldNormal.Dot(cap.normal) > 0) {
cap.normal = (cap.normal).ScaledBy(-1);
}
cap.TriangulateInto(&thisMesh, meta);
cap.Clear();
// Rewrite the source polygon so that the trajectory is along the
// z axis, and the poly lies in the xy plane
for(i = 0; i < edges.l.n; i++) {
SEdge *e = &(edges.l.elem[i]);
e->a = ((e->a).Minus(oldRef)).DotInToCsys(oldU, oldV, oldNormal);
e->b = ((e->b).Minus(oldRef)).DotInToCsys(oldU, oldV, oldNormal);
}
Vector polyn =
(section->poly.normal).DotInToCsys(oldU, oldV, oldNormal);
for(a = 1; a < traj.l.n; a++) {
Vector thisRef = traj.l.elem[a].p;
Vector thisNormal, useNormal;
if(a == traj.l.n - 1) {
thisNormal = oldNormal;
useNormal = oldNormal;
} else {
thisNormal = (traj.l.elem[a+1].p).Minus(thisRef);
useNormal = (thisNormal.Plus(oldNormal)).ScaledBy(0.5);
}
Vector useV, useU;
useNormal = useNormal.WithMagnitude(1);
if(helical) {
// The axis of rotation is always a basis vector
useU = axis.WithMagnitude(1);
useV = (useNormal.Cross(useU)).WithMagnitude(1);
} else {
// Choose a new coordinate system, normal to the trajectory and
// with the minimum possible twist about the normal.
useV = (useNormal.Cross(oldU)).WithMagnitude(1);
useU = (useV.Cross(useNormal)).WithMagnitude(1);
}
Quaternion qi = Quaternion::From(oldU, oldV);
Quaternion qf = Quaternion::From(useU, useV);
for(i = 0; i < edges.l.n; i++) {
SEdge *edge = &(edges.l.elem[i]);
Vector ai, bi, af, bf;
ai = qi.Rotate(edge->a).Plus(oldRef);
bi = qi.Rotate(edge->b).Plus(oldRef);
af = qf.Rotate(edge->a).Plus(thisRef);
bf = qf.Rotate(edge->b).Plus(thisRef);
Vector ab = (edge->b).Minus(edge->a);
Vector out = polyn.Cross(ab);
out = qf.Rotate(out);
AddQuadWithNormal(meta, out, ai, bi, bf, af);
}
oldRef = thisRef;
oldNormal = thisNormal;
oldU = useU;
oldV = useV;
}
Quaternion q = Quaternion::From(oldU, oldV);
for(i = 0; i < edges.l.n; i++) {
SEdge *edge = &(edges.l.elem[i]);
(edge->a) = q.Rotate(edge->a).Plus(oldRef);
(edge->b) = q.Rotate(edge->b).Plus(oldRef);
}
edges.l.ClearTags();
edges.AssemblePolygon(&cap, NULL);
cap.normal = cap.ComputeNormal();
if(oldNormal.Dot(cap.normal) < 0) {
cap.normal = (cap.normal).ScaledBy(-1);
}
cap.TriangulateInto(&thisMesh, meta);
cap.Clear();
traj.l.Clear();
edges.Clear();
}
void Group::GenerateMesh(void) {
thisMesh.Clear();
STriMeta meta = { 0, color };
@ -472,15 +325,6 @@ void Group::GenerateMesh(void) {
AddQuadWithNormal(meta, out, ai, bi, bf, af);
}
}
} else if(type == SWEEP) {
Vector zp = Vector::From(0, 0, 0);
GenerateMeshForSweep(false, zp, zp, zp);
} else if(type == HELICAL_SWEEP) {
Entity *ln = SS.GetEntity(predef.entityB);
Vector lna = SS.GetEntity(ln->point[0])->PointGetNum(),
lnb = SS.GetEntity(ln->point[1])->PointGetNum();
Vector onh = SS.GetEntity(predef.origin)->PointGetNum();
GenerateMeshForSweep(true, lna, lnb.Minus(lna), onh);
} else if(type == IMPORTED) {
// Triangles are just copied over, with the appropriate transformation
// applied.

View File

@ -207,8 +207,6 @@ public:
void AddQuadWithNormal(STriMeta meta, Vector out,
Vector a, Vector b, Vector c, Vector d);
void GenerateMeshForStepAndRepeat(void);
void GenerateMeshForSweep(bool helical,
Vector axisp, Vector axis, Vector onHelix);
void GenerateMesh(void);
void Draw(void);

View File

@ -123,7 +123,104 @@ void SPolyCurve::MakePwlWorker(List<Vector> *l, double ta, double tb) {
}
}
void SPolyCurve::Reverse(void) {
int i;
for(i = 0; i < (deg+1)/2; i++) {
SWAP(Vector, ctrl[i], ctrl[deg-i]);
SWAP(double, weight[i], weight[deg-i]);
}
}
void SPolyCurveList::Clear(void) {
l.Clear();
}
SPolyCurveLoop SPolyCurveLoop::FromCurves(SPolyCurveList *spcl, bool *notClosed)
{
SPolyCurveLoop loop;
ZERO(&loop);
if(spcl->l.n < 1) return loop;
spcl->l.ClearTags();
SPolyCurve *first = &(spcl->l.elem[0]);
first->tag = 1;
loop.l.Add(first);
Vector start = first->Start();
Vector hanging = first->Finish();
spcl->l.RemoveTagged();
while(spcl->l.n > 0 && !hanging.Equals(start)) {
int i;
for(i = 0; i < spcl->l.n; i++) {
SPolyCurve *test = &(spcl->l.elem[i]);
if((test->Finish()).Equals(hanging)) {
test->Reverse();
}
if((test->Start()).Equals(hanging)) {
test->tag = 1;
loop.l.Add(test);
hanging = test->Finish();
spcl->l.RemoveTagged();
break;
}
}
if(i >= spcl->l.n) {
// Didn't find the next curve in the loop
*notClosed = true;
return loop;
}
}
if(hanging.Equals(start)) {
*notClosed = false;
} else {
*notClosed = true;
}
return loop;
}
SSurface SSurface::FromExtrusionOf(SPolyCurve *spc, Vector t0, Vector t1) {
SSurface ret;
ZERO(&ret);
ret.degm = spc->deg;
ret.degn = 1;
int i;
for(i = 0; i <= ret.degm; i++) {
ret.ctrl[i][0] = (spc->ctrl[i]).Plus(t0);
ret.weight[i][0] = spc->weight[i];
ret.ctrl[i][1] = (spc->ctrl[i]).Plus(t1);
ret.weight[i][1] = spc->weight[i];
}
return ret;
}
SShell SShell::FromExtrusionOf(SPolyCurveList *spcl, Vector t0, Vector t1) {
SShell ret;
ZERO(&ret);
// Find the plane that contains our input section.
// Group the input curves into loops; this will reverse some of the
// curves if necessary for consistent (but not necessarily correct yet)
// direction.
// Generate a polygon from the curves, and use this to test how many
// times each loop is enclosed. Then set the direction (cw/ccw) to
// be correct for outlines/holes, so that we generate correct normals.
// Now generate all the surfaces, top/bottom planes plus extrusions.
// And now all the curves, trimming the top and bottom and their extrusion
// And the lines, trimming adjacent extrusion surfaces.
return ret;
}

View File

@ -19,6 +19,7 @@ public:
// our inputs.
class SPolyCurve {
public:
int tag;
int deg;
Vector ctrl[4];
double weight[4];
@ -29,6 +30,8 @@ public:
void MakePwlInto(List<Vector> *l);
void MakePwlWorker(List<Vector> *l, double ta, double tb);
void Reverse(void);
static SPolyCurve From(Vector p0, Vector p1, Vector p2, Vector p3);
static SPolyCurve From(Vector p0, Vector p1, Vector p2);
static SPolyCurve From(Vector p0, Vector p1);
@ -41,13 +44,23 @@ public:
void Clear(void);
};
class SPolyCurveLoop {
public:
List<SPolyCurve> l;
bool IsClockwiseProjdToNormal(Vector n);
static SPolyCurveLoop FromCurves(SPolyCurveList *spcl, bool *notClosed);
};
// Stuff for the surface trim curves: piecewise linear
class SCurve {
public:
hSCurve h;
List<Vector> pts;
SPolyCurve exact; // or deg = 0 if we don't know the exact form
List<Vector> pts;
hSSurface srfA;
hSSurface srfB;
};
@ -71,14 +84,23 @@ public:
int degm, degn;
Vector ctrl[4][4];
double weight[4][4];
Vector out00; // outer normal at ctrl[0][0]
List<STrimBy> trim;
static SSurface FromExtrusionOf(SPolyCurve *spc, Vector t0, Vector t1);
void TriangulateInto(SMesh *sm);
};
class SShell {
public:
IdList<SCurve,hSCurve> curve;
IdList<SSurface,hSSurface> surface;
static SShell FromExtrusionOf(SPolyCurveList *spcl, Vector t0, Vector t1);
static SShell FromUnionOf(SShell *a, SShell *b);
};
#endif