Make step and repeats step the mesh, as well as the entities. This

requires new entitiy types for the faces, by translation or by
axis-angle rotation.

[git-p4: depot-paths = "//depot/solvespace/": change = 1802]
solver
Jonathan Westhues 2008-06-21 14:49:57 -08:00
parent 5a22982e05
commit a5189f7f1a
9 changed files with 187 additions and 41 deletions

View File

@ -364,6 +364,8 @@ void Entity::DrawOrGetDistance(void) {
case FACE_NORMAL_PT: case FACE_NORMAL_PT:
case FACE_XPROD: case FACE_XPROD:
case FACE_N_ROT_TRANS: case FACE_N_ROT_TRANS:
case FACE_N_TRANS:
case FACE_N_ROT_AA:
// Do nothing; these are drawn with the triangle mesh // Do nothing; these are drawn with the triangle mesh
break; break;

View File

@ -225,12 +225,7 @@ Quaternion Entity::NormalGetNum(void) {
break; break;
case NORMAL_N_ROT_AA: { case NORMAL_N_ROT_AA: {
double theta = timesApplied*SS.GetParam(param[0])->val; q = GetAxisAngleQuaternion(0);
double s = sin(theta), c = cos(theta);
q.w = c;
q.vx = s*SS.GetParam(param[1])->val;
q.vy = s*SS.GetParam(param[2])->val;
q.vz = s*SS.GetParam(param[3])->val;
q = q.Times(numNormal); q = q.Times(numNormal);
break; break;
} }
@ -318,15 +313,7 @@ ExprQuaternion Entity::NormalGetExprs(void) {
case NORMAL_N_ROT_AA: { case NORMAL_N_ROT_AA: {
ExprQuaternion orig = ExprQuaternion::From(numNormal); ExprQuaternion orig = ExprQuaternion::From(numNormal);
q = GetAxisAngleQuaternionExprs(0);
Expr *theta = Expr::From(timesApplied)->Times(
Expr::From(param[0]));
Expr *c = theta->Cos(), *s = theta->Sin();
q.w = c;
q.vx = s->Times(Expr::From(param[1]));
q.vy = s->Times(Expr::From(param[2]));
q.vz = s->Times(Expr::From(param[3]));
q = q.Times(orig); q = q.Times(orig);
break; break;
} }
@ -486,14 +473,7 @@ ExprVector Entity::PointGetExprs(void) {
case POINT_N_ROT_AA: { case POINT_N_ROT_AA: {
ExprVector orig = ExprVector::From(numPoint); ExprVector orig = ExprVector::From(numPoint);
ExprVector trans = ExprVector::From(param[0], param[1], param[2]); ExprVector trans = ExprVector::From(param[0], param[1], param[2]);
Expr *theta = Expr::From(timesApplied)->Times( ExprQuaternion q = GetAxisAngleQuaternionExprs(3);
Expr::From(param[3]));
Expr *c = theta->Cos(), *s = theta->Sin();
ExprQuaternion q = {
c,
s->Times(Expr::From(param[4])),
s->Times(Expr::From(param[5])),
s->Times(Expr::From(param[6])) };
orig = orig.Minus(trans); orig = orig.Minus(trans);
orig = q.Rotate(orig); orig = q.Rotate(orig);
r = orig.Plus(trans); r = orig.Plus(trans);
@ -539,16 +519,35 @@ void Entity::PointForceQuaternionTo(Quaternion q) {
SS.GetParam(param[6])->val = q.vz; SS.GetParam(param[6])->val = q.vz;
} }
Quaternion Entity::GetAxisAngleQuaternion(int param0) {
Quaternion q;
double theta = timesApplied*SS.GetParam(param[param0+0])->val;
double s = sin(theta), c = cos(theta);
q.w = c;
q.vx = s*SS.GetParam(param[param0+1])->val;
q.vy = s*SS.GetParam(param[param0+2])->val;
q.vz = s*SS.GetParam(param[param0+3])->val;
return q;
}
ExprQuaternion Entity::GetAxisAngleQuaternionExprs(int param0) {
ExprQuaternion q;
Expr *theta = Expr::From(timesApplied)->Times(
Expr::From(param[param0+0]));
Expr *c = theta->Cos(), *s = theta->Sin();
q.w = c;
q.vx = s->Times(Expr::From(param[param0+1]));
q.vy = s->Times(Expr::From(param[param0+2]));
q.vz = s->Times(Expr::From(param[param0+3]));
return q;
}
Quaternion Entity::PointGetQuaternion(void) { Quaternion Entity::PointGetQuaternion(void) {
Quaternion q; Quaternion q;
if(type == POINT_N_ROT_AA) { if(type == POINT_N_ROT_AA) {
double theta = timesApplied*SS.GetParam(param[3])->val; q = GetAxisAngleQuaternion(3);
double s = sin(theta), c = cos(theta);
q.w = c;
q.vx = s*SS.GetParam(param[4])->val;
q.vy = s*SS.GetParam(param[5])->val;
q.vz = s*SS.GetParam(param[6])->val;
} else if(type == POINT_N_ROT_TRANS) { } else if(type == POINT_N_ROT_TRANS) {
q = Quaternion::From(param[3], param[4], param[5], param[6]); q = Quaternion::From(param[3], param[4], param[5], param[6]);
} else oops(); } else oops();
@ -561,6 +560,8 @@ bool Entity::IsFace(void) {
case FACE_NORMAL_PT: case FACE_NORMAL_PT:
case FACE_XPROD: case FACE_XPROD:
case FACE_N_ROT_TRANS: case FACE_N_ROT_TRANS:
case FACE_N_TRANS:
case FACE_N_ROT_AA:
return true; return true;
default: default:
return false; return false;
@ -586,6 +587,12 @@ ExprVector Entity::FaceGetNormalExprs(void) {
ExprQuaternion q = ExprQuaternion q =
ExprQuaternion::From(param[3], param[4], param[5], param[6]); ExprQuaternion::From(param[3], param[4], param[5], param[6]);
r = q.Rotate(r); r = q.Rotate(r);
} else if(type == FACE_N_TRANS) {
r = ExprVector::From(numNormal.vx, numNormal.vy, numNormal.vz);
} else if(type == FACE_N_ROT_AA) {
r = ExprVector::From(numNormal.vx, numNormal.vy, numNormal.vz);
ExprQuaternion q = GetAxisAngleQuaternionExprs(3);
r = q.Rotate(r);
} else oops(); } else oops();
return r; return r;
} }
@ -603,6 +610,12 @@ Vector Entity::FaceGetNormalNum(void) {
r = Vector::From(numNormal.vx, numNormal.vy, numNormal.vz); r = Vector::From(numNormal.vx, numNormal.vy, numNormal.vz);
Quaternion q = Quaternion::From(param[3], param[4], param[5], param[6]); Quaternion q = Quaternion::From(param[3], param[4], param[5], param[6]);
r = q.Rotate(r); r = q.Rotate(r);
} else if(type == FACE_N_TRANS) {
r = Vector::From(numNormal.vx, numNormal.vy, numNormal.vz);
} else if(type == FACE_N_ROT_AA) {
r = Vector::From(numNormal.vx, numNormal.vy, numNormal.vz);
Quaternion q = GetAxisAngleQuaternion(3);
r = q.Rotate(r);
} else oops(); } else oops();
return r.WithMagnitude(1); return r.WithMagnitude(1);
} }
@ -621,6 +634,17 @@ ExprVector Entity::FaceGetPointExprs(void) {
r = ExprVector::From(numPoint); r = ExprVector::From(numPoint);
r = q.Rotate(r); r = q.Rotate(r);
r = r.Plus(trans); r = r.Plus(trans);
} else if(type == FACE_N_TRANS) {
ExprVector trans = ExprVector::From(param[0], param[1], param[2]);
r = ExprVector::From(numPoint);
r = r.Plus(trans.ScaledBy(Expr::From(timesApplied)));
} else if(type == FACE_N_ROT_AA) {
ExprVector trans = ExprVector::From(param[0], param[1], param[2]);
ExprQuaternion q = GetAxisAngleQuaternionExprs(3);
r = ExprVector::From(numPoint);
r = r.Minus(trans);
r = q.Rotate(r);
r = r.Plus(trans);
} else oops(); } else oops();
return r; return r;
} }
@ -637,6 +661,15 @@ Vector Entity::FaceGetPointNum(void) {
Quaternion q = Quaternion::From(param[3], param[4], param[5], param[6]); Quaternion q = Quaternion::From(param[3], param[4], param[5], param[6]);
r = q.Rotate(numPoint); r = q.Rotate(numPoint);
r = r.Plus(trans); r = r.Plus(trans);
} else if(type == FACE_N_TRANS) {
Vector trans = Vector::From(param[0], param[1], param[2]);
r = numPoint.Plus(trans.ScaledBy(timesApplied));
} else if(type == FACE_N_ROT_AA) {
Vector trans = Vector::From(param[0], param[1], param[2]);
Quaternion q = GetAxisAngleQuaternion(3);
r = numPoint.Minus(trans);
r = q.Rotate(r);
r = r.Plus(trans);
} else oops(); } else oops();
return r; return r;
} }

View File

@ -642,9 +642,19 @@ void Group::CopyEntity(IdList<Entity,hEntity> *el,
case Entity::FACE_NORMAL_PT: case Entity::FACE_NORMAL_PT:
case Entity::FACE_XPROD: case Entity::FACE_XPROD:
case Entity::FACE_N_ROT_TRANS: case Entity::FACE_N_ROT_TRANS:
if(asTrans || asAxisAngle) return; case Entity::FACE_N_TRANS:
case Entity::FACE_N_ROT_AA:
if(asTrans) {
en.type = Entity::FACE_N_TRANS;
en.param[0] = dx;
en.param[1] = dy;
en.param[2] = dz;
} else {
if(asAxisAngle) {
en.type = Entity::FACE_N_ROT_AA;
} else {
en.type = Entity::FACE_N_ROT_TRANS; en.type = Entity::FACE_N_ROT_TRANS;
}
en.param[0] = dx; en.param[0] = dx;
en.param[1] = dy; en.param[1] = dy;
en.param[2] = dz; en.param[2] = dz;
@ -652,6 +662,7 @@ void Group::CopyEntity(IdList<Entity,hEntity> *el,
en.param[4] = qvx; en.param[4] = qvx;
en.param[5] = qvy; en.param[5] = qvy;
en.param[6] = qvz; en.param[6] = qvz;
}
en.numPoint = ep->actPoint; en.numPoint = ep->actPoint;
en.numNormal = ep->actNormal; en.numNormal = ep->actNormal;
break; break;

View File

@ -126,6 +126,77 @@ void Group::AddQuadWithNormal(STriMeta meta, Vector out,
if(n2.Magnitude() > LENGTH_EPS) thisMesh.AddTriangle(&quad2); if(n2.Magnitude() > LENGTH_EPS) thisMesh.AddTriangle(&quad2);
} }
void Group::GenerateMeshForStepAndRepeat(void) {
Group *src = SS.GetGroup(opA);
SMesh *srcm = &(src->thisMesh); // the mesh to step and repeat
if(srcm->l.n == 0) {
runningMesh.Clear();
runningMesh.MakeFromCopy(PreviousGroupMesh());
return;
}
SMesh origm;
ZERO(&origm);
origm.MakeFromCopy(src->PreviousGroupMesh());
int n = (int)valA, a0 = 0;
if(subtype == ONE_SIDED && skipFirst) {
a0++; n++;
}
int a;
for(a = a0; a < n; a++) {
int ap = a*2 - (subtype == ONE_SIDED ? 0 : (n-1));
int remap = (a == (n - 1)) ? REMAP_LAST : a;
thisMesh.Clear();
if(type == TRANSLATE) {
Vector trans = Vector::From(h.param(0), h.param(1), h.param(2));
trans = trans.ScaledBy(ap);
for(int i = 0; i < srcm->l.n; i++) {
STriangle tr = srcm->l.elem[i];
tr.a = (tr.a).Plus(trans);
tr.b = (tr.b).Plus(trans);
tr.c = (tr.c).Plus(trans);
if(tr.meta.face != 0) {
hEntity he = { tr.meta.face };
tr.meta.face = Remap(he, remap).v;
}
thisMesh.AddTriangle(&tr);
}
} else {
Vector trans = Vector::From(h.param(0), h.param(1), h.param(2));
double theta = ap * SS.GetParam(h.param(3))->val;
double c = cos(theta), s = sin(theta);
Vector axis = Vector::From(h.param(4), h.param(5), h.param(6));
Quaternion q = Quaternion::From(c, s*axis.x, s*axis.y, s*axis.z);
for(int i = 0; i < srcm->l.n; i++) {
STriangle tr = srcm->l.elem[i];
tr.a = (q.Rotate((tr.a).Minus(trans))).Plus(trans);
tr.b = (q.Rotate((tr.b).Minus(trans))).Plus(trans);
tr.c = (q.Rotate((tr.c).Minus(trans))).Plus(trans);
if(tr.meta.face != 0) {
hEntity he = { tr.meta.face };
tr.meta.face = Remap(he, remap).v;
}
thisMesh.AddTriangle(&tr);
}
}
runningMesh.Clear();
if(src->meshCombine == COMBINE_AS_DIFFERENCE) {
runningMesh.MakeFromDifference(&origm, &thisMesh);
} else {
runningMesh.MakeFromUnion(&origm, &thisMesh);
}
origm.Clear();
origm.MakeFromCopy(&runningMesh);
}
origm.Clear();
thisMesh.Clear();
}
void Group::GenerateMeshForSweep(void) { void Group::GenerateMeshForSweep(void) {
STriMeta meta = { 0, color }; STriMeta meta = { 0, color };
SEdgeList edges; SEdgeList edges;
@ -239,6 +310,11 @@ void Group::GenerateMesh(void) {
thisMesh.Clear(); thisMesh.Clear();
STriMeta meta = { 0, color }; STriMeta meta = { 0, color };
if(type == TRANSLATE || type == ROTATE) {
GenerateMeshForStepAndRepeat();
return;
}
if(type == EXTRUDE) { if(type == EXTRUDE) {
SEdgeList edges; SEdgeList edges;
ZERO(&edges); ZERO(&edges);
@ -384,9 +460,17 @@ void Group::GenerateMesh(void) {
} }
} }
runningMesh.Clear();
// If this group contributes no new mesh, then our running mesh is the
// same as last time, no combining required.
if(thisMesh.l.n == 0) {
runningMesh.MakeFromCopy(PreviousGroupMesh());
return;
}
// So our group's mesh appears in thisMesh. Combine this with the previous // So our group's mesh appears in thisMesh. Combine this with the previous
// group's mesh, using the requested operation. // group's mesh, using the requested operation.
runningMesh.Clear();
bool prevMeshError = meshError.yes; bool prevMeshError = meshError.yes;
meshError.yes = false; meshError.yes = false;
meshError.interferesAt.Clear(); meshError.interferesAt.Clear();
@ -424,7 +508,7 @@ void Group::Draw(void) {
// to show or hide just this with the "show solids" flag. // to show or hide just this with the "show solids" flag.
int specColor; int specColor;
if(type != EXTRUDE && type != IMPORTED && type != LATHE && type != SWEEP) { if(type == DRAWING_3D || type == DRAWING_WORKPLANE) {
specColor = RGB(25, 25, 25); // force the color to something dim specColor = RGB(25, 25, 25); // force the color to something dim
} else { } else {
specColor = -1; // use the model color specColor = -1; // use the model color

View File

@ -256,6 +256,13 @@ bool SMesh::MakeFromInterferenceCheck(SMesh *srca, SMesh *srcb, SMesh *error) {
return (error->l.n == 0); return (error->l.n == 0);
} }
void SMesh::MakeFromCopy(SMesh *a) {
int i;
for(i = 0; i < a->l.n; i++) {
AddTriangle(&(a->l.elem[i]));
}
}
DWORD SMesh::FirstIntersectionWith(Point2d mp) { DWORD SMesh::FirstIntersectionWith(Point2d mp) {
Vector p0 = Vector::From(mp.x, mp.y, 0); Vector p0 = Vector::From(mp.x, mp.y, 0);
Vector gn = Vector::From(0, 0, 1); Vector gn = Vector::From(0, 0, 1);

View File

@ -204,6 +204,7 @@ public:
void MakeFromUnion(SMesh *a, SMesh *b); void MakeFromUnion(SMesh *a, SMesh *b);
void MakeFromDifference(SMesh *a, SMesh *b); void MakeFromDifference(SMesh *a, SMesh *b);
bool MakeFromInterferenceCheck(SMesh *srca, SMesh *srcb, SMesh *errorAt); bool MakeFromInterferenceCheck(SMesh *srca, SMesh *srcb, SMesh *errorAt);
void MakeFromCopy(SMesh *a);
DWORD FirstIntersectionWith(Point2d mp); DWORD FirstIntersectionWith(Point2d mp);
}; };

View File

@ -189,6 +189,7 @@ public:
void GetTrajectory(hGroup hg, SContour *traj, SPolygon *section); void GetTrajectory(hGroup hg, SContour *traj, SPolygon *section);
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 GenerateMeshForSweep(void); void GenerateMeshForSweep(void);
void GenerateMesh(void); void GenerateMesh(void);
void Draw(void); void Draw(void);
@ -258,6 +259,8 @@ public:
static const int FACE_NORMAL_PT = 5000; static const int FACE_NORMAL_PT = 5000;
static const int FACE_XPROD = 5001; static const int FACE_XPROD = 5001;
static const int FACE_N_ROT_TRANS = 5002; static const int FACE_N_ROT_TRANS = 5002;
static const int FACE_N_TRANS = 5003;
static const int FACE_N_ROT_AA = 5004;
static const int WORKPLANE = 10000; static const int WORKPLANE = 10000;
@ -304,6 +307,8 @@ public:
// times to apply the transformation. // times to apply the transformation.
int timesApplied; int timesApplied;
Quaternion GetAxisAngleQuaternion(int param0);
ExprQuaternion GetAxisAngleQuaternionExprs(int param0);
bool IsVisible(void); bool IsVisible(void);
bool IsCircle(void); bool IsCircle(void);

View File

@ -322,6 +322,8 @@ void TextWindow::DescribeSelection(void) {
case Entity::FACE_NORMAL_PT: case Entity::FACE_NORMAL_PT:
case Entity::FACE_XPROD: case Entity::FACE_XPROD:
case Entity::FACE_N_ROT_TRANS: case Entity::FACE_N_ROT_TRANS:
case Entity::FACE_N_ROT_AA:
case Entity::FACE_N_TRANS:
Printf(false, "%FtPLANE FACE%E"); Printf(false, "%FtPLANE FACE%E");
p = e->FaceGetNormalNum(); p = e->FaceGetNormalNum();
Printf(true, " normal = " PT_AS_NUM, CO(p)); Printf(true, " normal = " PT_AS_NUM, CO(p));

View File

@ -8,6 +8,7 @@ remove back button in browser?
relative paths for import relative paths for import
auto-generate circles and faces when lathing auto-generate circles and faces when lathing
copy the section geometry to other end when sweeping copy the section geometry to other end when sweeping
cylindrical faces
partitioned subsystems in the solver partitioned subsystems in the solver