void TaskEditPanel::EditTaskPoint(unsigned ItemIndex) { if (ItemIndex < ordered_task->TaskSize()) { if (dlgTaskPointShowModal(&ordered_task, ItemIndex)) { *task_modified = true; ordered_task->ClearName(); ordered_task->UpdateGeometry(); RefreshView(); } } else if (!ordered_task->IsFull()) { OrderedTaskPoint* point = nullptr; AbstractTaskFactory &factory = ordered_task->GetFactory(); const Waypoint* way_point = ShowWaypointListDialog(ordered_task->TaskSize() > 0 ? ordered_task->GetPoint(ordered_task->TaskSize() - 1).GetLocation() : CommonInterface::Basic().location, ordered_task, ItemIndex); if (!way_point) return; if (ItemIndex == 0) { point = (OrderedTaskPoint*)factory.CreateStart(*way_point); } else { point = (OrderedTaskPoint*)factory.CreateIntermediate(*way_point); } if (point == nullptr) return; if (factory.Append(*point, true)) { *task_modified = true; ordered_task->ClearName(); ordered_task->UpdateGeometry(); RefreshView(); } delete point; } }
void TaskEditPanel::OnClearAllClicked() { if ((ordered_task->TaskSize() < 2) || (ShowMessageBox(_("Clear all points?"), _("Task edit"), MB_YESNO|MB_ICONQUESTION) == IDYES)) { ordered_task->RemoveAllPoints(); ordered_task->ClearName(); *task_modified = true; RefreshView(); } }
void TaskEditPanel::ReverseTask() { if (ordered_task->TaskSize() < 2) return; const unsigned start_index = 0; const unsigned finish_index = ordered_task->TaskSize() - 1; const Waypoint start_wp = ordered_task->GetTaskPoint(start_index).GetWaypoint(); const Waypoint finish_wp = ordered_task->GetTaskPoint(finish_index).GetWaypoint(); if (start_wp.location != finish_wp.location) { // swap start/finish TP if at different location but leave OZ type intact ordered_task->Relocate(start_index, finish_wp); ordered_task->Relocate(finish_index, start_wp); // remove optional start points while (ordered_task->HasOptionalStarts()) ordered_task->RemoveOptionalStart(0); } // reverse intermediate TPs order keeping the OZ type with the respective TP unsigned length = ordered_task->TaskSize()-1; for (unsigned i = 1; i < length - 1; ++i) { const OrderedTaskPoint &otp = ordered_task->GetTaskPoint(length - 1); if (!ordered_task->GetFactory().Insert(otp, i, false)) return; if (!ordered_task->GetFactory().Remove(length, false)) return; } *task_modified = true; ordered_task->ClearName(); ordered_task->GetFactory().CheckAddFinish(); ordered_task->UpdateStatsGeometry(); ordered_task->UpdateGeometry(); RefreshView(); }
void TaskEditPanel::MoveDown() { unsigned index = GetList().GetCursorIndex(); if (index >= ordered_task->TaskSize()) return; if (!ordered_task->GetFactory().Swap(index, true)) return; GetList().SetCursorIndex(index + 1); *task_modified = true; RefreshView(); }
bool FAITriangleValidator::Validate(const OrderedTask &task) { if (!task.GetFactory().IsUnique()) return false; if (task.TaskSize() != 4) return false; const fixed d1 = task.GetTaskPoint(1).GetVectorPlanned().distance; const fixed d2 = task.GetTaskPoint(2).GetVectorPlanned().distance; const fixed d3 = task.GetTaskPoint(3).GetVectorPlanned().distance; return TestDistances(d1, d2, d3); }
void TaskRenderer::Draw(const OrderedTask &task) { tpv.SetBoundingBox(task.get_bounding_box(screen_bounds)); tpv.SetActiveIndex(task.GetActiveIndex()); for (unsigned i = 0; i < 4; i++) { tpv.ResetIndex(); if (i != RenderTaskPoint::LAYER_SYMBOLS && i != RenderTaskPoint::LAYER_LEG) { tpv.SetModeOptional(true); for (unsigned j = 0, end = task.optional_start_points_size(); j < end; ++j) tpv.Draw(*task.get_optional_start(j), (RenderTaskPoint::Layer)i); } tpv.SetModeOptional(false); for (unsigned j = 0, end = task.TaskSize(); j < end; ++j) tpv.Draw(task.GetTaskPoint(j), (RenderTaskPoint::Layer)i); } }
void TaskEditPanel::RefreshView() { UpdateButtons(); dialog.InvalidateTaskView(); unsigned length = ordered_task->TaskSize(); if (!ordered_task->IsFull()) ++length; GetList().SetLength(length); GetList().Invalidate(); { TCHAR text[300]; OrderedTaskSummary(ordered_task, text, false); summary.SetText(text); } if (GetList().IsVisible() && two_widgets != nullptr) two_widgets->UpdateLayout(); }
static void RenderFAISectors(Canvas &canvas, const WindowProjection &projection, const OrderedTask &task) { const FAITriangleSettings &settings = task.GetOrderedTaskSettings().fai_triangle; const unsigned size = task.TaskSize(); const unsigned end = size - 1; for (unsigned i = 0; i != end; ++i) RenderFAISector(canvas, projection, task.GetPoint(i).GetLocation(), task.GetPoint(i + 1).GetLocation(), true, settings); for (unsigned i = 0; i != end; ++i) RenderFAISector(canvas, projection, task.GetPoint(i).GetLocation(), task.GetPoint(i + 1).GetLocation(), false, settings); }
void TaskPointWidget::RefreshView() { map.Invalidate(); OrderedTaskPoint &tp = ordered_task->GetPoint(active_index); properties_dock.SetWidget(new PanelWidget()); ObservationZonePoint &oz = tp.GetObservationZone(); const bool is_fai_general = ordered_task->GetFactoryType() == TaskFactoryType::FAI_GENERAL; properties_widget = CreateObservationZoneEditWidget(oz, is_fai_general); if (properties_widget != nullptr) { properties_widget->SetListener(this); properties_dock.SetWidget(properties_widget); } type_label.SetCaption(OrderedTaskPointName(ordered_task->GetFactory().GetType(tp))); previous_button->SetEnabled(active_index > 0); next_button->SetEnabled(active_index < (ordered_task->TaskSize() - 1)); optional_starts.SetVisible(active_index == 0); if (!ordered_task->HasOptionalStarts()) optional_starts.SetCaption(_("Enable Alternate Starts")); else { StaticString<50> tmp; tmp.Format(_T("%s (%d)"), _("Edit Alternates"), ordered_task->GetOptionalStartPointCount()); optional_starts.SetCaption(tmp); } if (tp.GetType() == TaskPointType::AST) { const ASTPoint &ast = (const ASTPoint &)tp; score_exit.Show(); score_exit.SetState(ast.GetScoreExit()); } else score_exit.Hide(); StaticString<100> name_prefix_buffer, type_buffer; switch (tp.GetType()) { case TaskPointType::START: type_buffer = _("Start point"); name_prefix_buffer = _T("Start: "); break; case TaskPointType::AST: type_buffer = _("Task point"); name_prefix_buffer.Format(_T("%d: "), active_index); break; case TaskPointType::AAT: type_buffer = _("Assigned area point"); name_prefix_buffer.Format(_T("%d: "), active_index); break; case TaskPointType::FINISH: type_buffer = _("Finish point"); name_prefix_buffer = _T("Finish: "); break; default: gcc_unreachable(); } dialog.SetCaption(type_buffer); { StaticString<100> buffer; buffer.Format(_T("%s %s"), name_prefix_buffer.c_str(), tp.GetWaypoint().name.c_str()); waypoint_name.SetCaption(buffer); } }
void PrintHelper::orderedtask_print(const OrderedTask &task, const AircraftState &state) { abstracttask_print(task, state); if (!task.CheckTask()) return; std::ofstream fi("output/results/res-isolines.txt"); for (unsigned i = 0; i < task.TaskSize(); ++i) { const OrderedTaskPoint &tp = task.GetPoint(i); fi << "## point " << i << "\n"; if (tp.GetType() == TaskPointType::AAT) { aatpoint_print(fi, (const AATPoint &)tp, state, task.GetTaskProjection(), 1); } else { orderedtaskpoint_print(fi, tp, state, 1); } fi << "\n"; } std::ofstream f1("output/results/res-task.txt"); f1 << "#### Task points\n"; for (unsigned i = 0; i < task.TaskSize(); ++i) { f1 << "## point " << i << " ###################\n"; const OrderedTaskPoint &tp = task.GetPoint(i); if (tp.GetType() == TaskPointType::AAT) { aatpoint_print(f1, (const AATPoint &)tp, state, task.GetTaskProjection(), 0); } else { orderedtaskpoint_print(f1, tp, state, 0); } f1 << "\n"; } std::ofstream f5("output/results/res-ssample.txt"); f5 << "#### Task sampled points\n"; for (unsigned i =0 ; i < task.TaskSize(); ++i) { const OrderedTaskPoint &tp = task.GetPoint(i); f5 << "## point " << i << "\n"; sampledtaskpoint_print_samples(f5, tp, state); f5 << "\n"; } std::ofstream f2("output/results/res-max.txt"); f2 << "#### Max task\n"; for (unsigned i = 0; i < task.TaskSize(); ++i) { const OrderedTaskPoint &tp = task.GetPoint(i); f2 << tp.GetLocationMax().longitude << " " << tp.GetLocationMax().latitude << "\n"; } std::ofstream f3("output/results/res-min.txt"); f3 << "#### Min task\n"; for (unsigned i = 0; i < task.TaskSize(); ++i) { const OrderedTaskPoint &tp = task.GetPoint(i); f3 << tp.GetLocationMin().longitude << " " << tp.GetLocationMin().latitude << "\n"; } std::ofstream f4("output/results/res-rem.txt"); f4 << "#### Remaining task\n"; for (unsigned i = 0; i < task.TaskSize(); ++i) { const OrderedTaskPoint &tp = task.GetPoint(i); f4 << tp.GetLocationRemaining().longitude << " " << tp.GetLocationRemaining().latitude << "\n"; } }
/** * Is the current task point the finish point? */ gcc_pure static bool FinishIsCurrent(const OrderedTask &task) { return task.GetActiveTaskPointIndex() + 1 == task.TaskSize(); }
void TaskEditPanel::OnPaintItem(Canvas &canvas, const PixelRect rc, unsigned DrawListIndex) { assert(DrawListIndex <= ordered_task->TaskSize()); const PixelScalar line_height = rc.bottom - rc.top; TCHAR buffer[120]; const Font &name_font = *dialog.GetLook().list.font_bold; const Font &small_font = *dialog.GetLook().small_font; // Draw "Add turnpoint" label if (DrawListIndex == ordered_task->TaskSize()) { canvas.Select(name_font); canvas.SetTextColor(COLOR_BLACK); _stprintf(buffer, _T(" (%s)"), _("Add Turnpoint")); canvas.DrawText(rc.left + line_height + Layout::FastScale(2), rc.top + line_height / 2 - name_font.GetHeight() / 2, buffer); return; } const OrderedTaskPoint &tp = ordered_task->GetTaskPoint(DrawListIndex); GeoVector leg = tp.GetNominalLegVector(); bool show_leg_info = leg.distance > fixed(0.01); // Draw icon const RasterPoint pt(rc.left + line_height / 2, rc.top + line_height / 2); PixelScalar radius = std::min(PixelScalar(line_height / 2 - Layout::FastScale(4)), Layout::FastScale(10)); OZPreviewRenderer::Draw(canvas, tp.GetObservationZone(), pt, radius, task_look, CommonInterface::GetMapSettings().airspace, airspace_look); // Y-Coordinate of the second row PixelScalar top2 = rc.top + name_font.GetHeight() + Layout::FastScale(4); // Use small font for details canvas.Select(small_font); canvas.SetTextColor(COLOR_BLACK); UPixelScalar leg_info_width = 0; if (show_leg_info) { // Draw leg distance FormatUserDistanceSmart(leg.distance, buffer, true); UPixelScalar width = leg_info_width = canvas.CalcTextWidth(buffer); canvas.DrawText(rc.right - Layout::FastScale(2) - width, rc.top + Layout::FastScale(2) + (name_font.GetHeight() - small_font.GetHeight()) / 2, buffer); // Draw leg bearing FormatBearing(buffer, ARRAY_SIZE(buffer), leg.bearing); width = canvas.CalcTextWidth(buffer); canvas.DrawText(rc.right - Layout::FastScale(2) - width, top2, buffer); if (width > leg_info_width) leg_info_width = width; leg_info_width += Layout::FastScale(2); } // Draw details line PixelScalar left = rc.left + line_height + Layout::FastScale(2); OrderedTaskPointRadiusLabel(tp.GetObservationZone(), buffer); if (!StringIsEmpty(buffer)) canvas.DrawClippedText(left, top2, rc.right - leg_info_width - left, buffer); // Draw turnpoint name canvas.Select(name_font); OrderedTaskPointLabel(tp.GetType(), tp.GetWaypoint().name.c_str(), DrawListIndex, buffer); canvas.DrawClippedText(left, rc.top + Layout::FastScale(2), rc.right - leg_info_width - left, buffer); }
void TaskEditPanel::OnPaintItem(Canvas &canvas, const PixelRect rc, unsigned DrawListIndex) { assert(DrawListIndex <= ordered_task->TaskSize()); const unsigned padding = Layout::GetTextPadding(); const unsigned line_height = rc.bottom - rc.top; TCHAR buffer[120]; // Draw "Add turnpoint" label if (DrawListIndex == ordered_task->TaskSize()) { row_renderer.DrawFirstRow(canvas, rc, _("Add Turnpoint")); return; } const OrderedTaskPoint &tp = ordered_task->GetTaskPoint(DrawListIndex); GeoVector leg = tp.GetNominalLegVector(); bool show_leg_info = leg.distance > fixed(0.01); PixelRect text_rc = rc; text_rc.left += line_height + padding; if (show_leg_info) { // Use small font for details canvas.Select(row_renderer.GetSecondFont()); // Draw leg distance FormatUserDistanceSmart(leg.distance, buffer, true); unsigned width = canvas.CalcTextWidth(buffer); const int x1 = rc.right - padding - width; canvas.DrawText(x1, rc.top + row_renderer.GetFirstY(), buffer); // Draw leg bearing FormatBearing(buffer, ARRAY_SIZE(buffer), leg.bearing); width = canvas.CalcTextWidth(buffer); const int x2 = rc.right - padding - width; canvas.DrawText(x2, rc.top + row_renderer.GetSecondY(), buffer); text_rc.right = std::min(x1, x2) - padding; } // Draw details line OrderedTaskPointRadiusLabel(tp.GetObservationZone(), buffer); if (!StringIsEmpty(buffer)) row_renderer.DrawSecondRow(canvas, text_rc, buffer); // Draw turnpoint name OrderedTaskPointLabel(tp.GetType(), tp.GetWaypoint().name.c_str(), DrawListIndex, buffer); row_renderer.DrawFirstRow(canvas, text_rc, buffer); // Draw icon const RasterPoint pt(rc.left + line_height / 2, rc.top + line_height / 2); const unsigned radius = line_height / 2 - padding; OZPreviewRenderer::Draw(canvas, tp.GetObservationZone(), pt, radius, task_look, CommonInterface::GetMapSettings().airspace, airspace_look); }
void PaintTask(Canvas &canvas, const WindowProjection &projection, const OrderedTask &task, const GeoPoint &location, const MapSettings &settings_map, const TaskLook &task_look, const AirspaceLook &airspace_look, const RasterTerrain *terrain, const Airspaces *airspaces, bool fai_sectors, int highlight_index) { BackgroundRenderer background; background.SetTerrain(terrain); background.Draw(canvas, projection, settings_map.terrain); if (airspaces != NULL) { AirspaceRenderer airspace_renderer(airspace_look); airspace_renderer.SetAirspaces(airspaces); #ifndef ENABLE_OPENGL BufferCanvas stencil_canvas; stencil_canvas.Create(canvas); #endif airspace_renderer.Draw(canvas, #ifndef ENABLE_OPENGL stencil_canvas, #endif projection, settings_map.airspace); } #ifdef ENABLE_OPENGL /* desaturate the map background, to focus on the task */ canvas.FadeToWhite(0xc0); #endif if (fai_sectors && IsFAITriangleApplicable(task)) { static constexpr Color fill_color = COLOR_YELLOW; #if defined(ENABLE_OPENGL) || defined(USE_MEMORY_CANVAS) #ifdef ENABLE_OPENGL const ScopeAlphaBlend alpha_blend; #endif canvas.Select(Brush(fill_color.WithAlpha(40))); canvas.Select(Pen(1, COLOR_BLACK.WithAlpha(80))); RenderFAISectors(canvas, projection, task); #else BufferCanvas buffer_canvas; buffer_canvas.Create(canvas); buffer_canvas.ClearWhite(); #ifdef HAVE_HATCHED_BRUSH buffer_canvas.Select(airspace_look.brushes[3]); buffer_canvas.SetTextColor(fill_color); buffer_canvas.SetBackgroundColor(COLOR_WHITE); #else buffer_canvas.Select(Brush(fill_color)); #endif buffer_canvas.SelectNullPen(); RenderFAISectors(buffer_canvas, projection, task); canvas.CopyAnd(buffer_canvas); canvas.SelectHollowBrush(); canvas.SelectBlackPen(); RenderFAISectors(canvas, projection, task); #endif } OZRenderer ozv(task_look, airspace_look, settings_map.airspace); TaskPointRenderer tpv(canvas, projection, task_look, task.GetTaskProjection(), ozv, false, TaskPointRenderer::NONE, location); TaskRenderer dv(tpv, projection.GetScreenBounds()); dv.Draw(task); // highlight a task point if (highlight_index >= 0 && highlight_index < (int) task.TaskSize()) { /* TODO: clumsy way of highlighting. maybe it should be done by * painting the task point with a different pen and brush, * e.g. red, 4px wide */ auto pt = projection.GeoToScreen(task.GetPoint(highlight_index). GetLocation()); canvas.Select(task_look.highlight_pen); canvas.DrawLine(pt.x - 7, pt.y - 7, pt.x + 7, pt.y + 7); canvas.DrawLine(pt.x + 7, pt.y - 7, pt.x - 7, pt.y + 7); } }