Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   [Алгоритмы] Условие попадания точки внутрь прямоугольника (http://www.flasher.ru/forum/showthread.php?t=211628)

australian incognito 04.10.2015 19:46

Условие попадания точки внутрь прямоугольника
 
Господа, подскажите красивое решение для следующей задачки.
Дано: координаты центра прямоугольника, угол поворота прямоугольника, а также его ширина и высота. Также даны координаты точки. Необходимо составить лаконичное условие проверки - лежит ли точка внутри прямоугольника.

Как-то не гуглится совсем, хотя задачка с первого взгляда совсем простая.

Заранее спасибо.

Tails 04.10.2015 19:55

Просто "поверните" точку на тот же угол и сравните её x,y с width,height.
Повернуть можно так:
1. Найти дистанцию точки от центра прямоугольника.
2. Получить новые x,y из дистанции, умноженной на косинус и синус нужного угла.

Ну а дальше, просто сравните эти x, y на выход за width, heigth соответственно.

Код AS3:

var a:Number = 2.1; // Угол поворота прямоугольника в радианах
var p:Point = new Point(15, 90); // Координаты точки от центра прямоугольника
 
var dist:Number = Math.sqrt(p.x*p.x + p.y*p.y);
var p2:Point = new Point(Math.cos(a) * dist, Math.sin(a) * dist); // Координаты точки от центра прямоугольника, в "его" угле поворота.

Добавлено через 18 минут
А ещё, если у вас дисплей объекты, можно использовать их готовые методы:
globalToLocal(), localToGlobal()

australian incognito 04.10.2015 20:25

Очень круто, большое спасибо. К сожалению, это JS код (без удобных globalToLocal(), localToGlobal()), а я по-старинке хожу за советом на любимый форум.

caseyryan 04.10.2015 20:40

Цитата:

Как-то не гуглится совсем, хотя задачка с первого взгляда совсем простая.
Первая же ссылка в гугле сразу привела к решению
http://math.stackexchange.com/questi...de-a-rectangle
вот вторая ссылка с другим решением
http://stackoverflow.com/questions/2...ctangle-or-not
третья
http://martin-thoma.com/how-to-check...e-a-rectangle/
Могу накидать ещё)
Или подсказать что вбить в гугл ;)

australian incognito 04.10.2015 21:33

Цитата:

Сообщение от caseyryan (Сообщение 1187686)
Могу накидать ещё)
Или подсказать что вбить в гугл ;)

Все 3 ссылки ведут на решения такой же задачи, но при других вводных данных. Соответственно, имеют другие подходы и способы решения. Меня интересовал как раз такой простой способ, как был подсказан выше.

caseyryan 04.10.2015 21:48

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

australian incognito 04.10.2015 22:00

Цитата:

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

В заголовке не описано (да и не нужно), в теле моего сообщения точная задача с точными вводными данными.

Смысл мне вводить в алгоритм дополнительные рассчеты вершин, чтобы применить в итоге еще более ресурсоемкий подход?

Добавлено через 4 часа 20 минут
Проверил предложенный алгоритм, но что-то он у меня странно работает. В зависимости от угла поворота прямоугольника срабатывает либо только большая сторона, либо только меньшая. В итоге точка просчитывает попадание в радиус от сработавшей стороны.

Ниже приведу примерно то, как я это реализовывал, возможно, кто-то заметит ошибку:

Код AS3:

var rAng:Number = 0.24; // Угол поворота прямоугольника в радианах
var xBound = 20; // Ширина прямоугольника деленная на 2
var yBound = 60; // Высота прямоугольника деленная на 2
var pDotNull:Point = new Point(156, 91); // Координаты точки от начала координат
var pRecNull:Point = new Point(26, -11); // Координаты центра прямоугольника от начала координат
 
// Считаю относительные координаты точки по отношению к прямоугольнику
var pDotRect:Point = new Point(156 - 26, 91 + 11);
// Считаю расстояние
var dist:Number = Math.sqrt(130*130 + 102*102);
// Координаты точки по отношению к центру прямоугольника с учетом поворота прямоугольника
var p2:Point = new Point(Math.cos(rAng) * dist, Math.sin(rAng) * dist);
// Проверяю точку на условие попадания в прямоугольник
if(Math.abs(p2.x) <= xBound && Math.abs(p2.y) <= yBound)
{
trace("inside!")
}

Подскажите, где я запутался?

Tails 05.10.2015 10:30

Код AS3:

import flash.geom.Point;
 
 
var rAng:Number                = 2;                                                // Угол поворота прямоугольника в радианах
var xBound                                = 20;                                                // Ширина прямоугольника деленная на 2
var yBound                                = 60;                                                // Высота прямоугольника деленная на 2
var pDotNull:Point                = new Point(110, 110);                // Координаты точки от начала координат
var pRecNull:Point                = new Point(100, 110);                // Координаты центра прямоугольника от начала координат
 
var dx:Number                        = pRecNull.x - pDotNull.x;
var dy:Number                        = pRecNull.y - pDotNull.y;
var dist:Number                        = Math.sqrt(dx*dx + dy*dy);
 
var pDotResult:Point        = new Point(Math.cos(rAng) * dist, Math.sin(rAng) * dist);
if(pDotResult.x > xBound || pDotResult.x < -xBound || pDotResult.y > yBound || pDotResult.y < -yBound)
        trace("Outside!");
else
        trace("Inside!");


Isfet 05.10.2015 10:35

весь смысл - перевести систему координат точки - глобальную, в систему координат повернутого прямоугольника, а далее проверяем стандартным способом (по ширине и высоте прямоугольника)

australian incognito 05.10.2015 22:11

Цитата:

Сообщение от Tails (Сообщение 1187712)
Код AS3:

import flash.geom.Point;
 
 
var rAng:Number                = 2;                                                // Угол поворота прямоугольника в радианах
var xBound                                = 20;                                                // Ширина прямоугольника деленная на 2
var yBound                                = 60;                                                // Высота прямоугольника деленная на 2
var pDotNull:Point                = new Point(110, 110);                // Координаты точки от начала координат
var pRecNull:Point                = new Point(100, 110);                // Координаты центра прямоугольника от начала координат
 
var dx:Number                        = pRecNull.x - pDotNull.x;
var dy:Number                        = pRecNull.y - pDotNull.y;
var dist:Number                        = Math.sqrt(dx*dx + dy*dy);
 
var pDotResult:Point        = new Point(Math.cos(rAng) * dist, Math.sin(rAng) * dist);
if(pDotResult.x > xBound || pDotResult.x < -xBound || pDotResult.y > yBound || pDotResult.y < -yBound)
        trace("Outside!");
else
        trace("Inside!");


В вашем примере вроде как ничего не поменялось принципиально (при вычислении dx / dy не важно что от чего отнимать, а ваше условие такое же, как и у меня, только в обратную сторону...). Вообщем, ваш пример работает у меня точно так же как и мой - одна из сторон прямоугольника срабатывает как радиус...

Добавлено через 29 минут
Задача решена!

Нужно было добавить несколько дополнительных действий в алгоритм:
Код AS3:

// Найти угол по dx, dy
var ang = Math.atan2(dy, dx);
 
// При подсчете обновленных координат использовать разницу углов
var pDotResult:Point        = new Point(Math.cos(ang - rAng) * dist, Math.sin(ang - rAng) * dist);

Всем огромное спасибо за подсказки.
Может кому пригодится на будущее!

Добавлено через 49 минут
////////////////////////////////////////////////////////////////////////////////////////////////

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

P. S. Первое, что пришло в голову - просто менять угол на противоположный, т.е.
Код AS3:

dotAng = -dotAng;

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

Может у кого-то созреют идеи в каком направлении можно еще "копать"...


Часовой пояс GMT +4, время: 23:52.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.