2009-08-29 4 views
10

Для линии с первой конечной точкой P (x1, y1) другая конечная точка неизвестна, пересекается с кругом, который расположен в начале координат с радиусом R только в одной точке (касательной) T (x2, y2). Кто-нибудь знает, как получить точку T? Заранее спасибо!Найти точку касания по кругу?

+0

Как это строка, если у вас есть только одна конечная точка? – obelix

+0

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

+1

dmindreader, вы действительно поняли мою точку зрения. Благодарю. – 2009-08-30 06:38:57

ответ

1

Используйте координаты x, y пересекающихся уравнений (один из окружности и один из линий). В этом-то и дело.

Если у вас есть только одна конечная точка для рисования линии, вы получите две разные точки, так как будут две разные касательные линии, одна вверх и одна вниз.

9

Взять R как радиус круга и D расстояние от внешней точки до центра круга, такое как D > R.

tanget линия делает и угол \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) 

, который все, что вам нужно.

+1

** @ HanWu: ** При рисовании картинки и проверке себя, я все равно получаю 'arcsin'. Вы использовали бы 'arccos' для угла между соединительной линией (CP) и радиусом (CT). – dmckee

+0

arcsin правильный: синус (альфа) = противоположный (R)/гипотенуза (D) – Argalatyr

+0

\ alpha = arcsin (R/D) должен быть \ alpha = arccos (R/D) – 2009-08-30 04:35:01

0

Другое решение; менее элегантно, чем dmindreader`s, но, может быть, проще понять:

Вы знаете, что точка T находится на окружности, и что линия OT перпендикулярно к линии PT

, что дает вам

abs(O - T) = R 
dotProduct(O - T, P - T) = 0 
32

Для строки с первой конечной точкой P (x1, y1) другая конечная точка неизвестна, пересекаются с кругом, расположенным в начале координат с радиусом R только в одной точке (касательной) T (x2, y2). Кто-нибудь знает, как получить точку T?

Некоторые из других решений кажутся немного переполненными. Я думаю, что самый простой способ - только заметить, что это правый треугольник с вершинами P, T и O (начало координат). Угол PTO является прямым углом, поскольку касательная линия всегда находится под прямым углом к ​​радиусу.

Вы знаете длину TO, поскольку она имеет длину r и имеет вершину в начале координат; вы знаете OP, потому что знаете, где O и P есть. Учитывая две стороны правого треугольника, легко найти длину и направление третьей стороны. Это домашнее задание, поэтому я оставлю остальных упражнением для читателя.

    __...------__ T(x2, y2)      
       _.-''    -(+) 
      ,-'     |----    
      ,'      |  ---- 
     ,'      |  ' ---- 
    /      |   `  ----  
    /      |   `.  ---- 
    /      |    \   ---- 
    |      |    |    ---- 
    |      |     |     ---- 
    |      |     |      ---- 
    |     (+)---------------------------------------------(+) P (x1,y1) 
    |          .'   
    |     O     |   
    |          .'   
     \         /   
     \         ,'   
     `        /   
     '.       ,'    
      '-.      _,'    
       '-._    _,(+) T'(x3, y3)     
        '`--......---'      

Есть два возможных направления TO, так как точка T»также является действительной точкой касательной, так что вы будете иметь два равных треугольника.

+18

+1 для искусства ascii! – ThibThib

+1

Это известно как теорема Фалеса (http://en.wikipedia.org/wiki/Thales%27_theorem). – JCM

+0

@JCM Я не вижу, как это теорема Тале. Тале установил бы, что «ОП» - это диаметр окружности для «ОПТ». –

2

Для меня не очевидно, что это домашнее задание, но мне нравится интуиция, что определяется правильный треугольник. Тем не менее, будет некоторая алгебра с этим решением.

Другим подходом, который представляется жизнеспособным, является просто определение проблемы как решения двух уравнений с двумя неизвестными. То есть, уравнение окружности с центром в точке (0,0), с радиусом R является

x^2 + y^2 = R^2 

Уравнение прямой, проходящей через точку (х, уг), с (неизвестной) наклона S is

(y - yt) = S*(x - xt) 

Решите систему двух уравнений для точки пересечения. В зависимости от значения S, эта пара уравнений будет равна нулю, одному или двум решениям. Выяснилось также, что существует два значения S, для которых единственное решение. Решите для этих двух значений S, которые делают решение уникальным, а затем верните точку пересечения (xt, yt). Я не буду углубленно рассматривать фактическое решение, если это домашнее задание, но эта часть является тривиальной алгеброй.

Я хочу сказать, что этот алгебраический подход является еще одним способом рассмотрения решения проблемы вычислительной геометрии. Интересно отметить, что есть две линии, которые пересекают окружность в касательной точке и что, когда линия пересекается в касательной точке, существует одна точка пересечения.

Недостаток этого подхода заключается в том, что это не удается из-за особенностей для НЕКОТОРЫХ проблем. I., когда линия с наклоном S является вертикальной, то S не определено. Другие подходы, основанные на простых расстояниях и теореме Пифагора, являются надежными для этого события.

14

Все, что вам нужно, это ответ 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) }; 
+0

Что представляет x: радиус? – 130nk3r5

+1

радиус = радиус круга. ta = объект со свойствами x и y (в основном точка). Чтобы ответить на ваш вопрос, x: радиус не представляет собой многого. Код определяет значение ta.x, где x = radius * Math.sin (t). Пожалуйста, убедитесь, что вы обратитесь к jsfiddle, чтобы увидеть рабочий пример. – imbrizi

+0

Я пытаюсь преобразовать это в код C# ....и я не мог понять, что такое x: radius is ... Но я неправильно прочитал код .... Я неправильно понял, что это объект x со значением радиуса ... где это просто значение x of ta. THanks;) – 130nk3r5

3
  1. Вы можете найти направление вектора DX, если вращать вектор DO углом альфа (угол альфа найден как asin (len (OX)/len (DO)), который просто arcsinus радиуса над гипотенузы)

  2. Вы можете найти длину вектора DX тривиальным следующим образом: SQRT (Len (DO) * LEN (DO) - Len (ОХ) * Len (ОХ))

  3. Учитывая направление и длина вектора 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 на минус альфа

Image demonstrating the algo

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; 
} 
+0

Спасибо, что ваше решение решило мою проблему. ;) – crypt

1

Я обычно использую программное обеспечение Maple для решения таких проблем. Он может даже генерировать код C из этих уравнений.

enter image description here

Вот результат:

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; 

Очевидно, что вам нужно добавить поплавок или дважды к переменным, а также проверить наличие отрицательного значения, прежде чем принимать квадратный корень.

Смежные вопросы