Угол между двумя точками

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
Drag
Обычный пользователь
Обычный пользователь
Аватара пользователя
 
Сообщения: 85
Зарегистрирован: 29.01.2005 (Сб) 23:54
Откуда: Москва

Угол между двумя точками

Сообщение Drag » 31.05.2006 (Ср) 11:42

Мне нужно вычислить угол в градусах между точкой A(x1,y1) и B(x2,y2). Угол считается не как у тригонометрических функций, а как на часах - точка отсчета находится в 12 часах, угол увеличивается по часовой стрелке. А тот вариант, что я намудрил, кажется мне слишком тормознутым и громоздким:
Код: Выделить всё
Public Function GetAngleBetween(X1 As Single, Y1 As Single, X2 As Single, Y2 As Single) As Single
    Dim alp As Single, DispX As Long, DispY As Long
    DispX = X2 - X1
    DispY = Y2 - Y1
    If DispX = 0 Then
        If DispY >= 0 Then alp = 0 Else alp = 180
        GoTo 1
    Else
        If DispY = 0 Then
            If DispX >= 0 Then alp = 90 Else alp = 270
            GoTo 1
        Else
            alp = Atn(DispY / DispX) * 180 / PI
        End If
    End If
    If DispX > 0 Then alp = 90 - alp Else alp = 270 - alp
1:
    GetAngleBetween = alp
End Function

Не самый лучший метод, как видите :)
PS: Исправил, теперь намного лучше
Последний раз редактировалось Drag 31.05.2006 (Ср) 12:27, всего редактировалось 3 раз(а).

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 31.05.2006 (Ср) 11:43

Между двумя точками не может быть угла. Угол может быть только между двумя прямыми.
Lasciate ogni speranza, voi ch'entrate.

Drag
Обычный пользователь
Обычный пользователь
Аватара пользователя
 
Сообщения: 85
Зарегистрирован: 29.01.2005 (Сб) 23:54
Откуда: Москва

Сообщение Drag » 31.05.2006 (Ср) 11:49

ну, я имею ввиду угол между лучом из точки A, направленным вверх, и отрезком, соединяющим эти две точки. Вот иллюстрация. Нужно найти угол alp.

Viper
Артефакт VBStreets
Артефакт VBStreets
Аватара пользователя
 
Сообщения: 4394
Зарегистрирован: 12.04.2005 (Вт) 17:50
Откуда: Н.Новгород

Сообщение Viper » 31.05.2006 (Ср) 12:06

Код писать лениво. Потому краткое изложение.

1. Пересчитываешь координаты точки B в систему координат с началом в точке A. Т.е. получаешь координаты Xb = X2 - X1 и Yb = Y2 - Y1.
2. При помощи функции Atn определяешь угол наклона отрезка AB. При этом надо учесть случаи, когда Yb = 0 и без использования Atn сразу получить либо Pi/2, либо -Pi/2 в зависимости от знака Xb. Можно также учесть случай равенства нулю и Xb, но это необязательно.
3. Преобразовать полученный угол в градусы и сменит его знак.
4. Прибавить к полченному значению 90°.

Должно сработать
Весь мир матрица, а мы в нем потоки байтов!

Drag
Обычный пользователь
Обычный пользователь
Аватара пользователя
 
Сообщения: 85
Зарегистрирован: 29.01.2005 (Сб) 23:54
Откуда: Москва

Сообщение Drag » 31.05.2006 (Ср) 12:08

Гы, ты фактически объяснил то, что я написал :). Но все равно спасибо - я почему-то раньше не замечал выражение alp=alp и
Код: Выделить всё
If DispY <= 0 Then
    If DispY < 0 Then alp = 180 Else alp = 180 - alp
Думаю, что лучше рассматривать равенство нулю и DispX и DispY, поскольку ключевую роль играет быстродействие - подпрограмма выполняется более 6000 раз в секунду. Спасибо, Viper, там, оказывается, много лишнего.
Последний раз редактировалось Drag 31.05.2006 (Ср) 13:51, всего редактировалось 1 раз.
Я не сплю, я перешел в режим замедленного функционирования.

Viper
Артефакт VBStreets
Артефакт VBStreets
Аватара пользователя
 
Сообщения: 4394
Зарегистрирован: 12.04.2005 (Вт) 17:50
Откуда: Н.Новгород

Сообщение Viper » 31.05.2006 (Ср) 13:35

Написал код покороче и попроще:
Код: Выделить всё
Public Function GetAngle(ByVal X1 As Double, ByVal Y1 As Double, ByVal X2 As Double, ByVal Y2 As Double) As Double
Dim Xb As Double: Xb = X2 - X1
Dim Yb As Double: Yb = Y2 - Y1
Dim nA As Double
    If Yb = 0# Then
        nA = CDbl(IIf(Xb >= 0#, 0#, 180#))
    ElseIf Xb = 0# Then
        nA = -Sgn(Yb) * 90#
    Else
        If Xb < 0 Then
            nA = -180# * (Sgn(Yb) * Pi - Atn(-Yb / Xb)) / Pi
        Else
            nA = -180# * Atn(Yb / Xb) / Pi
        End If
        If nA < -90# Then
            nA = nA + 360#
        End If
    End If
    GetAngle = nA + 90#
End Function


Менее громоздкий был бы возможен при наличии в VB функции Atan2.
Весь мир матрица, а мы в нем потоки байтов!

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 31.05.2006 (Ср) 13:47

Если нужно быстродействие, я бы советовал отказаться от тригонометрических формул и перейти на табличные значения или округленные методы. Например, эти.
Lasciate ogni speranza, voi ch'entrate.

Drag
Обычный пользователь
Обычный пользователь
Аватара пользователя
 
Сообщения: 85
Зарегистрирован: 29.01.2005 (Сб) 23:54
Откуда: Москва

Сообщение Drag » 31.05.2006 (Ср) 13:58

alibek, спасибо! Давно искал метод Ньютона :).
А так сделал себе такую библиотечку, которая заранее знает значения синуса и косинуса целочисленных углов, вот только не знаю, как из синуса и косинуса выразить арктангенс. Ну да ладно, это уже не так важно. Всем спасибо!
Я не сплю, я перешел в режим замедленного функционирования.


Вернуться в Visual Basic 1–6

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 84

    TopList