Просмотр полной версии : Алгоритмы Условие попадания точки внутрь прямоугольника
australian incognito
04.10.2015, 19:46
Господа, подскажите красивое решение для следующей задачки.
Дано: координаты центра прямоугольника, угол поворота прямоугольника, а также его ширина и высота. Также даны координаты точки. Необходимо составить лаконичное условие проверки - лежит ли точка внутри прямоугольника.
Как-то не гуглится совсем, хотя задачка с первого взгляда совсем простая.
Заранее спасибо.
Просто "поверните" точку на тот же угол и сравните её x,y с width,height.
Повернуть можно так:
1. Найти дистанцию точки от центра прямоугольника.
2. Получить новые x,y из дистанции, умноженной на косинус и синус нужного угла.
Ну а дальше, просто сравните эти x, y на выход за width, heigth соответственно.
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/questions/190111/how-to-check-if-a-point-is-inside-a-rectangle
вот вторая ссылка с другим решением
http://stackoverflow.com/questions/2752725/finding-whether-a-point-lies-inside-a-rectangle-or-not
третья
http://martin-thoma.com/how-to-check-if-a-point-is-inside-a-rectangle/
Могу накидать ещё)
Или подсказать что вбить в гугл ;)
australian incognito
04.10.2015, 21:33
Могу накидать ещё)
Или подсказать что вбить в гугл ;)
Все 3 ссылки ведут на решения такой же задачи, но при других вводных данных. Соответственно, имеют другие подходы и способы решения. Меня интересовал как раз такой простой способ, как был подсказан выше.
caseyryan
04.10.2015, 21:48
Здесь в теме не написано какие есть вводные данные и что из себя представляет этот прямоугольник
Хотя если тут прямоугольник, то рассчитать предворительно координаты его вершин, зная угол поворота, ширину и высоту, не составит никаких проблем. А дальше уже применить одно их этих решений
australian incognito
04.10.2015, 22:00
Здесь в теме не написано какие есть вводные данные и что из себя представляет этот прямоугольник
Хотя если тут прямоугольник, то рассчитать предворительно координаты его вершин, зная угол поворота, ширину и высоту, не составит никаких проблем. А дальше уже применить одно их этих решений
В заголовке не описано (да и не нужно), в теле моего сообщения точная задача с точными вводными данными.
Смысл мне вводить в алгоритм дополнительные рассчеты вершин, чтобы применить в итоге еще более ресурсоемкий подход?
Добавлено через 4 часа 20 минут
Проверил предложенный алгоритм, но что-то он у меня странно работает. В зависимости от угла поворота прямоугольника срабатывает либо только большая сторона, либо только меньшая. В итоге точка просчитывает попадание в радиус от сработавшей стороны.
Ниже приведу примерно то, как я это реализовывал, возможно, кто-то заметит ошибку:
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!")
}
Подскажите, где я запутался?
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!");
весь смысл - перевести систему координат точки - глобальную, в систему координат повернутого прямоугольника, а далее проверяем стандартным способом (по ширине и высоте прямоугольника)
australian incognito
05.10.2015, 22:11
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 минут
Задача решена!
Нужно было добавить несколько дополнительных действий в алгоритм:
// Найти угол по 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. Первое, что пришло в голову - просто менять угол на противоположный, т.е.
dotAng = -dotAng;
Однако данный подход работает только при определенных углах поворота прямоугольника и определенном направлении движения точки.
Может у кого-то созреют идеи в каком направлении можно еще "копать"...
Немного упростил алгоритм, что выше. Мне так понятнее, хоть и идея не изменилась.
var rAng:Number = 2;
var xBound = 50;
var yBound = 25;
var pDotNull:Point = new Point(mouseX, mouseY);
var pRecNull:Point = new Point(200, 200);
var dx:Number = pDotNull.x - pRecNull.x;
var dy:Number = pDotNull.y - pRecNull.y;
var sin:Number = Math.sin( rAng );
var cos:Number = Math.cos( rAng );
if ( Math.abs( cos * dx + sin * dy ) < xBound &&
Math.abs( cos * dy - sin * dx ) < yBound ) {
// inside !
} else {
// outside !
}
Мне лень искать, но прямоугольник - это два прямоугольных треугольника. А еще это две окружности вписанная в него, и та, в которую вписан он.
Работает на vBulletin ® версия 3.7.3. Copyright ©2000-2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Copyright © 1999-2008 Flasher.ru. All rights reserved.