diff --git a/README.md b/README.md index 50a916f..c59b6db 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,10 @@ ###HARDWARE +best option seems to be pi4 + pijuice zero (w/ rewired i2c) + hyperpixel 4. RTLSDR (stratux) sticks down or needs u shaped adapter. +For future tuner, need to test audio phat w/ little speaker, i2c knob, etc. + + Notes: Pi 3b+ and below are a little underpowerd for unoptimized map drawing Pi 4 is smooth, may have USB issues with RTLSDR? diff --git a/draw.c b/draw.c index 889f381..f0aaf92 100644 --- a/draw.c +++ b/draw.c @@ -235,11 +235,11 @@ void drawTrail(double *oldDx, double *oldDy, double *oldHeading, time_t * oldSee screenCoords(&prevX, &prevY, dx, dy); if(outOfBounds(currentX,currentY)) { - return; + continue; } if(outOfBounds(prevX,prevY)) { - return; + continue; } double age = pow(1.0 - (double)(now - oldSeen[currentIdx]) / TRAIL_TTL, 2.2); @@ -250,7 +250,7 @@ void drawTrail(double *oldDx, double *oldDy, double *oldHeading, time_t * oldSee uint8_t colorVal = (uint8_t)floor(255.0 * age); - //thickLineRGBA(appData.renderer, prevX, prevY, currentX, currentY, 4 * appData.screen_uiscale, colorVal, colorVal, colorVal, 127); + thickLineRGBA(appData.renderer, prevX, prevY, currentX, currentY, 2 * appData.screen_uiscale, colorVal, colorVal, colorVal, 64); //tick marks @@ -350,27 +350,6 @@ void drawGeography() { } } -void drawPlaneText(struct planeObj *p, int x, int y) { - - drawStringBG(p->flight, x + 5, y + appData.mapFontHeight, appData.mapBoldFont, white, black); - - char alt[10] = " "; - if (Modes.metric) { - snprintf(alt,10,"%dm", (int) (p->altitude / 3.2828)); - } else { - snprintf(alt,10,"%d'", p->altitude); - } - drawStringBG(alt, x + 5, y + 2*appData.mapFontHeight, appData.mapFont, grey, black); - - char speed[10] = " "; - if (Modes.metric) { - snprintf(speed,10,"%dkm/h", (int) (p->speed * 1.852)); - } else { - snprintf(speed,10,"%dmph", p->speed); - } - drawStringBG(speed, x + 5, y + 3*appData.mapFontHeight, appData.mapFont, grey, black); -} - void drawSignalMarks(struct planeObj *p, int x, int y) { unsigned char * pSig = p->signalLevel; unsigned int signalAverage = (pSig[0] + pSig[1] + pSig[2] + pSig[3] + @@ -380,21 +359,267 @@ void drawSignalMarks(struct planeObj *p, int x, int y) { Uint8 seenFade = (Uint8) (255.0 - (mstime() - p->msSeen) / 4.0); - circleRGBA(appData.renderer, x + 5 * appData.screen_uiscale, y + 10 * appData.screen_uiscale, 2 * appData.screen_uiscale, barColor.r, barColor.g, barColor.b, seenFade); + circleRGBA(appData.renderer, x, y - 5, 2 * appData.screen_uiscale, barColor.r, barColor.g, barColor.b, seenFade); seenFade = (Uint8) (255.0 - (mstime() - p->msSeenLatLon) / 4.0); - hlineRGBA(appData.renderer, x + 10 * appData.screen_uiscale, x + 14 * appData.screen_uiscale, y + 10 * appData.screen_uiscale, barColor.r, barColor.g, barColor.b, seenFade); - vlineRGBA(appData.renderer, x + 12 * appData.screen_uiscale, y + 8 * appData.screen_uiscale, y + 12 * appData.screen_uiscale, barColor.r, barColor.g, barColor.b, seenFade); + hlineRGBA(appData.renderer, x + 5 * appData.screen_uiscale, x + 9 * appData.screen_uiscale, y - 5, barColor.r, barColor.g, barColor.b, seenFade); + vlineRGBA(appData.renderer, x + 7 * appData.screen_uiscale, y - 2 * appData.screen_uiscale - 5, y + 2 * appData.screen_uiscale - 5, barColor.r, barColor.g, barColor.b, seenFade); } + +void drawPlaneText(struct planeObj *p) { + + drawSignalMarks(p, p->x, p->y); + + int maxCharCount; + int currentCharCount; + + int currentLine = 0; + + char flight[10] = " "; + maxCharCount = snprintf(flight,10,"%s", p->flight); + + if(maxCharCount > 0) { + drawStringBG(flight, p->x, p->y, appData.mapBoldFont, white, black); + currentLine++; + } + + char alt[10] = " "; + if (Modes.metric) { + currentCharCount = snprintf(alt,10,"%dm", (int) (p->altitude / 3.2828)); + } else { + currentCharCount = snprintf(alt,10,"%d'", p->altitude); + } + + if(currentCharCount > 0) { + drawStringBG(alt, p->x, p->y + currentLine * appData.mapFontHeight, appData.mapFont, grey, black); + currentLine++; + } + + if(currentCharCount > maxCharCount) { + maxCharCount = currentCharCount; + } + + char speed[10] = " "; + if (Modes.metric) { + currentCharCount = snprintf(speed,10,"%dkm/h", (int) (p->speed * 1.852)); + } else { + currentCharCount = snprintf(speed,10,"%dmph", p->speed); + } + + if(currentCharCount > 0) { + drawStringBG(speed, p->x, p->y + currentLine * appData.mapFontHeight, appData.mapFont, grey, black); + currentLine++; + } + + if(currentCharCount > maxCharCount) { + maxCharCount = currentCharCount; + } + + p->w = maxCharCount * appData.mapFontWidth; + p->h = currentLine * appData.mapFontHeight; +} + +float sign(float x) { + return (x > 0) - (x < 0); +} + + +void resolveLabelConflicts() { + struct planeObj *p = planes; + + while(p) { + + struct planeObj *check_p = planes; + + int p_left = p->x - 10 * appData.screen_uiscale; + int p_right = p->x + p->w + 10 * appData.screen_uiscale; + int p_top = p->y - 10 * appData.screen_uiscale; + int p_bottom = p->y + p->h + 10 * appData.screen_uiscale; + + //debug box + //rectangleRGBA(appData.renderer, p->x, p->y, p->x + p->w, p->y + p->h, 255,0,0, SDL_ALPHA_OPAQUE); + //lineRGBA(appData.renderer, p->cx, p->cy, p->x, p->y, 0,255,0, SDL_ALPHA_OPAQUE); + + //apply damping + + p->ddox -= 0.7f * p->dox; + p->ddoy -= 0.7f * p->doy; + + //spring back to origin + p->ddox -= 0.05f * p->ox; + p->ddoy -= 0.05f * p->oy; + + // // //screen edge + + if(p_left < 10 * appData.screen_uiscale) { + p->ox += (float)(10 * appData.screen_uiscale - p_left); + } + + if(p_right > (appData.screen_width - 10 * appData.screen_uiscale)) { + p->ox -= (float)(p_right - (appData.screen_width - 10 * appData.screen_uiscale)); + } + + if(p_top < 10 * appData.screen_uiscale) { + p->oy += (float)(10 * appData.screen_uiscale - p_top); + } + + if(p_bottom > (appData.screen_height - 10 * appData.screen_uiscale)) { + p->oy -= (float)(p_bottom - (appData.screen_height - 10 * appData.screen_uiscale)); + } + + + //check against other labels + + while(check_p) { + if(check_p->addr != p->addr) { + + int check_left = check_p->x - 5 * appData.screen_uiscale; + int check_right = check_p->x + check_p->w + 5 * appData.screen_uiscale; + int check_top = check_p->y - 5 * appData.screen_uiscale; + int check_bottom = check_p->y + check_p->h + 5 * appData.screen_uiscale; + + //if(check_left > (p_right + 10) || check_right < (p_left - 10)) { + if(check_left > p_right || check_right < p_left) { + check_p = check_p -> next; + continue; + } + + //if(check_top > (p_bottom + 10) || check_bottom < (p_top - 10)) { + if(check_top > p_bottom || check_bottom < p_top) { + check_p = check_p -> next; + continue; + } + + //left collision + if(check_left > p_left && check_left < p_right) { + check_p->ddox -= 0.1f * (float)(check_left - p_right); + } + + //right collision + if(check_right > p_left && check_right < p_right) { + check_p->ddox -= 0.1f * (float)(check_right - p_left); + } + + //top collision + if(check_top > p_top && check_top < p_bottom) { + check_p->ddoy -= 0.1f * (float)(check_top - p_bottom); + } + + //bottom collision + if(check_bottom > p_top && check_bottom < p_bottom) { + check_p->ddoy -= 0.1f * (float)(check_bottom - p_top); + } + } + check_p = check_p -> next; + } + + check_p = planes; + + //check against plane icons (include self) + + p_left = p->x - 5 * appData.screen_uiscale; + p_right = p->x + 5 * appData.screen_uiscale; + p_top = p->y - 5 * appData.screen_uiscale; + p_bottom = p->y + 5 * appData.screen_uiscale; + + while(check_p) { + + int check_left = check_p->x - 5 * appData.screen_uiscale; + int check_right = check_p->x + check_p->w + 5 * appData.screen_uiscale; + int check_top = check_p->y - 5 * appData.screen_uiscale; + int check_bottom = check_p->y + check_p->h + 5 * appData.screen_uiscale; + + if(check_left > p_right || check_right < p_left) { + check_p = check_p -> next; + continue; + } + + if(check_top > p_bottom || check_bottom < p_top) { + check_p = check_p -> next; + continue; + } + + //left collision + if(check_left > p_left && check_left < p_right) { + check_p->ddox -= 0.1f * (float)(check_left - p_right); + } + + //right collision + if(check_right > p_left && check_right < p_right) { + check_p->ddox -= 0.1f * (float)(check_right - p_left); + } + + //top collision + if(check_top > p_top && check_top < p_bottom) { + check_p->ddoy -= 0.1f * (float)(check_top - p_bottom); + } + + //bottom collision + if(check_bottom > p_top && check_bottom < p_bottom) { + check_p->ddoy -= 0.1f * (float)(check_bottom - p_top); + } + + check_p = check_p -> next; + } + + p = p->next; + } + + //update + + p = planes; + + while(p) { + //incorporate accelerate from label conflict resolution + + p->dox += p->ddox; + p->doy += p->ddoy; + + if(fabs(p->dox) > 10.0f) { + p->dox = sign(p->dox) * 10.0f; + } + + if(fabs(p->doy) > 10.0f) { + p->doy = sign(p->doy) * 10.0f; + } + + if(fabs(p->dox) < 1.0f) { + p->dox = 0; + } + + if(fabs(p->doy) < 1.0f) { + p->doy = 0; + } + + p->ox += p->dox; + p->oy += p->doy; + + //printf("p_ox: %f, p_oy %f\n",p->ox, p->oy); + + p->ddox = 0; + p->ddoy = 0; + + p->x = p->cx + (int)round(p->ox); + p->y = p->cy + (int)round(p->oy); + + p = p->next; + } +} + + void drawMap() { struct planeObj *p = planes; time_t now = time(NULL); SDL_Color planeColor; drawGeography(); - drawGrid(); + drawGrid(); + + //for(int i = 0; i < 2; i++) { + resolveLabelConflicts(); + //} //draw all trails first so they don't cover up planes and text @@ -402,6 +627,7 @@ void drawMap() { if ((now - p->seen) < Modes.interactive_display_ttl) { drawTrail(p->oldLon, p->oldLat, p->oldHeading, p->oldSeen, p->oldIdx); } + p = p->next; } @@ -424,13 +650,6 @@ void drawMap() { planeColor = white; } - if(outOfBounds(x,y)) { - int outx, outy; - drawPlaneOffMap(x, y, &outx, &outy, planeColor); - drawPlaneText(p, outx, outy); - } - - if(p->created == 0) { p->created = mstime(); } @@ -457,13 +676,28 @@ void drawMap() { usey = y + (mstime() - p->msSeenLatLon) * vely; } - drawPlaneHeading(usex, usey, p->track, planeColor); - drawSignalMarks(p, usex, usey); - drawPlaneText(p, usex, usey); - lineRGBA(appData.renderer, usex, usey, usex, usey + 4*appData.mapFontHeight, grey.r, grey.g, grey.b, SDL_ALPHA_OPAQUE); + + if(outOfBounds(x,y)) { + drawPlaneOffMap(x, y, &(p->cx), &(p->cy), planeColor); + thickLineRGBA(appData.renderer, p->cx, p->cy, p->x+(p->w>>2), p->y, appData.screen_uiscale, 200,200,200,SDL_ALPHA_OPAQUE); + } else { + drawPlaneHeading(usex, usey, p->track, planeColor); + + p->cx = usex;// + 5; + p->cy = usey;// + 10 * appData.screen_uiscale; + + if(p->cx != 0 && p->cy != 0 && p->x != 0 && p->y != 0) { + + thickLineRGBA(appData.renderer, usex, usey, p->x+(p->w>>2), p->y, appData.screen_uiscale, 200,200,200, SDL_ALPHA_OPAQUE); + } + } + + + drawPlaneText(p); + } else { - drawPlane(x, y, planeColor); + //drawPlane(x, y, planeColor); } } } diff --git a/draw.o.REMOVED.git-id b/draw.o.REMOVED.git-id index d84e7d7..8d1d3a5 100644 --- a/draw.o.REMOVED.git-id +++ b/draw.o.REMOVED.git-id @@ -1 +1 @@ -3329d96b9e8da09d38ac06e8cfcb2c9227d0593e \ No newline at end of file +a17d06a73e34e6e65d1ff9ed411da79667154ca6 \ No newline at end of file diff --git a/font.o b/font.o index eb8e2e3..120e521 100644 Binary files a/font.o and b/font.o differ diff --git a/init.o b/init.o index 824f2eb..c075893 100644 Binary files a/init.o and b/init.o differ diff --git a/input.o.REMOVED.git-id b/input.o.REMOVED.git-id index a79dc82..8dccc44 100644 --- a/input.o.REMOVED.git-id +++ b/input.o.REMOVED.git-id @@ -1 +1 @@ -2c4ed2ab46ef6a542479d8c3c9ea7de7298325c1 \ No newline at end of file +2305764a62eb8dd80a5f71e908a04bfaa9bc3cc9 \ No newline at end of file diff --git a/list.o b/list.o index e3a4518..cdfa683 100644 Binary files a/list.o and b/list.o differ diff --git a/mapbox_testing b/mapbox_testing new file mode 100644 index 0000000..5a82f5c --- /dev/null +++ b/mapbox_testing @@ -0,0 +1,6 @@ +curl "https://api.mapbox.com/v4/mapbox.mapbox-streets-v8/8/40/89.mvt?access_token=pk.eyJ1Ijoibm1hdHN1ZGEiLCJhIjoiY2swazhrdGNjMGZ3NzNvcmE0OGxoaGd2byJ9.PAYHqO3any_6vLdjQ44RGw" + +mapbox://styles/nmatsuda/ck0k7rvvt3rkv1cq6l74wjda2 + + +47.695,-123.489 \ No newline at end of file diff --git a/monokai.o b/monokai.o index 2a29f32..06326c5 100644 Binary files a/monokai.o and b/monokai.o differ diff --git a/planeObj.c b/planeObj.c index 6380a15..92b665d 100644 --- a/planeObj.c +++ b/planeObj.c @@ -31,6 +31,18 @@ struct planeObj *createPlaneObj(struct aircraft *a) { p->oldIdx = 0; p->prev_seen = 0; + p->x = 0; + p->y = 0; + p->cx = 0; + p->cy = 0; + + p->ox = 0; + p->oy = 0; + p->dox = 0; + p->doy = 0; + p->ddox = 0; + p->ddoy = 0; + memset(p->oldLon, 0, sizeof(p->oldLon)); memset(p->oldLat, 0, sizeof(p->oldLat)); memset(p->oldHeading, 0, sizeof(p->oldHeading)); @@ -85,7 +97,7 @@ void updatePlanes() { if(p->seenLatLon < a->seenLatLon) { p->msSeenLatLon = mstime(); - + p->oldIdx = (p->oldIdx+1) % 32; p->oldLon[p->oldIdx] = p->lon; diff --git a/planeObj.o b/planeObj.o index 56be23f..46f2380 100644 Binary files a/planeObj.o and b/planeObj.o differ diff --git a/status.o.REMOVED.git-id b/status.o.REMOVED.git-id index ca6393a..8c415a8 100644 --- a/status.o.REMOVED.git-id +++ b/status.o.REMOVED.git-id @@ -1 +1 @@ -e28b70359d329c69b61d0da196a74552ba4f6f8f \ No newline at end of file +30a2da16b88ee34ce3413fff471b01c956184f32 \ No newline at end of file diff --git a/structs.h b/structs.h index 93da617..a1fe80b 100644 --- a/structs.h +++ b/structs.h @@ -72,6 +72,12 @@ struct planeObj { int live; struct planeObj *next; // Next aircraft in our linked list + +//// label stuff + + int x, y, cx, cy, w, h; + float ox, oy, dox, doy, ddox, ddoy; + }; struct planeObj *planes; diff --git a/view1090.REMOVED.git-id b/view1090.REMOVED.git-id index d5f630d..5c9e4c9 100644 --- a/view1090.REMOVED.git-id +++ b/view1090.REMOVED.git-id @@ -1 +1 @@ -ae65e041076e061971bc7b3d686bee6c5f471abd \ No newline at end of file +8994067f92a4d800070c11716a732a5636bb6e5b \ No newline at end of file diff --git a/view1090.o.REMOVED.git-id b/view1090.o.REMOVED.git-id index 75ee653..05895e4 100644 --- a/view1090.o.REMOVED.git-id +++ b/view1090.o.REMOVED.git-id @@ -1 +1 @@ -566004a350fc256a0bc6ab112a14b09c91e6cc18 \ No newline at end of file +a549061b45cd62ae3ca46ebf3b8e29c4956b9641 \ No newline at end of file