Learn R Programming

grip

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() and score.layout() for real-data layout selection,
  • trace.grip() and trace.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

FamilyPresetTuned on
Rectangular grid or latticepreset = "mesh"8x8 and 12x12 meshes
Sierpinski carpetpreset = "carpet"Level 3 and 4 carpets
Tree-like graphpreset = "tree"Binary trees, depths 5 and 6
3D torus or cylinderpreset = "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() and score.layout() when the graph is important enough to justify a candidate shortlist rather than a single run.
  • Use trace.grip() or trace.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.

Sierpinski Carpet (Level 4)

Sierpinski Triangle (Level 6)

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

License

GPL (>= 3)

Copy Link

Version

Install

install.packages('grip')

Version

0.1.2

License

GPL (>= 3)

Issues

Pull Requests

Stars

Forks

Maintainer

Pawel Gajer

Last Published

August 5th, 2026

Functions in grip (0.1.2)

grip-package

grip: Graph dRawing with Intelligent Placement
geodesic.kk

Optimize a layout under the full geodesic KK energy
graph.riemannian.star.structure

Build a local Riemannian star structure for Gram-gKK layouts
graph_generators

Sample graph generators
gmds.result

Construct a common GMDS layout result
globalrep.grip

Compute a GRIP layout with coarse global repulsion
geometry.diagnostics

Geometry-aware diagnostics against a canonical target
grip.compare.layouts

Deprecated layout comparison name
grip

Compute a GRIP layout
globalrep.weighted.grip

Compute a weighted geometry-aware GRIP layout
grip.score.layout

Deprecated layout scoring name
gripui_family_app

Build the graph-family geometry explorer Shiny application
gripui_validate_project

Validate a `gripui_project`
gripui_project_from_dir

Create a `gripui_project` from a directory of saved artifacts
grip.prepare.edge.kk

Deprecated edge-KK preparation name
grip.optimize.edge.kk.layout

Deprecated edge-KK layout names
gripui_app

Build the `gripui` Shiny application
gripui_project_from_compare

Convert `compare.layouts()` output into a `gripui_project`
gripui_project

Create a normalized `gripui` project object
gripui_graph_family_catalog

Catalog of graph families for the geometry explorer app
irregular_annulus_surface_helpers

Weighted irregular annulus surface helpers
irregular_pair_of_pants_surface_helpers

Weighted irregular pair-of-pants surface helpers
irregular_sphere_surface_helpers

Weighted irregular sphere surface helpers
irregular_shell_solid_helpers

Weighted irregular shell solid helpers
irregular_double_torus_surface_helpers

Weighted irregular double-torus surface helpers
hmp.u01.gc.coarse

HMP/U01 Coarsened Giant-Component Graph
kary_tree_weighted_graph_helpers

Intrinsically weighted k-ary tree helpers
irregular_ball_solid_helpers

Weighted irregular ball solid helpers
irregular_rectangle_surface_helpers

Irregular rectangle surface helpers
irregular_torus_surface_helpers

Weighted irregular torus surface helpers
menger_sponge_surface_helpers

Weighted Menger sponge surface helpers
params.from.summary

Extract layout parameters from a comparison summary row
mask_pattern_helpers

Mask pattern helpers for recursive grid families
occupied_mesh_surface_helpers

Occupied-mesh and perforated-grid helpers
misf.geodesic.kk

Optimize an embedding with the MISF-based geodesic-KK pipeline
mesh_surface_helpers

Weighted mesh surface helpers
landmark.geodesic.kk

Optimize a layout under the landmark geodesic KK energy
metric.mds

Metric-MDS baseline layout for GMDS experiments
kernel.gram.gkk

Optimize a kernel Gram-gKK layout
legacy.grip

Compute the legacy GRIP layout
porous_cube_surface_helpers

Weighted porous cube-mask surface helpers
prepare.misf.geodesic.kk

Prepare a MISF-based multiscale geodesic-KK object
plot.layout

Quick plot for graph layouts
perforated_grid_helpers

Deterministic perforated-grid occupancy helpers
prepare.edge.kk

Prepare an edge-only graph for edge-KK repair
prepare.landmark.geodesic.kk

Prepare sparse landmark-geodesic KK data for repeated layout evaluation
prepare.graph.geodesic.mds

Prepare a graph-first geodesic-MDS path cache
recursive_cube_mask_surface_helpers

Weighted recursive cube-mask surface helpers
project.3d

Project 3D coordinates to 2D for static plotting
prepare.geodesic.kk

Prepare full geodesic KK data for repeated layout evaluation
score.geodesic.kk

Score a layout under the full geodesic KK energy
sampled_rectangle_surface_helpers

Sampled rectangle surface helpers
repulsive.stage

Optimize one pure repulsive layout stage
recursive_tetrahedron_mask_surface_helpers

Weighted recursive tetrahedron-mask surface helpers
repulsive.state

Evaluate a pure repulsive layout objective
run_gripui

Run the `gripui` Shiny application
recursive_triangle_mask_surface_helpers

Weighted recursive triangle-mask surface helpers
run_gripui_family

Run the graph-family geometry explorer Shiny application
recursive_mask_grid_surface_helpers

Weighted recursive mask-grid surface helpers
score.gmds

Score a layout with the common GMDS diagnostic panel
sierpinski_triangle_surface_helpers

Weighted Sierpinski triangle surface helpers
score.layout

Score a single layout using graph-aware quality heuristics
score.misf.geodesic.kk

Score a MISF-based geodesic-KK fit
torus_surface_helpers

Weighted torus surface helpers
sphere_surface_helpers

Weighted sphere surface helpers
sierpinski_carpet_surface_helpers

Weighted Sierpinski carpet surface helpers
trace.grip

Compute a GRIP layout trace
score.landmark.geodesic.kk

Score a layout under the landmark geodesic KK energy
tetrahedron_mask_helpers

Tetrahedron mask helpers for recursive gasket families
sierpinski_tetrahedron_surface_helpers

Weighted Sierpinski tetrahedron surface helpers
weighted.grip.nd

Weighted GRIP layout in arbitrary dimensions
weighted.grip

Alias of globalrep.weighted.grip()
triangulated_annulus_surface_helpers

Weighted triangulated annulus surface helpers
triangulated_pair_of_pants_surface_helpers

Weighted triangulated pair-of-pants surface helpers
vicsek_surface_helpers

Weighted Vicsek surface helpers
trace.weighted.grip

Trace a weighted geometry-aware GRIP layout
triangulated_polyhedron_surface_helpers

Weighted triangulated polyhedron surface helpers
trace.legacy.grip

Compute a trace for the legacy GRIP layout
triangle_mask_helpers

Triangle mask helpers for recursive gasket families
edge.repulsive.state

Evaluate an edge-isometric repulsive unfolding objective
cylinder_surface_helpers

Weighted cylinder surface helpers
edge.repulsive.stage

Optimize one edge-isometric repulsive unfolding stage
edge.length.density.stiffness

Construct edge-length stiffnesses for edge-isometric GMDS layouts
cube_mask_pattern_helpers

Cube mask pattern helpers for recursive porous families
build.misf

Build a maximal independent set filtration (MISF) for a graph
deprecated-grip-api

Deprecated long-form API names
compare.layouts

Compare multiple layout candidates across seeds
edge.kk

Optimize an edge-KK local repair layout
build.weighted.misf

Build a weighted MISF hierarchy