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();
|
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) {
|
void Group::GenerateMesh(void) {
|
||||||
thisMesh.Clear();
|
thisMesh.Clear();
|
||||||
STriMeta meta = { 0, color };
|
STriMeta meta = { 0, color };
|
||||||
|
@ -472,15 +325,6 @@ void Group::GenerateMesh(void) {
|
||||||
AddQuadWithNormal(meta, out, ai, bi, bf, af);
|
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) {
|
} else if(type == IMPORTED) {
|
||||||
// Triangles are just copied over, with the appropriate transformation
|
// Triangles are just copied over, with the appropriate transformation
|
||||||
// applied.
|
// applied.
|
||||||
|
|
2
sketch.h
2
sketch.h
|
@ -207,8 +207,6 @@ public:
|
||||||
void AddQuadWithNormal(STriMeta meta, Vector out,
|
void AddQuadWithNormal(STriMeta meta, Vector out,
|
||||||
Vector a, Vector b, Vector c, Vector d);
|
Vector a, Vector b, Vector c, Vector d);
|
||||||
void GenerateMeshForStepAndRepeat(void);
|
void GenerateMeshForStepAndRepeat(void);
|
||||||
void GenerateMeshForSweep(bool helical,
|
|
||||||
Vector axisp, Vector axis, Vector onHelix);
|
|
||||||
void GenerateMesh(void);
|
void GenerateMesh(void);
|
||||||
void Draw(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) {
|
void SPolyCurveList::Clear(void) {
|
||||||
l.Clear();
|
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.
|
// our inputs.
|
||||||
class SPolyCurve {
|
class SPolyCurve {
|
||||||
public:
|
public:
|
||||||
|
int tag;
|
||||||
int deg;
|
int deg;
|
||||||
Vector ctrl[4];
|
Vector ctrl[4];
|
||||||
double weight[4];
|
double weight[4];
|
||||||
|
@ -29,6 +30,8 @@ public:
|
||||||
void MakePwlInto(List<Vector> *l);
|
void MakePwlInto(List<Vector> *l);
|
||||||
void MakePwlWorker(List<Vector> *l, double ta, double tb);
|
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, Vector p3);
|
||||||
static SPolyCurve From(Vector p0, Vector p1, Vector p2);
|
static SPolyCurve From(Vector p0, Vector p1, Vector p2);
|
||||||
static SPolyCurve From(Vector p0, Vector p1);
|
static SPolyCurve From(Vector p0, Vector p1);
|
||||||
|
@ -41,13 +44,23 @@ public:
|
||||||
void Clear(void);
|
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
|
// Stuff for the surface trim curves: piecewise linear
|
||||||
class SCurve {
|
class SCurve {
|
||||||
public:
|
public:
|
||||||
hSCurve h;
|
hSCurve h;
|
||||||
|
|
||||||
List<Vector> pts;
|
SPolyCurve exact; // or deg = 0 if we don't know the exact form
|
||||||
|
List<Vector> pts;
|
||||||
hSSurface srfA;
|
hSSurface srfA;
|
||||||
hSSurface srfB;
|
hSSurface srfB;
|
||||||
};
|
};
|
||||||
|
@ -71,14 +84,23 @@ public:
|
||||||
int degm, degn;
|
int degm, degn;
|
||||||
Vector ctrl[4][4];
|
Vector ctrl[4][4];
|
||||||
double weight[4][4];
|
double weight[4][4];
|
||||||
|
Vector out00; // outer normal at ctrl[0][0]
|
||||||
|
|
||||||
List<STrimBy> trim;
|
List<STrimBy> trim;
|
||||||
|
|
||||||
|
static SSurface FromExtrusionOf(SPolyCurve *spc, Vector t0, Vector t1);
|
||||||
|
|
||||||
|
void TriangulateInto(SMesh *sm);
|
||||||
};
|
};
|
||||||
|
|
||||||
class SShell {
|
class SShell {
|
||||||
public:
|
public:
|
||||||
IdList<SCurve,hSCurve> curve;
|
IdList<SCurve,hSCurve> curve;
|
||||||
IdList<SSurface,hSSurface> surface;
|
IdList<SSurface,hSSurface> surface;
|
||||||
|
|
||||||
|
static SShell FromExtrusionOf(SPolyCurveList *spcl, Vector t0, Vector t1);
|
||||||
|
|
||||||
|
static SShell FromUnionOf(SShell *a, SShell *b);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue
Block a user