Для линии с первой конечной точкой P (x1, y1) другая конечная точка неизвестна, пересекайтесь с кругом, который расположен в начале координат с радиусом R только в одной точке (касательной) T (x2, y2). Кто-нибудь знает, как получить точку T? Спасибо заранее!
Найти касательную точку на круге?
Ответ 1
Для линии с первой конечной точкой P (x1, y1) другая конечная точка неизвестна, пересекайтесь с кругом, который расположен в начале координат с радиусом R только в одной точке (касательной) T (x2, y2). Кто-нибудь знает, как получить точку T?
Некоторые из других решений кажутся немного переполненными. Я думаю, что самый простой способ - только заметить, что это правый треугольник с вершинами P, T и O (начало координат). Угол ВОМ является прямым углом, поскольку касательная линия всегда находится под прямым углом к радиусу.
Вы знаете длину TO
, поскольку она имеет длину r
и имеет вершину в начале координат; вы знаете OP
, потому что знаете, где O
и P
. Учитывая две стороны правого треугольника, легко найти длину и направление третьей стороны. Это домашнее задание, поэтому я оставлю остальных в качестве упражнения для читателя.
__...------__ T(x2, y2)
_.-'' -(+)
,-' |----
,' | ----
,' | ' ----
/ | ` ----
/ | `. ----
/ | \ ----
| | | ----
| | | ----
| | | ----
| (+)---------------------------------------------(+) P (x1,y1)
| .'
| O |
| .'
\ /
\ ,'
` /
'. ,'
'-. _,'
'-._ _,(+) T'(x3, y3)
'`--......---'
Существует два возможных направления для TO
, так как точка T 'также является допустимой касательной точкой, поэтому у вас будет два конгруэнтных треугольника.
Ответ 2
Все, что вам нужно, это ответ dmckee, но если вам нужен какой-то код, проверьте эту реализацию, используя холст Javascript и HTML.
Полный пример: http://jsfiddle.net/zxqCw/1/
// find tangents
dx = cx - px;
dy = cy - py;
dd = Math.sqrt(dx * dx + dy * dy);
a = Math.asin(radius / dd);
b = Math.atan2(dy, dx);
t = b - a
ta = { x:radius * Math.sin(t), y:radius * -Math.cos(t) };
t = b + a
tb = { x:radius * -Math.sin(t), y:radius * Math.cos(t) };
Ответ 3
Возьмем R
как радиус круга и D
расстояние от внешней точки до центра круга, такое, что D > R
.
Линия танетта делает и угол \alpha
с линией, соединяющей внешнюю точку и центр, где
\alpha = arcsin(R/D)
Линия, соединяющая внешнюю точку (P
) и центр (C
), делает угол с горизонталью
\beta = arctan((C_y - P_y)/(C_x - P_x))
Это дает вам угол касательной линии с горизонтали как
\theta = \beta +/- \alpha
Обратите внимание на двусмысленность.
Длина касательного отрезка
L = sqrt(D^2 - R^2)
который вам нужен.
Ответ 4
imbrizi отвечает, что центр окружности равен (0,0).
Это правильный ответ в Objective C:
- (NSArray *)pointsTangentToCircleWithCenter:(CGPoint)centerPoint
radius:(CGFloat)radius
outerPoint:(CGPoint)outerPoint {
float dx = centerPoint.x - outerPoint.x;
float dy = centerPoint.y - outerPoint.y;
float dd = sqrt(dx*dx + dy*dy);
float a = asinf(radius / dd);
float b = atan2f(dy, dx);
float t1 = b - a;
CGPoint tangentPoint1 = CGPointMake(centerPoint.x + radius*sinf(t1),
centerPoint.y + radius*-cosf(t1));
float t2 = b + a;
CGPoint tangentPoint2 = CGPointMake(centerPoint.x + radius*-sinf(t2),
centerPoint.y + radius*cosf(t2));
NSArray *points = @[
[NSValue valueWithCGPoint:tangentPoint1],
[NSValue valueWithCGPoint:tangentPoint2]
];
return points;
}
Ответ 5
-
Вы можете найти направление вектора DX, если вы поворачиваете вектор DO по углу альфа (угол α найден как asin (len (OX)/len (DO)), который является просто арцинусом радиуса над гипотенузой)
-
Вы можете найти длину вектора DX тривиально следующим образом: sqrt (len (DO) * len (DO) - len (OX) * len (OX))
-
Учитывая направление и длину вектора DX, вы можете найти значение точки X. Один из подходов - нормализовать DX и умножить его на длину.
auto dist = D.Distance(O); auto side = sqrt(dist*dist - rad*rad) auto line = Vector2D(D, O); line.Rotate(asin(rad / dist)); //get the direction line.Normalize(); //set length to 1 line*=side; //we have the direction, now get length Point2D X = D + line;
P.S. Обратите внимание, что есть также вторая касательная, которая определяется поворотом DO минусом alpha
Ответ 6
Для меня не очевидно, что это домашнее задание, но мне нравится интуиция, что определяется правильный треугольник. Тем не менее, там будет какая-то алгебра с этим решением.
Другим подходом, который кажется жизнеспособным, является просто определение проблемы как решение двух уравнений с двумя неизвестными. То есть уравнение окружности с центром в (0,0) с радиусом R равно
x^2 + y^2 = R^2
Уравнение прямой, проходящей через точку (xt, yt), с (неизвестным) наклоном S есть
(y - yt) = S*(x - xt)
Решите систему двух уравнений для точки пересечения. В зависимости от значения S, эта пара уравнений будет равна нулю, одному или двум решениям. Выяснилось также, что существует два значения S, для которых единственное решение. Решите для этих двух значений S, которые делают решение уникальным, а затем верните точку пересечения (xt, yt). Я не буду углубленно рассматривать фактическое решение, если это домашнее задание, но эта часть является тривиальной алгеброй.
Я хочу сказать, что этот алгебраический подход - это еще один способ взглянуть на решение проблемы вычислительной геометрии. Интересно отметить, что есть две линии, которые пересекают круг в касательной точке и что, когда прямая пересекается в касательной точке, существует одна точка пересечения.
Недостаток этого подхода заключается в том, что он терпит неудачу из-за сингулярности для НЕКОТОРЫХ задач. I., когда линия с наклоном S вертикальна, то S является undefined. Другие подходы, основанные на простых расстояниях и теореме Пифагора, являются надежными для этого события.
Ответ 7
Используйте координаты x, y пересекающихся уравнений (один из окружности и один из линий). Это точка.
Если у вас есть только одна конечная точка для рисования линии, вы получите две разные точки, так как будут две разные касательные линии, одна вверх и одна вниз.
Ответ 8
Обычно я использую программное обеспечение Maple для решения таких проблем. Он может даже генерировать код C из этих уравнений.
Здесь вывод:
t1 = v_x * v_x;
t2 = t1 * t1;
t3 = v_y * v_y;
t6 = sqrt(t1 * t3 - t1 + t2);
t7 = v_y + t6;
t9 = 0.1e1 / (t1 + t3);
t13 = 0.1e1 / v_x;
x1 = -(t7 * t9 * v_y - 0.1e1) * t13;
y1 = t7 * t9;
t16 = (-v_y + t6) * t9;
x2 = -(-t16 * v_y - 0.1e1) * t13;
y2 = -t16;
Очевидно, вам нужно добавить float или double к переменным, а также проверить отрицательное значение, прежде чем принимать квадратный корень.
Ответ 9
Другое решение; менее элегантный, чем dmindreader`s, но, возможно, проще понять:
Вы знаете, что точка T
находится на круге и что строка OT
перпендикулярна строке PT
который дает вам
abs(O - T) = R
dotProduct(O - T, P - T) = 0