def triangle_circumference(triangle: Triangle, finder: Finder) -> None: side1, side2, side3 = triangle.sides yield symbol(triangle, 'circumference') \ - symbol(side1, 'length') \ - symbol(side2, 'length') \ - symbol(side3, 'length')
def the_law_of_cosines(triangle: Triangle, finder: Finder) -> None: known_sides = triangle.known_sides unknown_angles = triangle.unknown_angles if len(known_sides) == 3: if unknown_angles: angle = unknown_angles[0] opposite_side = triangle.opposite_side(angle) adj_side1, adj_side2 = triangle.adjacent_sides(angle) a = adj_side1.length b = adj_side2.length c = opposite_side.length angle_ = math.acos((a * a + b * b - c * c) / (2 * a * b)) yield symbol(angle, 'angle') - to_degree_measure(angle_) # angle.angle = math.acos((a * a + b * b - c * c) / (2 * a * b)) # angle.angle = to_degree_measure(angle.angle) # solving_path.append_deduction( # theory=zh_theory['the_law_of_cosines'], # eq='Angle_{0} = arccos((Line_{1}^2+Line_{2}^2-Line_{3}^2) / (2*Line_{1}*Line_{2}))'.format(angle.id, adj_side1.id, adj_side2.id, opposite_side.id), # result=angle.angle) elif len(known_sides) == 2: unknown_side = triangle.unknown_sides[0] angle = triangle.opposite_angle(unknown_side) if angle.angle is not None: a = known_sides[0].length b = known_sides[1].length cos_c = math.cos(to_radian_measure(angle.angle)) length = math.sqrt(a * a + b * b - 2 * a * b * cos_c) yield symbol(unknown_side, 'length') - length
def triangle_angle_sum(triangle: Triangle, finder: Finder) -> None: angle0, angle1, angle2 = triangle.angles yield symbol(angle0, 'angle') \ + symbol(angle1, 'angle') \ + symbol(angle2, 'angle') \ - 180
def n_angle_sector_ratio(n_angle_sector: NAngleSector, finder: Finder) -> None: angle = n_angle_sector.angle line = n_angle_sector.line ratio = n_angle_sector.ratio nearer_line = n_angle_sector.nearer_line if nearer_line is None: nearer_line = angle.sides[0] angle_mid = finder.find_angle_by_sides(line, nearer_line) yield symbol(angle, 'angle') * ratio - symbol(angle_mid, 'angle')
def similar_triangle_ratio(similar_triangle: SimilarTriangle, finder: Finder) -> None: ratio = symbol(similar_triangle, 'ratio') triangle1 = similar_triangle.triangle1 triangle2 = similar_triangle.triangle2 for angle1, angle2 in similar_triangle.corresponding: line1 = triangle1.opposite_side(angle1) line2 = triangle2.opposite_side(angle2) yield symbol(line1, 'length') - ratio*symbol(line2, 'length')
def n_line_sector_ratio(n_line_sector: NLineSector, finder: Finder) -> None: line = n_line_sector.line ratio = n_line_sector.ratio A = n_line_sector.nearer_point if A is None: A = line.ends[0] B = n_line_sector.point AB = finder.find_line_by_ends(A, B) yield symbol(line, 'length') * ratio - symbol(AB, 'length')
def perpendicular_angle(parallel: Parallel, finder: Finder) -> None: line1 = finder.extend_line(parallel.line1) line2 = finder.extend_line(parallel.line2) link1 = finder.find_link_by_ends(*line1.ends) link2 = finder.find_link_by_ends(*line2.ends) col1 = Collineation('Collineation ' + line1.id, points=link1) col2 = Collineation('Collineation ' + line2.id, points=link2) for angle1, angle2 in _find_alternate_angels(col1, col2, finder): yield symbol(angle1, 'angle') - symbol(angle2, 'angle')
def common_vertex_angle_sum(common_vertex_angle: CommonVertexAngle, finder: Finder) -> None: lines = common_vertex_angle.lines num_lines = len(lines) for i in range(num_lines): for j in range(i + 1, num_lines): for k in range(j + 1, num_lines): angle_ij = finder.find_angle_by_sides(lines[i], lines[j]) angle_jk = finder.find_angle_by_sides(lines[j], lines[k]) angle_ik = finder.find_angle_by_sides(lines[i], lines[k]) yield symbol(angle_ij, 'angle') \ + symbol(angle_jk, 'angle') \ - symbol(angle_ik, 'angle')
def collineation_line_length_sum(collineation: Collineation, finder: Finder) -> None: points = collineation.points num_points = len(points) if num_points < 3: return for i in range(num_points): for j in range(i + 1, num_points): for k in range(j + 1, num_points): line_ij = finder.find_line_by_ends(points[i], points[j]) line_jk = finder.find_line_by_ends(points[j], points[k]) line_ik = finder.find_line_by_ends(points[i], points[k]) yield symbol(line_ij, 'length') \ + symbol(line_jk, 'length') \ - symbol(line_ik, 'length')
def helen_formula(triangle: Triangle, finder: Finder) -> None: known_sides = triangle.known_sides if len(known_sides) == 3: a = known_sides[0].length b = known_sides[1].length c = known_sides[2].length p = (a + b + c) / 2 area = math.sqrt(p * (p - a) * (p - b) * (p - c)) yield symbol(triangle, 'area') - area
def _update_entity(self, result, e: Entity) -> None: for attr, value in e.__dict__.items(): # If value is unkonwn, check it. if value is not None: continue symbol_ = symbol(e, attr) if isinstance(symbol_, Symbol): try: value = result[symbol_] if isinstance(value, Number): # Deduction success if update entity. setattr(e, attr, value) self.success = True except KeyError: pass
def perpendicular_angle(perpendicular: Perpendicular, finder: Finder) -> None: line1 = perpendicular.line1 line2 = perpendicular.line2 # Extend line first. line1 = finder.extend_line(line1) line2 = finder.extend_line(line2) # Find intersection. intersection = finder.find_lines_intersection(line1, line2) if len(intersection) != 1: raise Exception('Perpendicular relationship is suppposed to include ' 'two perpendicular line. Except 1, got {}.' .format(len(intersection))) cross_p = intersection[0] for p1 in line1.ends: for p2 in line2.ends: if p1 == cross_p or p2 == cross_p: continue line1_ = finder.find_line_by_ends(p1, cross_p) line2_ = finder.find_line_by_ends(p2, cross_p) angle = finder.find_angle_by_sides(line1_, line2_) yield symbol(angle, 'angle') - 90
def vertical_angle_equality(opposite_vertical_angle: OppositeVerticalAngle, finder: Finder) -> None: angle1 = opposite_vertical_angle.angle1 angle2 = opposite_vertical_angle.angle2 yield symbol(angle1, 'angle') - symbol(angle2, 'angle')
def similar_triangle_angle_equality(similar_triangle: SimilarTriangle, finder: Finder) -> None: for angle1, angle2 in similar_triangle.corresponding: yield symbol(angle1, 'angle') - symbol(angle2, 'angle')
def the_law_of_sines(triangle: Triangle, finder: Finder) -> None: # known_angles = triangle.known_angles # if len(known_angles) == 1 and known_angles[0].angle >= 90: # # if only one angle is known and it larger than 90 degree, # # asin only has one solution. # angle = known_angles[0] # opposite_side = triangle.opposite_side(angle) # if opposite_side.length is not None: # for side in triangle.adjacent_sides(angle): # if side.length is not None: # unknown_angle = triangle.opposite_angle(side) # sin_angle = math.sin(to_radian_measure(angle.angle)) * \ # (side.length / opposite_side.length) # unknown_angle.angle = to_degree_measure( # math.asin(sin_angle)) # solving_path.append_deduction( # theory=zh_theory['the_law_of_sines'], # eq='Angle_{0} = arcsin(sin(Angle_{1}) * (Line_{2} / Line_{3}))'.format(unknown_angle.id, angle.id, side.id, opposite_side.id), # result=unknown_angle.angle) # return # else: # for angle in triangle.angles: # side = triangle.opposite_side(angle) # if angle.angle is not None: # yield symbol(side, 'length') / sympy.sin(to_radian_measure(symbol(angle, 'angle'))) \ # - 2 * symbol(triangle, 'r_outer') known_angles = triangle.known_angles if len(known_angles) == 0: return elif len(known_angles) == 1: angle = known_angles[0] opposite_side = triangle.opposite_side(angle) if opposite_side.length is not None: for side in triangle.adjacent_sides(angle): if side.length is not None: unknown_angle = triangle.opposite_angle(side) sin_angle = math.sin(to_radian_measure(angle.angle)) * \ (side.length / opposite_side.length) angle_ =to_degree_measure( math.asin(sin_angle)) yield symbol(unknown_angle, 'angle') - angle_ # unknown_angle.angle = to_degree_measure( # math.asin(sin_angle)) # solving_path.append_deduction( # theory=zh_theory['the_law_of_sines'], # eq='Angle_{0} = arcsin(sin(Angle_{1}) * (Line_{2} / Line_{3}))'.format(unknown_angle.id, angle.id, side.id, opposite_side.id), # result=unknown_angle.angle) return elif len(known_angles) > 1: opposite_sides = \ [triangle.opposite_side(angle) for angle in known_angles] for index1, side1 in enumerate(opposite_sides): for index2, side2 in enumerate(opposite_sides): if side1.length is None and side2.length is not None: angle1 = to_radian_measure(known_angles[index1].angle) angle2 = to_radian_measure(known_angles[index2].angle) length = side2.length * math.sin(angle1) / math.sin(angle2) yield symbol(side1, 'length') - length # side1.length = side2.length * math.sin(angle1) / math.sin(angle2) # solving_path.append_deduction( # theory=zh_theory['the_law_of_sines'], # eq='Line_{0} = Line_{1} * sin({2}) / sin({3})'.format(side1.id, side2.id, known_angles[index1].id, known_angles[index2].id), # result=side1.length) return
def supplementary_angle_sum(supplementary_angle: SupplementaryAngle, finder: Finder) -> None: angle1 = supplementary_angle.angle1 angle2 = supplementary_angle.angle2 yield symbol(angle1, 'angle') + symbol(angle2, 'angle') - 180