Tridiagonal Geometry & Rescaling Math
Brian S. Yandell
28 July 2026
triangle.RmdThis document outlines the triangular coordinate system used in the
ewing simulation package for modeling substrates and
organism movement, as described in the vignettes/ewing.Rmd
and implemented via the substrate.*.txt files.
Prompts
Start a new document inst/doc/refactor/triangle.md. This will be used
to document the triangular coordinate system described in
vignettes/ewing.Rmd subsection “Substrates and movement
around triangular grid”. Refer also to data/substrate.*.txt
files. Add to this discussion of R/triangle.R routines and
their use (notably rtri()) in other R routines.
Overview
The ewing simulation system allows individuals to
disperse across a set of interconnected substrate elements.
This environment is structured upon a triangular coordinate system.
The triangular grid captures the majority (~95%) of movement dynamics while significantly simplifying computational overhead. Approximations using minimum and maximum calculations replace the more intensive quadratic (Pythagorean) calculations that would be necessary in a standard rectangular coordinate system.
Each substrate patch on the grid is modeled as an interconnected
triangle, with an effective diameter of 10 units (hardwired in the
internal routine event.move).
Substrate Connectivity (substrate.substrate)
Connectivity between different substrate segments is determined by
the interaction matrix defined in
data/substrate.substrate.txt.
For example, a typical grid consists of fruits (fr1,
fr2, fr3, fr4),
twig, and leaves (lftop, lfbot),
with the configuration indicating pairwise connections. A value of
1 signifies an available path between components, whereas
0 (typically the diagonal) meaning no self-loop transition
is explicitly defined on the graph level.
Organism Movement Arrays (substrate.host and
substrate.parasite)
Movement options and biases for species traversing the grid are
directed by the data/substrate.host.txt and
data/substrate.parasite.txt matrices.
These tables parameterize:
-
substrate: The type of substrate component (e.g.,fruit,twig,leaf). -
side: Substrate elements may have complex, multi-sided topographies. For instance, fruits might have sides1, 2, 3, 4, and leaves may be categorized intotopandbottom. -
init: Relative weight determining the probability of an individual’s initial placement on this element. -
find: The relative probability parameter related to a parasite finding a host. -
move: The relative weight dictating the probability an individual will choose to traverse from the current element. -
Relative Destination Weights: The final columns
(e.g.,
fruit,twig,leaf) specify the comparative preference/weight of an organism transitioning from its current substrate to an adjacent one of the specified type.
By configuring these text files, users can fully customize the graph of the environment, establishing behavioral traits like affinity to specific plant structures (e.g., parasites preferring the top of a leaf compared to the underside) or aggregation dynamics.
Implementation of Tridiagonal Coordinates
(R/triangle.R)
The mathematical backing of the triangular coordinate system resides
in R/triangle.R, converting simulation parameters into
physical space. The fundamental characteristic of the tridiagonal system
is that coordinates consist of three axes values
()
which intrinsically sum to zero
().
Note that the terms triangle, tridiagonal, and
tri are used interchangeably in the codebase to reference
this same 3-axis space.
Core Routines
-
rtri(n, width, tri, roundoff): Generates randomized adjustments to coordinate positions for individuals. Within the spatial dimension bounds[0, width], it calculates randomized uniform variable transformations onto the 3 tridiagonal axes. -
car2tri(xy)andtri2car(tri): Helper transformation matrices parsing objects between conventional 2D Cartesian () mappings and the native tridiagonal format (). This translation is especially helpful for downstream plotting limits (plot.current) or interactions needing euclidean geometric interpretations. -
tridist(tri)andcardist(xy): Evaluate distance in 3-axis versus 2-axis formats. Distance in triangular bounds computationally reduces to retrieving themaxvalue of the matrices across an axis, further enabling performance optimizations mentioned earlier (~95% approximation with minimum processing cost).
Usages within Simulation State
The coordinate engine interacts closely with initialization and organism event handling:
-
R/init.population.R: During baseline generation viainit.population(), an initial positional dispersion on the substrate space is computed utilizingrtri(n, width = 100). Thus, individuals manifest randomly displaced throughout the substrate plane up to a radius of 100 units prior to assignment to nodespos.a,pos.b, andpos.c. -
R/move.R: Individuals progressing to anevent.movescheduled activity can hop across the substrate grid. Assuming they do not transfer directly entirely between disjoint components (sub.future), their physical step size traversing within their local substrate updates viartri(n, width = 10). This encapsulates standard micro-movements of scale 10 simulation units.
Substrate Triangle Reconstruction
Prompts
Develop an R script under
inst/scripts/substrate_triangle.R to programmatically
reconstruct the tridiagonal grid image from
Documents/plant_triangle.jpg. The image depicts a network
composed of 8 connected triangles: lftop,
lfbot, tw1, tw2,
fr1, fr2, fr3, and
fr4.
Instead of using random noise generation via rtri(), we
will generate a regular geometric lattice using native triangular
coordinates
,
and apply topology offsets to map the interconnected substrate
shapes.
Walkthrough
-
Fixed
car2tri.default(R/triangle.R): Discovered and patched a silent matrix dimension bug.rbind(x, y)was improperly generating a2xNmatrix instead of the expectedNx2matrix. This caused parsing errors and translation failures in the tridiagonal coordinate conversions. The function now appropriately runscbind, feeding correctly oriented memory tocar2tri(). -
Created
substrate_triangle.R: Added the new tridiagonal topological visualization toolinst/scripts/substrate_triangle.R. This tool generates a localized mesh array modeling interlocking geometries for standard upward and downward component orientations, correctly restricted to precisely 10 dots per edge using mathematical delta- stepadjustments. -
Topology Mappings: Formulated a refined tridiagonal
topology matrix spanning the visual plane. This explicitly builds the
hexagonal layout dictated by the adjacency limits, positioning
fr2as the downward central triangle seamlessly abutting (fr1,fr3,fr4), and sequentially attaching thetwigandleafmodules to form proper continuous branches without empty grid gaps. -
Visual Overlays & Alignment: In addition to
resolving a 1-dot alignment slip (calibrating the adjacency anchors
exactly to the offset bound distances
W = 9), the structure generates explicit bounding polygons spanning the substrate borders with black outer lines. Finally, it dynamically calculates side boundary midpoints and interpolates them 25% inward towards the substrate centroid to properly overlay the1, 2, 3numeric axis boundary identifiers right inside their respective sides.
By passing the aggregate topology to the package’s internal
tri2car() geometry transformer, the code accurately maps
the layout to standardized Euclidean spatial data
enabling robust visualization.
Object-Oriented Refactoring
To maximize reusability across the simulation suite, the core
construction loops from the prototype script have been completely
abstracted into the package’s source directory under
R/substrate_triangle.R. This explicitly decouples the
network structure into formal functional operations:
-
substrate_topology(width, step): Isolates mathematical configuration offsets and coordinate boundary limits globally. We explicitly transitioned away from “plant” nomenclature to the “substrate” standard to support generalized interaction meshes. -
create_substrate(topology, width, step): Iterates across the defined configuration to compute analytical geometry components (extracting Euclidean mesh dots, defining polygon bounds via topological vertices, and interpolating numerical boundary indicators automatically). Returns an S3 object of formatclass = "substrate". -
autoplot.substrate(object): Implements a scalable visual overlay handler utilizingggplot2. Users can instantiate the tridiagonal substrate network internally and map it instantly utilizing native commands likeautoplot(my_substrate)!
The inst/scripts/substrate_triangle.R script now
exclusively invokes these native package functions (via
library(ewing)) to render the reconstruction!
Interactive Substrate Network Explorer
(triangleApp)
Prompts
Use `inst/scripts/substrate_triangle.R` to create `R/triangleApp.R`. Create a `demos/triangleApp.qmd` for deployment. First create an Implementation Plan for approval.
Document in `inst/doc/refactor/triangle.md`.
Architectural Rationale & Features
-
Interactive Substrate Grid Scaling (
width&step):-
triangleApp(width = 10, step = 1)provides numeric inputs allowing users to dynamically scale substrate component radius (width) and grid dot density spacing (step). - Modifying
widthorstepinstantly recalculates the tridiagonal topology lattice (substrate_topology) and spatial geometry (create_substrate).
-
-
Modular Filtering & Layer Toggles:
-
Substrate Module Selector: Users can select or
remove individual plant components (
fr1..fr4fruits,tw1..tw2twigs,lftop..lfbotleaves) using a multi-select tag list (selectizeInput). -
Display Layer Checkboxes: Users can toggle
individual graphical layers:
-
Boundaries(geom_polygonoutlining substrate patch perimeters). -
Dots(geom_pointshowing grid coordinate points). -
Labels(geom_textdisplaying component center labels). -
Numbers(geom_textdisplaying side edge numbers 1, 2, 3).
-
-
Substrate Module Selector: Users can select or
remove individual plant components (
-
Substrate Statistics & Metrics Panel:
- A dedicated card displays real-time summary metrics:
- Active module count vs. total available modules.
- Total spatial coordinate dots across selected modules.
- Extents spanning spatial and dimensions.
- Point density breakdown list per substrate patch.
- A dedicated card displays real-time summary metrics:
-
Ultra-Compact Sidebar Design:
- Follows the tight side panel layout established in
tempApp.R(side-by-side flex inputs, inline checkboxes, ~180px height), ensuring the sidebar aligns with the plot height and eliminates empty space.
- Follows the tight side panel layout established in
-
Serverless Shinylive WebAssembly Deployment
(
demos/triangleApp.qmd):- Includes standalone implementations of core substrate routines
(
tricoord,tri2car,get_substrate_grid,substrate_topology,create_substrate). - Indexed in
demos/index.qmd(listing grid) anddemos/_quarto.yml(navbar navigation).
- Includes standalone implementations of core substrate routines
(
Hexagonal Grid Overlay & Global Organism Positioning
(hexmoveApp)
The tridiagonal substrate network engine has been expanded to map live simulation organism coordinates directly onto hexagonal substrate grid overlays:
-
Substrate Patch Resolution (ewing_substrate): Maps
organism substrate stage indices
individual["sub.stage"]to specific plant substrate elements (fr1,fr2,fr3,fr4,twig/tw1,lftop,lfbot). -
Hexagonal Overlay Generation (create_hex_overlay):
Constructs 6-vertex polygon tiles for each lattice dot in a
substrateobject, rendering discrete hexagonal cells across all substrate components (fr1..fr4,tw1..tw2,lftop..lfbot). -
Per-Substrate Surface Coordinate Rescaling (ewing_substrate):
Rescales organism local coordinates
into the unit triangle
of each active substrate patch (supporting custom substrate sizes
per surface). Applies topological offsets (
offset) and orientations (dir = "up"or"down"), converting to global Euclidean coordinates viatri2car()so all organisms are visualized strictly within their designated substrate surface bounds. -
Integrated Module Controls (substrateApp): Supports
switching between
"hex"(global hexagonal grid overlay) and"facet"(panel view faceted by substrate element), alongside action buttons for stepping through simulation events (+1,+10,+100steps). -
Interactive Application (hexmoveApp): Composes
initParInput,initServer, andsubstrateServerinto an interactive exploration tool. See hexmove.md for full documentation.