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 23if known context_three : endinput ; fi ; 24 25boolean context_three ; context_three := true ; 26 27pair mfun_three_xy ; % this avoids the costly save and allocate 28pair mfun_three_yz ; 29pair mfun_three_zx ; 30 31transform Txy ; 32 33def setTxy(expr ori, ang) = 34 begingroup 35 save P, t ; 36 pair P[] ; 37 transform t ; 38 39 P0 = ori ; % origin in MetaPost coordinates (bp) 40 P1 = (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 P0 ; % 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 P1 = (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 73enddef ; 74 75setTxy(origin,60) ; 76 77%D We already define triplet (as rgbcolor synonym) in in \type {mp-tool.mpiv}: 78 79let Xpart = redpart ; 80let Ypart = greenpart ; 81let Zpart = bluepart ; 82 83primarydef p Xscaled q = 84 (q*Xpart p, Ypart p, Zpart p) 85enddef ; 86 87primarydef p Yscaled q = 88 (Xpart p, q*Ypart p, Zpart p) 89enddef ; 90 91primarydef p Zscaled q = 92 (Xpart p, Ypart p, q*Zpart p) 93enddef ; 94 95primarydef p XYZscaled q = 96 (q*Xpart p,q*Ypart p,q*Zpart p) 97enddef ; 98 99vardef 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) 107enddef ; 108 109vardef 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 115enddef ; 116 117vardef Unitvector primary z = 118 z/Abs z 119enddef ; 120 121primarydef p dotproduct q = 122 ((Xpart p)*(Xpart q) + (Ypart p)*(Ypart q) + (Zpart p)*(Zpart q)) 123enddef ; 124 125primarydef 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 ) 131enddef ; 132 133primarydef 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) 139enddef ; 140 141primarydef 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) 147enddef ; 148 149primarydef 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) 155enddef ; 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 162vardef 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 169enddef ; 170 171%D Transform a (2D) path to a 3D plane 172 173def 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) 188enddef ; 189 190def 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) 205enddef ; 206 207def 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) 222enddef ; 223 224%D Some constants... 225 226triplet Origin, Xunitvector, Yunitvector, Zunitvector ; 227 228Origin := (0,0,0) ; 229Xunitvector := (1,0,0) ; 230Yunitvector := (0,1,0) ; 231Zunitvector := (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```