| 520 | // www.isbe.man.ac.uk/~bim/Mods/app_models.pdf. |
| 521 | |
| 522 | const MAT AlignmentMat( |
| 523 | const Shape& shape, // in |
| 524 | const Shape& anchorshape, // in |
| 525 | const double* weights) // in: if NULL (default) all points equally weighted |
| 526 | { |
| 527 | double W = 0; |
| 528 | double sx = 0, sy = 0, sx1 = 0, sy1 = 0; |
| 529 | double sxx_syy = 0, sxx1_syy1 = 0, sxy1_syx1 = 0; |
| 530 | |
| 531 | for (int i = 0; i < shape.rows; i++) |
| 532 | { |
| 533 | const double x = shape(i, IX); |
| 534 | const double y = shape(i, IY); |
| 535 | const double x1 = anchorshape(i, IX); |
| 536 | const double y1 = anchorshape(i, IY); |
| 537 | if (PointUsed(x, y) && PointUsed(x1, y1)) |
| 538 | { |
| 539 | const double w = (weights? weights[i]: 1.); |
| 540 | W += w; |
| 541 | sx += w * x; |
| 542 | sy += w * y; |
| 543 | sx1 += w * x1; |
| 544 | sy1 += w * y1; |
| 545 | sxy1_syx1 += w * (x * y1 - y * x1); |
| 546 | sxx1_syy1 += w * (x * x1 + y * y1); |
| 547 | sxx_syy += w * (x * x + y * y); |
| 548 | } |
| 549 | } |
| 550 | MAT soln_data = (MAT(4,4) << sxx_syy, 0, sx, sy, |
| 551 | 0, sxx_syy, -sy, sx, |
| 552 | sx, -sy, W, 0, |
| 553 | sy, sx, 0, W ); |
| 554 | |
| 555 | VEC vec_data = (MAT(4,1) << sxx1_syy1, |
| 556 | sxy1_syx1, |
| 557 | sx1, |
| 558 | sy1 ); |
| 559 | |
| 560 | const VEC soln(LinSolveLu(soln_data, vec_data)); |
| 561 | |
| 562 | return (MAT(3, 3) << soln(0), -soln(1), soln(2), // a -b tx |
| 563 | soln(1), soln(0), soln(3), // b a ty |
| 564 | 0, 0, 1 ); // 0 0 1 |
| 565 | } |
| 566 | |
| 567 | Shape ShiftShape( // add xshift and yshift to shape coords, skipping unused points |
| 568 | const Shape& shape, // in |
no test coverage detected