Panel Grid¶
This example arranges four independent panels in a 2x2 figure grid.
Preview¶
Run And Adapt¶
Commands below assume a Datoviz source checkout and start at the repository root. Use your configured build environment; Python routes additionally require local bindings.
| Route | Availability | Command or action |
|---|---|---|
| C | Canonical native source | just example-c features/panel_grid (build and run), or rerun ./build/examples/c/features/panel_grid |
| Python | Available; manually maintained direct-engine example | python3 -m examples.python.gallery.features.panel_grid |
| Browser | Live WebGPU route | Open live example |
This example is approved as a starting point for user code and coding agents. Keep the object lifetimes and data shapes intact while adapting the data and styling.
What To Look For¶
Each panel has its own border, background, and small point visual with position, color, and diameter_px arrays. The same point pattern is repeated with a different accent color in each grid cell, so compare how gutters, margins, and panel-local clipping keep the plots separated. Grid panels are useful for small multiples and side-by-side scientific comparisons.
Source¶
#!/usr/bin/env python3
"""Two-by-two panel grid with one point cluster per panel."""
from __future__ import annotations
import numpy as np
import datoviz as dvz
from examples.python.gallery import common as ex
def main() -> None:
scene = dvz.dvz_scene()
figure = dvz.dvz_figure(scene, ex.WIDTH, ex.HEIGHT, 0)
centers = [(-0.32, 0.22), (0.34, 0.18), (-0.24, -0.28), (0.28, -0.22)]
colors = [ex.CYAN, ex.GREEN, ex.YELLOW, ex.RED]
for i, (col, row) in enumerate([(0, 0), (1, 0), (0, 1), (1, 1)]):
panel = ex.panel_rect(figure, 0.05 + 0.48 * col, 0.06 + 0.45 * row, 0.42, 0.38)
cx, cy = centers[i]
positions = np.array(
[[cx - 0.18, cy - 0.12, 0.0], [cx, cy + 0.18, 0.0], [cx + 0.18, cy - 0.12, 0.0]],
dtype=np.float32,
)
ex.add_points(
scene,
panel,
positions,
ex.color_array(colors[i], ex.TEXT, colors[i]),
np.array([32.0, 44.0, 32.0], dtype=np.float32),
)
ex.run(scene, figure, "Panel Grid")
if __name__ == "__main__":
main()
/*
* Copyright (c) 2021 Cyrille Rossant and contributors. All rights reserved.
* Licensed under the MIT license. See LICENSE file in the project root for details.
* SPDX-License-Identifier: MIT
*/
/* This example arranges four independent panels in a 2x2 figure grid.
*
* What to look for: each panel has its own border, background, and small point visual with
* position, color, and diameter_px arrays. The same point pattern is repeated with a different
* accent color in each grid cell, so compare how gutters, margins, and panel-local clipping keep
* the plots separated. Grid panels are useful for small multiples and side-by-side scientific
* comparisons.
*
* Scenario: features_panel_grid
* Style: features, graphite_cyan, 1280x720 window target
*
* Build: just example-c features/panel_grid
* Run: ./build/examples/c/features/panel_grid --live
* Smoke: ./build/examples/c/features/panel_grid --png
*/
/*************************************************************************************************/
/* Includes */
/*************************************************************************************************/
#include <stdbool.h>
#include <stdint.h>
#include "datoviz/scene.h"
#include "example_style.h"
#include "runner/scenario_runner.h"
/*************************************************************************************************/
/* Forward declarations */
/*************************************************************************************************/
DvzScenarioSpec dvz_example_panel_grid_scenario(void);
/*************************************************************************************************/
/* Constants */
/*************************************************************************************************/
#define WIDTH EXAMPLE_WINDOW_WIDTH
#define HEIGHT EXAMPLE_WINDOW_HEIGHT
#define PANEL_COUNT 4u
#define POINT_COUNT 4u
/*************************************************************************************************/
/* Helpers */
/*************************************************************************************************/
/**
* Add one small point group to a grid panel.
*
* @param scene scene owning the visual
* @param panel panel receiving the visual
* @param accent main color for this panel
* @return true when the visual was added
*/
static bool _add_panel_points(DvzScene* scene, DvzPanel* panel, DvzColor accent)
{
const vec3 positions[POINT_COUNT] = {
{-0.35f, -0.28f, 0.0f},
{+0.35f, -0.28f, 0.0f},
{+0.00f, +0.32f, 0.0f},
{+0.00f, +0.00f, 0.0f},
};
DvzColor colors[POINT_COUNT] = {
accent,
example_graphite_cyan_color(EXAMPLE_STYLE_COLOR_ACCENT_SECONDARY),
example_graphite_cyan_color(EXAMPLE_STYLE_COLOR_TEXT),
example_graphite_cyan_color(EXAMPLE_STYLE_COLOR_WARNING),
};
const float diameters[POINT_COUNT] = {26.0f, 26.0f, 34.0f, 12.0f};
DvzVisual* point = dvz_point(scene, 0);
if (point == NULL)
return false;
DvzVisualDataUpdate updates[] = {
{.attr_name = "position", .data = positions, .item_count = POINT_COUNT},
{.attr_name = "color", .data = colors, .item_count = POINT_COUNT},
{.attr_name = "diameter_px", .data = diameters, .item_count = POINT_COUNT},
};
if (dvz_visual_set_data_many(point, updates, 3) != 0)
return false;
DvzPointStyleDesc style = dvz_point_style_desc();
style.aspect = DVZ_SHAPE_ASPECT_FILLED;
style.stroke_width_px = 0.0f;
if (dvz_point_set_style(point, &style) != 0)
return false;
if (dvz_visual_set_depth_test(point, false) != 0)
return false;
return dvz_panel_add_visual(panel, point, NULL) == 0;
}
/*************************************************************************************************/
/* Scenario callbacks */
/*************************************************************************************************/
/**
* Initialize the grid layout scenario.
*
* @param ctx scenario context
* @param out_user scenario state output
* @return true on success
*/
static bool _scenario_init(DvzScenarioContext* ctx, void** out_user)
{
if (ctx == NULL)
return false;
if (out_user != NULL)
*out_user = NULL;
ctx->figure = dvz_figure(ctx->scene, ctx->width, ctx->height, 0);
if (ctx->figure == NULL)
return false;
DvzGrid* grid = dvz_figure_grid(ctx->figure, 2, 2);
if (grid == NULL)
return false;
if (dvz_grid_set_margins(
grid,
&(DvzPanelReserve){
.left_px = 56.0f, .right_px = 56.0f, .top_px = 56.0f, .bottom_px = 56.0f}) != DVZ_OK)
return false;
if (dvz_grid_set_gutter(grid, 36.0f, 36.0f) != DVZ_OK)
return false;
DvzPanel* panels[PANEL_COUNT] = {
dvz_grid_panel(grid, 0, 0),
dvz_grid_panel(grid, 0, 1),
dvz_grid_panel(grid, 1, 0),
dvz_grid_panel(grid, 1, 1),
};
DvzColor accents[PANEL_COUNT] = {
example_graphite_cyan_color(EXAMPLE_STYLE_COLOR_ACCENT_PRIMARY),
example_graphite_cyan_color(EXAMPLE_STYLE_COLOR_ACCENT_SECONDARY),
example_graphite_cyan_color(EXAMPLE_STYLE_COLOR_WARNING),
example_graphite_cyan_color(EXAMPLE_STYLE_COLOR_ERROR),
};
for (uint32_t i = 0; i < PANEL_COUNT; i++)
{
if (panels[i] == NULL)
return false;
example_graphite_cyan_set_panel_background(panels[i]);
DvzPanelBorderDesc border = dvz_panel_border_desc();
border.color = example_graphite_cyan_color(EXAMPLE_STYLE_COLOR_GRID);
border.width_px = 1.5f;
if (dvz_panel_set_border(panels[i], &border) != DVZ_OK)
return false;
if (!_add_panel_points(ctx->scene, panels[i], accents[i]))
return false;
}
return true;
}
/**
* Return the panel-grid scenario specification.
*
* @return scenario specification
*/
DvzScenarioSpec dvz_example_panel_grid_scenario(void)
{
return (DvzScenarioSpec){
.id = "features_panel_grid",
.title = "Panel Grid",
.width = WIDTH,
.height = HEIGHT,
.fps = 60.0,
.requirements = DVZ_SCENARIO_REQ_POINT_VISUAL,
.init = _scenario_init,
};
}
/*************************************************************************************************/
/* Functions */
/*************************************************************************************************/
/**
* Run the grid layout feature example through the native scenario runner.
*
* @param argc command-line argument count
* @param argv command-line argument vector
* @return process exit code
*/
#ifndef DVZ_EXAMPLE_NO_MAIN
int main(int argc, char** argv)
{
DvzScenarioSpec spec = dvz_example_panel_grid_scenario();
return dvz_scenario_run_native_cli(&spec, argc, argv) == 0 ? 0 : 1;
}
#endif
Example details
- ID:
features_panel_grid - Category:
feature - Lane:
features - Status:
supported - Source:
examples/c/features/panel_grid.c - Approved adaptation starter:
yes - Python source:
examples/python/gallery/features/panel_grid.py - Python adaptation: Available; manually maintained direct-engine example
- Browser support: Live in browser
- WebGPU live route:
examples/webgpu/live.html?id=features_panel_grid - Browser capability tags:
panel-grid,point - Validation:
smoke+screenshot
Data
| Field | Value |
|---|---|
kind |
synthetic |
