// $Source: /local/data/cvs/yellowbank/tile/qstransform.h,v $
// $Revision: 1.2 $
// $State: Exp $
// $Date: 2004/07/19 03:25:40 $
// $Author: yrp001 $
// $Locker:  $

// symetry tranform

#if !defined(_QSTRANSFORM_H_)
#define _QSTRANSFORM_H_

#include <iostream>
#include <stdint.h>
#include "qtransform.h"
#include "qangle.h"
#include "qpoint.h"
#include "qedge.h"

// symetry transform
class qstransform {
 public:
  // constructors and destructor
  // qstransform();
  virtual ~qstransform() {};

  enum sttype { mirror = 0, rotation = 1, glide = 2, parallelogram = 3 };

  // interface
  virtual int findreal( const qpoint& pi, qpoint* po ) const = 0;

  // common operators

 private:
  // beyond end, return negative interval count
  // before start, return positive
  // on interval, return zero
 protected:
  int interval( double start, double end, double val ) const;
};

#endif

// a line.  one side real, one side reflection
class qstmirror : public qstransform {
 public:
  // constructors and destructor
  qstmirror(); // not implemented.

  //  qstmirror( const qpoint& p1, const qpoint& p2, qedge::side_t s );
  // -1:left 0:on 1:right
  qstmirror( const qpoint& p1, const qpoint& p2, int s );
  qstmirror( const qpoint& point, double angle, int side );

  ~qstmirror() {};

  // interface
  int findreal( const qpoint& pi, qpoint* po ) const;

 private:
  // data
  qedge _line; // mirror line
  int _real; // side of mirror line that is real
  qtransform _mirrort; // mirror transformation on _line
};


class qstpoint : public qstransform {
 public:
  // constructors and destructor
  qstpoint(); // not implemented.

  // 0 <= angle < 2 * PI
  qstpoint( const qpoint& point, float angle, uint32_t sections );
  ~qstpoint() {};

  // interface
  int findreal( const qpoint& pi, qpoint* po ) const;

 private:
  // data
  qpoint _point;
  double _startangle;
  double _includedangle;
};


class qstglide : public qstransform {
 public:
  //  enum mtype { nomirror = 0, mirror = 1 };

  // constructors and destructor
  qstglide(); // not implemented.

  // 0:nomirror 1:mirror
  qstglide( const qpoint& p1, const qpoint& p2, int m );
  qstglide( const qpoint& p1, float angle, float length, int m );

  ~qstglide() {};

  // interface

  int findreal( const qpoint& pi, qpoint* po ) const;

 private:

  // data

  int _ismirror; // mirror glide?
  qtransform _mirrora; // only used if mirror glide

  qedge _e1; // edge containing p1
  double _dd; // displacement distance
  qangle _da; // displacement angle
};


class qsttranslate : public qstransform {
 public:

  // constructors and destructor
  qsttranslate(); // not implemented.

  qsttranslate( const qpoint& displacement ) : _displacement( displacement ) {}
  ~qsttranslate() {};

  // interface
  int findreal( const qpoint& pi, qpoint* po ) const;

 private:
  // data
  qpoint _displacement;
};


class qstrotate : public qstransform {
 public:

  // constructors and destructor
  qstrotate(); // not implemented.

  qstrotate( const qpoint& point, float angle );
  ~qstrotate() {};

  // interface
  int findreal( const qpoint& pi, qpoint* po ) const;

 private:
  // data
  qtransform _rotatet;
};


class qstscale : public qstransform {
 public:

  // constructors and destructor
  qstscale(); // not implemented.

  qstscale( float scale ) : _scale( 1 / scale ) {}
  ~qstscale() {};

  // interface
  int findreal( const qpoint& pi, qpoint* po ) const;

 private:
  // data
  float _scale;
};

