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 #include <QStringList>
00029 #include <cmath>
00030 #include "tormapwidget.h"
00031
00032 #define IMG_WORLD_MAP ":/images/map/world-map.png"
00033
00034
00035 #define PEN_ROUTER QPen(QColor("#ff030d"), 1.0)
00036 #define PEN_CIRCUIT QPen(Qt::yellow, 0.5)
00037 #define PEN_SELECTED QPen(Qt::green, 2.0)
00038
00039
00040 #define IMG_WIDTH 1000
00041 #define IMG_HEIGHT 507
00042
00043
00044 #define MAP_TOP 2
00045 #define MAP_BOTTOM 2
00046 #define MAP_RIGHT 5
00047 #define MAP_LEFT 5
00048 #define MAP_WIDTH (IMG_WIDTH-MAP_LEFT-MAP_RIGHT)
00049 #define MAP_HEIGHT (IMG_HEIGHT-MAP_TOP-MAP_BOTTOM)
00050
00051
00052 #define MAP_ORIGIN -10
00053
00054
00055 #define MIN_SIZE QSize(512,256)
00056
00057
00058
00059 float plen[] = {
00060 1.0000, 0.9986, 0.9954, 0.9900,
00061 0.9822, 0.9730, 0.9600, 0.9427,
00062 0.9216, 0.8962, 0.8679, 0.8350,
00063 0.7986, 0.7597, 0.7186, 0.6732,
00064 0.6213, 0.5722, 0.5322
00065 };
00066
00067
00068 float pdfe[] = {
00069 0.0000, 0.0620, 0.1240, 0.1860,
00070 0.2480, 0.3100, 0.3720, 0.4340,
00071 0.4958, 0.5571, 0.6176, 0.6769,
00072 0.7346, 0.7903, 0.8435, 0.8936,
00073 0.9394, 0.9761, 1.0000
00074 };
00075
00076
00077 TorMapWidget::TorMapWidget(QWidget *parent)
00078 : ZImageView(parent)
00079 {
00080 QImage map(IMG_WORLD_MAP);
00081 setImage(map);
00082 }
00083
00084
00085 TorMapWidget::~TorMapWidget()
00086 {
00087 clear();
00088 }
00089
00090
00091 void
00092 TorMapWidget::addRouter(QString id, float latitude, float longitude)
00093 {
00094 QPointF routerCoord = toMapSpace(latitude, longitude);
00095
00096
00097 _routers.insert(id, new QPair<QPointF,bool>(routerCoord, false));
00098 }
00099
00100
00101 void
00102 TorMapWidget::addCircuit(quint64 circid, 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 TorMapWidget::removeCircuit(quint64 circid)
00140 {
00141 QPair<QPainterPath*,bool> *circ = _circuits.take(circid);
00142 QPainterPath *circpath = circ->first;
00143 if (circpath) {
00144 delete circpath;
00145 }
00146 }
00147
00148
00149 void
00150 TorMapWidget::selectRouter(QString id)
00151 {
00152 if (_routers.contains(id)) {
00153 QPair<QPointF, bool> *routerPair = _routers.value(id);
00154 routerPair->second = true;
00155 }
00156 repaint();
00157 }
00158
00159
00160
00161 void
00162 TorMapWidget::selectCircuit(quint64 circid)
00163 {
00164 if (_circuits.contains(circid)) {
00165 QPair<QPainterPath*, bool> *circuitPair = _circuits.value(circid);
00166 circuitPair->second = true;
00167 }
00168 repaint();
00169 }
00170
00171
00172 void
00173 TorMapWidget::deselectAll()
00174 {
00175
00176 foreach (QString router, _routers.keys()) {
00177 QPair<QPointF,bool> *routerPair = _routers.value(router);
00178 routerPair->second = false;
00179 }
00180
00181 foreach (quint64 circid, _circuits.keys()) {
00182 QPair<QPainterPath*,bool> *circuitPair = _circuits.value(circid);
00183 circuitPair->second = false;
00184 }
00185 }
00186
00187
00188 void
00189 TorMapWidget::clear()
00190 {
00191
00192 foreach (QString router, _routers.keys()) {
00193 delete _routers.take(router);
00194 }
00195
00196 foreach (quint64 circid, _circuits.keys()) {
00197 QPair<QPainterPath*,bool> *circuitPair = _circuits.take(circid);
00198 delete circuitPair->first;
00199 delete circuitPair;
00200 }
00201 }
00202
00203
00204 void
00205 TorMapWidget::paintImage(QPainter *painter)
00206 {
00207 painter->setRenderHint(QPainter::Antialiasing);
00208
00209
00210 foreach(QString router, _routers.keys()) {
00211 QPair<QPointF,bool> *routerPair = _routers.value(router);
00212 painter->setPen((routerPair->second ? PEN_SELECTED : PEN_ROUTER));
00213 painter->drawPoint(routerPair->first);
00214 }
00215
00216 foreach(quint64 circid, _circuits.keys()) {
00217 QPair<QPainterPath*,bool> *circuitPair = _circuits.value(circid);
00218 painter->setPen((circuitPair->second ? PEN_SELECTED : PEN_CIRCUIT));
00219 painter->drawPath(*(circuitPair->first));
00220 }
00221 }
00222
00223
00224 QPointF
00225 TorMapWidget::toMapSpace(float latitude, float longitude)
00226 {
00227 float width = MAP_WIDTH;
00228 float height = MAP_HEIGHT;
00229 float deg = width / 360.0;
00230 longitude += MAP_ORIGIN;
00231
00232 float lat;
00233 float lon;
00234
00235 lat = floor(longitude * (deg * lerp(abs(int(latitude)), plen))
00236 + width/2 + MAP_LEFT);
00237
00238 if (latitude < 0) {
00239 lon = floor((height/2) + (lerp(abs(int(latitude)), pdfe) * (height/2))
00240 + MAP_TOP);
00241 } else {
00242 lon = floor((height/2) - (lerp(abs(int(latitude)), pdfe) * (height/2))
00243 + MAP_TOP);
00244 }
00245
00246 return QPointF(lat, lon);
00247 }
00248
00249
00250 float
00251 TorMapWidget::lerp(float input, float *table)
00252 {
00253 int x = int(floor(input / 5));
00254
00255 return ((table[x+1] - table[x]) /
00256 (((x+1)*5) - (x*5))) * (input - x*5) + table[x];
00257 }
00258
00259
00260 QSize
00261 TorMapWidget::minimumSizeHint() const
00262 {
00263 return MIN_SIZE;
00264 }
00265
00266
00267
00268
00269 void
00270 TorMapWidget::zoomToFit()
00271 {
00272 QRectF rect = circuitBoundingBox();
00273
00274 if (rect.isNull()) {
00275
00276 resetZoomPoint();
00277 zoom(0.0);
00278 } else {
00279
00280 float zoomLevel = 1.0 - qMax(rect.height()/float(MAP_HEIGHT),
00281 rect.width()/float(MAP_WIDTH));
00282
00283 zoom(rect.center().toPoint(), zoomLevel+0.2);
00284 }
00285 }
00286
00287
00288
00289 QRectF
00290 TorMapWidget::circuitBoundingBox()
00291 {
00292 QRectF rect;
00293
00294
00295 foreach (quint64 circid, _circuits.keys()) {
00296 QPair<QPainterPath*,bool> *pair = _circuits.value(circid);
00297 QPainterPath *circuit = pair->first;
00298 rect = rect.unite(circuit->boundingRect());
00299 }
00300 return rect;
00301 }
00302