PatternGenerator is a Java application that generates two kinds of graphical pattern as static images and animations. It is provided primarily for entertainment, but the two kinds of pattern that it can generate are not very interesting, and its entertainment value is likely to diminish rapidly with use.
PatternGenerator is made available under two licences:
uk.blankaspect.patterngenerator
package (including
resources) may be used under the terms of version 3 of the GNU General Public License.
This section assumes that you have some experience of building and running a Java application.
A Java Development Kit (JDK) that supports Java 17, such as Eclipse Temurin from Adoptium, is required to build PatternGenerator.
The src
directory of the repository contains all the source code and
resources that constitute the application; there are no external dependencies. The
directory conforms to the Maven standard directory layout: the source code is in
src/main/java
and the resources are in src/main/resources
.
The supplied Kotlin-DSL-based Gradle
build script, build.gradle.kts
, modifies the compileJava
and
jar
tasks (provided by the java
plug-in) to compile the
application and to create an executable JAR file for it.
The supplied Kotlin-DSL-based Gradle build script, build.gradle.kts
,
defines two tasks that may be used to run PatternGenerator:
compileJava
task.
jar
task.
Both tasks extend the JavaExec
task.
When it starts up, PatternGenerator is configured with configuration properties that are read from two sources: the command line of the Java launcher and a configuration file whose location may be explicitly specified. If the same property is specified on the command line and in a configuration file, the value from the configuration file takes precedence.
The recommended method of setting the properties in a configuration file is with the Options > Preferences command. For command-line properties, which must be edited manually, the form of the property values is given in an appendix, and it can also be inferred by generating a configuration file with the desired values and inspecting the contents of the file.
When PatternGenerator is run, configuration properties may be passed to the
java
launcher on the command line as system properties; eg,
-Dapp.general.mainWindowLocation="100, 0"
.
PatternGenerator's command-line configuration properties all have the prefix
app.
. A list of all the properties that are recognised by PatternGenerator
is given in an appendix.
System properties can be added to the two supplied Gradle
tasks, runMain
and runJar
, with the
systemProperties(Map<String, ?>)
method.
One particular property, app.configDir, is used to specify the directory that contains a configuration file, as described below.
The configuration file is named patternGenerator-config.xml
.
PatternGenerator doesn't require a configuration file: it uses a default value for
any configuration property that is missing from the source(s) of configuration.
Similarly, if it finds a property value to be invalid, PatternGenerator will display a
message to this effect and use the default value of the property. If the configuration
file contains a property that was specified on the command line, the value from the
configuration file is used.
If the configuration has changed when you exit the application normally (ie, using the File > Exit command or an equivalent), PatternGenerator will save its configuration to a configuration file. If a configuration file was read on startup, it will overwrite that file; otherwise, it will write a configuration file to the default directory described above, unless the value of the app.configDir property was an empty string.
A configuration file can be written explicitly with the Save configuration command within the Preferences dialog.
When it starts up, PatternGenerator is informed of the location of the configuration file with the app.configDir property. The value of the property may contain special constructs for system properties, environment variables and the user's home directory.
The app.configDir property may be set in two ways:
java
launcher, or
patternGenerator-properties.xml
that resides in the same
directory as the patternGenerator.jar
JAR file.
The patternGenerator-properties.xml
file is a legacy from the time when
PatternGenerator was distributed as a JAR file with an installer; the properties file
was written by the installer. If you create a properties file, it should have the
following form, with the example pathname replaced by the actual pathname:
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> <properties> <entry key="app.configDir">/home/slothrop/.blankaspect/patternGenerator</entry> </properties>
If the app.configDir property is set both on the command line and in the properties file, the value in the properties file takes precedence.
The existence and value of the app.configDir property determines the locations that are searched for a configuration file:
$PWD
on Linux/UNIX systems, depends on the system and the way in
which PatternGenerator was run.
$HOME/.blankaspect/patternGenerator
, where $HOME
is
the environment variable that denotes the user's home directory. On
Windows systems, the default directory is
%APPDATA%\blankaspect\patternGenerator
, where
%APPDATA%
is an environment variable.
From a user's perspective, a document is the form in which PatternGenerator operates on and stores the data that constitute a pattern. As described below, PatternGenerator can generate two kinds of pattern. For each kind of pattern, there are two kinds of document: parameter documents and definition documents.
PatternGenerator generates a pattern from a set of parameters and a sequence of pseudo-random numbers. The parameters are a mixture of specific values and ranges of values — explicit or implicit — from which a specific value is randomly chosen. The use of random values reduces the number of parameters that have to be specified at the cost of forgoing some control over the pattern. A parameter document contains the set of parameters and a seed for generating the sequence of pseudo-random numbers that will be used to chose values from the ranges. Because the numbers are pseudo-random, not truly random, any given seed will always produce the same predictable sequence of numbers, but different seeds will produce different sequences. Thus, variations of a pattern can be generated effortlessly just by changing the seed.
A parameter document is PatternGenerator's primary document type; it is the kind of document that is created in response to the File > New command, and it is the precursor to a definition document. Parameter documents are editable whereas definition documents are not. A parameter document can be saved as a definition document but a parameter document cannot be derived from a definition document.
A parameter document is an XML document with the filename suffix .pgpar.xml
.
In contrast to a parameter document in which some parameters of a pattern are selected randomly from a range of values, a definition document contains only the specific parameter values that define a pattern. Definition documents are immutable: they can be opened and saved by PatternGenerator but their content cannot be edited from within the application. A definition document can be thought of as a snapshot of a parameter document; it is likely to be useful only for capturing a "still" — a single image — from the animation of a pattern.
A definition document is an XML document with the filename suffix
.pgdef.xml
.
PatternGenerator can generate two kinds of pattern, which are named Pattern 1 and Pattern 2 by default. If you prefer names that are more imaginative or memorable, you can choose your own name for each kind of pattern.
Pattern 1 is an interference pattern. You may be familiar with interference patterns from science lessons at school, where they are customarily demonstrated with a ripple tank. If not, an example of a simple interference pattern is the pattern of waves that forms when you drop two stones into a still pond: the waves move away from the point sources — the stones — as concentric circles until the two sets of waves meet and interfere with one another.
The model for Pattern 1 is a set of one or more point sources from which waves propagate outwards along the plane of the image. The waves are transverse; that is, they oscillate perpendicular to the plane. If there are multiple point sources, the superposition of the waves from the different sources creates an interference pattern. The pattern is rendered by converting the combined amplitudes of the waves to colours.
A point source (hereafter abbreviated to source) has a virtual shape — circle, ellipse or regular polygon — that is imparted to the wave that propagates from it. Each source that you specify in the pattern parameters may be supplemented by symmetrical copies of the source, according to the symmetry parameter of the pattern. Depending on the kind of symmetry, there may be between zero and seven copies of each original source.
The following images are two examples of Pattern 1. The first image is a "classic" interference pattern with two point sources (one explicit source, near the top of the pattern, reflected in the vertical axis). The second, more ornate image has 24 point sources: three explicit sources, reflected in four axes.
Each source has some key attributes that are randomly generated: position, phase offset and (if the source is an ellipse or polygon) orientation. A Pattern 1 is animated by changing one or more of these attributes over time.
A Pattern 1 image is rendered by calculating the colour of each pixel of the image by as the sum of the values of the waves from all the sources at the location of the pixel. The calculation involves a lot of floating-point arithmetic beyond just adding a few values together: it includes, for example, a conversion from the HSB colour model to the RGB colour model, a conversion back to HSB, then a final conversion to RGB. The amount of arithmetic increases in proportion to the area of the image and the number of sources — including any implicit sources that result from symmetry. (The cost of the implicit sources is offset by not having to calculate pixel values for the symmetrical regions, though some arithmetic is done in transforming the principal area into its symmetrical copies.)
The upshot of all this arithmetic is that rendering a Pattern 1 image places a heavy load on the CPU, and the rendering time of an image of moderate size and complexity may be in the order of hundreds of milliseconds, even on a fast processor with multiple cores. (For example, a pattern of size 640×480, with four explicit sources and four-way symmetry takes about a quarter of a second to render on a machine with an Intel Core i5-2500K CPU, which has four cores and a clock rate of 3.3 GHz.) Long rendering times are likely to be particularly problematic for animations: an acceptable frame rate will be achievable only for small images with few sources. If you want to create a Pattern 1 animation with a video-quality frame rate (eg, 25 frames per second), your only option may be to export the pattern as a sequence of images with the File > Export image sequence command, then to generate a video from the images with a suitable tool (eg, FFmpeg).
If you are experimenting with a pattern and are finding that rendering is too slow, you could try reducing the size of the pattern while you experiment, restoring the pattern to its intended size once you've finished. When a pattern is generated from its parameters, the position of each source is randomly generated relative to the dimensions of the pattern, so you can reduce the size of the pattern and you'll get a scaled-down version of the original as long as you preserve its aspect ratio. (Of course, you can do this only if the width and height of the image have a common factor, as is the case with common video resolutions, though an aspect ratio that is close to that of the original may be good enough for a static image or a short animation.)
The Pattern 1 rendering algorithm uses multiple threads to improve efficiency on machines with multiple processors, but, because of the need to measure the minimum and maximum brightness of the image as a whole, it is split into two stages with a bottleneck — a barrier, in the terminology of computer science — between the two stages. (The barrier is absent if brightness is normalised with the Sequence > Optimise animation command.) You can control the number of threads that are used to render a Pattern 1 image with the pattern1.numRenderingThreads configuration property. If the value of the property is zero, the number of threads will be set to the number of processors that are available to the system.
When you create a new Pattern 1 with the File > New > Pattern 1 command or edit the parameters of a Pattern 1 with the Edit > Edit pattern parameters command, a dialog box is displayed in which you can specify the values or ranges of values of the pattern's parameters. The parameters of the static image are described in the following sections whereas the animation parameters are described in the section on animation.
The two Size spinners specify the width and height of the pattern image in pixels.
Each source that is listed in the table in the Sources panel may be supplemented by copies of the source according to the value of the symmetry parameter. If the shape of the source is an ellipse or polygon, the original orientation is transformed appropriately in the symmetrical copies.
The following figures show the effect of the various kinds of symmetry on a single source. The original source is shown as a red dot, the symmetrical copies as blue dots.
When a Pattern 1 is rendered, some of the processing of the colour value of each pixel is done with the HSB colour model. (HSB stands for hue, saturation and brightness. It's also known as HSV, where V stands for value.) The saturation component of a pixel's colour value is set in one of three ways, according to the saturation mode parameter:
Variable | The saturation value of a pixel is a combination of the saturation values of the waves from all sources at the pixel. The saturation value of each contributing source (ie, explicit sources and their copies) is specified by the source's colour (hue and saturation) parameter. |
Maximum | The saturation value of a pixel is always set to its maximum. |
Brightness | The saturation value of a pixel is set to the pixel's brightness value, which is the sum of the amplitudes (heights) of the waves from all sources at the pixel. |
The wavelength of a wave is the distance between successive repeats of the waveform:
The two spinners specify the lower and upper bounds of the wavelength range. The wavelength of each source is selected randomly from this range with a uniform distribution (ie, all values in the range have an equal probability of being selected).
This is the value that is used to initialise the pseudo-random number generator that provides random values for some parameters of a Pattern 1. (No random numbers are used in an animation of the pattern.) The seed can be any 18-digit number; each of the 1018 possible seeds gives a unique sequence of pseudo-random numbers, which will be the same every time the generator is initialised with a particular seed.
The Random command generates a "random" seed that is derived from the system time.
The table in the Sources panel lists the explicit point sources from which waves will propagate to create the pattern. Depending on the symmetry parameter, each explicit source may be supplemented by symmetrical copies. You can edit the list of sources with the commands that are issued by the buttons on the right of the table. The Add and Edit commands bring up a dialog box in which you can specify the parameters of a source. The components of the Source dialog are described below.
The Shape drop-down list selects the virtual shape of a source, which is imparted to the wave that propagates from it. A source can have the following shapes:
Circle | A circular source has no shape-specific parameter nor an orientation. |
Ellipse | The Eccentricity drop-down list selects the eccentricity of the ellipse, which is a measure of how elongated the ellipse is: the greater the eccentricity, the more elongated the ellipse. The parameter in the range 1..9 corresponds to an actual eccentricity of 0.1 .. 0.9. |
Polygon | A polygonal source generates a wave that is a regular polygon with between 3 and 12 edges (sides), as selected by the Number of edges drop-down list. |
The Waveform drop-down list selects the kind of waveform and the Wave coefficient spinner applies an arbitrary parameter to the waveform. A single period of the resulting wave is displayed in the panel above the two controls.
The Attenuation coefficient spinner specifies the rate at which the amplitude of a wave diminishes as it travels away from a source: the higher the coefficient, the greater the attenuation. The attenuation is linear.
The Constraint drop-down list selects a constraint that will be applied to the position of the source. The position of a source may be unconstrained, or it may be fixed to either the vertical or horizontal axis of the pattern.
The Hue and saturation panel contains controls that allow the hue (H) and saturation (S) components of a source's colour to be specified. The saturation value of all sources is ignored unless the value of the saturation mode parameter is variable.
A Pattern 1 image is animated by generating a sequence of images (frames) from the definition of the pattern by changing one or more of three attributes of each source — position, phase offset and orientation — from one frame to the next. (The orientation attribute is meaningful only for elliptical and polygonal sources.) In the dialog that is displayed when the Sequence > Start animation command is issued, you can choose which of the three attributes to include in the animation.
The three attributes of a Pattern 1 that can be animated are controlled by parameters that are specified in the Animation panel of the Pattern 1 parameters dialog. The value of each of the primary parameters — motion rate, phase increment and rotation period — is randomly selected from a specified range, and the values for each explicit source are selected independently.
An animation can be generated from the set of pattern parameters that are contained in a Pattern 1 parameter document, as you might expect, but there is also enough information in a Pattern 1 definition document to generate an animation because the animation does not require a source of random numbers. This has one notable consequence: if a definition document is created with the Create a document command while a Pattern 1 animation is paused, it can then be used to generate an animation.
Any frame of a Pattern 1 animation can be generated from the definition of the pattern without the need to generate intermediate frames, so that an animation can be started equally quickly from any frame in the sequence.
Animation of the position attribute is called motion as a shorthand for linear motion. If position animation is enabled, the position attribute of a source changes from frame to frame along a line from the original position to the edge of the pattern. When the source reaches the edge, it is reflected back into the pattern at an angle equal to the angle of incidence. The initial direction of motion is randomly selected when the pattern is generated, though directions that are parallel or almost parallel to the edges of the pattern are disallowed. The appropriate symmetry is applied to the directions of symmetrical copies of a source.
The rate of motion is selected randomly for each source from the range specified with the Motion rate spinners.
By default, the rate of motion is constant, but an envelope can be applied to the rate of every source. The envelope consists of linear segments and is periodic (ie, it is applied repeatedly at a specified interval). The envelope is enabled with the Motion rate envelope check box, and the envelope can be edited in the dialog that is displayed when the Edit command is issued from the button adjacent to the check box.
The main component in the Animation motion-rate envelope dialog is a plot of the envelope in which lines are drawn between successive pairs of envelope nodes. Below this are two fields for specifying the scale factors of the x and y axes of the envelope plot:
The nodes of an envelope can be edited with the left mouse button using tools that are selected from a context menu. The menu is invoked from within the envelope plot in a system-dependent manner (eg, with the right mouse button). The toolkit comprises the following tools:
Select | A node can be selected by clicking on it or moved by dragging it. This is the default tool. |
Draw | Clicking in the envelope area creates a new node. |
Erase | A node is removed by clicking on it. An envelope must have at least two nodes. |
Edit value | Clicking on a node brings up a dialog box in which the coordinate values of the node can be edited. |
An envelope can be used to create an emphasis at some point in a repeating interval by increasing the rate of motion of the sources at that point. For example, if an animation of a pattern were accompanied by a soundtrack consisting of a sequence of bars with a 4/4 time signature at a constant tempo, the snares on the upbeats of a bar could be emphasised with an envelope whose period was set to the duration of a bar and that had peaks at ¼ and ¾ of its length.
The phase increment is a value that is added to the phase offset attribute from one frame to the next. A changing phase offset gives the appearance that the wave is moving away from the source if the phase increment is positive or towards the source if the phase increment is negative.
The phase increment is selected randomly for each source from the range specified with the Phase increment spinners.
The scale of the phase increment is logarithmic, with sign inversion. Zero represents no increment, while -100 represents a positive increment of a quarter of a cycle (π/2) and 100 represents a negative increment of a quarter of a cycle (−π/2).
To make rendering a bit faster, phase animation may be disabled with the pattern1.phaseAnimation configuration property. If phase animation is disabled, this property may still be edited but it will have no effect.
Animation of the orientation attribute is called rotation, and it has meaning only for elliptical and polygonal sources. Rotation is achieved by changing the orientation of a source by a constant amount from one frame to the next, in either a clockwise or anticlockwise (counterclockwise) sense. The rotation period is the number of frames over which a source completes a full revolution.
The rotation period is selected randomly for each source from the range specified with the Rotation period spinners.
A rotation period in the specified range is generated by inverting the bounds of the range to give a range of rotation rates, then taking a uniformly distributed random sample from the rate range. The specified rotation sense — clockwise, anticlockwise or any (clockwise or anticlockwise, randomly selected) — is applied to the rotation rate.
Unlike Pattern 1, which can easily be classified, Pattern 2 does not belong to an obvious class; it can be described as a set of non-intersecting polygonal paths whose vertices and edges correspond to those of an isometric grid. In other words, the pattern consists of connected line segments drawn on a regular grid of equilateral triangles, although the grid itself is not visible.
Most of the parameters of a Pattern 2, such as the background colour and the thickness of paths, are specified by the user. The paths themselves are then generated randomly with the aim of covering all the edges of the grid with paths. The directions of a path's edges are constrained by a set of user-specified probabilities. The paths are generated by a heuristic — a greedy algorithm that quickly gives good but not optimal coverage of the grid. When the generation of paths has finished, any vertices of the grid that remain empty may optionally be filled with zero-length paths, which are drawn as discs.
The form of Pattern 2 is perhaps best illustrated by some examples; the following images are two examples of Pattern 2. The first image shows the essential aspects of Pattern 2: non-intersecting paths on an invisible isometric grid. The second image illustrates some features of Pattern 2: the ability to weight the probabilities of the directions of paths (in this example, there are no paths orthogonal to the image) and to emphasise terminal vertices (some of the ends of the paths are enlarged).
It will be apparent from the two examples that Pattern 2 doesn't offer much in the way of variety.
Pattern 2 images are drawn with the floating-point graphics methods of the Java runtime environment. The speed and quality of rendering will vary with the Java implementation. Depending on the Java implementation, the pattern2.pathRendering configuration property may allow you to modify the way in which paths are rendered.
A Pattern 2 image can be exported in vector graphics (SVG) format with the File > Export as SVG file command.
The invisible grid on which the paths are drawn may be oriented either vertically or horizontally, as shown in the images below. The orientation of the grid is a parameter of the pattern. The grid is composed of three sets of parallel lines at an angle of 60 degrees to each other — the grey lines in the images. One of these sets of lines may be either vertical or horizontal relative to the image; it is this set of lines that defines the orientation of the grid.
Vertical orientation | Horizontal orientation |
The edges of paths correspond to edges of the grid, and the vertices of paths correspond to the grid's vertices, which are at the intersections of the grey lines in the images. A vertically oriented grid may have vertical paths but not horizontal paths whereas a horizontally oriented grid may have horizontal paths but not vertical paths.
A Pattern 2 grid actually extends beyond the visible image: there is an invisible margin on each of the four sides of the image. The purpose of the margin is to improve the homogeneity of the image by hiding the terminal vertices of paths that are located at the periphery of the grid. The four margins are paired as end margins and side margins: the end margins are the top and bottom margins of a vertically oriented grid but the left and right margins of a horizontally oriented grid, and vice versa for the side margins. The size of each pair of margins is a parameter of the pattern. The unit size of a margin is the grid interval (major or minor), which is the distance between successive vertical or horizontal lines in the images above: the major interval is the distance between successive parallel grey lines and the minor interval is the distance between successive light blue lines.
When a Pattern 2 is rendered, the image is centered in relation to the grid so that the distances from the outermost vertices of the grid to the edges of the image are distributed evenly in both dimensions.
When you create a new Pattern 2 with the File > New > Pattern 2 command or edit the parameters of a Pattern 2 with the Edit > Edit pattern parameters command, a dialog box is displayed in which you can specify the values or ranges of values of the pattern's parameters. The parameters of the static image are described in the following sections whereas the animation parameters are described in the section on animation.
The two Size spinners specify the width and height of the pattern image in pixels.
The paths of a pattern have a notional forward direction, which is relevant when you assign relative probabilities to the directions of the edges of paths. The orientation parameter specifies the forward direction for paths and, implicitly, the orientation of the grid: if it is up or down, the grid is oriented vertically; if it is left or right, the grid is oriented horizontally.
The role of the margins is described in the section on the grid. If the pattern has a vertical orientation (up or down), the end margins are the top and bottom margins; if the pattern has a horizontal orientation (left or right), the end margins are the left and right margins. The units of the end margins are the minor grid interval.
The role of the margins is described in the section on the grid. If the pattern has a vertical orientation (up or down), the side margins are the left and right margins; if the pattern has a horizontal orientation (left or right), the side margins are the top and bottom margins. The units of the side margins are the major grid interval.
This parameter specifies the major grid interval: the distance between successive parallel lines of the grid. If the pattern has a vertical orientation (up or down), it's the distance between successive vertical lines; if the pattern has a horizontal orientation (left or right), it's the distance between successive horizontal lines. The units of the interval are pixels.
This parameter specifies the thickness of the paths in pixels.
This parameter is used by the first stage of the algorithm that generates paths. When the initial population of paths is generated, the length of each path is a random sample from a Poisson distribution that has this parameter as its λ value (the expected value of the distribution). The expected path length is only a guide for the algorithm; because of constraints on the actual lengths of paths and the effect of later stages of the algorithm on path lengths, there is no guarantee that the mean length of the paths will be close to the expected length.
An empty path is a path whose length is zero. Such paths arise in static (ie, non-animated) images as a result of a failure by the path-generation algorithm to extend any of the adjacent non-empty paths into an unoccupied vertex of the grid. They can arise in animated images when a path of length 1 shrinks. If this parameter is selected, empty paths are shown as discs (filled circles). For the purpose of terminal emphasis, an empty path is treated as though it had two terminal vertices at the same grid vertex.
The terminal vertices of paths can be emphasised by drawing discs (filled circles) of a specified diameter over them; the "emphasis" is supposed to occur if the diameter of the disc is greater than the thickness of the path. This parameter controls which of the terminal vertices will have discs drawn over them. The start and end of a path are determined by the notional forward direction of the pattern that is set with the orientation parameter.
This parameter specifies the diameter of the discs that are drawn over selected terminal vertices of paths. If the diameter of the disc is greater than the thickness of the path, the vertex appears to be emphasised. The units of the diameter are pixels.
This is the value that is used to initialise the pseudo-random number generator that provides random values for generating the paths of a Pattern 2 and for animating the paths. The seed can be any 18-digit number; each of the 1018 possible seeds gives a unique sequence of pseudo-random numbers, which will be the same every time the generator is initialised with a particular seed.
The Random command generates a "random" seed that is derived from the system time.
The components of the Colours panel allow you to specify the colours of the pattern: a single background colour and up to 40 path colours. The colour of a path is selected randomly from the set of available colours, with each colour having an equal probability of being chosen. You can weight the selection by setting multiple path colours to the same value (eg, by using the Set command).
The samples of the path colours are shown in buttons that are arranged in five rows. Clicking on one of the buttons (or pressing Space when the button has keyboard focus) will bring up a colour-selection dialog in which you can choose the path colour.
The selection of a colour-sample button can be toggled by clicking the left mouse button on it while the Ctrl key is pressed or by pressing Ctrl+Space when the button has keyboard focus. A selected button is drawn with an orange border. The button with a left-pointing double arrow to the right of each row of colour-sample buttons selects all the buttons in the row.
The four buttons to the right of the row-selection buttons issue commands that apply to the selected colours:
Set | The command brings up a colour-selection dialog in which you can choose a colour to which all the selected path colours will be set. |
Graduate | The command brings up a dialog with a colour-range panel in which you can choose a range of colours. The selected colours will be set to a gradation over the range: the first colour will be set to the first bound of the range, the last colour will be set to the second bound of the range, and the colours in between will be set to intermediate values (using the HSB colour model) such that the steps between successive colours are equal. |
Randomise | The command brings up a dialog with a colour-range panel in which you can choose a range of colours. The selected colours will be set to colours that are sampled randomly from the range with a uniform distribution, using the HSB colour model. |
Clear selection | The command deselects all the selected colours. |
Each edge (line segment) of a path has a direction, from its start vertex to its end vertex. Whenever an edge is generated, either during the initial generation of paths or when a path is lengthened during an animation, its direction is chosen by taking a random sample from the probability distribution that is specified in the Direction probabilities panel.
The probability distribution maps directions to probabilities. The directions may be either absolute or relative, depending on the value that you select from the Direction mode drop-down list:
Depending on the direction mode, there are five or six possible directions out of every grid vertex, and these directions are assigned weights that determine how likely it is that any particular direction will be chosen when an edge is added to a path. The weights, which are specified with spinners, are values between 0 and 100. The probabilities corresponding to the weights are displayed in a box below each spinner, and the set of probabilities is updated as you edit a weight. You can choose any set of weight values that will give you the desired probability distribution; for example, if you want a probability distribution of { 0.333, 0.333, 0.333, 0.0, 0.0, 0.0 }, you could choose the weights { 40, 40, 40, 0, 0, 0 }.
The spinners and their adjoining boxes are labelled with directions according to the following key:
FL | Forward-left |
F | Forward |
FR | Forward-right |
BL | Backward-left |
B | Backward |
BR | Backward-right |
Above the spinners, as an alternative means of editing the direction weights, is graphical representation of the weights in the form of bars within spokes that emanate from a hub. The arrangement of the spokes corresponds roughly to the arrangement of the spinners, the uppermost spoke being the forward direction. The weight for each direction can be changed by dragging the bar along its spoke with the mouse.
If the L-R symmetrical check box is selected, any change to the weight of one of the lateral directions (FL, FR, BL, BR) will be mirrored in the corresponding weight on the opposite side.
A Pattern 2 image is animated by generating a sequence of images (frames) from the definition of the pattern. In the sequence, the lengths of some of the paths change from one frame to the next: as one path lengthens, an adjacent path will become shorter to make room for its growing neighbour. The animation aims to maintain an active fraction of paths — paths that are growing or shrinking. On each frame, some currently inactive terminal vertices of paths may be randomly selected to grow by adding a new edge to the path at that vertex. An adjacent grid vertex is selected, subject to constraints on the direction of growth, as the new terminal vertex. The new terminal location will usually be occupied by the terminal vertex of another path, which will have to be shortened as the first path is lengthened. Over the next few frames, the selected path is lengthened in the direction of its new terminal vertex, and, if necessary, an adjacent path is correspondingly shortened.
Under some circumstances, a long path may be shortened or even split into two to reduce its potential to block the growth of neighbouring paths. If a path is shortened, an empty path is created at the grid vertex that was vacated.
Because of the frame-by-frame selection of paths for lengthening, an arbitrary frame of a Pattern 2 animation cannot be generated directly from the definition of the pattern; all of the previous frames must be generated too. Thus, in order to start a Pattern 2 animation at a specified frame, the application must "fast-forward" through the animation from the beginning by updating the state of the paths on each frame. (The procedure is called "fast-forward" because none of the intermediate frames is rendered.)
An animation can be generated from the set of pattern parameters that are contained in a Pattern 2 parameter document. However, there is not enough information in a Pattern 2 definition document to generate an animation because, in addition to the initial state of the paths, the animation requires a source of random numbers for selecting the paths whose length will be changed.
During an animation, a path is considered to be active while it is being lengthened or shortened; that is, if at least one of its terminal vertices is in transition between grid vertices. The active fraction parameter specifies the fraction of the total set of paths that should be active when the paths are updated on each frame. If the actual fraction of active paths falls below the desired value, the animation algorithm tries to select more paths for lengthening, though it may not be possible to achieve the desired fraction because of constraints on the lengthening of paths.
The Active fraction spinner specifies the fraction as a percentage of the total number of paths in the pattern.
The transition interval is the number of frames over which the transition of a terminal vertex of a path from one grid vertex to another occurs. When a terminal vertex is selected for lengthening — and, to make room for it, an adjacent terminal vertex of another path is selected to be shortened —, the transition interval is randomly selected from the range specified by the Transition interval spinners.
A Pattern 2 image can be exported in Scalable Vector Graphics (SVG) format with the File > Export as SVG file command. The exported SVG file has the following structure:
<g>
elements.
<path>
element and each terminal vertex by a <circle>
element.
fill
, stroke-width
, stroke-linecap
and
stroke-linejoin
properties of paths are set by applying common styles
from an internal CSS style sheet to all foreground <path>
elements.
<clipPath>
element.
The clipping of the paths to the bounds of the image can be removed by editing the the SVG file; either
clip-path
attribute from the foreground
<g>
element, or
PatternGenerator uses a tabbed document interface to display multiple documents. This kind of interface has a single tabbed window in which only one document — referred to as the current document — is visible at any one time. You can select a document by clicking on its tab, or you can select a document from the alphabetically ordered list that is displayed by clicking on the down-arrow button at the right of the tab bar. You can move between documents by pressing Ctrl+PageUp and Ctrl+PageDown.
The main window can be resized in a platform-dependent manner (eg, by dragging a corner of the window). It can also be resized to the image of the current document with the View > Resize window to image command.
A slide show or an animation is displayed in a sequence window. When a Sequence > Start slide show or Sequence > Start animation command is issued, the main window is hidden and a sequence window is displayed. When a sequence is stopped, the sequence window disappears and the main window is made visible again.
A sequence window has no frame. It can be moved by dragging it with the mouse cursor while the left mouse button is pressed.
The window may be kept on top of the windows of other applications if this is supported by the platform, or it may behave like a normal window in allowing other windows to lie above it. This behaviour is controlled by the general.keepSequenceWindowOnTop configuration property.
At the bottom of the sequence window is a control panel that is visible when the mouse cursor hovers over the area of the control panel or when the sequence is paused. The control panel has three buttons for issuing commands, only two of which are available at any one time: the Pause and Stop commands are available when a sequence is playing; the Play and Stop commands are available when a sequence is paused. The commands are also accessible from a context menu that is displayed in a platform-dependent manner (eg, by clicking the right mouse button).
While the sequence is paused, the context menu of the sequence window has a command, Create a document (Ctrl+D), that creates a definition document from the current image in the sequence. This command can be used to take a snapshot of a particular frame of an animation.
Dialog boxes are displayed in response to some of PatternGenerator's commands. Some of the dialogs contain non-standard graphical components or standard components that have unusual features.
A spinner is a graphical component for editing a numerical value. It consists of a text field adjacent to a pair of small buttons. The value in the text field may be edited manually, or it may be incremented and decremented by one of the following methods:
Using the last two methods, the amount by which the value is incremented or decremented can be modified by holding down the Ctrl, Shift or Ctrl+Shift keys, which correspond to increments of 10, 100 and 1000 respectively.
A slider is a graphical component for editing a numerical value. It is usually located adjacent to a spinner as an alternative means of editing the spinner's value. The position of the slider is controlled with a knob, which is usually hidden but appears when the mouse cursor is in the region of the position marker.
The slider value may be edited by using the left mouse button. If the left button is pressed when the mouse cursor is within the knob, the knob can be dragged; otherwise, if the left button is pressed when the mouse cursor is inside the border of the slider, the knob is moved to the mouse cursor, and the knob can be then dragged. The slider value may be edited with the arrow keys when the slider has keyboard focus:
Left | Decrement the value by one unit |
Ctrl+Left | Decrement the value by one block |
Home | Set the value to its minimum |
Right | Increment the value by one unit |
Ctrl+Right | Increment the value by one block |
End | Set the value to its maximum |
A range bar is a graphical component for editing a pair of numerical values — a lower bound and an upper bound — that denote a range. It is usually invoked with a button adjacent to a pair of spinners for the two bounds, and it is displayed in a small, frameless dialog box consisting of a horizontal bar with arrowheads above and below it to indicate the upper and lower bounds respectively, and a button to the right of the bar that closes the dialog. The dialog is modal, so it is not possible to edit the bounds in the spinners while the range bar is displayed.
In the range-bar dialog, the lower and upper bounds may be edited by clicking or dragging the left mouse button over the range bar. The bounds may be edited with the arrow keys:
Left | Decrement the lower bound by one unit |
Ctrl+Left | Decrement the lower bound by one block |
Right | Increment the lower bound by one unit |
Ctrl+Right | Increment the lower bound by one block |
Down | Decrement the upper bound by one unit |
Ctrl+Down | Decrement the upper bound by one block |
Up | Increment the upper bound by one unit |
Ctrl+Down | Increment the upper bound by one block |
A colour-range panel is a graphical component for editing a range of colour values. The panel uses the HSB colour model to represent the colours in the range, which is specified as two hue–saturation pairs for the bounds along with an overall brightness value.
The panel is displayed in response to two commands in the Pattern2 parameters dialog. It is described here because it has some unusual behaviour.
The panel consists of a colour area and some spinners for editing the colour components. There are two sets of components for the hue and saturation of the two range bounds. The spinners for both bounds are permanently enabled, but one bound — the primary bound — is selected with the radio buttons to the left of the spinners, labelled Bound 1 and Bound 2.
The colour area is a representation of two revolutions of the curved surface of a cylinder; its horizontal dimension represents hue and its vertical dimension represents saturation. The duplicated portion of the area avoids the need for scrolling when the range wraps around in the hue dimension. The range is shown in the colour area as a rectangle that degenerates to a single pixel when the two bounds are equal. The range is controlled with the mouse buttons: the left button controls the primary bound and the right button controls the secondary bound. (The primary bound is selected with the radio buttons adjacent to the hue and saturation spinners.) As a result of the duplication of the hue dimension in the colour area, the tracking of mouse movements by the horizontal dimension of the range rectangle is rather strange, and it may take you a while to get used to it.
PatternGenerator's main commands are accessible from its main menu. Some of the commands are also accessible from a pop-up menu that is activated in a system-dependent manner (eg, by pressing or releasing the right mouse button) while the mouse cursor is over a pattern view of an open document.
The New command creates a new pattern via a subcommand for each kind of pattern. The subcommand brings up a dialog in which the parameters for the selected kind of pattern can be edited. A pattern will be generated from the parameters, and an image will be rendered and displayed in a new tab within the main window.
The document that is created by the New command is a parameter document.
The command is disabled if the maximum number of documents are open in the application.
The Open file command (Ctrl+O) brings up a file-selection dialog in which you can choose the file that you want to open. You can open either a parameter document or a definition document by first selecting the appropriate file type. If the document has the correct format, the document is loaded, a pattern image is generated and displayed in a new tab within the main window.
If you select a file that is already open in PatternGenerator, the file is not opened again. You can use the Revert file command to reload a file that is already open, discarding any changes.
The initial file type in the file-selection dialog is set from the general.defaultDocumentKind configuration property.
The command is disabled if the maximum number of documents are open in the application.
The Revert file command reads the current document again from the file system, replacing the modified document in PatternGenerator. Any changes that you have made to the current document will be lost.
The command is disabled if the current document has not changed from when it was last opened or saved.
The Close file command (Ctrl+W) closes the current document. If the document has unsaved changes, you will be prompted to save the document before it is closed.
The Close all files command closes all open documents. You will be prompted to save any documents that have unsaved changes.
The Save file command (Ctrl+S) writes the current document to a file. The kind of document (parameter or definition) and the pathname of the file will be those that were selected when the document was last opened or saved.
The command is disabled if the current document has not changed from when it was last opened or saved.
The Save file as command brings up a dialog in which you can choose the kind of document that will be saved and the file to which the document will be written.
You can choose the kind of document that will be saved by selecting from the available file types in the file-selection dialog. A parameter document can be saved as either a parameter document or a definition document but a definition document can be saved only as a definition document because it has no parameters. If you do not specify a file type in the dialog, the document is saved as its inherent kind.
Before a file is written, a warning is displayed if the selected file already exists.
The Export image command (Ctrl+E) exports the current document as a PNG image file. The command brings up a dialog in which you select the file to which the image will be written.
The Export image sequence command (Ctrl+Shift+E) exports an animation of the current document as a sequence of PNG image files that can be used to create a video with a tool such as FFmpeg.
The command brings up a dialog in which you specify some parameters for the image sequence:
.png
will be appended to form the filename. For example, if the filename stem were
myVideo
and a sequence of 3000 image files were generated, the files
would be named myVideo0000.png
, myVideo0001.png
…
myVideo2999.png
.
The output files are numbered from zero, which is what is expected by FFmpeg.
The Export as SVG file command exports the current document as a Scalable Vector Graphics (SVG) file. The command is supported only by Pattern 2, which is a vector-based pattern. The command brings up a dialog in which you select the file to which the SVG image will be written.
The Exit command terminates the application. Before the program shuts down, you will be prompted to save any open documents that have unsaved changes.
The edits that you make to a document — the changes that you make to a document's parameters or description — can be undone and redone. The edits to a document are stored in a list called the document's history. The length of this list is limited by the general.maxEditListLength configuration property. The edits that are stored in a document's history are those made with the following commands:
The Undo command reverses the last change to the current document.
If an edit is undone with the Undo command, it can
subsequently be restored with the Redo command provided
that no other edits have been made since it was undone. If general.clearEditListOnSave configuration
property is true
, the history of edits is cleared when a document is saved.
The Clear edit history command clears the history of edits to the current document. The command may be used to make more memory available if a "Not enough memory" error occurs.
If the current document is a parameter document, the Edit pattern parameters command (Ctrl+P) brings up a dialog box in which the document's parameters can be edited. The parameter dialogs are described in the sections on Pattern 1 parameters and Pattern 2 parameters.
The Edit description command (Ctrl+D) brings up a dialog box in which the document's description can be edited. The description applies to both parameter documents and definition documents.
If the current document is a parameter document, the Regenerate pattern with new seed command (F5) sets the document's seed to a new, random value and regenerates the pattern using the new seed. The new seed that is generated for each invocation of this command is virtually certain to be different from previous seeds. Thus, if you issue this command on the same parameter document on two occasions, you'll get a different pattern on each occasion.
The Show image rendering time command (Ctrl+T) brings up a dialog box in which the mean rendering time for the current document is displayed. The rendering time is shown as nanoseconds per pixel. The time is updated when a pattern is regenerated. In the Image rendering time dialog, the Reset command resets the mean rendering time for the current document.
The Start slide show command (F6), which is enabled only if the current document is a parameter document, starts an automated sequence of images in which each image is generated from the pattern parameters with a new, randomly generated seed. The sequence is equivalent to issuing a sequence of Regenerate pattern with new seed commands. The sequence of seeds that are generated for each invocation of the Start slide show command is virtually certain to be different from any previous sequence, so each slide show will be unique.
The command first brings up a dialog box in which parameters that affect a slide show can be edited. There is only one parameter: the interval between successive images (ie, the length of time for which each image is displayed).
The images of a slide show are displayed in a sequence window. When a slide show is paused, the index of the current image in the sequence is displayed in the top left corner of the sequence window. While a slide show is paused, the Create a document command from the context menu of the sequence window (Ctrl+D) will create a new definition document from the current image.
After a slide show is stopped, the sequence window disappears and the image of the document in the main window is updated with the last image of the slide show. The Edit > Undo and Edit > Redo commands can then be used to step backwards and forwards through the images in the slide show, up to the limit imposed by the general.maxEditListLength configuration property.
The Start animation command (F7) starts an animation of the current document. The way in which a pattern is animated is described in the sections on Pattern 1 animation and Pattern 2 animation.
The command first brings up a dialog box in which parameters that affect an animation can be edited. The number of parameters differ according to the pattern kind:
In the Animation kinds panel for a Pattern 1 document,
the Phase option is disabled if the pattern1.phaseAnimation
configuration property is false
. Each option can be toggled with a key
press:
Position | 1 |
Phase | 2 |
Orientation | 3 |
If the current document is a Pattern 2 document and the first frame of the animation (see Edit animation parameters) is not zero, a progress dialog will be displayed while PatternGenerator fast-forwards to the first frame.
The rate at which animation frames are generated and the index of the first frame to be displayed can be set with the Edit animation parameters command.
The frames of an animation are displayed in a sequence window. When an animation is paused, the absolute index of the current frame is displayed in the top left corner of the sequence window. While an animation is paused, the Create a document command from the context menu of the sequence window (Ctrl+D) will create a new definition document from the current frame.
The Optimise animation command (Ctrl+F7) is enabled only for Pattern 1 documents. There is only one available optimisation: the smoothing of transitions in brightness between animation frames.
By default, the brightness values of the pixels of a Pattern 1 image are scaled to give the widest possible range of brightness (ie, the brightest pixel of the image has the maximum brightness value and the dullest pixel has the minimum brightness value). This is desirable when rendering a single image, but it can result in unwanted shifts in brightness between successive frames of an animation as the maximum and minimum values change. Instead of performing the scaling using the brightest and dullest pixels of a single image, the optimisation measures the maximum and minimum brightness over a range of images (the sample) and uses the resulting interval when rendering all the frames of a subsequent animation.
There are two problems with the normalisation of brightness:
For each document, PatternGenerator maintains a mapping from a set of animation aspects and a first frame to a brightness range. The keys of this mapping — the set of animation aspects and first frames for which a brightness range has been recorded — are displayed in the table at the top of the Normalise animation brightness dialog. In this dialog, the parameters have the same meaning as those in the Animation parameters dialog that is displayed in response to the Start animation command, and the following commands are available:
The Resize window to image command (F12) sets the size of the main window so that its viewport is the same size of the image of the current document, though the width and height of the viewport cannot be smaller than 128 pixels and 64 pixels respectively.
The Preferences command brings up a tabbed dialog box in which the configuration properties of PatternGenerator can be edited. The properties on the various tabbed pages are described below.
Parameters
.
Yes
, pathnames are displayed in a reduced
"UNIX style" in some parts of the GUI. A pathname is converted from
its platform-specific form in two steps:
~
.
\
on Windows systems) is replaced
by /
.
No
.
Yes
, all the text in a text field will be
automatically selected when the field gains keyboard focus, regardless of how
the focus is transferred.
Yes
.
Yes
, the location of the main window on the screen
will be saved to the configuration file when you exit the application. The next
time that PatternGenerator is run, its main window will be positioned at the
previously saved location.
No
.
Yes
, a document's history of edits (see Edit > Undo/Redo) is cleared when
the document is saved.
No
.
Yes
, PatternGenerator tries to keep a sequence window (the window in which a slide show or
animation is displayed) on top of windows that belong to other applications.
The ability to keep the animation window on top of other windows is
platform-dependent.
Yes
.
awt.useSystemAAFontSettings
.
Default
.
Pattern 1
.
Yes
, the phase of each point source can
be animated in addition to the other two animation parameters (source location
and orientation). A source's wave table is generated and used in different
ways according to whether phase animation is enabled or disabled. If you select
No
, pattern images are rendered slightly faster than if phase
animation is enabled, but the small improvement in performance is likely to be
worthwhile only in rare circumstances.
Yes
.
Pattern 2
.
Pure
.
Some of the configuration properties will take effect when the Preferences dialog is accepted (by closing it with OK); other properties (eg, the look-and-feel and fonts) will not take effect until the next time that PatternGenerator is run.
The configuration file is normally saved automatically when PatternGenerator exits, if the configuration has changed. The Save configuration command in the Preferences dialog can be used to save a configuration file explicitly.
The Show full pathnames option controls whether the full pathname of the current document or only its filename is displayed in the title bar of the main window.
Where indicated elsewhere in this document, pathname parameters and properties in PatternGenerator can contain special constructs for system properties, environment variables and the user's home directory. The special constructs are expanded when the pathname is used.
user.home
)
and environment variables (eg, PATH
) are referenced by enclosing them
between ${
and }
; that is, they must have the form
${<name>}
. A Java system property takes precedence over an
environment variable with the same name.
${user.home}/projects
${HOME}/projects
sys.
to it.
${sys.user.home}/projects
env.
to it.
${env.HOME}/projects
~
in a pathname is expanded into the user's home directory
using the user.home
system property, which is usually equivalent to the
environment variable $HOME
on Linux/UNIX systems or
%USERPROFILE%
on Windows systems.
~/projects
The table below lists the configuration properties of PatternGenerator. Apart from the app.configDir property, which, for obvious reasons, cannot be used within a configuration file, all properties can be used in the two configuration locations: command-line properties and configuration file.
When used in a -D
command-line property, app.
must be prefixed
to the property key (eg, app.general.mainWindowLocation).
Any commas (,
) or backslash characters (\
) in the name of a
font must be escaped by prefixing a \
character to them.
In the table below, the initial character of an italicised component of a property value denotes its data type according to the following convention:
f | floating-point number |
i | integer |
p | platform-specific pathname, which may contain special constructs |
s | string |
Property key | Property value |
---|---|
configDir | pPathname |
animation.rate | fFramesPerSecond |
appearance.lookAndFeel | sName |
appearance.textAntialiasing | default | none | normal | subpixelHRgb | subpixelHBgr | subpixelVRgb | subpixelVBgr |
font.comboBox | sName, plain | bold | italic | boldItalic, iSize |
font.main | sName, plain | bold | italic | boldItalic, iSize |
font.scale | sName, plain | bold | italic | boldItalic, iSize |
font.textField | sName, plain | bold | italic | boldItalic, iSize |
general.clearEditListOnSave | false | true |
general.defaultDocumentKind | definition | parameters |
general.keepSequenceWindowOnTop | false | true |
general.ignoreFilenameCase | false | true |
general.mainWindowLocation | iX, iY |
general.mainWindowSize | iWidth, iHeight |
general.maxEditListLength | iLength |
general.selectTextOnFocusGained | false | true |
general.showFullPathnames | false | true |
general.showUnixPathnames | false | true |
path.exportImageDirectory | pPathname |
path.exportImageSequenceDirectory | pPathname |
path.exportSvgDirectory | pPathname |
path.openPatternDirectory | pPathname |
path.savePatternDirectory | pPathname |
pattern.name.pattern1 | sName |
pattern.name.pattern2 | sName |
pattern.defaultSize.pattern1 | iWidth, iHeight |
pattern.defaultSize.pattern2 | iWidth, iHeight |
pattern.numSlideShowThreads.pattern1 | iNumThreads |
pattern.numSlideShowThreads.pattern2 | iNumThreads |
pattern1.numRenderingThreads | iNumThreads |
pattern1.phaseAnimation | false | true |
pattern2.pathRendering | pure | normalised |
slideShow.interval | iSeconds |