Table of Contents
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
Errors
The conditions
(define-condition sdf-error (error) ...)
(define-condition invalid-contours-error (sdf-error type-error) ...)
(define-condition open-contour-error (sdf-error) ...)
Every error cl-sdf signals itself is an sdf-error, and its report says what went wrong and what to change. Two kinds have conditions of their own, with readers that say where the problem is:
invalid-contours-error: contours that are not a list of lists of segments. Also atype-error, with the bad object astype-error-datum.invalid-contours-error-contour-indexandinvalid-contours-error-segment-indexgive its place, ornil.open-contour-error: a contour that does not close, where a filled region is needed.open-contour-error-contour-indexgives the contour, andopen-contour-error-gapthe gap as(x0 y0 x1 y1).
The other sdf-errors carry only their message. Handle them as sdf-error; their own class is internal.
A wrong argument signals a cl:type-error. Every function declares the full type of each argument, as Type errors lists, and SBCL checks it when the function is entered, so the error is SBCL's and names the declared type, with the argument it binds:
The value
0
is not of type
(INTEGER 1)
when binding CL-SDF::WIDTH
When the argument is a constant number or keyword outside its type, such as a width of 0 or a fill rule of :odd, SBCL already warns where it compiles the call. A quoted list is typed only as a list there, so bounds or a segment of the wrong shape are refused when the call runs. The type of a rectangle, coordinate or segment is printed expanded, as unions of float and rational ranges.
(handler-case (sdf:generate-mtsdf contours 32 32)
(sdf:open-contour-error (e)
(format t "Contour ~D is open at ~A~%"
(sdf:open-contour-error-contour-index e) (sdf:open-contour-error-gap e)))
(sdf:sdf-error (e)
(format t "Cannot make a field: ~A~%" e)))
Malformed contours
invalid-contours-error. The message names the argument, then the contour and segment, quotes the object, says what is wrong, and ends with a reminder of the format. The argument is CONTOURS for most functions, SHAPE for queries given contours and CONTOUR for contour-bounds. A segment given alone, to make-colored-edge, is checked by its declared type, segment, instead.
| What is wrong | Message |
|---|---|
| Contours not a proper list | CONTOURS is x: it is not a proper list. |
| A segment given as the contours | CONTOURS is x: it is a single segment; contours nest two levels deep. |
| A contour not a proper list | CONTOURS contour i is x: a contour must be a proper list of segments. |
| A segment given as a contour | CONTOURS contour i is x: it is a single segment where a contour was expected; wrap it in a list. |
| A segment not a list | CONTOURS contour i segment j is x: it is not a list. |
| An unknown segment kind | CONTOURS contour i segment j is x: :kind is not a segment kind. |
| Too few or too many coordinates | CONTOURS contour i segment j is x: a :LINE segment takes 4 coordinates. |
| A coordinate that is not a real | CONTOURS contour i segment j is x: its coordinates must all be reals. |
| A coordinate beyond ±1e36 | CONTOURS contour i segment j is x: its coordinates must be within ±1e36; scale the outline down. |
| Generators: a plain segment among colored edges | CONTOURS contour i segment j is x: it is not a COLORED-EDGE, but the first edge is; color every edge or none. |
| Generators: a colored edge among plain segments | CONTOURS contour i segment j is x: it is a COLORED-EDGE, but the first edge is a plain segment; color every edge or none. |
| Generators: a colored contour not a proper list | CONTOURS contour i is x: a contour must be a proper list of COLORED-EDGEs. |
For example:
CONTOURS contour 0 segment 1 is (:ARC 1 0 0 0): :ARC is not a segment kind.
CONTOURS is a list of contours, each a list of segments. A segment is (:LINE x0 y0 x1 y1),
(:QUADRATIC x0 y0 cx cy x1 y1) or (:CUBIC x0 y0 c1x c1y c2x c2y x1 y1), all reals within ±1e36.
When the generators report a problem with colored contours, the reminder says that contours may also be lists of colored edges, as color-edges returns, with every edge colored or none.
Open contours
open-contour-error, from make-shape, inside-p, signed-distance and the generators:
Contour 0 is not closed: a segment ends at (0.5d0, 1.0d0) but the next starts at (0.0d0, 0.0d0).
Inside tests, signed distances and fields need closed contours, where each segment starts
where the previous one ends and the last ends where the first starts. Close the gap, for
example with (:LINE 0.5d0 1.0d0 0.0d0 0.0d0), or use UNSIGNED-DISTANCE for open paths.
Numbers in every message are the exact double-floats cl-sdf used, in Lisp syntax, whatever their size: 1.0d-300, not three hundred digits. They read back as exactly those numbers, so the suggested segment closes the gap when pasted in.
Points must match to within a few units in the last place of the coordinates' magnitude. A gap too small to see in the message, between points that print alike, comes from rounding: compute shared points once and reuse them.
Other errors
| From | Message | Cause and cure |
|---|---|---|
| Generators | The field bounds (x0 y0 x1 y1) have no area [after :PADDING p]. Pass :BOUNDS as (XMIN YMIN XMAX YMAX) with XMIN < XMAX and YMIN < YMAX, [and a :PADDING that does not shrink them away]. | Given bounds with no width or height, or a negative padding larger than half their size. |
| Generators | A :PX-SPREAD of p texels is s shape units, beyond 1e36. Give a smaller :PX-SPREAD, or :SPREAD in shape units. | Bounds so large that the spread in texels exceeds the coordinate range. |
Generators, flatten-contours, make-shape, queries |
Cannot flatten a :CUBIC segment to within t shape units in 24 subdivisions. Use a larger :FLATTEN-TOLERANCE: one that small cannot be reached for a segment this large. | A tolerance too small for the segment's size, such as 1e-12 for a curve a thousand units long. |
Generators, make-shape, signed-distance |
Cannot trace the filled shape's boundary at (x, y). Features there are closer together than cl-sdf's geometric precision (e shape units). Separate or merge them, or report the shape as a bug. | Edges or vertices closer than about 1e-14 of the coordinates' magnitude, but not the same. See Accuracy and Performance. |
inside-p, signed-distance, unsigned-distance |
INSIDE-P was given a SHAPE together with :FILL-RULE [and :FLATTEN-TOLERANCE]. A shape's fill rule and tolerance are fixed when it is made: pass them to MAKE-SHAPE instead. | Options given with a prepared shape. |
color-edges |
COLORS is x, but must be a list of at least two distinct colors from :CYAN, :MAGENTA and :YELLOW. Edges colored :RED, :GREEN or :BLUE feed only one channel, so the median of the three channels cannot reconstruct them. | A palette with fewer than two distinct CMY colors, or another color. |
color-edges |
Contour i has n sharp corners, an odd number, so its edges need three colors, but COLORS is x. Pass :COLORS '(:CYAN :MAGENTA :YELLOW), the default. | A two-color palette and an odd number of corners. |
generate-msdf, generate-mtsdf |
CONTOURS contour i edge j is :RED, which feeds only one channel. MSDF edges must be :CYAN, :MAGENTA, :YELLOW or :WHITE so that the median of the three channels can reconstruct them. | A single-channel color in your own coloring. |
field-ref, field-distance, (setf field-ref) |
Texel (x, y) channel c is outside this field: columns run from 0 to w−1, rows from 0 to h−1 and channels from 0 to n−1. | An index too large. A negative one is a type-error. |
field-octets |
FIELD-OCTETS needs a normalized field, but this one holds raw distances. Generate it without :NORMALIZE NIL, or encode the values yourself with ENCODE-DISTANCE. | A field made with :normalize nil. |
encode-distance |
A distance of d with a spread of s encodes to a sample beyond the single-float range. Clamp it, or use a larger spread. | :clamp nil with a distance many billions of spreads from the edge. |
decode-distance |
A sample of v with a spread of s decodes to a distance beyond the double-float range. | A huge sample times a huge spread. |
Type errors
| Argument | Declared type | Must be |
|---|---|---|
width, height |
(integer 1) |
a positive integer |
:bounds |
(or null rectangle) |
nil or a list of four reals within ±1e36 |
:padding |
coordinate |
a real within ±1e36 |
:spread |
(or null (real (0) 1d36)) |
nil or a positive real up to 1e36 |
:px-spread, :flatten-tolerance of make-shape and queries, :tolerance |
(real (0) 1d36) |
a positive real up to 1e36 |
:flatten-tolerance of generators |
(or null (real (0) 1d36)) |
nil or a positive real up to 1e36 |
:fill-rule |
fill-rule |
:nonzero or :even-odd |
:y-axis |
y-axis |
:up or :down |
:angle-threshold |
(real 0 π) |
a real from 0 to π |
segment of make-colored-edge |
segment |
a segment |
color of make-colored-edge, edge-color-channels |
edge-color |
an edge-color |
x, y of queries |
coordinate |
a real within ±1e36 |
distance of encode-distance, value of decode-distance |
(real -1.79…d308 1.79…d308) |
a real within the double-float range |
spread of encode-distance, decode-distance |
(real (0) 1.79…d308) |
a positive real within the double-float range |
value of (setf field-ref) |
(real -3.40…e38 3.40…e38) |
a real within the single-float range |
| column, row, channel | (integer 0) |
a non-negative integer |
Ranges
Coordinates, bounds, padding, query points, spreads and tolerances are limited to ±1e36, the type sdf:coordinate. Within it, every distance between a shape and the points of its padded bounds stays below most-positive-single-float, the largest value a field stores, and squared distances stay far inside the double-float range. Beyond it, cl-sdf reports the argument, rather than overflowing or quietly returning the empty-shape distance. Infinities and rationals too large to convert are rejected the same way. Scale such outlines down: distances are only meaningful relative to the outline's size anyway.
What is not an error
- An empty outline, or one whose filled area is zero: fields are outside everywhere, and queries return the values in Distance Queries.
- An outline larger than the field's bounds: the field shows the part inside.
- Overlapping, self-intersecting or oppositely wound contours: resolved by the fill rule.
- Segments of zero length, and point curves: ignored by fields and signed queries.
- Open contours for
unsigned-distance.