feat(viz): surface_plot_3d real (ImPlot3D) + scatter_3d nuevo
surface_plot_3d (v2.0.0): quita el STUB. API basada en SurfacePlot3DConfig (z[nx*ny] row-major + ranges X/Y) que delega en ImPlot3D::PlotSurface. Las coordenadas X/Y por vertice se generan internamente desde [x_min, x_max] x [y_min, y_max]. scatter_3d (v1.0.0): nuevo primitivo. Scatter 3D con tamano y color opcionales por punto via ImPlot3DSpec::MarkerSizes / MarkerFillColors. Util para PCA / clustering / nubes de puntos sinteticas. Ambos namespace fn::, kind component, purity pure. Orbit / zoom / pan los aporta ImPlot3D nativo. Issue 0028.
This commit is contained in:
@@ -1,12 +1,50 @@
|
||||
#include "viz/surface_plot_3d.h"
|
||||
#include "imgui.h"
|
||||
|
||||
void surface_plot_3d(const char* title, const float* values, int rows, int cols,
|
||||
float z_min, float z_max) {
|
||||
ImGui::BeginGroup();
|
||||
ImGui::TextDisabled("[STUB] %s", title);
|
||||
ImGui::TextWrapped("surface_plot_3d requires ImPlot3D. "
|
||||
"Add it to cpp/vendor/implot3d/ and rebuild.");
|
||||
ImGui::Text("Data: %dx%d, range [%.2f, %.2f]", rows, cols, z_min, z_max);
|
||||
ImGui::EndGroup();
|
||||
#include "imgui.h"
|
||||
#include "implot3d.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
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<float> xs(total);
|
||||
std::vector<float> 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
|
||||
|
||||
Reference in New Issue
Block a user