From 3e5f687c36bc25781c36d07a6210311129077cc5 Mon Sep 17 00:00:00 2001
From: Grant McDermott <grant.mcdermott@gmail.com>
Date: Sun, 7 Jul 2024 13:14:46 -0700
Subject: [PATCH 1/6] first stab at segments support

---
 R/tinyplot.R | 18 +++++++++++++-----
 1 file changed, 13 insertions(+), 5 deletions(-)

diff --git a/R/tinyplot.R b/R/tinyplot.R
index 5a780409..f967003d 100644
--- a/R/tinyplot.R
+++ b/R/tinyplot.R
@@ -562,7 +562,7 @@ tinyplot.default = function(
   # Capture deparsed expressions early, before x, y and by are evaluated
   x_dep = if (!missing(x)) {
     deparse1(substitute(x)) 
-  } else if (type == "rect") {
+  } else if (type %in% c("rect", "segments")) {
     x = NULL
     NULL
   }
@@ -624,8 +624,8 @@ tinyplot.default = function(
   }
   
   if (is.null(x)) {
-    ## Special catch for area plots without a specified y-var
-    if (type %in% c("rect")) {
+    ## Special catch for rect and segment plots without a specified y-var
+    if (type %in% c("rect", "segments")) {
       xmin_dep = deparse(substitute(xmin))
       xmax_dep = deparse(substitute(xmax))
       x_dep = paste0("[", xmin_dep, ", ", xmax_dep, "]")
@@ -635,7 +635,7 @@ tinyplot.default = function(
   } 
   if (is.null(y)) {
     ## Special catch for area and interval plots without a specified y-var
-    if (type %in% c("rect", "pointrange", "errorbar", "ribbon")) {
+    if (type %in% c("rect", "segments", "pointrange", "errorbar", "ribbon")) {
       ymin_dep = deparse(substitute(ymin))
       ymax_dep = deparse(substitute(ymax))
       y_dep = paste0("[", ymin_dep, ", ", ymax_dep, "]")
@@ -1370,7 +1370,7 @@ tinyplot.default = function(
       
       # empty plot flag
       empty_plot = FALSE
-      if (type=="n" || ((length(xx)==0) && type!="rect")) {
+      if (type=="n" || ((length(xx)==0) && !(type %in% c("rect","segments")))) {
         empty_plot = TRUE
       }
       
@@ -1488,9 +1488,17 @@ tinyplot.default = function(
         rect(
           xleft = xxmin, ybottom = yymin, xright = xxmax, ytop = yymax,
           lty = ilty,
+          lwd = ilwd,
           border = icol,
           col =  ibg
         )
+      } else if (type == "segments") {
+        segments(
+          x0 = xxmin, y0 = yymin, x1 = xxmax, y1 = yymax,
+          lty = ilty,
+          lwd = ilwd,
+          col = icol
+        )
       } else {
         stop("`type` argument not supported.", call. = FALSE)
       }

From a71bc708421d2e4b1228e4153375bc49b34086a1 Mon Sep 17 00:00:00 2001
From: Grant McDermott <grant.mcdermott@gmail.com>
Date: Sun, 7 Jul 2024 13:24:42 -0700
Subject: [PATCH 2/6] tests

---
 inst/tinytest/_tinysnapshot/segments_by.svg | 77 +++++++++++++++++++++
 inst/tinytest/test-segments.R               | 18 +++++
 2 files changed, 95 insertions(+)
 create mode 100644 inst/tinytest/_tinysnapshot/segments_by.svg
 create mode 100644 inst/tinytest/test-segments.R

diff --git a/inst/tinytest/_tinysnapshot/segments_by.svg b/inst/tinytest/_tinysnapshot/segments_by.svg
new file mode 100644
index 00000000..e2dbce50
--- /dev/null
+++ b/inst/tinytest/_tinysnapshot/segments_by.svg
@@ -0,0 +1,77 @@
+<?xml version='1.0' encoding='UTF-8' ?>
+<svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' class='svglite' width='504.00pt' height='504.00pt' viewBox='0 0 504.00 504.00'>
+<defs>
+  <style type='text/css'><![CDATA[
+    .svglite line, .svglite polyline, .svglite polygon, .svglite path, .svglite rect, .svglite circle {
+      fill: none;
+      stroke: #000000;
+      stroke-linecap: round;
+      stroke-linejoin: round;
+      stroke-miterlimit: 10.00;
+    }
+    .svglite text {
+      white-space: pre;
+    }
+  ]]></style>
+</defs>
+<rect width='100%' height='100%' style='stroke: none; fill: #FFFFFF;'/>
+<defs>
+  <clipPath id='cpMC4wMHw1MDQuMDB8MC4wMHw1MDQuMDA='>
+    <rect x='0.00' y='0.00' width='504.00' height='504.00' />
+  </clipPath>
+</defs>
+<g clip-path='url(#cpMC4wMHw1MDQuMDB8MC4wMHw1MDQuMDA=)'>
+<text x='485.06' y='230.40' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='17.34px' lengthAdjust='spacingAndGlyphs'>grp</text>
+<text x='489.15' y='248.93' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='8.01px' lengthAdjust='spacingAndGlyphs'>A</text>
+<text x='489.15' y='263.33' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='8.01px' lengthAdjust='spacingAndGlyphs'>B</text>
+</g>
+<defs>
+  <clipPath id='cpMC4wMHw0NTMuMTV8MC4wMHw1MDQuMDA='>
+    <rect x='0.00' y='0.00' width='453.15' height='504.00' />
+  </clipPath>
+</defs>
+<g clip-path='url(#cpMC4wMHw0NTMuMTV8MC4wMHw1MDQuMDA=)'>
+<text x='256.10' y='485.28' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='71.04px' lengthAdjust='spacingAndGlyphs'>[x[s], x[s + 2]]</text>
+<text transform='translate(12.96,244.80) rotate(-90)' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='71.04px' lengthAdjust='spacingAndGlyphs'>[y[s], y[s + 2]]</text>
+</g>
+<g clip-path='url(#cpMC4wMHw1MDQuMDB8MC4wMHw1MDQuMDA=)'>
+<line x1='103.35' y1='430.56' x2='376.22' y2='430.56' style='stroke-width: 0.75;' />
+<line x1='103.35' y1='430.56' x2='103.35' y2='437.76' style='stroke-width: 0.75;' />
+<line x1='194.31' y1='430.56' x2='194.31' y2='437.76' style='stroke-width: 0.75;' />
+<line x1='285.26' y1='430.56' x2='285.26' y2='437.76' style='stroke-width: 0.75;' />
+<line x1='376.22' y1='430.56' x2='376.22' y2='437.76' style='stroke-width: 0.75;' />
+<text x='103.35' y='456.48' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='16.68px' lengthAdjust='spacingAndGlyphs'>0.2</text>
+<text x='194.31' y='456.48' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='16.68px' lengthAdjust='spacingAndGlyphs'>0.4</text>
+<text x='285.26' y='456.48' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='16.68px' lengthAdjust='spacingAndGlyphs'>0.6</text>
+<text x='376.22' y='456.48' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='16.68px' lengthAdjust='spacingAndGlyphs'>0.8</text>
+<line x1='59.04' y1='371.12' x2='59.04' y2='92.75' style='stroke-width: 0.75;' />
+<line x1='59.04' y1='371.12' x2='51.84' y2='371.12' style='stroke-width: 0.75;' />
+<line x1='59.04' y1='301.52' x2='51.84' y2='301.52' style='stroke-width: 0.75;' />
+<line x1='59.04' y1='231.93' x2='51.84' y2='231.93' style='stroke-width: 0.75;' />
+<line x1='59.04' y1='162.34' x2='51.84' y2='162.34' style='stroke-width: 0.75;' />
+<line x1='59.04' y1='92.75' x2='51.84' y2='92.75' style='stroke-width: 0.75;' />
+<text transform='translate(41.76,371.12) rotate(-90)' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='10.67px' lengthAdjust='spacingAndGlyphs'>-2</text>
+<text transform='translate(41.76,301.52) rotate(-90)' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='10.67px' lengthAdjust='spacingAndGlyphs'>-1</text>
+<text transform='translate(41.76,231.93) rotate(-90)' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='6.67px' lengthAdjust='spacingAndGlyphs'>0</text>
+<text transform='translate(41.76,162.34) rotate(-90)' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='6.67px' lengthAdjust='spacingAndGlyphs'>1</text>
+<text transform='translate(41.76,92.75) rotate(-90)' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='6.67px' lengthAdjust='spacingAndGlyphs'>2</text>
+<polygon points='59.04,430.56 453.15,430.56 453.15,59.04 59.04,59.04 ' style='stroke-width: 0.75;' />
+</g>
+<defs>
+  <clipPath id='cpNTkuMDR8NDUzLjE1fDU5LjA0fDQzMC41Ng=='>
+    <rect x='59.04' y='59.04' width='394.11' height='371.52' />
+  </clipPath>
+</defs>
+<g clip-path='url(#cpNTkuMDR8NDUzLjE1fDU5LjA0fDQzMC41Ng==)'>
+<line x1='73.64' y1='251.33' x2='220.57' y2='251.71' style='stroke-width: 0.75;' />
+<line x1='220.57' y1='251.71' x2='304.25' y2='141.12' style='stroke-width: 0.75;' />
+<line x1='304.25' y1='141.12' x2='333.04' y2='187.68' style='stroke-width: 0.75;' />
+<line x1='333.04' y1='187.68' x2='347.38' y2='328.59' style='stroke-width: 0.75;' />
+<line x1='347.38' y1='328.59' x2='428.43' y2='126.74' style='stroke-width: 0.75;' />
+<line x1='142.52' y1='91.47' x2='248.47' y2='72.80' style='stroke-width: 0.75; stroke: #DF536B;' />
+<line x1='248.47' y1='72.80' x2='311.18' y2='241.21' style='stroke-width: 0.75; stroke: #DF536B;' />
+<line x1='311.18' y1='241.21' x2='339.43' y2='416.80' style='stroke-width: 0.75; stroke: #DF536B;' />
+<line x1='339.43' y1='416.80' x2='390.06' y2='236.30' style='stroke-width: 0.75; stroke: #DF536B;' />
+<line x1='390.06' y1='236.30' x2='438.56' y2='238.52' style='stroke-width: 0.75; stroke: #DF536B;' />
+</g>
+</svg>
diff --git a/inst/tinytest/test-segments.R b/inst/tinytest/test-segments.R
new file mode 100644
index 00000000..93ebf697
--- /dev/null
+++ b/inst/tinytest/test-segments.R
@@ -0,0 +1,18 @@
+source("helpers.R")
+using("tinysnapshot")
+
+f = function() {
+  # test case adapted from ?segments Examples
+  set.seed(42L)
+  x = stats::runif(12); y <- stats::rnorm(12)
+  i = order(x, y); x <- x[i]; y <- y[i]
+  s = seq(length(x)-1)  # one shorter than data
+  s = s[-length(s)]
+  grp = rep(LETTERS[1:2], 5)
+  plt(
+    xmin = x[s], ymin = y[s], xmax = x[s+2], ymax = y[s+2],
+    by = grp,
+    type = "segments"
+  )
+}
+expect_snapshot_plot(f, label = "segments_by")

From ff25dfb947d0c8fb33e5df8653008385f3029b8f Mon Sep 17 00:00:00 2001
From: Grant McDermott <grant.mcdermott@gmail.com>
Date: Sun, 7 Jul 2024 13:52:20 -0700
Subject: [PATCH 3/6] docs

---
 R/tinyplot.R    | 8 +++++---
 man/tinyplot.Rd | 4 +++-
 2 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/R/tinyplot.R b/R/tinyplot.R
index f967003d..dab64744 100644
--- a/R/tinyplot.R
+++ b/R/tinyplot.R
@@ -78,6 +78,11 @@
 #'   for segment intervals, and "ribbon" or "area" for polygon intervals (where
 #'   area plots are a special case of ribbon plots with `ymin` set to 0 and
 #'   `ymax` set to `y`; see below).
+#' @param xmin,xmax,ymin,ymax minimum and maximum coordinates of relevant area
+#'   or interval plot types. Only used when the `type` argument is one of
+#'   "rect" or "segments" (where all four min-max coordinates are required), or
+#'   "pointrange", "errorbar", or "ribbon" (where only `ymin` and `ymax`
+#'   required alongside `x`).
 #' @param xlim the x limits (x1, x2) of the plot. Note that x1 > x2 is allowed
 #'   and leads to a ‘reversed axis’. The default value, NULL, indicates that
 #'   the range of the `finite` values to be plotted should be used.
@@ -208,9 +213,6 @@
 #'   longer discussion about the trade-offs involved.
 #' @param subset,na.action,drop.unused.levels arguments passed to `model.frame`
 #'   when extracting the data from `formula` and `data`.
-#' @param xmin,xmax,ymin,ymax minimum and maximum coordinates of relevant area
-#'   or interval plot types. Only used when the `type` argument is one of
-#'   "pointrange", "errorbar", "ribbon", or "rect".
 #' @param ribbon.alpha numeric factor modifying the opacity alpha of any ribbon
 #'   shading; typically in `[0, 1]`. Only used when `type = "ribbon"`, or when
 #'   the `bg` fill argument is specified in a density plot (since filled density
diff --git a/man/tinyplot.Rd b/man/tinyplot.Rd
index 40580493..84cafc55 100644
--- a/man/tinyplot.Rd
+++ b/man/tinyplot.Rd
@@ -353,7 +353,9 @@ longer discussion about the trade-offs involved.}
 
 \item{xmin, xmax, ymin, ymax}{minimum and maximum coordinates of relevant area
 or interval plot types. Only used when the \code{type} argument is one of
-"pointrange", "errorbar", "ribbon", or "rect".}
+"rect" or "segments" (where all four min-max coordinates are required), or
+"pointrange", "errorbar", or "ribbon" (where only \code{ymin} and \code{ymax}
+required alongside \code{x}).}
 
 \item{ribbon.alpha}{numeric factor modifying the opacity alpha of any ribbon
 shading; typically in \verb{[0, 1]}. Only used when \code{type = "ribbon"}, or when

From b0524c18dd681f480eb90dd52b5c051de8032ba1 Mon Sep 17 00:00:00 2001
From: Grant McDermott <grant.mcdermott@gmail.com>
Date: Sun, 7 Jul 2024 13:53:01 -0700
Subject: [PATCH 4/6] news

---
 NEWS.md | 1 +
 1 file changed, 1 insertion(+)

diff --git a/NEWS.md b/NEWS.md
index 23a41c3f..8d38b9a5 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -15,6 +15,7 @@ New features:
   numeric is plotted against a factor. (#154 @grantmcdermott)
   - `type = "polypath`. (#159 @grantmcdermott)
   - `type = "rect"`. (#161 @grantmcdermott)
+  - `type = "segments"`. (#163 @grantmcdermott)
 
 Misc:
 

From e8e9dc93a3330c8698827e22f425023b46eee7d7 Mon Sep 17 00:00:00 2001
From: Grant McDermott <grant.mcdermott@gmail.com>
Date: Sun, 7 Jul 2024 14:08:13 -0700
Subject: [PATCH 5/6] support lty = "by"

---
 R/by_aesthetics.R | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/R/by_aesthetics.R b/R/by_aesthetics.R
index 8025463f..76dd10ba 100755
--- a/R/by_aesthetics.R
+++ b/R/by_aesthetics.R
@@ -167,7 +167,7 @@ by_pch = function(ngrps, type, pch=NULL) {
 by_lty = function(ngrps, type, lty=NULL) {
 
   # We only care about line types, otherwise return NULL
-  if (!type %in% c("l", "b", "o", "c", "h", "s", "S", "ribbon", "boxplot")) {
+  if (!type %in% c("l", "b", "o", "c", "h", "s", "S", "ribbon", "boxplot", "rect", "segments")) {
     out = NULL
     
     # special "by" convenience keyword

From 5f5caea9dceb5ac7881c0449a925d9dca24db723 Mon Sep 17 00:00:00 2001
From: Grant McDermott <grant.mcdermott@gmail.com>
Date: Sun, 7 Jul 2024 14:20:59 -0700
Subject: [PATCH 6/6] more tests

---
 inst/tinytest/_tinysnapshot/rect_by_fill.svg  | 84 +++++++++---------
 inst/tinytest/_tinysnapshot/segments_by.svg   | 58 +++++++------
 .../_tinysnapshot/segments_by_extra.svg       | 79 +++++++++++++++++
 .../_tinysnapshot/segments_by_xequal.svg      | 85 +++++++++++++++++++
 .../_tinysnapshot/segments_by_yequal.svg      | 79 +++++++++++++++++
 inst/tinytest/test-segments.R                 | 50 +++++++++--
 6 files changed, 358 insertions(+), 77 deletions(-)
 create mode 100644 inst/tinytest/_tinysnapshot/segments_by_extra.svg
 create mode 100644 inst/tinytest/_tinysnapshot/segments_by_xequal.svg
 create mode 100644 inst/tinytest/_tinysnapshot/segments_by_yequal.svg

diff --git a/inst/tinytest/_tinysnapshot/rect_by_fill.svg b/inst/tinytest/_tinysnapshot/rect_by_fill.svg
index ac564ad1..6dced252 100644
--- a/inst/tinytest/_tinysnapshot/rect_by_fill.svg
+++ b/inst/tinytest/_tinysnapshot/rect_by_fill.svg
@@ -21,40 +21,40 @@
   </clipPath>
 </defs>
 <g clip-path='url(#cpMC4wMHw1MDQuMDB8MC4wMHw1MDQuMDA=)'>
-<image width='18.00' height='86.40' x='465.09' y='205.84' preserveAspectRatio='none' xlink:href='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAABkCAYAAABHLFpgAAAAjElEQVQYlXWKsXHEQAzEQPDkwD24Ilf3Dd86kHSW9PMJB8CS359X3FI8zwg4dvqgncLBOTRgBxwsheOlC+yqRWBXTvJsCrb/Q67tQp3Vcm1vOo9mP2i+EWNi9cQaE7lQjoH7umtnae7tMQSRpTeKtVodf+lCWsTCtIdGke47DUw3stPAuCG9YfzC6Td/l79JGkcdgJAAAAAASUVORK5CYII='/>
-<text x='483.09' y='296.37' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='10.01px' lengthAdjust='spacingAndGlyphs'> 0</text>
-<text x='483.09' y='274.55' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='16.68px' lengthAdjust='spacingAndGlyphs'> 10</text>
-<text x='483.09' y='253.61' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='16.68px' lengthAdjust='spacingAndGlyphs'> 20</text>
-<text x='483.09' y='231.79' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='16.68px' lengthAdjust='spacingAndGlyphs'> 30</text>
-<text x='483.09' y='209.97' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='16.68px' lengthAdjust='spacingAndGlyphs'> 40</text>
-<text x='483.09' y='296.37' text-anchor='end' style='font-size: 12.00px;fill: #FFFFFF; font-family: "Liberation Sans";' textLength='17.99px' lengthAdjust='spacingAndGlyphs'>-   -</text>
-<text x='483.09' y='274.55' text-anchor='end' style='font-size: 12.00px;fill: #FFFFFF; font-family: "Liberation Sans";' textLength='17.99px' lengthAdjust='spacingAndGlyphs'>-   -</text>
-<text x='483.09' y='253.61' text-anchor='end' style='font-size: 12.00px;fill: #FFFFFF; font-family: "Liberation Sans";' textLength='17.99px' lengthAdjust='spacingAndGlyphs'>-   -</text>
-<text x='483.09' y='231.79' text-anchor='end' style='font-size: 12.00px;fill: #FFFFFF; font-family: "Liberation Sans";' textLength='17.99px' lengthAdjust='spacingAndGlyphs'>-   -</text>
-<text x='483.09' y='209.97' text-anchor='end' style='font-size: 12.00px;fill: #FFFFFF; font-family: "Liberation Sans";' textLength='17.99px' lengthAdjust='spacingAndGlyphs'>-   -</text>
-<text x='465.09' y='191.44' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='2.66px' lengthAdjust='spacingAndGlyphs'>i</text>
+<image width='18.00' height='86.40' x='459.15' y='205.84' preserveAspectRatio='none' xlink:href='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAABkCAYAAABHLFpgAAAAjElEQVQYlXWKsXHEQAzEQPDkwD24Ilf3Dd86kHSW9PMJB8CS359X3FI8zwg4dvqgncLBOTRgBxwsheOlC+yqRWBXTvJsCrb/Q67tQp3Vcm1vOo9mP2i+EWNi9cQaE7lQjoH7umtnae7tMQSRpTeKtVodf+lCWsTCtIdGke47DUw3stPAuCG9YfzC6Td/l79JGkcdgJAAAAAASUVORK5CYII='/>
+<text x='477.15' y='296.37' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='10.01px' lengthAdjust='spacingAndGlyphs'> 0</text>
+<text x='477.15' y='274.55' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='16.68px' lengthAdjust='spacingAndGlyphs'> 10</text>
+<text x='477.15' y='253.61' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='16.68px' lengthAdjust='spacingAndGlyphs'> 20</text>
+<text x='477.15' y='231.79' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='16.68px' lengthAdjust='spacingAndGlyphs'> 30</text>
+<text x='477.15' y='209.97' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='16.68px' lengthAdjust='spacingAndGlyphs'> 40</text>
+<text x='477.15' y='296.37' text-anchor='end' style='font-size: 12.00px;fill: #FFFFFF; font-family: "Liberation Sans";' textLength='17.99px' lengthAdjust='spacingAndGlyphs'>-   -</text>
+<text x='477.15' y='274.55' text-anchor='end' style='font-size: 12.00px;fill: #FFFFFF; font-family: "Liberation Sans";' textLength='17.99px' lengthAdjust='spacingAndGlyphs'>-   -</text>
+<text x='477.15' y='253.61' text-anchor='end' style='font-size: 12.00px;fill: #FFFFFF; font-family: "Liberation Sans";' textLength='17.99px' lengthAdjust='spacingAndGlyphs'>-   -</text>
+<text x='477.15' y='231.79' text-anchor='end' style='font-size: 12.00px;fill: #FFFFFF; font-family: "Liberation Sans";' textLength='17.99px' lengthAdjust='spacingAndGlyphs'>-   -</text>
+<text x='477.15' y='209.97' text-anchor='end' style='font-size: 12.00px;fill: #FFFFFF; font-family: "Liberation Sans";' textLength='17.99px' lengthAdjust='spacingAndGlyphs'>-   -</text>
+<text x='459.15' y='191.44' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='2.66px' lengthAdjust='spacingAndGlyphs'>i</text>
 </g>
 <defs>
-  <clipPath id='cpMC4wMHw0NDcuODF8MC4wMHw1MDQuMDA='>
-    <rect x='0.00' y='0.00' width='447.81' height='504.00' />
+  <clipPath id='cpMC4wMHw0NDEuODd8MC4wMHw1MDQuMDA='>
+    <rect x='0.00' y='0.00' width='441.87' height='504.00' />
   </clipPath>
 </defs>
-<g clip-path='url(#cpMC4wMHw0NDcuODF8MC4wMHw1MDQuMDA=)'>
-<text x='253.43' y='485.28' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='86.07px' lengthAdjust='spacingAndGlyphs'>[100 + i, 150 + i]</text>
+<g clip-path='url(#cpMC4wMHw0NDEuODd8MC4wMHw1MDQuMDA=)'>
+<text x='250.46' y='485.28' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='86.07px' lengthAdjust='spacingAndGlyphs'>[100 + i, 150 + i]</text>
 <text transform='translate(12.96,244.80) rotate(-90)' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='86.07px' lengthAdjust='spacingAndGlyphs'>[300 + i, 380 + i]</text>
 </g>
 <g clip-path='url(#cpMC4wMHw1MDQuMDB8MC4wMHw1MDQuMDA=)'>
-<line x1='73.44' y1='430.56' x2='393.42' y2='430.56' style='stroke-width: 0.75;' />
-<line x1='73.44' y1='430.56' x2='73.44' y2='437.76' style='stroke-width: 0.75;' />
-<line x1='153.43' y1='430.56' x2='153.43' y2='437.76' style='stroke-width: 0.75;' />
-<line x1='233.43' y1='430.56' x2='233.43' y2='437.76' style='stroke-width: 0.75;' />
-<line x1='313.42' y1='430.56' x2='313.42' y2='437.76' style='stroke-width: 0.75;' />
-<line x1='393.42' y1='430.56' x2='393.42' y2='437.76' style='stroke-width: 0.75;' />
-<text x='73.44' y='456.48' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='20.02px' lengthAdjust='spacingAndGlyphs'>100</text>
-<text x='153.43' y='456.48' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='20.02px' lengthAdjust='spacingAndGlyphs'>120</text>
-<text x='233.43' y='456.48' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='20.02px' lengthAdjust='spacingAndGlyphs'>140</text>
-<text x='313.42' y='456.48' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='20.02px' lengthAdjust='spacingAndGlyphs'>160</text>
-<text x='393.42' y='456.48' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='20.02px' lengthAdjust='spacingAndGlyphs'>180</text>
+<line x1='73.22' y1='430.56' x2='388.31' y2='430.56' style='stroke-width: 0.75;' />
+<line x1='73.22' y1='430.56' x2='73.22' y2='437.76' style='stroke-width: 0.75;' />
+<line x1='151.99' y1='430.56' x2='151.99' y2='437.76' style='stroke-width: 0.75;' />
+<line x1='230.76' y1='430.56' x2='230.76' y2='437.76' style='stroke-width: 0.75;' />
+<line x1='309.53' y1='430.56' x2='309.53' y2='437.76' style='stroke-width: 0.75;' />
+<line x1='388.31' y1='430.56' x2='388.31' y2='437.76' style='stroke-width: 0.75;' />
+<text x='73.22' y='456.48' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='20.02px' lengthAdjust='spacingAndGlyphs'>100</text>
+<text x='151.99' y='456.48' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='20.02px' lengthAdjust='spacingAndGlyphs'>120</text>
+<text x='230.76' y='456.48' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='20.02px' lengthAdjust='spacingAndGlyphs'>140</text>
+<text x='309.53' y='456.48' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='20.02px' lengthAdjust='spacingAndGlyphs'>160</text>
+<text x='388.31' y='456.48' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='20.02px' lengthAdjust='spacingAndGlyphs'>180</text>
 <line x1='59.04' y1='416.80' x2='59.04' y2='72.80' style='stroke-width: 0.75;' />
 <line x1='59.04' y1='416.80' x2='51.84' y2='416.80' style='stroke-width: 0.75;' />
 <line x1='59.04' y1='359.47' x2='51.84' y2='359.47' style='stroke-width: 0.75;' />
@@ -70,24 +70,24 @@
 <text transform='translate(41.76,187.47) rotate(-90)' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='20.02px' lengthAdjust='spacingAndGlyphs'>380</text>
 <text transform='translate(41.76,130.13) rotate(-90)' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='20.02px' lengthAdjust='spacingAndGlyphs'>400</text>
 <text transform='translate(41.76,72.80) rotate(-90)' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='20.02px' lengthAdjust='spacingAndGlyphs'>420</text>
-<polygon points='59.04,430.56 447.81,430.56 447.81,59.04 59.04,59.04 ' style='stroke-width: 0.75;' />
+<polygon points='59.04,430.56 441.87,430.56 441.87,59.04 59.04,59.04 ' style='stroke-width: 0.75;' />
 </g>
 <defs>
-  <clipPath id='cpNTkuMDR8NDQ3LjgxfDU5LjA0fDQzMC41Ng=='>
-    <rect x='59.04' y='59.04' width='388.77' height='371.52' />
+  <clipPath id='cpNTkuMDR8NDQxLjg3fDU5LjA0fDQzMC41Ng=='>
+    <rect x='59.04' y='59.04' width='382.83' height='371.52' />
   </clipPath>
 </defs>
-<g clip-path='url(#cpNTkuMDR8NDQ3LjgxfDU5LjA0fDQzMC41Ng==)'>
-<rect x='73.44' y='187.47' width='199.99' height='229.33' style='stroke-width: 0.75; stroke: #E7D39A; fill: #E7D39A; fill-opacity: 0.20;' />
-<rect x='89.44' y='176.00' width='199.99' height='229.33' style='stroke-width: 0.75; stroke: #EFBB6C; fill: #EFBB6C; fill-opacity: 0.20;' />
-<rect x='105.44' y='164.53' width='199.99' height='229.33' style='stroke-width: 0.75; stroke: #F2A05E; fill: #F2A05E; fill-opacity: 0.20;' />
-<rect x='121.44' y='153.07' width='199.99' height='229.33' style='stroke-width: 0.75; stroke: #F38464; fill: #F38464; fill-opacity: 0.20;' />
-<rect x='137.43' y='141.60' width='199.99' height='229.33' style='stroke-width: 0.75; stroke: #EF6575; fill: #EF6575; fill-opacity: 0.20;' />
-<rect x='153.43' y='130.13' width='199.99' height='229.33' style='stroke-width: 0.75; stroke: #E64886; fill: #E64886; fill-opacity: 0.20;' />
-<rect x='169.43' y='118.67' width='199.99' height='229.33' style='stroke-width: 0.75; stroke: #D13094; fill: #D13094; fill-opacity: 0.20;' />
-<rect x='185.43' y='107.20' width='199.99' height='229.33' style='stroke-width: 0.75; stroke: #B71C9B; fill: #B71C9B; fill-opacity: 0.20;' />
-<rect x='201.43' y='95.73' width='199.99' height='229.33' style='stroke-width: 0.75; stroke: #9A0F9C; fill: #9A0F9C; fill-opacity: 0.20;' />
-<rect x='217.43' y='84.27' width='199.99' height='229.33' style='stroke-width: 0.75; stroke: #771399; fill: #771399; fill-opacity: 0.20;' />
-<rect x='233.43' y='72.80' width='199.99' height='229.33' style='stroke-width: 0.75; stroke: #4B1D91; fill: #4B1D91; fill-opacity: 0.20;' />
+<g clip-path='url(#cpNTkuMDR8NDQxLjg3fDU5LjA0fDQzMC41Ng==)'>
+<rect x='73.22' y='187.47' width='196.93' height='229.33' style='stroke-width: 0.75; stroke: #E7D39A; fill: #E7D39A; fill-opacity: 0.20;' />
+<rect x='88.97' y='176.00' width='196.93' height='229.33' style='stroke-width: 0.75; stroke: #EFBB6C; fill: #EFBB6C; fill-opacity: 0.20;' />
+<rect x='104.73' y='164.53' width='196.93' height='229.33' style='stroke-width: 0.75; stroke: #F2A05E; fill: #F2A05E; fill-opacity: 0.20;' />
+<rect x='120.48' y='153.07' width='196.93' height='229.33' style='stroke-width: 0.75; stroke: #F38464; fill: #F38464; fill-opacity: 0.20;' />
+<rect x='136.24' y='141.60' width='196.93' height='229.33' style='stroke-width: 0.75; stroke: #EF6575; fill: #EF6575; fill-opacity: 0.20;' />
+<rect x='151.99' y='130.13' width='196.93' height='229.33' style='stroke-width: 0.75; stroke: #E64886; fill: #E64886; fill-opacity: 0.20;' />
+<rect x='167.75' y='118.67' width='196.93' height='229.33' style='stroke-width: 0.75; stroke: #D13094; fill: #D13094; fill-opacity: 0.20;' />
+<rect x='183.50' y='107.20' width='196.93' height='229.33' style='stroke-width: 0.75; stroke: #B71C9B; fill: #B71C9B; fill-opacity: 0.20;' />
+<rect x='199.25' y='95.73' width='196.93' height='229.33' style='stroke-width: 0.75; stroke: #9A0F9C; fill: #9A0F9C; fill-opacity: 0.20;' />
+<rect x='215.01' y='84.27' width='196.93' height='229.33' style='stroke-width: 0.75; stroke: #771399; fill: #771399; fill-opacity: 0.20;' />
+<rect x='230.76' y='72.80' width='196.93' height='229.33' style='stroke-width: 0.75; stroke: #4B1D91; fill: #4B1D91; fill-opacity: 0.20;' />
 </g>
 </svg>
diff --git a/inst/tinytest/_tinysnapshot/segments_by.svg b/inst/tinytest/_tinysnapshot/segments_by.svg
index e2dbce50..4f394833 100644
--- a/inst/tinytest/_tinysnapshot/segments_by.svg
+++ b/inst/tinytest/_tinysnapshot/segments_by.svg
@@ -21,29 +21,31 @@
   </clipPath>
 </defs>
 <g clip-path='url(#cpMC4wMHw1MDQuMDB8MC4wMHw1MDQuMDA=)'>
-<text x='485.06' y='230.40' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='17.34px' lengthAdjust='spacingAndGlyphs'>grp</text>
+<line x1='456.75' y1='244.80' x2='478.35' y2='244.80' style='stroke-width: 0.75;' />
+<line x1='456.75' y1='259.20' x2='478.35' y2='259.20' style='stroke-width: 0.75; stroke: #DF536B;' />
+<text x='474.26' y='230.40' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='17.34px' lengthAdjust='spacingAndGlyphs'>grp</text>
 <text x='489.15' y='248.93' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='8.01px' lengthAdjust='spacingAndGlyphs'>A</text>
 <text x='489.15' y='263.33' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='8.01px' lengthAdjust='spacingAndGlyphs'>B</text>
 </g>
 <defs>
-  <clipPath id='cpMC4wMHw0NTMuMTV8MC4wMHw1MDQuMDA='>
-    <rect x='0.00' y='0.00' width='453.15' height='504.00' />
+  <clipPath id='cpMC4wMHw0MzEuNTV8MC4wMHw1MDQuMDA='>
+    <rect x='0.00' y='0.00' width='431.55' height='504.00' />
   </clipPath>
 </defs>
-<g clip-path='url(#cpMC4wMHw0NTMuMTV8MC4wMHw1MDQuMDA=)'>
-<text x='256.10' y='485.28' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='71.04px' lengthAdjust='spacingAndGlyphs'>[x[s], x[s + 2]]</text>
+<g clip-path='url(#cpMC4wMHw0MzEuNTV8MC4wMHw1MDQuMDA=)'>
+<text x='245.30' y='485.28' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='71.04px' lengthAdjust='spacingAndGlyphs'>[x[s], x[s + 2]]</text>
 <text transform='translate(12.96,244.80) rotate(-90)' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='71.04px' lengthAdjust='spacingAndGlyphs'>[y[s], y[s + 2]]</text>
 </g>
 <g clip-path='url(#cpMC4wMHw1MDQuMDB8MC4wMHw1MDQuMDA=)'>
-<line x1='103.35' y1='430.56' x2='376.22' y2='430.56' style='stroke-width: 0.75;' />
-<line x1='103.35' y1='430.56' x2='103.35' y2='437.76' style='stroke-width: 0.75;' />
-<line x1='194.31' y1='430.56' x2='194.31' y2='437.76' style='stroke-width: 0.75;' />
-<line x1='285.26' y1='430.56' x2='285.26' y2='437.76' style='stroke-width: 0.75;' />
-<line x1='376.22' y1='430.56' x2='376.22' y2='437.76' style='stroke-width: 0.75;' />
-<text x='103.35' y='456.48' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='16.68px' lengthAdjust='spacingAndGlyphs'>0.2</text>
-<text x='194.31' y='456.48' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='16.68px' lengthAdjust='spacingAndGlyphs'>0.4</text>
-<text x='285.26' y='456.48' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='16.68px' lengthAdjust='spacingAndGlyphs'>0.6</text>
-<text x='376.22' y='456.48' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='16.68px' lengthAdjust='spacingAndGlyphs'>0.8</text>
+<line x1='100.92' y1='430.56' x2='358.83' y2='430.56' style='stroke-width: 0.75;' />
+<line x1='100.92' y1='430.56' x2='100.92' y2='437.76' style='stroke-width: 0.75;' />
+<line x1='186.89' y1='430.56' x2='186.89' y2='437.76' style='stroke-width: 0.75;' />
+<line x1='272.86' y1='430.56' x2='272.86' y2='437.76' style='stroke-width: 0.75;' />
+<line x1='358.83' y1='430.56' x2='358.83' y2='437.76' style='stroke-width: 0.75;' />
+<text x='100.92' y='456.48' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='16.68px' lengthAdjust='spacingAndGlyphs'>0.2</text>
+<text x='186.89' y='456.48' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='16.68px' lengthAdjust='spacingAndGlyphs'>0.4</text>
+<text x='272.86' y='456.48' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='16.68px' lengthAdjust='spacingAndGlyphs'>0.6</text>
+<text x='358.83' y='456.48' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='16.68px' lengthAdjust='spacingAndGlyphs'>0.8</text>
 <line x1='59.04' y1='371.12' x2='59.04' y2='92.75' style='stroke-width: 0.75;' />
 <line x1='59.04' y1='371.12' x2='51.84' y2='371.12' style='stroke-width: 0.75;' />
 <line x1='59.04' y1='301.52' x2='51.84' y2='301.52' style='stroke-width: 0.75;' />
@@ -55,23 +57,23 @@
 <text transform='translate(41.76,231.93) rotate(-90)' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='6.67px' lengthAdjust='spacingAndGlyphs'>0</text>
 <text transform='translate(41.76,162.34) rotate(-90)' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='6.67px' lengthAdjust='spacingAndGlyphs'>1</text>
 <text transform='translate(41.76,92.75) rotate(-90)' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='6.67px' lengthAdjust='spacingAndGlyphs'>2</text>
-<polygon points='59.04,430.56 453.15,430.56 453.15,59.04 59.04,59.04 ' style='stroke-width: 0.75;' />
+<polygon points='59.04,430.56 431.55,430.56 431.55,59.04 59.04,59.04 ' style='stroke-width: 0.75;' />
 </g>
 <defs>
-  <clipPath id='cpNTkuMDR8NDUzLjE1fDU5LjA0fDQzMC41Ng=='>
-    <rect x='59.04' y='59.04' width='394.11' height='371.52' />
+  <clipPath id='cpNTkuMDR8NDMxLjU1fDU5LjA0fDQzMC41Ng=='>
+    <rect x='59.04' y='59.04' width='372.51' height='371.52' />
   </clipPath>
 </defs>
-<g clip-path='url(#cpNTkuMDR8NDUzLjE1fDU5LjA0fDQzMC41Ng==)'>
-<line x1='73.64' y1='251.33' x2='220.57' y2='251.71' style='stroke-width: 0.75;' />
-<line x1='220.57' y1='251.71' x2='304.25' y2='141.12' style='stroke-width: 0.75;' />
-<line x1='304.25' y1='141.12' x2='333.04' y2='187.68' style='stroke-width: 0.75;' />
-<line x1='333.04' y1='187.68' x2='347.38' y2='328.59' style='stroke-width: 0.75;' />
-<line x1='347.38' y1='328.59' x2='428.43' y2='126.74' style='stroke-width: 0.75;' />
-<line x1='142.52' y1='91.47' x2='248.47' y2='72.80' style='stroke-width: 0.75; stroke: #DF536B;' />
-<line x1='248.47' y1='72.80' x2='311.18' y2='241.21' style='stroke-width: 0.75; stroke: #DF536B;' />
-<line x1='311.18' y1='241.21' x2='339.43' y2='416.80' style='stroke-width: 0.75; stroke: #DF536B;' />
-<line x1='339.43' y1='416.80' x2='390.06' y2='236.30' style='stroke-width: 0.75; stroke: #DF536B;' />
-<line x1='390.06' y1='236.30' x2='438.56' y2='238.52' style='stroke-width: 0.75; stroke: #DF536B;' />
+<g clip-path='url(#cpNTkuMDR8NDMxLjU1fDU5LjA0fDQzMC41Ng==)'>
+<line x1='72.84' y1='251.33' x2='211.71' y2='251.71' style='stroke-width: 0.75;' />
+<line x1='211.71' y1='251.71' x2='290.81' y2='141.12' style='stroke-width: 0.75;' />
+<line x1='290.81' y1='141.12' x2='318.03' y2='187.68' style='stroke-width: 0.75;' />
+<line x1='318.03' y1='187.68' x2='331.58' y2='328.59' style='stroke-width: 0.75;' />
+<line x1='331.58' y1='328.59' x2='408.18' y2='126.74' style='stroke-width: 0.75;' />
+<line x1='137.95' y1='91.47' x2='238.09' y2='72.80' style='stroke-width: 0.75; stroke: #DF536B;' />
+<line x1='238.09' y1='72.80' x2='297.36' y2='241.21' style='stroke-width: 0.75; stroke: #DF536B;' />
+<line x1='297.36' y1='241.21' x2='324.06' y2='416.80' style='stroke-width: 0.75; stroke: #DF536B;' />
+<line x1='324.06' y1='416.80' x2='371.92' y2='236.30' style='stroke-width: 0.75; stroke: #DF536B;' />
+<line x1='371.92' y1='236.30' x2='417.76' y2='238.52' style='stroke-width: 0.75; stroke: #DF536B;' />
 </g>
 </svg>
diff --git a/inst/tinytest/_tinysnapshot/segments_by_extra.svg b/inst/tinytest/_tinysnapshot/segments_by_extra.svg
new file mode 100644
index 00000000..a7eb5b80
--- /dev/null
+++ b/inst/tinytest/_tinysnapshot/segments_by_extra.svg
@@ -0,0 +1,79 @@
+<?xml version='1.0' encoding='UTF-8' ?>
+<svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' class='svglite' width='504.00pt' height='504.00pt' viewBox='0 0 504.00 504.00'>
+<defs>
+  <style type='text/css'><![CDATA[
+    .svglite line, .svglite polyline, .svglite polygon, .svglite path, .svglite rect, .svglite circle {
+      fill: none;
+      stroke: #000000;
+      stroke-linecap: round;
+      stroke-linejoin: round;
+      stroke-miterlimit: 10.00;
+    }
+    .svglite text {
+      white-space: pre;
+    }
+  ]]></style>
+</defs>
+<rect width='100%' height='100%' style='stroke: none; fill: #FFFFFF;'/>
+<defs>
+  <clipPath id='cpMC4wMHw1MDQuMDB8MC4wMHw1MDQuMDA='>
+    <rect x='0.00' y='0.00' width='504.00' height='504.00' />
+  </clipPath>
+</defs>
+<g clip-path='url(#cpMC4wMHw1MDQuMDB8MC4wMHw1MDQuMDA=)'>
+<line x1='456.75' y1='244.80' x2='478.35' y2='244.80' style='stroke-width: 0.75;' />
+<line x1='456.75' y1='259.20' x2='478.35' y2='259.20' style='stroke-width: 1.50; stroke: #DF536B; stroke-dasharray: 8.00,8.00;' />
+<text x='474.26' y='230.40' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='17.34px' lengthAdjust='spacingAndGlyphs'>grp</text>
+<text x='489.15' y='248.93' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='8.01px' lengthAdjust='spacingAndGlyphs'>A</text>
+<text x='489.15' y='263.33' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='8.01px' lengthAdjust='spacingAndGlyphs'>B</text>
+</g>
+<defs>
+  <clipPath id='cpMC4wMHw0MzEuNTV8MC4wMHw1MDQuMDA='>
+    <rect x='0.00' y='0.00' width='431.55' height='504.00' />
+  </clipPath>
+</defs>
+<g clip-path='url(#cpMC4wMHw0MzEuNTV8MC4wMHw1MDQuMDA=)'>
+<text x='245.30' y='485.28' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='71.04px' lengthAdjust='spacingAndGlyphs'>[x[s], x[s + 2]]</text>
+<text transform='translate(12.96,244.80) rotate(-90)' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='71.04px' lengthAdjust='spacingAndGlyphs'>[y[s], y[s + 2]]</text>
+</g>
+<g clip-path='url(#cpMC4wMHw1MDQuMDB8MC4wMHw1MDQuMDA=)'>
+<line x1='100.92' y1='430.56' x2='358.83' y2='430.56' style='stroke-width: 0.75;' />
+<line x1='100.92' y1='430.56' x2='100.92' y2='437.76' style='stroke-width: 0.75;' />
+<line x1='186.89' y1='430.56' x2='186.89' y2='437.76' style='stroke-width: 0.75;' />
+<line x1='272.86' y1='430.56' x2='272.86' y2='437.76' style='stroke-width: 0.75;' />
+<line x1='358.83' y1='430.56' x2='358.83' y2='437.76' style='stroke-width: 0.75;' />
+<text x='100.92' y='456.48' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='16.68px' lengthAdjust='spacingAndGlyphs'>0.2</text>
+<text x='186.89' y='456.48' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='16.68px' lengthAdjust='spacingAndGlyphs'>0.4</text>
+<text x='272.86' y='456.48' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='16.68px' lengthAdjust='spacingAndGlyphs'>0.6</text>
+<text x='358.83' y='456.48' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='16.68px' lengthAdjust='spacingAndGlyphs'>0.8</text>
+<line x1='59.04' y1='371.12' x2='59.04' y2='92.75' style='stroke-width: 0.75;' />
+<line x1='59.04' y1='371.12' x2='51.84' y2='371.12' style='stroke-width: 0.75;' />
+<line x1='59.04' y1='301.52' x2='51.84' y2='301.52' style='stroke-width: 0.75;' />
+<line x1='59.04' y1='231.93' x2='51.84' y2='231.93' style='stroke-width: 0.75;' />
+<line x1='59.04' y1='162.34' x2='51.84' y2='162.34' style='stroke-width: 0.75;' />
+<line x1='59.04' y1='92.75' x2='51.84' y2='92.75' style='stroke-width: 0.75;' />
+<text transform='translate(41.76,371.12) rotate(-90)' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='10.67px' lengthAdjust='spacingAndGlyphs'>-2</text>
+<text transform='translate(41.76,301.52) rotate(-90)' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='10.67px' lengthAdjust='spacingAndGlyphs'>-1</text>
+<text transform='translate(41.76,231.93) rotate(-90)' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='6.67px' lengthAdjust='spacingAndGlyphs'>0</text>
+<text transform='translate(41.76,162.34) rotate(-90)' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='6.67px' lengthAdjust='spacingAndGlyphs'>1</text>
+<text transform='translate(41.76,92.75) rotate(-90)' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='6.67px' lengthAdjust='spacingAndGlyphs'>2</text>
+<polygon points='59.04,430.56 431.55,430.56 431.55,59.04 59.04,59.04 ' style='stroke-width: 0.75;' />
+</g>
+<defs>
+  <clipPath id='cpNTkuMDR8NDMxLjU1fDU5LjA0fDQzMC41Ng=='>
+    <rect x='59.04' y='59.04' width='372.51' height='371.52' />
+  </clipPath>
+</defs>
+<g clip-path='url(#cpNTkuMDR8NDMxLjU1fDU5LjA0fDQzMC41Ng==)'>
+<line x1='72.84' y1='251.33' x2='211.71' y2='251.71' style='stroke-width: 0.75;' />
+<line x1='211.71' y1='251.71' x2='290.81' y2='141.12' style='stroke-width: 0.75;' />
+<line x1='290.81' y1='141.12' x2='318.03' y2='187.68' style='stroke-width: 0.75;' />
+<line x1='318.03' y1='187.68' x2='331.58' y2='328.59' style='stroke-width: 0.75;' />
+<line x1='331.58' y1='328.59' x2='408.18' y2='126.74' style='stroke-width: 0.75;' />
+<line x1='137.95' y1='91.47' x2='238.09' y2='72.80' style='stroke-width: 1.50; stroke: #DF536B; stroke-dasharray: 8.00,8.00;' />
+<line x1='238.09' y1='72.80' x2='297.36' y2='241.21' style='stroke-width: 1.50; stroke: #DF536B; stroke-dasharray: 8.00,8.00;' />
+<line x1='297.36' y1='241.21' x2='324.06' y2='416.80' style='stroke-width: 1.50; stroke: #DF536B; stroke-dasharray: 8.00,8.00;' />
+<line x1='324.06' y1='416.80' x2='371.92' y2='236.30' style='stroke-width: 1.50; stroke: #DF536B; stroke-dasharray: 8.00,8.00;' />
+<line x1='371.92' y1='236.30' x2='417.76' y2='238.52' style='stroke-width: 1.50; stroke: #DF536B; stroke-dasharray: 8.00,8.00;' />
+</g>
+</svg>
diff --git a/inst/tinytest/_tinysnapshot/segments_by_xequal.svg b/inst/tinytest/_tinysnapshot/segments_by_xequal.svg
new file mode 100644
index 00000000..6be78610
--- /dev/null
+++ b/inst/tinytest/_tinysnapshot/segments_by_xequal.svg
@@ -0,0 +1,85 @@
+<?xml version='1.0' encoding='UTF-8' ?>
+<svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' class='svglite' width='504.00pt' height='504.00pt' viewBox='0 0 504.00 504.00'>
+<defs>
+  <style type='text/css'><![CDATA[
+    .svglite line, .svglite polyline, .svglite polygon, .svglite path, .svglite rect, .svglite circle {
+      fill: none;
+      stroke: #000000;
+      stroke-linecap: round;
+      stroke-linejoin: round;
+      stroke-miterlimit: 10.00;
+    }
+    .svglite text {
+      white-space: pre;
+    }
+  ]]></style>
+</defs>
+<rect width='100%' height='100%' style='stroke: none; fill: #FFFFFF;'/>
+<defs>
+  <clipPath id='cpMC4wMHw1MDQuMDB8MC4wMHw1MDQuMDA='>
+    <rect x='0.00' y='0.00' width='504.00' height='504.00' />
+  </clipPath>
+</defs>
+<g clip-path='url(#cpMC4wMHw1MDQuMDB8MC4wMHw1MDQuMDA=)'>
+<line x1='456.75' y1='244.80' x2='478.35' y2='244.80' style='stroke-width: 0.75;' />
+<line x1='456.75' y1='259.20' x2='478.35' y2='259.20' style='stroke-width: 1.50; stroke: #DF536B; stroke-dasharray: 8.00,8.00;' />
+<text x='474.26' y='230.40' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='17.34px' lengthAdjust='spacingAndGlyphs'>grp</text>
+<text x='489.15' y='248.93' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='8.01px' lengthAdjust='spacingAndGlyphs'>A</text>
+<text x='489.15' y='263.33' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='8.01px' lengthAdjust='spacingAndGlyphs'>B</text>
+</g>
+<defs>
+  <clipPath id='cpMC4wMHw0MzEuNTV8MC4wMHw1MDQuMDA='>
+    <rect x='0.00' y='0.00' width='431.55' height='504.00' />
+  </clipPath>
+</defs>
+<g clip-path='url(#cpMC4wMHw0MzEuNTV8MC4wMHw1MDQuMDA=)'>
+<text x='245.30' y='485.28' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='50.69px' lengthAdjust='spacingAndGlyphs'>[x[s], x[s]]</text>
+<text transform='translate(12.96,244.80) rotate(-90)' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='71.04px' lengthAdjust='spacingAndGlyphs'>[y[s], y[s + 2]]</text>
+</g>
+<g clip-path='url(#cpMC4wMHw1MDQuMDB8MC4wMHw1MDQuMDA=)'>
+<line x1='105.22' y1='430.56' x2='402.66' y2='430.56' style='stroke-width: 0.75;' />
+<line x1='105.22' y1='430.56' x2='105.22' y2='437.76' style='stroke-width: 0.75;' />
+<line x1='154.80' y1='430.56' x2='154.80' y2='437.76' style='stroke-width: 0.75;' />
+<line x1='204.37' y1='430.56' x2='204.37' y2='437.76' style='stroke-width: 0.75;' />
+<line x1='253.94' y1='430.56' x2='253.94' y2='437.76' style='stroke-width: 0.75;' />
+<line x1='303.52' y1='430.56' x2='303.52' y2='437.76' style='stroke-width: 0.75;' />
+<line x1='353.09' y1='430.56' x2='353.09' y2='437.76' style='stroke-width: 0.75;' />
+<line x1='402.66' y1='430.56' x2='402.66' y2='437.76' style='stroke-width: 0.75;' />
+<text x='105.22' y='456.48' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='16.68px' lengthAdjust='spacingAndGlyphs'>0.2</text>
+<text x='154.80' y='456.48' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='16.68px' lengthAdjust='spacingAndGlyphs'>0.3</text>
+<text x='204.37' y='456.48' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='16.68px' lengthAdjust='spacingAndGlyphs'>0.4</text>
+<text x='253.94' y='456.48' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='16.68px' lengthAdjust='spacingAndGlyphs'>0.5</text>
+<text x='303.52' y='456.48' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='16.68px' lengthAdjust='spacingAndGlyphs'>0.6</text>
+<text x='353.09' y='456.48' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='16.68px' lengthAdjust='spacingAndGlyphs'>0.7</text>
+<text x='402.66' y='456.48' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='16.68px' lengthAdjust='spacingAndGlyphs'>0.8</text>
+<line x1='59.04' y1='371.12' x2='59.04' y2='92.75' style='stroke-width: 0.75;' />
+<line x1='59.04' y1='371.12' x2='51.84' y2='371.12' style='stroke-width: 0.75;' />
+<line x1='59.04' y1='301.52' x2='51.84' y2='301.52' style='stroke-width: 0.75;' />
+<line x1='59.04' y1='231.93' x2='51.84' y2='231.93' style='stroke-width: 0.75;' />
+<line x1='59.04' y1='162.34' x2='51.84' y2='162.34' style='stroke-width: 0.75;' />
+<line x1='59.04' y1='92.75' x2='51.84' y2='92.75' style='stroke-width: 0.75;' />
+<text transform='translate(41.76,371.12) rotate(-90)' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='10.67px' lengthAdjust='spacingAndGlyphs'>-2</text>
+<text transform='translate(41.76,301.52) rotate(-90)' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='10.67px' lengthAdjust='spacingAndGlyphs'>-1</text>
+<text transform='translate(41.76,231.93) rotate(-90)' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='6.67px' lengthAdjust='spacingAndGlyphs'>0</text>
+<text transform='translate(41.76,162.34) rotate(-90)' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='6.67px' lengthAdjust='spacingAndGlyphs'>1</text>
+<text transform='translate(41.76,92.75) rotate(-90)' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='6.67px' lengthAdjust='spacingAndGlyphs'>2</text>
+<polygon points='59.04,430.56 431.55,430.56 431.55,59.04 59.04,59.04 ' style='stroke-width: 0.75;' />
+</g>
+<defs>
+  <clipPath id='cpNTkuMDR8NDMxLjU1fDU5LjA0fDQzMC41Ng=='>
+    <rect x='59.04' y='59.04' width='372.51' height='371.52' />
+  </clipPath>
+</defs>
+<g clip-path='url(#cpNTkuMDR8NDMxLjU1fDU5LjA0fDQzMC41Ng==)'>
+<line x1='72.84' y1='251.33' x2='72.84' y2='251.71' style='stroke-width: 0.75;' />
+<line x1='233.00' y1='251.71' x2='233.00' y2='141.12' style='stroke-width: 0.75;' />
+<line x1='324.21' y1='141.12' x2='324.21' y2='187.68' style='stroke-width: 0.75;' />
+<line x1='355.60' y1='187.68' x2='355.60' y2='328.59' style='stroke-width: 0.75;' />
+<line x1='371.23' y1='328.59' x2='371.23' y2='126.74' style='stroke-width: 0.75;' />
+<line x1='147.93' y1='91.47' x2='147.93' y2='72.80' style='stroke-width: 1.50; stroke: #DF536B; stroke-dasharray: 8.00,8.00;' />
+<line x1='263.41' y1='72.80' x2='263.41' y2='241.21' style='stroke-width: 1.50; stroke: #DF536B; stroke-dasharray: 8.00,8.00;' />
+<line x1='331.77' y1='241.21' x2='331.77' y2='416.80' style='stroke-width: 1.50; stroke: #DF536B; stroke-dasharray: 8.00,8.00;' />
+<line x1='362.56' y1='416.80' x2='362.56' y2='236.30' style='stroke-width: 1.50; stroke: #DF536B; stroke-dasharray: 8.00,8.00;' />
+<line x1='417.76' y1='236.30' x2='417.76' y2='238.52' style='stroke-width: 1.50; stroke: #DF536B; stroke-dasharray: 8.00,8.00;' />
+</g>
+</svg>
diff --git a/inst/tinytest/_tinysnapshot/segments_by_yequal.svg b/inst/tinytest/_tinysnapshot/segments_by_yequal.svg
new file mode 100644
index 00000000..3dfdf1bc
--- /dev/null
+++ b/inst/tinytest/_tinysnapshot/segments_by_yequal.svg
@@ -0,0 +1,79 @@
+<?xml version='1.0' encoding='UTF-8' ?>
+<svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' class='svglite' width='504.00pt' height='504.00pt' viewBox='0 0 504.00 504.00'>
+<defs>
+  <style type='text/css'><![CDATA[
+    .svglite line, .svglite polyline, .svglite polygon, .svglite path, .svglite rect, .svglite circle {
+      fill: none;
+      stroke: #000000;
+      stroke-linecap: round;
+      stroke-linejoin: round;
+      stroke-miterlimit: 10.00;
+    }
+    .svglite text {
+      white-space: pre;
+    }
+  ]]></style>
+</defs>
+<rect width='100%' height='100%' style='stroke: none; fill: #FFFFFF;'/>
+<defs>
+  <clipPath id='cpMC4wMHw1MDQuMDB8MC4wMHw1MDQuMDA='>
+    <rect x='0.00' y='0.00' width='504.00' height='504.00' />
+  </clipPath>
+</defs>
+<g clip-path='url(#cpMC4wMHw1MDQuMDB8MC4wMHw1MDQuMDA=)'>
+<line x1='456.75' y1='244.80' x2='478.35' y2='244.80' style='stroke-width: 0.75;' />
+<line x1='456.75' y1='259.20' x2='478.35' y2='259.20' style='stroke-width: 1.50; stroke: #DF536B; stroke-dasharray: 8.00,8.00;' />
+<text x='474.26' y='230.40' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='17.34px' lengthAdjust='spacingAndGlyphs'>grp</text>
+<text x='489.15' y='248.93' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='8.01px' lengthAdjust='spacingAndGlyphs'>A</text>
+<text x='489.15' y='263.33' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='8.01px' lengthAdjust='spacingAndGlyphs'>B</text>
+</g>
+<defs>
+  <clipPath id='cpMC4wMHw0MzEuNTV8MC4wMHw1MDQuMDA='>
+    <rect x='0.00' y='0.00' width='431.55' height='504.00' />
+  </clipPath>
+</defs>
+<g clip-path='url(#cpMC4wMHw0MzEuNTV8MC4wMHw1MDQuMDA=)'>
+<text x='245.30' y='485.28' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='71.04px' lengthAdjust='spacingAndGlyphs'>[x[s], x[s + 2]]</text>
+<text transform='translate(12.96,244.80) rotate(-90)' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='50.69px' lengthAdjust='spacingAndGlyphs'>[y[s], y[s]]</text>
+</g>
+<g clip-path='url(#cpMC4wMHw1MDQuMDB8MC4wMHw1MDQuMDA=)'>
+<line x1='100.92' y1='430.56' x2='358.83' y2='430.56' style='stroke-width: 0.75;' />
+<line x1='100.92' y1='430.56' x2='100.92' y2='437.76' style='stroke-width: 0.75;' />
+<line x1='186.89' y1='430.56' x2='186.89' y2='437.76' style='stroke-width: 0.75;' />
+<line x1='272.86' y1='430.56' x2='272.86' y2='437.76' style='stroke-width: 0.75;' />
+<line x1='358.83' y1='430.56' x2='358.83' y2='437.76' style='stroke-width: 0.75;' />
+<text x='100.92' y='456.48' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='16.68px' lengthAdjust='spacingAndGlyphs'>0.2</text>
+<text x='186.89' y='456.48' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='16.68px' lengthAdjust='spacingAndGlyphs'>0.4</text>
+<text x='272.86' y='456.48' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='16.68px' lengthAdjust='spacingAndGlyphs'>0.6</text>
+<text x='358.83' y='456.48' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='16.68px' lengthAdjust='spacingAndGlyphs'>0.8</text>
+<line x1='59.04' y1='371.12' x2='59.04' y2='92.75' style='stroke-width: 0.75;' />
+<line x1='59.04' y1='371.12' x2='51.84' y2='371.12' style='stroke-width: 0.75;' />
+<line x1='59.04' y1='301.52' x2='51.84' y2='301.52' style='stroke-width: 0.75;' />
+<line x1='59.04' y1='231.93' x2='51.84' y2='231.93' style='stroke-width: 0.75;' />
+<line x1='59.04' y1='162.34' x2='51.84' y2='162.34' style='stroke-width: 0.75;' />
+<line x1='59.04' y1='92.75' x2='51.84' y2='92.75' style='stroke-width: 0.75;' />
+<text transform='translate(41.76,371.12) rotate(-90)' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='10.67px' lengthAdjust='spacingAndGlyphs'>-2</text>
+<text transform='translate(41.76,301.52) rotate(-90)' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='10.67px' lengthAdjust='spacingAndGlyphs'>-1</text>
+<text transform='translate(41.76,231.93) rotate(-90)' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='6.67px' lengthAdjust='spacingAndGlyphs'>0</text>
+<text transform='translate(41.76,162.34) rotate(-90)' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='6.67px' lengthAdjust='spacingAndGlyphs'>1</text>
+<text transform='translate(41.76,92.75) rotate(-90)' text-anchor='middle' style='font-size: 12.00px; font-family: "Liberation Sans";' textLength='6.67px' lengthAdjust='spacingAndGlyphs'>2</text>
+<polygon points='59.04,430.56 431.55,430.56 431.55,59.04 59.04,59.04 ' style='stroke-width: 0.75;' />
+</g>
+<defs>
+  <clipPath id='cpNTkuMDR8NDMxLjU1fDU5LjA0fDQzMC41Ng=='>
+    <rect x='59.04' y='59.04' width='372.51' height='371.52' />
+  </clipPath>
+</defs>
+<g clip-path='url(#cpNTkuMDR8NDMxLjU1fDU5LjA0fDQzMC41Ng==)'>
+<line x1='72.84' y1='251.33' x2='211.71' y2='251.33' style='stroke-width: 0.75;' />
+<line x1='211.71' y1='251.71' x2='290.81' y2='251.71' style='stroke-width: 0.75;' />
+<line x1='290.81' y1='141.12' x2='318.03' y2='141.12' style='stroke-width: 0.75;' />
+<line x1='318.03' y1='187.68' x2='331.58' y2='187.68' style='stroke-width: 0.75;' />
+<line x1='331.58' y1='328.59' x2='408.18' y2='328.59' style='stroke-width: 0.75;' />
+<line x1='137.95' y1='91.47' x2='238.09' y2='91.47' style='stroke-width: 1.50; stroke: #DF536B; stroke-dasharray: 8.00,8.00;' />
+<line x1='238.09' y1='72.80' x2='297.36' y2='72.80' style='stroke-width: 1.50; stroke: #DF536B; stroke-dasharray: 8.00,8.00;' />
+<line x1='297.36' y1='241.21' x2='324.06' y2='241.21' style='stroke-width: 1.50; stroke: #DF536B; stroke-dasharray: 8.00,8.00;' />
+<line x1='324.06' y1='416.80' x2='371.92' y2='416.80' style='stroke-width: 1.50; stroke: #DF536B; stroke-dasharray: 8.00,8.00;' />
+<line x1='371.92' y1='236.30' x2='417.76' y2='236.30' style='stroke-width: 1.50; stroke: #DF536B; stroke-dasharray: 8.00,8.00;' />
+</g>
+</svg>
diff --git a/inst/tinytest/test-segments.R b/inst/tinytest/test-segments.R
index 93ebf697..9ed22dec 100644
--- a/inst/tinytest/test-segments.R
+++ b/inst/tinytest/test-segments.R
@@ -1,14 +1,15 @@
 source("helpers.R")
 using("tinysnapshot")
 
+# test case adapted from ?segments Examples
+set.seed(42L)
+x = stats::runif(12); y <- stats::rnorm(12)
+i = order(x, y); x = x[i]; y = y[i]
+s = seq(length(x)-1)  # one shorter than data
+s = s[-length(s)]
+grp = rep(LETTERS[1:2], 5)
+
 f = function() {
-  # test case adapted from ?segments Examples
-  set.seed(42L)
-  x = stats::runif(12); y <- stats::rnorm(12)
-  i = order(x, y); x <- x[i]; y <- y[i]
-  s = seq(length(x)-1)  # one shorter than data
-  s = s[-length(s)]
-  grp = rep(LETTERS[1:2], 5)
   plt(
     xmin = x[s], ymin = y[s], xmax = x[s+2], ymax = y[s+2],
     by = grp,
@@ -16,3 +17,38 @@ f = function() {
   )
 }
 expect_snapshot_plot(f, label = "segments_by")
+
+# also vary lty and lwd by groups
+f = function() {
+  plt(
+    xmin = x[s], ymin = y[s], xmax = x[s+2], ymax = y[s+2],
+    by = grp,
+    lty = "by", lwd = "by",
+    type = "segments"
+  )
+}
+expect_snapshot_plot(f, label = "segments_by_extra")
+
+# xmin = xmax
+f = function() {
+  plt(
+    xmin = x[s], ymin = y[s], xmax = x[s], ymax = y[s+2],
+    by = grp,
+    lty = "by", lwd = "by",
+    type = "segments"
+  )
+}
+expect_snapshot_plot(f, label = "segments_by_xequal")
+
+# ymin = ymax
+f = function() {
+  plt(
+    xmin = x[s], ymin = y[s], xmax = x[s+2], ymax = y[s],
+    by = grp,
+    lty = "by", lwd = "by",
+    type = "segments"
+  )
+}
+expect_snapshot_plot(f, label = "segments_by_yequal")
+
+rm(x, y, i, s, grp)
