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:
parent
f904c0fbee
commit
7a874c20c0
156
groupmesh.cpp
156
groupmesh.cpp
@ -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.
|
||||
|
2
sketch.h
2
sketch.h
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user