Skip to content

Commit 73f6bff

Browse files
authored
Clipping in geom_abline() (#6109)
* clip `geom_abline()` in y-direction * add test * accept visual changes * add news bullet
1 parent 4af509e commit 73f6bff

File tree

6 files changed

+32
-7
lines changed

6 files changed

+32
-7
lines changed

NEWS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,8 @@
223223
the new default in many scales (@teunbrand, #4696).
224224
* `guide_axis()` no longer reserves space for blank ticks
225225
(@teunbrand, #4722, #6069).
226+
* `geom_abline()` clips to the panel range in the vertical direction too
227+
(@teunbrand, #6086).
226228

227229
# ggplot2 3.5.1
228230

R/geom-abline.R

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -132,12 +132,16 @@ GeomAbline <- ggproto("GeomAbline", Geom,
132132
# Ensure the line extends well outside the panel to avoid visible line
133133
# ending for thick lines
134134
ranges$x <- ranges$x + c(-1, 1) * diff(ranges$x)
135+
ranges$y <- ranges$y + c(-1, 1) * diff(ranges$y)
135136
}
136137

137-
data$x <- ranges$x[1]
138-
data$xend <- ranges$x[2]
139-
data$y <- ranges$x[1] * data$slope + data$intercept
140-
data$yend <- ranges$x[2] * data$slope + data$intercept
138+
# Restrict 'x' to where 'y' is in range: x = (y - intercept) / slope
139+
x <- sweep(outer(ranges$y, data$intercept, FUN = "-"), 2, data$slope, FUN = "/")
140+
141+
data$x <- pmax(ranges$x[1], pmin(x[1, ], x[2, ]))
142+
data$xend <- pmin(ranges$x[2], pmax(x[1, ], x[2, ]))
143+
data$y <- data$x * data$slope + data$intercept
144+
data$yend <- data$xend * data$slope + data$intercept
141145

142146
GeomSegment$draw_panel(unique0(data), panel_params, coord, lineend = lineend)
143147
},

tests/testthat/_snaps/geom-hline-vline-abline/cartesian-lines-intersect-mid-bars.svg

Lines changed: 1 addition & 1 deletion
Loading

tests/testthat/_snaps/geom-hline-vline-abline/flipped-lines-intersect-mid-bars.svg

Lines changed: 1 addition & 1 deletion
Loading

tests/testthat/_snaps/geom-hline-vline-abline/polar-lines-intersect-mid-bars.svg

Lines changed: 1 addition & 1 deletion
Loading

tests/testthat/test-geom-hline-vline-abline.R

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,25 @@ test_that("curved lines in map projections", {
4343
)
4444
})
4545

46+
test_that("geom_abline is clipped to x/y ranges", {
47+
48+
df <- data.frame(slope = c(-0.2, -1, -5, 5, 1, 0.2))
49+
50+
p <- ggplot(df) +
51+
geom_abline(aes(slope = slope, intercept = 0)) +
52+
scale_x_continuous(limits = c(-1, 1), expand = FALSE) +
53+
scale_y_continuous(limits = c(-1, 1), expand = FALSE) +
54+
coord_cartesian(clip = "off")
55+
56+
data <- layer_grob(p)[[1]]
57+
58+
x <- c(as.numeric(data$x0), as.numeric(data$x1))
59+
expect_true(all(x >= 0 & x <= 1))
60+
61+
y <- c(as.numeric(data$y0), as.numeric(data$y1))
62+
expect_true(all(y >= 0 & y <= 1))
63+
})
64+
4665
# Warning tests ------------------------------------------------------------
4766

4867
test_that("warnings are thrown when parameters cause mapping and data to be ignored", {

0 commit comments

Comments
 (0)