stevens@hsi.UUCP (Richard Stevens) (01/25/89)
About 8 months ago I posted a query to this group about a pic problem that I was having with its drawing of arrow heads. The problem is quite widespread - look at any of the UNIX books that have used pic/ditroff to draw arrows: the latest Kernighan and Ritchie (p. 144), Bach's "The Design of the UNIX Op. Sys." (this is the worst, see pp. 347-348 especially), the AWK book (p. 131, p. 173), and on and on ... Anyway, I didn't get any positive responses, so I finally spent a day and tracked the problem down. It is an interesting problem, with many potential "fixes". First consider a typical arrow head: E:| | | A:\ | /:C \ | / \ | / \ | / \ | / B:\F| /:D Now the goal is to have the three lines AB, CD and EF all end at the same point (that is, the three points B, D and F should be the same). Unfortunately they sometimes aren't. (1) The pic output is fine, however, pic deals in floating point coordinates. This is the start of the problem, since ditroff converts the floating point inch values into machine units. I think another part of the problem is the way pic draws an arrow with a head. First it draws the line EF, from E going a specified distance to F. Then it draws the line AB, starting at A and going a specified distance in both x and y. Then it draws CD, again starting at C and going a specified distance in x and y. If pic were to start all three line segments at a single point (B=D=F) and draw from there, the problem might be solved, but I'm not positive. (2) ditroff converts the floating point inch values into machine units, using its own atol() function and using the number of machine units per inch (ditroff's "Inch" variable), which depends on the typesetter. I'm using Adobe's TranScript package which uses a value of 576 units/inch for the PostScript device. Since machine units are integer values for ditroff, this conversion can cause problems since any fractional part is truncated. There is no rounding. (3) Even though three floating point numbers satisfy x+y=z, you don't have int(x)+int(y)=int(z), and this indeed is the problem. pic deals in floating point inches and ditroff deals in integral machine units and the conversion between the two isn't perfect. The problem is that the ends of the three lines above can all be off by 1 unit in both the x and y directions. Visually I find it hard to distinguish some of the "error" output, on our LaserWriter, but you can sure pick it out in typeset books. My guess is that the error of 1 machine unit (1/567-inch) doesn't always correspond to a different dot at 300 dots/inch, but corresponds to multiple dots at the higher typesetter resolutions. Perhaps the authors of these books did all their proofing on a 300 dpi laser printer and only noticed the problem when running the final typeset copy, when it was too late to fix ? My solution is two-fold: (1) First, I now set my own pic defaults and any other pic sizes, so that the chosen floating point value in inches corresponds to an exact number of machine units. For example, I set arrowwid = 0.0625i arrowht = 0.125i This is because 0.0625/2 * 576 equals 18 units exactly. There is no truncation performed by ditroff when it converts it. (The divide by 2 is because the arrowwid value is the total distance between the starts of the two arrow heads, and pic needs the distance from the start of the arrow head to the line.) This means I'll have to change these values if I use another post- processor that uses a value other than 576, but I figure the Adobe PostScript values will be all I need for a while. The default values used by pic (0.05 and 0.1) are unsuitable since they'll cause the truncation errors when ditroff converts them. (2) Second, I modified our pic source code so that it outputs 5 digits to the right of the decimal point, instead of its default of 3. This is so that it maintains the complete floating point values that I give it. Without this change, using the values I show above, the 0.0625/2=0.03125 gets output by pic as 0.031 and this is then truncated by ditroff, which I don't want to happen. Richard Stevens Health Systems International, New Haven, CT stevens@hsi.com ... { uunet | yale } ! hsi ! stevens /* FLAME ON. */ Please no comments from all the troff vendors saying "hey fool, if you'd have only bought our complete troff package we fixed this years ago ...". /* FLAME OFF. */