### 5Geometry

 (require sfont/geometry) package: sfont

This is the module for vector operations, transformations and bezier paths.

 value
Generic interface that defines methods for geometric transformations.

 parameter (precision p) → void? p : real?
A parameter that controls rounding.

 procedure(approx n) → real? n : real?
Approximate the numbers with the precision defined by precision.

 struct(struct vec (x y)) x : real? y : real?
A structure that represents a 2D vector. A vec implements the gen:geometric interface.

 struct(struct vec3 (x y z)) x : real? y : real? z : real?
A structure that represents a 3D vector.

 procedure(vec3->vec v) → vec? v : vec3?
 procedure(vec->vec3 v) → vec3? v : vec?
Conversion between 3D and 2D vcectors.

 struct(struct trans-mat (x xy yx y x-offset y-offset)) x : real? xy : real? yx : real? y : real? x-offset : real? y-offset : real?
A transformation matrix. A trans-mat implements the gen:geometric interface.

 procedure o : any/c
A predicate for structures that implement the generic group gen:geometric

 procedure(transform o m) → geometric? o : geometric? m : trans-mat?
Applies the trasformation matrix to the object.

 procedure(translate o x y) → geometric? o : geometric? x : real? y : real?
Applies the translation to the object.

 procedure(rotate o angle) → geometric? o : geometric? angle : real?
Applies the rotation to the object.

 procedure(scale o fx [fy]) → geometric? o : geometric? fx : real? fy : real? = fx
Scales the object.

 procedure(skew-x o angle) → geometric? o : geometric? angle : real?
Applies a shear transformation to the object.

 procedure(skew-y o angle) → geometric? o : geometric? angle : real?
Applies a shear transformation to the object.

 procedure o : geometric?
Reflects the object around the x axis.

 procedure o : geometric?
Reflects the object around the y axis.

 procedure(vec= v1 v2) → boolean? v1 : vec? v2 : vec?
True if the x and y coordinates of the vectors are equal.

 procedure(vec-approx= v1 v2) → boolean? v1 : vec? v2 : vec?
True if the x and y coordinates of the vectors are approximately equal (using the precision parameter).

 procedure(list->vec l) → vec? l : (list/c real? real?)
Produces a vec from a list of two numbers.

 procedure v : vec?
Produces a list of two numbers from a vec.

 procedure v : vec?
Produces the length of the vector.

 procedure(vec-angle v) → real? v : vec?
Produces the angle of the vector.

 procedure(vec+ v1 v2) → vec? v1 : vec? v2 : vec?
Sum two vectors.

 procedure(vec- v1 v2) → vec? v1 : vec? v2 : vec?
Subtract two vectors.

 procedure(vec* v1 n) → vec? v1 : vec? n : real?
Scalar multiplications.

 procedure(vec/ v1 n) → vec? v1 : vec? n : real?
Scalar division.

 procedure(aligned? v1 v2 v3) → boolean? v1 : vec? v2 : vec? v3 : vec?
True if the vectors v1, v1 and v1 are aligned.

 procedure x : real? y : real?
Produces a translation matrix.

 procedure(rotation-matrix angle) → trans-mat? angle : real?
Produces a rotation matrix.

 procedure(scale-matrix fx [fy]) → trans-mat? fx : real? fy : real? = fx
Produces a scale matrix.

 procedure x : real? y : real?
Produces a shear matrix.

 procedure(trans-mat* m1 m2) → trans-mat? m1 : trans-mat? m2 : trans-mat?
Multiplies two transformation matrices.

 procedure(trans-mat-vec* m v) → vec3? m : trans-mat? v : vec3?
Multiplies the translation matrix and the 3D vector.

 procedure(dot-prod v1 v2) → real? v1 : vec? v2 : vec?
Produces the dot product of two 2D vectors.

 procedure(dot-prod-3 v1 v2) → real? v1 : vec3? v2 : vec3?
Produces the dot product of two 3D vectors.

 procedure(cross-prod-2d v1 v2) → real? v1 : vec? v2 : vec?
The third scalar component of the cross product.

 procedure(segment-intersection v1 v2 v3 v4) → (or/c vec? #f) v1 : vec? v2 : vec? v3 : vec? v4 : vec?
The intersection (if any) between the segments v1-v2 and v3-v4.

 procedure(signed-area v1 v2) → real? v1 : vec? v2 : vec?
The signed area of the triangle formed by the two vectors. Positive if the angle between vectors is counter-clockwise.

 procedure lov : (listof vec?)
The signed area of the polygon formed by the list of vectors. Positive if counter-clockwise.

 procedure(intersect-hor h v1 v2) → (or/c vec? #f) h : real? v1 : vec? v2 : vec?
Produces the intersection (if any) between the horizontal line passing from (0, h) and the line segment v1-v2.

 procedure(intersect-vert v v1 v2) → (or/c vec? #f) v : real? v1 : vec? v2 : vec?
Produces the intersection (if any) between the vertical line passing from (v, 0) and the line segment v1-v2.

 procedure(pass-through-hor? h v1 v2) → boolean? h : real? v1 : vec? v2 : vec?
True if the line segment v1-v2 intersects horizontal line passing from (0, h).

 procedure(pass-through-vert? v v1 v2) → boolean? v : real? v1 : vec? v2 : vec?
True if the line segment v1-v2 intersects the vertical line passing from (v, 0).

#### 5.1Bezier Curves

In Sfont a ’bezier path’ is a list of vec, a segment is a bezier path with only two ’on-curve’ points.

 value
 value
 value
 value
 value

 procedure(closed? b) → boolean? b : bezier/c
True if the first and last points coincide.

 procedure(segments b [o]) → (listof segment/c) b : bezier/c o : natural-number/c = 3
’Explodes’ a path in a list of segments. The optional arguments declares the ’order’ of the bezier path (basically: the number of control points for each segments plus one, cubic beziers have two points, quadratic one, etc.

 procedure(on-curve-points b [o]) → (listof vec?) b : bezier/c o : natural-number/c = 3
Produce a list of points removing all the control points from the bezier.

 procedure(off-curve-points b [o]) → (listof vec?) b : bezier/c o : natural-number/c = 3
Produce a list of control points of the bezier path.

 procedure(end-points b) → (cons/c vec? vec?) b : bezier/c
Produce a pair with the first and last point of the path.

 procedure s : segment/c
True if the segment represents a line (ie. the points are aligned)

 procedure s : cubic-segment/c
Produces a cubic line segment where control points are placed at the extrema.

procedure

(split s t)
 segment/c segment/c
s : segment/c
t : (real-in 0 1)
Splits the segment in two parts. If t is 0 or 1 the first/second half is an empty list.

procedure

(split-at-point s v)
 segment/c segment/c
s : segment/c
v : vec?
Like split but try to split the path near the point provided.

 procedure(join-beziers b1 b ...) → bezier/c b1 : bezier/c b : bezier/c
Concatenate bezier paths. If the last and first points of two consecutive paths are not vec-approx= an error is raised.

 procedure(point-at s t) → vec? s : segment/c t : (real-in 0 1)
Find the point on a segment at ’time’ t.

 procedure(polygonize-segment s n) → (listof vec?) s : segment/c n : natural-number/c
Transform the segment in a polygon with n sides.

 procedure s : segment/c
Produces the bounding box of the line segment that joins the endpoints of the bezier segment.

 procedure s : segment/c
True if the bounding-box of the segment and end-points-bounding-box are the same.

 procedure s : segment/c
Produces the bounding-box of the segment.

 procedure b : bezier/c o : natural-number/c = 3
Produces the bounding-box of the bezier path.

 procedure(bezier-signed-area b [o s]) → real? b : bezier/c o : natural-number/c = 3 s : natural-number/c = 200
The area of the bezier path of order o. The path will be trasformed in a polygon, s controls in how many sides every segment is divided. Positive if the path is counter-clockwise.

 procedure(bezier-area b [o s]) → (and/c real? positive?) b : bezier/c o : natural-number/c = 3 s : natural-number/c = 200
The absolute value of bezier-signed-area.

 procedure b : bezier/c
True if the path is clockwise.

 procedure b : bezier/c
Reverses the path if it isn’t clockwise.

 procedure(cubic-bezier-intersections b1 b2) → (listof vec?) b1 : cubic-bezier/c b2 : cubic-bezier/c
Produces a list of intersections between the two cubic bezier paths.

 procedure(cubic-segments-intersections s1 s2) → (listof vec?) s1 : cubic-segment/c s2 : cubic-segment/c
Produces a list of intersections between the two cubic bezier segments.

 procedure l : segment/c s : segment/c
Produces a list of intersections between the line segment and the segment.

 procedure h : real? s : segment/c
Produces a list of intersections between the bezier segment and a the horizontal line y = h.

 procedure v : real? s : segment/c
Produces a list of intersections between the bezier segment and a the vertical line x = v.

 procedure h : real? s : segment/c
Produces a list of intersections between the bezier path and a the horizontal line y = h.

 procedure v : real? s : segment/c
Produces a list of intersections between the bezier path and a the vertical line x = v.

 procedure h : real? s : segment/c
Produces the bounding box of the intersections between the bezier path and a the horizontal line y = h.

 procedure v : vec? b : closed-bezier/c
True if the point is inside the bezier path.

 procedure(bezier->path b path) → (is-a?/c dc-path%) b : cubic-bezier/c path : (is-a?/c dc-path%)
Write the bezier to a dc-path%.

 procedure(print-beziers b ...) → pict? b : cubic-bezier/c
Print a graphic representation of the cubic bezier paths.

##### 5.1.1Boolean operations

 procedure(bezier-subtract b1 b2) → (listof closed-bezier/c) b1 : closed-bezier/c b2 : closed-bezier/c
Subtract the second closed bezier path from the first, produces a list of closed bezier paths.

 procedure(bezier-union b1 b2) → (listof closed-bezier/c) b1 : closed-bezier/c b2 : closed-bezier/c
Add the second closed bezier path to the first, produces a list of closed bezier paths (if the paths don’t intersect, for example, the two original paths are returned).

 procedure b1 : closed-bezier/c b2 : closed-bezier/c
Intersect the second closed bezier path with the first, produces a list of closed bezier paths.

#### 5.2Bounding Boxes

 value
A Bounding Box can be a pair of vec with the first one representing the lower left corner and the second one the upper right corner, or #f for the null Bounding Box.

 procedure(combine-bounding-boxes bb b ...) → bounding-box/c bb : bounding-box/c b : bounding-box/c
Produces the bounding box of the bounding boxes.

 procedure l : (cons/c vec? vec?)
Produces the bounding box of the line segment represented by the two vec.

 procedure v : vec? bb : bounding-box/c
True if the vec is inside the bounding box.

 procedure(overlap-bounding-boxes? bb1 bb2) → boolean? bb1 : bounding-box/c bb2 : bounding-box/c
True if the bounding boxes overlap.

 procedure(include-bounding-box? bb1 bb2) → boolean? bb1 : bounding-box/c bb2 : bounding-box/c
True if the second bounding box is surrounded by the first one.