IPB

Здравствуйте, гость ( Вход | Регистрация )

 
Ответить в данную темуНачать новую тему
Пересечение окружностей и прямых, Нахождение координат
Agny
сообщение 12.1.2013, 5:39
Сообщение #1


Активный участник
***

Группа: Пользователи
Сообщений: 267
Регистрация: 10.1.2013
Из: Kazahstan,Pavlodar
Пользователь №: 65718



Вобщем, для моего проекта потребовались функции для вычисления координат точек пересечения: двух окружностей, двух прямых, окружности и прямой. Причем прямые и окружности могут находится где угодно в разных координатах и уравнения прямой должны вычислятся по координатам двух произвольно взятых точек.

В интернете есть статьи на эту тему , исходники написанные на Delphi , Turbo Pascal и С++.

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

Задача усложняется ещё тем , что Dark Basic Pro не очень хорошо дружит с математикой. Например, если попробовать в нём разделить 1024 / 768 , то получим результат равный 1 без дроби.
Я ещё раньше на Dark Basic Classic когда программы писал, заметил, что например если написать уравнение
Код
2 * b# * c# * COS(a#)

то результат получится неправильным , что бы было правильно нужно написать
Код
COS(a#) * 2 * b# * c#

Когда на свет появился Dark Basic Pro болячки с математикой всё же остались (видимо перешли по наследству от Classic).

К примеру, я нашел в интеренете два способа как можно вычислить координаты точек пересечения двух окружностей, к этим двум я ещё один добавил способ ( вычисление через синусы и косинусы).Написал три функции. Но из этих трех стала работать только одна. И не потому что остальные два способа неправильные. Если взять калькулятор и вручную посчитать по всем уравнениям, то всё получается правильно.
Но Dark Basic Pro ни в какую нехотел работать с оставшимися двумя функциями. На выходе получался какой то странный результат типа : -1,FFFFFFFFF или -1,HHHHHHHHH.И что я только не пробовал делать ( менял в уравнениях переменные разными местами, пробовал разбить уравнения на отдельные части) , ничего не помогает.И если бы ещё сам Dark Basic понимал тот результат , что он выдает... Но ведь дальше этот результат не пригоден , программа работать не будет.

Ну после тяжких трудов и стараний мне удалось написать нужные мне функции.

Вобщем в начале программы устанавливаем глобальную переменную. В неё будет вписываться информация пересеклись или нет.
Код
Global Mathem

И создаем массив куда будет вписываться результат( можно, конечно, использовать тоже глобальные переменные, кому как удобно)
Код
DIM Coord#(3)


Ну и сами функции.
Пересечение двух прямых:
Код
Remstart Функция вычисления точки пересечения ДВУХ ПРЯМЫХ
Xa# , Ya# - координаты одной точки первой прямой
Xb# , Yb# - координаты второй точки первой прямой
Xc# , Yc# - координаты одной точки второй прямой
Xd# , Yd# - координаты второй точки второй прямой
Remend
Function lineline(Xa# , Ya# , Xb# , Yb# , Xc# , Yc# , Xd# , Yd#)
Rem Находим уравнение первой прямой
Aa# = Ya# - Yb#
Ba# = Xb# - Xa#
Ca# = -Aa#*Xa# - Ba#*Ya#
Rem Находим уравнение второй прямой
Ab# = Yc# - Yd#
Bb# = Xd# - Xc#
Cb# = -Ab#*Xc# - Bb#*Yc#
Rem Проверяем прямые на параллельность
If Aa#*Bb# = Ab#*Ba#
  Mathem = 0
  Rem проверка на совпадение прямых
  IF Aa#*Cb# = Ab#*Ca# and Ba#*Cb# = Bb#*Ca#
   Mathem = 3
  Endif
Else
Mathem = 1
REM Если прямые не параллельны , значит они пересекаются
REM Вычисляем точку пересечения
Rem Coord#(0) = X0; Coord#(1) = Y0
Znam# = Aa#*Bb# - Ab#*Ba#
Coord#(0) = -(Ca#*Bb# - Cb#*Ba#)/Znam#
Coord#(1) = -(Aa#*Cb# - Ab#*Ca#)/Znam#
ENDIF
    
ENDFUNCTION

Пересечение окружности и прямой:
Код
Remstart Функция вычисления точек пересечения ОКРУЖНОСТИ и ПРЯМОЙ .
Ax# , Ay# - координаты одной точки прямой
Bx# , By# - координаты второй точки прямой
R# - радиус окружности
Ox# , Oy# - координаты центра окружности
Remend
Function linecircle(Ax# , Ay# , Bx# , By# , R# , Ox# , Oy#)
Rem Вычисляем уравнение прямой , делаем корректировку координат с учетом центра окружности .
Rem Окружность находиться как бы в центре координат в точке (0,0) , а мы двигаем прямую и позже подкорректируем результат.
A# = (Ay# - Oy#) - (By# - Oy#)
B# = (Bx# - Ox#) - (Ax# - Ox#)
C# = -A#*(Ax# - Ox#) - B#*(Ay# - Oy#)
Rem Вычисляем ближайшую к центру точку прямой.
Xo# = -A#*C#/(A#*A#+B#*B#)
Yo# = -B#*C#/(A#*A#+B#*B#)
Rem вычисляем расстояние до центра от данной точки (т.к считается что окружность находится в центре )
Dist# = SQRT((Xo#*Xo#)+(Yo#*Yo#))
Rem Если расстояние больше радиуса , значит окружность и прямая не пересекаются
IF Dist# > R#
Mathem = 0
ENDIF
Rem Если расстояние равно радиусу , значит окружность и прямая пересекаются в одной точке
Rem Эта точка соответствует ближайшей к центру точке прямой . Делаем корректировку результата с учетом центра окружности.
Rem Coord#(0) = X0; Coord#(1) = Y0
IF Dist# = R#
Mathem = 1
Coord#(0) = Xo# + Ox#
Coord#(1) = Yo# + Oy#
ENDIF
Rem Если расстояние меньше радиуса , значит окружность и прямая пересекаются в двух точках.
Rem Вычисляем их координаты. Делаем корректировку результата с учетом центра окружности.
Rem Coord#(0) = X0; Coord#(1) = Y0; Coord#(2) = X1; Coord#(3) = Y1
If Dist# < R#
Mathem = 2
D# = R#*R# - C#*C#/(A#*A#+B#*B#)
mult# = sqrt (D#/(A#*A#+B#*B#))
Coord#(0) = (Xo# + B# * mult#) + Ox#
Coord#(2) = (Xo# - B# * mult#) + Ox#
Coord#(1) = (Yo# - A# * mult#) + Oy#
Coord#(3) = (Yo# + A# * mult#) + Oy#
ENDIF
    
ENDFUNCTION

Пересечение двух окружностей:
Код
Remstart Функция вычисления точек пересечения ДВУХ ОКРУЖНОСТЕЙ
Ox# , Oy# - координаты центра первой окружности
OR# - радиус первой окружности
Ax# , Ay# - координаты центра второй окружности
AR# - радиус второй окружности
Remend
Function circlecircle(OR# , Ox# , Oy# , AR# , Ax# , Ay#)

Rem Если координаты центров окружности и радиуса совпадают, то точек может быть бесконечное множество(нет решения задаче)    
IF OR# = AR# And Ox# = Ax# And Oy# = Ay#
   Mathem = 0
   EXITFUNCTION  
ENDIF
Rem Вычисляем расстояние между центрами окружностей
Px# = Ax# - Ox#
Py# = Ay# - Oy#
Dist# = SQRT((Px#*Px#)+(Py#*Py#))
Rem Если одна из частей отрицательна , то система не имеет решения и окружности не пересекаются
IF OR# + AR# < Dist# or AR# + Dist# < OR# or OR# + Dist# < AR#
  Mathem = 0
ELSE
  Rem Если одна из частей не отрицательна , то продолжаем вычисления
  A# =((OR#*OR#)-(AR#*AR#)+(Dist#*Dist#))/(2*Dist#)
  H# = SQRT((OR#*OR#) - (A#*A#))
  XX# = Ox# + A#*(Ax# - Ox#)/Dist#
  YY# = Oy# + A#*(Ay# - Oy#)/Dist#
  Rem Если соблюдается равенство , то окружности соприкасаются в одной точке
  Rem Coord#(0) = X0; Coord#(1) = Y0
  IF OR# + AR# = Dist# or AR# + Dist# = OR# or OR# + Dist# = AR#
   Mathem = 1
   Coord#(0) = XX#
   Coord#(1) = YY#
  ELSE
  Rem Если иначе , то окружности пересекаются в двух точках
  Rem Вычисляем их координаты.
  Rem Coord#(0) = X0; Coord#(1) = Y0; Coord#(2) = X1; Coord#(3) = Y
   Mathem = 2
   Coord#(0) = XX# - H#*(Ay# - Oy#)/Dist#
   Coord#(1) = YY# + H#*(Ax# - Ox#)/Dist#
   Coord#(2) = XX# + H#*(Ay# - Oy#)/Dist#
   Coord#(3) = YY# - H#*(Ax# - Ox#)/Dist#
  ENDIF
ENDIF
  
ENDFUNCTION


Проверено, у меня всё работат . Dark Basic Pro v1.077
Перейти в начало страницы
 
+Цитировать сообщение
Big V.
сообщение 6.4.2013, 17:39
Сообщение #2


Активный участник
***

Группа: Пользователи
Сообщений: 33
Регистрация: 9.10.2011
Пользователь №: 65697



Цитата(Agny @ 12.1.2013, 5:39) *
Dark Basic Pro не очень хорошо дружит с математикой. Например, если попробовать в нём разделить 1024 / 768 , то получим результат равный 1 без дроби.


Коню понятно, что будет выдавать без дробной части, если в операции задействованы целые числа.
Ты же int делишь на int. Хочешь float - дели 1024.0 / 768.0
И это не баг бейсика, а чистейшая логика, которая кстати почти такая же в любом другом языке.
Вы бы, сударь, поучились программированию, прежде чем на бейсики бочку катить...

Вообще судя по тексту, все проблемы из за неправильного понимания структуры и методов языка.
На счет пересечений, то лично делал интерсеки линия-линия, линия-окружность, окружность-окружность и все стабильно работало. Так что проблема судя по всему в кривизне пространства-времени рук.

З.Ы. Не в обиду. Просто не люблю когда бейсик судят не по заслугам.
Перейти в начало страницы
 
+Цитировать сообщение
Agny
сообщение 7.4.2013, 3:59
Сообщение #3


Активный участник
***

Группа: Пользователи
Сообщений: 267
Регистрация: 10.1.2013
Из: Kazahstan,Pavlodar
Пользователь №: 65718



Цитата
Вы бы, сударь, поучились программированию, прежде чем на бейсики бочку катить...
На счет пересечений, то лично делал интерсеки линия-линия, линия-окружность, окружность-окружность и все стабильно работало.


Ничего ты не делал. Просто решил лишний раз поумничать. Сразу видно.
Даже те функции которые я привел не во всех случаях дают правильный результат. Как там оно у тебя стабильно работало?

Цитата
Просто не люблю когда бейсик судят не по заслугам.


Ну судя по твоим постам на форуме ты сам этим делом позволяешь себе заниматься.
Перейти в начало страницы
 
+Цитировать сообщение
Big V.
сообщение 7.4.2013, 11:27
Сообщение #4


Активный участник
***

Группа: Пользователи
Сообщений: 33
Регистрация: 9.10.2011
Пользователь №: 65697



Держи, ламер:

CODE

`SETUP***********************************************************************
*************************
Set Display Mode 1024,768,32,1
Sync On
Sync Rate 60
Autocam Off
Backdrop On
Color Backdrop RGB(128,128,128)
`
dim result#(2)
`DO**************************************************************************
***********************************
Do
`
gosub get_system_data
`
pos_x_1#=-100
pos_y_1#=0
pos_x_1#=SW2#+(pos_x_1#*SW_#)
pos_y_1#=SH2#-(pos_y_1#*SH_#)
pos_x_2#=100
pos_y_2#=0
pos_x_2#=SW2#+(pos_x_2#*SW_#)
pos_y_2#=SH2#-(pos_y_2#*SH_#)
ink rgb(255,255,0),0
line pos_x_1#,pos_y_1#,pos_x_2#,pos_y_2#
`
cursor_x#=(mousex_-SW2#)/SW_#
cursor_y#=(0-(mousey_-SH2#))/SH_#
pos_x_1#=cursor_x#
pos_y_1#=cursor_y#
pos_x_1#=SW2#+(pos_x_1#*SW_#)
pos_y_1#=SH2#-(pos_y_1#*SH_#)
pos_x_2#=-100
pos_y_2#=100
pos_x_2#=SW2#+(pos_x_2#*SW_#)
pos_y_2#=SH2#-(pos_y_2#*SH_#)
`collision check
p1x#=-100 :p1y#=0
p2x#=100 :p2y#=0
p3x#=-100 :p3y#=100
p4x#=cursor_x#
p4y#=cursor_y#
`
if get_intersection(p1x#,p1y#,p2x#,p2y#,p3x#,p3y#,p4x#,p4y#)=1
ink rgb(255,0,0),0
text 10,10,str$(result#(1))
text 10,25,str$(result#(2))
t_pos_x#=result#(1)
t_pos_y#=result#(2)
t_pos_x#=SW2#+(t_pos_x#*SW_#)
t_pos_y#=SH2#-(t_pos_y#*SH_#)
circle t_pos_x#,t_pos_y#,5
endif
`
line pos_x_1#,pos_y_1#,pos_x_2#,pos_y_2#
`
`SYNC************************************************************************
*************************************
Sync
`LOOP************************************************************************
*************************************
Loop
`END GAME****************************************************************************
*********************************

`GET_SYSTEM_DATA*************************************************************
***********************************************************************
get_system_data:
`
SW#=screen width()
SH#=screen height()
SW2#=SW#/2
SH2#=SH#/2
SW_#=SW#/640.0
SH_#=SH#/480.0
mousex_=mousex()
mousey_=mousey()
mousez_=mousez()
mousemovex#=mousemovex()
mousemovey#=mousemovey()
mousemovez#=mousemovez()
mouseclick_=mouseclick()
if mouseclick_=1 or mouseclick_=3 :mouseclick_1=1 :else :mouseclick_1=0 :endif
if mouseclick_=2 or mouseclick_=3 :mouseclick_2=1 :else :mouseclick_2=0 :endif
if mouseclick_=3 :mouseclick_3=1 :else :mouseclick_3=0 :endif
if mouseclick_=4 :mouseclick_4=1 :else :mouseclick_4=0 :endif
if mouse_click_1=1 and mouseclick_1=0 then mouse_click_1=0
if mouse_click_2=1 and mouseclick_2=0 then mouse_click_2=0
if mouse_click_3=1 and mouseclick_3=0 then mouse_click_3=0
if mouse_click_4=1 and mouseclick_4=0 then mouse_click_4=0
`
return
`
`
`
function get_intersection(p1x#,p1y#,p2x#,p2y#,p3x#,p3y#,p4x#,p4y#)
`
value=0
`
Ua#=((p4x# - p3x#) * (p1y# - p3y#) - (p4y# - p3y#) * (p1x# - p3x#)) / ((p4y# - p3y#) * (p2x# - p1x#) - (p4x# - p3x#) * (p2y# - p1y#))
Ub#=((p2x# - p1x#) * (p1y# - p3y#) - (p2y# - p1y#) * (p1x# - p3x#)) / ((p4y# - p3y#) * (p2x# - p1x#) - (p4x# - p3x#) * (p2y# - p1y#))
`
if Ua#=>0 and Ua#<=1.0 and Ub#>0 and Ub#<1.0
result#(1)=p1x# + Ua# * (p2x# - p1x#)
result#(2)=p1y# + Ua# * (p2y# - p1y#)
value=1
endif
`
endfunction value



Конечно может и говнокод, но этому примеру по крайней мере около двух лет.
Тут пересечение двух прямых. Ка видишь все нормально работает.
Если сомневаешься - подправь код и подвигай все это.

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

З.Ы. Искать пересечения 2-ух сфер и сфера-линия в горе демок и недоделок, что бы просто доказать что то тебе - лень.
Перейти в начало страницы
 
+Цитировать сообщение
Agny
сообщение 7.4.2013, 12:41
Сообщение #5


Активный участник
***

Группа: Пользователи
Сообщений: 267
Регистрация: 10.1.2013
Из: Kazahstan,Pavlodar
Пользователь №: 65718



Я почему и говорю что ты ничего не писал. Если и писал то как следует не тестировал.

По твоему коду сразу замечания. Ты используешь целые числа типа 0 и 100. И твоя линия горизонтальная.
Ты как бы в одной позиции всё просмотрел и приводишь мне в доказательство моей кривости рук.
И ты ведь даже не знаешь для чего эти вычисления мне нужны.

И мои функции работают нормально. И когда линия горизонтальная и используются целые числа всё ОК.
Но в моей программе все значения могут менятся. Точки могут перемещаться в пространстве и иметь не целые значения координат. Линии могут изменять свои иглы.Очень трудно поймать момент когда бывает ошибка вычислений.
Но когда постоянно в программе происходят вычисления и они влияют на сцену. Это очень даже становится заметно.

Вообще на некоторых форумах есть правило: "Сперва читаем всё что есть на форуме , затем пишем и задаем вопросы"
По поводу математики тут тема уже была:

http://area.mediahouse.ru/index.php?showtopic=2369
Перейти в начало страницы
 
+Цитировать сообщение
Big V.
сообщение 7.4.2013, 13:09
Сообщение #6


Активный участник
***

Группа: Пользователи
Сообщений: 33
Регистрация: 9.10.2011
Пользователь №: 65697



Цитата(Agny @ 7.4.2013, 12:41) *
Ты используешь целые числа типа 0 и 100. И твоя линия горизонтальная.


Ага, а float - переменные на входе в ф-цию уже ни о чем не говорят?
function get_intersection(p1x#,p1y#,p2x#,p2y#,p3x#,p3y#,p4x#,p4y#)

Да линия может быть какой угодно.
Параметры есть - можешь менять.

Ещё вопросы?

И да, я тут каг бэ не доказываю, что _твои_ ф-ции не работают, а просто подтверждаю тот факт, что я сам писал такие же рабочие ф-ции, но у меня проблем с бейсиковской математикой не возникало. А не возникало - потому что их нет.
В общем суть в том, что твои доводы в пользу "кривости" бейсиковской математики высосаны из пальца.
Перейти в начало страницы
 
+Цитировать сообщение
Agny
сообщение 7.4.2013, 15:29
Сообщение #7


Активный участник
***

Группа: Пользователи
Сообщений: 267
Регистрация: 10.1.2013
Из: Kazahstan,Pavlodar
Пользователь №: 65718



Вопросов у меня к тебе нет . Какие к тебе могут быть вопросы, умник ? Да и нет желания спорить тут с тобой до бесконечности.

Моё мнение почему возникает ошибка. Потому что в функции используются операции деления.
В определенных ситуациях в результате получается результат близкий к нулю.
И из-за неточности float при делении Dark Basic думает что ты делишь на ноль.
А как известно на ноль делить нельзя. Отсюда результат о котором я писал типа: -1,FFFFFFFFF или -1,HHHHHHHHH
И программа не работает.
Хотя это только моё предположение.

Ну, конечно, у тебя проблем нет.
Это как самая беспроблемная и экономичная машина - это та что в гараже стоит.

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

Если пользовался бы почаще, то наверняка что то подобное о чём я говорю заметил бы.

Да и собственно что ты там написал то? Ещё нужно проанализировать твой код и мой. То что я разбил на части чтобы понятно было , возможно ты в одну строчку написал. А так одно и тоже.
Перейти в начало страницы
 
+Цитировать сообщение
Agny
сообщение 8.4.2013, 14:32
Сообщение #8


Активный участник
***

Группа: Пользователи
Сообщений: 267
Регистрация: 10.1.2013
Из: Kazahstan,Pavlodar
Пользователь №: 65718



Цитата
В общем суть в том, что твои доводы в пользу "кривости" бейсиковской математики высосаны из пальца.


Да что вы говорите blink.gif

Кстати вот код который неработал. Нашел у себя. Вроде он.

Код
Remstart Функция вычисления точек пересечения ДВУХ ОКРУЖНОСТЕЙ
Ox# , Oy# - координаты центра первой окружности
OR# - радиус первой окружности
Ax# , Ay# - координаты центра второй окружности
AR# - радиус второй окружности
Remend
Function circlecircle(OR# , Ox# , Oy# , AR# , Ax# , Ay#)
Rem Вычисляем расстояние между центрами окружностей
Px# = Ax# - Ox#
Py# = Ay# - Oy#
Dist# = SQRT((Px#*Px#)+(Py#*Py#))
Rem Если одна из частей отрицательна , то система не имеет решения и окружности не пересекаются
IF OR# + AR# < Dist# or AR# + Dist# < OR# or OR# + Dist# < AR#
  Mathem = 0
ELSE
  Rem Если одна из частей не отрицательна , то продолжаем вычисления
  Rem Вычисление пересечения двух окружностей сведем к задаче о пересечении первой окружности и прямой
  Rem Первая окружность находиться как бы в центре координат в точке (0,0) , а мы двигаем прямую и позже подкорректируем результат.
  Rem Вычисляем уравнение прямой, делаем корректировку координат с учетом центра первой окружности.
  A# = -2*(Ax# - Ox#)
  B# = -2*(Ay# - Oy#)
  C# = (Ax# - Ox#)*(Ax# - Ox#) + (Ay# - Oy#)*(Ay# - Oy#) + OR#*OR# - AR#*AR#
  Rem Вычисляем ближайшую к центру точку прямой.
  Xo# = -A#*C#/(A#*A#+B#*B#)
  Yo# = -B#*C#/(A#*A#+B#*B#)
  Rem Если соблюдается равенство , то окружности соприкасаются в одной точке
  Rem Эта точка соответствует ближайшей к центру точке прямой . Делаем корректировку результата с учетом центра окружности.
  Rem Coord#(0) = X0; Coord#(1) = Y0
  IF OR# + AR# = Dist# or AR# + Dist# = OR# or OR# + Dist# = AR#
   Mathem = 1
   Coord#(0) = Xo# + Ox#
   Coord#(1) = Yo# + Oy#
  ENDIF
  Rem Если соблюдается условие , то окружности пересекаются в двух точках
  Rem Вычисляем их координаты. Делаем корректировку результата с учетом центра окружности.
  Rem Coord#(0) = X0; Coord#(1) = Y0; Coord#(2) = X1; Coord#(3) = Y1
  IF OR# + AR# > Dist# or AR# + Dist# > OR# or OR# + Dist# > AR#
   Mathem = 2
   D# = R#*R# - C#*C#/(A#*A#+B#*B#)
   mult# = sqrt (D#/(A#*A#+B#*B#))
   Coord#(0) = (Xo# + B# * mult#) + Ox#
   Coord#(2) = (Xo# - B# * mult#) + Ox#
   Coord#(1) = (Yo# - A# * mult#) + Oy#
   Coord#(3) = (Yo# + A# * mult#) + Oy#
  ENDIF
ENDIF
  
ENDFUNCTION


Помню что пробовал на калькуляторе вручную считать по формулам. Всё получалось нормально.
И пробовал анализировать код функции, разбивал на части уравнения. И где то в середине кода, по непонятной причине, результат от деления получался: -1,HHHHHHHHH.

Другую функцию , где я пытался решить задачу через синусы и косинусы так я у себя и не нашел, несохранилась. Писал давно, больше года прошло, видимо удалил за ненадобностью.
Перейти в начало страницы
 
+Цитировать сообщение

Ответить в данную темуНачать новую тему
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 



RSS Текстовая версия Сейчас: 23.8.2017, 1:24
 X 
Ссылки на работы форумчан:
1. Cайт по использованию 3D технологий
в образовании

2. 15 Defense. Underwater Battle

3. GlaZ в Steam Greenlight