engrharis commited on
Commit
01b44ac
·
verified ·
1 Parent(s): 915db13

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +269 -0
app.py ADDED
@@ -0,0 +1,269 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import numpy as np
3
+ import matplotlib.pyplot as plt
4
+ from matplotlib.patches import Polygon, Circle
5
+
6
+ # Function to calculate the distance between two points
7
+ def calculate_distance(x1, y1, x2, y2):
8
+ return np.sqrt((x2 - x1) * 2 + (y2 - y1) * 2)
9
+
10
+ # Function to calculate angles using the Law of Cosines
11
+ def calculate_angle(a, b, c):
12
+ try:
13
+ angle = np.degrees(np.acos((b * 2 + c * 2 - a ** 2) / (2 * b * c)))
14
+ except ValueError:
15
+ angle = 0 # Handle possible domain error in acos
16
+ return angle
17
+
18
+ # Function to calculate area using Heron's formula
19
+ def calculate_area(a, b, c):
20
+ s = (a + b + c) / 2
21
+ area = np.sqrt(s * (s - a) * (s - b) * (s - c))
22
+ return area
23
+
24
+ # Function to calculate the perimeter
25
+ def calculate_perimeter(a, b, c):
26
+ return a + b + c
27
+
28
+ # Function to calculate the radius of the inscribed circle
29
+ def calculate_radius_inscribed_circle(a, b, c):
30
+ try:
31
+ s = (a + b + c) / 2
32
+ area = calculate_area(a, b, c)
33
+ radius = area / s
34
+ except ZeroDivisionError:
35
+ radius = 0 # Handle case where area or perimeter is zero
36
+ return radius
37
+
38
+ # Function to calculate the radius of the circumscribed circle
39
+ def calculate_radius_circumscribed_circle(a, b, c):
40
+ try:
41
+ area = calculate_area(a, b, c)
42
+ radius = (a * b * c) / (4 * area)
43
+ except ZeroDivisionError:
44
+ radius = 0 # Handle case where area is zero
45
+ return radius
46
+
47
+ # Function to calculate the centroid coordinates
48
+ def calculate_centroid(x1, y1, x2, y2, x3, y3):
49
+ G_x = (x1 + x2 + x3) / 3
50
+ G_y = (y1 + y2 + y3) / 3
51
+ return G_x, G_y
52
+
53
+ # Function to calculate the incenter coordinates
54
+ def calculate_incenter(x1, y1, x2, y2, x3, y3, a, b, c):
55
+ try:
56
+ I_x = (a * x1 + b * x2 + c * x3) / (a + b + c)
57
+ I_y = (a * y1 + b * y2 + c * y3) / (a + b + c)
58
+ except ZeroDivisionError:
59
+ I_x, I_y = 0, 0 # Handle division by zero if sides sum to zero
60
+ return I_x, I_y
61
+
62
+ # Function to calculate the circumcenter coordinates
63
+ def calculate_circumcenter(x1, y1, x2, y2, x3, y3, a, b, c):
64
+ try:
65
+ D = 2 * (x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2))
66
+ U_x = ((x1*2 + y12) * (y2 - y3) + (x22 + y22) * (y3 - y1) + (x32 + y3*2) * (y1 - y2)) / D
67
+ U_y = ((x1*2 + y12) * (x3 - x2) + (x22 + y22) * (x1 - x3) + (x32 + y3*2) * (x2 - x1)) / D
68
+ except ZeroDivisionError:
69
+ U_x, U_y = 0, 0 # Handle division by zero in circumcenter calculation
70
+ return U_x, U_y
71
+
72
+ # Function to calculate midpoints of sides
73
+ def calculate_midpoints(x1, y1, x2, y2, x3, y3):
74
+ # Midpoint of AB
75
+ M1_x = (x1 + x2) / 2
76
+ M1_y = (y1 + y2) / 2
77
+ # Midpoint of BC
78
+ M2_x = (x2 + x3) / 2
79
+ M2_y = (y2 + y3) / 2
80
+ # Midpoint of CA
81
+ M3_x = (x3 + x1) / 2
82
+ M3_y = (y3 + y1) / 2
83
+ return (M1_x, M1_y), (M2_x, M2_y), (M3_x, M3_y)
84
+
85
+ # Function to format values close to zero as 0
86
+ def format_zero(val):
87
+ if abs(val) < 1e-6:
88
+ return 0.0
89
+ return val
90
+
91
+ # Function to plot the triangle with all points in different colors and a legend
92
+ def plot_triangle(x1, y1, x2, y2, x3, y3, I_x, I_y, U_x, U_y, G_x, G_y, midpoints, a, b, c):
93
+ fig, ax = plt.subplots(figsize=(8, 6))
94
+ triangle = Polygon([(x1, y1), (x2, y2), (x3, y3)], closed=True, edgecolor='b', facecolor='lightblue')
95
+ ax.add_patch(triangle)
96
+
97
+ # Define colors for different points
98
+ vertex_color = 'blue'
99
+ midpoint_color = 'green'
100
+ centroid_color = 'orange'
101
+ incenter_color = 'red'
102
+ circumcenter_color = 'purple'
103
+
104
+ # Plot the triangle vertices
105
+ vertices = [(x1, y1), (x2, y2), (x3, y3)]
106
+ vertex_labels = [f"Vertex A ({x1:.3f}, {y1:.3f})", f"Vertex B ({x2:.3f}, {y2:.3f})", f"Vertex C ({x3:.3f}, {y3:.3f})"]
107
+ for i, (vx, vy) in enumerate(vertices):
108
+ ax.scatter(vx, vy, color=vertex_color, zorder=3)
109
+
110
+ # Plot key points with their corresponding colors
111
+ key_points = [
112
+ (I_x, I_y, incenter_color),
113
+ (U_x, U_y, circumcenter_color),
114
+ (G_x, G_y, centroid_color)
115
+ ]
116
+ key_points_labels = [f"Incenter ({I_x:.3f}, {I_y:.3f})", f"Circumcenter ({U_x:.3f}, {U_y:.3f})", f"Centroid ({G_x:.3f}, {G_y:.3f})"]
117
+
118
+ for x, y, color in key_points:
119
+ ax.scatter(x, y, color=color, zorder=4)
120
+
121
+ # Plot midpoints of sides
122
+ for i, (mx, my) in enumerate(midpoints):
123
+ ax.scatter(mx, my, color=midpoint_color, zorder=5)
124
+
125
+ # Draw the inscribed circle (incircle)
126
+ radius_in = calculate_radius_inscribed_circle(a, b, c)
127
+ incircle = Circle((I_x, I_y), radius_in, color=incenter_color, fill=False, linestyle='--', linewidth=2, label="Inscribed Circle")
128
+ ax.add_patch(incircle)
129
+
130
+ # Draw the circumscribed circle (circumcircle)
131
+ radius_circum = calculate_radius_circumscribed_circle(a, b, c)
132
+ circumcircle = Circle((U_x, U_y), radius_circum, color=circumcenter_color, fill=False, linestyle='--', linewidth=2, label="Circumscribed Circle")
133
+ ax.add_patch(circumcircle)
134
+
135
+ # Add legend
136
+ handles = [
137
+ plt.Line2D([0], [0], marker='o', color='w', markerfacecolor=vertex_color, markersize=8, label=vertex_labels[0]),
138
+ plt.Line2D([0], [0], marker='o', color='w', markerfacecolor=vertex_color, markersize=8, label=vertex_labels[1]),
139
+ plt.Line2D([0], [0], marker='o', color='w', markerfacecolor=vertex_color, markersize=8, label=vertex_labels[2]),
140
+ plt.Line2D([0], [0], marker='o', color='w', markerfacecolor=midpoint_color, markersize=8, label=midpoints[0]),
141
+ plt.Line2D([0], [0], marker='o', color='w', markerfacecolor=midpoint_color, markersize=8, label=midpoints[1]),
142
+ plt.Line2D([0], [0], marker='o', color='w', markerfacecolor=midpoint_color, markersize=8, label=midpoints[2]),
143
+ plt.Line2D([0], [0], marker='o', color='w', markerfacecolor=incenter_color, markersize=8, label=key_points_labels[0]),
144
+ plt.Line2D([0], [0], marker='o', color='w', markerfacecolor=circumcenter_color, markersize=8, label=key_points_labels[1]),
145
+ plt.Line2D([0], [0], marker='o', color='w', markerfacecolor=centroid_color, markersize=8, label=key_points_labels[2])
146
+ ]
147
+ ax.legend(handles=handles, loc='upper left', fontsize=12)
148
+
149
+ # Adjust the plot limits and aspect ratio
150
+ padding = 3
151
+ ax.set_xlim([min(x1, x2, x3) - padding, max(x1, x2, x3) + padding])
152
+ ax.set_ylim([min(y1, y2, y3) - padding, max(y1, y2, y3) + padding])
153
+ ax.set_aspect('equal', adjustable='datalim')
154
+
155
+ ax.set_title('Solved Triangle', fontsize=18)
156
+ ax.set_xlabel('X-axis', fontsize=12)
157
+ ax.set_ylabel('Y-axis', fontsize=12)
158
+
159
+ plt.grid(True)
160
+ st.pyplot(fig)
161
+
162
+ # Function to check if the sides form a valid triangle
163
+ def is_valid_triangle(a, b, c):
164
+ # Check if the sum of two sides is greater than the third side (Triangle Inequality Theorem)
165
+ return a + b > c and b + c > a and c + a > b
166
+
167
+ # Main function to interact with the user
168
+ def main():
169
+ st.title("Advanced Triangle Solver")
170
+
171
+ st.sidebar.header("Enter the coordinates of the three points:")
172
+
173
+ # Coordinates input (X1, Y1), (X2, Y2), (X3, Y3)
174
+ x1 = st.sidebar.number_input("X1", min_value=-100.0, max_value=100.0, step=0.1, format="%.3f")
175
+ y1 = st.sidebar.number_input("Y1", min_value=-100.0, max_value=100.0, step=0.1, format="%.3f")
176
+ x2 = st.sidebar.number_input("X2", min_value=-100.0, max_value=100.0, step=0.1, format="%.3f")
177
+ y2 = st.sidebar.number_input("Y2", min_value=-100.0, max_value=100.0, step=0.1, format="%.3f")
178
+ x3 = st.sidebar.number_input("X3", min_value=-100.0, max_value=100.0, step=0.1, format="%.3f")
179
+ y3 = st.sidebar.number_input("Y3", min_value=-100.0, max_value=100.0, step=0.1, format="%.3f")
180
+
181
+ if st.sidebar.button("Calculate"):
182
+ # Calculate the lengths of the sides of the triangle using Euclidean distance
183
+ a = calculate_distance(x2, y2, x3, y3)
184
+ b = calculate_distance(x1, y1, x3, y3)
185
+ c = calculate_distance(x1, y1, x2, y2)
186
+
187
+ # Validate if it's a valid triangle
188
+ if not is_valid_triangle(a, b, c):
189
+ st.error("The entered points do not form a valid triangle.")
190
+ return
191
+
192
+ # Calculate angles using the Law of Cosines
193
+ A = calculate_angle(a, b, c)
194
+ B = calculate_angle(b, a, c)
195
+ C = calculate_angle(c, a, b)
196
+
197
+ # Check if angles sum up to 180 degrees
198
+ if abs(A + B + C - 180) > 1e-2:
199
+ st.error("The sum of the angles is not 180 degrees.")
200
+ return
201
+
202
+ # Calculate area, perimeter, and radius of inscribed and circumscribed circles
203
+ area = calculate_area(a, b, c)
204
+ perimeter = calculate_perimeter(a, b, c)
205
+ radius_in = calculate_radius_inscribed_circle(a, b, c)
206
+ radius_circum = calculate_radius_circumscribed_circle(a, b, c)
207
+
208
+ # Calculate centroid, incenter, and circumcenter coordinates
209
+ G_x, G_y = calculate_centroid(x1, y1, x2, y2, x3, y3)
210
+ I_x, I_y = calculate_incenter(x1, y1, x2, y2, x3, y3, a, b, c)
211
+ U_x, U_y = calculate_circumcenter(x1, y1, x2, y2, x3, y3, a, b, c)
212
+
213
+ # Calculate midpoints of the sides
214
+ midpoints = calculate_midpoints(x1, y1, x2, y2, x3, y3)
215
+
216
+ # Display results in columns
217
+ col1, col2 = st.columns(2)
218
+
219
+ with col1:
220
+ st.subheader("Coordinates of Triangle:")
221
+ st.markdown(f"Vertex A: *({x1:.3f}, {y1:.3f})*")
222
+ st.markdown(f"Vertex B: *({x2:.3f}, {y2:.3f})*")
223
+ st.markdown(f"Vertex C: *({x3:.3f}, {y3:.3f})*")
224
+
225
+ with col2:
226
+ st.subheader("Mid-Points of Triangle:")
227
+ st.markdown(f"Midpoint of AB: ({midpoints[0][0]:.3f}, {midpoints[0][1]:.3f})")
228
+ st.markdown(f"Midpoint of BC: ({midpoints[1][0]:.3f}, {midpoints[1][1]:.3f})")
229
+ st.markdown(f"Midpoint of CA: ({midpoints[2][0]:.3f}, {midpoints[2][1]:.3f})")
230
+
231
+
232
+ col1, col2 = st.columns(2)
233
+
234
+ with col1:
235
+ st.subheader("Angles of Triangle:")
236
+ st.markdown(f"Angle A: *{format_zero(A):.3f}°*")
237
+ st.markdown(f"Angle B: *{format_zero(B):.3f}°*")
238
+ st.markdown(f"Angle C: *{format_zero(C):.3f}°*")
239
+
240
+ with col2:
241
+ st.subheader("Sides of Triangle:")
242
+ st.markdown(f"Side a: *{format_zero(a):.3f}* units")
243
+ st.markdown(f"Side b: *{format_zero(b):.3f}* units")
244
+ st.markdown(f"Side c: *{format_zero(c):.3f}* units")
245
+
246
+
247
+ col1, col2, col3 = st.columns(3)
248
+
249
+ with col1:
250
+ st.subheader("Incenter of Triangle:")
251
+ st.markdown(f"Coordinates: *({format_zero(I_x):.3f}, {format_zero(I_y):.3f})*")
252
+ st.markdown(f"Radius: *{radius_in:.3f}* units")
253
+
254
+ with col2:
255
+ st.subheader("Circumcenter of Triangle:")
256
+ st.markdown(f"Coordinates: *({format_zero(U_x):.3f}, {format_zero(U_y):.3f})*")
257
+ st.markdown(f"Radius: *{radius_circum:.3f}* units")
258
+
259
+ with col3:
260
+ st.subheader("Other Properties:")
261
+ st.markdown(f"Area: *{format_zero(area):.3f}* square units")
262
+ st.markdown(f"Perimeter: *{format_zero(perimeter):.3f}* units")
263
+ st.markdown(f"Centroid: *({format_zero(G_x):.3f}, {format_zero(G_y):.3f})*")
264
+
265
+ # Display triangle graph with midpoints and colored points
266
+ plot_triangle(x1, y1, x2, y2, x3, y3, I_x, I_y, U_x, U_y, G_x, G_y, midpoints, a, b, c)
267
+
268
+ if _name_ == "_main_":
269
+ main()