jlouthan / perspective-transform

A small JavaScript library for creating and applying perspective transforms
MIT License
182 stars 29 forks source link

Confusing results #5

Open sebastian-raubach opened 4 years ago

sebastian-raubach commented 4 years ago

I'm trying to use this library, but I get weird results that I can't really explain.

Using this code below:

   const srcCorners = [
      491218.662528078, 6259800.43254993,
      491664.008009023, 6259799.53201322,
      491606.373219169, 6260054.09226945,
      491240.25960665, 6260028.56590027
    ]
    const dstCorners = [
      0, 0,
      100, 0,
      100, 100,
      0, 100
    ]
    const perspT = PerspT(srcCorners, dstCorners)
    console.log(perspT.transform(491438.780488201, 6259922.52984722))

Which when plotted looks like this: 2020-08-24 10_16_57-Book1 - Excel

I've got four corner points and a query point right in the center. I'm mapping this to a rectangle spanning (0,0) to (100, 100). When I run this code, though, I get [-144.37178139160187, -125.00368410330502], whereas it should be around [54.644979834216294, 45.89394897084863].

Am I doing something wrong here?

arifhussain353 commented 3 years ago

@jlouthan Is it possible that we use more than 8 source or destination points to transform?

stevage commented 1 year ago

@sebastian-raubach Yeah, I have spent a while testing, and I think there's something pretty wrong.

My testing was basically attempting to map a point in the middle of 4 points to the same 4 points - it should end up at the exact same location. But for many sets of numbers, it doesn't.

I don't have a clear pattern for when it goes wrong. But posting some of my testing code here in case it's useful to someone.

const middle = (corners) => [
    (corners[0] + corners[2] + corners[4] + corners[6]) / 4,
    (corners[1] + corners[3] + corners[5] + corners[7]) / 4,
];
const clean = (corners) => corners.map((x) => x.toFixed(1)).join(',');
function run(src, dest, pt) {
    var perspT = PerspT(src, dest);
    var dstPt = perspT.transform(pt[0], pt[1]);
    return dstPt;
}

const check = (a, b) => clean(a) === clean(b);
const test = (corners) => {
    const out = run(corners, corners, middle(corners));
    const src = middle(corners);
    console.log(
        !check(src, out) ? 'ERROR' : 'ok',
        clean(src),
        ' => ',
        clean(out)
    );
};

const boxTest = (west, south, east, north) =>
    test([west, south, east, south, east, north, west, north]);

const ccwBoxTest = (west, south, east, north) =>
    test([west, north, east, north, east, south, west, south]);

const s = [115.99, -31.88, 116.01, -31.88, 116.01, -31.86, 115.99, -31.86];
test(s); // bad
test(s.map((x) => -x)); // bad
test([115.99, 31.88, 116.01, 31.88, 116.01, 31.86, 115.99, 31.86]); //bad
test([115.99, 40, 116.01, 40, 116.01, 31.86, 115.99, 31.86]); //ok
boxTest(116, 40, 117, 31); //ok
boxTest(115.99, 40, 116.01, 31.86); //ok
boxTest(115.99, 30, 116.01, 31.86); //ok-ish
boxTest(116, 30, 117, 40); //ok
ccwBoxTest(116, 40, 117, 31); //ok
ccwBoxTest(115.99, 40, 116.01, 31.86); //ok
ccwBoxTest(115.99, 30, 116.01, 31.86); //ok
ccwBoxTest(116, 30, 117, 40); //ok
test([115.99, 31.88, 116.01, 31.88, 116.01, 31.86, 115.99, 31.86]); //bad CW
test([115.99, 31.88, 116.01, 31.88, 116.01, 32.86, 115.99, 32.86]); //ok CCW
test([115.99, 31.88, 116.01, 31.88, 116.01, 31.86, 115.99, 31.86]); //bad CCW

test([115, 31.88, 116, 31.88, 116, 31.86, 115, 31.86]); //ok-ish CW

boxTest(115.99, 31.88, 116.01, 31.86); //bad
ccwBoxTest(115.99, 31.88, 116.01, 31.86); // medium bad