.PS # Traintracks.m4 # https://tex.stackexchange.com/questions/729226/implementing-train-tracks-in-latex gen_init define(`robustcode_',1) divert(-1) ######################################################################## `Default sizes' define(`sectionlen',linewid) define(`railgauge',(linewid/5)) define(`railthick',`1.5') define(`buttlen',`(railthick bp__ * 3)') define(`sleeperthick',`0.4') define(`buttthick',`(sleeperthick*2)') `straight(position,direction,keys) keys: length=expr; (default sectionlen) gauge=expr; (default railgauge) tiecount=expr; (number of sleepers) tie=attributes; rail=attributes;' define(`straight',`ifelse(`$1',,,move to `$1';) ifelse(`$2',,,`setdir_(`$2')') pushkeys_(`$3', `length:sectionlen:N; gauge:railgauge; rail::N; tiecount:3:; tie::N;')dnl for straighti=1 to m4tiecount do { {line from rvec_((straighti-1/2)*m4length/m4tiecount, m4gauge/2+buttlen/2) \ to rvec_((straighti-1/2)*m4length/m4tiecount,-m4gauge/2-buttlen/2) \ thick sleeperthick m4tie }} {strail(m4gauge/2)}; {strail(-m4gauge/2)}; move to rvec_(m4length,0)dnl popdef(`m4tie',`m4tiecount',`m4length',`m4gauge',`m4rail') ') define(`strail', `{line from rvec_(0,`$1') to rvec_(sectionlen,`$1') thick railthick m4rail line from rvec_(0,-buttlen/2) to rvec_(0,buttlen/2) thick buttthick} {line from rvec_(0,`$1'-buttlen/2) to rvec_(0,`$1'+buttlen/2) \ thick buttthick m4rail} ') `curve(position,direction,L|R,keys) keys: radius=expr; (default sectionlen*2) gauge=expr; (default railgauge) tiecount=expr; (number of sleepers) tie=attributes; rail=attributes; Calls to robust rvec_r instead of rvec_ are for use in pic loops' define(`curve',`ifelse(`$1',,,move to `$1';) ifelse(`$2',,,`setdir_(`$2')') pushkeys_(`$4', `radius:sectionlen*2; gauge:railgauge; rail::N; tiecount:3:; tie::N;')dnl pushdef(`m4pm',`ifelse(`$3',,+,`$3',L,+,-)')dnl M4C: rvec_r(0,m4pm m4radius) # robust rvec m4rs = rp_ang*rtod_-(m4pm 90); m4rf = m4rs m4pm 30 for curvei=1 to m4tiecount do {{ line \ from M4C+(Rect_(m4radius+m4gauge/2+buttlen/2,\ m4rs+(curvei-1/2)*(m4rf-m4rs)/m4tiecount))\ to M4C+(Rect_(m4radius-m4gauge/2-buttlen/2,\ m4rs+(curvei-1/2)*(m4rf-m4rs)/m4tiecount)) thick sleeperthick m4tie }} move to M4C+(Rect_(m4radius,m4rs)) {crail(M4C,m4radius-(m4pm m4gauge/2), m4gauge/2,m4pm)} {crail(M4C,m4radius+(m4pm m4gauge/2),-m4gauge/2,m4pm)} move to M4C+(Rect_(m4radius,m4rf)); setdir_(rp_ang*rtod_ m4pm 30) popdef(`m4tie',`m4tiecount',`m4rail',`m4gauge',`m4radius',`m4pm') ') define(`crail', #`crail(center,rad,offset,+|-)' `move to rvec_r(0,`$3'); crbuttf = buttlen/2/(`$2') {arc ifelse(`$4',-,cw) to rvec_r((`$2')/2,`$4'((1-sqrt(3)/2)*(`$2'))) \ with .c at `$1' thick railthick m4rail line from (-crbuttf between Here and `$1') \ to ( crbuttf between Here and `$1') thick buttthick} {line from (-crbuttf between Here and `$1') \ to ( crbuttf between Here and `$1') thick buttthick} ') ######################################################################## divert(0)dnl [ straight {curve; curve(,,R); straight; curve(,,R); curve; straight} for i=1 to 5 do { straight } ] [ straight for i=1 to 6 do { curve(,,R) } straight {T: Here curve(,,R,rail=outlined "red"); curve(,,,rail=outlined "red") straight crad = sectionlen*2-(Here.y-T.y) for i=1 to 6 do { curve(,,R,radius=crad) } straight define rgbpurp { rgbstring(0.5,0,1) } { curve(,,, rail=outlined rgbpurp); curve(,,R, rail=outlined rgbpurp) for i=1 to 5 do { straight(,180) } } for i=1 to 3 do { straight(,0) } for i=1 to 6 do { curve(,,R,radius=crad) } for i=1 to 3 do { straight } } for i=1 to 5 do { straight } ] with .nw at last [].sw+(0,-0.2) [ for dir=90 to 570 by 240 do { curve(,dir,,tiecount=5;tie=outlined "gray" thick 2.5) curve(, ,,tiecount=5;tie=outlined "gray" thick 2.5) } ] with .nw at 1st [].ne+(0.2,0) .PE