Skip to content

Commit c7c870b

Browse files
pjt222claude
andcommitted
fix(snic): make image follow pieces when offset > 0
Store per-piece offset_dx/offset_dy during tessellation positioning and accumulate through repel translations, then use these offsets to position the image element inside each piece's clipPath group. Also use original (pre-expansion) canvas size for image dimensions so the image covers only the puzzle area, not the expanded offset canvas. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 53c10af commit c7c870b

3 files changed

Lines changed: 23 additions & 8 deletions

File tree

R/image_fill_rendering.R

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -88,14 +88,16 @@ render_image_filled_pieces <- function(pieces, image_data_uri, canvas_size,
8888
canvas_offset = c(0, 0),
8989
stroke_width = 1.5, colors = "black",
9090
opacity = 1.0,
91-
image_width = NULL, image_height = NULL) {
91+
image_width = NULL, image_height = NULL,
92+
original_canvas_size = NULL) {
9293
if (length(colors) == 1) {
9394
colors <- rep(colors, length(pieces))
9495
}
9596

96-
# Image dimensions in canvas mm units — canvas_size is always c(width, height)
97-
img_w <- canvas_size[1] # width
98-
img_h <- canvas_size[2] # height
97+
# Use original (pre-offset-expansion) canvas for image dimensions
98+
orig <- original_canvas_size %||% canvas_size
99+
img_w <- orig[1] # width
100+
img_h <- orig[2] # height
99101

100102
sapply(seq_along(pieces), function(i) {
101103
piece <- pieces[[i]]
@@ -104,19 +106,23 @@ render_image_filled_pieces <- function(pieces, image_data_uri, canvas_size,
104106

105107
opacity_attr <- if (opacity < 1.0) sprintf(' opacity="%.2f"', opacity) else ""
106108

109+
# Per-piece image offset (tracks radial/repel translation)
110+
img_x <- piece$offset_dx %||% 0
111+
img_y <- piece$offset_dy %||% 0
112+
107113
# Clipped image group + stroke outline
108114
sprintf(paste0(
109115
'<g%s>\n',
110116
' <clipPath id="piece-%d-clip"><path d="%s" /></clipPath>\n',
111117
' <g clip-path="url(#piece-%d-clip)">\n',
112-
' <image href="%s" x="0" y="0" width="%.1f" height="%.1f" preserveAspectRatio="none" />\n',
118+
' <image href="%s" x="%.4f" y="%.4f" width="%.1f" height="%.1f" preserveAspectRatio="none" />\n',
113119
' </g>\n',
114120
' <path d="%s" fill="none" stroke="%s" stroke-width="%.1f" />\n',
115121
'</g>'),
116122
opacity_attr,
117123
piece_id, piece$path,
118124
piece_id,
119-
image_data_uri, img_w, img_h,
125+
image_data_uri, img_x, img_y, img_w, img_h,
120126
piece$path, color, stroke_width
121127
)
122128
})

R/piece_positioning.R

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,9 @@ apply_tessellation_positioning <- function(piece_result, offset) {
397397
is_boundary = piece$is_boundary,
398398
fusion_group = piece$fusion_group,
399399
fused_edges = piece$fused_edges,
400-
fused_neighbor_ids = piece$fused_neighbor_ids
400+
fused_neighbor_ids = piece$fused_neighbor_ids,
401+
offset_dx = dx,
402+
offset_dy = dy
401403
)
402404

403405
# Copy the type-specific position data
@@ -958,6 +960,10 @@ translate_piece <- function(piece, dx, dy) {
958960
}
959961
}
960962

963+
# Accumulate offset tracking for image fill positioning
964+
piece$offset_dx <- (piece$offset_dx %||% 0) + dx
965+
piece$offset_dy <- (piece$offset_dy %||% 0) + dy
966+
961967
piece
962968
}
963969

R/renderer_main.R

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,12 +192,15 @@ render_puzzle_svg <- function(positioned, fill = "none", fills = NULL,
192192
# Get image dimensions from parameters
193193
img_w <- positioned$parameters$image_width
194194
img_h <- positioned$parameters$image_height
195+
# Original canvas size before offset expansion — size is c(height, width)
196+
original_canvas_size <- c(positioned$parameters$size[2], positioned$parameters$size[1])
195197
piece_elements <- render_image_filled_pieces(
196198
positioned$pieces, image_data_uri, positioned$canvas_size,
197199
canvas_offset = if (!is.null(positioned$canvas_offset)) positioned$canvas_offset else c(0, 0),
198200
stroke_width = stroke_width, colors = colors,
199201
opacity = opacity,
200-
image_width = img_w, image_height = img_h
202+
image_width = img_w, image_height = img_h,
203+
original_canvas_size = original_canvas_size
201204
)
202205
}
203206

0 commit comments

Comments
 (0)