%D \module %D [ file=mp-chem.mpiv, %D version=2009.05.13, %D title=\CONTEXT\ \METAPOST\ graphics, %D subtitle=chemicals, %D author=Hans Hagen \& Alan Braslau, %D date=\currentdate, %D copyright={PRAGMA ADE \& \CONTEXT\ Development Team}] %C %C This module is part of the \CONTEXT\ macro||package and is %C therefore copyrighted by \PRAGMA. See licen-en.pdf for %C details. %D This module is incomplete and experimental. Okay, it's not that bad but we do need %D some disclaimer. % either consistent setting or not if known context_chem : endinput ; fi ; boolean context_chem ; context_chem := true ; numeric chem_num[], % scratch chem_text_min, chem_text_max, chem_rotation, chem_adjacent, chem_stack_n, chem_substituent, chem_substituent.lft, chem_substituent.rt, chem_setting_offset, chem_text_offset, chem_center_offset, chem_dbl_offset, chem_bb_angle, chem_axis_rulethickness, chem_setting_l, chem_setting_r, chem_setting_t, chem_setting_b, chem_setting_rotation, chem_emwidth, chem_b_length, chem_front_b[] ; boolean chem_setting_axis, chem_doing_pb, chem_bd_wedge, chem_star[], chem_front[], chem_stacked[], chem_tetra[] ; string chem_previous ; path chem_path[], % scratch chem_b_path[], chem_c_path[], chem_r_path[], chem_r_path.lft[], chem_r_path.rt[] ; pair chem_origin, chem_mirror, chem_pair[], % scratch chem_sb_pair, chem_sb_pair.m, chem_sb_pair.mm, chem_sb_pair.p, chem_sb_pair.pp, chem_sb_pair.b ; picture chem_pic; % scratch % The use of dashpattern is found to dot the starting point with chem_sb_dash.m... %chem_sb_dash, chem_sb_dash.m, chem_sb_dash.p, chem_sb_dash.b, % nice hack but now redone % % picture chem_axis_color ; % % chem_axis_color := image(draw origin withcolor axiscolor) ; % so we handle all color models % % withpen pencircle scaled chem_axis_rulethickness withcolor colorpart(chem_axis_color) ; string chem_axis_color ; transform chem_t ; % scratch % debugging boolean chem_trace_nesting ; chem_trace_nesting := false ; boolean chem_trace_text ; chem_trace_text := false ; boolean chem_trace_boundingbox ; chem_trace_boundingbox := false ; chem_axis_color := "lightblue" ; chem_setting_axis := false ; chem_axis_rulethickness := 1pt ; chem_emwidth := 10pt ; % EmWidth or \the\emwidth does not work... chem_b_length := 3 chem_emwidth ; chem_text_offset := -.3chem_emwidth ; % -.71chem_emwidth ; % 1/sqrt(2) chem_center_offset := .5chem_emwidth ; chem_dbl_offset := .05 ; chem_bb_angle := angle(1,2chem_dbl_offset) ; chem_text_min := 0.75 ; chem_text_max := 1.25 ; chem_dot_factor := 2 ; % *linewidth chem_sb_pair := (0.25,0.75) ; %chem_sb_dash := dashpattern(off 0.25 on 0.5 off 0.25) ; chem_sb_pair.m := (0.25,1 ) ; %chem_sb_dash.m := dashpattern(off 0.25 on 0.75) ; chem_sb_pair.mm := (0.50,1 ) ; %chem_sb_dash.m := dashpattern(off 0.25 on 0.75) ; chem_sb_pair.p := (0 ,0.75) ; %chem_sb_dash.p := dashpattern(on 0.75 off 0.25) ; chem_sb_pair.pp := (0 ,0.50) ; %chem_sb_dash.p := dashpattern(on 0.75 off 0.25) ; chem_sb_pair.b := (0 ,1 ) ; %chem_sb_dash.b := dashpattern(on 1) ; chem_bd_wedge := true ; % according to IUPAC 2005 def chem_reset = chem_rotation := 0 ; chem_mirror := origin ; chem_adjacent := 0 ; chem_substituent := 0 ; chem_substituent.lft := 0 ; chem_substituent.rt := 0 ; chem_stack_n := 0 ; chem_doing_pb := false ; chem_origin := origin ; chem_previous := "one" ; pair chem_mark_pair[] ; enddef ; chem_reset ; newinternal numeric one, carbon, alkyl, newmanstagger, newmaneclipsed, three, four, five, six, seven, eight, nine, fivefront, sixfront, chair, boat ; vardef chem_init_some (suffix $) (expr e) = if not known chem_star[$] : chem_star[$] := false ; fi if not known chem_front[$] : chem_front[$] := false ; fi if not known chem_stacked[$] : chem_stacked[$] := false ; fi if not known chem_tetra[$] : chem_tetra[$] := false ; fi % We define all paths as closed, so that they may be indexed mod length. if path(e) : chem_b_path[$] := e if not cycle(e) : -- cycle fi ; chem_num0 := length(chem_b_path[$]) ; else : % polygon chem_num0 := e ; chem_num1 := 360/chem_num0 ; chem_b_path[$] := ( for i=0 upto chem_num0-1 : dir(if chem_star[$] : -i else : (.5-i) fi *chem_num1) -- endfor cycle ) if chem_front[$] : rotated (chem_num1-90) fi if not chem_star[$] : scaled (.5/(sind .5chem_num1)) % carbon-carbon benzene bond length scaled (1.4/1.54) fi ; fi ; if chem_front[$] and (not known chem_front_b[$]) : chem_front_b[$] := floor(.5(length chem_b_path[$])) + 1 ; fi chem_num2 := 0 ; chem_c_path[$] := reverse(fullcircle) rotated angle(point 0 of chem_b_path[$]) if not chem_star[$] : hide (for i=0 upto chem_num0-1: if abs(point i+.5 of chem_b_path[$]) < abs(point chem_num2+.5 of chem_b_path[$]) : chem_num2 := i ; fi endfor) scaled (2*(abs(point chem_num2+.5 of chem_b_path[$]) - 2chem_dbl_offset)) fi ; chem_r_path[$] := if chem_star[$] : chem_b_path[$] else : ( for i=0 upto chem_num0-1 : (unitvector point i of chem_b_path[$]) shifted point i of chem_b_path[$] -- endfor cycle ) fi ; chem_r_path.lft[$] := ( for i=0 upto chem_num0-1 : if chem_front[$] : up scaled .5 shifted point i of chem_b_path[$] elseif chem_star[$] : point i of chem_b_path[$] else : point i+1 of chem_b_path[$] rotatedabout(point i of chem_b_path[$],180) fi -- endfor cycle ) ; chem_r_path.rt[$] := ( for i=0 upto chem_num0-1 : if chem_front[$] : down scaled .5 shifted point i of chem_b_path[$] elseif chem_star[$] : point i+2 of chem_b_path[$] else : point i-1 of chem_b_path[$] rotatedabout(point i of chem_b_path[$],180) fi -- endfor cycle ) ; enddef ; % The following is used only once: def chem_init_all = begingroup save a, b, c, d, e ; numeric a, b, c, d, e ; save lft, rt ; path lft, rt ; % tetrahedrial angle a := 2angle(1,sqrt 2) ; % solve for chair 2b = 180 - .5a ; 4c = 180 - .5a ; d + e = 360 - 2a ; d = 5e ; % this is the one tunable parameter which fixes the perspective. z2 = z1 shifted dir(90+a+d) ; z3 = z2 shifted dir(270-a) ; z4 = z3 shifted dir(90+a) ; z6 = z1 shifted dir(90+a) ; z5 = z6 shifted dir(270-a) ; z4 = z1 xyscaled (-1,-1) ; z5 = z2 xyscaled (-1,-1) ; save indx ; numeric indx ; indx = 2 ; % starting value doesn't matter, really. % polygons three := incr indx ; % 3 (these numbers don't matter - they are just indices) four := incr indx ; % 4 five := incr indx ; % 5 six := incr indx ; % 6 seven := incr indx ; % 7 eight := incr indx ; % 8 nine := incr indx ; % 9 chem_init_some(three,3) ; chem_init_some(four, 4) ; chem_init_some(five, 5) ; chem_init_some(six, 6) ; chem_init_some(seven,7) ; chem_init_some(eight,8) ; chem_init_some(nine, 9) ; % star-form one := incr indx ; % 10 carbon := incr indx ; % 11 alkyl := incr indx ; % 12 newmanstagger := incr indx ; % 13 newmaneclipsed := incr indx ; % 14 chem_star[one] := true ; chem_star[carbon] := true ; chem_tetra[carbon] := true ; chem_star[alkyl] := true ; chem_tetra[alkyl] := true ; chem_star[newmanstagger] := true ; chem_tetra[newmanstagger] := true ; chem_star[newmaneclipsed] := true ; chem_tetra[newmaneclipsed] := true ; chem_stacked[newmanstagger] := true ; chem_stacked[newmaneclipsed] := true ; chem_init_some(one, 8) ; chem_init_some(carbon, dir(0)--dir(360-a)--dir(180-.5a+b)--dir(180-.5a)) ; chem_init_some(alkyl, dir(0)--dir(360-a)--dir(360-a-90)--dir(90)) ; chem_init_some(newmanstagger, dir(30)--dir(270)--dir(150)--dir(330)--dir(210)--dir(90)) ; chem_init_some(newmaneclipsed, dir(30)--dir(270)--dir(150)--dir(0)--dir(240)--dir(120)) ; % front views fivefront := incr indx ; % 15 sixfront := incr indx ; % 16 chair := incr indx ; % 17 boat := incr indx ; % 18 chem_front[fivefront] := true ; chem_front_b[fivefront] := 3 ; chem_front[sixfront] := true ; chem_front_b[sixfront] := 3 ; chem_init_some(fivefront,5) ; chem_init_some(sixfront, 6) ; % chair chem_front[chair] := true ; chem_front_b[chair] := 4 ; chem_init_some(chair, z1--z2--z3--z4--z5--z6) ; lft := dir(90-a)--down--dir(90+a+d)--down--dir(90+a)--down ; rt := up--dir(270+a)--up--dir(270-a)--up--dir(90+e) ; chem_r_path.lft[chair] := for i=0 upto 5 : point i of lft shifted point i of chem_b_path[chair] -- endfor cycle ; chem_r_path.rt[chair] := for i=0 upto 5 : point i of rt shifted point i of chem_b_path[chair] -- endfor cycle ; % boat chem_front[boat] := true ; chem_front_b[boat] := 4 ; chem_init_some(boat, for i=1 upto 4 : point i-1 of chem_b_path[sixfront] -- endfor point 2 of chem_b_path[sixfront] yscaled .5 -- point 1 of chem_b_path[sixfront] yscaled .5 ) ; lft := dir(30+.5a)--dir(330+.5a)--dir(210-.5a)--dir(150-.5a)--dir(120)--dir(60) ; rt := dir(30-.5a)--dir(330-.5a)--dir(210+.5a)--dir(150+.5a)--dir(120+a)--dir(60-a) ; chem_r_path.lft[boat] := for i=0 upto 5 : point i of lft shifted point i of chem_b_path[boat] -- endfor cycle ; chem_r_path.rt[boat] := for i=0 upto 5 : point i of rt shifted point i of chem_b_path[boat] -- endfor cycle ; endgroup enddef ; chem_init_all ; % WHY does this not work unless defined and then called? % Like most often in ConTeXt, we will trap but then silently ignore mistaken use, % unless of course the error be too harmful... % \startchemical def chem_start_structure(expr i, l, r, t, b, rotation, unit, bond, scale, offset, axis, rulethickness, axiscolor) = save chem_setting_l, chem_setting_r, chem_setting_t, chem_setting_b ; chem_emwidth := unit ; % dynamically set for each structure. chem_text_offset := -.3chem_emwidth ; % -.71chem_emwidth ; % 1/sqrt(2) chem_center_offset := .5chem_emwidth ; chem_b_length := chem_emwidth * bond * scale ; % scale (normally 1) scales the structure but not the text. if numeric l : chem_setting_l := -l ; fi if numeric r : chem_setting_r := r ; fi if numeric t : chem_setting_t := t ; fi if numeric b : chem_setting_b := -b ; fi chem_setting_rotation := rotation ; chem_setting_offset := offset ; chem_setting_axis := if boolean axis : axis else : (axis<>0) fi ; chem_axis_rulethickness := .75*(rulethickness) ; % axis 50% thinner than frame and bonds. chem_axis_color := axiscolor ; chem_reset ; enddef ; % \stopchemical vardef chem_stop_structure = % Make sure that all of the saved stack has been restored... (this was a gotcha!) forever : exitif chem_stack_n=0 ; chem_restore ; endfor currentpicture := (currentpicture shifted -chem_origin) rotated chem_setting_rotation ; save l, r, b, t ; l := min(xpart llcorner currentpicture, xpart lrcorner currentpicture) ; r := max(xpart llcorner currentpicture, xpart lrcorner currentpicture) ; b := min(ypart llcorner currentpicture, ypart ulcorner currentpicture) ; t := max(ypart llcorner currentpicture, ypart ulcorner currentpicture) ; if unknown chem_setting_l : chem_setting_l := l ; fi if unknown chem_setting_r : chem_setting_r := r ; fi if unknown chem_setting_b : chem_setting_b := b ; fi if unknown chem_setting_t : chem_setting_t := t ; fi if chem_setting_axis : % put it behind the picture chem_pic := currentpicture ; currentpicture := nullpicture ; chem_num0 := .5chem_b_length ; chem_num1 := .2chem_num0 ; % draw the axes to the bounding box of the entire structure, % not necessarily the bounding box of the final figure draw (l,0) -- (r,0) withpen pencircle scaled chem_axis_rulethickness withcolor chem_axis_color ; draw (0,b) -- (0,t) withpen pencircle scaled chem_axis_rulethickness withcolor chem_axis_color ; for i = 0 step chem_num0 until r : draw (i,-chem_num1) -- (i,chem_num1) withpen pencircle scaled chem_axis_rulethickness withcolor chem_axis_color ; endfor for i = 0 step -chem_num0 until l : draw (i,-chem_num1) -- (i,chem_num1) withpen pencircle scaled chem_axis_rulethickness withcolor chem_axis_color ; endfor for i = 0 step chem_num0 until t : draw (-chem_num1,i) -- (chem_num1,i) withpen pencircle scaled chem_axis_rulethickness withcolor chem_axis_color ; endfor for i = 0 step -chem_num0 until b : draw (-chem_num1,i) -- (chem_num1,i) withpen pencircle scaled chem_axis_rulethickness withcolor chem_axis_color ; endfor addto currentpicture also chem_pic ; fi ; if chem_trace_boundingbox : fill boundingbox currentpicture withcolor blue withtransparency(1,.25) ; fi ; setbounds currentpicture to ((chem_setting_l,chem_setting_b) -- (chem_setting_r,chem_setting_b) -- (chem_setting_r,chem_setting_t) -- (chem_setting_l,chem_setting_t) -- cycle) ; if chem_trace_boundingbox : fill boundingbox currentpicture withcolor red withtransparency(1,.25) ; fi ; enddef ; % \chemical vardef chem_start_component = enddef ; vardef chem_stop_component = enddef ; vardef chem_pb = % PB : if chem_trace_nesting : draw boundingbox currentpicture withpen pencircle scaled 1mm withcolor chem_axis_color ; draw origin withpen pencircle scaled 2mm withcolor chem_axis_color ; fi ; chem_doing_pb := true ; enddef ; vardef chem_pe = % PE if chem_trace_nesting : draw boundingbox currentpicture withpen pencircle scaled .5mm withcolor red ; draw origin withpen pencircle scaled 1mm withcolor red ; fi ; currentpicture := currentpicture shifted -chem_origin ; if chem_trace_nesting : draw origin withpen pencircle scaled .5mm withcolor green ; fi ; chem_origin := origin ; chem_doing_pb := false ; enddef ; vardef chem_do (expr pos) = if (unknown chem_doing_pb) or (not chem_doing_pb) : pos else : chem_doing_pb := false ; currentpicture := currentpicture shifted -pos ; chem_origin := chem_origin shifted -pos ; origin % nullpicture fi enddef ; picture chem_stack_p[] ; pair chem_stack_origin[], chem_stack_mirror[] ; numeric chem_stack_rotation[] ; string chem_stack_previous[] ; vardef chem_save = % SAVE chem_stack_p [incr chem_stack_n] := currentpicture ; chem_stack_origin [ chem_stack_n] := chem_origin ; chem_origin := origin ; chem_stack_rotation[ chem_stack_n] := chem_rotation ; chem_stack_mirror [ chem_stack_n] := chem_mirror ; chem_stack_previous[ chem_stack_n] := chem_previous ; currentpicture := nullpicture ; enddef ; vardef chem_restore = % RESTORE if chem_stack_n>0 : currentpicture := currentpicture shifted -chem_origin ; addto chem_stack_p [chem_stack_n] also currentpicture ; currentpicture := chem_stack_p [chem_stack_n] ; chem_stack_p[chem_stack_n] := nullpicture ; chem_origin := chem_stack_origin [chem_stack_n] ; chem_rotation := chem_stack_rotation[chem_stack_n] ; chem_mirror := chem_stack_mirror [chem_stack_n] ; chem_previous := chem_stack_previous[chem_stack_n] ; chem_stack_n := chem_stack_n - 1 ; fi ; enddef ; % chem_adj and chem_sub are to be followed by chem_set(n) which does all the work... vardef chem_adj (suffix $) (expr d, s) = % ADJ % scale s is ignored (for now?) if not chem_front[$] : chem_substituent := 0 ; chem_substituent.lft := 0 ; chem_substituent.rt := 0 ; chem_adjacent := d ; fi enddef ; vardef chem_lsub (suffix $) (expr d, s) = % LSUB chem_sub.lft($,d,s) ; enddef ; vardef chem_rsub (suffix $) (expr d, s) = % RSUB chem_sub.rt ($,d,s) ; enddef ; vardef chem_sub@# (suffix $) (expr d, s) = % SUB % scale s is ignored (for now?) chem_adjacent := 0 ; chem_substituent := 0 ; chem_substituent.lft := 0 ; chem_substituent.rt := 0 ; % then : chem_substituent@# := d ; enddef ; def chem_transformed (suffix $) = % not vardef! scaled chem_b_length if not chem_front[$] : if chem_mirror<>origin : reflectedabout(origin,chem_mirror) fi rotated chem_rotation fi enddef ; % vardef chem_draw (expr what, r, c) (text extra) = % draw what % withpen pencircle scaled r % withcolor c % extra ; % enddef ; vardef chem_draw (expr what, r, c) (text extra) = draw what withpen pencircle scaled r if string c : if c <> "" : withcolor c fi else : withcolor c fi extra ; enddef ; vardef chem_fill (expr what, r, c) (text extra) = fill what withpen pencircle scaled r withcolor c extra ; enddef ; vardef chem_drawarrow (expr what, r, c) (text extra) = drawarrow what withpen pencircle scaled r withcolor c extra ; enddef ; vardef chem_set (suffix $) = forsuffixes P = scantokens chem_previous : % This is a fairly complicated optimization and ajustement. It took some % thinking to get right, so beware! % And then even more time fixing a bug of a rotation +- half the symmetry % angle of a structure depending on the scale and/or the font size % (through chem_b_length). % first save the symmetry angle of the structure (as in chem_rot): chem_num0 := if chem_stacked[$] : 3 else : 0 fi ; chem_num9 := if chem_tetra[$] : 360 else : abs(angle(point 0+chem_num0 of chem_b_path[$]) - angle(point 1+chem_num0 of chem_b_path[$])) fi ; if (chem_adjacent<>0) and chem_star[P] and chem_star[$] : % nop chem_adjacent := 0 ; elseif (chem_adjacent<>0) and (chem_front[P] or chem_front[$]) : % not allowed for FRONT chem_adjacent := 0 ; elseif chem_adjacent<>0 : chem_substituent := 0 ; chem_substituent.lft := 0 ; chem_substituent.rt := 0 ; % move to the bond midpoint of the first structure chem_pair0 := center ( if chem_star[P] : origin -- point (chem_adjacent-1) else : subpath (chem_adjacent-1,chem_adjacent) fi of chem_b_path[P] ) chem_transformed(P) ; % find the closest opposite bond of the second structure chem_pair1 := chem_pair0 rotated if chem_star[P] : 90 else : 180 fi ; chem_num0 := abs(chem_pair1) ; chem_num1 := if chem_tetra[$] : 1 else : length chem_b_path[$] fi ; % only consider even indices (cardinal points) for ONE chem_num2 := if chem_star[$] and not chem_tetra[$] : 2 else : 1 fi ; for i=0 step chem_num2 until chem_num1 : chem_pair2 := ( ( unitvector center ( if chem_star[$] : origin -- point i else : subpath (i,i+1) fi of chem_b_path[$]) ) scaled chem_num0 ) chem_transformed($) ; if i=0 : chem_pair3 := chem_pair2 ; chem_num3 := 0 ; elseif (abs(chem_pair1 shifted -chem_pair2)) < (abs(chem_pair1 shifted -chem_pair3)) : chem_pair3 := chem_pair2 ; chem_num3 := i ; fi endfor if chem_star[$] : chem_pair4 := chem_pair0 shifted -((point (chem_adjacent-1) of chem_b_path[P]) chem_transformed(P)) ; fi % adjust the bond angles chem_num4 := (angle(chem_pair1)-angle(chem_pair3)) zmod chem_num9 ; chem_rotation := chem_rotation + chem_num4 ; if not chem_star[$] : chem_pair4 := if chem_star[P] : (point chem_num3 else : center(subpath (chem_num3,chem_num3+1) fi of chem_b_path[$]) chem_transformed($) ; fi if not chem_star[P] : chem_pair4 := chem_pair4 shifted -chem_pair0 ; fi currentpicture := currentpicture shifted chem_pair4 ; chem_origin := chem_origin shifted chem_pair4 ; chem_adjacent := 0 ; fi ; % Insure that only one, if any, will be nonzero if ((chem_substituent <> 0) and (chem_substituent.lft <> 0)) or ((chem_substituent <> 0) and (chem_substituent.rt <> 0)) or ((chem_substituent.lft <> 0) and (chem_substituent.rt <> 0)) : chem_substituent := 0 ; chem_substituent.lft := 0 ; chem_substituent.rt := 0 ; fi if (chem_substituent <> 0) or (chem_substituent.lft <> 0) or (chem_substituent.rt <> 0) : % move origin to radical endpoint of the first structure if chem_substituent.lft > 0 : chem_pair0 := point chem_substituent.lft-1 of chem_r_path.lft[P] ; chem_substituent := chem_substituent.lft ; chem_substituent.lft := 0 ; elseif chem_substituent.rt > 0 : chem_pair0 := point chem_substituent.rt-1 of chem_r_path.rt[P] ; chem_substituent := chem_substituent.rt ; chem_substituent.rt := 0 ; else : chem_pair0 := point chem_substituent-1 of chem_r_path[P] ; fi chem_pair1 := chem_pair0 if not chem_star[P] : shifted -(point chem_substituent-1 of chem_b_path[P]) fi ; chem_t := identity chem_transformed(P) ; chem_pair0 := chem_pair0 transformed chem_t ; % radical chem_pair1 := chem_pair1 transformed chem_t ; % recentered (see below) currentpicture := currentpicture shifted -chem_pair0 ; chem_origin := chem_origin shifted -chem_pair0 ; if (not (chem_star[P] and chem_star[$])) or chem_tetra[P] or chem_tetra[$] : if chem_tetra[P] and chem_tetra[$] and ((chem_substituent=1) or (chem_substituent=2)): chem_rotation := (chem_rotation + 180) mod 360 ; % trans-alkane chem_pair2 := (point .5 of chem_b_path[$]) ; % bisector, not chem_transformed if chem_mirror=origin : chem_mirror := chem_pair2 ; else : chem_num0 := angle(chem_mirror)-angle(chem_pair2) ; if (chem_num0>0) and (chem_num0> 180) : chem_num0 := 360 - chem_num0 ; elseif (chem_num0<0) and (chem_num0<-180) : chem_num0 := -360 - chem_num0 ; fi chem_rotation := (chem_rotation + 2chem_num0) mod 360 ; chem_mirror := origin ; fi fi chem_t := identity chem_transformed($) ; chem_pair1 := chem_pair1 rotated 180 ; % opposite direction of radical bond % find the closest node chem_num0 := abs(chem_pair1) ; % distance % search to find the nearest node of $; only consider 1 and 2 for CARBON,ALKYL chem_num1 := if chem_tetra[$] : 1 else : length chem_b_path[$] fi ; % only consider even indices (cardinal points) for ONE chem_num2 := if chem_star[$] and not chem_tetra[$] : 2 else : 1 fi ; for i=0 step chem_num2 until chem_num1 : chem_pair2 := (unitvector(point i of chem_b_path[$]) scaled chem_num0) transformed chem_t ; if i=0 : chem_pair3 := chem_pair2 ; chem_num3 := 0 ; elseif (abs(chem_pair1 shifted -chem_pair2)) < (abs(chem_pair1 shifted -chem_pair3)) : chem_pair3 := chem_pair2 ; chem_num3 := i ; fi endfor if not chem_front[$] : % adjust rotation chem_num4 := angle(chem_pair1)-angle(chem_pair3) ; chem_rotation := (chem_rotation + chem_num4) mod 360 ; fi ; chem_t := identity chem_transformed($) ; chem_pair4 := (point chem_num3 of chem_b_path[$]) transformed chem_t ; if not chem_star[$] : currentpicture := currentpicture shifted chem_pair4 ; chem_origin := chem_origin shifted chem_pair4 ; fi if not chem_front[$] : % adjust rotation chem_rotation := chem_rotation zmod chem_num9 ; fi fi chem_substituent := 0 ; fi ; endfor chem_previous := str $ ; enddef ; % line (f_rom, t_o, r_ule, c_olor) vardef chem_b@# (suffix $) (expr f, t, r, c) = % B if chem_star[$] : chem_r@#($,f,t,r,c) ; elseif length(str @#)>0 : chem_sb@#($,f,t,r,c) ; else : chem_draw( (subpath (f-1,t) of chem_b_path[$]) chem_transformed($), r,c,) ; fi enddef ; vardef chem_sb@# (suffix $) (expr f, t, r, c) = % SB if chem_star[$] : chem_sr@#($,f,t,r,c) ; else : %chem_draw( % (subpath (f-1,t) of chem_b_path[$]) chem_transformed($), % r,c,dashed chem_sb_dash@# scaled chem_b_length) ; chem_t := identity chem_transformed($) ; for i=f upto t : chem_draw( (subpath (chem_sb_pair@# shifted (i-1,i-1)) of chem_b_path[$]) transformed chem_t, r,c,) ; endfor fi enddef ; vardef chem_sd@# (suffix $) (expr f, t, r, c) = % SD if chem_star[$] : chem_rd@#($,f,t,r,c) ; else : chem_t := identity chem_transformed($) ; for i=f upto t : chem_draw( (subpath (chem_sb_pair@# shifted (i-1,i-1)) of chem_b_path[$]) transformed chem_t, r,c,dashed evenly) ; endfor fi enddef ; vardef chem_r_fragment@# (suffix $) (expr i) = ( if chem_star[$] : origin else : point i-1 of chem_b_path[$] fi -- point i-1 of chem_r_path@#[$] ) % no ; enddef ; vardef chem_r@# (suffix $) (expr f, t, r, c) = % R if length(str @#)>0 : chem_sr@#($,f,t,r,c) ; else : chem_sr.b($,f,t,r,c) ; fi enddef ; vardef chem_er@# (suffix $) (expr f, t, r, c) = % ER if length(str @#)>0: chem_dr@#($,f,t,r,c) ; else : chem_dr.b($,f,t,r,c) ; fi enddef ; vardef chem_dr@# (suffix $) (expr f, t, r, c) = % DR if not chem_front[$] : chem_t := identity chem_transformed($) ; for i=f upto t : chem_path0 := (subpath chem_sb_pair@# of chem_r_fragment($,i)) ; chem_draw( (chem_path0 paralleled chem_dbl_offset) transformed chem_t, r,c,) ; chem_draw( (chem_path0 paralleled -chem_dbl_offset) transformed chem_t, r,c,) ; endfor fi enddef ; vardef chem_lr@# (suffix $) (expr f, t, r, c) = % LR if length(str @#)>0 : chem_lsr@#($,f,t,r,c) ; else : chem_lsr.b($,f,t,r,c) ; fi enddef ; vardef chem_rr@# (suffix $) (expr f, t, r, c) = % RR if length(str @#)>0 : chem_rsr@#($,f,t,r,c) ; else : chem_rsr.b($,f,t,r,c) ; fi enddef ; vardef chem_eb@# (suffix $) (expr f, t, r, c) = % EB if not chem_star[$] : %chem_draw( % ((subpath (f-1,t) of chem_b_path[$]) paralleled -2chem_dbl_offset) % chem_transformed($), % r,c,dashed chem_sb_dash scaled chem_b_length) ; for i=f upto t : chem_t := identity chem_transformed($) ; chem_draw( ((subpath (chem_sb_pair@# shifted (i-1,i-1)) of chem_b_path[$]) paralleled -2chem_dbl_offset) transformed chem_t, r,c,) ; endfor fi enddef ; vardef chem_ad@# (suffix $) (expr f, t, r, c) = % AD chem_t := identity chem_transformed($) ; for i=f upto t : chem_drawarrow( ( (subpath if chem_star[$] : chem_sb_pair@# of chem_r_fragment($,i) ) paralleled 5chem_dbl_offset else : (chem_sb_pair@# shifted (i-1,i-1)) of chem_b_path[$] ) paralleled 2chem_dbl_offset fi ) transformed chem_t, r,c,) ; endfor enddef ; vardef chem_au@# (suffix $) (expr f, t, r, c) = % AU chem_t := identity chem_transformed($) ; for i=f upto t : chem_drawarrow( ((reverse subpath if chem_star[$] : chem_sb_pair@# of chem_r_fragment($,i) ) paralleled -5chem_dbl_offset else : (chem_sb_pair@# shifted (i-1,i-1)) of chem_b_path[$] ) paralleled -2chem_dbl_offset fi ) transformed chem_t, r,c,) ; endfor enddef ; vardef chem_es@# (suffix $) (expr f, t, r, c) = % ES if chem_star[$] : chem_t := identity chem_transformed($) ; for i=f upto t : chem_draw( ((point i-1 of chem_r_path[$]) scaled (xpart chem_sb_pair)) transformed chem_t, chem_dot_factor*r,c,) ; endfor fi enddef ; vardef chem_ed@# (suffix $) (expr f, t, r, c) = % ED chem_t := identity chem_transformed($) ; for i=f upto t : if chem_star[$] : chem_path0 := subpath chem_sb_pair of chem_r_fragment($,i) ; chem_draw( (point 0 of (chem_path0 paralleled -chem_dbl_offset)) transformed chem_t, chem_dot_factor*r,c,) ; chem_draw( (point 0 of (chem_path0 paralleled chem_dbl_offset)) transformed chem_t, chem_dot_factor*r,c,) ; else : chem_draw( ((subpath (chem_sb_pair shifted (i-1,i-1)) of chem_b_path[$]) paralleled -2chem_dbl_offset) transformed chem_t, r,c,dashed evenly) ; fi endfor enddef ; vardef chem_ep@# (suffix $) (expr f, t, r, c) = % EP if chem_star[$] : chem_t := identity chem_transformed($) ; for i=f upto t : chem_path0 := subpath chem_sb_pair of chem_r_fragment($,i) ; chem_draw( (point 0 of (chem_path0 paralleled -chem_dbl_offset) -- point 0 of (chem_path0 paralleled chem_dbl_offset)) transformed chem_t, r,c,) ; endfor fi enddef ; vardef chem_et@# (suffix $) (expr f, t, r, c) = % ET if chem_star[$] : chem_t := identity chem_transformed($) ; for i=f upto t : chem_path0 := subpath chem_sb_pair of chem_r_fragment($,i) ; chem_draw( (point 0 of (chem_path0 paralleled -2chem_dbl_offset)) transformed chem_t, chem_dot_factor*r,c,) ; chem_draw( (point 0 of chem_path0) transformed chem_t, chem_dot_factor*r,c,) ; chem_draw( (point 0 of (chem_path0 paralleled 2chem_dbl_offset)) transformed chem_t, chem_dot_factor*r,c,) ; endfor fi enddef ; vardef chem_db@# (suffix $) (expr f, t, r, c) = % DB if chem_star[$] : chem_dr@#($,f,t,r,c) ; elseif not chem_front[$] : chem_t := identity chem_transformed($) ; %chem_draw( % ((subpath (f-1,t) of chem_b_path[$]) paralleled -chem_dbl_offset) % transformed chem_t, % r,c,dashed chem_sb_dash@# scaled chem_b_length) ; %chem_draw( % ((subpath (f-1,t) of chem_b_path[$]) paralleled chem_dbl_offset) % transformed chem_t, % r,c,dashed chem_sb_dash@# scaled chem_b_length) ; for i=f upto t : chem_path0 := subpath (chem_sb_pair@# shifted (i-1,i-1)) of chem_b_path[$] ; chem_draw( (chem_path0 paralleled -chem_dbl_offset) transformed chem_t, r,c,) ; chem_draw( (chem_path0 paralleled chem_dbl_offset) transformed chem_t, r,c,) ; % todo : this should be cut-off where it overlaps a neighboring standard bond. endfor fi enddef ; vardef chem_tb@# (suffix $) (expr f, t, r, c) = % TB if chem_star[$] : chem_t := identity chem_transformed($) ; for i=f upto t : chem_path0 := subpath chem_sb_pair@# of chem_r_fragment($,i) ; chem_draw( (chem_path0 paralleled -2chem_dbl_offset) transformed chem_t, r,c,) ; chem_draw( chem_path0 transformed chem_t, r,c,) ; chem_draw( (chem_path0 paralleled 2chem_dbl_offset) transformed chem_t, r,c,) ; endfor fi enddef ; vardef chem_sr@# (suffix $) (expr f, t, r, c) = % SR chem_t := identity chem_transformed($) ; if chem_stacked[$] : chem_num0 := length chem_b_path[$] ; chem_num1 := floor(.5chem_num0) ; for i=f upto t : chem_draw( (subpath (if i>chem_num1: .5,ypart fi chem_sb_pair@#) of chem_r_fragment($,i)) transformed chem_t, r,c,) ; endfor else : for i=f upto t : chem_draw( (subpath chem_sb_pair@# of chem_r_fragment($,i)) transformed chem_t, r,c,) ; endfor fi enddef ; vardef chem_rd@# (suffix $) (expr f, t, r, c) = % RD chem_t := identity chem_transformed($) ; if chem_stacked[$] : chem_num0 := length chem_b_path[$] ; chem_num1 := floor(.5chem_num0) ; for i=f upto t : chem_draw( (subpath (if i>chem_num1: .5,ypart fi chem_sb_pair@#) of chem_r_fragment($,i)) transformed chem_t, r,c,dashed evenly) ; endfor else : for i=f upto t : chem_draw( (subpath chem_sb_pair@# of chem_r_fragment($,i)) transformed chem_t, r,c,dashed evenly) ; endfor fi enddef ; vardef chem_rh@# (suffix $) (expr f, t, r, c) = % RH chem_t := identity chem_transformed($) ; for i=f upto t : chem_draw( (subpath chem_sb_pair@# of chem_r_fragment($,i)) transformed chem_t, chem_dot_factor*r,c,dashed withdots scaled ((.5chem_b_length/3)/5bp)) ; % not symmetric - needs to be tweaked... endfor enddef ; vardef chem_lrh@# (suffix $) (expr f, t, r, c) = % LRH chem_t := identity chem_transformed($) ; for i=f upto t : chem_draw( (subpath chem_sb_pair@# of chem_r_fragment.lft($,i)) transformed chem_t, chem_dot_factor*r,c,dashed withdots scaled ((.5chem_b_length/3)/5bp)) ; % not symmetric - needs to be tweaked... endfor enddef ; vardef chem_rrh@# (suffix $) (expr f, t, r, c) = % RRH chem_t := identity chem_transformed($) ; for i=f upto t : chem_draw( (subpath chem_sb_pair@# of chem_r_fragment.rt($,i)) transformed chem_t, chem_dot_factor*r,c,dashed withdots scaled ((.5chem_b_length/3)/5bp)) ; % not symmetric - needs to be tweaked... endfor enddef ; vardef chem_hb@# (suffix $) (expr f, t, r, c) = % HB if chem_star[$] : chem_rh@#($,f,t,r,c) else : chem_t := identity chem_transformed($) ; for i=f upto t : chem_draw( (subpath (chem_sb_pair@# shifted (i-1,i-1)) of chem_b_path[$]) transformed chem_t, chem_dot_factor*r,c,dashed withdots scaled ((.5chem_b_length/3)/5bp)) ; % not symmetric - needs to be tweaked... endfor fi enddef ; vardef chem_bb@# (suffix $) (expr f, t, r, c) = % BB if chem_star[$] : chem_rb@#($,f,t,r,c) ; elseif chem_front[$] : chem_t := identity chem_transformed($) ; chem_draw( (subpath (f-1,t) of chem_b_path[$]) transformed chem_t, r,c,) ; chem_num0 := length chem_b_path[$] ; % total number of bonds chem_num1 := chem_front_b[$] ; % number of bonds to be made bold % bold bonds within f and t chem_num2 := if f<0 :((f+1) mod chem_num0) + chem_num0 else : ((f-1) mod chem_num0) + 1 fi ; chem_num3 := if t<0 :((t+1) mod chem_num0) + chem_num0 else : ((t-1) mod chem_num0) + 1 fi ; if chem_num31) : chem_path0 := subpath (if chem_num2>2 : chem_num2-1 else : 1 fi, if chem_num3=chem_num1 : chem_fill( (point chem_num1 of chem_b_path[$] -- point chem_num1-1 of chem_b_path[$] shifted (0,-chem_dbl_offset) -- point chem_num1-1 of chem_b_path[$] shifted (0, chem_dbl_offset) -- cycle) transformed chem_t, r,c,) ; fi fi fi enddef ; vardef chem_rb@# (suffix $) (expr f, t, r, c) = % RB chem_t := identity chem_transformed($) ; for i=f upto t : chem_path0 := subpath chem_sb_pair@# of chem_r_fragment($,i) ; chem_fill( (point 0 of chem_path0 -- point 1 of chem_path0 rotatedaround(point 0 of chem_path0, -chem_bb_angle) -- point 1 of chem_path0 rotatedaround(point 0 of chem_path0, chem_bb_angle) -- cycle) transformed chem_t, r,c,) ; endfor enddef ; vardef chem_lrb@# (suffix $) (expr f, t, r, c) = % LRB if not chem_star[$] : chem_t := identity chem_transformed($) ; for i=f upto t : chem_path0 := subpath chem_sb_pair@# of chem_r_fragment.lft($,i) ; chem_fill( (point 0 of chem_path0 -- point 1 of chem_path0 rotatedaround(point 0 of chem_path0, -chem_bb_angle) -- point 1 of chem_path0 rotatedaround(point 0 of chem_path0, chem_bb_angle) -- cycle) transformed chem_t, r,c,) ; endfor fi enddef ; vardef chem_rrb@# (suffix $) (expr f, t, r, c) = % RRB if not chem_star[$] : chem_t := identity chem_transformed($) ; for i=f upto t : chem_path0 := subpath chem_sb_pair@# of chem_r_fragment.rt($,i) ; chem_fill( (point 0 of chem_path0 -- point 1 of chem_path0 rotatedaround(point 0 of chem_path0, -chem_bb_angle) -- point 1 of chem_path0 rotatedaround(point 0 of chem_path0, chem_bb_angle) -- cycle) transformed chem_t, r,c,) ; endfor fi enddef ; vardef chem_lsr@# (suffix $) (expr f, t, r, c) = % LSR if not chem_star[$] : chem_t := identity chem_transformed($) ; for i=f upto t : chem_draw( (subpath chem_sb_pair@# of chem_r_fragment.lft($,i)) transformed chem_t, r,c,) ; endfor fi enddef ; vardef chem_rsr@# (suffix $) (expr f, t, r, c) = % RSR if not chem_star[$] : chem_t := identity chem_transformed($) ; for i=f upto t : chem_draw( (subpath chem_sb_pair@# of chem_r_fragment.rt($,i)) transformed chem_t, r,c,) ; endfor fi enddef ; vardef chem_lrd@# (suffix $) (expr f, t, r, c) = % LRD if not chem_star[$] : chem_t := identity chem_transformed($) ; for i=f upto t : chem_draw( (subpath chem_sb_pair@# of chem_r_fragment.lft($,i)) transformed chem_t, r,c,dashed evenly) ; endfor fi enddef ; vardef chem_rrd@# (suffix $) (expr f, t, r, c) = % RRD if not chem_star[$] : chem_t := identity chem_transformed($) ; for i=f upto t : chem_draw( (subpath chem_sb_pair@# of chem_r_fragment.rt($,i)) transformed chem_t, r,c,dashed evenly) ; endfor fi enddef ; vardef chem_s@# (suffix $) (expr f, t, r, c) = % S if length(str @#)>0 : chem_ss@#($,f,t,r,c) ; else : chem_ss.b($,f,t,r,c) ; fi enddef ; vardef chem_ss@# (suffix $) (expr f, t, r, c) = % SS if not (chem_star[$] or chem_front[$]) : chem_draw( subpath chem_sb_pair@# of (point f-2 of chem_b_path[$] -- point t of chem_b_path[$]) chem_transformed($), r,c,) ; fi enddef ; vardef chem_mid@# (suffix $) (expr f, t, r, c) = % MID if length(str @#)>0 : chem_mids@#($,f,t,r,c) ; else : chem_mids.b($,f,t,r,c) ; fi enddef ; vardef chem_mids@# (suffix $) (expr f, t, r, c) = % MIDS if not (chem_star[$] or chem_front[$]) : chem_t := identity chem_transformed($) ; for i=f upto t : chem_draw( (subpath chem_sb_pair@# of (origin -- point i-1 of chem_b_path[$])) transformed chem_t, r,c,) ; endfor fi enddef ; vardef chem_cd (suffix $) (expr r, c) = % CD chem_draw( chem_c_path[$] chem_transformed($), r,c,dashed evenly) ; enddef ; vardef chem_c (suffix $) (expr r, c) = % C chem_draw( chem_c_path[$] chem_transformed($), r,c,) ; enddef ; vardef chem_ccd (suffix $) (expr f, t, r, c) = % CCD chem_num0 := ypart((origin--center(subpath (f-2,f-1) of chem_b_path[$])) intersectiontimes chem_c_path[$]) ; chem_num1 := ypart((origin--center(subpath (t-1,t) of chem_b_path[$])) intersectiontimes chem_c_path[$]) ; if chem_num1>chem_num0 : chem_num0 := chem_num0 + length chem_c_path[$] ; fi chem_draw( subpath (chem_num1,chem_num0) of chem_c_path[$] chem_transformed($), r,c,dashed evenly) ; enddef ; vardef chem_cc (suffix $) (expr f, t, r, c) = % CC chem_num0 := ypart((origin--center(subpath (f-2,f-1) of chem_b_path[$])) intersectiontimes chem_c_path[$]) ; chem_num1 := ypart((origin--center(subpath (t-1,t) of chem_b_path[$])) intersectiontimes chem_c_path[$]) ; if chem_num1>chem_num0 : chem_num0 := chem_num0 + length chem_c_path[$] ; fi chem_draw( subpath (chem_num1,chem_num0) of chem_c_path[$] chem_transformed($), r,c,) ; enddef ; vardef chem_ldb@# (suffix $) (expr f, t, r, c) = % LD if chem_star[$] : chem_t := identity chem_transformed($) ; for i=f upto t : chem_path0 := subpath chem_sb_pair@# of chem_r_fragment($,i) ; chem_draw( chem_path0 transformed chem_t, r,c,) ; chem_draw( (chem_path0 paralleled 2chem_dbl_offset) transformed chem_t, r,c,) ; endfor fi enddef ; vardef chem_rdb@# (suffix $) (expr f, t, r, c) = % LD if chem_star[$] : chem_t := identity chem_transformed($) ; for i=f upto t : chem_path0 := subpath chem_sb_pair@# of chem_r_fragment($,i) ; chem_draw( chem_path0 transformed chem_t, r,c,) ; chem_draw( (chem_path0 paralleled -2chem_dbl_offset) transformed chem_t, r,c,) ; endfor fi enddef ; vardef chem_ldd@# (suffix $) (expr f, t, r, c) = % LDD if chem_star[$] : chem_t := identity chem_transformed($) ; for i=f upto t : chem_path0 := subpath chem_sb_pair@# of chem_r_fragment($,i) ; chem_draw( chem_path0 transformed chem_t, r,c,) ; chem_draw( (chem_path0 paralleled 2chem_dbl_offset) transformed chem_t, r,c,dashed evenly) ; endfor fi enddef ; vardef chem_rdd@# (suffix $) (expr f, t, r, c) = % RDD if chem_star[$] : chem_t := identity chem_transformed($) ; for i=f upto t : chem_path0 := subpath chem_sb_pair@# of chem_r_fragment($,i) ; chem_draw( chem_path0 transformed chem_t, r,c,) ; chem_draw( (chem_path0 paralleled -2chem_dbl_offset) transformed chem_t, r,c,dashed evenly) ; endfor fi enddef ; vardef chem_oe@# (suffix $) (expr f, t, r, c) = % OE if chem_star[$] : chem_t := identity chem_transformed($) ; for i=f upto t : chem_path0 := subpath chem_sb_pair@# of chem_r_fragment($,i) ; chem_path1 := chem_path0 paralleled -.5chem_dbl_offset ; chem_path2 := chem_path0 paralleled .5chem_dbl_offset ; chem_draw( ( point 0 of chem_path0 -- .2[point 0 of chem_path0, point infinity of chem_path0].. .3[point 0 of chem_path1, point infinity of chem_path1].. .4[point 0 of chem_path0, point infinity of chem_path0].. .5[point 0 of chem_path2, point infinity of chem_path2].. .6[point 0 of chem_path0, point infinity of chem_path0].. .7[point 0 of chem_path1, point infinity of chem_path1].. .8[point 0 of chem_path0, point infinity of chem_path0]-- point infinity of chem_path0) transformed chem_t, r,c,) ; endfor fi enddef ; vardef chem_bw@# (suffix $) (expr f, t, r, c) = % BW if chem_star[$] : chem_t := identity chem_transformed($) ; for i=f upto t : chem_path0 := subpath chem_sb_pair@# of chem_r_fragment($,i) ; chem_path1 := chem_path0 paralleled -.5chem_dbl_offset ; chem_path2 := chem_path0 paralleled .5chem_dbl_offset ; chem_draw( ( point 0 of chem_path0.. .1[point 0 of chem_path1, point infinity of chem_path1].. .2[point 0 of chem_path0, point infinity of chem_path0].. .3[point 0 of chem_path2, point infinity of chem_path2].. .4[point 0 of chem_path0, point infinity of chem_path0].. .5[point 0 of chem_path1, point infinity of chem_path1].. .6[point 0 of chem_path0, point infinity of chem_path0].. .7[point 0 of chem_path2, point infinity of chem_path2].. .8[point 0 of chem_path0, point infinity of chem_path0].. .9[point 0 of chem_path1, point infinity of chem_path1].. point infinity of chem_path0) transformed chem_t, r,c,) ; endfor fi enddef ; vardef chem_bd@# (suffix $) (expr f, t, r, c) = % BD if chem_star[$] : chem_rbd@#($,f,t,r,c) ; fi enddef ; vardef chem_rbd@# (suffix $) (expr f, t, r, c) = % RBD chem_t := identity chem_transformed($) ; for i=f upto t : chem_path0 := subpath chem_sb_pair@# of chem_r_fragment($,i) ; if chem_bd_wedge : chem_path1 := chem_path0 rotated -chem_bb_angle ; chem_path2 := chem_path0 rotated chem_bb_angle ; else : chem_path1 := chem_path0 paralleled -chem_dbl_offset ; chem_path2 := chem_path0 paralleled chem_dbl_offset ; fi for j=0 upto 3 : chem_draw( (point (j/3) of chem_path1 -- point (j/3) of chem_path2) transformed chem_t, 2r,c,) ; endfor endfor enddef ; vardef chem_lrbd@# (suffix $) (expr f, t, r, c) = % LRBD if not chem_star[$] : chem_t := identity chem_transformed($) ; for i=f upto t : chem_path0 := subpath chem_sb_pair@# of chem_r_fragment.lft($,i) ; if chem_bd_wedge : chem_path1 := chem_path0 rotated -chem_bb_angle ; chem_path2 := chem_path0 rotated chem_bb_angle ; else : chem_path1 := chem_path0 paralleled -.5chem_dbl_offset ; chem_path2 := chem_path0 paralleled .5chem_dbl_offset ; fi for j=0 upto 3 : chem_draw( (point (j/3) of chem_path1 -- point (j/3) of chem_path2) transformed chem_t, 2r,c,) ; endfor endfor fi enddef ; vardef chem_rrbd@# (suffix $) (expr f, t, r, c) = % RRBD if not chem_star[$] : chem_t := identity chem_transformed($) ; for i=f upto t : chem_path0 := subpath chem_sb_pair@# of chem_r_fragment.rt($,i) ; if chem_bd_wedge : chem_path1 := chem_path0 rotated -chem_bb_angle ; chem_path2 := chem_path0 rotated chem_bb_angle ; else : chem_path1 := chem_path0 paralleled -.5chem_dbl_offset ; chem_path2 := chem_path0 paralleled .5chem_dbl_offset ; fi for j=0 upto 3 : chem_draw( (point (j/3) of chem_path1 -- point (j/3) of chem_path2) transformed chem_t, 2r,c,) ; endfor endfor fi enddef ; % text, number (no alignment on number); vardef chem_z@#(suffix $) (expr p) (text t) = % Z draw chem_text@# (t,chem_do( if p=0 : origin else : (point p-1 of chem_b_path[$]) chem_transformed($) fi )) ; enddef ; vardef chem_cz@#(suffix $) (expr p) (text t) = chem_z@#($,p,t) ; enddef ; % CZ ? vardef chem_midz@#(suffix $) (expr p) (text t) = % MIDZ if not (chem_star[$] or chem_front[$]) : draw chem_text@# (t,chem_do( (xpart chem_sb_pair, 0) scaled (xpart point 0 of chem_b_path[$]) chem_transformed($) )) ; fi enddef ; vardef chem_rz@#(suffix $) (expr p) (text t) = % RZ draw chem_text@# (t, chem_do((point p-1 of chem_r_path[$]) chem_transformed($))) ; enddef ; vardef chem_lrz@#(suffix $) (expr p) (text t) = % LRZ if not chem_star[$] : draw chem_text@# (t, chem_do((point p-1 of chem_r_path.lft[$]) chem_transformed($))) ; fi enddef ; vardef chem_rrz@#(suffix $) (expr p) (text t) = % RRZ if not chem_star[$] : draw chem_text@# (t, chem_do((point p-1 of chem_r_path.rt[$]) chem_transformed($))) ; fi enddef ; vardef chem_zn@#(suffix $) (expr p) (text t) = % ZN chem_zt($,p,t) ; enddef ; vardef chem_zt@#(suffix $) (expr p) (text t) = % ZT draw chem_text@#(t,chem_do ((point p-1 of chem_b_path[$]) chem_transformed($) scaled chem_text_min)) ; enddef ; vardef chem_zln@#(suffix $) (expr p) (text t) = % ZLN chem_zlt($,p,t) ; enddef ; vardef chem_zlt@#(suffix $) (expr p) (text t) = % ZLT draw chem_text@#(t, chem_do((point p-1.5 of chem_b_path[$]) chem_transformed($) scaled chem_text_min)) ; enddef ; vardef chem_zrn@#(suffix $) (expr p) (text t) = % ZRN chem_zrt($,p,t) ; enddef ; vardef chem_zrt@#(suffix $) (expr p) (text t) = % ZRT draw chem_text@#(t, chem_do((point p-0.5 of chem_b_path[$]) chem_transformed($) scaled chem_text_min)) ; enddef ; vardef chem_crz@#(suffix $) (expr p) (text t) = % CRZ ???? if chem_star[$] : draw chem_text@#(t, chem_do((point p-1 of chem_b_path[$] enlonged chem_center_offset) chem_transformed($))) ; fi enddef ; vardef chem_rn@#(suffix $) (expr i, t) = % RN chem_rt($,i,t) ; enddef ; vardef chem_rt@#(suffix $) (expr p) (text t) = % RT draw chem_text@#(t, chem_do((center chem_r_fragment($,p)) chem_transformed($))) ; enddef ; vardef chem_lrn@#(suffix $) (expr i, t) = % LRN chem_lrt($,i,t) ; enddef ; vardef chem_lrt@#(suffix $) (expr p) (text t) = % LRT draw chem_text@#(t, chem_do((center chem_r_fragment.lft($,p)) chem_transformed($))) ; enddef ; vardef chem_rrn@# (suffix $) (expr i, t) = % RRN chem_rrt($,i,t) ; enddef ; vardef chem_rrt@#(suffix $) (expr p) (text t) = % RRT draw chem_text@#(t, chem_do((center chem_r_fragment.rt($,p)) chem_transformed($))) ; enddef ; vardef chem_symbol(expr t) = draw textext(t) ; enddef ; vardef chem_align@#(expr pic) = pic if (mfun_labtype@# >= 10) : shifted (0,ypart center pic) fi shifted (-(mfun_labxf@#*lrcorner pic + mfun_labyf@#*ulcorner pic + (1-mfun_labxf@#-mfun_labyf@#)*llcorner pic)) enddef ; vardef chem_text@#(expr txt, z) = chem_pic := textext(txt) ; if length(str @#)=0 : chem_pic := chem_align(chem_pic) ; elseif (str @#) = "auto" : if z<>origin : chem_num0 := abs(angle(z rotated chem_setting_rotation)) ; if chem_num0<=60 : chem_pic := chem_align.rt (chem_pic) xshifted chem_text_offset ; elseif chem_num0>=120 : chem_pic := chem_align.lft(chem_pic) xshifted -chem_text_offset ; else : chem_pic := chem_align (chem_pic) ; fi else : chem_pic := chem_align (chem_pic) ; fi else : chem_pic := chem_align@#(chem_pic) shifted (chem_text_offset*mfun_laboff@#) ; fi chem_pic := (chem_pic rotated -chem_setting_rotation) shifted z ; if chem_trace_text : draw z withpen pencircle scaled 2pt withcolor red ; draw boundingbox chem_pic withpen pencircle scaled 1pt withcolor red ; fi chem_pic enddef ; % transform % rotations and reflections vardef chem_rot (suffix $) (expr d, s) = % ROT if not chem_front[$] : if d=0 : chem_rotation := 0 else : chem_num0 := if chem_stacked[$] : 3 else : 0 fi ; chem_num1 := .5(angle(point d+chem_num0 of chem_b_path[$]) - angle(point d+chem_num0-1 of chem_b_path[$])) ; chem_rotation := (chem_rotation + s*chem_num1) zmod 360 ; fi fi enddef ; vardef chem_mir (suffix $) (expr d, s) = % MIR % We take the scale factor s to multiply the rotation, but only ONCE. % For example: CARBON,.5MIR12 will give a rotation by 104° if not chem_front[$] : if d=0 : % inversion if chem_mirror=origin : chem_rotation := (chem_rotation + 180*s) zmod 360 ; else : chem_mirror := chem_mirror rotated 90 ; fi else : chem_pair0 := (point d-1 of chem_b_path[$]) scaled s ; % not chem_transformed if chem_mirror=origin : chem_mirror := chem_pair0 ; else : chem_num0 := angle(chem_mirror)-angle(chem_pair0) ; if (chem_num0>0) and (chem_num0> 180) : chem_num0 := 360 - chem_num0 ; elseif (chem_num0<0) and (chem_num0<-180) : chem_num0 := -360 - chem_num0 ; fi chem_num0 := chem_num0 * s ; chem_rotation := (chem_rotation + 2chem_num0) zmod 360 ; chem_mirror := origin ; fi fi fi enddef ; % translations vardef chem_dir (suffix $) (expr d, s) = % DIR (same as MOV(d-1)MOV(d+1)) if not chem_front[$] : if d=0 : currentpicture := currentpicture shifted -chem_origin ; chem_origin := origin ; else : chem_pair0 := (((point d-2 of chem_b_path[$]) shifted (point d of chem_b_path[$])) scaled s) chem_transformed($) ; currentpicture := currentpicture shifted -chem_pair0 ; chem_origin := chem_origin shifted -chem_pair0 ; fi fi enddef ; vardef chem_mov (suffix $) (expr d, s) = % MOV if d=0 : currentpicture := currentpicture shifted -chem_origin ; chem_origin := origin ; else : chem_pair0 := ((point d-1 of chem_b_path[$]) scaled s) chem_transformed($) ; currentpicture := currentpicture shifted -chem_pair0 ; chem_origin := chem_origin shifted -chem_pair0 ; fi ; enddef ; vardef chem_mark (suffix $) (expr d, s) = % MARK % scale s is ignored if d<>0 : chem_mark_pair[d] := -chem_origin ; fi enddef ; vardef chem_marked (expr d) = if d=0 : chem_origin elseif known chem_mark_pair[d] : chem_mark_pair[d] shifted chem_origin else : origin fi enddef ; vardef chem_number@#(suffix $) (expr p) (text t) = chem_label@#($,p,t) enddef ; % NUMBER vardef chem_label@# (suffix $) (expr p) (text t) = % LABEL draw chem_text@#(t,chem_do(chem_marked(p))) ; enddef ; vardef chem_move (suffix $) (expr d, s) = % MOVE chem_pair0 := chem_marked(d) scaled s ; currentpicture := currentpicture shifted -chem_pair0 ; chem_origin := chem_origin shifted -chem_pair0 ; enddef ; vardef chem_diff (suffix $) (expr d, s) = % DIFF chem_pair0 := (chem_marked(d) shifted -chem_origin) scaled s ; currentpicture := currentpicture shifted -chem_pair0 ; chem_origin := chem_origin shifted -chem_pair0 ; enddef ; vardef chem_line (suffix $) (expr f, t, r, c) = % LINE draw if f=t : origin else : chem_marked(f) fi -- chem_marked(t) % no chem_transformed withpen pencircle scaled r withcolor c enddef ; vardef chem_dash (suffix $) (expr f, t, r, c) = % DASH draw if f=t : origin else : chem_marked(f) fi -- chem_marked(t) % no chem_transformed withpen pencircle scaled r withcolor c dashed evenly ; enddef ; vardef chem_arrow (suffix $) (expr f, t, r, c) = % ARROW drawarrow if f=t : origin else : chem_marked(f) fi -- chem_marked(t) % no chem_transformed withpen pencircle scaled r withcolor c enddef ; vardef chem_rm (suffix $) (expr d, s) = % RM if (not chem_front[$]) and (d<>0) : chem_pair0 := ((point d-1 of chem_r_path[$]) scaled s) chem_transformed($) ; currentpicture := currentpicture shifted -chem_pair0 ; chem_origin := chem_origin shifted -chem_pair0 ; fi ; enddef ; vardef chem_off (suffix $) (expr d, s) = % OFF if d=0 : currentpicture := currentpicture shifted -chem_origin ; chem_origin := origin ; else : chem_pair0 := (unitvector(point d-1 of chem_b_path[one])) scaled chem_setting_offset*s ; % not chem_transformed currentpicture := currentpicture shifted -chem_pair0 ; chem_origin := chem_origin shifted -chem_pair0 ; fi ; enddef ;