Проверить принадлежность точки области ограниченной двумя лучами
Пишу код на c# для задачки, не могу сообразить как проверить вхождение, когда область не ограничена:
Есть точка А (8;9). Из нее исходят два луча: один в сторону В (3;6) и второй в сторону С (10; 7). В заштрихованной области есть точка D (5;4).
Необходимо ответить на вопрос: точка (x, y) принадлежит ли той же области в которой лежит точка D.
Данные для теста:
- x = 1; y = 2; Ответ: true;
- x = 11; y = 12; Ответ: false;
Ответы (3 шт):
Составьте уравнения двух прямых: 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: Есть еще три случая, когда совпадают точки А и В, А и С, и А и В и С. Но их можно было бы и не рассматривать, т.к. противоречат условию (два луча), но в виде "защиты от дурака" их таки придется в программе рассмотреть. В обычном мат. решении их можно даже не упоминать.
Составляем векторы 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)
Поскольку в картинке и текстовом описании все координаты перепутаны, пример расчёта давать не буду (как на картинке - знаки будут + и -)
Ответ @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;
}
}
