/* Compute the determinant, given the adjoint matrix */ double B2DHomMatrix::computeDeterminant(constdouble (&dst)[6]) const
{ return mfValues[0][0] * dst[0] + mfValues[0][1] * dst[3];
}
B2DHomMatrix& B2DHomMatrix::operator*=(const B2DHomMatrix& rMat)
{ if(rMat.isIdentity())
{ // multiply with identity, no change -> nothing to do
} elseif(isIdentity())
{ // we are identity, result will be rMat -> assign
*this = rMat;
} else
{ // multiply
doMulMatrix(rMat);
}
return *this;
}
void B2DHomMatrix::doMulMatrix(const B2DHomMatrix& rMat)
{ // create a copy as source for the original values const B2DHomMatrix aCopy(*this);
for(sal_uInt16 a(0); a < 2; ++a)
{ for(sal_uInt16 b(0); b < 3; ++b)
{ double fValue = 0.0;
void B2DHomMatrix::shearX(double fSx)
{ // #i76239# do not test against 1.0, but against 0.0. We are talking about a value not on the diagonal (!) if(!fTools::equalZero(fSx))
{
B2DHomMatrix aShearXMat;
aShearXMat.set(0, 1, fSx);
doMulMatrix(aShearXMat);
}
}
void B2DHomMatrix::shearY(double fSy)
{ // #i76239# do not test against 1.0, but against 0.0. We are talking about a value not on the diagonal (!) if(!fTools::equalZero(fSy))
{
B2DHomMatrix aShearYMat;
aShearYMat.set(1, 0, fSy);
doMulMatrix(aShearYMat);
}
}
/** Decomposition
New,optimizedversionwithlocalshearXdetection.Oldversion(keeping below,isworkingwell,too)usedthe3Dmatrixdecompositionwhen shearwasused.Keepingoldversionascommentbelowsinceitmayget necessarytoaddthedeterminant()testfromtherehere,too.
*/ bool B2DHomMatrix::decompose(B2DTuple& rScale, B2DTuple& rTranslate, double& rRotate, double& rShearX) const
{ // reset rotate and shear and copy translation values in every case
rRotate = rShearX = 0.0;
rTranslate.setX(get(0, 2));
rTranslate.setY(get(1, 2));
// test for rotation and shear if(fTools::equalZero(get(0, 1)) && fTools::equalZero(get(1, 0)))
{ // no rotation and shear, copy scale values
rScale.setX(get(0, 0));
rScale.setY(get(1, 1));
// or is there? if( rScale.getX() < 0 && rScale.getY() < 0 )
{ // there is - 180 degree rotated
rScale *= -1;
rRotate = M_PI;
}
} else
{ // get the unit vectors of the transformation -> the perpendicular vectors
B2DVector aUnitVecX(get(0, 0), get(1, 0));
B2DVector aUnitVecY(get(0, 1), get(1, 1)); constdouble fScalarXY(aUnitVecX.scalar(aUnitVecY));
// Test if shear is zero. That's the case if the unit vectors in the matrix // are perpendicular -> scalar is zero. This is also the case when one of // the unit vectors is zero. if(fTools::equalZero(fScalarXY))
{ // calculate unsigned scale values
rScale.setX(aUnitVecX.getLength());
rScale.setY(aUnitVecY.getLength());
// check unit vectors for zero lengths constbool bXIsZero(fTools::equalZero(rScale.getX())); constbool bYIsZero(fTools::equalZero(rScale.getY()));
if(bXIsZero || bYIsZero)
{ // still extract as much as possible. Scalings are already set if(!bXIsZero)
{ // get rotation of X-Axis
rRotate = atan2(aUnitVecX.getY(), aUnitVecX.getX());
} elseif(!bYIsZero)
{ // get rotation of X-Axis. When assuming X and Y perpendicular // and correct rotation, it's the Y-Axis rotation minus 90 degrees
rRotate = atan2(aUnitVecY.getY(), aUnitVecY.getX()) - M_PI_2;
}
// one or both unit vectors do not exist, determinant is zero, no decomposition possible. // Eventually used rotations or shears are lost returnfalse;
} else
{ // no shear // calculate rotation of X unit vector relative to (1, 0)
rRotate = atan2(aUnitVecX.getY(), aUnitVecX.getX());
// use orientation to evtl. correct sign of Y-Scale constdouble fCrossXY(aUnitVecX.cross(aUnitVecY));
if(fCrossXY < 0.0)
{
rScale.setY(-rScale.getY());
}
}
} else
{ // fScalarXY is not zero, thus both unit vectors exist. No need to handle that here // shear, extract it double fCrossXY(aUnitVecX.cross(aUnitVecY));
// get rotation by calculating angle of X unit vector relative to (1, 0). // This is before the parallel test following the motto to extract // as much as possible
rRotate = atan2(aUnitVecX.getY(), aUnitVecX.getX());
// get unsigned scale value for X. It will not change and is useful // for further corrections
rScale.setX(aUnitVecX.getLength());
if(fTools::equalZero(fCrossXY))
{ // extract as much as possible
rScale.setY(aUnitVecY.getLength());
// unit vectors are parallel, thus not linear independent. No // useful decomposition possible. This should not happen since // the only way to get the unit vectors nearly parallel is // a very big shearing. Anyways, be prepared for hand-filled // matrices // Eventually used rotations or shears are lost returnfalse;
} else
{ // calculate the contained shear
rShearX = fScalarXY / fCrossXY;
if(!fTools::equalZero(rRotate))
{ // To be able to correct the shear for aUnitVecY, rotation needs to be // removed first. Correction of aUnitVecX is easy, it will be rotated back to (1, 0).
aUnitVecX.setX(rScale.getX());
aUnitVecX.setY(0.0);
// for Y correction we rotate the UnitVecY back about -rRotate constdouble fNegRotate(-rRotate); constdouble fSin(sin(fNegRotate)); constdouble fCos(cos(fNegRotate));
// Correct aUnitVecY and fCrossXY to fShear=0. Rotation is already removed. // Shear correction can only work with removed rotation
aUnitVecY.setX(aUnitVecY.getX() - (aUnitVecY.getY() * rShearX));
fCrossXY = aUnitVecX.cross(aUnitVecY);
// calculate unsigned scale value for Y, after the corrections since // the shear correction WILL change the length of aUnitVecY
rScale.setY(aUnitVecY.getLength());
// use orientation to set sign of Y-Scale if(fCrossXY < 0.0)
{
rScale.setY(-rScale.getY());
}
}
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.