GeoMap and Jammer clean up

Jammer ranges can now be set with center and width
GeoMap can be moved with touch
GeoMap negative coordinates bugfix
Replay app throws error if no files found instead of crashing
This commit is contained in:
furrtek 2017-08-12 07:07:21 +01:00
parent 1a6d80cd10
commit cb880258fb
7 changed files with 499 additions and 304 deletions

View file

@ -22,7 +22,6 @@
#include "ui_geomap.hpp"
#include "adsb.hpp"
#include "portapack.hpp"
#include <cstring>
@ -53,18 +52,23 @@ GeoPos::GeoPos(
set_lat(0);
set_lon(0);
const auto changed = [this](int32_t) {
if (on_change)
on_change();
const auto changed_fn = [this](int32_t) {
if (on_change && report_change)
on_change(altitude(), lat(), lon());
};
field_altitude.on_change = changed;
field_lat_degrees.on_change = changed;
field_lat_minutes.on_change = changed;
field_lat_seconds.on_change = changed;
field_lon_degrees.on_change = changed;
field_lon_minutes.on_change = changed;
field_lon_seconds.on_change = changed;
field_altitude.on_change = changed_fn;
field_lat_degrees.on_change = changed_fn;
field_lat_minutes.on_change = changed_fn;
field_lat_seconds.on_change = changed_fn;
field_lon_degrees.on_change = changed_fn;
field_lon_minutes.on_change = changed_fn;
field_lon_seconds.on_change = changed_fn;
}
// Stupid hack to avoid an event loop
void GeoPos::set_report_change(bool v) {
report_change = v;
}
void GeoPos::focus() {
@ -77,14 +81,14 @@ void GeoPos::set_altitude(int32_t altitude) {
void GeoPos::set_lat(float lat) {
field_lat_degrees.set_value(lat);
field_lat_minutes.set_value((uint32_t)(lat / (1.0 / 60)) % 60);
field_lat_seconds.set_value((uint32_t)(lat / (1.0 / 3600)) % 60);
field_lat_minutes.set_value((uint32_t)abs(lat / (1.0 / 60)) % 60);
field_lat_seconds.set_value((uint32_t)abs(lat / (1.0 / 3600)) % 60);
}
void GeoPos::set_lon(float lon) {
field_lon_degrees.set_value(lon);
field_lon_minutes.set_value((uint32_t)(lon / (1.0 / 60)) % 60);
field_lon_seconds.set_value((uint32_t)(lon / (1.0 / 3600)) % 60);
field_lon_minutes.set_value((uint32_t)abs(lon / (1.0 / 60)) % 60);
field_lon_seconds.set_value((uint32_t)abs(lon / (1.0 / 3600)) % 60);
}
float GeoPos::lat() {
@ -103,19 +107,102 @@ void GeoPos::set_read_only(bool v) {
set_focusable(~v);
};
void GeoMapView::focus() {
if (!file_error) {
geopos.focus();
move_map();
} else
nav_.display_modal("No map", "No world_map.bin file in\n/ADSB/ directory", ABORT, nullptr);
GeoMap::GeoMap(
Rect parent_rect
) : Widget { parent_rect }
{
//set_focusable(true);
}
GeoMapView::~GeoMapView() {
void GeoMap::paint(Painter& painter) {
Coord line;
std::array<ui::Color, 240> map_line_buffer;
//Color border;
const auto r = screen_rect();
// Ony redraw map if it moved by at least 1 pixel
if ((x_pos != prev_x_pos) || (y_pos != prev_y_pos)) {
for (line = 0; line < r.height(); line++) {
map_file.seek(4 + ((x_pos + (map_width * (y_pos + line))) << 1));
map_file.read(map_line_buffer.data(), r.width() << 1);
display.draw_pixels({ 0, r.top() + line, r.width(), 1 }, map_line_buffer);
}
prev_x_pos = x_pos;
prev_y_pos = y_pos;
}
if (mode_ == PROMPT) {
// Cross
display.fill_rectangle({ r.center() - Point(16, 1), { 32, 2 } }, Color::red());
display.fill_rectangle({ r.center() - Point(1, 16), { 2, 32 } }, Color::red());
} else {
draw_bearing({ 120, 32 + 144 }, angle_, 16, Color::red());
}
/*if (has_focus() || highlighted())
border = style().foreground;
else
border = Color::grey();
painter.draw_rectangle(
{ r.location().x(), r.location().y(), r.size().width(), r.size().height() },
border
);*/
}
void GeoMapView::draw_bearing(const Point origin, const uint32_t angle, uint32_t size, const Color color) {
bool GeoMap::on_touch(const TouchEvent event) {
if (event.type == TouchEvent::Type::Start) {
set_highlighted(true);
if (on_move) {
Point p = event.point - screen_rect().center();
on_move(p.x() / 2.0 * lon_ratio, p.y() / 2.0 * lat_ratio);
return true;
}
}
return false;
}
void GeoMap::move(const float lon, const float lat) {
lon_ = lon;
lat_ = lat;
Rect map_rect = screen_rect();
// Map is in Equidistant "Plate Carrée" projection
x_pos = map_center_x - (map_rect.width() / 2) + (lon_ / lon_ratio);
y_pos = map_center_y - (map_rect.height() / 2) + (lat_ / lat_ratio);
// Cap position
if (x_pos > (map_width - map_rect.width()))
x_pos = map_width - map_rect.width();
if (y_pos > (map_height + map_rect.height()))
y_pos = map_height - map_rect.height();
}
bool GeoMap::init() {
auto result = map_file.open("ADSB/world_map.bin");
if (result.is_valid()) {
return false;
}
map_file.read(&map_width, 2);
map_file.read(&map_height, 2);
map_center_x = map_width >> 1;
map_center_y = map_height >> 1;
lon_ratio = 180.0 / map_center_x;
lat_ratio = 90.0 / map_center_y;
return true;
}
void GeoMap::set_mode(GeoMapMode mode) {
mode_ = mode;
}
void GeoMap::draw_bearing(const Point origin, const uint32_t angle, uint32_t size, const Color color) {
Point arrow_a, arrow_b, arrow_c;
for (size_t thickness = 0; thickness < 3; thickness++) {
@ -131,62 +218,43 @@ void GeoMapView::draw_bearing(const Point origin, const uint32_t angle, uint32_t
}
}
void GeoMapView::move_map() {
Coord line;
int32_t x_pos, y_pos;
std::array<ui::Color, 240> map_line_buffer;
auto r = screen_rect();
Rect map_rect = { r.left(), r.top() + banner_height, r.width(), r.height() - banner_height };
altitude_ = geopos.altitude();
lat_ = geopos.lat();
lon_ = geopos.lon();
// Map is in Equidistant "Plate Carrée" projection
x_pos = map_center_x - (map_rect.width() / 2) + ((lat_ * map_center_x) / 180);
y_pos = map_center_y - (map_rect.height() / 2) + ((lon_ * map_center_y) / 90);
if (x_pos > (map_width - map_rect.width()))
x_pos = map_width - map_rect.width();
if (y_pos > (map_height + map_rect.height()))
y_pos = map_height - map_rect.height();
for (line = 0; line < map_rect.height(); line++) {
map_file.seek(4 + ((x_pos + (map_width * (y_pos + line))) << 1));
map_file.read(map_line_buffer.data(), map_rect.width() << 1);
display.draw_pixels({ 0, map_rect.top() + line, map_rect.width(), 1 }, map_line_buffer);
}
if (mode_ == PROMPT) {
display.fill_rectangle({ map_rect.center() - Point(16, 1), { 32, 2 } }, Color::red());
display.fill_rectangle({ map_rect.center() - Point(1, 16), { 2, 32 } }, Color::red());
} else {
draw_bearing({ 120, 32 + 144 }, angle_, 16, Color::red());
}
void GeoMapView::focus() {
if (!file_error) {
geopos.focus();
} else
nav_.display_modal("No map", "No world_map.bin file in\n/ADSB/ directory", ABORT, nullptr);
}
void GeoMapView::setup() {
auto result = map_file.open("ADSB/world_map.bin");
if (result.is_valid()) {
file_error = true;
return;
}
map_file.read(&map_width, 2);
map_file.read(&map_height, 2);
map_center_x = map_width >> 1;
map_center_y = map_height >> 1;
add_child(&geopos);
add_children({
&geopos,
&geomap
});
geopos.set_altitude(altitude_);
geopos.set_lat(lat_);
geopos.set_lon(lon_);
geopos.on_change = [this]() {
move_map();
geopos.on_change = [this](int32_t altitude, float lat, float lon) {
altitude_ = altitude;
lat_ = lat;
lon_ = lon;
geomap.move(lon_, lat_);
geomap.set_dirty();
};
geomap.on_move = [this](float move_x, float move_y) {
lon_ += move_x;
lat_ += move_y;
// Stupid hack to avoid an event loop
geopos.set_report_change(false);
geopos.set_lon(lon_);
geopos.set_lat(lat_);
geopos.set_report_change(true);
geomap.move(lon_, lat_);
geomap.set_dirty();
};
}
@ -206,8 +274,15 @@ GeoMapView::GeoMapView(
angle_ (angle)
{
mode_ = DISPLAY;
file_error = !geomap.init();
if (file_error) return;
setup();
geomap.set_mode(mode_);
geomap.move(lon_, lat_);
geopos.set_read_only(true);
}
@ -224,10 +299,16 @@ GeoMapView::GeoMapView(
lon_ (lon)
{
mode_ = PROMPT;
setup();
file_error = !geomap.init();
if (file_error) return;
setup();
add_child(&button_ok);
geomap.set_mode(mode_);
geomap.move(lon_, lat_);
button_ok.on_select = [this, on_done, &nav](Button&) {
if (on_done)
on_done(altitude_, lat_, lon_);