5

Problem:

I have a three-dimensional point cloud each centroid of a block representing a block. For simplicity this example is just two dimensional. As illustrated in the picture I want to include blocks of interest, based on a parameter. In the case here block 1,6,5,4. In order to further process them i need to find the smallest hull around them by either using an alpha shape or a convex hull. I have the coordinates of every centroid and i know the block extension so I can find easily the edge point of the blocks by:

    xdimension=5;
ydimension=5;
block1=[5 15 1];
block2=[5 10 0];
block3=[5 5 0];
block4=[10 5 1];
block5=[10 10 1];
block6=[10 15 1];
block7=[15 5 0];
block8=[15 10 0];
block9=[15 15 0];
blocks=[block1;block2;block3;block4;block5;block6;block7;block8;block9]

dimension=[xdimension/2 ydimension/2];
point1=[1 1].*dimension;
point2=[1 -1].*dimension;
point3=[-1 1].*dimension;
point4=[-1 -1].*dimension;
i=size(blocks,1);
point1=repmat(point1,i,1);
point2=repmat(point2,i,1);
point3=repmat(point3,i,1);
point4=repmat(point4,i,1);
edges1=[blocks(:,1:2)+point1, blocks(:,3)] ;
edges2=[blocks(:,1:2)+point2, blocks(:,3)];
edges3=[blocks(:,1:2)+point3, blocks(:,3)];
edges4=[blocks(:,1:2)+point4, blocks(:,3)];
edges=[edges1;edges2;edges3;edges4];
x=edges(edges(:,3)==1,1);
y=edges(edges(:,3)==1,2);
K=convhull(x,y)
scatter(edges(:,1), edges(:,2))
hold on
plot(x(K),y(K),'r-')
hold off

This produces a picture similar to the one here.

Question

How can I query the surface (or in my real problem the volume) that is included by the convex hull of block 2 and 3 ? I need the exact surface/ volume of every individual block included apart from those that I specify to be in (here with the binary indicator). Please note that this is an example and I am looking for ideas how to do this independant of the example. I would really appreciate some help, cause I a majorly stuck here and I have no idea how to tackle it.

enter image description here

KiW
  • 593
  • 3
  • 20

3 Answers3

1

In 2D I would use the inpolygon function to test if a point is inside the intersection of the convex Hull and squares 2 and 3.

For 3D I didn't found an equivalent in MATLAB but the following matlab exchange file supposed to be the solution.

An example of how to use the function inhull to find the points of the areas inside:

% Create a 3D cube
cubePoints = randi(5,[500,3]);

% Bounding volume
boundingVolume = zeros(8,3);
boundingVolume(1,:) = [1,3,1];
boundingVolume(2,:) = [1,3,3];
boundingVolume(3,:) = [3,3,1];
boundingVolume(4,:) = [3,3,3];
boundingVolume(5,:) = [3,1,3];
boundingVolume(6,:) = [3,1,1];
boundingVolume(7,:) = [2,1,1];
boundingVolume(8,:) = [2,1,3];

% Find points inside area
inVol = inhull(cubePoints,boundingVolume);

% Plot the point in the bounding volume in blue and the points outsode the
% bounding volume in red
scatter3(cubePoints(:,1).*inVol,cubePoints(:,2).*inVol,cubePoints(:,3).*inVol,36,'blue');
hold on
scatter3(cubePoints(:,1).*~inVol,cubePoints(:,2).*~inVol,cubePoints(:,3).*~inVol,36,'red');
Amitay Nachmani
  • 3,259
  • 1
  • 18
  • 21
  • This is a nice start, but based on the points how could you exactly get the surface/volume of the included blocks? Using the single edge points would be an approximation, but dependant on the size of the hull quite inaccurate – KiW Sep 22 '16 at 19:34
  • 1
    Whilst this may theoretically answer the question, [it would be preferable](//meta.stackoverflow.com/q/8259) to include the essential parts of the answer here, and provide the link for reference. – Adriaan Sep 23 '16 at 07:31
0

If you are successful in finding your covex hull (using the convhull function), its second output variable will give you what you need (?).

[IDs,V] = convhull(X,Y,Z)

Here V is the volume enclosed in the convex hull of the points (X,Y,Z). Bless Matlab!

ptev
  • 183
  • 2
  • 7
  • 1
    I know, the thing is I want to know the exact amount included of 2 and 3 individually, not the total volume. ;) – KiW Sep 20 '16 at 14:16
0

I believe this method works, but if the system is large, in terms of memory consumption it has nothing to show off with:

First construct the total convex hull in the form of a 3d binary array. Also, each block should form a 3d binary array over the whole space, with true elements over the extend of the block and false elsewhere. (To accomplish this, check the link in Amitay's answer.)

Now you can calculate the share of each block from it. If you have formed everything as explained, the rest is straightforward: You can directly count the overlap of the conv with each block as follows:

num = numel(block);
shareofblock = zeros(num, 1);
for jj = 1:num
    overlap = block(jj) & conv;
    shareofblock(jj) = sum(overlap(:));
end
Community
  • 1
  • 1
Erfan
  • 1,897
  • 13
  • 23