src/warpcoord.h

00001 /* This file is part of WarpTree
00002  *
00003  * Copyright (C) 2007 Jos van den Oever <jos@vandenoever.info>
00004  *               2001 Christophe Bouthier <christ.bouthier@free.fr>
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Library General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Library General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Library General Public License
00017  * along with this library; see the file COPYING.LIB.  If not, write to
00018  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00019  * Boston, MA 02110-1301, USA.
00020  */
00021 
00022 /*
00023    The functions
00024     void translate(const WarpCoord& t)
00025     void transform(const WarpCoord& c1, const WarpCoord& c2)
00026    contain code adapted from the program HyperTree by Christophe Bouthier and
00027    are used with permission.
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 /* This class provides the methods to handle the points in the graph.
00039  * It allows points to be translated in the unit square.
00040  */
00041 
00042 #define ZONE_LENGTH 4 // size of the zone
00043 
00044 // if WARPCOORD is not defined, the standard Poincare disk projection is used
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     /* the value for d is cached in this class. This function updates the
00056        value */
00057     inline void updateD() {
00058         md = sqrt(d2());
00059     }
00060     /* multiply this point with point z */
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     /* divide this point by point z */
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     /* calculate the arg of this point */
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     /* translate this point by adding the vector t */
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     /* zoom this point. this means the point move closer to or away from the
00110        center of the square */
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     /* move this point from the disk positiong to the square position */
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     /* move this point from the square position to the disk position */
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     /* is this point visible, in other words, is it not too close to the edge
00160        of the unit square */
00161     inline bool visible() const {
00162         return mx > -0.95 && mx < 0.95 && my > -0.95 && my < 0.95;
00163     }
00164     /* is this point valid, in other words, does it lie inside the unit
00165        square */
00166     inline bool valid() const {
00167         return mx > -1 && mx < 1 && my > -1 && my < 1;
00168     }
00169     /* return the negative value of this point */
00170     inline WarpCoord operator-() const {
00171         return WarpCoord(-mx, -my);
00172     }
00173     /* substract the value of point e from this point. Note that this is not
00174        equal to translation. */
00175     inline void operator-=(const WarpCoord& e) {
00176         mx -= e.mx;
00177         my -= e.my;
00178         updateD();
00179     }
00180     /* apply the translation that is needed to get from point c1 to c2 to this
00181        point */
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     /* change the value of this point */
00209     inline void set(double x, double y) {
00210         mx = x;
00211         my = y;
00212         updateD();
00213     }
00214 };
00215 
00216 #endif 

Generated on Sun Jun 3 19:54:02 2007 for WarpTree by  doxygen 1.5.0