Соедините точки и вычислите площадь - PullRequest
0 голосов
/ 02 октября 2009

это мой первый пост, поэтому, пожалуйста, будьте добры.

У меня есть матрица с 3 ~ 10 координатами, и я хочу соединить эти точки, чтобы получить полигон с максимальным размером.

Я пытался заполнить () [1], чтобы сгенерировать график, но как мне рассчитать площадь этого графика? Есть ли способ преобразования графика обратно в матрицу?

Что бы вы мне порекомендовали?

Заранее спасибо!

[1]

x1 = [ 0.0, 0.5, 0.5 ];
y1 = [ 0.5, 0.5, 1.0 ];
fill ( x1, y1, 'r' );

[обновление]

Спасибо за ваш ответ MatlabDoug, но я думаю, что я не сформулировал свой вопрос достаточно ясно. Я хочу соединить все этих точек, чтобы они стали полигоном с максимальным размером.

Есть новые идеи?

Ответы [ 4 ]

3 голосов
/ 02 октября 2009
 x1 = rand(1,10)
 y1 = rand(1,10)

 vi = convhull(x1,y1)
 polyarea(x1(vi),y1(vi))

 fill ( x1(vi), y1(vi), 'r' ); 
 hold on
 plot(x1,y1,'.')
 hold off

Здесь происходит то, что CONVHULL сообщает нам, какие вершины (vi) находятся на выпуклой оболочке (наименьший многоугольник, который охватывает все точки). Зная, какие из них находятся на выпуклом корпусе, мы спрашиваем у MATLAB область с POLYAREA.

Наконец, мы используем вашу команду FILL, чтобы нарисовать многоугольник, затем PLOT, чтобы поместить туда точки для подтверждения.

1 голос
/ 06 октября 2009

Я второе предложение Groovingandi попробовать все полигоны; вам просто нужно проверить правильность многоугольника (без самопересечений и т. д.).

Теперь, если вы хотите работать с большим количеством точек ... Как указал MatlabDoug, выпуклая оболочка - хорошее место для старта. Обратите внимание, что выпуклая оболочка дает многоугольник, площадь которого максимально возможна. Проблема, конечно, в том, что внутри корпуса могут быть точки, которые не являются частью многоугольника. Я предлагаю следующий жадный алгоритм, но я не уверен, гарантирует ли он полигон максимальной площади.

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

Given: Points P = {p1, ... pN}, convex hull H = {h1, ..., hM}
       where each h is a point that lies on the convex hull.
       H is a subset of P, and it is also ordered such that adjacent
       points in the list of H are edges of the convex hull, and the
       first and last points form an edge.
Let Q = H
while(Q.size < P.size)
    % For each point, compute minimum area triangle
    T = empty heap of triangles with value of their area
    For each P not in Q
        For each edge E of Q
            If triangle formed by P and E does not contain any other point
                Add triangle(P,E) with value area(triangle(P,E))
    % Modify the current polygon Q to carve out the triangle
    Let t=(P,E) be the element of T with minimum area
    Find the ordered pair of points that form the edge E within Q
    (denote them Pa and Pb)
    Replace the pair (Pa,Pb) with (Pa,E,Pb)

Теперь на практике вам не нужна куча для T, просто добавьте данные в четыре списка: один для P, один для Pa, один для Pb и один для области. Чтобы проверить, лежит ли точка внутри треугольника, вам нужно только проверить каждую точку на соответствие линиям, образующим стороны треугольника, и вам нужно только проверить точки, которых еще нет в Q. Наконец, чтобы вычислить площадь конечного многоугольника, вы можете триангулировать его (как с помощью функции delaunay, и суммировать площади каждого треугольника в триангуляции), или вы можете найти площадь выпуклой оболочки и вычесть области треугольников по мере их вырезания .

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

1 голос
/ 06 октября 2009

Вы сказали, что у вас есть только 3 ... 10 точек для подключения. В этом случае я предлагаю вам просто взять все возможные комбинации, вычислить области с полиарией и взять самую большую.

Только если ваше количество очков увеличивается или вам приходится часто его вычислять, чтобы время вычислений имело значение, стоит потратить некоторое время на лучший алгоритм. Однако я думаю, что сложно придумать алгоритм и доказать его полноту.

0 голосов
/ 06 октября 2009

Поиск правильного порядка очков - сложная часть, как прокомментировал Амро. Достаточно ли этой функции?

function [idx] = Polyfy(x, y)
% [idx] = Polyfy(x, y)
% Given vectors x and y that contain pairs of points, find the order that
% joins them into a polygon. fill(x(idx),y(idx),'r') should show no holes.

%ensure column vectors
if (size(x,1) == 1)
  x = x';
end
if (size(y,1) == 1)
  y = y';
end

% vectors from centroid of points to each point
vx = x - mean(x);
vy = y - mean(y);
% unit vectors from centroid towards each point
v = (vx + 1i*vy)./abs(vx + 1i*vy);
vx = real(v);
vy = imag(v);

% rotate all unit vectors by first
rot = [vx(1) vy(1) ; -vy(1) vx(1)];
v = (rot*[vx vy]')';

% find angles from first vector to each vector
angles = atan2(v(:,2), v(:,1));
[angles, idx] = sort(angles);
end

Идея состоит в том, чтобы найти центр тяжести точек, а затем найти векторы от центра тяжести до каждой точки. Вы можете думать об этих векторах как о сторонах треугольников. Многоугольник состоит из набора треугольников, где каждый вектор используется как «левый» и «правый» только один раз, и векторы не пропускаются. Это сводится к упорядочению векторов по углу вокруг центроида.

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

Это тестовая функция:

function [x, y] = TestPolyArea(N)
x = rand(N,1);
y = rand(N,1);
[indexes] = Polyfy(x, y);
x2 = x(indexes);
y2 = y(indexes);
a = polyarea(x2, y2);
disp(num2str(a));
fill(x2, y2, 'r');
hold on
plot(x2, y2, '.');
hold off
end

Вы можете получить довольно дикие картинки, передав N = 100 или около того!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...