例如,使用下面的代码,我有一个坐标矩阵,其中3个立方体对象各自由8个角定义,总共24个坐标。我对我的坐标应用旋转,然后删除y坐标以获得x-z平面中的投影。如何在x-z平面中计算这些立方体的面积,忽略间隙并考虑重叠?我尝试过使用polyarea
,但这似乎不起作用。
clear all
clc
A=[-100 -40 50
-100 -40 0
-120 -40 50
-120 -40 0
-100 5 0
-100 5 50
-120 5 50
-120 5 0
-100 0 52
-100 0 52
20 0 5
20 0 5
-100 50 5
-100 50 5
20 50 52
20 50 52
-30 70 53
-30 70 0
5 70 0
5 70 53
-30 120 53
-30 120 0
5 120 53
5 120 0]; %3 Buildings Coordinate Matrix
theta=60; %Angle
rota = [cosd(theta) -sind(theta) 0; sind(theta) cosd(theta) 0; 0 0 1]; %Rotation matrix
R=A*rota; %rotates the matrix
R(:,2)=[];%deletes the y column
答案 0 :(得分:3)
第一步是使用convhull
(作为yar suggests)来获取每个投影多边形区域的轮廓。应该注意的是,凸起的船体适合在这里使用,因为你正在处理长方体,它们是凸起的物体。我认为你的第二个长方体的坐标有错误(位于A(9:16, :)
),所以我将你的代码修改为以下内容:
A = [-100 -40 50
-100 -40 0
-120 -40 50
-120 -40 0
-100 5 0
-100 5 50
-120 5 50
-120 5 0
-100 0 52
-100 0 5
20 0 52
20 0 5
-100 50 5
-100 50 52
20 50 5
20 50 52
-30 70 53
-30 70 0
5 70 0
5 70 53
-30 120 53
-30 120 0
5 120 53
5 120 0];
theta = 60;
rota = [cosd(theta) -sind(theta) 0; sind(theta) cosd(theta) 0; 0 0 1];
R = A*rota;
您可以生成多边形轮廓并将其可视化:
nPerPoly = 8;
nPoly = size(R, 1)/nPerPoly;
xPoly = mat2cell(R(:, 1), nPerPoly.*ones(1, nPoly));
zPoly = mat2cell(R(:, 3), nPerPoly.*ones(1, nPoly));
C = cell(1, nPoly);
for iPoly = 1:nPoly
P = convhull(xPoly{iPoly}, zPoly{iPoly});
xPoly{iPoly} = xPoly{iPoly}(P);
zPoly{iPoly} = zPoly{iPoly}(P);
C{iPoly} = P([1:end-1; 2:end].')+nPerPoly.*(iPoly-1); % Constrained edges, needed later
end
figure();
colorOrder = get(gca, 'ColorOrder');
nColors = size(colorOrder, 1);
for iPoly = 1:nPoly
faceColor = colorOrder(rem(iPoly-1, nColors)+1, :);
patch(xPoly{iPoly}, zPoly{iPoly}, faceColor, 'EdgeColor', faceColor, 'FaceAlpha', 0.6);
hold on;
end
axis equal;
axis off;
这是情节:
如果你想计算每个多边形投影的面积并将它们相加,那将非常简单:只需更改上面的循环即可捕获并汇总调用convexhull
的第二个输出:
totalArea = 0;
for iPoly = 1:nPoly
[~, cuboidArea] = convhull(xPoly{iPoly}, zPoly{iPoly});
totalArea = totalArea+cuboidArea;
end
然而,如果您想要多边形的 union 区域,则必须考虑重叠。你有几个选择。如果您拥有Mapping Toolbox,则可以使用函数polybool
获取大纲,然后使用polyarea
计算其区域。您还可以在MathWorks File Exchange上找到实用工具(例如this和this)。我将在这里向您展示另一种使用delaunayTriangulation
的替代方法。首先,我们可以采用上面创建的边缘约束C
来创建投影点的三角剖分时使用:
oldState = warning('off', 'all');
DT = delaunayTriangulation(R(:, [1 3]), vertcat(C{:}));
warning(oldState);
这将自动创建约束边相交的新顶点。不幸的是,它还将在所有点的凸包上执行三角测量,填充我们不想填充的点。这是三角测量的样子:
figure();
triplot(DT, 'Color', 'k');
axis equal;
axis off;
我们现在必须确定我们不想要的额外三角形并将其删除。我们可以通过找到每个三角形的质心并使用inpolygon
测试它们是否在我们所有3个单独的长方体投影之外来做到这一点。然后我们可以计算剩余三角形的面积并使用polyarea
对它们求和,得出投影的总面积:
dtFaces = DT.ConnectivityList;
dtVertices = DT.Points;
meanX = mean(reshape(dtVertices(dtFaces, 1), size(dtFaces)), 2);
meanZ = mean(reshape(dtVertices(dtFaces, 2), size(dtFaces)), 2);
index = inpolygon(meanX, meanZ, xPoly{1}, zPoly{1});
for iPoly = 2:nPoly
index = index | inpolygon(meanX, meanZ, xPoly{iPoly}, zPoly{iPoly});
end
dtFaces = dtFaces(index, :);
xUnion = reshape(dtVertices(dtFaces, 1), size(dtFaces)).';
yUnion = reshape(dtVertices(dtFaces, 2), size(dtFaces)).';
totalArea = sum(polyarea(xUnion, yUnion));
此示例的总面积为:
totalArea =
9.970392341143055e+03
注意:以上代码已针对任意数量的长方体进行了推广。
答案 1 :(得分:1)
polyarea
是正确的方法,但您需要在每个投影的es6 string interpolation上调用它。如果没有,您将在投影的中心有点,结果不是“简单”多边形。