13 KiB
Tes file format
The tes file format is used to describe tessellations that can be loaded with HyperRogue/RogueViz. The format is designed to be written and read by humans, so all the numerical values can be provided as formulas.
To load a tes file in HyperRogue, do: special modes -> experiment with geometry -> geometry -> hyperbolic* ->
load from file. You can also do it with command line, e.g. ./hyperrogue -tes tessellations/sample/marjorie-rice.tes
.
- You can also pick Euclidean or spherical here -- does not matter, any file can be loaded.
Structure
A typical tes file consists of the following parts:
-
Name of the tessellation (as displayed in HyperRogue). This is given in a line starting with
##
. -
Geometry. Usually
h2.
(hyperbolic),e2.
(Euclidean),s2.
(spherical). -
A definition of distance and angle units. For example
angleunit(deg)
defines the angle unit to be 1 degree, anddistunit(arcmedge(3,3,4,4,4))
defines the distance unit to be x such that the total internal angle of two triangles and three quadrangles of edge x equals 360 degrees. The default angle unit is radian and the default distance unit is 1 (absolute unit). -
A definition of tiles. Use tile(e0, a0, e1, a1, e2, a2) to construct a tile with edge lengths e0, e1, e2 and angles a0, a1, a2, ... Edges are given clockwise and angles are internal. You can also use unittile(a0, a1, a2) if all edge lengths are 1. Tiles are indexed starting from 0.
-
A definition of connections. Most tes files use the Doily notation, e.g. conway("(0 0)(1 2)"), which means that the edge 0 of tile 0 always connects to itself, and edge 1 of tile 0 always connect to edge 2 of tile 0. You can use
i
,i'
,i''
,i'''
,i@n
to refer to edge i of tile 0, 1, 2, 3, n. Use [ ] instead of ( ) if the connection is to be mirrored. You can also use c(i1,n1,i2,n2,0) (the last value becomes 1 for mirrored connections).
Symmetries
Some tessellations include tiles with rotational symmetry. For example, in the standard HyperRogue tiling (bitruncated {7,3}), the heptagonal tiles have 7-fold rotational symmetry, and the hexagonal tiles have 3-fold rotational symmetry. (We mean symmetries not only of the tile itself, but of the whole tiling.) In this case, it is convenient to not give an index to every edge of every tile, but only to the part which repeats (i.e., heptagons have 7 edges of index 0, and hexagons have 3 edges of index 0 and 3 edges of index 1).
Such situation can be defined with e.g. tile(e0, a0, e1, a1, *3)
(this defines a hexagon with edges e0,e1,e0,e1,e0,e1
and angles a0,a1,a0,a1,a0,a1; edges are indexed with 0,1,0,1,0,1).
For mirror symmetries, use e.g. tile(e0, a0, e1, a1, e2, a2, |2)
, which means that the tile has mirror symmetry,
and edge i is the mirror image of tile 2-i. (For simplicity, you still need to write all the edge lengths and angles
in this case, even if mirror symmetry could theoretically be used to infer some of this information.)
When both rotational and mirror symmetries exist, put *
before |
.
You can also use repeat(tile_index, qty)
to make every edge index of tile tile_index repeat qty times, for example,
tile(e0, a0, e1, a1, e2, a2) repeat(0, 3)
has the same effect as tile(e0, a0, e1, a1, *3).
Some older tessellation definitions do not use this, for example 73.tes
simply lists all connections as c(i,0,i,0,0)
.
This indexing will not be consistent: there is no way to index edges of every tile clockwise so that tile indexed i
always connects to a tile indexed i. (The engine ignores this; but for new tessellations it is recommended to use
*k
or repeat
to explain the situation explicitly.)
Formulas
As mentioned above, all the numerical values can be provided as formulas. Formulas can use complex numbers.
You can use the constants: pi
, deg
(pi/180), e
, i
, inf
(infinity). You can also declare new constants as in let(tau=2*pi)
.
You can use the standard math operators +
, -
, *
(multiplication), /
(division), ^
(exponentation), and math functions sin
, cos
, tan
, sinh
, cosh
, tanh
, asin
, acos
, atan
, asinh
, acosh
, atanh
, exp
, sqrt
, log
(natural logarithm), tan
,
re
(real part), im
(imaginary part), conj
(conjugation), floor
, frac
(fractional part), min
, max
.
Programming-style functions: ifz(x,a,b)
(a if x=0, b otherwise), ifp(x,a,b)
(a if x is positive, b otherwise), test(x)
(returns x but also displays x while reading the file),
let(x=a,b)
(compute the formula a and use its value as x
in b).
Specialized functions are very useful for defining tilings.
-
edge_angles(x,y,z)
is the edge opposite x of the triangle with angles x, y, z (angles given in angleunits). Works only in non-Euclidean geometry. Length returned in absolute units. -
edge(a,b)
is the edge of the {a,b} tiling. Works only if the {a,b} tiling is possible in the current non-Euclidean geometry. Length returned in absolute units. -
regradius(a,b)
is the radius of the circumscribed circle on {a,b} tile. Works only if the {a,b} tiling is possible in the current non-Euclidean geometry. Length returned in absolute units. -
arcmedge(3:^2,4:^3)
is the edge x such that the total internal angle of two triangles and three quadrangles of edge x equals 360 degrees. Works only if the tiling is possible in the current geometry. Returns 1 in Euclidean geometry. Length returned in absolute units. -
regangle(d,s)
is the internal angle of an s-sided regular tile with edge length d distunits. Angle returned in angle units.
Note: while it may seem that a and b in edge
, regradius
, and arcmedge(a:^b)
are integers, the formulas actually also make sense for real numbers, which is sometimes useful (e.g. for star tilings).
Also a is allowed to be infinity (inf).
Special features
The tes format also has some more features. Please read the tes files in samples
subdirectory to see these in action.
-
Real-valued sliders. These represent real values than can be changed in the engine. For example, you could have a real-valued slider x, that defines a Euclidean tiling with parallelograms of angles x and 180<38>-x. Changing the value of a real-valued slider does not change the structure of the tiling (so it can be called without regenerating the map). See e.g.
slider.tes
. -
Integer-valued sliders. These represent integer values than can be changed in the engine. For example, a tes file can describe all {a,b} regular tessellations, where both a and b can be changed using sliders. Changing the value of an integer-valued slider usually does change the structure of the tiling (so the map needs to be regenerated). See e.g.
regular.tes
. -
Affine tessellations. These are tessellations of the affine two-dimensional plane; their symmetries are not Euclidean isometries but rather affine transformations of R^2. See the examples in
affine
subdirectory. -
Tiles with (ultra-)ideal angles. To achieve these, put
e1, [a1, e2, a2], e3
inside thetile
definition; this will generate the tile ase1, a1, e2, a2, e3
would, and then the edgese1
ande3
are extended until they cross (usually, in an (ultra-)ideal point), and the edgee2
is removed. Two convenient functionsideal_angle
andideal_edge
are helpful. See e.g.inf.tes
. -
Apeirogonal tiles. These are achieved by giving the tile multiplier as
*inf
(e.g.,tile(e0, a0, *inf)
). See e.g.pseudogons.tes
. -
Star polygons. Just add a line "star." so that the engine is not confused. See e.g.
star-72-7.tes
. Star polyhedra are best viewed in 3D (in settings -> 3D configuration, enable "configure FPP automatically", and also "make the tiles flat"; then leave the menu and move the camera using Home/End and arrow keys). -
Tessellations including a definition of a regular tree used to construct the tessellation. This allows non-periodic tessellations (in the style of binary tiling), see
horotiling.tes
. -
If the tessellation is invalid, HyperRogue will invoke a debugger, which lets you see the tiles you have defined and move according to their connections. You can also invoke this debugger maually with
debug(tile_index)
.
How to make the tessellations look good
Normally, when you choose to load a tes file, a game of HyperRogue is run on the tiling selected. Which might be not what you wanted. Here are some hints for making nice pictures.
-
If you just wanted to draw the tessellation, do 'experiment with geometry' -> 'pattern'. Most useful patterns are: single color, random, types, sides.
-
By default, HyperRogue tiles have wide borders, which might be not what you want. In the 'pattern' menu, you can enable 'display full floors' to prevent this, or 'width of cell boundaries' to change the width of wide borders. You can also add `boundary_ratio(value)' to the tes file, which works similar to the 'width of cell boundaries' setting.
-
HyperRogue approximates the edges using polylines. If the current approximation is not sufficient, change main menu -> settings -> general graphics -> vector settings -> line quality to a higher value. From the same menu you can also change the line width.
-
For tessellations including apeirogons you probably want the setting "simplified display of apeirogons" in 'experiment with geometry'. (This way you avoid the semicircular artifacts in the parts of the apeirogons which are close to the boundary.)
-
The screenshot menu 'experiment with geometry' -> 'take screenshot' has many useful options, e.g., to hide the player, change the pattern colors (for tile/type patterns), center the screenshot on a tile center/vertex/edge, increase the range of tiles rendered, etc.
-
To post screenshots of hyperbolic tessellations online, we recommend the following screenshot settings. In the 'projection' menu (experiment with geometry -> projection) change the scale factor to something slightly less than 1 (otherwise the Poincar<61> disk fills the whole image which does not look great). Make the screenshot transparent (screenshot menu). Change the projection background (screenshot -> colors & aura) to solid black (by setting the alpha to max value). This will make the background of the Poincar<61> disk black, while the rest of the image will be transparent, so it will use the background color of the website you post it on.
-
To print the screenshots of tessellations (e.g. to use them in math papers), it is recommended to use a vector-based format rather than PNG. Change the screenshot format (in screenshot menu) to SVG. SVG files can be converted to PDF using e.g. Inkscape. Unfortunately SVG/PDF files of hyperbolic tessellations tend to be large (lots of details), so you might want to control the quality (using sight range settings). Options such as line width, transparency, etc. do affect SVG screenshots.
-
You can also try menu -> creative mode -> map editor -> map settings -> canvas floor shape. This applies some HyperRogue floor shape tessellations to the current tiling. (You need to select the 'pattern' first as explained above).
-
Most options can be also set from the commandline. For example
hyperrogue -tes tessellations/sample/hr-standard-tiling.tes -canvas B -wsh 9 -shot-1000 -shott 1 -fillmodel 000000ff -zoom .95 -smart 1 -noplayer -vlq 3 -lw 5
will load the named tessellation file, color the tiles with "sides" pattern (B), use full floors, make screenshots of size 1000x1000, make screenshot transparent with the Poincar<61> disk black, set scaling to 0.95, and draw tiles if their size is at least 1 pixel, hide the player character, line quality to 3, and line width to 5. Add-genlimit 999999 -pngshot x.png
or-svgshot x.svg
to take a screenshot (genlimit here makes sure that tiles are generated, the default is at most 250 tiles generated per call). -rulegen-play -palrgba gtree ffffffff -palw gtree 3 -expansion 1 2 7` to generate and display a tree (explained below).
How is this implemented
Every tile on screen is represented in the memory. Tiles are generated as needed.
By default, Archimedean/tes files are generated using a simple method: when we check for a tile across an edge, we see whether a tile already exists at that coordinates -- if yes we connect to that tile, if no we generate a new tile. However, coordinate-based computations in hyperbolic geometry are prone to numerical precision errors, so occassionally this may result in errors.
HyperRogue also implements the algorithm described here to create tree structures which avoid this problem. This is not used by default because occassionally (very rarely) generating a tree structure can take some time (also it currently does not support affine, star, or tessellations with (ultra-)ideal-vertices). To run the algorithm, in 'experiment with geometry' pick 'size of the world' -> 'strict tree maps' -> 'strict tree based'. In the 'size of the world' menu you can also get various information regarding the tree structure obtained.