Given three vertices of a triangle, this program will calculate the circumcenter, orthocenter, incenter, and centroid of the triangle - provided none of the sides are vertical.
## J Wysocki ## Computes the circumcenter, orthocenter, and centroid of a triangle given the three vertices. ## Notes for a future update: make it work with sides (or medians or perpendicular lines) that are vertical from math import * def distance(point1, point2): """ Calculates the distance between two points :param point1 the first point :param point2 the second point :return: distance between them, as a float """ return sqrt((point1[0] - point2[0])**2 + (point1[1] - point2[1])**2) def find_slope(point1, point2): """ Calculate the slope between two points :param point1: first point :param point2: second point :return: slope or 'vertical' """ if point1[0] == point2[0]: return 'vertical' else: return (point1[1] - point2[1]) / (point1[0] - point2[0]) def find_midpoint(point1, point2): """ Calculates the midpoint between two points :param point1: first point :param point2: second point """ return ((point1[0] + point2[0]) / 2, (point1[1] + point2[1]) / 2) def y_intercept(slope, point): """ Calculates the y-intercept of a line given the slope and a point :param slope: slope of the line :param point: point on the line :return: the y-intercept """ return -1 * slope * point[0] + point[1] def solve_system(slope1, point1, slope2, point2): """ Solve a system of two linear equations, returns the intersection point :param slope1: slope of the first line :param point1: point on the first line :param slope2: slope of the second line :param point2: point on the second line :return: intersection point """ x = (slope1*point1[0] - slope2*point2[0] + point2[1] - point1[1]) / (slope1 - slope2) y = slope1 * (x - point1[0]) + point1[1] return x,y def ratio_of_sides(common_point, endpoint1, endpoint2): """ Calculates the ratio of segment lengths :param common_point point connected to both endpoints :param endpoint1 first endpoint :param endpoint2 second endpoint :return ratio of sides as a float """ distance1 = distance(common_point, endpoint1) distance2 = distance(common_point, endpoint2) return distance2 / distance1 def round_tuple(point, digits_to_round): """ Rounds the values in a tuple to a specified value :param point: the point to be rounded :param digits_to_round: the decimal place to round to :return: the point with rounded values """ return round(point[0], digits_to_round) + 0, round(point[1], digits_to_round) + 0 def input_coord(): """ inputs the coordinates for three points :return: the three points of the triangle """ labels = ['A', 'B', 'C'] points = [] for item, label in enumerate(labels): pt1 = float(input("x-coordinate of " + label + ": ")) pt2 = float(input("y-coordinate of " + label + ": ")) points.append((pt1, pt2)) return points def slopes(point_list): """ Creates the slopes of the sides of a triangle :param point_list: list of vertices of the triangle (A,B,C) :return: a list of the slopes (AB, BC, CA) """ new_points = point_list[:] new_points.append(point_list[0]) slope_list = [] for i in range(len(new_points)-1): slope_list.append(find_slope(new_points[i],new_points[i+1])) return slope_list def perp_slopes(slope_list): """ calculate perpendicular slopes :param slope_list list of slopes :return list of slopes perpendicular """ p_slopes = [] for i in range(len(slope_list)): if slope_list[i] == 'vertical': p_slopes.append(0) elif slope_list[i] == 0: p_slopes.append('vertical') else: p_slopes.append(-1 / slope_list[i]) return p_slopes def seg_midpoints(point_list): """ List of midpoints :param point_list: list of vertices in triangle :return list of midpoints """ points2 = point_list[:] points2.append(point_list[0]) mdpts = [] for i in range(len(points2)-1): mdpts.append(find_midpoint(points2[i], points2[i+1])) mdpts = mdpts[1:] + mdpts[:1] return mdpts def two_point_slopes(point_list, second_list): """ Calculate the slopes between two lists of points :param point_list: list of vertices in triangle :param second_list: list of other points """ seconds = second_list[:] seconds.append(second_list[0]) new_slopes = [] for i in range(len(point_list)): new_slopes.append(find_slope(seconds[i], point_list[i])) return new_slopes def angle_bisector_points(point_list): """ Calculates a point for each of the vertices that would then create a line that represents the angle bisector of the angle at that point :param point_list: list of vertices in triangle :return: the points that would create angle bisectors """ points2 = point_list[:] points2.append(point_list[0]) points2.append(point_list[1]) angle_points = [] for i in range(len(point_list)): scale = ratio_of_sides(points2[i], points2[i+1], points2[i+2]) delta_x = points2[i+1][0] - points2[i][0] delta_y = points2[i+1][1] - points2[i][1] point = (points2[i][0] + scale * delta_x, points2[i][1] + scale * delta_y) second_point = find_midpoint(points2[i+2],point) angle_points.append(second_point) return angle_points def main(): # program summary print("Program Summary: This program will prompt the user to enter the coordinates of the vertices of a triangle ABC.") print("It will then calculate the points of concurrency of the triangle.\n") coords = input_coord() # check for distinct points if len(coords) <= 2: print("These are not distinct points. No triangle.") exit() line_slopes = slopes(coords) if len(set(line_slopes)) <= 2: print("These points are all on the the same line. No triangle.") exit() perpendicular_slopes = perp_slopes(line_slopes) midpoints = seg_midpoints(coords) medians = two_point_slopes(coords, midpoints) bisectors = angle_bisector_points(coords) bisector_slopes = two_point_slopes(coords, bisectors) # calculate circumcenter circumcenter = solve_system(perpendicular_slopes[0], midpoints[2], perpendicular_slopes[1], midpoints[0]) # calculate incenter incenter = solve_system(bisector_slopes[0], coords[0], bisector_slopes[1], coords[1]) # calculate orthocenter orthocenter = solve_system(perpendicular_slopes[0], coords[2], perpendicular_slopes[1], coords[0]) # calculate centroid centroid = solve_system(medians[0], coords[0], medians[1], coords[1]) # calculate Euler line euler_slope = find_slope(circumcenter, orthocenter) euler_intercept = y_intercept(euler_slope, circumcenter) # print results print("Triangle ABC with \nA = " + str(coords[0]) + "\nB = " + str(coords[1]) + "\nC = " + str(coords[2]) + " has") print("-------------------------------") print("its circumcenter at:\n" + str(round_tuple(circumcenter, 2))) print("its incenter at:\n" + str(round_tuple(incenter, 2))) print("its centroid at:\n" + str(round_tuple(centroid, 2))) print("its orthocenter at:\n" + str(round_tuple(orthocenter, 2))) print("The Euler line is\n y = " + str(round(euler_slope, 2)) + "x + " + str(round(euler_intercept, 2)))