├── .gitignore ├── screenshots ├── gui.png ├── gui_bend_points.png └── gui_common_points.png ├── setup.py ├── get_common_points.py ├── README.md ├── get_locus.py └── Auto_Locus.py /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | *.xml 3 | *.iml 4 | .idea/$CACHE_FILE$ 5 | *.pyc 6 | -------------------------------------------------------------------------------- /screenshots/gui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gobidev/auto-locus/master/screenshots/gui.png -------------------------------------------------------------------------------- /screenshots/gui_bend_points.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gobidev/auto-locus/master/screenshots/gui_bend_points.png -------------------------------------------------------------------------------- /screenshots/gui_common_points.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gobidev/auto-locus/master/screenshots/gui_common_points.png -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from cx_Freeze import setup, Executable 2 | 3 | setup( 4 | name="Auto Locus", 5 | version="1.0", 6 | description="Auto locus is a small programm that automatically determines the locus of a given funciton.", 7 | executables=[Executable(script="Auto_Locus.py", base="Win32GUI")] 8 | ) 9 | -------------------------------------------------------------------------------- /get_common_points.py: -------------------------------------------------------------------------------- 1 | from sympy import * 2 | x = Symbol("x") 3 | a = Symbol("a") 4 | b = Symbol("b") 5 | 6 | 7 | def f_x(x, p_function): 8 | return eval(p_function) 9 | 10 | 11 | def get_common_points(p_function): 12 | function_a = p_function 13 | function_b = p_function.replace("a", "b") 14 | common_x_values = solve(eval(function_a) - eval(function_b), x) 15 | results = [] 16 | for value in common_x_values: 17 | results.append((value, f_x(value, p_function))) 18 | return results 19 | 20 | 21 | if __name__ == '__main__': 22 | f_function = input("Function:\n") 23 | print("common points:", get_common_points(f_function)) 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # auto-locus 2 | Auto locus is a small programm that automatically determines the locus of a given funciton. 3 | 4 | ## Installation (Windows) 5 | 6 | 1. Download the latest release from [release tab](https://github.com/Gobidev/auto-locus/releases). 7 | 2. Unzip the file. 8 | 3. Run _Auto_Locus.exe_ 9 | 10 | ## Installation (Mac/Linux) 11 | 12 | 1. Make sure you have Python 3.5 or higher installed. 13 | 2. Install [sympy](https://pypi.org/project/sympy/). 14 | 3. [Clone the repository](https://github.com/Gobidev/auto-locus/archive/master.zip). 15 | 4. Run _Auto_Locus.py_ 16 | 17 | ## Installation (Android) 18 | 19 | 1. Download [Pydroid 3](https://play.google.com/store/apps/details?id=ru.iiec.pydroid3) from the Google Play Store. 20 | 2. Open the app, expand the menu and navigate to Pip. 21 | 3. Type **sympy** and click install. 22 | 4. [Clone the repository](https://github.com/Gobidev/auto-locus/archive/master.zip), unzip it and move it to your phone. 23 | 5. Open _Auto_Locus.py_ in Pydroid 3. 24 | 6. Run the program. 25 | 26 | ## How to Use 27 | 28 | ![alt text](https://github.com/Gobidev/auto-locus/blob/master/screenshots/gui.png?raw=true) 29 | 30 | - Insert a function f(x) with the parameter a: 31 |
32 |     Translations:
33 |     Squareroot = sqrt()
34 |     x^2 = x^2
35 |     a*x = ax
36 |     3a = 3*a
37 |     
38 |     Examples:
39 |     1. x^2+ax+2
40 |     2. x^2-6*x+11+ax-3*a
41 |     
42 |     Make sure to add a '*' after coefficients!
43 |     Exponential functions can not be processed.
44 | 
45 | - Select if you want the locus for the bend points or the turning points 46 | - Click either on _Calculate Locus_ or on _Calculate Common Points_. 47 | 48 | ### Examples 49 | ![alt text](https://github.com/Gobidev/auto-locus/blob/master/screenshots/gui_bend_points.png?raw=true) 50 | ![alt text](https://github.com/Gobidev/auto-locus/blob/master/screenshots/gui_common_points.png?raw=true) -------------------------------------------------------------------------------- /get_locus.py: -------------------------------------------------------------------------------- 1 | from sympy import * 2 | 3 | x = Symbol("x") 4 | a = Symbol("a") 5 | 6 | 7 | def get_first_derivative(p_function): 8 | x = Symbol("x") 9 | return diff(p_function, x) 10 | 11 | 12 | def get_second_derivative(p_function): 13 | x = Symbol("x") 14 | return diff(p_function, x, x) 15 | 16 | 17 | def f_x(x, p_function): 18 | return eval(p_function) 19 | 20 | 21 | def g_x(x, p_function): 22 | return eval(p_function) 23 | 24 | 25 | def g_a(a, p_function): 26 | return eval(p_function) 27 | 28 | 29 | def convert_function_to_python(old_function): 30 | new_function = old_function.replace("^", "**").replace("ax", "a*x").replace("xa", "x*a") 31 | return new_function 32 | 33 | 34 | def convert_function_from_python(old_function): 35 | old_function = str(old_function) 36 | new_function = old_function.replace("**", "^").replace("a*x", "ax").replace("x*a", "xa") 37 | new_function = new_function.replace(" ", "") 38 | return new_function 39 | 40 | 41 | def get_bend_points(p_function): 42 | first_derivative = get_first_derivative(p_function) 43 | x_value = solve(first_derivative, x) 44 | y_value = [] 45 | for value in x_value: 46 | y_value.append(f_x(value, p_function)) 47 | results = [] 48 | for value in x_value: 49 | results.append((value, y_value[x_value.index(value)])) 50 | return results 51 | 52 | 53 | def get_turning_points(p_function): 54 | second_derivative = get_second_derivative(p_function) 55 | x_value = solve(second_derivative, x) 56 | y_value = [] 57 | for value in x_value: 58 | y_value.append(f_x(value, p_function)) 59 | results = [] 60 | for value in x_value: 61 | results.append((value, y_value[x_value.index(value)])) 62 | return results 63 | 64 | 65 | def get_x_param(x_value): 66 | try: 67 | return solve(x_value-x, a)[0] 68 | except: 69 | return [] 70 | 71 | 72 | def insert_into_y_value(x_param, y_value): 73 | g_function = str(y_value) 74 | return g_a(x_param, g_function) 75 | 76 | 77 | if __name__ == '__main__': 78 | f_function = input("Function:\n") 79 | if int(input("1=bend points (Extrempunkte), 2=turning points (Wendepunkte)\n")) == 1: 80 | bend_points = get_bend_points(f_function) 81 | print("bend_points:", bend_points) 82 | x_p = get_x_param(bend_points[0][0]) 83 | print("x_param:", x_p) 84 | print("g(x)=" + str(insert_into_y_value(x_p, bend_points[0][1]))) 85 | else: 86 | turning_points = get_turning_points(f_function) 87 | print("turning_points:", turning_points) 88 | x_p = get_x_param(turning_points[0][0]) 89 | print("x_param:", x_p) 90 | print("g(x)=" + str(insert_into_y_value(x_p, turning_points[0][1]))) 91 | -------------------------------------------------------------------------------- /Auto_Locus.py: -------------------------------------------------------------------------------- 1 | import get_locus, get_common_points 2 | import tkinter as tk 3 | from tkinter import ttk 4 | 5 | root = tk.Tk() 6 | 7 | root.title("Auto Locus") 8 | root.resizable(False, False) 9 | 10 | 11 | def calculate_locus_button_click(): 12 | input_function = input_entry.get() 13 | input_function = get_locus.convert_function_to_python(input_function) 14 | x_param = None 15 | points = None 16 | 17 | # check if function is empty 18 | if input_function == "": 19 | locus_output_label.config(text="Missing Parameter") 20 | return False 21 | kind_of_points = points_combobox.get() 22 | 23 | # check if combobox is empty 24 | if kind_of_points == "": 25 | locus_output_label.config(text="Missing Parameter") 26 | return False 27 | elif kind_of_points == "Bend Points": 28 | try: 29 | # calculate bend points 30 | points = get_locus.get_bend_points(input_function) 31 | print("bend_points:", points) 32 | except: 33 | locus_output_label.config(text="Invalid Input") 34 | return False 35 | 36 | if not points: 37 | locus_output_label.config(text="No bendpoints found") 38 | return False 39 | 40 | elif kind_of_points == "Turning Points": 41 | try: 42 | # calculate turning points 43 | points = get_locus.get_turning_points(input_function) 44 | print("turning_points:", points) 45 | except: 46 | locus_output_label.config(text="Invalid Input") 47 | return False 48 | 49 | if not points: 50 | locus_output_label.config(text="No turning points found") 51 | return False 52 | 53 | # calculating x_param 54 | x_param = get_locus.get_x_param(points[0][0]) 55 | print("x_param:", x_param) 56 | 57 | if not x_param: 58 | locus_output_label.config(text="No locus found") 59 | return False 60 | try: 61 | output_function = get_locus.insert_into_y_value(x_param, points[0][1]) 62 | print("output_function:", output_function) 63 | except: 64 | locus_output_label.config(text="No locus found") 65 | return False 66 | 67 | # reconverting function 68 | output_function = get_locus.convert_function_from_python(output_function) 69 | locus_output_label.config(text="g(x)=" + output_function) 70 | 71 | 72 | def calculate_common_points_button_click(): 73 | input_function = input_entry.get() 74 | input_function = get_locus.convert_function_to_python(input_function) 75 | 76 | # check if function is empty 77 | if input_function == "": 78 | common_points_label.config(text="Missing Parameter") 79 | return False 80 | 81 | try: 82 | # get common points 83 | common_points = get_common_points.get_common_points(input_function) 84 | print("common_points:", common_points) 85 | except: 86 | common_points_label.config(text="Invalid Input") 87 | return False 88 | 89 | if not common_points: 90 | common_points_label.config(text="No common points found") 91 | return False 92 | 93 | output_string = "" 94 | for n in common_points: 95 | output_string += str(n) 96 | if common_points.index(n) > 0: 97 | output_string += ", " 98 | 99 | common_points_label.config(text=output_string) 100 | 101 | 102 | # Row 0 103 | input_label = ttk.Label(root, text="Input Function:") 104 | input_label.grid(row=0, column=0, padx=5, pady=5, sticky="w") 105 | 106 | input_entry = ttk.Entry(root) 107 | input_entry.grid(row=0, column=1, padx=5, pady=5, sticky="e") 108 | 109 | # Row 1 110 | points_label = ttk.Label(root, text="Points:") 111 | points_label.grid(row=1, column=0, padx=5, pady=5, sticky="w") 112 | 113 | points_combobox = ttk.Combobox(root, values=["Bend Points", "Turning Points"], state="readonly") 114 | points_combobox.grid(row=1, column=1, padx=5, pady=5, sticky="e") 115 | 116 | # Row 2 117 | run_button = ttk.Button(root, text="Calculate Locus", command=calculate_locus_button_click) 118 | run_button.grid(row=2, column=0, padx=5, pady=5, sticky="w") 119 | 120 | run_button_2 = ttk.Button(root, text="Calculate Common Points", command=calculate_common_points_button_click) 121 | run_button_2.grid(row=2, column=1, padx=5, pady=5, sticky="w") 122 | 123 | # Row 3 124 | space_label = ttk.Label(root) 125 | space_label.grid(row=3, column=0, pady=4, sticky="w") 126 | 127 | # Row 4 128 | locus_output_label_name = ttk.Label(root, text="Locus:") 129 | locus_output_label_name.grid(row=4, column=0, padx=5, pady=5, sticky="w") 130 | 131 | locus_output_label = ttk.Label(root, borderwidth=2, relief="groove") 132 | locus_output_label.grid(row=4, column=1, padx=5, pady=5, sticky="we") 133 | 134 | # Row 5 135 | common_points_label_name = ttk.Label(root, text="Common Points:") 136 | common_points_label_name.grid(row=5, column=0, padx=5, pady=5, sticky="w") 137 | 138 | common_points_label = ttk.Label(root, borderwidth=2, relief="groove") 139 | common_points_label.grid(row=5, column=1, padx=5, pady=5, sticky="we") 140 | 141 | 142 | root.mainloop() 143 | --------------------------------------------------------------------------------