grip (Graph dRawing with Intelligent Placement) is an R package for multiscale graph layout in 2D and 3D. The main workflow is:
-
grip()for unweighted graphs, -
weighted.grip()for weighted graphs, -
compare.layouts()andscore.layout()for real-data layout selection, -
trace.grip()andtrace.weighted.grip()for diagnostics.
The package also includes advanced public experimental geodesic-KK utilities for weighted-layout scoring and polish. It builds on the GRIP method described in Gajer & Kobourov (2002) and Gajer, Goodrich & Kobourov (2004).
Installation
# Install from GitHub
install.packages("remotes")
remotes::install_github("pgajer/grip")Quick start
library(grip)
# Lay out a small mesh in 2D using the "mesh" preset
edges <- edges.mesh(8, 8)
coords <- grip(edges, n = 64, dim = 2, preset = "mesh", seed = 1)
plot.layout(coords, edges, pch = 16, cex = 0.6, main = "8x8 mesh")Features
- Multiscale force-directed layout in 2D and 3D via C++ (Rcpp).
-
grip()for unweighted graphs. -
weighted.grip()for weighted graphs. - Layout comparison and quality scoring across seeds and parameter settings (
compare.layouts(),score.layout()). - Multiscale trace diagnostics for both workflows (
trace.grip(),trace.weighted.grip()). - Advanced public experimental geodesic-KK utilities for weighted-layout scoring and polish (
prepare.geodesic.kk(),score.geodesic.kk(),prepare.landmark.geodesic.kk(),score.landmark.geodesic.kk()). - Synthetic graph-family helpers for benchmark and geometry-rich examples.
- Handles disconnected graphs automatically (component packing).
- Tuned presets for common graph families (see table below).
- Static 3D projection for vignettes and reports (
plot.layout(projection = "ortho"),project.3d()). - Optional Shiny explorers and interactive 3D viewing via
rgl.
Presets
| Family | Preset | Tuned on |
|---|---|---|
| Rectangular grid or lattice | preset = "mesh" |
8x8 and 12x12 meshes |
| Sierpinski carpet | preset = "carpet" |
Level 3 and 4 carpets |
| Tree-like graph | preset = "tree" |
Binary trees, depths 5 and 6 |
| 3D torus or cylinder | preset = "torus" |
Torus sizes 8x8 through 20x20
|
Presets set sensible defaults for the GRIP parameters. Any explicit argument you pass overrides the preset value.
Choosing a workflow
- Start with
grip()when the graph is unweighted. - Switch to
weighted.grip()when the graph is weighted. - Use
compare.layouts()andscore.layout()when the graph is important enough to justify a candidate shortlist rather than a single run. - Use
trace.grip()ortrace.weighted.grip()when you need to diagnose how a solve evolved. - Add GKK/LGKK only after you already have weighted candidate layouts and need geodesic-aware scoring or polish; these are advanced public experimental tools rather than the default starting point.
Gallery
The animations below show the multiscale refinement process captured by trace.grip(). Starting from a coarse global placement, the algorithm iteratively refines vertex positions until the layout converges.
More examples
Edge-list input (2D, circle placement)
edges <- edges.cycle(18)
coords <- grip(edges, n = 18, dim = 2, placement = "circle", seed = 2)
plot.layout(coords, edges, pch = 16, cex = 0.7)Weighted adjacency list (geometry-aware)
adj_list <- list(c(2), c(1, 3), c(2, 4), c(3))
weight_list <- list(c(1.0), c(1.0, 2.0), c(2.0, 1.5), c(1.5))
coords <- weighted.grip(adj_list = adj_list, weight_list = weight_list,
n = 4, dim = 2, seed = 12)
plot.layout(coords)3D layout with static projection
edges <- edges.torus(8, 12)
coords <- grip(edges, n = max(edges), dim = 3, preset = "torus", seed = 3)
plot.layout(coords, edges, projection = "ortho", main = "Torus (8x12)")Layout comparison
For real-world graphs without a known target layout, compare.layouts() compares candidates across seeds and reports quality metrics. Use params.from.summary() to extract the winning parameters for reuse.
edges <- edges.mesh(10, 10)
cmp <- compare.layouts(edges, n = 100, dim = 2,
candidates = c("default", "mesh"),
seeds = 1:3)
cmp$summary[, c("candidate", "score.composite", "sampled.stress.mean")]Documentation
The package ships with four core vignettes:
- Getting Started with grip — the shortest path through the default unweighted workflow, with guidance on when to switch to weighted, trace, or comparison workflows.
- Weighted Graph Layouts with grip — geometry-aware layouts, geodesic scoring, and 2D-versus-3D decisions for weighted graphs.
- Choosing Layouts for Real Data — a step-by-step workflow using the Zachary karate club and Krackhardt kite examples, plus a larger weighted HMP/U01 case study.
- Tracing and Diagnosing Layouts — frame-by-frame tracing for understanding how a solve evolves.
The pkgdown site also includes companion articles such as the interactive explorer guide, the HMP/U01 object-structure note, the comparison article, and the synthetic-family gallery.
The geodesic-KK helpers are public and documented in the reference index, but they are intentionally positioned as advanced experimental tools layered on top of the main weighted workflow.
Citation
If you use grip in published work, please cite the underlying algorithm:
Gajer, P. and Kobourov, S.G. (2002). GRIP: Graph dRawing with Intelligent Placement. Journal of Graph Algorithms and Applications, 6(3), 203–224. doi: 10.7155/jgaa.00052
Gajer, P., Goodrich, M.T. and Kobourov, S.G. (2004). A multi-dimensional approach to force-directed layouts of large graphs. Computational Geometry, 29(1), 3–18. doi: 10.1016/j.comgeo.2004.03.014

