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()