|
尝试将转换应用于新创建的 AcDb3dSolid 对象,如以下代码片段所示,遇到错误 Acad::eCannotScaleNonUniformly
试试下面的函数makeUniform(mat)。它使垫子均匀,同时尽可能多地保留其特性:
AcGeMatrix3d &makeUniformNoRounding(AcGeMatrix3d &mat);
// Make mat uniform
// Preserves:
// + direction of the Z-axis
// + ZX-plane
// + "average" length of the base vectors
// + all elements m[i][3] und m[3][j]
AcGeMatrix3d &makeUniform(AcGeMatrix3d &mat)
{
// set values to 0 / 1 that only differ by 1e-12 from 0 / 1
int i, j;
double *dval;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
{
dval = &(mat(i, j));
if (fabs(*dval) < 1e-12)
*dval = 0.0;
else if (fabs(*dval - 1.0) < 1e-6)
*dval = 1.0;
}
dval = &(mat(i, 3));
if (fabs(*dval) < 1e-12)
*dval = 0.0;
}
makeUniformNoRounding(mat);
return mat;
}
bool approx(const double &x1, const double &x2, const double &tol)
{
int exp1, exp2;
double mant1 = frexp(x1, &exp1);
double mant2 = frexp(x2, &exp2);
if (abs(exp1 - exp2) > 1)
return FALSE; // exp1 > 2*exp2 or exp2 > 2*exp1
else if (exp1 > exp2)
mant2 *= 2; // to same exponent
else if (exp2 > exp1)
mant1 *= 2;
return (fabs(mant1 - mant2) < tol);
}
AcGeMatrix3d &makeUniformNoRounding(AcGeMatrix3d &mat)
{
AcGePoint3d origin;
AcGeVector3d eX, eY, eZ;
mat.getCoordSystem(origin, eX, eY, eZ);
bool bSetKoSys = false;
double spXY = eX.dotProduct(eY),
spZX = eZ.dotProduct(eX),
spYZ = eY.dotProduct(eZ);
// make pairwise perpendicular
if (spXY != 0.0 || spZX != 0.0 || spYZ != 0.0)
{
// keep eZ
AcGeVector3d eZnorm(eZ), eYnorm;
eZnorm.normalize();
eX -= eZnorm * eX.dotProduct(eZnorm);
// eX must be perpendicular to eY and eZ
eYnorm = eX.crossProduct(eZnorm).normalize();
double lY = eY.dotProduct(eYnorm);
eY = lY * eYnorm;
bSetKoSys = true;
}
double slX = eX.dotProduct(eX), // = eX.lengthSqrd()
slY = eY.dotProduct(eY),
slZ = eZ.dotProduct(eZ);
// make same length
if (!approx(slX, slY, 1e-12) || !approx(slX, slZ, 1e-12))
{
double lav = sqrt((slX + slY + slZ) / 3.0); // average length
eX.normalize(); eX *= lav;
eY.normalize(); eY *= lav;
eZ.normalize(); eZ *= lav;
bSetKoSys = true;
}
if (bSetKoSys)
mat.setCoordSystem(origin, eX, eY, eZ);
return mat;
} |
|