2. Levers tikzο
Diagrams of levers can be built using tikz.
2.1. First Class levers mechanical advantageο
A First Class lever diagram is shown below.
The LaTeX:
1\documentclass[12pt, varwidth, border={20mm 5mm 5mm 20mm}]{standalone}
2\usepackage{tikz}
3\usepackage{amsmath}
4\usepackage[a4paper, portrait, margin=1cm]{geometry}
5\begin{document}
6\section*{First Class Lever mechanical advantage}
7\begin{minipage}{0.5\textwidth}
8 \begin{tikzpicture}[scale=0.7,>=stealth]
9 % First class lever
10 % rod
11 \draw[fill=gray!20] (-0.25,0) rectangle (6,0.1);
12 %fulcrum
13 \draw[fill=black] (0.8,-0.5) -- (1.2,-0.5) node[right] {fulcrum} -- (1.0,0) -- cycle;
14 %load
15 \draw[fill=red] (-0.25,0.1) rectangle (0.25,0.6);
16 \draw[->,thick] (0.0,0.35) -- (0.0,-2.15) node[midway,left,yshift=-0.5cm,align=center] {Load \\\\[-3ex] $F_L = 10N$};
17 %effort
18 \draw[->,thick] (6,0.0) -- (6,-0.5) node[midway,right,align=center] {Effort \\\\[-3ex] $F_E = 2N$};
19
20 % Distance markers
21 \draw[<->] (1,-3.0) -- (6,-3.0) node[midway,below,align=center] {$d_E= 50cm$};
22 \draw[<->] (0,-3.1) -- (1.0,-3.1) node[midway,below,xshift=-0.5cm,align=left] {$d_L = 10cm$};
23 \end{tikzpicture}
24\end{minipage}%
25\hfill
26\begin{minipage}{0.3\textwidth}
27 \begin{align*}
28 % ma
29 m.a.&=\frac{F_L}{F_E}=\frac{10N}{2N}=5 \\\\
30 m.a.&=\frac{d_E}{d_L}=\frac{50cm}{10cm}=5
31 \end{align*}
32\end{minipage}
33\end{document}
2.2. First Class levers Fd=Fdο
A question diagram of a First Class lever is shown below with an incomplete force distance calculation.
The LaTeX:
1\documentclass[12pt, varwidth, border=5mm]{standalone}
2\usepackage{tikz}
3\usepackage{amsmath}
4% Underlining package
5\usepackage{ulem}
6% \usepackage[a4paper, portrait, margin=1cm]{geometry}
7\begin{document}
8\section*{First Class Levers}
9 \begin{minipage}{0.65\textwidth}
10 \begin{tikzpicture}[scale=0.7,>=stealth]
11 % First class lever
12 % rod
13 \draw[fill=gray!20] (-0.25,0) rectangle (6,0.1);
14 %fulcrum
15 \draw[fill=black] (0.8,-0.5) -- (1.2,-0.5) node[below,xshift=2mm] {fulcrum} -- (1.0,0) -- cycle;
16 %load
17 \draw[fill=red] (-0.25,0.1) rectangle (0.25,0.6);
18 \draw[->,thick] (0.0,0.35) -- (0.0,-2.15) node[midway,left,yshift=-0.5cm,align=center] {Load \\\\[-3ex] $F_L = 10N$};
19 %effort
20 \draw[->,thick] (6,0.0) -- (6,-0.5) node[midway,right,align=center] {Effort \\\\[-3ex] $F_E = \dotuline{~~~~~~~}N$};
21
22 % Distance markers
23 \draw[<->] (1.0,-2.5) -- (6,-2.5) node[midway,below,align=center] {$d_E = 50.0cm$};
24 \draw[<->] (0,-2.6) -- (1.0,-2.6) node[midway,below,xshift=-0.5cm,align=left] {$d_L = 10.0cm$};
25 \end{tikzpicture}
26\end{minipage}%
27\hfill
28\begin{minipage}{0.3\textwidth}
29 \begin{align*}
30 F_E \times d_E &= F_L \times d_L \\
31 F_E &= \frac{F_L \times d_L}{d_E} \\
32 F_E &= \frac{\dotuline{~~~~~~~} \times \dotuline{~~~~~~~}}{\dotuline{~~~~~~~}} \\
33 F_E &= \dotuline{~~~~~~~}N
34 \end{align*}
35\end{minipage}
36\end{document}
An answer diagram of a First Class lever is shown below with a completed force distance calculation.
The LaTeX:
1\documentclass[12pt, varwidth, border=5mm]{standalone}
2\usepackage{tikz}
3\usepackage{amsmath}
4% Underlining package
5\usepackage{ulem}
6% \usepackage[a4paper, portrait, margin=1cm]{geometry}
7\begin{document}
8\section*{First Class Levers}
9 \begin{minipage}{0.65\textwidth}
10 \begin{tikzpicture}[scale=0.7,>=stealth]
11 % First class lever
12 % rod
13 \draw[fill=gray!20] (-0.25,0) rectangle (6,0.1);
14 %fulcrum
15 \draw[fill=black] (0.8,-0.5) -- (1.2,-0.5) node[below,xshift=2mm] {fulcrum} -- (1.0,0) -- cycle;
16 %load
17 \draw[fill=red] (-0.25,0.1) rectangle (0.25,0.6);
18 \draw[->,thick] (0.0,0.35) -- (0.0,-2.15) node[midway,left,yshift=-0.5cm,align=center] {Load \\\\[-3ex] $F_L = 10.0N$};
19 %effort
20 \draw[->,thick] (6,0.0) -- (6,-0.5) node[midway,right,align=center] {Effort \\\\[-3ex] $F_E = 2.0N$};
21
22 % Distance markers
23 \draw[<->] (1.0,-2.5) -- (6,-2.5) node[midway,below,align=center] {$d_E = 50.0cm$};
24 \draw[<->] (0,-2.6) -- (1.0,-2.6) node[midway,below,xshift=-0.5cm,align=left] {$d_L = 10.0cm$};
25 \end{tikzpicture}
26\end{minipage}%
27\hfill
28\begin{minipage}{0.3\textwidth}
29 \begin{align*}
30 F_E \times d_E &= F_L \times d_L \\
31 F_E &= \frac{F_L \times d_L}{d_E} \\
32 F_E &= \frac{10.0 \times 10.0}{50.0} \\
33 F_E &= 2.0N
34 \end{align*}
35\end{minipage}
36\end{document}
2.3. Booklet: First Class levers Fd=Fdο
A booklet of random first class levers can be created.
2.4. Maker filesο
The python below requires the following .tex files:
The Python code that creates a booklet of 5 lever diagrams and calculations per page is:
The python file, lever_booklet_diagram_maker.py, when run, will ask for these inputs:
Choose the lever class:
"Enter 1, 2, 3 or 4 for 1st, 2nd, 3rd class levers or random ".Choose the numnber of questions:
"- Choose the numnber of questions: "Choose the file name base:
"Enter the base filename to be added to the prefix lever_Bk_:".The filename will have β_qβ added for the question booklet and β_ansβ for the answer booklet.
1from pathlib import Path
2import subprocess
3import os
4import time
5# import magick_pdf_to_png
6import lever_functions as levf
7
8currfile_dir = Path(__file__).parent
9tex_template_path = currfile_dir / "lever_booklet_template.tex"
10texans_template_path = currfile_dir / "lever_booklet_ans_template.tex"
11tex_diagram_template_path = currfile_dir / "lever_booklet_diagram_template.tex"
12
13
14def convert_to_pdf(tex_path, outputdir):
15 tex_path = Path(tex_path).resolve()
16 outputdir = Path(outputdir).resolve()
17 # for testing
18 # print(f"tex_path: {tex_path}")
19 # print(f"outputdir: {outputdir}")
20 try:
21 # Generate the PDF
22 subprocess.run(["latexmk", "-pdf", "-outdir=" + str(outputdir), str(tex_path)], check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
23 # # Clean auxiliary files after successful PDF generation
24 subprocess.run(["latexmk", "-c", "-outdir=" + str(outputdir), str(tex_path)], check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
25 # for hosted remove stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL for debugging any errors
26 # Remove the .tex file manually
27 if tex_path.exists():
28 os.remove(tex_path)
29 except subprocess.CalledProcessError as e:
30 print(f"Error: {e}")
31
32
33# % end modify values for lever
34# tex_keys = ['ans_force_l','ans_force_e','ans_dist_l', 'ans_dist_e', 'effort_vector','fulc_c', 'fulc_l', 'fulc_r' ]
35tex_keys_q = ["force_l", "force_e", "dist_l", "dist_e", 'effort_vector','fulc_c', 'fulc_l', 'fulc_r']
36
37
38def make1_diagram(tex_diagram_template_txt, num1,):
39 tex_diagram_template_txt_ans = tex_diagram_template_txt
40 kv = levf.get_lever_dict(num1)
41 for key, value in kv.items():
42 tex_diagram_template_txt_ans = tex_diagram_template_txt_ans.replace(
43 "<<" + key + ">>", value
44 )
45 for key, value in kv.items():
46 if key in tex_keys_q:
47 tex_diagram_template_txt = tex_diagram_template_txt.replace(
48 "<<" + key + ">>", value
49 )
50 else:
51 tex_diagram_template_txt = tex_diagram_template_txt.replace(
52 "<<" + key + ">>", "\\dotuline{~~~~~~~}" # non breaking spaces for gaps
53 )
54 return tex_diagram_template_txt, tex_diagram_template_txt_ans
55
56
57def main():
58 num1 = input("Enter 1, 2, 3 or 4 for 1st, 2nd, 3rd class levers or random \n")
59 if num1.strip().isdigit():
60 num1 = int(num1)
61 if num1 not in [1, 2, 3, 4]:
62 num1 = 4 # random by default
63 else:
64 num1 = 4 # random by default
65 #
66 numq = input("Enter the number of questions from 1 to 20 \n")
67 if numq.strip().isdigit():
68 numq = int(numq)
69 if not numq in range(1,21):
70 numq = 6 # random by default
71 else:
72 numq = 6 # random by default
73 #
74 filename = input("Enter the base filename to be added to the prefix lever_Bk_: \n")
75 if not filename:
76 filename = "1" # "lever_Bk_1_q and lever_Bk_1_ans as default file"
77 # set names of files that are made
78 # questions
79 tex_output_path = currfile_dir / f"lever_Bk_{filename}_q.tex"
80 pdf_path = currfile_dir / f"lever_Bk_{filename}_q.pdf"
81
82 # answers
83 tex_output_path_ans = currfile_dir / f"lever_Bk_{filename}_ans.tex"
84 pdf_path_ans = currfile_dir / f"lever_Bk_{filename}_ans.pdf"
85
86 # Read in the LaTeX template file
87 with open(tex_template_path, "r") as infile:
88 tex_template_txt = infile.read()
89 # Read in the LaTeX template file for answers
90 with open(texans_template_path, "r") as infile:
91 tex_template_txt_ans = infile.read()
92 # Read in the LaTeX diagram template file
93 with open(tex_diagram_template_path, "r") as infile:
94 tex_diagram_template_txt = infile.read()
95
96 # Generate the <<diagram>> replacement tex
97 # diagram_text, diagram_text_ans = make1_diagram(tex_diagram_template_txt, num1)
98
99 # <<diagrams>>
100 # generate diagrams text and text for answers
101 diagrams_text = ""
102 diagrams_text_ans = ""
103 # add the headtext
104 headtext = r"\pagebreak ~ \newline ~ \newline"
105 for i in range(1, numq + 1):
106 img_tex, img_tex_ans = make1_diagram(tex_diagram_template_txt, num1)
107 if i > 5 and i % 5 == 1:
108 diagrams_text += headtext
109 diagrams_text_ans += headtext
110 diagrams_text += img_tex
111 diagrams_text_ans += img_tex_ans
112
113 # Replace the <<diagrams>> placeholder in the LaTeX template
114 tex_template_txt = tex_template_txt.replace("<<diagrams>>", diagrams_text)
115 tex_template_txt_ans = tex_template_txt_ans.replace("<<diagrams>>", diagrams_text_ans)
116 # Write the question diagrams tex to an output file
117 with open(tex_output_path, "w") as outfile:
118 outfile.write(tex_template_txt)
119 # Write the answer diagrams tex to an output file
120 with open(tex_output_path_ans, "w") as outfile:
121 outfile.write(tex_template_txt_ans)
122
123 # Wait for the files to be created
124 time.sleep(1)
125 # convert to pdf
126 convert_to_pdf(tex_output_path, currfile_dir)
127 convert_to_pdf(tex_output_path_ans, currfile_dir)
128
129 # Wait for the files to be created
130 # time.sleep(1)
131 # convert to png
132 # magick_pdf_to_png.convert_pdf_to_png(pdf_path, png_path)
133 # magick_pdf_to_png.convert_pdf_to_png(pdf_path_ans, png_path_ans)
134
135
136if __name__ == "__main__":
137 print("starting")
138 main()
139 print("finished")