test_pysketcher.py 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448
  1. from __future__ import division
  2. from __future__ import unicode_literals
  3. from __future__ import print_function
  4. from __future__ import absolute_import
  5. from future import standard_library
  6. standard_library.install_aliases()
  7. from builtins import zip
  8. from builtins import *
  9. from past.utils import old_div
  10. from pysketcher import *
  11. def equal_dict(d1, d2):
  12. """Return True if nested dicts d1 and d2 are equal."""
  13. for k in d1:
  14. #print 'comparing', k
  15. if k not in d2:
  16. return False
  17. else:
  18. if isinstance(d1[k], dict):
  19. if not equal_dict(d1[k], d2[k]):
  20. return False
  21. else:
  22. # Hack: remove u' for unicode if present
  23. d1_k = d1[k].replace("u'", "'")
  24. d2_k = d2[k].replace("u'", "'")
  25. if d1_k != d2_k:
  26. #print 'values differ: [%s] vs [%s]' % (d1_k, d2_k)
  27. return False
  28. return True
  29. def test_Axis():
  30. drawing_tool.set_coordinate_system(
  31. xmin=0, xmax=15, ymin=-7, ymax=8, axis=True,
  32. instruction_file='tmp_Axis.py')
  33. # Draw normal x and y axis with origin at (7.5, 2)
  34. # in the coordinate system of the sketch: [0,15]x[-7,8]
  35. x_axis = Axis((7.5,2), 5, 'x', rotation_angle=0)
  36. y_axis = Axis((7.5,2), 5, 'y', rotation_angle=90)
  37. system = Composition({'x axis': x_axis, 'y axis': y_axis})
  38. system.draw()
  39. drawing_tool.display()
  40. # Rotate this system 40 degrees counter clockwise
  41. # and draw it with dashed lines
  42. system.set_linestyle('dashed')
  43. system.rotate(40, (7.5,2))
  44. system.draw()
  45. drawing_tool.display()
  46. # Rotate this system another 220 degrees and show
  47. # with dotted lines
  48. system.set_linestyle('dotted')
  49. system.rotate(220, (7.5,2))
  50. system.draw()
  51. drawing_tool.display()
  52. drawing_tool.display('Axis')
  53. drawing_tool.savefig('tmp_Axis')
  54. expected = {
  55. 'x axis': {
  56. 'arrow': {
  57. 'head left': {'line': "2 (x,y) coords linestyle='dotted'",},
  58. 'line': {'line': "2 (x,y) coords linestyle='dotted'",},
  59. 'head right': {'line': "2 (x,y) coords linestyle='dotted'",},},
  60. 'label': "Text at (6.57388,-3.25231)",},
  61. 'y axis': {
  62. 'arrow': {
  63. 'head left': {'line': "2 (x,y) coords linestyle='dotted'",},
  64. 'line': {'line': "2 (x,y) coords linestyle='dotted'",},
  65. 'head right': {'line': "2 (x,y) coords linestyle='dotted'",},},
  66. 'label': "Text at (12.7523,1.07388)",},}
  67. computed = eval(repr(system))
  68. msg = 'expected=%s, computed=%s' % (expected, computed)
  69. assert equal_dict(computed, expected), msg
  70. def test_Distance_wText():
  71. drawing_tool.set_coordinate_system(
  72. xmin=0, xmax=10, ymin=0, ymax=6,
  73. axis=True, instruction_file='tmp_Distance_wText.py')
  74. fontsize=14
  75. t = r'$ 2\pi R^2 $' # sample text
  76. examples = Composition({
  77. 'a0': Distance_wText((4,5), (8, 5), t, fontsize),
  78. 'a6': Distance_wText((4,5), (4, 4), t, fontsize),
  79. 'a1': Distance_wText((0,2), (2, 4.5), t, fontsize),
  80. 'a2': Distance_wText((0,2), (2, 0), t, fontsize),
  81. 'a3': Distance_wText((2,4.5), (0, 5.5), t, fontsize),
  82. 'a4': Distance_wText((8,4), (10, 3), t, fontsize,
  83. text_spacing=old_div(-1.,60)),
  84. 'a5': Distance_wText((8,2), (10, 1), t, fontsize,
  85. text_spacing=old_div(-1.,40), alignment='right'),
  86. 'c1': Text_wArrow('text_spacing=-1./60',
  87. (4, 3.5), (9, 3.2),
  88. fontsize=10, alignment='left'),
  89. 'c2': Text_wArrow('text_spacing=-1./40, alignment="right"',
  90. (4, 0.5), (9, 1.2),
  91. fontsize=10, alignment='left'),
  92. })
  93. examples.draw()
  94. drawing_tool.display('Distance_wText and text positioning')
  95. drawing_tool.savefig('tmp_Distance_wText')
  96. expected = {
  97. 'a1': {
  98. 'text': "Text at (1.13014,3.14588)",
  99. 'arrow': {
  100. 'arrow': {
  101. 'line': "2 (x,y) coords linecolor='k' linewidth=1 arrow='<->'",},},},
  102. 'a0': {
  103. 'text': "Text at (6,5.16667)",
  104. 'arrow': {'arrow': {
  105. 'line': "2 (x,y) coords linecolor='k' linewidth=1 arrow='<->'",},},},
  106. 'a3': {
  107. 'text': "Text at (1.07454,5.14907)",
  108. 'arrow': {'arrow': {
  109. 'line': "2 (x,y) coords linecolor='k' linewidth=1 arrow='<->'",},},},
  110. 'a2': {
  111. 'text': "Text at (1.11785,1.11785)",
  112. 'arrow': {'arrow': {
  113. 'line': "2 (x,y) coords linecolor='k' linewidth=1 arrow='<->'",},},},
  114. 'a5': {
  115. 'text': "Text at (8.8882,1.27639)",
  116. 'arrow': {'arrow': {
  117. 'line': "2 (x,y) coords linecolor='k' linewidth=1 arrow='<->'",},},},
  118. 'a4': {
  119. 'text': "Text at (8.92546,3.35093)",
  120. 'arrow': {'arrow': {
  121. 'line': "2 (x,y) coords linecolor='k' linewidth=1 arrow='<->'",},},},
  122. 'a6': {
  123. 'text': "Text at (4.16667,4.5)",
  124. 'arrow': {'arrow': {
  125. 'line': "2 (x,y) coords linecolor='k' linewidth=1 arrow='<->'",},},},
  126. 'c2': "Text_wArrow at (4,0.5)",
  127. 'c1': "Text_wArrow at (4,3.5)",
  128. }
  129. computed = eval(repr(examples))
  130. msg = 'expected=%s, computed=%s' % (expected, computed)
  131. assert equal_dict(computed, expected), msg
  132. def test_Rectangle():
  133. L = 3.0
  134. W = 4.0
  135. drawing_tool.set_coordinate_system(
  136. xmin=0, xmax=2*W, ymin=old_div(-L,2), ymax=2*L,
  137. axis=True, instruction_file='tmp_Rectangle.py')
  138. drawing_tool.set_linecolor('blue')
  139. drawing_tool.set_grid(True)
  140. xpos = old_div(W,2)
  141. r = Rectangle(lower_left_corner=(xpos,0), width=W, height=L)
  142. r.draw()
  143. r.draw_dimensions()
  144. drawing_tool.display('Rectangle')
  145. drawing_tool.savefig('tmp_Rectangle')
  146. expected = {'rectangle': "5 (x,y) coords",}
  147. computed = eval(repr(r))
  148. msg = 'expected=%s, computed=%s' % (expected, computed)
  149. assert equal_dict(computed, expected), msg
  150. def test_Triangle():
  151. L = 3.0
  152. W = 4.0
  153. drawing_tool.set_coordinate_system(
  154. xmin=0, xmax=2*W, ymin=old_div(-L,2), ymax=1.2*L,
  155. axis=True, instruction_file='tmp_Triangle.py')
  156. drawing_tool.set_linecolor('blue')
  157. drawing_tool.set_grid(True)
  158. xpos = 1
  159. t = Triangle(p1=(old_div(W,2),0), p2=(3*W/2,old_div(W,2)), p3=(4*W/5.,L))
  160. t.draw()
  161. t.draw_dimensions()
  162. drawing_tool.display('Triangle')
  163. drawing_tool.savefig('tmp_Triangle')
  164. expected = {'triangle': "4 (x,y) coords",}
  165. computed = eval(repr(t))
  166. msg = 'expected=%s, computed=%s' % (expected, computed)
  167. assert equal_dict(computed, expected), msg
  168. def test_Arc():
  169. L = 4.0
  170. W = 4.0
  171. drawing_tool.set_coordinate_system(
  172. xmin=old_div(-W,2), xmax=W, ymin=old_div(-L,2), ymax=1.5*L,
  173. axis=True, instruction_file='tmp_Arc.py')
  174. drawing_tool.set_linecolor('blue')
  175. drawing_tool.set_grid(True)
  176. center = point(0,0)
  177. radius = old_div(L,2)
  178. start_angle = 60
  179. arc_angle = 45
  180. a = Arc(center, radius, start_angle, arc_angle)
  181. a.draw()
  182. R1 = 1.25*radius
  183. R2 = 1.5*radius
  184. R = 2*radius
  185. a.dimensions = {
  186. 'start_angle':
  187. Arc_wText(
  188. 'start_angle', center, R1, start_angle=0,
  189. arc_angle=start_angle, text_spacing=old_div(1,10.)),
  190. 'arc_angle':
  191. Arc_wText(
  192. 'arc_angle', center, R2, start_angle=start_angle,
  193. arc_angle=arc_angle, text_spacing=old_div(1,20.)),
  194. 'r=0':
  195. Line(center, center +
  196. point(R*cos(radians(start_angle)),
  197. R*sin(radians(start_angle)))),
  198. 'r=start_angle':
  199. Line(center, center +
  200. point(R*cos(radians(start_angle+arc_angle)),
  201. R*sin(radians(start_angle+arc_angle)))),
  202. 'r=start+arc_angle':
  203. Line(center, center +
  204. point(R, 0)).set_linestyle('dashed'),
  205. 'radius': Distance_wText(center, a(0), 'radius', text_spacing=old_div(1,40.)),
  206. 'center': Text('center', center-point(old_div(radius,10.), old_div(radius,10.))),
  207. }
  208. for dimension in a.dimensions:
  209. if dimension.startswith('r='):
  210. dim = a.dimensions[dimension]
  211. dim.set_linestyle('dashed')
  212. dim.set_linewidth(1)
  213. dim.set_linecolor('black')
  214. a.draw_dimensions()
  215. drawing_tool.display('Arc')
  216. drawing_tool.savefig('tmp_Arc')
  217. expected = {'arc': "181 (x,y) coords"}
  218. computed = eval(repr(a))
  219. msg = 'expected=%s, computed=%s' % (expected, computed)
  220. assert equal_dict(computed, expected), msg
  221. expected = {
  222. 'center': 'text "center" at (-0.2,-0.2)',
  223. 'start_angle': {'text': "Text at (2.68468,1.55)",
  224. 'arc': {'arc': "181 (x,y) coords",},},
  225. 'r=start+arc_angle': {
  226. 'line': "2 (x,y) coords linecolor='k' linewidth=1 linestyle='dashed'",},
  227. 'r=0': {'line': "2 (x,y) coords linecolor='k' linewidth=1 linestyle='dashed'",},
  228. 'radius': {'text': "Text at (0.629904,0.791025)",
  229. 'arrow': {'arrow': {
  230. 'line': "2 (x,y) coords linecolor='k' linewidth=1 arrow='<->'",},},},
  231. 'r=start_angle': {'line': "2 (x,y) coords linecolor='k' linewidth=1 linestyle='dashed'",},
  232. 'arc_angle': {'text': "Text at (0.430736,3.27177)",
  233. 'arc': {'arc': "181 (x,y) coords",},}
  234. }
  235. computed = eval(repr(a.dimensions))
  236. msg = 'expected=%s, computed=%s' % (expected, computed)
  237. assert equal_dict(computed, expected), msg
  238. def test_Spring():
  239. L = 5.0
  240. W = 2.0
  241. drawing_tool.set_coordinate_system(
  242. xmin=0, xmax=7*W, ymin=old_div(-L,2), ymax=1.5*L,
  243. axis=True, instruction_file='tmp_Spring.py')
  244. drawing_tool.set_linecolor('blue')
  245. drawing_tool.set_grid(True)
  246. xpos = W
  247. s1 = Spring((W,0), L, teeth=True)
  248. s1_title = Text('Default Spring',
  249. s1.geometric_features()['end'] + point(0,old_div(L,10)))
  250. s1.draw()
  251. s1_title.draw()
  252. #s1.draw_dimensions()
  253. xpos += 3*W
  254. s2 = Spring(start=(xpos,0), length=L, width=old_div(W,2.),
  255. bar_length=old_div(L,6.), teeth=False)
  256. s2.draw()
  257. s2.draw_dimensions()
  258. drawing_tool.display('Spring')
  259. drawing_tool.savefig('tmp_Spring')
  260. # Check s1 and s1.dimensions
  261. expected = {
  262. 'bar1': {'line': "2 (x,y) coords",},
  263. 'bar2': {'line': "2 (x,y) coords",},
  264. 'spiral': "45 (x,y) coords",}
  265. computed = eval(repr(s1))
  266. msg = 'expected=%s, computed=%s' % (expected, computed)
  267. assert equal_dict(computed, expected), msg
  268. expected = {
  269. 'bar_length1': {'text': "Text_wArrow at (-1.5,1.75)",
  270. 'arrow': {'arrow': {
  271. 'line': "2 (x,y) coords linecolor='k' linewidth=1 arrow='<->'",},},},
  272. 'bar_length2': {'text': "Text_wArrow at (-1.5,5.5)",
  273. 'arrow': {'arrow': {
  274. 'line': "2 (x,y) coords linecolor='k' linewidth=1 arrow='<->'",},},},
  275. 'width': {'text': "Text at (2,-1.51667)",
  276. 'arrow': {'arrow': {
  277. 'line': "2 (x,y) coords linecolor='k' linewidth=1 arrow='<->'",},},},
  278. 'start': 'annotation "start" at (1.25,-0.75) with arrow to (2,0)',
  279. 'length': {'text': "Text at (3.73333,2.5)",
  280. 'arrow': {'arrow': {
  281. 'line': "2 (x,y) coords linecolor='k' linewidth=1 arrow='<->'",},},},
  282. 'num_windings': 'annotation "num_windings" at (3,5.5) with arrow to (2.6,2.5)'
  283. }
  284. computed = eval(repr(s1.dimensions))
  285. msg = 'expected=%s, computed=%s' % (expected, computed)
  286. assert equal_dict(computed, expected), msg
  287. def test_Dashpot():
  288. L = 5.0
  289. W = 2.0
  290. xpos = 0
  291. drawing_tool.set_coordinate_system(
  292. xmin=xpos, xmax=xpos+5.5*W, ymin=old_div(-L,2), ymax=1.5*L,
  293. axis=True, instruction_file='tmp_Dashpot.py')
  294. drawing_tool.set_linecolor('blue')
  295. drawing_tool.set_grid(True)
  296. # Default (simple) dashpot
  297. xpos = 1.5
  298. d1 = Dashpot(start=(xpos,0), total_length=L)
  299. d1_title = Text('Dashpot (default)',
  300. d1.geometric_features()['end'] + point(0,old_div(L,10)))
  301. d1.draw()
  302. d1_title.draw()
  303. # Dashpot for animation with fixed bar_length, dashpot_length and
  304. # prescribed piston_pos
  305. xpos += 2.5*W
  306. d2 = Dashpot(start=(xpos,0), total_length=1.2*L, width=old_div(W,2),
  307. bar_length=W, dashpot_length=old_div(L,2), piston_pos=2*W)
  308. d2.draw()
  309. d2.draw_dimensions()
  310. drawing_tool.display('Dashpot')
  311. drawing_tool.savefig('tmp_Dashpot')
  312. expected = {
  313. 'line start': {'line': "2 (x,y) coords",},
  314. 'piston': {
  315. 'line': {'line': "2 (x,y) coords",},
  316. 'rectangle': {
  317. 'rectangle': "5 (x,y) coords fillcolor='' fillpattern='X'",},},
  318. 'pot': "4 (x,y) coords",
  319. }
  320. computed = eval(repr(d2))
  321. msg = 'expected=%s, computed=%s' % (expected, computed)
  322. assert equal_dict(computed, expected), msg
  323. expected = {
  324. 'width': {'text': "Text at (6.5,-1.56667)",
  325. 'arrow': {'arrow': {
  326. 'line': "2 (x,y) coords linecolor='k' linewidth=1 arrow='<->'",},},},
  327. 'start': 'annotation "start" at (5.75,-0.75) with arrow to (6.5,0)',
  328. 'bar_length': {'text': "Text_wArrow at (3.5,1.5)",
  329. 'arrow': {'arrow': {
  330. 'line': "2 (x,y) coords linecolor='k' linewidth=1 arrow='<->'",},},},
  331. 'total_length': {'text': "Text_wArrow at (8.75,5)",
  332. 'arrow': {'arrow': {
  333. 'line': "2 (x,y) coords linecolor='k' linewidth=1 arrow='<->'",},},},
  334. 'dashpot_length': {'text': "Text_wArrow at (7,-0.5)",
  335. 'arrow': {'arrow': {
  336. 'line': "2 (x,y) coords linecolor='k' linewidth=1 arrow='<->'",},},},
  337. 'piston_pos': {'text': "Text_wArrow at (3.5,3.6875)",
  338. 'arrow': {'arrow': {
  339. 'line': "2 (x,y) coords linecolor='k' linewidth=1 arrow='<->'",},},}
  340. }
  341. computed = eval(repr(d2.dimensions))
  342. msg = 'expected=%s, computed=%s' % (expected, computed)
  343. assert equal_dict(computed, expected), msg
  344. def test_Wavy():
  345. drawing_tool.set_coordinate_system(xmin=0, xmax=1.5,
  346. ymin=-0.5, ymax=5,
  347. axis=True,
  348. instruction_file='tmp_Wavy.py')
  349. w = Wavy(main_curve=lambda x: 1 + sin(2*x),
  350. interval=[0,1.5],
  351. wavelength_of_perturbations=0.3,
  352. amplitude_of_perturbations=0.1,
  353. smoothness=0.05)
  354. w.draw()
  355. drawing_tool.display('Wavy')
  356. drawing_tool.savefig('tmp_Wavy')
  357. expected = {'wavy': "2001 (x,y) coords",}
  358. computed = eval(repr(w))
  359. msg = 'expected=%s, computed=%s' % (expected, computed)
  360. assert equal_dict(computed, expected), msg
  361. def diff_files(files1, files2, mode='HTML'):
  362. import difflib, time
  363. n = 3
  364. for fromfile, tofile in zip(files1, files2):
  365. fromdate = time.ctime(os.stat(fromfile).st_mtime)
  366. todate = time.ctime(os.stat(tofile).st_mtime)
  367. fromlines = open(fromfile, 'U').readlines()
  368. tolines = open(tofile, 'U').readlines()
  369. diff_html = difflib.HtmlDiff().\
  370. make_file(fromlines,tolines,
  371. fromfile,tofile,context=True,numlines=n)
  372. diff_plain = difflib.unified_diff(fromlines, tolines, fromfile, tofile, fromdate, todate, n=n)
  373. filename_plain = fromfile + '.diff.txt'
  374. filename_html = fromfile + '.diff.html'
  375. if os.path.isfile(filename_plain):
  376. os.remove(filename_plain)
  377. if os.path.isfile(filename_html):
  378. os.remove(filename_html)
  379. f = open(filename_plain, 'w')
  380. f.writelines(diff_plain)
  381. f.close()
  382. size = os.path.getsize(filename_plain)
  383. if size > 4:
  384. print('found differences:', fromfile, tofile)
  385. f = open(filename_html, 'w')
  386. f.writelines(diff_html)
  387. f.close()
  388. def _test_test():
  389. """Compare files."""
  390. # Does not work yet.
  391. os.chdir('test')
  392. funcs = [name for name in globals() if name.startswith('test_') and callable(globals()[name])]
  393. funcs.remove('test_test')
  394. new_files = []
  395. res_files = []
  396. for func in funcs:
  397. mplfile = func.replace('test_', 'tmp_') + '.py'
  398. #exec(func + '()')
  399. new_files.append(mplfile)
  400. resfile = mplfile.replace('tmp_', 'res_')
  401. res_files.append(resfile)
  402. diff_files(new_files, res_files)
  403. test_Arc()