diff options
| author | Star Rauchenberger <fefferburbia@gmail.com> | 2024-05-18 15:33:30 -0400 |
|---|---|---|
| committer | Star Rauchenberger <fefferburbia@gmail.com> | 2024-05-18 15:33:30 -0400 |
| commit | a2b67cf27dbd41bcfa75835e36c605adfc040e40 (patch) | |
| tree | 53cffc4d0163a5f6923e3851eb8281400cc028f6 | |
| parent | 4d8e36245e8ce43eef9b687a9108fd4c353f756f (diff) | |
| download | lingo-ap-tracker-a2b67cf27dbd41bcfa75835e36c605adfc040e40.tar.gz lingo-ap-tracker-a2b67cf27dbd41bcfa75835e36c605adfc040e40.tar.bz2 lingo-ap-tracker-a2b67cf27dbd41bcfa75835e36c605adfc040e40.zip | |
Coordinate transformation functions
| -rw-r--r-- | src/subway_map.cpp | 99 | ||||
| -rw-r--r-- | src/subway_map.h | 3 |
2 files changed, 50 insertions, 52 deletions
| diff --git a/src/subway_map.cpp b/src/subway_map.cpp index 2e7b36f..5a4be4b 100644 --- a/src/subway_map.cpp +++ b/src/subway_map.cpp | |||
| @@ -143,23 +143,20 @@ void SubwayMap::OnPaint(wxPaintEvent &event) { | |||
| 143 | int item_width = col_width + 10 + 32; | 143 | int item_width = col_width + 10 + 32; |
| 144 | int full_width = item_width + 20; | 144 | int full_width = item_width + 20; |
| 145 | 145 | ||
| 146 | int popup_x = (subway_item.x + AREA_ACTUAL_SIZE / 2) * render_width_ / | 146 | wxPoint popup_pos = |
| 147 | map_image_.GetWidth() + | 147 | MapPosToRenderPos({subway_item.x + AREA_ACTUAL_SIZE / 2, |
| 148 | render_x_; | 148 | subway_item.y + AREA_ACTUAL_SIZE / 2}); |
| 149 | int popup_y = (subway_item.y + AREA_ACTUAL_SIZE / 2) * render_width_ / | 149 | |
| 150 | map_image_.GetWidth() + | 150 | if (popup_pos.x + full_width > GetSize().GetWidth()) { |
| 151 | render_y_; | 151 | popup_pos.x = GetSize().GetWidth() - full_width; |
| 152 | |||
| 153 | if (popup_x + full_width > GetSize().GetWidth()) { | ||
| 154 | popup_x = GetSize().GetWidth() - full_width; | ||
| 155 | } | 152 | } |
| 156 | if (popup_y + acc_height > GetSize().GetHeight()) { | 153 | if (popup_pos.y + acc_height > GetSize().GetHeight()) { |
| 157 | popup_y = GetSize().GetHeight() - acc_height; | 154 | popup_pos.y = GetSize().GetHeight() - acc_height; |
| 158 | } | 155 | } |
| 159 | 156 | ||
| 160 | dc.SetPen(*wxTRANSPARENT_PEN); | 157 | dc.SetPen(*wxTRANSPARENT_PEN); |
| 161 | dc.SetBrush(*wxBLACK_BRUSH); | 158 | dc.SetBrush(*wxBLACK_BRUSH); |
| 162 | dc.DrawRectangle({popup_x, popup_y}, {full_width, acc_height}); | 159 | dc.DrawRectangle(popup_pos, {full_width, acc_height}); |
| 163 | 160 | ||
| 164 | dc.SetFont(GetFont()); | 161 | dc.SetFont(GetFont()); |
| 165 | 162 | ||
| @@ -168,14 +165,15 @@ void SubwayMap::OnPaint(wxPaintEvent &event) { | |||
| 168 | for (const auto& [text, obtained] : report) { | 165 | for (const auto& [text, obtained] : report) { |
| 169 | wxBitmap *eye_ptr = obtained ? &unchecked_eye_ : &checked_eye_; | 166 | wxBitmap *eye_ptr = obtained ? &unchecked_eye_ : &checked_eye_; |
| 170 | 167 | ||
| 171 | dc.DrawBitmap(*eye_ptr, {popup_x + 10, popup_y + cur_height}); | 168 | dc.DrawBitmap(*eye_ptr, popup_pos + wxPoint{10, cur_height}); |
| 172 | 169 | ||
| 173 | dc.SetTextForeground(obtained ? *wxWHITE : *wxRED); | 170 | dc.SetTextForeground(obtained ? *wxWHITE : *wxRED); |
| 174 | wxSize item_extent = dc.GetTextExtent(text); | 171 | wxSize item_extent = dc.GetTextExtent(text); |
| 175 | dc.DrawText( | 172 | dc.DrawText( |
| 176 | text, | 173 | text, |
| 177 | {popup_x + 10 + 32 + 10, | 174 | popup_pos + |
| 178 | popup_y + cur_height + (32 - dc.GetFontMetrics().height) / 2}); | 175 | wxPoint{10 + 32 + 10, |
| 176 | cur_height + (32 - dc.GetFontMetrics().height) / 2}); | ||
| 179 | 177 | ||
| 180 | cur_height += 10 + 32; | 178 | cur_height += 10 + 32; |
| 181 | } | 179 | } |
| @@ -189,43 +187,34 @@ void SubwayMap::OnPaint(wxPaintEvent &event) { | |||
| 189 | const SubwayItem &item1 = GD_GetSubwayItem(item_id1); | 187 | const SubwayItem &item1 = GD_GetSubwayItem(item_id1); |
| 190 | const SubwayItem &item2 = GD_GetSubwayItem(item_id2); | 188 | const SubwayItem &item2 = GD_GetSubwayItem(item_id2); |
| 191 | 189 | ||
| 192 | int item1_x = (item1.x + AREA_ACTUAL_SIZE / 2) * render_width_ / | 190 | wxPoint item1_pos = MapPosToRenderPos( |
| 193 | map_image_.GetWidth() + | 191 | {item1.x + AREA_ACTUAL_SIZE / 2, item1.y + AREA_ACTUAL_SIZE / 2}); |
| 194 | render_x_; | 192 | wxPoint item2_pos = MapPosToRenderPos( |
| 195 | int item1_y = (item1.y + AREA_ACTUAL_SIZE / 2) * render_width_ / | 193 | {item2.x + AREA_ACTUAL_SIZE / 2, item2.y + AREA_ACTUAL_SIZE / 2}); |
| 196 | map_image_.GetWidth() + | 194 | |
| 197 | render_y_; | 195 | int left = std::min(item1_pos.x, item2_pos.x); |
| 198 | 196 | int top = std::min(item1_pos.y, item2_pos.y); | |
| 199 | int item2_x = (item2.x + AREA_ACTUAL_SIZE / 2) * render_width_ / | 197 | int right = std::max(item1_pos.x, item2_pos.x); |
| 200 | map_image_.GetWidth() + | 198 | int bottom = std::max(item1_pos.y, item2_pos.y); |
| 201 | render_x_; | ||
| 202 | int item2_y = (item2.y + AREA_ACTUAL_SIZE / 2) * render_width_ / | ||
| 203 | map_image_.GetWidth() + | ||
| 204 | render_y_; | ||
| 205 | |||
| 206 | int left = std::min(item1_x, item2_x); | ||
| 207 | int top = std::min(item1_y, item2_y); | ||
| 208 | int right = std::max(item1_x, item2_x); | ||
| 209 | int bottom = std::max(item1_y, item2_y); | ||
| 210 | 199 | ||
| 211 | int halfwidth = right - left; | 200 | int halfwidth = right - left; |
| 212 | int halfheight = bottom - top; | 201 | int halfheight = bottom - top; |
| 213 | 202 | ||
| 214 | if (halfwidth < 4 || halfheight < 4) { | 203 | if (halfwidth < 4 || halfheight < 4) { |
| 215 | dc.SetPen(*wxThePenList->FindOrCreatePen(*wxBLACK, 4)); | 204 | dc.SetPen(*wxThePenList->FindOrCreatePen(*wxBLACK, 4)); |
| 216 | dc.DrawLine(item1_x, item1_y, item2_x, item2_y); | 205 | dc.DrawLine(item1_pos, item2_pos); |
| 217 | dc.SetPen(*wxThePenList->FindOrCreatePen(*wxCYAN, 2)); | 206 | dc.SetPen(*wxThePenList->FindOrCreatePen(*wxCYAN, 2)); |
| 218 | dc.DrawLine(item1_x, item1_y, item2_x, item2_y); | 207 | dc.DrawLine(item1_pos, item2_pos); |
| 219 | } else { | 208 | } else { |
| 220 | int ellipse_x; | 209 | int ellipse_x; |
| 221 | int ellipse_y; | 210 | int ellipse_y; |
| 222 | double start; | 211 | double start; |
| 223 | double end; | 212 | double end; |
| 224 | 213 | ||
| 225 | if (item1_x > item2_x) { | 214 | if (item1_pos.x > item2_pos.x) { |
| 226 | ellipse_y = top; | 215 | ellipse_y = top; |
| 227 | 216 | ||
| 228 | if (item1_y > item2_y) { | 217 | if (item1_pos.y > item2_pos.y) { |
| 229 | ellipse_x = left - halfwidth; | 218 | ellipse_x = left - halfwidth; |
| 230 | 219 | ||
| 231 | start = 0; | 220 | start = 0; |
| @@ -239,7 +228,7 @@ void SubwayMap::OnPaint(wxPaintEvent &event) { | |||
| 239 | } else { | 228 | } else { |
| 240 | ellipse_y = top - halfheight; | 229 | ellipse_y = top - halfheight; |
| 241 | 230 | ||
| 242 | if (item1_y > item2_y) { | 231 | if (item1_pos.y > item2_pos.y) { |
| 243 | ellipse_x = left - halfwidth; | 232 | ellipse_x = left - halfwidth; |
| 244 | 233 | ||
| 245 | start = 270; | 234 | start = 270; |
| @@ -267,15 +256,10 @@ void SubwayMap::OnPaint(wxPaintEvent &event) { | |||
| 267 | } | 256 | } |
| 268 | 257 | ||
| 269 | void SubwayMap::OnMouseMove(wxMouseEvent &event) { | 258 | void SubwayMap::OnMouseMove(wxMouseEvent &event) { |
| 270 | int mouse_x = std::clamp( | 259 | wxPoint mouse_pos = RenderPosToMapPos(event.GetPosition()); |
| 271 | (event.GetX() - render_x_) * map_image_.GetWidth() / render_width_, | 260 | |
| 272 | 0, map_image_.GetWidth() - 1); | ||
| 273 | int mouse_y = std::clamp( | ||
| 274 | (event.GetY() - render_y_) * map_image_.GetWidth() / render_width_, | ||
| 275 | 0, map_image_.GetHeight() - 1); | ||
| 276 | |||
| 277 | std::vector<int> hovered = tree_->query( | 261 | std::vector<int> hovered = tree_->query( |
| 278 | {static_cast<float>(mouse_x), static_cast<float>(mouse_y), 2, 2}); | 262 | {static_cast<float>(mouse_pos.x), static_cast<float>(mouse_pos.y), 2, 2}); |
| 279 | std::optional<int> new_hovered_item; | 263 | std::optional<int> new_hovered_item; |
| 280 | if (!hovered.empty()) { | 264 | if (!hovered.empty()) { |
| 281 | new_hovered_item = hovered[0]; | 265 | new_hovered_item = hovered[0]; |
| @@ -369,10 +353,7 @@ void SubwayMap::Redraw() { | |||
| 369 | } | 353 | } |
| 370 | } | 354 | } |
| 371 | 355 | ||
| 372 | int real_area_x = | 356 | wxPoint real_area_pos = MapPosToRenderPos({subway_item.x, subway_item.y}); |
| 373 | render_x_ + subway_item.x * render_width_ / image_size.GetWidth(); | ||
| 374 | int real_area_y = | ||
| 375 | render_y_ + subway_item.y * render_width_ / image_size.GetWidth(); | ||
| 376 | 357 | ||
| 377 | int real_area_size = | 358 | int real_area_size = |
| 378 | render_width_ * | 359 | render_width_ * |
| @@ -385,17 +366,31 @@ void SubwayMap::Redraw() { | |||
| 385 | if (draw_type == ItemDrawType::kBox) { | 366 | if (draw_type == ItemDrawType::kBox) { |
| 386 | dc.SetPen(*wxThePenList->FindOrCreatePen(*wxBLACK, 1)); | 367 | dc.SetPen(*wxThePenList->FindOrCreatePen(*wxBLACK, 1)); |
| 387 | dc.SetBrush(*brush_color); | 368 | dc.SetBrush(*brush_color); |
| 388 | dc.DrawRectangle({real_area_x, real_area_y}, | 369 | dc.DrawRectangle(real_area_pos, |
| 389 | {real_area_size, real_area_size}); | 370 | {real_area_size, real_area_size}); |
| 390 | } else if (draw_type == ItemDrawType::kOwl) { | 371 | } else if (draw_type == ItemDrawType::kOwl) { |
| 391 | wxBitmap owl_bitmap = wxBitmap( | 372 | wxBitmap owl_bitmap = wxBitmap( |
| 392 | owl_image_.Scale(real_area_size, real_area_size, | 373 | owl_image_.Scale(real_area_size, real_area_size, |
| 393 | wxIMAGE_QUALITY_BILINEAR)); | 374 | wxIMAGE_QUALITY_BILINEAR)); |
| 394 | dc.DrawBitmap(owl_bitmap, {real_area_x, real_area_y}); | 375 | dc.DrawBitmap(owl_bitmap, real_area_pos); |
| 395 | } | 376 | } |
| 396 | } | 377 | } |
| 397 | } | 378 | } |
| 398 | 379 | ||
| 380 | |||
| 381 | wxPoint SubwayMap::MapPosToRenderPos(wxPoint pos) const { | ||
| 382 | return {pos.x * render_width_ / map_image_.GetSize().GetWidth() + render_x_, | ||
| 383 | pos.y * render_width_ / map_image_.GetSize().GetWidth() + render_y_}; | ||
| 384 | } | ||
| 385 | |||
| 386 | wxPoint SubwayMap::RenderPosToMapPos(wxPoint pos) const { | ||
| 387 | return { | ||
| 388 | std::clamp((pos.x - render_x_) * map_image_.GetWidth() / render_width_, 0, | ||
| 389 | map_image_.GetWidth() - 1), | ||
| 390 | std::clamp((pos.y - render_y_) * map_image_.GetWidth() / render_width_, 0, | ||
| 391 | map_image_.GetHeight() - 1)}; | ||
| 392 | } | ||
| 393 | |||
| 399 | quadtree::Box<float> SubwayMap::GetItemBox::operator()(const int& id) const { | 394 | quadtree::Box<float> SubwayMap::GetItemBox::operator()(const int& id) const { |
| 400 | const SubwayItem &subway_item = GD_GetSubwayItem(id); | 395 | const SubwayItem &subway_item = GD_GetSubwayItem(id); |
| 401 | return {static_cast<float>(subway_item.x), static_cast<float>(subway_item.y), | 396 | return {static_cast<float>(subway_item.x), static_cast<float>(subway_item.y), |
| diff --git a/src/subway_map.h b/src/subway_map.h index 52d07b8..0d26d0b 100644 --- a/src/subway_map.h +++ b/src/subway_map.h | |||
| @@ -32,6 +32,9 @@ class SubwayMap : public wxPanel { | |||
| 32 | 32 | ||
| 33 | void Redraw(); | 33 | void Redraw(); |
| 34 | 34 | ||
| 35 | wxPoint MapPosToRenderPos(wxPoint pos) const; | ||
| 36 | wxPoint RenderPosToMapPos(wxPoint pos) const; | ||
| 37 | |||
| 35 | wxImage map_image_; | 38 | wxImage map_image_; |
| 36 | wxImage owl_image_; | 39 | wxImage owl_image_; |
| 37 | wxBitmap unchecked_eye_; | 40 | wxBitmap unchecked_eye_; |
