Custom shapes

Polygons, holes, curves and beziers in a with shape() block.

shape

shape(close=False)

Builds a custom shape in a with block and draws it at the block’s end.

Add points inside the block with vertex and friends; anything collected before the block is discarded::

with kiln.shape(close=True):
    kiln.vertex(10, 10)
    kiln.vertex(90, 10)
    kiln.vertex(50, 80)

If the block raises, the shape is dropped and nothing is drawn.

With a fill colour the shape is filled (every contour is implicitly closed) following the current winding rule. With a stroke colour it is outlined stroke(width=) points wide with mitred corners, on top of its fill; close joins the last contour’s end back to its start (the outline is open unless close). With the default Winding.ODD each contour is outlined as drawn. With another rule the outline follows the boundary of what that rule fills: NONZERO outlines the union of overlapping contours and ABS_GEQ_TWO their intersection, with no interior edges. The transform is the one current at the end of the block.

Filling contours that cross or touch costs O(edges^2) or more, since every crossing splits edges: a scribble of 20 points that crosses itself everywhere takes about 5 ms to fill, 80 points 60-100 ms and 160 points several hundred, where a simple contour of the same size takes under a millisecond. Outlining such a shape under a rule other than ODD costs about a tenth of that. Keep heavily self-crossing shapes small, or few per frame.

Parameters

Name Type Description Default
close bool Close the outline of the last contour. False

Returns

Name Type Description
_ShapeScope A context manager.

vertex

vertex(x, y, z=0.0)

Adds a corner point to the current shape.

Parameters

Name Type Description Default
x float Point x. required
y float Point y. required
z float Accepted and ignored: Kiln is 2D. 0.0

vertices

vertices(points)

Adds many corner points to the current shape at once.

Parameters

Name Type Description Default
points Iterable[Iterable[float]] | np.ndarray An (n, 2) array-like of (x, y), or (n, 3) with z ignored. required

curve_vertex

curve_vertex(x, y, z=0.0)

Adds a point of a smooth Catmull-Rom curve to the current shape.

The curve passes through every curve point except the first and the last, which only steer its start and end: four curve points draw the stretch between the second and the third. curve_resolution sets the number of points per stretch. A vertex or bezier_vertex ends the curve.

Parameters

Name Type Description Default
x float Point x. required
y float Point y. required
z float Accepted and ignored: Kiln is 2D. 0.0

bezier_vertex

bezier_vertex(cx1, cy1, cx2, cy2, x, y)

Adds a cubic bezier from the shape’s last point to (x, y).

(cx1, cy1) and (cx2, cy2) are the control points: the curve leaves the last point towards the first and arrives at (x, y) from the second. It needs a previous point in the contour (start with vertex) and is ignored otherwise. curve_resolution sets its number of points.

Parameters

Name Type Description Default
cx1 float First control point x. required
cy1 float First control point y. required
cx2 float Second control point x. required
cy2 float Second control point y. required
x float End point x. required
y float End point y. required

next_contour

next_contour(close=False)

Ends the current contour and starts a new one in the same shape.

Contours are filled together, so a contour inside another one makes a hole (under the default Winding.ODD).

Parameters

Name Type Description Default
close bool Close the outline of the contour being ended. False

bezier

bezier(x0, y0, x1, y1, x2, y2, x3, y3)

Draws a cubic bezier from (x0, y0) to (x3, y3).

(x1, y1) and (x2, y2) are the control points. It follows the fill state: use fill(None) and a stroke colour for a curve line; with a fill colour it fills the area between the curve and its chord.

Parameters

Name Type Description Default
x0 float Start x. required
y0 float Start y. required
x1 float First control point x. required
y1 float First control point y. required
x2 float Second control point x. required
y2 float Second control point y. required
x3 float End x. required
y3 float End y. required

curve

curve(x0, y0, x1, y1, x2, y2, x3, y3)

Draws a Catmull-Rom curve from (x1, y1) to (x2, y2).

(x0, y0) and (x3, y3) are control points that set the curve’s direction at its ends; the curve does not reach them. It follows the fill state: use fill(None) and a stroke colour for a curve line.

Parameters

Name Type Description Default
x0 float Start control point x. required
y0 float Start control point y. required
x1 float Start x. required
y1 float Start y. required
x2 float End x. required
y2 float End y. required
x3 float End control point x. required
y3 float End control point y. required

winding

winding(mode)

Sets the winding rule that decides what a custom shape fills.

Matters where contours overlap, touch or cross themselves. The default, Winding.ODD, makes a contour inside another one a hole and leaves the centre of a self-crossing star empty; NONZERO fills them.

POSITIVE and NEGATIVE depend on which direction counts as positive: the one that gives the whole shape a positive total area. When the areas cancel out, as for a symmetric figure-8, neither direction wins, and Kiln counts the contours as drawn, so a part traced clockwise on screen is positive. Nearly cancelling areas can still tip either way.

The rule also shapes the outlines (see shape). Contours that cross or touch are split at every contact, which costs O(edges^2) or more: a scribble of 80 points that crosses itself everywhere takes 60-100 ms to fill (see shape).

Parameters

Name Type Description Default
mode Winding | WindingValue A Winding member or its name ("nonzero"). required

Raises

Name Type Description
ValueError An unknown rule name; the message lists the valid ones.

Winding

Winding()

Which parts of a custom shape are filled.

The winding number of a point counts how many times the shape’s contours go around it, with the direction that gives the whole shape a positive area counted as positive (so a single contour is +1 whichever way it is drawn). A point is filled when its winding number w is:

  • ODD: odd, the default. Inner contours make holes and the centre of a self-crossing star is empty.
  • NONZERO: not zero. Overlaps and the star’s centre are filled.
  • POSITIVE: above zero.
  • NEGATIVE: below zero (a contour drawn against the shape’s main direction).
  • ABS_GEQ_TWO: two or more in absolute value, i.e. only where contours overlap.

All five are exact, for overlapping and self-crossing contours too.