diff --git a/NAMESPACE b/NAMESPACE index 24c6f003..f028280f 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -324,6 +324,7 @@ importFrom(igraph,as.undirected) importFrom(igraph,as_edgelist) importFrom(igraph,bfs) importFrom(igraph,components) +importFrom(igraph,count_components) importFrom(igraph,degree) importFrom(igraph,delete_edges) importFrom(igraph,delete_vertex_attr) diff --git a/NEWS.md b/NEWS.md index 25873a18..1351d80d 100644 --- a/NEWS.md +++ b/NEWS.md @@ -26,6 +26,7 @@ periphery of their parent (#226) * Updated layout functions from the graphlayouts package to support grouped and constrained versions (centrality, focus, and stress layouts) +* Added H Tree layout for binary trees (#58) # ggraph 2.1.0 diff --git a/R/RcppExports.R b/R/RcppExports.R index 90fbde1a..282688fa 100644 --- a/R/RcppExports.R +++ b/R/RcppExports.R @@ -52,6 +52,10 @@ dendrogram_spread <- function(graph, starts, y, leaf, repel, pad, ratio) { .Call('_ggraph_dendrogram_spread', PACKAGE = 'ggraph', graph, starts, y, leaf, repel, pad, ratio) } +hTree <- function(parent, order) { + .Call('_ggraph_hTree', PACKAGE = 'ggraph', parent, order) +} + partitionTree <- function(parent, order, weight, height) { .Call('_ggraph_partitionTree', PACKAGE = 'ggraph', parent, order, weight, height) } diff --git a/R/ggraph.R b/R/ggraph.R index 9c0f0b51..268a42d7 100644 --- a/R/ggraph.R +++ b/R/ggraph.R @@ -83,6 +83,8 @@ #' \item{`unrooted`}{Draws unrooted trees based on equal angle with optional #' equal daylight modification. See [layout_tbl_graph_unrooted()] for further #' details} +#' \item{`htree`}{Draws binary trees as a space filling fractal. See +#' [layout_tbl_graph_htree()] for further details} #' } #' #' Alternatively a matrix or a data.frame can be provided to the `layout` diff --git a/R/layout_htree.R b/R/layout_htree.R new file mode 100644 index 00000000..e33b4186 --- /dev/null +++ b/R/layout_htree.R @@ -0,0 +1,52 @@ +#' Layout binary trees in a fractal H formation +#' +#' This is a spac efficient layout only useful for binary trees. It is fractal +#' and works by offsetting child nodes from their parent either horizontally or +#' vertically depending on depth. The offset is decreased at each step by a +#' factor of the square root of 2. +#' +#' @note +#' H Tree is a layout intended for trees, that is, graphs where nodes +#' only have one parent and zero or more children. If the provided graph does +#' not fit this format an attempt to convert it to such a format will be made. +#' +#' @param graph An `tbl_graph` object +#' +#' @param sort.by The name of a node variable to sort the nodes by. +#' +#' @param direction The direction of the tree in the graph. `'out'` (default) +#' means that parents point towards their children, while `'in'` means that +#' children point towards their parent. +#' +#' @param circular Logical. Should the layout be transformed to a circular +#' representation. Ignored +#' +#' @return A data.frame with the columns `x`, `y`, `leaf`, `depth`, `circular` +#' as well as any information stored as node variables in the tbl_graph object. +#' +#' @family layout_tbl_graph_* +#' +#' @importFrom igraph degree count_components +#' +layout_tbl_graph_htree <- function(graph, sort.by = NULL, direction = 'out', circular = FALSE) { + if (any(degree(graph, mode = direction) > 2)) { + cli::cli_abort("H-Tree layouts can only be used with binary trees") + } + if (count_components(graph, "weak") != 1) { + cli::cli_abort("H-Tree layouts can only be used with fully connected graphs") + } + sort.by <- enquo(sort.by) + sort.by <- eval_tidy(sort.by, .N()) + hierarchy <- tree_to_hierarchy(graph, direction, sort.by, NULL) + layout <- hTree(hierarchy$parent, hierarchy$order)[-1, ] + nodes <- data_frame0( + x = layout[, 1], + y = layout[, 2], + circular = FALSE + ) + nodes$leaf <- degree(graph, mode = direction) == 0 + nodes$depth <- node_depth(graph, mode = direction) + nodes <- combine_layout_nodes(nodes, as_tibble(graph, active = 'nodes')) + attr(nodes, 'graph') <- add_direction(graph, nodes) + nodes +} diff --git a/R/tbl_graph.R b/R/tbl_graph.R index 91aadeec..a0ff8bfc 100644 --- a/R/tbl_graph.R +++ b/R/tbl_graph.R @@ -85,7 +85,8 @@ prepare_graph <- function(graph, layout, direction = 'out', ...) { 'treemap', 'circlepack', 'partition', - 'cactustree' + 'cactustree', + 'htree' ) graph_is_treeish <- with_graph(graph, graph_is_tree() || graph_is_forest()) if (is_hierarchy || (layout == 'auto' && graph_is_treeish)) { diff --git a/_pkgdown.yml b/_pkgdown.yml index 4928541f..f9db83f0 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -75,6 +75,7 @@ reference: - layout_tbl_graph_treemap - layout_tbl_graph_partition - layout_tbl_graph_cactustree + - layout_tbl_graph_htree - layout_tbl_graph_matrix - layout_tbl_graph_hive - layout_tbl_graph_fabric diff --git a/man/layout_tbl_graph_auto.Rd b/man/layout_tbl_graph_auto.Rd index 0e836b08..5be31589 100644 --- a/man/layout_tbl_graph_auto.Rd +++ b/man/layout_tbl_graph_auto.Rd @@ -40,6 +40,7 @@ Other layout_tbl_graph_*: \code{\link{layout_tbl_graph_fabric}()}, \code{\link{layout_tbl_graph_focus}()}, \code{\link{layout_tbl_graph_hive}()}, +\code{\link{layout_tbl_graph_htree}()}, \code{\link{layout_tbl_graph_igraph}()}, \code{\link{layout_tbl_graph_linear}()}, \code{\link{layout_tbl_graph_manual}()}, diff --git a/man/layout_tbl_graph_backbone.Rd b/man/layout_tbl_graph_backbone.Rd index 8c753aad..dbe7e2ff 100644 --- a/man/layout_tbl_graph_backbone.Rd +++ b/man/layout_tbl_graph_backbone.Rd @@ -44,6 +44,7 @@ Other layout_tbl_graph_*: \code{\link{layout_tbl_graph_fabric}()}, \code{\link{layout_tbl_graph_focus}()}, \code{\link{layout_tbl_graph_hive}()}, +\code{\link{layout_tbl_graph_htree}()}, \code{\link{layout_tbl_graph_igraph}()}, \code{\link{layout_tbl_graph_linear}()}, \code{\link{layout_tbl_graph_manual}()}, diff --git a/man/layout_tbl_graph_cactustree.Rd b/man/layout_tbl_graph_cactustree.Rd index 1b192e3d..ca964ba1 100644 --- a/man/layout_tbl_graph_cactustree.Rd +++ b/man/layout_tbl_graph_cactustree.Rd @@ -69,6 +69,7 @@ Other layout_tbl_graph_*: \code{\link{layout_tbl_graph_fabric}()}, \code{\link{layout_tbl_graph_focus}()}, \code{\link{layout_tbl_graph_hive}()}, +\code{\link{layout_tbl_graph_htree}()}, \code{\link{layout_tbl_graph_igraph}()}, \code{\link{layout_tbl_graph_linear}()}, \code{\link{layout_tbl_graph_manual}()}, diff --git a/man/layout_tbl_graph_centrality.Rd b/man/layout_tbl_graph_centrality.Rd index 70ff38de..3be1361c 100644 --- a/man/layout_tbl_graph_centrality.Rd +++ b/man/layout_tbl_graph_centrality.Rd @@ -63,6 +63,7 @@ Other layout_tbl_graph_*: \code{\link{layout_tbl_graph_fabric}()}, \code{\link{layout_tbl_graph_focus}()}, \code{\link{layout_tbl_graph_hive}()}, +\code{\link{layout_tbl_graph_htree}()}, \code{\link{layout_tbl_graph_igraph}()}, \code{\link{layout_tbl_graph_linear}()}, \code{\link{layout_tbl_graph_manual}()}, diff --git a/man/layout_tbl_graph_circlepack.Rd b/man/layout_tbl_graph_circlepack.Rd index 292b866d..dfa09be7 100644 --- a/man/layout_tbl_graph_circlepack.Rd +++ b/man/layout_tbl_graph_circlepack.Rd @@ -74,6 +74,7 @@ Other layout_tbl_graph_*: \code{\link{layout_tbl_graph_fabric}()}, \code{\link{layout_tbl_graph_focus}()}, \code{\link{layout_tbl_graph_hive}()}, +\code{\link{layout_tbl_graph_htree}()}, \code{\link{layout_tbl_graph_igraph}()}, \code{\link{layout_tbl_graph_linear}()}, \code{\link{layout_tbl_graph_manual}()}, diff --git a/man/layout_tbl_graph_dendrogram.Rd b/man/layout_tbl_graph_dendrogram.Rd index 7f754401..52b1e00d 100644 --- a/man/layout_tbl_graph_dendrogram.Rd +++ b/man/layout_tbl_graph_dendrogram.Rd @@ -67,6 +67,7 @@ Other layout_tbl_graph_*: \code{\link{layout_tbl_graph_fabric}()}, \code{\link{layout_tbl_graph_focus}()}, \code{\link{layout_tbl_graph_hive}()}, +\code{\link{layout_tbl_graph_htree}()}, \code{\link{layout_tbl_graph_igraph}()}, \code{\link{layout_tbl_graph_linear}()}, \code{\link{layout_tbl_graph_manual}()}, diff --git a/man/layout_tbl_graph_eigen.Rd b/man/layout_tbl_graph_eigen.Rd index 67f9a599..024558df 100644 --- a/man/layout_tbl_graph_eigen.Rd +++ b/man/layout_tbl_graph_eigen.Rd @@ -42,6 +42,7 @@ Other layout_tbl_graph_*: \code{\link{layout_tbl_graph_fabric}()}, \code{\link{layout_tbl_graph_focus}()}, \code{\link{layout_tbl_graph_hive}()}, +\code{\link{layout_tbl_graph_htree}()}, \code{\link{layout_tbl_graph_igraph}()}, \code{\link{layout_tbl_graph_linear}()}, \code{\link{layout_tbl_graph_manual}()}, diff --git a/man/layout_tbl_graph_fabric.Rd b/man/layout_tbl_graph_fabric.Rd index 457b7c42..b891b99b 100644 --- a/man/layout_tbl_graph_fabric.Rd +++ b/man/layout_tbl_graph_fabric.Rd @@ -62,6 +62,7 @@ Other layout_tbl_graph_*: \code{\link{layout_tbl_graph_eigen}()}, \code{\link{layout_tbl_graph_focus}()}, \code{\link{layout_tbl_graph_hive}()}, +\code{\link{layout_tbl_graph_htree}()}, \code{\link{layout_tbl_graph_igraph}()}, \code{\link{layout_tbl_graph_linear}()}, \code{\link{layout_tbl_graph_manual}()}, diff --git a/man/layout_tbl_graph_focus.Rd b/man/layout_tbl_graph_focus.Rd index e332b115..9697ba3a 100644 --- a/man/layout_tbl_graph_focus.Rd +++ b/man/layout_tbl_graph_focus.Rd @@ -60,6 +60,7 @@ Other layout_tbl_graph_*: \code{\link{layout_tbl_graph_eigen}()}, \code{\link{layout_tbl_graph_fabric}()}, \code{\link{layout_tbl_graph_hive}()}, +\code{\link{layout_tbl_graph_htree}()}, \code{\link{layout_tbl_graph_igraph}()}, \code{\link{layout_tbl_graph_linear}()}, \code{\link{layout_tbl_graph_manual}()}, diff --git a/man/layout_tbl_graph_hive.Rd b/man/layout_tbl_graph_hive.Rd index 9d74a680..f2b684df 100644 --- a/man/layout_tbl_graph_hive.Rd +++ b/man/layout_tbl_graph_hive.Rd @@ -103,6 +103,7 @@ Other layout_tbl_graph_*: \code{\link{layout_tbl_graph_eigen}()}, \code{\link{layout_tbl_graph_fabric}()}, \code{\link{layout_tbl_graph_focus}()}, +\code{\link{layout_tbl_graph_htree}()}, \code{\link{layout_tbl_graph_igraph}()}, \code{\link{layout_tbl_graph_linear}()}, \code{\link{layout_tbl_graph_manual}()}, diff --git a/man/layout_tbl_graph_htree.Rd b/man/layout_tbl_graph_htree.Rd new file mode 100644 index 00000000..b72fc222 --- /dev/null +++ b/man/layout_tbl_graph_htree.Rd @@ -0,0 +1,87 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/layout_htree.R +\name{layout_tbl_graph_htree} +\alias{layout_tbl_graph_htree} +\title{Calculate nodes as areas dividing their parent} +\usage{ +layout_tbl_graph_htree(graph, sort.by = NULL, direction = "out") +} +\arguments{ +\item{graph}{An \code{tbl_graph} object} + +\item{sort.by}{The name of a node variable to sort the nodes by.} + +\item{direction}{The direction of the tree in the graph. \code{'out'} (default) +means that parents point towards their children, while \code{'in'} means that +children point towards their parent.} + +\item{weight}{An optional node variable to use as weight. Will only affect +the weight of leaf nodes as the weight of non-leaf nodes are derived from +their children.} + +\item{circular}{Logical. Should the layout be transformed to a circular +representation. If \code{TRUE} the resulting layout will be a sunburst +diagram.} + +\item{height}{An optional node variable to use as height. If \code{NULL} +all nodes will be given a height of 1.} + +\item{const.area}{Logical. Should 'height' be scaled for area proportionality +when using \code{circular = TRUE}. Defaults to \code{TRUE}.} + +\item{offset}{If \code{circular = TRUE}, where should it begin. Defaults to +\code{pi/2} which is equivalent to 12 o'clock.} +} +\value{ +If \code{circular = FALSE} A data.frame with the columns \code{x}, +\code{y}, \code{width}, \code{height}, \code{leaf}, +\code{depth}, \code{circular} as well as any information stored as node +variables in the tbl_graph object. +If \code{circular = TRUE} A data.frame with the columns \code{x}, \code{y}, +\code{r0}, \code{r}, \code{start}, \code{end}, \code{leaf}, +\code{depth}, \code{circular} as well as any information stored as node +variables in the tbl_graph object. +} +\description{ +The partition layout is a way to show hierarchical data in the same way as +\code{\link[=layout_tbl_graph_treemap]{layout_tbl_graph_treemap()}}. Instead of subdividing the parent area +the partition layout shows the division of a nodes children next to the area +of the node itself. As such the node positions will be very reminiscent of +a reingold-tilford tree layout but by plotting nodes as areas it better +communicate the total weight of a node by summing up all its children. +Often partition layouts are called icicle plots or sunburst diagrams (in case +a radial transform is applied). +} +\note{ +partition is a layout intended for trees, that is, graphs where nodes +only have one parent and zero or more children. If the provided graph does +not fit this format an attempt to convert it to such a format will be made. +} +\references{ +Kruskal, J. B., Landwehr, J. M. (1983). \emph{Icicle Plots: Better Displays +for Hierarchical Clustering}. American Statistician Vol 37(2), 162-168. +https://doi.org/10.2307/2685881 +} +\seealso{ +Other layout_tbl_graph_*: +\code{\link{layout_tbl_graph_auto}()}, +\code{\link{layout_tbl_graph_backbone}()}, +\code{\link{layout_tbl_graph_cactustree}()}, +\code{\link{layout_tbl_graph_centrality}()}, +\code{\link{layout_tbl_graph_circlepack}()}, +\code{\link{layout_tbl_graph_dendrogram}()}, +\code{\link{layout_tbl_graph_eigen}()}, +\code{\link{layout_tbl_graph_fabric}()}, +\code{\link{layout_tbl_graph_focus}()}, +\code{\link{layout_tbl_graph_hive}()}, +\code{\link{layout_tbl_graph_igraph}()}, +\code{\link{layout_tbl_graph_linear}()}, +\code{\link{layout_tbl_graph_manual}()}, +\code{\link{layout_tbl_graph_matrix}()}, +\code{\link{layout_tbl_graph_partition}()}, +\code{\link{layout_tbl_graph_pmds}()}, +\code{\link{layout_tbl_graph_stress}()}, +\code{\link{layout_tbl_graph_treemap}()}, +\code{\link{layout_tbl_graph_unrooted}()} +} +\concept{layout_tbl_graph_*} diff --git a/man/layout_tbl_graph_igraph.Rd b/man/layout_tbl_graph_igraph.Rd index bf98feb7..0eb79336 100644 --- a/man/layout_tbl_graph_igraph.Rd +++ b/man/layout_tbl_graph_igraph.Rd @@ -115,6 +115,7 @@ Other layout_tbl_graph_*: \code{\link{layout_tbl_graph_fabric}()}, \code{\link{layout_tbl_graph_focus}()}, \code{\link{layout_tbl_graph_hive}()}, +\code{\link{layout_tbl_graph_htree}()}, \code{\link{layout_tbl_graph_linear}()}, \code{\link{layout_tbl_graph_manual}()}, \code{\link{layout_tbl_graph_matrix}()}, diff --git a/man/layout_tbl_graph_linear.Rd b/man/layout_tbl_graph_linear.Rd index f458fad9..20625c99 100644 --- a/man/layout_tbl_graph_linear.Rd +++ b/man/layout_tbl_graph_linear.Rd @@ -57,6 +57,7 @@ Other layout_tbl_graph_*: \code{\link{layout_tbl_graph_fabric}()}, \code{\link{layout_tbl_graph_focus}()}, \code{\link{layout_tbl_graph_hive}()}, +\code{\link{layout_tbl_graph_htree}()}, \code{\link{layout_tbl_graph_igraph}()}, \code{\link{layout_tbl_graph_manual}()}, \code{\link{layout_tbl_graph_matrix}()}, diff --git a/man/layout_tbl_graph_manual.Rd b/man/layout_tbl_graph_manual.Rd index a33bc43b..36e7e147 100644 --- a/man/layout_tbl_graph_manual.Rd +++ b/man/layout_tbl_graph_manual.Rd @@ -33,6 +33,7 @@ Other layout_tbl_graph_*: \code{\link{layout_tbl_graph_fabric}()}, \code{\link{layout_tbl_graph_focus}()}, \code{\link{layout_tbl_graph_hive}()}, +\code{\link{layout_tbl_graph_htree}()}, \code{\link{layout_tbl_graph_igraph}()}, \code{\link{layout_tbl_graph_linear}()}, \code{\link{layout_tbl_graph_matrix}()}, diff --git a/man/layout_tbl_graph_matrix.Rd b/man/layout_tbl_graph_matrix.Rd index 07815ec0..bc504b67 100644 --- a/man/layout_tbl_graph_matrix.Rd +++ b/man/layout_tbl_graph_matrix.Rd @@ -45,6 +45,7 @@ Other layout_tbl_graph_*: \code{\link{layout_tbl_graph_fabric}()}, \code{\link{layout_tbl_graph_focus}()}, \code{\link{layout_tbl_graph_hive}()}, +\code{\link{layout_tbl_graph_htree}()}, \code{\link{layout_tbl_graph_igraph}()}, \code{\link{layout_tbl_graph_linear}()}, \code{\link{layout_tbl_graph_manual}()}, diff --git a/man/layout_tbl_graph_partition.Rd b/man/layout_tbl_graph_partition.Rd index 1f48cabf..0b02493a 100644 --- a/man/layout_tbl_graph_partition.Rd +++ b/man/layout_tbl_graph_partition.Rd @@ -83,6 +83,7 @@ Other layout_tbl_graph_*: \code{\link{layout_tbl_graph_fabric}()}, \code{\link{layout_tbl_graph_focus}()}, \code{\link{layout_tbl_graph_hive}()}, +\code{\link{layout_tbl_graph_htree}()}, \code{\link{layout_tbl_graph_igraph}()}, \code{\link{layout_tbl_graph_linear}()}, \code{\link{layout_tbl_graph_manual}()}, diff --git a/man/layout_tbl_graph_pmds.Rd b/man/layout_tbl_graph_pmds.Rd index a1b5cd79..8d019794 100644 --- a/man/layout_tbl_graph_pmds.Rd +++ b/man/layout_tbl_graph_pmds.Rd @@ -42,6 +42,7 @@ Other layout_tbl_graph_*: \code{\link{layout_tbl_graph_fabric}()}, \code{\link{layout_tbl_graph_focus}()}, \code{\link{layout_tbl_graph_hive}()}, +\code{\link{layout_tbl_graph_htree}()}, \code{\link{layout_tbl_graph_igraph}()}, \code{\link{layout_tbl_graph_linear}()}, \code{\link{layout_tbl_graph_manual}()}, diff --git a/man/layout_tbl_graph_stress.Rd b/man/layout_tbl_graph_stress.Rd index 87d6a685..5a84afcd 100644 --- a/man/layout_tbl_graph_stress.Rd +++ b/man/layout_tbl_graph_stress.Rd @@ -79,6 +79,7 @@ Other layout_tbl_graph_*: \code{\link{layout_tbl_graph_fabric}()}, \code{\link{layout_tbl_graph_focus}()}, \code{\link{layout_tbl_graph_hive}()}, +\code{\link{layout_tbl_graph_htree}()}, \code{\link{layout_tbl_graph_igraph}()}, \code{\link{layout_tbl_graph_linear}()}, \code{\link{layout_tbl_graph_manual}()}, diff --git a/man/layout_tbl_graph_treemap.Rd b/man/layout_tbl_graph_treemap.Rd index 0a77b344..d0aa94b6 100644 --- a/man/layout_tbl_graph_treemap.Rd +++ b/man/layout_tbl_graph_treemap.Rd @@ -96,6 +96,7 @@ Other layout_tbl_graph_*: \code{\link{layout_tbl_graph_fabric}()}, \code{\link{layout_tbl_graph_focus}()}, \code{\link{layout_tbl_graph_hive}()}, +\code{\link{layout_tbl_graph_htree}()}, \code{\link{layout_tbl_graph_igraph}()}, \code{\link{layout_tbl_graph_linear}()}, \code{\link{layout_tbl_graph_manual}()}, diff --git a/man/layout_tbl_graph_unrooted.Rd b/man/layout_tbl_graph_unrooted.Rd index 4f5db93d..6fa2b9aa 100644 --- a/man/layout_tbl_graph_unrooted.Rd +++ b/man/layout_tbl_graph_unrooted.Rd @@ -69,6 +69,7 @@ Other layout_tbl_graph_*: \code{\link{layout_tbl_graph_fabric}()}, \code{\link{layout_tbl_graph_focus}()}, \code{\link{layout_tbl_graph_hive}()}, +\code{\link{layout_tbl_graph_htree}()}, \code{\link{layout_tbl_graph_igraph}()}, \code{\link{layout_tbl_graph_linear}()}, \code{\link{layout_tbl_graph_manual}()}, diff --git a/src/RcppExports.cpp b/src/RcppExports.cpp index 5a63a125..7734a724 100644 --- a/src/RcppExports.cpp +++ b/src/RcppExports.cpp @@ -66,6 +66,18 @@ BEGIN_RCPP return rcpp_result_gen; END_RCPP } +// hTree +NumericMatrix hTree(IntegerVector parent, IntegerVector order); +RcppExport SEXP _ggraph_hTree(SEXP parentSEXP, SEXP orderSEXP) { +BEGIN_RCPP + Rcpp::RObject rcpp_result_gen; + Rcpp::RNGScope rcpp_rngScope_gen; + Rcpp::traits::input_parameter< IntegerVector >::type parent(parentSEXP); + Rcpp::traits::input_parameter< IntegerVector >::type order(orderSEXP); + rcpp_result_gen = Rcpp::wrap(hTree(parent, order)); + return rcpp_result_gen; +END_RCPP +} // partitionTree NumericMatrix partitionTree(IntegerVector parent, IntegerVector order, NumericVector weight, NumericVector height); RcppExport SEXP _ggraph_partitionTree(SEXP parentSEXP, SEXP orderSEXP, SEXP weightSEXP, SEXP heightSEXP) { @@ -149,6 +161,7 @@ static const R_CallMethodDef CallEntries[] = { {"_ggraph_pack", (DL_FUNC) &_ggraph_pack, 1}, {"_ggraph_circlePackLayout", (DL_FUNC) &_ggraph_circlePackLayout, 2}, {"_ggraph_dendrogram_spread", (DL_FUNC) &_ggraph_dendrogram_spread, 7}, + {"_ggraph_hTree", (DL_FUNC) &_ggraph_hTree, 2}, {"_ggraph_partitionTree", (DL_FUNC) &_ggraph_partitionTree, 4}, {"_ggraph_cut_lines", (DL_FUNC) &_ggraph_cut_lines, 9}, {"_ggraph_pathAttr", (DL_FUNC) &_ggraph_pathAttr, 2}, diff --git a/src/hTree.cpp b/src/hTree.cpp new file mode 100644 index 00000000..0e6d2a18 --- /dev/null +++ b/src/hTree.cpp @@ -0,0 +1,37 @@ +#include +#include "nodes.h" +using namespace Rcpp; + +void hLayout(Node* node, double x, double y, bool horizontal, double length) { + Rectangle r = {x, y, 0.0, 0.0}; + node->bounds = r; + std::vector children = node->getChildren(); + double next_length = length / 1.414214; + for (unsigned int i = 0; i < children.size(); i++) { + length *= -1; + hLayout(children[i], horizontal ? x + length : x, horizontal ? y : y + length, !horizontal, next_length); + } +} + +//[[Rcpp::export]] +NumericMatrix hTree(IntegerVector parent, IntegerVector order) { + NumericMatrix pos(parent.size(), 2); + unsigned int i; + + std::vector nodes = createHierarchy(as< std::vector >(parent), as< std::vector >(order)); + + for (i = 0; i < nodes.size(); ++i) { + nodes[i]->sortChildren(); + } + + Node* startNode = nodes[0]->getRoot(); + hLayout(startNode, 0, 0, false, 1.0); + + for (i = 0; i < nodes.size(); ++i) { + pos(i, 0) = nodes[i]->bounds.x; + pos(i, 1) = nodes[i]->bounds.y; + delete nodes[i]; + } + + return pos; +} diff --git a/src/nodes.cpp b/src/nodes.cpp index 2a971c98..c5c0db1b 100644 --- a/src/nodes.cpp +++ b/src/nodes.cpp @@ -27,6 +27,20 @@ std::vector createHierarchy(std::vector parent, std::vector ord } return nodes; } +std::vector createHierarchy(std::vector parent, std::vector order) { + std::vector nodes; + unsigned int i; + for (i = 0; i < parent.size(); ++i) { + Node* node = new Node(i, order[i], 0.0); + nodes.push_back(node); + } + for (i = 0; i < parent.size(); ++i) { + if (parent[i] >= 0) { + nodes[parent[i]]->addNode(nodes[i]); + } + } + return nodes; +} std::vector createUnrooted(std::vector parent, std::vector order, std::vector length) { std::vector nodes; diff --git a/src/nodes.h b/src/nodes.h index 730068ee..51ac167c 100644 --- a/src/nodes.h +++ b/src/nodes.h @@ -197,4 +197,5 @@ class Node { std::vector createHierarchy(std::vector parent, std::vector order, std::vector weight); std::vector createHierarchy(std::vector parent, std::vector order, std::vector weight, std::vector height); +std::vector createHierarchy(std::vector parent, std::vector order); std::vector createUnrooted(std::vector parent, std::vector order, std::vector length);