src/tools/tCoord.h

Go to the documentation of this file.
00001 /*
00002 
00003 *************************************************************************
00004 
00005 ArmageTron -- Just another Tron Lightcycle Game in 3D.
00006 Copyright (C) 2000  Manuel Moos (manuel@moosnet.de)
00007 
00008 **************************************************************************
00009 
00010 This program is free software; you can redistribute it and/or
00011 modify it under the terms of the GNU General Public License
00012 as published by the Free Software Foundation; either version 2
00013 of the License, or (at your option) any later version.
00014 
00015 This program is distributed in the hope that it will be useful,
00016 but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 GNU General Public License for more details.
00019 
00020 You should have received a copy of the GNU General Public License
00021 along with this program; if not, write to the Free Software
00022 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00023   
00024 ***************************************************************************
00025 
00026 */
00027 
00028 #ifndef ArmageTron_tCOORD_H
00029 #define ArmageTron_tCOORD_H
00030 
00031 //#include <iostream>
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     // Calculations:
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             //check for 90 degree angles...
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             //check for opposite sides
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     // I/O:
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     // find the point that's closest to the bottom, preferring points to the left
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     //std::cerr << "P: " << P << std::endl;
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; //all points equeal P, kinda boring...
00188 
00189     //std::copy(in.begin(), in.end(), std::ostream_iterator<tCoord>(std::cerr, " "));
00190     //std::cerr << std::endl;
00191     for(typename T::iterator iter = in.begin(); iter != in.end(); ++iter) {
00192         //std::cerr << "New point: " << *iter << "; angle=" << (atanf(Tangent(P, *iter))*180/M_PI) << std::endl;
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; //duplicate or near- duplicate point; We don't want that mess.
00198         //std::cerr << "New point: " << *iter << "; angle=" << Tangent(P, *iter) << std::endl;
00199         //if(iter->y > 200) std::cerr << "==================\n";
00200         float product = CrossProduct(out[out.size()-2], out.back(), *iter);
00201         if (product < 0 || fabs(product) < EPS) {
00202             //the last three points are concave, remove points until they're not
00203             while((product < 0 || fabs(product) < EPS) && out.size() > 2) {
00204                 //std::cerr << "concave: " << *(iter-2) << " " << *(iter-1) << " " << *iter << std::endl;
00205                 //std::copy(out.begin(), out.end(), std::ostream_iterator<tCoord>(std::cerr, " "));
00206                 //std::cerr << std::endl;
00207                 out.pop_back();
00208                 product = CrossProduct(out[out.size()-2], out.back(), *iter);
00209             }
00210         } else {
00211             //std::cerr << "Passed point: " << *iter << std::endl;
00212         }
00213         out.push_back(*iter);
00214         //std::copy(out.begin(), out.end(), std::ostream_iterator<tCoord>(std::cerr, " "));
00215         //std::cerr << std::endl;
00216     }
00217     float product = CrossProduct(out[out.size()-2], out.back(), P);
00218     while((product < 0 || fabs(product) < EPS) && out.size() > 2) {
00219         //std::cerr << "concave: " << *(iter-2) << " " << *(iter-1) << " " << *iter << std::endl;
00220         //std::copy(out.begin(), out.end(), std::ostream_iterator<tCoord>(std::cerr, " "));
00221         //std::cerr << std::endl;
00222         out.pop_back();
00223         product = CrossProduct(out[out.size()-2], out.back(), P);
00224     }
00225     //std::cerr << "=====\n";
00226     //for(typename T::iterator iter = out.begin(); iter != out.end(); ++iter) {
00227     //  std::cerr << *iter << std::endl;
00228     //}
00229 
00230 }
00231 
00233 extern const tCoord se_zeroCoord;
00234 #endif

Generated on Sat Mar 15 22:55:59 2008 for Armagetron Advanced by  doxygen 1.5.4