engrharis commited on
Commit
c8bc3b1
·
verified ·
1 Parent(s): 14e92cc

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +205 -97
app.py CHANGED
@@ -10,114 +10,222 @@ def calculate_distance(x1, y1, x2, y2):
10
  # Function to calculate angles using the Law of Cosines
11
  def calculate_angle(a, b, c):
12
  try:
13
- angle = np.degrees(np.arccos((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 the area of a triangle using Heron's formula
19
  def calculate_area(a, b, c):
20
  s = (a + b + c) / 2
21
- return np.sqrt(s * (s - a) * (s - b) * (s - c))
 
22
 
23
- # Function to calculate the perimeter of the triangle
24
  def calculate_perimeter(a, b, c):
25
  return a + b + c
26
 
27
- # Main function to run the app
28
- def main():
29
- st.set_page_config(
30
- page_title="Advanced Triangle Solver",
31
- layout="wide",
32
- initial_sidebar_state="expanded",
33
- )
34
-
35
- st.markdown(
36
- """
37
- <style>
38
- body {
39
- background-color: #f7f9fc;
40
- color: #333333;
41
- font-family: 'Open Sans', sans-serif;
42
- }
43
- .stTitle, .stHeader, .stSubheader {
44
- color: #1a73e8;
45
- font-weight: bold;
46
- }
47
- .stSidebar {
48
- background-color: #f0f4f8;
49
- color: #333333;
50
- }
51
- .stMarkdown {
52
- font-size: 16px;
53
- }
54
- .stButton > button {
55
- background-color: #1a73e8;
56
- color: white;
57
- border: none;
58
- border-radius: 5px;
59
- padding: 10px 20px;
60
- font-size: 16px;
61
- cursor: pointer;
62
- }
63
- .stButton > button:hover {
64
- background-color: #155ab3;
65
- }
66
- </style>
67
- """,
68
- unsafe_allow_html=True,
69
- )
70
-
71
- st.title("🔺 Advanced Triangle Solver")
72
- st.sidebar.header("📌 Input Coordinates")
73
-
74
- # Collect user input
75
- x1 = st.sidebar.number_input("X1", min_value=-100.0, max_value=100.0, step=0.1, format="%.2f")
76
- y1 = st.sidebar.number_input("Y1", min_value=-100.0, max_value=100.0, step=0.1, format="%.2f")
77
- x2 = st.sidebar.number_input("X2", min_value=-100.0, max_value=100.0, step=0.1, format="%.2f")
78
- y2 = st.sidebar.number_input("Y2", min_value=-100.0, max_value=100.0, step=0.1, format="%.2f")
79
- x3 = st.sidebar.number_input("X3", min_value=-100.0, max_value=100.0, step=0.1, format="%.2f")
80
- y3 = st.sidebar.number_input("Y3", min_value=-100.0, max_value=100.0, step=0.1, format="%.2f")
81
-
82
- if st.sidebar.button("Calculate 🔍"):
83
- # Calculate distances
84
- a = calculate_distance(x2, y2, x3, y3)
85
- b = calculate_distance(x1, y1, x3, y3)
86
- c = calculate_distance(x1, y1, x2, y2)
87
-
88
- # Calculate angles
89
- angle_A = calculate_angle(b, a, c)
90
- angle_B = calculate_angle(c, a, b)
91
- angle_C = calculate_angle(a, b, c)
92
-
93
- # Calculate area and perimeter
94
  area = calculate_area(a, b, c)
95
- perimeter = calculate_perimeter(a, b, c)
96
-
97
- # Display results
98
- st.subheader("📐 Triangle Properties")
99
- st.write(f"**Side a (between points (x2, y2) and (x3, y3)): {a:.2f} units**")
100
- st.write(f"**Side b (between points (x1, y1) and (x3, y3)): {b:.2f} units**")
101
- st.write(f"**Side c (between points (x1, y1) and (x2, y2)): {c:.2f} units**")
102
- st.write(f"**Angle A (at point (x1, y1)): {angle_A:.2f}°**")
103
- st.write(f"**Angle B (at point (x2, y2)): {angle_B:.2f}°**")
104
- st.write(f"**Angle C (at point (x3, y3)): {angle_C:.2f}°**")
105
- st.write(f"**Area of the Triangle: {area:.2f} square units**")
106
- st.write(f"**Perimeter of the Triangle: {perimeter:.2f} units**")
107
-
108
- # Plot the triangle
109
- fig, ax = plt.subplots()
110
- triangle = Polygon([(x1, y1), (x2, y2), (x3, y3)], closed=True, fill=None, edgecolor='r')
111
- ax.add_patch(triangle)
112
- ax.text(x1, y1, f'({x1}, {y1})', fontsize=12, ha='right')
113
- ax.text(x2, y2, f'({x2}, {y2})', fontsize=12, ha='right')
114
- ax.text(x3, y3, f'({x3}, {y3})', fontsize=12, ha='right')
115
-
116
- ax.set_xlim(min(x1, x2, x3) - 5, max(x1, x2, x3) + 5)
117
- ax.set_ylim(min(y1, y2, y3) - 5, max(y1, y2, y3) + 5)
118
- ax.set_aspect('equal', adjustable='box')
119
- ax.set_title("Triangle Visualization")
120
- st.pyplot(fig)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121
 
122
  if __name__ == "__main__":
123
  main()
 
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 + y1**2) * (y2 - y3) + (x2**2 + y2**2) * (y3 - y1) + (x3**2 + y3**2) * (y1 - y2)) / D
67
+ U_y = ((x1**2 + y1**2) * (x3 - x2) + (x2**2 + y2**2) * (x1 - x3) + (x3**2 + 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
+ midpoints_labels = [f"Mid-Point M1 ({(x1 + x2) / 2:.3f}, {(y1 + y2) / 2:.3f})",
125
+ f"Mid-Point M2 ({(x2 + x3) / 2:.3f}, {(y2 + y3) / 2:.3f})",
126
+ f"Mid-Point M3 ({(x1 + x3) / 2:.3f}, {(y1 + y3) / 2:.3f})"]
127
+
128
+ # Draw the inscribed circle (incircle)
129
+ radius_in = calculate_radius_inscribed_circle(a, b, c)
130
+ incircle = Circle((I_x, I_y), radius_in, color=incenter_color, fill=False, linestyle='--', linewidth=2, label="Inscribed Circle")
131
+ ax.add_patch(incircle)
132
+
133
+ # Draw the circumscribed circle (circumcircle)
134
+ radius_circum = calculate_radius_circumscribed_circle(a, b, c)
135
+ circumcircle = Circle((U_x, U_y), radius_circum, color=circumcenter_color, fill=False, linestyle='--', linewidth=2, label="Circumscribed Circle")
136
+ ax.add_patch(circumcircle)
137
+
138
+ # Add legend
139
+ handles = [
140
+ plt.Line2D([0], [0], marker='o', color='w', markerfacecolor=vertex_color, markersize=8, label=vertex_labels[0]),
141
+ plt.Line2D([0], [0], marker='o', color='w', markerfacecolor=vertex_color, markersize=8, label=vertex_labels[1]),
142
+ plt.Line2D([0], [0], marker='o', color='w', markerfacecolor=vertex_color, markersize=8, label=vertex_labels[2]),
143
+ plt.Line2D([0], [0], marker='o', color='w', markerfacecolor=midpoint_color, markersize=8, label=midpoints_labels[0]),
144
+ plt.Line2D([0], [0], marker='o', color='w', markerfacecolor=midpoint_color, markersize=8, label=midpoints_labels[1]),
145
+ plt.Line2D([0], [0], marker='o', color='w', markerfacecolor=midpoint_color, markersize=8, label=midpoints_labels[2]),
146
+ plt.Line2D([0], [0], marker='o', color='w', markerfacecolor=incenter_color, markersize=8, label=key_points_labels[0]),
147
+ plt.Line2D([0], [0], marker='o', color='w', markerfacecolor=circumcenter_color, markersize=8, label=key_points_labels[1]),
148
+ plt.Line2D([0], [0], marker='o', color='w', markerfacecolor=centroid_color, markersize=8, label=key_points_labels[2])
149
+ ]
150
+ ax.legend(handles=handles, loc='upper left', fontsize=12)
151
+
152
+ # Adjust the plot limits and aspect ratio
153
+ padding = 3
154
+ ax.set_xlim([min(x1, x2, x3) - padding, max(x1, x2, x3) + padding])
155
+ ax.set_ylim([min(y1, y2, y3) - padding, max(y1, y2, y3) + padding])
156
+ ax.set_aspect('equal', adjustable='datalim')
157
+
158
+ ax.set_title('Solved Triangle', fontsize=18)
159
+ ax.set_xlabel('X-axis', fontsize=12)
160
+ ax.set_ylabel('Y-axis', fontsize=12)
161
+
162
+ plt.grid(True)
163
+ st.pyplot(fig)
164
+
165
+ # Function to check if the sides form a valid triangle
166
+ def is_valid_triangle(a, b, c):
167
+ # Check if the sum of two sides is greater than the third side (Triangle Inequality Theorem)
168
+ return a + b > c and b + c > a and c + a > b
169
+
170
+ # Main function to interact with the user
171
+ def main():
172
+ st.title("Advanced Triangle Solver", anchor='center')
173
+
174
+ st.sidebar.header("Enter the coordinates of the three points:")
175
+
176
+ # Coordinates input (X1, Y1), (X2, Y2), (X3, Y3)
177
+ x1 = st.sidebar.number_input("X1", min_value=-100.0, max_value=100.0, step=0.1, format="%.3f")
178
+ y1 = st.sidebar.number_input("Y1", min_value=-100.0, max_value=100.0, step=0.1, format="%.3f")
179
+ x2 = st.sidebar.number_input("X2", min_value=-100.0, max_value=100.0, step=0.1, format="%.3f")
180
+ y2 = st.sidebar.number_input("Y2", min_value=-100.0, max_value=100.0, step=0.1, format="%.3f")
181
+ x3 = st.sidebar.number_input("X3", min_value=-100.0, max_value=100.0, step=0.1, format="%.3f")
182
+ y3 = st.sidebar.number_input("Y3", min_value=-100.0, max_value=100.0, step=0.1, format="%.3f")
183
+
184
+ # Calculate the lengths of the sides
185
+ a = calculate_distance(x2, y2, x3, y3)
186
+ b = calculate_distance(x1, y1, x3, y3)
187
+ c = calculate_distance(x1, y1, x2, y2)
188
+
189
+ # Check if the triangle is valid
190
+ if not is_valid_triangle(a, b, c):
191
+ st.error("The given points do not form a valid triangle.")
192
+ return
193
+
194
+ # Calculate angles using the law of cosines
195
+ angle_A = calculate_angle(a, b, c)
196
+ angle_B = calculate_angle(b, a, c)
197
+ angle_C = calculate_angle(c, a, b)
198
+
199
+ # Calculate area and perimeter
200
+ area = calculate_area(a, b, c)
201
+ perimeter = calculate_perimeter(a, b, c)
202
+
203
+ # Calculate the radius of the inscribed and circumscribed circles
204
+ radius_inscribed_circle = calculate_radius_inscribed_circle(a, b, c)
205
+ radius_circumscribed_circle = calculate_radius_circumscribed_circle(a, b, c)
206
+
207
+ # Calculate the centroid coordinates
208
+ G_x, G_y = calculate_centroid(x1, y1, x2, y2, x3, y3)
209
+
210
+ # Calculate the incenter coordinates
211
+ I_x, I_y = calculate_incenter(x1, y1, x2, y2, x3, y3, a, b, c)
212
+
213
+ # Calculate the circumcenter coordinates
214
+ U_x, U_y = calculate_circumcenter(x1, y1, x2, y2, x3, y3, a, b, c)
215
+
216
+ # Calculate midpoints of sides
217
+ midpoints = calculate_midpoints(x1, y1, x2, y2, x3, y3)
218
+
219
+ # Display results
220
+ st.subheader("Calculated Properties:")
221
+ st.write(f"**Side Lengths (a, b, c):** {a:.3f}, {b:.3f}, {c:.3f}")
222
+ st.write(f"**Angles (A, B, C):** {angle_A:.3f}°, {angle_B:.3f}°, {angle_C:.3f}°")
223
+ st.write(f"**Area:** {area:.3f}")
224
+ st.write(f"**Perimeter:** {perimeter:.3f}")
225
+ st.write(f"**Radius of Inscribed Circle:** {radius_inscribed_circle:.3f}")
226
+ st.write(f"**Radius of Circumscribed Circle:** {radius_circumscribed_circle:.3f}")
227
+
228
+ plot_triangle(x1, y1, x2, y2, x3, y3, I_x, I_y, U_x, U_y, G_x, G_y, midpoints, a, b, c)
229
 
230
  if __name__ == "__main__":
231
  main()