8 Incheckningar 679f3a239c ... bcec0fd16e

Upphovsman SHA1 Meddelande Datum
  Gilbert Brault bcec0fd16e Added Trajectory and jet_pump 5 år sedan
  Gilbert Brault 97a015cd04 update postbuild 5 år sedan
  Gilbert Brault f103f17b7d update Trajectory 5 år sedan
  Gilbert Brault 8807fc7175 added Trajectory to User Guide 5 år sedan
  Gilbert Brault 75f1f3b8f5 update User Guide 5 år sedan
  Gilbert Brault f566ab60c3 tweak postBuild 5 år sedan
  Gilbert Brault 4ec6492b45 update user guide 5 år sedan
  Gilbert Brault 8dd385234f added Trajectory Class + jet_pump sketch 5 år sedan
70 ändrade filer med 6250 tillägg och 1502 borttagningar
  1. 2 0
      .gitignore
  2. 1 1
      .vscode/settings.json
  3. 3 0
      devrequirements.txt
  4. BIN
      doc/design/jet-pump.png
  5. 64 0
      jupysketch-doc/docs/Gallery/car.svg
  6. 43 0
      jupysketch-doc/docs/Gallery/car.yml
  7. 141 0
      jupysketch-doc/docs/Gallery/dryfriction.svg
  8. 98 0
      jupysketch-doc/docs/Gallery/dryfriction.yml
  9. 276 0
      jupysketch-doc/docs/Gallery/jet_pump.svg
  10. 157 0
      jupysketch-doc/docs/Gallery/jet_pump.yml
  11. 97 0
      jupysketch-doc/docs/Gallery/pendulum.svg
  12. 52 0
      jupysketch-doc/docs/Gallery/pendulum.yml
  13. 123 0
      jupysketch-doc/docs/Gallery/springdashpotmass.svg
  14. 56 0
      jupysketch-doc/docs/Gallery/springdashpotmass.yml
  15. 107 0
      jupysketch-doc/docs/Gallery/springmass.svg
  16. 51 0
      jupysketch-doc/docs/Gallery/springmass.yml
  17. 9 0
      jupysketch-doc/docs/gallerydoc.md
  18. 31 0
      jupysketch-doc/docs/shapereference.md
  19. 1 0
      jupysketch-doc/mkdocs.yml
  20. 17 5
      jupysketch-doc/site/404.html
  21. 64 0
      jupysketch-doc/site/Gallery/car.svg
  22. 43 0
      jupysketch-doc/site/Gallery/car.yml
  23. 141 0
      jupysketch-doc/site/Gallery/dryfriction.svg
  24. 98 0
      jupysketch-doc/site/Gallery/dryfriction.yml
  25. 276 0
      jupysketch-doc/site/Gallery/jet_pump.svg
  26. 157 0
      jupysketch-doc/site/Gallery/jet_pump.yml
  27. 97 0
      jupysketch-doc/site/Gallery/pendulum.svg
  28. 52 0
      jupysketch-doc/site/Gallery/pendulum.yml
  29. 123 0
      jupysketch-doc/site/Gallery/springdashpotmass.svg
  30. 56 0
      jupysketch-doc/site/Gallery/springdashpotmass.yml
  31. 107 0
      jupysketch-doc/site/Gallery/springmass.svg
  32. 51 0
      jupysketch-doc/site/Gallery/springmass.yml
  33. 17 5
      jupysketch-doc/site/about/index.html
  34. 0 2
      jupysketch-doc/site/assets/javascripts/bundle.b39636ac.min.js
  35. 0 1
      jupysketch-doc/site/assets/javascripts/bundle.b39636ac.min.js.map
  36. 2 0
      jupysketch-doc/site/assets/javascripts/bundle.f9edbbd5.min.js
  37. 1 0
      jupysketch-doc/site/assets/javascripts/bundle.f9edbbd5.min.js.map
  38. 1 1
      jupysketch-doc/site/assets/javascripts/lunr/tinyseg.min.js
  39. 31 0
      jupysketch-doc/site/assets/javascripts/vendor.c3dc8c49.min.js
  40. 1 0
      jupysketch-doc/site/assets/javascripts/vendor.c3dc8c49.min.js.map
  41. 0 31
      jupysketch-doc/site/assets/javascripts/vendor.d710d30a.min.js
  42. 0 1
      jupysketch-doc/site/assets/javascripts/vendor.d710d30a.min.js.map
  43. 7 7
      jupysketch-doc/site/assets/javascripts/worker/search.a68abb33.min.js
  44. 1 0
      jupysketch-doc/site/assets/javascripts/worker/search.8e2cddea.min.js.map
  45. 0 1
      jupysketch-doc/site/assets/javascripts/worker/search.a68abb33.min.js.map
  46. 3 0
      jupysketch-doc/site/assets/stylesheets/main.947af8d5.min.css
  47. 1 0
      jupysketch-doc/site/assets/stylesheets/main.947af8d5.min.css.map
  48. 0 3
      jupysketch-doc/site/assets/stylesheets/main.fe0cca5b.min.css
  49. 0 1
      jupysketch-doc/site/assets/stylesheets/main.fe0cca5b.min.css.map
  50. 2 2
      jupysketch-doc/site/assets/stylesheets/palette.a46bcfb3.min.css
  51. 1 0
      jupysketch-doc/site/assets/stylesheets/palette.7f672a1f.min.css.map
  52. 0 1
      jupysketch-doc/site/assets/stylesheets/palette.a46bcfb3.min.css.map
  53. 363 0
      jupysketch-doc/site/gallerydoc/index.html
  54. 17 5
      jupysketch-doc/site/index.html
  55. 17 5
      jupysketch-doc/site/learningbyexample/index.html
  56. 17 5
      jupysketch-doc/site/presentation/index.html
  57. 1 1
      jupysketch-doc/site/search/search_index.json
  58. 17 5
      jupysketch-doc/site/shapereference/index.html
  59. 10 6
      jupysketch-doc/site/sitemap.xml
  60. BIN
      jupysketch-doc/site/sitemap.xml.gz
  61. 31 5
      jupysketch-doc/site/yamlsketcher/index.html
  62. 389 8
      notebooks/.ipynb_checkpoints/DryFriction-checkpoint.ipynb
  63. 376 88
      notebooks/DryFriction.ipynb
  64. 9 8
      notebooks/Gallery.ipynb
  65. 2092 1288
      notebooks/Reference.ipynb
  66. 157 0
      notebooks/jet_pump.yml
  67. 1 3
      postBuild
  68. 73 13
      pysketcher/shapes.py
  69. 17 0
      test/docs/index.md
  70. 1 0
      test/mkdocs.yml

+ 2 - 0
.gitignore

@@ -25,6 +25,8 @@ temp*
 *.toc
 *.snm
 *.vrb
+# vscode files
+.vscode/settings.json
 # eclipse files:
 *.cproject
 *.project

+ 1 - 1
.vscode/settings.json

@@ -1,4 +1,4 @@
 {
-    "python.pythonPath": "c:\\Users\\gilbe\\Documents\\GitHub\\venv\\Scripts\\python.exe",
+    "python.pythonPath": "/home/gilbert/Github/venv/bin/python3",
     "python.dataScience.jupyterServerURI": "local"
 }

+ 3 - 0
devrequirements.txt

@@ -0,0 +1,3 @@
+mkdocs
+mkdocs-material
+ipywidgetsm

BIN
doc/design/jet-pump.png


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 64 - 0
jupysketch-doc/docs/Gallery/car.svg


+ 43 - 0
jupysketch-doc/docs/Gallery/car.yml

@@ -0,0 +1,43 @@
+!!omap
+- name: car
+- parts:
+  - name: head
+    shapes:
+      libraries: ['from math import tan, radians, sin, cos', 'from pysketcher import *']
+  - name: constants
+    shapes:
+        R: 1.0    # radius of wheel
+        L: 4.0    # distance between wheels
+        H: 2.0    # height of vehicle body
+        w_1: 5.0  # position of front wheel
+  - name: frame
+    shapes:
+        xmax: w_1 + 2*L + 3*R
+        setframe:
+            action: drawing_tool.set_coordinate_system(xmin=0, xmax=xmax,
+                                   ymin=-1, ymax=2*R + 3*H,
+                                   axis=False)
+        wheel1: |
+                 Composition({'wheel': Circle(center=(w_1, R), radius=R),
+                    'cross': Composition({'cross1': Line((w_1,0),(w_1,2*R)),
+                    'cross2': Line((w_1-R,R), (w_1+R,R))})})
+        wheel2: 
+            formula: wheel1.copy()
+            transform: 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)
+
+        car: |
+               Composition({'vehicle': vehicle, 'ground': ground})

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 141 - 0
jupysketch-doc/docs/Gallery/dryfriction.svg


+ 98 - 0
jupysketch-doc/docs/Gallery/dryfriction.yml

@@ -0,0 +1,98 @@
+!!omap
+- name: unknown
+- parts:
+  - name: head
+    shapes:
+      libraries: ['from math import tan, radians, sin, cos', from pysketcher import
+          *]
+  - name: constants
+    shapes:
+      fontsize: 18       # size of the characters
+      g: 9.81            # constant gravity
+      theta: 30.0        # inclined plane angle
+      L: 10.0            # sketch sizing parameter
+      a: 1.0             #
+      xmin: 0.0          # sketech min Abscissa
+      ymin: -3.0         # sketech min Ordinate     
+      rl: 2.0            # rectangle width
+      rL: 1.0            # rectangle length
+  - name: frame
+    shapes:
+      setframe:          # sketch setup
+        action: drawing_tool.set_coordinate_system(xmin=xmin-L/5, xmax=xmin+1.5*L,ymin=ymin,
+          ymax=ymin+1.5*L,instruction_file='tmp_mpl_friction.py')
+      setblackline:      # default frame values and actions
+        action: drawing_tool.set_linecolor('black')
+      B: point(a+L,0)                    # wall right end
+      A: point(a,tan(radians(theta))*L)  # wall left end
+      normal_vec: point(sin(radians(theta)),cos(radians(theta)))   # Vector normal to wall
+      tangent_vec: point(cos(radians(theta)),-sin(radians(theta))) # Vector tangent to wall
+      help_line: Line(A,B)               # wall line
+      x: a + 3*L/10.                     # contact point Abscissa
+      y: help_line(x=x)                  # contact point Ordinate
+      contact: point(x, y)               # contact point: middle of the rectangle bottom edge
+      c: contact + rL/2*normal_vec
+  - name: body
+    shapes:
+      rectangle:
+        formula: Rectangle(contact, rl, rL)
+        style:
+          linecolor: blue
+          filled_curves: 
+              color: blue
+        transform: ['rotate(-theta, contact)', translate(-rl/2*tangent_vec)]
+      N:
+        formula: Force(contact - rl*normal_vec, contact, r'$N$', text_pos='start')
+        style:
+          linecolor: black
+      wheel:
+        formula: "Composition({'outer': rectangle})"
+        style:
+          shadow: 1
+      mc:
+        formula: Text(r'$c$', c)
+      body:
+        formula: "Composition({'wheel': wheel, 'N': N, 'mc': mc})"
+        style:
+          linecolor: black
+  - name: plan
+    shapes:
+      mB:
+        formula: Text(r'$B$',B)
+      mA:
+        formula: Text(r'$A$', A)
+      wall:
+        formula: Wall(x=[A[0], B[0]], y=[A[1], B[1]], thickness=-0.25,transparent=False)
+        style:
+          linecolor: black
+      x_const:
+        formula: Line(contact, contact + point(0,4))
+        style:
+          linestyle: dotted
+        transform: rotate(-theta, contact)
+      x_axis:
+        formula: Axis(start=contact+ 2*rl*normal_vec, length=2*rl,label='$x$', rotation_angle=-theta)
+      plan:
+        formula: "Composition({'body': body, 'inclined wall': wall, 'x start': x_const,\
+          \ 'x axis': x_axis, 'mA': mA, 'mB': mB})"
+  - name: friction
+    shapes:
+      mg:
+        formula: Gravity(c, rl, text='$Mg$')
+        style:
+          linecolor: black
+      angle:
+        formula: Arc_wText(r'$<bslash>theta$', center=B, radius=3, start_angle=180-theta,
+          arc_angle=theta, fontsize=fontsize)
+        style:
+          linecolor: black
+          linewidth: 1
+      ground:
+        formula: Line((B[0]-L/10., 0), (B[0]-L/2.,0))
+        stlye:
+          linecolor: black
+          linestyle: dashed
+          linewidth: 1
+      friction:
+        formula: "Composition({'plan': plan, 'ground': ground, 'mg': mg, 'angle':\
+          \ angle})"

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 276 - 0
jupysketch-doc/docs/Gallery/jet_pump.svg


+ 157 - 0
jupysketch-doc/docs/Gallery/jet_pump.yml

@@ -0,0 +1,157 @@
+!!omap
+- name: jet_pump
+- parts:
+  - name: head
+    shapes:
+      libraries: ['from math import tan, radians, degrees, sin, cos, atan2, pi', 'from pysketcher import *']
+  - name: constants
+    shapes:          # All dimenssions in cm angles in degrees
+        Ljp: 16.0    # Total length
+        Lcy: 1.5     # Lenght of input cylindre
+        Lcon: 3.0    # length of input cone
+        Lmix: 2.0    # Length of mixing chamber cylinder
+        Lct: 1.0     # Length of penetration of jet cone inside cone mixing chamber
+        Lt: 5.0      # Length of transit cylinder
+        Ld: 4.0      # length of diffussion cone
+        D: 4         # external diameter
+        Din: 2.5     # Input cylinder internal diameter
+        Dout: 2.5    # Output internal Diameter
+        Dn: 0.5      # Nozzle internal diametre
+        Dmix: 3.5    # Diameter mixing chamber
+        einc: 0.25   # Thickness of the jet cone
+        eain: 0.2    # air input pipe thickness
+        x0: 1        # x drawing padding
+        y0: 1        # y drawing padding
+        H: 2.0       # Air pipe heigth
+        N: 0.75      # position of the nozzle exit with respect to mixing chamber output cone start
+  - name: frame
+    shapes:
+        Dt: D/3
+        setframe:          # sketch setup
+            action: drawing_tool.set_coordinate_system(xmin=0, xmax=Ljp+2*x0,
+                                   ymin=0, ymax=H+2*y0+D*1.5,
+                                   axis=False)
+        setblackline:      # default frame values and actions
+            action: drawing_tool.set_linecolor('blue')
+  - name: part0
+    shapes:
+        P01: Point(x0,y0+H)
+        P02: P01 + Point(0,(D-Din)/2)
+        P03: P02 + Point(Lcy,0)
+        P04: P03 + Point(Lcon,(Din-Dn)/2)
+        alpha: atan2((P04.y-P03.y),(P04.x-P03.x))
+        P05: P04 - Point(0,einc/cos(alpha))
+        P06: P05 - Point((Lmix+N)*cos(alpha),(Lmix+N)*sin(alpha))
+        P07: Point(P06.x,y0)
+        P08: P07-Point(eain,0)
+        P09: P08+Point(0,H)
+        p0: |
+            [P01,P02,P03,P04,P05,P06,P07,P08,P09,P01]
+        part0: 
+            formula: Trajectory(p0)
+            style:
+                filled_curves: 
+                    pattern: '/'
+        Lmixcone: Ljp-Ld-Lt-2*eain-Lmix-(P09.x-P01.x) # length of the mixing chamber cone
+        P11: Point(P07.x+Lmix,y0)
+        P12: P11 + Point(0,H+(D-Dmix)/2)
+        P13: P12 + Point(Lmixcone,(Dmix-Dt)/2)
+        P14: P13 + Point(Lt,0)
+        P15: P14 + Point(Ld,-(Dout-Dt)/2)
+        P16: P15 - Point(0,(D-Dout)/2)
+        P17: P16 - Point(Ld+Lt+Lmixcone-eain,0)
+        P18: P17 - Point(0,H)
+        p1: |
+               [P11,P12,P13,P14,P15,P16,P17,P18,P11]        
+        part1:
+            formula: Trajectory(p1)
+            style:
+                filled_curves:
+                    pattern: '/'
+        P21: Point(x0,y0+H+D)
+        P22: P21 + Point(Ljp-eain,0)
+        P23: P22 + Point(0,-(D-Dout)/2)
+        P24: P23 + Point(-Ld,-(Dout-Dt)/2)
+        P25: P24 + Point(-Lt,0)
+        P26: P25 + Point(-Lmixcone, (Dmix-Dt)/2)
+        P27: P26 + Point(-(Lmix),0)
+        P2C: P21 + Point(0,-(D-Din)/2)
+        P2B: P2C + Point(Lcy,0)
+        P2A: P2B + Point((Lcon+eain)*cos(alpha),-(Lcon+eain)*sin(alpha))
+        P29: P2A + Point(0,einc/cos(alpha))
+        P28: P29 + Point(-(Lmix+N)*cos(alpha), (Lmix+N)*sin(alpha))
+        p2:  |
+               [P21,P22,P23,P24,P25,P26,P27,P28,P29,P2A,P2B,P2C]
+        part2:
+            formula: Trajectory(p2)
+            style:
+                filled_curves:
+                    pattern: '/'
+        venturi: |  
+            Composition({'part0':part0,'part1':part1, 'part2':part2})
+        dljp: 
+            formula: Distance_wText(P21+Point(0,0.5),P22+Point(0,0.5),r'$L<bslash>textsubscript{jp}$')
+            style:
+                linecolor: 'black'
+                linewidth: 1
+        dld: 
+            formula: Distance_wText(Point(P14.x,P16.y)+Point(0,-1.5),P16+Point(0,-1.5),r'$L<bslash>textsubscript{d}$')
+            style:
+                linecolor: 'black'
+                linewidth: 1
+        dlt: 
+            formula: Distance_wText(Point(P13.x,P16.y)+Point(0,-1.5),Point(P14.x,P16.y)+Point(0,-1.5),r'$L<bslash>textsubscript{t}$')
+            style:
+                linecolor: 'black'
+                linewidth: 1
+        dlcm: 
+            formula: Distance_wText(Point(P12.x,P16.y)+Point(0,-1.5),Point(P13.x,P16.y)+Point(0,-1.5),r'$L<bslash>textsubscript{cm}$')
+            style:
+                linecolor: 'black'
+                linewidth: 1
+        dlmix: 
+            formula: Distance_wText(Point(P06.x,P16.y)+Point(0,-1.5),Point(P11.x,P16.y)+Point(0,-1.5),r'$L<bslash>textsubscript{mix}$')
+            style:
+                linecolor: 'black'
+                linewidth: 1
+        dlin: 
+            formula: Distance_wText(P02+Point(0,0.5),P03+Point(0,0.5),r'$L<bslash>textsubscript{in}$')
+            style:
+                linecolor: 'black'
+                linewidth: 1
+        dd:
+            formula: Distance_wText(P01-Point(0.5,0),P21-Point(0.5,0),r'$D$',alignment='right')
+            style:
+                linecolor: 'black'
+                linewidth: 1
+        dn:
+            formula: Distance_wText(P04+Point(0.5,0),P2A+Point(0.5,0),r'$D<bslash>textsubscript{n}$')
+            style:
+                linecolor: 'black'
+                linewidth: 1
+        ddmix:
+            formula: Distance_wText(P12,P26,r'$D<bslash>textsubscript{mix}$',alignment='right')
+            style:
+                linecolor: 'black'
+                linewidth: 1
+        ddin:
+            formula: Distance_wText(P02+Point(1.5,0),P2C+Point(1.5,0),r'$D<bslash>textsubscript{in}$',alignment='right')
+            style:
+                linecolor: 'black'
+                linewidth: 1
+        ddout:
+            formula: Distance_wText(P15+Point(0.5,0),P23+Point(0.5,0),r'$D<bslash>textsubscript{out}$')
+            style:
+                linecolor: 'black'
+                linewidth: 1
+        ddt:
+            formula: Distance_wText(P13,P25,r'$D<bslash>textsubscript{t}$')
+            style:
+                linecolor: 'black'
+                linewidth: 1
+        dim:  |
+            Composition({'dljp': dljp,'dld': dld,'dlt': dlt,'dlcm': dlcm,'dlmix': dlmix,'dlin': dlin,
+                        'ddin': ddin,'ddout': ddout,'ddt': ddt,'dd': dd,'dn':dn,'ddmix': ddmix})
+        jet_pump: |
+            Composition({'venturi':venturi, 'dim':dim})
+        

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 97 - 0
jupysketch-doc/docs/Gallery/pendulum.svg


+ 52 - 0
jupysketch-doc/docs/Gallery/pendulum.yml

@@ -0,0 +1,52 @@
+!!omap
+- name: pendulum
+- parts:
+  - name: head
+    shapes:
+      libraries: ['from math import tan, radians, sin, cos', 'from pysketcher import *']
+  - name: constants
+    shapes:
+        H: 7.0
+        W: 6.0
+  - name: frame
+    shapes:
+        setframe:          # sketch setup
+            action: drawing_tool.set_coordinate_system(xmin=0, xmax=W,
+                                   ymin=0, ymax=H,
+                                   axis=False)
+        setblackline:      # default frame values and actions
+            action: drawing_tool.set_linecolor('blue')
+        L: 5*H/7          # length
+        P: (W/6, 0.85*H)  # rotation point
+        a: 40             # angle
+        vertical: 
+            formula: Line(P, P-point(0,L))
+            style:
+                linecolor: black
+                linewidth: 1
+        path: 
+            formula: Arc(P, L, -90, a)
+            style:
+                linecolor: black
+                linewidth: 1
+        angle: Arc_wText(r'$\theta$', P, L/4, -90, a, text_spacing=1/30.)
+
+        #rod: Line(P, P + L*point(sin(radians(a)), -L*cos(radians(a)))) is a less reliable alternative
+        mass_pt: path.geometric_features()['end']
+        rod: Line(P, mass_pt)
+
+        mass: 
+            formula: Circle(center=mass_pt, radius=L/20.)
+            style:
+                filled_curves: 
+                    color: 'blue'
+        rod_vec: rod.geometric_features()['end'] - rod.geometric_features()['start']
+        unit_rod_vec: unit_vec(rod_vec)
+        mass_symbol: Text('$m$', mass_pt + L/10*unit_rod_vec)
+
+        length: 
+            formula: Distance_wText(P, mass_pt, '$L$') # Displace length indication
+            transform: translate(L/15*point(cos(radians(a)), sin(radians(a))))
+        gravity: Gravity(start=P+point(0.8*L,0), length=L/3)
+
+        pendulum: "Composition({'body': mass, 'rod': rod,'vertical': vertical, 'theta': angle, 'path': path,'g': gravity, 'L': length, 'm': mass_symbol})"

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 123 - 0
jupysketch-doc/docs/Gallery/springdashpotmass.svg


+ 56 - 0
jupysketch-doc/docs/Gallery/springdashpotmass.yml

@@ -0,0 +1,56 @@
+!!omap
+- name: springdashpotmass
+- parts:
+  - name: head
+    shapes:
+      libraries: ['from math import tan, radians, sin, cos', 'from pysketcher import *']
+  - name: constants
+    shapes:
+        L: 12.
+  - name: frame
+    shapes:
+        H: L/6
+        W: L/6
+        xmax: L
+        x: 0        
+        setframe:
+            action: drawing_tool.set_coordinate_system(xmin=-L, xmax=xmax,
+                                   ymin=-1, ymax=L+H,
+                                   axis=False,
+                                   instruction_file='tmp_mpl_spring_mass.py')
+        globallinecolor:
+            action: drawing_tool.set_linecolor('black')
+        d_start: (-L,2*H)
+        dashpot:
+            formula: Dashpot(start=d_start, total_length=L+x, width=W,
+                bar_length=3*H/2, dashpot_length=L/2, piston_pos=H+x)
+            transform: rotate(-90, d_start)
+        s_start: (-L,4*H)
+        spring: 
+            formula: Spring(start=s_start, length=L+x, bar_length=3*H/2, teeth=True)
+            transform: rotate(-90, s_start)
+        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: 
+            formula: wheel1.copy()
+            transform: 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: 
+            formula: Line((2*H, L-H/4), (2*H, L+H/4))
+            style:
+                linewidth: 4
+
+        springdashpotmass: |
+                      Composition({
+                        'spring': spring, 'dashpot': dashpot, '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})

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 107 - 0
jupysketch-doc/docs/Gallery/springmass.svg


+ 51 - 0
jupysketch-doc/docs/Gallery/springmass.yml

@@ -0,0 +1,51 @@
+!!omap
+- name: springmass
+- parts:
+  - name: head
+    shapes:
+      libraries: ['from math import tan, radians, sin, cos', 'from pysketcher import *']
+  - name: constants
+    shapes:
+        L: 12.
+  - name: frame
+    shapes:
+        H: L/6
+        W: L/6
+        xmax: L
+        x: 0        
+        setframe:
+            action: drawing_tool.set_coordinate_system(xmin=-L, xmax=xmax,
+                                   ymin=-1, ymax=L+H,
+                                   axis=False,
+                                   instruction_file='tmp_mpl_spring_mass.py')
+        globallinecolor:
+            action: drawing_tool.set_linecolor('black')
+        s_start: (-L,4*H)
+        spring: 
+            formula: Spring(start=s_start, length=L+x, bar_length=3*H/2, teeth=True)
+            transform: rotate(-90, s_start)
+        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: 
+            formula: wheel1.copy()
+            transform: 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: 
+            formula: Line((2*H, L-H/4), (2*H, L+H/4))
+            style:
+                linewidth: 4
+
+        springmass: |
+                      Composition({
+                        'spring': spring, '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})

+ 9 - 0
jupysketch-doc/docs/gallerydoc.md

@@ -0,0 +1,9 @@
+| Dry Friction                           | Car                         | Pendulum                         |
+|:--------------------------------------:|:---------------------------:|:--------------------------------:|
+| ![](Gallery/dryfriction.svg)           |  ![](Gallery/car.svg)       | ![](Gallery/pendulum.svg)        |
+|[Dry Friction](Gallery/dryfriction.yml) | [Car](Gallery/car.yml)      | [Pendulum](Gallery/pendulum.yml) |
+
+| Spring Mass                            | Spring Dashpot Mass                             |  Jet pump                        |
+|:--------------------------------------:|:-----------------------------------------------:|:--------------------------------:|
+| ![](Gallery/springmass.svg)            |  ![](Gallery/springdashpotmass.svg)             | ![](Gallery/jet_pump.svg)        |
+|[Spring](Gallery/springmass.yml)        | [Spring Dashpot](Gallery/springdashpotmass.yml) | [Jet pump](Gallery/jet_pump.yml) |

+ 31 - 0
jupysketch-doc/docs/shapereference.md

@@ -16,6 +16,7 @@
 - [Force](#force): defines an Indication of a force by an arrow and a text (symbol)
 - [Wall](#wall): defines an hached box given starting, ending point and thickness, filled with a pattern
 - [Curve](#curve): defines a general curve as a sequence of (x,y) coordinates
+- [Trajectory](#trajectory): defines a general curve as a sequence of Point (subclass Curve)
 - [Gravity](#gravity): defines a downward-pointing gravity arrow with the symbol g or user given symbol.
 - [Moment](#moment): defines a Moment arrow with text given text, center and radius
 - [Text_wArrow](#text_warrow): defines Text, but an arrow is drawn from the mid part of the text to some point arrow_tip
@@ -301,6 +302,36 @@ curve.set_name("curve")
 ```
 ![Curve](reference/curve.svg)
 
+## Trajectory
+[home](#list-of-shapes) defines a general curve as a sequence of Point (subclass Curve)
+
+### Yaml
+```yaml
+trajectory="""\
+name: trajectory
+shapes:
+    P1: Point(1,-1)
+    P2: P1 + Point(0,2)
+    P3: P2 + Point(-2,0)
+    P4: P3 + Point(0,-2)
+    psq: |
+       [P1,P2,P3,P4]  
+    trajectory: Trajectory(psq)
+"""
+```
+### Python
+```python
+P1 = Point(1,-1)
+P2 = P1 + Point(0,2)
+P3 = P2 + Point(-2,0)
+P4 = P3 + Point(0,-2)
+psq = [P1,P2,P3,P4]
+trajectory = Trajectory(psq)
+trajectory.draw()
+curve.set_name("trajectory")
+```
+![Curve](reference/trajectory.svg)
+
 ## Gravity
 [home](#list-of-shapes) defines a downward-pointing gravity arrow with the symbol g or user given symbol.
 

+ 1 - 0
jupysketch-doc/mkdocs.yml

@@ -6,6 +6,7 @@ nav:
     - Learning by Example: learningbyexample.md
     - Shapes Reference: shapereference.md
     - YAML files Reference: yamlsketcher.md
+    - Gallery: gallerydoc.md
 theme:
   name: material
 markdown_extensions:

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 17 - 5
jupysketch-doc/site/404.html


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 64 - 0
jupysketch-doc/site/Gallery/car.svg


+ 43 - 0
jupysketch-doc/site/Gallery/car.yml

@@ -0,0 +1,43 @@
+!!omap
+- name: car
+- parts:
+  - name: head
+    shapes:
+      libraries: ['from math import tan, radians, sin, cos', 'from pysketcher import *']
+  - name: constants
+    shapes:
+        R: 1.0    # radius of wheel
+        L: 4.0    # distance between wheels
+        H: 2.0    # height of vehicle body
+        w_1: 5.0  # position of front wheel
+  - name: frame
+    shapes:
+        xmax: w_1 + 2*L + 3*R
+        setframe:
+            action: drawing_tool.set_coordinate_system(xmin=0, xmax=xmax,
+                                   ymin=-1, ymax=2*R + 3*H,
+                                   axis=False)
+        wheel1: |
+                 Composition({'wheel': Circle(center=(w_1, R), radius=R),
+                    'cross': Composition({'cross1': Line((w_1,0),(w_1,2*R)),
+                    'cross2': Line((w_1-R,R), (w_1+R,R))})})
+        wheel2: 
+            formula: wheel1.copy()
+            transform: 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)
+
+        car: |
+               Composition({'vehicle': vehicle, 'ground': ground})

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 141 - 0
jupysketch-doc/site/Gallery/dryfriction.svg


+ 98 - 0
jupysketch-doc/site/Gallery/dryfriction.yml

@@ -0,0 +1,98 @@
+!!omap
+- name: unknown
+- parts:
+  - name: head
+    shapes:
+      libraries: ['from math import tan, radians, sin, cos', from pysketcher import
+          *]
+  - name: constants
+    shapes:
+      fontsize: 18       # size of the characters
+      g: 9.81            # constant gravity
+      theta: 30.0        # inclined plane angle
+      L: 10.0            # sketch sizing parameter
+      a: 1.0             #
+      xmin: 0.0          # sketech min Abscissa
+      ymin: -3.0         # sketech min Ordinate     
+      rl: 2.0            # rectangle width
+      rL: 1.0            # rectangle length
+  - name: frame
+    shapes:
+      setframe:          # sketch setup
+        action: drawing_tool.set_coordinate_system(xmin=xmin-L/5, xmax=xmin+1.5*L,ymin=ymin,
+          ymax=ymin+1.5*L,instruction_file='tmp_mpl_friction.py')
+      setblackline:      # default frame values and actions
+        action: drawing_tool.set_linecolor('black')
+      B: point(a+L,0)                    # wall right end
+      A: point(a,tan(radians(theta))*L)  # wall left end
+      normal_vec: point(sin(radians(theta)),cos(radians(theta)))   # Vector normal to wall
+      tangent_vec: point(cos(radians(theta)),-sin(radians(theta))) # Vector tangent to wall
+      help_line: Line(A,B)               # wall line
+      x: a + 3*L/10.                     # contact point Abscissa
+      y: help_line(x=x)                  # contact point Ordinate
+      contact: point(x, y)               # contact point: middle of the rectangle bottom edge
+      c: contact + rL/2*normal_vec
+  - name: body
+    shapes:
+      rectangle:
+        formula: Rectangle(contact, rl, rL)
+        style:
+          linecolor: blue
+          filled_curves: 
+              color: blue
+        transform: ['rotate(-theta, contact)', translate(-rl/2*tangent_vec)]
+      N:
+        formula: Force(contact - rl*normal_vec, contact, r'$N$', text_pos='start')
+        style:
+          linecolor: black
+      wheel:
+        formula: "Composition({'outer': rectangle})"
+        style:
+          shadow: 1
+      mc:
+        formula: Text(r'$c$', c)
+      body:
+        formula: "Composition({'wheel': wheel, 'N': N, 'mc': mc})"
+        style:
+          linecolor: black
+  - name: plan
+    shapes:
+      mB:
+        formula: Text(r'$B$',B)
+      mA:
+        formula: Text(r'$A$', A)
+      wall:
+        formula: Wall(x=[A[0], B[0]], y=[A[1], B[1]], thickness=-0.25,transparent=False)
+        style:
+          linecolor: black
+      x_const:
+        formula: Line(contact, contact + point(0,4))
+        style:
+          linestyle: dotted
+        transform: rotate(-theta, contact)
+      x_axis:
+        formula: Axis(start=contact+ 2*rl*normal_vec, length=2*rl,label='$x$', rotation_angle=-theta)
+      plan:
+        formula: "Composition({'body': body, 'inclined wall': wall, 'x start': x_const,\
+          \ 'x axis': x_axis, 'mA': mA, 'mB': mB})"
+  - name: friction
+    shapes:
+      mg:
+        formula: Gravity(c, rl, text='$Mg$')
+        style:
+          linecolor: black
+      angle:
+        formula: Arc_wText(r'$<bslash>theta$', center=B, radius=3, start_angle=180-theta,
+          arc_angle=theta, fontsize=fontsize)
+        style:
+          linecolor: black
+          linewidth: 1
+      ground:
+        formula: Line((B[0]-L/10., 0), (B[0]-L/2.,0))
+        stlye:
+          linecolor: black
+          linestyle: dashed
+          linewidth: 1
+      friction:
+        formula: "Composition({'plan': plan, 'ground': ground, 'mg': mg, 'angle':\
+          \ angle})"

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 276 - 0
jupysketch-doc/site/Gallery/jet_pump.svg


+ 157 - 0
jupysketch-doc/site/Gallery/jet_pump.yml

@@ -0,0 +1,157 @@
+!!omap
+- name: jet_pump
+- parts:
+  - name: head
+    shapes:
+      libraries: ['from math import tan, radians, degrees, sin, cos, atan2, pi', 'from pysketcher import *']
+  - name: constants
+    shapes:          # All dimenssions in cm angles in degrees
+        Ljp: 16.0    # Total length
+        Lcy: 1.5     # Lenght of input cylindre
+        Lcon: 3.0    # length of input cone
+        Lmix: 2.0    # Length of mixing chamber cylinder
+        Lct: 1.0     # Length of penetration of jet cone inside cone mixing chamber
+        Lt: 5.0      # Length of transit cylinder
+        Ld: 4.0      # length of diffussion cone
+        D: 4         # external diameter
+        Din: 2.5     # Input cylinder internal diameter
+        Dout: 2.5    # Output internal Diameter
+        Dn: 0.5      # Nozzle internal diametre
+        Dmix: 3.5    # Diameter mixing chamber
+        einc: 0.25   # Thickness of the jet cone
+        eain: 0.2    # air input pipe thickness
+        x0: 1        # x drawing padding
+        y0: 1        # y drawing padding
+        H: 2.0       # Air pipe heigth
+        N: 0.75      # position of the nozzle exit with respect to mixing chamber output cone start
+  - name: frame
+    shapes:
+        Dt: D/3
+        setframe:          # sketch setup
+            action: drawing_tool.set_coordinate_system(xmin=0, xmax=Ljp+2*x0,
+                                   ymin=0, ymax=H+2*y0+D*1.5,
+                                   axis=False)
+        setblackline:      # default frame values and actions
+            action: drawing_tool.set_linecolor('blue')
+  - name: part0
+    shapes:
+        P01: Point(x0,y0+H)
+        P02: P01 + Point(0,(D-Din)/2)
+        P03: P02 + Point(Lcy,0)
+        P04: P03 + Point(Lcon,(Din-Dn)/2)
+        alpha: atan2((P04.y-P03.y),(P04.x-P03.x))
+        P05: P04 - Point(0,einc/cos(alpha))
+        P06: P05 - Point((Lmix+N)*cos(alpha),(Lmix+N)*sin(alpha))
+        P07: Point(P06.x,y0)
+        P08: P07-Point(eain,0)
+        P09: P08+Point(0,H)
+        p0: |
+            [P01,P02,P03,P04,P05,P06,P07,P08,P09,P01]
+        part0: 
+            formula: Trajectory(p0)
+            style:
+                filled_curves: 
+                    pattern: '/'
+        Lmixcone: Ljp-Ld-Lt-2*eain-Lmix-(P09.x-P01.x) # length of the mixing chamber cone
+        P11: Point(P07.x+Lmix,y0)
+        P12: P11 + Point(0,H+(D-Dmix)/2)
+        P13: P12 + Point(Lmixcone,(Dmix-Dt)/2)
+        P14: P13 + Point(Lt,0)
+        P15: P14 + Point(Ld,-(Dout-Dt)/2)
+        P16: P15 - Point(0,(D-Dout)/2)
+        P17: P16 - Point(Ld+Lt+Lmixcone-eain,0)
+        P18: P17 - Point(0,H)
+        p1: |
+               [P11,P12,P13,P14,P15,P16,P17,P18,P11]        
+        part1:
+            formula: Trajectory(p1)
+            style:
+                filled_curves:
+                    pattern: '/'
+        P21: Point(x0,y0+H+D)
+        P22: P21 + Point(Ljp-eain,0)
+        P23: P22 + Point(0,-(D-Dout)/2)
+        P24: P23 + Point(-Ld,-(Dout-Dt)/2)
+        P25: P24 + Point(-Lt,0)
+        P26: P25 + Point(-Lmixcone, (Dmix-Dt)/2)
+        P27: P26 + Point(-(Lmix),0)
+        P2C: P21 + Point(0,-(D-Din)/2)
+        P2B: P2C + Point(Lcy,0)
+        P2A: P2B + Point((Lcon+eain)*cos(alpha),-(Lcon+eain)*sin(alpha))
+        P29: P2A + Point(0,einc/cos(alpha))
+        P28: P29 + Point(-(Lmix+N)*cos(alpha), (Lmix+N)*sin(alpha))
+        p2:  |
+               [P21,P22,P23,P24,P25,P26,P27,P28,P29,P2A,P2B,P2C]
+        part2:
+            formula: Trajectory(p2)
+            style:
+                filled_curves:
+                    pattern: '/'
+        venturi: |  
+            Composition({'part0':part0,'part1':part1, 'part2':part2})
+        dljp: 
+            formula: Distance_wText(P21+Point(0,0.5),P22+Point(0,0.5),r'$L<bslash>textsubscript{jp}$')
+            style:
+                linecolor: 'black'
+                linewidth: 1
+        dld: 
+            formula: Distance_wText(Point(P14.x,P16.y)+Point(0,-1.5),P16+Point(0,-1.5),r'$L<bslash>textsubscript{d}$')
+            style:
+                linecolor: 'black'
+                linewidth: 1
+        dlt: 
+            formula: Distance_wText(Point(P13.x,P16.y)+Point(0,-1.5),Point(P14.x,P16.y)+Point(0,-1.5),r'$L<bslash>textsubscript{t}$')
+            style:
+                linecolor: 'black'
+                linewidth: 1
+        dlcm: 
+            formula: Distance_wText(Point(P12.x,P16.y)+Point(0,-1.5),Point(P13.x,P16.y)+Point(0,-1.5),r'$L<bslash>textsubscript{cm}$')
+            style:
+                linecolor: 'black'
+                linewidth: 1
+        dlmix: 
+            formula: Distance_wText(Point(P06.x,P16.y)+Point(0,-1.5),Point(P11.x,P16.y)+Point(0,-1.5),r'$L<bslash>textsubscript{mix}$')
+            style:
+                linecolor: 'black'
+                linewidth: 1
+        dlin: 
+            formula: Distance_wText(P02+Point(0,0.5),P03+Point(0,0.5),r'$L<bslash>textsubscript{in}$')
+            style:
+                linecolor: 'black'
+                linewidth: 1
+        dd:
+            formula: Distance_wText(P01-Point(0.5,0),P21-Point(0.5,0),r'$D$',alignment='right')
+            style:
+                linecolor: 'black'
+                linewidth: 1
+        dn:
+            formula: Distance_wText(P04+Point(0.5,0),P2A+Point(0.5,0),r'$D<bslash>textsubscript{n}$')
+            style:
+                linecolor: 'black'
+                linewidth: 1
+        ddmix:
+            formula: Distance_wText(P12,P26,r'$D<bslash>textsubscript{mix}$',alignment='right')
+            style:
+                linecolor: 'black'
+                linewidth: 1
+        ddin:
+            formula: Distance_wText(P02+Point(1.5,0),P2C+Point(1.5,0),r'$D<bslash>textsubscript{in}$',alignment='right')
+            style:
+                linecolor: 'black'
+                linewidth: 1
+        ddout:
+            formula: Distance_wText(P15+Point(0.5,0),P23+Point(0.5,0),r'$D<bslash>textsubscript{out}$')
+            style:
+                linecolor: 'black'
+                linewidth: 1
+        ddt:
+            formula: Distance_wText(P13,P25,r'$D<bslash>textsubscript{t}$')
+            style:
+                linecolor: 'black'
+                linewidth: 1
+        dim:  |
+            Composition({'dljp': dljp,'dld': dld,'dlt': dlt,'dlcm': dlcm,'dlmix': dlmix,'dlin': dlin,
+                        'ddin': ddin,'ddout': ddout,'ddt': ddt,'dd': dd,'dn':dn,'ddmix': ddmix})
+        jet_pump: |
+            Composition({'venturi':venturi, 'dim':dim})
+        

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 97 - 0
jupysketch-doc/site/Gallery/pendulum.svg


+ 52 - 0
jupysketch-doc/site/Gallery/pendulum.yml

@@ -0,0 +1,52 @@
+!!omap
+- name: pendulum
+- parts:
+  - name: head
+    shapes:
+      libraries: ['from math import tan, radians, sin, cos', 'from pysketcher import *']
+  - name: constants
+    shapes:
+        H: 7.0
+        W: 6.0
+  - name: frame
+    shapes:
+        setframe:          # sketch setup
+            action: drawing_tool.set_coordinate_system(xmin=0, xmax=W,
+                                   ymin=0, ymax=H,
+                                   axis=False)
+        setblackline:      # default frame values and actions
+            action: drawing_tool.set_linecolor('blue')
+        L: 5*H/7          # length
+        P: (W/6, 0.85*H)  # rotation point
+        a: 40             # angle
+        vertical: 
+            formula: Line(P, P-point(0,L))
+            style:
+                linecolor: black
+                linewidth: 1
+        path: 
+            formula: Arc(P, L, -90, a)
+            style:
+                linecolor: black
+                linewidth: 1
+        angle: Arc_wText(r'$\theta$', P, L/4, -90, a, text_spacing=1/30.)
+
+        #rod: Line(P, P + L*point(sin(radians(a)), -L*cos(radians(a)))) is a less reliable alternative
+        mass_pt: path.geometric_features()['end']
+        rod: Line(P, mass_pt)
+
+        mass: 
+            formula: Circle(center=mass_pt, radius=L/20.)
+            style:
+                filled_curves: 
+                    color: 'blue'
+        rod_vec: rod.geometric_features()['end'] - rod.geometric_features()['start']
+        unit_rod_vec: unit_vec(rod_vec)
+        mass_symbol: Text('$m$', mass_pt + L/10*unit_rod_vec)
+
+        length: 
+            formula: Distance_wText(P, mass_pt, '$L$') # Displace length indication
+            transform: translate(L/15*point(cos(radians(a)), sin(radians(a))))
+        gravity: Gravity(start=P+point(0.8*L,0), length=L/3)
+
+        pendulum: "Composition({'body': mass, 'rod': rod,'vertical': vertical, 'theta': angle, 'path': path,'g': gravity, 'L': length, 'm': mass_symbol})"

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 123 - 0
jupysketch-doc/site/Gallery/springdashpotmass.svg


+ 56 - 0
jupysketch-doc/site/Gallery/springdashpotmass.yml

@@ -0,0 +1,56 @@
+!!omap
+- name: springdashpotmass
+- parts:
+  - name: head
+    shapes:
+      libraries: ['from math import tan, radians, sin, cos', 'from pysketcher import *']
+  - name: constants
+    shapes:
+        L: 12.
+  - name: frame
+    shapes:
+        H: L/6
+        W: L/6
+        xmax: L
+        x: 0        
+        setframe:
+            action: drawing_tool.set_coordinate_system(xmin=-L, xmax=xmax,
+                                   ymin=-1, ymax=L+H,
+                                   axis=False,
+                                   instruction_file='tmp_mpl_spring_mass.py')
+        globallinecolor:
+            action: drawing_tool.set_linecolor('black')
+        d_start: (-L,2*H)
+        dashpot:
+            formula: Dashpot(start=d_start, total_length=L+x, width=W,
+                bar_length=3*H/2, dashpot_length=L/2, piston_pos=H+x)
+            transform: rotate(-90, d_start)
+        s_start: (-L,4*H)
+        spring: 
+            formula: Spring(start=s_start, length=L+x, bar_length=3*H/2, teeth=True)
+            transform: rotate(-90, s_start)
+        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: 
+            formula: wheel1.copy()
+            transform: 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: 
+            formula: Line((2*H, L-H/4), (2*H, L+H/4))
+            style:
+                linewidth: 4
+
+        springdashpotmass: |
+                      Composition({
+                        'spring': spring, 'dashpot': dashpot, '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})

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 107 - 0
jupysketch-doc/site/Gallery/springmass.svg


+ 51 - 0
jupysketch-doc/site/Gallery/springmass.yml

@@ -0,0 +1,51 @@
+!!omap
+- name: springmass
+- parts:
+  - name: head
+    shapes:
+      libraries: ['from math import tan, radians, sin, cos', 'from pysketcher import *']
+  - name: constants
+    shapes:
+        L: 12.
+  - name: frame
+    shapes:
+        H: L/6
+        W: L/6
+        xmax: L
+        x: 0        
+        setframe:
+            action: drawing_tool.set_coordinate_system(xmin=-L, xmax=xmax,
+                                   ymin=-1, ymax=L+H,
+                                   axis=False,
+                                   instruction_file='tmp_mpl_spring_mass.py')
+        globallinecolor:
+            action: drawing_tool.set_linecolor('black')
+        s_start: (-L,4*H)
+        spring: 
+            formula: Spring(start=s_start, length=L+x, bar_length=3*H/2, teeth=True)
+            transform: rotate(-90, s_start)
+        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: 
+            formula: wheel1.copy()
+            transform: 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: 
+            formula: Line((2*H, L-H/4), (2*H, L+H/4))
+            style:
+                linewidth: 4
+
+        springmass: |
+                      Composition({
+                        'spring': spring, '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})

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 17 - 5
jupysketch-doc/site/about/index.html


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 2
jupysketch-doc/site/assets/javascripts/bundle.b39636ac.min.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 1
jupysketch-doc/site/assets/javascripts/bundle.b39636ac.min.js.map


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 2 - 0
jupysketch-doc/site/assets/javascripts/bundle.f9edbbd5.min.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 0
jupysketch-doc/site/assets/javascripts/bundle.f9edbbd5.min.js.map


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 1
jupysketch-doc/site/assets/javascripts/lunr/tinyseg.min.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 31 - 0
jupysketch-doc/site/assets/javascripts/vendor.c3dc8c49.min.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 0
jupysketch-doc/site/assets/javascripts/vendor.c3dc8c49.min.js.map


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 31
jupysketch-doc/site/assets/javascripts/vendor.d710d30a.min.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 1
jupysketch-doc/site/assets/javascripts/vendor.d710d30a.min.js.map


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 7 - 7
jupysketch-doc/site/assets/javascripts/worker/search.a68abb33.min.js


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 0
jupysketch-doc/site/assets/javascripts/worker/search.8e2cddea.min.js.map


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 1
jupysketch-doc/site/assets/javascripts/worker/search.a68abb33.min.js.map


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 3 - 0
jupysketch-doc/site/assets/stylesheets/main.947af8d5.min.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 0
jupysketch-doc/site/assets/stylesheets/main.947af8d5.min.css.map


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 3
jupysketch-doc/site/assets/stylesheets/main.fe0cca5b.min.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 1
jupysketch-doc/site/assets/stylesheets/main.fe0cca5b.min.css.map


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 2 - 2
jupysketch-doc/site/assets/stylesheets/palette.a46bcfb3.min.css


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 0
jupysketch-doc/site/assets/stylesheets/palette.7f672a1f.min.css.map


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 0 - 1
jupysketch-doc/site/assets/stylesheets/palette.a46bcfb3.min.css.map


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 363 - 0
jupysketch-doc/site/gallerydoc/index.html


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 17 - 5
jupysketch-doc/site/index.html


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 17 - 5
jupysketch-doc/site/learningbyexample/index.html


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 17 - 5
jupysketch-doc/site/presentation/index.html


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 1 - 1
jupysketch-doc/site/search/search_index.json


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 17 - 5
jupysketch-doc/site/shapereference/index.html


+ 10 - 6
jupysketch-doc/site/sitemap.xml

@@ -1,27 +1,31 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"><url>
      <loc>None</loc>
-     <lastmod>2020-08-07</lastmod>
+     <lastmod>2020-08-10</lastmod>
      <changefreq>daily</changefreq>
     </url><url>
      <loc>None</loc>
-     <lastmod>2020-08-07</lastmod>
+     <lastmod>2020-08-10</lastmod>
      <changefreq>daily</changefreq>
     </url><url>
      <loc>None</loc>
-     <lastmod>2020-08-07</lastmod>
+     <lastmod>2020-08-10</lastmod>
      <changefreq>daily</changefreq>
     </url><url>
      <loc>None</loc>
-     <lastmod>2020-08-07</lastmod>
+     <lastmod>2020-08-10</lastmod>
      <changefreq>daily</changefreq>
     </url><url>
      <loc>None</loc>
-     <lastmod>2020-08-07</lastmod>
+     <lastmod>2020-08-10</lastmod>
      <changefreq>daily</changefreq>
     </url><url>
      <loc>None</loc>
-     <lastmod>2020-08-07</lastmod>
+     <lastmod>2020-08-10</lastmod>
+     <changefreq>daily</changefreq>
+    </url><url>
+     <loc>None</loc>
+     <lastmod>2020-08-10</lastmod>
      <changefreq>daily</changefreq>
     </url>
 </urlset>

BIN
jupysketch-doc/site/sitemap.xml.gz


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 31 - 5
jupysketch-doc/site/yamlsketcher/index.html


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 389 - 8
notebooks/.ipynb_checkpoints/DryFriction-checkpoint.ipynb


Filskillnaden har hållts tillbaka eftersom den är för stor
+ 376 - 88
notebooks/DryFriction.ipynb


+ 9 - 8
notebooks/Gallery.ipynb

@@ -27,7 +27,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 7,
+   "execution_count": 3,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -36,13 +36,13 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 3,
+   "execution_count": 4,
    "metadata": {},
    "outputs": [
     {
      "data": {
       "application/vnd.jupyter.widget-view+json": {
-       "model_id": "d78995ed95724bb68c60298b74ef60d8",
+       "model_id": "7fd5d20c5f974004896c722afbd3243e",
        "version_major": 2,
        "version_minor": 0
       },
@@ -61,7 +61,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 4,
+   "execution_count": 5,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -70,7 +70,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 5,
+   "execution_count": 6,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -79,7 +79,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 6,
+   "execution_count": 7,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -92,7 +92,8 @@
    "metadata": {},
    "outputs": [],
    "source": [
-    "files = [(\"dryfriction\",\"friction\"),(\"pendulum\",\"pendulum\"),(\"car\",\"car\"),(\"springmass\",\"springmass\"),(\"springdashpotmass\",\"springdashpotmass\")]"
+    "files = [(\"dryfriction\",\"friction\"),(\"pendulum\",\"pendulum\"),(\"car\",\"car\"),(\"springmass\",\"springmass\"),\n",
+    "         (\"springdashpotmass\",\"springdashpotmass\"),(\"jet_pump\",\"jet_pump\")]"
    ]
   },
   {
@@ -155,7 +156,7 @@
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.8.5"
+   "version": "3.8.2"
   }
  },
  "nbformat": 4,

Filskillnaden har hållts tillbaka eftersom den är för stor
+ 2092 - 1288
notebooks/Reference.ipynb


+ 157 - 0
notebooks/jet_pump.yml

@@ -0,0 +1,157 @@
+!!omap
+- name: jet_pump
+- parts:
+  - name: head
+    shapes:
+      libraries: ['from math import tan, radians, degrees, sin, cos, atan2, pi', 'from pysketcher import *']
+  - name: constants
+    shapes:          # All dimenssions in cm angles in degrees
+        Ljp: 16.0    # Total length
+        Lcy: 1.5     # Lenght of input cylindre
+        Lcon: 3.0    # length of input cone
+        Lmix: 2.0    # Length of mixing chamber cylinder
+        Lct: 1.0     # Length of penetration of jet cone inside cone mixing chamber
+        Lt: 5.0      # Length of transit cylinder
+        Ld: 4.0      # length of diffussion cone
+        D: 4         # external diameter
+        Din: 2.5     # Input cylinder internal diameter
+        Dout: 2.5    # Output internal Diameter
+        Dn: 0.5      # Nozzle internal diametre
+        Dmix: 3.5    # Diameter mixing chamber
+        einc: 0.25   # Thickness of the jet cone
+        eain: 0.2    # air input pipe thickness
+        x0: 1        # x drawing padding
+        y0: 1        # y drawing padding
+        H: 2.0       # Air pipe heigth
+        N: 0.75      # position of the nozzle exit with respect to mixing chamber output cone start
+  - name: frame
+    shapes:
+        Dt: D/3
+        setframe:          # sketch setup
+            action: drawing_tool.set_coordinate_system(xmin=0, xmax=Ljp+2*x0,
+                                   ymin=0, ymax=H+2*y0+D*1.5,
+                                   axis=False)
+        setblackline:      # default frame values and actions
+            action: drawing_tool.set_linecolor('blue')
+  - name: part0
+    shapes:
+        P01: Point(x0,y0+H)
+        P02: P01 + Point(0,(D-Din)/2)
+        P03: P02 + Point(Lcy,0)
+        P04: P03 + Point(Lcon,(Din-Dn)/2)
+        alpha: atan2((P04.y-P03.y),(P04.x-P03.x))
+        P05: P04 - Point(0,einc/cos(alpha))
+        P06: P05 - Point((Lmix+N)*cos(alpha),(Lmix+N)*sin(alpha))
+        P07: Point(P06.x,y0)
+        P08: P07-Point(eain,0)
+        P09: P08+Point(0,H)
+        p0: |
+            [P01,P02,P03,P04,P05,P06,P07,P08,P09,P01]
+        part0: 
+            formula: Trajectory(p0)
+            style:
+                filled_curves: 
+                    pattern: '/'
+        Lmixcone: Ljp-Ld-Lt-2*eain-Lmix-(P09.x-P01.x) # length of the mixing chamber cone
+        P11: Point(P07.x+Lmix,y0)
+        P12: P11 + Point(0,H+(D-Dmix)/2)
+        P13: P12 + Point(Lmixcone,(Dmix-Dt)/2)
+        P14: P13 + Point(Lt,0)
+        P15: P14 + Point(Ld,-(Dout-Dt)/2)
+        P16: P15 - Point(0,(D-Dout)/2)
+        P17: P16 - Point(Ld+Lt+Lmixcone-eain,0)
+        P18: P17 - Point(0,H)
+        p1: |
+               [P11,P12,P13,P14,P15,P16,P17,P18,P11]        
+        part1:
+            formula: Trajectory(p1)
+            style:
+                filled_curves:
+                    pattern: '/'
+        P21: Point(x0,y0+H+D)
+        P22: P21 + Point(Ljp-eain,0)
+        P23: P22 + Point(0,-(D-Dout)/2)
+        P24: P23 + Point(-Ld,-(Dout-Dt)/2)
+        P25: P24 + Point(-Lt,0)
+        P26: P25 + Point(-Lmixcone, (Dmix-Dt)/2)
+        P27: P26 + Point(-(Lmix),0)
+        P2C: P21 + Point(0,-(D-Din)/2)
+        P2B: P2C + Point(Lcy,0)
+        P2A: P2B + Point((Lcon+eain)*cos(alpha),-(Lcon+eain)*sin(alpha))
+        P29: P2A + Point(0,einc/cos(alpha))
+        P28: P29 + Point(-(Lmix+N)*cos(alpha), (Lmix+N)*sin(alpha))
+        p2:  |
+               [P21,P22,P23,P24,P25,P26,P27,P28,P29,P2A,P2B,P2C]
+        part2:
+            formula: Trajectory(p2)
+            style:
+                filled_curves:
+                    pattern: '/'
+        venturi: |  
+            Composition({'part0':part0,'part1':part1, 'part2':part2})
+        dljp: 
+            formula: Distance_wText(P21+Point(0,0.5),P22+Point(0,0.5),r'$L<bslash>textsubscript{jp}$')
+            style:
+                linecolor: 'black'
+                linewidth: 1
+        dld: 
+            formula: Distance_wText(Point(P14.x,P16.y)+Point(0,-1.5),P16+Point(0,-1.5),r'$L<bslash>textsubscript{d}$')
+            style:
+                linecolor: 'black'
+                linewidth: 1
+        dlt: 
+            formula: Distance_wText(Point(P13.x,P16.y)+Point(0,-1.5),Point(P14.x,P16.y)+Point(0,-1.5),r'$L<bslash>textsubscript{t}$')
+            style:
+                linecolor: 'black'
+                linewidth: 1
+        dlcm: 
+            formula: Distance_wText(Point(P12.x,P16.y)+Point(0,-1.5),Point(P13.x,P16.y)+Point(0,-1.5),r'$L<bslash>textsubscript{cm}$')
+            style:
+                linecolor: 'black'
+                linewidth: 1
+        dlmix: 
+            formula: Distance_wText(Point(P06.x,P16.y)+Point(0,-1.5),Point(P11.x,P16.y)+Point(0,-1.5),r'$L<bslash>textsubscript{mix}$')
+            style:
+                linecolor: 'black'
+                linewidth: 1
+        dlin: 
+            formula: Distance_wText(P02+Point(0,0.5),P03+Point(0,0.5),r'$L<bslash>textsubscript{in}$')
+            style:
+                linecolor: 'black'
+                linewidth: 1
+        dd:
+            formula: Distance_wText(P01-Point(0.5,0),P21-Point(0.5,0),r'$D$',alignment='right')
+            style:
+                linecolor: 'black'
+                linewidth: 1
+        dn:
+            formula: Distance_wText(P04+Point(0.5,0),P2A+Point(0.5,0),r'$D<bslash>textsubscript{n}$')
+            style:
+                linecolor: 'black'
+                linewidth: 1
+        ddmix:
+            formula: Distance_wText(P12,P26,r'$D<bslash>textsubscript{mix}$',alignment='right')
+            style:
+                linecolor: 'black'
+                linewidth: 1
+        ddin:
+            formula: Distance_wText(P02+Point(1.5,0),P2C+Point(1.5,0),r'$D<bslash>textsubscript{in}$',alignment='right')
+            style:
+                linecolor: 'black'
+                linewidth: 1
+        ddout:
+            formula: Distance_wText(P15+Point(0.5,0),P23+Point(0.5,0),r'$D<bslash>textsubscript{out}$')
+            style:
+                linecolor: 'black'
+                linewidth: 1
+        ddt:
+            formula: Distance_wText(P13,P25,r'$D<bslash>textsubscript{t}$')
+            style:
+                linecolor: 'black'
+                linewidth: 1
+        dim:  |
+            Composition({'dljp': dljp,'dld': dld,'dlt': dlt,'dlcm': dlcm,'dlmix': dlmix,'dlin': dlin,
+                        'ddin': ddin,'ddout': ddout,'ddt': ddt,'dd': dd,'dn':dn,'ddmix': ddmix})
+        jet_pump: |
+            Composition({'venturi':venturi, 'dim':dim})
+        

+ 1 - 3
postBuild

@@ -3,9 +3,7 @@ conda update -y notebook
 conda update -y jupyterlab
 pip install git+https://github.com/pycontribs/ruyaml.git
 pip install ipywidgets
-pip install --upgrade ruamel.yaml
 jupyter labextension update --all
-jupyter labextension install --no-build @jupyter-widgets/jupyterlab-manager
-jupyter labextension install @jupyter-widgets/jupyterlab-manager jupyter-matplotlib
+jupyter labextension install --no-build @jupyter-widgets/jupyterlab-manager jupyter-matplotlib
 pip install git+https://github.com/gbrault/jupytersketcher.git
 jupyter lab build

+ 73 - 13
pysketcher/shapes.py

@@ -161,7 +161,11 @@ class Sketch():
                     if type(_r) == str:
                         print(_r)
                         return False
-                    exec(l,self.container)
+                    try:
+                        exec(l,self.container)
+                    except Exception as e:
+                        print(f"{_k} / {l} error: {str(e)}")
+                        return False
             #print(_k, _c, _t)
             if _t == "<class 'ruamel.yaml.scalarfloat.ScalarFloat'>" or \
             _t == "<class 'str'>" or _t == "<class 'int'>" or _t == "<class 'ruamel.yaml.scalarstring.LiteralScalarString'>":
@@ -172,7 +176,11 @@ class Sketch():
                 if type(_r) == str:
                     print(_r)
                     return False
-                exec(_formula,self.container)
+                try:
+                    exec(_formula,self.container)
+                except Exception as e:
+                    print(f"{_formula} error: {str(e)}")
+                    return False
             elif _t == "<class 'ruamel.yaml.comments.CommentedMap'>":
                 #print(_c)
                 _keys = list(_c.keys())
@@ -185,7 +193,11 @@ class Sketch():
                     if type(_r) == str:
                         print(_r)
                         return False
-                    exec(_formula,self.container)
+                    try:
+                        exec(_formula,self.container)
+                    except Exception as e:
+                        print(f"{_formula} error: {str(e)}")
+                        return False
                     # if the new object is a shape and has the sketch name, set this shape name as the sketch name
                     if issubclass(type(self.container[_k]), Shape):
                         if _k == sketch_name:
@@ -201,18 +213,34 @@ class Sketch():
                                 _style = f"{_k}.set_{_style}(pixel_displacement={_param})"
                             else:
                                 _style = f"{_k}.set_{_style}({_param})"
-                            exec(_style,self.container)
+                            try:
+                                exec(_style,self.container)
+                            except Exception as e:
+                                print(f"{_style} error: {str(e)}")
+                                return False
                         else:
                             if 'filled_curves' == _style:
                                 if 'color' in list(_param.keys()):
                                     _style = f"{_k}.set_{_style}(color='{_param['color']}')"
-                                    exec(_style,self.container)
+                                    try:
+                                        exec(_style,self.container)
+                                    except Exception as e:
+                                        print(f"{_style} error: {str(e)}")
+                                        return False
                                 if 'pattern' in list(_param.keys()):
                                     _style = f"{_k}.set_{_style}(pattern='{_param['pattern']}')"
-                                    exec(_style,self.container)
+                                    try:
+                                        exec(_style,self.container)
+                                    except Exception as e:
+                                        print(f"{_style} error: {str(e)}")
+                                        return False
                             else:
                                 _style = f"{_k}.set_{_style}('{_param}')"
-                                exec(_style,self.container)
+                                try:
+                                    exec(_style,self.container)
+                                except Exception as e:
+                                    print(f"{_style} error: {str(e)}")
+                                    return False
                         #print(_style)                        
                 if 'transform' in _keys:
                     #print(_c['transform'])
@@ -223,7 +251,11 @@ class Sketch():
                         if type(_r) == str:
                             print(_r)
                             return False
-                        exec(_t,self.container)
+                        try:
+                            exec(_t,self.container)
+                        except Exception as e:
+                            print(f"{_t} error: {str(e)}")
+                            return False
                     else:
                         for _transform in _c["transform"]:
                         #  x_const.rotate(-theta, contact)
@@ -233,7 +265,11 @@ class Sketch():
                             if type(_r) == str:
                                 print(_r)
                                 return False
-                            exec(_t,self.container)
+                            try:
+                                exec(_t,self.container)
+                            except Exception as e:
+                                print(f"{_t} error: {str(e)}")
+                                return False
                 if "action" in _keys:
                     _action = self.normalize(_c["action"])
                     #print(_action)
@@ -241,7 +277,11 @@ class Sketch():
                     if type(_r) == str:
                         print(_r)
                         return False
-                    exec(_action,self.container)
+                    try:
+                        exec(_action,self.container)
+                    except Exception as e:
+                        print(f"{_k}/{_action} error: {str(e)}")
+                        return False
         return True
 
 def point(x, y, check_inside=False):
@@ -286,8 +326,12 @@ def arr2D(x, check_inside=False):
         else:
             raise ValueError('x=%s has length %d, not 2' % (x, len(x)))
     else:
-        raise TypeError('x=%s must be list/tuple/ndarray, not %s' %
-                        (x, type(x)))
+        if isinstance(x, (Point)):
+            x = (x.x,x.y)
+        else:
+            raise TypeError('x=%s must be list/tuple/ndarray, not %s' %
+                            (x, type(x)))
+
     if check_inside:
         ok, msg = drawing_tool.inside(x, exception=True)
         if not ok:
@@ -700,7 +744,6 @@ class Shape(object):
         return self.show_hierarchy(format='dict')
         #return pprint.pformat(self.shapes)
 
-
 class Curve(Shape):
     """General curve as a sequence of (x,y) coordinates."""
     def __init__(self, x, y):
@@ -866,6 +909,18 @@ class Curve(Shape):
     def __repr__(self):
         return str(self)
 
+class Trajectory(Curve):
+    def __init__(self,points):
+        self.x = asarray([p.x for p in points], dtype=float)
+        self.y = asarray([p.y for p in points], dtype=float)
+        self.linestyle = None
+        self.linewidth = None
+        self.linecolor = None
+        self.fillcolor = None
+        self.fillpattern = None
+        self.arrow = None
+        self.shadow = False
+        self.name = None  # name of object that this Curve represents
 
 class Spline(Shape):
     # Note: UnivariateSpline interpolation may not work if
@@ -984,6 +1039,11 @@ class Point(Shape):
             other = Point(other)
         return Point(self.x+other.x, self.y+other.y)
 
+    def __sub__(self, other):
+        if isinstance(other, (list,tuple)):
+            other = Point(other)
+        return Point(self.x-other.x, self.y-other.y)
+
     # class Point is an abstract class - only subclasses are useful
     # and must implement draw
     def draw(self, verbose=0):

+ 17 - 0
test/docs/index.md

@@ -0,0 +1,17 @@
+# Welcome to MkDocs
+
+For full documentation visit [mkdocs.org](https://www.mkdocs.org).
+
+## Commands
+
+* `mkdocs new [dir-name]` - Create a new project.
+* `mkdocs serve` - Start the live-reloading docs server.
+* `mkdocs build` - Build the documentation site.
+* `mkdocs -h` - Print help message and exit.
+
+## Project layout
+
+    mkdocs.yml    # The configuration file.
+    docs/
+        index.md  # The documentation homepage.
+        ...       # Other markdown pages, images and other files.

+ 1 - 0
test/mkdocs.yml

@@ -0,0 +1 @@
+site_name: My Docs