
#include "randn.h"
#include <string>
#include <vector>
#include <cmath>
#include "mystr.h"

#ifndef MYMATH_H_INCLUDED
#define MYMATH_H_INCLUDED

#define	DEGTORAD			0.01745329251994329577f






class Vec2D {
public:
   float x, y;


   // CONSTRUCTORS //

   Vec2D( float x = 0.0, float y = 0.0 )
      : x( x ), y( y ) {}


   static inline Vec2D PolarCoords( float angle, float magnitude ) {
      return Vec2D( magnitude * std::cos( angle ), magnitude * std::sin( angle ));
   }


   // METHODS //

   inline float GetAngle() const {
      return std::atan2( y, x );
   }


   inline float GetMagnitude() const {
      return std::sqrt( GetMagnitudeSquared() );
   }


   inline float GetMagnitudeSquared() const {
      return x * x + y * y;
   }


   inline Vec2D Normalized() const {
      float magnitude = GetMagnitude();

      return Vec2D( x / magnitude, y / magnitude );
   }


   // OPERATORS //


   inline void operator += ( const Vec2D &other ) {
      x += other.x; y += other.y;
   }

   inline void operator -= ( const Vec2D &other ) {
      x -= other.x; y -= other.y;
   }


   inline void operator *= ( float factor ) {
      x *= factor; y *= factor;
   }


   inline void operator /= ( float divisor ) {
      x /= divisor; y /= divisor;
   }


   inline std::string GetString() const {
      return "( " + ToString( x ) + ", " + ToString( y ) + " )";
   }
};


// ADDITION AND SUBTRACTION //

inline Vec2D operator + ( Vec2D first, Vec2D second ) {
   return Vec2D( first.x + second.x, first.y + second.y );
}


inline Vec2D operator - ( Vec2D first, Vec2D second ) {
   return Vec2D( first.x - second.x, first.y - second.y );
}


// MULTIPLICATION AND DIVISION

inline Vec2D operator * ( Vec2D vec, float factor ) {
   return Vec2D( factor * vec.x, factor * vec.y );
}


inline Vec2D operator * ( float factor, Vec2D vec ) {
   return Vec2D( factor * vec.x, factor * vec.y );
}


inline Vec2D operator / ( Vec2D vec, float divisor ) {
   return Vec2D( vec.x / divisor, vec.y / divisor );
}


// DOT PRODUCT //

inline float operator * ( Vec2D first, Vec2D second ) {
   return first.x * second.x + first.y * second.y;
}


// SIGN //

inline Vec2D operator - ( Vec2D vec ) {
   return Vec2D( -vec.x, -vec.y );
}


// NORMALIZATION

inline Vec2D operator ~ ( Vec2D vec ) {
   return vec.Normalized();
}


// TESTS


// Checks if the points are in counter clockwise order //

inline bool IsCounterClockwise( const Vec2D first, const Vec2D second, const Vec2D third ) {
  float dx1, dx2, dy1, dy2;

  dx1 = second.x - first.x;
  dy1 = second.y - first.y;
  dx2 = third.x - second.x;
  dy2 = third.y - second.y;

  return dy1*dx2 < dy2*dx1;
}



class HashDataString {
  public:
    std::string id;
    void *value;
    HashDataString(std::string i, void *v) {
      id = i;
      value = v;
    }
    bool Compare(std::string d) {
      if (id == d) return true;
      return false;
    }
    void *GetValue() {return value;}
    std::string GetIdentifier() {return id;}
    ~HashDataString() {
      id.clear();
    }
};


class HashString {
  public:
    std::vector<HashDataString> list;
    HashString() {
      list.clear();
    }
    void push_back(std::string i, void *v) {
      list.push_back(HashDataString(i, v));
    }
    void *get(std::string i) {
      std::vector<HashDataString>::iterator it;
      for (it=list.begin(); it!=list.end(); it+=1) {
        if ((*it).Compare(i)) return (*it).GetValue();
      }
      return NULL;
    }
    HashDataString *get_data(int i) {
      return &(list[i]);
    }
    void clear() {
      list.clear();
    }
    ~HashString() {
      list.clear();
    }
    int size() {
      return list.size();
    }
};


class Intermitent {
  protected:
    float l, r;
    bool d;
    float s;
  public:
    Intermitent(float rg, float sp){l=0;r=rg;d=false;s=sp;}
    void update() {
      if (d) {
        l += s;
        if (l > r) d = false;
      }
      else {
        l -= s;
        if (l < -r) d = true;
      }
    }
    float get_l(){return l;}
    float get_r(){return r;}
};


float FixRadAngle(float v);

bool inside_rect(float a, float b, float x, float y, float fx, float fy);
float AngleToRad(float a);
float RadToAngle(float a);

float RSX(float v);
float RSY(float v);
float RSW(float v);
float RSH(float v);
float SRW(float v);
float SRH(float v);
float SRX(float v);
float SRY(float v);
float BSX(float v);
float BSY(float v);

extern float GlobalAspectRatio;
extern float GlobalZoom;

Vec2D Perpendicular(Vec2D v);

float mabs(float v);
int sgn(float v);

float distance_between_points(float x, float y, float tx, float ty);

const float SnapBehavior=0.06;

int ToInteger(char *str);
float ToFloat(std::string n);

void UpdateGlobalZoomFactor();

#endif
