Repository navigation
Getting into the code
We use a Model/View/Controller design pattern, with:
- the View in
JS-Sandpile.htmlandcss/, - the Controller in
js/app.js, - the Model in all other files of
js/:-
js/Tiling.jsfor theTileandTilingObjects (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.
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.
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:
-
appinvoked asvar app = new App();, so thatapp.sceneis thethree.Scene(), -
currentTilingthe currentTilingObject, -
play = false, -
it_per_framethe number of iterations per frame, -
playthe state of the start button, -
delaythe current delay (ms), -
selectedTilethe index of the mouse selected tile incurrentTiling.tilesArray.
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/).
A Tile contains:
- an
id(expected to be unique) which can be anything (Arrays may be convenient) (note that theTilingconstructor will overwrite all tileidas consecutive integers), - an Array of its
ǹeighors'idandundefinedif there is no neighbor (for tiles on the border) (note that theTillingconstructor will remove fromneighborsanything that do not corresponds to a tileid), - an Array of coordinates of the form
[x_1,y_1,x_2,y_2,...,x_k,y_k]defining itsbounds, i.e. the vertices of the polygon to be drawn in the Canvas, - its
sandcontent (integer), and itsprevSandcontent (for implementation purpose only), - its stability threshold
limit(it will topple whensand >= limit), - an Array of
pointsindices corresponding the the triangulation of the tile to be drawn bythree.Mesh(this is handled by the constructor ofTiling).
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).
A Tiling is constructed from an Array of Tile.
The constructor is invoked as new Tiling(tiles);, with two optional arguments:
- a
Booleanto show (false) or hide (true) the tiling. Default isfalse, user may have no reason to set it tofalse(copies of the tiling configuration are hidden during some operations such as identity computation, via theTilingmethod.hiddenCopy()). - a
Booleanto 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:
-
tilesis the Array ofTile, -
identitystores the identity of the sandpile group (declared in method.get_identity()), -
super_identitystores the super identity of the sandpile group,3m-(3m)°(declared in method.get_inverse()), -
hide=falseindicates 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 coloredthree.Meshcorresponding to the tiling (tiles are cut into triangles with Mapbox/earcut inUtils/earcut.js), -
wireFrame(computed by the constructor) is thethree.LineSegmentsof 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 inTile.points(by the constructor ofTiling).
Main methods of Tiling:
-
iterate()computes one sandpile step, -
stabilize()reaches the stable configuration, -
get_maxStable()returns the maximum stable configurationmwitht.sand = t.limit-1for each tilet, -
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 stores3m-(3m)°in attribute.super_identityfor faster subsequent inverse computations, -
hiddenCopy()creates a copy of the configuration, as a Tiling Object without rendering it (onlyid,neighbors,limitandsandfrom tiles are copied, nobounds, andTiling.hide=true), -
colorTiles(), sets the color of each tile and (updates attributemeshby callingcolorTileon all elements oftilesArray), - many configuration manipulations (sand number/addition/subtraction at one position/everwhere, etc).
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.
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.jsonfiles, -
batch_roundness()runsmakeRoundnessFileFaston the tilings for which the user gives.jsonfiles 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).