librarylib/Geometry3D.xtl
Geometry3D: points in space as arrays (a standard library, built into xetal). Import it with an alias of your choice: "g:" u_se< "Geometry3D". Points are a 3-row matrix, x over y over z, one column per point, as []P_ATH takes 2 rows; a rotation is a 3 x 3 matrix, and turning the points is one inner product. A face is a 3 x 4 matrix of corners, and a solid is faces stacked along a new first axis (F x 3 x 4), so one expression orders them far to near for painting. Names with l: are exported; the others are private to this file.
ˡr̲otX : Num a => a -> Float
The rotation of d degrees about the x axis (y toward z), 3 x 3.
ᵍ⁼u̲se< "Geometry3D"
f̲loor 0.5 + ᵍr̲otX 90 1 0 0 0 0 -1 0 1 0
ˡr̲otX ← { d → c ← c̲os r̲adians d s ← s̲in r̲adians d 3 3 r̲eshape 1.0 0.0 0.0 0.0 c̲at c c̲at (n̲eg s) c̲at 0.0 c̲at s c̲at c }
ˡr̲otY : Num a => a -> Float
The rotation of d degrees about the y axis (z toward x), 3 x 3.
ᵍ⁼u̲se< "Geometry3D"
f̲loor 0.5 + ᵍr̲otY 90 0 0 1 0 1 0 -1 0 0
ˡr̲otY ← { d → c ← c̲os r̲adians d s ← s̲in r̲adians d 3 3 r̲eshape c c̲at 0.0 c̲at s c̲at 0.0 1.0 0.0 c̲at (n̲eg s) c̲at 0.0 c̲at c }
ˡr̲otZ : Num a => a -> Float
The rotation of d degrees about the z axis (x toward y), 3 x 3.
ᵍ⁼u̲se< "Geometry3D"
f̲loor 0.5 + ᵍr̲otZ 90 0 -1 0 1 0 0 0 0 1
ˡr̲otZ ← { d → c ← c̲os r̲adians d s ← s̲in r̲adians d 3 3 r̲eshape c c̲at (n̲eg s) c̲at 0.0 c̲at s c̲at c c̲at 0.0 0.0 0.0 1.0 }
ˡt̲urn : Num a => a -> a -> a
The points turned by a rotation (or moved by any 3 x 3 matrix):
m ᵍt̲urn points. Rotations compose by g:t_urn too, the rightmost
applied first: (ᵍr̲otX 30) ᵍt̲urn ᵍr̲otY 45.
ᵍ⁼u̲se< "Geometry3D"
f̲loor 0.5 + (ᵍr̲otZ 90) ᵍt̲urn 3 1 r̲eshape 1 0 0 0 1 0
ˡt̲urn ← { m points → m '+ '× i̲nner points }
ˡp̲roject : Num a => a -> Float -> Float
The points as seen by a viewer at distance d up the z axis, looking
at the origin, as 2 rows (x over y) for []P_ATH: a nearer point (a
larger z) is drawn farther from the center. d ᵍp̲roject points.
ᵍ⁼u̲se< "Geometry3D"
10 ᵍp̲roject 3 2 r̲eshape 1 1 1 1 0 5 1.0 2.0 1.0 2.0
ˡp̲roject ← { d points → scale ← (f̲loat d) ÷ (f̲loat d) − 3 s̲elect points (2 t̲ake points) × (2 c̲at t̲ally scale) r̲eshape scale }
ˡf̲ar : Num a => a -> Float
How near each face of a solid is to the viewer: the mean z of its corners, one number per face (F x 3 x 4 to F); larger is nearer.
ᵍ⁼u̲se< "Geometry3D"
ᵍf̲ar 2 3 1 r̲eshape 0 0 -3 0 0 2 -3.0 2.0
ˡf̲ar ← { faces → (f̲loat '+ r̲/ o̲\ 3 s̲elect₂ faces) ÷ f̲loat 1 s̲elect r̲ev s̲hape faces }
ˡo̲rder : Num a => a -> Int
The faces of a solid from the farthest to the nearest, as positions (the order to draw them in, so nearer faces cover farther ones).
ᵍ⁼u̲se< "Geometry3D"
ᵍo̲rder 2 3 1 r̲eshape 0 0 2 0 0 -3 2 1
ˡo̲rder ← { faces → g̲rade ˡf̲ar faces }
ˡc̲ube : Num a => a -> Float
The 8 corners of a cube of side s centered on the origin, 3 x 8, in the order near face (z = s/2, toward the viewer) then far face, each anticlockwise from the top left.
ᵍ⁼u̲se< "Geometry3D"
s̲hape ᵍc̲ube 2 3 8
ˡc̲ube ← { s → h ← (f̲loat s) ÷ 2 h × 3 8 r̲eshape -1 1 1 -1 -1 1 1 -1 1 1 -1 -1 1 1 -1 -1 1 1 1 1 -1 -1 -1 -1 }
ˡc̲ubeFaces : Num a => Unit -> a
The six faces of the cube corners g:c_ube gives, as corner positions, 6 x 4: front, back, top, bottom, left, right.
ᵍ⁼u̲se< "Geometry3D"
1 s̲elect ᵍc̲ubeFaces @ 1 2 3 4
ˡc̲ubeFaces ← { @ → 6 4 r̲eshape 1 2 3 4 5 6 7 8 1 2 6 5 4 3 7 8 1 4 8 5 2 3 7 6 }
ˡf̲ace : Int -> a -> a
One face of a solid's points: the corners at the given positions,
as a 3 x n matrix. positions ᵍf̲ace points.
ᵍ⁼u̲se< "Geometry3D"
1 2 ᵍf̲ace ᵍc̲ube 2 -1.0 1.0 1.0 1.0 1.0 1.0
ˡf̲ace ← { positions points → positions s̲elect₂ points }
ˡs̲olid : Int -> a -> a
Every face of a solid as corners: F x 3 x n from the points and the
F x n positions of g:c_ubeFaces. faces ᵍs̲olid points.
ᵍ⁼u̲se< "Geometry3D"
s̲hape (ᵍc̲ubeFaces @) ᵍs̲olid ᵍc̲ube 2 6 3 4
ˡs̲olid ← { faces points → 2 1 3 t̲ranspose (3 c̲at s̲hape faces) r̲eshape (r̲avel faces) s̲elect₂ points }