Documentation

Geon
DSL Reference

A zero-dependency JavaScript library that renders static 2D mathematical graphics from a concise, natural-language-like DSL into SVG — directly in the browser.

No dependencies Single file SVG output Expressions Function plots Intersections

Design philosophy: Geon is deliberately minimal. Line-based declarations, lowercase keywords, and order-sensitive evaluation keep programs readable and predictable, while v2 adds variables, expressions, plots, reusable styles, and more geometric primitives.


Quickstart

Drop geon.js into your page. Call Geon.render(source, container). That's it.

<!-- 1. Include the library -->
<script src="geon.js"></script>

<!-- 2. Create a container -->
<div id="canvas"></div>

<!-- 3. Render a scene -->
<script>
Geon.render(`
  scene 600x600
  grid x -5 to 5 step 1 y -5 to 5 step 1

  let r = 2

  point A (0,0)
  point B polar (r,30)

  circle C center A r r stroke blue fill lightblue opacity 0.35
  segment AB from A to B stroke black width 2 arrow end
  plot S y=x^2-2 from -3 to 3 stroke crimson width 2

  label A "Origin" position southwest
  label C "Circle C" color blue
  label S "Parabola" color crimson
`, document.getElementById("canvas"));
</script>
Rendered by local geon.js Quickstart

Installation

Geon is a single file with zero external dependencies. Download and include it directly.

# Via <script> tag (recommended)
<script src="geon.js"></script>

# Or inline the contents of geon.js directly into your HTML

Once included, the global Geon object is available on window.


Program Structure

Every Geon program needs one scene and one grid. Identifiers are resolved top-to-bottom, so declare points and shapes before using them.

Program   ::= SceneDecl GridDecl Statement*
Statement ::= Let | Style | Point | Midpoint | Segment | Circle
            | Ellipse | Rect | Arc | Polygon | Line | Ray
            | Bezier | Plot | Intersect | Label | Layer
Strict order: Geon does not support forward references. Every identifier must be declared before it is used. Statements are evaluated top-to-bottom, exactly as written.

Scene

Declares the SVG viewport dimensions in pixels. Must be the first statement.

scene <width>x<height>
Example
scene 600x400   # 600px wide, 400px tall
scene 800x800   # Square canvas
FieldTypeDescription
widthintegerSVG width in pixels
heightintegerSVG height in pixels

Grid

Defines the logical coordinate system — the bounds and step interval for both axes. The grid is rendered as light lines in the SVG, with the x=0 and y=0 axes drawn darker.

grid x <xmin> to <xmax> step <dx> y <ymin> to <ymax> step <dy>
Example
grid x -5 to 5 step 1 y -5 to 5 step 1
grid x 0 to 10 step 2 y 0 to 10 step 2
FieldConstraintDescription
xmin / xmaxxmin < xmaxHorizontal logical bounds
ymin / ymaxymin < ymaxVertical logical bounds
dx / dy> 0Grid line interval
Note: The Y-axis is inverted from SVG's default. In Geon, positive Y goes up, matching standard math conventions.

Expressions & Variables

Geon v2 supports numeric expressions in coordinates, polar tuples, radii, dimensions, plot formulas, and let declarations. Function calls such as sin(30) are safest inside tuple expressions; scalar fields and plot formulas should be compact single-token expressions such as r*0.5 or x^2-2.

let <name> = <expression>
Examples
let r = 2.5
let theta = 30

point A (r*cos(theta), r*sin(theta))
circle C center A r r*0.5
SupportedSyntax
Operators+, -, *, /, ^
Constantspi, tau, e
Degree trigsin, cos, tan
Radian trigsinr, cosr, tanr
Other functionssqrt, abs, floor, ceil, round, log, exp, sign

Point

Declares a named point. Points render as small filled circles and serve as anchors for other shapes.

point <id> (<x>,<y>)
point <id> <AnchorExpr>
point <id> polar (<r>,<degrees>)
Examples
point A (0,0)                 # Absolute coordinate
point B A + (2,1)             # Offset from another point
point P C.center + (1,0)      # Offset from circle center
point Q T.p2                   # Second vertex of polygon T
point R polar (3,45)           # Polar coordinate from origin

Midpoint

Creates a named point halfway between two existing point-like identifiers.

midpoint <id> of <pointA> <pointB>
midpoint M of A B
label M "midpoint"

Segment

Draws a line between two anchor expressions. Renders as an SVG <line>.

segment <id> from <AnchorExpr> to <AnchorExpr> [style]
Examples
segment AB from A to B
segment S from (-2,0) to (2,0) stroke red width 3
segment R from A to C.center stroke blue
AnchorReturns
segId.fromStart point of the segment
segId.toEnd point of the segment
segId.midMidpoint of the segment

Circle

Draws a circle. The radius is specified in logical (grid) units.

circle <id> center <AnchorExpr> r <expression> [style]
Examples
circle C center A r 2
circle C center (0,0) r 3 stroke blue fill lightblue opacity 0.35
circle D center C.center r 0  # Renders as a dot
AnchorReturns
circleId.centerCenter point of the circle
Radius = 0 is allowed and renders as a point. Negative radius throws an error.

Polygon

Draws a closed polygon through a sequence of anchor expressions. Requires at least 3 points. Renders as SVG <polygon>.

polygon <id> points <AnchorExpr> <AnchorExpr> <AnchorExpr> ... [style]
Examples
polygon T points A B (1,2)
polygon Q points (-1,-1) (1,-1) (1,1) (-1,1) fill pink opacity 0.6
AnchorReturns
polyId.p1, p2, p3, …The Nth vertex (1-indexed)
polyId.centroidGeometric center of the polygon

v2 Primitives

Geon v2 adds ellipses, rectangles, arcs, infinite lines, rays, and cubic Bezier curves. All accept the same inline style tokens as existing shapes.

ellipse E center A rx 3 ry 1.5 stroke purple
rect R at (-2,2) w 4 h 2 stroke black fill gainsboro opacity 0.5
arc K center A r 3 from 20 to 160 stroke orange width 3
line L through A B stroke gray dash 4,4
ray Y from A through (1,1) stroke red arrow end
bezier BZ from (-4,-1) control (-2,3) (2,-3) to (4,1) stroke green
PrimitiveSyntaxAnchors
ellipseellipse id center A rx x ry ycenter
rectrect id at A w x h ytopleft, topright, bottomleft, bottomright, center
arcarc id center A r x from deg to degcenter
lineline id through A Bp1, p2, mid
rayray id from A through Borigin
bezierbezier id from A control B C to Dfrom, to, mid

Plot & Intersect

Plots sample y=<expression> over an x-domain. Intersections create point symbols from supported shape pairs.

plot P y=x^2 from -3 to 3 stroke crimson width 2
plot Q y=x^3-x from -3 to 3 step 0.05 stroke blue

line L through (-3,0) (3,0)
circle C center (0,0) r 2
intersect X L C
label X "first"
label X_2 "second"
If step is omitted, plots sample roughly 300 points. Intersections support line-family vs line-family, line-family vs circle, and circle vs circle; the second intersection, when present, is named id_2.

Anchor Expressions

An anchor expression resolves to a 2D coordinate. They are used wherever a position is needed.

AnchorExpr ::=
    (x,y)                      # Literal coordinate
  | pointId                    # Named point
  | shapeId.anchor            # Named anchor on a shape
  | AnchorExpr + (dx,dy)     # Vector offset
Supported Shape Anchors
ShapeAnchorDescription
pointpointIdThe point itself
circlecircleId.centerCenter of the circle
ellipseellipseId.centerCenter of the ellipse
rectrectId.topleft, topright, bottomleft, bottomright, centerRectangle corners and center
arcarcId.centerCenter of the arc
polygonpolyId.p1polyId.pNNth vertex
segmentsegId.from, segId.to, segId.midEndpoints and midpoint
linelineId.p1, lineId.p2, lineId.midDefining points and midpoint
rayrayId.originRay origin
bezierbezierId.from, bezierId.to, bezierId.midEndpoints and endpoint midpoint
Valid Vector Addition
# ✓ Right-hand side must always be a literal (dx,dy)
point P A + (1,0)
point Q C.center + (-1,2)

# ✗ Cannot add two anchor refs together
point B A + A   # Error: expected (dx,dy)
Tuple coordinates and vector offsets may contain expressions, such as (r*cos(30), r*sin(30)).

Styling

Style tokens are appended inline after a shape or label declaration, or defined once in a named style block and applied with use.

style construction {
  stroke gray
  width 1
  dash 4,4
  opacity 0.75
}

circle C center (0,0) r 2 stroke blue fill lightblue opacity 0.35 width 3
segment S from A to B use construction arrow end
label A "Origin" color red size 14
TokenDefaultAccepts
strokeblackSingle-token CSS color names are safest; # starts comments
fillnoneSingle-token CSS color names, or none
width2SVG stroke width
dashnullSVG dash array such as 4,4
opacity1Number, commonly 0 to 1
arrownullstart, end, or both
color#222Single-token CSS color names for labels
size12Label font size
usen/aName of a declared style block
Invalid color names are passed directly to SVG, so browser fallback behavior applies.

Labels

Attaches a text annotation to a declared shape or point. Labels are always rendered as the topmost layer, after all shapes.

label <target> "<text>" [position <direction>] [style]
Examples
label A  "Origin"
label C  "Unit Circle"
label T  "Triangle"
label AB "Hypotenuse"
label P  "North-east label" position northeast color crimson

# Multiple labels on the same target are both rendered; overlaps are auto-avoided
label A "First"
label A "Second"
Target TypeLabel Anchors At
pointExact point location
circleCenter of the circle
segmentMidpoint of the segment
polygonCentroid of the polygon
rectCenter of the rectangle
plotMiddle sampled point
Supported position hints are north, south, east, west, northeast, northwest, southeast, and southwest. Without a hint, labels use automatic overlap avoidance.

Rendering Order

Geon renders in three layers, in this fixed sequence:

Layer 1 Grid lines and axis labels
Layer 2 Shapes — in declaration order (later shapes appear on top)
Layer 3 Labels — always on top, regardless of where label appears in source
circle A center (0,0) r 2   # drawn first → underneath
circle B center (1,0) r 2   # drawn second → on top of A
layer <name> is accepted as a source marker, but the current renderer still uses this fixed grid, shapes, labels order.

Coordinate System

Geon uses a standard mathematical coordinate system: Y increases upward. This is the opposite of SVG's default (where Y increases downward). The mapping is handled automatically.

# Logical space (Geon)    →   SVG pixel space
(xmin, ymax)  top-left    →   (0, 0)
(xmax, ymin)  bottom-right →  (width, height)
(0, 0)        origin      →   center (if grid is symmetric)

JavaScript API

The global Geon object exposes rendering plus parse/resolve helpers for tooling.

Signature
Geon.render(source: string, container: HTMLElement): Result

Result ::= { success: true }
         | { success: false, error: string }
Behavior
ConditionEffect
SuccessClears container, appends the rendered <svg>
ErrorClears container, appends a styled error message div; returns { success: false, error }
Example with error handling
const result = Geon.render(source, document.getElementById('canvas'));
if (!result.success) {
  console.error('Geon error:', result.error);
}
Tooling helpers
Geon.parse(source)      # returns { ast, styleBlocks } or throws
Geon.resolve(source)    # returns resolved scene, grid, symbols, labels, vars
Geon.version            # "2.0.0"

Error Reference

All errors include a line number where possible. Errors stop execution immediately — no partial rendering occurs.

ErrorTrigger
Missing 'scene WxH' No scene statement in program
Missing 'grid x ... y ...' No grid statement in program
Undefined identifier 'X' Referencing a name that was never declared
Duplicate id 'X' Declaring the same name twice
Invalid anchor 'X.prop' Accessing a property that does not exist on the shape (e.g. circle.radius)
Expression error in (...) A coordinate expression could not be evaluated
Undefined variable or function: 'x' An expression references an unknown variable or function
Division by zero An expression divides by zero
Polygon requires >= 3 points A polygon with fewer than 3 vertices
Invalid radius A circle with a negative radius
Grid step must be > 0 A step value of zero or negative
Grid x min must be < x max Inverted grid range
Undefined label target 'X' label X "..." where X was never declared
Unknown keyword 'X' Unrecognized keyword — also catches capitalized keywords like Point
Malformed coordinate Coordinates like (1,) or (,2)
Expected (dx,dy) after '+' Vector addition with non-literal right-hand side
No intersection found between 'A' and 'B' Supported shapes do not intersect
Cannot intersect shapes of types ... Intersection requested for unsupported shape types

Edge Cases

A summary of how Geon handles boundary and degenerate inputs.

Forward References
Using an identifier before it is declared
Error
segment S from A to B   # Error: A not declared yet
point A (0,0)
point B (1,1)
Expression Errors
Unknown variables, unknown functions, or division by zero
Error
let r = missingValue   # Error: undefined variable
point A (1/0,0)          # Error: division by zero
Zero Radius Circle
A circle with radius = 0
Allowed
circle C center (0,0) r 0   # Renders as a dot
Zero-Length Segment
A segment whose endpoints are identical
Allowed
point A (1,1)
segment S from A to A   # Renders as point-like line
Degenerate / Collinear Polygon
All points on the same line (area = 0)
Allowed (renders as line)
polygon T points (0,0) (1,1) (2,2)
Self-Intersecting Polygon
A non-simple (butterfly/bowtie) polygon
Allowed
polygon P points (0,0) (2,2) (0,2) (2,0)   # SVG handles it
Coordinates Outside Grid
Points or shapes outside the declared bounds
Allowed (SVG clips)
point A (1000,1000)   # Will be outside SVG viewport
Extra Whitespace
Multiple spaces between tokens
Allowed
point   A    (0,0)   # Valid
Capitalized Keywords
Keywords must be lowercase
Error
Point A (0,0)    # Error: keywords are lowercase
Circle C ...     # Error

Full Example

A complete Geon v2 program demonstrating variables, reusable styles, polar points, new primitives, plotting, intersections, and labels.

scene 700x450
grid x -6 to 6 step 1 y -4 to 4 step 1

let r = 2.5
let angle = 35

style construction {
  stroke gray
  width 1
  dash 4,4
  opacity 0.75
}

# Define anchor points
point A (0,0)
point B polar (r,angle)
midpoint M of A B

# Core geometry
segment AB from A to B stroke gray width 2 arrow end
circle C center A r r stroke blue fill lightblue opacity 0.35
ellipse E center M rx 1.4 ry 0.6 stroke purple fill plum opacity 0.35
rect R at (-5,3) w 2 h 1.25 stroke black fill gainsboro opacity 0.5
arc K center A r 3 from 20 to 150 stroke orange width 3

# Lines, curves, and derived points
line L through (-5,-1) (5,2) use construction
ray Y from A through (1,1) stroke crimson arrow end
bezier BZ from (-4,-2) control (-2,3) (2,-3) to (4,2) stroke green width 2
plot P y=x^2-2 from -3 to 3 step 0.05 stroke crimson width 2
intersect X L C

# Labels
label A  "Origin" position southwest size 14 color black
label B  "Polar point" position northeast
label M  "Midpoint" position south
label C  "Circle C" color blue
label X  "Intersection"
label P  "y = x^2 - 2" color crimson
Rendered by local geon.js Full v2 example