Add a map homogenous points to SkMatrix
BUG= R=bsalomon@google.com Review URL: https://codereview.chromium.org/22330004 git-svn-id: http://skia.googlecode.com/svn/trunk@10659 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
3f05c91690
commit
2fae54d945
@ -423,6 +423,19 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
/** Apply this matrix to the array of homogeneous points, specified by src,
|
||||
where a homogeneous point is defined by 3 contiguous scalar values,
|
||||
and write the transformed points into the array of scalars specified by dst.
|
||||
dst[] = M * src[]
|
||||
@param dst Where the transformed coordinates are written. It must
|
||||
contain at least 3 * count entries
|
||||
@param src The original coordinates that are to be transformed. It
|
||||
must contain at least 3 * count entries
|
||||
@param count The number of triples (homogeneous points) in src to read,
|
||||
and then transform into dst.
|
||||
*/
|
||||
void mapHomogeneousPoints(SkScalar dst[], const SkScalar src[], int count) const;
|
||||
|
||||
void mapXY(SkScalar x, SkScalar y, SkPoint* result) const {
|
||||
SkASSERT(result);
|
||||
this->getMapXYProc()(*this, x, y, result);
|
||||
|
@ -1218,7 +1218,7 @@ const SkMatrix::MapPtsProc SkMatrix::gMapPtsProcs[] = {
|
||||
};
|
||||
|
||||
void SkMatrix::mapPoints(SkPoint dst[], const SkPoint src[], int count) const {
|
||||
SkASSERT((dst && src && count > 0) || count == 0);
|
||||
SkASSERT((dst && src && count > 0) || 0 == count);
|
||||
// no partial overlap
|
||||
SkASSERT(src == dst || SkAbs32((int32_t)(src - dst)) >= count);
|
||||
|
||||
@ -1227,6 +1227,42 @@ void SkMatrix::mapPoints(SkPoint dst[], const SkPoint src[], int count) const {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void SkMatrix::mapHomogeneousPoints(SkScalar dst[], const SkScalar src[], int count) const {
|
||||
SkASSERT((dst && src && count > 0) || 0 == count);
|
||||
// no partial overlap
|
||||
SkASSERT(src == dst || SkAbs32((int32_t)(src - dst)) >= 3*count);
|
||||
|
||||
if (count > 0) {
|
||||
if (this->isIdentity()) {
|
||||
memcpy(dst, src, 3*count*sizeof(SkScalar));
|
||||
return;
|
||||
}
|
||||
do {
|
||||
SkScalar sx = src[0];
|
||||
SkScalar sy = src[1];
|
||||
SkScalar sw = src[2];
|
||||
src += 3;
|
||||
|
||||
SkScalar x = SkScalarMul(sx, fMat[kMScaleX]) +
|
||||
SkScalarMul(sy, fMat[kMSkewX]) +
|
||||
SkScalarMul(sw, fMat[kMTransX]);
|
||||
SkScalar y = SkScalarMul(sx, fMat[kMSkewY]) +
|
||||
SkScalarMul(sy, fMat[kMScaleY]) +
|
||||
SkScalarMul(sw, fMat[kMTransY]);
|
||||
SkScalar w = SkScalarMul(sx, fMat[kMPersp0]) +
|
||||
SkScalarMul(sy, fMat[kMPersp1]) +
|
||||
SkScalarMul(sw, fMat[kMPersp2]);
|
||||
|
||||
dst[0] = x;
|
||||
dst[1] = y;
|
||||
dst[2] = w;
|
||||
dst += 3;
|
||||
} while (--count);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void SkMatrix::mapVectors(SkPoint dst[], const SkPoint src[], int count) const {
|
||||
if (this->hasPerspective()) {
|
||||
SkPoint origin;
|
||||
|
@ -592,6 +592,141 @@ static void test_matrix_decomposition(skiatest::Reporter* reporter) {
|
||||
REPORTER_ASSERT(reporter, !SkDecomposeUpper2x2(mat, &rotation0, &scaleX, &scaleY, &rotation1));
|
||||
}
|
||||
|
||||
// For test_matrix_homogeneous, below.
|
||||
static bool scalar_array_nearly_equal_relative(const SkScalar a[], const SkScalar b[], int count) {
|
||||
for (int i = 0; i < count; ++i) {
|
||||
if (!scalar_nearly_equal_relative(a[i], b[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// For test_matrix_homogeneous, below.
|
||||
// Maps a single triple in src using m and compares results to those in dst
|
||||
static bool naive_homogeneous_mapping(const SkMatrix& m, const SkScalar src[3],
|
||||
const SkScalar dst[3]) {
|
||||
SkScalar res[3];
|
||||
res[0] = src[0] * m[0] + src[1] * m[1] + src[2] * m[2];
|
||||
res[1] = src[0] * m[3] + src[1] * m[4] + src[2] * m[5];
|
||||
res[2] = src[0] * m[6] + src[1] * m[7] + src[2] * m[8];
|
||||
return scalar_array_nearly_equal_relative(res, dst, 3);
|
||||
}
|
||||
|
||||
static void test_matrix_homogeneous(skiatest::Reporter* reporter) {
|
||||
SkMatrix mat;
|
||||
|
||||
const float kRotation0 = 15.5f;
|
||||
const float kRotation1 = -50.f;
|
||||
const float kScale0 = 5000.f;
|
||||
|
||||
const int kTripleCount = 1000;
|
||||
const int kMatrixCount = 1000;
|
||||
SkRandom rand;
|
||||
|
||||
SkScalar randTriples[3*kTripleCount];
|
||||
for (int i = 0; i < 3*kTripleCount; ++i) {
|
||||
randTriples[i] = rand.nextRangeF(-3000.f, 3000.f);
|
||||
}
|
||||
|
||||
SkMatrix mats[kMatrixCount];
|
||||
for (int i = 0; i < kMatrixCount; ++i) {
|
||||
for (int j = 0; j < 9; ++j) {
|
||||
mats[i].set(j, rand.nextRangeF(-3000.f, 3000.f));
|
||||
}
|
||||
}
|
||||
|
||||
// identity
|
||||
{
|
||||
mat.reset();
|
||||
SkScalar dst[3*kTripleCount];
|
||||
mat.mapHomogeneousPoints(dst, randTriples, kTripleCount);
|
||||
REPORTER_ASSERT(reporter, scalar_array_nearly_equal_relative(randTriples, dst, kTripleCount*3));
|
||||
}
|
||||
|
||||
// zero matrix
|
||||
{
|
||||
mat.setAll(0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f);
|
||||
SkScalar dst[3*kTripleCount];
|
||||
mat.mapHomogeneousPoints(dst, randTriples, kTripleCount);
|
||||
SkScalar zeros[3] = {0.f, 0.f, 0.f};
|
||||
for (int i = 0; i < kTripleCount; ++i) {
|
||||
REPORTER_ASSERT(reporter, scalar_array_nearly_equal_relative(&dst[i*3], zeros, 3));
|
||||
}
|
||||
}
|
||||
|
||||
// zero point
|
||||
{
|
||||
SkScalar zeros[3] = {0.f, 0.f, 0.f};
|
||||
for (int i = 0; i < kMatrixCount; ++i) {
|
||||
SkScalar dst[3];
|
||||
mats[i].mapHomogeneousPoints(dst, zeros, 1);
|
||||
REPORTER_ASSERT(reporter, scalar_array_nearly_equal_relative(dst, zeros, 3));
|
||||
}
|
||||
}
|
||||
|
||||
// doesn't crash with null dst, src, count == 0
|
||||
{
|
||||
mats[0].mapHomogeneousPoints(NULL, NULL, 0);
|
||||
}
|
||||
|
||||
// uniform scale of point
|
||||
{
|
||||
mat.setScale(kScale0, kScale0);
|
||||
SkScalar dst[3];
|
||||
SkScalar src[3] = {randTriples[0], randTriples[1], 1.f};
|
||||
SkPoint pnt;
|
||||
pnt.set(src[0], src[1]);
|
||||
mat.mapHomogeneousPoints(dst, src, 1);
|
||||
mat.mapPoints(&pnt, &pnt, 1);
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(dst[0], pnt.fX));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(dst[1], pnt.fY));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(dst[2], SK_Scalar1));
|
||||
}
|
||||
|
||||
// rotation of point
|
||||
{
|
||||
mat.setRotate(kRotation0);
|
||||
SkScalar dst[3];
|
||||
SkScalar src[3] = {randTriples[0], randTriples[1], 1.f};
|
||||
SkPoint pnt;
|
||||
pnt.set(src[0], src[1]);
|
||||
mat.mapHomogeneousPoints(dst, src, 1);
|
||||
mat.mapPoints(&pnt, &pnt, 1);
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(dst[0], pnt.fX));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(dst[1], pnt.fY));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(dst[2], SK_Scalar1));
|
||||
}
|
||||
|
||||
// rotation, scale, rotation of point
|
||||
{
|
||||
mat.setRotate(kRotation1);
|
||||
mat.postScale(kScale0, kScale0);
|
||||
mat.postRotate(kRotation0);
|
||||
SkScalar dst[3];
|
||||
SkScalar src[3] = {randTriples[0], randTriples[1], 1.f};
|
||||
SkPoint pnt;
|
||||
pnt.set(src[0], src[1]);
|
||||
mat.mapHomogeneousPoints(dst, src, 1);
|
||||
mat.mapPoints(&pnt, &pnt, 1);
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(dst[0], pnt.fX));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(dst[1], pnt.fY));
|
||||
REPORTER_ASSERT(reporter, SkScalarNearlyEqual(dst[2], SK_Scalar1));
|
||||
}
|
||||
|
||||
// compare with naive approach
|
||||
{
|
||||
for (int i = 0; i < kMatrixCount; ++i) {
|
||||
for (int j = 0; j < kTripleCount; ++j) {
|
||||
SkScalar dst[3];
|
||||
mats[i].mapHomogeneousPoints(dst, &randTriples[j*3], 1);
|
||||
REPORTER_ASSERT(reporter, naive_homogeneous_mapping(mats[i], &randTriples[j*3], dst));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void TestMatrix(skiatest::Reporter* reporter) {
|
||||
SkMatrix mat, inverse, iden1, iden2;
|
||||
|
||||
@ -713,6 +848,7 @@ static void TestMatrix(skiatest::Reporter* reporter) {
|
||||
test_matrix_is_similarity(reporter);
|
||||
test_matrix_recttorect(reporter);
|
||||
test_matrix_decomposition(reporter);
|
||||
test_matrix_homogeneous(reporter);
|
||||
}
|
||||
|
||||
#include "TestClassDef.h"
|
||||
|
Loading…
Reference in New Issue
Block a user