/* * This file is part of Chalk * * Copyright (c) 2006 Cyrille Berger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_perspective_math.h" #include #if 1 #include #include #include //#define NDEBUG // uncomment to remove checking of assert() #include #define DEFAULT_ALLOC 2 namespace math { // TODO: use eigen template class matrix; template class vector { public: friend class matrix; ElType * data; int len; int length()const; vector(); vector(int n); ~vector(){ delete [] data;} //Copy operator vector(const vector& v) ; //assignment operator vector& operator =(const vector &original); ElType& operator[](int i)const ; void zero(); vector operator+(const vector& v); vector operator-(const vector&v); void rprint()const; //print entries on a single line void resize(int n); int operator==(const vector& v)const; friend vector operator* (ElType c,vector& v ); friend vector operator*(vector& v,ElType c ); friend std::ostream& operator<<(std::ostream& s,vector& v); }; template void vector::zero() { for(int i=0;i int vector::length()const { return len; } template ElType& vector::operator[](int i)const { assert(i>=0 && i < len); return data[i]; } template vector::vector() { data=new ElType[ DEFAULT_ALLOC]; assert(data!=0); len= DEFAULT_ALLOC; } template vector::vector(int n) { data = new ElType[len=n]; assert(data!=0); } template vector::vector(const vector& v) { data=new ElType[len=v.len]; assert(data!=0); for(int i=0;i vector& vector::operator =(const vector &original) { if(this != &original) { delete [] data; data= new ElType[len=original.len]; assert(data!=0); for(int i=0;i vector vector::operator+(const vector& v) { vector sum(len); for(int i=0;i vector vector::operator-(const vector& v) { vector sum(len); for(int i=0;i void vector::rprint()const //print entries on a single line { int i; std::cout << "VECTOR: "; std::cout << "("; for(i=0;i void vector::resize(int n) { delete[]data; data = new ElType[len=n]; assert(data !=0); } template int vector::operator==(const vector& v)const { if(len != v.len) return 0; for(int i=0;i vector operator*(ElType c,vector& v ) { vector ans(v.len); for(int i=0;i vector operator*(vector& v,ElType c ) { vector ans(v.len); for(int i=0;i std::ostream& operator<<(std::ostream& s,vector& v) { s << "("; for(int i=0;i class matrix { public: vector *m; int rows,cols; matrix(); matrix( int r, int c); matrix(const matrix &s); ~matrix(); matrix& operator =(const matrix& s); vector& operator[](const int i); vector operator*(const vector&); friend matrix operator*(const ElType&, const matrix&); friend matrix operator*(const matrix&, const ElType&); matrix operator*(const matrix& a); matrix operator+(const matrix& a); matrix operator-(const matrix& a); matrix transpose(); //matrix inverse(); friend std::ostream& operator<<(std::ostream& s,matrix& m); friend void ludcmp(matrix& a,vector& indx,double &d); friend void lubksb(matrix&a,vector& indx,vector&b); }; template matrix::matrix() { m = new vector[DEFAULT_ALLOC]; assert(m !=0); rows=cols=DEFAULT_ALLOC; for(int i=0;i v; m[i]= v; } } template matrix::matrix(int r, int c) { m= new vector[r]; assert(m != 0); rows=r; cols=c; for(int i=0;i v(cols); m[i]=v; } } template matrix::matrix(const matrix &s) { int i; rows=s.rows; m = new vector[rows]; assert(m!=0); cols =s.cols; for(i=0;i matrix::~matrix() { delete [] m; } template matrix& matrix::operator =(const matrix &s) { if(this != &s) { delete []m; rows= s.rows; cols=s.cols; m = new vector[rows]; assert(m !=0); for(int i=0;i vector& matrix::operator[](const int i) { assert(i>=0 && i < rows); return m[i]; } template vector matrix::operator*(const vector& v) { int i,j; assert(cols == v.len); vector ans(rows); for(i=0;i matrix operator*(const ElType& x,const matrix& s) { matrix ans(s.rows,s.cols); for(int i=0;i matrix matrix::transpose() { matrix ans(cols,rows); for(int i=0;i matrix operator*(const matrix& s,const ElType& x) { matrix ans(s.rows,s.cols); for(int i=0;i matrix matrix ::operator*(const matrix& a) { assert(cols == a.rows); matrix ans(rows,a.cols); for(int i=0;i matrix matrix ::operator+(const matrix & a) { int i,j; assert(rows== a.rows); assert(cols== a.cols); matrix ans(a.rows,a.cols); for(i=0;i matrix matrix::operator-(const matrix& a) { int i,j; assert(rows == a.rows); assert(cols == a.cols); matrix ans(rows,cols); for(i=0;i std::ostream& operator<<(std::ostream& s,matrix& m) { for(int i=0; i void ludcmp(matrix& a, vector& indx,double& d) { int i,imax,j,k; ElType big,dum,sum,temp; int n=a.rows; vector vv(n); assert(a.rows == a.cols); d=1.0; for (i=0;i big) big=temp; /* kdDebug() << temp << " " << fabs(a[i][j]) << " "<< big <= big) { big=dum; imax=i; } } if (j != imax) { for (k=0;k void lubksb(matrix& a,vector& indx,vector& b) { int i,ip,j; ElType sum; int n=a.rows; for (i=0;i=0;i--) { sum=b[i]; for (j=i+1;j a(10,10); math::vector b(10); math::vector indx(10); double d = 0.; for(int i = 0; i <= 9; i++) { for(int j = 0; j <= 9; j++) { a[i][j] = 0.; } b[i] = 0.; indx[i] = 0; } // topLeft a[0][0] = topLeft1.x(); a[0][1] = topLeft1.y(); a[0][2] = 1; a[0][6] = -topLeft2.x() * topLeft1.x(); a[0][7] = -topLeft2.x() * topLeft1.y(); a[0][8] = -topLeft2.x(); a[1][3] = topLeft1.x(); a[1][4] = topLeft1.y(); a[1][5] = 1; a[1][6] = -topLeft2.y() * topLeft1.x(); a[1][7] = -topLeft2.y() * topLeft1.y(); a[1][8] = -topLeft2.y(); // topRight a[2][0] = topRight1.x(); a[2][1] = topRight1.y(); a[2][2] = 1; a[2][6] = -topRight2.x() * topRight1.x(); a[2][7] = -topRight2.x() * topRight1.y(); a[2][8] = -topRight2.x(); a[3][3] = topRight1.x(); a[3][4] = topRight1.y(); a[3][5] = 1; a[3][6] = -topRight2.y() * topRight1.x(); a[3][7] = -topRight2.y() * topRight1.y(); a[3][8] = -topRight2.y(); // bottomLeft1 a[4][0] = bottomLeft1.x(); a[4][1] = bottomLeft1.y(); a[4][2] = 1; a[4][6] = -bottomLeft2.x() * bottomLeft1.x(); a[4][7] = -bottomLeft2.x() * bottomLeft1.y(); a[4][8] = -bottomLeft2.x(); a[5][3] = bottomLeft1.x(); a[5][4] = bottomLeft1.y(); a[5][5] = 1; a[5][6] = -bottomLeft2.y() * bottomLeft1.x(); a[5][7] = -bottomLeft2.y() * bottomLeft1.y(); a[5][8] = -bottomLeft2.y(); // bottomRight a[6][0] = bottomRight1.x(); a[6][1] = bottomRight1.y(); a[6][2] = 1; a[6][6] = -bottomRight2.x() * bottomRight1.x(); a[6][7] = -bottomRight2.x() * bottomRight1.y(); a[6][8] = -bottomRight2.x(); a[7][3] = bottomRight1.x(); a[7][4] = bottomRight1.y(); a[7][5] = 1; a[7][6] = -bottomRight2.y() * bottomRight1.x(); a[7][7] = -bottomRight2.y() * bottomRight1.y(); a[7][8] = -bottomRight2.y(); a[8][8] = 1; b[8] = 1; // kdDebug() << " a := { { " << a[0][0] << " , " << a[0][1] << " , " << a[0][2] << " , " << a[0][3] << " , " << a[0][4] << " , " << a[0][5] << " , " << a[0][6] << " , " << a[0][7] << " , " << a[0][8] << " } , { " << a[1][0] << " , " << a[1][1] << " , " << a[1][2] << " , " << a[1][3] << " , " << a[1][4] << " , " << a[1][5] << " , " << a[1][6] << " , " << a[1][7] << " , " << a[1][8] << " } , { " << a[2][0] << " , " << a[2][1] << " , " << a[2][2] << " , " << a[2][3] << " , " << a[2][4] << " , " << a[2][5] << " , " << a[2][6] << " , " << a[2][7] << " , " << a[2][8] << " } , { " << a[3][0] << " , " << a[3][1] << " , " << a[3][2] << " , " << a[3][3] << " , " << a[3][4] << " , " << a[3][5] << " , " << a[3][6] << " , " << a[3][7] << " , " << a[3][8] << " } , { " << a[4][0] << " , " << a[4][1] << " , " << a[4][2] << " , " << a[4][3] << " , " << a[4][4] << " , " << a[4][5] << " , " << a[4][6] << " , " << a[4][7] << " , " << a[4][8] << " } , { " << a[5][0] << " , " << a[5][1] << " , " << a[5][2] << " , " << a[5][3] << " , " << a[5][4] << " , " << a[5][5] << " , " << a[5][6] << " , " << a[5][7] << " , " << a[5][8] << " } , { " << a[6][0] << " , " << a[6][1] << " , " << a[6][2] << " , " << a[6][3] << " , " << a[6][4] << " , " << a[6][5] << " , " << a[6][6] << " , " << a[6][7] << " , " << a[6][8] << " } , { "<< a[7][0] << " , " << a[7][1] << " , " << a[7][2] << " , " << a[7][3] << " , " << a[7][4] << " , " << a[7][5] << " , " << a[7][6] << " , " << a[7][7] << " , " << a[7][8] << " } , { "<< a[8][0] << " , " << a[8][1] << " , " << a[8][2] << " , " << a[8][3] << " , " << a[8][4] << " , " << a[8][5] << " , " << a[8][6] << " , " << a[8][7] << " , " << a[8][8] << " } }; " << endl; math::ludcmp(a,indx,d); math::lubksb(a,indx,b); for(int i = 0; i < 9; i++) { matrix[i] = b[i]; } return matrix; } double* KisPerspectiveMath::computeMatrixTransfoToPerspective(const KisPoint& topLeft, const KisPoint& topRight, const KisPoint& bottomLeft, const KisPoint& bottomRight, const TQRect& r) { return KisPerspectiveMath::computeMatrixTransfo(topLeft, topRight, bottomLeft, bottomRight, KisPoint(r.topLeft()), KisPoint(r.topRight()), KisPoint(r.bottomLeft()), KisPoint(r.bottomRight())); } double* KisPerspectiveMath::computeMatrixTransfoFromPerspective(const TQRect& r, const KisPoint& topLeft, const KisPoint& topRight, const KisPoint& bottomLeft, const KisPoint& bottomRight) { return KisPerspectiveMath::computeMatrixTransfo(KisPoint(r.topLeft()), KisPoint(r.topRight()), KisPoint(r.bottomLeft()), KisPoint(r.bottomRight()), topLeft, topRight, bottomLeft, bottomRight); }