From 2053d782b87bae601f82c562f07a6b262c144ccc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Szabolcs=20Horva=CC=81t?= Date: Mon, 7 Jul 2025 11:41:43 +0000 Subject: [PATCH 1/6] feat: `layout_nicely()` now aligns the layout with the axes for small graphs --- R/layout.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/layout.R b/R/layout.R index 4915534df6a..c4546a47837 100644 --- a/R/layout.R +++ b/R/layout.R @@ -957,7 +957,7 @@ layout_nicely <- function(graph, dim = 2, ...) { args$dim <- dim if (vcount(graph) < 1000) { - do.call(layout_with_fr, args) + layout_align_impl(graph, do.call(layout_with_fr, args)) } else { do.call(layout_with_drl, args) } From ca42aaa1f926a248add1cbeb18f11f082d4f91aa Mon Sep 17 00:00:00 2001 From: schochastics Date: Mon, 7 Jul 2025 15:03:03 +0200 Subject: [PATCH 2/6] added automatic tree layout --- R/layout.R | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/R/layout.R b/R/layout.R index c4546a47837..3887ff1f221 100644 --- a/R/layout.R +++ b/R/layout.R @@ -877,12 +877,18 @@ layout.circle <- function(..., params = list()) { #' #' `layout_nicely()` tries to choose an appropriate layout function for the #' supplied graph, and uses that to generate the layout. The current -#' implementation works like this: \enumerate{ \item If the graph has a graph -#' attribute called \sQuote{layout}, then this is used. If this attribute is an -#' R function, then it is called, with the graph and any other extra arguments. +#' implementation works like this: +#' \enumerate{ +#' \item If the graph has a graph attribute called \sQuote{layout}, +#' then this is used. If this attribute is an R function, then it is called, with the graph and any other extra arguments. +#' #' \item Otherwise, if the graph has vertex attributes called \sQuote{x} and #' \sQuote{y}, then these are used as coordinates. If the graph has an -#' additional \sQuote{z} vertex attribute, that is also used. \item Otherwise, +#' additional \sQuote{z} vertex attribute, that is also used. +#' +#' \item Otherwise, if the graph is a forest and has less than 30 vertices, `layout_as_tree()` is used. +#' +#' \item Otherwise, #' if the graph is connected and has less than 1000 vertices, the #' Fruchterman-Reingold layout is used, by calling `layout_with_fr()`. #' \item Otherwise the DrL layout is used, `layout_with_drl()` is called. } @@ -916,6 +922,7 @@ layout_nicely <- function(graph, dim = 2, ...) { ## 1. If there is a 'layout' graph attribute, we just use that. ## 2. Otherwise, if there are vertex attributes called 'x' and 'y', ## we use those (and the 'z' vertex attribute as well, if present). + ## 3. If the graph is a forest and has less than 30 vertices, layout_as_tree is used ## 3. Otherwise, if the graph is small (<1000) we use ## the Fruchterman-Reingold layout. ## 4. Otherwise we use the DrL layout generator. @@ -954,10 +961,15 @@ layout_nicely <- function(graph, dim = 2, ...) { } args$graph <- graph + + if (is_forest(graph) && vcount(graph) <= 30) { + return(align_layout(graph, do.call(layout_as_tree, args))) + } + args$dim <- dim if (vcount(graph) < 1000) { - layout_align_impl(graph, do.call(layout_with_fr, args)) + align_layout(graph, do.call(layout_with_fr, args)) } else { do.call(layout_with_drl, args) } @@ -3008,3 +3020,18 @@ drl_defaults <- list( final = igraph.drl.final, refine = igraph.drl.refine ) + +#' Align a vertex layout +#' This function centers a vertex layout on the coordinate system origin and +#' rotates the layout to achieve a visually pleasing alignment with the coordinate +#' axes. Doing this is particularly useful with force-directed layouts such as [layout_with_fr()]. +#' @param graph The graph whose layout is to be aligned. +#' @param layout A matrix whose rows are the coordinates of vertices. +#' @return modified layout matrix +#' @examples +#' g <- make_lattice(c(3, 3)) +#' l1 <- layout_with_fr(g) +#' l2 <- align_layout(g,l1) +#' plot(g, layout = l1) +#' plot(g, layout = l2) +align_layout <- layout_align_impl From 3379805cf0bc96ed23c9a03e372269b40b68ae7f Mon Sep 17 00:00:00 2001 From: schochastics Date: Mon, 7 Jul 2025 15:03:12 +0200 Subject: [PATCH 3/6] documentation --- man/align_layout.Rd | 32 ++++++++++++++++++++++++++++++++ man/layout_nicely.Rd | 14 ++++++++++---- 2 files changed, 42 insertions(+), 4 deletions(-) create mode 100644 man/align_layout.Rd diff --git a/man/align_layout.Rd b/man/align_layout.Rd new file mode 100644 index 00000000000..5ecdbe4ac9d --- /dev/null +++ b/man/align_layout.Rd @@ -0,0 +1,32 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/layout.R +\name{align_layout} +\alias{align_layout} +\title{Align a vertex layout +This function centers a vertex layout on the coordinate system origin and +rotates the layout to achieve a visually pleasing alignment with the coordinate +axes. Doing this is particularly useful with force-directed layouts such as \code{\link[=layout_with_fr]{layout_with_fr()}}.} +\usage{ +align_layout(graph, layout) +} +\arguments{ +\item{graph}{The graph whose layout is to be aligned.} + +\item{layout}{A matrix whose rows are the coordinates of vertices.} +} +\value{ +modified layout matrix +} +\description{ +Align a vertex layout +This function centers a vertex layout on the coordinate system origin and +rotates the layout to achieve a visually pleasing alignment with the coordinate +axes. Doing this is particularly useful with force-directed layouts such as \code{\link[=layout_with_fr]{layout_with_fr()}}. +} +\examples{ +g <- make_lattice(c(3, 3)) +l1 <- layout_with_fr(g) +l2 <- align_layout(g,l1) +plot(g, layout = l1) +plot(g, layout = l2) +} diff --git a/man/layout_nicely.Rd b/man/layout_nicely.Rd index 6ac67a3e336..a8df0563316 100644 --- a/man/layout_nicely.Rd +++ b/man/layout_nicely.Rd @@ -28,12 +28,18 @@ graph, automatically, based on a simple algorithm. See details below. \details{ \code{layout_nicely()} tries to choose an appropriate layout function for the supplied graph, and uses that to generate the layout. The current -implementation works like this: \enumerate{ \item If the graph has a graph -attribute called \sQuote{layout}, then this is used. If this attribute is an -R function, then it is called, with the graph and any other extra arguments. +implementation works like this: +\enumerate{ +\item If the graph has a graph attribute called \sQuote{layout}, +then this is used. If this attribute is an R function, then it is called, with the graph and any other extra arguments. + \item Otherwise, if the graph has vertex attributes called \sQuote{x} and \sQuote{y}, then these are used as coordinates. If the graph has an -additional \sQuote{z} vertex attribute, that is also used. \item Otherwise, +additional \sQuote{z} vertex attribute, that is also used. + +\item Otherwise, if the graph is a forest and has less than 30 vertices, \code{layout_as_tree()} is used. + +\item Otherwise, if the graph is connected and has less than 1000 vertices, the Fruchterman-Reingold layout is used, by calling \code{layout_with_fr()}. \item Otherwise the DrL layout is used, \code{layout_with_drl()} is called. } From c285ab20ca57c561ada2600edbff30b4d5c3a2c1 Mon Sep 17 00:00:00 2001 From: schochastics Date: Mon, 7 Jul 2025 15:18:11 +0200 Subject: [PATCH 4/6] export --- NAMESPACE | 1 + R/layout.R | 1 + 2 files changed, 2 insertions(+) diff --git a/NAMESPACE b/NAMESPACE index 4bd16e4bea4..0642cdf4496 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -126,6 +126,7 @@ export(aging.ba.game) export(aging.barabasi.game) export(aging.prefatt.game) export(algorithm) +export(align_layout) export(all_shortest_paths) export(all_simple_paths) export(alpha.centrality) diff --git a/R/layout.R b/R/layout.R index 3887ff1f221..37a9e52ff07 100644 --- a/R/layout.R +++ b/R/layout.R @@ -3028,6 +3028,7 @@ drl_defaults <- list( #' @param graph The graph whose layout is to be aligned. #' @param layout A matrix whose rows are the coordinates of vertices. #' @return modified layout matrix +#' @export #' @examples #' g <- make_lattice(c(3, 3)) #' l1 <- layout_with_fr(g) From 42f7161dd0a01bfab4224d7c8e883c0da2e9575e Mon Sep 17 00:00:00 2001 From: schochastics Date: Mon, 7 Jul 2025 15:24:12 +0200 Subject: [PATCH 5/6] dont align tree layout --- R/layout.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/layout.R b/R/layout.R index 37a9e52ff07..d25fee763f5 100644 --- a/R/layout.R +++ b/R/layout.R @@ -963,7 +963,7 @@ layout_nicely <- function(graph, dim = 2, ...) { args$graph <- graph if (is_forest(graph) && vcount(graph) <= 30) { - return(align_layout(graph, do.call(layout_as_tree, args))) + return(do.call(layout_as_tree, args)) } args$dim <- dim From a384af209d19a0d4b8c763dcbcebfeffff8a1e99 Mon Sep 17 00:00:00 2001 From: schochastics Date: Mon, 7 Jul 2025 15:55:19 +0200 Subject: [PATCH 6/6] added align_layout to pkgdown --- _pkgdown.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/_pkgdown.yml b/_pkgdown.yml index 646b86e8fc8..e543b111bf1 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -65,6 +65,7 @@ reference: - has_concept("plot.common") - has_concept("plot.shapes") - vertex.shape.pie + - align_layout - subtitle: Graph coloring - contents: - has_concept("coloring")