00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "config.h"
00018 #include "TorMapImageView.h"
00019
00020 #include <QStringList>
00021
00022 #if defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION >= 730
00023 #include <math.h>
00024 #else
00025 #include <cmath>
00026 #endif
00027
00028 #define IMG_WORLD_MAP ":/images/map/world-map.png"
00029
00030
00031 #define PEN_ROUTER QPen(QColor("#ff030d"), 1.0)
00032 #define PEN_CIRCUIT QPen(Qt::yellow, 0.5)
00033 #define PEN_SELECTED QPen(Qt::green, 2.0)
00034
00035
00036 #define IMG_WIDTH 1000
00037 #define IMG_HEIGHT 507
00038
00039
00040 #define MAP_TOP 2
00041 #define MAP_BOTTOM 2
00042 #define MAP_RIGHT 5
00043 #define MAP_LEFT 5
00044 #define MAP_WIDTH (IMG_WIDTH-MAP_LEFT-MAP_RIGHT)
00045 #define MAP_HEIGHT (IMG_HEIGHT-MAP_TOP-MAP_BOTTOM)
00046
00047
00048 #define MAP_ORIGIN -10
00049
00050
00051 #define MIN_SIZE QSize(512,256)
00052
00053
00054
00055 static float plen[] = {
00056 1.0000, 0.9986, 0.9954, 0.9900,
00057 0.9822, 0.9730, 0.9600, 0.9427,
00058 0.9216, 0.8962, 0.8679, 0.8350,
00059 0.7986, 0.7597, 0.7186, 0.6732,
00060 0.6213, 0.5722, 0.5322
00061 };
00062
00063
00064 static float pdfe[] = {
00065 0.0000, 0.0620, 0.1240, 0.1860,
00066 0.2480, 0.3100, 0.3720, 0.4340,
00067 0.4958, 0.5571, 0.6176, 0.6769,
00068 0.7346, 0.7903, 0.8435, 0.8936,
00069 0.9394, 0.9761, 1.0000
00070 };
00071
00072
00073 TorMapImageView::TorMapImageView(QWidget *parent)
00074 : ZImageView(parent)
00075 {
00076 QImage map(IMG_WORLD_MAP);
00077 setImage(map);
00078 }
00079
00080
00081 TorMapImageView::~TorMapImageView()
00082 {
00083 clear();
00084 }
00085
00086
00087 void
00088 TorMapImageView::addRouter(const RouterDescriptor &desc, const GeoIp &geoip)
00089 {
00090 QString id = desc.id();
00091 QPointF routerCoord = toMapSpace(geoip.latitude(), geoip.longitude());
00092
00093
00094 if (_routers.contains(id))
00095 _routers.value(id)->first = routerCoord;
00096 else
00097 _routers.insert(id, new QPair<QPointF,bool>(routerCoord, false));
00098 }
00099
00100
00101 void
00102 TorMapImageView::addCircuit(const CircuitId &circid, const QStringList &path)
00103 {
00104 QPainterPath *circPainterPath = new QPainterPath;
00105
00106
00107 for (int i = 0; i < path.size()-1; i++) {
00108 QString fromNode = path.at(i);
00109 QString toNode = path.at(i+1);
00110
00111
00112 if (_routers.contains(fromNode) && _routers.contains(toNode)) {
00113
00114 QPointF fromPos = _routers.value(fromNode)->first;
00115 QPointF endPos = _routers.value(toNode)->first;
00116
00117
00118 circPainterPath->moveTo(fromPos);
00119 circPainterPath->lineTo(endPos);
00120 circPainterPath->moveTo(endPos);
00121 }
00122 }
00123
00124
00125 if (_circuits.contains(circid)) {
00126
00127
00128 QPair<QPainterPath*,bool> *circuitPair = _circuits.value(circid);
00129 delete circuitPair->first;
00130 circuitPair->first = circPainterPath;
00131 } else {
00132
00133 _circuits.insert(circid, new QPair<QPainterPath*,bool>(circPainterPath,false));
00134 }
00135 }
00136
00137
00138 void
00139 TorMapImageView::removeCircuit(const CircuitId &circid)
00140 {
00141 QPair<QPainterPath*,bool> *circ = _circuits.take(circid);
00142 QPainterPath *circpath = circ->first;
00143 if (circpath) {
00144 delete circpath;
00145 }
00146 delete circ;
00147 }
00148
00149
00150 void
00151 TorMapImageView::selectRouter(const QString &id)
00152 {
00153 if (_routers.contains(id)) {
00154 QPair<QPointF, bool> *routerPair = _routers.value(id);
00155 routerPair->second = true;
00156 }
00157 repaint();
00158 }
00159
00160
00161
00162 void
00163 TorMapImageView::selectCircuit(const CircuitId &circid)
00164 {
00165 if (_circuits.contains(circid)) {
00166 QPair<QPainterPath*, bool> *circuitPair = _circuits.value(circid);
00167 circuitPair->second = true;
00168 }
00169 repaint();
00170 }
00171
00172
00173 void
00174 TorMapImageView::deselectAll()
00175 {
00176
00177 foreach (QString router, _routers.keys()) {
00178 QPair<QPointF,bool> *routerPair = _routers.value(router);
00179 routerPair->second = false;
00180 }
00181
00182 foreach (CircuitId circid, _circuits.keys()) {
00183 QPair<QPainterPath*,bool> *circuitPair = _circuits.value(circid);
00184 circuitPair->second = false;
00185 }
00186 }
00187
00188
00189 void
00190 TorMapImageView::clear()
00191 {
00192
00193 foreach (QString router, _routers.keys()) {
00194 delete _routers.take(router);
00195 }
00196
00197 foreach (CircuitId circid, _circuits.keys()) {
00198 QPair<QPainterPath*,bool> *circuitPair = _circuits.take(circid);
00199 delete circuitPair->first;
00200 delete circuitPair;
00201 }
00202 }
00203
00204
00205 void
00206 TorMapImageView::paintImage(QPainter *painter)
00207 {
00208 painter->setRenderHint(QPainter::Antialiasing);
00209
00210
00211 foreach(QString router, _routers.keys()) {
00212 QPair<QPointF,bool> *routerPair = _routers.value(router);
00213 painter->setPen((routerPair->second ? PEN_SELECTED : PEN_ROUTER));
00214 painter->drawPoint(routerPair->first);
00215 }
00216
00217 foreach(CircuitId circid, _circuits.keys()) {
00218 QPair<QPainterPath*,bool> *circuitPair = _circuits.value(circid);
00219 painter->setPen((circuitPair->second ? PEN_SELECTED : PEN_CIRCUIT));
00220 painter->drawPath(*(circuitPair->first));
00221 }
00222 }
00223
00224
00225 QPointF
00226 TorMapImageView::toMapSpace(float latitude, float longitude)
00227 {
00228 float width = MAP_WIDTH;
00229 float height = MAP_HEIGHT;
00230 float deg = width / 360.0;
00231 longitude += MAP_ORIGIN;
00232
00233 float lat;
00234 float lon;
00235
00236 lat = floor(longitude * (deg * lerp(abs(int(latitude)), plen))
00237 + width/2 + MAP_LEFT);
00238
00239 if (latitude < 0) {
00240 lon = floor((height/2) + (lerp(abs(int(latitude)), pdfe) * (height/2))
00241 + MAP_TOP);
00242 } else {
00243 lon = floor((height/2) - (lerp(abs(int(latitude)), pdfe) * (height/2))
00244 + MAP_TOP);
00245 }
00246
00247 return QPointF(lat, lon);
00248 }
00249
00250
00251 float
00252 TorMapImageView::lerp(float input, float *table)
00253 {
00254 int x = int(floor(input / 5));
00255
00256 return ((table[x+1] - table[x]) /
00257 (((x+1)*5) - (x*5))) * (input - x*5) + table[x];
00258 }
00259
00260
00261 QSize
00262 TorMapImageView::minimumSizeHint() const
00263 {
00264 return MIN_SIZE;
00265 }
00266
00267
00268
00269
00270 void
00271 TorMapImageView::zoomToFit()
00272 {
00273 QRectF rect = circuitBoundingBox();
00274
00275 if (rect.isNull()) {
00276
00277 resetZoomPoint();
00278 zoom(0.0);
00279 } else {
00280
00281 float zoomLevel = 1.0 - qMax(rect.height()/float(MAP_HEIGHT),
00282 rect.width()/float(MAP_WIDTH));
00283
00284 zoom(rect.center().toPoint(), zoomLevel+0.2);
00285 }
00286 }
00287
00288
00289 void
00290 TorMapImageView::zoomToCircuit(const CircuitId &circid)
00291 {
00292 if (_circuits.contains(circid)) {
00293 QPair<QPainterPath*,bool> *pair = _circuits.value(circid);
00294 QRectF rect = ((QPainterPath *)pair->first)->boundingRect();
00295 if (!rect.isNull()) {
00296 float zoomLevel = 1.0 - qMax(rect.height()/float(MAP_HEIGHT),
00297 rect.width()/float(MAP_WIDTH));
00298
00299 zoom(rect.center().toPoint(), zoomLevel+0.2);
00300 }
00301 }
00302 }
00303
00304
00305 void
00306 TorMapImageView::zoomToRouter(const QString &id)
00307 {
00308 QPair<QPointF,bool> *routerPair;
00309
00310 if (_routers.contains(id)) {
00311 deselectAll();
00312 routerPair = _routers.value(id);
00313 routerPair->second = true;
00314 zoom(routerPair->first.toPoint(), 1.0);
00315 }
00316 }
00317
00318
00319
00320 QRectF
00321 TorMapImageView::circuitBoundingBox()
00322 {
00323 QRectF rect;
00324
00325
00326 foreach (CircuitId circid, _circuits.keys()) {
00327 QPair<QPainterPath*,bool> *pair = _circuits.value(circid);
00328 QPainterPath *circuit = pair->first;
00329 rect = rect.unite(circuit->boundingRect());
00330 }
00331 return rect;
00332 }
00333