2017-09-14 16:39:56 +02:00
|
|
|
#include "dump1090.h"
|
2017-09-14 05:21:36 +02:00
|
|
|
#include "draw.h"
|
|
|
|
#include "parula.h"
|
2017-09-17 16:46:48 +02:00
|
|
|
#include "magma.h"
|
2017-09-15 04:13:02 +02:00
|
|
|
#include "SDL/SDL_gfxPrimitives.h"
|
2017-09-14 05:21:36 +02:00
|
|
|
|
2017-09-16 04:25:26 +02:00
|
|
|
#define LOGMAXDIST 1000.0
|
|
|
|
#define MAXDIST 50.0
|
2017-09-14 05:21:36 +02:00
|
|
|
|
2017-09-16 04:25:26 +02:00
|
|
|
#define AA 0
|
2017-09-15 16:57:20 +02:00
|
|
|
|
2017-09-17 16:46:48 +02:00
|
|
|
#define MAGMA 0
|
|
|
|
|
2017-09-14 05:21:36 +02:00
|
|
|
void CROSSVP(double *v, double *u, double *w)
|
|
|
|
{
|
|
|
|
v[0] = u[1]*w[2] - u[2]*(w)[1];
|
|
|
|
v[1] = u[2]*w[0] - u[0]*(w)[2];
|
|
|
|
v[2] = u[0]*w[1] - u[1]*(w)[0];
|
|
|
|
}
|
|
|
|
|
2017-09-15 16:57:20 +02:00
|
|
|
SDL_Color setColor(uint8_t r, uint8_t g, uint8_t b) {
|
|
|
|
SDL_Color out;
|
|
|
|
out.r = r;
|
|
|
|
out.g = g;
|
|
|
|
out.b = b;
|
|
|
|
return out;
|
|
|
|
}
|
2017-09-14 07:08:22 +02:00
|
|
|
|
2017-09-17 16:46:48 +02:00
|
|
|
SDL_Color signalToColor(int signal) {
|
|
|
|
SDL_Color planeColor;
|
|
|
|
|
|
|
|
if(signal > 127) {
|
|
|
|
signal = 127;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(signal < 0) {
|
|
|
|
planeColor = setColor(96, 96, 96);
|
|
|
|
} else {
|
|
|
|
if(MAGMA) {
|
|
|
|
planeColor = setColor(magma[signal][0], magma[signal][1], magma[signal][2]);
|
|
|
|
} else {
|
|
|
|
planeColor = setColor(parula[signal][0], parula[signal][1], parula[signal][2]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return planeColor;
|
|
|
|
}
|
|
|
|
|
2017-09-15 16:57:20 +02:00
|
|
|
int screenDist(double d) {
|
2017-09-16 04:25:26 +02:00
|
|
|
if(Modes.mapLogDist) {
|
|
|
|
return round((double)SCREEN_WIDTH * 0.5 * log(1.0+fabs(d)) / log(1.0+LOGMAXDIST));
|
2017-09-15 16:57:20 +02:00
|
|
|
} else {
|
2017-09-16 04:25:26 +02:00
|
|
|
return round((double)SCREEN_WIDTH * 0.5 * fabs(d) / MAXDIST);
|
2017-09-15 16:57:20 +02:00
|
|
|
}
|
2017-09-14 07:08:22 +02:00
|
|
|
}
|
2017-09-15 16:57:20 +02:00
|
|
|
|
|
|
|
void screenCoords(int *outX, int *outY, double dx, double dy) {
|
2017-09-16 04:25:26 +02:00
|
|
|
*outX = (SCREEN_WIDTH>>1) + ((dx>0) ? 1 : -1) * screenDist(dx);
|
|
|
|
*outY = (SCREEN_HEIGHT>>1) + ((dy>0) ? 1 : -1) * screenDist(dy);
|
2017-09-15 16:57:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
int outOfBounds(int x, int y) {
|
|
|
|
if(x < 0 || x >= SCREEN_WIDTH || y < 0 || y >= SCREEN_HEIGHT ) {
|
|
|
|
return 1;
|
|
|
|
} else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-14 07:08:22 +02:00
|
|
|
void drawPlaneHeading(double dx, double dy, double heading, int signal, char *flight)
|
2017-09-14 05:21:36 +02:00
|
|
|
{
|
2017-09-15 16:57:20 +02:00
|
|
|
int x, y;
|
|
|
|
screenCoords(&x, &y, dx, dy);
|
2017-09-14 07:08:22 +02:00
|
|
|
|
2017-09-15 16:57:20 +02:00
|
|
|
if(outOfBounds(x,y)) {
|
2017-09-14 07:08:22 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-09-17 16:46:48 +02:00
|
|
|
SDL_Color planeColor = signalToColor(signal);
|
2017-09-14 05:21:36 +02:00
|
|
|
|
|
|
|
double body = 8.0;
|
|
|
|
double wing = 6.0;
|
|
|
|
double tail = 3.0;
|
|
|
|
|
|
|
|
double vec[3];
|
|
|
|
vec[0] = sin(heading * M_PI / 180);
|
|
|
|
vec[1] = cos(heading * M_PI / 180);
|
|
|
|
vec[2] = 0;
|
|
|
|
|
|
|
|
double up[] = {0,0,1};
|
|
|
|
|
|
|
|
double out[3];
|
|
|
|
|
|
|
|
CROSSVP(out,vec,up);
|
|
|
|
|
|
|
|
int x1, x2, y1, y2;
|
|
|
|
|
|
|
|
//body
|
2017-09-15 16:57:20 +02:00
|
|
|
x1 = x + round(-body*vec[0]);
|
|
|
|
y1 = y + round(-body*vec[1]);
|
|
|
|
x2 = x + round(body*vec[0]);
|
|
|
|
y2 = y + round(body*vec[1]);
|
2017-09-14 05:21:36 +02:00
|
|
|
|
2017-09-16 04:25:26 +02:00
|
|
|
if(AA) {
|
|
|
|
aalineRGBA(game.screen,x1,y1,x2,y2,planeColor.r,planeColor.g,planeColor.b,SDL_ALPHA_OPAQUE);
|
2017-09-17 16:46:48 +02:00
|
|
|
aatrigonRGBA(game.screen, x + round(-wing*.35*out[0]), y + round(-wing*.35*out[1]), x + round(wing*.35*out[0]), y + round(wing*.35*out[1]), x1, y1,planeColor.r,planeColor.g,planeColor.b,SDL_ALPHA_OPAQUE);
|
|
|
|
aacircleRGBA(game.screen, x2,y2,1,planeColor.r,planeColor.g,planeColor.b,SDL_ALPHA_OPAQUE);
|
2017-09-16 04:25:26 +02:00
|
|
|
} else {
|
|
|
|
thickLineRGBA(game.screen,x,y,x2,y2,2,planeColor.r,planeColor.g,planeColor.b,SDL_ALPHA_OPAQUE);
|
2017-09-17 16:46:48 +02:00
|
|
|
filledTrigonRGBA(game.screen, x + round(-wing*.35*out[0]), y + round(-wing*.35*out[1]), x + round(wing*.35*out[0]), y + round(wing*.35*out[1]), x1, y1,planeColor.r,planeColor.g,planeColor.b,SDL_ALPHA_OPAQUE);
|
|
|
|
filledCircleRGBA(game.screen, x2,y2,1,planeColor.r,planeColor.g,planeColor.b,SDL_ALPHA_OPAQUE);
|
2017-09-16 04:25:26 +02:00
|
|
|
}
|
2017-09-14 05:21:36 +02:00
|
|
|
|
|
|
|
//wing
|
2017-09-15 16:57:20 +02:00
|
|
|
x1 = x + round(-wing*out[0]);
|
|
|
|
y1 = y + round(-wing*out[1]);
|
|
|
|
x2 = x + round(wing*out[0]);
|
|
|
|
y2 = y + round(wing*out[1]);
|
2017-09-14 05:21:36 +02:00
|
|
|
|
2017-09-16 04:25:26 +02:00
|
|
|
if(AA) {
|
2017-09-17 16:46:48 +02:00
|
|
|
aatrigonRGBA(game.screen, x1, y1, x2, y2, x+round(body*.35*vec[0]), y+round(body*.35*vec[1]),planeColor.r,planeColor.g,planeColor.b,SDL_ALPHA_OPAQUE);
|
2017-09-16 04:25:26 +02:00
|
|
|
} else {
|
2017-09-17 16:46:48 +02:00
|
|
|
filledTrigonRGBA(game.screen, x1, y1, x2, y2, x+round(body*.35*vec[0]), y+round(body*.35*vec[1]),planeColor.r,planeColor.g,planeColor.b,SDL_ALPHA_OPAQUE);
|
2017-09-16 04:25:26 +02:00
|
|
|
}
|
2017-09-14 05:21:36 +02:00
|
|
|
|
2017-09-17 16:46:48 +02:00
|
|
|
//tail
|
2017-09-16 04:25:26 +02:00
|
|
|
x1 = x + round(-body*.75*vec[0]) + round(-tail*out[0]);
|
|
|
|
y1 = y + round(-body*.75*vec[1]) + round(-tail*out[1]);
|
|
|
|
x2 = x + round(-body*.75*vec[0]) + round(tail*out[0]);
|
|
|
|
y2 = y + round(-body*.75*vec[1]) + round(tail*out[1]);
|
2017-09-14 05:21:36 +02:00
|
|
|
|
2017-09-16 04:25:26 +02:00
|
|
|
if(AA) {
|
2017-09-17 16:46:48 +02:00
|
|
|
aatrigonRGBA (game.screen, x1, y1, x2, y2, x+round(-body*.5*vec[0]), y+round(-body*.5*vec[1]),planeColor.r,planeColor.g,planeColor.b,SDL_ALPHA_OPAQUE);
|
2017-09-16 04:25:26 +02:00
|
|
|
} else {
|
|
|
|
filledTrigonRGBA (game.screen, x1, y1, x2, y2, x+round(-body*.5*vec[0]), y+round(-body*.5*vec[1]),planeColor.r,planeColor.g,planeColor.b,SDL_ALPHA_OPAQUE);
|
|
|
|
}
|
2017-09-14 05:21:36 +02:00
|
|
|
|
2017-09-17 17:38:22 +02:00
|
|
|
drawString(flight, x + 10, y + 10, game.font, planeColor);
|
2017-09-14 05:21:36 +02:00
|
|
|
}
|
|
|
|
|
2017-09-14 07:08:22 +02:00
|
|
|
void drawPlane(double dx, double dy, int signal)
|
2017-09-14 05:21:36 +02:00
|
|
|
{
|
2017-09-14 07:08:22 +02:00
|
|
|
|
2017-09-15 16:57:20 +02:00
|
|
|
int x, y;
|
|
|
|
screenCoords(&x, &y, dx, dy);
|
|
|
|
|
|
|
|
if(outOfBounds(x,y)) {
|
2017-09-14 07:08:22 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2017-09-17 16:46:48 +02:00
|
|
|
SDL_Color planeColor = signalToColor(signal);
|
2017-09-14 05:21:36 +02:00
|
|
|
|
|
|
|
int length = 3.0;
|
|
|
|
|
2017-09-15 16:57:20 +02:00
|
|
|
rectangleRGBA (game.screen, x - length, y - length, x+length, y + length, planeColor.r, planeColor.g, planeColor.b, SDL_ALPHA_OPAQUE);
|
2017-09-14 07:08:22 +02:00
|
|
|
}
|
|
|
|
|
2017-09-14 16:39:56 +02:00
|
|
|
void drawTrail(double *oldDx, double *oldDy, time_t * oldSeen, int idx) {
|
2017-09-15 04:13:02 +02:00
|
|
|
|
2017-09-15 16:57:20 +02:00
|
|
|
|
2017-09-14 16:39:56 +02:00
|
|
|
int currentIdx, prevIdx;
|
2017-09-14 07:08:22 +02:00
|
|
|
|
2017-09-15 16:57:20 +02:00
|
|
|
int currentX, currentY, prevX, prevY;
|
2017-09-14 07:08:22 +02:00
|
|
|
|
2017-09-14 16:39:56 +02:00
|
|
|
time_t now = time(NULL);
|
2017-09-14 07:08:22 +02:00
|
|
|
|
2017-09-14 16:39:56 +02:00
|
|
|
for(int i=0; i < (MODES_INTERACTIVE_TRAIL_LENGTH - 1); i++) {
|
|
|
|
currentIdx = (idx - i) % MODES_INTERACTIVE_TRAIL_LENGTH;
|
|
|
|
currentIdx = currentIdx < 0 ? currentIdx + MODES_INTERACTIVE_TRAIL_LENGTH : currentIdx;
|
|
|
|
prevIdx = (idx - (i + 1)) % MODES_INTERACTIVE_TRAIL_LENGTH;
|
|
|
|
prevIdx = prevIdx < 0 ? prevIdx + MODES_INTERACTIVE_TRAIL_LENGTH : prevIdx;
|
|
|
|
|
|
|
|
if(oldDx[currentIdx] == 0 || oldDy[currentIdx] == 0) {
|
2017-09-14 07:08:22 +02:00
|
|
|
continue;
|
|
|
|
}
|
2017-09-14 05:21:36 +02:00
|
|
|
|
2017-09-14 16:39:56 +02:00
|
|
|
if(oldDx[prevIdx] == 0 || oldDy[prevIdx] == 0) {
|
|
|
|
continue;
|
|
|
|
}
|
2017-09-14 07:08:22 +02:00
|
|
|
|
2017-09-15 16:57:20 +02:00
|
|
|
screenCoords(¤tX, ¤tY, oldDx[currentIdx], oldDy[currentIdx]);
|
2017-09-14 07:08:22 +02:00
|
|
|
|
2017-09-15 16:57:20 +02:00
|
|
|
screenCoords(&prevX, &prevY, oldDx[prevIdx], oldDy[prevIdx]);
|
2017-09-14 07:08:22 +02:00
|
|
|
|
2017-09-15 16:57:20 +02:00
|
|
|
if(outOfBounds(currentX,currentY)) {
|
|
|
|
return;
|
|
|
|
}
|
2017-09-14 07:08:22 +02:00
|
|
|
|
2017-09-15 16:57:20 +02:00
|
|
|
if(outOfBounds(prevX,prevY)) {
|
|
|
|
return;
|
|
|
|
}
|
2017-09-14 16:39:56 +02:00
|
|
|
|
|
|
|
double age = 1.0 - (double)(now - oldSeen[currentIdx]) / MODES_INTERACTIVE_TRAIL_TTL;
|
|
|
|
|
|
|
|
if(age < 0) {
|
|
|
|
age = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t colorVal = (uint8_t)floor(127.0 * age);
|
2017-09-16 04:25:26 +02:00
|
|
|
|
|
|
|
if(AA) {
|
2017-09-17 16:46:48 +02:00
|
|
|
aalineRGBA(game.screen, prevX, prevY, currentX, currentY,colorVal, colorVal, colorVal, SDL_ALPHA_OPAQUE);
|
2017-09-16 04:25:26 +02:00
|
|
|
} else {
|
2017-09-17 16:46:48 +02:00
|
|
|
thickLineRGBA(game.screen, prevX, prevY, currentX, currentY, 2, colorVal, colorVal, colorVal, SDL_ALPHA_OPAQUE);
|
2017-09-16 04:25:26 +02:00
|
|
|
}
|
2017-09-15 16:57:20 +02:00
|
|
|
}
|
2017-09-14 05:21:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void drawGrid()
|
|
|
|
{
|
2017-09-15 16:57:20 +02:00
|
|
|
int p1km = screenDist(1.0);
|
|
|
|
int p10km = screenDist(10.0);
|
|
|
|
int p100km = screenDist(100.0);
|
|
|
|
|
|
|
|
hlineRGBA (game.screen, 0, SCREEN_WIDTH, SCREEN_HEIGHT>>1, 127, 127, 127, SDL_ALPHA_OPAQUE);
|
|
|
|
vlineRGBA (game.screen, SCREEN_WIDTH>>1, 0, SCREEN_HEIGHT, 127, 127, 127, SDL_ALPHA_OPAQUE);
|
|
|
|
|
2017-09-17 16:46:48 +02:00
|
|
|
if(AA) {
|
|
|
|
aacircleRGBA (game.screen, SCREEN_WIDTH>>1, SCREEN_HEIGHT>>1, p1km, 249,38,114, SDL_ALPHA_OPAQUE);
|
2017-09-17 19:58:42 +02:00
|
|
|
aacircleRGBA (game.screen, SCREEN_WIDTH>>1, SCREEN_HEIGHT>>1, p10km, 187,29,86, SDL_ALPHA_OPAQUE);
|
|
|
|
aacircleRGBA (game.screen, SCREEN_WIDTH>>1, SCREEN_HEIGHT>>1, p100km, 125,19,57, SDL_ALPHA_OPAQUE);
|
2017-09-17 16:46:48 +02:00
|
|
|
} else {
|
|
|
|
circleRGBA (game.screen, SCREEN_WIDTH>>1, SCREEN_HEIGHT>>1, p1km, 249,38,114, SDL_ALPHA_OPAQUE);
|
2017-09-17 19:58:42 +02:00
|
|
|
circleRGBA (game.screen, SCREEN_WIDTH>>1, SCREEN_HEIGHT>>1, p10km, 187,29,86, SDL_ALPHA_OPAQUE);
|
|
|
|
circleRGBA (game.screen, SCREEN_WIDTH>>1, SCREEN_HEIGHT>>1, p100km, 125,19,57, SDL_ALPHA_OPAQUE);
|
2017-09-17 16:46:48 +02:00
|
|
|
}
|
2017-09-15 16:57:20 +02:00
|
|
|
|
2017-09-17 19:58:42 +02:00
|
|
|
drawString("1km", (SCREEN_WIDTH>>1) + p1km + 5, (SCREEN_HEIGHT>>1) + 5, game.font, setColor(249,38,114));
|
|
|
|
drawString("10km", (SCREEN_WIDTH>>1) + p10km + 5, (SCREEN_HEIGHT>>1) + 5, game.font, setColor(187,29,86));
|
|
|
|
drawString("100km", (SCREEN_WIDTH>>1) + p100km + 5, (SCREEN_HEIGHT>>1) + 5, game.font, setColor(125,19,57));
|
2017-09-14 05:21:36 +02:00
|
|
|
}
|
|
|
|
|
2017-09-17 16:46:48 +02:00
|
|
|
void drawGeography() {
|
|
|
|
int x1, y1, x2, y2;
|
|
|
|
for(int i=1; i<mapPoints_count/2; i++) {
|
|
|
|
|
|
|
|
if(!mapPoints_relative[i * 2] || !mapPoints_relative[(i - 1) * 2 + 1] || !mapPoints_relative[i * 2] || !mapPoints_relative[i * 2 + 1]) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
screenCoords(&x1, &y1, mapPoints_relative[(i - 1) * 2], -mapPoints_relative[(i - 1) * 2 + 1]);
|
|
|
|
screenCoords(&x2, &y2, mapPoints_relative[i * 2], -mapPoints_relative[i * 2 + 1]);
|
|
|
|
|
|
|
|
if(outOfBounds(x1,y1) && outOfBounds(x2,y2)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
SDL_Color geoColor;
|
|
|
|
|
|
|
|
// double x1d = (double) abs(x1 - (SCREEN_WIDTH>>1));
|
|
|
|
// double y1d = (double) abs(y1 - (SCREEN_HEIGHT>>1));
|
|
|
|
|
|
|
|
// double colorDist = sqrt(x1d * x1d + y1d * y1d) / (double) SCREEN_HEIGHT;
|
|
|
|
|
|
|
|
// colorDist = (colorDist < 0.0) ? 0.0 : colorDist;
|
|
|
|
// colorDist = (colorDist > 1.0) ? 1.0 : colorDist;
|
|
|
|
|
|
|
|
// geoColor.r = (uint8_t) (colorDist * 114.0 + (1.0 - colorDist) * 166.0);
|
|
|
|
// geoColor.g = (uint8_t) (colorDist * 29.0 + (1.0 - colorDist) * 266.0);
|
|
|
|
// geoColor.b = (uint8_t) (colorDist * 240.0 + (1.0 - colorDist) * 16.0);
|
|
|
|
|
2017-09-17 19:58:42 +02:00
|
|
|
geoColor.r = 100;
|
|
|
|
geoColor.g = 0;
|
|
|
|
geoColor.b = 200;
|
2017-09-17 16:46:48 +02:00
|
|
|
|
|
|
|
if(AA) {
|
|
|
|
aalineRGBA(game.screen, x1, y1, x2, y2,geoColor.r,geoColor.g,geoColor.b, SDL_ALPHA_OPAQUE);
|
|
|
|
} else {
|
|
|
|
lineRGBA(game.screen, x1, y1, x2, y2,geoColor.r,geoColor.g,geoColor.b, SDL_ALPHA_OPAQUE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-09-14 05:21:36 +02:00
|
|
|
|
|
|
|
void delay(unsigned int frameLimit)
|
|
|
|
{
|
|
|
|
unsigned int ticks = SDL_GetTicks();
|
|
|
|
|
|
|
|
if (frameLimit < ticks)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (frameLimit > ticks + 16)
|
|
|
|
{
|
|
|
|
SDL_Delay(16);
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SDL_Delay(frameLimit - ticks);
|
|
|
|
}
|
|
|
|
}
|