mp-chem.mpiv /size: 60 Kb    last modification: 2020-07-01 14:35
1%D \module
2%D   [       file=mp-chem.mpiv,
3%D        version=2009.05.13,
4%D          title=\CONTEXT\ \METAPOST\ graphics,
5%D       subtitle=chemicals,
6%D         author=Hans Hagen \& 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 is incomplete and experimental. Okay, it's not that bad but we do need
15%D some disclaimer.
16
17% either consistent setting or not
18
19if known context_chem : endinput ; fi ;
20
21boolean context_chem ; context_chem := true ;
22
23numeric
24    chem_num[], % scratch
25    chem_text_min, chem_text_max,
26    chem_rotation, chem_adjacent, chem_stack_n,
27    chem_substituent, chem_substituent.lft, chem_substituent.rt,
28    chem_setting_offset, chem_text_offset,
29    chem_center_offset, chem_dbl_offset,
30    chem_bb_angle, chem_axis_rulethickness,
31    chem_setting_l, chem_setting_r, chem_setting_t, chem_setting_b,
32    chem_setting_rotation, chem_emwidth, chem_b_length,
33    chem_front_b[] ;
34
35boolean
36    chem_setting_axis,
37    chem_doing_pb, chem_bd_wedge,
38    chem_star[], chem_front[], chem_stacked[], chem_tetra[] ;
39
40string
41    chem_previous ;
42
43path
44    chem_path[], % scratch
45    chem_b_path[], chem_c_path[],
46    chem_r_path[], chem_r_path.lft[], chem_r_path.rt[] ;
47
48pair
49    chem_origin, chem_mirror,
50    chem_pair[], % scratch
51    chem_sb_pair, chem_sb_pair.m, chem_sb_pair.mm, chem_sb_pair.p, chem_sb_pair.pp, chem_sb_pair.b ;
52
53picture
54    chem_pic; % scratch
55    % The use of dashpattern is found to dot the starting point with chem_sb_dash.m...
56    %chem_sb_dash, chem_sb_dash.m, chem_sb_dash.p, chem_sb_dash.b,
57
58% nice hack but now redone
59%
60% picture chem_axis_color ;
61%
62% chem_axis_color := image(draw origin withcolor axiscolor) ; % so we handle all color models
63%
64% withpen pencircle scaled chem_axis_rulethickness withcolor colorpart(chem_axis_color) ;
65
66string
67    chem_axis_color ;
68
69transform
70    chem_t ; % scratch
71
72% debugging
73
74boolean chem_trace_nesting     ; chem_trace_nesting     := false ;
75boolean chem_trace_text        ; chem_trace_text        := false ;
76boolean chem_trace_boundingbox ; chem_trace_boundingbox := false ;
77
78chem_axis_color         := "lightblue" ;
79chem_setting_axis       := false ;
80chem_axis_rulethickness := 1pt ;
81chem_emwidth            := 10pt ; % EmWidth or \the\emwidth does not work...
82chem_b_length           := 3  chem_emwidth ;
83chem_text_offset        := -.3chem_emwidth ; % -.71chem_emwidth ; % 1/sqrt(2)
84chem_center_offset      :=  .5chem_emwidth ;
85chem_dbl_offset         := .05 ;
86chem_bb_angle           := angle(1,2chem_dbl_offset) ;
87chem_text_min           := 0.75 ;
88chem_text_max           := 1.25 ;
89chem_dot_factor         := 2 ; % *linewidth
90chem_sb_pair            := (0.25,0.75) ; %chem_sb_dash   := dashpattern(off 0.25 on 0.5 off 0.25) ;
91chem_sb_pair.m          := (0.25,1   ) ; %chem_sb_dash.m := dashpattern(off 0.25 on 0.75) ;
92chem_sb_pair.mm         := (0.50,1   ) ; %chem_sb_dash.m := dashpattern(off 0.25 on 0.75) ;
93chem_sb_pair.p          := (0   ,0.75) ; %chem_sb_dash.p := dashpattern(on  0.75 off 0.25) ;
94chem_sb_pair.pp         := (0   ,0.50) ; %chem_sb_dash.p := dashpattern(on  0.75 off 0.25) ;
95chem_sb_pair.b          := (0   ,1   ) ; %chem_sb_dash.b := dashpattern(on  1) ;
96
97chem_bd_wedge           := true ; % according to IUPAC 2005
98
99def chem_reset =
100    chem_rotation         := 0 ;
101    chem_mirror           := origin ;
102    chem_adjacent         := 0 ;
103    chem_substituent      := 0 ;
104    chem_substituent.lft  := 0 ;
105    chem_substituent.rt   := 0 ;
106    chem_stack_n          := 0 ;
107    chem_doing_pb         := false ;
108    chem_origin           := origin ;
109    chem_previous         := "one" ;
110    pair chem_mark_pair[] ;
111enddef ;
112
113chem_reset ;
114
115newinternal numeric
116    one, carbon, alkyl, newmanstagger, newmaneclipsed,
117    three, four, five, six, seven, eight, nine,
118    fivefront, sixfront, chair, boat ;
119
120vardef chem_init_some (suffix $) (expr e) =
121    if not known chem_star[$]    : chem_star[$]    := false ; fi
122    if not known chem_front[$]   : chem_front[$]   := false ; fi
123    if not known chem_stacked[$] : chem_stacked[$] := false ; fi
124    if not known chem_tetra[$]   : chem_tetra[$]   := false ; fi
125
126    % We define all paths as closed, so that they may be indexed mod length.
127    if path(e) :
128        chem_b_path[$] := e if not cycle(e) : -- cycle fi ;
129        chem_num0 := length(chem_b_path[$]) ;
130    else : % polygon
131        chem_num0 := e ;
132        chem_num1 := 360/chem_num0 ;
133        chem_b_path[$] :=
134            (
135                for i=0 upto chem_num0-1 :
136                    dir(if chem_star[$] : -i else : (.5-i) fi *chem_num1) --
137                endfor
138                cycle
139            )
140            if chem_front[$] :
141                rotated (chem_num1-90)
142            fi
143            if not chem_star[$] :
144                scaled (.5/(sind .5chem_num1))
145                % carbon-carbon benzene bond length
146                scaled (1.4/1.54)
147            fi ;
148    fi ;
149
150    if chem_front[$] and (not known chem_front_b[$]) :
151        chem_front_b[$] := floor(.5(length chem_b_path[$])) + 1 ;
152    fi
153
154    chem_num2 := 0 ;
155    chem_c_path[$] :=
156        reverse(fullcircle) rotated angle(point 0 of chem_b_path[$])
157        if not chem_star[$] :
158             hide (for i=0 upto chem_num0-1:
159                       if abs(point i+.5 of chem_b_path[$]) <
160                          abs(point chem_num2+.5 of chem_b_path[$]) :
161                           chem_num2 := i ;
162                       fi
163                   endfor)
164             scaled (2*(abs(point chem_num2+.5 of chem_b_path[$]) - 2chem_dbl_offset))
165        fi ;
166
167    chem_r_path[$] :=
168        if chem_star[$] :
169            chem_b_path[$]
170        else :
171            (
172                for i=0 upto chem_num0-1 :
173                    (unitvector point i of chem_b_path[$])
174                    shifted point i of chem_b_path[$] --
175                endfor
176                cycle
177            )
178        fi ;
179
180    chem_r_path.lft[$] :=
181        (
182        for i=0 upto chem_num0-1 :
183            if chem_front[$] :
184                up
185                scaled .5
186                shifted point i of chem_b_path[$]
187            elseif chem_star[$] :
188                point i   of chem_b_path[$]
189            else :
190                point i+1 of chem_b_path[$]
191                rotatedabout(point i of chem_b_path[$],180)
192            fi --
193        endfor
194        cycle
195        ) ;
196    chem_r_path.rt[$] :=
197        (
198        for i=0 upto chem_num0-1 :
199            if chem_front[$] :
200                down
201                scaled .5
202                shifted point i of chem_b_path[$]
203            elseif chem_star[$] :
204                point i+2 of chem_b_path[$]
205            else :
206                point i-1 of chem_b_path[$]
207                rotatedabout(point i of chem_b_path[$],180)
208            fi --
209        endfor
210        cycle
211        ) ;
212
213enddef ;
214
215% The following is used only once:
216def chem_init_all =
217begingroup
218    save a, b, c, d, e ; numeric a, b, c, d, e ;
219    save lft, rt ; path lft, rt ;
220
221    % tetrahedrial angle
222    a := 2angle(1,sqrt 2) ;
223
224    % solve for chair
225    2b = 180 - .5a ;
226    4c = 180 - .5a ;
227    d + e = 360 - 2a ;
228    d = 5e ; % this is the one tunable parameter which fixes the perspective.
229    z2 = z1 shifted dir(90+a+d) ;
230    z3 = z2 shifted dir(270-a) ;
231    z4 = z3 shifted dir(90+a) ;
232    z6 = z1 shifted dir(90+a) ;
233    z5 = z6 shifted dir(270-a) ;
234    z4 = z1 xyscaled (-1,-1) ;
235    z5 = z2 xyscaled (-1,-1) ;
236
237    save indx ; numeric indx ; indx = 2 ; % starting value doesn't matter, really.
238    % polygons
239    three          := incr indx ; % 3 (these numbers don't matter - they are just indices)
240    four           := incr indx ; % 4
241    five           := incr indx ; % 5
242    six            := incr indx ; % 6
243    seven          := incr indx ; % 7
244    eight          := incr indx ; % 8
245    nine           := incr indx ; % 9
246
247    chem_init_some(three,3) ;
248    chem_init_some(four, 4) ;
249    chem_init_some(five, 5) ;
250    chem_init_some(six,  6) ;
251    chem_init_some(seven,7) ;
252    chem_init_some(eight,8) ;
253    chem_init_some(nine, 9) ;
254
255    % star-form
256    one            := incr indx ; % 10
257    carbon         := incr indx ; % 11
258    alkyl          := incr indx ; % 12
259    newmanstagger  := incr indx ; % 13
260    newmaneclipsed := incr indx ; % 14
261
262    chem_star[one]            := true ;
263    chem_star[carbon]         := true ; chem_tetra[carbon]         := true ;
264    chem_star[alkyl]          := true ; chem_tetra[alkyl]          := true ;
265    chem_star[newmanstagger]  := true ; chem_tetra[newmanstagger]  := true ;
266    chem_star[newmaneclipsed] := true ; chem_tetra[newmaneclipsed] := true ;
267    chem_stacked[newmanstagger]  := true ;
268    chem_stacked[newmaneclipsed] := true ;
269    chem_init_some(one,            8) ;
270    chem_init_some(carbon,         dir(0)--dir(360-a)--dir(180-.5a+b)--dir(180-.5a)) ;
271    chem_init_some(alkyl,          dir(0)--dir(360-a)--dir(360-a-90)--dir(90)) ;
272    chem_init_some(newmanstagger,  dir(30)--dir(270)--dir(150)--dir(330)--dir(210)--dir(90)) ;
273    chem_init_some(newmaneclipsed, dir(30)--dir(270)--dir(150)--dir(0)--dir(240)--dir(120)) ;
274
275    % front views
276    fivefront      := incr indx ; % 15
277    sixfront       := incr indx ; % 16
278    chair          := incr indx ; % 17
279    boat           := incr indx ; % 18
280
281    chem_front[fivefront]    := true ; chem_front_b[fivefront] := 3 ;
282    chem_front[sixfront]     := true ; chem_front_b[sixfront]  := 3 ;
283    chem_init_some(fivefront,5) ;
284    chem_init_some(sixfront, 6) ;
285    % chair
286    chem_front[chair]        := true ; chem_front_b[chair]     := 4 ;
287    chem_init_some(chair,          z1--z2--z3--z4--z5--z6) ;
288    lft := dir(90-a)--down--dir(90+a+d)--down--dir(90+a)--down ;
289    rt  := up--dir(270+a)--up--dir(270-a)--up--dir(90+e) ;
290    chem_r_path.lft[chair] :=
291        for i=0 upto 5 : point i of lft shifted point i of chem_b_path[chair] -- endfor
292        cycle ;
293    chem_r_path.rt[chair] :=
294        for i=0 upto 5 : point i of rt shifted point i of chem_b_path[chair] -- endfor
295        cycle ;
296    % boat
297    chem_front[boat]         := true ; chem_front_b[boat]      := 4 ;
298    chem_init_some(boat,
299        for i=1 upto 4 : point i-1 of chem_b_path[sixfront] -- endfor
300        point 2 of chem_b_path[sixfront] yscaled .5 --
301        point 1 of chem_b_path[sixfront] yscaled .5
302    ) ;
303    lft := dir(30+.5a)--dir(330+.5a)--dir(210-.5a)--dir(150-.5a)--dir(120)--dir(60) ;
304    rt  := dir(30-.5a)--dir(330-.5a)--dir(210+.5a)--dir(150+.5a)--dir(120+a)--dir(60-a) ;
305    chem_r_path.lft[boat] :=
306        for i=0 upto 5 : point i of lft shifted point i of chem_b_path[boat] -- endfor
307        cycle ;
308    chem_r_path.rt[boat] :=
309        for i=0 upto 5 : point i of rt shifted point i of chem_b_path[boat] -- endfor
310        cycle ;
311endgroup
312enddef ;
313
314chem_init_all ; % WHY does this not work unless defined and then called?
315
316% Like most often in ConTeXt, we will trap but then silently ignore mistaken use,
317% unless of course the error be too harmful...
318
319% \startchemical
320
321def chem_start_structure(expr i, l, r, t, b, rotation, unit, bond, scale, offset, axis, rulethickness, axiscolor) =
322    save chem_setting_l, chem_setting_r, chem_setting_t, chem_setting_b ;
323
324    chem_emwidth            := unit ; % dynamically set for each structure.
325    chem_text_offset        := -.3chem_emwidth ; % -.71chem_emwidth ; % 1/sqrt(2)
326    chem_center_offset      :=  .5chem_emwidth ;
327    chem_b_length           :=    chem_emwidth * bond * scale ;
328    % scale (normally 1) scales the structure but not the text.
329
330    if numeric l :
331        chem_setting_l      := -l ;
332    fi
333    if numeric r :
334        chem_setting_r      := r ;
335    fi
336    if numeric t :
337        chem_setting_t      := t ;
338    fi
339    if numeric b  :
340        chem_setting_b      := -b ;
341    fi
342    chem_setting_rotation   := rotation ;
343    chem_setting_offset     := offset ;
344    chem_setting_axis       := if boolean axis : axis else : (axis<>0) fi ;
345    chem_axis_rulethickness := .75*(rulethickness) ; % axis 50% thinner than frame and bonds.
346    chem_axis_color         := axiscolor ;
347
348    chem_reset ;
349enddef ;
350
351% \stopchemical
352
353vardef chem_stop_structure =
354    % Make sure that all of the saved stack has been restored... (this was a gotcha!)
355    forever :
356        exitif chem_stack_n=0 ;
357        chem_restore ;
358    endfor
359
360    currentpicture := (currentpicture shifted -chem_origin) rotated chem_setting_rotation ;
361
362    save l, r, b, t ;
363    l := min(xpart llcorner currentpicture, xpart lrcorner currentpicture) ;
364    r := max(xpart llcorner currentpicture, xpart lrcorner currentpicture) ;
365    b := min(ypart llcorner currentpicture, ypart ulcorner currentpicture) ;
366    t := max(ypart llcorner currentpicture, ypart ulcorner currentpicture) ;
367
368    if unknown chem_setting_l : chem_setting_l := l ; fi
369    if unknown chem_setting_r : chem_setting_r := r ; fi
370    if unknown chem_setting_b : chem_setting_b := b ; fi
371    if unknown chem_setting_t : chem_setting_t := t ; fi
372
373    if chem_setting_axis : % put it behind the picture
374        chem_pic := currentpicture ; currentpicture := nullpicture ;
375        chem_num0 := .5chem_b_length ;
376        chem_num1 := .2chem_num0 ;
377        % draw the axes to the bounding box of the entire structure,
378        % not necessarily the bounding box of the final figure
379        draw (l,0) -- (r,0)
380            withpen pencircle scaled chem_axis_rulethickness withcolor chem_axis_color ;
381        draw (0,b) -- (0,t)
382            withpen pencircle scaled chem_axis_rulethickness withcolor chem_axis_color ;
383        for i = 0 step  chem_num0 until r :
384            draw (i,-chem_num1) -- (i,chem_num1)
385            withpen pencircle scaled chem_axis_rulethickness withcolor chem_axis_color ;
386        endfor
387        for i = 0 step -chem_num0 until l :
388            draw (i,-chem_num1) -- (i,chem_num1)
389            withpen pencircle scaled chem_axis_rulethickness withcolor chem_axis_color ;
390        endfor
391        for i = 0 step  chem_num0 until t :
392            draw (-chem_num1,i) -- (chem_num1,i)
393            withpen pencircle scaled chem_axis_rulethickness withcolor chem_axis_color ;
394        endfor
395        for i = 0 step -chem_num0 until b :
396            draw (-chem_num1,i) -- (chem_num1,i)
397            withpen pencircle scaled chem_axis_rulethickness withcolor chem_axis_color ;
398        endfor
399        addto currentpicture also chem_pic ;
400    fi ;
401    if chem_trace_boundingbox :
402        fill boundingbox currentpicture withcolor blue withtransparency(1,.25) ;
403    fi ;
404    setbounds currentpicture to
405        ((chem_setting_l,chem_setting_b) -- (chem_setting_r,chem_setting_b) --
406         (chem_setting_r,chem_setting_t) -- (chem_setting_l,chem_setting_t) -- cycle) ;
407    if chem_trace_boundingbox :
408        fill boundingbox currentpicture withcolor red withtransparency(1,.25) ;
409    fi ;
410enddef ;
411
412% \chemical
413
414vardef chem_start_component = enddef ;
415vardef chem_stop_component  = enddef ;
416
417vardef chem_pb = % PB :
418    if chem_trace_nesting :
419        draw boundingbox currentpicture withpen pencircle scaled 1mm withcolor chem_axis_color ;
420        draw origin withpen pencircle scaled 2mm withcolor chem_axis_color ;
421    fi ;
422    chem_doing_pb := true ;
423enddef ;
424
425vardef chem_pe = % PE
426    if chem_trace_nesting :
427        draw boundingbox currentpicture withpen pencircle scaled .5mm withcolor red ;
428        draw origin withpen pencircle scaled 1mm withcolor red ;
429    fi ;
430    currentpicture := currentpicture shifted -chem_origin ;
431    if chem_trace_nesting :
432        draw origin withpen pencircle scaled .5mm withcolor green ;
433    fi ;
434    chem_origin := origin ;
435    chem_doing_pb := false ;
436enddef ;
437
438vardef chem_do (expr pos) =
439    if (unknown chem_doing_pb) or (not chem_doing_pb) :
440        pos
441    else :
442        chem_doing_pb := false ;
443        currentpicture := currentpicture shifted -pos ;
444        chem_origin    := chem_origin    shifted -pos ;
445        origin %  nullpicture
446    fi
447enddef ;
448
449
450picture chem_stack_p[] ;
451pair    chem_stack_origin[], chem_stack_mirror[] ;
452numeric chem_stack_rotation[] ;
453string  chem_stack_previous[] ;
454
455vardef chem_save = % SAVE
456    chem_stack_p       [incr chem_stack_n] := currentpicture ;
457    chem_stack_origin  [     chem_stack_n] := chem_origin ; chem_origin := origin ;
458    chem_stack_rotation[     chem_stack_n] := chem_rotation ;
459    chem_stack_mirror  [     chem_stack_n] := chem_mirror ;
460    chem_stack_previous[     chem_stack_n] := chem_previous ;
461    currentpicture := nullpicture ;
462enddef ;
463
464vardef chem_restore = % RESTORE
465    if chem_stack_n>0 :
466        currentpicture := currentpicture shifted -chem_origin ;
467        addto             chem_stack_p       [chem_stack_n] also currentpicture ;
468        currentpicture := chem_stack_p       [chem_stack_n] ;
469        chem_stack_p[chem_stack_n] := nullpicture ;
470        chem_origin    := chem_stack_origin  [chem_stack_n] ;
471        chem_rotation  := chem_stack_rotation[chem_stack_n] ;
472        chem_mirror    := chem_stack_mirror  [chem_stack_n] ;
473        chem_previous  := chem_stack_previous[chem_stack_n] ;
474        chem_stack_n := chem_stack_n - 1 ;
475    fi ;
476enddef ;
477
478% chem_adj and chem_sub are to be followed by chem_set(n) which does all the work...
479
480vardef chem_adj (suffix $) (expr d, s) = % ADJ
481    % scale s is ignored (for now?)
482    if not chem_front[$] :
483        chem_substituent     := 0 ;
484        chem_substituent.lft := 0 ;
485        chem_substituent.rt  := 0 ;
486        chem_adjacent := d ;
487    fi
488enddef ;
489
490vardef chem_lsub (suffix $) (expr d, s) =  % LSUB
491    chem_sub.lft($,d,s) ;
492enddef ;
493
494vardef chem_rsub (suffix $) (expr d, s) =  % RSUB
495    chem_sub.rt ($,d,s) ;
496enddef ;
497
498vardef chem_sub@# (suffix $) (expr d, s) = % SUB
499    % scale s is ignored (for now?)
500    chem_adjacent        := 0 ;
501    chem_substituent     := 0 ;
502    chem_substituent.lft := 0 ;
503    chem_substituent.rt  := 0 ;
504    % then :
505    chem_substituent@#   := d ;
506enddef ;
507
508def chem_transformed (suffix $) = % not vardef!
509    scaled chem_b_length
510    if not chem_front[$] :
511        if chem_mirror<>origin : reflectedabout(origin,chem_mirror) fi
512        rotated chem_rotation
513    fi
514enddef ;
515
516% vardef chem_draw (expr what, r, c) (text extra) =
517%     draw what
518%         withpen pencircle scaled r
519%         withcolor c
520%         extra ;
521% enddef ;
522
523vardef chem_draw (expr what, r, c) (text extra) =
524    draw what
525        withpen pencircle scaled r
526        if string c :
527            if c <> "" : withcolor c fi
528        else :
529            withcolor c
530        fi
531        extra ;
532enddef ;
533
534vardef chem_fill (expr what, r, c) (text extra) =
535    fill what
536        withpen pencircle scaled r
537        withcolor c
538        extra ;
539enddef ;
540
541vardef chem_drawarrow (expr what, r, c) (text extra) =
542    drawarrow what
543        withpen pencircle scaled r
544        withcolor c
545        extra ;
546enddef ;
547
548vardef chem_set (suffix $) =
549    forsuffixes P = scantokens chem_previous :
550
551    % This is a fairly complicated optimization and ajustement. It took some
552    % thinking to get right, so beware!
553
554    % And then even more time fixing a bug of a rotation +- half the symmetry
555    % angle of a structure depending on the scale and/or the font size
556    % (through chem_b_length).
557
558    % first save the symmetry angle of the structure (as in chem_rot):
559    chem_num0 := if chem_stacked[$] : 3 else : 0 fi ;
560    chem_num9 := if chem_tetra[$] : 360 else :
561                 abs(angle(point 0+chem_num0 of chem_b_path[$]) -
562                     angle(point 1+chem_num0 of chem_b_path[$]))
563                 fi ;
564
565    if (chem_adjacent<>0) and chem_star[P] and chem_star[$] :
566        % nop
567        chem_adjacent := 0 ;
568    elseif (chem_adjacent<>0) and (chem_front[P] or chem_front[$]) :
569        % not allowed for FRONT
570        chem_adjacent := 0 ;
571    elseif chem_adjacent<>0 :
572        chem_substituent     := 0 ;
573        chem_substituent.lft := 0 ;
574        chem_substituent.rt  := 0 ;
575        % move to the bond midpoint of the first structure
576        chem_pair0 := center (
577            if chem_star[P] :
578                origin -- point (chem_adjacent-1)
579            else :
580                subpath (chem_adjacent-1,chem_adjacent)
581            fi
582            of chem_b_path[P]
583        ) chem_transformed(P) ;
584        % find the closest opposite bond of the second structure
585        chem_pair1 := chem_pair0 rotated if chem_star[P] : 90 else : 180 fi ;
586        chem_num0 := abs(chem_pair1) ;
587        chem_num1 := if chem_tetra[$] : 1 else : length chem_b_path[$] fi ;
588        % only consider even indices (cardinal points) for ONE
589        chem_num2 := if chem_star[$] and not chem_tetra[$] : 2 else : 1 fi ;
590        for i=0 step chem_num2 until chem_num1 :
591            chem_pair2 := (
592                (
593                    unitvector
594                    center (
595                        if chem_star[$] :
596                            origin -- point i
597                        else :
598                            subpath (i,i+1)
599                        fi
600                        of chem_b_path[$])
601                    )
602                    scaled chem_num0
603                ) chem_transformed($) ;
604            if i=0 :
605                chem_pair3 := chem_pair2 ;
606                chem_num3 := 0 ;
607            elseif (abs(chem_pair1 shifted -chem_pair2)) < (abs(chem_pair1 shifted -chem_pair3)) :
608                chem_pair3 := chem_pair2 ;
609                chem_num3 := i ;
610            fi
611        endfor
612        if chem_star[$] :
613            chem_pair4 := chem_pair0 shifted
614                          -((point (chem_adjacent-1) of chem_b_path[P]) chem_transformed(P)) ;
615        fi
616        % adjust the bond angles
617        chem_num4 := (angle(chem_pair1)-angle(chem_pair3)) zmod chem_num9 ;
618        chem_rotation := chem_rotation + chem_num4 ;
619        if not chem_star[$] :
620            chem_pair4 :=
621                if chem_star[P] :
622                    (point chem_num3
623                else :
624                    center(subpath (chem_num3,chem_num3+1)
625                fi
626                of chem_b_path[$])
627                chem_transformed($) ;
628        fi
629        if not chem_star[P] :
630            chem_pair4 := chem_pair4 shifted -chem_pair0 ;
631        fi
632        currentpicture := currentpicture shifted chem_pair4 ;
633        chem_origin    := chem_origin    shifted chem_pair4 ;
634        chem_adjacent  := 0 ;
635    fi ;
636
637    % Insure that only one, if any, will be nonzero
638    if ((chem_substituent     <> 0) and (chem_substituent.lft <> 0)) or
639       ((chem_substituent     <> 0) and (chem_substituent.rt  <> 0)) or
640       ((chem_substituent.lft <> 0) and (chem_substituent.rt  <> 0)) :
641        chem_substituent     := 0 ;
642        chem_substituent.lft := 0 ;
643        chem_substituent.rt  := 0 ;
644    fi
645    if (chem_substituent <> 0) or (chem_substituent.lft <> 0) or (chem_substituent.rt <> 0) :
646        % move origin to radical endpoint of the first structure
647        if chem_substituent.lft > 0 :
648            chem_pair0 := point chem_substituent.lft-1 of chem_r_path.lft[P] ;
649            chem_substituent := chem_substituent.lft ;
650            chem_substituent.lft := 0 ;
651        elseif chem_substituent.rt > 0 :
652            chem_pair0 := point chem_substituent.rt-1 of chem_r_path.rt[P] ;
653            chem_substituent := chem_substituent.rt ;
654            chem_substituent.rt := 0 ;
655        else :
656            chem_pair0 := point chem_substituent-1 of chem_r_path[P] ;
657        fi
658        chem_pair1 := chem_pair0 if not chem_star[P] :
659                                 shifted -(point chem_substituent-1 of chem_b_path[P]) fi ;
660        chem_t := identity chem_transformed(P) ;
661        chem_pair0 := chem_pair0 transformed chem_t ; % radical
662        chem_pair1 := chem_pair1 transformed chem_t ; % recentered (see below)
663        currentpicture := currentpicture shifted -chem_pair0 ;
664        chem_origin    := chem_origin    shifted -chem_pair0 ;
665        if (not (chem_star[P] and chem_star[$])) or chem_tetra[P] or chem_tetra[$] :
666            if chem_tetra[P] and chem_tetra[$] and ((chem_substituent=1) or (chem_substituent=2)):
667                chem_rotation := (chem_rotation + 180) mod 360 ; % trans-alkane
668                chem_pair2 := (point .5 of chem_b_path[$]) ; % bisector, not chem_transformed
669                if chem_mirror=origin :
670                    chem_mirror := chem_pair2 ;
671                else :
672                    chem_num0 := angle(chem_mirror)-angle(chem_pair2) ;
673                    if (chem_num0>0) and (chem_num0> 180) :
674                        chem_num0 :=  360 - chem_num0 ;
675                    elseif (chem_num0<0) and (chem_num0<-180) :
676                        chem_num0 := -360 - chem_num0 ;
677                    fi
678                    chem_rotation := (chem_rotation + 2chem_num0) mod 360 ;
679                    chem_mirror := origin ;
680                fi
681            fi
682            chem_t := identity chem_transformed($) ;
683            chem_pair1 := chem_pair1 rotated 180 ; % opposite direction of radical bond
684            % find the closest node
685            chem_num0 := abs(chem_pair1) ;         % distance
686            % search to find the nearest node of $; only consider 1 and 2 for CARBON,ALKYL
687            chem_num1 := if chem_tetra[$] : 1 else : length chem_b_path[$] fi ;
688            % only consider even indices (cardinal points) for ONE
689            chem_num2 := if chem_star[$] and not chem_tetra[$] : 2 else : 1 fi ;
690            for i=0 step chem_num2 until chem_num1 :
691                chem_pair2 := (unitvector(point i of chem_b_path[$]) scaled chem_num0)
692                              transformed chem_t ;
693                if i=0 :
694                    chem_pair3 := chem_pair2 ;
695                    chem_num3  := 0 ;
696                elseif (abs(chem_pair1 shifted -chem_pair2)) <
697                       (abs(chem_pair1 shifted -chem_pair3)) :
698                    chem_pair3 := chem_pair2 ;
699                    chem_num3  := i ;
700                fi
701            endfor
702            if not chem_front[$] : % adjust rotation
703                chem_num4 := angle(chem_pair1)-angle(chem_pair3) ;
704                chem_rotation := (chem_rotation + chem_num4) mod 360 ;
705            fi ;
706            chem_t := identity chem_transformed($) ;
707            chem_pair4 := (point chem_num3 of chem_b_path[$]) transformed chem_t ;
708            if not chem_star[$] :
709                currentpicture := currentpicture shifted chem_pair4 ;
710                chem_origin    := chem_origin    shifted chem_pair4 ;
711            fi
712            if not chem_front[$] : % adjust rotation
713                chem_rotation := chem_rotation zmod chem_num9 ;
714            fi
715        fi
716        chem_substituent := 0 ;
717    fi ;
718    endfor
719    chem_previous := str $ ;
720enddef ;
721
722% line (f_rom, t_o, r_ule, c_olor)
723
724vardef chem_b@# (suffix $) (expr f,     t,   r,     c) = % B
725    if chem_star[$] :
726        chem_r@#($,f,t,r,c) ;
727    elseif length(str @#)>0 :
728        chem_sb@#($,f,t,r,c) ;
729    else :
730        chem_draw(
731            (subpath (f-1,t) of chem_b_path[$]) chem_transformed($),
732            r,c,) ;
733    fi
734enddef ;
735
736vardef chem_sb@# (suffix $) (expr f, t, r, c) = % SB
737    if chem_star[$] :
738        chem_sr@#($,f,t,r,c) ;
739    else :
740        %chem_draw(
741        %    (subpath (f-1,t) of chem_b_path[$]) chem_transformed($),
742        %    r,c,dashed chem_sb_dash@# scaled chem_b_length) ;
743        chem_t := identity chem_transformed($) ;
744        for i=f upto t :
745            chem_draw(
746                (subpath (chem_sb_pair@# shifted (i-1,i-1)) of chem_b_path[$])
747                transformed chem_t,
748                r,c,) ;
749        endfor
750    fi
751enddef ;
752
753vardef chem_sd@# (suffix $) (expr f, t, r, c) = % SD
754    if chem_star[$] :
755        chem_rd@#($,f,t,r,c) ;
756    else :
757        chem_t := identity chem_transformed($) ;
758        for i=f upto t :
759            chem_draw(
760                (subpath (chem_sb_pair@# shifted (i-1,i-1)) of chem_b_path[$])
761                transformed chem_t,
762                r,c,dashed evenly) ;
763        endfor
764    fi
765enddef ;
766
767vardef chem_r_fragment@# (suffix $) (expr i) =
768    (
769        if chem_star[$] :
770             origin
771        else :
772             point i-1 of chem_b_path[$]
773        fi --
774        point i-1 of chem_r_path@#[$]
775    ) % no ;
776enddef ;
777
778vardef chem_r@# (suffix $) (expr f, t, r, c) = % R
779    if length(str @#)>0 :
780        chem_sr@#($,f,t,r,c) ;
781    else :
782        chem_sr.b($,f,t,r,c) ;
783    fi
784enddef ;
785
786vardef chem_er@# (suffix $) (expr f, t, r, c) = % ER
787    if length(str @#)>0:
788        chem_dr@#($,f,t,r,c) ;
789    else :
790        chem_dr.b($,f,t,r,c) ;
791    fi
792enddef ;
793
794vardef chem_dr@# (suffix $) (expr f, t, r, c) = % DR
795    if not chem_front[$] :
796        chem_t := identity chem_transformed($) ;
797        for i=f upto t :
798            chem_path0 := (subpath chem_sb_pair@# of chem_r_fragment($,i)) ;
799            chem_draw(
800                (chem_path0 paralleled  chem_dbl_offset) transformed chem_t,
801                r,c,) ;
802            chem_draw(
803                (chem_path0 paralleled -chem_dbl_offset) transformed chem_t,
804                r,c,) ;
805        endfor
806    fi
807enddef ;
808
809vardef chem_lr@# (suffix $) (expr f, t, r, c) = % LR
810    if length(str @#)>0 :
811        chem_lsr@#($,f,t,r,c) ;
812    else :
813        chem_lsr.b($,f,t,r,c) ;
814    fi
815enddef ;
816
817vardef chem_rr@# (suffix $) (expr f, t, r, c) = % RR
818    if length(str @#)>0 :
819        chem_rsr@#($,f,t,r,c) ;
820    else :
821        chem_rsr.b($,f,t,r,c) ;
822    fi
823enddef ;
824
825vardef chem_eb@# (suffix $) (expr f, t, r, c) = % EB
826    if not chem_star[$] :
827        %chem_draw(
828        %    ((subpath (f-1,t) of chem_b_path[$]) paralleled -2chem_dbl_offset)
829        %    chem_transformed($),
830        %    r,c,dashed chem_sb_dash scaled chem_b_length) ;
831        for i=f upto t :
832            chem_t := identity chem_transformed($) ;
833            chem_draw(
834                ((subpath (chem_sb_pair@# shifted (i-1,i-1)) of chem_b_path[$])
835                paralleled -2chem_dbl_offset) transformed chem_t,
836                r,c,) ;
837        endfor
838    fi
839enddef ;
840
841vardef chem_ad@# (suffix $) (expr f, t, r, c) = % AD
842    chem_t := identity chem_transformed($) ;
843    for i=f upto t :
844        chem_drawarrow(
845            (
846            (subpath
847            if chem_star[$] :
848                 chem_sb_pair@#                    of chem_r_fragment($,i)
849                ) paralleled 5chem_dbl_offset
850             else :
851                (chem_sb_pair@# shifted (i-1,i-1)) of chem_b_path[$]
852                ) paralleled 2chem_dbl_offset
853             fi
854            ) transformed chem_t,
855            r,c,) ;
856    endfor
857enddef ;
858
859vardef chem_au@# (suffix $) (expr f, t, r, c) = % AU
860    chem_t := identity chem_transformed($) ;
861    for i=f upto t :
862        chem_drawarrow(
863             ((reverse
864               subpath
865             if chem_star[$] :
866                 chem_sb_pair@#                    of chem_r_fragment($,i)
867                ) paralleled -5chem_dbl_offset
868             else :
869                (chem_sb_pair@# shifted (i-1,i-1)) of chem_b_path[$]
870                ) paralleled -2chem_dbl_offset
871             fi
872            ) transformed chem_t,
873            r,c,) ;
874    endfor
875enddef ;
876
877vardef chem_es@# (suffix $) (expr f, t, r, c) = % ES
878    if chem_star[$] :
879        chem_t := identity chem_transformed($) ;
880        for i=f upto t :
881            chem_draw(
882                ((point i-1 of chem_r_path[$]) scaled (xpart chem_sb_pair)) transformed chem_t,
883                chem_dot_factor*r,c,) ;
884        endfor
885    fi
886enddef ;
887
888vardef chem_ed@# (suffix $) (expr f, t, r, c) = % ED
889    chem_t := identity chem_transformed($) ;
890    for i=f upto t :
891        if chem_star[$] :
892            chem_path0 := subpath chem_sb_pair of chem_r_fragment($,i) ;
893            chem_draw(
894                (point 0 of (chem_path0 paralleled -chem_dbl_offset)) transformed chem_t,
895                chem_dot_factor*r,c,) ;
896            chem_draw(
897                (point 0 of (chem_path0 paralleled  chem_dbl_offset)) transformed chem_t,
898                chem_dot_factor*r,c,) ;
899        else :
900            chem_draw(
901                ((subpath (chem_sb_pair shifted (i-1,i-1)) of chem_b_path[$])
902                paralleled -2chem_dbl_offset) transformed chem_t,
903                r,c,dashed evenly) ;
904        fi
905    endfor
906enddef ;
907
908vardef chem_ep@# (suffix $) (expr f, t, r, c) = % EP
909    if chem_star[$] :
910        chem_t := identity chem_transformed($) ;
911        for i=f upto t :
912            chem_path0 := subpath chem_sb_pair of chem_r_fragment($,i) ;
913            chem_draw(
914                (point 0 of (chem_path0 paralleled -chem_dbl_offset) --
915                 point 0 of (chem_path0 paralleled  chem_dbl_offset)) transformed chem_t,
916                r,c,) ;
917        endfor
918    fi
919enddef ;
920
921vardef chem_et@# (suffix $) (expr f, t, r, c) = % ET
922    if chem_star[$] :
923        chem_t := identity chem_transformed($) ;
924        for i=f upto t :
925            chem_path0 := subpath chem_sb_pair of chem_r_fragment($,i) ;
926            chem_draw(
927                (point 0 of (chem_path0 paralleled -2chem_dbl_offset)) transformed chem_t,
928                chem_dot_factor*r,c,) ;
929            chem_draw(
930                (point 0 of chem_path0) transformed chem_t,
931                chem_dot_factor*r,c,) ;
932            chem_draw(
933                (point 0 of (chem_path0 paralleled  2chem_dbl_offset)) transformed chem_t,
934                chem_dot_factor*r,c,) ;
935        endfor
936    fi
937enddef ;
938
939vardef chem_db@# (suffix $) (expr f, t, r, c) = % DB
940    if chem_star[$] :
941        chem_dr@#($,f,t,r,c) ;
942    elseif not chem_front[$] :
943        chem_t := identity chem_transformed($) ;
944        %chem_draw(
945        %    ((subpath (f-1,t) of chem_b_path[$]) paralleled -chem_dbl_offset)
946        %    transformed chem_t,
947        %    r,c,dashed chem_sb_dash@# scaled chem_b_length) ;
948        %chem_draw(
949        %    ((subpath (f-1,t) of chem_b_path[$]) paralleled  chem_dbl_offset)
950        %    transformed chem_t,
951        %    r,c,dashed chem_sb_dash@# scaled chem_b_length) ;
952        for i=f upto t :
953            chem_path0 := subpath (chem_sb_pair@# shifted (i-1,i-1)) of chem_b_path[$] ;
954            chem_draw(
955                (chem_path0 paralleled -chem_dbl_offset) transformed chem_t,
956                r,c,) ;
957            chem_draw(
958                (chem_path0 paralleled  chem_dbl_offset) transformed chem_t,
959                r,c,) ;
960            % todo : this should be cut-off where it overlaps a neighboring standard bond.
961        endfor
962    fi
963enddef ;
964
965vardef chem_tb@# (suffix $) (expr f, t, r, c) = % TB
966    if chem_star[$] :
967        chem_t := identity chem_transformed($) ;
968        for i=f upto t :
969            chem_path0 := subpath chem_sb_pair@# of chem_r_fragment($,i) ;
970            chem_draw(
971                (chem_path0 paralleled -2chem_dbl_offset) transformed chem_t,
972                r,c,) ;
973            chem_draw(
974                chem_path0 transformed chem_t,
975                r,c,) ;
976            chem_draw(
977                (chem_path0 paralleled  2chem_dbl_offset) transformed chem_t,
978                r,c,) ;
979        endfor
980    fi
981enddef ;
982
983vardef chem_sr@# (suffix $) (expr f, t, r, c) = % SR
984    chem_t := identity chem_transformed($) ;
985    if chem_stacked[$] :
986        chem_num0 := length chem_b_path[$] ; chem_num1 := floor(.5chem_num0) ;
987        for i=f upto t :
988            chem_draw(
989                (subpath (if i>chem_num1: .5,ypart fi chem_sb_pair@#) of chem_r_fragment($,i))
990                transformed chem_t,
991                r,c,) ;
992        endfor
993    else :
994        for i=f upto t :
995            chem_draw(
996                (subpath chem_sb_pair@# of chem_r_fragment($,i))
997                transformed chem_t,
998                r,c,) ;
999        endfor
1000    fi
1001enddef ;
1002
1003vardef chem_rd@# (suffix $) (expr f, t, r, c) = % RD
1004    chem_t := identity chem_transformed($) ;
1005    if chem_stacked[$] :
1006        chem_num0 := length chem_b_path[$] ; chem_num1 := floor(.5chem_num0) ;
1007        for i=f upto t :
1008            chem_draw(
1009                (subpath (if i>chem_num1: .5,ypart fi chem_sb_pair@#) of chem_r_fragment($,i))
1010                transformed chem_t,
1011                r,c,dashed evenly) ;
1012        endfor
1013    else :
1014        for i=f upto t :
1015            chem_draw(
1016                (subpath chem_sb_pair@# of chem_r_fragment($,i))
1017                transformed chem_t,
1018                r,c,dashed evenly) ;
1019        endfor
1020    fi
1021enddef ;
1022
1023vardef chem_rh@# (suffix $) (expr f, t, r, c) = % RH
1024    chem_t := identity chem_transformed($) ;
1025    for i=f upto t :
1026        chem_draw(
1027            (subpath chem_sb_pair@# of chem_r_fragment($,i))
1028            transformed chem_t,
1029            chem_dot_factor*r,c,dashed withdots scaled ((.5chem_b_length/3)/5bp)) ;
1030            % not symmetric - needs to be tweaked...
1031    endfor
1032enddef ;
1033
1034vardef chem_lrh@# (suffix $) (expr f, t, r, c) = % LRH
1035    chem_t := identity chem_transformed($) ;
1036    for i=f upto t :
1037        chem_draw(
1038            (subpath chem_sb_pair@# of chem_r_fragment.lft($,i))
1039            transformed chem_t,
1040            chem_dot_factor*r,c,dashed withdots scaled ((.5chem_b_length/3)/5bp)) ;
1041            % not symmetric - needs to be tweaked...
1042    endfor
1043enddef ;
1044
1045vardef chem_rrh@# (suffix $) (expr f, t, r, c) = % RRH
1046    chem_t := identity chem_transformed($) ;
1047    for i=f upto t :
1048        chem_draw(
1049            (subpath chem_sb_pair@# of chem_r_fragment.rt($,i))
1050            transformed chem_t,
1051            chem_dot_factor*r,c,dashed withdots scaled ((.5chem_b_length/3)/5bp)) ;
1052            % not symmetric - needs to be tweaked...
1053    endfor
1054enddef ;
1055
1056vardef chem_hb@# (suffix $) (expr f, t, r, c) = % HB
1057    if chem_star[$] :
1058        chem_rh@#($,f,t,r,c)
1059    else :
1060        chem_t := identity chem_transformed($) ;
1061        for i=f upto t :
1062            chem_draw(
1063                (subpath (chem_sb_pair@# shifted (i-1,i-1)) of chem_b_path[$])
1064                transformed chem_t,
1065                chem_dot_factor*r,c,dashed withdots scaled ((.5chem_b_length/3)/5bp)) ;
1066                % not symmetric - needs to be tweaked...
1067        endfor
1068    fi
1069enddef ;
1070
1071vardef chem_bb@# (suffix $) (expr f, t, r, c) = % BB
1072    if chem_star[$] :
1073        chem_rb@#($,f,t,r,c) ;
1074    elseif chem_front[$] :
1075        chem_t := identity chem_transformed($) ;
1076        chem_draw(
1077            (subpath (f-1,t) of chem_b_path[$]) transformed chem_t,
1078            r,c,) ;
1079        chem_num0 := length chem_b_path[$] ; % total number of bonds
1080        chem_num1 := chem_front_b[$] ;       % number of bonds to be made bold
1081        % bold bonds within f and t
1082        chem_num2 := if f<0 :((f+1) mod chem_num0) + chem_num0 else : ((f-1) mod chem_num0) + 1 fi ;
1083        chem_num3 := if t<0 :((t+1) mod chem_num0) + chem_num0 else : ((t-1) mod chem_num0) + 1 fi ;
1084        if chem_num3<chem_num2 :
1085            chem_num4 := chem_num3 ;
1086            chem_num3 := chem_num2 ;
1087            chem_num2 := chem_num4 ;
1088        fi
1089        if chem_num2<chem_num1 : % Are there any bonds to be made bold?
1090            if chem_num2=1 :     % Skip the first bold bond.
1091                chem_fill(
1092                    (point chem_num2-1 of chem_b_path[$] --
1093                     point chem_num2   of chem_b_path[$] shifted (0,-chem_dbl_offset) --
1094                     point chem_num2   of chem_b_path[$] shifted (0, chem_dbl_offset) --
1095                     cycle) transformed chem_t,
1096                    r,c,) ;
1097            fi
1098            if (chem_num2<=chem_num1-1) and (chem_num3>1) :
1099                chem_path0 := subpath (if chem_num2>2 :         chem_num2-1 else : 1 fi,
1100                                       if chem_num3<chem_num1 : chem_num3   else : chem_num1-1 fi)
1101                    of chem_b_path[$] ;
1102                chem_fill(
1103                    (chem_path0          paralleled -chem_dbl_offset --
1104                     reverse(chem_path0) paralleled -chem_dbl_offset --
1105                    cycle) transformed chem_t,
1106                    r,c,) ;
1107            fi
1108            if chem_num3>=chem_num1 :
1109                chem_fill(
1110                    (point chem_num1 of chem_b_path[$] --
1111                     point chem_num1-1 of chem_b_path[$] shifted (0,-chem_dbl_offset) --
1112                     point chem_num1-1 of chem_b_path[$] shifted (0, chem_dbl_offset) --
1113                     cycle) transformed chem_t,
1114                    r,c,) ;
1115            fi
1116        fi
1117    fi
1118enddef ;
1119
1120vardef chem_rb@# (suffix $) (expr f, t, r, c) = % RB
1121    chem_t := identity chem_transformed($) ;
1122    for i=f upto t :
1123        chem_path0 := subpath chem_sb_pair@# of chem_r_fragment($,i) ;
1124        chem_fill(
1125            (point 0 of chem_path0 --
1126             point 1 of chem_path0
1127                 rotatedaround(point 0 of chem_path0, -chem_bb_angle) --
1128             point 1 of chem_path0
1129                 rotatedaround(point 0 of chem_path0,  chem_bb_angle) --
1130             cycle) transformed chem_t,
1131            r,c,) ;
1132    endfor
1133enddef ;
1134
1135vardef chem_lrb@# (suffix $) (expr f, t, r, c) = % LRB
1136    if not chem_star[$] :
1137        chem_t := identity chem_transformed($) ;
1138        for i=f upto t :
1139            chem_path0 := subpath chem_sb_pair@# of chem_r_fragment.lft($,i) ;
1140            chem_fill(
1141                (point 0 of chem_path0 --
1142                 point 1 of chem_path0
1143                     rotatedaround(point 0 of chem_path0, -chem_bb_angle) --
1144                 point 1 of chem_path0
1145                     rotatedaround(point 0 of chem_path0,  chem_bb_angle) --
1146                 cycle) transformed chem_t,
1147                r,c,) ;
1148        endfor
1149    fi
1150enddef ;
1151
1152vardef chem_rrb@# (suffix $) (expr f, t, r, c) = % RRB
1153    if not chem_star[$] :
1154        chem_t := identity chem_transformed($) ;
1155        for i=f upto t :
1156            chem_path0 := subpath chem_sb_pair@# of chem_r_fragment.rt($,i) ;
1157            chem_fill(
1158                (point 0 of chem_path0 --
1159                 point 1 of chem_path0
1160                     rotatedaround(point 0 of chem_path0, -chem_bb_angle) --
1161                 point 1 of chem_path0
1162                     rotatedaround(point 0 of chem_path0,  chem_bb_angle) --
1163                 cycle) transformed chem_t,
1164                r,c,) ;
1165        endfor
1166    fi
1167enddef ;
1168
1169vardef chem_lsr@# (suffix $) (expr f, t, r, c) = % LSR
1170    if not chem_star[$] :
1171        chem_t := identity chem_transformed($) ;
1172        for i=f upto t :
1173            chem_draw(
1174                (subpath chem_sb_pair@# of chem_r_fragment.lft($,i)) transformed chem_t,
1175                r,c,) ;
1176        endfor
1177    fi
1178enddef ;
1179
1180vardef chem_rsr@# (suffix $) (expr f, t, r, c) = % RSR
1181    if not chem_star[$] :
1182        chem_t := identity chem_transformed($) ;
1183        for i=f upto t :
1184            chem_draw(
1185                (subpath chem_sb_pair@# of chem_r_fragment.rt($,i)) transformed chem_t,
1186                r,c,) ;
1187        endfor
1188    fi
1189enddef ;
1190
1191vardef chem_lrd@# (suffix $) (expr f, t, r, c) = % LRD
1192    if not chem_star[$] :
1193        chem_t := identity chem_transformed($) ;
1194        for i=f upto t :
1195            chem_draw(
1196                (subpath chem_sb_pair@# of chem_r_fragment.lft($,i)) transformed chem_t,
1197                r,c,dashed evenly) ;
1198        endfor
1199    fi
1200enddef ;
1201
1202vardef chem_rrd@# (suffix $) (expr f, t, r, c) = % RRD
1203    if not chem_star[$] :
1204        chem_t := identity chem_transformed($) ;
1205        for i=f upto t :
1206            chem_draw(
1207                (subpath chem_sb_pair@# of chem_r_fragment.rt($,i)) transformed chem_t,
1208                r,c,dashed evenly) ;
1209        endfor
1210    fi
1211enddef ;
1212
1213vardef chem_s@# (suffix $) (expr f, t, r, c) = % S
1214    if length(str @#)>0 :
1215       chem_ss@#($,f,t,r,c) ;
1216    else :
1217       chem_ss.b($,f,t,r,c) ;
1218    fi
1219enddef ;
1220
1221vardef chem_ss@# (suffix $) (expr f, t, r, c) = % SS
1222    if not (chem_star[$] or chem_front[$]) :
1223        chem_draw(
1224            subpath chem_sb_pair@# of (point f-2 of chem_b_path[$] -- point t of chem_b_path[$])
1225            chem_transformed($),
1226            r,c,) ;
1227    fi
1228enddef ;
1229
1230vardef chem_mid@# (suffix $) (expr f, t, r, c) = % MID
1231    if length(str @#)>0 :
1232        chem_mids@#($,f,t,r,c) ;
1233    else :
1234        chem_mids.b($,f,t,r,c) ;
1235    fi
1236enddef ;
1237
1238vardef chem_mids@# (suffix $) (expr f, t, r, c) = % MIDS
1239    if not (chem_star[$] or chem_front[$]) :
1240        chem_t := identity chem_transformed($) ;
1241        for i=f upto t :
1242            chem_draw(
1243                (subpath chem_sb_pair@# of (origin -- point i-1 of chem_b_path[$]))
1244                transformed chem_t,
1245                r,c,) ;
1246        endfor
1247    fi
1248enddef ;
1249
1250vardef chem_cd  (suffix $) (expr r, c) =  % CD
1251    chem_draw(
1252        chem_c_path[$] chem_transformed($),
1253        r,c,dashed evenly) ;
1254enddef ;
1255
1256vardef chem_c (suffix $) (expr r, c) = % C
1257    chem_draw(
1258        chem_c_path[$] chem_transformed($),
1259        r,c,) ;
1260enddef ;
1261
1262vardef chem_ccd  (suffix $) (expr f, t, r, c) = % CCD
1263    chem_num0 := ypart((origin--center(subpath (f-2,f-1) of chem_b_path[$]))
1264               intersectiontimes chem_c_path[$]) ;
1265    chem_num1 := ypart((origin--center(subpath (t-1,t)   of chem_b_path[$]))
1266               intersectiontimes chem_c_path[$]) ;
1267    if chem_num1>chem_num0 :
1268        chem_num0 := chem_num0 + length chem_c_path[$] ;
1269    fi
1270    chem_draw(
1271        subpath (chem_num1,chem_num0) of chem_c_path[$] chem_transformed($),
1272        r,c,dashed evenly) ;
1273enddef ;
1274
1275vardef chem_cc (suffix $) (expr f, t, r, c) = % CC
1276    chem_num0 := ypart((origin--center(subpath (f-2,f-1) of chem_b_path[$]))
1277               intersectiontimes chem_c_path[$]) ;
1278    chem_num1 := ypart((origin--center(subpath (t-1,t)   of chem_b_path[$]))
1279               intersectiontimes chem_c_path[$]) ;
1280    if chem_num1>chem_num0 :
1281        chem_num0 := chem_num0 + length chem_c_path[$] ;
1282    fi
1283    chem_draw(
1284        subpath (chem_num1,chem_num0) of chem_c_path[$] chem_transformed($),
1285        r,c,) ;
1286enddef ;
1287
1288vardef chem_ldb@# (suffix $) (expr f, t, r, c) = % LD
1289    if chem_star[$] :
1290        chem_t := identity chem_transformed($) ;
1291        for i=f upto t :
1292            chem_path0 := subpath chem_sb_pair@# of chem_r_fragment($,i) ;
1293            chem_draw(
1294                chem_path0 transformed chem_t,
1295                r,c,) ;
1296            chem_draw(
1297                (chem_path0 paralleled  2chem_dbl_offset) transformed chem_t,
1298                r,c,) ;
1299        endfor
1300    fi
1301enddef ;
1302
1303vardef chem_rdb@# (suffix $) (expr f, t, r, c) = % LD
1304    if chem_star[$] :
1305        chem_t := identity chem_transformed($) ;
1306        for i=f upto t :
1307            chem_path0 := subpath chem_sb_pair@# of chem_r_fragment($,i) ;
1308            chem_draw(
1309                chem_path0 transformed chem_t,
1310                r,c,) ;
1311            chem_draw(
1312                (chem_path0 paralleled -2chem_dbl_offset) transformed chem_t,
1313                r,c,) ;
1314        endfor
1315    fi
1316enddef ;
1317
1318vardef chem_ldd@# (suffix $) (expr f, t, r, c) = % LDD
1319    if chem_star[$] :
1320        chem_t := identity chem_transformed($) ;
1321        for i=f upto t :
1322            chem_path0 := subpath chem_sb_pair@# of chem_r_fragment($,i) ;
1323            chem_draw(
1324                chem_path0 transformed chem_t,
1325                r,c,) ;
1326            chem_draw(
1327                (chem_path0 paralleled  2chem_dbl_offset) transformed chem_t,
1328                r,c,dashed evenly) ;
1329        endfor
1330    fi
1331enddef ;
1332
1333vardef chem_rdd@# (suffix $) (expr f, t, r, c) = % RDD
1334    if chem_star[$] :
1335        chem_t := identity chem_transformed($) ;
1336        for i=f upto t :
1337            chem_path0 := subpath chem_sb_pair@# of chem_r_fragment($,i) ;
1338            chem_draw(
1339                chem_path0 transformed chem_t,
1340                r,c,) ;
1341            chem_draw(
1342                (chem_path0 paralleled -2chem_dbl_offset) transformed chem_t,
1343                r,c,dashed evenly) ;
1344        endfor
1345    fi
1346enddef ;
1347
1348vardef chem_oe@# (suffix $) (expr f, t, r, c) = % OE
1349    if chem_star[$] :
1350        chem_t := identity chem_transformed($) ;
1351        for i=f upto t :
1352            chem_path0 := subpath chem_sb_pair@# of chem_r_fragment($,i) ;
1353            chem_path1 := chem_path0 paralleled -.5chem_dbl_offset ;
1354            chem_path2 := chem_path0 paralleled  .5chem_dbl_offset ;
1355            chem_draw(
1356                (  point 0 of chem_path0 --
1357                .2[point 0 of chem_path0, point infinity of chem_path0]..
1358                .3[point 0 of chem_path1, point infinity of chem_path1]..
1359                .4[point 0 of chem_path0, point infinity of chem_path0]..
1360                .5[point 0 of chem_path2, point infinity of chem_path2]..
1361                .6[point 0 of chem_path0, point infinity of chem_path0]..
1362                .7[point 0 of chem_path1, point infinity of chem_path1]..
1363                .8[point 0 of chem_path0, point infinity of chem_path0]--
1364                   point infinity of chem_path0) transformed chem_t,
1365                r,c,) ;
1366        endfor
1367    fi
1368enddef ;
1369
1370vardef chem_bw@# (suffix $) (expr f, t, r, c) = % BW
1371    if chem_star[$] :
1372        chem_t := identity chem_transformed($) ;
1373        for i=f upto t :
1374            chem_path0 := subpath chem_sb_pair@# of chem_r_fragment($,i) ;
1375            chem_path1 := chem_path0 paralleled -.5chem_dbl_offset ;
1376            chem_path2 := chem_path0 paralleled  .5chem_dbl_offset ;
1377            chem_draw(
1378                (  point 0 of chem_path0..
1379                .1[point 0 of chem_path1, point infinity of chem_path1]..
1380                .2[point 0 of chem_path0, point infinity of chem_path0]..
1381                .3[point 0 of chem_path2, point infinity of chem_path2]..
1382                .4[point 0 of chem_path0, point infinity of chem_path0]..
1383                .5[point 0 of chem_path1, point infinity of chem_path1]..
1384                .6[point 0 of chem_path0, point infinity of chem_path0]..
1385                .7[point 0 of chem_path2, point infinity of chem_path2]..
1386                .8[point 0 of chem_path0, point infinity of chem_path0]..
1387                .9[point 0 of chem_path1, point infinity of chem_path1]..
1388                   point infinity of chem_path0) transformed chem_t,
1389                r,c,) ;
1390        endfor
1391    fi
1392enddef ;
1393
1394vardef chem_bd@# (suffix $) (expr f, t, r, c) = % BD
1395    if chem_star[$] : chem_rbd@#($,f,t,r,c) ; fi
1396enddef ;
1397
1398vardef chem_rbd@# (suffix $) (expr f, t, r, c) = % RBD
1399    chem_t := identity chem_transformed($) ;
1400    for i=f upto t :
1401        chem_path0 := subpath chem_sb_pair@# of chem_r_fragment($,i) ;
1402        if chem_bd_wedge :
1403            chem_path1 := chem_path0 rotated -chem_bb_angle ;
1404            chem_path2 := chem_path0 rotated  chem_bb_angle ;
1405        else :
1406            chem_path1 := chem_path0 paralleled -chem_dbl_offset ;
1407            chem_path2 := chem_path0 paralleled  chem_dbl_offset ;
1408        fi
1409        for j=0 upto 3 :
1410            chem_draw(
1411                (point (j/3) of chem_path1 -- point (j/3) of chem_path2) transformed chem_t,
1412                2r,c,) ;
1413        endfor
1414    endfor
1415enddef ;
1416
1417vardef chem_lrbd@# (suffix $) (expr f, t, r, c) = % LRBD
1418    if not chem_star[$] :
1419        chem_t := identity chem_transformed($) ;
1420        for i=f upto t :
1421            chem_path0 := subpath chem_sb_pair@# of chem_r_fragment.lft($,i) ;
1422            if chem_bd_wedge :
1423                chem_path1 := chem_path0 rotated -chem_bb_angle ;
1424                chem_path2 := chem_path0 rotated  chem_bb_angle ;
1425            else :
1426                chem_path1 := chem_path0 paralleled -.5chem_dbl_offset ;
1427                chem_path2 := chem_path0 paralleled  .5chem_dbl_offset ;
1428            fi
1429            for j=0 upto 3 :
1430                chem_draw(
1431                    (point (j/3) of chem_path1 -- point (j/3) of chem_path2) transformed chem_t,
1432                    2r,c,) ;
1433            endfor
1434        endfor
1435    fi
1436enddef ;
1437
1438vardef chem_rrbd@# (suffix $) (expr f, t, r, c) = % RRBD
1439    if not chem_star[$] :
1440        chem_t := identity chem_transformed($) ;
1441        for i=f upto t :
1442            chem_path0 := subpath chem_sb_pair@# of chem_r_fragment.rt($,i) ;
1443            if chem_bd_wedge :
1444                chem_path1 := chem_path0 rotated -chem_bb_angle ;
1445                chem_path2 := chem_path0 rotated  chem_bb_angle ;
1446            else :
1447                chem_path1 := chem_path0 paralleled -.5chem_dbl_offset ;
1448                chem_path2 := chem_path0 paralleled  .5chem_dbl_offset ;
1449            fi
1450            for j=0 upto 3 :
1451                chem_draw(
1452                    (point (j/3) of chem_path1 -- point (j/3) of chem_path2) transformed chem_t,
1453                    2r,c,) ;
1454            endfor
1455        endfor
1456    fi
1457enddef ;
1458
1459% text, number (no alignment on number);
1460
1461vardef chem_z@#(suffix $) (expr p) (text t) = % Z
1462    draw chem_text@#
1463        (t,chem_do(
1464            if p=0 :
1465                origin
1466            else :
1467                (point p-1 of chem_b_path[$]) chem_transformed($)
1468            fi
1469        )) ;
1470enddef ;
1471
1472vardef chem_cz@#(suffix $) (expr p) (text t) = chem_z@#($,p,t) ; enddef ; % CZ ?
1473
1474vardef chem_midz@#(suffix $) (expr p) (text t) = % MIDZ
1475    if not (chem_star[$] or chem_front[$]) :
1476        draw chem_text@#
1477            (t,chem_do(
1478                (xpart chem_sb_pair, 0) scaled (xpart point 0 of chem_b_path[$])
1479                chem_transformed($)
1480            )) ;
1481    fi
1482enddef ;
1483
1484vardef chem_rz@#(suffix $) (expr p) (text t) = % RZ
1485     draw chem_text@#
1486         (t, chem_do((point p-1 of chem_r_path[$]) chem_transformed($))) ;
1487enddef ;
1488
1489vardef chem_lrz@#(suffix $) (expr p) (text t) = % LRZ
1490    if not chem_star[$] :
1491        draw chem_text@#
1492            (t,
1493             chem_do((point p-1 of chem_r_path.lft[$]) chem_transformed($))) ;
1494    fi
1495enddef ;
1496
1497vardef chem_rrz@#(suffix $) (expr p) (text t) = % RRZ
1498    if not chem_star[$] :
1499        draw chem_text@#
1500            (t, chem_do((point p-1 of chem_r_path.rt[$]) chem_transformed($))) ;
1501    fi
1502enddef ;
1503
1504vardef chem_zn@#(suffix $) (expr p) (text t) =  % ZN
1505    chem_zt($,p,t) ;
1506enddef ;
1507
1508vardef chem_zt@#(suffix $) (expr p) (text t) = % ZT
1509    draw chem_text@#(t,chem_do ((point p-1 of chem_b_path[$]) chem_transformed($)
1510                                 scaled chem_text_min)) ;
1511enddef ;
1512
1513vardef chem_zln@#(suffix $) (expr p) (text t) = % ZLN
1514    chem_zlt($,p,t) ;
1515enddef ;
1516
1517vardef chem_zlt@#(suffix $) (expr p) (text t) = % ZLT
1518    draw chem_text@#(t, chem_do((point p-1.5 of chem_b_path[$]) chem_transformed($)
1519                                scaled chem_text_min)) ;
1520enddef ;
1521
1522vardef chem_zrn@#(suffix $) (expr p) (text t) = % ZRN
1523    chem_zrt($,p,t) ;
1524enddef ;
1525
1526vardef chem_zrt@#(suffix $) (expr p) (text t) = % ZRT
1527    draw chem_text@#(t, chem_do((point p-0.5 of chem_b_path[$]) chem_transformed($)
1528                                 scaled chem_text_min)) ;
1529enddef ;
1530
1531vardef chem_crz@#(suffix $) (expr p) (text t) = % CRZ ????
1532    if chem_star[$] :
1533        draw chem_text@#(t, chem_do((point p-1 of chem_b_path[$] enlonged chem_center_offset)
1534                                   chem_transformed($))) ;
1535    fi
1536enddef ;
1537
1538vardef chem_rn@#(suffix $) (expr i, t) =  % RN
1539    chem_rt($,i,t) ;
1540enddef ;
1541
1542vardef chem_rt@#(suffix $) (expr p) (text t) = % RT
1543    draw chem_text@#(t, chem_do((center chem_r_fragment($,p)) chem_transformed($))) ;
1544enddef ;
1545
1546vardef chem_lrn@#(suffix $) (expr i, t) = % LRN
1547    chem_lrt($,i,t) ;
1548enddef ;
1549
1550vardef chem_lrt@#(suffix $) (expr p) (text t) = % LRT
1551    draw chem_text@#(t, chem_do((center chem_r_fragment.lft($,p)) chem_transformed($))) ;
1552enddef ;
1553
1554vardef chem_rrn@# (suffix $) (expr i, t) = % RRN
1555    chem_rrt($,i,t) ;
1556enddef ;
1557
1558vardef chem_rrt@#(suffix $) (expr p) (text t) = % RRT
1559    draw chem_text@#(t, chem_do((center chem_r_fragment.rt($,p)) chem_transformed($))) ;
1560enddef ;
1561
1562vardef chem_symbol(expr t) = draw textext(t) ; enddef ;
1563
1564vardef chem_align@#(expr pic) =
1565    pic
1566        if (mfun_labtype@# >= 10) :
1567            shifted (0,ypart center pic)
1568        fi
1569        shifted (-(mfun_labxf@#*lrcorner pic + mfun_labyf@#*ulcorner pic + (1-mfun_labxf@#-mfun_labyf@#)*llcorner pic))
1570enddef ;
1571
1572vardef chem_text@#(expr txt, z) =
1573    chem_pic := textext(txt) ;
1574        if length(str @#)=0 :
1575            chem_pic := chem_align(chem_pic) ;
1576        elseif (str @#) = "auto" :
1577            if z<>origin :
1578                chem_num0 := abs(angle(z rotated chem_setting_rotation)) ;
1579                if chem_num0<=60 :
1580                    chem_pic := chem_align.rt (chem_pic) xshifted  chem_text_offset ;
1581                elseif chem_num0>=120 :
1582                    chem_pic := chem_align.lft(chem_pic) xshifted -chem_text_offset ;
1583                else :
1584                    chem_pic := chem_align    (chem_pic) ;
1585                fi
1586            else :
1587                    chem_pic := chem_align    (chem_pic) ;
1588            fi
1589        else :
1590            chem_pic := chem_align@#(chem_pic) shifted (chem_text_offset*mfun_laboff@#) ;
1591        fi
1592    chem_pic := (chem_pic rotated -chem_setting_rotation) shifted z ;
1593
1594    if chem_trace_text :
1595        draw z                    withpen pencircle scaled 2pt withcolor red ;
1596        draw boundingbox chem_pic withpen pencircle scaled 1pt withcolor red ;
1597    fi
1598
1599    chem_pic
1600enddef ;
1601
1602% transform
1603
1604% rotations and reflections
1605
1606vardef chem_rot (suffix $) (expr d, s) = % ROT
1607    if not chem_front[$] :
1608        if d=0 :
1609            chem_rotation := 0
1610        else :
1611            chem_num0 := if chem_stacked[$] : 3 else : 0 fi ;
1612            chem_num1 := .5(angle(point d+chem_num0   of chem_b_path[$]) -
1613                            angle(point d+chem_num0-1 of chem_b_path[$])) ;
1614            chem_rotation := (chem_rotation + s*chem_num1) zmod 360 ;
1615        fi
1616    fi
1617enddef ;
1618
1619vardef chem_mir (suffix $) (expr d, s)  = % MIR
1620    % We take the scale factor s to multiply the rotation, but only ONCE.
1621    % For example: CARBON,.5MIR12 will give a rotation by 104°
1622    if not chem_front[$] :
1623        if d=0 : % inversion
1624            if chem_mirror=origin :
1625                chem_rotation := (chem_rotation + 180*s) zmod 360 ;
1626            else :
1627                chem_mirror := chem_mirror rotated 90 ;
1628            fi
1629        else :
1630            chem_pair0 := (point d-1 of chem_b_path[$]) scaled s ; % not chem_transformed
1631            if chem_mirror=origin :
1632                chem_mirror := chem_pair0 ;
1633            else :
1634                chem_num0 := angle(chem_mirror)-angle(chem_pair0) ;
1635                if (chem_num0>0) and (chem_num0> 180) :
1636                    chem_num0 :=  360 - chem_num0 ;
1637                elseif (chem_num0<0) and (chem_num0<-180) :
1638                    chem_num0 := -360 - chem_num0 ;
1639                fi
1640                chem_num0 := chem_num0 * s ;
1641                chem_rotation := (chem_rotation + 2chem_num0) zmod 360 ;
1642                chem_mirror := origin ;
1643            fi
1644        fi
1645    fi
1646enddef ;
1647
1648% translations
1649
1650vardef chem_dir (suffix $) (expr d, s) = % DIR (same as MOV(d-1)MOV(d+1))
1651    if not chem_front[$] :
1652        if d=0 :
1653            currentpicture := currentpicture shifted -chem_origin ;
1654            chem_origin    := origin ;
1655        else :
1656            chem_pair0 :=
1657                 (((point d-2 of chem_b_path[$]) shifted (point d of chem_b_path[$])) scaled s)
1658                 chem_transformed($) ;
1659            currentpicture := currentpicture shifted -chem_pair0 ;
1660            chem_origin    := chem_origin    shifted -chem_pair0 ;
1661        fi
1662   fi
1663enddef ;
1664
1665vardef chem_mov (suffix $) (expr d, s) = % MOV
1666    if d=0 :
1667        currentpicture := currentpicture shifted -chem_origin ;
1668        chem_origin    := origin ;
1669    else :
1670        chem_pair0 := ((point d-1 of chem_b_path[$]) scaled s) chem_transformed($) ;
1671        currentpicture := currentpicture shifted -chem_pair0 ;
1672        chem_origin    := chem_origin    shifted -chem_pair0 ;
1673    fi ;
1674enddef ;
1675
1676vardef chem_mark (suffix $) (expr d, s) = % MARK
1677    % scale s is ignored
1678    if d<>0 :
1679        chem_mark_pair[d] := -chem_origin ;
1680    fi
1681enddef ;
1682
1683vardef chem_marked (expr d) =
1684    if d=0 :
1685        chem_origin
1686    elseif known chem_mark_pair[d] :
1687        chem_mark_pair[d] shifted chem_origin
1688    else :
1689        origin
1690    fi
1691enddef ;
1692
1693vardef chem_number@#(suffix $) (expr p) (text t) = chem_label@#($,p,t) enddef ; % NUMBER
1694vardef chem_label@# (suffix $) (expr p) (text t) = % LABEL
1695    draw chem_text@#(t,chem_do(chem_marked(p))) ;
1696enddef ;
1697
1698vardef chem_move (suffix $) (expr d, s) = % MOVE
1699    chem_pair0 := chem_marked(d) scaled s ;
1700    currentpicture := currentpicture shifted -chem_pair0 ;
1701    chem_origin    := chem_origin    shifted -chem_pair0 ;
1702enddef ;
1703
1704vardef chem_diff (suffix $) (expr d, s) = % DIFF
1705    chem_pair0 := (chem_marked(d) shifted -chem_origin) scaled s ;
1706    currentpicture := currentpicture shifted -chem_pair0 ;
1707    chem_origin    := chem_origin    shifted -chem_pair0 ;
1708enddef ;
1709
1710vardef chem_line (suffix $) (expr f, t, r, c) = % LINE
1711    draw if f=t : origin else : chem_marked(f) fi -- chem_marked(t)
1712        % no chem_transformed
1713        withpen pencircle scaled r
1714        withcolor c
1715enddef ;
1716
1717vardef chem_dash (suffix $) (expr f, t, r, c) = % DASH
1718    draw if f=t : origin else : chem_marked(f) fi -- chem_marked(t)
1719        % no chem_transformed
1720        withpen pencircle scaled r
1721        withcolor c
1722        dashed evenly ;
1723enddef ;
1724
1725vardef chem_arrow (suffix $) (expr f, t, r, c) = % ARROW
1726    drawarrow if f=t : origin else : chem_marked(f) fi -- chem_marked(t)
1727        % no chem_transformed
1728        withpen pencircle scaled r
1729        withcolor c
1730enddef ;
1731
1732
1733vardef chem_rm (suffix $) (expr d, s) = % RM
1734    if (not chem_front[$]) and (d<>0) :
1735        chem_pair0 := ((point d-1 of chem_r_path[$]) scaled s) chem_transformed($) ;
1736        currentpicture := currentpicture shifted -chem_pair0 ;
1737        chem_origin    := chem_origin    shifted -chem_pair0 ;
1738    fi ;
1739enddef ;
1740
1741vardef chem_off (suffix $) (expr d, s) = % OFF
1742    if d=0 :
1743        currentpicture := currentpicture shifted -chem_origin ;
1744        chem_origin    := origin ;
1745    else :
1746        chem_pair0 := (unitvector(point d-1 of chem_b_path[one])) scaled chem_setting_offset*s ;
1747        % not chem_transformed
1748        currentpicture := currentpicture shifted -chem_pair0 ;
1749        chem_origin    := chem_origin    shifted -chem_pair0 ;
1750    fi ;
1751enddef ;
1752