XGM Forum
Сайт - Статьи - Проекты - Ресурсы - Блоги

Форуме в режиме ТОЛЬКО ЧТЕНИЕ. Вы можете задать вопросы в Q/A на сайте, либо создать свой проект или ресурс.
Вернуться   XGM Forum > Warcraft> Академия: форум для вопросов
Ник
Пароль
Войти через VK в один клик
Сайт использует только имя.

Ответ
 
exAres
I love magic :)
offline
Опыт: 7,788
Активность:
Как просчитать пересечение двух линий
У меня проблема : не знаю как узнать что две линии пересеклись(у меня есть стена(юнит с двумя точками:начала и конца)и кастер(юнит который должен кастить через стену)). Как узнать что юнит кастит именно через стену ? Ну у меня не на одного юнита должно быть розсчитано, ну типа мне нужно знать именно когда любой вражеский юнит будет кастить через ету стену.
Старый 17.04.2006, 15:56
exAres
I love magic :)
offline
Опыт: 7,788
Активность:
Аааааааауууууууу !!! Что никто не знает как ето зделать ? Может я не очень хорошо обьяснил ? Так вы скажите что не ясно, я уточню !
Старый 17.04.2006, 22:39
Iron
Листовой
offline
Опыт: 24,427
Активность:
Ну координаты то нам известны (или получаемы триггерно).
Остается только составить 2-а уравнения прямых, потом решать систему этих двух уравнений, и проверять решения системы на то, входят они в границы отрезков или нет.
Короче, если в 2-х словах - гемор редкостный.
Старый 18.04.2006, 00:28
NETRAT

offline
Опыт: 83,712
Активность:
В-общем ответы на такие вопросы следует искать как-то так
И в результате получаем что-то такое
http://alglib.sources.ru/geometry/sectint.php
http://doc-for-prog.narod.ru/topics/math/crossing.html
http://www.gamedev.ru/forum/?group=0&topic=20732

Хотя что-то мне помницца их можно через определитель матрицы, составленной из точек(?) найти

NETRAT добавил:
Это по-школьному геморр, а вообще есть "прямые" формулы, в которые достаточно просто подставить координаты
Старый 18.04.2006, 11:51
YoGA

offline
Опыт: 243
Активность:
Салют от матфака ОмГУ! :)
Будем считать, что прямые заданы точками: (xb1, yb1) - (xe1, ye1) и (xb2, yb2) - (xe2, ye2)
Для удобства введем новые переменные:
a1 = xe1 - xb1
b1 = ye1 - yb1
a2 = xe2 - xb2
b2 = ye2 - yb2
Вектора (a1, b1) и (a2, b2) не должны быть коллинеарны, т. е. необходимое условие для существования искомой точки пересечения: a2 * b1 - a1 * b2 не равно 0
Тогда координаты точки пересечения заданных прямых равны:
x = xb2 + a2 * p
y = yb2 + b2 * p
где p = ((xb2 - xb1) * b1 - (yb2 - yb1) * a1) / (a2 * b1 - a1 * b2)
Теперь нужно проверить, принадлежит ли найденная точка заданным отрезкам. Для этого необходимо выполнение неравенств:
x >= min (xb1, xe1)
x >= min (xb2, xe2)
x <= max (xb1, xe1)
x <= max (xb2, xe2)
y >= min (yb1, ye1)
y >= min (yb2, ye2)
y <= max (yb1, ye1)
y <= max (yb2, ye2)
Вот и все, вроде. Я нигде не ошибся?
Старый 18.04.2006, 12:29
Iron
Листовой
offline
Опыт: 24,427
Активность:
YoGA В общем ты расписал, то что я и говорил. Имхо это гемор.
Старый 18.04.2006, 13:44
exAres
I love magic :)
offline
Опыт: 7,788
Активность:
YoGA - Сенк! Ща буду считать.
Старый 18.04.2006, 15:15
exAres
I love magic :)
offline
Опыт: 7,788
Активность:
YoGA я неправильно понял или... незнаю но у меня такая функция :
Код:
function Trig_Antimagic_wall_Conditions takes nothing returns boolean
    return GetSpellAbilityId()=='A006'
endfunction

function NoSpell takes nothing returns nothing
    local unit wall=i2u(GetStoredInteger(udg_cache,I2S(h2i(GetExpiredTimer())),"wall"))
    call UnitRemoveBuffs(wall,true,true)
    set wall=null
endfunction

function UnSpell_Check takes nothing returns boolean
    local trigger t=GetTriggeringTrigger()
    local string st=I2S(h2i(t))
    local real x=GetStoredReal(udg_cache,st,"x")
    local real y=GetStoredReal(udg_cache,st,"y")
    local real x1=GetStoredReal(udg_cache,st,"x1")
    local real y1=GetStoredReal(udg_cache,st,"y1")
    local real xc=GetUnitX(GetTriggerUnit())
    local real yc=GetUnitY(GetTriggerUnit())
    local real xu=GetUnitX(GetSpellTargetUnit())
    local real yu=GetUnitY(GetSpellTargetUnit())
    call echo("CHECK")
 return IsLinesCrossed(x,y,x1,y1,xc,yc,xu,yu)
endfunction

function UnSpell takes nothing returns nothing
    call echo("SPELL")
endfunction

function Trig_Antimagic_wall_Actions takes nothing returns nothing
    local unit wall=CreateUnit(GetTriggerPlayer(),'h002',GetLocationX(GetSpellTargetLoc()),GetL  ocationY(GetSpellTargetLoc()),GetUnitFacing(GetTriggerUnit())-45)
    local timer ti=CreateTimer()
    local trigger spell=CreateTrigger()
    local string ss=I2S(h2i(spell))
    local real x=MoveX(GetUnitX(wall),300,GetUnitFacing(wall)-45)
    local real y=MoveY(GetUnitY(wall),300,GetUnitFacing(wall)-45)
    local real x1=MoveX(GetUnitX(wall),300,(GetUnitFacing(wall)-45)-180)
    local real y1=MoveY(GetUnitY(wall),300,(GetUnitFacing(wall)-45)-180)
    call StoreReal(udg_cache,ss,"x",x)
    call StoreReal(udg_cache,ss,"y",y)
    call StoreReal(udg_cache,ss,"x1",x1)
    call StoreReal(udg_cache,ss,"y1",y1)
    call TriggerRegisterAnyUnitEventBJ(spell,EVENT_PLAYER_UNIT_SPELL_CAST)
    call TriggerAddCondition(spell,Condition(function UnSpell_Check))
    call TriggerAddAction(spell,function UnSpell)
    call StoreInteger(udg_cache,I2S(h2i(ti)),"wall",h2i(wall))
    call TimerStart(ti,0.1,true,function NoSpell)
endfunction

function InitTrig_Antimagic_wall takes nothing returns nothing
    set gg_trg_Antimagic_wall=CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(gg_trg_Antimagic_wall,EVENT_PLAYER_UNIT_SPELL_EFFE  CT)
    call TriggerAddCondition(gg_trg_Antimagic_wall,Condition(function Trig_Antimagic_wall_Conditions))
    call TriggerAddAction(gg_trg_Antimagic_wall,function Trig_Antimagic_wall_Actions)
endfunction

и приставная функция пересечения(ну типа я задаю координаты а оно мне - пересеклись линии или нет):
Код:
function IsLinesCrossed takes real xb1,real yb1,real xe1,real ye1,real xb2,real yb2,real xe2,real ye2 returns boolean
local real a1=xe1-xb1
local real b1=ye1-yb1
local real a2=xe2-xb2
local real b2=ye2-yb2
local real p=((xb2-xb1)*b1-(yb2-yb1)*a1)/(a2*b1-a1*b2)
local real x=0
local real y=0
 if a2*b1-a1*b2!=0 then
   set x=xb2+a2*p
   set y=yb2+b2*p
 endif
return x>=RMinBJ(xb1,xe1) and x>=RMinBJ(xb2,xe2) and x<=RMaxBJ(xb1,xe1) and x<=RMaxBJ(xb2,xe2) and y>=RMinBJ(yb1,ye1) and y>=RMinBJ(yb2,ye2) and y<=RMaxBJ(yb1,ye1) and y<=RMaxBJ(yb2,ye2)
endfunction

но при запуске через стену у меня на екране появляется лишь CHECK a SPELL не хочет :( Что не так ?
Старый 18.04.2006, 18:58
YoGA

offline
Опыт: 243
Активность:
Попробуй в знаменателе p поменять местами произведения, т.е.
p = ((xb2 - xb1) * b1 - (yb2 - yb1) * a1) / (a1 * b2 - a2 * b1)
и еще, в твоем коде условие a2*b1-a1*b2!=0 нужно поставить в начале, т.е. если a2*b1-a1*b2==0,то выйти из функции, вернув false, а блок
set x=xb2+a2*p
set y=yb2+b2*p
сделать безусловным, но оставить в конце. Если условие в конце, то при a2*b1-a1*b2==0 знаменатель p станет равным 0 и возникнет ошибка.
Старый 19.04.2006, 13:20
Алексей
Где кошачья мята?!
offline
Опыт: 26,303
Активность:
В общем, ошибку искать лень, поэтому выкладываю тот алгоритм, который используется в MdlVis (для определения, пересекаются ли отрезки). Его основное достоинство заключается в том, что в нём нет ни единой операции деления (а значит, не нужны проверки на 0).
Код предварительно проверил (скопировал прямо из редактора триггеров WE), всё работает:
Код:
function Orient takes real ax, real ay, real bx, real by, real cx, real cy returns real
 return (ax-cx)*(by-cy)-(ay-cy)*(bx-cx)
endfunction

function IsLinesCrossed takes real ax1,real ay1,real ax2,real ay2,real bx1,real by1,real bx2,real by2 returns boolean
local real bb=Orient(ax1,ay1,ax2,ay2,bx2,by2)*Orient(ax1,ay1,ax2,ay2,bx1,by1)
local real ba=Orient(bx1,by1,ax2,ay2,ax1,ay1)*Orient(bx1,by1,ax2,ay2,bx2,by2)
local real ab=Orient(ax1,ay1,bx1,by1,bx2,by2)*Orient(ax1,ay1,bx1,by1,ax2,ay2)
return (bb<0) and (ba>0) and (ab>0)
endfunction

Как вы понимаете, (ax1,ay1)-(ax2,ay2) - первый отрезок, а (bx1,by1)-(bx2,by2) - второй. Причем без разницы, где у отрезков начало, а где конец (точки можно подавать в произвольном порядке).
Математические основы алгоритма излагать не буду (т.к. всё равно оно никому не нужно - лишь бы работало ;)). Скажу только, что тут не решается уравнение прямой, а просто анализируется взаимное расположение точек (чётность/нечётность перестановок).
Старый 19.04.2006, 15:19
exAres
I love magic :)
offline
Опыт: 7,788
Активность:
Алексей спасибо но я посмотрел на одном сайте... и сделал так
Код:
function IsLinesCrossed takes real xb1,real yb1,real xe1,real ye1,real xb2,real yb2,real xe2,real ye2 returns boolean
local real X=(ye1-yb1)*(xb2-xe2)-(yb2-ye2)*(xe1-xb1)
local real Y=(ye1-yb1)*(xb2-xb1)-(yb2-yb1)*(xe1-xb1)
local real Z=(yb2-yb1)*(xb2-xe2)-(yb2-ye2)*(xb2-xb1)
local real Ua=Y/X
local real Ub=Z/X
 return 0<=Ua and Ua<=1 and 0<=Ub and Ub<=1
endfunction

и всё работает так что тему можна закрыть.
Старый 19.04.2006, 19:02
NETRAT

offline
Опыт: 83,712
Активность:
MrSmiLe в точке с Х=0 функция срабатывать не будет - ибо деление на ноль, Алексей дело говорит

Гм, интересно, с такой проверкой не сталкивался, надо обмозговать...
Старый 20.04.2006, 02:40
Toadcop

offline
Опыт: 54,313
Активность:
NETRAT если раьлта с рилами то вероятность что будет ровно 0 практически не возможна ! хотя если так то можно ставить проверку если 0 то делать 1 и всё :)
Алексей - рульно ;)
Старый 20.04.2006, 14:40
Ответ

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы можете скачивать файлы

BB-коды Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход



Часовой пояс GMT +3, время: 09:39.