Implements GRIP multiscale graph layout with a unified choice
between hop-count and geometry-aware edge-length graph metrics in 2D and
3D. Provides layout scoring, candidate
comparison, multiscale trace diagnostics, synthetic graph families,
and advanced experimental geodesic-KK utilities for weighted-layout
evaluation and polish. Based on Gajer and Kobourov (2002)
grip (Graph dRawing with Intelligent Placement) is an R package for multiscale graph layout. Its primary unweighted and weighted workflows target 2D and 3D, while opt-in weighted-GRIP, metric-MDS, and edge-KK workflows also support higher-dimensional embeddings. The main workflow is:
grip(metric = "hop") for topology-first layouts,grip(metric = "edge_length") when edge lengths define the graph
metric,compare.layouts() and score.layout() for real-data layout
selection,trace.grip() with the same metric choice 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).
# Install from GitHub
install.packages("remotes")
remotes::install_github("pgajer/grip")
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")
grip() interface for hop-metric and edge-length-metric
layouts.weighted.grip.nd(), with higher-dimensional metric-MDS and edge-KK
workflows available through metric.mds() and edge.kk().compare.layouts(), score.layout()).trace.grip().prepare.geodesic.kk(), score.geodesic.kk(),
prepare.landmark.geodesic.kk(), score.landmark.geodesic.kk()).plot.layout(projection = "ortho"), project.3d()).| 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.
grip(metric = "hop"), the default, when topology should
define the multiscale hierarchy and graph neighborhoods.grip(metric = "edge_length") when positive edge lengths should
also define shortest-path distances, hierarchy construction,
neighborhoods, and insertion anchors.compare.layouts() and score.layout() when the graph is
important enough to justify a candidate shortlist rather than a single
run.trace.grip() with the corresponding metric when you need to
diagnose how a solve evolved.The historical argument names edge_weights and weight_list represent
positive edge lengths, not connection strengths. With
metric = "hop", supplied lengths set adjacent-edge force targets while
standard GRIP hierarchy and neighborhood searches still count hops. With
metric = "edge_length", the lengths also define weighted shortest
paths throughout the multiscale engine and are median-normalized by
default. See ?grip for the complete semantics and normalization
options.
trace.grip() records the multiscale refinement process from coarse
placement through the final layout. Local Sierpinski carpet and triangle
animations can be generated with make readme-assets; generated
animations are intentionally kept outside Git history.
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)
Edge-length-metric 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 <- grip(
adj_list = adj_list, weight_list = weight_list,
metric = "edge_length", 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)")
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")]
The package ships with four core vignettes:
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.
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
GPL (>= 3)