| Name | Last modified | Size | Description | |
|---|---|---|---|---|
| Parent Directory | - | |||
| 3d/ | 2025-11-15 17:10 | - | ||
| COLOURS/ | 2025-11-15 17:10 | - | ||
| EFFECTS/ | 2025-11-15 13:33 | - | ||
| Messages/ | 2025-11-15 13:33 | - | ||
| art.zip | 2025-11-15 17:23 | 83M | ||
| art/ | 2025-11-15 17:10 | - | ||
| art_no_data.zip | 2025-11-15 17:23 | 4.3M | ||
| colourspace/ | 2025-11-15 17:10 | - | ||
| components/ | 2025-11-15 17:10 | - | ||
| config/ | 2025-11-15 13:33 | - | ||
| core/ | 2025-11-15 17:10 | - | ||
| data.zip | 2025-11-15 17:23 | 51M | ||
| data/ | 2025-11-15 17:10 | - | ||
| dependencies | 2025-11-15 13:34 | 102K | ||
| documentation.zip | 2025-11-15 17:24 | 2.7M | ||
| documentation/ | 2025-11-15 16:20 | - | ||
| examples/ | 2025-11-15 17:10 | - | ||
| forhumans/ | 2025-10-07 09:32 | - | ||
| geo/ | 2025-11-15 17:10 | - | ||
| image/ | 2025-11-15 17:10 | - | ||
| lib/ | 2025-11-15 13:37 | - | ||
| libs.zip | 2025-11-15 17:24 | 25M | ||
| makefile | 2025-11-15 13:33 | 24K | ||
| math/ | 2025-11-15 14:55 | - | ||
| music/ | 2025-11-15 17:10 | - | ||
| noise/ | 2025-11-15 17:10 | - | ||
| sdf/ | 2025-11-15 17:10 | - | ||
| shapes/ | 2025-11-15 17:10 | - | ||
| string/ | 2025-11-15 17:10 | - | ||
| structures/ | 2025-11-15 14:55 | - | ||
| svg/ | 2025-11-15 17:10 | - | ||
| tests/ | 2025-11-15 14:55 | - | ||
| tiling/ | 2025-11-15 17:10 | - | ||
| types/ | 2025-11-15 17:10 | - | ||
| wfc/ | 2025-11-15 17:10 | - | ||
API documentation is available in the documentation) subdirectory. There are also api.html documents in some subdirectories, e.g. string/api.html, which provide summary information but have been mostly superceded by the generated API documentation.
The code here is generally licensed as CC-BY (https://creativecommons.org/licenses/by/4.0/).
Attribution should be to Mary Holstege and include a link to the code base at http://mathling.com/code/
Some of the same data is based on WordNet 3.0® and is made available under that license (see data directory). The UnicodeData.txt file is made available under the Unicode data license (see data directory).
The noise code is a port of noise-rs which is used under an MIT License (see noise directory).
Much of the colour space conversion code is a port of hsluv-c which is used under an MIT License (see colourspace directory).
Much of the SDF code is based in part on code from Inigo Quilez which is used under an MIT License with some operators from Karsten Schmidt which is used under an Apache license, and a few details from Electric Square Ltd., also under and MIT License (see sdf directory).
The gradients are based on gradient definitions from a variety of sources used under MIT, BSD, and CC Licenses (see COLOURS directory).
The Wave Function Collapse algorithm is a port of the WFC code, which is used under an MIT license. See wfc directory.
The Hyphae component is based on a port of Anders Hoff's Hyphae, which is used under an MIT license.
Some of the shape fills are based on ideas from Preet Shihn's rough.js library, which is used under an MIT license.
The Hobby splines are based on code ported and adapted from Jake Low's hobby.js licence, used under an ISC license. See geo/spline.xqy.
UnicodeData.txt is version 15.1.0 and used subject to Unicode license. See data/Unicode_license.txt.
oeis.stripped.txt is from the Online Encyclopedia of Integer Sequences as of 2025/04/07 and is used subject to the OEIS End-User License Agreement. See data/OEIS-LICENSE.txt.
Some of the operations depend on Java extensions provided by Saxon. They will not work with other processors.
PNG image operations depend on various Java libraries (java.io, javax.imageio, java.awt). These classes are part of the Java runtime environment.
IXML operations depend on Normal Walsh's NineML CoffeeSacks (and CoffeePot) version 3.2.9. See structures subdirectory. These libraries are available in the lib subdirectory, subject to an MIT license.
An alternative implementation of IXML operations depends on Gunther Rademacher's MarkupBlitz, which is Copyright (c) 2023-2025 Gunther Rademacher, and is available under the Apache license. See structures subdirectory.
Some of the mathematical operations depend on Apache Commons Math version 3.6.1. See math subdirectory. These libraries are available in the lib subdirectory, subject to the Apache License.
Many of the libraries have maker functions associated with them, marked with the art:maker annotation. These are intended for use with the text interface driver (still a work-in-progress and not currently part of the release). They provide a standardized callback interface for making things and generally provide a limited set of heavily defaulted options. They can be called directly, and can provide examples of how to use some of the APIs. All these functions are bleeding edge, and the details of the interfaces are certainly subject to some change.
The maker functions come in three basic signatures: direct makers, contextual makers, and relationship makers.
Direct makers make something directly. The signature is:
direct-maker(
$dynamics as map(xs:string,item()*),
$canvas as map(xs:string,item()*),
$randomizers as map(xs:string,item()*),
$parameters as map(xs:string,item()*)
) as map(xs:string,item()*)*
The parameters are:
$dynamics: dynamic parameters setting standard and non-standard options$canvas: drawing space$randomizers: active randomizers for component$parameters: active parameters for componentContextual makers modify something or make something new from it. The signature is:
contextual-maker(
$context as map(xs:string,item()*)*,
$dynamics as map(xs:string,item()*),
$canvas as map(xs:string,item()*),
$randomizers as map(xs:string,item()*),
$parameters as map(xs:string,item()*)
) as map(xs:string,item()*)*
The parameters are the same except for the context:
$context: context objects for the maker$dynamics: dynamic parameters setting standard and non-standard options$canvas: drawing space$randomizers: active randomizers for component$parameters: active parameters for componentRelationship makers combine two things something or make something new. The signature is:
contextual-maker(
$base as map(xs:string,item()*)*,
$related as map(xs:string,item()*)*,
$dynamics as map(xs:string,item()*),
$canvas as map(xs:string,item()*),
$randomizers as map(xs:string,item()*),
$parameters as map(xs:string,item()*)
) as map(xs:string,item()*)*
The parameters are the same except for the base and related group:
$base: base context objects for the maker$related: related context objects for the maker$dynamics: dynamic parameters setting standard and non-standard options$canvas: drawing space$randomizers: active randomizers for component$parameters: active parameters for componentThe canvas, randomizers, and parameters are the standard triad present in all components. The dynamic parameters include special options for the specific maker as well as several standard options. The makers do not require any of the standard options.
"use": What kind of object is being made?
"thing": something to draw (or a collection of things)"space": a space to draw something into (or a collection of spaces)"location": a place to draw something at (or a collection of locations)"modifier": for contextual makers; something that alters an object"decorator": for contextual makers; something that is added to an object"gender": Dimensionality, to indicate whether colour applies to bounds or areas
"zone": treat as an area, so a red circle(zone) is red-filled"stroke": treat as a line, so a red circle(stroke) is a red boundary"neutral" (default): apply default treatment"size": exact sizing of the thing/space in pixels; if present should be no "scaling""scaling": relative size of the object to the canvas; if present should be no "size""location": point representing where the object should be drawn"colour": colour of the object"opacity": opacity of the object"width": line widthThis release is largely an accumulation of some small bug fixes. The major change is the integration of Markup Blitz for Invisible XML processing, and a reshuffling of those APIs to allow for the selection of processor. Currently CoffeeSacks and Markup Blitz are supported. Libraries are included, although it is up to you to include the right options when you invoke Saxon. See the makefile for examples. Markup Blitz is generally much faster and scales better, due to the separation of tokenization and parsing, but CoffeePot provides more control and better debugging capabilities.
This release also adds full text search to the website, encompassing the documentation as well.
Incompatibilities
Invisible XML (structures/ixml-blitz.xqy)
Math
stats:quantile(), stats:quantile-range() to compute weighted or unweighted quantile selections for a given fraction (math/statistics.xqy)mmath:close() to test whether values are within epsilon of each other (math/math.xqy)binary:is-power-of-two() to test whether integer is a power of two (core/binary.xqy)seq:rotate() now handles negative offsets as rotation from end (core/sequences.xqy)Colours and rendering (svg/gradients.xqy)
rgb:to-int-v to return integer RGB value from vector form of RGB point (colourspace/rgb.xqy)gradient:random() not applying exclusion properlygradient:gradient-sample() produces bad gradients with small gradients and high limitsgradient:colours("X-reverse") double-reversed* New function `geom:trace()` which can chain with other operations to provide intermediate tracing using descriptions of geometric objects
* `path:reverse()` now takes sequence of paths, the better to chain operations ([geo/path.xqy](https://mathling.com/code/art/documentation/geo/path.xqy.html))
* Aesthetic: arc edge end-points get snapped when when translating edge
* Adjustment to the logic of swapping in edge normalization
* Bug: `edge:chop()` sometimes computes incorrect splits ([geo/edge.xqy](https://mathling.com/code/art/documentation/geo/edge.xqy.html))
* Bug: `geom:as-polygon()` dropping properties
* Bug: incorrect calculation of tangent vectors on ellipses ([geo/ellipse.xqy](https://mathling.com/code/art/documentation/geo/ellipse.xqy.html))
* Add offset adjustment parameter to `fonts:text-as-glyphs()`
* Bug: mishandling of font lookup for characters in FF-FFF range
* Add `component-map()` method to all components to simplify their use
Incompatibilities
shapes:scale-and-plaster() renamed to shapes:scale-and-plaster-solid() to accommodate new shapes:scale-and-plaster() function applied to faces (shapes/shapes.xqy)gradient:random-gradient() (svg/gradients.xqy)seq:extend-repeat() on all partial sequences (e.g. Katydid) in seq:sequence() (math/sequences.xqy)New modules
Math, sequences (math/math.xqy and math/sequences.xqy)
seq:odds(), seq:evens(), seq:extend-repeat()seq:oeis-random-sequence(), seq:random-limited-oeis-sequence(), seq:oeis-sequence(), and in seq:sequence()mmath:rpow(), mmath:fpow(), mmath:modix-diff()Randomizers (core/random.xqy and types/distributions.xqy)
rand2:random-polar-points-on()dist:ceiling(), dist:resample(), dist:drop()dist:uniform-centered(), dist:normal-centered()Rendering and colouring (svg/gradients.xqy and svg/draw.xqy and art/draw.xqy)
gradient:any-random-gradient()gradient:luminance-range() to avoid overruns on colour valuesrgb:named-colour() as RGBA(0,0,0,0) (colourspace/rgb.xqy)point:destination() shouldn't lose Z values in 3D pointspoints:destination(), shape:scale-and-center()svg:draw() and art:draw()effect:colour() needs to rotate through colour sequence (svg/effects.xqy)Miscellaneous new features and functions
shapes:scale-and-plaster() to apply to faces (shapes/shapes.xqy)path:consolidate-all(), path:consolidate-all-points(); specific consolidation functions deprecated (geo/path.xqy)path:points-on() for fadespath:ngon()knot:extend() to extend paths to ribbons (components/knots.xqy)patterns:wave() (shapes/patterns.xqy)fills:irregular-hachure-lines(), fills:irregular-crosshatch(), fills:irregular-zigzags(), fills:irregular-star() (shapes/fills.xqy)grids:right-straight(), grids:left-straight(), grids:hex-coordinates() (shapes/grids.xqy)paths:reverse-circle-spiral() (shapes/paths.xqy)backgrounds:crisscross() (components/backgrounds.xqy)solid:as-face() (geo/solid.xqy)Miscellaneous fixes and enhancements
file:resolve-path() when loading STL files (stl/stl.xqy)geom:bounding-box() (geo/euclidean.xqy)path:same() should return false() rather than error if number of edges different (geo/path.xqy)conrec:as-path() for closing off polygons (geo/conrec.xqy)conrec:extent()grids:down-left() (shapes/grids.xqy)This release includes some major (incompatible) restructuring of the core libraries: various libraries have been moved from core to math and many of the functions in "http://mathling.com/core/utilities" (core/utilities.xqy) have been moved to new libraries. There are some new advanced mathematic capabilities, various drawing components, and more capable colouring and rendering.
Incompatibilities
is-prime(), logK(), log2(), decimal(), round(), trunc(), factorial(), binomial(), modix(), twixt(), clamp(), clamp-some(), sign(), zsign(), cbrt(), smoothstep(), mix(), intmix(), hypermix(), expmix(), remap(), intremap(), radians(), degrees(), remap-radians(), remap-degrees(), cos(), sinh(), cosh(), asinh(), and acosh(). The functions decimal(), round(), modix(), twixt(), clamp(), mix(), and intmix() remain, but are deprecated and will be removed in a later release.unsignedLong(), xor(), or(), and(), lshift(), rshift(), count-bits(), count-digits(), bits-to-integer(), integer-to-bits(), as-base(), hex-to-integer(), integer-to-hex()core:do-randomize() has been moved to rand:random-value() (core/random.xqy)rgb:to-int() now produces 32 bit integer values values compatible with PNGs (colourspace/rgb.xqy)New modules
Colouring and rendering (svg/gradients.xqy) (svg/draw.xqy) (art/draw.xqy)
draw:draw() for 3D renderingdraw:projection-draw()rgb:to-int() to produce 32 bit values compatible with PNGs (colourspace/rgb.xqy)pens:colour(), pens:colour-at(), pens:constant-colour(), pens:fade-colour(), pens:taper-colour(), pens:wobble-colour() (shapes/pens.xqy)solids:crystal(), solids:divide-body(), solids:divide-faces(), solids:divide-base() (shapes/solids.xqy)gradient:gradient-offset()Geometric (geo/index.html)
geom:bounding-box(), geom:bounding-circle()edge:angle-between(), path:remove-useless(), path:angle(), path:inclination(), coord:hyperbolic()simplify:regions() and simplify:convex-hull() which improved region findingpath:chaikin()path:normalize()arf:layout-as-graph()box:quote() repeating box parameters multiple timesMiscellaneous bugs and improvements
util:doc(), util:unparsed-text(), util:unparsed-text-lines() to control whether to warn or not (core/utilities.xqy)util:context-filter(), util:context-map(), util:for-each() (core/utilities.xqy)array:outer(), array:is-zero(), array:is-identity(), array:is-tridiagonal(), array:is-upper-triangular(), array:is-lower-triangular(), array:is-singular() plus array:vector() and matrix:as-array() (core/array.xqy) (core/matrix.xqy)curves:polar-plot(), paths:round(), gradient:gradient-offset(), `bin:i32()cf:mixed-function() (components/complex-functions.xqy)paths:extended-star() output (shapes/paths.xqy)fonts:length() and fonts:text-as-glyphs() (components/fonts.xqy)$errors:QUOTE-LIMIT to 200 (core/config.xqy)speckles.prune option to remove out-of-canvas speckles (components/speckles.xqy)This release includes a lot of work on the experimental maker functions: reworking handling of some of the dynamic parameters, adding more maker functions, and adding a new class maker function for relationships. The experimentation with the art shell (not released) that is driving this work has also produced a number of new modules. There are also some follow-up bug fixes from the change to default 3D rendering.
Documentation improvements
Incompatibilities
background:border() renamed to background:frame() (components/backgrounds.xqy)util:repeat() (core/utilities.xqy)string:capitalize() lowercases non-initial letters (core/string.xqy)New modules:
Rendering
shapes:scale-and-center(), shapes:fitting-scale-and-center(), and shapes:center() to take either a flat space or a block and adjust either 2D or 3DGeometry (geo/euclidean.xqy)
geom:bounding-block(), geom:points-on(), geom:flatten(), geom:process-polygonlike(), geom:process-pathlike()path:subsegments(), path:has-segments() to break paths into subsegments (geo/path.xqy)edge:end() as settor (geo/edge.xqy)path:as-polygon() (default false)georand:polar-random-points-in() takes either circle or sphere, producing 2D or 3D results as appropriate (geo/random.xqy)geom:bounding-box()point:with-properties() takes sequencebox:edge() looks for "edge" property firstgeom:process-xxx() functions not honouring delegatorspath:streamline() handling of leading and trailing skip edgespath:simplify() should not trim skip edgespath:with-edge-ts() and path:path-point() when path is length 0solid:face-centroid() when all zs are 0geom:delegate() loses exception list in recursive callsMiscellaneous new functions and features
seq:every-nth() (core/sequences.xqy)core:edge() (art/core.xqy)util:timestamp() (core/utilities.xqy)shapes:triangulate() (shapes/shapes.xqy)ppm:p6-bytes() and png:png-bytes() to return octets (image/ppm.xqy, image/png.xqy)fractal:newton() (components/fractal.xqy)effect:texture() (svg/effects.xqy)+ for colour+colour combinations (svg/gradients.xqy)"raw" modifier for canvas resolution for border size 0 (art/core.xqy)fills:hachure-lines() et all handle ellipses via interpolation (shapes/fills.xqy)background:terrain() and background:crosshatch() support spaces with arbitrary offsets as minimum point; modernize to fit with new rendering (components/backgrounds.xqy)Miscellaneous bugs
dist:max() settor should recalculate Zipf and Binomial tablesfills:hachure-lines() shouldn't add useless zero-length edgesgrid:navigable-hex-grid()This release includes a great number of maker functions, a lot of new solids, and the replacement of simple projection with automatic depth-ordered 3D rendering by default. The configuration option $config:RENDER controls this (core/config.xqy).
Incompatibilities:
merge(), glue(), revolve(), extrude(), and onion() moved from http://mathling.com/geometric/solid to http://mathling.com/shape/solids (shapes/solids.xqy)images:image() is now images:random-image() and images:svg() is images:random-svg() (components/images.xqy)edge:skip() only returns skip edge if it is useful (start!=end)Deprecations
spline:spline() is deprecated; prefer spline:open-spline() or spline:closed-spline() as appropriateNew modules
Solid geometry geo/solid.xqy, shapes/solids.xqy
solid:solids(), solid:regular-polyhedra()solid:regular-polyhedron()solid:great-icosahedron(), solids:borromean-rings(), solids:hex-knot-star(), solids:hex-knot-links(), solids:toroid-7-3-11()solid:merge(), solid:glue(), solid:revolve(), solid:extrude(), solid:onion() to new modulesolid:volume() for generic polyhedrasolid:as-polygon(), solid:depth-ordered-faces()solid:scale() on sphere returns radius not errorshapes:plaster(), shapes:scale-and-plaster() shapes/shapes.xqyDrawing and rendering
$config:RENDER variable (core/config.xqy)solid:ordered-translucent-faces() geo/solid.xqypath:ordered-translucent-edges() geo/path.xqycomplex-polygon drawing function should draw inner polygons, unfilledSigned distance functions sdf/sdf.xqy
sdf:cache(), sdf:opRenderVolumetric()sd3:sdSphere() with center sdf/sd3.xqysd2:sdPoint() and sd2:sdSignPoint() sdf/sd2.xqyImages
images.granularity to images module components/images.xqyimages:image() to images:random-image() and images:svg() to images:random-svg()image:image(), images:image(), and images:svg()image:bounding-box(), image:delegate()greyscale-value support to dithering image/dithering.xqygreyscale-value support in png/ppm image/ppm.xqy image/png.xqyPaths and edges
paths:focus-fill(), paths:fit(), paths:triangulate(), paths:starr-rose() shapes/paths.xqypaths:essbend() mispositioning second control pointspline:open-spline(), spline:closed-spline(), spline:open-hobby-spline(), spline:closed-hobby-spline(), spline:open-natural-spline(), spline:closed-natural-spline() geo/spline.xqypath:points-on(), path:triangle-chain(), path:consolidate-by-colour-and-opacity(), path:depth-ordered-edges() geo/path.xqypath:consolidate() creating multiple redundant pathspath:path-points()edge:is-skip() geo/edge.xqyedge:vertices() and (rough) edge:bounding-box()support for ellipse arcedge:skip() only returns skip edge if it is useful (start!=end)Core utilities core/utilities.xqy
util:append-into(), util:include-filter(), util:exclude-filter()util:remap(), util:intremap()util:doc(), util:unparsed-text(), util:unparsed-text-lines(): check and warn if file doesn't exist, don't throw errorutil:exclude() and util:include() to allow non-string keysutil:quote() always wrap multiple-item sequences in parenthesesutil:merge-into()util:rangeindexes()util:cbrt() mishandling negative numbersutil:include() shouldn't add empty entries for non-existent keysutil:annotations() was dropping annotations with no parameters; now it sets a boolean in the output mapseq:interleave() core/sequences.xqywrapper:body-with-properties() to push properties into body types/wrapper.xqyslot:quote() types/slot.xqyto-angles() at (0; √2/2, 0, √2/2); rounding err or leads to NaN core/quaternion.xqy, core/vquaternion.xqyMiscellaneous geometry
point:one-of()geom:with-properties() shouldn't delegate wrapper objectsMiscellaneous
flower:flower(), flower:flowers() for Starr roses components/flowers.xqypatterns:maze(), patterns:maze-xxx() bias and k functions shapes/patterns.xqyshape:scale-and-center(), shape:fitting-scale-and-center() shapes/shapes.xqytext:estimated-bounding-box() and delegator function types/text.xqygradient:colours() not handling interleaved reverse gradients properly svg/gradients.xqy(Refreshed 20240202.)
This release includes a number of new capabilities in the area of paths, shapes, and patterns, a reworking of hyperbolic geometry, and some more refactoring of the geometry code.
Incompatibilities
geom:xxx-distance() functionsdist:weighted-distribution-of()geom:signed-distance(), geom:shortest-distance() to sdf:signed-distance() and sdf:shortest-distance() sdf/sdf.xqygeom:projection(), geom:isometric(), geom:stereographic() to new module geo/projection.xqypaths:dusty-path() paths:dusty()paths:taper-path() to paths:taper()paths:sweep-path() to paths:sweep()paths:stroke-path() to paths:stroke()paths:bend-path() to paths:bend()$rand:DECIMAL-DIGITS to 3hyper:sorted-hypers() into hyper:tesselate() and made it privateseq:primes() to return first n primes; use seq:primes-to() to get primes less than or equal to n (old seq:primes())New deprecations
geom:random-point() et al (moved to geo/random.xqy)geom:to-edges() (moved to geo/edge.xqy)New modules
Pixel arrays and image processing
draw:draw-point-matrix() and relatedimages.pixel-function option components/images.xqyRandom distributions
euclidean.xqy to geo/random.xqygeorand:random-polar-points(), georand:poisson-disk-sample()dist:constant-index-of(), dist:normal-index-of(), dist:skewed-index-of(), dist:bernoulli-index-of(), dist:binomial-index-of(), dist:binomial-poisson-index-of(), dist:poisson-index-of(), dist:gamma-index-of(), dist:beta-index-of(), dist:binomial-beta-index-of(), dist:exponential-index-of(), dist:markov-index-of() geo/random.xqyGeometry geo/euclidean.xqy
euclidean.xqy to geo/random.xqyeuclidean.xqy to sdf/sdf.xqyeuclidean.xqy to geo/projection.xqygeom:invert(), geom:ellipse-invert()point:sqdistance(), v:sqdistance() geo/point.xqy, core/vector.xqyedge:slope() geo/edge.xqypath:star() geo/path.xqyellipse:destination() geo/ellipse.xqygeom:bounding-circle() takes sequence of regions$config:CANVAS-GEOMETRY in edge:angle()geom:reflect() on arcs incorrectPaths shapes/paths.xqy
paths:horizontal-modulated-torus-knot(), paths:vertical-modulated-torus-knot(), paths:dashed(), paths:dotted(), paths:constrained-walk(), paths:hex-constrained-walk(), paths:pure-hex-constrained-walk(), paths:extended-star(), paths:essbend()paths:dusty(), paths:taper(), paths:sweep(), paths:stroke() take multiple paths as parameterpaths:taper-path() infinite recursion for unspecified inclinationShapes, patterns, grids, etc.
shape:fitting-scale-and-center() shapes/shapes.xqygrids:exact-array(), grids:diagonal-array() shapes/grids.xqypatterns:hvedges() shapes/patterns.xqyfills:hachure-lines(), fills:crosshatch(), fills:zigzag(), :star() shapes/fills.xqyguilloche:guilloche(), guilloche:knot-guilloche(), guilloche:stack() shapes/guilloche.xqysystems:contextual-lsystem(), systems:curve() with delegation shapes/system.xqygrid:hex-grid()SDF sdf/sdf.xqy
sd2:circle() (with center), sd2:donut(); use new sd2:circle() in sdf:regionToSDF()sdf:signXXX() for sign-only SDF for in/out/on testingsdf:opDrift()sdf:toSDF()sdf:toSDF() with union of 1Miscellaneous
arr:as-array(), arr:array(array(array(*))) core/array.xqyutil:index-of()core/utilities.xqytransform:is-identity() geo/transform.xqytext:shrink() types/text.xqygradient:random-large-gradient() tied "largerandom" svg/gradients.xqyisohedral:describe() tiling/isohedral-tiling.xqyflowers.rose.precision, fish.eye.colour, mutations.random.augment, random+none tiling colour mode components/flowers.xqy, components/fish.xqy, components/mutations.xqy, components/tiling.xqyseq:rotate() vis-a-vis comment core/sequences.xqyA small refresh update to pick up some 3D extensions, fixes, and clean-up of the parametric L-system code.
L-Systems shapes/systems.xqy
sys:random(), sys:forwards3D(), sys:move3D(), sys:rotate3D(), sys:set-inclination(), sys:up(), sys:down(), sys:reverse-inclination(), sys:flip-inclination(), sys:flip()$this:PARAMETRIC-CALLBACKS)$lrand_, $arand_, $wrand_, $irand_ for randomized values from builtin randomizersColours svg/gradients.xqy
gradient:xxx-random() in favour of gradient:xxx-shuffle() and "-random" modifier in favour of "-shuffle"Paths shapes/paths.xqy
paths:taper-path(), paths:taper:segments(), paths:stroke-segments()paths:stroke-path()shape:scale-and-center() mishandling circles shapes/shape.xqyMiscellaneous
geom:bounding-sphere() incorrectly used geom:bounding-box() for most 2D objects geo/euclidean.xqygeom:bounding-box() to apply to polyhedra (ignores z coordinate) geo/euclidean.xqyWith Saxon 12.3 the need for additional JAR files (see 20230424 release notes) is gone. Saxon-JS problems with heap errors and string "too large" errors still apply (see 20230722 release notes). Some of the heap errors now show up with XSL as well (e.g. the fish example). Saxon-JS remains unusable except for very small and constrained examples that do not use many packages. XSL is still broadly usable.
L-System code has been extensively refactored, streamlined, and extended. Support for parametric systems has been added, as have a collection of drawing functions to make modifying rendering callbacks more straightforward as well as to provide some builtins for parametric systems. Specific L-systems have been moved to the http://mathling.com/art/lsystems module. Various API incompatibilities exists (see details) See shapes/systems.xqy and components/lsystems.xqy.
Refactoring of geometric delegation to make use of generic geom:delegate() function which honours "delegate" methods on objects. Refactoring of some of the structured components, such as http://mathling.com/art/octopus to leverage this new method. See geo/euclidean.xqy.
Incompatibility: the default drawing map for solids now uses 2-angle projection rather than 3-point perspective. The results are easier to control and more likely to be useful as-is. The default angles are -45 and 90.
(Bleeding Edge) Experimental 'maker' functions for various components, paths, an objects. The goal is to hook these into an Invisible XML driver art shell (not yet releases). The API and parameter usage in these maker functions is definitely subject to some change. In particular colour-handling is still up in the air. They can be used as exemplars of how to drive some of these components, however. Currently makers are all annotated with art:maker(somename). Makers may probably ultimately come in a few flavours, depending on intention as arrangements, spaces, or objects.
lsys:algae(), lsys:anklets(), lsys:boxes(), lsys:cracks(), lsys:daisy-chain(), lsys:double-penrose(), lsys:hex-crystal(), lsys:island(), lsys:island-and-lakes(), lsys:koch-island(), lsys:parametric-tree() lsys:peano(), lsys:peano-offset(), lsys:pentagram(), lsys:quartet(), lsys:gappy-quartet(), lsys:seaweed(), lsys:seaweed-wreath(), lsys:terdragon-boundary(), lsys:zigzag() components/lsystems.xqysystem:parametric-lsystem(), system:parametric-lsystem-translate(), system:parametric-lsystem-translate-curve()system:start(), system:end(), system:set-randomizers(), system:enable-randomizers(), system:disable-randomizers(), system:forwards(), system:forwards(), system:move(), system:move(), system:rotate(), system:set-angle(), system:left(), system:right(), system:reverse(), system:set-length(), system:adjust-length(), system:shorten(), system:lengthen(), system:set-width(), system:adjust-thickness(), system:widen(), system:narrow(), system:set-colour(), system:next-colour(), system:previous-colour(), system:set-kind(), system:make-path(), system:start-path(), system:start-path(), system:end-path(), system:circle(), system:circle(), system:ngon(), system:triangle(), system:square(), system:pentagon(), system:hexagon(), system:start-polygon(), system:end-polygon(), system:push(), system:pop(), system:start-branch(), system:end-branch(), system:no-op(), system:trace(), system:compose(), system:compose(), and ;. New property system.colours defines the palette.system.infer.polygons is true"current" key is no longer available in the default rendering map: use stack:top() instead.system:lsystem-curve()system:simple-lsystem-curve(), system:stochastic-lsystem-curve()@system:lsystem() delegates to either system:simple-lsystem() or system:stochastic-lsystem() as appropriate; similarly with system:lsystem-curve()lsys:koch-snowflake() to be 60 degree closed versiongeom:collect() gather actual geometric objects from nest of slots, defs, and wrappers geo/euclidean.xqyoctopus:rescale() et al with simpler octopus:style() + octopus:draw() as draw hook (thus: automaticly applied)arrangement:star(), arrangement:pie(), arrangement:rays(), arrangement:pseudospiral()arrangement:circle() using wrong angle calculationtiling:colour-function() has been flipped to be more consistenttiling:colour-function()isohedral:wild-complex-edges tiling/isohedral-tiling.xqyseq:hamming-weight() OEIS sequence A000120 core/sequences.xqypaths:dusty-path() shapes/paths.xqydist:cast(): dist:integer(), dist:double() etc. types/distributions.xqypath:edges() work on raw edges too (so path consolidation methods work on raw edges too) geo/path.xqycore:inner-canvas() not honouring offsets properly art/core.xqycs:cmyk-to-rgb() mishandles k=1 case colourspace/colour-space.xqyThe Saxon 12 and Saxon-JS issues mentioned in 20230424 still apply. The Saxon-JS issues are further exacerbated by heap errors during export and "too large" errors at run time. Saxon-JS is really not usable yet except for very small and constrained examples that do not use many packages.
geom:is-straight(), geom:is-straight-edge() to edge (geo/euclidean.xqy, geo/edge.xqysim:simplify(), sim:streamline(), sim:chaikin()geom:convex-hull() to simplifygeom:bounding-sphere(), geom:stereographic(), geom:stereographic3D(), geom:apply-matrix3(), geom:projection(), geom:process-polygons(), geom:process-areas(), geom:process-solids(), geom:process-paths(), geom:delegate() (geo/euclidean.xqy)affine:apply-matrix3(), affine:projection3(), affine:projection() (geo/affine.xqy)point:sum(), point:counterclockwise() (geo/point.xqy)edge:osculating-circle(), edge:signed-curvature(), edge:curvature() (geo/edge.xqy)path:quadrangle(), path:ngon(), path:osculating-circle(), path:simplify(), path:simplify-points(), path:streamline(), path:chaikin(), path:chaikin-points(), path:normalize(), path:consolidate-points-by-colour(), path:consolidate-points-by-colour-and-opacity() (geo/path.xqy)ellipse:ellipse-contains-ellipse() (geo/ellipse.xqy)solid:to-polyhedron(), solid:simple-polyhedron(), solid:extrude(), solid:glue(), solid:merge() (geo/slot.xqy)coord:stereographic(), coord:stereographic3D() (geo/coordinates.xqy)v:distance(), v:valid() (core/vector.xqy)geom:region-center() supports slot/wrapperedge:inclination() with just edge argumentedge:tangent() supports arc and ellipsesolid:insphere() supports blockgeom:edges() takes region sequence not just singletonpath:path() handles sequence of pointsspline:spline() excludes points with infinite coordinatesgeom:length() add support for polygonssolid:properties() missing case for generic polyhedronsolid:with-properties() missing case for generic polyhedronsolid:circumsphere() missing case for generic polyhedronpoint:distinct() should return () for empty sequence of pointssolid:same() generic polyhedron should be less sensitive to vertex reorderingsolid:points(), solid:vertices(), solid:face-indexes() should give error for ellipsoidsgeom:length() mishandling box/spaceedge:line-intersection() fails in some cases because test of -0=0 fails (?!)box:vertices() to be consistent with counterclockwise polygonpoly:as-real(), poly:is-constant(), zpoly:is-real(), zpoly:as-real-polynomial(), zpoly:as-polynomial(), poly:times(), zpoly:times(), zpoly:ztimes(), poly:zvaluev(), zpoly:zvaluez()complex:asin(), complex:acos(), vcomplex:asin(), vcomplex:acos(), complex:asinh(), complex:acosh(), vcomplex:asin(), vcomplex:acosh(), complex:modsq(), vcomplex:modsq(), complex:vector(), complex:as-vector() (core/complex.xqy, (core/vcomplex.xqy)q:quaternion() (from angles), q:from-vector(), q:rotation-between(), q:rotation3(), q:to-angles() (core/complex.xqy, (core/vquaternion.xqy)seq:continued-fraction(), seq:convergents(), seq:numerators(), seq:denominators(), seq:modp(), seq:modz(), seq:unmodp(), seq:unmodz()seq:sequence() supports "counter" + other new functionsseq:sequence() incorrect handling of "prime-sequence"util:some(), util:every(), util:none(), util:extreme()util:linspace() n=1, inclusivedist:weighted-distribution-of() to dist:weighted-index-of() (types/distributions.xqy)$rand:STD-UNIT (core/random.xqy)tone:shade(), tone:shadev() (colourspace/tonemap.xqy)effect:colour() take sequence of colours, rotates through them (svg/effects.xqy)patterns:center() and patterns:scale-and-center() to shapes (shapes/patterns.xqy, shapes/shapes.xqy)paths:stroke-path(), paths:looping-meander(), paths:bend(), paths:bend-path() (shapes/paths.xqy)grids:hexagon() (shapes/grids.xqy)patterns:scale-and-center() support width != height better (shapes/patterns.xqy)paths:meander() should use just sin() not derivative; paths:looping-meander() uses derivative (shapes/paths.xqy)grids:hex-point() maybe returns empty (not error) (shapes/grids.xqy)music:parse() and associated objects (music/music.xqy)music:note(), music:rest() additional parameter for note index (music/music.xqy)mnoise:noise-pitch(), mnoise:noise-pitch-vector(), mnoise:noise-density(), mnoise:noise-density-vector(), mnoise:noise-extreme(), mnoise:noise-extreme-vector()) (music/noise.xqy)ppm:p6-array() reading P6 into array (image/ppm.xqy)imagematrix:sample() (image/matrix.xqy)draw:project to default drawing mapstats:mean(), stats:median(), stats:mode(), stats:std() (core/statistics.xqy)density:chloropleth(), density:dots(), density:dot-diagram() (shapes/density.xqy)Saxon 12 issues
Saxon-JS issues
saxon:xquery()) which is not available in that context.Major changes
Major incompatibilities: Mutation functions, modifier functions, and noise functions
callable:function() to get an actual function item to call.mutation:as-vector(), mutation:as-point(), noise:as-point(), noise:as-vector() to switch modalities. (components/mutations.xqy, components/modifiers.xqy, noise/)Other incompatibilities:
mutation:random-mutation() and mutation:random-mutations() changed order of arguments to make compatible with general usage (components/mutations.xqy)components/systems.xqy is now shapes/systems.xqy with namespace changed from "http://mathling.com/art/systems" to "http://mathling.com/shape/systems"point:orientation() arguments order interpreted so that first two points are edge and orientation is of third point relative to that edge (geo/point.xqy); calls should flipped 2nd and 3rd parametersgeom:point(), geom:x(), geom:y(), geom:px(), geom:py(), geom:midpoint() Use point functions instead. Not present in XSL package. (geo/euclidean.xqy)Major new capabilities:
seq:sequence() (core/sequences.xqy)seq:mirror(), seq:alternate(), seq:shift(), seq:modix()grid:hex-triads(), grid:hex-subgrid(), grid:hex-points(), grid:hexagons(), grid:excluded() (shapes/grids.xqy)Other new things:
edge:skip() (geo/edge.xqy)vector:destination(), vector:mutate() (core/vector.xqy)path:consolidate(), path:consolidate-by-colour(), path:consolidate-by-width(), path:consolidate-points() (geo/path.xqy)point:sorientation() orientation of point triplets as a numerical sign (geo/point.xqy)geom:convex-hull() (geo/euclidean.xqy)patterns:scale-and-center(), patterns:center() (shapes/patterns.xqy)paths:meander(), paths:circle-spiral() (shapes/paths.xqy)complex:sum(), complex:eq(), vcomplex:sum(), vcomplex:eq()effect:distant-light()noise:trace-bounds(), noise:cache() (noise/modifiers.xqy)noise-map:flat-static(), noise-map:sphere-static() (noise/noise-map.xqy)tests/test-noise.xqy testing noise functions and modifierssdf:opRepeat2(), sdf:opMirrorRepeat2(), sdf:opGridRepeat2(), sdf:opPolarRepeat2()util:zsign() see bugs (core/utilities.xqy)mask:ref() (types/mask.xqy)poly:multiply() (types/polynomial.xqy)arr:blur(), arr:horizontal-blur(), arr:vertical-blur() (core/array.xqy)examples/contours.xqy, examples/tree.xqy (examples/)Bug fixes, clean-ups, and tweaks
seq:primes(), seq:prime-factors(), seq:foreach-combination(), seq:lazy-caterer(), seq:thue-morse(), seq:binomial()tests/test-sequences.xqy seq:foreach-permutation()local:testThueMorse() in tests/test-sequences.xqy$config:tolerance instead of $config:εsolid:ry(), solid:rz() using wrong accessor for spheressolid:ordered-edges() and solid:edges() reporting inverted edgestransform:translate() and transform:rotate() check for no-opsdelaunay:base-triangle() check for empty point listmarching:contours-by-function() wrong cardinality on parametergeo/translate.xsl leading to improper formattingsd3:sdPyramid() misbehaves because util:sign(-0) should be 0 but ends up negative as $v=0 fails (?!); however, some of the complex functions fail if util:sign(-0) is not negative (?!) so add util:zsign() for sd3:sdPyramid()simplex:noise4() raising type errorbox:min-point() offsets to grid:hex-grid() calculationscore:randomize() wrt keysMajor incompatibility: SDF functions
callable:function() to get at the actual function now. Other functions-that-produce-annotated functions (noise, modifiers) will get this treatment going forward. However, callable:function() will work on bare functions too, so it is advisable to just use it with these modules to future-proof code.Other incompatibilities
components/paths.xqy to shapes/paths.xqy; namespace changed from http://mathling.com/art/paths to http://mathling.com/shape/pathscomponents/paths.xqy into shapes/grids.xqy with namespace http://mathling.com/gridDocumentation
XSL APIs
Examples
Complete reworking of drawing functions
Major new objects and capabilities
geo/box.xqy)geo/coordinates.xqy)shapes/patterns.xqy)types/reach.xqy)shapes/grids.xqy)Sequences (see core/sequences.xqy)
SDF changes (see sdf/)
New art components and capabilities
components/people.xqy)components/squishy.xqy)components/barnsley.xqy)Miscellaneous new functions
core/utilities.xqy)types/distributions.xqy)geo/curves.xqy)geo/splitree.xqy)svg/effects.xqy)svg/gradients.xqy)components/english.xqy)geo/path.xqy)geo/edge.xqy)Bug fixes
Tests
Major new components and capabilities
core/quaternion.xqy, core/vquaternion.xqy)music/music.xqy)types/text.xqy, string/string.xqy)components/paths.xqy)components/polyspiral.xqy)components/arrangements.xqy)components/modifiers.xqy)components/refraction.xqy)components/pixelsort.xqy)components/crosshatch.xqy)components/english.xqy)components/oldkey.xqy)Effects and filters
Colours and gradients
Images
image/image.xqy)image/convolution.xqy)image/pixelsort.xqy)Randomizers
Geometry
Complex numbers
Tweaks
Misc
Major new algorithm: Wave Function Collapse (wfc/)
Mutations:
Other new:
Refactoring of geometry code
geo/affine.xqygeo/edge.xqy; some renaming, e.g. geom:slice-edge() => edge:slice()geo/box.xqy to avoid twisted imports; external interface unchangedGeometry additional:
edge:as-point-arc()Colours
Other bugs:
Major new components and features
3d/)images/png.xqy)geo/conrec.xqy)types/distibutions.xqy)geo/curves.xqy)types/polynomial.xqy)svg/effects.xqy)Randomized components:
components/backgrounds.xqy)components/cellular.xqy)components/contours.xqy)components/egg.xqy)components/divisions.xqy)components/fflame.xqy)components/waves.xqy)components/xtrs.xqy)components/harmonograph.xqy)Various spirals and curves (components/paths.xqy)
Colours and gradients:
svg/gradients.xqy)gradient:average-luminance() to compute relative brightness of a set of coloursRandom distributions:
dist:post-shift() to add a value to the output of the core algorithmdist:simple-sums() method for constructing a cumulative weight table from an ordered set of raw weightskeys hook for automating getting values from random indexes (art/core.xqy)double cast to override the implicit integer cast of some of the distributions (e.g. Zipf)Types:
Isohedral tiling:
tiling:create-tiles to control the extent of the bounds and override the defaultGeometry:
geom:area(), geom:length(), geom:n-faces(), geom:region-point() functionsgeom:tangent() and geom:normal() for 2D linear, quad, or cubic edge, plus associated geom:tangent-angle() and geom:normal-angle() (angle of the tangent or normal vector)point:valid() to check for point coordinates that are infinite or NaNsolid:normal(), solid:face-area(), solid:face-centroid()Framework
core:randomize()core:random-parameter-map(), core:random-parameters()Signed distance functions
sdf:toSDF()sdf:opUnion(), sdf:opIntersect()Components
mut:drift(), handle missing parametersIncompatibilities
util:min-key() and util:max-key()geom:region-center() honours a center propertysolid:edges() to return distinct edges; add solid:ordered-edges() to get the full set of edges (including shared), in face ordertransform:describe() to better match SVG transform propertyVarious fixes:
geom:region-center(), fix bug in center of 4-sided polygongeom:ellipse-point()core:dump-randomizer() and $core:EVAL11systems:pentaplexity() to use parameters for scaling and generationsPossible future mayhem:
components/paths.xqy[1] Requires functions from the http://expath.org/ns/file and http://expath.org/ns/binary namespaces.
[2] Depends on Saxon Java API extensions; metadata saved in a secondary file due to lacunae in Java PNG implementation.
[3] See Paul Bourke "CONREC: A Contouring Subroutine" (http://paulbourke.net/papers/conrec/) for more information.
[4] See https://en.wikipedia.org/wiki/Elementary_cellular_automaton for more information.
[5] See Valeriy G. Narushin, Michael N. Romanov, and Darren K. Griffin " A universal formula for avian egg shape" (https://www.biorxiv.org/content/10.1101/2020.08.15.252148v1) for more information.
[6] See Scott Draves & Erik Reckase "The Fractal Flame Algorithm" (https://flam3.com/flame_draves.pdf) for more information.
Geometry:
box:max-y for spacesgeom:project return typemutate()Sequences:
Utilities:
util:logK() and util:log2() (log base K and log base 2)rand:mutual-prime-pair() (pair of mutually prime integers)util:modix handle negative numbers to preserve sequentialitypaths:array() calculationsDrawing/Colour/Effects:
gradient:random-gradient() select a random well-known gradient or its reverseComponents:
Additions, extensions, and bug fixes to geometry code:
geo:region-intersects between most region typesgeo:region-contains between some region typesgeo:shortest-distance from point to regiongeo:intersection between edgesgeo:bounding-circle of region (Weltz' algorithm)geo:bounding-box of regiongeo:region-centergeo:regions edge following to construct polygons from edge graphgraph.xqy)treemap.xqy)delaunay.xqy)Drawing code
draw.xqy)effects.xqy)Miscellaneous
tonemap.xqy)$EDGE-START and $EDGE-END in tiling coderoots.xqy)complex.xqy)Major refactoring of geospatial code, with some additional operations for splinning and reversing edges, among others. As a consequence of this a number of edge and path functions have shifted from euclidean.xqy to edge.xqy or path.xqy in some cases with a slight renaming. Example: geom:linear-edge-point is not edge:linear-point. In addition a few functions have moved to utilities.xqy (remap-degrees, remap-radians).
Handle error cases in edge:quad-length better.
Change geom:inclination to define it as 90° not 0° when the points are the same.
Change geom:destination to avoid small round-off errors in Z values from inclination imprecision.
Add split tree and well-separated pair decomposition and spanning edges on WSPDs. (Depends on bug-fix in Saxon 10.6 to work.)
Add support for dithering of raw images.
Add support for complex numbers.
Add modules for signed distance function calculation, with various rendering and lighting calculations, with tests.
Add SVG gradient collection and module for manipulating SVG gradients.
Add permutation and combination calculations to utilities.xqy.
Slight refactoring of random distributions code to avoid tangled imports.
ε is now defined globally in config.xqy
util:twixt will reorder out-of-order arguments.
Bug fix to rand:skewed(): incorrect calculation of standard deviation.
Bug fix to rand:flip(): scaling error.
Reimplementation and API change to rand:random-selection() to give more precise probability mapping.
Additional/cleaned-up randomizer tests: advice on optimizer flags for Saxon EE
util:rangeindex() + tests