00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifndef ArmageTron_tCOORD_H
00029 #define ArmageTron_tCOORD_H
00030
00031
00032 #include "defs.h"
00033 #include "tError.h"
00034 #include <iterator>
00035 #include <algorithm>
00036 #include <map>
00037 #include <vector>
00038
00040 class tCoord{
00041 public:
00042 REAL x,y;
00043 explicit tCoord(REAL X=0,REAL Y=0):x(X),y(Y){};
00044
00045
00046 inline bool operator==(const tCoord &a) const;
00047 bool operator!=(const tCoord &a) const{return !operator==(a);}
00048 tCoord operator-(const tCoord &a) const{return tCoord(x-a.x,y-a.y);}
00049 tCoord operator-() const{return tCoord(-x,-y);}
00050 tCoord operator+(const tCoord &a) const{return tCoord(x+a.x,y+a.y);}
00051 const tCoord& operator+=(tCoord const &other) { x+=other.x; y+=other.y; return *this;}
00052 const tCoord& operator-=(tCoord const &other) { x-=other.x; y-=other.y; return *this;}
00053 tCoord operator*(REAL a) const {return tCoord(x*a,y*a);}
00054 const tCoord& operator*=(REAL a) { x*=a; y*=a; return *this;}
00055 const tCoord& operator*=(tCoord const &other) { x*=other.x; y*=other.y; return *this;}
00056 REAL NormSquared() const {return x*x+y*y;}
00057 REAL Norm() const {return sqrt(NormSquared());}
00058 void Normalize() { *this *= 1/Norm(); }
00059 const tCoord &operator=(const tCoord &a){ x=a.x;y=a.y; return *this; }
00060
00062 static REAL F(const tCoord &a,const tCoord &b){
00063 return(a.x*b.x+a.y*b.y);
00064 }
00065
00068 static REAL V(const tCoord &a,const tCoord &b,const tCoord &c){
00069 tCoord ab=b-a;
00070 tCoord ac=c-a;
00071 return(F(ab,ac)/F(ac,ac));
00072 }
00073
00075 static REAL CrossProduct(tCoord const &a, tCoord const &b, tCoord const &c) {
00076 return (b.x - a.x)*(c.y - a.y) - (c.x - a.x)*(b.y - a.y);
00077 }
00078
00080 static REAL Tangent(tCoord const &a, tCoord const &b) {
00081 return (b.y - a.y)/(b.x-a.x);
00082 }
00083
00084 private:
00085 class GrahamComparator {
00086 tCoord const &m_reference;
00087 public:
00088 GrahamComparator(tCoord const &reference) : m_reference(reference) {}
00089 bool operator()(tCoord const &a, tCoord const &b) {
00090 REAL ta = Tangent(m_reference, a), tb = Tangent(m_reference, b);
00091
00092
00093 if(ta == NAN && tb == NAN) return fabs((m_reference-a).NormSquared()) < fabs((m_reference-b).NormSquared());
00094 if(ta == NAN) return tb<0;
00095 if(tb == NAN) return ta>0;
00096
00097
00098 if(ta>0 && tb<0) return true;
00099 if(tb>0 && ta<0) return false;
00100
00101 return (ta<tb-EPS) || ((fabs(ta-tb)<EPS) && fabs((m_reference-a).NormSquared()) < fabs((m_reference-b).NormSquared()));
00102 }
00103 };
00104 public:
00105
00107 template<typename T> static void GrahamScan(T &in, T &out);
00108
00112 REAL operator*(const tCoord &a) const{return -x*a.y+y*a.x;}
00113
00114
00116 tCoord Turn(const tCoord &a) const{return tCoord(x*a.x-y*a.y,y*a.x+x*a.y);}
00118 tCoord Turn(REAL x,REAL y) const{return Turn(tCoord(x,y));}
00120 tCoord Conj() const{return tCoord(x,-y);}
00121
00122
00123 void Print(std::ostream &s) const;
00124 void Read(std::istream &s);
00125 };
00126
00129 REAL se_EstimatedRangeOfMult(const tCoord &a,const tCoord &b);
00130
00132 REAL st_GetDifference( const tCoord & a, const tCoord & b );
00133
00136 inline bool tCoord::operator==(const tCoord &a) const{
00137 return ((*this-a).NormSquared()<=(EPS*EPS)*se_EstimatedRangeOfMult(*this,a));
00138 }
00139
00143 inline std::ostream &operator<< (std::ostream &s,const tCoord &c){
00144 c.Print(s);
00145 return s;
00146 }
00147
00151 inline std::istream &operator>> (std::istream &s,tCoord &c){
00152 c.Read(s);
00153 return s;
00154 }
00155
00157 inline tCoord operator*(REAL a, tCoord const &c) {
00158 return c*a;
00159 }
00160
00163 template<typename T> void tCoord::GrahamScan(T &in, T &out) {
00164 tASSERT(!in.empty());
00165 out.clear();
00166
00167
00168 tCoord P=in.front();
00169 typename T::iterator iter(in.begin()+1);
00170 for(; iter != in.end(); ++iter) {
00171 if(iter->y < P.y || iter->y == P.y && iter->x < P.x) {
00172 P = *iter;
00173 }
00174 }
00175
00176 std::sort(in.begin(), in.end(), GrahamComparator(P));
00177
00178
00179
00180 out.push_back(P);
00181 for(typename T::iterator iter = in.begin()+1; iter != in.end(); ++iter) {
00182 if(*iter != P) {
00183 out.push_back(*iter);
00184 break;
00185 }
00186 }
00187 if(out.size()<2) return;
00188
00189
00190
00191 for(typename T::iterator iter = in.begin(); iter != in.end(); ++iter) {
00192
00193 }
00194
00195 for(typename T::iterator iter = in.begin()+2; iter != in.end(); ++iter) {
00196 if(*iter == P) continue;
00197 if(*iter == *(iter - 1)) continue;
00198
00199
00200 float product = CrossProduct(out[out.size()-2], out.back(), *iter);
00201 if (product < 0 || fabs(product) < EPS) {
00202
00203 while((product < 0 || fabs(product) < EPS) && out.size() > 2) {
00204
00205
00206
00207 out.pop_back();
00208 product = CrossProduct(out[out.size()-2], out.back(), *iter);
00209 }
00210 } else {
00211
00212 }
00213 out.push_back(*iter);
00214
00215
00216 }
00217 float product = CrossProduct(out[out.size()-2], out.back(), P);
00218 while((product < 0 || fabs(product) < EPS) && out.size() > 2) {
00219
00220
00221
00222 out.pop_back();
00223 product = CrossProduct(out[out.size()-2], out.back(), P);
00224 }
00225
00226
00227
00228
00229
00230 }
00231
00233 extern const tCoord se_zeroCoord;
00234 #endif