Not logged in

A surface is essentially a 2D array. Currently, only floating-point values are supported, although hopefully colors and integers will be added in the near future.

A surface can be either infinite or finite. An infinite surface is one that has its width and height fields equal to infinity.

A surface may or may not be writable. Writable surfaces have a .set() method which can be used to set the value of a specific cell. Non-writable surfaces have no such method.

Most surface operations are lazy, in that they perform the operation only as needed, when values are requested via .get(). Some operations are strict, and must compute the operation over every cell in the input. Strict operations have method names ending with $.

.render(surface) (Flextime instance method)

Renders a surface to the canvas, as a grayscale image (0.0 is black and 1.0 is white).

Surface constructors


Constructs the null surface, an infinite non-writable surface which returns 0.0 everywhere.


Constructs an infinite, non-writable surface with the value c everywhere.


Constructs a non-writable surface that evaluates the function f(x,y) to determine the value at point x,y. If a width and height are provided the surface will be finite, otherwise it will be infinite.


Constructs a surface from an existing Float32Array. Note that the length of the array must equal width*height.

Surface instance methods

Most surface instance methods are chainable, except for those that return usable values (such as .get()).


Returns the value in the surface at the point (x,y).


Sets the value in the surface at (x,y) to v. Not valid on non-writable surfaces.

.build$([w,h]) Forces strictness of the surface. This method will create a new array surface of the required size and store the computed values of every cell into it. The optional width and height arguments are required when building an infinite surface.

Value transformations

These operations apply some transformation to the values in each cell; the transformation is purely local, and does not depend on the location of the cell or the values in neighboring cells. Consequently, most of these methods preserve the infinite/finite nature of the inputs. .map(f[,f'])
Returns the surface that results from applying the function f to the values in the input surface. Optionally, an inverse function f' can be specified as the second argument; if present, then the resulting surface will be writable, if its input is, with written values passed through f'.


Returns a possibly-writable surface that results from multiplying all the values in the input by s. (When setting values, the value will be divided by s.)


Returns a possibly-writable surface that results from adding o to all the values in the input. (When setting values, o will be subtracted from the value.)


Returns the result of thresholding the input surface to 0.0 or 1.0 by the threshold t, which defaults to 0.5.


Returns the result of clamping the input values to the range low...high, inclusive.

Geometry transformations

These methods affect the geometry of the incoming surface, but not its values.


Returns the surface, translated by dx,dy. That is, a .get(x,y) on the output is translated into .get(x+dx,y+dy) on the input.


Returns a subsurface of the input surface. The resulting surface will be finite, with width = 1 + x2-x1 and height = 1 + y2-y1. In the subsurface, the point 0,0 will map to x1,y1 in the input.