Hans Petter Langtangen преди 10 години
родител
ревизия
8246903977

+ 10 - 1
README.do.txt

@@ -49,10 +49,19 @@ See the `examples` directory for some examples beyond the more basic
 ones in the tutorial.
 For example, a pendulum and its body diagram,
 
-FIGURE: [examples/pendulum2, width=800 frac=1]
+FIGURE: [fig/pendulum2, width=800 frac=1]
 
 can be created by the program "`examples/pendulum.py`": "https://github.com/hplgit/pysketcher/tree/master/examples/pendulum.py".
 
+Here is an illustration of the idea of numerical integration:
+
+FIGURE: [fig/integral_noncomic_strip, width=800 frac=1]
+
+As shown in the figure-generating program "`examples/integral_comic_strip.py`": "https://github.com/hplgit/pysketcher/tree/master/examples/integral_comic_strip.py",
+this illustration can easily be turned into an XCKD-style comic strip:
+
+FIGURE: [fig/integral_noncomic_strip, width=800 frac=1]
+
 ===== Technology =====
 
 Pysketcher applies Matplotlib to make the drawings, but it is quite

+ 13 - 2
README.md

@@ -53,11 +53,22 @@ See the `examples` directory for some examples beyond the more basic
 ones in the tutorial.
 For example, a pendulum and its body diagram,
 
-<!-- <img src="examples/pendulum2.png" width=800> -->
-![](examples/pendulum2.png)
+<!-- <img src="fig/pendulum2.png" width=800> -->
+![](fig/pendulum2.png)
 
 can be created by the program [`examples/pendulum.py`](https://github.com/hplgit/pysketcher/tree/master/examples/pendulum.py).
 
+Here is an illustration of the idea of numerical integration:
+
+<!-- <img src="fig/integral_noncomic_strip.png" width=800> -->
+![](fig/integral_noncomic_strip.png)
+
+As shown in the figure-generating program [`examples/integral_comic_strip.py`](https://github.com/hplgit/pysketcher/tree/master/examples/integral_comic_strip.py),
+this illustration can easily be turned into an XCKD-style comic strip:
+
+<!-- <img src="fig/integral_noncomic_strip.png" width=800> -->
+![](fig/integral_noncomic_strip.png)
+
 ### Technology
 
 Pysketcher applies Matplotlib to make the drawings, but it is quite

BIN
examples/FE_comic_strip.pdf


BIN
examples/FE_comic_strip.png


BIN
examples/FE_noncomic_strip.pdf


BIN
examples/FE_noncomic_strip.png


examples/ForwardEuler.py → examples/ForwardEuler_comic_strip.py


BIN
examples/integral_comic_strip.pdf


examples/integral.py → examples/integral_comic_strip.py


BIN
examples/integral_noncomic_strip.pdf


+ 84 - 0
examples/oscillator_sketch.py

@@ -0,0 +1,84 @@
+"""Draw mechanical vibration system."""
+
+from pysketcher import *
+
+L = 12.
+H = L/6
+W = L/6
+
+xmax = L
+drawing_tool.set_coordinate_system(xmin=-L, xmax=xmax,
+                                   ymin=-1, ymax=L+H,
+                                   axis=False,
+                                   instruction_file='tmp_mpl.py')
+x = 0
+drawing_tool.set_linecolor('black')
+
+def make_dashpot(x):
+    d_start = (-L,2*H)
+    d = Dashpot(start=d_start, total_length=L+x, width=W,
+                bar_length=3*H/2, dashpot_length=L/2, piston_pos=H+x)
+    d.rotate(-90, d_start)
+    return d
+
+def make_spring(x):
+    s_start = (-L,4*H)
+    s = Spring(start=s_start, length=L+x, bar_length=3*H/2, teeth=True)
+    s.rotate(-90, s_start)
+    return s
+
+d = make_dashpot(0)
+s = make_spring(0)
+
+M = Rectangle((0,H), 4*H, 4*H).set_linewidth(4)
+left_wall = Rectangle((-L,0),H/10,L).set_filled_curves(pattern='/')
+ground = Wall(x=[-L/2,L], y=[0,0], thickness=-H/10)
+wheel1 = Circle((H,H/2), H/2)
+wheel2 = wheel1.copy()
+wheel2.translate(point(2*H, 0))
+
+fontsize = 18
+text_m = Text('$m$', (2*H, H+2*H), fontsize=fontsize)
+text_ku = Text('$ku$', (-L/2, H+4*H), fontsize=fontsize)
+text_bv = Text("$bu'$", (-L/2, H), fontsize=fontsize)
+x_axis = Axis((2*H, L), H, '$u(t)$', fontsize=fontsize,
+              label_spacing=(0.04, -0.01))
+x_axis_start = Line((2*H, L-H/4), (2*H, L+H/4)).set_linewidth(4)
+
+fig = Composition({
+    'spring': s, 'mass': M, 'left wall': left_wall,
+    'ground': ground, 'wheel1': wheel1, 'wheel2': wheel2,
+    'text_m': text_m, 'text_ku': text_ku,
+    'x_axis': x_axis, 'x_axis_start': x_axis_start})
+
+fig.draw()
+drawing_tool.display()
+drawing_tool.savefig('tmp_oscillator_spring')
+
+drawing_tool.erase()
+
+fig['dashpot'] = d
+fig['text_bv'] = text_bv
+
+# or fig = Composition(dict(fig=fig, dashpot=d, text_bv=text_bv))
+fig.draw()
+
+drawing_tool.display()
+drawing_tool.savefig('tmp_oscillator')
+
+drawing_tool.erase()
+
+text_ku = Text('$ku$', (-L/2, H+4*H), fontsize=fontsize)
+text_bv = Text("$bu'$", (-L/2, H), fontsize=fontsize)
+x_axis = Axis((2*H, L), H, '$u(t)$', fontsize=fontsize,
+              label_spacing=(0.04, -0.01))
+F_force = Force((4*H, H+2*H), (4*H+H, H+2*H), '$F(t)$',
+                text_spacing=(0.057, -0.007), text_alignment='left', fontsize=fontsize)
+fig['text_ku'] = text_ku
+fig['text_bv'] = text_bv
+fig['x_axis'] = x_axis
+fig['F_force'] = F_force
+fig.draw()
+drawing_tool.savefig('tmp_oscillator_general')
+
+raw_input()

BIN
examples/pendulum2.pdf


examples/integral_comic_strip.png → fig/integral_comic_strip.png


examples/integral_noncomic_strip.png → fig/integral_noncomic_strip.png


examples/pendulum2.png → fig/pendulum2.png


+ 3 - 2
pysketcher/shapes.py

@@ -80,7 +80,7 @@ def _is_sequence(seq, length=None,
             if length == len(seq):
                 return True
             elif error_message:
-                raise TypeError('%s is %s; must be %s of length %d' %
+                raise TypeError('sequence %s is not a sequence but %s; must be %s of length %d' %
                             (str(seq), type(seq),
                             ', '.join([str(t) for t in legal_types]),
                              len(seq)))
@@ -89,7 +89,7 @@ def _is_sequence(seq, length=None,
         else:
             return True
     elif error_message:
-        raise TypeError('%s is %s, %s; must be %s' %
+        raise TypeError('sequence %s is not a sequence but %s, %s; must be %s' %
                         (str(seq), seq.__class__.__name__, type(seq),
                         ','.join([str(t)[5:-1] for t in legal_types])))
     else:
@@ -101,6 +101,7 @@ def is_sequence(*sequences, **kwargs):
     error_message = kwargs.get('error_message', True)
     check_inside = kwargs.get('check_inside', False)
     for x in sequences:
+        print('XXX', x, str(x))
         _is_sequence(x, length=length, can_be_None=can_be_None,
                      error_message=error_message)
         if check_inside: