Hans Petter Langtangen %!s(int64=10) %!d(string=hai) anos
pai
achega
4e9d422fd8

+ 31 - 1
README.do.txt

@@ -1,4 +1,34 @@
-Python-based drawing tool for making sketches of mechanics problems.
+======= Pysketcher =======
+
+Tool for defining sketches of physics problems in terms of Python code.
+
+===== Purpose =====
+
+Pysketcher can typically be used to draw figures like
+
+FIGURE: [doc/src/tut/fig-tut/wheel_on_inclined_plane, width=600 frac=0.6]
+
+Such figures can easily be *interactively* made using a lot of drawing programs.
+A Pysketcher figure, however, is defined in terms of computer code. This gives
+a great advantage: geometric features can be parameterized in term
+of variables, as here:
+
+FIGURE: [doc/src/tut/fig-tut/vehicle0_dim, width=600 frac=0.6]
+
+One can then quickly change parameters, here to
+`R=0.5; L=5; H=2` and `R=2; L=7; H=1`, and get new figures that would be
+tedious to draw manually in an interactive tool.
+
+FIGURE: [doc/src/tut/fig-tut/vehicle_v23, width=800]
+
+Another major feature of Pysketcher is the ability to let animate the
+sketch. Here is an example of a very simple vehicle on a bumpy road,
+where the solution of a differential equation (upper blue line) is fed
+back to the sketch to make a vertical displacement of the spring and
+other objects in the vehicle, "view animation": "http://hplgit.github.io/bumpy/doc/src/mov-bumpy/m2_k1_5_b0_2/index.html".
+
+FIGURE: [http://hplgit.github.io/bumpy/doc/src/mov-bumpy/m2_k1_5_b0_2/tmp_frame_0000.png, width=600]
+
 
 ===== Tutorial =====
 

+ 35 - 1
README.md

@@ -1,4 +1,38 @@
-Python-based drawing tool for making sketches of mechanics problems.
+## Pysketcher
+
+Tool for defining sketches of physics problems in terms of Python code.
+
+### Purpose
+
+Pysketcher can typically be used to draw figures like
+
+<!-- <img src="doc/src/tut/fig-tut/wheel_on_inclined_plane.png" width=600> -->
+![](doc/src/tut/fig-tut/wheel_on_inclined_plane.png)
+
+Such figures can easily be *interactively* made using a lot of drawing programs.
+A Pysketcher figure, however, is defined in terms of computer code. This gives
+a great advantage: geometric features can be parameterized in term
+of variables, as here:
+
+<!-- <img src="doc/src/tut/fig-tut/vehicle0_dim.png" width=600> -->
+![](doc/src/tut/fig-tut/vehicle0_dim.png)
+
+One can then quickly change parameters, here to
+`R=0.5; L=5; H=2` and `R=2; L=7; H=1`, and get new figures that would be
+tedious to draw manually in an interactive tool.
+
+<!-- <img src="doc/src/tut/fig-tut/vehicle_v23.png" width=800> -->
+![](doc/src/tut/fig-tut/vehicle_v23.png)
+
+Another major feature of Pysketcher is the ability to let animate the
+sketch. Here is an example of a very simple vehicle on a bumpy road,
+where the solution of a differential equation (upper blue line) is fed
+back to the sketch to make a vertical displacement of the spring and
+other objects in the vehicle, [view animation](http://hplgit.github.io/bumpy/doc/src/mov-bumpy/m2_k1_5_b0_2/index.html).
+
+<!-- <img src="http://hplgit.github.io/bumpy/doc/src/mov-bumpy/m2_k1_5_b0_2/tmp_frame_0000.png" width=600> -->
+![](http://hplgit.github.io/bumpy/doc/src/mov-bumpy/m2_k1_5_b0_2/tmp_frame_0000.png)
+
 
 ### Tutorial
 

+ 22 - 0
doc/src/tut/basics.do.txt

@@ -80,11 +80,33 @@ several elements: two circles, two rectangles, and a ``ground'' element.
 
 FIGURE: [fig-tut/vehicle0_dim, width=600] Sketch of a simple figure. label{sketcher:fig:vehicle0}
 
+When the sketch is defined in terms of computer code, it is natural to
+parameterize geometric features, such as the radius of the wheel ($R$),
+the center point of the left wheel ($w_1$), as well as the height ($H$) and
+length ($L$) of the main part. The simple vehicle in
+Figure ref{sketcher:fig:vehicle0} is quickly drawn in almost any interactive
+tool. However, if we want to change the radius of the wheels, you need a
+sophosticated drawing tool to avoid redrawing the whole figure, while
+in computer code this is a matter of changing the $R$ parameter and
+rerunning the program.
+For example, below are two variations of the drawing in
+Figure ref{sketcher:fig:vehicle0} obtained by just setting
+$R=0.5$, $L=5$, $H=2$ and $R=2$, $L=7$, $H=1$, respectively. Being able
+to quickly change geometric sizes is key to many problem settings in
+physics and engineering, but then a program must define the geometry.
+
+<linebreak>
+<linebreak>
+
+FIGURE: [fig-tut/vehicle_v23, width=800]
+
+
 === Basic Drawing ===
 
 A typical program creating these five elements is shown next.
 After importing the `pysketcher` package, the first task is always to
 define a coordinate system:
+
 !bc pycod
 from pysketcher import *
 

+ 43 - 3
doc/src/tut/classes.do.txt

@@ -1,5 +1,12 @@
 ======= Basic Shapes =======
 
+This section presents many of the basic shapes in Pysketcher:
+`Axis`, `Distance_wText`, `Rectangle`, 	Triangle`, `Arc`,
+`Spring`, `Dashpot`, and `Wavy`.
+Each shape is demonstrated with a figure and a
+unit test that shows how the figure is constructed in Python code.
+
+
 ===== Axis =====
 
 The `Axis` object gives the possibility draw a single axis to
@@ -7,8 +14,14 @@ notify a coordinate system. Here is an example where we
 draw $x$ and $y$ axis of three coordinate systems of different
 rotation:
 
+<linebreak>
+<linebreak>
+
 FIGURE: [fig-tut/Axis, width=500 frac=0.7]
 
+<linebreak>
+<linebreak>
+
 The corresponding code looks like this:
 
 @@@CODE ../../../pysketcher/shapes.py fromto: def test_Axis@drawing_tool.savefig\('tmp_Axis'\)
@@ -20,8 +33,16 @@ a distance in a sketch, with an additional text in the middle of the arrow.
 
 The figure
 
+
+<linebreak>
+<linebreak>
+
 FIGURE: [fig-tut/Distance_wText, width=500 frac=0.7]
 
+<linebreak>
+<linebreak>
+
+
 was produced by this code:
 
 @@@CODE ../../../pysketcher/shapes.py fromto: def test_Distance_wText@drawing_tool.savefig\('tmp_Distance
@@ -34,6 +55,9 @@ the appearance of the text that goes with the distance arrow.
 
 FIGURE: [fig-tut/Rectangle, width=500 frac=0.7]
 
+<linebreak>
+<linebreak>
+
 The above figure can be produced by the following code.
 
 @@@CODE ../../../pysketcher/shapes.py fromto: def test_Rectangle@drawing_tool.savefig\('tmp_Rectangle
@@ -45,6 +69,9 @@ important argument in the construction of a shape.
 
 FIGURE: [fig-tut/Triangle, width=500 frac=0.7]
 
+<linebreak>
+<linebreak>
+
 The code below produces the figure.
 
 @@@CODE ../../../pysketcher/shapes.py fromto: def test_Triangle@drawing_tool.savefig\('tmp_Triangle
@@ -55,11 +82,12 @@ to the location of the p1, p2, and even p3 texts.
 
 ===== Arc =====
 
-An arc like
-
 FIGURE: [fig-tut/Arc, width=400 frac=0.5]
 
-is produced by
+<linebreak>
+<linebreak>
+
+An arc like the one above is produced by
 
 @@@CODE ../../../pysketcher/shapes.py fromto: def test_Arc@drawing_tool.savefig\('tmp_Arc
 
@@ -67,6 +95,9 @@ is produced by
 
 FIGURE: [fig-tut/Spring, width=800 frac=1]
 
+<linebreak>
+<linebreak>
+
 The code for making this spring is
 
 @@@CODE ../../../pysketcher/shapes.py fromto: def test_Spring@drawing_tool.savefig\('tmp_Spring
@@ -75,6 +106,9 @@ The code for making this spring is
 
 FIGURE: [fig-tut/Dashpot, width=600 frac=0.8]
 
+<linebreak>
+<linebreak>
+
 This dashpot is produced by
 
 @@@CODE ../../../pysketcher/shapes.py fromto: def test_Dashpot@drawing_tool.savefig\('tmp_Dashpot
@@ -88,8 +122,14 @@ Looks strange. Fix x axis.
 The `StochasticWavyCurve` object offers three precomputed
 graphics that have a random variation:
 
+<linebreak>
+<linebreak>
+
 FIGURE: [fig-tut/StochasticWavyCurve.png, width=600 frac=1]
 
+<linebreak>
+<linebreak>
+
 The usage is simple. The construction
 
 !bc pycod

BIN=BIN
doc/src/tut/fig-tut/vehicle_v1.pdf


BIN=BIN
doc/src/tut/fig-tut/vehicle_v1.png


BIN=BIN
doc/src/tut/fig-tut/vehicle_v2.pdf


BIN=BIN
doc/src/tut/fig-tut/vehicle_v2.png


BIN=BIN
doc/src/tut/fig-tut/vehicle_v23.pdf


BIN=BIN
doc/src/tut/fig-tut/vehicle_v23.png


BIN=BIN
doc/src/tut/fig-tut/vehicle_v3.pdf


BIN=BIN
doc/src/tut/fig-tut/vehicle_v3.png


+ 3 - 0
doc/src/tut/main_sketcher.do.txt

@@ -41,8 +41,11 @@ no further background is required.
 # Learning Goals: these targets the inner workings of pysketcher,
 # which is just a part of this document...
 
+!split
 # #include "basics.do.txt"
 
+!split
 # #include "classes.do.txt"
 
+!split
 # #include "implementation.do.txt"

+ 17 - 13
doc/src/tut/make.sh

@@ -7,23 +7,27 @@ if [ $? -ne 0 ]; then
   exit 1
 fi
 
-main=main_sketcher
-doconce format html $main
+name=main_sketcher
+doconce format html $name
 
-cp .ptex2tex.cfg-minted .ptex2tex.cfg
-doconce format pdflatex $main --skip_inline_comments
-ptex2tex -DMINTED $main
-pdflatex -shell-escape $main
-makeindex $main
-pdflatex -shell-escape $main
-pdflatex -shell-escape $main
+#cp .ptex2tex.cfg-minted .ptex2tex.cfg
+doconce format pdflatex $name --skip_inline_comments --latex_code_style=pyg
+#ptex2tex -DMINTED $name
+pdflatex -shell-escape $name
+makeindex $name
+pdflatex -shell-escape $name
+pdflatex -shell-escape $name
+cp $name.pdf pysketcher.pdf
 
-doconce format sphinx $main --skip_inline_comments
-doconce sphinx_dir author="H. P. Langtangen" version=0.1 theme=pyramid $main
+doconce format html $name --skip_inline_comments --html_style=boostrap_bluegray --html_output=pysketcher
+doconce split_html $name.html
+
+doconce format sphinx $name --skip_inline_comments
+doconce sphinx_dir author="H. P. Langtangen" version=0.1 theme=pyramid $name
 python automake_sphinx.py
 
+# Publish
 dest=../../pub/tutorial
-cp ${main}.pdf $dest/pysketcher.pdf
-#cp $main.html ../../tutorial/pysketcher.html
+cp ${name}.html ._${name}*.html ${name}.pdf $dest/
 rm -rf $dest/html
 cp -r sphinx-rootdir/_build/html $dest/html

+ 10 - 0
doc/src/tut/src-tut/README.txt

@@ -0,0 +1,10 @@
+vehicle0.py: draw vehicle, change colors, let it move
+
+vehicle0_dim.py: draw vehicle and add dimensions used in the sketch
+
+vehicle0_scaling.py: example on how to easily make different vehicles
+from the same code
+
+vehicle1.py: as vehicle0.py, but rolling wheels
+
+vehicle2.py: how to make the vehicle drawing a shape in the Shape hierarchy

+ 42 - 0
doc/src/tut/src-tut/vehicle0_scaling.py

@@ -0,0 +1,42 @@
+from pysketcher import *
+
+def draw_vehicle(
+    R=1,    # radius of wheel
+    L=4,    # distance between wheels
+    H=2,    # height of vehicle body
+    w_1=5,  # position of front wheel
+    ):
+
+    xmax = w_1 + 2*L + 3*R
+    drawing_tool.set_coordinate_system(xmin=0, xmax=xmax,
+                                       ymin=-1, ymax=2*R + 3*H,
+                                       axis=False)
+
+    wheel1 = Circle(center=(w_1, R), radius=R)
+    wheel2 = wheel1.copy()
+    wheel2.translate((L,0))
+
+    under = Rectangle(lower_left_corner=(w_1-2*R, 2*R),
+                      width=2*R + L + 2*R, height=H)
+    over  = Rectangle(lower_left_corner=(w_1, 2*R + H),
+                      width=2.5*R, height=1.25*H)
+
+    wheels = Composition({'wheel1': wheel1, 'wheel2': wheel2})
+    body = Composition({'under': under, 'over': over})
+
+    vehicle = Composition({'wheels': wheels, 'body': body})
+    ground = Wall(x=[R, xmax], y=[0, 0], thickness=-0.3*R)
+
+    fig = Composition({'vehicle': vehicle, 'ground': ground})
+    return fig
+
+#fig = draw_vehicle(R=1, L=4, H=2, w_1=8)
+#fig = draw_vehicle(R=0.5, L=5, H=2, w_1=8)
+fig = draw_vehicle(R=2, L=7, H=1, w_1=10)
+fig.draw()  # send all figures to plotting backend
+
+drawing_tool.display()
+drawing_tool.savefig('tmp1.png')
+drawing_tool.savefig('tmp1.pdf')
+
+raw_input()

BIN=BIN
examples/FE_comic_strip.pdf


BIN=BIN
examples/FE_comic_strip.png


+ 15 - 10
examples/ForwardEuler.py

@@ -1,10 +1,13 @@
+"""Comic strip for illustrating Euler's method for ODEs."""
+
 from pysketcher import *
 import numpy as np
+xkcd = True
 
 xmin = 0
 drawing_tool.set_coordinate_system(xmin=xmin, xmax=4,
                                    ymin=0, ymax=2.5,
-                                   axis=True, xkcd=True)
+                                   axis=True, xkcd=xkcd)
 drawing_tool.set_linecolor('blue')
 
 def ForwardEuler(I, a, T, dt):
@@ -16,7 +19,7 @@ def ForwardEuler(I, a, T, dt):
         t.append(t[-1] + dt)
     return np.array(u), np.array(t)
 
-def make_fig(dt=0.5):
+def make_fig(dt=0.5, heading=''):
     I = 2
     a = 0.5
     T_e = 3
@@ -49,35 +52,37 @@ def make_fig(dt=0.5):
     text_exact = Text_wArrow("exact solution", (2.5, 1), (2.5, I*np.exp(-a*2.5)),
                              alignment='left')
 
-    text_predict = Text_wArrow("Here we know the slope:\n$u'=-au$!\nLet the solution continue\nalong that slope.",
+    text_predict = Text_wArrow("Here we know the slope:\n$u'=f(u,t)$!\nLet the solution continue\nalong that slope.",
                                (1.7, 1.7), (t[-1], u[-1]),
                                alignment='left')
     text_next = Text_wArrow("This is the next\npredicted point",
                             (1, 0.25), (t_next, u_next),
                             alignment='left')
 
+    text_comment = Text(heading, (0.3, 2.05), alignment='left')
+
     fig = Composition(dict(curves=curves,
                            circles=circles,
                            exact=text_exact,
                            predict=text_predict,
-                           next=text_next))
+                           next=text_next,
+                           comment=text_comment))
     return fig
 
-fig = make_fig(dt=0.5)
+fig = make_fig(dt=0.5, heading="Differential equations $u'=f(u,t)$\nare hard to solve,\nbut not with programming!")
 fig.draw()
 drawing_tool.display()
 drawing_tool.savefig('tmp1')
 
 drawing_tool.erase()
-text_comment = Text('Just reduce the time step to\nmake more accurate predictions!', (1, 2.25))
-fig = make_fig(dt=0.24)
-fig = Composition(dict(prev_fig=fig, comment=text_comment))
+fig = make_fig(dt=0.24, heading='Just reduce the time step\nto make more accurate\npredictions!')
 fig.draw()
 drawing_tool.display()
 drawing_tool.savefig('tmp2')
 
 import os
-os.system('doconce combine_images pdf -2 tmp1 tmp2 FE_strip')
-os.system('doconce combine_images png -2 tmp1 tmp2 FE_strip')
+comic = 'comic' if xkcd else 'non_comic'
+os.system('doconce combine_images pdf -2 tmp1 tmp2 FE_%s_strip' % comic)
+os.system('doconce combine_images png -2 tmp1 tmp2 FE_%s_strip' % comic)
 
 raw_input()

+ 7 - 3
examples/integral.py

@@ -1,4 +1,7 @@
+"""Comic strip for illustrating numerical integration."""
+
 from pysketcher import *
+xdcd = True
 
 def f(x):
     return 3*np.exp(-x**4)
@@ -6,7 +9,7 @@ def f(x):
 xmin = -2
 drawing_tool.set_coordinate_system(xmin=xmin, xmax=4,
                                    ymin=0, ymax=4,
-                                   axis=True, xkcd=True)
+                                   axis=True, xkcd=xkcd)
 drawing_tool.set_linecolor('blue')
 
 import numpy as np
@@ -77,7 +80,8 @@ drawing_tool.display()
 drawing_tool.savefig('tmp3')
 
 import os
-os.system('doconce combine_images pdf -3 tmp1 tmp2 tmp3 integral_comic_strip')
-os.system('doconce combine_images png -3 tmp1 tmp2 tmp3 integral_comic_strip')
+comic = 'comic' if xkcd else 'non_comic'
+os.system('doconce combine_images pdf -3 tmp1 tmp2 tmp3 integral_%s_strip' % comic)
+os.system('doconce combine_images png -3 tmp1 tmp2 tmp3 integral_%s_strip' % comic)
 
 raw_input()