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