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