Compute area of 3D surface given coordinates of points - matlab

Given the coordinates of each point, how to calculate the area of a three-dimensional surface in MATLAB?
x=-5:1:5;y=-5:1:5;
[xx,yy]=meshgrid(x,y);zz=Z;
figure(1)
mesh(xx,yy,zz)
figure(2)
xb=-5:0.25:5;
yb=-5:0.25:5;
[xxb,yyb]=meshgrid(xb,yb);
zzb=interp2(xx,yy,zz,xxb,yyb,'cubic');
mesh(xxb,yyb,zzb)
above is my code.
the picture is the data of z.
I tried to search for questions alike but I just couldn't find it.

Try converting it to an AlphaShape then use SurfaceArea.

1.- alphaShape does not work for this question because this particular surface is open.
alphaShape generates 2D or 3D closed POLYGONS.
This is the 1st surface
x=-5:1:5;y=-5:1:5;
[xx,yy]=meshgrid(x,y);
zz=[13.6 -8.2 -14.8 -6.6 1.4 0 -3.8 1.4 13.6 16.8 0
-8.2 -15.8 -7.9 2.2 3.8 0 0.6 7.3 10.1 0 -16.8
-14.8 -7.9 2.5 5.8 2.3 0 2.7 5.1 0 -10.1 -13.7
-6.6 2.2 5.9 3.0 -0.3 0 1.9 0 -5.1 -7.3 -1.4
1.4 3.8 2.3 -0.3 -0.9 0 0 -1.7 -2.7 -0.6 3.8
0 0 0 0 0 0 0 0 0 0 0
-3.8 0.6 2.7 1.7 0 0 0.9 0.3 -2.3 -3.8 -1.4
1.4 7.3 5.1 0 -1.7 0 0.3 -3.1 -5.8 -2.2 6.6
13.6 10.1 0 -5.1 -2.7 0 -2.3 -5.8 -2.5 7.9 14.8
16.8 0 -10.1 -7.3 -0.6 0 -3.8 -2.2 7.9 15.8 8.2
0 16.3 -13.6 -1.4 3.8 0 -1.4 6.6 14.8 8.2 -13.6];
figure(1)
sh1=mesh(xx,yy,zz)
And this is the 2nd surface
figure(2)
xb=-5:0.1:5;
yb=-5:0.1:5;
[xxb,yyb]=meshgrid(xb,yb);
zzb=interp2(xx,yy,zz,xxb,yyb,'cubic');
mesh(xxb,yyb,zzb)
Now try alphaShape on the 1st surface
P1=[xx(:) yy(:) zz(:)];
shp1 = alphaShape(P1(:,1),P1(:,2),P1(:,3));
figure;
plot(shp1)
axis equal
voila : here is the contraption
and when attempting
A1=area(shp1)
bang :
Error using alphaShape/area
This method is only applicable to 2D alpha shapes.
2.- One has to integrate adding up each flat surface.
The vertexs of each flat surface are available using the handle available from mesh
sh1=mesh(xx,yy,zz)
check the abridged properties
sh1 =
Surface with properties:
EdgeColor: 'flat'
LineStyle: '-'
FaceColor: [1 1 1]
FaceLighting: 'none'
FaceAlpha: 1
XData: [11×11 double]
YData: [11×11 double]
ZData: [11×11 double]
CData: [11×11 double]
click on Show all properties that shows up right after the abridged properties in Command Window to read all properties
AlignVertexCenters: off
AlphaData: 1
AlphaDataMapping: 'scaled'
AmbientStrength: 0.300000000000000
Annotation: [1×1 matlab.graphics.eventdata.Annotation]
BackFaceLighting: 'reverselit'
BeingDeleted: off
BusyAction: 'queue'
ButtonDownFcn: ''
CData: [11×11 double]
CDataMapping: 'scaled'
CDataMode: 'auto'
...
VertexNormals: [11×11×3 double]
VertexNormalsMode: 'auto'
Visible: on
XData: [11×11 double]
XDataMode: 'manual'
XDataSource: ''
YData: [11×11 double]
YDataMode: 'manual'
YDataSource: ''
ZData: [11×11 double]
ZDataSource: ''
3.- Good News : In The Mathworks File Exchange there is a function called surfarea, thanks to Sky Santorius, that does exactly the task mentioned in point 2 which is what 石sh asks for.
surfarea is available in the following link :
https://uk.mathworks.com/matlabcentral/fileexchange/62992-surface-area?s_tid=srchtitle_surface%20area_2
Applying surfare to 1st surface
[A1,cell_areas_A1,centroid1]=surfarea(xx,yy,zz);
the resulting surface area is
A1 =
6.783763291711880e+02
and when calculating area of the interpolated 2nd surface
[A2,cell_areas_A2,centroid2]=surfarea(xxb,yyb,zzb);
the resulting surface area is
A2 =
6.504878453848488e+02

Related

Smooth data and graph in MATLAB [duplicate]

Using MATLAB, I have a matrix (data) and am plotting using imagesc(data) to produce a heatmap:
data = [1 1 1 1 1 1 1 1 1 1; 1 1.04 1.04 1.04 1.03 1 1.01 1.01 1.03 1.01; 1.36 1.3 1.25 1.2 1.15 1.1 1.2 1.13 1.07 1.11; 3.65 3.16 2.94 2.68 2.39 2.22 2.17 1.95 1.79 1.81; 5.91 5.75 5.47 5.3 4.98 4.79 4.62 4.55 4.38 4.19; 6 6 5.99 5.83 5.49 5.33 5.14 4.94 4.77 4.74];
imagesc(data)
Is there a way to 'smooth' the pixels in order to produce something more like this:
interp2 may be of use here. Use the data as key points, then create a finer grid of points that span the same width and height and interpolate in between the key points.
Something like this:
%// Define your data
data = [1 1 1 1 1 1 1 1 1 1; 1 1.04 1.04 1.04 1.03 1 1.01 1.01 1.03 1.01; 1.36 1.3 1.25 1.2 1.15 1.1 1.2 1.13 1.07 1.11; 3.65 3.16 2.94 2.68 2.39 2.22 2.17 1.95 1.79 1.81; 5.91 5.75 5.47 5.3 4.98 4.79 4.62 4.55 4.38 4.19; 6 6 5.99 5.83 5.49 5.33 5.14 4.94 4.77 4.74];
%// Define integer grid of coordinates for the above data
[X,Y] = meshgrid(1:size(data,2), 1:size(data,1));
%// Define a finer grid of points
[X2,Y2] = meshgrid(1:0.01:size(data,2), 1:0.01:size(data,1));
%// Interpolate the data and show the output
outData = interp2(X, Y, data, X2, Y2, 'linear');
imagesc(outData);
%// Cosmetic changes for the axes
set(gca, 'XTick', linspace(1,size(X2,2),size(X,2)));
set(gca, 'YTick', linspace(1,size(X2,1),size(X,1)));
set(gca, 'XTickLabel', 1:size(X,2));
set(gca, 'YTickLabel', 1:size(X,1));
%// Add colour bar
colorbar;
The code that's at the bottom is required because defining the finer grid ultimately increases the size of the image. I need to relabel the axes to go back to the original size.
We get this:
Small Note
I'm using MATLAB R2014a, and the default colour map is jet. You're using R2014b+ and the default colour map is parula. You won't get the same colour distribution as me, but you will get the smoothness you desire.
You can also use the pcolor(data) function with shading interp to make the color resolution smooth. No need to interpolate the data before plotting.

Matlab cdfplof do not show complete graph when multiple cdfs are plotted in one graph with x-axis as log scale

I am trying to use cdfplot() to plot multiple sets of data in one graph. When I use the normal x-axis, everything is fine. However, when I try to change the x-axis to log scale, the cdf plot of some sets of data do not display complete.
I have two sets of data: setFive and setSeven. I want to plot cdf of them in the same graph, with x-axis being log scale.
Here are the two graphs, one is in normal x-axis, the other is in log scale x-axis. The cdf of "five" in log scale x-axis does not go to 0.
The two sets of data are:
setSeven=[ 0.1478
0.2493
0.0650
0.1808
0.3633
0.1684
0.3116
0.1398
0
0
0.3069
0.3252
0.1762
0.4192
0
0.1163
0
0
0.2338
0
0.1388
0
0.2420
0.1115
0
0
0
0.1530
0.1675
0.3333
0
0
0.2351
0.1555
0
0
0.1691
0.2042
0.3143
0
0
0.2206
0
0.2288
0.1271
0
0.1852
0
0
0
0.1226
0
0
0.1571
0.1807
0
0
0
0.3231
0.1358
0.1681
0
0.1924
0.1494
0.1474
0.1030
0.2008
0.1455
0
0.2351
0.2537
0
0.1353
0
0.1320
0.1675
0.1844
0
0
0.2691
0.3640
0
0
0
0
0
0.2395
0
0
0
0.3156
0.2007
0.4463
0
0
0.2526
0.2375
0.3521
0.2279
0];
setFive=[0.1476
0.3300
0.0940
0.2704
0.3659
0.2214
0.3658
0.1402
0.2295
0.2105
0.3324
0.4011
0.2823
0.5740
0.2916
0.1940
0.2559
0
0.2423
0.1734
0.1992
0
0.2822
0.4122
0.2312
0
0.2598
0.3808
0.5833
0.6131
0
0.2831
0.6418
0.2269
0.2532
0.1944
0.3515
0.2734
0.3908
0.3223
0
0.3303
0
0.2759
0.2144
0
0
0
0.1747
0.2721
0.2509
0.2542
0
0.1381
0.2562
0.1918
0.2243
0.2260
0.3823
0.2404
0.3963
0.2917
0.2390
0.2818
0.2863
0.2366
0.2289
0
0.1183
0.2660
0.2535
0.1917
0.1976
0
0
0
0
0.4433
0
0.3395
0.4199
0.3674
0
0
0.2814
0
0.3816
0.4754
0.3198
0.4995
0.5585
0.2965
0.5316
0.4914
0.6343
0.4036
0.3632
0.4205
0.3089
0.4521];
Here are the codes:
e=cdfplot(setFive);
set(e,'LineStyle','-','color','k');
hold on;
g=cdfplot(setSeven);
set(g,'LineStyle','--','color','k');
hold on;
set(gca,'Xscale','log');
axis([0 1 0 1]);
get(gca,'xlim')
The problem is due to the processing the function cdfplot makes on the input, coupled with the logarithmic representation.
Consider the setSeven input data set (the same applies to setFive): the first 5 points generated by cdfplot are:
x7= -Inf 0 0 0.0650 0.0650
y7= 0 0 0.4300 0.4300 0.4400
You canget these points using the get function wiht the handles returned by cdfplot:
x5=get(e,'xdata');
y5=get(e,'ydata');
x7=get(g,'xdata');
y7=get(g,'ydata');
where:
x5: x data from setFive data set
y5: y data from setFive data set
x7: x data from setSeven data set
x7: y data from setSeven data set
In the first of your graph, you see the line starting from x=0, y=0 then climbing to x=0, y=0.43.
In this graph actually the first point x=-inf, y=0 is missing since the plot function simply ignores values such as -inf, inf, NaN.
Something similar happens when you set the xaxis scale as logarithmic:
In this case, the first 3 point are ignored, since
log10([-Inf 0 0 0.0650 0.0650]) is [ Inf + 1.3644i -Inf -Inf -1.1871 -1.1871]
so, the first two point displayable on the graph are the fourth and the fifth which correspond to:
x=0.0650, y=0.4300
x=0.0650, y=0.4400
the first three point are then ignored.
As said at the beginning, this also happens for the setFive data set.
In this case you have:
x5= -Inf 0 0 0.0940 0.0940
y5= 0 0 0.1900 0.1900 0.2000
So in the first graph the first point is not diplayed and since
log10([ -Inf 0 0 0.0940 0.0940]) is Inf + 1.3644i -Inf -Inf -1.0269 -1.0269
the first three point will not be displayed in the second graph (log scale).
In conlcusion, you are right, some points are not diplayed in both the graphs but this is correct given the set of data to be displayed and the function you are using.
You can find below the two graphs zoomed to highlight the first point plotted (setFive in red, setSeven in black).
Zoom of the graph with xaxis linear scale
Zoom of the graph with xaxis logarithmic scale
Hope this helps.
Well it does exactly what it should do.
The cdf tries to generate a function that mimics the population distribution from the sample you gave it.
As a tule of thumb I prefer using the plot function, as it gives you more power and you are in complete control of the data.
So if you consider the below code and the figure it creates, it just means that in log space (where log(0) = -inf) you cannot plot any value of zero.
Therefore, only values that differ from zeros are viable, and the rest are omitted from the plot.
now if you find out these in the two data sets, using the following line
[min(cx5(cx5>0)),min(cx7(cx7>0))]
you will see that set five minimal value is much larger than set seven.
Now think on what is the log spacing when max is one, it emphasizes differences that are closer to zero on the expense of differences that are closer to one.
But as far as cdf's go these results are impressive.
Enjoy.
[cy5,cx5] = ecdf(setFive);
[cy7,cx7] = ecdf(setSeven);
subplot(221)
plot(cx5,cy5,'LineStyle','-','color','k');hold on
plot(cx7,cy7,'LineStyle','--','color','k');hold off
ylabel('F(x)'); xlabel('x');title('Empirical CDF');
axis([0 1 0 1])
subplot(222)
plot(cx5,cy5,'LineStyle','-','color','k');hold on
plot(cx7,cy7,'LineStyle','--','color','k');hold off
ylabel('F(x)'); xlabel('x');title('Empirical CDF');
set(gca,'Yscale','log');
axis([0 1 0 1])
subplot(223)
plot(cx5,cy5,'LineStyle','-','color','k');hold on
plot(cx7,cy7,'LineStyle','--','color','k');hold off
ylabel('F(x)'); xlabel('x');title('Empirical CDF');
set(gca,'Xscale','log');
axis([0 1 0 1])
subplot(224)
plot(cx5,cy5,'LineStyle','-','color','k');hold on
plot(cx7,cy7,'LineStyle','--','color','k');hold off
ylabel('F(x)'); xlabel('x');title('Empirical CDF');
set(gca,'Xscale','log','Yscale','log');
axis([0 1 0 1])

How to shift x-axis label to right in matlab

I am trying to draw a box plot using matlab. I want to shift the position of the x-axis labels to the right. See the following code which seems not to work correctly.
positions = [2.5 3.5 4.5 5.5 6.5 7.5];
colors = [0 0 1; 0 0 1;0 0 1; 1 0 0;1 0 0;1 0 0];
x = boxplot([KA_query_length Plan_query_length Comp_query_length FR_query_length KI_query_length QA_query_length], 'Position', positions, 'Colors',colors,'whisker',0);
set(gca, 'FontSize', 20,'FontWeight','bold');
Given below is what the graph looks like at the moment.

How to entegrate existing .m file into the simulink .mdl file

I'm using robotic toolbox by Peter Corke in Matlab . I have .m file for puma560 robot (it is for robot trajectory. The robot follows given path). When I try to use for ex. "sl_ctorque" simulink file which is in robotic toolbox(it is about computed torque method) , I couldn't entegrate my .m file into the simulink file. My .m file is given below. So if anyone know how to do this idea, I'd appreciate it. Thanks!
clear;clc;
mdl_puma560 %to create puma robot
for type=1:3 % main for loop. It turns 3 times. At first, it sets the path
% to x-y plane and draw the robot, at second for y-z plane
% and then for x-z plane
if type==1
% The path of robot for x-y plane
path=[0 0 1;0 0 0;0 2 0 ;0.5 1 0 ;1 2 0;1 0 0;1.5 0 1;1.5 0 0;
1.5 2 0;2.2 2 0;2.5 1.6 0;2.5 0.4 0;2.2 0 0;1.5 0 0;0 0 1];
elseif type==2
% Same thing as first part
path=[-0.5 0 0;0 0 0;0 0 1;0 -0.5 0.5;0 -1 1;0 -1 0;-0.5 -1.2 0;0 -1.2 0;
0 -1.2 1;0 -1.7 1;0 -2 0.7;0 -2 0.3;0 -1.7 0;0 -1.2 0];
elseif type==3
% Same thing as first and second part
path=[0 -0.5 0;0 0 0;0 0 1;0.5 0 0.5;1 0 1;1 0 0;1.3 -0.5 0;1.3 0 0;
1.3 0 1;1.7 0 1;2 0 0.7;2 0 0.3;1.7 0 0;1.3 0 0];
end
% I created a trajectory
p=mstraj(path, [15 15 15], [], [1 0 1], 0.02 , 0.2);
% [15 15 15] means the maximum speed in x,y,z directions.
% [1 0 1] means the initial coordinates
% 0.02 means acceleration time
% 0.2 means smoothness of robot
numrows(p)*0.2; % 200 ms sample interval
Tp=transl(0.1*p); % Scale factor of robot
Tp=homtrans( transl(0.4,0,0),Tp); % Origin of the letter
q=p560.ikine6s(Tp); % The inverse kinematic
for i=1:length(q)
% q matrix has 280 rows and 6 columns. So this for loop turns 280 times
% At every turns , it plots one part of movement. q(1,:), q(2,:), ...
p560.plot(q(i,:))
end
end
You need to write your m file as a function and then use the MATLAB Function Block.
The MATLAB Function block allows you to add MATLAB® functions to Simulink® models for deployment to desktop and embedded processors. This capability is useful for coding algorithms that are better stated in the textual language of the MATLAB software than in the graphical language of the Simulink product.
Then you can open the block as paste your function:
to see an example check out this page.

Perspective projection of a 3D model to a 2D plane

I'm trying to project a 3D model to a 2D plane and I found I should use the projection equation C*((R*X)+T) to do so. C, which is the camera calibration matrix is calculated as follows:
C =[f 0 px;
0 f py;
0 0 1];
First, I want to ask about the focal length f used in the camera calibration matrix. Should I use it with the value in pixels or mm? If in mm how can I get it?
Second I don't really know what the px and py variables stand for I got some information about the data I'm working on bye the exifread function in MATLAB and these are the information I got:
Sharpness: 0
Contrast: 0
SceneCaptureType: 0
FocalLengthIn35mmFilm: 27
DigitalZoomRatio: 1
WhiteBalance: 0
ExposureMode: 0
SceneType: 1
FileSource: 3
SensingMethod: 2
PixelYDimension: 3000
PixelXDimension: 4000
ColorSpace: 1
FlashpixVersion: '0100'
FocalLength: 4.9000
Flash: 1
LightSource: 0
MeteringMode: 4
MaxApertureValue: 3.6150
ExposureBiasValue: 0
ApertureValue: 3.6150
ShutterSpeedValue: 2.3220
CompressedBitsPerPixel: 2.8149
ComponentsConfiguration: [1 2 3 0]
DateTimeDigitized: '2011:06:26 16:55:08'
DateTimeOriginal: '2011:06:26 16:55:08'
ExifVersion: '0221'
ISOSpeedRatings: 100
ExposureProgram: 2
FNumber: 3.5000
ExposureTime: 0.2000
Copyright: 'Copyright 2010'
YCbCrPositioning: 2
DateTime: '2011:06:26 16:55:08'
Software: ' 0.8913'
ResolutionUnit: 2
YResolution: 96
XResolution: 96
Orientation: 1
Model: 'SAMSUNG ES30/VLUU ES30'
Make: 'SAMSUNG'
Thumbnail: [1x1 struct]
Do px and py refer to any of them?
px and py are the coordinates of the principal point. On an ideal camera that would be the center of the image, so you can use width/2, height/2 for a start. For actual values you should use a calibration algorithm.
f should be in pixels.