У меня есть набор треугольников. Я ищу способ для найти все комбинации этих треугольников, которые образуют выпуклый корпус при объединении. Выпуклая оболочка должна быть пустой, т. Е. нет точек внутри выпуклой оболочки только на ребре. И только треугольники, которые разделяют сторону, могут быть соединены вместе, т.е. никаких пробелов в союзе.Комбинации треугольников, образующих выпуклый корпус
Пример: Следующие пункты дают 12 треугольников (триангуляция Делоне).
xy = [3.3735 0.7889; -0.1072 -3.4814; -3.9732 4.1955; -5 5; 5 5; 5 -5; -5 -5];
DT = delaunayTriangulation(xy);
triplot(DT);
%The coordinates for each triangle -- each row is a triangle.
TRIX = reshape(DT.Points(DT.ConnectivityList, 1), size(DT.ConnectivityList));
TRIY = reshape(DT.Points(DT.ConnectivityList, 2), size(DT.ConnectivityList));
Ищу крупнейшие выпуклые оболочки, поэтому выпуклая оболочка должна включать в себя как можно больше треугольников, как это возможно. Но если у меня есть все возможные комбинации, я могу легко отфильтровать те, у кого меньше треугольников. В примере сверху я должен закончить с этими шестью выпуклых оболочек:
Я предполагаю, что я должен использовать, что каждый треугольник имеет не более трех соседних треугольников (по одному на каждой стороне). И что я должен проверить, равна ли сумма угла меньше или равна 180 градусам в точках пересечения. Это гарантирует, что союз выпуклый - см. Рисунок ниже. (Угол может также быть ровно на 360 градусов, если несколько треугольников образуют полный круг).
треугольник Углы:
% Vectors connecting points
diffx = diff([TRIX TRIX(:,1)], [], 2); diffy = diff([TRIY TRIY(:,1)], [], 2); diffxy = [diffx(:) diffy(:)];
% Norm
normxy = reshape(arrayfun(@(row) norm(diffxy(row,:)), 1:size(diffxy,1)), size(DT.ConnectivityList));
nominator = repmat(sum(normxy.^2, 2), 1, 3) - 2*normxy.^2;
denominator = 2 * repmat(prod(normxy, 2), 1, 3)./normxy;
% Angle
tri_angle = acosd(nominator./denominator);
tri_angle = circshift(tri_angle, [0 -1]); % Shift so the angles match the correct point.
Я переформатировать информацию таким образом, что строки являются точками и столбцы треугольников:
n_tri = size(TRIX,1); % Number of triangles
% Adjacency matrix connecting points (rows) with triangles (columns).
adj_points = zeros(size(xy,1), n_tri);
adj_angle = NaN(size(adj_points));
for point =1:size(xy,1)
idx = find(DT.ConnectivityList == point);
[a_tri, ~] = ind2sub(size(DT.ConnectivityList), idx);
adj_points(point,a_tri) = 1;
adj_angle(point,a_tri) = tri_angle(idx);
end
Я цикл по всем краям и рассчитать углы по обеим сторонам края (edges angles
). Таким образом, я могу найти пары треугольников, образующих выпуклое множество (adj_convex
):
DT_edges = edges(DT); % All edges in the Delaunay triangulation
% Adjacency matrix connecting edges (rows) with triangles (columns).
adj_edge = logical(adj_points(DT_edges(:,1),:) .* adj_points(DT_edges(:,2),:));
edgesangles = NaN(size(DT_edges));
adj = zeros(n_tri); % Adjacency matrix indicating which triangles are neighbours.
adj_convex = zeros(n_tri);
for edge=1:size(DT_edges,1)
% The angles on either side of the edge.
tri = adj_edge(edge,:);
t = adj_angle(DT_edges(edge,:), tri);
edgesangles(edge,:) = sum(t, 2);
tri_idx = find(tri);
adj(tri_idx,tri_idx) = 1;
adj_convex(tri_idx,tri_idx) = prod(edgesangles(edge,:) <= 180);
end
convexedges = (edgesangles <= 180);
% Set diagonals to zero.
adj(logical(eye(n_tri))) = 0;
adj_convex(logical(eye(n_tri))) = 0;
Однако я не уверен, как поступить, если я хочу, чтобы все комбинации, или самый большой выпуклой оболочки. И я не уверен, как объяснить особый случай, когда несколько треугольников из полного круга (т.е. 360 градусов).
бы решения, которые не используют Делоне треугольники, но произвольные треугольники вместо действительными, а? Я вижу возможные решения для обоих, но обе проблемы очень разные. – Daniel
Из вашего описания я вижу больше, чем 6 найденных вами решений. Возможно, вы можете пометить точки/треугольники, чтобы мы могли говорить о решениях. – Daniel
Я не понимаю твое последнее предложение. Как несколько треугольников образуют полный круг? – Daniel