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.
levers.png
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.
lever_fcl1_q.png
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.
lever_fcl1_ans.png
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.

Questions  pdf Questions tex

Answers pdf Answerstex


2.4. Maker files

The python below requires the following .tex files:

The 2 custom python modules required are:
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")