working runway drawing and airport names with conversion

This commit is contained in:
nathan 2020-06-20 21:44:30 -07:00
parent ab1dce1d15
commit 80e776d470
8 changed files with 308 additions and 80 deletions

View file

@ -62,16 +62,20 @@ void AppData::initialize() {
void AppData::connect() { void AppData::connect() {
c = (struct client *) malloc(sizeof(*c));
while(1) { if(connected) {
if ((fd = setupConnection(c)) == ANET_ERR) { return;
fprintf(stderr, "Waiting on %s:%d\n", server, modes.net_input_beast_port);
sleep(1);
} else {
break;
}
} }
c = (struct client *) malloc(sizeof(*c));
if ((fd = setupConnection(c)) == ANET_ERR) {
fprintf(stderr, "Waiting on %s:%d\n", server, modes.net_input_beast_port);
return;
}
connected = true;
fprintf(stderr, "Connected to %s:%d\n", server, modes.net_input_beast_port);
} }
@ -82,6 +86,10 @@ void AppData::disconnect() {
void AppData::update() { void AppData::update() {
if(!connected) {
return;
}
if ((fd == ANET_ERR) || (recv(c->fd, pk_buf, sizeof(pk_buf), MSG_PEEK | MSG_DONTWAIT) == 0)) { if ((fd == ANET_ERR) || (recv(c->fd, pk_buf, sizeof(pk_buf), MSG_PEEK | MSG_DONTWAIT) == 0)) {
free(c); free(c);
usleep(1000000); usleep(1000000);
@ -154,4 +162,6 @@ AppData::AppData(){
modes.interactive = 0; modes.interactive = 0;
modes.quiet = 1; modes.quiet = 1;
connected = false;
} }

View file

@ -45,6 +45,7 @@ class AppData {
// //
struct client *c; struct client *c;
bool connected;
int fd; int fd;
char pk_buf[8]; char pk_buf[8];

220
Map.cpp
View file

@ -189,70 +189,135 @@ std::vector<Line*> Map::getLines(float screen_lat_min, float screen_lat_max, flo
Map::Map() { Map::Map() {
FILE *fileptr; FILE *fileptr;
if(!(fileptr = fopen("mapdata.bin", "rb"))) { if((fileptr = fopen("mapdata.bin", "rb"))) {
fseek(fileptr, 0, SEEK_END);
mapPoints_count = ftell(fileptr) / sizeof(float);
rewind(fileptr);
mapPoints = (float *)malloc(mapPoints_count * sizeof(float));
if(!fread(mapPoints, sizeof(float), mapPoints_count, fileptr)){
printf("Map read error\n");
exit(0);
}
fclose(fileptr);
printf("Read %d map points.\n",mapPoints_count / 2);
// load quad tree
for(int i = 0; i < mapPoints_count; i+=2) {
if(mapPoints[i] == 0)
continue;
if(mapPoints[i] < root.lon_min) {
root.lon_min = mapPoints[i];
} else if(mapPoints[i] > root.lon_max) {
root.lon_max = mapPoints[i];
}
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];
}
}
//printf("map bounds: %f %f %f %f\n",root.lon_min, root.lon_max, root.lat_min, root.lat_max);
Point currentPoint;
Point nextPoint;
for(int i = 0; i < mapPoints_count - 2; i+=2) {
if(mapPoints[i] == 0)
continue;
if(mapPoints[i + 1] == 0)
continue;
if(mapPoints[i + 2] == 0)
continue;
if(mapPoints[i + 3] == 0)
continue;
currentPoint.lon = mapPoints[i];
currentPoint.lat = mapPoints[i + 1];
nextPoint.lon = mapPoints[i + 2];
nextPoint.lat = mapPoints[i + 3];
// printf("inserting [%f %f] -> [%f %f]\n",currentPoint.lon,currentPoint.lat,nextPoint.lon,nextPoint.lat);
QTInsert(&root, new Line(currentPoint, nextPoint), 0);
}
} else {
printf("No map file found\n"); printf("No map file found\n");
return; }
//
if((fileptr = fopen("airportdata.bin", "rb"))) {
fseek(fileptr, 0, SEEK_END);
airportPoints_count = ftell(fileptr) / sizeof(float);
rewind(fileptr);
airportPoints = (float *)malloc(airportPoints_count * sizeof(float));
if(!fread(airportPoints, sizeof(float), airportPoints_count, fileptr)){
printf("Map read error\n");
exit(0);
}
fclose(fileptr);
printf("Read %d airport points.\n",airportPoints_count / 2);
// load quad tree
for(int i = 0; i < airportPoints_count; i+=2) {
if(airportPoints[i] == 0)
continue;
if(airportPoints[i] < airport_root.lon_min) {
airport_root.lon_min = airportPoints[i];
} else if(airportPoints[i] > airport_root.lon_max) {
airport_root.lon_max = airportPoints[i];
}
if(airportPoints[i+1] < airport_root.lat_min) {
airport_root.lat_min = airportPoints[i+1];
} else if(airportPoints[i+1] > airport_root.lat_max) {
airport_root.lat_max = airportPoints[i+1];
}
}
//printf("map bounds: %f %f %f %f\n",root.lon_min, root.lon_max, root.lat_min, root.lat_max);
Point currentPoint;
Point nextPoint;
for(int i = 0; i < airportPoints_count - 2; i+=2) {
if(airportPoints[i] == 0)
continue;
if(airportPoints[i + 1] == 0)
continue;
if(airportPoints[i + 2] == 0)
continue;
if(airportPoints[i + 3] == 0)
continue;
currentPoint.lon = airportPoints[i];
currentPoint.lat = airportPoints[i + 1];
nextPoint.lon = airportPoints[i + 2];
nextPoint.lat = airportPoints[i + 3];
//printf("inserting [%f %f] -> [%f %f]\n",currentPoint.lon,currentPoint.lat,nextPoint.lon,nextPoint.lat);
QTInsert(&airport_root, new Line(currentPoint, nextPoint), 0);
}
} else {
printf("No airport file found\n");
} }
fseek(fileptr, 0, SEEK_END); //
mapPoints_count = ftell(fileptr) / sizeof(float);
rewind(fileptr);
mapPoints = (float *)malloc(mapPoints_count * sizeof(float));
if(!fread(mapPoints, sizeof(float), mapPoints_count, fileptr)){
printf("Map read error\n");
exit(0);
}
fclose(fileptr);
printf("Read %d map points.\n",mapPoints_count / 2);
// load quad tree
for(int i = 0; i < mapPoints_count; i+=2) {
if(mapPoints[i] == 0)
continue;
if(mapPoints[i] < root.lon_min) {
root.lon_min = mapPoints[i];
} else if(mapPoints[i] > root.lon_max) {
root.lon_max = mapPoints[i];
}
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];
}
}
//printf("map bounds: %f %f %f %f\n",root.lon_min, root.lon_max, root.lat_min, root.lat_max);
Point currentPoint;
Point nextPoint;
for(int i = 0; i < mapPoints_count - 2; i+=2) {
if(mapPoints[i] == 0)
continue;
if(mapPoints[i + 1] == 0)
continue;
if(mapPoints[i + 2] == 0)
continue;
if(mapPoints[i + 3] == 0)
continue;
currentPoint.lon = mapPoints[i];
currentPoint.lat = mapPoints[i + 1];
nextPoint.lon = mapPoints[i + 2];
nextPoint.lat = mapPoints[i + 3];
// printf("inserting [%f %f] -> [%f %f]\n",currentPoint.lon,currentPoint.lat,nextPoint.lon,nextPoint.lat);
QTInsert(&root, new Line(currentPoint, nextPoint), 0);
}
std::string line; std::string line;
@ -283,5 +348,38 @@ Map::Map() {
std::cout << "Read " << mapnames.size() << " place names\n"; std::cout << "Read " << mapnames.size() << " place names\n";
infile.close();
infile.open("airportnames");
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);
airportnames.push_back(label);
}
std::cout << "Read " << airportnames.size() << " airport names\n";
infile.close();
printf("done\n"); printf("done\n");
} }

6
Map.h
View file

@ -119,16 +119,22 @@ class Map {
public: public:
QuadTree root; QuadTree root;
QuadTree airport_root;
bool QTInsert(QuadTree *tree, Line *line, int depth); bool QTInsert(QuadTree *tree, Line *line, int depth);
std::vector<Line*> getLinesRecursive(QuadTree *tree, float screen_lat_min, float screen_lat_max, float screen_lon_min, float screen_lon_max); std::vector<Line*> getLinesRecursive(QuadTree *tree, float screen_lat_min, float screen_lat_max, float screen_lon_min, float screen_lon_max);
std::vector<Line*> getLines(float screen_lat_min, float screen_lat_max, float screen_lon_min, float screen_lon_max); std::vector<Line*> getLines(float screen_lat_min, float screen_lat_max, float screen_lon_min, float screen_lon_max);
std::vector<Label*> mapnames; std::vector<Label*> mapnames;
std::vector<Label*> airportnames;
Map(); Map();
int mapPoints_count; int mapPoints_count;
float *mapPoints; float *mapPoints;
int airportPoints_count;
float *airportPoints;
}; };
#endif #endif

View file

@ -647,12 +647,14 @@ void View::drawLines(int left, int top, int right, int bottom, int bailTime) {
latLonFromScreenCoords(&screen_lat_min, &screen_lon_min, left, top); latLonFromScreenCoords(&screen_lat_min, &screen_lon_min, left, top);
latLonFromScreenCoords(&screen_lat_max, &screen_lon_max, right, bottom); latLonFromScreenCoords(&screen_lat_max, &screen_lon_max, right, bottom);
drawLinesRecursive(&(map.root), screen_lat_min, screen_lat_max, screen_lon_min, screen_lon_max); drawLinesRecursive(&(map.root), screen_lat_min, screen_lat_max, screen_lon_min, screen_lon_max, style.mapInnerColor);
drawLinesRecursive(&(map.airport_root), screen_lat_min, screen_lat_max, screen_lon_min, screen_lon_max, orange);
drawTrails(left, top, right, bottom); drawTrails(left, top, right, bottom);
} }
void View::drawLinesRecursive(QuadTree *tree, float screen_lat_min, float screen_lat_max, float screen_lon_min, float screen_lon_max) { void View::drawLinesRecursive(QuadTree *tree, float screen_lat_min, float screen_lat_max, float screen_lon_min, float screen_lon_max, SDL_Color color) {
if(tree == NULL) { if(tree == NULL) {
return; return;
} }
@ -665,13 +667,13 @@ void View::drawLinesRecursive(QuadTree *tree, float screen_lat_min, float screen
return; return;
} }
drawLinesRecursive(tree->nw, screen_lat_min, screen_lat_max, screen_lon_min, screen_lon_max); drawLinesRecursive(tree->nw, screen_lat_min, screen_lat_max, screen_lon_min, screen_lon_max, color);
drawLinesRecursive(tree->sw, screen_lat_min, screen_lat_max, screen_lon_min, screen_lon_max); drawLinesRecursive(tree->sw, screen_lat_min, screen_lat_max, screen_lon_min, screen_lon_max, color);
drawLinesRecursive(tree->ne, screen_lat_min, screen_lat_max, screen_lon_min, screen_lon_max); drawLinesRecursive(tree->ne, screen_lat_min, screen_lat_max, screen_lon_min, screen_lon_max, color);
drawLinesRecursive(tree->se, screen_lat_min, screen_lat_max, screen_lon_min, screen_lon_max); drawLinesRecursive(tree->se, screen_lat_min, screen_lat_max, screen_lon_min, screen_lon_max, color);
std::vector<Line*>::iterator currentLine; std::vector<Line*>::iterator currentLine;
@ -695,7 +697,7 @@ void View::drawLinesRecursive(QuadTree *tree, float screen_lat_min, float screen
continue; continue;
} }
lineRGBA(renderer, x1, y1, x2, y2, style.mapInnerColor.r, style.mapInnerColor.g, style.mapInnerColor.b, 255); lineRGBA(renderer, x1, y1, x2, y2, color.r, color.g, color.b, 255);
} }
// //Debug quadtree // //Debug quadtree
@ -742,6 +744,20 @@ void View::drawPlaceNames() {
drawString((*label)->text, x, y, mapFont, grey); drawString((*label)->text, x, y, mapFont, grey);
} }
for(std::vector<Label*>::iterator label = map.airportnames.begin(); label != map.airportnames.end(); ++label) {
float dx, dy;
int x,y;
pxFromLonLat(&dx, &dy, (*label)->location.lon, (*label)->location.lat);
screenCoords(&x, &y, dx, dy);
if(outOfBounds(x,y)) {
continue;
}
drawString((*label)->text, x, y, listFont, red);
}
} }
void View::drawGeography() { void View::drawGeography() {
@ -1202,6 +1218,13 @@ void View::drawPlanes() {
while(p) { while(p) {
if (p->lon && p->lat) { if (p->lon && p->lat) {
// if lon lat argments were not provided, start by snapping to the first plane we see
if(centerLon == 0 && centerLat == 0) {
mapTargetLon = p->lon;
mapTargetLat = p->lat;
}
int x, y; int x, y;
float dx, dy; float dx, dy;
@ -1256,6 +1279,10 @@ void View::drawPlanes() {
drawPlaneOffMap(x, y, &(p->cx), &(p->cy), planeColor); drawPlaneOffMap(x, y, &(p->cx), &(p->cy), planeColor);
} else { } else {
drawPlaneIcon(usex, usey, p->track, planeColor); drawPlaneIcon(usex, usey, p->track, planeColor);
p->x += usex - p->cx;
p->y += usey - p->cy;
p->cx = usex; p->cx = usex;
p->cy = usey; p->cy = usey;
} }
@ -1517,6 +1544,9 @@ View::View(AppData *appData){
fullscreen = 0; fullscreen = 0;
screen_index = 0; screen_index = 0;
centerLon = 0;
centerLat = 0;
maxDist = 25.0; maxDist = 25.0;
mapMoved = 1; mapMoved = 1;

2
View.h
View file

@ -122,7 +122,7 @@ class View {
void drawPlaneIcon(int x, int y, float heading, SDL_Color planeColor); void drawPlaneIcon(int x, int y, float heading, SDL_Color planeColor);
void drawTrails(int left, int top, int right, int bottom); void drawTrails(int left, int top, int right, int bottom);
void drawScaleBars(); void drawScaleBars();
void drawLinesRecursive(QuadTree *tree, float screen_lat_min, float screen_lat_max, float screen_lon_min, float screen_lon_max); void drawLinesRecursive(QuadTree *tree, float screen_lat_min, float screen_lat_max, float screen_lon_min, float screen_lon_max, SDL_Color color);
void drawLines(int left, int top, int right, int bottom, int bailTime); void drawLines(int left, int top, int right, int bottom, int bailTime);
void drawPlaceNames(); void drawPlaceNames();
void drawGeography(); void drawGeography();

View file

@ -0,0 +1,85 @@
import fiona
from shapely.geometry import shape
import numpy as np
from tqdm import tqdm
import zipfile
from io import BytesIO
#from urllib.request import urlopen
import requests
import argparse
import os
def convertLinestring(linestring):
outlist = []
pointx = linestring.coords.xy[0]
pointy = linestring.coords.xy[1]
for j in range(len(pointx)):
outlist.extend([float(pointx[j]),float(pointy[j])])
outlist.extend([0,0])
return outlist
def extractLines(shapefile, tolerance):
print("Extracting map lines")
outlist = []
for i in tqdm(range(len(shapefile))):
simplified = shape(shapefile[i]['geometry'])#.simplify(tolerance, preserve_topology=False)
if(simplified.geom_type == "LineString"):
outlist.extend(convertLinestring(simplified))
elif(simplified.geom_type == "MultiPolygon" or simplified.geom_type == "Polygon"):
if(simplified.boundary.geom_type == "MultiLineString"):
for boundary in simplified.boundary:
outlist.extend(convertLinestring(boundary))
else:
outlist.extend(convertLinestring(simplified.boundary))
else:
print("Unsupported type: " + simplified.geom_type)
return outlist
parser = argparse.ArgumentParser(description='viz1090 Natural Earth Data Map Converter')
parser.add_argument("--tolerance", default=0.001, type=float, help="map simplification tolerance")
parser.add_argument("--scale", default="10m", choices=["10m","50m","110m"], type=str, help="map file scale")
parser.add_argument("mapfile", type=str, help="shapefile to load (e.g., from https://www.naturalearthdata.com/downloads/")
args = parser.parse_args()
shapefile = fiona.open(args.mapfile)
outlist = extractLines(shapefile, args.tolerance)
bin_file = open("airportdata.bin", "wb")
np.asarray(outlist).astype(np.single).tofile(bin_file)
bin_file.close()
print("Wrote %d points" % (len(outlist) / 2))
bin_file = open("airportnames", "w")
shapefile = fiona.open("ne_10m_airports.shp")
count = 0
for i in tqdm(range(len(shapefile))):
xcoord = shapefile[i]['geometry']['coordinates'][0]
ycoord = shapefile[i]['geometry']['coordinates'][1]
name = shapefile[i]['properties']['iata_code']
outstring = "{0} {1} {2}\n".format(xcoord, ycoord, name)
bin_file.write(outstring)
count = count + 1
bin_file.close()
print("Wrote %d airport names" % count)

View file

@ -115,9 +115,6 @@ int main(int argc, char **argv) {
int go; int go;
appData.connect();
view.SDL_init(); view.SDL_init();
view.font_init(); view.font_init();
@ -125,6 +122,7 @@ int main(int argc, char **argv) {
while (go == 1) while (go == 1)
{ {
appData.connect();
input.getInput(); input.getInput();
appData.update(); appData.update();
view.draw(); view.draw();