Pysketcher initial version [HPL Pysketcher]() enable sketch definition in python. HPL is showing the hierachical nature of sketches. This is implemented via the Composition function. One can further grasp this using the graphviz_dot function applied to discover the composition herarchy implemented as a graphviz image see The hierarchy of the "friction" sketch at the end of this page.
Due to the hierarchical nature of sketches, it is quite straightforward to think about using yaml as the syntax for defining a sketch.
Benefits are the following:
This example provides the yaml content to define the Dry Friction case
An inclined plan (the A-B edge) supports a blue rectangle which is dragged down by gravity. The plan makes an angle $\theta$ with the ground level. Sketch implementation notebook includes a controller enabling the $\theta$ angle to change. The whole plan, including the body, can rotate arround point B.
The example we are developing now is based upon the "Dry Friction mockup" notebook
Sketcher language is defined as a yaml compliant file or string. The yaml file is a dictionnary of "objects". Objects can be regular python objects or sketcher objects. A skertcher object is composed as follow:
As a general rule, a new object suppose all parameters to be defined before they are used to construct it.
For example, you can create a circle if the center and the radius have been defined earlier in the file.
The general layout of a sketcher file is as follow:
libraries = """\
name: head
shapes:
libraries: ["from math import tan, radians, sin, cos","from pysketcher import *"]
"""
constants = """\
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
"""
frame = """\
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
"""
body = """\
name: body
shapes:
rectangle:
formula: Rectangle(contact, rl, rL)
style:
linecolor: blue
filled_curves: 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
"""
plan = """\
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})"
"""
friction = """\
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})"
"""
To parse the above example, the following code do the job.
The parser checks for syntax precedence and warns of any detected error.
myfig = {}
if sketchParse(libraries,myfig):
if sketchParse(constants,myfig):
if sketchParse(frame,myfig):
if sketchParse(body,myfig):
if sketchParse(plan,myfig):
if sketchParse(friction,myfig):
print("success")