sourcelib/Geometry3D.xtl
1⍝# Geometry3D: points in space as arrays (a standard library, built into
2⍝# xetal). Import it with an alias of your choice: "g:" u_se< "Geometry3D".
3⍝# Points are a 3-row matrix, x over y over z, one column per point, as
4⍝# []P_ATH takes 2 rows; a rotation is a 3 x 3 matrix, and turning the
5⍝# points is one inner product. A face is a 3 x 4 matrix of corners,
6⍝# and a solid is faces stacked along a new first axis (F x 3 x 4), so
7⍝# one expression orders them far to near for painting.
8⍝# Names with l: are exported; the others are private to this file.
9
10r̲adians ← { (f̲loat ⍵) × (p̲i @) ÷ 180 } ⍝ private
11
12⍝# The rotation of d degrees about the x axis (y toward z), 3 x 3.
13⍝# >> "g:" u_se< "Geometry3D"
14⍝# >> f_loor 0.5 + g:r_otX 90
15⍝# 1 0 0
16⍝# 0 0 -1
17⍝# 0 1 0
18ˡr̲otX ← { d →
19 c ← c̲os r̲adians d
20 s ← s̲in r̲adians d
21 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
22}
23
24⍝# The rotation of d degrees about the y axis (z toward x), 3 x 3.
25⍝# >> "g:" u_se< "Geometry3D"
26⍝# >> f_loor 0.5 + g:r_otY 90
27⍝# 0 0 1
28⍝# 0 1 0
29⍝# -1 0 0
30ˡr̲otY ← { d →
31 c ← c̲os r̲adians d
32 s ← s̲in r̲adians d
33 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
34}
35
36⍝# The rotation of d degrees about the z axis (x toward y), 3 x 3.
37⍝# >> "g:" u_se< "Geometry3D"
38⍝# >> f_loor 0.5 + g:r_otZ 90
39⍝# 0 -1 0
40⍝# 1 0 0
41⍝# 0 0 1
42ˡr̲otZ ← { d →
43 c ← c̲os r̲adians d
44 s ← s̲in r̲adians d
45 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
46}
47
48⍝# The points turned by a rotation (or moved by any 3 x 3 matrix):
49⍝# m ᵍt̲urn points. Rotations compose by g:t_urn too, the rightmost
50⍝# applied first: (ᵍr̲otX 30) ᵍt̲urn ᵍr̲otY 45.
51⍝# >> "g:" u_se< "Geometry3D"
52⍝# >> f_loor 0.5 + (g:r_otZ 90) g:t_urn 3 1 r_eshape 1 0 0
53⍝# 0
54⍝# 1
55⍝# 0
56ˡt̲urn ← { m points → m '+ '× i̲nner points }
57
58⍝# The points as seen by a viewer at distance d up the z axis, looking
59⍝# at the origin, as 2 rows (x over y) for []P_ATH: a nearer point (a
60⍝# larger z) is drawn farther from the center. d ᵍp̲roject points.
61⍝# >> "g:" u_se< "Geometry3D"
62⍝# >> 10 g:p_roject 3 2 r_eshape 1 1 1 1 0 5
63⍝# 1.0 2.0
64⍝# 1.0 2.0
65ˡp̲roject ← { d points →
66 scale ← (f̲loat d) ÷ (f̲loat d) − 3 s̲elect points
67 (2 t̲ake points) × (2 c̲at t̲ally scale) r̲eshape scale
68}
69
70⍝# How near each face of a solid is to the viewer: the mean z of its
71⍝# corners, one number per face (F x 3 x 4 to F); larger is nearer.
72⍝# >> "g:" u_se< "Geometry3D"
73⍝# >> g:f_ar 2 3 1 r_eshape 0 0 -3 0 0 2
74⍝# -3.0 2.0
75ˡf̲ar ← { faces → (f̲loat '+ r̲/ o̲\ 3 s̲elect₂ faces) ÷ f̲loat 1 s̲elect r̲ev s̲hape faces }
76
77⍝# The faces of a solid from the farthest to the nearest, as positions
78⍝# (the order to draw them in, so nearer faces cover farther ones).
79⍝# >> "g:" u_se< "Geometry3D"
80⍝# >> g:o_rder 2 3 1 r_eshape 0 0 2 0 0 -3
81⍝# 2 1
82ˡo̲rder ← { faces → g̲rade ˡf̲ar faces }
83
84⍝# The 8 corners of a cube of side s centered on the origin, 3 x 8, in
85⍝# the order near face (z = s/2, toward the viewer) then far face, each
86⍝# anticlockwise from the top left.
87⍝# >> "g:" u_se< "Geometry3D"
88⍝# >> s_hape g:c_ube 2
89⍝# 3 8
90ˡc̲ube ← { s →
91 h ← (f̲loat s) ÷ 2
92 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
93}
94
95⍝# The six faces of the cube corners g:c_ube gives, as corner positions,
96⍝# 6 x 4: front, back, top, bottom, left, right.
97⍝# >> "g:" u_se< "Geometry3D"
98⍝# >> 1 s_elect g:c_ubeFaces @
99⍝# 1 2 3 4
100ˡ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 }
101
102⍝# One face of a solid's points: the corners at the given positions,
103⍝# as a 3 x n matrix. positions ᵍf̲ace points.
104⍝# >> "g:" u_se< "Geometry3D"
105⍝# >> 1 2 g:f_ace g:c_ube 2
106⍝# -1.0 1.0
107⍝# 1.0 1.0
108⍝# 1.0 1.0
109ˡf̲ace ← { positions points → positions s̲elect₂ points }
110
111⍝# Every face of a solid as corners: F x 3 x n from the points and the
112⍝# F x n positions of g:c_ubeFaces. faces ᵍs̲olid points.
113⍝# >> "g:" u_se< "Geometry3D"
114⍝# >> s_hape (g:c_ubeFaces @) g:s_olid g:c_ube 2
115⍝# 6 3 4
116ˡs̲olid ← { faces points → 2 1 3 t̲ranspose (3 c̲at s̲hape faces) r̲eshape (r̲avel faces) s̲elect₂ points }