#! /usr/bin/gawk -f # Last edited on 2003-11-20 22:53:35 by stolfi BEGIN { usage = ( ARGV[0] " COORDSFILE CANDSFILE > PICTEXFILE" ); # Generates a LaTeX "picture" plot of the dual fragment graph, # suitable for overlaying on top of an image of the reassembled # object. # # The COORDSFILE must contain two lines of the form "width = NNN" # and "height = NNN", specifying the dimensions of the underlying # image; followed by one of more lines of the form "NFRAG H V", # giving the number NFRAG of each fragment, and the H and V coordinates # (pixel indices) of its approximate center in that image. # # The CANDSFILE is a candidate list in the ".can" format. abort = -1; # printf "%d %s %s\n", ARGC, ARGV[0], ARGV[1], ARGV[2], ARGV[3] > "/dev/stderr"; if ( ARGC != 3 ) { arg_error(("usage: " usage)); } load_coords(ARGV[1]); load_edges(ARGV[2]); print_graph(); exit 0; } function load_coords(fname, lin,maxFrag,frag) { # sets "nFrags", "width, "height" # and "xFrag[i]", "yFrag[i]" for "i=0..nFrags-1" nFrags = 0; maxFrag = -1; split("",xFrag); split("",yFrag); width = read_named_param(fname, "width"); height = read_named_param(fname, "height"); while((getline lin < fname) > 0) { if (! match(lin, /^[#]/)) { nfld = split(lin, fld, " "); if (nfld != 3) { file_error(fname, ("bad coord file entry = \"" lin "\"")); } frag = sprintf("%03d", fld[1] + 0); if (frag in xFrag) { file_error(fname, ("repeated fragment = \"" lin "\"")); } if (frag < 0) { file_error(fname, ("bad fragment = \"" lin "\"")); } xFrag[frag] = fld[2]; yFrag[frag] = fld[3]; printf "%s %s %s\n", frag, xFrag[frag], yFrag[frag] > "/dev/stderr"; if (frag > maxFrag) { maxFrag = frag; } nFrags++; } } if (ERRNO != "0") { arg_error(("file \"" fname "\": " ERRNO)); } close (fname); if (nFrags == 0) { arg_error(("file \"" fname "\" empty or missing")); } if ((maxFrag+0) != (nFrags - 1)) { arg_error(("file \"" fname "\" inconsistent numbering: " (nFrags-1) " " (maxFrag+0))); } printf "loaded %6d fragment coordinates\n", nFrags > "/dev/stderr"; } function read_named_param(fname, pname, lin,p,r) { p = length(pname); getline lin < fname; if (substr(lin,1,p) != pname) { file_error(fname, ("missing \"" pname " = \" line")); } lin = substr(lin,p+1); if (! match(lin, /^ *= */)) { file_error(fname, ("missing \"=\" on \"" pname " = \" line")); } r = substr(lin, RLENGTH+1) + 0; printf "%s = %d\n", pname, r > "/dev/stderr"; return r; } function load_edges(fname, lin,u,v) { # sets "nEdges" and "org[i]", "dst[i], mult[i]" for "i=0..nEdges-1" nEdges = 0; split("", org); split("", dst); split("", mult); while((getline lin < fname) > 0) { if (match(lin, /^ *[0-9]/)) { nfld = split(lin, fld, " "); if (nfld < 13) file_error(fname, ("bad candidate file entry = \"" lin "\"")); u = sprintf("%03d", fld[1] + 0); v = sprintf("%03d", fld[6] + 0); if (! (u in xFrag)) file_error(fname, ("invalid org fragment = \"" lin "\"")); if (! (v in xFrag)) file_error(fname, ("invalid dst fragment = \"" lin "\"")); if ((nEdges > 0) && (u == org[nEdges-1]) && (v == dst[nEdges-1])) { mult[nEdges]++; } else { org[nEdges] = u; dst[nEdges] = v; mult[nEdges] = 0; nEdges++; } } } if (ERRNO != "0") { arg_error(("file \"" fname "\": " ERRNO)); } close (fname); if (nEdges == 0) { arg_error(("file \"" fname "\" empty or missing")); } printf "loaded %6d candidates\n", nEdges > "/dev/stderr" } function print_graph( i,rad) { # Prints the graph in TeX's "pic" format from # the arrays "xFrag[0..nFrags-1]". "yFrag[0..nFrags-1]", # "org[0..nEdges-1]", "dst[0..nEdges-1], mult[0..nEdges-1]". # Compute a suitable circle radius: rad = int(height*2/239 + 0.5); # Draw the vertices of the graph: for(i in xFrag) { printf " \\put(%d,%d){\\circle*{%d}}", xFrag[i], height - yFrag[i], rad; printf " \\put(%d,%d){\\makebox(0,0)[l]{%s}}\n", xFrag[i] + 2*rad, height - yFrag[i], i; } # Draw the edges of the graph: for (i in org) { printf " \\drawline(%d,%d)(%d,%d)\n", xFrag[org[i]], height - yFrag[org[i]], xFrag[dst[i]], height - yFrag[dst[i]]; } } function file_error(fname, msg) { printf "\"%s\", line %d: %s\n", fname, FNR, msg >> "/dev/stderr"; abort = 1; exit 1 } function arg_error(msg) { printf "%s\n", msg >> "/dev/stderr"; abort = 1; exit 1 }