📄 transform3d.java
字号:
} else { // Not even congruent, so isRigid must be false type &= ~RIGID; } dirtyBits &= ~RIGID_BIT; } } return ((type & RIGID) != 0); } /** * Returns the least general type of this matrix; the order of * generality from least to most is: ZERO, IDENTITY, * SCALE/TRANSLATION, ORTHOGONAL, RIGID, CONGRUENT, AFFINE. * If the matrix is ORTHOGONAL, calling the method * getDeterminantSign() will yield more information. * @return the least general matrix type */ public final int getBestType() { getType(); // force classify if necessary if ((type & ZERO) != 0 ) return ZERO; if ((type & IDENTITY) != 0 ) return IDENTITY; if ((type & SCALE) != 0 ) return SCALE; if ((type & TRANSLATION) != 0 ) return TRANSLATION; if ((type & ORTHOGONAL) != 0 ) return ORTHOGONAL; if ((type & RIGID) != 0 ) return RIGID; if ((type & CONGRUENT) != 0 ) return CONGRUENT; if ((type & AFFINE) != 0 ) return AFFINE; if ((type & NEGATIVE_DETERMINANT) != 0 ) return NEGATIVE_DETERMINANT; return 0; } /* private void print_type() { if ((type & ZERO) > 0 ) System.err.print(" ZERO"); if ((type & IDENTITY) > 0 ) System.err.print(" IDENTITY"); if ((type & SCALE) > 0 ) System.err.print(" SCALE"); if ((type & TRANSLATION) > 0 ) System.err.print(" TRANSLATION"); if ((type & ORTHOGONAL) > 0 ) System.err.print(" ORTHOGONAL"); if ((type & RIGID) > 0 ) System.err.print(" RIGID"); if ((type & CONGRUENT) > 0 ) System.err.print(" CONGRUENT"); if ((type & AFFINE) > 0 ) System.err.print(" AFFINE"); if ((type & NEGATIVE_DETERMINANT) > 0 ) System.err.print(" NEGATIVE_DETERMINANT"); } */ /** * Returns the sign of the determinant of this matrix; a return value * of true indicates a non-negative determinant; a return value of false * indicates a negative determinant. A value of true will be returned if * the determinant is NaN. In general, an orthogonal matrix * with a positive determinant is a pure rotation matrix; an orthogonal * matrix with a negative determinant is a both a rotation and a * reflection matrix. * @return determinant sign : true means non-negative, false means negative */ public final boolean getDeterminantSign() { double det = determinant(); if (Double.isNaN(det)) { return true; } return det >= 0; } /** * Sets a flag that enables or disables automatic SVD * normalization. If this flag is enabled, an automatic SVD * normalization of the rotational components (upper 3x3) of this * matrix is done after every subsequent matrix operation that * modifies this matrix. This is functionally equivalent to * calling normalize() after every subsequent call, but may be * less computationally expensive. * The default value for this parameter is false. * @param autoNormalize the boolean state of auto normalization */ public final void setAutoNormalize(boolean autoNormalize) { this.autoNormalize = autoNormalize; if (autoNormalize) { normalize(); } } /** * Returns the state of auto-normalization. * @return boolean state of auto-normalization */ public final boolean getAutoNormalize() { return this.autoNormalize; } /** * Transforms the point parameter with this transform and * places the result into pointOut. The fourth element of the * point input paramter is assumed to be one. * @param point the input point to be transformed * @param pointOut the transformed point */ void transform(Point3d point, Point4d pointOut) { pointOut.x = mat[0]*point.x + mat[1]*point.y + mat[2]*point.z + mat[3]; pointOut.y = mat[4]*point.x + mat[5]*point.y + mat[6]*point.z + mat[7]; pointOut.z = mat[8]*point.x + mat[9]*point.y + mat[10]*point.z + mat[11]; pointOut.w = mat[12]*point.x + mat[13]*point.y + mat[14]*point.z + mat[15]; } private static final boolean almostZero(double a) { return ((a < EPSILON_ABSOLUTE) && (a > -EPSILON_ABSOLUTE)); } private static final boolean almostOne(double a) { return ((a < 1+EPSILON_ABSOLUTE) && (a > 1-EPSILON_ABSOLUTE)); } private static final boolean almostEqual(double a, double b) { double diff = a-b; if (diff >= 0) { if (diff < EPSILON) { return true; } // a > b if ((b > 0) || (a > -b)) { return (diff < EPSILON_RELATIVE*a); } else { return (diff < -EPSILON_RELATIVE*b); } } else { if (diff > -EPSILON) { return true; } // a < b if ((b < 0) || (-a > b)) { return (diff > EPSILON_RELATIVE*a); } else { return (diff > -EPSILON_RELATIVE*b); } } } private final void classifyAffine() { if (!isInfOrNaN() && almostZero(mat[12]) && almostZero(mat[13]) && almostZero(mat[14]) && almostOne(mat[15])) { type |= AFFINE; } else { type &= ~AFFINE; } dirtyBits &= ~AFFINE_BIT; } // same amount of work to classify rigid and congruent private final void classifyRigid() { if ((dirtyBits & AFFINE_BIT) != 0) { // should not touch ORTHO bit type &= ORTHO; classifyAffine(); } else { // keep the affine bit if there is one // and clear the others (CONGRUENT/RIGID) bit type &= (ORTHO | AFFINE); } if ((type & AFFINE) != 0) { // checking orthogonal condition if (isOrtho()) { if ((dirtyBits & SCALE_BIT) != 0) { double s0 = mat[0]*mat[0] + mat[4]*mat[4] + mat[8]*mat[8]; double s1 = mat[1]*mat[1] + mat[5]*mat[5] + mat[9]*mat[9]; if (almostEqual(s0, s1)) { double s2 = mat[2]*mat[2] + mat[6]*mat[6] + mat[10]*mat[10]; if (almostEqual(s2, s0)) { type |= CONGRUENT; // Note that scales[0] = sqrt(s0); if (almostOne(s0)) { type |= RIGID; } } } } else { if(scales == null) scales = new double[3]; double s = scales[0]; if (almostEqual(s, scales[1]) && almostEqual(s, scales[2])) { type |= CONGRUENT; if (almostOne(s)) { type |= RIGID; } } } } } dirtyBits &= (~RIGID_BIT | ~CONGRUENT_BIT); } /** * Classifies a matrix. */ private final void classify() { if ((dirtyBits & (RIGID_BIT|AFFINE_BIT|CONGRUENT_BIT)) != 0) { // Test for RIGID, CONGRUENT, AFFINE. classifyRigid(); } // Test for ZERO, IDENTITY, SCALE, TRANSLATION, // ORTHOGONAL, NEGATIVE_DETERMINANT if ((type & AFFINE) != 0) { if ((type & CONGRUENT) != 0) { if ((type & RIGID) != 0) { if (zeroTranslation()) { type |= ORTHOGONAL; if (rotateZero()) { // mat[0], mat[5], mat[10] can be only be // 1 or -1 when reach here if ((mat[0] > 0) && (mat[5] > 0) && (mat[10] > 0)) { type |= IDENTITY|SCALE|TRANSLATION; } } } else { if (rotateZero()) { type |= TRANSLATION; } } } else { // uniform scale if (zeroTranslation() && rotateZero()) { type |= SCALE; } } } } else { // last row is not (0, 0, 0, 1) if (almostZero(mat[12]) && almostZero(mat[13]) && almostZero(mat[14]) && almostZero(mat[15]) && zeroTranslation() && rotateZero() && almostZero(mat[0]) && almostZero(mat[5]) && almostZero(mat[10])) { type |= ZERO; } } if (!getDeterminantSign()) { type |= NEGATIVE_DETERMINANT; } dirtyBits &= ~CLASSIFY_BIT; } final boolean zeroTranslation() { return (almostZero(mat[3]) && almostZero(mat[7]) && almostZero(mat[11])); } final boolean rotateZero() { return (almostZero(mat[1]) && almostZero(mat[2]) && almostZero(mat[4]) && almostZero(mat[6]) && almostZero(mat[8]) && almostZero(mat[9])); } /** * Returns the matrix elements of this transform as a string. * @return the matrix elements of this transform */ public String toString() { // also, print classification? return mat[0] + ", " + mat[1] + ", " + mat[2] + ", " + mat[3] + "\n" + mat[4] + ", " + mat[5] + ", " + mat[6] + ", " + mat[7] + "\n" + mat[8] + ", " + mat[9] + ", " + mat[10] + ", " + mat[11] + "\n" + mat[12] + ", " + mat[13] + ", " + mat[14] + ", " + mat[15] + "\n"; } /** * Sets this transform to the identity matrix. */ public final void setIdentity() { mat[0] = 1.0; mat[1] = 0.0; mat[2] = 0.0; mat[3] = 0.0; mat[4] = 0.0; mat[5] = 1.0; mat[6] = 0.0; mat[7] = 0.0; mat[8] = 0.0; mat[9] = 0.0; mat[10] = 1.0; mat[11] = 0.0; mat[12] = 0.0; mat[13] = 0.0; mat[14] = 0.0; mat[15] = 1.0; type = IDENTITY | SCALE | ORTHOGONAL | RIGID | CONGRUENT | AFFINE | TRANSLATION | ORTHO; dirtyBits = SCALE_BIT | ROTATION_BIT; // No need to set SVD_BIT } /** * Sets this transform to all zeros. */ public final void setZero() { mat[0] = 0.0; mat[1] = 0.0; mat[2] = 0.0; mat[3] = 0.0; mat[4] = 0.0; mat[5] = 0.0; mat[6] = 0.0; mat[7] = 0.0; mat[8] = 0.0; mat[9] = 0.0; mat[10] = 0.0; mat[11] = 0.0; mat[12] = 0.0; mat[13] = 0.0; mat[14] = 0.0; mat[15] = 0.0; type = ZERO | ORTHO; dirtyBits = SCALE_BIT | ROTATION_BIT; } /** * Adds this transform to transform t1 and places the result into * this: this = this + t1. * @param t1 the transform to be added to this transform */ public final void add(Transform3D t1) { for (int i=0 ; i<16 ; i++) { mat[i] += t1.mat[i]; } dirtyBits = ALL_DIRTY; if (autoNormalize) { normalize(); } } /** * Adds transforms t1 and t2 and places the result into this transform. * @param t1 the transform to be added * @param t2 the transform to be added */ public final void add(Transform3D t1, Transform3D t2) { for (int i=0 ; i<16 ; i++) { mat[i] = t1.mat[i] + t2.mat[i]; } dirtyBits = ALL_DIRTY; if (autoNormalize) { normalize(); } } /** * Subtracts transform t1 from this transform and places the result * into this: this = this - t1. * @param t1 the transform to be subtracted from this transform */ public final void sub(Transform3D t1) { for (int i=0 ; i<16 ; i++) { mat[i] -= t1.mat[i]; } dirtyBits = ALL_DIRTY; if (autoNormalize) { normalize(); } } /** * Subtracts transform t2 from transform t1 and places the result into * this: this = t1 - t2. * @param t1 the left transform * @param t2 the right transform */ public final void sub(Transform3D t1, Transform3D t2) { for (int i=0 ; i<16 ; i++) { mat[i] = t1.mat[i] - t2.mat[i]; } dirtyBits = ALL_DIRTY; if (autoNormalize) { normalize(); } } /** * Transposes this matrix in place. */ public final void transpose() { double temp; temp = mat[4]; mat[4] = mat[1]; mat[1] = temp; temp = mat[8]; mat[8] = mat[2]; mat[2] = temp; temp = mat[12]; mat[12] = mat[3]; mat[3] = temp; temp = mat[9]; mat[9] = mat[6]; mat[6] = temp; temp = mat[13]; mat[13] = mat[7]; mat[7] = temp; temp = mat[14]; mat[14] = mat[11]; mat[11] = temp; dirtyBits = ALL_DIRTY; if (autoNormalize) { normalize(); } } /** * Transposes transform t1 and places the value into this transform. * The transform t1 is not modified. * @param t1 the transform whose transpose is placed into this transform */ public final void transpose(Transform3D t1) { if (this != t1) { mat[0] = t1.mat[0]; mat[1] = t1.mat[4]; mat[2] = t1.mat[8]; mat[3] = t1.mat[12]; mat[4] = t1.mat[1]; mat[5] = t1.mat[5]; mat[6] = t1.mat[9];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -