._pysketcher002.html 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887
  1. <!--
  2. Automatically generated HTML file from DocOnce source
  3. (https://github.com/hplgit/doconce/)
  4. -->
  5. <html>
  6. <head>
  7. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  8. <meta name="generator" content="DocOnce: https://github.com/hplgit/doconce/" />
  9. <meta name="description" content="Using Pysketcher to Create Principal Sketches of Physics Problems">
  10. <meta name="keywords" content="tree data structure,recursive function calls">
  11. <title>Using Pysketcher to Create Principal Sketches of Physics Problems</title>
  12. <!-- Bootstrap style: bootswatch_readable -->
  13. <link href="http://netdna.bootstrapcdn.com/bootswatch/3.1.1/readable/bootstrap.min.css" rel="stylesheet">
  14. <!-- not necessary
  15. <link href="http://netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet">
  16. -->
  17. <style type="text/css">
  18. /* Add scrollbar to dropdown menus in bootstrap navigation bar */
  19. .dropdown-menu {
  20. height: auto;
  21. max-height: 400px;
  22. overflow-x: hidden;
  23. }
  24. </style>
  25. </head>
  26. <!-- tocinfo
  27. {'highest level': 1,
  28. 'sections': [('A first glimpse of Pysketcher', 1, None, '___sec0'),
  29. ('Basic construction of sketches', 2, None, '___sec1'),
  30. ('Basic drawing', 3, None, '___sec2'),
  31. ('Groups of objects', 3, None, '___sec3'),
  32. ('Changing line styles and colors', 3, None, '___sec4'),
  33. ('The figure composition as an object hierarchy',
  34. 3,
  35. None,
  36. '___sec5'),
  37. ('Animation: translating the vehicle', 3, None, '___sec6'),
  38. ('Animation: rolling the wheels',
  39. 3,
  40. 'sketcher:vehicle1:anim',
  41. 'sketcher:vehicle1:anim'),
  42. ('A simple pendulum',
  43. 1,
  44. 'sketcher:ex:pendulum',
  45. 'sketcher:ex:pendulum'),
  46. ('The basic physics sketch',
  47. 2,
  48. 'sketcher:ex:pendulum:basic',
  49. 'sketcher:ex:pendulum:basic'),
  50. ('The body diagram', 2, None, '___sec10'),
  51. ('Animated body diagram',
  52. 2,
  53. 'sketcher:ex:pendulum:anim',
  54. 'sketcher:ex:pendulum:anim'),
  55. ('Function for drawing the body diagram', 3, None, '___sec12'),
  56. ('Equations for the motion and forces', 3, None, '___sec13'),
  57. ('Numerical solution', 3, None, '___sec14'),
  58. ('Animation', 3, None, '___sec15'),
  59. ('Basic shapes', 1, None, '___sec16'),
  60. ('Axis', 2, None, '___sec17'),
  61. ('Distance with text', 2, None, '___sec18'),
  62. ('Rectangle', 2, None, '___sec19'),
  63. ('Triangle', 2, None, '___sec20'),
  64. ('Arc', 2, None, '___sec21'),
  65. ('Spring', 2, None, '___sec22'),
  66. ('Dashpot', 2, None, '___sec23'),
  67. ('Wavy', 2, None, '___sec24'),
  68. ('Stochastic curves', 2, None, '___sec25'),
  69. ('Inner workings of the Pysketcher tool', 1, None, '___sec26'),
  70. ('Example of classes for geometric objects',
  71. 2,
  72. None,
  73. '___sec27'),
  74. ('Simple geometric objects', 3, None, '___sec28'),
  75. ('Class curve', 3, None, '___sec29'),
  76. ('Compound geometric objects', 3, None, '___sec30'),
  77. ('Adding functionality via recursion', 2, None, '___sec31'),
  78. ('Basic principles of recursion', 3, None, '___sec32'),
  79. ('Explaining recursion', 3, None, '___sec33'),
  80. ('Scaling, translating, and rotating a figure',
  81. 2,
  82. 'sketcher:scaling',
  83. 'sketcher:scaling'),
  84. ('Scaling', 3, None, '___sec35'),
  85. ('Translation', 3, None, '___sec36'),
  86. ('Rotation', 3, None, '___sec37')]}
  87. end of tocinfo -->
  88. <body>
  89. <script type="text/x-mathjax-config">
  90. MathJax.Hub.Config({
  91. TeX: {
  92. equationNumbers: { autoNumber: "none" },
  93. extensions: ["AMSmath.js", "AMSsymbols.js", "autobold.js", "color.js"]
  94. }
  95. });
  96. </script>
  97. <script type="text/javascript"
  98. src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML">
  99. </script>
  100. <!-- newcommands.tex -->
  101. $$
  102. \newcommand{\half}{\frac{1}{2}}
  103. \newcommand{\tp}{\thinspace .}
  104. \newcommand{\rpos}{\boldsymbol{r}}
  105. \newcommand{\ii}{\boldsymbol{i}}
  106. \newcommand{\jj}{\boldsymbol{j}}
  107. \newcommand{\ir}{\boldsymbol{i}_r}
  108. \newcommand{\ith}{\boldsymbol{i}_{\theta}}
  109. $$
  110. <!-- Bootstrap navigation bar -->
  111. <div class="navbar navbar-default navbar-fixed-top">
  112. <div class="navbar-header">
  113. <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-responsive-collapse">
  114. <span class="icon-bar"></span>
  115. <span class="icon-bar"></span>
  116. <span class="icon-bar"></span>
  117. </button>
  118. <a class="navbar-brand" href="pysketcher.html">Using Pysketcher to Create Principal Sketches of Physics Problems</a>
  119. </div>
  120. <div class="navbar-collapse collapse navbar-responsive-collapse">
  121. <ul class="nav navbar-nav navbar-right">
  122. <li class="dropdown">
  123. <a href="#" class="dropdown-toggle" data-toggle="dropdown">Contents <b class="caret"></b></a>
  124. <ul class="dropdown-menu">
  125. <!-- navigation toc: --> <li><a href="#___sec0" style="font-size: 80%;"><b>A first glimpse of Pysketcher</b></a></li>
  126. <!-- navigation toc: --> <li><a href="#___sec1" style="font-size: 80%;">&nbsp;&nbsp;&nbsp;Basic construction of sketches</a></li>
  127. <!-- navigation toc: --> <li><a href="#___sec2" style="font-size: 80%;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Basic drawing</a></li>
  128. <!-- navigation toc: --> <li><a href="#___sec3" style="font-size: 80%;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Groups of objects</a></li>
  129. <!-- navigation toc: --> <li><a href="#___sec4" style="font-size: 80%;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Changing line styles and colors</a></li>
  130. <!-- navigation toc: --> <li><a href="#___sec5" style="font-size: 80%;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;The figure composition as an object hierarchy</a></li>
  131. <!-- navigation toc: --> <li><a href="#___sec6" style="font-size: 80%;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Animation: translating the vehicle</a></li>
  132. <!-- navigation toc: --> <li><a href="#sketcher:vehicle1:anim" style="font-size: 80%;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Animation: rolling the wheels</a></li>
  133. <!-- navigation toc: --> <li><a href="._pysketcher003.html#sketcher:ex:pendulum" style="font-size: 80%;"><b>A simple pendulum</b></a></li>
  134. <!-- navigation toc: --> <li><a href="._pysketcher003.html#sketcher:ex:pendulum:basic" style="font-size: 80%;">&nbsp;&nbsp;&nbsp;The basic physics sketch</a></li>
  135. <!-- navigation toc: --> <li><a href="._pysketcher003.html#___sec10" style="font-size: 80%;">&nbsp;&nbsp;&nbsp;The body diagram</a></li>
  136. <!-- navigation toc: --> <li><a href="._pysketcher003.html#sketcher:ex:pendulum:anim" style="font-size: 80%;">&nbsp;&nbsp;&nbsp;Animated body diagram</a></li>
  137. <!-- navigation toc: --> <li><a href="._pysketcher003.html#___sec12" style="font-size: 80%;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Function for drawing the body diagram</a></li>
  138. <!-- navigation toc: --> <li><a href="._pysketcher003.html#___sec13" style="font-size: 80%;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Equations for the motion and forces</a></li>
  139. <!-- navigation toc: --> <li><a href="._pysketcher003.html#___sec14" style="font-size: 80%;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Numerical solution</a></li>
  140. <!-- navigation toc: --> <li><a href="._pysketcher003.html#___sec15" style="font-size: 80%;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Animation</a></li>
  141. <!-- navigation toc: --> <li><a href="._pysketcher004.html#___sec16" style="font-size: 80%;"><b>Basic shapes</b></a></li>
  142. <!-- navigation toc: --> <li><a href="._pysketcher004.html#___sec17" style="font-size: 80%;">&nbsp;&nbsp;&nbsp;Axis</a></li>
  143. <!-- navigation toc: --> <li><a href="._pysketcher004.html#___sec18" style="font-size: 80%;">&nbsp;&nbsp;&nbsp;Distance with text</a></li>
  144. <!-- navigation toc: --> <li><a href="._pysketcher004.html#___sec19" style="font-size: 80%;">&nbsp;&nbsp;&nbsp;Rectangle</a></li>
  145. <!-- navigation toc: --> <li><a href="._pysketcher004.html#___sec20" style="font-size: 80%;">&nbsp;&nbsp;&nbsp;Triangle</a></li>
  146. <!-- navigation toc: --> <li><a href="._pysketcher004.html#___sec21" style="font-size: 80%;">&nbsp;&nbsp;&nbsp;Arc</a></li>
  147. <!-- navigation toc: --> <li><a href="._pysketcher004.html#___sec22" style="font-size: 80%;">&nbsp;&nbsp;&nbsp;Spring</a></li>
  148. <!-- navigation toc: --> <li><a href="._pysketcher004.html#___sec23" style="font-size: 80%;">&nbsp;&nbsp;&nbsp;Dashpot</a></li>
  149. <!-- navigation toc: --> <li><a href="._pysketcher004.html#___sec24" style="font-size: 80%;">&nbsp;&nbsp;&nbsp;Wavy</a></li>
  150. <!-- navigation toc: --> <li><a href="._pysketcher004.html#___sec25" style="font-size: 80%;">&nbsp;&nbsp;&nbsp;Stochastic curves</a></li>
  151. <!-- navigation toc: --> <li><a href="._pysketcher005.html#___sec26" style="font-size: 80%;"><b>Inner workings of the Pysketcher tool</b></a></li>
  152. <!-- navigation toc: --> <li><a href="._pysketcher005.html#___sec27" style="font-size: 80%;">&nbsp;&nbsp;&nbsp;Example of classes for geometric objects</a></li>
  153. <!-- navigation toc: --> <li><a href="._pysketcher005.html#___sec28" style="font-size: 80%;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Simple geometric objects</a></li>
  154. <!-- navigation toc: --> <li><a href="._pysketcher005.html#___sec29" style="font-size: 80%;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Class curve</a></li>
  155. <!-- navigation toc: --> <li><a href="._pysketcher005.html#___sec30" style="font-size: 80%;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Compound geometric objects</a></li>
  156. <!-- navigation toc: --> <li><a href="._pysketcher005.html#___sec31" style="font-size: 80%;">&nbsp;&nbsp;&nbsp;Adding functionality via recursion</a></li>
  157. <!-- navigation toc: --> <li><a href="._pysketcher005.html#___sec32" style="font-size: 80%;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Basic principles of recursion</a></li>
  158. <!-- navigation toc: --> <li><a href="._pysketcher005.html#___sec33" style="font-size: 80%;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Explaining recursion</a></li>
  159. <!-- navigation toc: --> <li><a href="._pysketcher005.html#sketcher:scaling" style="font-size: 80%;">&nbsp;&nbsp;&nbsp;Scaling, translating, and rotating a figure</a></li>
  160. <!-- navigation toc: --> <li><a href="._pysketcher005.html#___sec35" style="font-size: 80%;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Scaling</a></li>
  161. <!-- navigation toc: --> <li><a href="._pysketcher005.html#___sec36" style="font-size: 80%;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Translation</a></li>
  162. <!-- navigation toc: --> <li><a href="._pysketcher005.html#___sec37" style="font-size: 80%;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Rotation</a></li>
  163. </ul>
  164. </li>
  165. </ul>
  166. </div>
  167. </div>
  168. </div> <!-- end of navigation bar -->
  169. <div class="container">
  170. <p>&nbsp;</p><p>&nbsp;</p><p>&nbsp;</p> <!-- add vertical space -->
  171. <a name="part0002"></a>
  172. <!-- !split -->
  173. <h1 id="___sec0">A first glimpse of Pysketcher </h1>
  174. <p>
  175. Formulation of physical problems makes heavy use of <em>principal sketches</em>
  176. such as the one in Figure <a href="#sketcher:fig:inclinedplane">1</a>.
  177. This particular sketch illustrates the classical mechanics problem
  178. of a rolling wheel on an inclined plane.
  179. The figure
  180. is made up many individual elements: a rectangle
  181. filled with a pattern (the inclined plane), a hollow circle with color
  182. (the wheel), arrows with labels (the \( N \) and \( Mg \) forces, and the \( x \)
  183. axis), an angle with symbol \( \theta \), and a dashed line indicating the
  184. starting location of the wheel.
  185. <p>
  186. Drawing software and plotting programs can produce such figures quite
  187. easily in principle, but the amount of details the user needs to
  188. control with the mouse can be substantial. Software more tailored to
  189. producing sketches of this type would work with more convenient
  190. abstractions, such as circle, wall, angle, force arrow, axis, and so
  191. forth. And as soon we start <em>programming</em> to construct the figure we
  192. get a range of other powerful tools at disposal. For example, we can
  193. easily translate and rotate parts of the figure and make an animation
  194. that illustrates the physics of the problem.
  195. Programming as a superior alternative to interactive drawing is
  196. the mantra of this section.
  197. <p>
  198. <center> <!-- figure -->
  199. <hr class="figure">
  200. <center><p class="caption">Figure 1: Sketch of a physics problem. <div id="sketcher:fig:inclinedplane"></div> </p></center>
  201. <p><img src="fig-tut/wheel_on_inclined_plane.png" align="bottom" width=400></p>
  202. </center>
  203. <h2 id="___sec1">Basic construction of sketches </h2>
  204. <p>
  205. Before attacking real-life sketches as in Figure <a href="#sketcher:fig:inclinedplane">1</a>
  206. we focus on the significantly simpler drawing shown
  207. in Figure <a href="#sketcher:fig:vehicle0">2</a>. This toy sketch consists of
  208. several elements: two circles, two rectangles, and a &quot;ground&quot; element.
  209. <p>
  210. <center> <!-- figure -->
  211. <hr class="figure">
  212. <center><p class="caption">Figure 2: Sketch of a simple figure. <div id="sketcher:fig:vehicle0"></div> </p></center>
  213. <p><img src="fig-tut/vehicle0_dim.png" align="bottom" width=600></p>
  214. </center>
  215. <p>
  216. When the sketch is defined in terms of computer code, it is natural to
  217. parameterize geometric features, such as the radius of the wheel (\( R \)),
  218. the center point of the left wheel (\( w_1 \)), as well as the height (\( H \)) and
  219. length (\( L \)) of the main part. The simple vehicle in
  220. Figure <a href="#sketcher:fig:vehicle0">2</a> is quickly drawn in almost any interactive
  221. tool. However, if we want to change the radius of the wheels, you need a
  222. sophisticated drawing tool to avoid redrawing the whole figure, while
  223. in computer code this is a matter of changing the \( R \) parameter and
  224. rerunning the program.
  225. For example, Figure <a href="#sketcher:fig:vehicle0b">3</a> shows
  226. a variation of the drawing in
  227. Figure <a href="#sketcher:fig:vehicle0">2</a> obtained by just setting
  228. \( R=0.5 \), \( L=5 \), \( H=2 \), and \( R=2 \). Being able
  229. to quickly change geometric sizes is key to many problem settings in
  230. physics and engineering, but then a program must define the geometry.
  231. <p>
  232. <center> <!-- figure -->
  233. <hr class="figure">
  234. <center><p class="caption">Figure 3: Redrawing a figure with other geometric parameters. <div id="sketcher:fig:vehicle0b"></div> </p></center>
  235. <p><img src="fig-tut/vehicle_v2.png" align="bottom" width=500></p>
  236. </center>
  237. <h3 id="___sec2">Basic drawing </h3>
  238. <p>
  239. A typical program creating these five elements is shown next.
  240. After importing the <code>pysketcher</code> package, the first task is always to
  241. define a coordinate system:
  242. <p>
  243. <!-- code=python (!bc pycod) typeset with pygments style "default" -->
  244. <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span style="color: #008000; font-weight: bold">from</span> <span style="color: #0000FF; font-weight: bold">pysketcher</span> <span style="color: #008000; font-weight: bold">import</span> <span style="color: #666666">*</span>
  245. drawing_tool<span style="color: #666666">.</span>set_coordinate_system(
  246. xmin<span style="color: #666666">=0</span>, xmax<span style="color: #666666">=10</span>, ymin<span style="color: #666666">=-1</span>, ymax<span style="color: #666666">=8</span>)
  247. </pre></div>
  248. <p>
  249. Instead of working with lengths expressed by specific numbers it is
  250. highly recommended to use variables to parameterize lengths as
  251. this makes it easier to change dimensions later.
  252. Here we introduce some key lengths for the radius of the wheels,
  253. distance between the wheels, etc.:
  254. <p>
  255. <!-- code=python (!bc pycod) typeset with pygments style "default" -->
  256. <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%">R <span style="color: #666666">=</span> <span style="color: #666666">1</span> <span style="color: #408080; font-style: italic"># radius of wheel</span>
  257. L <span style="color: #666666">=</span> <span style="color: #666666">4</span> <span style="color: #408080; font-style: italic"># distance between wheels</span>
  258. H <span style="color: #666666">=</span> <span style="color: #666666">2</span> <span style="color: #408080; font-style: italic"># height of vehicle body</span>
  259. w_1 <span style="color: #666666">=</span> <span style="color: #666666">5</span> <span style="color: #408080; font-style: italic"># position of front wheel</span>
  260. drawing_tool<span style="color: #666666">.</span>set_coordinate_system(xmin<span style="color: #666666">=0</span>, xmax<span style="color: #666666">=</span>w_1 <span style="color: #666666">+</span> <span style="color: #666666">2*</span>L <span style="color: #666666">+</span> <span style="color: #666666">3*</span>R,
  261. ymin<span style="color: #666666">=-1</span>, ymax<span style="color: #666666">=2*</span>R <span style="color: #666666">+</span> <span style="color: #666666">3*</span>H)
  262. </pre></div>
  263. <p>
  264. With the drawing area in place we can make the first <code>Circle</code> object
  265. in an intuitive fashion:
  266. <p>
  267. <!-- code=python (!bc pycod) typeset with pygments style "default" -->
  268. <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%">wheel1 <span style="color: #666666">=</span> Circle(center<span style="color: #666666">=</span>(w_1, R), radius<span style="color: #666666">=</span>R)
  269. </pre></div>
  270. <p>
  271. to change dimensions later.
  272. <p>
  273. To translate the geometric information about the <code>wheel1</code> object to
  274. instructions for the plotting engine (in this case Matplotlib), one calls the
  275. <code>wheel1.draw()</code>. To display all drawn objects, one issues
  276. <code>drawing_tool.display()</code>. The typical steps are hence:
  277. <p>
  278. <!-- code=python (!bc pycod) typeset with pygments style "default" -->
  279. <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%">wheel1 <span style="color: #666666">=</span> Circle(center<span style="color: #666666">=</span>(w_1, R), radius<span style="color: #666666">=</span>R)
  280. wheel1<span style="color: #666666">.</span>draw()
  281. <span style="color: #408080; font-style: italic"># Define other objects and call their draw() methods</span>
  282. drawing_tool<span style="color: #666666">.</span>display()
  283. drawing_tool<span style="color: #666666">.</span>savefig(<span style="color: #BA2121">&#39;tmp.png&#39;</span>) <span style="color: #408080; font-style: italic"># store picture</span>
  284. </pre></div>
  285. <p>
  286. The next wheel can be made by taking a copy of <code>wheel1</code> and
  287. translating the object to the right according to a
  288. displacement vector \( (L,0) \):
  289. <p>
  290. <!-- code=python (!bc pycod) typeset with pygments style "default" -->
  291. <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%">wheel2 <span style="color: #666666">=</span> wheel1<span style="color: #666666">.</span>copy()
  292. wheel2<span style="color: #666666">.</span>translate((L,<span style="color: #666666">0</span>))
  293. </pre></div>
  294. <p>
  295. The two rectangles are also made in an intuitive way:
  296. <p>
  297. <!-- code=python (!bc pycod) typeset with pygments style "default" -->
  298. <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%">under <span style="color: #666666">=</span> Rectangle(lower_left_corner<span style="color: #666666">=</span>(w_1<span style="color: #666666">-2*</span>R, <span style="color: #666666">2*</span>R),
  299. width<span style="color: #666666">=2*</span>R <span style="color: #666666">+</span> L <span style="color: #666666">+</span> <span style="color: #666666">2*</span>R, height<span style="color: #666666">=</span>H)
  300. over <span style="color: #666666">=</span> Rectangle(lower_left_corner<span style="color: #666666">=</span>(w_1, <span style="color: #666666">2*</span>R <span style="color: #666666">+</span> H),
  301. width<span style="color: #666666">=2.5*</span>R, height<span style="color: #666666">=1.25*</span>H)
  302. </pre></div>
  303. <h3 id="___sec3">Groups of objects </h3>
  304. <p>
  305. Instead of calling the <code>draw</code> method of every object, we can
  306. group objects and call <code>draw</code>, or perform other operations, for
  307. the whole group. For example, we may collect the two wheels
  308. in a <code>wheels</code> group and the <code>over</code> and <code>under</code> rectangles
  309. in a <code>body</code> group. The whole vehicle is a composition
  310. of its <code>wheels</code> and <code>body</code> groups. The code goes like
  311. <p>
  312. <!-- code=python (!bc pycod) typeset with pygments style "default" -->
  313. <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%">wheels <span style="color: #666666">=</span> Composition({<span style="color: #BA2121">&#39;wheel1&#39;</span>: wheel1, <span style="color: #BA2121">&#39;wheel2&#39;</span>: wheel2})
  314. body <span style="color: #666666">=</span> Composition({<span style="color: #BA2121">&#39;under&#39;</span>: under, <span style="color: #BA2121">&#39;over&#39;</span>: over})
  315. vehicle <span style="color: #666666">=</span> Composition({<span style="color: #BA2121">&#39;wheels&#39;</span>: wheels, <span style="color: #BA2121">&#39;body&#39;</span>: body})
  316. </pre></div>
  317. <p>
  318. The ground is illustrated by an object of type <code>Wall</code>,
  319. mostly used to indicate walls in sketches of mechanical systems.
  320. A <code>Wall</code> takes the <code>x</code> and <code>y</code> coordinates of some curve,
  321. and a <code>thickness</code> parameter, and creates a thick curve filled
  322. with a simple pattern. In this case the curve is just a flat
  323. line so the construction is made of two points on the
  324. ground line (\( (w_1-L,0) \) and \( (w_1+3L,0) \)):
  325. <p>
  326. <!-- code=python (!bc pycod) typeset with pygments style "default" -->
  327. <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%">ground <span style="color: #666666">=</span> Wall(x<span style="color: #666666">=</span>[w_1 <span style="color: #666666">-</span> L, w_1 <span style="color: #666666">+</span> <span style="color: #666666">3*</span>L], y<span style="color: #666666">=</span>[<span style="color: #666666">0</span>, <span style="color: #666666">0</span>], thickness<span style="color: #666666">=-0.3*</span>R)
  328. </pre></div>
  329. <p>
  330. The negative thickness makes the pattern-filled rectangle appear below
  331. the defined line, otherwise it appears above.
  332. <p>
  333. We may now collect all the objects in a &quot;top&quot; object that contains
  334. the whole figure:
  335. <p>
  336. <!-- code=python (!bc pycod) typeset with pygments style "default" -->
  337. <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%">fig <span style="color: #666666">=</span> Composition({<span style="color: #BA2121">&#39;vehicle&#39;</span>: vehicle, <span style="color: #BA2121">&#39;ground&#39;</span>: ground})
  338. fig<span style="color: #666666">.</span>draw() <span style="color: #408080; font-style: italic"># send all figures to plotting backend</span>
  339. drawing_tool<span style="color: #666666">.</span>display()
  340. drawing_tool<span style="color: #666666">.</span>savefig(<span style="color: #BA2121">&#39;tmp.png&#39;</span>)
  341. </pre></div>
  342. <p>
  343. The <code>fig.draw()</code> call will visit
  344. all subgroups, their subgroups,
  345. and so forth in the hierarchical tree structure of
  346. figure elements,
  347. and call <code>draw</code> for every object.
  348. <h3 id="___sec4">Changing line styles and colors </h3>
  349. <p>
  350. Controlling the line style, line color, and line width is
  351. fundamental when designing figures. The <code>pysketcher</code>
  352. package allows the user to control such properties in
  353. single objects, but also set global properties that are
  354. used if the object has no particular specification of
  355. the properties. Setting the global properties are done like
  356. <p>
  357. <!-- code=python (!bc pycod) typeset with pygments style "default" -->
  358. <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%">drawing_tool<span style="color: #666666">.</span>set_linestyle(<span style="color: #BA2121">&#39;dashed&#39;</span>)
  359. drawing_tool<span style="color: #666666">.</span>set_linecolor(<span style="color: #BA2121">&#39;black&#39;</span>)
  360. drawing_tool<span style="color: #666666">.</span>set_linewidth(<span style="color: #666666">4</span>)
  361. </pre></div>
  362. <p>
  363. At the object level the properties are specified in a similar
  364. way:
  365. <p>
  366. <!-- code=python (!bc pycod) typeset with pygments style "default" -->
  367. <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%">wheels<span style="color: #666666">.</span>set_linestyle(<span style="color: #BA2121">&#39;solid&#39;</span>)
  368. wheels<span style="color: #666666">.</span>set_linecolor(<span style="color: #BA2121">&#39;red&#39;</span>)
  369. </pre></div>
  370. <p>
  371. and so on.
  372. <p>
  373. Geometric figures can be specified as <em>filled</em>, either with a color or with a
  374. special visual pattern:
  375. <p>
  376. <!-- code=python (!bc pycod) typeset with pygments style "default" -->
  377. <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span style="color: #408080; font-style: italic"># Set filling of all curves</span>
  378. drawing_tool<span style="color: #666666">.</span>set_filled_curves(color<span style="color: #666666">=</span><span style="color: #BA2121">&#39;blue&#39;</span>, pattern<span style="color: #666666">=</span><span style="color: #BA2121">&#39;/&#39;</span>)
  379. <span style="color: #408080; font-style: italic"># Turn off filling of all curves</span>
  380. drawing_tool<span style="color: #666666">.</span>set_filled_curves(<span style="color: #008000">False</span>)
  381. <span style="color: #408080; font-style: italic"># Fill the wheel with red color</span>
  382. wheel1<span style="color: #666666">.</span>set_filled_curves(<span style="color: #BA2121">&#39;red&#39;</span>)
  383. </pre></div>
  384. <p>
  385. <!-- <a href="http://packages.python.org/ete2/" target="_self"><tt>http://packages.python.org/ete2/</tt></a> for visualizing tree structures! -->
  386. <h3 id="___sec5">The figure composition as an object hierarchy </h3>
  387. <p>
  388. The composition of objects making up the figure
  389. is hierarchical, similar to a family, where
  390. each object has a parent and a number of children. Do a
  391. <code>print fig</code> to display the relations:
  392. <p>
  393. <!-- code=text (!bc dat) typeset with pygments style "default" -->
  394. <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%">ground
  395. wall
  396. vehicle
  397. body
  398. over
  399. rectangle
  400. under
  401. rectangle
  402. wheels
  403. wheel1
  404. arc
  405. wheel2
  406. arc
  407. </pre></div>
  408. <p>
  409. The indentation reflects how deep down in the hierarchy (family)
  410. we are.
  411. This output is to be interpreted as follows:
  412. <ul>
  413. <li> <code>fig</code> contains two objects, <code>ground</code> and <code>vehicle</code></li>
  414. <li> <code>ground</code> contains an object <code>wall</code></li>
  415. <li> <code>vehicle</code> contains two objects, <code>body</code> and <code>wheels</code></li>
  416. <li> <code>body</code> contains two objects, <code>over</code> and <code>under</code></li>
  417. <li> <code>wheels</code> contains two objects, <code>wheel1</code> and <code>wheel2</code></li>
  418. </ul>
  419. In this listing there are also objects not defined by the
  420. programmer: <code>rectangle</code> and <code>arc</code>. These are of type <code>Curve</code>
  421. and automatically generated by the classes <code>Rectangle</code> and <code>Circle</code>.
  422. <p>
  423. More detailed information can be printed by
  424. <p>
  425. <!-- code=python (!bc pycod) typeset with pygments style "default" -->
  426. <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span style="color: #008000; font-weight: bold">print</span> fig<span style="color: #666666">.</span>show_hierarchy(<span style="color: #BA2121">&#39;std&#39;</span>)
  427. </pre></div>
  428. <p>
  429. yielding the output
  430. <p>
  431. <!-- code=text (!bc dat) typeset with pygments style "default" -->
  432. <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%">ground (Wall):
  433. wall (Curve): 4 coords fillcolor=&#39;white&#39; fillpattern=&#39;/&#39;
  434. vehicle (Composition):
  435. body (Composition):
  436. over (Rectangle):
  437. rectangle (Curve): 5 coords
  438. under (Rectangle):
  439. rectangle (Curve): 5 coords
  440. wheels (Composition):
  441. wheel1 (Circle):
  442. arc (Curve): 181 coords
  443. wheel2 (Circle):
  444. arc (Curve): 181 coords
  445. </pre></div>
  446. <p>
  447. Here we can see the class type for each figure object, how many
  448. coordinates that are involved in basic figures (<code>Curve</code> objects), and
  449. special settings of the basic figure (fillcolor, line types, etc.).
  450. For example, <code>wheel2</code> is a <code>Circle</code> object consisting of an <code>arc</code>,
  451. which is a <code>Curve</code> object consisting of 181 coordinates (the
  452. points needed to draw a smooth circle). The <code>Curve</code> objects are the
  453. only objects that really holds specific coordinates to be drawn.
  454. The other object types are just compositions used to group
  455. parts of the complete figure.
  456. <p>
  457. One can also get a graphical overview of the hierarchy of figure objects
  458. that build up a particular figure <code>fig</code>.
  459. Just call <code>fig.graphviz_dot('fig')</code> to produce a file <code>fig.dot</code> in
  460. the <em>dot format</em>. This file contains relations between parent and
  461. child objects in the figure and can be turned into an image,
  462. as in Figure <a href="#sketcher:fig:vehicle0:hier1">4</a>, by
  463. running the <code>dot</code> program:
  464. <p>
  465. <!-- code=text (!bc sys) typeset with pygments style "default" -->
  466. <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%">Terminal&gt; dot -Tpng -o fig.png fig.dot
  467. </pre></div>
  468. <p>
  469. <center> <!-- figure -->
  470. <hr class="figure">
  471. <center><p class="caption">Figure 4: Hierarchical relation between figure objects. <div id="sketcher:fig:vehicle0:hier1"></div> </p></center>
  472. <p><img src="fig-tut/vehicle0_hier1.png" align="bottom" width=500></p>
  473. </center>
  474. <p>
  475. The call <code>fig.graphviz_dot('fig', classname=True)</code> makes a <code>fig.dot</code> file
  476. where the class type of each object is also visible, see
  477. Figure <a href="#sketcher:fig:vehicle0:hier2">5</a>. The ability to write out the
  478. object hierarchy or view it graphically can be of great help when
  479. working with complex figures that involve layers of subfigures.
  480. <p>
  481. <center> <!-- figure -->
  482. <hr class="figure">
  483. <center><p class="caption">Figure 5: Hierarchical relation between figure objects, including their class names. <div id="sketcher:fig:vehicle0:hier2"></div> </p></center>
  484. <p><img src="fig-tut/Vehicle0_hier2.png" align="bottom" width=500></p>
  485. </center>
  486. <p>
  487. Any of the objects can in the program be reached through their names, e.g.,
  488. <p>
  489. <!-- code=python (!bc pycod) typeset with pygments style "default" -->
  490. <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%">fig[<span style="color: #BA2121">&#39;vehicle&#39;</span>]
  491. fig[<span style="color: #BA2121">&#39;vehicle&#39;</span>][<span style="color: #BA2121">&#39;wheels&#39;</span>]
  492. fig[<span style="color: #BA2121">&#39;vehicle&#39;</span>][<span style="color: #BA2121">&#39;wheels&#39;</span>][<span style="color: #BA2121">&#39;wheel2&#39;</span>]
  493. fig[<span style="color: #BA2121">&#39;vehicle&#39;</span>][<span style="color: #BA2121">&#39;wheels&#39;</span>][<span style="color: #BA2121">&#39;wheel2&#39;</span>][<span style="color: #BA2121">&#39;arc&#39;</span>]
  494. fig[<span style="color: #BA2121">&#39;vehicle&#39;</span>][<span style="color: #BA2121">&#39;wheels&#39;</span>][<span style="color: #BA2121">&#39;wheel2&#39;</span>][<span style="color: #BA2121">&#39;arc&#39;</span>]<span style="color: #666666">.</span>x <span style="color: #408080; font-style: italic"># x coords</span>
  495. fig[<span style="color: #BA2121">&#39;vehicle&#39;</span>][<span style="color: #BA2121">&#39;wheels&#39;</span>][<span style="color: #BA2121">&#39;wheel2&#39;</span>][<span style="color: #BA2121">&#39;arc&#39;</span>]<span style="color: #666666">.</span>y <span style="color: #408080; font-style: italic"># y coords</span>
  496. fig[<span style="color: #BA2121">&#39;vehicle&#39;</span>][<span style="color: #BA2121">&#39;wheels&#39;</span>][<span style="color: #BA2121">&#39;wheel2&#39;</span>][<span style="color: #BA2121">&#39;arc&#39;</span>]<span style="color: #666666">.</span>linestyle
  497. fig[<span style="color: #BA2121">&#39;vehicle&#39;</span>][<span style="color: #BA2121">&#39;wheels&#39;</span>][<span style="color: #BA2121">&#39;wheel2&#39;</span>][<span style="color: #BA2121">&#39;arc&#39;</span>]<span style="color: #666666">.</span>linetype
  498. </pre></div>
  499. <p>
  500. Grabbing a part of the figure this way is handy for
  501. changing properties of that part, for example, colors, line styles
  502. (see Figure <a href="#sketcher:fig:vehicle0:v2">6</a>):
  503. <p>
  504. <!-- code=python (!bc pycod) typeset with pygments style "default" -->
  505. <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%">fig[<span style="color: #BA2121">&#39;vehicle&#39;</span>][<span style="color: #BA2121">&#39;wheels&#39;</span>]<span style="color: #666666">.</span>set_filled_curves(<span style="color: #BA2121">&#39;blue&#39;</span>)
  506. fig[<span style="color: #BA2121">&#39;vehicle&#39;</span>][<span style="color: #BA2121">&#39;wheels&#39;</span>]<span style="color: #666666">.</span>set_linewidth(<span style="color: #666666">6</span>)
  507. fig[<span style="color: #BA2121">&#39;vehicle&#39;</span>][<span style="color: #BA2121">&#39;wheels&#39;</span>]<span style="color: #666666">.</span>set_linecolor(<span style="color: #BA2121">&#39;black&#39;</span>)
  508. fig[<span style="color: #BA2121">&#39;vehicle&#39;</span>][<span style="color: #BA2121">&#39;body&#39;</span>][<span style="color: #BA2121">&#39;under&#39;</span>]<span style="color: #666666">.</span>set_filled_curves(<span style="color: #BA2121">&#39;red&#39;</span>)
  509. fig[<span style="color: #BA2121">&#39;vehicle&#39;</span>][<span style="color: #BA2121">&#39;body&#39;</span>][<span style="color: #BA2121">&#39;over&#39;</span>]<span style="color: #666666">.</span>set_filled_curves(pattern<span style="color: #666666">=</span><span style="color: #BA2121">&#39;/&#39;</span>)
  510. fig[<span style="color: #BA2121">&#39;vehicle&#39;</span>][<span style="color: #BA2121">&#39;body&#39;</span>][<span style="color: #BA2121">&#39;over&#39;</span>]<span style="color: #666666">.</span>set_linewidth(<span style="color: #666666">14</span>)
  511. fig[<span style="color: #BA2121">&#39;vehicle&#39;</span>][<span style="color: #BA2121">&#39;body&#39;</span>][<span style="color: #BA2121">&#39;over&#39;</span>][<span style="color: #BA2121">&#39;rectangle&#39;</span>]<span style="color: #666666">.</span>linewidth <span style="color: #666666">=</span> <span style="color: #666666">4</span>
  512. </pre></div>
  513. <p>
  514. The last line accesses the <code>Curve</code> object directly, while the line above,
  515. accesses the <code>Rectangle</code> object, which will then set the linewidth of
  516. its <code>Curve</code> object, and other objects if it had any.
  517. The result of the actions above is shown in Figure <a href="#sketcher:fig:vehicle0:v2">6</a>.
  518. <p>
  519. <center> <!-- figure -->
  520. <hr class="figure">
  521. <center><p class="caption">Figure 6: Left: Basic line-based drawing. Right: Thicker lines and filled parts. <div id="sketcher:fig:vehicle0:v2"></div> </p></center>
  522. <p><img src="fig-tut/vehicle0.png" align="bottom" width=700></p>
  523. </center>
  524. <p>
  525. We can also change position of parts of the figure and thereby make
  526. animations, as shown next.
  527. <h3 id="___sec6">Animation: translating the vehicle </h3>
  528. <p>
  529. Can we make our little vehicle roll? A first attempt will be to
  530. fake rolling by just displacing all parts of the vehicle.
  531. The relevant parts constitute the <code>fig['vehicle']</code> object.
  532. This part of the figure can be translated, rotated, and scaled.
  533. A translation along the ground means a translation in \( x \) direction,
  534. say a length \( L \) to the right:
  535. <p>
  536. <!-- code=python (!bc pycod) typeset with pygments style "default" -->
  537. <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%">fig[<span style="color: #BA2121">&#39;vehicle&#39;</span>]<span style="color: #666666">.</span>translate((L,<span style="color: #666666">0</span>))
  538. </pre></div>
  539. <p>
  540. You need to erase, draw, and display to see the movement:
  541. <p>
  542. <!-- code=python (!bc pycod) typeset with pygments style "default" -->
  543. <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%">drawing_tool<span style="color: #666666">.</span>erase()
  544. fig<span style="color: #666666">.</span>draw()
  545. drawing_tool<span style="color: #666666">.</span>display()
  546. </pre></div>
  547. <p>
  548. Without erasing, the old drawing of the vehicle will remain in
  549. the figure so you get two vehicles. Without <code>fig.draw()</code> the
  550. new coordinates of the vehicle will not be communicated to
  551. the drawing tool, and without calling display the updated
  552. drawing will not be visible.
  553. <p>
  554. A figure that moves in time is conveniently realized by the
  555. function <code>animate</code>:
  556. <p>
  557. <!-- code=python (!bc pycod) typeset with pygments style "default" -->
  558. <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%">animate(fig, tp, action)
  559. </pre></div>
  560. <p>
  561. Here, <code>fig</code> is the entire figure, <code>tp</code> is an array of
  562. time points, and <code>action</code> is a user-specified function that changes
  563. <code>fig</code> at a specific time point. Typically, <code>action</code> will move
  564. parts of <code>fig</code>.
  565. <p>
  566. In the present case we can define the movement through a velocity
  567. function <code>v(t)</code> and displace the figure <code>v(t)*dt</code> for small time
  568. intervals <code>dt</code>. A possible velocity function is
  569. <p>
  570. <!-- code=python (!bc pycod) typeset with pygments style "default" -->
  571. <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">v</span>(t):
  572. <span style="color: #008000; font-weight: bold">return</span> <span style="color: #666666">-8*</span>R<span style="color: #666666">*</span>t<span style="color: #666666">*</span>(<span style="color: #666666">1</span> <span style="color: #666666">-</span> t<span style="color: #666666">/</span>(<span style="color: #666666">2*</span>R))
  573. </pre></div>
  574. <p>
  575. Our action function for horizontal displacements <code>v(t)*dt</code> becomes
  576. <p>
  577. <!-- code=python (!bc pycod) typeset with pygments style "default" -->
  578. <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">move</span>(t, fig):
  579. x_displacement <span style="color: #666666">=</span> dt<span style="color: #666666">*</span>v(t)
  580. fig[<span style="color: #BA2121">&#39;vehicle&#39;</span>]<span style="color: #666666">.</span>translate((x_displacement, <span style="color: #666666">0</span>))
  581. </pre></div>
  582. <p>
  583. Since our velocity is negative for \( t\in [0,2R] \) the displacement is
  584. to the left.
  585. <p>
  586. The <code>animate</code> function will for each time point <code>t</code> in <code>tp</code> erase
  587. the drawing, call <code>action(t, fig)</code>, and show the new figure by
  588. <code>fig.draw()</code> and <code>drawing_tool.display()</code>.
  589. Here we choose a resolution of the animation corresponding to
  590. 25 time points in the time interval \( [0,2R] \):
  591. <p>
  592. <!-- code=python (!bc pycod) typeset with pygments style "default" -->
  593. <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span style="color: #008000; font-weight: bold">import</span> <span style="color: #0000FF; font-weight: bold">numpy</span>
  594. tp <span style="color: #666666">=</span> numpy<span style="color: #666666">.</span>linspace(<span style="color: #666666">0</span>, <span style="color: #666666">2*</span>R, <span style="color: #666666">25</span>)
  595. dt <span style="color: #666666">=</span> tp[<span style="color: #666666">1</span>] <span style="color: #666666">-</span> tp[<span style="color: #666666">0</span>] <span style="color: #408080; font-style: italic"># time step</span>
  596. animate(fig, tp, move, pause_per_frame<span style="color: #666666">=0.2</span>)
  597. </pre></div>
  598. <p>
  599. The <code>pause_per_frame</code> adds a pause, here 0.2 seconds, between
  600. each frame in the animation.
  601. <p>
  602. We can also ask <code>animate</code> to store each frame in a file:
  603. <p>
  604. <!-- code=python (!bc pycod) typeset with pygments style "default" -->
  605. <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%">files <span style="color: #666666">=</span> animate(fig, tp, move_vehicle, moviefiles<span style="color: #666666">=</span><span style="color: #008000">True</span>,
  606. pause_per_frame<span style="color: #666666">=0.2</span>)
  607. </pre></div>
  608. <p>
  609. The <code>files</code> variable, here <code>'tmp_frame_%04d.png'</code>,
  610. is the printf-specification used to generate the individual
  611. plot files. We can use this specification to make a video
  612. file via <code>ffmpeg</code> (or <code>avconv</code> on Debian-based Linux systems such
  613. as Ubuntu). Videos in the Flash and WebM formats can be created
  614. by
  615. <p>
  616. <!-- code=text (!bc sys) typeset with pygments style "default" -->
  617. <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%">Terminal&gt; ffmpeg -r 12 -i tmp_frame_%04d.png -vcodec flv mov.flv
  618. Terminal&gt; ffmpeg -r 12 -i tmp_frame_%04d.png -vcodec libvpx mov.webm
  619. </pre></div>
  620. <p>
  621. An animated GIF movie can also be made using the <code>convert</code> program
  622. from the ImageMagick software suite:
  623. <p>
  624. <!-- code=text (!bc sys) typeset with pygments style "default" -->
  625. <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%">Terminal&gt; convert -delay 20 tmp_frame*.png mov.gif
  626. Terminal&gt; animate mov.gif # play movie
  627. </pre></div>
  628. <p>
  629. The delay between frames, in units of 1/100 s,
  630. governs the speed of the movie.
  631. To play the animated GIF file in a web page, simply insert
  632. <code>&lt;img src=&quot;mov.gif&quot;&gt;</code> in the HTML code.
  633. <p>
  634. The individual PNG frames can be directly played in a web
  635. browser by running
  636. <p>
  637. <!-- code=text (!bc sys) typeset with pygments style "default" -->
  638. <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%">Terminal&gt; scitools movie output_file=mov.html fps=5 tmp_frame*
  639. </pre></div>
  640. <p>
  641. or calling
  642. <p>
  643. <!-- code=python (!bc pycod) typeset with pygments style "default" -->
  644. <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%"><span style="color: #008000; font-weight: bold">from</span> <span style="color: #0000FF; font-weight: bold">scitools.std</span> <span style="color: #008000; font-weight: bold">import</span> movie
  645. movie(files, encoder<span style="color: #666666">=</span><span style="color: #BA2121">&#39;html&#39;</span>, output_file<span style="color: #666666">=</span><span style="color: #BA2121">&#39;mov.html&#39;</span>)
  646. </pre></div>
  647. <p>
  648. in Python. Load the resulting file <code>mov.html</code> into a web browser
  649. to play the movie.
  650. <p>
  651. Try to run <a href="http://tinyurl.com/ot733jn/vehicle0.py" target="_self"><tt>vehicle0.py</tt></a> and
  652. then load <code>mov.html</code> into a browser, or play one of the <code>mov.*</code>
  653. video files. Alternatively, you can view a ready-made <a href="http://tinyurl.com/oou9lp7/mov-tut/vehicle0.html" target="_self">movie</a>.
  654. <h3 id="sketcher:vehicle1:anim">Animation: rolling the wheels</h3>
  655. <p>
  656. It is time to show rolling wheels. To this end, we add spokes to the
  657. wheels, formed by two crossing lines, see Figure <a href="#sketcher:fig:vehicle1">7</a>.
  658. The construction of the wheels will now involve a circle and two lines:
  659. <p>
  660. <!-- code=python (!bc pycod) typeset with pygments style "default" -->
  661. <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%">wheel1 <span style="color: #666666">=</span> Composition({
  662. <span style="color: #BA2121">&#39;wheel&#39;</span>: Circle(center<span style="color: #666666">=</span>(w_1, R), radius<span style="color: #666666">=</span>R),
  663. <span style="color: #BA2121">&#39;cross&#39;</span>: Composition({<span style="color: #BA2121">&#39;cross1&#39;</span>: Line((w_1,<span style="color: #666666">0</span>), (w_1,<span style="color: #666666">2*</span>R)),
  664. <span style="color: #BA2121">&#39;cross2&#39;</span>: Line((w_1<span style="color: #666666">-</span>R,R), (w_1<span style="color: #666666">+</span>R,R))})})
  665. wheel2 <span style="color: #666666">=</span> wheel1<span style="color: #666666">.</span>copy()
  666. wheel2<span style="color: #666666">.</span>translate((L,<span style="color: #666666">0</span>))
  667. </pre></div>
  668. <p>
  669. Observe that <code>wheel1.copy()</code> copies all the objects that make
  670. up the first wheel, and <code>wheel2.translate</code> translates all
  671. the copied objects.
  672. <p>
  673. <center> <!-- figure -->
  674. <hr class="figure">
  675. <center><p class="caption">Figure 7: Wheels with spokes to illustrate rolling. <div id="sketcher:fig:vehicle1"></div> </p></center>
  676. <p><img src="fig-tut/vehicle1.png" align="bottom" width=400></p>
  677. </center>
  678. <p>
  679. The <code>move</code> function now needs to displace all the objects in the
  680. entire vehicle and also rotate the <code>cross1</code> and <code>cross2</code>
  681. objects in both wheels.
  682. The rotation angle follows from the fact that the arc length
  683. of a rolling wheel equals the displacement of the center of
  684. the wheel, leading to a rotation angle
  685. <p>
  686. <!-- code=python (!bc pycod) typeset with pygments style "default" -->
  687. <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%">angle <span style="color: #666666">=</span> <span style="color: #666666">-</span> x_displacement<span style="color: #666666">/</span>R
  688. </pre></div>
  689. <p>
  690. With <code>w_1</code> tracking the \( x \) coordinate of the center
  691. of the front wheel, we can rotate that wheel by
  692. <p>
  693. <!-- code=python (!bc pycod) typeset with pygments style "default" -->
  694. <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%">w1 <span style="color: #666666">=</span> fig[<span style="color: #BA2121">&#39;vehicle&#39;</span>][<span style="color: #BA2121">&#39;wheels&#39;</span>][<span style="color: #BA2121">&#39;wheel1&#39;</span>]
  695. <span style="color: #008000; font-weight: bold">from</span> <span style="color: #0000FF; font-weight: bold">math</span> <span style="color: #008000; font-weight: bold">import</span> degrees
  696. w1<span style="color: #666666">.</span>rotate(degrees(angle), center<span style="color: #666666">=</span>(w_1, R))
  697. </pre></div>
  698. <p>
  699. The <code>rotate</code> function takes two parameters: the rotation angle
  700. (in degrees) and the center point of the rotation, which is the
  701. center of the wheel in this case. The other wheel is rotated by
  702. <p>
  703. <!-- code=python (!bc pycod) typeset with pygments style "default" -->
  704. <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%">w2 <span style="color: #666666">=</span> fig[<span style="color: #BA2121">&#39;vehicle&#39;</span>][<span style="color: #BA2121">&#39;wheels&#39;</span>][<span style="color: #BA2121">&#39;wheel2&#39;</span>]
  705. w2<span style="color: #666666">.</span>rotate(degrees(angle), center<span style="color: #666666">=</span>(w_1 <span style="color: #666666">+</span> L, R))
  706. </pre></div>
  707. <p>
  708. That is, the angle is the same, but the rotation point is different.
  709. The update of the center point is done by <code>w_1 += x_displacement</code>.
  710. The complete <code>move</code> function with translation of the entire
  711. vehicle and rotation of the wheels then becomes
  712. <p>
  713. <!-- code=python (!bc pycod) typeset with pygments style "default" -->
  714. <div class="highlight" style="background: #f8f8f8"><pre style="line-height: 125%">w_1 <span style="color: #666666">=</span> w_1 <span style="color: #666666">+</span> L <span style="color: #408080; font-style: italic"># start position</span>
  715. <span style="color: #008000; font-weight: bold">def</span> <span style="color: #0000FF">move</span>(t, fig):
  716. x_displacement <span style="color: #666666">=</span> dt<span style="color: #666666">*</span>v(t)
  717. fig[<span style="color: #BA2121">&#39;vehicle&#39;</span>]<span style="color: #666666">.</span>translate((x_displacement, <span style="color: #666666">0</span>))
  718. <span style="color: #408080; font-style: italic"># Rotate wheels</span>
  719. <span style="color: #008000; font-weight: bold">global</span> w_1
  720. w_1 <span style="color: #666666">+=</span> x_displacement
  721. <span style="color: #408080; font-style: italic"># R*angle = -x_displacement</span>
  722. angle <span style="color: #666666">=</span> <span style="color: #666666">-</span> x_displacement<span style="color: #666666">/</span>R
  723. w1 <span style="color: #666666">=</span> fig[<span style="color: #BA2121">&#39;vehicle&#39;</span>][<span style="color: #BA2121">&#39;wheels&#39;</span>][<span style="color: #BA2121">&#39;wheel1&#39;</span>]
  724. w1<span style="color: #666666">.</span>rotate(degrees(angle), center<span style="color: #666666">=</span>(w_1, R))
  725. w2 <span style="color: #666666">=</span> fig[<span style="color: #BA2121">&#39;vehicle&#39;</span>][<span style="color: #BA2121">&#39;wheels&#39;</span>][<span style="color: #BA2121">&#39;wheel2&#39;</span>]
  726. w2<span style="color: #666666">.</span>rotate(degrees(angle), center<span style="color: #666666">=</span>(w_1 <span style="color: #666666">+</span> L, R))
  727. </pre></div>
  728. <p>
  729. The complete example is found in the file
  730. <a href="http://tinyurl.com/ot733jn/vehicle1.py" target="_self"><tt>vehicle1.py</tt></a>. You may run this file or watch a <a href="http://tinyurl.com/oou9lp7/mov-tut/vehicle1.html" target="_self">ready-made movie</a>.
  731. <p>
  732. The advantages with making figures this way, through programming
  733. rather than using interactive drawing programs, are numerous. For
  734. example, the objects are parameterized by variables so that various
  735. dimensions can easily be changed. Subparts of the figure, possible
  736. involving a lot of figure objects, can change color, linetype, filling
  737. or other properties through a <em>single</em> function call. Subparts of the
  738. figure can be rotated, translated, or scaled. Subparts of the figure
  739. can also be copied and moved to other parts of the drawing
  740. area. However, the single most important feature is probably the
  741. ability to make animations governed by mathematical formulas or data
  742. coming from physics simulations of the problem, as shown in the example above.
  743. <p>
  744. <p>
  745. <!-- navigation buttons at the bottom of the page -->
  746. <ul class="pagination">
  747. <li><a href="._pysketcher001.html">&laquo;</a></li>
  748. <li><a href="._pysketcher000.html">1</a></li>
  749. <li><a href="._pysketcher001.html">2</a></li>
  750. <li class="active"><a href="._pysketcher002.html">3</a></li>
  751. <li><a href="._pysketcher003.html">4</a></li>
  752. <li><a href="._pysketcher004.html">5</a></li>
  753. <li><a href="._pysketcher005.html">6</a></li>
  754. <li><a href="._pysketcher003.html">&raquo;</a></li>
  755. </ul>
  756. <!-- ------------------- end of main content --------------- -->
  757. </div> <!-- end container -->
  758. <!-- include javascript, jQuery *first* -->
  759. <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
  760. <script src="http://netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
  761. <!-- Bootstrap footer
  762. <footer>
  763. <a href="http://..."><img width="250" align=right src="http://..."></a>
  764. </footer>
  765. -->
  766. </body>
  767. </html>