// Listing 11.1. Przekształcenie afiniczne
// Mapuje trzy punkty (0, 0), (0, height-1), (width-1, 0) określone w srcTri[] na
// wyznaczone punkty w tablicy dstTri za pomocą obliczonego przekształcenia afinicznego. 
#include <opencv2/opencv.hpp>
#include <iostream>

using namespace std;

int main(int argc, char** argv) {

  if(argc != 2) {
    cout << "Przekształcenie afiniczne\nSposób użycia: " <<argv[0] <<" <imagename>\n" << endl;
    return -1;
  }

  cv::Mat src = cv::imread(argv[1],1);
  if( src.empty() ) { cout << "Nie udało się załadować " << argv[1] << endl; return -1; }

  cv::Point3f srcTri[] = {
	  cv::Point2f(0,0),           // źródło, lewy górny
	  cv::Point2f(src.cols - 1, 0), // źródło, prawy górny
	  cv::Point2f(0, src.rows - 1)  // źródło, lewy dolny
  };

  cv::Point2f dstTri[] = {
	  cv::Point2f(src.cols*0.f, src.rows*0.33f),   // cel, lewy górny
	  cv::Point2f(src.cols*0.85f, src.rows*0.25f), // cel, prawy górny
	  cv::Point2f(src.cols*0.15f, src.rows*0.7f)   // cel, lewy dolny
  };

  // OBLICZANIE 
  //
  cv::Mat warp_mat = cv::getAffineTransform(srcTri, dstTri);
  cv::Mat dst, dst2;
  cv::warpAffine(
    src,
    dst,
    warp_mat,
    src.size(),
    cv::INTER_LINEAR,
    cv::BORDER_CONSTANT,
    cv::Scalar()
  );
  for( int i = 0; i < 3; ++i )
    cv::circle(dst, dstTri[i], 5, cv::Scalar(255, 0, 255), -1, cv::LINE_AA);

  cv::imshow("Test przekształcenia afinicznego", dst);
  cv::waitKey();

  for(int frame=0;;++frame) {

	  // OBLICZANIE MACIERZY ROTACJI
    cv::Point2f center(src.cols*0.5f, src.rows*0.5f);
    double angle = frame*3 % 360, scale = (cos((angle - 60)* CV_PI/180) + 1.05)*0.8;

    cv::Mat rot_mat = cv::getRotationMatrix2D(center, angle, scale);

    cv::warpAffine(
      src,
      dst,
      rot_mat,
      src.size(),
      cv::INTER_LINEAR,
      cv::BORDER_CONSTANT,
      cv::Scalar()
    );
    cv::imshow("Obrócony obraz", dst);
    if(cv::waitKey(30) >= 0 )
      break;

  }

  return 0;
}
