Skip to content

Commit f6d38b9

Browse files
committed
Add scatterplot tests
1 parent adc1347 commit f6d38b9

3 files changed

Lines changed: 35 additions & 12 deletions

File tree

spec/reference_spec.cr

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -463,6 +463,13 @@ describe "Julia reference output compatibility" do
463463
test_ref("scatterplot/scale2.txt", p)
464464
end
465465

466+
it "matches scatterplot/scale3" do
467+
miny = -1.2796649117521434e218
468+
maxy = -miny
469+
p = UnicodePlot.scatterplot([1.0], [miny], xlim: {1.0, 1.0}, ylim: {miny, maxy})
470+
test_ref("scatterplot/scale3.txt", p)
471+
end
472+
466473
it "matches scatterplot/limits" do
467474
p = UnicodePlot.scatterplot(x, y, xlim: {-1.5, 3.5}, ylim: {-5.5, 2.5})
468475
test_ref("scatterplot/limits.txt", p)
@@ -507,6 +514,16 @@ describe "Julia reference output compatibility" do
507514
p = UnicodePlot.scatterplot(x, y, title: "Scatter", canvas: :dot, height: 5, width: 10)
508515
test_ref("scatterplot/canvassize.txt", p)
509516
end
517+
518+
it "matches scatterplot/units_temp" do
519+
p = UnicodePlot.scatterplot(
520+
[22.0, 23.0, 24.0],
521+
marker: :circle,
522+
ylabel: "°C",
523+
)
524+
UnicodePlot.scatterplot!(p, [23.5, 22.5, 23.0], marker: :cross, color: :red)
525+
test_ref("scatterplot/units_temp.txt", p)
526+
end
510527
end
511528

512529
describe "barplot" do

src/unicode_plot/canvas.cr

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,17 @@ module UnicodePlot
131131
floored.to_i32
132132
end
133133

134+
# Convert pixel coordinates to 1-based char-cell coordinates.
135+
# Boundary pixels are nudged one step inward to match Julia's canvas mapping.
136+
private def pixel_to_char_point(pixel_x : Float64, pixel_y : Float64) : Tuple(Int32, Int32)?
137+
px = pixel_x >= @pixel_width ? pixel_x - 1.0 : pixel_x
138+
py = pixel_y >= @pixel_height ? pixel_y - 1.0 : pixel_y
139+
cx = floor_to_i32(px / x_pixel_per_char.to_f)
140+
cy = floor_to_i32(py / y_pixel_per_char.to_f)
141+
return unless cx && cy
142+
{cx + 1, cy + 1}
143+
end
144+
134145
private def plot_pixel_if_visible(
135146
pixel_x : Float64,
136147
pixel_y : Float64,
@@ -238,12 +249,9 @@ module UnicodePlot
238249
# Annotate a character at canvas coords (x, y)
239250
def annotate!(x : Float64, y : Float64, char : Char, color : UInt32, blend : Bool) : self
240251
return self unless valid_x?(x) && valid_y?(y)
241-
cx = floor_to_i32(scale_x_to_pixel(x) / x_pixel_per_char.to_f)
242-
cy = floor_to_i32(scale_y_to_pixel(y) / y_pixel_per_char.to_f)
243-
return self unless cx && cy
244-
245-
cx += 1
246-
cy += 1
252+
point = pixel_to_char_point(scale_x_to_pixel(x), scale_y_to_pixel(y))
253+
return self unless point
254+
cx, cy = point
247255
char_point!(cx, cy, char, color, blend)
248256
self
249257
end
@@ -253,12 +261,9 @@ module UnicodePlot
253261
return self unless valid_x?(x) && valid_y?(y)
254262
px = scale_x_to_pixel(x)
255263
py = scale_y_to_pixel(y)
256-
cx = floor_to_i32(px / x_pixel_per_char.to_f)
257-
cy = floor_to_i32(py / y_pixel_per_char.to_f)
258-
return self unless cx && cy
259-
260-
cx += 1
261-
cy += 1
264+
point = pixel_to_char_point(px, py)
265+
return self unless point
266+
cx, cy = point
262267
n = text.size
263268
cx = case halign
264269
when :center, :hcenter then cx - n // 2

src/unicode_plot/common.cr

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ module UnicodePlot
232232
parts = str.split('e')
233233
left = parts[0]
234234
right = parts[1]
235+
right = right.starts_with?("+") ? right[1..] : right
235236
right = superscript(right) if unicode_exponent
236237
"#{left}e#{right}"
237238
else

0 commit comments

Comments
 (0)