diff --git a/firmware/application/ui/ui_geomap.cpp b/firmware/application/ui/ui_geomap.cpp index 4d0d7e29c..e2a30aa90 100644 --- a/firmware/application/ui/ui_geomap.cpp +++ b/firmware/application/ui/ui_geomap.cpp @@ -134,7 +134,7 @@ int32_t GeoPos::altitude() { GeoMap::GeoMap( Rect parent_rect -) : Widget { parent_rect } +) : Widget { parent_rect }, markerListLen(0) { //set_focusable(true); } @@ -144,34 +144,44 @@ void GeoMap::paint(Painter& painter) { std::array map_line_buffer; 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)) { + // Ony redraw map if it moved by at least 1 pixel + // or the markers list was updated + int x_diff = abs(x_pos-prev_x_pos); + int y_diff = abs(y_pos-prev_y_pos); + if (markerListUpdated || (x_diff>=3) || (y_diff>=3)) { 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; + + // Draw the other markers + for ( int i=0; i=0) && (x10) && (y=32) { // Dont draw text if it would overlap top + // Text and symbol + draw_marker(painter, itemPoint, item.angle, item.tag, Color::blue(), Color::blue(), Color::magenta() ); + } else { + // Only symbol + draw_bearing( itemPoint, item.angle, 10, Color::blue()); + } + } + markerListUpdated = false; + } // Draw the other markers } - //center tag above point - if(tag_.find_first_not_of(' ') != tag_.npos){ //only draw tag if we have something other than spaces - painter.draw_string(r.center() - Point(((int)tag_.length() * 8 / 2), 2 * 16), style(), tag_); - } - 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 if (angle_ < 360){ - //if we have a valid angle draw bearing - draw_bearing(r.center(), angle_, 10, Color::red()); - } - else { - //draw a small cross - display.fill_rectangle({ r.center() - Point(8, 1), { 16, 2 } }, Color::red()); - display.fill_rectangle({ r.center() - Point(1, 8), { 2, 16 } }, Color::red()); - } + + //Draw the marker in the center + draw_marker(painter, r.center(), angle_, tag_, Color::red(), Color::white(), Color::black() ); } bool GeoMap::on_touch(const TouchEvent event) { @@ -196,10 +206,7 @@ void GeoMap::move(const float lon, const float lat) { x_pos = map_width * (lon_+180)/360 - (map_rect.width() / 2); // Latitude calculation based on https://stackoverflow.com/a/10401734/2278659 - double map_bottom = sin(-85.05 * pi / 180); // Map bitmap only goes from about -85 to 85 lat double lat_rad = sin(lat * pi / 180); - double map_world_lon = map_width / (2 * pi); - double map_offset = (map_world_lon / 2 * log((1 + map_bottom) / (1 - map_bottom))); y_pos = map_height - ((map_world_lon / 2 * log((1 + lat_rad) / (1 - lat_rad))) - map_offset) - 128; // Offset added for the GUI // Cap position @@ -222,7 +229,11 @@ bool GeoMap::init() { lon_ratio = 180.0 / map_center_x; lat_ratio = -90.0 / map_center_y; - + + map_bottom = sin(-85.05 * pi / 180); // Map bitmap only goes from about -85 to 85 lat + map_world_lon = map_width / (2 * pi); + map_offset = (map_world_lon / 2 * log((1 + map_bottom) / (1 - map_bottom))); + return true; } @@ -234,9 +245,9 @@ void GeoMap::draw_bearing(const Point origin, const uint16_t angle, uint32_t siz Point arrow_a, arrow_b, arrow_c; for (size_t thickness = 0; thickness < 3; thickness++) { - arrow_a = polar_to_point(angle, size) + origin; - arrow_b = polar_to_point(angle + 180 - 35, size) + origin; - arrow_c = polar_to_point(angle + 180 + 35, size) + origin; + arrow_a = fast_polar_to_point((int)angle, size) + origin; + arrow_b = fast_polar_to_point((int)(angle + 180 - 35), size) + origin; + arrow_c = fast_polar_to_point((int)(angle + 180 + 35), size) + origin; display.draw_line(arrow_a, arrow_b, color); display.draw_line(arrow_b, arrow_c, color); @@ -246,6 +257,65 @@ void GeoMap::draw_bearing(const Point origin, const uint16_t angle, uint32_t siz } } +void GeoMap::draw_marker(Painter& painter, const ui::Point itemPoint, const uint16_t itemAngle, const std::string itemTag, + const Color color, const Color fontColor, const Color backColor ) +{ + int tagOffset = 10; + if (mode_ == PROMPT) { + // Cross + display.fill_rectangle({ itemPoint - Point(16, 1), { 32, 2 } }, color); + display.fill_rectangle({ itemPoint - Point(1, 16), { 2, 32 } }, color); + tagOffset = 16; + } else if (angle_ < 360){ + //if we have a valid angle draw bearing + draw_bearing( itemPoint, itemAngle, 10, color); + tagOffset = 10; + } + else { + //draw a small cross + display.fill_rectangle({ itemPoint - Point(8, 1), { 16, 2 } }, color); + display.fill_rectangle({ itemPoint - Point(1, 8), { 2, 16 } }, color); + tagOffset = 8; + } + //center tag above point + if(itemTag.find_first_not_of(' ') != itemTag.npos){ //only draw tag if we have something other than spaces + painter.draw_string( itemPoint - Point(((int)itemTag.length() * 8 / 2), 14 + tagOffset ), + style().font, fontColor, backColor, itemTag); + } +} + +void GeoMap::clear_markers() +{ + markerListLen = 0; +} + +MapMarkerStored GeoMap::store_marker(GeoMarker & marker) +{ + MapMarkerStored ret; + + // Check if it could be on screen + // Only checking one direction to reduce CPU + const auto r = screen_rect(); + double lat_rad = sin(marker.lat * pi / 180); + int x = (map_width * (marker.lon+180)/360) - x_pos; + int y = (map_height - ((map_world_lon / 2 * log((1 + lat_rad) / (1 - lat_rad))) - map_offset)) - y_pos; // Offset added for the GUI + if (false==((x>=0) && (x10) && (y on_move { }; @@ -133,20 +157,35 @@ public: angle_ = new_angle; } + static const int NumMarkerListElements = 30; + + void clear_markers(); + MapMarkerStored store_marker(GeoMarker & marker); + private: void draw_bearing(const Point origin, const uint16_t angle, uint32_t size, const Color color); - + void draw_marker(Painter& painter, const ui::Point itemPoint, const uint16_t itemAngle, const std::string itemTag, + const Color color = Color::red(), const Color fontColor = Color::white(), const Color backColor = Color::black() ); + GeoMapMode mode_ { }; File map_file { }; uint16_t map_width { }, map_height { }; int32_t map_center_x { }, map_center_y { }; float lon_ratio { }, lat_ratio { }; + double map_bottom { }; + double map_world_lon { }; + double map_offset { }; + int32_t x_pos { }, y_pos { }; int32_t prev_x_pos { 0xFFFF }, prev_y_pos { 0xFFFF }; float lat_ { }; float lon_ { }; uint16_t angle_ { }; std::string tag_ { }; + + int markerListLen {0}; + GeoMarker markerList[NumMarkerListElements]; + bool markerListUpdated {false}; }; class GeoMapView : public View { @@ -181,6 +220,12 @@ public: std::string title() const override { return "Map view"; }; + void clear_markers(); + MapMarkerStored store_marker(GeoMarker & marker); + + void update_tag(const std::string tag); + + private: NavigationView& nav_;