Spaces:
Sleeping
Sleeping
Download app.py from Shakeel1979/Triangle_Solution: direct link, hf CLI and curl.
- Browser
- Download file 17.2 kB
-
https://huggingface.co/spaces/Shakeel1979/Triangle_Solution/resolve/main/app.py
- Command line
-
hf download hf://spaces/Shakeel1979/Triangle_Solution/app.py
-
curl -L -o app.py https://huggingface.co/spaces/Shakeel1979/Triangle_Solution/resolve/main/app.py
17.2 kB
| import streamlit as st | |
| import numpy as np | |
| import matplotlib.pyplot as plt | |
| from matplotlib.patches import Polygon, Circle | |
| from reportlab.lib.pagesizes import letter | |
| from reportlab.pdfgen import canvas | |
| from functools import lru_cache | |
| from io import BytesIO | |
| # Cached functions for efficiency | |
| def calculate_distance(x1, y1, x2, y2): | |
| return np.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2) | |
| def calculate_angle(a, b, c): | |
| cos_angle = (b ** 2 + c ** 2 - a ** 2) / (2 * b * c) | |
| cos_angle = np.clip(cos_angle, -1.0, 1.0) | |
| return np.degrees(np.arccos(cos_angle)) | |
| def is_valid_triangle(a, b, c): | |
| return a + b > c and b + c > a and c + a > b | |
| def calculate_area(a, b, c): | |
| s = (a + b + c) / 2 | |
| return np.sqrt(max(0, s * (s - a) * (s - b) * (s - c))) | |
| def calculate_triangle_properties(x1, y1, x2, y2, x3, y3): | |
| a = calculate_distance(x2, y2, x3, y3) | |
| b = calculate_distance(x1, y1, x3, y3) | |
| c = calculate_distance(x1, y1, x2, y2) | |
| if not is_valid_triangle(a, b, c): | |
| st.error("The entered points do not form a valid triangle. Please enter the coordinates again.") | |
| return None | |
| area = calculate_area(a, b, c) | |
| perimeter = a + b + c | |
| s = perimeter / 2 | |
| A = calculate_angle(a, b, c) | |
| B = calculate_angle(b, a, c) | |
| C = calculate_angle(c, a, b) | |
| G_x, G_y = (x1 + x2 + x3) / 3, (y1 + y2 + y3) / 3 # Centroid | |
| I_x = (a * x1 + b * x2 + c * x3) / perimeter | |
| I_y = (a * y1 + b * y2 + c * y3) / perimeter | |
| 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 | |
| radius_in = area / s | |
| radius_circum = (a * b * c) / (4 * area) | |
| midpoints = ( | |
| ((x1 + x2) / 2, (y1 + y2) / 2), | |
| ((x2 + x3) / 2, (y2 + y3) / 2), | |
| ((x3 + x1) / 2, (y3 + y1) / 2) | |
| ) | |
| return { | |
| 'sides': (a, b, c), | |
| 'angles': (A, B, C), | |
| 'area': area, | |
| 'perimeter': perimeter, | |
| 'centroid': (G_x, G_y), | |
| 'incenter': (I_x, I_y), | |
| 'circumcenter': (U_x, U_y), | |
| 'radius_in': radius_in, | |
| 'radius_circum': radius_circum, | |
| 'midpoints': midpoints | |
| } | |
| def plot_triangle(vertices, properties): | |
| fig, ax = plt.subplots(figsize=(18, 12)) | |
| (x1, y1), (x2, y2), (x3, y3) = vertices | |
| a, b, c = properties['sides'] | |
| A, B, C = properties['angles'] | |
| I_x, I_y = properties['incenter'] | |
| U_x, U_y = properties['circumcenter'] | |
| G_x, G_y = properties['centroid'] | |
| midpoints = properties['midpoints'] | |
| radius_in = properties['radius_in'] | |
| radius_circum = properties['radius_circum'] | |
| perimeter = properties['perimeter'] | |
| area = properties['area'] | |
| triangle = Polygon(vertices, closed=True, edgecolor='b', facecolor='lightblue', linewidth=2) | |
| ax.add_patch(triangle) | |
| vertex_labels = [f"Vertex A ({x1:.1f}, {y1:.1f})", f"Vertex B ({x2:.1f}, {y2:.1f})", f"Vertex C ({x3:.1f}, {y3:.1f})"] | |
| vertex_name = ["A", "B", "C"] | |
| for i, (vx, vy) in enumerate(vertices): | |
| ax.scatter(vx, vy, color='blue', zorder=3) | |
| ax.text(vx+0.01*G_x, vy+0.02*G_y, vertex_name[i], fontsize=10, ha="left", va="bottom", color='blue') | |
| key_points = [ | |
| (G_x, G_y, 'green', f"Centroid ({G_x:.1f}, {G_y:.1f})"), | |
| (I_x, I_y, 'red', f"Incenter ({I_x:.1f}, {I_y:.1f})"), | |
| (U_x, U_y, 'black', f"Circumcenter ({U_x:.1f}, {U_y:.1f})") | |
| ] | |
| for x, y, color, label in key_points: | |
| ax.scatter(x, y, color=color, zorder=5) | |
| mid_points = [ | |
| (midpoints[0], 'orange', f"Mid-point M1 ({midpoints[0][0]:.1f}, {midpoints[0][1]:.1f})"), | |
| (midpoints[1], 'orange', f"Mid-point M2 ({midpoints[1][0]:.1f}, {midpoints[1][1]:.1f})"), | |
| (midpoints[2], 'orange', f"Mid-point M3 ({midpoints[2][0]:.1f}, {midpoints[2][1]:.1f})") | |
| ] | |
| for i, (midpoint, color, label) in enumerate(mid_points): | |
| mx, my = midpoint | |
| ax.scatter(mx, my, color=color, zorder=3) | |
| ax.text(mx + 0.01 * G_x, my + 0.02 * G_y, f"M{i}", fontsize=10, ha="left", va="bottom", color=color) | |
| incircle = Circle((I_x, I_y), radius_in, color='red', fill=False, linestyle='--', linewidth=1) | |
| circumcircle = Circle((U_x, U_y), radius_circum, color='black', fill=False, linestyle='--', linewidth=1) | |
| ax.add_patch(incircle) | |
| ax.add_patch(circumcircle) | |
| handles = [ | |
| plt.Line2D([0], [0], marker='o', color='w', markerfacecolor='blue', markersize=7, label=label) | |
| for label in vertex_labels | |
| ] | |
| handles.extend([ | |
| plt.Line2D([0], [0], marker='o', color='w', markerfacecolor=color, markersize=7, label=label) | |
| for _, color, label in mid_points | |
| ]) | |
| handles.extend([ | |
| plt.Line2D([0], [0], marker='<', color='blue', markersize=7, linestyle='none', label=f"Angle {angle}: {value:.1f}Β°") | |
| for angle, value in zip(['A', 'B', 'C'], [A, B, C]) | |
| ]) | |
| handles.extend([ | |
| plt.Line2D([0], [0], marker='o', color='w', markerfacecolor=color, markersize=7, label=label) | |
| for _, _, color, label in key_points | |
| ]) | |
| handles.extend([ | |
| plt.Line2D([0], [0], linestyle='-', color='blue', markersize=6, label=f"Side {side}: {length:.1f}") | |
| for side, length in zip(['a = BC', 'b = AC', 'c = AB'], [a, b, c]) | |
| ]) | |
| handles.extend([ | |
| plt.Line2D([0], [0], marker='o', markerfacecolor='white', markeredgecolor='red', markersize=5, linestyle='none', label=f"Incircle radius: {radius_in:.1f}"), | |
| plt.Line2D([0], [0], marker='o', markerfacecolor='white', markeredgecolor='black', markersize=8, linestyle='none', label=f"Circumcircle radius: {radius_circum:.1f}") | |
| ]) | |
| handles.extend([ | |
| plt.Line2D([0], [0], marker='^', markerfacecolor='white', markeredgecolor='blue', markersize=7, linestyle='none', label=f"Perimeter: {perimeter:.1f}"), | |
| plt.Line2D([0], [0], marker='^', markerfacecolor='lightblue', markeredgecolor='lightblue', markersize=7, linestyle='none', label=f"Area: {area:.1f}") | |
| ]) | |
| ax.legend(handles=handles, loc='upper left', fontsize=8) | |
| padding = 5 | |
| 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('Triangle Visualization', fontsize=23) | |
| ax.set_xlabel('X-axis', fontsize=12) | |
| ax.set_ylabel('Y-axis', fontsize=12) | |
| plt.grid(color='gray', linestyle='--', linewidth=0.5, alpha=0.5) | |
| st.pyplot(fig) | |
| return fig | |
| def save_as_pdf_reportlab(x1, y1, x2, y2, x3, y3, a, b, c, A, B, C, area, perimeter, | |
| I_x, I_y, U_x, U_y, G_x, G_y, midpoints, radius_in, radius_circum, fig): | |
| fig.savefig("triangle_plot.png") | |
| canvas_obj = canvas.Canvas("Triangle_solver_results.pdf", pagesize=letter) | |
| width, height = letter | |
| canvas_obj.setFont("Helvetica", 16) | |
| canvas_obj.drawString(100, height - 40, "Triangle Solver Results") | |
| canvas_obj.setFont("Helvetica", 12) | |
| canvas_obj.drawString(30, height - 60, "Coordinates of Triangle:") | |
| canvas_obj.drawString(50, height - 75, f"Vertex A: ({x1:.3f}, {y1:.3f})") | |
| canvas_obj.drawString(50, height - 90, f"Vertex B: ({x2:.3f}, {y2:.3f})") | |
| canvas_obj.drawString(50, height - 105, f"Vertex C: ({x3:.3f}, {y3:.3f})") | |
| canvas_obj.drawString(30, height - 130, "Mid-Points of Triangle:") | |
| canvas_obj.drawString(50, height - 145, f"Midpoint of AB: ({midpoints[0][0]:.3f}, {midpoints[0][1]:.3f})") | |
| canvas_obj.drawString(50, height - 160, f"Midpoint of BC: ({midpoints[1][0]:.3f}, {midpoints[1][1]:.3f})") | |
| canvas_obj.drawString(50, height - 175, f"Midpoint of AC: ({midpoints[2][0]:.3f}, {midpoints[2][1]:.3f})") | |
| canvas_obj.drawString(30, height - 200, "Angles of Triangle:") | |
| canvas_obj.drawString(50, height - 215, f"Angle A: {A:.3f}Β°") | |
| canvas_obj.drawString(50, height - 230, f"Angle B: {B:.3f}Β°") | |
| canvas_obj.drawString(50, height - 245, f"Angle C: {C:.3f}Β°") | |
| canvas_obj.drawString(30, height - 270, "Sides of Triangle:") | |
| canvas_obj.drawString(50, height - 285, f"Side a = BC: {a:.3f} units") | |
| canvas_obj.drawString(50, height - 300, f"Side b = AC: {b:.3f} units") | |
| canvas_obj.drawString(50, height - 315, f"Side c = AB: {c:.3f} units") | |
| canvas_obj.drawString(30, height - 340, "Other Properties:") | |
| canvas_obj.drawString(50, height - 355, f"Centroid: ({G_x:.3f}, {G_y:.3f})") | |
| canvas_obj.drawString(50, height - 370, f"Perimeter: {perimeter:.3f} units") | |
| canvas_obj.drawString(50, height - 385, f"Area: {area:.3f} square units") | |
| canvas_obj.drawString(30, height - 410, "Incenter of Triangle:") | |
| canvas_obj.drawString(50, height - 425, f"Coordinates: ({I_x:.3f}, {I_y:.3f})") | |
| canvas_obj.drawString(50, height - 440, f"Radius: {radius_in:.3f} units") | |
| canvas_obj.drawString(30, height - 465, "Circumcenter of Triangle:") | |
| canvas_obj.drawString(50, height - 480, f"Coordinates: ({U_x:.3f}, {U_y:.3f})") | |
| canvas_obj.drawString(50, height - 495, f"Radius: {radius_circum:.3f} units") | |
| canvas_obj.drawImage("triangle_plot.png", 30, height - 650, width=500, height=300) | |
| canvas_obj.save() | |
| return | |
| def main(): | |
| st.markdown(""" | |
| <h1 style='text-align: left;'> | |
| <span style="display: inline-block; transform: scaleX(-1);">β</span> Advanced Triangle Solver β | |
| </h1> """, unsafe_allow_html=True) | |
| def get_coordinate_inputs(): | |
| st.sidebar.header("Enter the cartesian coordinates for the three points of a triangle:") | |
| coordinates = {} | |
| for point, label in [('1', 'A'), ('2', 'B'), ('3', 'C')]: | |
| cols = st.sidebar.columns([3, 3]) | |
| coordinates[f'x{point}'] = cols[0].number_input( | |
| f"X{point}", value=0.0, min_value=-100.0, max_value=100.0, step=0.001, format="%.3f" | |
| ) | |
| coordinates[f'y{point}'] = cols[1].number_input( | |
| f"Y{point}", value=0.0, min_value=-100.0, max_value=100.0, step=0.001, format="%.3f" | |
| ) | |
| return coordinates | |
| coords = get_coordinate_inputs() | |
| st.sidebar.markdown("<br>", unsafe_allow_html=True) | |
| button_col = st.sidebar.columns([1, 2, 1]) | |
| if not button_col[1].button("Solve Triangle"): | |
| return | |
| properties = calculate_triangle_properties( | |
| coords['x1'], coords['y1'], | |
| coords['x2'], coords['y2'], | |
| coords['x3'], coords['y3'] | |
| ) | |
| if properties is None: | |
| return | |
| a, b, c = properties['sides'] | |
| A, B, C = properties['angles'] | |
| area = properties['area'] | |
| perimeter = properties['perimeter'] | |
| G_x, G_y = properties['centroid'] | |
| I_x, I_y = properties['incenter'] | |
| U_x, U_y = properties['circumcenter'] | |
| radius_in = properties['radius_in'] | |
| radius_circum = properties['radius_circum'] | |
| midpoints = properties['midpoints'] | |
| vertices = [(coords['x1'], coords['y1']), | |
| (coords['x2'], coords['y2']), | |
| (coords['x3'], coords['y3'])] | |
| st.success("The entered points form a valid triangle.") | |
| def display_coordinates(): | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| st.subheader("Coordinates of Triangle:") | |
| for i, vertex in enumerate(['A', 'B', 'C']): | |
| st.markdown(f"Vertex {vertex}: **({vertices[i][0]:.3f}, {vertices[i][1]:.3f})**") | |
| with col2: | |
| st.subheader("Mid-Points of Triangle:") | |
| for i, points in enumerate([('A','B'), ('B','C'), ('A','C')]): | |
| st.markdown(f"Midpoint of {points[0]}{points[1]}: **({midpoints[i][0]:.3f}, {midpoints[i][1]:.3f})**") | |
| def display_measurements(): | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| st.subheader("Angles of Triangle:") | |
| for angle, value in zip(['A', 'B', 'C'], [A, B, C]): | |
| st.markdown(f"Angle {angle}: **{value:.3f}Β°**") | |
| with col2: | |
| st.subheader("Sides of Triangle:") | |
| for side, value in zip(['a = BC', 'b = AC', 'c = AB'], [a, b, c]): | |
| st.markdown(f"Side {side}: **{value:.3f}** units") | |
| def display_centers(): | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| st.subheader("Incenter of Triangle:") | |
| st.markdown(f"Coordinates: **({I_x:.3f}, {I_y:.3f})**") | |
| st.markdown(f"Radius: **{radius_in:.3f}** units") | |
| with col2: | |
| st.subheader("Circumcenter of Triangle:") | |
| st.markdown(f"Coordinates: **({U_x:.3f}, {U_y:.3f})**") | |
| st.markdown(f"Radius: **{radius_circum:.3f}** units") | |
| def display_other_properties(): | |
| col1, col2, col3 = st.columns([1, 2, 1]) | |
| with col2: | |
| st.subheader("Other Properties:") | |
| st.markdown(f"Centroid: **({G_x:.3f}, {G_y:.3f})**") | |
| st.markdown(f"Perimeter: **{perimeter:.3f}** units") | |
| st.markdown(f"Area: **{area:.3f}** square units") | |
| display_coordinates() | |
| display_measurements() | |
| display_centers() | |
| display_other_properties() | |
| # Plot triangle | |
| fig = plot_triangle(vertices, properties) | |
| ### Code for Save as PDF | |
| # Generate PDF and get the data | |
| save_as_pdf_reportlab( | |
| coords['x1'], coords['y1'], coords['x2'], coords['y2'], coords['x3'], coords['y3'], | |
| a, b, c, A, B, C, area, perimeter, I_x, I_y, U_x, U_y, G_x, G_y, | |
| midpoints, radius_in, radius_circum, fig) | |
| # Read the saved PDF file | |
| with open("Triangle_solver_results.pdf", "rb") as pdf_file: | |
| pdf_data = pdf_file.read() | |
| # Download button | |
| st.download_button("Download PDF", pdf_data, | |
| file_name="Triangle_solver_results.pdf", | |
| mime="application/pdf") | |
| ## Old code for Save as PDF | |
| # if st.button("Save as PDF"): | |
| # save_as_pdf_reportlab( | |
| # coords['x1'], coords['y1'], coords['x2'], coords['y2'], coords['x3'], coords['y3'], | |
| # a, b, c, A, B, C, area, perimeter, I_x, I_y, U_x, U_y, G_x, G_y, | |
| # midpoints, radius_in, radius_circum, fig | |
| # ) | |
| # st.success("Results saved as PDF!") | |
| # with open("Triangle_solver_results.pdf", "rb") as pdf_file: | |
| # st.download_button("Download PDF", pdf_file, file_name="Triangle_solver_results.pdf") | |
| ### New code for Save as PDF | |
| # if st.button("Save as PDF"): | |
| # try: | |
| # # Add debug message | |
| # st.info("Creating PDF... Please wait") | |
| # # Call your PDF creation function | |
| # save_as_pdf_reportlab( | |
| # coords['x1'], coords['y1'], coords['x2'], coords['y2'], coords['x3'], coords['y3'], | |
| # a, b, c, A, B, C, area, perimeter, I_x, I_y, U_x, U_y, G_x, G_y, | |
| # midpoints, radius_in, radius_circum, fig | |
| # ) | |
| # # Check if file exists and has content | |
| # pdf_path = "Triangle_solver_results.pdf" | |
| # if os.path.exists(pdf_path) and os.path.getsize(pdf_path) > 0: | |
| # st.success("PDF created successfully!") | |
| # # Read the PDF file | |
| # with open(pdf_path, "rb") as pdf_file: | |
| # pdf_data = pdf_file.read() | |
| # # Create download button | |
| # st.download_button( | |
| # label="π Download PDF", | |
| # data=pdf_data, | |
| # file_name="Triangle_solver_results.pdf", | |
| # mime="application/pdf" | |
| # ) | |
| # else: | |
| # st.error("β PDF file was not created or is empty!") | |
| # st.info("Check if the save_as_pdf_reportlab function is working correctly") | |
| # except FileNotFoundError as e: | |
| # st.error(f"β File not found: {e}") | |
| # except PermissionError as e: | |
| # st.error(f"β Permission denied: {e}") | |
| # except Exception as e: | |
| # st.error(f"β Error creating PDF: {str(e)}") | |
| # st.info("Please check your save_as_pdf_reportlab function for errors") | |
| # # Alternative: Test if your PDF function works at all | |
| # if st.button("π Debug PDF Function"): | |
| # try: | |
| # st.info("Testing PDF creation...") | |
| # # Test with minimal parameters | |
| # save_as_pdf_reportlab( | |
| # coords['x1'], coords['y1'], coords['x2'], coords['y2'], coords['x3'], coords['y3'], | |
| # a, b, c, A, B, C, area, perimeter, I_x, I_y, U_x, U_y, G_x, G_y, | |
| # midpoints, radius_in, radius_circum, fig | |
| # ) | |
| # st.success("PDF function executed without errors") | |
| # except Exception as e: | |
| # st.error(f"PDF function failed: {str(e)}") | |
| # st.code(str(e)) # Show detailed error | |
| if __name__ == "__main__": | |
| main() |