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