#include "viz/surface_plot_3d.h" #include "imgui.h" #include "implot3d.h" #include namespace fn { void surface_plot_3d(const char* title, const SurfacePlot3DConfig& cfg) { if (!cfg.z || cfg.nx < 2 || cfg.ny < 2) { ImGui::BeginGroup(); ImGui::TextDisabled("%s", title ? title : "##surface_plot_3d"); ImGui::TextWrapped("surface_plot_3d: necesita z != nullptr y nx,ny >= 2 (recibido %dx%d)", cfg.nx, cfg.ny); ImGui::EndGroup(); return; } // Genera coordenadas X / Y por vertice (row-major, mismo layout que z). // ImPlot3D::PlotSurface espera arrays paralelos de nx*ny valores. const int total = cfg.nx * cfg.ny; std::vector xs(total); std::vector ys(total); const float dx = (cfg.nx > 1) ? (cfg.x_max - cfg.x_min) / float(cfg.nx - 1) : 0.f; const float dy = (cfg.ny > 1) ? (cfg.y_max - cfg.y_min) / float(cfg.ny - 1) : 0.f; for (int j = 0; j < cfg.ny; ++j) { const float y = cfg.y_min + dy * float(j); const int row = j * cfg.nx; for (int i = 0; i < cfg.nx; ++i) { xs[row + i] = cfg.x_min + dx * float(i); ys[row + i] = y; } } if (ImPlot3D::BeginPlot(title, cfg.size)) { ImPlot3D::SetupAxes(cfg.x_label, cfg.y_label, cfg.z_label); ImPlot3D::PlotSurface("##surface", xs.data(), ys.data(), cfg.z, cfg.nx, cfg.ny); ImPlot3D::EndPlot(); } if (cfg.show_colormap) { // ImPlot3D rinde su propia leyenda dentro del plot; el flag aqui se // reserva como contrato API por si en el futuro se necesita una // colormap-bar externa (no implementado todavia). } } } // namespace fn