._pysketcher002.html 49 KB

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