jwpb7

brij-diagram.py

Aug 21st, 2014
361
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/usr/bin/python
  2. # edited 22 Aug 2014 to correct COG scale & print COG
  3. # brij-diagram.py -- Generates a PS picture of bridge assemblies.
  4. # Ref: <http://puzzling.stackexchange.com/questions/2138/make-a-wide-tower-of-bridge-shapes>
  5.  
  6. # Each program parameter is 2 letters a...e plus an optional depth.
  7. # Eg: "cd" (or "cd0") says to connect side c of new piece to side d of
  8. # 0-previous piece, ie the just-previous piece.  "ae2" says to connect
  9. # side a of new piece to side e of 2-previous piece.
  10.  
  11. # Examples of use to generate and view three sample diagrams:
  12. #   ./brij-diagram.py da dc ca ca ea3 > t.ps; gs t.ps
  13. #   ./brij-diagram.py ca ae cd ca da ae2 > t.ps; gs t.ps
  14. #   ./brij-diagram.py ee ca ca ca ca > t.ps; gs t.ps
  15. # Also, can make .jpg files via commands like:
  16. # gs -sDEVICE=jpeg -sPAPERSIZE=letter -sOutputFile=t.jpg - < t.ps
  17.  
  18. from math import sin, cos, pi, sqrt, atan2
  19. import sys
  20. #---------------------------------------------------------
  21. def docInitString(bbx, bby):
  22.     import datetime
  23.     now = str(datetime.datetime.now())[:-7]
  24.     return '''%!PS-Adobe-1.0
  25. %%Creator: brij-diagram.py
  26. %%Title: Show "bridge shapes" stackups
  27. %%CreationDate: {}
  28. %%Pages: (atend)
  29. %%DocumentFonts: NewCenturySchlbk-Bold
  30. %%BoundingBox: 0 0 {} {}
  31. %%EndComments'''.format(now, bbx, bby)
  32. #---------------------------------------------------------
  33. def fontSizeString(fsize):
  34.     return '''% Select a font
  35. /NewCenturySchlbk-Bold findfont {} scalefont setfont'''.format(fsize)
  36. #---------------------------------------------------------
  37. def rotate(angle,point):
  38.     x, y = point
  39.     s, c = sin(angle), cos(angle)
  40.     return (x*c-y*s, x*s+y*c)
  41. #---------------------------------------------------------
  42. def pdelta(p1, p2):
  43.     return (p2[0]-p1[0], p2[1]-p1[1])
  44. #---------------------------------------------------------
  45. # Compute rotation angle and translation amount so that new side nside
  46. # coincides with old side oside. The caller can say ra, ro =
  47. # rotrans(oside, nside) and then for each point p in new polygon can
  48. # say pt = pdelta(ro, rotate(ra, p)) to get rotated/translated point pt.
  49. def rotrans(oside, nside):
  50.     (b, c),   (h, g)   = oside, nside     # Unpack side-pairs to points
  51.     (dx, dy), (ex, ey) = pdelta(b, c), pdelta(g, h) # Get deltas of pairs
  52.     ra = atan2(dy, dx)-atan2(ey, ex)      # Get angles of sides
  53.     gr, hr = rotate(ra, g), rotate(ra, h) # Rotate ends of new side
  54.     ro = pdelta(c,hr)                     # ro+hr = c, ro+gr = b
  55.     return ra, ro
  56. #---------------------------Main program-----------------
  57. fscale, bbx, bby = 18, 612, 612
  58. lmarg, rmarg, tmarg, ff = 60, 60, 60, 200
  59. lx, rx, by, ty = lmarg, bbx-rmarg, 30, bby-tmarg
  60. bwide, bhigh = 10, 18
  61. xscale, yscale = (rx-lx)/bwide, (ty-by)/bhigh
  62. scale = min(xscale, yscale)
  63. rx, ty = lx + bwide*scale, by + bhigh*scale
  64. print docInitString(bbx, bby)
  65. print fontSizeString(fscale)
  66. brij = [(0,0), (.5,sqrt(3)/2), (1.5,sqrt(3)/2), (2,0), (1,0)]
  67. brin, cog = ['A', 'B', 'C', 'D', 'E'], (1, sqrt(3)*2/9.)
  68. cogTotal = (0,0,0)
  69. legs = zip(brij,brij[1:]+brij[:1])
  70. hist = [(i,0) for i in range(6)]
  71.  
  72. for i, item in enumerate(sys.argv[1:]):
  73.     print '\n% Processing  {}'.format(item),
  74.     item += '0  '
  75.     nsidel = (ord(item[0])-1) & 7
  76.     osidel = (ord(item[1])-1) & 7
  77.     deep = ord(item[2]) & 15
  78.     if nsidel>4 or osidel>4 or deep>9:
  79.         break
  80.     print ' :  new,old,deep = {} {} {}'.format(brin[nsidel], brin[osidel], deep)
  81.     hinx = -deep*6-6+osidel
  82.     oside = (hist[hinx], hist[hinx+1])
  83.     nside = legs[nsidel]
  84.     ra, ro = rotrans(oside, nside)
  85.     print '{} {} {} setrgbcolor'.format((0==i%3)*1, (1==i%3)*1, (2==i%3)*1)
  86.     (ox, oy) = pdelta(ro, rotate(ra, brij[0]))
  87.     hist.append((ox, oy))
  88.     print '{:3.1f} {:3.1f} moveto'.format(ff+lx+scale*ox, by+scale*oy),
  89.     for p in brij[1:]:
  90.         (px, py) = pdelta(ro, rotate(ra, p))
  91.         hist.append((px, py))
  92.         print ' {:3.1f} {:3.1f} lineto'.format(ff+lx+scale*px, by+scale*py),
  93.     hist.append((ox, oy))
  94.     print ' fill'
  95.     (px, py) = pdelta(ro, rotate(ra, cog))
  96.     print '0 0 0 setrgbcolor {:3.1f} {:3.1f} moveto (.{}) show'.format(ff+lx+scale*px, by+scale*py, i)
  97.     cogTotal = (cogTotal[0]+px, cogTotal[1]+py, cogTotal[2]+1)
  98.     print '0.3 0.2 0.1 setrgbcolor {:3.1f} {:3.1f} moveto (*) show'.format(ff+lx+scale*cogTotal[0]/cogTotal[2]-fscale/8, by+scale*cogTotal[1]/cogTotal[2]-fscale/2)
  99.     print '% new COG = ( {:6.3f}, {:6.3f} ), ox ox = {:8.3f} {:8.3f}'.format(cogTotal[0]/cogTotal[2], cogTotal[1]/cogTotal[2], oside[0][0], oside[1][0])
  100.  
  101. print fontSizeString(3*fscale)
  102. print '0.3 0.2 0.1 setrgbcolor {:3.1f} {:3.1f} moveto (*) show'.format(ff+lx+scale*cogTotal[0]/cogTotal[2]-fscale/3, by+scale*cogTotal[1]/cogTotal[2]-1.5*fscale)
  103. print 'showpage'
RAW Paste Data