реклама на сайте
подробности

 
 
3 страниц V   1 2 3 >  
Reply to this topicStart new topic
> Геометрическая задачка - определить принадлежность точки к треугольнику в гексагоне, Подскажите алгоритм, а то запутался
syoma
сообщение Feb 5 2010, 10:58
Сообщение #1


Профессионал
*****

Группа: Свой
Сообщений: 1 817
Регистрация: 14-02-07
Из: наших, которые работают за бугром
Пользователь №: 25 368



Народ подскажите пожалуйста, может кто с геометрией на "ты", как проще решить следующую задачу.
Есть правильный шестиугольник разбитый на равносторонние треугольники как на рисунке.
Прикрепленное изображение


Координаты некоторых точек я указал. Все пляшет от величины а - расстояния от центра до удаленной вершины.
И есть точка с координатами x,y которая находится где-то в гексагоне. Задача - определить, в каком треугольнике 1-24 она находится.
Возможно Вы скажете "просто", но есть ограничения - задача будет решаться на микроконтроллере, поэтому просто "взять тангенс от x/y" и т.д. не получится. Умножать на любое число и делить на константу можно, но корень, тригонометр функции и деление на число - нельзя. Число а - сравнительно медленно измеряемая величина, поэтому от нее корень и деление можно использовать.
Пока есть и работает алгоритм определения треугольников 1-18, но с добавлением внутренних треугольников - проблема.
Вот как я делаю:
Код
%% Quarter calculation and rotation
if X<0
    X=-X;
    Xinv=1;
else
    Xinv=0;
end
if Y<0
    Y=-Y;
    Yinv=1;
else
    Yinv=0;
end


%% Triangle calculation

Xshift=X-a/4;

if (Y<(a*sqrt(3)/4)) %If Y less than half height then point is in triangle 1 or 2
    Yshift=Y+a*sqrt(3)/4;
    if (Yshift>sqrt(3)*Xshift)
        triangle=2;
    else
        triangle=1;
    end
else %otherwise it is in triangles 3, 4 or 5
    Yshift=Y-a*sqrt(3)/4;
    if (Xshift==0)
        triangle=4;
    else
        if (Xshift<0)
            if Yshift>(-sqrt(3))*Xshift
                triangle=4;
            else
                triangle=5;
            end
        else
            if (Yshift>sqrt(3)*Xshift)
                triangle=4;
            else
                triangle=3;
            end
        end
    end
end

Таким образом я разбираюсь только с одной четвертью, а остальные треугольники получаю, просто поворачивая координаты точки.
Go to the top of the page
 
+Quote Post
Tanya
сообщение Feb 5 2010, 11:18
Сообщение #2


Гуру
******

Группа: Модераторы
Сообщений: 8 752
Регистрация: 6-01-06
Пользователь №: 12 883



Цитата(syoma @ Feb 5 2010, 13:58) *
Народ подскажите пожалуйста, может кто с геометрией на "ты", как проще решить следующую задачу.

Один из вариантов. Рассмотрим приведение в 1-ю четверть.
Находите квадраты расстояния от центров правильных треугольничков до Вашей точки - их всего 7.
Минимум определяет искомое.
Go to the top of the page
 
+Quote Post
ukpyr
сообщение Feb 5 2010, 12:30
Сообщение #3


Профессионал
*****

Группа: Участник
Сообщений: 1 264
Регистрация: 17-06-08
Из: бандустан
Пользователь №: 38 347



http://local.wasp.uwa.edu.au/~pbourke/geometry/insidepoly/
http://www.ecse.rpi.edu/Homepages/wrf/Rese...tes/pnpoly.html
Go to the top of the page
 
+Quote Post
scifi
сообщение Feb 5 2010, 12:31
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Мне кажется, тут нужно перейти от прямоугольного базиса к "косому" (вдоль сторон треугольников) - это простое линейное преобразование координат. В новых координатах задача будет значительно проще: треугольники превратятся в половинки квадратов.
Go to the top of the page
 
+Quote Post
тау
сообщение Feb 5 2010, 16:28
Сообщение #5


.
******

Группа: Участник
Сообщений: 2 424
Регистрация: 25-12-08
Пользователь №: 42 757



Умножаем все по оси Х на sqrt(3). В том числе координату "x" искомой точки.
Получаем систему координат где треугольники превратились в прямоугольные. Приводим все в 1-й квадрант .
Нормализуем размеры фигуры к разрядности вычислений и координаты точки тоже .

Старшие 2 разряда по Х и 1 разряд по Y определяют большой квадрат (например зеленый).
следующие 2 бита после них по одному разряду от Х и Y определяют квадрант внутри зеленого квадрата. При 00 или 11 ответ сразу виден. Иначе повторяем еще по одному разряду, пока те не кончатся smile.gif .

Сообщение отредактировал тау - Feb 5 2010, 16:44
Эскизы прикрепленных изображений
Прикрепленное изображение
 
Go to the top of the page
 
+Quote Post
syoma
сообщение Feb 5 2010, 16:51
Сообщение #6


Профессионал
*****

Группа: Свой
Сообщений: 1 817
Регистрация: 14-02-07
Из: наших, которые работают за бугром
Пользователь №: 25 368



Цитата
Умножаем все по оси Х на sqrt(3). В том числе координату "x" искомой точки.
Получаем систему координат где треугольники превратились в прямоугольные.
Нормализуем размеры фигуры к разрядности вычислений одновременно с координатой Х.

Этот прикол мне нравится - что-то интересненькое уже вырисовывается.
Но
Цитата
Иначе повторяем еще по одному разряду, пока те не кончатся

Не подойдет - итерации мне не подходят. Надо чтобы раз и все.

Вот в IEEE нашел статейку, где все предлагают перевести в X'=3*X/2, a Y'=sqrt(3)*Y. Помоему идея та же, но не пойму, что получится.
Go to the top of the page
 
+Quote Post
тау
сообщение Feb 5 2010, 17:17
Сообщение #7


.
******

Группа: Участник
Сообщений: 2 424
Регистрация: 25-12-08
Пользователь №: 42 757



IF-ы ничем не лучше итераций, суть одна. Можете развернуть итерации в IF-ы,
Бэйсик непонятно зачем используете. Тут бы си/асм для быстроты
Go to the top of the page
 
+Quote Post
Guest_@Ark_*
сообщение Feb 5 2010, 22:55
Сообщение #8





Guests






Я бы так решил эту задачу: Провел бы через все вершины треугольников горизонтальные и вертикальные линии (горизонтальные уже проведены). В итоге - получится 28 прямоугольников. Принадлежность точки к конкретному прямоугольнику определяется по ее координатам X и Y. Такой прямоугольник всегда делится диагональю на две области, принадлежащие двум треугольникам. Остается определить по специально составленной таблице тип прямоугольника - из частей каких треугольников он состоит, как идет его диагональ и установить расположение точки относительно ее...
P.S. Может, не совсем понятно объяснил, но программно все это можно выполнить с помощью только табличных функций, сложений и сравнений, не пребегая даже к умножению...
Go to the top of the page
 
+Quote Post
ReAl
сообщение Feb 6 2010, 00:52
Сообщение #9


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Имеем три системы прямых - горизонтальные, наклонные "левые" и "правые".
Если в каноническое уравнение прямой A*x + B*y + C = 0 подставить координаты конкретной точки (x,y), то по результату A*x + B*y + C можно выяснить, лежит точка на прямой (0), под ней (>0) или над ней (<0).

Для каждой системы прямых можно идти сверху от прямой к прямой и искать смену знака - т.е. искать прямую, "как раз над которой" находится точка. По трём номерам прямых однозначно определяетя где находится точка (ну тм с нулями, конгда точка на прямой - нужно просто решить заранее, как это интерпретировать, вылбется в > или >= при сравнениях с 0).
Например, если взять только "косые" прямые, то определяется "вертикальный" ромб, в котором лежит точка, по горизонтальной прямой выясняется в каком из двух треугольников точка.

Ну для горизонтальных прямых достаточно поделить y точки на шаг между прямыми.

Ха - как вариант - int(y/шаг) - это номер прямой для горизонтальных линий.
Теперь поворачиваем точку на 60 градусов влево и вправо и для y-ка новой точки так же делением на шаг выясняем номер. Дальше при помощи этих трёх номеров из фикисрованного 3-мерного массива вынимаем номер треугольника.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
ALEKSIU
сообщение Feb 6 2010, 07:41
Сообщение #10


Участник
*

Группа: Участник
Сообщений: 22
Регистрация: 29-07-08
Пользователь №: 39 270



Подобную задачу принадлежности точки треугольника решал следующим образом.
любую точку в плоскости треугольника можно выразить симплексные координаты (a,b,c), как это сделать можно найти почни в люьой книге по МКЭ. Если точка принадлежит треугольнику, то |a|+|b|+|c|=1.
Go to the top of the page
 
+Quote Post
Миша Т
сообщение Feb 6 2010, 12:04
Сообщение #11


Участник
*

Группа: Участник
Сообщений: 17
Регистрация: 29-08-08
Из: СПб
Пользователь №: 39 876



Цитата(ALEKSIU @ Feb 6 2010, 10:41) *
Подобную задачу принадлежности точки треугольника решал следующим образом.
любую точку в плоскости треугольника можно выразить симплексные координаты (a,b,c), как это сделать можно найти почни в люьой книге по МКЭ. Если точка принадлежит треугольнику, то |a|+|b|+|c|=1.


Любопытно. Так, видимо, проще всего.

Вариант реализации:
если (Xa,Ya) (Xb,Yb) (Xc, Yc) --- координаты точек A, B, C, (X,Y) координаты точки, то
a=( (Yb-Yc)*(X-Xc)+(Xc-Xb)*( Y-Yc) )/ ( (Yb-Yc)*(Xa-Xc)+(Xc-Xb)*( Ya-Yc) )
b =( (Yc-Ya)*(X-Xc)+(Xa-Xb)*( Y-Yc) )/ ( (Yb-Yc)*(Xa-Xc)+(Xc-Xb)*( Ya-Yc) )
c = 1 - a - b
условие принадлежности треугольнику a >= 0, b >= 0, c>= 0 (ноль, если оказались на границе).

для ускорения работы программы, можно задать 6 массивов: Xa[24], Ya[24], Xb[24], ... --- координаты вершин треугольника (это, конечно занудно), и массив C[24][4] в котором для каждого из треугольников задать константы:
Код
    for(i=0; i < 24; i++)
    {
        C[i][0]= (Yb[i]-Yc[i])/( (Yb[i]-Yc[i])*(Xa[i]-Xc[i])+(Xc[i]-Xb[i])*( Ya[i]-Yc[i]) );
        C[i][1]= (Xc[i]-Xb[i])/( (Yb[i]-Yc[i])*(Xa[i]-Xc[i])+(Xc[i]-Xb[i])*( Ya[i]-Yc[i]) );
        C[i][2]= (Yc[i]-Ya[i])/( (Yb[i]-Yc[i])*(Xa[i]-Xc[i])+(Xc[i]-Xb[i])*( Ya[i]-Yc[i]) );
        C[i][3]= (Xa[i]-Xb[i])/( (Yb[i]-Yc[i])*(Xa[i]-Xc[i])+(Xc[i]-Xb[i])*( Ya[i]-Yc[i]) );
    }

И в цикле проверить
Код
    i=0;
    do {
        a = C[i][0]*(X-Xc[i])+C[i][1]*(Y-Yc[i]);
        b = C[i][2]*(X-Xc[i])+C[i][3]*(Y-Yc[i]);
        c = 1 - a - b;
        i++;
    }while ( !( (a >= 0) && (b >=0) && (c>=0) ) )
    return i;

PS Исходные коды на С
PPS В арифметике мог лажануться))) (хотя, вряд ли)
Go to the top of the page
 
+Quote Post
ALEKSIU
сообщение Feb 6 2010, 12:35
Сообщение #12


Участник
*

Группа: Участник
Сообщений: 22
Регистрация: 29-07-08
Пользователь №: 39 270



Цитата(Миша Т @ Feb 6 2010, 16:04) *
для ускорения работы программы, можно задать 6 массивов: Xa[24], Ya[24], Xb[24], ... --- координаты вершин треугольника (это, конечно занудно), и массив C[24][4] в котором для каждого из треугольников задать константы:


Именно так когда-то и делал
Go to the top of the page
 
+Quote Post
syoma
сообщение Feb 6 2010, 17:34
Сообщение #13


Профессионал
*****

Группа: Свой
Сообщений: 1 817
Регистрация: 14-02-07
Из: наших, которые работают за бугром
Пользователь №: 25 368



Цитата(тау @ Feb 5 2010, 20:17) *
Бэйсик непонятно зачем используете. Тут бы си/асм для быстроты

Это не бейсик, а матлаб - я в нем моделирую сперва, а потом переношу на МК. Так можно все проверить а потом быстрее отлаживать.
Go to the top of the page
 
+Quote Post
тау
сообщение Feb 6 2010, 21:26
Сообщение #14


.
******

Группа: Участник
Сообщений: 2 424
Регистрация: 25-12-08
Пользователь №: 42 757



Вот еще проще способ.
координаты X точки модифицируете
X'=X+Y/sqrt(3)
Y'=Y*2/sqrt(3)
или , что то-же самое , если есть куда расти:
X''=X*sqrt(3) +Y
Y'"=Y*2
Образуется наклоненная фигура в прямоугольной системе отсчета, как на рисунке.
Переносите начало системы координат в левый нижний угол фигуры , добавлением (а) к X'' и Y''
Теперь пронормализовать X'' и Y'' к размеру всей фигуры (2*а) относительно новой системы координат
и старшие разряды (по два разряда от X'' и Y'' ) будут определять номер квадратика во всей фигуре ( а не только в четверти)
Останется определить к какому треугольнику внутри квадратика относится точка. Для этого накладываете нулевую маску на 2 старших разряда X'' и Y'' (которые определяли номер квадратика). Оставшиеся величины при сравнении покажут к верхнему (X'' < Y'') или нижнему (X''>Y'') треугольнику относится точка.

Впрочем, этом метод и был предложен scifi

Сообщение отредактировал тау - Feb 6 2010, 21:32
Эскизы прикрепленных изображений
Прикрепленное изображение
 
Go to the top of the page
 
+Quote Post
blackfin
сообщение Feb 8 2010, 06:30
Сообщение #15


Гуру
******

Группа: Свой
Сообщений: 3 106
Регистрация: 18-04-05
Пользователь №: 4 261



Цитата(syoma @ Feb 5 2010, 19:51) *
Не подойдет - итерации мне не подходят. Надо чтобы раз и все.

Если нужно, чтобы "раз и все", можно воспользоваться трехмерным массивом:
Код
TRIANGLES[2][4][4] =
{
    {
        { 9,12,13, 0},
        { 8,21,14,15},
        { 0,20,19,16},
        { 0, 0, 2, 1}
    },
    {
        {10,11, 0, 0},
        { 7,22,23, 0},
        { 6, 5,24,17},
        { 0, 4, 3,18}
    }
};


Пусть:

P - точка на плоскости в координатах X,Y.

A - вектор направленный вдоль оси Y и имеющий длину равную 1/H.
B - вектор направленный под углом плюс 30° к оси X и имеющий длину равную 1/H.
C - вектор направленный под углом минус 30° к оси X и имеющий длину равную 1/H.

где, H - высота треугольника равная H = a*cos(30°)/2.

Вычисляем целое значение для трех скалярных произведений:

COMPA = (int)<P,A> = (int)(X*0+Y*(1/H)) = (int)(Y*(2/a)/cos(30°)).
COMPB = (int)<P,B> = (int)(X*cos(30°)*(1/H)+Y*sin(30°)*(1/H)) = (int)(X*(2/a)+Y*(2/a)*tg(30°)).
COMPC = (int)<P,C> = (int)(X*cos(30°)*(1/H)-Y*sin(30°)*(1/H)) = (int)(X*(2/a)-Y*(2/a)*tg(30°)).

Вычисляем значение индексов массива:

INDEXA = COMPA & 1;
INDEXB = COMPB + 2;
INDEXC = COMPC + 2;

Тогда номер треугольника:

N = TRIANGLES[INDEXA][INDEXB][INDEXC].

На Си это можно записать так:
Код
#define a 1.0

TRIANGLES[2][4][4] =
{
    {
        { 9,12,13, 0},
        { 8,21,14,15},
        { 0,20,19,16},
        { 0, 0, 2, 1}
    },
    {
        {10,11, 0, 0},
        { 7,22,23, 0},
        { 6, 5,24,17},
        { 0, 4, 3,18}
    }
};

int
num(double X,double Y)
{
    int COMPA = (int)(Y*(2/a)/cos(30°));
    int COMPB = (int)(X*(2/a)+Y*(2/a)*tg(30°));
    int COMPC = (int)(X*(2/a)-Y*(2/a)*tg(30°));

    int INDEXA = COMPA & 1;
    int INDEXB = COMPB + 2;
    int INDEXC = COMPC + 2;

    return TRIANGLES[INDEXA][INDEXB][INDEXC];
}
Go to the top of the page
 
+Quote Post

3 страниц V   1 2 3 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 12:06
Рейтинг@Mail.ru


Страница сгенерированна за 0.01512 секунд с 7
ELECTRONIX ©2004-2016