From 5b70c753464d2b49ba7fbc78092cd68e0b24fa57 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 10 Sep 2026 06:34:23 +0000 Subject: [PATCH 1/5] feat(ggplot2): implement wireframe-3d-basic Regen from quality 89. Addressed: - interior crosshatch near the central humps: replaced the semi-transparent geom_path grid lines with depth-sorted opaque geom_polygon quads (painter's algorithm), so nearer mesh cells occlude the far-side grid lines that used to bleed through - the same hidden-line trick base R's persp() uses instead of a real z-buffer - grid resolution raised 15x15 -> 20x20, now inside the spec's recommended 20x20-50x50 range; the occlusion keeps this from reintroducing clutter - added a distance-based alpha falloff on the mesh edges (bolder near camera, softer far away) as an extra depth cue - added a faint floor reference plane for spatial grounding (minor, carried over from earlier reviews) Kept unchanged: camera projection math, axis box/ticks/labels, theme tokens, canvas size (8x4.5in @ 400dpi -> 3200x1800, still on target). --- .../implementations/r/ggplot2.R | 82 +++++++++++++++---- 1 file changed, 66 insertions(+), 16 deletions(-) diff --git a/plots/wireframe-3d-basic/implementations/r/ggplot2.R b/plots/wireframe-3d-basic/implementations/r/ggplot2.R index 4fe4b0c448e..c6e969421b5 100644 --- a/plots/wireframe-3d-basic/implementations/r/ggplot2.R +++ b/plots/wireframe-3d-basic/implementations/r/ggplot2.R @@ -18,7 +18,7 @@ BRAND <- "#009E73" # --- Camera: orthographic projection (elevation 30, azimuth 45) --------------- # ggplot2 has no 3D grammar, so the mesh is projected to 2D screen coordinates # ourselves (the same technique any static 3D renderer uses under the hood), -# then drawn with plain geom_path/geom_segment/geom_text. +# then drawn with plain geom_polygon/geom_segment/geom_text. elev <- 30 * pi / 180 azim <- 45 * pi / 180 @@ -39,21 +39,71 @@ up_axis <- c( z_lift <- 3.5 # visual height exaggeration so the shallow ripple reads clearly project_x <- function(x, y, z) x * right_axis[1] + y * right_axis[2] + z * z_lift * right_axis[3] project_y <- function(x, y, z) x * up_axis[1] + y * up_axis[2] + z * z_lift * up_axis[3] +depth_toward_camera <- function(x, y, z) x * view_dir[1] + y * view_dir[2] + z * z_lift * view_dir[3] # --- Data: ripple surface z = sin(sqrt(x^2 + y^2)) ----------------------------- -grid_n <- 15 +grid_n <- 20 x_vals <- seq(-6, 6, length.out = grid_n) y_vals <- seq(-6, 6, length.out = grid_n) - -surface <- expand.grid(x = x_vals, y = y_vals) -surface$z <- sin(sqrt(surface$x^2 + surface$y^2)) -surface$px <- project_x(surface$x, surface$y, surface$z) -surface$py <- project_y(surface$x, surface$y, surface$z) - -z_min <- min(surface$z) -z_max <- max(surface$z) -floor_z <- z_min - 0.3 -ceil_z <- z_max + 0.3 +z_fun <- function(x, y) sin(sqrt(x^2 + y^2)) + +z_range <- range(outer(x_vals, y_vals, z_fun)) +floor_z <- z_range[1] - 0.3 +ceil_z <- z_range[2] + 0.3 + +# --- Mesh quads with painter's-algorithm hidden-line removal ------------------ +# Each grid cell becomes a filled quad. Quads are drawn back-to-front (farthest +# from the camera first) with an opaque page-background fill, so nearer quads +# occlude the grid lines sitting behind them - the same trick base R's persp() +# uses instead of a real z-buffer. This lets the mesh resolution sit inside the +# spec's recommended 20x20-50x50 range without the interior crosshatching a +# flat semi-transparent wireframe produces. +n_cells <- (grid_n - 1)^2 +mesh <- data.frame( + quad_id = integer(n_cells * 4), + corner = integer(n_cells * 4), + px = numeric(n_cells * 4), + py = numeric(n_cells * 4) +) +quad_depth <- numeric(n_cells) + +row <- 1 +quad <- 1 +for (i in seq_len(grid_n - 1)) { + for (j in seq_len(grid_n - 1)) { + cx <- c(x_vals[i], x_vals[i + 1], x_vals[i + 1], x_vals[i]) + cy <- c(y_vals[j], y_vals[j], y_vals[j + 1], y_vals[j + 1]) + cz <- z_fun(cx, cy) + idx <- row:(row + 3) + mesh$quad_id[idx] <- quad + mesh$corner[idx] <- 1:4 + mesh$px[idx] <- project_x(cx, cy, cz) + mesh$py[idx] <- project_y(cx, cy, cz) + quad_depth[quad] <- mean(depth_toward_camera(cx, cy, cz)) + row <- row + 4 + quad <- quad + 1 + } +} + +# Farthest quad gets draw_rank 1 (painted first); nearest gets n_cells (painted +# last, on top). The fill itself must stay fully opaque for the occlusion to +# work - only the edge colour's alpha channel is faded with depth, as a subtle +# depth cue (bolder edges up close, softer far away). +draw_rank <- rank(quad_depth, ties.method = "first") +mesh$draw_rank <- draw_rank[mesh$quad_id] +fade <- 0.55 + 0.45 * (mesh$draw_rank - 1) / (n_cells - 1) +brand_rgb <- col2rgb(BRAND) / 255 +mesh$edge_color <- rgb(brand_rgb[1], brand_rgb[2], brand_rgb[3], alpha = fade) +mesh <- mesh[order(mesh$draw_rank, mesh$corner), ] + +# --- Floor reference plane (spatial grounding) --------------------------------- +floor_plane <- data.frame( + x = c(-6, 6, 6, -6), + y = c(-6, -6, 6, 6), + z = floor_z +) +floor_plane$px <- project_x(floor_plane$x, floor_plane$y, floor_plane$z) +floor_plane$py <- project_y(floor_plane$x, floor_plane$y, floor_plane$z) # --- Axis box: three edges meeting at the front-left-bottom corner ------------ axis_lines <- data.frame( @@ -98,10 +148,10 @@ axis_labels$py <- project_y(axis_labels$x, axis_labels$y, axis_labels$z) # --- Plot ----------------------------------------------------------------- p <- ggplot() + - geom_path(data = surface, aes(px, py, group = y), - color = BRAND, linewidth = 0.3, alpha = 0.35, lineend = "round") + - geom_path(data = surface, aes(px, py, group = x), - color = BRAND, linewidth = 0.3, alpha = 0.35, lineend = "round") + + geom_polygon(data = floor_plane, aes(px, py), + fill = NA, color = INK_SOFT, linewidth = 0.4, alpha = 0.4) + + geom_polygon(data = mesh, aes(px, py, group = draw_rank, colour = I(edge_color)), + fill = PAGE_BG, linewidth = 0.25) + geom_segment(data = axis_lines, aes(x = px, y = py, xend = pxend, yend = pyend), color = INK_SOFT, linewidth = 0.6) + geom_text(data = ticks, aes(px, py, label = label), From 4b3bfa56bb5f4352092117e398f089c34b4e9a3b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 10 Sep 2026 06:34:33 +0000 Subject: [PATCH 2/5] chore(ggplot2): add metadata for wireframe-3d-basic --- .../metadata/r/ggplot2.yaml | 257 +----------------- 1 file changed, 8 insertions(+), 249 deletions(-) diff --git a/plots/wireframe-3d-basic/metadata/r/ggplot2.yaml b/plots/wireframe-3d-basic/metadata/r/ggplot2.yaml index 78e3ebf59d3..11f9d6627bb 100644 --- a/plots/wireframe-3d-basic/metadata/r/ggplot2.yaml +++ b/plots/wireframe-3d-basic/metadata/r/ggplot2.yaml @@ -1,10 +1,13 @@ +# Per-library metadata for ggplot2 implementation of wireframe-3d-basic +# Auto-generated by impl-generate.yml + library: ggplot2 language: r specification_id: wireframe-3d-basic created: '2026-08-24T12:45:01Z' -updated: '2026-08-24T12:58:43Z' +updated: '2026-09-10T06:34:32Z' generated_by: claude-sonnet -workflow_run: 32727527087 +workflow_run: 34445087987 issue: 1015 language_version: 4.4.1 library_version: 3.5.1 @@ -12,251 +15,7 @@ preview_url_light: https://storage.googleapis.com/anyplot-images/plots/wireframe preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/wireframe-3d-basic/r/ggplot2/plot-dark.png preview_html_light: null preview_html_dark: null -quality_score: 89 +quality_score: null review: - strengths: - - Grid density and alpha reduced significantly (625->225 points, alpha 0.6->0.35) - per prior review feedback, producing a markedly cleaner wireframe read - - Z-axis and Y-axis tick label columns now clearly separated (horizontal offset - increased -7.6->-13), eliminating the ambiguous shared-column read flagged in - Review 1 - - Tick label font size bumped 2.8mm->3.3mm for better balance against the bold 3.6mm - axis titles - - Genuinely inventive hand-rolled orthographic camera projection (elevation 30deg - / azimuth 45deg) that works around ggplot2's lack of 3D grammar, matching the - spec's exact viewing angle request - - Clean KISS code, reproducible seed, only ggplot2 + ragg imported, theme-adaptive - chrome flips correctly between renders while the mesh color stays identical - - 'Full spec compliance: correct plot type, all required features present (grid - lines in both x and y directions, labeled X/Y/Z axes with tick marks), correct - mandated title format, no legend needed for a single series' - weaknesses: - - Interior of the mesh, especially near the two central ripple peaks, still shows - a moderately dense crosshatch of crossing lines (no depth-sorting/hidden-line - removal in the projection) - individual grid cells are hard to trace there even - though the overall dome/ripple silhouette reads clearly - - Grid resolution (15x15 = 225 points) is below the spec's recommended 20x20-50x50 - range; a defensible clarity trade-off given the no-occlusion projection technique, - but a distance-based alpha/color falloff would let resolution increase without - reintroducing clutter - - No back/top box edges or floor reference plane - leaves spatial grounding slightly - ambiguous (minor, carried over from Review 1, not a blocker) - image_description: |- - Light render (plot-light.png): - Background: Warm off-white matching #FAF8F1, not pure white. - Chrome: Title "wireframe-3d-basic · r · ggplot2 · anyplot.ai" centered at top in dark ink (#1A1A17), fully visible with no clipping. Bold "X"/"Y"/"Z" axis labels sit at the three box endpoints in the same dark ink. Muted grey-brown (#4A4A44) tick labels run along the two mirrored X/Y diagonals (-6, -3, 0, 3, 6) and up the vertical Z axis (-1, 0, 1); the Z-tick column is now clearly offset to the left, no longer sharing a screen column with the Y-tick labels. - Data: Single-series wireframe mesh entirely in brand green (#009E73), forming a dome/crown-shaped ripple surface with grid lines running in both x and y directions per spec. The overall topology (central peak, concentric dips and rises) reads clearly; the interior near the two central humps still shows a moderate crosshatch of crossing lines from the lack of hidden-line removal, though noticeably less cluttered than a denser 625-point mesh would be. - Legibility verdict: PASS - all text is readable against the light background, no light-on-light issues. - - Dark render (plot-dark.png): - Background: Warm near-black matching #1A1A17, not pure black. - Chrome: Same title, axis labels, and tick labels as the light render, now rendered in light ink (#F0EFE8) / soft grey (#B8B7B0) respectively - fully legible against the dark surface, no dark-on-dark failures anywhere. - Data: Mesh color is identical brand green (#009E73) to the light render - only chrome (background, ink) flipped, confirming correct theme-adaptive implementation. Same interior crosshatch density as the light render. - Legibility verdict: PASS - all text remains clearly readable, brand green reads well against the dark surface. - - Both renders pass the theme-readability check; data colors are identical between themes and only chrome flips as required. - criteria_checklist: - visual_quality: - score: 27 - max: 30 - items: - - id: VQ-01 - name: Text Legibility - score: 7 - max: 8 - passed: true - comment: Font sizes explicitly set (title 12pt, axis labels 3.6mm bold, tick - labels bumped 2.8mm->3.3mm); readable at full size in both themes - - id: VQ-02 - name: No Overlap - score: 6 - max: 6 - passed: true - comment: Z-tick column now clearly separated from the Y-tick column after - the offset increase; no text collisions - - id: VQ-03 - name: Element Visibility - score: 4 - max: 6 - passed: true - comment: Grid density and alpha halved from Review 1, improving legibility; - interior near the central ripple peaks still crosshatches due to no depth-sorting - in the projection - - id: VQ-04 - name: Color Accessibility - score: 2 - max: 2 - passed: true - comment: Single-hue brand green against theme-adaptive neutral chrome, no - red-green reliance - - id: VQ-05 - name: Layout & Canvas - score: 4 - max: 4 - passed: true - comment: Balanced margins, plot and axis box use a healthy share of the canvas, - nothing cut off - - id: VQ-06 - name: Axis Labels & Title - score: 2 - max: 2 - passed: true - comment: X/Y/Z bold labels plus numeric tick marks on all three axes; Z vs - Y tick ambiguity from Review 1 is fixed - - id: VQ-07 - name: Palette Compliance - score: 2 - max: 2 - passed: true - comment: 'First series is #009E73 in both renders; backgrounds and chrome - are theme-correct' - design_excellence: - score: 14 - max: 20 - items: - - id: DE-01 - name: Aesthetic Sophistication - score: 6 - max: 8 - passed: true - comment: Custom hand-rolled 3D camera projection is a genuinely sophisticated - solve; reduced mesh clutter lets the design read more clearly than Review - 1 - - id: DE-02 - name: Visual Refinement - score: 4 - max: 6 - passed: true - comment: theme_void chrome is clean and minimal; lower grid density/alpha - improved refinement over Review 1's crosshatch texture - - id: DE-03 - name: Data Storytelling - score: 4 - max: 6 - passed: true - comment: Ripple shape and central focal point read more clearly now that density - is reduced, though no explicit emphasis/annotation is added - spec_compliance: - score: 15 - max: 15 - items: - - id: SC-01 - name: Plot Type - score: 5 - max: 5 - passed: true - comment: Correct 3D wireframe plot type, projected via custom camera - - id: SC-02 - name: Required Features - score: 4 - max: 4 - passed: true - comment: Grid lines in both x/y directions, 3D perspective at elevation 30/azimuth - 45, all three axes labeled with tick marks - - id: SC-03 - name: Data Mapping - score: 3 - max: 3 - passed: true - comment: x/y/z correctly mapped through the projection; full data range visible - - id: SC-04 - name: Title & Legend - score: 3 - max: 3 - passed: true - comment: Title matches the mandated format exactly; no legend needed for single - series - data_quality: - score: 15 - max: 15 - items: - - id: DQ-01 - name: Feature Coverage - score: 6 - max: 6 - passed: true - comment: Ripple surface shows multiple peaks/dips across the domain; grid_n=15 - is below the spec's 20-50 recommendation but a deliberate, documented legibility - trade-off - - id: DQ-02 - name: Realistic Context - score: 5 - max: 5 - passed: true - comment: Neutral mathematical ripple function z = sin(sqrt(x^2+y^2)), matches - the spec's own example - - id: DQ-03 - name: Appropriate Scale - score: 4 - max: 4 - passed: true - comment: Domain and z-range are mathematically correct for the chosen function - code_quality: - score: 10 - max: 10 - items: - - id: CQ-01 - name: KISS Structure - score: 3 - max: 3 - passed: true - comment: 'Linear script: tokens -> camera math -> data -> plot -> save, no - functions/classes' - - id: CQ-02 - name: Reproducibility - score: 2 - max: 2 - passed: true - comment: set.seed(42) - - id: CQ-03 - name: Clean Imports - score: 2 - max: 2 - passed: true - comment: Only ggplot2 + ragg imported, both used - - id: CQ-04 - name: Code Elegance - score: 2 - max: 2 - passed: true - comment: Appropriate complexity for a hand-rolled 3D projection, no fake UI - or fabricated interactivity - - id: CQ-05 - name: Output & API - score: 1 - max: 1 - passed: true - comment: Saves plot-{THEME}.png via ragg::agg_png, current ggplot2 API (linewidth, - not size) - library_mastery: - score: 8 - max: 10 - items: - - id: LM-01 - name: Idiomatic Usage - score: 4 - max: 5 - passed: true - comment: Idiomatic geom_path/geom_segment/geom_text layering and theme_void - base - - id: LM-02 - name: Distinctive Features - score: 4 - max: 5 - passed: true - comment: Hand-rolled camera projection to work around ggplot2's lack of 3D - support is distinctive and hard to replicate trivially in another library - verdict: APPROVED -impl_tags: - dependencies: [] - techniques: - - 3d-projection - - manual-ticks - - layer-composition - patterns: - - data-generation - - matrix-construction - dataprep: [] - styling: - - alpha-blending - - minimal-chrome + strengths: [] + weaknesses: [] From e2a8d585adbc7efca967ff17b32f65a96ec8f7c2 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 10 Sep 2026 06:38:58 +0000 Subject: [PATCH 3/5] chore(ggplot2): update quality score 87 and review feedback for wireframe-3d-basic --- .../implementations/r/ggplot2.R | 2 +- .../metadata/r/ggplot2.yaml | 251 +++++++++++++++++- 2 files changed, 245 insertions(+), 8 deletions(-) diff --git a/plots/wireframe-3d-basic/implementations/r/ggplot2.R b/plots/wireframe-3d-basic/implementations/r/ggplot2.R index c6e969421b5..13b49ed9c6e 100644 --- a/plots/wireframe-3d-basic/implementations/r/ggplot2.R +++ b/plots/wireframe-3d-basic/implementations/r/ggplot2.R @@ -1,7 +1,7 @@ #' anyplot.ai #' wireframe-3d-basic: Basic 3D Wireframe Plot #' Library: ggplot2 3.5.1 | R 4.4.1 -#' Quality: 89/100 | Created: 2026-08-24 +#' Quality: 87/100 | Updated: 2026-09-10 library(ggplot2) library(ragg) diff --git a/plots/wireframe-3d-basic/metadata/r/ggplot2.yaml b/plots/wireframe-3d-basic/metadata/r/ggplot2.yaml index 11f9d6627bb..41989b12331 100644 --- a/plots/wireframe-3d-basic/metadata/r/ggplot2.yaml +++ b/plots/wireframe-3d-basic/metadata/r/ggplot2.yaml @@ -1,11 +1,8 @@ -# Per-library metadata for ggplot2 implementation of wireframe-3d-basic -# Auto-generated by impl-generate.yml - library: ggplot2 language: r specification_id: wireframe-3d-basic created: '2026-08-24T12:45:01Z' -updated: '2026-09-10T06:34:32Z' +updated: '2026-09-10T06:38:58Z' generated_by: claude-sonnet workflow_run: 34445087987 issue: 1015 @@ -15,7 +12,247 @@ preview_url_light: https://storage.googleapis.com/anyplot-images/plots/wireframe preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/wireframe-3d-basic/r/ggplot2/plot-dark.png preview_html_light: null preview_html_dark: null -quality_score: null +quality_score: 87 review: - strengths: [] - weaknesses: [] + strengths: + - 'Genuinely sophisticated 3D-in-2D engineering: manual perspective projection (elevation + 30°, azimuth 45°) combined with a painter''s-algorithm hidden-line removal (quads + sorted back-to-front, opaque fill occluding farther mesh lines) — a real technical + achievement given ggplot2 has no native 3D grammar.' + - Depth-based alpha fading on mesh edges (bolder near the camera, softer far away) + adds a convincing depth cue without introducing a second hue. + - Single-series brand green (#009E73) is used consistently and is pixel-identical + between light and dark renders; only chrome (axis lines, floor plane, tick/label + colors) flips correctly between themes. + - All three axes (X, Y, Z) are clearly labeled with tick marks, a floor reference + plane grounds the surface spatially, and the title matches the required '{spec-id} + · r · ggplot2 · anyplot.ai' format exactly. + - Data (ripple function z = sin(sqrt(x²+y²))) matches the spec's suggested example + precisely, with a sensible axis range and deterministic generation. + weaknesses: + - X-axis and Y-axis tick labels ('-6' and '-3', mirrored on both the left and right + sides) are positioned inside the wireframe's screen footprint and visually overlap + mesh strands crossing directly through the glyphs, confirmed by close crops in + both light and dark renders. Push the '-3'/'-6' tick anchors further outside the + mesh's projected footprint (matching the offset technique already used for the + '0'/'3'/'6' ticks and the Z-tick labels) so no tick text sits on top of mesh lines. + - Grid resolution (20x20) sits at the very bottom of the spec's recommended 20x20-50x50 + range; a modest bump (e.g. 28-32) would add surface fidelity without hurting legibility + now that hidden-line removal keeps the mesh readable. + image_description: |- + Light render (plot-light.png): + Background: Warm off-white, matches #FAF8F1, not pure white. + Chrome: Title "wireframe-3d-basic · r · ggplot2 · anyplot.ai" centered at top in dark ink, clearly readable. Axis lines (front-left-bottom corner box) in medium-dark gray. "X", "Y", "Z" axis labels in bold dark ink at the far ends of each axis line. Tick labels (-6, -3, 0, 3, 6 for X and Y; -1, 0, 1 for Z) in a softer gray. + Data: A single ripple surface z = sin(sqrt(x^2+y^2)) rendered as a green (#009E73) wireframe mesh of diamond-shaped quads, with nearer quads occluding farther mesh lines (hidden-line removal) and edge opacity fading with depth. A faint floor plane outline grounds the surface. First (only) series is the brand green. + Legibility verdict: PASS overall, with one caveat — the X/Y tick labels "-6" and "-3" (appearing mirrored on both the left and right sides of the Z axis) sit directly on top of the wireframe mesh, with thin green mesh lines crossing through the glyphs. The numbers remain decipherable (dark-gray text has enough contrast against both the pale background and the thin green lines) but the overlap is a real, confirmed layout flaw, not just proximity. + + Dark render (plot-dark.png): + Background: Warm near-black, matches #1A1A17, not pure black. + Chrome: Title in light ink, clearly readable. Axis lines in light gray, "X"/"Y"/"Z" labels in bold near-white, tick labels in a softer light gray. No dark-on-dark failures observed — all chrome text has strong contrast against the near-black background. + Data: Identical green (#009E73) wireframe mesh, same shape, same depth-fade behavior as the light render — confirms data colors are unchanged between themes; only the chrome (background, axis lines, text colors) flipped. + Legibility verdict: PASS overall, with the same caveat as the light render — "-6" and "-3" tick labels overlap the mesh lines (confirmed via cropped close-up), though the light-gray text against the dark green lines remains legible. + criteria_checklist: + visual_quality: + score: 24 + max: 30 + items: + - id: VQ-01 + name: Text Legibility + score: 7 + max: 8 + passed: true + comment: All text sized explicitly and readable in both themes; slightly reduced + clarity where '-6'/'-3' tick glyphs are crossed by mesh lines. + - id: VQ-02 + name: No Overlap + score: 3 + max: 6 + passed: false + comment: 'Confirmed overlap: X/Y tick labels ''-6'' and ''-3'' sit inside + the mesh''s projected footprint with mesh strands crossing through the text + in both renders.' + - id: VQ-03 + name: Element Visibility + score: 5 + max: 6 + passed: true + comment: Mesh line weight and density appropriate for a 20x20 grid; hidden-line + removal keeps the structure readable. + - id: VQ-04 + name: Color Accessibility + score: 2 + max: 2 + passed: true + comment: Single-hue data color, grayscale chrome, no red-green reliance, CVD-safe. + - id: VQ-05 + name: Layout & Canvas + score: 3 + max: 4 + passed: true + comment: Good margins, nothing clipped, title well within bounds; minor deduction + for tick labels floating mid-air inside the plot rather than clearly outside + it. + - id: VQ-06 + name: Axis Labels & Title + score: 2 + max: 2 + passed: true + comment: X/Y/Z clearly labeled with tick marks; title matches required format + exactly. + - id: VQ-07 + name: Palette Compliance + score: 2 + max: 2 + passed: true + comment: 'First (only) series is #009E73; backgrounds match #FAF8F1/#1A1A17; + chrome flips correctly, data color identical between themes.' + design_excellence: + score: 17 + max: 20 + items: + - id: DE-01 + name: Aesthetic Sophistication + score: 7 + max: 8 + passed: true + comment: Custom perspective projection with painter's-algorithm hidden-line + removal and depth-based alpha fading — well above generic defaults. + - id: DE-02 + name: Visual Refinement + score: 5 + max: 6 + passed: true + comment: theme_void chrome, subtle floor plane, generous whitespace; tick + placement keeps it from full marks. + - id: DE-03 + name: Data Storytelling + score: 5 + max: 6 + passed: true + comment: z-exaggeration (z_lift) makes the shallow ripple read clearly; hidden-line + removal creates a strong sense of solid form. + spec_compliance: + score: 15 + max: 15 + items: + - id: SC-01 + name: Plot Type + score: 5 + max: 5 + passed: true + comment: Correctly renders as a 3D wireframe mesh, matching the spec's see-through-mesh + definition. + - id: SC-02 + name: Required Features + score: 4 + max: 4 + passed: true + comment: Grid lines in both directions, consistent line color, elev 30/azim + 45 perspective, labeled axes with ticks — all present. + - id: SC-03 + name: Data Mapping + score: 3 + max: 3 + passed: true + comment: X/Y/Z correctly mapped; full data range shown. + - id: SC-04 + name: Title & Legend + score: 3 + max: 3 + passed: true + comment: Title format exact; no legend needed for single series. + data_quality: + score: 14 + max: 15 + items: + - id: DQ-01 + name: Feature Coverage + score: 5 + max: 6 + passed: true + comment: Shows the full wireframe mesh concept well; grid_n=20 is at the low + end of the spec's recommended 20-50 range. + - id: DQ-02 + name: Realistic Context + score: 5 + max: 5 + passed: true + comment: Classic, neutral ripple function example matching the spec's own + suggestion. + - id: DQ-03 + name: Appropriate Scale + score: 4 + max: 4 + passed: true + comment: Sensible domain (-6 to 6) and resulting z range for a ripple demo. + code_quality: + score: 9 + max: 10 + items: + - id: CQ-01 + name: KISS Structure + score: 2 + max: 3 + passed: true + comment: A few small helper functions for the projection math, but justified + — no classes, flat script otherwise. + - id: CQ-02 + name: Reproducibility + score: 2 + max: 2 + passed: true + comment: set.seed(42) present; surface itself is deterministic. + - id: CQ-03 + name: Clean Imports + score: 2 + max: 2 + passed: true + comment: Only ggplot2 and ragg, both used. + - id: CQ-04 + name: Code Elegance + score: 2 + max: 2 + passed: true + comment: Complexity is appropriate to the hard problem of faking 3D in a grammar-of-graphics + library; no fake UI. + - id: CQ-05 + name: Output & API + score: 1 + max: 1 + passed: true + comment: Saves plot-{THEME}.png via ragg::agg_png as required. + library_mastery: + score: 8 + max: 10 + items: + - id: LM-01 + name: Idiomatic Usage + score: 4 + max: 5 + passed: true + comment: Composes geom_polygon/geom_segment/geom_text and theme_void idiomatically + to build a scene ggplot2 has no native primitive for. + - id: LM-02 + name: Distinctive Features + score: 4 + max: 5 + passed: true + comment: Full painter's-algorithm hidden-line removal implemented purely in + ggplot2 grammar — a distinctive, library-specific workaround well beyond + generic usage. + verdict: APPROVED +impl_tags: + dependencies: [] + techniques: + - 3d-projection + - manual-ticks + - layer-composition + patterns: + - data-generation + - matrix-construction + - iteration-over-groups + dataprep: [] + styling: + - minimal-chrome + - alpha-blending + - publication-ready From 9521b587602c25665c970e65f034d2b5739a358b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 10 Sep 2026 06:47:05 +0000 Subject: [PATCH 4/5] fix(ggplot2): address review feedback for wireframe-3d-basic Attempt 1/4 - fixes based on AI review --- .../implementations/r/ggplot2.R | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/plots/wireframe-3d-basic/implementations/r/ggplot2.R b/plots/wireframe-3d-basic/implementations/r/ggplot2.R index 13b49ed9c6e..a5c945ae534 100644 --- a/plots/wireframe-3d-basic/implementations/r/ggplot2.R +++ b/plots/wireframe-3d-basic/implementations/r/ggplot2.R @@ -42,7 +42,7 @@ project_y <- function(x, y, z) x * up_axis[1] + y * up_axis[2] + z * z_lif depth_toward_camera <- function(x, y, z) x * view_dir[1] + y * view_dir[2] + z * z_lift * view_dir[3] # --- Data: ripple surface z = sin(sqrt(x^2 + y^2)) ----------------------------- -grid_n <- 20 +grid_n <- 30 x_vals <- seq(-6, 6, length.out = grid_n) y_vals <- seq(-6, 6, length.out = grid_n) z_fun <- function(x, y) sin(sqrt(x^2 + y^2)) @@ -124,12 +124,21 @@ y_breaks <- c(-6, -3, 0, 3, 6) z_breaks <- c(-1, 0, 1) ticks <- rbind( - data.frame(x = x_breaks, y = -9.6, z = floor_z, label = x_breaks), - data.frame(x = -9.6, y = y_breaks, z = floor_z, label = y_breaks) + data.frame(x = x_breaks, y = -9.6, z = floor_z, label = x_breaks, axis = "x"), + data.frame(x = -9.6, y = y_breaks, z = floor_z, label = y_breaks, axis = "y") ) ticks$px <- project_x(ticks$x, ticks$y, ticks$z) ticks$py <- project_y(ticks$x, ticks$y, ticks$z) +# The X-tick and Y-tick label columns sit on the mesh's near side, where the +# wireframe's screen footprint is widest, so a couple of low-value ticks +# ("-3"/"-6") land inside the mesh's silhouette instead of clearing it. Nudge +# each column sideways, away from the vertical Z axis, by a fixed screen +# offset (same lateral-offset trick used for z_ticks below) - harmless for +# the ticks that already clear the mesh, since it just adds margin. +tick_clearance <- 5.5 +ticks$px <- ticks$px + ifelse(ticks$axis == "x", tick_clearance, -tick_clearance) + # Z ticks sit on the vertical axis line itself; nudge the label text # (not the axis line) sideways into the open gap left of the mesh, well past # the Y-axis tick column so the two label groups don't merge into one line. From 179bea05eadcbdab301cb808acaf8ca146bf0a64 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 10 Sep 2026 06:51:25 +0000 Subject: [PATCH 5/5] chore(ggplot2): update quality score 87 and review feedback for wireframe-3d-basic --- .../metadata/r/ggplot2.yaml | 156 +++++++++--------- 1 file changed, 77 insertions(+), 79 deletions(-) diff --git a/plots/wireframe-3d-basic/metadata/r/ggplot2.yaml b/plots/wireframe-3d-basic/metadata/r/ggplot2.yaml index 41989b12331..226fa5ad44b 100644 --- a/plots/wireframe-3d-basic/metadata/r/ggplot2.yaml +++ b/plots/wireframe-3d-basic/metadata/r/ggplot2.yaml @@ -2,7 +2,7 @@ library: ggplot2 language: r specification_id: wireframe-3d-basic created: '2026-08-24T12:45:01Z' -updated: '2026-09-10T06:38:58Z' +updated: '2026-09-10T06:51:25Z' generated_by: claude-sonnet workflow_run: 34445087987 issue: 1015 @@ -16,44 +16,51 @@ quality_score: 87 review: strengths: - 'Genuinely sophisticated 3D-in-2D engineering: manual perspective projection (elevation - 30°, azimuth 45°) combined with a painter''s-algorithm hidden-line removal (quads - sorted back-to-front, opaque fill occluding farther mesh lines) — a real technical - achievement given ggplot2 has no native 3D grammar.' - - Depth-based alpha fading on mesh edges (bolder near the camera, softer far away) - adds a convincing depth cue without introducing a second hue. - - Single-series brand green (#009E73) is used consistently and is pixel-identical - between light and dark renders; only chrome (axis lines, floor plane, tick/label - colors) flips correctly between themes. - - All three axes (X, Y, Z) are clearly labeled with tick marks, a floor reference - plane grounds the surface spatially, and the title matches the required '{spec-id} - · r · ggplot2 · anyplot.ai' format exactly. - - Data (ripple function z = sin(sqrt(x²+y²))) matches the spec's suggested example - precisely, with a sensible axis range and deterministic generation. + 30°, azimuth 45°) combined with painter''s-algorithm hidden-line removal implemented + purely in ggplot2 grammar (geom_polygon + geom_segment + geom_text).' + - Grid resolution raised from 20x20 to 30x30 this attempt, now solidly mid-range + within the spec's recommended 20x20-50x50 window, with no legibility cost thanks + to the opaque-fill occlusion trick. + - Depth-based alpha fading on mesh edges adds a convincing depth cue without introducing + a second hue. + - Single-series brand green (#009E73) is pixel-identical between light and dark + renders; only chrome (background, axis lines, tick/axis labels) flips between + themes, with no dark-on-dark or light-on-light failures. + - All three axes clearly labeled (bold X/Y/Z) with tick marks; title matches the + required '{spec-id} · {language} · {library} · anyplot.ai' format exactly. + - Data (ripple function z = sin(sqrt(x²+y²))) matches the spec's own suggested example + with a sensible axis range and floor plane for spatial grounding. weaknesses: - - X-axis and Y-axis tick labels ('-6' and '-3', mirrored on both the left and right - sides) are positioned inside the wireframe's screen footprint and visually overlap - mesh strands crossing directly through the glyphs, confirmed by close crops in - both light and dark renders. Push the '-3'/'-6' tick anchors further outside the - mesh's projected footprint (matching the offset technique already used for the - '0'/'3'/'6' ticks and the Z-tick labels) so no tick text sits on top of mesh lines. - - Grid resolution (20x20) sits at the very bottom of the spec's recommended 20x20-50x50 - range; a modest bump (e.g. 28-32) would add surface fidelity without hurting legibility - now that hidden-line removal keeps the mesh readable. + - 'The X/Y tick-label overlap flagged in Attempt 1 is still present after repair, + confirmed by pixel-cropped close-up on both renders: the ''-6'' and ''-3'' labels + (mirrored on both sides of the Z axis) still have wireframe mesh strands crossing + directly through the glyphs. The applied fix (tick_clearance <- 5.5 px lateral + offset) was too small to clear the mesh''s silhouette, and bumping grid_n from + 20 to 30 in the same commit made the local mesh denser, so roughly the same number + of strands now cross the labels as before. Increase tick_clearance substantially + (try 15-20 instead of 5.5) and re-check against the denser 30x30 mesh specifically + at the ''-6''/''-3'' positions, since those are the values whose screen-projected + position lands deepest inside the mesh''s near-side footprint.' + - The '-6'/'-3' tick labels still read as floating mid-plot rather than clearly + outside the mesh silhouette, which softens the layout/canvas cleanliness slightly + (minor, secondary to the overlap itself). image_description: |- Light render (plot-light.png): - Background: Warm off-white, matches #FAF8F1, not pure white. - Chrome: Title "wireframe-3d-basic · r · ggplot2 · anyplot.ai" centered at top in dark ink, clearly readable. Axis lines (front-left-bottom corner box) in medium-dark gray. "X", "Y", "Z" axis labels in bold dark ink at the far ends of each axis line. Tick labels (-6, -3, 0, 3, 6 for X and Y; -1, 0, 1 for Z) in a softer gray. - Data: A single ripple surface z = sin(sqrt(x^2+y^2)) rendered as a green (#009E73) wireframe mesh of diamond-shaped quads, with nearer quads occluding farther mesh lines (hidden-line removal) and edge opacity fading with depth. A faint floor plane outline grounds the surface. First (only) series is the brand green. - Legibility verdict: PASS overall, with one caveat — the X/Y tick labels "-6" and "-3" (appearing mirrored on both the left and right sides of the Z axis) sit directly on top of the wireframe mesh, with thin green mesh lines crossing through the glyphs. The numbers remain decipherable (dark-gray text has enough contrast against both the pale background and the thin green lines) but the overlap is a real, confirmed layout flaw, not just proximity. + Background: Warm off-white, consistent with #FAF8F1 — not pure white, not dark. + Chrome: Title "wireframe-3d-basic · r · ggplot2 · anyplot.ai" centered at top in dark ink, clearly readable. Bold "X"/"Y"/"Z" axis labels and axis-box edges in dark ink/gray, all clearly legible. Floor-plane diamond outline faint but visible. Z-axis tick labels ("1", "0", "-1") sit cleanly clear of the mesh with no overlap (verified via crop). X/Y-axis tick labels ("-6", "-3", "0", "3", "6", mirrored on both sides of the Z axis) are readable, but the "-6" and "-3" instances have thin green mesh strands crossing directly through the glyphs (verified via cropped close-up) — text remains decipherable but the overlap is real. + Data: Single ripple surface z = sin(sqrt(x²+y²)) rendered as a green (#009E73) wireframe mesh of diamond-shaped quads with painter's-algorithm hidden-line removal (nearer quads occlude farther mesh lines via opaque page-background fill) and depth-based edge-opacity fading (bolder near camera, softer far away). This is the sole data color, correctly matching the Imprint first-series green. + Legibility verdict: PASS overall, with a caveat — the "-6"/"-3" tick label / mesh-line overlap (VQ-02) persists from Attempt 1 despite a repair attempt. Dark render (plot-dark.png): - Background: Warm near-black, matches #1A1A17, not pure black. - Chrome: Title in light ink, clearly readable. Axis lines in light gray, "X"/"Y"/"Z" labels in bold near-white, tick labels in a softer light gray. No dark-on-dark failures observed — all chrome text has strong contrast against the near-black background. - Data: Identical green (#009E73) wireframe mesh, same shape, same depth-fade behavior as the light render — confirms data colors are unchanged between themes; only the chrome (background, axis lines, text colors) flipped. - Legibility verdict: PASS overall, with the same caveat as the light render — "-6" and "-3" tick labels overlap the mesh lines (confirmed via cropped close-up), though the light-gray text against the dark green lines remains legible. + Background: Warm near-black, consistent with #1A1A17 — not pure black, not light. + Chrome: Same title, same layout. Axis-box lines, "X"/"Y"/"Z" labels, and all tick labels correctly flip to light gray/near-white with strong contrast against the dark background — no dark-on-dark failures detected anywhere. + Data: Wireframe mesh color is pixel-identical green (#009E73) to the light render — confirmed only chrome flipped, data color did not shift. + Legibility verdict: PASS overall, with the same "-6"/"-3" tick-label / mesh-line overlap caveat as the light render (confirmed via cropped close-up) — legibility itself still holds, but the overlap is unresolved. + + Both renders viewed and analyzed above; a targeted pixel crop of the tick-label region was taken on both PNGs to confirm the overlap status precisely (screenshot evidence, not just visual estimate). criteria_checklist: visual_quality: - score: 24 + score: 23 max: 30 items: - id: VQ-01 @@ -61,51 +68,48 @@ review: score: 7 max: 8 passed: true - comment: All text sized explicitly and readable in both themes; slightly reduced - clarity where '-6'/'-3' tick glyphs are crossed by mesh lines. + comment: All text readable in both themes; mesh lines cross through '-6'/'-3' + glyphs but do not obscure legibility - id: VQ-02 name: No Overlap - score: 3 + score: 2 max: 6 passed: false - comment: 'Confirmed overlap: X/Y tick labels ''-6'' and ''-3'' sit inside - the mesh''s projected footprint with mesh strands crossing through the text - in both renders.' + comment: X/Y tick labels ('-6'/'-3') still overlap mesh strands in both renders + — same issue flagged in Attempt 1; the applied tick_clearance=5.5 fix plus + the grid_n 20->30 density bump did not clear it - id: VQ-03 name: Element Visibility score: 5 max: 6 passed: true - comment: Mesh line weight and density appropriate for a 20x20 grid; hidden-line - removal keeps the structure readable. + comment: Mesh density/line weight appropriate for the denser 30x30 grid - id: VQ-04 name: Color Accessibility score: 2 max: 2 passed: true - comment: Single-hue data color, grayscale chrome, no red-green reliance, CVD-safe. + comment: Single hue, CVD-safe - id: VQ-05 name: Layout & Canvas score: 3 max: 4 passed: true - comment: Good margins, nothing clipped, title well within bounds; minor deduction - for tick labels floating mid-air inside the plot rather than clearly outside - it. + comment: No clipping, good margins; '-6'/'-3' tick labels float mid-plot rather + than clearly outside the mesh silhouette - id: VQ-06 name: Axis Labels & Title score: 2 max: 2 passed: true - comment: X/Y/Z clearly labeled with tick marks; title matches required format - exactly. + comment: X/Y/Z labeled, title format exact - id: VQ-07 name: Palette Compliance score: 2 max: 2 passed: true - comment: 'First (only) series is #009E73; backgrounds match #FAF8F1/#1A1A17; - chrome flips correctly, data color identical between themes.' + comment: Brand green sole data color, correct backgrounds, correct chrome + flip design_excellence: score: 17 max: 20 @@ -115,22 +119,21 @@ review: score: 7 max: 8 passed: true - comment: Custom perspective projection with painter's-algorithm hidden-line - removal and depth-based alpha fading — well above generic defaults. + comment: Custom perspective projection + painter's-algorithm hidden-line removal + + depth-fade - id: DE-02 name: Visual Refinement score: 5 max: 6 passed: true - comment: theme_void chrome, subtle floor plane, generous whitespace; tick - placement keeps it from full marks. + comment: theme_void chrome, subtle floor plane, generous whitespace - id: DE-03 name: Data Storytelling score: 5 max: 6 passed: true - comment: z-exaggeration (z_lift) makes the shallow ripple read clearly; hidden-line - removal creates a strong sense of solid form. + comment: Z-exaggeration and hidden-line removal create a clear, solid-looking + focal form spec_compliance: score: 15 max: 15 @@ -140,51 +143,49 @@ review: score: 5 max: 5 passed: true - comment: Correctly renders as a 3D wireframe mesh, matching the spec's see-through-mesh - definition. + comment: Correct 3D wireframe - id: SC-02 name: Required Features score: 4 max: 4 passed: true - comment: Grid lines in both directions, consistent line color, elev 30/azim - 45 perspective, labeled axes with ticks — all present. + comment: Grid lines both directions, consistent line color, elev 30/azim 45, + labeled axes with ticks - id: SC-03 name: Data Mapping score: 3 max: 3 passed: true - comment: X/Y/Z correctly mapped; full data range shown. + comment: X/Y/Z correctly mapped and projected - id: SC-04 name: Title & Legend score: 3 max: 3 passed: true - comment: Title format exact; no legend needed for single series. + comment: Title matches required format exactly; no legend needed (single series) data_quality: - score: 14 + score: 15 max: 15 items: - id: DQ-01 name: Feature Coverage - score: 5 + score: 6 max: 6 passed: true - comment: Shows the full wireframe mesh concept well; grid_n=20 is at the low - end of the spec's recommended 20-50 range. + comment: grid_n now 30, solidly mid the spec's 20-50 recommended range (up + from 20, the previous review's ding) - id: DQ-02 name: Realistic Context score: 5 max: 5 passed: true - comment: Classic, neutral ripple function example matching the spec's own - suggestion. + comment: Matches the spec's own suggested ripple example - id: DQ-03 name: Appropriate Scale score: 4 max: 4 passed: true - comment: Sensible domain (-6 to 6) and resulting z range for a ripple demo. + comment: Sensible axis ranges and z-exaggeration for legibility code_quality: score: 9 max: 10 @@ -194,33 +195,32 @@ review: score: 2 max: 3 passed: true - comment: A few small helper functions for the projection math, but justified - — no classes, flat script otherwise. + comment: Small projection helper functions, justified by the manual 3D-projection + workaround ggplot2 requires - id: CQ-02 name: Reproducibility score: 2 max: 2 passed: true - comment: set.seed(42) present; surface itself is deterministic. + comment: set.seed(42) present (data itself is deterministic) - id: CQ-03 name: Clean Imports score: 2 max: 2 passed: true - comment: Only ggplot2 and ragg, both used. + comment: Only ggplot2 + ragg imported, both used - id: CQ-04 name: Code Elegance score: 2 max: 2 passed: true - comment: Complexity is appropriate to the hard problem of faking 3D in a grammar-of-graphics - library; no fake UI. + comment: No fake UI/interactivity; appropriate complexity for the technique - id: CQ-05 name: Output & API score: 1 max: 1 passed: true - comment: Saves plot-{THEME}.png via ragg::agg_png as required. + comment: Saves plot-{THEME}.png via ragg::agg_png at the correct canvas size library_mastery: score: 8 max: 10 @@ -230,16 +230,15 @@ review: score: 4 max: 5 passed: true - comment: Composes geom_polygon/geom_segment/geom_text and theme_void idiomatically - to build a scene ggplot2 has no native primitive for. + comment: Composes geom_polygon/geom_segment/geom_text + theme_void idiomatically + for a scene ggplot2 has no native primitive for - id: LM-02 name: Distinctive Features score: 4 max: 5 passed: true comment: Full painter's-algorithm hidden-line removal implemented purely in - ggplot2 grammar — a distinctive, library-specific workaround well beyond - generic usage. + ggplot2 grammar verdict: APPROVED impl_tags: dependencies: [] @@ -255,4 +254,3 @@ impl_tags: styling: - minimal-chrome - alpha-blending - - publication-ready