Tuesday, December 20, 2011

Надоел Enterprise. Немного геометрии

Недавно наводил порядок в архивах и наткнулся на папку с диссертацией. покопался немного в исходниках матлаба и решил проверить рабочее ли все?

Взор у меня пал на скрипт Circles.m. Скажу честно код совершенно нечитабелен. И если бы его когдато написал не я то наверно я черти с два понял что там написано.

сценарий таков:

1. Есть изображение черно белое, какой то слитной фигуры, например самолета. Вот пример
2. Делаем над ним двумерное преобразование Гильберта. В результате мы получим точки в местах перегибов контура фигуры - назовем их характерными точками
3. А теперь геометрия. Задача найти центр масс слитной фигуры, в данном случае самолета, и провести концентрические окружности с центом в центре масс фигуры. Представить эти окружности как радар, и предположить что если характерная точка в пределах видимости радара, то засветить её. Должно получиться что то типа вот этого:
проблема в том что характерные точки вовсе не обязательно будут лежать на концентрических окружностях радар. Необходимо сделать допущение что если характерная точка в непосредственной близости от радара, то она засветится, как то вот так

черным цветом  обозначил светящиеся точки, не лучший вариант но тем не менее понятно вроде.

Теперь о реализации.

Писалось это очень давно и на скриптовом языке для научных вычислениях Matlab.

скрипт выглядит примерно так


for r = 10 : 10 : 130
        %рассчет координат точек окружности радара - 100 точек с радиусом r и центром в xr,yr
        circlePoints = calcCirclePoints(xr, yr, r, 100, 0);
        hold on
        plot(circlePoints(1,:), circlePoints(2,:), 'r-')
        hold on
        for i = 1 : length(arClasterData)
            d = sqrt((arClasterData(i,1) - xr)^2 + (arClasterData(i,2) - yr)^2);
            if d >= (r-1)
%уравнение прямой ax+b рассчитаем коэффициенты a и b для прямой проходящей от центра до характерной точки
[a, b] = calcLineKoef(xr, yr, arClasterData(i,1), arClasterData(i,2));
%а теперь рассчитаем расстояние от характерной точки до окружности радара
d = pointToCircleDist(arClasterData(i,1), arClasterData(i,2), xr, yr, r, a, b);
%если расстояние меньше 1 то засветим точку
                if d <= 1
                    hold on
                    plot(arClasterData(i,1), arClasterData(i,2),'k*')
                end
            end
        end
    end

Самой интересной функцией тут является на мой взгляд расчет расстояния от точки до окружности. Как известно это можно сделать с помощью касательной к окружности, а именно нахождения координат точки соприкосновения касательной и окружности и расчета Евклидова расстояния от этой точки до характерной точки. Сделал я это так


function d = pointToCircleDist(xp, yp, xr, yr, r, a, b)

switch checkCircleSector(xr, yr, xp, yp)
    case 1
        y = yr + r * sin(abs(atan(a)));
        x = xr + r * cos(abs(atan(a)));
    case 2
        y = yr + r * sin(pi - abs(atan(a)));
        x = xr + r * cos(pi - abs(atan(a)));
    case 3
        y = yr + r * sin(pi + abs(atan(a)));
        x = xr + r * cos(pi + abs(atan(a)));
    case 4
        y = yr + r * sin(2*pi - abs(atan(a)));
        x = xr + r * cos(2*pi - abs(atan(a)));
end
d = sqrt((xp - x)^2 + (yp - y)^2);

В зависимости от того в каком квандранте находится характерная точка, координаты точки касания рассчитываются по разному


Как то так. На мой взгляд интересно.

No comments: