2020-06-19 05:03:38 +02:00
|
|
|
// viz1090, a vizualizer for dump1090 ADSB output
|
|
|
|
//
|
|
|
|
// Copyright (C) 2020, Nathan Matsuda <info@nathanmatsuda.com>
|
|
|
|
// Copyright (C) 2014, Malcolm Robb <Support@ATTAvionics.com>
|
|
|
|
// Copyright (C) 2012, Salvatore Sanfilippo <antirez at gmail dot com>
|
|
|
|
// All rights reserved.
|
|
|
|
//
|
|
|
|
// Redistribution and use in source and binary forms, with or without
|
|
|
|
// modification, are permitted provided that the following conditions are
|
|
|
|
// met:
|
|
|
|
//
|
|
|
|
// * Redistributions of source code must retain the above copyright
|
|
|
|
// notice, this list of conditions and the following disclaimer.
|
|
|
|
//
|
|
|
|
// * Redistributions in binary form must reproduce the above copyright
|
|
|
|
// notice, this list of conditions and the following disclaimer in the
|
|
|
|
// documentation and/or other materials provided with the distribution.
|
|
|
|
//
|
|
|
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
|
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
|
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
|
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
|
|
// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
|
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
|
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
|
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
//
|
|
|
|
|
2020-03-19 06:22:59 +01:00
|
|
|
#include "Map.h"
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <cstdlib>
|
2020-06-20 07:04:57 +02:00
|
|
|
#include <sstream>
|
|
|
|
#include <fstream>
|
|
|
|
#include <string>
|
|
|
|
#include <iostream>
|
2020-02-27 07:44:30 +01:00
|
|
|
|
2020-06-13 05:32:42 +02:00
|
|
|
bool Map::QTInsert(QuadTree *tree, Line *line, int depth) {
|
2020-02-27 07:44:30 +01:00
|
|
|
|
2020-06-19 04:29:45 +02:00
|
|
|
// if(depth > 25) {
|
|
|
|
// // printf("fail [%f %f] -> [%f %f]\n",line->start.lon,line->start.lat,line->end.lon,line->end.lat);
|
2020-06-18 08:42:39 +02:00
|
|
|
|
2020-06-19 04:29:45 +02:00
|
|
|
// // printf("bounds %f %f %f %f\n",tree->lon_min, tree->lon_max, tree->lat_min, tree->lat_max);
|
|
|
|
// // fflush(stdout);
|
|
|
|
// tree->lines.push_back(&(*line));
|
|
|
|
// return true;
|
|
|
|
// }
|
2020-06-18 08:42:39 +02:00
|
|
|
|
|
|
|
|
2020-06-14 07:15:47 +02:00
|
|
|
bool startInside = line->start.lat >= tree->lat_min &&
|
2020-06-14 05:54:21 +02:00
|
|
|
line->start.lat <= tree->lat_max &&
|
|
|
|
line->start.lon >= tree->lon_min &&
|
2020-06-18 08:42:39 +02:00
|
|
|
line->start.lon <= tree->lon_max;
|
2020-06-14 07:15:47 +02:00
|
|
|
|
|
|
|
bool endInside = line->end.lat >= tree->lat_min &&
|
2020-06-14 05:54:21 +02:00
|
|
|
line->end.lat <= tree->lat_max &&
|
|
|
|
line->end.lon >= tree->lon_min &&
|
2020-06-18 08:42:39 +02:00
|
|
|
line->end.lon <= tree->lon_max;
|
2020-06-14 07:15:47 +02:00
|
|
|
|
2020-06-19 04:29:45 +02:00
|
|
|
// if (!startInside || !endInside) {
|
2020-06-18 08:42:39 +02:00
|
|
|
// return false;
|
|
|
|
// }
|
2020-06-19 04:29:45 +02:00
|
|
|
if (!startInside && !endInside) {
|
|
|
|
return false;
|
|
|
|
}
|
2020-06-14 05:54:21 +02:00
|
|
|
|
2020-06-19 04:29:45 +02:00
|
|
|
if (startInside != endInside) {
|
|
|
|
tree->lines.push_back(&(*line));
|
|
|
|
return true;
|
|
|
|
}
|
2020-06-13 05:32:42 +02:00
|
|
|
|
2020-03-02 07:40:11 +01:00
|
|
|
if (tree->nw == NULL) {
|
2020-03-19 06:22:59 +01:00
|
|
|
tree->nw = new QuadTree;
|
2020-03-02 07:40:11 +01:00
|
|
|
|
|
|
|
tree->nw->lat_min = tree->lat_min;
|
|
|
|
tree->nw->lat_max = tree->lat_min + 0.5 * (tree->lat_max - tree->lat_min);
|
|
|
|
tree->nw->lon_min = tree->lon_min;
|
|
|
|
tree->nw->lon_max = tree->lon_min + 0.5 * (tree->lon_max - tree->lon_min);
|
|
|
|
}
|
|
|
|
|
2020-06-13 05:32:42 +02:00
|
|
|
if (QTInsert(tree->nw, line, depth++)){
|
2020-03-02 07:40:11 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tree->sw == NULL) {
|
2020-03-19 06:22:59 +01:00
|
|
|
tree->sw = new QuadTree;
|
2020-03-02 07:40:11 +01:00
|
|
|
|
|
|
|
tree->sw->lat_min = tree->lat_min;
|
|
|
|
tree->sw->lat_max = tree->lat_min + 0.5 * (tree->lat_max - tree->lat_min);
|
|
|
|
tree->sw->lon_min = tree->lon_min + 0.5 * (tree->lon_max - tree->lon_min);
|
|
|
|
tree->sw->lon_max = tree->lon_max;
|
|
|
|
}
|
2020-02-27 07:44:30 +01:00
|
|
|
|
2020-06-13 05:32:42 +02:00
|
|
|
if (QTInsert(tree->sw, line, depth++)){
|
2020-03-02 07:40:11 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tree->ne == NULL) {
|
2020-03-19 06:22:59 +01:00
|
|
|
tree->ne = new QuadTree;
|
2020-03-02 07:40:11 +01:00
|
|
|
|
|
|
|
tree->ne->lat_min = tree->lat_min + 0.5 * (tree->lat_max - tree->lat_min);
|
|
|
|
tree->ne->lat_max = tree->lat_max;
|
|
|
|
tree->ne->lon_min = tree->lon_min;
|
|
|
|
tree->ne->lon_max = tree->lon_min + 0.5 * (tree->lon_max - tree->lon_min);
|
|
|
|
}
|
|
|
|
|
2020-06-13 05:32:42 +02:00
|
|
|
if (QTInsert(tree->ne, line, depth++)){
|
2020-03-02 07:40:11 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tree->se == NULL) {
|
2020-03-19 06:22:59 +01:00
|
|
|
tree->se = new QuadTree;
|
2020-03-02 07:40:11 +01:00
|
|
|
|
|
|
|
tree->se->lat_min = tree->lat_min + 0.5 * (tree->lat_max - tree->lat_min);
|
|
|
|
tree->se->lat_max = tree->lat_max;
|
|
|
|
tree->se->lon_min = tree->lon_min + 0.5 * (tree->lon_max - tree->lon_min);
|
|
|
|
tree->se->lon_max = tree->lon_max;
|
|
|
|
}
|
|
|
|
|
2020-06-13 05:32:42 +02:00
|
|
|
if (QTInsert(tree->se, line, depth++)){
|
2020-03-02 07:40:11 +01:00
|
|
|
return true;
|
2020-02-27 07:44:30 +01:00
|
|
|
}
|
|
|
|
|
2020-06-14 05:54:21 +02:00
|
|
|
tree->lines.push_back(&(*line));
|
2020-06-18 08:42:39 +02:00
|
|
|
|
2020-03-02 07:40:11 +01:00
|
|
|
return true;
|
2020-02-27 07:44:30 +01:00
|
|
|
}
|
|
|
|
|
2020-03-19 06:22:59 +01:00
|
|
|
|
2020-06-14 05:54:21 +02:00
|
|
|
std::vector<Line*> Map::getLinesRecursive(QuadTree *tree, float screen_lat_min, float screen_lat_max, float screen_lon_min, float screen_lon_max) {
|
|
|
|
std::vector<Line*> retLines;
|
2020-03-19 06:22:59 +01:00
|
|
|
|
|
|
|
if(tree == NULL) {
|
2020-06-13 05:32:42 +02:00
|
|
|
return retLines;
|
2020-03-19 06:22:59 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (tree->lat_min > screen_lat_max || screen_lat_min > tree->lat_max) {
|
2020-06-13 05:32:42 +02:00
|
|
|
return retLines;
|
2020-03-19 06:22:59 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (tree->lon_min > screen_lon_max || screen_lon_min > tree->lon_max) {
|
2020-06-13 05:32:42 +02:00
|
|
|
return retLines;
|
2020-03-19 06:22:59 +01:00
|
|
|
}
|
|
|
|
|
2020-06-14 05:54:21 +02:00
|
|
|
std::vector<Line*> ret;
|
2020-06-13 05:32:42 +02:00
|
|
|
ret = getLinesRecursive(tree->nw, screen_lat_min, screen_lat_max, screen_lon_min, screen_lon_max);
|
|
|
|
retLines.insert(retLines.end(), ret.begin(), ret.end());
|
2020-06-10 20:28:52 +02:00
|
|
|
|
2020-06-13 05:32:42 +02:00
|
|
|
ret = getLinesRecursive(tree->sw, screen_lat_min, screen_lat_max, screen_lon_min, screen_lon_max);
|
|
|
|
retLines.insert(retLines.end(), ret.begin(), ret.end());
|
2020-03-19 06:22:59 +01:00
|
|
|
|
2020-06-13 05:32:42 +02:00
|
|
|
ret = getLinesRecursive(tree->ne, screen_lat_min, screen_lat_max, screen_lon_min, screen_lon_max);
|
|
|
|
retLines.insert(retLines.end(), ret.begin(), ret.end());
|
2020-03-19 06:22:59 +01:00
|
|
|
|
2020-06-13 05:32:42 +02:00
|
|
|
ret = getLinesRecursive(tree->se, screen_lat_min, screen_lat_max, screen_lon_min, screen_lon_max);
|
|
|
|
retLines.insert(retLines.end(), ret.begin(), ret.end());
|
2020-03-19 06:22:59 +01:00
|
|
|
|
2020-06-13 05:32:42 +02:00
|
|
|
retLines.insert(retLines.end(), tree->lines.begin(), tree->lines.end());
|
2020-06-11 09:11:52 +02:00
|
|
|
|
2020-06-14 05:54:21 +02:00
|
|
|
// Debug quadtree
|
|
|
|
// Point TL, TR, BL, BR;
|
|
|
|
|
|
|
|
// TL.lat = tree->lat_min;
|
|
|
|
// TL.lon = tree->lon_min;
|
|
|
|
|
|
|
|
// TR.lat = tree->lat_max;
|
|
|
|
// TR.lon = tree->lon_min;
|
|
|
|
|
|
|
|
// BL.lat = tree->lat_min;
|
|
|
|
// BL.lon = tree->lon_max;
|
|
|
|
|
|
|
|
// BR.lat = tree->lat_max;
|
|
|
|
// BR.lon = tree->lon_max;
|
|
|
|
|
|
|
|
// retLines.push_back(new Line(TL,TR));
|
|
|
|
// retLines.push_back(new Line(TR,BR));
|
|
|
|
// retLines.push_back(new Line(BL,BR));
|
|
|
|
// retLines.push_back(new Line(TL,BL));
|
|
|
|
|
2020-06-13 05:32:42 +02:00
|
|
|
return retLines;
|
2020-03-19 06:22:59 +01:00
|
|
|
}
|
|
|
|
|
2020-06-14 05:54:21 +02:00
|
|
|
std::vector<Line*> Map::getLines(float screen_lat_min, float screen_lat_max, float screen_lon_min, float screen_lon_max) {
|
2020-06-13 05:32:42 +02:00
|
|
|
return getLinesRecursive(&root, screen_lat_min, screen_lat_max, screen_lon_min, screen_lon_max);
|
2020-03-19 06:22:59 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
Map::Map() {
|
2020-02-27 07:44:30 +01:00
|
|
|
FILE *fileptr;
|
|
|
|
|
2020-03-02 07:40:11 +01:00
|
|
|
if(!(fileptr = fopen("mapdata.bin", "rb"))) {
|
2020-06-20 07:04:57 +02:00
|
|
|
printf("No map file found\n");
|
|
|
|
return;
|
2020-03-02 07:40:11 +01:00
|
|
|
}
|
2020-02-27 07:44:30 +01:00
|
|
|
|
2020-03-02 07:40:11 +01:00
|
|
|
fseek(fileptr, 0, SEEK_END);
|
|
|
|
mapPoints_count = ftell(fileptr) / sizeof(float);
|
|
|
|
rewind(fileptr);
|
2020-03-02 06:17:12 +01:00
|
|
|
|
2020-03-02 07:40:11 +01:00
|
|
|
mapPoints = (float *)malloc(mapPoints_count * sizeof(float));
|
|
|
|
if(!fread(mapPoints, sizeof(float), mapPoints_count, fileptr)){
|
2020-06-20 07:04:57 +02:00
|
|
|
printf("Map read error\n");
|
2020-03-02 07:40:11 +01:00
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
fclose(fileptr);
|
2020-03-02 06:17:12 +01:00
|
|
|
|
2020-06-11 09:11:52 +02:00
|
|
|
printf("Read %d map points.\n",mapPoints_count / 2);
|
2020-02-27 07:44:30 +01:00
|
|
|
|
2020-03-02 07:40:11 +01:00
|
|
|
// load quad tree
|
|
|
|
|
2020-02-27 07:44:30 +01:00
|
|
|
for(int i = 0; i < mapPoints_count; i+=2) {
|
|
|
|
if(mapPoints[i] == 0)
|
|
|
|
continue;
|
|
|
|
|
2020-03-19 06:22:59 +01:00
|
|
|
if(mapPoints[i] < root.lon_min) {
|
|
|
|
root.lon_min = mapPoints[i];
|
|
|
|
} else if(mapPoints[i] > root.lon_max) {
|
|
|
|
root.lon_max = mapPoints[i];
|
2020-02-27 07:44:30 +01:00
|
|
|
}
|
|
|
|
|
2020-03-19 06:22:59 +01:00
|
|
|
if(mapPoints[i+1] < root.lat_min) {
|
|
|
|
root.lat_min = mapPoints[i+1];
|
|
|
|
} else if(mapPoints[i+1] > root.lat_max) {
|
|
|
|
root.lat_max = mapPoints[i+1];
|
2020-02-27 07:44:30 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-20 07:04:57 +02:00
|
|
|
//printf("map bounds: %f %f %f %f\n",root.lon_min, root.lon_max, root.lat_min, root.lat_max);
|
2020-06-18 08:42:39 +02:00
|
|
|
|
2020-06-13 05:32:42 +02:00
|
|
|
Point currentPoint;
|
|
|
|
Point nextPoint;
|
2020-02-27 07:44:30 +01:00
|
|
|
|
2020-06-13 05:32:42 +02:00
|
|
|
for(int i = 0; i < mapPoints_count - 2; i+=2) {
|
|
|
|
if(mapPoints[i] == 0)
|
|
|
|
continue;
|
2020-06-14 05:54:21 +02:00
|
|
|
if(mapPoints[i + 1] == 0)
|
|
|
|
continue;
|
|
|
|
if(mapPoints[i + 2] == 0)
|
|
|
|
continue;
|
|
|
|
if(mapPoints[i + 3] == 0)
|
|
|
|
continue;
|
2020-06-13 05:32:42 +02:00
|
|
|
currentPoint.lon = mapPoints[i];
|
|
|
|
currentPoint.lat = mapPoints[i + 1];
|
2020-02-27 07:44:30 +01:00
|
|
|
|
2020-06-13 05:32:42 +02:00
|
|
|
nextPoint.lon = mapPoints[i + 2];
|
|
|
|
nextPoint.lat = mapPoints[i + 3];
|
2020-02-27 07:44:30 +01:00
|
|
|
|
2020-06-18 08:42:39 +02:00
|
|
|
// printf("inserting [%f %f] -> [%f %f]\n",currentPoint.lon,currentPoint.lat,nextPoint.lon,nextPoint.lat);
|
|
|
|
|
2020-06-13 05:32:42 +02:00
|
|
|
QTInsert(&root, new Line(currentPoint, nextPoint), 0);
|
2020-02-27 07:44:30 +01:00
|
|
|
}
|
2020-06-11 09:11:52 +02:00
|
|
|
|
2020-06-20 07:04:57 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::string line;
|
|
|
|
std::ifstream infile("mapnames");
|
|
|
|
|
|
|
|
|
|
|
|
while (std::getline(infile, line))
|
|
|
|
{
|
|
|
|
float lon, lat;
|
|
|
|
|
|
|
|
std::istringstream iss(line);
|
|
|
|
|
|
|
|
iss >> lon;
|
|
|
|
iss >> lat;
|
|
|
|
|
|
|
|
std::string assemble;
|
|
|
|
|
|
|
|
iss >> assemble;
|
|
|
|
|
|
|
|
for(std::string s; iss >> s; ) {
|
|
|
|
assemble = assemble + " " + s;
|
|
|
|
}
|
|
|
|
|
|
|
|
// std::cout << "[" << x << "," << y << "] " << assemble << "\n";
|
|
|
|
Label *label = new Label(lon,lat,assemble);
|
|
|
|
mapnames.push_back(label);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::cout << "Read " << mapnames.size() << " place names\n";
|
|
|
|
|
2020-06-18 08:42:39 +02:00
|
|
|
printf("done\n");
|
2020-06-12 06:55:04 +02:00
|
|
|
}
|