Проверить принадлежность точки области ограниченной двумя лучами

Пишу код на c# для задачки, не могу сообразить как проверить вхождение, когда область не ограничена:

Есть точка А (8;9). Из нее исходят два луча: один в сторону В (3;6) и второй в сторону С (10; 7). В заштрихованной области есть точка D (5;4).

Необходимо ответить на вопрос: точка (x, y) принадлежит ли той же области в которой лежит точка D.

Данные для теста:

  1. x = 1; y = 2; Ответ: true;
  2. x = 11; y = 12; Ответ: false;

введите сюда описание изображения


Ответы (3 шт):

Автор решения: Zombotron
  • Составьте уравнения двух прямых: AB и AC

  • Подставьте в них координаты точек D и X - получите 4 числа: AB_D, AC_D, AB_X, AC_X

  • Если знаки AB_D и AB_X, а также AC_D и AC_X совпадают - D и X в одной области. Если какое-то число == 0, то соответствующая точка, на соответствующей прямой (особый случай 1)

  • Также возможны варианты, когда прямые AB и AC совпадают - точки A, B и C лежат на одной и той же прямой:

    • и на одной полупрямой (особый случай 2)
    • но на разных лучах (особый случай 3)
    • на разных лучах, параллельных OX и OY (особый случай 4)

Думаю, это поможет. Расписывать особые случаи нет желания, думаю, там не сложно.

Удачи. )

PS. А область таки ограничена. Лучами АВ, АС и отрезком несобственной прямой. ;)

upd: Есть еще три случая, когда совпадают точки А и В, А и С, и А и В и С. Но их можно было бы и не рассматривать, т.к. противоречат условию (два луча), но в виде "защиты от дурака" их таки придется в программе рассмотреть. В обычном мат. решении их можно даже не упоминать.

→ Ссылка
Автор решения: MBo

Составляем векторы B-A, C-A, D-A, и P-A для тестируемой точки P

bax = b.x - a.x, bay = b.y - a.y и т.д.

Смотрим знаки векторных произведений (P-A) x (B-A) и (P-A) x (С-A) - они должны совпадать с подобными знаками для точки D

sign(pax * bay - pay * bax), sign(pax * cay - pay * cax)

Поскольку в картинке и текстовом описании все координаты перепутаны, пример расчёта давать не буду (как на картинке - знаки будут + и -)

→ Ссылка
Автор решения: Aleksandr Sergeevich

Ответ @MBo на c#. Проверил 5ю тестами. Если Точка P в том же месте где и С, то она не засчитывается как вхождение. Возможно проверку на то лежит ли точка на лучах AB \ AC надо делать отдельно (мне это не требуется).

/// <summary> Калькулятор вхождения (принадлежнности) точки какому-то участку </summary>
public class PointEntryCalculator
{

    /// <summary> Принадлежит ли точка области ограниченной двумя лучами: https://i.stack.imgur.com/BkduV.png  Вопрос на стаке: https://ru.stackoverflow.com/q/1336594/285922 </summary>
    /// <param name="A"> Центр двух лучей </param>
    /// <param name="B"> Точка на которую смотрит первый луч </param>
    /// <param name="C"> Точка на которую смотрит второй луч  </param>
    /// <param name="D"> Точка которая находится на проверяемой территории </param>
    /// <param name="P"> Точка которую проверяем на принадленость территории, на которой так же находится D </param>
    /// <returns> True - если X принадленжит той же территоии, что и D </returns>
    public bool IsPointWithInD(Point A, Point B, Point C, Point D, Point P)
    {
        var CA_vector2D = GetPointsDifference(C, A);
        var BA_vector2D = GetPointsDifference(B, A);
        var PA_vector2D = GetPointsDifference(P, A);
        var DA_vector2D = GetPointsDifference(D, A);

        var signCrossProductPA_BA = Math.Sign(GetCrossProduct(PA_vector2D, BA_vector2D));
        var signCrossProductPA_CA = Math.Sign(GetCrossProduct(PA_vector2D, CA_vector2D));

        var signCrossProductDA_BA = Math.Sign(GetCrossProduct(DA_vector2D, BA_vector2D));
        var signCrossProductDA_CA = Math.Sign(GetCrossProduct(DA_vector2D, CA_vector2D));

        return signCrossProductPA_BA == signCrossProductDA_BA && signCrossProductPA_CA == signCrossProductDA_CA;
    }

    /// <summary> Получить произведения векторов </summary>
    private decimal GetCrossProduct(Vector2D first, Vector2D second) => first.ByX * second.ByY - first.ByY * second.ByX;

    /// <summary> Получить вектор: разность координат </summary>
    private Vector2D GetPointsDifference(Point first, Point second) => new Vector2D(first.X - second.X, first.Y - second.Y);
}


public struct Point
{
    public decimal X;
    public decimal Y;

    public Point(decimal x, decimal y)
    {
        X = x;
        Y = y;
    }
}


public struct Vector2D
{
    public decimal ByX;
    public decimal ByY;

    public Vector2D(decimal byY, decimal byX)
    {
        ByY = byY;
        ByX = byX;
    }
}
→ Ссылка