Некоторые элементарные задачи

Иногда бывает необходимо вычислить длину проекции радиус-вектора не на ось системы координат, а на другой радиус-вектор. Найдем длину проекции вектора Некоторые элементарные задачи - student2.ru на вектор Некоторые элементарные задачи - student2.ru . Эта ситуация изображена на рис. 7, из которого, очевидно, следует и решение задачи.

Некоторые элементарные задачи - student2.ru Искомая проекция: Некоторые элементарные задачи - student2.ru = Некоторые элементарные задачи - student2.ru = Некоторые элементарные задачи - student2.ru .

В случае тупого угла между векторами a и b значение Некоторые элементарные задачи - student2.ru в данном выражении будет отрицательным. Поэтому для получения длины проекции следует взять Некоторые элементарные задачи - student2.ru .

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

С помощью формулы длины проекции вектора на вектор можно еще одним способом получить уравнение плоскости, если заметить, что длины проекций радиус-векторов, принадле­жащих плоскости, на вектор нормали к плоскости всегда равны между собой.

Рассмотрим задачу нахождения ми­ни­мального расстояния от начала коор­динат до плоскости. Очевидно, что это расстояние необходимо откладывать вдоль прямой, определяемой вектором нормали к плоскости. Но для нахож­дения этого расстояния надо найти сначала точку пересечения прямой с плоскостью. Поэтому найдем вначале решение задачи нахождения точки пересечения прямой и плоскости. Обозначим искомую точку, или соответствующий ей радиус-вектор x. Тогда эта точка должна одновременно удовлетворять уравнениям прямой и плоскости, например, Некоторые элементарные задачи - student2.ru и Некоторые элементарные задачи - student2.ru , где Некоторые элементарные задачи - student2.ru и Некоторые элементарные задачи - student2.ru – базовый и направляющий векторы, а Некоторые элементарные задачи - student2.ru – вектор нормали к плоскости. Подставив x из первого уравнения во второе, найдем значение константы Некоторые элементарные задачи - student2.ru , которое затем подставим в исходное уравнение прямой для получения координат искомой точки:

Некоторые элементарные задачи - student2.ru Некоторые элементарные задачи - student2.ru Некоторые элементарные задачи - student2.ru

Уравнение прямой вдоль вектора нормали к плоскости запишем как Некоторые элементарные задачи - student2.ru , так как прямая проходит через начало координат и базовый вектор Некоторые элементарные задачи - student2.ru равен нулю. Перед тем как подставить в это уравнение выражение для Некоторые элементарные задачи - student2.ru , заметим, что направляющий вектор совпадает с вектором нормали Некоторые элементарные задачи - student2.ru . Учитывая это, запишем:

Некоторые элементарные задачи - student2.ru

Отсюда искомое расстояние от начала координат до плоскости равно

Некоторые элементарные задачи - student2.ru

Некоторые элементарные задачи - student2.ru
В том случае, когда вектор нормали Некоторые элементарные задачи - student2.ru является нормированным, т.е. его длина равна 1, константа Некоторые элементарные задачи - student2.ru в уравнении плоскости равна расстоянию от начала координат до данной плоскости.

Кроме определения положения точек в пространстве радиус-векторы также определяют направление в пространстве. Направление, определяемое радиус-вектором, удобно описывать с помощью, так называемых, направляющих косинусов. Пусть радиус-вектор Некоторые элементарные задачи - student2.ru составляет с осями координат Некоторые элементарные задачи - student2.ru , Некоторые элементарные задачи - student2.ru и Некоторые элементарные задачи - student2.ru углы, соответственно, Некоторые элементарные задачи - student2.ru и Некоторые элементарные задачи - student2.ru (рисунок 8). Тогда его направляющие косинусы равны:

Некоторые элементарные задачи - student2.ru , Некоторые элементарные задачи - student2.ru , Некоторые элементарные задачи - student2.ru

Отсюда, очевидно, вытекают следующие свойства направляющих косинусов:

Некоторые элементарные задачи - student2.ru .

Направляющие косинусы пропорциональны соответствующим координатам:

Некоторые элементарные задачи - student2.ru ,

а в случае, когда вектор Некоторые элементарные задачи - student2.ru нормирован, значения его координат равны соответствующим направляющим косинусам.

Уравнение плоскости можно представить как функцию трех переменных. Для этого в уравнении (5) перенесем константу из правой части в левую и запишем функцию трех переменных Некоторые элементарные задачи - student2.ru . Если подставить координаты точки, при­над­лежащей данной плоскости, в это уравнение, то Некоторые элементарные задачи - student2.ru . Если же точка не принадлежит плоскости, то значение функции, очевидно, будет больше или меньше нуля. Интересен тот факт, что для точек, лежащих по одну и ту же сторону от плоскости, функция Некоторые элементарные задачи - student2.ru имеет всегда один и тот же знак. С помощью чертежа на рисунке 9 , можно показать, что для точек, лежащих в полупространстве, порождаемом плоскостью и содержащем начало координат, функция Некоторые элементарные задачи - student2.ru отрицательна, а для точек, лежащих в другом полупространстве, как, например, для точки Некоторые элементарные задачи - student2.ru на рисунке, она положительна. В общем же случае необходимо учитывать направление вектора нормали.

Некоторые элементарные задачи - student2.ru Свойство сохранения знака функции Некоторые элементарные задачи - student2.ru удобно использовать в алгоритмах удаления невидимых ребер и граней для определения того, лежат ли точки по одну сторону от плоской грани или нет. Для этого достаточно лишь подставить значения координат точек в функциональное представление плоскости, определяемой соответствующей гранью, и проверить, совпадают знаки функции или нет. Аналогичные рассуждения можно провести и для более простого случая прямой на плоскости. Тогда для любой точки на плоскости можно определить ее нахождение в одной из полуплоскостей, на которые прямая делит плоскость. Это свойство используется в следующем примере.

Рассмотрим методы решения классической задачи определения принадлежности точки внутренней или граничной области треугольника на плоскости. Эта задача имеет, конечно, много решений, некоторые из которых может придумать и сам читатель. Здесь приводится четыре из более чем двадцати методов решения этой задачи, известных автору. Лучшим из них может считаться метод, допускающий самую быструю программную реализацию, и в первую очередь это относится к минимизации количества операций умножения и деления, не говоря уже о трансцендентных функциях, вроде квадратного корня или тригонометрических функций, для вычисления которых требуется разложение в ряд. В начале рассмотрим один из известных методов решения этой задачи.

Пусть на плоскости Некоторые элементарные задачи - student2.ru заданы три точки Некоторые элементарные задачи - student2.ru и Некоторые элементарные задачи - student2.ru , образующие треугольник (рис. 10). Некоторые элементарные задачи - student2.ru Через каждую пару вершин треугольника можно провести прямую. Ограниченная часть плоскости, образованная этими прямыми, есть внутренняя область треугольника. Если вектор нормали к прямой Некоторые элементарные задачи - student2.ru , то можно записать уравнение прямой на плоскости в виде: Некоторые элементарные задачи - student2.ru . По знаку функции Некоторые элементарные задачи - student2.ru можно определить нахождение произ­воль­ной точки с координатами Некоторые элементарные задачи - student2.ru в той или иной полуплоскости относительно данной прямой. Идея первого метода состоит в том, чтобы записать функциональные представ­ления уравнений прямых, образую­щих стороны треугольника, таким образом, чтобы внутренняя область треугольника соответствовала, например, отрицательным значе­ниям. Тогда условием принад­лежности внутренней области треугольника будут отрицательные значения трех функциональных уравнений прямых при подстановке координат проверяемой точки. Основной проблемой в этом методе является правильный выбор направления вектора нормали к прямой.

Некоторые элементарные задачи - student2.ru
Следующий метод, разработанный автором в 1991 году, основан на преобразовании треугольника с помощью операции переноса таким образом, чтобы проверяемая точка совпала с началом координат. Поворотом плоскости вокруг начала координат расположим одну (любую) из вершин треугольника на оси Некоторые элементарные задачи - student2.ru . Тогда если знаки координат Некоторые элементарные задачи - student2.ru оставшихся двух точек совпадают, то искомая точка лежит вне треугольника. Если же знаки различны, то берем следующую из оставшихся вершин треугольника и поворотом плоскости устанавливаем ее на ось Некоторые элементарные задачи - student2.ru . После чего вновь проверяем знаки координат Некоторые элементарные задачи - student2.ru двух других вершин, и т.д.

Условием принадлежности точки внутренней области треугольника будет несовпадение знаков Некоторые элементарные задачи - student2.ru ‑ координат оставшихся двух вершин после каждого из трех поворотов.

 
  Некоторые элементарные задачи - student2.ru

Нахождение точки на одной из сторон треугольника легко определяется по несовпадению знаков Некоторые элементарные задачи - student2.ru -координат двух вершин, которые после одного из поворотов оказались лежащими на оси Некоторые элементарные задачи - student2.ru . Этот метод эффективен, когда больше вероятность, что точка лежит вне треугольника. Отрицательной его чертой является необходимость вычисления синусов и косинусов углов при повороте системы координат.

Третий из приводимых здесь методов до 2005 года считался мною одним из наиболее компактных и скоростных с вычислительной точки зрения. Этот метод был предложен автору Д. Чистяковым в 1999 году. Заметим, что очень просто можно определить при­над­лежность точки внутренней области треугольника – единичного симплекса, то есть треугольника, образованного точками с координатами Некоторые элементарные задачи - student2.ru , Некоторые элементарные задачи - student2.ru , Некоторые элементарные задачи - student2.ru . Для этого достаточно чтобы координаты искомой точки имели значения в отрезке Некоторые элементарные задачи - student2.ru , и выполнялось условие Некоторые элементарные задачи - student2.ru , где Некоторые элементарные задачи - student2.ru и Некоторые элементарные задачи - student2.ru ‑ координаты точки. Заметим также, что с помощью аффинных преобразований и операций переноса или непрерывных деформаций любой треугольник можно преобразовать к единичному симплексу.

 
  Некоторые элементарные задачи - student2.ru

После таких преобразований внутренняя и внешняя области треугольника остаются таковыми. Применив такое преобразование к искомой точке, достаточно затем будет определить ее нахождение во внутренней или внешней области симплекса. Найдем такое преобразование. Координаты векторов единичного базиса совпадают с координатами точек Некоторые элементарные задачи - student2.ru и Некоторые элементарные задачи - student2.ru симплекса, соответственно. Будем считать, что точка Некоторые элементарные задачи - student2.ru треугольника совпадает с началом координат. Этого всегда можно добиться параллельным переносом треугольника на вектор Некоторые элементарные задачи - student2.ru . При этом координаты точек Некоторые элементарные задачи - student2.ru и Некоторые элементарные задачи - student2.ru треугольника суть коэффициенты разложения соответствующих векторов Некоторые элементарные задачи - student2.ru и Некоторые элементарные задачи - student2.ru по единичному базису. Матрица преобразования Некоторые элементарные задачи - student2.ru от единичного базиса к базису на векторах Некоторые элементарные задачи - student2.ru и Некоторые элементарные задачи - student2.ru составлена из координат этих векторов.

Некоторые элементарные задачи - student2.ru

Значит, для обратного перехода к единичному базису, (на векторах которого построен симплекс), необходимо найти обратную матрицу:

Некоторые элементарные задачи - student2.ru .

Умножение радиус-вектора искомой точки на матрицу Некоторые элементарные задачи - student2.ru дает точку, которую достаточно проверить на попадание во внутреннюю или внешнюю область единичного симплекса, как было указано выше.

Идея четвертого метода, без строгого математического доказательства, была предложена одним из моих студентов Д. Трагером в 2005 году. Этот метод немного похож на метод углов приведенный в [8] и превосходит по скорости выполнения все из выше упомянутых методов. После описания для него будет приведен текст процедуры на Delphi, написанный автором данной работы.

Некоторые элементарные задачи - student2.ru Рисунок 14. Последовательное измерение углов для получения разности Некоторые элементарные задачи - student2.ru .  

Зададим порядок обхода вершин и перенесем вершины треугольника и проверяемую точку так чтобы начало координат совпало с точкой A, например, как показано на рис. 14а. Конкретное направление обхода вершин треугольника, по или против часовой стрелки, не имеет значения. Рассмотрим углы Некоторые элементарные задачи - student2.ru и Некоторые элементарные задачи - student2.ru , как показано на Рис. 14a, b и c, где X – точка, проверяемая на принадлежность внутренней области треугольника.

Утверждается, что только в том случае когда точка X находится внутри треугольника, знак Некоторые элементарные задачи - student2.ru будет всегда совпадать для всех циклически выбираемых пар углов Некоторые элементарные задачи - student2.ru и Некоторые элементарные задачи - student2.ru при последовательном совмещении вершин треугольника с началом координат. Пусть вершинам треугольника A, B, C и проверяемой точке X соответствуют радиус-векторы Некоторые элементарные задачи - student2.ru , Некоторые элементарные задачи - student2.ru , Некоторые элементарные задачи - student2.ru и Некоторые элементарные задачи - student2.ru .

Найдем выражение, по которому можно легко вычислить знак Некоторые элементарные задачи - student2.ru .

Для ситуации, изображенной на Рис.14 a

Некоторые элементарные задачи - student2.ru

Очевидно, что знак Некоторые элементарные задачи - student2.ru совпадает со знаком числителя правой части. Таким образом, получаем, что знак левой части определяется выражением

Некоторые элементарные задачи - student2.ru ,

где Sign – функция получения знака числа. Аналогичные рассуждения для оставшихся двух случаев, изображенных на рисунках b и с, приводят, соответственно, к выражениям

Некоторые элементарные задачи - student2.ru

Некоторые элементарные задачи - student2.ru .

Доказательство правильности утверждения данного метода можно получить, если заметить, что знак Некоторые элементарные задачи - student2.ru не меняется при повороте плоскости относительно начала координат. Тогда, для каждого из трех случаев, изображенных на рисунках 14 a, b и c, соответствующими поворотами плоскости можно добиться того, чтобы угол Некоторые элементарные задачи - student2.ru был равен нулю, а оставшаяся часть треугольника, вместе с проверяемой точкой, оказалась бы выше или ниже оси ox, в зависимости от выбранного направления обхода вершин треугольника.

Рассмотрим версию функции InTri, в которой реализуется данный метод для целочисленных координат треугольника A=(AX,AY), B=(BX,BY), C=(CX,CY) и проверяемой точки X=(x,y). Функция выдает результат TRUE, если точка находится внутри или на границе треугольника (граница, таким образом, считается принадлежащей внутренней области треугольника), или FALSE, если точка находится за его пределами. Этой функцией удобно пользоваться если точки находятся на растровой сетке монитора, где координаты являются целыми числами.

function InTriI(x,y,AX,AY,BX,BY,CX,CY: Integer): boolean;

var

Res1,Res2: Integer;

begin

Res1:= (y-ay)*(cx-ax)-(x-ax)*(cy-ay);

Res2:= (y-cy)*(bx-cx)-(x-cx)*(by-cy);

// if (Res1>0)and(Res2<0)or(Res1<0)and(Res2>0) then

if Res1 XOR Res2 < 0 then

Result:= false //дальше не вычисляем

else

begin

Res2:= (y-by)*(ax-bx)-(x-bx)*(ay-by);

// if (Res1>0)and(Res2<0)or(Res1<0)and(Res2>0) then

if Res1 XOR Res2 < 0 then

Result:= false

else

Result:= true;

end;

end;

Обратите внимание на пару строк, которые дважды встречаются в тексте функции.

// if (Res1>0)and(Res2<0)or(Res1<0)and(Res2>0) then

if Res1 XOR Res2 < 0 then

Первая из двух строк специально закомментирована, так как вторая представляет собой ее оптимизированный вариант. Изначально в методе требуются действия, записанные в первой строке, где производится проверка на совпадение или несовпадение знаков вычисленных углов, что определяется переменными Res1 и Res2. Поскольку знак целого числа определяется его левым битом, точнее число считается отрицательным, если самый старший его бит равен 1, то он всегда будет равен единице при умножении двух чисел разного знака. Операцией целочисленного умножения здесь можно было бы воспользоваться, если бы операция XOR не давала аналогичный результат значительно быстрее. Код ассемблера, который генерирует Delpi, в случае использования операции XOR, примерно в 4 раза короче чем тот, что получается при использовании первой из двух рассмотренных нами строк на Паскале. Точнее, при включенной опции оптимизации компиляции в Delphi, вторая строка реализуется всего двумя инструкциями ассемблера, включая команду условного перехода. Но самое интересное, что аналогичный программный трюк можно применить и для вещественных входных параметров функции – типов Single и Double. Я не буду более вдаваться в технические тонкости, просто посмотрите текст функций. В случае вещественных входных параметров в них появляются небольшие отличия от целочисленного варианта.

Версия функции InTri для входных параметров типа Single.

function InTriS(x,y,AX,AY,BX,BY,CX,CY: Single): boolean;

var

Res1,Res2: Single;

ReI1: Integer absolute Res1;

ReI2: Integer absolute Res2;

begin

Res1:= (y-ay)*(cx-ax)-(x-ax)*(cy-ay);

Res2:= (y-cy)*(bx-cx)-(x-cx)*(by-cy);

// if (Res1>0)and(Res2<0)or(Res1<0)and(Res2>0) then

if ReI1 XOR ReI2 < 0 then

Result:= false //дальше не вычисляем

else

begin

Res2:= (y-by)*(ax-bx)-(x-bx)*(ay-by);

// if (Res1>0)and(Res2<0)or(Res1<0)and(Res2>0) then

if ReI1 XOR ReI2 < 0 then

Result:= false

else

Result:= true;

end;

end;//function InTriS

Версия функции InTri для входных параметров типа Double.

function InTriD(x,y,AX,AY,BX,BY,CX,CY: Double): boolean;

var

Res1,Res2: Double;

ReI1: Int64 absolute Res1;

ReI2: Int64 absolute Res2;

begin

Res1:= (y-ay)*(cx-ax)-(x-ax)*(cy-ay);

Res2:= (y-cy)*(bx-cx)-(x-cx)*(by-cy);

// if (Res1>0)and(Res2<0)or(Res1<0)and(Res2>0) then

if ReI1 XOR ReI2 < 0 then

Result:= false //дальше не вычисляем

else

begin

Res2:= (y-by)*(ax-bx)-(x-bx)*(ay-by);

// if (Res1>0)and(Res2<0)or(Res1<0)and(Res2>0) then

if ReI1 XOR ReI2 < 0 then

Result:= false

else

Result:= true;

end;

end;//function InTriD

В результате, как можно видеть по тексту приведенных процедур, задача решается в худшем случае за 6 операций умножения и 15 операций вычитания, а в лучшем случае всего за 4 операции умножения и 10 операций вычитания.

Наши рекомендации