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