Compare commits
29 commits
Author | SHA1 | Date | |
---|---|---|---|
|
1e2b0dda2f | ||
|
6743e1adf7 | ||
|
7ceb1e69ab | ||
|
26a610c1a3 | ||
|
1922324b40 | ||
![]() |
d1f53019b2 | ||
![]() |
36a398814e | ||
![]() |
ec055e1220 | ||
![]() |
94930dde48 | ||
![]() |
43d4edebee | ||
![]() |
69081b84c6 | ||
![]() |
efe2687c10 | ||
![]() |
319d910e8d | ||
![]() |
721b9a4a17 | ||
![]() |
383081d0de | ||
![]() |
2c484dc5fd | ||
![]() |
74b1ae1c36 | ||
![]() |
c3bfbe4ff0 | ||
![]() |
6dbdaca8d0 | ||
![]() |
f50cfc3c6e | ||
![]() |
56a4f252d6 | ||
![]() |
e9372475c9 | ||
![]() |
d29a1e04e4 | ||
![]() |
e3563f49e7 | ||
![]() |
532d174362 | ||
![]() |
4b976a273b | ||
![]() |
ddb9019194 | ||
![]() |
3762585202 | ||
![]() |
831f4f672a |
14
.gitignore
vendored
14
.gitignore
vendored
|
@ -12,4 +12,18 @@ thumbs.db
|
||||||
*.shx
|
*.shx
|
||||||
*.geojson
|
*.geojson
|
||||||
|
|
||||||
|
*.cpg
|
||||||
|
*.dbf
|
||||||
|
*.zip*
|
||||||
|
*.prj
|
||||||
|
*.xml
|
||||||
|
*.html
|
||||||
|
*.txt
|
||||||
|
|
||||||
|
airportnames
|
||||||
|
mapnames
|
||||||
|
|
||||||
|
|
||||||
viz1090
|
viz1090
|
||||||
|
|
||||||
|
result
|
||||||
|
|
17
Aircraft.cpp
17
Aircraft.cpp
|
@ -30,25 +30,18 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "Aircraft.h"
|
#include "Aircraft.h"
|
||||||
|
#include "AircraftLabel.h"
|
||||||
|
|
||||||
Aircraft::Aircraft(uint32_t addr) {
|
Aircraft::Aircraft(uint32_t addr) {
|
||||||
this->addr = addr;
|
this->addr = addr;
|
||||||
prev_seen = 0;
|
prev_seen = 0;
|
||||||
|
|
||||||
x = 0;
|
|
||||||
y = 0;
|
|
||||||
cx = 0;
|
|
||||||
cy = 0;
|
|
||||||
|
|
||||||
ox = 0;
|
|
||||||
oy = 0;
|
|
||||||
dox = 0;
|
|
||||||
doy = 0;
|
|
||||||
ddox = 0;
|
|
||||||
ddoy = 0;
|
|
||||||
|
|
||||||
lon = 0;
|
lon = 0;
|
||||||
lat = 0;
|
lat = 0;
|
||||||
|
|
||||||
|
label = NULL;
|
||||||
|
|
||||||
|
next = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
18
Aircraft.h
18
Aircraft.h
|
@ -35,12 +35,14 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
|
class AircraftLabel;
|
||||||
|
|
||||||
class Aircraft {
|
class Aircraft {
|
||||||
public:
|
public:
|
||||||
uint32_t addr; // ICAO address
|
uint32_t addr; // ICAO address
|
||||||
char flight[16]; // Flight number
|
char flight[16]; // Flight number
|
||||||
unsigned char signalLevel[8]; // Last 8 Signal Amplitudes
|
unsigned char signalLevel[8]; // Last 8 Signal Amplitudes
|
||||||
double messageRate;
|
float messageRate;
|
||||||
int altitude; // Altitude
|
int altitude; // Altitude
|
||||||
int speed; // Velocity
|
int speed; // Velocity
|
||||||
int track; // Angle of flight
|
int track; // Angle of flight
|
||||||
|
@ -48,13 +50,16 @@ public:
|
||||||
time_t seen; // Time at which the last packet was received
|
time_t seen; // Time at which the last packet was received
|
||||||
time_t seenLatLon; // Time at which the last packet was received
|
time_t seenLatLon; // Time at which the last packet was received
|
||||||
time_t prev_seen;
|
time_t prev_seen;
|
||||||
double lat, lon; // Coordinated obtained from CPR encoded data
|
float lat, lon; // Coordinated obtained from CPR encoded data
|
||||||
|
|
||||||
//history
|
//history
|
||||||
|
|
||||||
std::vector <float> lonHistory, latHistory, headingHistory;
|
std::vector <float> lonHistory, latHistory, headingHistory;
|
||||||
std::vector <std::chrono::high_resolution_clock::time_point> timestampHistory;
|
std::vector <std::chrono::high_resolution_clock::time_point> timestampHistory;
|
||||||
|
|
||||||
|
|
||||||
|
AircraftLabel *label;
|
||||||
|
|
||||||
// float oldLon[TRAIL_LENGTH];
|
// float oldLon[TRAIL_LENGTH];
|
||||||
// float oldLat[TRAIL_LENGTH];
|
// float oldLat[TRAIL_LENGTH];
|
||||||
// float oldHeading[TRAIL_LENGTH];
|
// float oldHeading[TRAIL_LENGTH];
|
||||||
|
@ -69,9 +74,12 @@ public:
|
||||||
|
|
||||||
//// label stuff -> should go to aircraft icon class
|
//// label stuff -> should go to aircraft icon class
|
||||||
|
|
||||||
int x, y, cx, cy, w, h;
|
// int x, y, cx, cy;
|
||||||
float ox, oy, dox, doy, ddox, ddoy;
|
int x, y;
|
||||||
float pressure;
|
// float w, h, target_w, target_h;
|
||||||
|
// float ox, oy, dox, doy, ddox, ddoy;
|
||||||
|
// float labelLevel;
|
||||||
|
// float opacity, target_opacity;
|
||||||
|
|
||||||
/// methods
|
/// methods
|
||||||
|
|
||||||
|
|
538
AircraftLabel.cpp
Normal file
538
AircraftLabel.cpp
Normal file
|
@ -0,0 +1,538 @@
|
||||||
|
#include "AircraftLabel.h"
|
||||||
|
#include "Aircraft.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include "SDL2/SDL2_gfxPrimitives.h"
|
||||||
|
|
||||||
|
using fmilliseconds = std::chrono::duration<float, std::milli>;
|
||||||
|
|
||||||
|
static std::chrono::high_resolution_clock::time_point now() {
|
||||||
|
return std::chrono::high_resolution_clock::now();
|
||||||
|
}
|
||||||
|
|
||||||
|
static float elapsed(std::chrono::high_resolution_clock::time_point ref) {
|
||||||
|
return (fmilliseconds {now() - ref}).count();
|
||||||
|
}
|
||||||
|
|
||||||
|
static float sign(float x) {
|
||||||
|
return (x > 0) - (x < 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Rect AircraftLabel::getFullRect(int labelLevel) {
|
||||||
|
SDL_Rect rect = {static_cast<int>(x),static_cast<int>(y),0,0};
|
||||||
|
|
||||||
|
SDL_Rect currentRect;
|
||||||
|
|
||||||
|
if(labelLevel < 2) {
|
||||||
|
currentRect = speedLabel.getRect();
|
||||||
|
|
||||||
|
rect.w = std::max(rect.w,currentRect.w);
|
||||||
|
rect.h += currentRect.h;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(labelLevel < 1) {
|
||||||
|
currentRect = altitudeLabel.getRect();
|
||||||
|
|
||||||
|
rect.w = std::max(rect.w,currentRect.w);
|
||||||
|
rect.h += currentRect.h;
|
||||||
|
|
||||||
|
currentRect = speedLabel.getRect();
|
||||||
|
|
||||||
|
rect.w = std::max(rect.w,currentRect.w);
|
||||||
|
rect.h += currentRect.h;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AircraftLabel::update() {
|
||||||
|
char flight[17] = "";
|
||||||
|
snprintf(flight,17," %s", p->flight);
|
||||||
|
|
||||||
|
|
||||||
|
std::string flightString = flight;
|
||||||
|
flightString.erase(std::remove_if(flightString.begin(), flightString.end(), isspace), flightString.end());
|
||||||
|
|
||||||
|
flightLabel.setText(flightString);
|
||||||
|
|
||||||
|
char alt[10] = "";
|
||||||
|
if (metric) {
|
||||||
|
snprintf(alt,10," %dm", static_cast<int>(p->altitude / 3.2828));
|
||||||
|
} else {
|
||||||
|
snprintf(alt,10," %d'", p->altitude);
|
||||||
|
}
|
||||||
|
|
||||||
|
altitudeLabel.setText(alt);
|
||||||
|
|
||||||
|
char speed[10] = "";
|
||||||
|
if (metric) {
|
||||||
|
snprintf(speed,10," %dkm/h", static_cast<int>(p->speed * 1.852));
|
||||||
|
} else {
|
||||||
|
snprintf(speed,10," %dmph", p->speed);
|
||||||
|
}
|
||||||
|
|
||||||
|
speedLabel.setText(speed);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AircraftLabel::clearAcceleration() {
|
||||||
|
ddx = 0;
|
||||||
|
ddy = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
float AircraftLabel::calculateDensity(Aircraft *check_p, int labelLevel) {
|
||||||
|
float density_max = 0;
|
||||||
|
|
||||||
|
while(check_p) {
|
||||||
|
if(check_p->addr == p->addr) {
|
||||||
|
check_p = check_p->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!check_p->label) {
|
||||||
|
check_p = check_p->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(check_p->label->x + check_p->label->w < 0) {
|
||||||
|
check_p = check_p->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(check_p->label->y + check_p->label->h < 0) {
|
||||||
|
check_p = check_p->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(check_p->label->x > screen_width) {
|
||||||
|
check_p = check_p->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(check_p->label->y > screen_height) {
|
||||||
|
check_p = check_p->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Rect currentRect = getFullRect(labelLevel);
|
||||||
|
|
||||||
|
float width_proportion = (currentRect.w + check_p->label->w) / fabs(x - check_p->label->x);
|
||||||
|
float height_proportion = (currentRect.h + check_p->label->h) / fabs(y - check_p->label->y);
|
||||||
|
|
||||||
|
float density = width_proportion * height_proportion;
|
||||||
|
|
||||||
|
if(density > density_max) {
|
||||||
|
density_max = density;
|
||||||
|
}
|
||||||
|
|
||||||
|
check_p = check_p -> next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return density_max;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AircraftLabel::calculateForces(Aircraft *check_p) {
|
||||||
|
if(w == 0 || h == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Aircraft *head = check_p;
|
||||||
|
|
||||||
|
int p_left = x;
|
||||||
|
int p_right = x + w;
|
||||||
|
int p_top = y;
|
||||||
|
int p_bottom = y + h;
|
||||||
|
|
||||||
|
|
||||||
|
float boxmid_x = static_cast<float>(p_left + p_right) / 2.0f;
|
||||||
|
float boxmid_y = static_cast<float>(p_top + p_bottom) / 2.0f;
|
||||||
|
|
||||||
|
float offset_x = boxmid_x - p->x;
|
||||||
|
float offset_y = boxmid_y - p->y;
|
||||||
|
|
||||||
|
float target_length_x = attachment_dist + w / 2.0f;
|
||||||
|
float target_length_y = attachment_dist + h / 2.0f;
|
||||||
|
|
||||||
|
// stay icon_dist away from own icon
|
||||||
|
|
||||||
|
ddx -= sign(offset_x) * attachment_force * (fabs(offset_x) - target_length_x);
|
||||||
|
ddy -= sign(offset_y) * attachment_force * (fabs(offset_y) - target_length_y);
|
||||||
|
|
||||||
|
|
||||||
|
// screen edge
|
||||||
|
|
||||||
|
if(p_left < edge_margin) {
|
||||||
|
ddx += boundary_force * static_cast<float>(edge_margin - p_left);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(p_right > screen_width - edge_margin) {
|
||||||
|
ddx += boundary_force * static_cast<float>(screen_width - edge_margin - p_right);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(p_top < edge_margin) {
|
||||||
|
ddy += boundary_force * static_cast<float>(edge_margin - p_top);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(p_bottom > screen_height - edge_margin) {
|
||||||
|
ddy += boundary_force * static_cast<float>(screen_height - edge_margin - p_bottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float all_x = 0;
|
||||||
|
float all_y = 0;
|
||||||
|
int count = 0;
|
||||||
|
//check against other labels
|
||||||
|
|
||||||
|
while(check_p) {
|
||||||
|
if(check_p->addr == p->addr) {
|
||||||
|
check_p = check_p->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!check_p->label) {
|
||||||
|
check_p = check_p->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int check_left = check_p->label->x;
|
||||||
|
int check_right = check_p->label->x + check_p->label->w;
|
||||||
|
int check_top = check_p->label->y;
|
||||||
|
int check_bottom = check_p->label->y + check_p->label->h;
|
||||||
|
|
||||||
|
float icon_x = static_cast<float>(check_p->x);
|
||||||
|
float icon_y = static_cast<float>(check_p->y);
|
||||||
|
|
||||||
|
float checkboxmid_x = static_cast<float>(check_left + check_right) / 2.0f;
|
||||||
|
float checkboxmid_y = static_cast<float>(check_top + check_bottom) / 2.0f;
|
||||||
|
|
||||||
|
float offset_x = boxmid_x - checkboxmid_x;
|
||||||
|
float offset_y = boxmid_y - checkboxmid_y;
|
||||||
|
|
||||||
|
float target_length_x = label_dist + static_cast<float>(check_p->label->w + w) / 2.0f;
|
||||||
|
float target_length_y = label_dist + static_cast<float>(check_p->label->h + h) / 2.0f;
|
||||||
|
|
||||||
|
float x_mag = std::max(0.0f,(target_length_x - fabs(offset_x)));
|
||||||
|
float y_mag = std::max(0.0f,(target_length_y - fabs(offset_y)));
|
||||||
|
|
||||||
|
// stay at least label_dist away from other icons
|
||||||
|
|
||||||
|
if(x_mag > 0 && y_mag > 0) {
|
||||||
|
ddx += sign(offset_x) * label_force * x_mag;
|
||||||
|
ddy += sign(offset_y) * label_force * y_mag;
|
||||||
|
}
|
||||||
|
|
||||||
|
// stay at least icon_dist away from other icons
|
||||||
|
|
||||||
|
offset_x = boxmid_x - check_p->x;
|
||||||
|
offset_y = boxmid_y - check_p->y;
|
||||||
|
|
||||||
|
target_length_x = icon_dist + static_cast<float>(check_p->label->w) / 2.0f;
|
||||||
|
target_length_y = icon_dist + static_cast<float>(check_p->label->h) / 2.0f;
|
||||||
|
|
||||||
|
x_mag = std::max(0.0f,(target_length_x - fabs(offset_x)));
|
||||||
|
y_mag = std::max(0.0f,(target_length_y - fabs(offset_y)));
|
||||||
|
|
||||||
|
if(x_mag > 0 && y_mag > 0) {
|
||||||
|
ddx += sign(offset_x) * icon_force * x_mag;
|
||||||
|
ddy += sign(offset_y) * icon_force * y_mag;
|
||||||
|
}
|
||||||
|
|
||||||
|
all_x += sign(boxmid_x - checkboxmid_x);
|
||||||
|
all_y += sign(boxmid_y - checkboxmid_y);
|
||||||
|
|
||||||
|
count++;
|
||||||
|
|
||||||
|
check_p = check_p -> next;
|
||||||
|
}
|
||||||
|
|
||||||
|
// move away from others
|
||||||
|
ddx += density_force * all_x / count;
|
||||||
|
ddy += density_force * all_y / count;
|
||||||
|
|
||||||
|
// char buff[100];
|
||||||
|
// snprintf(buff, sizeof(buff), "%2.2f", labelLevel);
|
||||||
|
// debugLabel.setText(buff);
|
||||||
|
|
||||||
|
float density_mult = 0.5f;
|
||||||
|
float level_rate = 0.25f;
|
||||||
|
|
||||||
|
if(elapsed(lastLevelChange) > 1000.0) {
|
||||||
|
if(labelLevel < 0.8f * density_mult * calculateDensity(head, labelLevel + 1)) {
|
||||||
|
if(labelLevel <= 2) {
|
||||||
|
labelLevel += level_rate;
|
||||||
|
lastLevelChange = now();
|
||||||
|
}
|
||||||
|
} else if (labelLevel > 1.2f * density_mult * calculateDensity(head, labelLevel - 1)) {
|
||||||
|
if(labelLevel >= 0) {
|
||||||
|
labelLevel -= level_rate;
|
||||||
|
lastLevelChange = now();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AircraftLabel::applyForces() {
|
||||||
|
dx += ddx;
|
||||||
|
dy += ddy;
|
||||||
|
|
||||||
|
dx *= damping_force;
|
||||||
|
dy *= damping_force;
|
||||||
|
|
||||||
|
if(fabs(dx) > velocity_limit) {
|
||||||
|
dx = sign(dx) * velocity_limit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(fabs(dy) > velocity_limit) {
|
||||||
|
dy = sign(dy) * velocity_limit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(fabs(dx) < 0.01f) {
|
||||||
|
dx = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(fabs(dy) < 0.01f) {
|
||||||
|
dy = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
x += dx;
|
||||||
|
y += dy;
|
||||||
|
|
||||||
|
if(isnan(x)) {
|
||||||
|
x = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(isnan(y)) {
|
||||||
|
y = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// x = p->cx + (int)round(p->ox);
|
||||||
|
// y = p->cy + (int)round(p->oy);
|
||||||
|
}
|
||||||
|
|
||||||
|
// SDL_Color signalToColor(int signal) {
|
||||||
|
// SDL_Color planeColor;
|
||||||
|
|
||||||
|
// if(signal > 127) {
|
||||||
|
// signal = 127;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if(signal < 0) {
|
||||||
|
// planeColor = setColor(96, 96, 96);
|
||||||
|
// } else {
|
||||||
|
// planeColor = setColor(parula[signal][0], parula[signal][1], parula[signal][2]);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return planeColor;
|
||||||
|
// }
|
||||||
|
// void View::drawSignalMarks(Aircraft *p, int x, int y) {
|
||||||
|
// unsigned char * pSig = p->signalLevel;
|
||||||
|
// unsigned int signalAverage = (pSig[0] + pSig[1] + pSig[2] + pSig[3] +
|
||||||
|
// pSig[4] + pSig[5] + pSig[6] + pSig[7] + 3) >> 3;
|
||||||
|
|
||||||
|
// SDL_Color barColor = signalToColor(signalAverage);
|
||||||
|
|
||||||
|
// Uint8 seenFade;
|
||||||
|
|
||||||
|
// if(elapsed(p->msSeen) < 1024) {
|
||||||
|
// seenFade = (Uint8) (255.0 - elapsed(p->msSeen) / 4.0);
|
||||||
|
|
||||||
|
// circleRGBA(renderer, x + mapFontWidth, y - 5, 2 * screen_uiscale, barColor.r, barColor.g, barColor.b, seenFade);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if(elapsed(p->msSeenLatLon) < 1024) {
|
||||||
|
// seenFade = (Uint8) (255.0 - elapsed(p->msSeenLatLon) / 4.0);
|
||||||
|
|
||||||
|
// hlineRGBA(renderer, x + mapFontWidth + 5 * screen_uiscale, x + mapFontWidth + 9 * screen_uiscale, y - 5, barColor.r, barColor.g, barColor.b, seenFade);
|
||||||
|
// vlineRGBA(renderer, x + mapFontWidth + 7 * screen_uiscale, y - 2 * screen_uiscale - 5, y + 2 * screen_uiscale - 5, barColor.r, barColor.g, barColor.b, seenFade);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
void AircraftLabel::draw(SDL_Renderer *renderer, bool selected) {
|
||||||
|
if(x == 0 || y == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// char buff[100];
|
||||||
|
// snprintf(buff, sizeof(buff), "%f %f", x, y);
|
||||||
|
// debugLabel.setText(buff);
|
||||||
|
|
||||||
|
int totalWidth = 0;
|
||||||
|
int totalHeight = 0;
|
||||||
|
|
||||||
|
// int margin = 4 * screen_uiscale;
|
||||||
|
|
||||||
|
int margin = 4;
|
||||||
|
|
||||||
|
SDL_Rect outRect;
|
||||||
|
|
||||||
|
if(opacity == 0 && labelLevel < 2) {
|
||||||
|
target_opacity = 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(opacity > 0 && labelLevel >= 2) {
|
||||||
|
target_opacity = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
opacity += 0.25f * (target_opacity - opacity);
|
||||||
|
|
||||||
|
if(opacity < 0.05f) {
|
||||||
|
opacity = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(w != 0 && h != 0 && opacity > 0) {
|
||||||
|
|
||||||
|
SDL_Color drawColor = style.labelLineColor;
|
||||||
|
|
||||||
|
drawColor.a = static_cast<int>(255.0f * opacity);
|
||||||
|
|
||||||
|
if(selected) {
|
||||||
|
drawColor = style.selectedColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tick = 4;
|
||||||
|
|
||||||
|
int anchor_x, anchor_y, exit_x, exit_y;
|
||||||
|
|
||||||
|
if(x + w / 2 > p->x) {
|
||||||
|
anchor_x = x;
|
||||||
|
} else {
|
||||||
|
anchor_x = x + w;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(y + h / 2 > p->y) {
|
||||||
|
anchor_y = y - margin;
|
||||||
|
} else {
|
||||||
|
anchor_y = y + h + margin;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(abs(anchor_x - p->x) > abs(anchor_y - p->y)) {
|
||||||
|
exit_x = (anchor_x + p->x) / 2;
|
||||||
|
exit_y = anchor_y;
|
||||||
|
} else {
|
||||||
|
exit_x = anchor_x;
|
||||||
|
exit_y = (anchor_y + p->y) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
Sint16 vx[3] = {
|
||||||
|
static_cast<Sint16>(p->x),
|
||||||
|
static_cast<Sint16>(exit_x),
|
||||||
|
static_cast<Sint16>(anchor_x)};
|
||||||
|
|
||||||
|
Sint16 vy[3] = {
|
||||||
|
static_cast<Sint16>(p->y),
|
||||||
|
static_cast<Sint16>(exit_y),
|
||||||
|
static_cast<Sint16>(anchor_y)};
|
||||||
|
|
||||||
|
boxRGBA(renderer, x, y, x + w, y + h, style.labelBackground.r, style.labelBackground.g, style.labelBackground.b, drawColor.a);
|
||||||
|
|
||||||
|
// char buff[100];
|
||||||
|
// snprintf(buff, sizeof(buff), "%d", drawColor.a);
|
||||||
|
// debugLabel.setText(buff);
|
||||||
|
|
||||||
|
bezierRGBA(renderer, vx, vy, 3, 2, drawColor.r, drawColor.g, drawColor.b, drawColor.a);
|
||||||
|
|
||||||
|
//lineRGBA(renderer, x,y - margin, x + tick, y - margin, drawColor.r, drawColor.g, drawColor.b, drawColor.a);
|
||||||
|
lineRGBA(renderer, x,y - margin, x + w, y - margin, drawColor.r, drawColor.g, drawColor.b, drawColor.a);
|
||||||
|
lineRGBA(renderer, x,y - margin, x, y - margin + tick, drawColor.r, drawColor.g, drawColor.b, drawColor.a);
|
||||||
|
|
||||||
|
// lineRGBA(renderer, x + w, y - margin, x + w - tick, y - margin, drawColor.r, drawColor.g, drawColor.b, drawColor.a);
|
||||||
|
lineRGBA(renderer, x + w, y - margin, x + w, y - margin + tick, drawColor.r, drawColor.g, drawColor.b, drawColor.a);
|
||||||
|
|
||||||
|
//lineRGBA(renderer, x, y + h + margin, x + tick, y + h + margin, drawColor.r, drawColor.g, drawColor.b, drawColor.a);
|
||||||
|
lineRGBA(renderer, x, y + h + margin, x + w, y + h + margin, drawColor.r, drawColor.g, drawColor.b, drawColor.a);
|
||||||
|
lineRGBA(renderer, x, y + h + margin, x, y + h + margin - tick, drawColor.r, drawColor.g, drawColor.b, drawColor.a);
|
||||||
|
|
||||||
|
// lineRGBA(renderer, x + w, y + h + margin,x + w - tick, y + h + margin, drawColor.r, drawColor.g, drawColor.b, drawColor.a);
|
||||||
|
lineRGBA(renderer, x + w, y + h + margin,x + w, y + h + margin - tick, drawColor.r, drawColor.g, drawColor.b, drawColor.a);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(labelLevel < 2 || selected) {
|
||||||
|
// drawSignalMarks(p, x, y);
|
||||||
|
|
||||||
|
SDL_Color drawColor = style.labelColor;
|
||||||
|
drawColor.a = static_cast<int>(255.0f * opacity);
|
||||||
|
|
||||||
|
flightLabel.setColor(drawColor);
|
||||||
|
flightLabel.setPosition(x,y);
|
||||||
|
flightLabel.draw(renderer);
|
||||||
|
// outRect = drawString(flight, x, y, mapBoldFont, drawColor);
|
||||||
|
outRect = flightLabel.getRect();
|
||||||
|
|
||||||
|
totalWidth = std::max(totalWidth,outRect.w);
|
||||||
|
totalHeight += outRect.h;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if(labelLevel < 1 || selected) {
|
||||||
|
SDL_Color drawColor = style.subLabelColor;
|
||||||
|
drawColor.a = static_cast<int>(255.0f * opacity);
|
||||||
|
|
||||||
|
altitudeLabel.setColor(drawColor);
|
||||||
|
altitudeLabel.setPosition(x,y + totalHeight);
|
||||||
|
altitudeLabel.draw(renderer);
|
||||||
|
outRect = altitudeLabel.getRect();
|
||||||
|
|
||||||
|
totalWidth = std::max(totalWidth,outRect.w);
|
||||||
|
totalHeight += outRect.h;
|
||||||
|
|
||||||
|
speedLabel.setColor(drawColor);
|
||||||
|
speedLabel.setPosition(x,y + totalHeight);
|
||||||
|
speedLabel.draw(renderer);
|
||||||
|
outRect = speedLabel.getRect();
|
||||||
|
|
||||||
|
totalWidth = std::max(totalWidth,outRect.w);
|
||||||
|
totalHeight += outRect.h;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
debugLabel.setPosition(x,y + totalHeight);
|
||||||
|
debugLabel.draw(renderer);
|
||||||
|
|
||||||
|
target_w = totalWidth;
|
||||||
|
target_h = totalHeight;
|
||||||
|
|
||||||
|
w += 0.25f * (target_w - w);
|
||||||
|
h += 0.25f * (target_h - h);
|
||||||
|
|
||||||
|
if(w < 0.05f) {
|
||||||
|
w = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(h < 0.05f) {
|
||||||
|
h = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AircraftLabel::AircraftLabel(Aircraft *p, bool metric, int screen_width, int screen_height, TTF_Font *font) {
|
||||||
|
this->p = p;
|
||||||
|
|
||||||
|
this->metric = metric;
|
||||||
|
|
||||||
|
x = p->x;
|
||||||
|
y = p->y + 20; //*screen_uiscale
|
||||||
|
w = 0;
|
||||||
|
h = 0;
|
||||||
|
target_w = 0;
|
||||||
|
target_h = 0;
|
||||||
|
|
||||||
|
opacity = 0;
|
||||||
|
target_opacity = 0;
|
||||||
|
|
||||||
|
dx = 0;
|
||||||
|
dy = 0;
|
||||||
|
ddx = 0;
|
||||||
|
ddy = 0;
|
||||||
|
|
||||||
|
this->screen_width = screen_width;
|
||||||
|
this->screen_height = screen_height;
|
||||||
|
|
||||||
|
labelLevel = 0;
|
||||||
|
|
||||||
|
flightLabel.setFont(font);
|
||||||
|
altitudeLabel.setFont(font);
|
||||||
|
speedLabel.setFont(font);
|
||||||
|
debugLabel.setFont(font);
|
||||||
|
|
||||||
|
lastLevelChange = now();
|
||||||
|
}
|
76
AircraftLabel.h
Normal file
76
AircraftLabel.h
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include "SDL2/SDL_ttf.h"
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
|
#include "Label.h"
|
||||||
|
#include "Style.h"
|
||||||
|
|
||||||
|
class Aircraft;
|
||||||
|
|
||||||
|
|
||||||
|
class AircraftLabel {
|
||||||
|
public:
|
||||||
|
void update();
|
||||||
|
void clearAcceleration();
|
||||||
|
void calculateForces(Aircraft *check_p);
|
||||||
|
void applyForces();
|
||||||
|
|
||||||
|
void draw(SDL_Renderer *renderer, bool selected);
|
||||||
|
|
||||||
|
AircraftLabel(Aircraft *p, bool metric, int screen_width, int screen_height, TTF_Font *font);
|
||||||
|
|
||||||
|
private:
|
||||||
|
SDL_Rect getFullRect(int labelLevel);
|
||||||
|
float calculateDensity(Aircraft *check_p, int labelLevel);
|
||||||
|
|
||||||
|
Aircraft *p;
|
||||||
|
|
||||||
|
Label flightLabel;
|
||||||
|
Label altitudeLabel;
|
||||||
|
Label speedLabel;
|
||||||
|
Label debugLabel;
|
||||||
|
|
||||||
|
float labelLevel;
|
||||||
|
|
||||||
|
bool metric;
|
||||||
|
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
float w;
|
||||||
|
float h;
|
||||||
|
|
||||||
|
float target_w;
|
||||||
|
float target_h;
|
||||||
|
|
||||||
|
float dx;
|
||||||
|
float dy;
|
||||||
|
float ddx;
|
||||||
|
float ddy;
|
||||||
|
|
||||||
|
float opacity;
|
||||||
|
float target_opacity;
|
||||||
|
|
||||||
|
float pressure;
|
||||||
|
|
||||||
|
int screen_width;
|
||||||
|
int screen_height;
|
||||||
|
|
||||||
|
std::chrono::high_resolution_clock::time_point lastLevelChange;
|
||||||
|
|
||||||
|
///////////
|
||||||
|
|
||||||
|
float label_force = 0.001f;
|
||||||
|
float label_dist = 2.0f;
|
||||||
|
float density_force = 0.05f;
|
||||||
|
float attachment_force = 0.0015f;
|
||||||
|
float attachment_dist = 10.0f;
|
||||||
|
float icon_force = 0.001f;
|
||||||
|
float icon_dist = 15.0f;
|
||||||
|
float boundary_force = 0.01f;
|
||||||
|
float damping_force = 0.85f;
|
||||||
|
float velocity_limit = 2.0f;
|
||||||
|
float edge_margin = 15.0f;
|
||||||
|
|
||||||
|
Style style;
|
||||||
|
};
|
|
@ -53,10 +53,14 @@ void AircraftList::update(Modes *modes) {
|
||||||
Aircraft *p = head;
|
Aircraft *p = head;
|
||||||
|
|
||||||
while(p) {
|
while(p) {
|
||||||
p->live = 0;
|
p->live = 0;
|
||||||
p = p->next;
|
p = p->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//debug
|
||||||
|
//find(1)->live = 1;
|
||||||
|
|
||||||
|
|
||||||
while(a) {
|
while(a) {
|
||||||
|
|
||||||
p = find(a->addr);
|
p = find(a->addr);
|
||||||
|
@ -144,6 +148,10 @@ void AircraftList::update(Modes *modes) {
|
||||||
|
|
||||||
AircraftList::AircraftList() {
|
AircraftList::AircraftList() {
|
||||||
head = nullptr;
|
head = nullptr;
|
||||||
|
|
||||||
|
// //debug aircraft attached to mouse
|
||||||
|
// head = new Aircraft(1);
|
||||||
|
// memcpy(head->flight, "mouse", sizeof("mouse"));
|
||||||
}
|
}
|
||||||
|
|
||||||
AircraftList::~AircraftList() {
|
AircraftList::~AircraftList() {
|
||||||
|
|
70
Label.cpp
Normal file
70
Label.cpp
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
#include "Label.h"
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
void Label::draw(SDL_Renderer *renderer) {
|
||||||
|
SDL_Rect rect = getRect();
|
||||||
|
|
||||||
|
if(rect.h == 0 || rect.w == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, surface);
|
||||||
|
SDL_RenderCopy(renderer, texture, NULL, &rect);
|
||||||
|
SDL_DestroyTexture(texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Label::makeSurface() {
|
||||||
|
if(surface != NULL) {
|
||||||
|
SDL_FreeSurface(surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
surface = TTF_RenderUTF8_Solid(font, text.c_str(), color);
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Rect Label::getRect() {
|
||||||
|
SDL_Rect rect = {0,0,0,0};
|
||||||
|
|
||||||
|
if(!text.length()) {
|
||||||
|
return rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(surface == NULL) {
|
||||||
|
return rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
rect.x = x;
|
||||||
|
rect.y = y;
|
||||||
|
rect.w = surface->w;
|
||||||
|
rect.h = surface->h;
|
||||||
|
|
||||||
|
return rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Label::setText(std::string text) {
|
||||||
|
this->text = text;
|
||||||
|
makeSurface();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Label::setPosition(int x, int y) {
|
||||||
|
this->x = x;
|
||||||
|
this->y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Label::setFont(TTF_Font *font) {
|
||||||
|
this->font = font;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Label::setColor(SDL_Color color) {
|
||||||
|
this->color = color;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
Label::Label() {
|
||||||
|
this->color = {255,255,255,255};
|
||||||
|
surface = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Label::~Label() {
|
||||||
|
SDL_FreeSurface(surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
29
Label.h
Normal file
29
Label.h
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
|
||||||
|
#include "SDL2/SDL.h"
|
||||||
|
#include "SDL2/SDL_ttf.h"
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class Label {
|
||||||
|
public:
|
||||||
|
void draw(SDL_Renderer *renderer);
|
||||||
|
|
||||||
|
void setText(std::string text);
|
||||||
|
void setPosition(int x, int y);
|
||||||
|
void setFont(TTF_Font *font);
|
||||||
|
void setColor(SDL_Color color);
|
||||||
|
|
||||||
|
SDL_Rect getRect();
|
||||||
|
|
||||||
|
Label();
|
||||||
|
~Label();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void makeSurface();
|
||||||
|
|
||||||
|
std::string text;
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
TTF_Font *font;
|
||||||
|
SDL_Color color;
|
||||||
|
SDL_Surface *surface;
|
||||||
|
};
|
17
Makefile
17
Makefile
|
@ -3,8 +3,8 @@
|
||||||
# sure that the variable PREFIX is defined, e.g. make PREFIX=/usr/local
|
# sure that the variable PREFIX is defined, e.g. make PREFIX=/usr/local
|
||||||
#
|
#
|
||||||
|
|
||||||
CXXFLAGS=-O2 -std=c++11
|
CXXFLAGS=-O2 -std=c++11 -g
|
||||||
LIBS= -lm -lSDL2 -lSDL2_ttf -lSDL2_gfx
|
LIBS= -lm -lSDL2 -lSDL2_ttf -lSDL2_gfx -g
|
||||||
CXX=g++
|
CXX=g++
|
||||||
|
|
||||||
all: viz1090
|
all: viz1090
|
||||||
|
@ -12,8 +12,15 @@ all: viz1090
|
||||||
%.o: %.c %.cpp
|
%.o: %.c %.cpp
|
||||||
$(CXX) $(CXXFLAGS) $(EXTRACFLAGS) -c $<
|
$(CXX) $(CXXFLAGS) $(EXTRACFLAGS) -c $<
|
||||||
|
|
||||||
viz1090: viz1090.o AppData.o AircraftList.o Aircraft.o anet.o interactive.o mode_ac.o mode_s.o net_io.o Input.o View.o Map.o parula.o monokai.o
|
viz1090: viz1090.o AppData.o AircraftList.o Aircraft.o Label.o AircraftLabel.o anet.o interactive.o mode_ac.o mode_s.o net_io.o Input.o View.o Map.o parula.o monokai.o
|
||||||
$(CXX) -o viz1090 viz1090.o AppData.o AircraftList.o Aircraft.o anet.o interactive.o mode_ac.o mode_s.o net_io.o Input.o View.o Map.o parula.o monokai.o $(LIBS) $(LDFLAGS)
|
$(CXX) -o viz1090 viz1090.o AppData.o AircraftList.o Aircraft.o Label.o AircraftLabel.o anet.o interactive.o mode_ac.o mode_s.o net_io.o Input.o View.o Map.o parula.o monokai.o $(LIBS) $(LDFLAGS)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f *.o viz1090
|
rm -f \
|
||||||
|
airportdata.bin \
|
||||||
|
airportnames \
|
||||||
|
mapdata/* \
|
||||||
|
mapdata.bin \
|
||||||
|
mapnames \
|
||||||
|
*.o \
|
||||||
|
viz1090
|
||||||
|
|
4
Map.cpp
4
Map.cpp
|
@ -342,7 +342,7 @@ Map::Map() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// std::cout << "[" << x << "," << y << "] " << assemble << "\n";
|
// std::cout << "[" << x << "," << y << "] " << assemble << "\n";
|
||||||
Label *label = new Label(lon,lat,assemble);
|
MapLabel *label = new MapLabel(lon,lat,assemble);
|
||||||
mapnames.push_back(label);
|
mapnames.push_back(label);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -371,7 +371,7 @@ Map::Map() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// std::cout << "[" << x << "," << y << "] " << assemble << "\n";
|
// std::cout << "[" << x << "," << y << "] " << assemble << "\n";
|
||||||
Label *label = new Label(lon,lat,assemble);
|
MapLabel *label = new MapLabel(lon,lat,assemble);
|
||||||
airportnames.push_back(label);
|
airportnames.push_back(label);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
10
Map.h
10
Map.h
|
@ -40,16 +40,16 @@ typedef struct Point{
|
||||||
float lon;
|
float lon;
|
||||||
} Point;
|
} Point;
|
||||||
|
|
||||||
typedef struct Label{
|
typedef struct MapLabel{
|
||||||
Point location;
|
Point location;
|
||||||
std::string text;
|
std::string text;
|
||||||
|
|
||||||
Label(float lon, float lat, std::string text) {
|
MapLabel(float lon, float lat, std::string text) {
|
||||||
this->location.lon = lon;
|
this->location.lon = lon;
|
||||||
this->location.lat = lat;
|
this->location.lat = lat;
|
||||||
this->text = text;
|
this->text = text;
|
||||||
}
|
}
|
||||||
} Label;
|
} MapLabel;
|
||||||
|
|
||||||
typedef struct Line{
|
typedef struct Line{
|
||||||
float lat_min;
|
float lat_min;
|
||||||
|
@ -125,8 +125,8 @@ public:
|
||||||
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<MapLabel*> mapnames;
|
||||||
std::vector<Label*> airportnames;
|
std::vector<MapLabel*> airportnames;
|
||||||
|
|
||||||
Map();
|
Map();
|
||||||
|
|
||||||
|
|
57
README.md
57
README.md
|
@ -1,10 +1,10 @@
|
||||||
# viz1090
|
# viz1090
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
**This is work in progress**
|
**This is a work in progress**
|
||||||
|
|
||||||
There are some major fixes and cleanup that need to happen before a relase:
|
There are some major fixes and cleanup that need to happen before a release:
|
||||||
* Everything is a grab bag of C and C++, need to more consistently modernize
|
* Everything is a grab bag of C and C++, need to more consistently modernize
|
||||||
* A full refactor, especially View.cpp, necessary for many of the new features below.
|
* A full refactor, especially View.cpp, necessary for many of the new features below.
|
||||||
* A working Android build, as this is the best way to run this on portable hardware.
|
* A working Android build, as this is the best way to run this on portable hardware.
|
||||||
|
@ -27,18 +27,18 @@ Tested and working on Ubuntu 18.04, Raspbian Stretch / Buster, Windows Subsystem
|
||||||
sudo apt-get install build-essential
|
sudo apt-get install build-essential
|
||||||
```
|
```
|
||||||
|
|
||||||
1. Install SDL and RTL-SDR libararies
|
1. Install SDL and RTL-SDR libraries
|
||||||
```
|
```
|
||||||
sudo apt-get install libsdl2-dev libsdl2-ttf-dev libsdl2-gfx-dev librtlsdr-dev
|
sudo apt-get install libsdl2-dev libsdl2-ttf-dev libsdl2-gfx-dev librtlsdr-dev libgdal-dev
|
||||||
```
|
```
|
||||||
|
|
||||||
Note: On Raspbian the SDL2 package requires X to be running. See the Raspberry Pi section for notes on running from the terminal and other improvements.
|
Note: On Raspbian the SDL2 package requires X to be running. See the Raspberry Pi section for notes on running from the terminal and other improvements.
|
||||||
|
|
||||||
2. Download and build spidr
|
2. Download and build viz1090
|
||||||
```
|
```
|
||||||
cd ~
|
cd ~
|
||||||
git clone https://www.github.com/nmatsuda/spidr
|
git clone https://www.github.com/nmatsuda/viz1090
|
||||||
cd spidr
|
cd viz1090
|
||||||
make clean; make
|
make clean; make
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -46,13 +46,13 @@ make clean; make
|
||||||
|
|
||||||
```
|
```
|
||||||
sudo apt install python3 python3-pip
|
sudo apt install python3 python3-pip
|
||||||
pip3 install fiona tqdm
|
pip3 install fiona tqdm shapely
|
||||||
./getmap.sh
|
./getmap.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
This will produce files for map and airport geometry, with labels, that viz1090 reads. If any of these files don't exist then visualizer will show planes and trails without any geography.
|
This will produce files for map and airport geometry, with labels, that viz1090 reads. If any of these files don't exist then visualizer will show planes and trails without any geography.
|
||||||
|
|
||||||
The default parameters for mapconverter should render resonably quickly on a Raspberri Pi 4. See the mapconverter section below for other options and more information about map sources.
|
The default parameters for mapconverter should render reasonably quickly on a Raspberry Pi 4. See the mapconverter section below for other options and more information about map sources.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -60,14 +60,30 @@ The default parameters for mapconverter should render resonably quickly on a Ras
|
||||||
|
|
||||||
As WSL does not have an X server built in, you will need to install a 3rd party X server, such as https://sourceforge.net/projects/vcxsrv/
|
As WSL does not have an X server built in, you will need to install a 3rd party X server, such as https://sourceforge.net/projects/vcxsrv/
|
||||||
|
|
||||||
* run Xlaunch from the start menu
|
* run Xlaunch from the start menu
|
||||||
* Uncheck "Use Native openGL"
|
* Uncheck "Use Native openGL"
|
||||||
* Open the Ubuntu WSL terminal
|
* Add parameter ```-ac``` (WSL 2 only)
|
||||||
* Specify the X display to use
|
* Open the Ubuntu WSL terminal
|
||||||
```
|
* Specify the X display to use (WSL 1)
|
||||||
export DISPLAY=:0
|
```
|
||||||
```
|
export DISPLAY=:0
|
||||||
* Start viz1090 as described below.
|
```
|
||||||
|
* or for (WSL 2)
|
||||||
|
```
|
||||||
|
export DISPLAY=$(cat /etc/resolv.conf | grep nameserver | awk '{print $2}'):0
|
||||||
|
```
|
||||||
|
* Start viz1090 as described below.
|
||||||
|
|
||||||
|
#### Nix
|
||||||
|
|
||||||
|
Run without installing
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nix shell git+https://git.vulpecula.zone/tasiaiso/viz1090
|
||||||
|
```
|
||||||
|
TODO docs
|
||||||
|
|
||||||
|
A shell is now open with viz1090 in the path
|
||||||
|
|
||||||
### RUNNING
|
### RUNNING
|
||||||
|
|
||||||
|
@ -91,7 +107,7 @@ viz1090 will open an SDL window set to the resolution of your screen.
|
||||||
| --port [port number] | Specify dump1090 server port |
|
| --port [port number] | Specify dump1090 server port |
|
||||||
| --metric | Display metric units |
|
| --metric | Display metric units |
|
||||||
| --lat | Specify your latitude in degrees |
|
| --lat | Specify your latitude in degrees |
|
||||||
| --lon | Specify your longitiude in degrees |
|
| --lon | Specify your longitude in degrees |
|
||||||
| --screensize [width] [height] | Specify a resolution, otherwise use resolution of display |
|
| --screensize [width] [height] | Specify a resolution, otherwise use resolution of display |
|
||||||
| --uiscale [scale] | Scale up UI elements by integer amounts for high resolution screen |
|
| --uiscale [scale] | Scale up UI elements by integer amounts for high resolution screen |
|
||||||
| --fullscreen | Render fullscreen rather than in a window |
|
| --fullscreen | Render fullscreen rather than in a window |
|
||||||
|
@ -108,7 +124,7 @@ I've been using these files:
|
||||||
* [Airport IATA codes](https://www.naturalearthdata.com/http//www.naturalearthdata.com/download/10m/cultural/ne_10m_airports.zip)
|
* [Airport IATA codes](https://www.naturalearthdata.com/http//www.naturalearthdata.com/download/10m/cultural/ne_10m_airports.zip)
|
||||||
* [Airport runway geometry](https://opendata.arcgis.com/datasets/4d8fa46181aa470d809776c57a8ab1f6_0.zip)
|
* [Airport runway geometry](https://opendata.arcgis.com/datasets/4d8fa46181aa470d809776c57a8ab1f6_0.zip)
|
||||||
|
|
||||||
The bash script getmap.sh will download (so long as the links don't break) and convert these. Alternatiely, you can pass shapefiles and other arguments to mapconverter.py directly
|
The bash script getmap.sh will download (so long as the links don't break) and convert these. Alternatively, you can pass shapefiles and other arguments to mapconverter.py directly
|
||||||
|
|
||||||
### MAPCONVERTER.PY RUNTIME OPTIONS
|
### MAPCONVERTER.PY RUNTIME OPTIONS
|
||||||
|
|
||||||
|
@ -138,6 +154,7 @@ This software was originally intended for Raspberry Pi devices, and it is curren
|
||||||
* [Noelec Nano V3](https://www.nooelec.com/store/nesdr-nano-three.html)
|
* [Noelec Nano V3](https://www.nooelec.com/store/nesdr-nano-three.html)
|
||||||
* Stratux V2 \*very low power but hard to find
|
* Stratux V2 \*very low power but hard to find
|
||||||
|
|
||||||
|
If you want to print the case in the GIF shown above, you can [download it here](https://github.com/nmatsuda/viz1090_case).
|
||||||
|
|
||||||
If running as a front end only, with a separate dump1090 server, the best option is to use an Android phone, such as the Pixel 2, which significantly outperforms a Raspberry Pi 4.
|
If running as a front end only, with a separate dump1090 server, the best option is to use an Android phone, such as the Pixel 2, which significantly outperforms a Raspberry Pi 4.
|
||||||
|
|
||||||
|
|
94
Style.h
Normal file
94
Style.h
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
#ifndef STYLE_H
|
||||||
|
#define STYLE_H
|
||||||
|
|
||||||
|
#include "SDL2/SDL.h"
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// This should go to a full theming class
|
||||||
|
//
|
||||||
|
typedef struct Style {
|
||||||
|
SDL_Color backgroundColor;
|
||||||
|
|
||||||
|
SDL_Color selectedColor;
|
||||||
|
SDL_Color planeColor;
|
||||||
|
SDL_Color planeGoneColor;
|
||||||
|
SDL_Color trailColor;
|
||||||
|
|
||||||
|
SDL_Color geoColor;
|
||||||
|
SDL_Color airportColor;
|
||||||
|
|
||||||
|
SDL_Color labelColor;
|
||||||
|
SDL_Color labelLineColor;
|
||||||
|
SDL_Color subLabelColor;
|
||||||
|
SDL_Color labelBackground;
|
||||||
|
|
||||||
|
SDL_Color scaleBarColor;
|
||||||
|
SDL_Color buttonColor;
|
||||||
|
SDL_Color buttonBackground;
|
||||||
|
SDL_Color buttonOutline;
|
||||||
|
|
||||||
|
SDL_Color clickColor;
|
||||||
|
|
||||||
|
SDL_Color black;
|
||||||
|
SDL_Color white;
|
||||||
|
SDL_Color red;
|
||||||
|
SDL_Color green;
|
||||||
|
SDL_Color blue;
|
||||||
|
|
||||||
|
//
|
||||||
|
// todo separate style stuff
|
||||||
|
//
|
||||||
|
|
||||||
|
Style() {
|
||||||
|
|
||||||
|
SDL_Color pink = {249,38,114,255};
|
||||||
|
|
||||||
|
SDL_Color purple = {85, 0, 255,255};
|
||||||
|
SDL_Color purple_dark = {33, 0, 122,255};
|
||||||
|
|
||||||
|
SDL_Color blue = {102,217,239,255};
|
||||||
|
SDL_Color blue_dark = {102,217,239,255};
|
||||||
|
|
||||||
|
SDL_Color green = {0,255,234,255};
|
||||||
|
SDL_Color green_dark = {24,100,110,255};
|
||||||
|
|
||||||
|
SDL_Color yellow = {216,255,0,255};
|
||||||
|
SDL_Color yellow_dark = {90,133,50,255};
|
||||||
|
|
||||||
|
SDL_Color orange = {253,151,31,255};
|
||||||
|
SDL_Color grey_light = {196,196,196,255};
|
||||||
|
SDL_Color grey = {127,127,127,255};
|
||||||
|
SDL_Color grey_dark = {64,64,64,255};
|
||||||
|
|
||||||
|
black = {0,0,0,255};
|
||||||
|
white = {255,255,255,255};
|
||||||
|
red = {255,0,0,255};
|
||||||
|
green = {0,255,0,255};
|
||||||
|
blue = {0,0,255,255};
|
||||||
|
|
||||||
|
|
||||||
|
backgroundColor = black;
|
||||||
|
|
||||||
|
selectedColor = pink;
|
||||||
|
planeColor = yellow;
|
||||||
|
planeGoneColor = grey;
|
||||||
|
trailColor = yellow_dark;
|
||||||
|
|
||||||
|
geoColor = purple_dark;
|
||||||
|
airportColor = purple;
|
||||||
|
|
||||||
|
labelColor = white;
|
||||||
|
labelLineColor = grey_dark;
|
||||||
|
subLabelColor = grey;
|
||||||
|
labelBackground = black;
|
||||||
|
scaleBarColor = grey_light;
|
||||||
|
buttonColor = grey_light;
|
||||||
|
buttonBackground = black;
|
||||||
|
buttonOutline = grey_light;
|
||||||
|
|
||||||
|
clickColor = grey;
|
||||||
|
}
|
||||||
|
} Style;
|
||||||
|
|
||||||
|
#endif
|
73
Text.cpp
Normal file
73
Text.cpp
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
#include "SDL2/SDL2_gfxPrimitives.h"
|
||||||
|
|
||||||
|
#include "Text.h"
|
||||||
|
|
||||||
|
SDL_Rect Text::drawString(std::string text, int x, int y, TTF_Font *font, SDL_Color color)
|
||||||
|
{
|
||||||
|
SDL_Rect dest = {0,0,0,0};
|
||||||
|
|
||||||
|
if(!text.length()) {
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Surface *surface;
|
||||||
|
|
||||||
|
surface = TTF_RenderUTF8_Solid(font, text.c_str(), color);
|
||||||
|
|
||||||
|
if (surface == NULL)
|
||||||
|
{
|
||||||
|
printf("Couldn't create String %s: %s\n", text.c_str(), SDL_GetError());
|
||||||
|
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
dest.x = x;
|
||||||
|
dest.y = y;
|
||||||
|
dest.w = surface->w;
|
||||||
|
dest.h = surface->h;
|
||||||
|
|
||||||
|
SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, surface);
|
||||||
|
SDL_RenderCopy(renderer, texture, NULL, &dest);
|
||||||
|
SDL_DestroyTexture(texture);
|
||||||
|
SDL_FreeSurface(surface);
|
||||||
|
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Rect Text::drawStringBG(std::string text, int x, int y, TTF_Font *font, SDL_Color color, SDL_Color bgColor) {
|
||||||
|
SDL_Rect dest = {0,0,0,0};
|
||||||
|
|
||||||
|
if(!text.length()) {
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_Surface *surface;
|
||||||
|
|
||||||
|
surface = TTF_RenderUTF8_Shaded(font, text.c_str(), color, bgColor);
|
||||||
|
|
||||||
|
if (surface == NULL)
|
||||||
|
{
|
||||||
|
printf("Couldn't create String %s: %s\n", text.c_str(), SDL_GetError());
|
||||||
|
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
dest.x = x;
|
||||||
|
dest.y = y;
|
||||||
|
dest.w = surface->w;
|
||||||
|
dest.h = surface->h;
|
||||||
|
|
||||||
|
SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, surface);
|
||||||
|
SDL_RenderCopy(renderer, texture, NULL, &dest);
|
||||||
|
SDL_DestroyTexture(texture);
|
||||||
|
SDL_FreeSurface(surface);
|
||||||
|
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// check if text has changed and surface exists
|
||||||
|
// redraw existing surface
|
||||||
|
// or make new surface
|
||||||
|
// for BG, draw bg size of surface
|
||||||
|
// draw surface
|
99
View.h
99
View.h
|
@ -34,19 +34,19 @@
|
||||||
|
|
||||||
#include "AppData.h"
|
#include "AppData.h"
|
||||||
#include "Map.h"
|
#include "Map.h"
|
||||||
|
#include "Style.h"
|
||||||
#include "SDL2/SDL.h"
|
#include "SDL2/SDL.h"
|
||||||
#include "SDL2/SDL_ttf.h"
|
#include "SDL2/SDL_ttf.h"
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
|
||||||
//defs - should all move to config file setup
|
//defs - should all move to config file setup
|
||||||
#define ROUND_RADIUS 3 //radius of text box corners
|
#define ROUND_RADIUS 3 //radius of text box corners
|
||||||
|
|
||||||
#define CENTEROFFSET .5 //vertical offset for middle of screen
|
|
||||||
|
|
||||||
#define TRAIL_LENGTH 120
|
#define TRAIL_LENGTH 120
|
||||||
#define TRAIL_TTL 240.0
|
#define TRAIL_TTL 240.0
|
||||||
#define DISPLAY_ACTIVE 30
|
#define DISPLAY_ACTIVE 30.0
|
||||||
#define TRAIL_TTL_STEP 2
|
#define TRAIL_TTL_STEP 2
|
||||||
|
|
||||||
#define MIN_MAP_FEATURE 2
|
#define MIN_MAP_FEATURE 2
|
||||||
|
@ -58,90 +58,6 @@
|
||||||
#define LATLONMULT 111.195 // 6371.0 * M_PI / 180.0
|
#define LATLONMULT 111.195 // 6371.0 * M_PI / 180.0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// This should go to a full theming class
|
|
||||||
//
|
|
||||||
typedef struct Style {
|
|
||||||
SDL_Color backgroundColor;
|
|
||||||
|
|
||||||
SDL_Color selectedColor;
|
|
||||||
SDL_Color planeColor;
|
|
||||||
SDL_Color planeGoneColor;
|
|
||||||
SDL_Color trailColor;
|
|
||||||
|
|
||||||
SDL_Color geoColor;
|
|
||||||
SDL_Color airportColor;
|
|
||||||
|
|
||||||
SDL_Color labelColor;
|
|
||||||
SDL_Color labelLineColor;
|
|
||||||
SDL_Color subLabelColor;
|
|
||||||
SDL_Color labelBackground;
|
|
||||||
|
|
||||||
SDL_Color scaleBarColor;
|
|
||||||
SDL_Color buttonColor;
|
|
||||||
SDL_Color buttonBackground;
|
|
||||||
SDL_Color buttonOutline;
|
|
||||||
|
|
||||||
SDL_Color clickColor;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// todo separate style stuff
|
|
||||||
//
|
|
||||||
|
|
||||||
Style() {
|
|
||||||
|
|
||||||
SDL_Color pink = {249,38,114,255};
|
|
||||||
|
|
||||||
SDL_Color purple = {85, 0, 255,255};
|
|
||||||
SDL_Color purple_dark = {33, 0, 122,255};
|
|
||||||
|
|
||||||
SDL_Color blue = {102,217,239,255};
|
|
||||||
SDL_Color blue_dark = {102,217,239,255};
|
|
||||||
|
|
||||||
SDL_Color green = {0,255,234,255};
|
|
||||||
SDL_Color green_dark = {24,100,110,255};
|
|
||||||
|
|
||||||
SDL_Color yellow = {216,255,0,255};
|
|
||||||
SDL_Color yellow_dark = {90,133,50,255};
|
|
||||||
|
|
||||||
SDL_Color orange = {253,151,31,255};
|
|
||||||
SDL_Color grey_light = {196,196,196,255};
|
|
||||||
SDL_Color grey = {127,127,127,255};
|
|
||||||
SDL_Color grey_dark = {64,64,64,255};
|
|
||||||
SDL_Color black = {0,0,0,255};
|
|
||||||
SDL_Color white = {255,255,255,255};
|
|
||||||
SDL_Color red = {255,0,0,255};
|
|
||||||
|
|
||||||
|
|
||||||
backgroundColor = black;
|
|
||||||
|
|
||||||
selectedColor = pink;
|
|
||||||
planeColor = yellow;
|
|
||||||
planeGoneColor = grey;
|
|
||||||
trailColor = yellow_dark;
|
|
||||||
|
|
||||||
geoColor = purple_dark;
|
|
||||||
airportColor = purple;
|
|
||||||
|
|
||||||
labelColor = white;
|
|
||||||
labelLineColor = grey_dark;
|
|
||||||
subLabelColor = grey;
|
|
||||||
labelBackground = black;
|
|
||||||
scaleBarColor = grey_light;
|
|
||||||
buttonColor = grey_light;
|
|
||||||
buttonBackground = black;
|
|
||||||
buttonOutline = grey_light;
|
|
||||||
|
|
||||||
clickColor = grey;
|
|
||||||
}
|
|
||||||
} Style;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class View {
|
class View {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -165,8 +81,8 @@ class View {
|
||||||
|
|
||||||
TTF_Font* loadFont(const char *name, int size);
|
TTF_Font* loadFont(const char *name, int size);
|
||||||
void closeFont(TTF_Font *font);
|
void closeFont(TTF_Font *font);
|
||||||
void drawString(std::string text, int x, int y, TTF_Font *font, SDL_Color color);
|
SDL_Rect drawString(std::string text, int x, int y, TTF_Font *font, SDL_Color color);
|
||||||
void drawStringBG(std::string text, int x, int y, TTF_Font *font, SDL_Color color, SDL_Color bgColor);
|
SDL_Rect drawStringBG(std::string text, int x, int y, TTF_Font *font, SDL_Color color, SDL_Color bgColor);
|
||||||
void drawStatusBox(int *left, int *top, std::string label, std::string message, SDL_Color color);
|
void drawStatusBox(int *left, int *top, std::string label, std::string message, SDL_Color color);
|
||||||
void drawStatus();
|
void drawStatus();
|
||||||
|
|
||||||
|
@ -191,8 +107,7 @@ class View {
|
||||||
void drawGeography();
|
void drawGeography();
|
||||||
void drawSignalMarks(Aircraft *p, int x, int y);
|
void drawSignalMarks(Aircraft *p, int x, int y);
|
||||||
void drawPlaneText(Aircraft *p);
|
void drawPlaneText(Aircraft *p);
|
||||||
void drawSelectedAircraftText(Aircraft *p);
|
float resolveLabelConflicts();
|
||||||
void resolveLabelConflicts();
|
|
||||||
void drawPlanes();
|
void drawPlanes();
|
||||||
void animateCenterAbsolute(float x, float y);
|
void animateCenterAbsolute(float x, float y);
|
||||||
void moveCenterAbsolute(float x, float y);
|
void moveCenterAbsolute(float x, float y);
|
||||||
|
@ -215,6 +130,8 @@ class View {
|
||||||
////////////////
|
////////////////
|
||||||
bool metric;
|
bool metric;
|
||||||
|
|
||||||
|
bool fps;
|
||||||
|
|
||||||
float maxDist;
|
float maxDist;
|
||||||
float currentMaxDist;
|
float currentMaxDist;
|
||||||
|
|
||||||
|
|
61
flake.lock
Normal file
61
flake.lock
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"flake-utils": {
|
||||||
|
"inputs": {
|
||||||
|
"systems": "systems"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1731533236,
|
||||||
|
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1739758141,
|
||||||
|
"narHash": "sha256-uq6A2L7o1/tR6VfmYhZWoVAwb3gTy7j4Jx30MIrH0rE=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "c618e28f70257593de75a7044438efc1c1fc0791",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"ref": "nixos-24.11",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-utils": "flake-utils",
|
||||||
|
"nixpkgs": "nixpkgs"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"systems": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1681028828,
|
||||||
|
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
50
flake.nix
Normal file
50
flake.nix
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
{
|
||||||
|
# TODO desc
|
||||||
|
description = "viz1090";
|
||||||
|
|
||||||
|
inputs = {
|
||||||
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11";
|
||||||
|
flake-utils.url = "github:numtide/flake-utils";
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs = {
|
||||||
|
self,
|
||||||
|
nixpkgs,
|
||||||
|
flake-utils,
|
||||||
|
}:
|
||||||
|
flake-utils.lib.eachDefaultSystem (system: let
|
||||||
|
pkgs = import nixpkgs {
|
||||||
|
inherit system;
|
||||||
|
};
|
||||||
|
in rec
|
||||||
|
{
|
||||||
|
# Nix formatter, run using `$ nix fmt`
|
||||||
|
formatter = pkgs.alejandra;
|
||||||
|
|
||||||
|
# Exports the package
|
||||||
|
# Build with `$ nix build`
|
||||||
|
packages.viz1090 = pkgs.callPackage ./nix/viz1090.nix {inherit self system;};
|
||||||
|
packages.viz1090-mapdata = pkgs.callPackage ./nix/viz1090-mapdata.nix {};
|
||||||
|
packages.default = packages.viz1090;
|
||||||
|
|
||||||
|
# Creates a shell with the necessary dependencies
|
||||||
|
# Enter using `$ nix develop`
|
||||||
|
devShell = pkgs.mkShell {
|
||||||
|
buildInputs = with pkgs; [
|
||||||
|
rtl-sdr-librtlsdr
|
||||||
|
SDL2
|
||||||
|
SDL2_ttf
|
||||||
|
SDL2_gfx
|
||||||
|
gdal
|
||||||
|
python3
|
||||||
|
python312Packages.pip
|
||||||
|
python312Packages.shapely
|
||||||
|
python312Packages.fiona
|
||||||
|
python312Packages.tqdm
|
||||||
|
unzip
|
||||||
|
python312Packages.requests
|
||||||
|
git
|
||||||
|
];
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
24
getmap.sh
24
getmap.sh
|
@ -1,12 +1,24 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
wget https://www.naturalearthdata.com/http//www.naturalearthdata.com/download/10m/cultural/ne_10m_admin_1_states_provinces.zip
|
mkdir -p mapdata
|
||||||
wget https://www.naturalearthdata.com/http//www.naturalearthdata.com/download/10m/cultural/ne_10m_populated_places.zip
|
pushd mapdata > /dev/null
|
||||||
wget https://www.naturalearthdata.com/http//www.naturalearthdata.com/download/10m/cultural/ne_10m_airports.zip
|
|
||||||
|
wget --no-verbose https://naciscdn.org/naturalearth/10m/cultural/ne_10m_admin_1_states_provinces.zip
|
||||||
|
wget --no-verbose https://naciscdn.org/naturalearth/10m/cultural/ne_10m_populated_places.zip
|
||||||
|
wget --no-verbose https://naciscdn.org/naturalearth/10m/cultural/ne_10m_airports.zip
|
||||||
|
|
||||||
#this may not be up to date
|
#this may not be up to date
|
||||||
wget https://opendata.arcgis.com/datasets/4d8fa46181aa470d809776c57a8ab1f6_0.zip
|
wget --no-verbose https://opendata.arcgis.com/datasets/4d8fa46181aa470d809776c57a8ab1f6_0.zip
|
||||||
|
|
||||||
unzip '*.zip'
|
for file in *.zip; do
|
||||||
|
unzip -o "${file}"
|
||||||
|
rm "${file}"
|
||||||
|
done
|
||||||
|
|
||||||
python3 mapconverter.py --mapfile ne_10m_admin_1_states_provinces.shp --mapnames ne_10m_populated_places.shp --airportfile Runways.shp --airportnames ne_10m_airports.shp
|
popd > /dev/null
|
||||||
|
|
||||||
|
python3 mapconverter.py \
|
||||||
|
--mapfile mapdata/ne_10m_admin_1_states_provinces.shp \
|
||||||
|
--mapnames mapdata/ne_10m_populated_places.shp \
|
||||||
|
--airportfile mapdata/Runways.shp \
|
||||||
|
--airportnames mapdata/ne_10m_airports.shp
|
||||||
|
|
|
@ -38,7 +38,7 @@ def extractLines(shapefile, tolerance):
|
||||||
elif(simplified.geom_type == "MultiPolygon" or simplified.geom_type == "Polygon"):
|
elif(simplified.geom_type == "MultiPolygon" or simplified.geom_type == "Polygon"):
|
||||||
|
|
||||||
if(simplified.boundary.geom_type == "MultiLineString"):
|
if(simplified.boundary.geom_type == "MultiLineString"):
|
||||||
for boundary in simplified.boundary:
|
for boundary in simplified.boundary.geoms:
|
||||||
outlist.extend(convertLinestring(boundary))
|
outlist.extend(convertLinestring(boundary))
|
||||||
else:
|
else:
|
||||||
outlist.extend(convertLinestring(simplified.boundary))
|
outlist.extend(convertLinestring(simplified.boundary))
|
||||||
|
|
70
nix/viz1090-mapdata.nix
Normal file
70
nix/viz1090-mapdata.nix
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
{
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
stdenv,
|
||||||
|
fetchFromGitea,
|
||||||
|
}: let
|
||||||
|
runways = fetchTarball {
|
||||||
|
url = "https://opendata.arcgis.com/datasets/4d8fa46181aa470d809776c57a8ab1f6_0.zip";
|
||||||
|
sha256 = "sha256:1ivwx8glk8yk68nmqz467yzvlb3l66l1s3ibmd9p41wz737lmz88";
|
||||||
|
};
|
||||||
|
provinces = fetchTarball {
|
||||||
|
url = "https://naciscdn.org/naturalearth/10m/cultural/ne_10m_admin_1_states_provinces.zip";
|
||||||
|
sha256 = "sha256:06ai02b8rfsfzpa0gq4nsg29lxvwy4zvjw44099hc78vr7dkfsdp";
|
||||||
|
};
|
||||||
|
places = fetchTarball {
|
||||||
|
url = "https://naciscdn.org/naturalearth/10m/cultural/ne_10m_populated_places.zip";
|
||||||
|
sha256 = "sha256:1dhh569520f02yml1m5zp2znjv85cqbccl4nvpmigynxd37kid3j";
|
||||||
|
};
|
||||||
|
airports = fetchTarball {
|
||||||
|
url = "https://naciscdn.org/naturalearth/10m/cultural/ne_10m_airports.zip";
|
||||||
|
sha256 = "sha256:0893zg63ygr2l2d1wpyigls1syfkryjlygvnbbjikpqk5i5cwr56";
|
||||||
|
};
|
||||||
|
in
|
||||||
|
stdenv.mkDerivation rec {
|
||||||
|
pname = "viz1090-mapdata";
|
||||||
|
version = "0.1.0";
|
||||||
|
|
||||||
|
src = fetchFromGitea {
|
||||||
|
domain = "git.vulpecula.zone";
|
||||||
|
owner = "tasiaiso";
|
||||||
|
repo = pname;
|
||||||
|
rev = "d1f53019b22a9e605506bed90fcffcdc5f7e6186";
|
||||||
|
hash = "sha256-gtv0u7o+5fqVgA0CHDWdZr0h9A1Nbky1+okHvSv1cVU=";
|
||||||
|
};
|
||||||
|
|
||||||
|
nativeBuildInputs = with pkgs; [
|
||||||
|
python3
|
||||||
|
python312Packages.pip
|
||||||
|
python312Packages.shapely
|
||||||
|
python312Packages.fiona
|
||||||
|
python312Packages.tqdm
|
||||||
|
python312Packages.requests
|
||||||
|
];
|
||||||
|
|
||||||
|
buildPhase = ''
|
||||||
|
mkdir -p mapdata
|
||||||
|
|
||||||
|
cp ${runways}/* mapdata
|
||||||
|
cp ${provinces}/* mapdata
|
||||||
|
cp ${places}/* mapdata
|
||||||
|
cp ${airports}/* mapdata
|
||||||
|
|
||||||
|
python3 mapconverter.py \
|
||||||
|
--mapfile mapdata/ne_10m_admin_1_states_provinces.shp \
|
||||||
|
--mapnames mapdata/ne_10m_populated_places.shp \
|
||||||
|
--airportfile mapdata/Runways.shp \
|
||||||
|
--airportnames mapdata/ne_10m_airports.shp
|
||||||
|
'';
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
mkdir -p $out $out/font
|
||||||
|
|
||||||
|
cp airportdata.bin $out
|
||||||
|
cp airportnames $out
|
||||||
|
cp mapdata.bin $out
|
||||||
|
cp mapnames $out
|
||||||
|
|
||||||
|
cp font/* $out/font
|
||||||
|
'';
|
||||||
|
}
|
116
nix/viz1090.nix
Normal file
116
nix/viz1090.nix
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
{
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
stdenv,
|
||||||
|
fetchFromGitea,
|
||||||
|
self,
|
||||||
|
system,
|
||||||
|
}: let
|
||||||
|
viz1090-mapdata = self.packages.${system}.viz1090-mapdata;
|
||||||
|
in
|
||||||
|
stdenv.mkDerivation rec {
|
||||||
|
pname = "viz1090";
|
||||||
|
version = "0.1.0";
|
||||||
|
|
||||||
|
src = fetchFromGitea {
|
||||||
|
domain = "git.vulpecula.zone";
|
||||||
|
owner = "tasiaiso";
|
||||||
|
repo = pname;
|
||||||
|
rev = "1922324b40f84fd449cec3fbfdade8aa33597bf6";
|
||||||
|
hash = "sha256-bPVFKbGtPXOitzzHb3yJ6XW3fRh8PF/7kfP7EJkJX3c=";
|
||||||
|
};
|
||||||
|
|
||||||
|
nativeBuildInputs = with pkgs; [
|
||||||
|
rtl-sdr-librtlsdr
|
||||||
|
SDL2
|
||||||
|
SDL2_ttf
|
||||||
|
SDL2_gfx
|
||||||
|
gdal
|
||||||
|
git
|
||||||
|
];
|
||||||
|
|
||||||
|
buildInputs = [
|
||||||
|
viz1090-mapdata
|
||||||
|
];
|
||||||
|
|
||||||
|
buildPhase = ''
|
||||||
|
echo "diff --git a/Makefile b/Makefile
|
||||||
|
index 5e60779..d5b30ab 100644
|
||||||
|
--- a/Makefile
|
||||||
|
+++ b/Makefile
|
||||||
|
@@ -3,7 +3,7 @@
|
||||||
|
# sure that the variable PREFIX is defined, e.g. make PREFIX=/usr/local
|
||||||
|
#
|
||||||
|
|
||||||
|
-CXXFLAGS=-O2 -std=c++11 -g
|
||||||
|
+CXXFLAGS=-O2 -std=c++11 -g -I ${pkgs.SDL2.dev}/include/SDL2/
|
||||||
|
LIBS= -lm -lSDL2 -lSDL2_ttf -lSDL2_gfx -g
|
||||||
|
CXX=g++
|
||||||
|
|
||||||
|
diff --git a/Map.cpp b/Map.cpp
|
||||||
|
index cd798ec..c5736bd 100644
|
||||||
|
--- a/Map.cpp
|
||||||
|
+++ b/Map.cpp
|
||||||
|
@@ -189,7 +189,7 @@ std::vector<Line*> Map::getLines(float screen_lat_min, float screen_lat_max, flo
|
||||||
|
Map::Map() {
|
||||||
|
FILE *fileptr;
|
||||||
|
|
||||||
|
- if((fileptr = fopen(\"mapdata.bin\", \"rb\"))) {
|
||||||
|
+ if((fileptr = fopen(\"${viz1090-mapdata}/mapdata.bin\", \"rb\"))) {
|
||||||
|
|
||||||
|
|
||||||
|
fseek(fileptr, 0, SEEK_END);
|
||||||
|
@@ -255,7 +255,7 @@ Map::Map() {
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
|
- if((fileptr = fopen(\"airportdata.bin\", \"rb\"))) {
|
||||||
|
+ if((fileptr = fopen(\"${viz1090-mapdata}/airportdata.bin\", \"rb\"))) {
|
||||||
|
fseek(fileptr, 0, SEEK_END);
|
||||||
|
airportPoints_count = ftell(fileptr) / sizeof(float);
|
||||||
|
rewind(fileptr);
|
||||||
|
@@ -350,7 +350,7 @@ Map::Map() {
|
||||||
|
|
||||||
|
infile.close();
|
||||||
|
|
||||||
|
- infile.open(\"airportnames\");
|
||||||
|
+ infile.open(\"${viz1090-mapdata}/airportnames\");
|
||||||
|
|
||||||
|
|
||||||
|
while (std::getline(infile, line))
|
||||||
|
|
||||||
|
diff --git a/View.cpp b/View.cpp
|
||||||
|
index d5dace7..90f6165 100644
|
||||||
|
--- a/View.cpp
|
||||||
|
+++ b/View.cpp
|
||||||
|
@@ -174,13 +174,13 @@ void View::closeFont(TTF_Font *font)
|
||||||
|
|
||||||
|
|
||||||
|
void View::font_init() {
|
||||||
|
- mapFont = loadFont(\"font/TerminusTTF-4.46.0.ttf\", 12 * screen_uiscale);
|
||||||
|
- mapBoldFont = loadFont(\"font/TerminusTTF-Bold-4.46.0.ttf\", 12 * screen_uiscale);
|
||||||
|
+ mapFont = loadFont(\"${viz1090-mapdata}/font/TerminusTTF-4.46.0.ttf\", 12 * screen_uiscale);
|
||||||
|
+ mapBoldFont = loadFont(\"${viz1090-mapdata}/font/TerminusTTF-Bold-4.46.0.ttf\", 12 * screen_uiscale);
|
||||||
|
|
||||||
|
- listFont = loadFont(\"font/TerminusTTF-4.46.0.ttf\", 12 * screen_uiscale);
|
||||||
|
+ listFont = loadFont(\"${viz1090-mapdata}/font/TerminusTTF-4.46.0.ttf\", 12 * screen_uiscale);
|
||||||
|
|
||||||
|
- messageFont = loadFont(\"font/TerminusTTF-Bold-4.46.0.ttf\", 12 * screen_uiscale);
|
||||||
|
- labelFont = loadFont(\"font/TerminusTTF-Bold-4.46.0.ttf\", 12 * screen_uiscale);
|
||||||
|
+ messageFont = loadFont(\"${viz1090-mapdata}/font/TerminusTTF-Bold-4.46.0.ttf\", 12 * screen_uiscale);
|
||||||
|
+ labelFont = loadFont(\"${viz1090-mapdata}/font/TerminusTTF-Bold-4.46.0.ttf\", 12 * screen_uiscale);
|
||||||
|
|
||||||
|
mapFontWidth = 5 * screen_uiscale;
|
||||||
|
mapFontHeight = 12 * screen_uiscale;
|
||||||
|
" | git apply -
|
||||||
|
|
||||||
|
cat Map.cpp | grep mapdata
|
||||||
|
|
||||||
|
make -j $NIX_BUILD_CORES
|
||||||
|
'';
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
mkdir -p $out/bin
|
||||||
|
cp -v viz1090 $out/bin
|
||||||
|
'';
|
||||||
|
}
|
23
viz1090.cpp
23
viz1090.cpp
|
@ -48,16 +48,17 @@ void showHelp(void) {
|
||||||
"-----------------------------------------------------------------------------\n"
|
"-----------------------------------------------------------------------------\n"
|
||||||
"| viz1090 ADSB Viewer Ver : 0.1 |\n"
|
"| viz1090 ADSB Viewer Ver : 0.1 |\n"
|
||||||
"-----------------------------------------------------------------------------\n"
|
"-----------------------------------------------------------------------------\n"
|
||||||
"--server <IPv4/hosname> TCP Beast output listen IPv4 (default: 127.0.0.1)\n"
|
"--fps Show current framerate\n"
|
||||||
"--port <port> TCP Beast output listen port (default: 30005)\n"
|
"--fullscreen Start fullscreen\n"
|
||||||
"--lat <latitude> Latitide in degrees\n"
|
"--help Show this help\n"
|
||||||
"--lon <longitude> Longitude in degrees\n"
|
"--lat <latitude> Latitude in degrees\n"
|
||||||
"--metric Use metric units\n"
|
"--lon <longitude> Longitude in degrees\n"
|
||||||
"--help Show this help\n"
|
"--metric Use metric units\n"
|
||||||
"--uiscale <factor> UI global scaling (default: 1)\n"
|
"--port <port> TCP Beast output listen port (default: 30005)\n"
|
||||||
"--screensize <width> <height> Set frame buffer resolution (default: screen resolution)\n"
|
"--server <IPv4/hosname> TCP Beast output listen IPv4 (default: 127.0.0.1)\n"
|
||||||
"--screenindex <i> Set the index of the display to use (default: 0)\n"
|
"--screensize <width> <height> Set frame buffer resolution (default: screen resolution)\n"
|
||||||
"--fullscreen Start fullscreen\n"
|
"--screenindex <i> Set the index of the display to use (default: 0)\n"
|
||||||
|
"--uiscale <factor> UI global scaling (default: 1)\n"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,6 +95,8 @@ int main(int argc, char **argv) {
|
||||||
view.centerLon = appData.modes.fUserLon;
|
view.centerLon = appData.modes.fUserLon;
|
||||||
} else if (!strcmp(argv[j],"--metric")) {
|
} else if (!strcmp(argv[j],"--metric")) {
|
||||||
view.metric = 1;
|
view.metric = 1;
|
||||||
|
} else if (!strcmp(argv[j],"--fps")) {
|
||||||
|
view.fps = 1;
|
||||||
} else if (!strcmp(argv[j],"--fullscreen")) {
|
} else if (!strcmp(argv[j],"--fullscreen")) {
|
||||||
view.fullscreen = 1;
|
view.fullscreen = 1;
|
||||||
} else if (!strcmp(argv[j],"--screenindex")) {
|
} else if (!strcmp(argv[j],"--screenindex")) {
|
||||||
|
|
Loading…
Reference in a new issue