Координаты касательной к окружности

Надо найти координаты p2 и p3

1 лайк

Обозначим x-координату P_i как P_{ix}, y-координату как P_{iy}.

Если P_1 лежит внутри окружности, т. е. P_0P_1 < P_0P_2 \iff (P_{0x} - P_{1x})^2 + (P_{0y} - P_{1y})^2 < (P_{0x} - P_{2x})^2 + (P_{0y} - P_{2y})^2, то точек касания 0. Если P_1 на окружности, то мы имеем единственную точку касания совпадающей с P_1. Пусть теперь P_1 вне окружности.

Заметим, что точка P_2 задается двумя условиями: P_0P_2 = r и \angle P_0P_2P_1 = 90^{\circ}. Первое условие равносильно тому, что P_2 лежит на окружности с центром в P_0 и с радиусом r, второе условие равносильно тому, что P_2 лежит на окружности с диаметром P_0P_1 (или с радиусом \frac{P_0P_1}{2}) и с центром в середине отрезка P_0P_1, т. е. \left(\frac{P_{0x} + P_{1x}}{2}, \frac{P_{0y} + P_{1y}}{2}\right).

Тогда искомые точки касания – это пересечение этих двух окружностей. На питоне пересечение окружностей можно реализовать так,

def circles_inter(x0: float, y0: float,
                  x1: float, y1: float,
                  r0: float, r1: float) -> tuple:
    """
    Входные данные:
        x0, y0, r0 - координаты центра и радиус первой окружности
        x1, y1, r1 - координаты центра и радиус второй окружности
    Выходные данные:
        x2, y2 - координаты середины отрезка с концами в точках пересечения
        x3, y3 - координаты первой точки пересечения
        x4, y4 - координаты второй точки пересечения
    """
    d = sqrt((x1 - x0)**2 + (y1 - y0)**2)
    a = (r0**2 - r1**2 + d**2) / (2*d)
    h = sqrt(r0**2 - a**2)
    x2 = x0 + a*(x1 - x0) / d
    y2 = y0 + a*(y1 - y0) / d
    x3 = x2 + h*(y1 - y0) / d
    y3 = y2 - h*(x1 - x0) / d
    x4 = x2 - h*(y1 - y0) / d
    y4 = y2 + h*(x1 - x0) / d
    return x3, y3, x4, y4

Почему это работает и что такое a, d и h можно почитать в этой статье под пунктом Intersection of two circles.

Как только вычислим координаты точек пересечения, можем сразу получить P_3 как середину отрезка с концами в этих точках. А дальше длины векторов \overrightarrow{P_1P_3} и \overrightarrow{P_2P_3} вычислить несложно.

6 лайков

Откуда кстати задача?

2 лайка

А я хотел находить расстояние \overline{P_1P_2} через прямоугольный треугольник, потом его углы, потом угол наклона прямой P_1P_0 и оттуда находить P_2. А для P_3 использовать подобие треугольников P_0P_2P_1 и P_0P_3P_2. Однако твоё решение выглядит гораздо более красиво, чем моё что неудивительно)

2 лайка

Решение задачи на путоне, вроде как работает

from math import sqrt

def distance(x0: float, y0: float,
             x1: float, y1: float) -> float:
    """
    Входные данные:
        x0, y0 - координаты первой точки
        x1, y1 - координаты второй точки
    Выходные данные:
        d - расстояние между двумя точками
    """
    d = sqrt((x0 - x1)**2 + (y0 - y1)**2)
    return d

def circles_inter(x0: float, y0: float,
                  x1: float, y1: float,
                  r0: float, r1: float) -> tuple:
    """
    Входные данные:
        x0, y0, r0 - координаты центра и радиус первой окружности
        x1, y1, r1 - координаты центра и радиус второй окружности
    Выходные данные:
        x2, y2 - координаты середины отрезка с концами в точках пересечения
        x3, y3 - координаты первой точки пересечения
        x4, y4 - координаты второй точки пересечения
    """
    d = distance(x0, y0, x1, y1)
    a = (r0**2 - r1**2 + d**2) / (2*d)
    h = sqrt(r0**2 - a**2)
    x2 = x0 + a * (x1 - x0) / d
    y2 = y0 + a * (y1 - y0) / d
    x3 = x2 + h * (y1 - y0) / d
    y3 = y2 - h * (x1 - x0) / d
    x4 = x2 - h * (y1 - y0) / d
    y4 = y2 + h * (x1 - x0) / d
    return x3, y3, x4, y4

with open('tangent.in', 'r') as f:
    p0x, p0y = map(int, f.readline().split())
    r = int(f.readline())
    p1x, p1y = map(int, f.readline().split())
    d = distance(p1x, p1y, p0x, p0y)
    if d < r:
        ans = "0"
    elif d == r:
        ans = "1\n{:.6f} {:.6f}".format(p1x, p1y)
    else:
        ans = "2\n"
        midx, midy = (p0x + p1x) / 2, (p0y + p1y) / 2
        r2 = d / 2
        p21x, p21y, p22x, p22y = circles_inter(p0x, p0y, midx, midy, r, r2)
        p3x, p3y = (p21x + p22x) / 2, (p21y + p22y) / 2
        d13, d23 = distance(p1x, p1y, p3x, p3y), distance(p21x, p21y, p3x, p3y)
        ans += "{:.6f} {:.6f}\n".format(p3x, p3y) + \
               "{:.6f} {:.6f}\n".format(d13, d23) + \
               "{:.6f} {:.6f}\n{:.6f} {:.6f}".format(p21x, p21y, p22x, p22y)

with open('tangent.out', 'w') as f:
    f.write(ans)
4 лайка

2012-2013 Тренировка СПбГУ C #9. Геометрия. Продолжение.

2 лайка

2012-2013 Тренировка СПбГУ C #9. Геометрия. Продолжение.

Решение Ашурова Альтаира

Если точка находится внутри круга то ответ 0. Проверить можно сравнив радиус круга и расстояние между точкой и центром круга.

Если точка находится на окружности то ответ 1, и это и есть сама эта точка. Проверить можно сравнив радиус круга и расстояние между точкой и центром круга .

Иначе достаточно вычислить то что просят в задаче, Пользователи выше написали подробное объяснение того как это делать.

2 лайка