How can I find a fit to my data points and using triangulation to approximate the planar area?

5 views (last 30 days)
I got these data points, I want to approx the planar area of the shape.
I am thinking of finding a fit then approxmate from the function but I am not sure.

Answers (4)

John D'Errico
John D'Errico on 14 Nov 2018
Edited: John D'Errico on 14 Nov 2018
I don't have your data, while they say a picture is worth a thousand words, it is still just words, not numbers. Anyway, I think you are asking to find the cancave region where the points live, but not including those triangular chaped voids.
For this purpose, an alpha shape is often the best approach. The idea is to visualize a circle or ball, of radius r. Now imagine that ball rolling around the perimeter of your points, in a way where the ball cannot cross any data point. Allow the alpha ball to erode a triangulation to the extent that it can. So any triangles around the perimeter with long edges will be deleted. Again, since I lack any data, I'll make some up.
xy = rand(5000,2);
k = (sqrt(sum((xy - [1 .5]).^2,2)) < 0.3) | ...
(sqrt(sum((xy - [0 .5]).^2,2)) < 0.3) | ...
(sqrt(sum((xy - [0.5 1]).^2,2)) < 0.3) | ...
(sqrt(sum((xy - [0.5 0]).^2,2)) < 0.3);
xy(k,:) = [];
plot(xy(:,1),xy(:,2),'.')
grid on
Admittedly, not a very good approximation to what you had. But it is early in the morning, and I don't care about the difference.
S = alphaShape(xy(:,1),xy(:,2),.20)
S =
alphaShape with properties:
Points: [2163×2 double]
Alpha: 0.2
HoleThreshold: 0
RegionThreshold: 0
plot(S)
I choise 0.2 for the alpha radius arbitrarily, assuming I did not know the diameter of the circle I had actually used. Anyway, in real life, you will never have exactly circular cutouts as I did here. Regardless, it is not a poor approximation, but only that. See that if I chose the alpha radius to be too large, it will start to leave large triangles aound the perimeter. Too small an alpha radius, and we will get too much erosion of the real domain we are interested in. Luckily with alpha shapes, there tends to be a fuzzy region where you can be a little wrong and it won't matter much. A problem can arise where you have sharp internal corners, but thats life.
What is the area contained though?
area(S)
ans =
0.42664
Lets see, since I know the actual shape of the region, I can easily compute the area as:
1 - 4*(pi*0.3^2/2)
ans =
0.43451
Not bad at all.
By way of comparison, consider what a Delaunay triangulation does on the same data.
D = delaunayTriangulation(xy);
triplot(D)
untitled.jpg
As you can see, it is those triangles with the long edges around the pererimeter that we need to erode away, and the alpha shape did that spectacularly well. Remember that a Delaunay triangulation will always create a convex domain.
I would point out that with fewer points, the underlying delaunay triangulation that is eroded to create the alpha shape will be a coarse one, and therefore you may have some issues if you make alpha too small. But since you do have moderately sharp internal corners there, you want a small alpha ball. Hey, the real world is like that, and I've only once ever met a client in my career as a consultant who offered more data than I really wanted to do the best job possible. Remember that your eyes/brain form a very good pattern recognition utility. They do easily what computers often need real work to do well.
  11 Comments
fengsen huang
fengsen huang on 15 Nov 2018
With the variables I have now I dont know how to find the volume, I am not trying to ignore your code, I am tryingto keep up to it but dont understand. You said something about triangles??

Sign in to comment.


KSSV
KSSV on 13 Nov 2018
Read about boundary and polyarea. Let (x,y) be your data.
idx = boundry(x,y) ;
bx = x(idx) ; by = y(idx) ;
A = polyarea(bx,by) ;
If the above is not working....have a look on delaunaytriangulation. It will triangulate the area and also gives you area.
  6 Comments
John D'Errico
John D'Errico on 15 Nov 2018
Edited: John D'Errico on 15 Nov 2018
I've used them heavily over many years in both 2 and 3 dimensions. In fact, I wrote working versions of them around 20 years ago in MATLAB. They work quite well.
Bruno Luong
Bruno Luong on 15 Nov 2018
Edited: Bruno Luong on 15 Nov 2018
Hi John, I don't deny it works well. But
I have problem with the curvature criteria.
To me a outer surface of an object can have big curvaturre, like a corner of the box. Fixing a threhold on that seems to me then just "try it and see until you are happy", very operator dependent. The second reason is also on curvature but in 3D, anypoint have 2 separate principal curvatures, and alphashape just smooths them out by a sphere.
But it's just me.

Sign in to comment.


Bjorn Gustavsson
Bjorn Gustavsson on 14 Nov 2018
One thing you could try to squeeze around some difficult parts of your problem is to run through a coordinate transformation - for example to cylindrical coordinates (r, theta), after plotting your points in that coordinate system perhaps a mathematically simpler paramterization of your boundary can be found that way.
HTH
  2 Comments
John D'Errico
John D'Errico on 15 Nov 2018
Edited: John D'Errico on 15 Nov 2018
This might work if done carefully. It would probably be a periodic spline approximation to the envelope in r, were I to do it. Of course then, the area computation becomes an easy thing. A virtue of the approach is you can also do smoothing on that envelope if you wanted. The biggest problem I would foresee is the envelope function, thus r(theta) may not be a single valued function of polar angle theta. That appears in fact to be a potential problem for the 4 leafed clover region we have seen.
Bjorn Gustavsson
Bjorn Gustavsson on 15 Nov 2018
If one are a bit lucky it might work even with a QD first stab. I got something reasonably similar with
x_perim = cos(theta).*sin(n*theta);
y_perim = sin(theta).*sin(n*theta);
...and technically that is not a preimeter of a simple closed region, but it would be pretty
straightforward to fix that and adjust things for the regions where the distance to the centre
is small. If this is how the original problem was designed it is not all that very interesting - the general problem is both more difficult and interesting .

Sign in to comment.


Bruno Luong
Bruno Luong on 14 Nov 2018
Edited: Bruno Luong on 14 Nov 2018
Quick and dirty fix, just discard outside delaunay triangles with long sides
Delaunay.png
load('x-data.mat');
load('y-data.mat');
xy = [JJ KK];
DT = delaunayTriangulation(xy);
K = convexHull(DT);
% adjustable threshold
dmax = 6;
T = DT.ConnectivityList;
T = sortrows(sort(T,2));
while true
xyb = xy(K,:);
d = diff(xyb,1,1);
d = sqrt(sum(d.^2,2));
Tbad = find(d > dmax);
ibad = Tbad+[0 1];
Kbad = reshape(K(ibad),size(ibad));
K12 = sort(Kbad,2);
[b12,i12] = ismember(T(:,[1 2]),K12,'rows');
[b23,i23] = ismember(T(:,[2 3]),K12,'rows');
[b13,i13] = ismember(T(:,[1 3]),K12,'rows');
i12 = i12(b12);
i23 = i23(b23);
i13 = i13(b13);
k12 = T(b12,3);
k23 = T(b23,1);
k13 = T(b13,2);
b = b12 | b23 | b13;
K3 = accumarray([i12;i23;i13],[k12;k23;k13]);
if isempty(K3)
break
end
T(b,:) = [];
Tbad = Tbad(:)';
for i=length(K3):-1:1
K3i = K3(i);
if K3i == 0
continue
end
j = Tbad(i);
K = [K(1:j); K3i; K(j+1:end)];
end
end
close all
trisurf(T,DT.Points(:,1),DT.Points(:,2),zeros(size(DT.Points(:,2))));
view(2)
axis equal
  1 Comment
Bruno Luong
Bruno Luong on 15 Nov 2018
Compute the volume:
load('all data.mat')
X1 = cell2mat(C(:,2));
Y1 = cell2mat(C(:,3));
d1 = cell2mat(C(:,5));
d2 = cell2mat(C(:,6));
t = d1 - d2;
m = (t>0);
XX = X1(m); JJ = double(XX);
YY = Y1(m); KK = double(YY);
D1=nonzeros(d1);
D2=nonzeros(d2);
jj=abs(JJ); kk=abs(KK);
xy = [jj,kk];
DT = delaunayTriangulation(xy);
K = convexHull(DT);
% adjustable threshold
dmax = 6;
T = DT.ConnectivityList;
T = sortrows(sort(T,2));
while true
xyb = xy(K,:);
d = diff(xyb,1,1);
d = sqrt(sum(d.^2,2));
Tbad = find(d > dmax);
ibad = Tbad+[0 1];
Kbad = reshape(K(ibad),size(ibad));
K12 = sort(Kbad,2);
[b12,i12] = ismember(T(:,[1 2]),K12,'rows');
[b23,i23] = ismember(T(:,[2 3]),K12,'rows');
[b13,i13] = ismember(T(:,[1 3]),K12,'rows');
i12 = i12(b12);
i23 = i23(b23);
i13 = i13(b13);
k12 = T(b12,3);
k23 = T(b23,1);
k13 = T(b13,2);
b = b12 | b23 | b13;
K3 = accumarray([i12;i23;i13],[k12;k23;k13]);
if isempty(K3)
break
end
T(b,:) = [];
Tbad = Tbad(:)';
for i=length(K3):-1:1
K3i = K3(i);
if K3i == 0
continue
end
j = Tbad(i);
K = [K(1:j); K3i; K(j+1:end)];
end
end
% close all
% hold on
% trisurf(T,DT.Points(:,1),DT.Points(:,2),D1);
% trisurf(T,DT.Points(:,1),DT.Points(:,2),D2);
% view(3)
% axis equal
H = abs(D2-D1);
ABC = xy(T,:);
ABC = reshape(ABC,[size(T),2]);
ABC = permute(ABC,[3 2 1]);
ABC = ABC(:,2:3,:)-ABC(:,1,:);
% Triangle areas
S = 0.5*abs(ABC(1,1,:).*ABC(2,2,:)-ABC(1,2,:).*ABC(2,1,:));
HT = 1/3*sum(H(T),2);
S = reshape(S,size(HT));
V = sum(S.*HT);
fprintf('Volume = %g\n', V);

Sign in to comment.

Categories

Find more on Delaunay Triangulation in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!