我有一组三角形。我正在寻找一种方法来找到这些三角形的所有组合,这些三角形在连接在一起时构成凸包。凸包应该是空的,即。仅在边缘上的凸包内没有点。并且只有共享一条边的三角形可以连接在一起,即。工会没有缺口。
示例:以下几点给出了 12 个三角形(Delaunay 三角剖分)。
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度)的特殊情况。