// $Source: /local/data/cvs/yellowbank/tile/qstransform.cc,v $
// $Revision: 1.1.1.1 $
// $State: Exp $
// $Date: 2002/12/23 19:53:24 $
// $Author: yrp001 $
// $Locker:  $

#include "qstransform.h"

int
qstransform::
interval( double start, double end, double val ) const {
  double ilen = end - start;
  double len;
  if( val < start ) {
    len = start - val;
    return (int)((len / ilen) + 1);
  } else if ( val > end ) {
    len = val - end;
    return -(int)((len / ilen) + 1);
  }
  return 0;
}

qstmirror::
qstmirror( const qpoint& p1, const qpoint& p2, int s )
  : qstransform(),
    _line( p1, p2 ),
    _real( s )
{
  _mirrort.mirror( p1, p2 );
}

qstmirror::
qstmirror( const qpoint& point, double angle, int side )
  : qstransform(),
    _line( point, angle ),
    _real( side )
{
  _mirrort.mirror( point, angle );
}

int
qstmirror::
findreal( const qpoint& pi, qpoint* po ) const {
  int side = _line.side( pi );
  if( side == _real ) {
    *po = pi;
    return 0;
  }
  *po = _mirrort * pi;
  return 1;
}

qstpoint::
qstpoint( const qpoint& point, float angle, uint32_t sections )
  : qstransform(),
    _point( point ),
    _startangle( fmod( angle, M_PI * 2) ),
    _includedangle( (M_PI * 2) / sections )
{
  _startangle -= _includedangle / 2;
  if( _startangle < 0 )
    _startangle += M_PI * 2;
}

int
qstpoint::
findreal( const qpoint& pi, qpoint* po ) const {
  qpoint pt = pi - _point;
  double a = pt.anglef();
  a -= _startangle;
  if( a < 0 )
    a += (M_PI * 2.0);
  int n = interval( 0, _includedangle, a );
  a = n * _includedangle;
  qtransform t;
  t.rotate( _point, a );
  *po = t * pi;
  return n;
}

qstglide::
qstglide( const qpoint& p1, const qpoint& p2, int m )
  : qstransform(),
    _ismirror( m )
{
  if ( _ismirror != 0 )
    _mirrora.mirror( p1, p2 );

  qpoint pt;

  pt = p2;
  pt.rotate90ccw( p1 );
  _e1 = qedge( p1, pt );

  pt = p2 - p1;
  _dd = pt.length();
  _da = pt.angle();
}

qstglide::
qstglide( const qpoint& p1, float angle, float length, int m )
  : _ismirror( m ),
    _dd( length ),
    _da( angle )
{
  if( _ismirror != 0 )
    _mirrora.mirror( p1, angle );
  qpoint p2( p1, angle, length );
  _e1 = qedge( p1, p2 );
}

int
qstglide::
findreal( const qpoint& pi, qpoint* po ) const {

  qpoint ptemp;
  float r = _e1.projection( pi, &ptemp );

  // this could be more efficient because projection
  // is being called twice.
  float d = _e1.distance( pi ); // negative if left of _e1
  int n = interval( 0, _dd, d );

  d = n * _dd;

  qpoint origin( 0, 0 );
  qpoint dp( origin, _da.valrad(), d );

  *po = pi + dp;

  if( _ismirror && (n % 2) != 0 )
    *po = _mirrora * *po;
  if( _ismirror && (r > 0) )
    n += 1;

  return n;
}

int
qsttranslate::
findreal( const qpoint& pi, qpoint* po ) const {
  *po = pi - _displacement;
  return 0;
}

qstrotate::
qstrotate( const qpoint& point, float angle ) {
  _rotatet.rotate( point, angle );
}

int
qstrotate::
findreal( const qpoint& pi, qpoint* po ) const {
  *po = _rotatet * pi;
  return 0;
}

int
qstscale::
findreal( const qpoint& pi, qpoint* po ) const {
  po->setx( pi.getx() * _scale );
  po->sety( pi.gety() * _scale );
  return 0;
}

