Skip to content

Getting into the code

huacayacauh edited this page May 21, 2020 · 26 revisions

Main Architeture

We use a Model/View/Controller design pattern, with:

  • the View in JS-Sandpile.html and css/,
  • the Controller in js/app.js,
  • the Model in all other files of js/:
    • js/Tiling.js for the Tile and Tiling Objects (including sandpile logics),
    • js/Features/ for important features,
    • js/TilingPresets/ for tiling presets,
    • js/Utils/ for abstract functionalities and libraries.

The tiling is render with library three.js in Utils/three.min.js.

File dependencies

JS-Sandpile.html uses functions from all JS files (in js/ folder), however if one JS file is missing, the corresponding buttons or features will produce an error but will not block the rest of the app.

All JS files in Features/ and TilingPresets/ rely exclusively on app.js and Tiling.js.

app.js relies on Tiling.js and Features/ChangeDisplay.js.

Apart from that, all files are mutually independent, each one adding either a Feature or a Tiling Preset.

Controller app.js

The App object contains the sandpile canvas render using three.js, its main attribute is scene, the three.Scene() Object.

Many important global state variables:

  • app invoked as var app = new App();, so that app.scene is the three.Scene(),
  • currentTiling the current Tiling Object,
  • play = false,
  • it_per_frame the number of iterations per frame,
  • play the state of the start button,
  • delay the current delay (ms),
  • selectedTile the index of the mouse selected tile in currentTiling.tiles Array.

Each GUI button basically calls some function of app.js, which itself calls some functionality from Tiling.js or Feature/ (which themselves may use Utils/).

Main Objects

Tile

A Tile contains:

  • an id (expected to be unique) which can be anything (Arrays may be convenient) (note that the Tiling constructor will overwrite all tile id as consecutive integers),
  • an Array of its ǹeighors' id and undefined if there is no neighbor (for tiles on the border) (note that the Tilling constructor will remove from neighbors anything that do not corresponds to a tile id),
  • an Array of coordinates of the form [x_1,y_1,x_2,y_2,...,x_k,y_k] defining its bounds, i.e. the vertices of the polygon to be drawn in the Canvas,
  • its sand content (integer), and its prevSand content (for implementation purpose only),
  • its stability threshold limit (it will topple when sand >= limit),
  • an Array of points indices corresponding the the triangulation of the tile to be drawn by three.Mesh (this is handled by the constructor of Tiling).

The Tile constructor is invoked as new Tile(id, neighbors, bounds, limit);. One may then manually set some .sand content for decoration (default at 0).

Tiling

A Tiling is constructed from an Array of Tile.
The constructor is invoked as new Tiling(tiles);, with two optional arguments:

  • a Boolean to show (false) or hide (true) the tiling. Default is false, user may have no reason to set it to false (copies of the tiling configuration are hidden during some operations such as identity computation, via the Tiling method .hiddenCopy()).
  • a Boolean to do nothing (false) or recenter (true) the tiling. The recentering puts coordinate (0,0) at the barycenter of all tile bounds.

Main attributes of a Tiling:

  • tiles is the Array of Tile,
  • identity stores the identity of the sandpile group (declared in method .get_identity()),
  • super_identity stores the super identity of the sandpile group, 3m-(3m)° (declared in method .get_inverse()),
  • hide=false indicates whether to render the tiling in the canvas with three.js (used by .hiddenCopy() to copy the current configuration),
  • mesh (computed by the constructor) is the colored three.Mesh corresponding to the tiling (tiles are cut into triangles with Mapbox/earcut in Utils/earcut.js),
  • wireFrame (computed by the constructor) is the three.LineSegments of tile edges.
  • points (computed by the constructor) is the triplets of bound coordinates of the form [x_1,y_1,z_1,x_2,y_2,z_2,...,x_k,y_k,z_k], corresponding to vertices of the tile triangles. The triangle points corresponding to a tile are indexed in Tile.points (by the constructor of Tiling).

Main methods of Tiling:

  • iterate() computes one sandpile step,
  • stabilize() reaches the stable configuration,
  • get_maxStable() returns the maximum stable configuration m with t.sand = t.limit-1 for each tile t,
  • get_identity() computes the identity element of the sandpile group once, as (2m-(2m)°)°, then recovers it from attribute .identity,
  • get_inverse() computes the inverse (sandpile group) of the current configuration (assumed to be recurrent without check), as (3m-(3m)°-c)°, and stores 3m-(3m)° in attribute .super_identity for faster subsequent inverse computations,
  • hiddenCopy() creates a copy of the configuration, as a Tiling Object without rendering it (only id, neighbors, limit and sand from tiles are copied, no bounds, and Tiling.hide=true),
  • colorTiles(), sets the color of each tile and (updates attribute mesh by calling colorTile on all elements of tiles Array),
  • many configuration manipulations (sand number/addition/subtraction at one position/everwhere, etc).

Debug tips

In Mouse controls panel there is a Select option printing a Tile Object in the JS Console. Although ids are recomputed when calling new Tiling(...), one may get useful debug information. Default is false.

It may also be convenient to set some tile .sand content to non-zero in order to identify it.

Batch processings

In order to run multiple (offline) simulations on after the other, one can write some function in js/Features/Batch_processings.js, and add an associated button in the Control bar. These functions may call the desired functionalities as if user clicks on the app, generating datas, etc.
The functions already implemented are:

  • batch_identities() computes some (big) identity elements and export them as .json files,
  • batch_roundness() runs makeRoundnessFileFast on the tilings for which the user gives .json files of the identities (this includes file prompt, which may be useful to compute identities only once and reuse them for multiple simulations),
  • batch_frontiers() computes the frontiers on the configurations at the beginning of phase 2 on some tilings, for which the user is prompted to give a precise list of identities (number of steps needed to reach the beginning of phase 2 are hard coded).

Clone this wiki locally