mp-tres.mpiv /size: 6498 b    last modification: 2021-10-28 13:50
1
%D \module
2
%D [ file=mp-tres.mpiv,
3
%D version=2017.11.08,
4
%D title=\CONTEXT\ \METAPOST\ graphics,
5
%D subtitle=Pseudo 3D,
6
%D author=Alan Braslau,
7
%D date=\currentdate,
8
%D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}]
9
%C
10
%C This module is part of the \CONTEXT\ macro||package and is
11
%C therefore copyrighted by \PRAGMA. See licen-en.pdf for
12
%C details.
13 14
%D This module provides simple 3D->2D projections. The code is an adaption of code
15
%D by Urs Oswald, Dr.sc.math.\ ETH as presented in:
16
%D
17
%D \starttyping
18
%D http://www.ursoswald.ch/metapost/tutorial.html.
19
%D \stoptyping
20
%D
21
%D We need a bit more so it got extended.
22 23
if
known
context_three
:
endinput
;
fi
;
24 25
boolean
context_three
;
context_three
:
=
true
;
26 27
pair
mfun_three_xy
;
% this avoids the costly save and allocate
28
pair
mfun_three_yz
;
29
pair
mfun_three_zx
;
30 31
transform
Txy
;
32 33
def
setTxy
(
expr
ori
,
ang
)
=
34
begingroup
35
save
P
,
t
;
36
pair
P
[
]
;
37
transform
t
;
38 39
P
0
=
ori
;
% origin in MetaPost coordinates (bp)
40
P
1
=
(
left
rotated
ang
)
scaled
(
cosd
ang
)
;
% x axis (in mathematical coordinates)
41 42
% A sort of "cavalier projection".
43 44
% t: maps mathematical 2D coordinates onto MetaPost coordinates.
45 46
t
:
=
identity
shifted
P
0
;
% Note: no shift when P0 = origin!
47 48
% Txy: maps the x-y plane of 3D space onto MetaPost coordinates,
49
% z is the vertical (MetaPost y).
50 51
% Txy:=identity
52
% reflectedabout((0,0), (1,1))
53
% yscaled ypart P1
54
% slanted (xpart P1/ypart P1)
55
% transformed t ;
56 57
% Alternatively, defined via Pxy:
58 59
% Pxy is the projection of the 3D plane z=0 onto the mathematical 2D coordinates.
60
% Pxy is determined by 3 e q u a t i o n s describing
61
% how (1,0), (0,1), and (0,0) are mapped
62 63
save
Pxy
;
64
transform
Pxy
;
65
P
1
=
(
1
,
0
)
transformed
Pxy
;
% Pxy: (1,0) --> P1
66
(
1
,
0
)
=
(
0
,
1
)
transformed
Pxy
;
% (0,1) --> (1,0)
67
(
0
,
0
)
=
(
0
,
0
)
transformed
Pxy
;
% (0,0) --> (0,0)
68 69
% mathematical 2D coordinates --> MetaPost coordinates
70 71
Txy
:
=
Pxy
transformed
t
;
72
endgroup
73
enddef
;
74 75
setTxy
(
origin
,
60
)
;
76 77
%D We already define triplet (as rgbcolor synonym) in in \type {mp-tool.mpiv}:
78 79
let
Xpart
=
redpart
;
80
let
Ypart
=
greenpart
;
81
let
Zpart
=
bluepart
;
82 83
primarydef
p
Xscaled
q
=
84
(
q
*
Xpart
p
,
Ypart
p
,
Zpart
p
)
85
enddef
;
86 87
primarydef
p
Yscaled
q
=
88
(
Xpart
p
,
q
*
Ypart
p
,
Zpart
p
)
89
enddef
;
90 91
primarydef
p
Zscaled
q
=
92
(
Xpart
p
,
Ypart
p
,
q
*
Zpart
p
)
93
enddef
;
94 95
primarydef
p
XYZscaled
q
=
96
(
q
*
Xpart
p
,
q
*
Ypart
p
,
q
*
Zpart
p
)
97
enddef
;
98 99
vardef
projection
primary
t
=
100
(
if
triplet
t
:
101
(
Xpart
t
,
Ypart
t
)
transformed
Txy
shifted
(
0
,
Zpart
t
)
102
elseif
pair
t
:
103
t
transformed
Txy
104
else
:
105
origin
transformed
Txy
106
fi
)
107
enddef
;
108 109
vardef
Abs
primary
p
=
110
if
triplet
p
:
111
sqrt
(
(
Xpart
p
)
*
*
2
+
(
Ypart
p
)
*
*
2
+
(
Zpart
p
)
*
*
2
)
112
else
:
113
length
p
114
fi
115
enddef
;
116 117
vardef
Unitvector
primary
z
=
118
z
/
Abs
z
119
enddef
;
120 121
primarydef
p
dotproduct
q
=
122
(
(
Xpart
p
)
*
(
Xpart
q
)
+
(
Ypart
p
)
*
(
Ypart
q
)
+
(
Zpart
p
)
*
(
Zpart
q
)
)
123
enddef
;
124 125
primarydef
p
crossproduct
q
=
126
(
127
(
Ypart
p
)
*
(
Zpart
q
)
-
(
Zpart
p
)
*
(
Ypart
q
)
,
128
(
Zpart
p
)
*
(
Xpart
q
)
-
(
Xpart
p
)
*
(
Zpart
q
)
,
129
(
Xpart
p
)
*
(
Ypart
q
)
-
(
Ypart
p
)
*
(
Xpart
q
)
130
)
131
enddef
;
132 133
primarydef
p
rotatedaboutX
q
=
134
hide
(
135
mfun_three_yz
:
=
(
Ypart
p
,
Zpart
p
)
;
136
mfun_three_yz
:
=
mfun_three_yz
rotated
q
;
137
)
138
(
Xpart
p
,
xpart
mfun_three_yz
,
ypart
mfun_three_yz
)
139
enddef
;
140 141
primarydef
p
rotatedaboutY
q
=
142
hide
(
143
mfun_three_zx
:
=
(
Zpart
p
,
Xpart
p
)
;
144
mfun_three_zx
:
=
mfun_three_zx
rotated
q
;
145
)
146
(
ypart
mfun_three_zx
,
Ypart
p
,
xpart
mfun_three_zx
)
147
enddef
;
148 149
primarydef
p
rotatedaboutZ
q
=
150
hide
(
151
mfun_three_xy
:
=
(
Xpart
p
,
Ypart
p
)
;
152
mfun_three_xy
:
=
mfun_three_xy
rotated
q
;
153
)
154
(
xpart
mfun_three_xy
,
ypart
mfun_three_xy
,
Zpart
p
)
155
enddef
;
156 157
%D We can use a rotation about an arbitrary direction t ... (easy)
158 159
% primarydef p rotatedabout(expr t, a) =
160
% enddef ;
161 162
vardef
draw_vector
@#
(
expr
v
,
s
)
text
t
=
163
if
triplet
v
:
164
drawarrow
projection
(
Origin
)
--
projection
(
v
)
t
;
165
if
string
s
:
166
label
@#
(
s
,
projection
(
v
)
)
t
;
167
fi
168
fi
169
enddef
;
170 171
%D Transform a (2D) path to a 3D plane
172 173
def
XYpath
primary
p
=
174
(
for
i
=
0
upto
(
length
p
)
if
cycle
p
:
-1
fi
:
175
if
i
>
0
:
..
fi
176
projection
(
xpart
point
i
of
p
,
177
ypart
point
i
of
p
,
178
0
)
179
.
.
controls
180
projection
(
xpart
postcontrol
i
of
p
,
181
ypart
postcontrol
i
of
p
,
182
0
)
183
and
184
projection
(
xpart
precontrol
(
i
+1
)
of
p
,
185
ypart
precontrol
(
i
+1
)
of
p
,
186
0
)
187
endfor
if
cycle
p
:
.
.
cycle
fi
)
188
enddef
;
189 190
def
XZpath
primary
p
=
191
(
for
i
=
0
upto
(
length
p
)
if
cycle
p
:
-1
fi
:
192
if
i
>
0
:
..
fi
193
projection
(
xpart
point
i
of
p
,
194
0
,
195
ypart
point
i
of
p
)
196
.
.
controls
197
projection
(
xpart
postcontrol
i
of
p
,
198
0
,
199
ypart
postcontrol
i
of
p
)
200
and
201
projection
(
xpart
precontrol
(
i
+1
)
of
p
,
202
0
,
203
ypart
precontrol
(
i
+1
)
of
p
)
204
endfor
if
cycle
p
:
.
.
cycle
fi
)
205
enddef
;
206 207
def
YZpath
primary
p
=
208
(
for
i
=
0
upto
(
length
p
)
if
cycle
p
:
-1
fi
:
209
if
i
>
0
:
..
fi
210
projection
(
0
,
211
xpart
point
i
of
p
,
212
ypart
point
i
of
p
)
213
.
.
controls
214
projection
(
0
,
215
xpart
postcontrol
i
of
p
,
216
ypart
postcontrol
i
of
p
)
217
and
218
projection
(
0
,
219
xpart
precontrol
(
i
+1
)
of
p
,
220
ypart
precontrol
(
i
+1
)
of
p
)
221
endfor
if
cycle
p
:
.
.
cycle
fi
)
222
enddef
;
223 224
%D Some constants...
225 226
triplet
Origin
,
Xunitvector
,
Yunitvector
,
Zunitvector
;
227 228
Origin
:
=
(
0
,
0
,
0
)
;
229
Xunitvector
:
=
(
1
,
0
,
0
)
;
230
Yunitvector
:
=
(
0
,
1
,
0
)
;
231
Zunitvector
:
=
(
0
,
0
,
1
)
;
232 233
%D We could do but don't:
234 235
% let normalxpart = xpart ;
236
% let normalypart = ypart ;
237 238
% vardef xpart expr p = if triplet p : redpart else : normalxpart fi p enddef ;
239
% vardef ypart expr p = if triplet p : greenpart else : normalypart fi p enddef ;
240
% vardef zpart expr p = bluepart p enddef ;
241 242