%D \module %D [ file=mp-char.mpiv, %D version=2011.10.1, % 1998.10.10, %D title=\CONTEXT\ \METAPOST\ graphics, %D subtitle=charts, %D author=Hans Hagen, %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 is ancient code .. but I see no need to rewrite it. This is %D already a partial rewrite but more could be delegated to \LUA\ %D when used in \CONTEXT\ but it does not pay off now to look into %D that. %D For historic reason we first build and then flush but we could %D as well flush directly which would save us caching. if unknown context_shap : input "mp-shap.mpiv" ; fi ; if known context_flow : endinput ; fi ; boolean context_flow ; context_flow := true ; %D settings numeric flow_grid_width ; flow_grid_width := 60pt ; numeric flow_shape_width ; flow_shape_width := 45pt ; numeric flow_grid_height ; flow_grid_height := 40pt ; numeric flow_shape_height ; flow_shape_height := 30pt ; numeric flow_chart_offset ; flow_chart_offset := 2pt ; numeric flow_chart_clip_offset ; flow_chart_offset := 10pt ; string flow_chart_background_color ; flow_chart_background_color := "white" ; boolean flow_show_mid_points ; flow_show_mid_points := false ; boolean flow_show_con_points ; flow_show_con_points := false ; boolean flow_show_all_points ; flow_show_all_points := false ; numeric flow_shape_line_width ; flow_shape_line_width := 2pt ; string flow_shape_line_color ; flow_shape_line_color := "gray-5" ; string flow_shape_fill_color ; flow_shape_fill_color := "gray-9"; string flow_connection_line_color ; flow_connection_line_color := "gray-2" ; numeric flow_connection_line_width ; flow_connection_line_width := flow_shape_line_width ; numeric flow_connection_smooth_size ; flow_connection_smooth_size := 5pt ; numeric flow_connection_arrow_size ; flow_connection_arrow_size := 4pt ; numeric flow_connection_dash_size ; flow_connection_dash_size := 3pt ; numeric flow_max_x ; flow_max_x := 6 ; numeric flow_max_y ; flow_max_y := 4 ; boolean flow_smooth ; flow_smooth := true ; boolean flow_peepshape ; flow_peepshape := false ; boolean flow_arrowtip ; flow_arrowtip := true ; boolean flow_dashline ; flow_dashline := false ; boolean flow_forcevalid ; flow_forcevalid := false ; boolean flow_touchshape ; flow_touchshape := false ; boolean flow_showcrossing ; flow_showcrossing := false ; boolean flow_reverse_y ; flow_reverse_y := true ; picture flow_dash_pattern ; flow_dash_pattern := nullpicture ; numeric flow_shape_node ; flow_shape_node := 0 ; numeric flow_shape_action ; flow_shape_action := 24 ; numeric flow_shape_procedure ; flow_shape_procedure := 5 ; numeric flow_shape_product ; flow_shape_product := 12 ; numeric flow_shape_decision ; flow_shape_decision := 14 ; numeric flow_shape_archive ; flow_shape_archive := 19 ; numeric flow_shape_loop ; flow_shape_loop := 35 ; numeric flow_shape_wait ; flow_shape_wait := 6 ; numeric flow_shape_subprocedure ; flow_shape_subprocedure := 20 ; numeric flow_shape_singledocument ; flow_shape_singledocument := 32 ; numeric flow_shape_multidocument ; flow_shape_multidocument := 33 ; numeric flow_shape_right ; flow_shape_right := 66 ; numeric flow_shape_left ; flow_shape_left := 67 ; numeric flow_shape_up ; flow_shape_up := 68 ; numeric flow_shape_down ; flow_shape_down := 69 ; numeric flow_label_offset ; flow_label_offset := 0 ; numeric flow_exit_offset ; flow_exit_offset := 0 ; numeric flow_comment_offset ; flow_comment_offset := 0 ; % vardef some_shape_path (expr type) == imported from mp-shap def flow_show_shapes(expr n) = flow_begin_chart(n,8,10) ; flow_show_con_points := true ; for i=0 upto 7 : for j=0 upto 9 : flow_new_shape(i+1,j+1,i*10+j); endfor ; endfor ; flow_end_chart ; enddef ; %D connections def flow_new_chart = flow_grid_width := 60pt ; flow_shape_width := 45pt ; flow_grid_height := 40pt ; flow_shape_height := 30pt ; flow_chart_offset := 2pt ; flow_chart_clip_offset := 10pt ; flow_chart_background_color := "white" ; flow_show_mid_points := false ; flow_show_con_points := false ; flow_show_all_points := false ; flow_shape_line_width := 2pt ; flow_shape_line_color := "gray-5" ; flow_shape_fill_color := "gray-9" ; flow_connection_line_color := "gray-2" ; flow_connection_line_width := flow_shape_line_width ; flow_connection_smooth_size := 5pt ; flow_connection_arrow_size := 4pt ; flow_connection_dash_size := 3pt ; flow_label_offset := 0 ; flow_exit_offset := 0 ; flow_comment_offset := 0 ; flow_max_x := 6 ; flow_max_y := 4 ; flow_smooth := true ; flow_peepshape := false ; flow_arrowtip := true ; flow_dashline := false ; flow_forcevalid := false ; flow_touchshape := false ; flow_showcrossing := false ; flow_reverse_y := true ; flow_dash_pattern := nullpicture ; numeric flow_xypoint ; flow_xypoint := 0 ; numeric flow_cpath ; flow_cpath := 0 ; pair flow_xypoints [] ; boolean flow_xyfree [][] ; path flow_xypath [][] ; numeric flow_xysx [][] ; numeric flow_xysy [][] ; string flow_xyfill [][] ; string flow_xydraw [][] ; numeric flow_xyline [][] ; boolean flow_xypeep [][] ; picture flow_xytext [][] ; picture flow_xylabel [][] ; picture flow_xyexit [][] ; picture flow_xycomment [][] ; path flow_cpaths [] ; numeric flow_cline [] ; string flow_ccolor [] ; boolean flow_carrow [] ; boolean flow_cdash [] ; boolean flow_ccross [] ; picture flow_tpicture [][] ; picture flow_bpicture [][] ; picture flow_lpicture [][] ; picture flow_rpicture [][] ; path flow_connections[][][] ; predefined_shapes[61] := (fullcircle scaled (1.5*predefined_shapes_yradius) xscaled (flow_grid_height/flow_grid_width)) ; predefined_shapes[62] := (fullcircle scaled (2.0*predefined_shapes_yradius) xscaled (flow_grid_height/flow_grid_width)) ; enddef ; flow_new_chart ; def flow_y_pos(expr y) = % if flow_reverse_y : flow_max_y + 1 - y % else : % y % fi enddef ; def flow_initialize_grid(expr maxx, maxy) = flow_max_x := maxx ; flow_max_y := maxy ; flow_dsp_x := 0 ; flow_dsp_y := 0 ; for x=1 upto flow_max_x : for y=1 upto flow_max_y : flow_xyfree[x][y] := true ; flow_xyfill[x][y] := flow_shape_fill_color ; flow_xydraw[x][y] := flow_shape_line_color ; flow_xyline[x][y] := flow_shape_line_width ; endfor ; endfor ; enddef ; def flow_scaled_to_grid = xscaled flow_grid_width yscaled flow_grid_height enddef ; def flow_xy_offset(expr x, y) = (x+.5,y+.5) enddef ; def flow_draw_shape(expr x, yy, p, sx, sy) = begingroup ; save y ; numeric y ; y := flow_y_pos(yy) ; flow_xypath [x][y] := (p xscaled sx yscaled sy) shifted flow_xy_offset(x,y) ; flow_xyfree [x][y] := false ; flow_xysx [x][y] := sx ; flow_xysy [x][y] := sy ; flow_xyfill [x][y] := flow_shape_fill_color ; flow_xydraw [x][y] := flow_shape_line_color ; flow_xyline [x][y] := flow_shape_line_width ; flow_xypeep [x][y] := flow_peepshape ; endgroup ; enddef ; vardef flow_i_point (expr x, y, p, t) = begingroup ; save q, ok ; pair q ; boolean ok ; q := flow_xypath[x][y] intersection_point ((p) shifted flow_xy_offset(x,y)) ; ok := true ; if not ok : message (t & " of shape (" & decimal x & "," & decimal y & ") limited") ; fi ; q endgroup enddef ; vardef flow_trimmed (expr x, y, z, t) = if flow_touchshape and t : flow_xyline[x][y]/z else : epsilon fi enddef ; numeric flow_zfactor ; flow_zfactor := 1/3 ; vardef flow_xy_bottom (expr x, y, z, t) = flow_i_point(x, y, ((0,0)--(0,-2)) shifted (flow_zfactor*z*flow_xysx[x][y],0), "bottom") shifted(0,-flow_trimmed(x,y,flow_grid_height,t)) enddef ; vardef flow_xy_top (expr x, y, z, t) = flow_i_point (x, y, ((0,0)--(0,2)) shifted (flow_zfactor*z*flow_xysx[x][y],0), "top") shifted(0,flow_trimmed(x,y,flow_grid_height,t)) enddef ; vardef flow_xy_left (expr x, y, z, t) = flow_i_point (x, y, ((0,0)--(-2,0)) shifted (0,flow_zfactor*z*flow_xysy[x][y]), "left") shifted(-flow_trimmed(x,y,flow_grid_width,t),0) enddef ; vardef flow_xy_right (expr x, y, z, t) = flow_i_point (x, y, ((0,0)--(2,0)) shifted (0,flow_zfactor*z*flow_xysy[x][y]), "right") shifted(flow_trimmed(x,y,flow_grid_width,t),0) enddef ; def flow_flush_shapes = for x=1 upto flow_max_x : for y=1 upto flow_max_y : flow_flush_shape(x, y) ; endfor ; endfor ; enddef ; def flow_flush_pictures = for x=1 upto flow_max_x : for y=1 upto flow_max_y : flow_flush_picture(x, y) ; endfor ; endfor ; enddef ; def flow_draw_connection_point(expr x, y, z) = pickup pencircle scaled if (z=0): 2 fi flow_xyline[x][y] ; drawdot flow_xy_bottom(x,y,z,false) flow_scaled_to_grid withcolor (1,0,0) ; drawdot flow_xy_top (x,y,z,false) flow_scaled_to_grid withcolor (0,1,0) ; drawdot flow_xy_left (x,y,z,false) flow_scaled_to_grid withcolor (0,0,1) ; drawdot flow_xy_right (x,y,z,false) flow_scaled_to_grid withcolor (1,1,0) ; enddef ; def flow_flush_shape(expr x, yy) = begingroup ; save y ; numeric y ; y := flow_y_pos(yy) ; if not flow_xyfree[x][y] : pickup pencircle scaled flow_xyline[x][y] ; if flow_xypeep[x][y] : fill (flow_xypath[x][y] peepholed (unitsquare shifted (x,y))) flow_scaled_to_grid withpen pencircle scaled 0 withcolor flow_chart_background_color ; else : fill flow_xypath[x][y] flow_scaled_to_grid withcolor flow_xyfill[x][y] ; fi ; draw flow_xypath[x][y] flow_scaled_to_grid withcolor flow_xydraw[x][y] ; if flow_show_con_points or flow_show_all_points : flow_draw_connection_point(x, y, 0) ; fi ; if flow_show_all_points : for i=-1 upto 1 : flow_draw_connection_point(x, y, i) ; endfor ; fi ; fi ; endgroup ; enddef ; vardef flow_points_initialized(expr xfrom, yfrom, xto, yto, n) = if unknown flow_xyfree[xfrom][yfrom] or unknown flow_xyfree[xto][yto] : flow_xypoint := 0 ; false elseif not flow_xyfree[xfrom][yfrom] and not flow_xyfree[xto][yto] : flow_xypoint := n ; true else : flow_xypoint := 0 ; false fi enddef ; def flow_collapse_points = % this can become a core macro begingroup ; % remove redundant points save n ; numeric n ; n := 1 ; for i=2 upto flow_xypoint : if not (flow_xypoints[i] = flow_xypoints[n]) : n := n + 1 ; flow_xypoints[n] := flow_xypoints[i] fi ; endfor ; flow_xypoint := n ; % make straight lines if flow_xypoints[2] = flow_xypoints[flow_xypoint-1] : flow_xypoints[3] := flow_xypoints[flow_xypoint] ; flow_xypoint := 3 ; fi ; endgroup ; enddef ; vardef flow_smooth_connection(expr a,b) = if ypart a = ypart b : a shifted ( if xpart a >= xpart b : - fi (flow_connection_smooth_size/flow_grid_width ),0) else : a shifted (0,if ypart a >= ypart b : - fi (flow_connection_smooth_size/flow_grid_height) ) fi enddef ; vardef flow_trim_points = begingroup save p, a, b, d, i ; numeric a, b ; path p ; pair d ; p := for i=1 upto flow_xypoint-1 : flow_xypoints[i]-- endfor flow_xypoints[flow_xypoint] ; if flow_touchshape : a := flow_shape_line_width/flow_grid_width ; b := flow_shape_line_width/flow_grid_height ; else : a := epsilon ; b := epsilon ; fi ; d := direction infinity of p ; flow_xypoints[flow_xypoint] := flow_xypoints[flow_xypoint] shifted if xpart d < 0 : (+a,0) ; elseif xpart d > 0 : (-a,0) ; elseif ypart d < 0 : (0,+b) ; elseif ypart d > 0 : (0,-b) ; else : origin ; fi ; d := direction 0 of p ; flow_xypoints[1] := flow_xypoints[1] shifted if xpart d < 0 : (-a,0) ; elseif xpart d > 0 : (+a,0) ; elseif ypart d < 0 : (0,-b) ; elseif ypart d > 0 : (0,+b) ; else : origin ; fi ; endgroup enddef ; vardef flow_trim_points = enddef ; vardef flow_connection_path = if flow_reverse_connection : reverse fi (flow_xypoints[1] -- for i=2 upto flow_xypoint-1 : if flow_smooth : flow_smooth_connection(flow_xypoints[i],flow_xypoints[i-1]) .. controls flow_xypoints[i] and flow_xypoints[i] .. flow_smooth_connection(flow_xypoints[i],flow_xypoints[i+1]) -- else : flow_xypoints[i] -- fi endfor flow_xypoints[flow_xypoint]) enddef ; def flow_draw_connection(expr i,xfrom,yfrom,xto,yto) = % 'i' is a comment reference if flow_xypoint > 0 : flow_collapse_points ; flow_trim_points ; flow_cpath := flow_cpath + 1 ; % maybe also store as x,y flow_cpaths[flow_cpath] := flow_connection_path flow_scaled_to_grid ; flow_cline[flow_cpath] := flow_connection_line_width ; flow_ccolor[flow_cpath] := flow_connection_line_color ; flow_carrow[flow_cpath] := flow_arrowtip ; flow_cdash[flow_cpath] := flow_dashline ; flow_ccross[flow_cpath] := flow_showcrossing ; if flow_reverse_connection : flow_connections[xto] [yto] [i] := flow_cpaths[flow_cpath] ; else : flow_connections[xfrom][yfrom][i] := flow_cpaths[flow_cpath] ; fi ; else : message("no connection defined") ; fi ; flow_reverse_connection := false ; enddef ; def flow_flush_connections = % protect locals begingroup ; save ip, crossing, cp ; numeric ip ; boolean crossing ; path cp ; ahlength := flow_connection_arrow_size ; flow_dash_pattern := dashpattern(on flow_connection_dash_size off flow_connection_dash_size) ; for i=1 upto flow_cpath : if flow_ccross[i] : crossing := false ; for j=1 upto i : if not (point infinity of flow_cpaths[i] = point infinity of flow_cpaths[j]) : ip := flow_cpaths[i] intersection_point flow_cpaths[j] ; if intersection_found : crossing := true fi ; fi ; endfor ; if crossing : pickup pencircle scaled 2flow_cline[i] ; cp := flow_cpaths[i] ; cp := cp cutbefore point .05 length cp of cp ; cp := cp cutafter point .95 length cp of cp ; draw cp withcolor flow_chart_background_color ; fi ; fi ; pickup pencircle scaled flow_cline[i] ; if flow_carrow[i] : if flow_cdash[i] : drawarrow flow_cpaths[i] withcolor flow_ccolor[i] dashed flow_dash_pattern ; else : drawarrow flow_cpaths[i] withcolor flow_ccolor[i] ; fi ; else : if flow_cdash[i] : draw flow_cpaths[i] withcolor flow_ccolor[i] dashed flow_dash_pattern ; else : draw flow_cpaths[i] withcolor flow_ccolor[i] ; fi ; fi ; flow_draw_midpoint(i) ; endfor ; endgroup ; enddef ; def flow_draw_midpoint (expr n) = begingroup save p ; pair p ; p := point .5*length(flow_cpaths[n]) of flow_cpaths[n]; pickup pencircle scaled 2flow_cline[n] ; if flow_show_mid_points : drawdot p withcolor .7white ; fi ; endgroup ; enddef ; def flow_flush_picture(expr x, yy) = begingroup ; save y ; numeric y ; y := flow_y_pos(yy) ; % maybe move this to the makers if known flow_xytext[x][y] : draw flow_xytext[x][y] ; fi ; if known flow_xylabel[x][y] : draw flow_xylabel[x][y] ; fi ; if known flow_xyexit[x][y] : draw flow_xyexit[x][y] ; fi ; if known flow_xycomment[x][y] : draw flow_xycomment[x][y] ; fi ; endgroup ; enddef ; vardef flow_offset(expr x, y) = flow_xy_offset((x+0.5)*flow_grid_width,(flow_max_y-y+1.5)*flow_grid_height) shifted (-flow_xyline[x][y]/4,-flow_xyline[x][y]/4) % terrible hack (some compensation) enddef ; def flow_chart_draw_text(expr x, y, p) = if known flow_xytext[x][y] : addto flow_xytext[x][y] also else : flow_xytext[x][y] := fi p shifted flow_offset(x,y) ; enddef ; def flow_chart_draw_label (expr x, y, loc, txt) = begingroup ; save p, s ; path p ; picture s ; p := fullsquare xscaled flow_grid_width yscaled flow_grid_height ; p := p shifted flow_offset(x,y) ; s := txt ; setbounds s to boundingbox s enlarged flow_label_offset ; if known flow_xylabel[x][y] : addto flow_xylabel[x][y] also else : flow_xylabel[x][y] := fi if loc = "tr" : anchored.llft(s,0.5[ulcorner p,urcorner p]) ; elseif loc = "t" : anchored.bot (s,0.5[ulcorner p,urcorner p]) ; elseif loc = "tl" : anchored.lrt (s,0.5[ulcorner p,urcorner p]) ; elseif loc = "br" : anchored.ulft(s,0.5[llcorner p,lrcorner p]) ; elseif loc = "b" : anchored.top (s,0.5[llcorner p,lrcorner p]) ; elseif loc = "bl" : anchored.urt (s,0.5[llcorner p,lrcorner p]) ; elseif loc = "lb" : anchored.urt (s,0.5[ulcorner p,llcorner p]) ; elseif loc = "l" : anchored.rt (s,0.5[ulcorner p,llcorner p]) ; elseif loc = "lt" : anchored.lrt (s,0.5[ulcorner p,llcorner p]) ; elseif loc = "rb" : anchored.ulft(s,0.5[urcorner p,lrcorner p]) ; elseif loc = "r" : anchored.lft (s,0.5[urcorner p,lrcorner p]) ; elseif loc = "rt" : anchored.llft(s,0.5[urcorner p,lrcorner p]) ; else : anchored (s,center p) ; fi ; endgroup ; enddef ; def flow_chart_draw_exit (expr x, y, loc, txt) = begingroup ; save p, s ; path p ; picture s ; p := fullsquare xscaled flow_grid_width yscaled flow_grid_height ; p := p shifted flow_offset(x,y) ; s := txt ; setbounds s to boundingbox s enlarged flow_exit_offset ; if known flow_xyexit[x][y] : addto flow_xyexit[x][y] also else : flow_xyexit[x][y] := fi if loc = "t" : anchored.top(s,0.5[ulcorner p,urcorner p]) ; elseif loc = "b" : anchored.bot(s,0.5[llcorner p,lrcorner p]) ; elseif loc = "l" : anchored.lft(s,0.5[ulcorner p,llcorner p]) ; elseif loc = "r" : anchored.rt (s,0.5[urcorner p,lrcorner p]) ; else : anchored (s,center p) ; fi ; endgroup ; enddef ; def flow_chart_draw_comment (expr x, y, i, loc, len, txt) = % per connection begingroup ; if known flow_connections[x][y][i] : save p, q, s ; path p, q ; picture s ; p := fullsquare xscaled flow_shape_width yscaled flow_shape_height ; p := p shifted flow_offset(x,y) ; q := flow_connections[x][y][i] ; % already relocated s := txt ; setbounds s to boundingbox s enlarged flow_comment_offset ; if known flow_xycomment[x][y] : addto flow_xycomment[x][y] also else : flow_xycomment[x][y] := fi if loc = "tr" : anchored.llft(s,if len = 0 : 0.5[ulcorner p,urcorner p] else : point len along q fi) ; elseif loc = "t" : anchored.bot (s,if len = 0 : 0.5[ulcorner p,urcorner p] else : point len along q fi) ; elseif loc = "tl" : anchored.lrt (s,if len = 0 : 0.5[ulcorner p,urcorner p] else : point len along q fi) ; elseif loc = "br" : anchored.ulft(s,if len = 0 : 0.5[llcorner p,lrcorner p] else : point len along q fi) ; elseif loc = "b" : anchored.top (s,if len = 0 : 0.5[llcorner p,lrcorner p] else : point len along q fi) ; elseif loc = "bl" : anchored.urt (s,if len = 0 : 0.5[llcorner p,lrcorner p] else : point len along q fi) ; elseif loc = "lb" : anchored.urt (s,if len = 0 : 0.5[ulcorner p,llcorner p] else : point len along q fi) ; elseif loc = "l" : anchored.rt (s,if len = 0 : 0.5[ulcorner p,llcorner p] else : point len along q fi) ; elseif loc = "lt" : anchored.lrt (s,if len = 0 : 0.5[ulcorner p,llcorner p] else : point len along q fi) ; elseif loc = "rb" : anchored.ulft(s,if len = 0 : 0.5[urcorner p,lrcorner p] else : point len along q fi) ; elseif loc = "r" : anchored.lft (s,if len = 0 : 0.5[urcorner p,lrcorner p] else : point len along q fi) ; elseif loc = "rt" : anchored.llft(s,if len = 0 : 0.5[urcorner p,lrcorner p] else : point len along q fi) ; elseif loc = "tr:*" : anchored.llft(s,point 0 of q) ; elseif loc = "t:*" : anchored.bot (s,point 0 of q) ; elseif loc = "tl:*" : anchored.lrt (s,point 0 of q) ; elseif loc = "br:*" : anchored.ulft(s,point 0 of q) ; elseif loc = "b:*" : anchored.top (s,point 0 of q) ; elseif loc = "bl:*" : anchored.urt (s,point 0 of q) ; elseif loc = "lb:*" : anchored.urt (s,point 0 of q) ; elseif loc = "l:*" : anchored.rt (s,point 0 of q) ; elseif loc = "lt:*" : anchored.lrt (s,point 0 of q) ; elseif loc = "rb:*" : anchored.ulft(s,point 0 of q) ; elseif loc = "r:*" : anchored.lft (s,point 0 of q) ; elseif loc = "rt:*" : anchored.llft(s,point 0 of q) ; else : anchored (s,point 0 of q) ; fi ; fi ; endgroup ; enddef ; boolean flow_reverse_connection ; flow_reverse_connection := false ; vardef flow_up_on_grid (expr n) = (xpart flow_xypoints[n],(ypart flow_xypoints[n]+1) div 1) enddef ; vardef flow_down_on_grid (expr n) = (xpart flow_xypoints[n],(ypart flow_xypoints[n]) div 1) enddef ; vardef flow_left_on_grid (expr n) = ((xpart flow_xypoints[n]) div 1, ypart flow_xypoints[n]) enddef ; vardef flow_right_on_grid (expr n) = ((xpart flow_xypoints[n]+1) div 1, ypart flow_xypoints[n]) enddef ; vardef flow_x_on_grid (expr n, xfrom, xto, zfrom) = if (xfrom = xto) and not (zfrom = 0) : if (zfrom=1) : flow_right_on_grid(2) else : flow_left_on_grid(2) fi elseif xpart flow_xypoints[1] < xpart flow_xypoints[6] : flow_right_on_grid(n) else : flow_left_on_grid(n) fi enddef ; vardef flow_y_on_grid (expr n, yfrom, yto, zfrom) = if (yfrom = yto) and not (zfrom = 0) : if (zfrom = 1) : flow_up_on_grid(2) else : flow_down_on_grid(2) fi elseif ypart flow_xypoints[1] < ypart flow_xypoints[6] : flow_up_on_grid(n) else : flow_down_on_grid(n) fi enddef ; vardef flow_xy_on_grid (expr n, m) = (xpart flow_xypoints[n], ypart flow_xypoints[m]) enddef ; vardef flow_down_to_grid (expr a,b) = (xpart flow_xypoints[a], ypart flow_xypoints[if ypart flow_xypoints[a]ypart flow_xypoints[b] : a else : b fi]) enddef ; vardef flow_left_to_grid (expr a,b) = (xpart flow_xypoints[if xpart flow_xypoints[a]xpart flow_xypoints[b] : a else : b fi], ypart flow_xypoints[a]) enddef ; vardef flow_valid_connection (expr xfrom, yfrom, xto, yto) = begingroup ; save ok, vc, pp ; boolean ok ; pair vc ; path pp ; save flow_xyfirst, flow_xylast ; pair flow_xyfirst, flow_xylast ; % check for slanted lines ok := true ; for i=1 upto flow_xypoint-1 : if not ((xpart flow_xypoints[i]=xpart flow_xypoints[i+1]) or (ypart flow_xypoints[i]=ypart flow_xypoints[i+1])) : ok := false ; fi ; endfor ; if not ok : % message("slanted"); false elseif flow_forcevalid : % message("force"); true elseif (xfrom=xto) and (yfrom=yto) : % message("self"); false else : % check for crossing shapes flow_xyfirst := flow_xypoints[1] ; flow_xylast := flow_xypoints[flow_xypoint] ; flow_trim_points ; pp := for i=1 upto flow_xypoint-1 : flow_xypoints[i]-- endfor flow_xypoints[flow_xypoint] ; flow_xypoints[1] := flow_xyfirst ; flow_xypoints[flow_xypoint] := flow_xylast ; for i=1 upto flow_max_x : for j=1 upto flow_max_y : % was bug: xfrom,yto % if not ( ( (i,j)=(xfrom,yfrom) ) or ( (i,j)=(xto,yto) ) ) : if not flow_xyfree[i][j] : vc := pp intersection_point flow_xypath[i][j] ; if intersection_found : ok := false fi ; fi ; % fi ; endfor ; endfor ; % if not ok: message("crossing") ; fi ; ok fi endgroup enddef ; def flow_connect_top_bottom (expr n) (expr xfrom, yyfrom, zfrom) (expr xto, yyto, zto) = yfrom := flow_y_pos(yyfrom) ; yto := flow_y_pos(yyto) ; if flow_points_initialized(xfrom,yfrom,xto,yto,6) : flow_xypoints[1] := flow_xy_top(xfrom,yfrom,zfrom,true) ; flow_xypoints[6] := flow_xy_bottom(xto,yto,zto,true) ; flow_xypoints[2] := flow_up_on_grid(1) ; flow_xypoints[5] := flow_down_on_grid(6) ; flow_xypoints[3] := flow_up_to_grid(2,5) ; flow_xypoints[4] := flow_up_to_grid(2,5) ; if not flow_valid_connection(xfrom,yfrom,xto,yto) : flow_xypoints[3] := flow_x_on_grid(2,xfrom,xto,zfrom) ; flow_xypoints[4] := flow_xy_on_grid(3,5) ; fi ; %%%% begin experiment flow_xypoints[3] := flow_xypoints[3] shifted (flow_dsp_x,0) ; flow_xypoints[4] := flow_xypoints[4] shifted (flow_dsp_x,0) ; if flow_dsp_y>0 : flow_xypoints[2] := flow_xypoints[2] shifted (0,flow_dsp_y) ; flow_xypoints[3] := flow_xypoints[3] shifted (0,flow_dsp_y) ; elseif flow_dsp_y<0 : flow_xypoints[4] := flow_xypoints[4] shifted (0,flow_dsp_y) ; flow_xypoints[5] := flow_xypoints[5] shifted (0,flow_dsp_y) ; fi %%%% end experiment flow_draw_connection(n,xfrom,yyfrom,xto,yyto) ; fi ; enddef ; def flow_connect_left_right (expr n) (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) = yfrom := flow_y_pos(yyfrom) ; yto := flow_y_pos(yyto) ; if flow_points_initialized(xfrom,yfrom,xto,yto,6) : flow_xypoints[1] := flow_xy_left(xfrom,yfrom,zfrom,true) ; flow_xypoints[6] := flow_xy_right(xto,yto,zto,true) ; flow_xypoints[2] := flow_left_on_grid(1) ; flow_xypoints[5] := flow_right_on_grid(6) ; flow_xypoints[3] := flow_left_to_grid(2,5) ; flow_xypoints[4] := flow_left_to_grid(2,5) ; if not flow_valid_connection(xfrom,yfrom,xto,yto) : flow_xypoints[3] := flow_y_on_grid(2,yfrom,yto,zfrom) ; flow_xypoints[4] := flow_xy_on_grid(5,3) ; fi ; %%%% begin experiment if flow_dsp_y <> 0 : flow_xypoints[3] := flow_xypoints[3] shifted (0,-flow_dsp_y) ; flow_xypoints[4] := flow_xypoints[4] shifted (0,-flow_dsp_y) ; fi ; %%%% end experiment flow_draw_connection(n,xfrom,yyfrom,xto,yyto) ; fi ; enddef ; def flow_connect_left_top (expr n) (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) = yfrom := flow_y_pos(yyfrom) ; yto := flow_y_pos(yyto) ; if flow_points_initialized(xfrom,yfrom,xto,yto,5) : flow_xypoints[1] := flow_xy_left(xfrom,yfrom,zfrom,true) ; flow_xypoints[5] := flow_xy_top(xto,yto,zto,true) ; flow_xypoints[2] := flow_left_on_grid(1) ; flow_xypoints[4] := flow_up_on_grid(5) ; flow_xypoints[3] := flow_left_to_grid(2,5) ; if not flow_valid_connection(xfrom,yfrom,xto,yto) : flow_xypoints[3] := flow_xy_on_grid(2,4) ; fi ; flow_draw_connection(n,xfrom,yyfrom,xto,yyto) ; fi ; enddef ; def flow_connect_left_bottom (expr n) (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) = yfrom := flow_y_pos(yyfrom) ; yto := flow_y_pos(yyto) ; if flow_points_initialized(xfrom,yfrom,xto,yto,5) : flow_xypoints[1] := flow_xy_left(xfrom,yfrom,zfrom,true) ; flow_xypoints[5] := flow_xy_bottom(xto,yto,zto,true) ; flow_xypoints[2] := flow_left_on_grid(1) ; flow_xypoints[4] := flow_down_on_grid(5) ; flow_xypoints[3] := flow_left_to_grid(2,5) ; if not flow_valid_connection(xfrom,yfrom,xto,yto) : flow_xypoints[3] := flow_xy_on_grid(2,4) ; fi ; flow_draw_connection(n,xfrom,yyfrom,xto,yyto) ; fi ; enddef ; def flow_connect_right_top (expr n) (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) = yfrom := flow_y_pos(yyfrom) ; yto := flow_y_pos(yyto) ; if flow_points_initialized(xfrom,yfrom,xto,yto,5) : flow_xypoints[1] := flow_xy_right(xfrom,yfrom,zfrom,true) ; flow_xypoints[5] := flow_xy_top(xto,yto,zto,true) ; flow_xypoints[2] := flow_right_on_grid(1) ; flow_xypoints[4] := flow_up_on_grid(5) ; flow_xypoints[3] := flow_right_to_grid(2,5) ; if not flow_valid_connection(xfrom,yfrom,xto,yto) : flow_xypoints[3] := flow_xy_on_grid(2,4) ; fi ; flow_draw_connection(n,xfrom,yyfrom,xto,yyto) ; fi ; enddef ; def flow_connect_right_bottom (expr n) (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) = yfrom := flow_y_pos(yyfrom) ; yto := flow_y_pos(yyto) ; if flow_points_initialized(xfrom,yfrom,xto,yto,5) : flow_xypoints[1] := flow_xy_right(xfrom,yfrom,zfrom,true) ; flow_xypoints[5] := flow_xy_bottom(xto,yto,zto,true) ; flow_xypoints[2] := flow_right_on_grid(1) ; flow_xypoints[4] := flow_down_on_grid(5) ; flow_xypoints[3] := flow_right_to_grid(2,5) ; if not flow_valid_connection(xfrom,yfrom,xto,yto) : flow_xypoints[3] := flow_xy_on_grid(2,4) ; fi ; %%%% begin experiment flow_xypoints[2] := flow_xypoints[2] shifted (flow_dsp_x,0) ; flow_xypoints[3] := flow_xypoints[3] shifted (flow_dsp_x,0) ; if flow_dsp_y>0 : flow_xypoints[3] := flow_xypoints[3] shifted (0,-flow_dsp_y) ; flow_xypoints[4] := flow_xypoints[4] shifted (0,-flow_dsp_y) ; elseif flow_dsp_y<0 : flow_xypoints[3] := flow_xypoints[3] shifted (0,flow_dsp_y) ; flow_xypoints[4] := flow_xypoints[4] shifted (0,flow_dsp_y) ; fi %%%% end experiment flow_draw_connection(n,xfrom,yyfrom,xto,yyto) ; fi ; enddef ; def flow_connect_left_left (expr n) (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) = yfrom := flow_y_pos(yyfrom) ; yto := flow_y_pos(yyto) ; if flow_points_initialized(xfrom,yfrom,xto,yto,6) : flow_xypoints[1] := flow_xy_left(xfrom,yfrom,zfrom,true) ; flow_xypoints[6] := flow_xy_left(xto,yto,zto,true) ; flow_xypoints[2] := flow_left_on_grid(1) ; flow_xypoints[5] := flow_left_on_grid(6) ; flow_xypoints[3] := flow_left_to_grid(2,5) ; flow_xypoints[4] := flow_left_to_grid(5,2) ; if not flow_valid_connection(xfrom,yfrom,xto,yto) : flow_xypoints[3] := flow_y_on_grid(2,yfrom,yto,zfrom) ; flow_xypoints[4] := flow_xy_on_grid(5,3) ; fi ; flow_draw_connection(n,xfrom,yyfrom,xto,yyto) ; fi ; enddef ; def flow_connect_right_right (expr n) (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) = yfrom := flow_y_pos(yyfrom) ; yto := flow_y_pos(yyto) ; if flow_points_initialized(xfrom,yfrom,xto,yto,6) : flow_xypoints[1] := flow_xy_right(xfrom,yfrom,zfrom,true) ; flow_xypoints[6] := flow_xy_right(xto,yto,zto,true) ; flow_xypoints[2] := flow_right_on_grid(1) ; flow_xypoints[5] := flow_right_on_grid(6) ; flow_xypoints[3] := flow_right_to_grid(2,5) ; flow_xypoints[4] := flow_right_to_grid(5,2) ; if not flow_valid_connection(xfrom,yfrom,xto,yto) : flow_xypoints[3] := flow_y_on_grid(2,yfrom,yto,zfrom) ; flow_xypoints[4] := flow_xy_on_grid(5,3) ; fi ; flow_draw_connection(n,xfrom,yyfrom,xto,yyto) ; fi ; enddef ; def flow_connect_top_top (expr n) (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) = yfrom := flow_y_pos(yyfrom) ; yto := flow_y_pos(yyto) ; if flow_points_initialized(xfrom,yfrom,xto,yto,6) : flow_xypoints[1] := flow_xy_top(xfrom,yfrom,zfrom,true) ; flow_xypoints[6] := flow_xy_top(xto,yto,zto,true) ; flow_xypoints[2] := flow_up_on_grid(1) ; flow_xypoints[5] := flow_up_on_grid(6) ; flow_xypoints[3] := flow_up_to_grid(2,5) ; flow_xypoints[4] := flow_up_to_grid(5,2) ; if not flow_valid_connection(xfrom,yfrom,xto,yto) : flow_xypoints[3] := flow_x_on_grid(2,xfrom,xto,zfrom) ; flow_xypoints[4] := flow_xy_on_grid(3,5) ; fi ; %%%% begin experiment (todo: not value but just + and ) if flow_dsp_y <> 0 : flow_xypoints[2] := flow_xypoints[2] shifted (0,flow_dsp_y) ; flow_xypoints[3] := flow_xypoints[3] shifted (0,flow_dsp_y) ; flow_xypoints[4] := flow_xypoints[4] shifted (0,flow_dsp_y) ; flow_xypoints[5] := flow_xypoints[5] shifted (0,flow_dsp_y) ; fi ; %%%% end experiment flow_draw_connection(n,xfrom,yyfrom,xto,yyto) ; fi ; enddef ; def flow_connect_bottom_bottom (expr n) (expr xfrom,yyfrom,zfrom) (expr xto,yyto,zto) = yfrom := flow_y_pos(yyfrom) ; yto := flow_y_pos(yyto) ; if flow_points_initialized(xfrom,yfrom,xto,yto,6) : flow_xypoints[1] := flow_xy_bottom(xfrom,yfrom,zfrom,true) ; flow_xypoints[6] := flow_xy_bottom(xto,yto,zto,true) ; flow_xypoints[2] := flow_down_on_grid(1) ; flow_xypoints[5] := flow_down_on_grid(6) ; flow_xypoints[3] := flow_down_to_grid(2,5) ; flow_xypoints[4] := flow_down_to_grid(5,2) ; if not flow_valid_connection(xfrom,yfrom,xto,yto) : flow_xypoints[3] := flow_x_on_grid(2,xfrom,xto,zfrom) ; flow_xypoints[4] := flow_xy_on_grid(3,5) ; fi ; %%%% begin experiment flow_xypoints[3] := flow_xypoints[3] shifted (flow_dsp_x,0) ; flow_xypoints[4] := flow_xypoints[4] shifted (flow_dsp_x,0) ; if flow_dsp_y<0 : flow_xypoints[2] := flow_xypoints[2] shifted (0,-flow_dsp_y) ; flow_xypoints[3] := flow_xypoints[3] shifted (0,-flow_dsp_y) ; elseif flow_dsp_y>0 : flow_xypoints[4] := flow_xypoints[4] shifted (0,flow_dsp_y) ; flow_xypoints[5] := flow_xypoints[5] shifted (0,flow_dsp_y) ; fi %%%% end experiment flow_draw_connection(n,xfrom,yyfrom,xto,yyto) ; fi ; enddef ; def flow_connect_bottom_top (expr n) (expr xfrom,yfrom,zfrom) (expr xto,yto,zto) = flow_reverse_connection := true ; flow_connect_top_bottom (n) (xto,yto,zto) (xfrom,yfrom,zfrom) ; enddef ; def flow_connect_right_left (expr n) (expr xfrom,yfrom,zfrom) (expr xto,yto,zto) = flow_reverse_connection := true ; flow_connect_left_right (n) (xto,yto,zto) (xfrom,yfrom,zfrom) ; enddef ; def flow_connect_top_left (expr n) (expr xfrom,yfrom,zfrom) (expr xto,yto,zto) = flow_reverse_connection := true ; flow_connect_left_top (n) (xto,yto,zto) (xfrom,yfrom,zfrom) ; enddef ; def flow_connect_bottom_left (expr n) (expr xfrom,yfrom,zfrom) (expr xto,yto,zto) = flow_reverse_connection := true ; flow_connect_left_bottom (n) (xto,yto,zto) (xfrom,yfrom,zfrom) ; enddef ; def flow_connect_top_right (expr n) (expr xfrom,yfrom,zfrom) (expr xto,yto,zto) = flow_reverse_connection := true ; flow_connect_right_top (n) (xto,yto,zto) (xfrom,yfrom,zfrom) ; enddef ; def flow_connect_bottom_right (expr n) (expr xfrom,yfrom,zfrom) (expr xto,yto,zto) = flow_reverse_connection := true ; flow_connect_right_bottom (n) (xto,yto,zto) (xfrom,yfrom,zfrom) ; enddef ; def flow_draw_test_shape(expr x, y) = flow_draw_shape(x,y,fullcircle,flow_shape_width/flow_grid_width,flow_shape_height/flow_grid_height) ; enddef ; def flow_draw_test_shapes = flow_draw_test_area ; for i=1 upto flow_max_x : for j=1 upto flow_max_y : flow_draw_test_shape(i,j) ; flow_chart_draw_label(i,j,"",textext("\ttx(" & decimal i & "," & decimal j & ")")) endfor ; endfor ; enddef; def flow_draw_test_area = pickup pencircle scaled .5flow_shape_line_width ; for i=1 upto flow_max_x + 1 : draw ((i,1) -- (i,flow_max_y+1)) flow_scaled_to_grid withcolor white/2 ; endfor ; for i=1 upto flow_max_y + 1 : draw ((1,i) -- (flow_max_x+1,i)) flow_scaled_to_grid withcolor white/2 ; endfor ; enddef ; def flow_show_connection(expr n, m) = flow_begin_chart(100+n,6,6) ; flow_draw_test_area ; flow_smooth := true ; flow_arrowtip := true ; flow_dashline := true ; flow_draw_test_shape(2,2) ; flow_draw_test_shape(4,5) ; flow_draw_test_shape(3,3) ; flow_draw_test_shape(5,1) ; flow_draw_test_shape(2,5) ; flow_draw_test_shape(1,3) ; flow_draw_test_shape(6,2) ; flow_draw_test_shape(4,6) ; if (m=1) : flow_connect_top_bottom (0) (2,2,0) (4,5,0) ; flow_connect_top_bottom (0) (3,3,0) (5,1,0) ; flow_connect_top_bottom (0) (2,5,0) (1,3,0) ; flow_connect_top_bottom (0) (6,2,0) (4,6,0) ; elseif (m=2) : flow_connect_top_top (0) (2,2,0) (4,5,0) ; flow_connect_top_top (0) (3,3,0) (5,1,0) ; flow_connect_top_top (0) (2,5,0) (1,3,0) ; flow_connect_top_top (0) (6,2,0) (4,6,0) ; elseif (m=3) : flow_connect_bottom_bottom (0) (2,2,0) (4,5,0) ; flow_connect_bottom_bottom (0) (3,3,0) (5,1,0) ; flow_connect_bottom_bottom (0) (2,5,0) (1,3,0) ; flow_connect_bottom_bottom (0) (6,2,0) (4,6,0) ; elseif (m=4) : flow_connect_left_right (0) (2,2,0) (4,5,0) ; flow_connect_left_right (0) (3,3,0) (5,1,0) ; flow_connect_left_right (0) (2,5,0) (1,3,0) ; flow_connect_left_right (0) (6,2,0) (4,6,0) ; elseif (m=5) : flow_connect_left_left (0) (2,2,0) (4,5,0) ; flow_connect_left_left (0) (3,3,0) (5,1,0) ; flow_connect_left_left (0) (2,5,0) (1,3,0) ; flow_connect_left_left (0) (6,2,0) (4,6,0) ; elseif (m=6) : flow_connect_right_right (0) (2,2,0) (4,5,0) ; flow_connect_right_right (0) (3,3,0) (5,1,0) ; flow_connect_right_right (0) (2,5,0) (1,3,0) ; flow_connect_right_right (0) (6,2,0) (4,6,0) ; elseif (m=7) : flow_connect_left_top (0) (2,2,0) (4,5,0) ; flow_connect_left_top (0) (3,3,0) (5,1,0) ; flow_connect_left_top (0) (2,5,0) (1,3,0) ; flow_connect_left_top (0) (6,2,0) (4,6,0) ; elseif (m=8) : flow_connect_left_bottom (0) (2,2,0) (4,5,0) ; flow_connect_left_bottom (0) (3,3,0) (5,1,0) ; flow_connect_left_bottom (0) (2,5,0) (1,3,0) ; flow_connect_left_bottom (0) (6,2,0) (4,6,0) ; elseif (m=9) : flow_connect_right_top (0) (2,2,0) (4,5,0) ; flow_connect_right_top (0) (3,3,0) (5,1,0) ; flow_connect_right_top (0) (2,5,0) (1,3,0) ; flow_connect_right_top (0) (6,2,0) (4,6,0) ; else : flow_connect_right_bottom (0) (2,2,0) (4,5,0) ; flow_connect_right_bottom (0) (3,3,0) (5,1,0) ; flow_connect_right_bottom (0) (2,5,0) (1,3,0) ; flow_connect_right_bottom (0) (6,2,0) (4,6,0) ; fi ; flow_end_chart ; enddef ; def flow_show_connections = for f=1 upto 10 : flow_show_connection(f,f) ; endfor ; enddef ; %D charts def flow_clip_chart(expr minx, miny, maxx, maxy) = flow_cmin_x := minx ; flow_cmax_x := maxx ; flow_cmin_y := miny ; flow_cmax_y := maxy ; enddef ; def flow_begin_chart(expr n, maxx, maxy) = flow_new_chart ; flow_chart_figure := n ; flow_chart_scale := 1 ; if flow_chart_figure>0: beginfig(flow_chart_figure) ; fi ; flow_initialize_grid (maxx, maxy) ; bboxmargin := 0 ; flow_cmin_x := 1 ; flow_cmax_x := maxx ; flow_cmin_y := 1 ; flow_cmax_y := maxy ; enddef ; def flow_end_chart = begingroup ; save p, c ; path p, c ; flow_flush_shapes ; flow_flush_connections ; flow_flush_pictures ; flow_cmin_x := flow_cmin_x ; flow_cmax_x := flow_cmin_x+flow_cmax_x ; flow_cmin_y := flow_cmin_y-1 ; flow_cmax_y := flow_cmin_y+flow_cmax_y ; if flow_reverse_y : flow_cmin_y := flow_y_pos(flow_cmin_y) ; flow_cmax_y := flow_y_pos(flow_cmax_y) ; fi ; p := (((flow_cmin_x,flow_cmin_y)--(flow_cmax_x,flow_cmin_y)-- (flow_cmax_x,flow_cmax_y)--(flow_cmin_x,flow_cmax_y)--cycle)) flow_scaled_to_grid ; %draw p withcolor red ; c := p enlarged flow_chart_clip_offset ; p := p enlarged flow_chart_offset ; clip currentpicture to c ; setbounds currentpicture to p ; endgroup ; currentpicture := currentpicture scaled flow_chart_scale ; if flow_chart_figure>0: endfig ; fi ; enddef ; def flow_new_shape(expr x, y, n) = if known n : if (x>0) and (x<=flow_max_x) and (y>0) and (y<=flow_max_y) : flow_draw_shape(x,y,some_shape_path(n), flow_shape_width/flow_grid_width, flow_shape_height/flow_grid_height) ; else : message ("shape outside grid ignored") ; fi ; else : message ("shape not known" ) ; fi ; enddef ; def flow_begin_sub_chart = begingroup ; save flow_shape_line_width, flow_connection_line_width ; save flow_shape_line_color, flow_shape_fill_color, flow_connection_line_color ; string flow_shape_line_color, flow_shape_fill_color, flow_connection_line_color ; save flow_smooth, flow_arrowtip, flow_dashline, flow_peepshape ; boolean flow_smooth, flow_arrowtip, flow_dashline, flow_peepshape ; enddef ; def flow_end_sub_chart = endgroup ; enddef ;