Тест точки и эллипса (повернутый): алгоритм - PullRequest
13 голосов
/ 30 октября 2011

Как проверить, находится ли точка P = [xp, yp] внутри / снаружи какого-либо повернутого эллипса, заданного центром C = [x, y], a, b и phi (угол поворота)?

В данный момент я использую следующее решение: повернуть эллипс и точку на угол -phi, а затем общий тест для положения точки и «не повернутого» эллипса.

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

Мне не нужен код, но алгоритм. Спасибо за вашу помощь.

Ответы [ 5 ]

26 голосов
/ 29 мая 2013

Другой вариант - просто бросить все в уравнение для вращающегося 2D-эллипса и посмотреть, будет ли результат меньше единицы.

Таким образом, точка находится внутри эллипса, если верно следующее неравенство

ellipse equation

Где (xp, yp) - координаты точки, а (x0, y0)является центром эллипса.

Я реализовал небольшую Mathematica программу, демонстрирующую, что это действительно работает: Manipulate screen shot

Вот оно в действии:

Animation

А вот и код:

ellipse[x_, y_, a_, b_, \[Alpha]_, x0_: 0, y0_: 0] := 
     (((x - x0)*Cos[\[Alpha]] + (y - y0)*Sin[\[Alpha]])/a)^2
   + (((x - x0)*Sin[\[Alpha]] - (y - y0)*Cos[\[Alpha]])/b)^2;

Manipulate[
 RegionPlot[
  ellipse[x, y, a, b, \[Alpha] \[Degree], Sequence @@ pos] < 1, {x, -5, 5}, {y, -5, 5}, 
  PlotStyle -> If[ellipse[Sequence @@ p, a, b, \[Alpha] \[Degree], Sequence @@ pos] <= 1, Orange, LightBlue], 
  PlotPoints -> 25]
, {{a, 2}, 1, 5, Appearance -> "Labeled"}
, {{b, 4}, 2, 5, Appearance -> "Labeled"}
, {\[Alpha], 0, 180,  Appearance -> "Labeled"}
, {{p, {3, 1}}, Automatic, ControlType -> Locator}
, {{pos, {0, 0}}, Automatic, ControlType -> Locator}]
9 голосов
/ 30 мая 2013

Вы можете просто ввести свои данные в формулу, указанную выше. Вот реализация Python, которую я сделал по рекомендациям Ajasja:

def pointInEllipse(x,y,xp,yp,d,D,angle):
    #tests if a point[xp,yp] is within
    #boundaries defined by the ellipse
    #of center[x,y], diameter d D, and tilted at angle

    cosa=math.cos(angle)
    sina=math.sin(angle)
    dd=d/2*d/2
    DD=D/2*D/2

    a =math.pow(cosa*(xp-x)+sina*(yp-y),2)
    b =math.pow(sina*(xp-x)-cosa*(yp-y),2)
    ellipse=(a/dd)+(b/DD)

    if ellipse <= 1:
        return True
    else:
        return False
6 голосов
/ 30 октября 2011

Для работы с эллипсами я предпочитаю преобразовывать их в другую систему координат, где эллипс - это единичный круг с центром в начале координат.

Если вы видите эллипс как единичный круг (радиус 1), масштабированный (a, b), повернутый на фи и преобразованный на (x, y), тогда жизнь станет намного проще. Если у вас есть эта матрица преобразования, вы можете использовать ее для упрощения запроса сдерживания. Если вы преобразуете точку в систему координат, где эллипс является единичным кругом, все, что вам нужно сделать, - это тест окружности точка-единица, который является тривиальным. Если «transform» - это матрица, которая преобразует единичный круг в ваш эллипс, как описано, то

transformedPoint = transform.Invert().Transform(point);
pointInEllipse = transformedPoint.DistanceTo(0,0) < 1.0;
1 голос
/ 30 октября 2011

Вот алгоритм, я позволю вам разработать код:

  1. Определить вектор v1 между центром эллипса и вашей точкой
  2. Определить угол a1 между вектором v1 и xось в мировых координатах
  3. Отнимите фи от a1, чтобы получить a2, наш векторный угол в локальных координатах
  4. Определите точку P2 на эллипсе под углом a2 в локальных координатах, не смещенную на (x, y)
  5. Вычислить L1 и L2, длину вектора a1 и a2

Оценка:

  1. Если L1
  2. Если L1 = L2 (плюс / минус небольшой допуск), точка находится на эллипсе
  3. Если L2> L2, точка находится вне

Параметрическая формула эллипса:

x = a * cos (u)
y = b * sin (u)

действительно для u между -pi и + pi.Добавьте фи к вам, чтобы вращать свой эллипс.

Приведенный выше алгоритм может быть упрощен и оптимизирован из уравнений эллипса.

Удачи!

0 голосов
/ 24 октября 2014

Matplotlib имеет метод Ellipse в классе патчей, который позволяет вам задать вопрос, находится ли точка внутри или вне патча.Проверьте здесь и найдите метод contains_point ().Вам нужно будет создать эллипс с классом Ellipse, а затем, как если бы внутри была точка.Кстати, matplotlib - это пакет для Python.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...