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-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-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-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-14 05:21:36 +02:00
if ( signal > 127 ) {
signal = 127 ;
}
2017-09-15 16:57:20 +02:00
SDL_Color planeColor ;
2017-09-14 16:39:56 +02:00
if ( signal < 0 ) {
2017-09-15 16:57:20 +02:00
planeColor = setColor ( 96 , 96 , 96 ) ;
2017-09-14 16:39:56 +02:00
} else {
2017-09-15 16:57:20 +02:00
planeColor = setColor ( parula [ signal ] [ 0 ] , parula [ signal ] [ 1 ] , parula [ signal ] [ 2 ] ) ;
2017-09-14 16:39:56 +02:00
}
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 ) ;
} else {
thickLineRGBA ( game . screen , x , y , x2 , y2 , 2 , planeColor . r , planeColor . g , planeColor . b , SDL_ALPHA_OPAQUE ) ;
//lineRGBA(game.screen,x1,y1,x2,y2,planeColor.r,planeColor.g,planeColor.b,SDL_ALPHA_OPAQUE);
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 ) ;
//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]), x2, y2,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-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-15 16:57:20 +02:00
//thickLineRGBA(game.screen,x1,y1,x2,y2,planeWidth,planeColor.r,planeColor.g,planeColor.b,SDL_ALPHA_OPAQUE);
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 ) ;
} else {
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 ) ;
//lineRGBA(game.screen,x1,y1,x2,y2,planeColor.r,planeColor.g,planeColor.b,SDL_ALPHA_OPAQUE);
}
2017-09-14 05:21:36 +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-15 16:57:20 +02:00
//thickLineRGBA(game.screen,x1,y1,x2,y2,planeWidth,planeColor.r,planeColor.g,planeColor.b,SDL_ALPHA_OPAQUE);
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 ) ;
} else {
//lineRGBA(game.screen,x1,y1,x2,y2,planeColor.r,planeColor.g,planeColor.b,SDL_ALPHA_OPAQUE);
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-15 16:57:20 +02:00
if ( strlen ( flight ) ) {
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 ;
}
if ( signal > 127 ) {
signal = 127 ;
}
2017-09-15 16:57:20 +02:00
SDL_Color planeColor ;
2017-09-14 16:39:56 +02:00
if ( signal < 0 ) {
2017-09-15 16:57:20 +02:00
planeColor = setColor ( 96 , 96 , 96 ) ;
2017-09-14 16:39:56 +02:00
} else {
2017-09-15 16:57:20 +02:00
planeColor = setColor ( parula [ signal ] [ 0 ] , parula [ signal ] [ 1 ] , parula [ signal ] [ 2 ] ) ;
2017-09-14 16:39:56 +02:00
}
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 ( & currentX , & currentY , 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 ) {
aalineRGBA ( game . screen , prevX , prevY , currentX , currentY , colorVal , colorVal , colorVal , SDL_ALPHA_OPAQUE ) ;
} else {
//lineRGBA(game.screen, prevX, prevY, currentX, currentY,colorVal, colorVal, colorVal, SDL_ALPHA_OPAQUE);
thickLineRGBA ( game . screen , prevX , prevY , currentX , currentY , 1 , colorVal , colorVal , colorVal , SDL_ALPHA_OPAQUE ) ;
}
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 ) ;
aacircleRGBA ( game . screen , SCREEN_WIDTH > > 1 , SCREEN_HEIGHT > > 1 , p1km , 64 , 64 , 64 , SDL_ALPHA_OPAQUE ) ;
aacircleRGBA ( game . screen , SCREEN_WIDTH > > 1 , SCREEN_HEIGHT > > 1 , p10km , 64 , 64 , 64 , SDL_ALPHA_OPAQUE ) ;
aacircleRGBA ( game . screen , SCREEN_WIDTH > > 1 , SCREEN_HEIGHT > > 1 , p100km , 64 , 64 , 64 , SDL_ALPHA_OPAQUE ) ;
drawString ( " 1km " , ( SCREEN_WIDTH > > 1 ) + p1km + 5 , ( SCREEN_HEIGHT > > 1 ) + 5 , game . font , setColor ( 64 , 64 , 64 ) ) ;
drawString ( " 10km " , ( SCREEN_WIDTH > > 1 ) + p10km + 5 , ( SCREEN_HEIGHT > > 1 ) + 5 , game . font , setColor ( 64 , 64 , 64 ) ) ;
drawString ( " 100km " , ( SCREEN_WIDTH > > 1 ) + p100km + 5 , ( SCREEN_HEIGHT > > 1 ) + 5 , game . font , setColor ( 64 , 64 , 64 ) ) ;
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 ) ;
}
}