// Micha, Februar/März/Mai 2004

#include "opencvext.h"

namespace seemicro
{

void circular_shift(IplImage *src, IplImage *dst, int dx, int dy)
{
  IplImage *src2;

  if(dx==0 || dy==0)
  {
    std::cerr << "dx or dy ==0: not implemented. skipping circular_shift.\n";
    return;
  }

  if(src==dst) src2=cvCloneImage(src);
  else src2=src;

  if(dx<0) dx = src->width-dx;
  if(dy<0) dy = src->height-dy;

  int splitx = src->width-dx;
  int splity = src->height-dy;

  // 1
  cvSetImageROI(src2, cvRect(0, 0, splitx, splity));
  cvSetImageROI(dst , cvRect(dx, dy, src->width, src->height));
  cvCopy(src2, dst);

  // 2
  cvSetImageROI(src2, cvRect(splitx, 0, src->width, splity));
  cvSetImageROI(dst , cvRect(0, dy, dx, src->height));
  cvCopy(src2, dst);

  // 3
  cvSetImageROI(src2, cvRect(0, splity, splitx, src->height));
  cvSetImageROI(dst , cvRect(dx, 0, src->width, dy));
  cvCopy(src2, dst);

  // 4
  cvSetImageROI(src2, cvRect(splitx, splity, src->width, src->height));
  cvSetImageROI(dst , cvRect(0, 0, dx, dy));
  cvCopy(src2, dst);

  cvResetImageROI(src2);
  cvResetImageROI(dst);
  if(src==dst) cvReleaseImage(&src2);
}

mypoint operator+(const mypoint& p1, const mypoint& p2)
{
  return mypoint(p1.p.x+p2.p.x, p1.p.y+p2.p.y);
}

mypoint operator-(const mypoint& p1, const mypoint& p2)
{
  return mypoint(p1.p.x-p2.p.x, p1.p.y-p2.p.y);
}

std::ostream& operator<<(std::ostream& s, const mypoint& p)
{
  return s << '(' << p.p.x << ' ' << p.p.y << ')';
}

double abs(const mypoint& p)
{
  return sqrt(double(p.p.x*p.p.x+p.p.y*p.p.y));
}

std::ostream& operator<<(std::ostream& s, const myrect& r)
{
  return s << '(' << r.r.x << ' ' << r.r.y << ") "
    << r.r.width << 'x' << r.r.height;
}

} // namespace seemicro

