我的项目遇到一个与矩阵乘法有关的问题。我必须将两个矩阵相乘,一个是我做的,另一个是参数。但是,它必须通过茉莉花测试,并且当前由于NaN错误而没有通过。任何帮助将不胜感激。谢谢。 我的矩阵代码:
class Matrix {
constructor(pX0, pX1, pX2, pY0, pY1, pY2, pZ0, pZ1, pZ2) {
this.Matrix = [
[pX0, pX1, pX2],
[pY0, pY1, pY2],
[pZ0, pZ1, pZ2]
];
}
getX0() {
return this.mX0;
}
setX0(pX0) {
this.mX0 = pX0;
}
getX1() {
return this.mX1;
}
setX1(pX1) {
this.mX1 = pX1;
}
getX2() {
return this.mX2;
}
setX2(pX2) {
this.mX2 = pX2;
}
getY0() {
return this.mY0;
}
setY0(pY0) {
this.mY0 = pY0;
}
getY1() {
return this.mY1;
}
setY1(pY1) {
this.mY1 = pY1;
}
getY2() {
return this.mY2;
}
setY2(pY2) {
this.mY2 = pY2;
}
getZ0() {
return this.mZ0;
}
setZ0(pZ0) {
this.mZ0 = pZ0;
}
getZ1() {
return this.mZ1;
}
setZ1(pZ1) {
this.mZ1 = pZ1;
}
getZ2() {
return this.mZ2;
}
setZ2(pZ2) {
this.mZ2 = pZ2;
}
getElement(pRow, pColumn) {
return this.Matrix[pRow][pColumn];
}
static createIdentity() {
return new Matrix(1, 0, 0, 0, 1, 0, 0, 0, 1);
}
static createTranslation(pTranslationVector) {
return new Matrix(1, 0, pTranslationVector.getX(), 0, 1, pTranslationVector.getY(), 0, 0, 1);
}
static createScale(pScaleVector) {
return new Matrix(pScaleVector.getX(), 0, 0, 0, pScaleVector.getY(), 0, 0, 0, 1);
}
static createRotation(pRotationScalar) {
return new Matrix(Math.cos(pRotationScalar), -Math.sin(pRotationScalar), 0, Math.sin(pRotationScalar), Math.cos(pRotationScalar), 0, 0, 0, 1);
}
multiply(pMatrix) {
return new Matrix(this.getX0 * pMatrix.getX0, this.getX1 * pMatrix.getY0, this.getX2 * pMatrix.getZ0, this.getY0 * pMatrix.getX1, this.getY1 * pMatrix.getY1, this.getY2 * pMatrix.getZ1, this.getZ0 * pMatrix.getX2, this.getZ1 * pMatrix.getY2, this.getZ2 * pMatrix.getZ2);
}
必须通过的测试:
describe("Multiply", function() {
var rotation, scaleVector, translationVector, translationMatrix,
scaleMatrix, rotationMatrix, scaleXTranslationMatrix, translationXScaleMatrix,
chainedMatrix;
rotation = Math.PI / 2;
rotationMatrix = Matrix.createRotation(rotation);
scaleVector = new Vector(2, 2, 1);
scaleMatrix = Matrix.createScale(scaleVector);
translationVector = new Vector(10, 20, 1);
translationMatrix = Matrix.createTranslation(translationVector);
describe("Scale X Translate", function() {
scaleXTranslationMatrix = scaleMatrix.multiply(translationMatrix);
it("Element (0,0) Set", function() {
expect(scaleXTranslationMatrix.getElement(0, 0)).toEqual(2);
});
it("Element (0,1) Set", function() {
expect(scaleXTranslationMatrix.getElement(0, 1)).toEqual(0);
});
it("Element (0,2) Set", function() {
expect(scaleXTranslationMatrix.getElement(0, 2)).toEqual(20);
});
it("Element (1,0) Set", function() {
expect(scaleXTranslationMatrix.getElement(1, 0)).toEqual(0);
});
it("Element (1,1) Set", function() {
expect(scaleXTranslationMatrix.getElement(1, 1)).toEqual(2);
});
it("Element (1,2) Set", function() {
expect(scaleXTranslationMatrix.getElement(1, 2)).toEqual(40);
});
it("Element (2,0) Set", function() {
expect(scaleXTranslationMatrix.getElement(2, 0)).toEqual(0);
});
it("Element (2,1) Set", function() {
expect(scaleXTranslationMatrix.getElement(2, 1)).toEqual(0);
});
it("Element (2,2) Set", function() {
expect(scaleXTranslationMatrix.getElement(2, 2)).toEqual(1);
});
});
describe("Translate X Scale", function() {
translationXScaleMatrix = translationMatrix.multiply(scaleMatrix);
it("Element (0,0) Set", function() {
expect(translationXScaleMatrix.getElement(0, 0)).toEqual(2);
});
it("Element (0,1) Set", function() {
expect(translationXScaleMatrix.getElement(0, 1)).toEqual(0);
});
it("Element (0,2) Set", function() {
expect(translationXScaleMatrix.getElement(0, 2)).toEqual(10);
});
it("Element (1,0) Set", function() {
expect(translationXScaleMatrix.getElement(1, 0)).toEqual(0);
});
it("Element (1,1) Set", function() {
expect(translationXScaleMatrix.getElement(1, 1)).toEqual(2);
});
it("Element (1,2) Set", function() {
expect(translationXScaleMatrix.getElement(1, 2)).toEqual(20);
});
it("Element (2,0) Set", function() {
expect(translationXScaleMatrix.getElement(2, 0)).toEqual(0);
});
it("Element (2,1) Set", function() {
expect(translationXScaleMatrix.getElement(2, 1)).toEqual(0);
});
it("Element (2,2) Set", function() {
expect(translationXScaleMatrix.getElement(2, 2)).toEqual(1);
});
});
describe("Chaining", function() {
var cosAngle, sinAngle;
cosAngle = Math.cos(Math.PI / 2);
sinAngle = Math.sin(Math.PI / 2);
chainedMatrix =
translationMatrix.multiply(scaleMatrix).multiply(rotationMatrix);
it("Element (0,0) Set", function() {
expect(chainedMatrix.getElement(0, 0)).toEqual(2 * cosAngle);
});
it("Element (0,1) Set", function() {
expect(chainedMatrix.getElement(0, 1)).toEqual(2 * -sinAngle);
});
it("Element (0,2) Set", function() {
expect(chainedMatrix.getElement(0, 2)).toEqual(10);
});
it("Element (1,0) Set", function() {
expect(chainedMatrix.getElement(1, 0)).toEqual(2 * sinAngle);
});
it("Element (1,1) Set", function() {
expect(chainedMatrix.getElement(1, 1)).toEqual(2 * cosAngle);
});
it("Element (1,2) Set", function() {
expect(chainedMatrix.getElement(1, 2)).toEqual(20);
});
it("Element (2,0) Set", function() {
expect(chainedMatrix.getElement(2, 0)).toEqual(0);
});
it("Element (2,1) Set", function() {
expect(chainedMatrix.getElement(2, 1)).toEqual(0);
});
it("Element (2,2) Set", function() {
expect(chainedMatrix.getElement(2, 2)).toEqual(1);
});
});
});
});
我没有主意,所以任何形式的帮助都将非常有用,谢谢。
答案 0 :(得分:0)
您的multiply
方法尝试乘以函数,而不是数字:
multiply(pMatrix) {
return new Matrix(
this.getX0 * pMatrix.getX0,
this.getX1 * pMatrix.getY0,
this.getX2 * pMatrix.getZ0,
this.getY0 * pMatrix.getX1,
this.getY1 * pMatrix.getY1,
this.getY2 * pMatrix.getZ1,
this.getZ0 * pMatrix.getX2,
this.getZ1 * pMatrix.getY2,
this.getZ2 * pMatrix.getZ2
);
}
这就是为什么您得到NaN
的原因。更改代码以乘以数值或调用getter函数:
multiply(pMatrix) {
return new Matrix(
this.getX0() * pMatrix.getX0(),
this.getX1() * pMatrix.getY0(),
this.getX2() * pMatrix.getZ0(),
this.getY0() * pMatrix.getX1(),
this.getY1() * pMatrix.getY1(),
this.getY2() * pMatrix.getZ1(),
this.getZ0() * pMatrix.getX2(),
this.getZ1() * pMatrix.getY2(),
this.getZ2() * pMatrix.getZ2()
);
}
编辑:
您还需要更新这些getter函数,因为它们会尝试获取未定义的属性。例如,getX0()
在内部返回this.mX0
。但是this.mX0
从未设置,因此返回undefined
。
像这样更改您的getter函数:
...
getX0: function () {
return this.getElement(0, 0);
}
...
您必须为每个吸气剂执行此操作 。另一种解决方案是在构造函数中调用相应的setter函数:
class Matrix {
constructor(pX0, pX1, pX2, pY0, pY1, pY2, pZ0, pZ1, pZ2) {
this.Matrix = [
[pX0, pX1, pX2],
[pY0, pY1, pY2],
[pZ0, pZ1, pZ2]
];
this.setX0(pX0);
this.setX1(pX1);
// ...
this.setZ2(pZ2);
}
// ...
}
这是您的Matrix
类的“固定”版本:
class Matrix {
constructor(pX0, pX1, pX2, pY0, pY1, pY2, pZ0, pZ1, pZ2) {
this.__matrix = [
[pX0, pX1, pX2],
[pY0, pY1, pY2],
[pZ0, pZ1, pZ2]
];
}
getX0() {
return this.getElement(0, 0);
}
setX0(pX0) {
return this.setElement(0, 0, pX0);
}
getX1() {
return this.getElement(0, 1);
}
setX1(pX1) {
return this.setElement(0, 1, pX1);
}
getX2() {
return this.getElement(0, 2);
}
setX2(pX2) {
return this.setElement(0, 2, pX2);
}
getY0() {
return this.getElement(1, 0);
}
setY0(pY0) {
return this.setElement(1, 0, pY0);
}
getY1() {
return this.getElement(1, 1);
}
setY1(pY1) {
return this.setElement(1, 1, pY1);
}
getY2() {
return this.getElement(1, 2);
}
setY2(pY2) {
return this.setElement(1, 2, pY2);
}
getZ0() {
return this.getElement(2, 0);
}
setZ0(pZ0) {
return this.setElement(2, 0, pZ0);
}
getZ1() {
return this.getElement(2, 1);
}
setZ1(pZ1) {
return this.setElement(2, 1, pZ1);
}
getZ2() {
return this.getElement(2, 2);
}
setZ2(pZ2) {
return this.setElement(2, 2, pZ2);
}
getElement(pRow, pColumn) {
return this.__matrix[pRow][pColumn];
}
setElement(pRow, pColumn, value) {
this.__matrix[pRow][pColumn] = value;
return this;
}
toString() {
return `Matrix([${this.__matrix.reduce((acc, row) => acc + '[' + row.join(',') + ']', '')}])`;
}
static createIdentity() {
return new Matrix(1, 0, 0, 0, 1, 0, 0, 0, 1);
}
static isIdentity(pMatrix) {
return Matrix.prototype.isPrototypeOf(pMatrix) &&
pMatrix.__matrix[0][0] === 1 &&
pMatrix.__matrix[0][1] === 0 &&
pMatrix.__matrix[0][2] === 0 &&
pMatrix.__matrix[1][0] === 0 &&
pMatrix.__matrix[1][1] === 1 &&
pMatrix.__matrix[1][2] === 0 &&
pMatrix.__matrix[2][0] === 0 &&
pMatrix.__matrix[2][1] === 0 &&
pMatrix.__matrix[2][2] === 1;
}
static createTranslation(pTranslationVector) {
return new Matrix(
1,
0,
pTranslationVector.getX(),
0,
1,
pTranslationVector.getY(),
0,
0,
1
);
}
static createScale(pScaleVector) {
return new Matrix(
pScaleVector.getX(),
0,
0,
0,
pScaleVector.getY(),
0,
0,
0,
1
);
}
static createRotation(pRotationScalar) {
return new Matrix(
Math.cos(pRotationScalar),
-Math.sin(pRotationScalar),
0,
Math.sin(pRotationScalar),
Math.cos(pRotationScalar),
0,
0,
0,
1
);
}
multiply(pMatrix) {
return new Matrix(
this.getX0() * pMatrix.getX0(),
this.getX1() * pMatrix.getY0(),
this.getX2() * pMatrix.getZ0(),
this.getY0() * pMatrix.getX1(),
this.getY1() * pMatrix.getY1(),
this.getY2() * pMatrix.getZ1(),
this.getZ0() * pMatrix.getX2(),
this.getZ1() * pMatrix.getY2(),
this.getZ2() * pMatrix.getZ2()
);
}
}
// TEST
let m1 = new Matrix(1, 0, 0, 0, 1, 0, 0, 0, 1);
let m2 = Matrix.createIdentity();
let m3 = m1.multiply(m2); // should give us identity again
console.log(Matrix.isIdentity(m3)); // should log true
console.log(m3.toString());