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_XPROD:
case FACE_N_ROT_TRANS:
case FACE_N_TRANS:
case FACE_N_ROT_AA:
// Do nothing; these are drawn with the triangle mesh
break;

View File

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

View File

@ -642,16 +642,27 @@ void Group::CopyEntity(IdList<Entity,hEntity> *el,
case Entity::FACE_NORMAL_PT:
case Entity::FACE_XPROD:
case Entity::FACE_N_ROT_TRANS:
if(asTrans || asAxisAngle) return;
en.type = Entity::FACE_N_ROT_TRANS;
en.param[0] = dx;
en.param[1] = dy;
en.param[2] = dz;
en.param[3] = qw;
en.param[4] = qvx;
en.param[5] = qvy;
en.param[6] = qvz;
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.param[0] = dx;
en.param[1] = dy;
en.param[2] = dz;
en.param[3] = qw;
en.param[4] = qvx;
en.param[5] = qvy;
en.param[6] = qvz;
}
en.numPoint = ep->actPoint;
en.numNormal = ep->actNormal;
break;

View File

@ -126,6 +126,77 @@ void Group::AddQuadWithNormal(STriMeta meta, Vector out,
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) {
STriMeta meta = { 0, color };
SEdgeList edges;
@ -239,6 +310,11 @@ void Group::GenerateMesh(void) {
thisMesh.Clear();
STriMeta meta = { 0, color };
if(type == TRANSLATE || type == ROTATE) {
GenerateMeshForStepAndRepeat();
return;
}
if(type == EXTRUDE) {
SEdgeList 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
// group's mesh, using the requested operation.
runningMesh.Clear();
bool prevMeshError = meshError.yes;
meshError.yes = false;
meshError.interferesAt.Clear();
@ -424,7 +508,7 @@ void Group::Draw(void) {
// to show or hide just this with the "show solids" flag.
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
} else {
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);
}
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) {
Vector p0 = Vector::From(mp.x, mp.y, 0);
Vector gn = Vector::From(0, 0, 1);

View File

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

View File

@ -189,6 +189,7 @@ public:
void GetTrajectory(hGroup hg, SContour *traj, SPolygon *section);
void AddQuadWithNormal(STriMeta meta, Vector out,
Vector a, Vector b, Vector c, Vector d);
void GenerateMeshForStepAndRepeat(void);
void GenerateMeshForSweep(void);
void GenerateMesh(void);
void Draw(void);
@ -258,6 +259,8 @@ public:
static const int FACE_NORMAL_PT = 5000;
static const int FACE_XPROD = 5001;
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;
@ -304,6 +307,8 @@ public:
// times to apply the transformation.
int timesApplied;
Quaternion GetAxisAngleQuaternion(int param0);
ExprQuaternion GetAxisAngleQuaternionExprs(int param0);
bool IsVisible(void);
bool IsCircle(void);

View File

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

View File

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