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 
00029 
00030 #ifndef WARPTREE_H
00031 #define WARPTREE_H
00032 
00033 #include <iostream>
00034 #include <cmath>
00035 #include <cassert>
00036 #include <cstdlib>
00037 
00038 
00039 
00040 
00041 
00042 #define ZONE_LENGTH 4 // size of the zone
00043 
00044 
00045 #define WARPCOORD
00046 
00047 class WarpCoord;
00048 std::ostream& operator<<(std::ostream& o, const WarpCoord& e);
00049 class WarpCoord {
00050 private:
00051     double mx;
00052     double my;
00053     double md;
00054 
00055     
00056 
00057     inline void updateD() {
00058         md = sqrt(d2());
00059     }
00060     
00061     void
00062     operator*=(const WarpCoord& z) {
00063         double tx = mx;
00064         mx = tx*z.mx - my * z.my;
00065         my = tx*z.my + my * z.mx;
00066         updateD();
00067     }
00068     
00069     void
00070     operator/=(const WarpCoord& z) {
00071         double d2 = z.d2();
00072         double tx = mx;
00073         mx = (tx*z.mx + my*z.my) / d2;
00074         my = (my*z.mx - tx*z.my) / d2;
00075         updateD();
00076     }
00077 public:
00078     WarpCoord() :mx(0), my(0), md(0) {}
00079     WarpCoord(double x, double y) :mx(x), my(y) {
00080         updateD();
00081     }
00082     inline double x() const { return mx; }
00083     inline double y() const { return my; }
00084     inline double d() const { return md; }
00085     inline double d2() const { return mx*mx + my*my; }
00086     
00087     double arg() const {
00088         double a = atan(my / mx);
00089         if (mx < 0) {
00090             a += M_PI;
00091         } else if (my < 0) {
00092             a += 2 * M_PI;
00093         }
00094         return a;
00095     }
00096     
00097     void translate(const WarpCoord& t) {
00098         double denX = mx * t.mx + my * t.my + 1;
00099         double denY = my * t.mx - mx * t.my;
00100         double dd = denX * denX + denY * denY;
00101 
00102         double numX = mx + t.mx;
00103         double numY = my + t.my;
00104 
00105         mx = (numX * denX + numY * denY) / dd;
00106         my = (numY * denX - numX * denY) / dd;
00107         updateD();
00108     }
00109     
00110 
00111     void zoom(double f) {
00112         assert(f > 0);
00113         if (md < 0.001) return;
00114         double r = md;
00115         double c = pow((1+md)/(1-md),f);
00116         c = (c-1)/(c+1)/r;
00117         mx *= c;
00118         my *= c;
00119         md *= c;
00120     }
00121     
00122     void stretch() {
00123         if (md < 0.0001) return;
00124 #ifdef WARPCOORD
00125         double fx = fabs(mx);
00126         double fy = fabs(my);
00127         if (fy > 0 && fy > fx) {
00128             double f = md/fy;
00129             my = (my>0) ?md :-md;
00130             mx *= f;
00131             md *= f;
00132         } else if (fx > 0) {
00133             double f = md/fx;
00134             mx = (mx>0) ?md :-md;
00135             my *= f;
00136             md *= f;
00137         }
00138 #endif
00139     }
00140     
00141     void unstretch() {
00142         assert(md >= 0);
00143         if (md < 0.0001) return;
00144 #ifdef WARPCOORD
00145         double f = 1;
00146         double fx = fabs(mx);
00147         double fy = fabs(my);
00148         if (fy > 0 && fy > fx) {
00149             f = md/fy;
00150             md = (my>0) ?my :-my;
00151         } else if (fx > 0) {
00152             f = md/fx;
00153             md = (mx>0) ?mx :-mx;
00154         }
00155         mx /= f;
00156         my /= f;
00157 #endif
00158     }
00159     
00160 
00161     inline bool visible() const {
00162         return mx > -0.95 && mx < 0.95 && my > -0.95 && my < 0.95;
00163     }
00164     
00165 
00166     inline bool valid() const {
00167         return mx > -1 && mx < 1 && my > -1 && my < 1;
00168     }
00169     
00170     inline WarpCoord operator-() const {
00171         return WarpCoord(-mx, -my);
00172     }
00173     
00174 
00175     inline void operator-=(const WarpCoord& e) {
00176         mx -= e.mx;
00177         my -= e.my;
00178         updateD();
00179     }
00180     
00181 
00182     void transform(const WarpCoord& c1, const WarpCoord& c2) {
00183         WarpCoord p(c1.mx + c2.mx, c1.my + c2.my);
00184 
00185         WarpCoord d(c2.mx, -c2.my);
00186         d *= c1;
00187         d.mx += 1;
00188         p /= d;
00189 
00190         WarpCoord o(c1.mx, -c1.my);
00191         o *= c2;
00192         o.mx += 1;
00193         o /= d;
00194 
00195         WarpCoord z(*this);
00196         *this *= o;
00197         mx += p.mx;
00198         my += p.my;
00199 
00200         d.set(p.mx, -p.my);
00201         d *= z;
00202         d *= o;
00203         d.mx += 1;
00204 
00205         *this /= d;
00206         updateD();
00207     }
00208     
00209     inline void set(double x, double y) {
00210         mx = x;
00211         my = y;
00212         updateD();
00213     }
00214 };
00215 
00216 #endif