Why does the figure size change when I use print -dpng and -djpeg? - matlab

I have this code:
x = 1:1:1000;
Hw = 2;
T1 = 60;
L1 = 100;
eta1 = (Hw/2)*(sin(2*pi*((x/L1)-(1/T1))));
units_out ='centimeters';
width = 8;
height = 6;
typefon = 'Times';
fsize_axis = 8;
fsize_label = 10;
fig1 = figure;
h0 = plot(x, eta1,'r');
ylim([-2 2]);
set(gca,'FontName',typefon,'FontSize',fsize_axis,'FontWeight','bold');
title('Water wave 1');
xl0 = xlabel('x (m)');
set(xl0,'FontSize',fsize_label);
yl0 =ylabel('\eta (m)');
set(yl0,'FontSize',fsize_label);
pos =get(gcf,'Position');
pos(3) = width;
pos(4) = height;
set(gcf,'units','centimeters','Position',pos);
set(gca,'LooseInset',max(get(gca,'TightInset'), 0.02))
set(gcf,'PaperPositionMode','auto');
print('my_figure', '-dpng', '-r600');
delete(fig1);
winopen('my_figure.png');
I got an image of: 8.0 x 6.0 cm; 3.15 x 2.36 inches (I expected this size), but if I only modify the formattype to –djpeg of print function, I got a graphics file of: 66.7 x 50.0 cm; 26.25 x 19.68 inches. Why does the size change? How can I compute the size of the image, in centimeters, taking into account the resolution of the image?

Related

I want to be able to plot a 3D circle in MATLAB's AppDesigner. How can I do so?

I have a code where I am taking x1, y1, z1 and the radius d as inputs from the user. In my callback function, I am reading these values and I have to plot a 3D circle in MATLAB's App Designer. How can I do so? I have a code for plotting a point in 2D but the same thing is not working when I am trying for a 3D plot.
x1 = app.NumericEditField.Value;
y1 = app.NumericEditField4.Value;
z1 = app.NumericEditField7.Value;
plot(app.UIAxes,x1,y1,'o'); %Code for a point in 2D plot.
grid(app.UIAxes,'on');
Plotting Circles and Spheres on UIAxes
A circle can be plotted in MATLAB app-designer by using the plot3() function. Sin() and cos() can then be used to get a set number of (x,y) points which can be stored in a matrix. Another matrix of the same size which stores the (z) points must also be created.
In short 3 vectors for the x,y,z points and plot3() are required. I also included a sphere just in case.
app = uifigure();
app.Color = '#FFFFFF';
Field_Height = 20;
Field_Width = 80;
%Creating input text field for x1%
x1 = uieditfield(app,'numeric');
x1.Position = [10 100 Field_Width Field_Height];
x1_Label = uilabel(app);
x1_Label.Text = 'x1';
x1_Label.Position = [100 100 Field_Width Field_Height];
%Creating input text field for y1%
y1 = uieditfield(app,'numeric');
y1.Position = [10 70 Field_Width Field_Height];
y1_Label = uilabel(app);
y1_Label.Text = 'y1';
y1_Label.Position = [100 70 Field_Width Field_Height];
%Creating input text field for z1%
z1 = uieditfield(app,'numeric');
z1.Position = [10 40 Field_Width Field_Height];
z1_Label = uilabel(app);
z1_Label.Text = 'z1';
z1_Label.Position = [100 40 Field_Width Field_Height];
%Creating input text field for the radius%
Radius = uieditfield(app,'numeric');
Radius.Position = [10 10 Field_Width Field_Height];
Radius_Label = uilabel(app);
Radius_Label.Text = 'Radius';
Radius_Label.Position = [100 10 Field_Width Field_Height];
%Creating 3D axes%
Axes_3D = uiaxes(app);
Axes_3D.Position = [150 20 400 400];
plot3(Axes_3D,0,0,0,'Color','b');
Axes_3D.XGrid = 'on';
Axes_3D.YGrid = 'on';
Axes_3D.ZGrid = 'on';
Axes_3D.XLabel.String = "x axis";
Axes_3D.YLabel.String = "y axis";
Axes_3D.ZLabel.String = "z axis";
Axes_3D.BackgroundColor = '#FFFFFF';
%Setting callback functions for each input field%
x1.ValueChangedFcn = #(x1,event) Plot_Sphere(x1,y1,z1,Radius,Axes_3D);
y1.ValueChangedFcn = #(y1,event) Plot_Sphere(x1,y1,z1,Radius,Axes_3D);
z1.ValueChangedFcn = #(z1,event) Plot_Sphere(x1,y1,z1,Radius,Axes_3D);
Radius.ValueChangedFcn = #(Radius,event) Plot_Sphere(x1,y1,z1,Radius,Axes_3D);
%Function that gets called when any input field is changed%
function [] = Plot_Sphere(X_Field,Y_Field,Z_Field,Radius_Field,Axes_3D)
%Grab the positions.offsets from each field%
X_Position = X_Field.Value;
Y_Position = Y_Field.Value;
Z_Position = Z_Field.Value;
Radius = Radius_Field.Value;
%Creating a matrix of points for the sphere%
[X_Base,Y_Base,Z_Base] = sphere;
%Multiplying the points depending on a given radius%
X = X_Base * Radius;
Y = Y_Base * Radius;
Z = Z_Base * Radius;
%Creating a matrix of points for the circle%
Number_Of_Data_Points = 200;
theta = linspace(0,2*pi,Number_Of_Data_Points);
X_Circle = Radius*cos(theta);
Y_Circle = Radius*sin(theta);
Z_Circle = zeros(1,Number_Of_Data_Points);
%Plotting the circle%
plot3(Axes_3D,X_Circle+X_Position,Y_Circle+Y_Position,Z_Circle+Z_Position);
%Switch this line to get sphere%
% plot3(Axes_3D,X+X_Position,Y+Y_Position,Z+Z_Position,'Color',[0, 0.4470, 0.7410]);
%Switch this line to get sphere filled%
% surf(Axes_3D,X+X_Position,Y+Y_Position,Z+Z_Position);
end
Ran using MATLAB R2019b

How to draw a rectangle using 4 corners on an image in Matlab R2018b?

In Matlab, there is rectangle('Position',[x,y,w,h]) to draw a rectangle object, that w and h are a width and a height respectively (This link). While I try to draw a rectangle on an image using 4 corners: min_x, max_x, min_y and max_y that are specified in the following image.
Ex:
min_x = 193; max_x = 220; min_y = 168; max_y = 190;
I saw this link and like that, but they couldn't help me. Is there any way to draw a rectangle with 4 corners?
A = imresize( imread('peppers.png'),0.6);%resizing for better visibility
min_x = 193; max_x = 220; min_y = 168; max_y = 190;
x = min_x;
y = min_y;
w = max_x-min_x;
h = max_y-min_y;
imshow(A)
rectangle('Position',[x,y,w,h],'EdgeColor','r','Linewidth',3);
% Or insert shape to bitmap:
% B = insertShape(A,'rectangle',[x,y,w,h]);
% imshow(B)

Moving a star marker along a hexagon trajectory?

I want to move a star marker along hexagon trajectory similar to "Circle trajectory" that I have added at the end of my question. Thanks.
This is the source code to that I have written yet for creating concentric hegzagons but I don't know how to move a star marker which traverses the concentric hexagons, I had written a similar simulation code for circle trajectory but I couldn't do it for hexagon.
%clc; % Clear the command window.
%close all; % Close all figures (except those of imtool.)
%clear; % Erase all existing variables. Or clearvars if you want.
workspace; % Make sure the workspace panel is showing.
format long g;
format compact;
fontSize = 20;
angles = linspace(0, 360, 7);
radii = [20, 35, 50,70];
% First create and draw the hexagons.
numberOfHexagons = 4;
% Define x and y arrays. Each row is one hexagon.
% Columns are the vertices.
x1=radii(1) * cosd(angles)+50;
y1 = radii(1) * sind(angles)+50;
x2=radii(2) * cosd(angles)+50;
y2 = radii(2) * sind(angles)+50;
x3=radii(3) * cosd(angles)+50;
y3 = radii(3) * sind(angles)+50;
x4=radii(4) * cosd(angles)+50;
y4 = radii(4) * sind(angles)+50;
plot(x1 , y1, 'b');
hold on
plot(x2, y2, 'b');
hold on
plot(x3, y3, 'b');
hold on
plot(x4, y4, 'b');
hold on
% Connecting Line:
plot([70 100], [50 50],'color','b')
axis([0 100 0 100])
hold on
Circle trajectory:
% Initialization steps.
format long g;
format compact;
fontSize = 20;
r1 = 50;
r2 = 35;
r3= 20;
xc = 50;
yc = 50;
% Since arclength = radius * (angle in radians),
% (angle in radians) = arclength / radius = 5 / radius.
deltaAngle1 = 5 / r1;
deltaAngle2 = 5 / r2;
deltaAngle3 = 5 / r3;
theta1 = 0 : deltaAngle1 : (2 * pi);
theta2 = 0 : deltaAngle2 : (2 * pi);
theta3 = 0 : deltaAngle3 : (2 * pi);
x1 = r1*cos(theta1) + xc;
y1 = r1*sin(theta1) + yc;
x2 = r2*cos(theta2) + xc;
y2 = r2*sin(theta2) + yc;
x3 = r3*cos(theta3) + xc;
y3 = r3*sin(theta3) + yc;
plot(x1,y1,'color',[1 0.5 0])
hold on
plot(x2,y2,'color',[1 0.5 0])
hold on
plot(x3,y3,'color',[1 0.5 0])
hold on
% Connecting Line:
plot([70 100], [50 50],'color',[1 0.5 0])
% Set up figure properties:
% Enlarge figure to full screen.
set(gcf, 'Units', 'Normalized', 'OuterPosition', [0, 0, 1, 1]);
drawnow;
axis square;
for i = 1 : length(theta1)
plot(x1(i),y1(i),'r*')
pause(0.1)
end
for i = 1 : length(theta2)
plot(x2(i),y2(i),'r*')
pause(0.1)
end
for i = 1 : length(theta3)
plot(x3(i),y3(i),'r*')
pause(0.1)
end
I would generalize your problem with parametric function for the trajectory. In it use rotation kernel which you want here few examples in C++/VCL/GDI (sorry I am not Matlab friendly but the equations should be the same in Matlab too) for circle,square and hexagon rotation kernels:
void getpnt_circle(double &x,double &y,double &pi2,double r,double t) // (x,y) = circle(r,t) t=<0,1>
{
pi2=2.0*M_PI; // circumference(r=1) 6.283185307179586476925286766559
t*=pi2;
x=r*cos(t);
y=r*sin(t);
}
//---------------------------------------------------------------------------
void getpnt_square(double &x,double &y,double &pi2,double r,double t) // (x,y) = square(r,t) t=<0,1>
{
pi2=8.0; // circumference(r=1)
// kernel
const int n=4; // sides
const double x0[n]={+1.0,+1.0,-1.0,-1.0}; // side start point
const double y0[n]={-1.0,+1.0,+1.0,-1.0};
const double dx[n]={ 0.0,-2.0, 0.0,+2.0}; // side tangent
const double dy[n]={+2.0, 0.0,-2.0, 0.0};
int ix;
t-=floor(t); // t = <0, 1.0)
t*=n; // t = <0,n)
ix=floor(t); // side of square
t-=ix; // distance from side start
x=r*(x0[ix]+t*dx[ix]);
y=r*(y0[ix]+t*dy[ix]);
}
//---------------------------------------------------------------------------
void getpnt_hexagon(double &x,double &y,double &pi2,double r,double t) // (x,y) = square(r,t) t=<0,1>
{
pi2=6.0; // circumference(r=1)
// kernel
const int n=6; // sides
const double c60=cos(60.0*M_PI/180.0);
const double s60=sin(60.0*M_PI/180.0);
const double x0[n]={+1.0,+c60,-c60,-1.0,-c60,+c60}; // side start point
const double y0[n]={ 0.0,+s60,+s60, 0.0,-s60,-s60};
const double dx[n]={-c60,-1.0,-c60,+c60,+1.0,+c60}; // side tangent
const double dy[n]={+s60, 0.0,-s60,-s60, 0.0,+s60};
int ix;
t-=floor(t); // t = <0, 1.0)
t*=n; // t = <0,n)
ix=floor(t); // side of square
t-=ix; // distance from side start
x=r*(x0[ix]+t*dx[ix]);
y=r*(y0[ix]+t*dy[ix]);
}
//---------------------------------------------------------------------------
void TMain::draw()
{
if (!_redraw) return;
// clear buffer
bmp->Canvas->Brush->Color=clBlack;
bmp->Canvas->FillRect(TRect(0,0,xs,ys));
int e;
double r,t,x,y,c,dr=15.0,dl=15.0;
int xx,yy,rr=3;
bmp->Canvas->MoveTo(xs2,ys2);
bmp->Canvas->Pen->Color=clAqua;
bmp->Canvas->Brush->Color=clBlue;
for (r=dr,t=0.0;;)
{
// get point from selected kernel
// getpnt_circle (x,y,c,r,t);
// getpnt_square (x,y,c,r,t);
getpnt_hexagon(x,y,c,r,t);
// render it
xx=xs2+x;
yy=ys2+y;
bmp->Canvas->LineTo(xx,yy);
bmp->Canvas->Ellipse(xx-rr,yy-rr,xx+rr,yy+rr);
// update position
r+=dr*dr/(r*c);
t+=dl/(r*c); t-=floor(t);
if (r>=xs2) break;
if (r>=ys2) break;
}
// render backbuffer
Main->Canvas->Draw(0,0,bmp);
_redraw=false;
}
//---------------------------------------------------------------------------
You can ignore the VCL/GDI rendering stuff.
xs,ys is full and xs2,ys2 is half resolution of window to scale the plot properly...
dl is distance between markers [pixels]
dr is distance between spiral screws [pixels]
the spiral is sampled with r,t step depending on the actual circumference (that is what the pi2 or c is for). The getpnt_xxxxx function will return x,y coordinate of your shape from parameter t=<0,1> and actual radius r. It also returns the actual value of circumference/r ratio called pi2
Here preview of the 3 kernels used for spiral ...

Plot equally spaced markers along a spiral

I want to move a red star marker along the spiral trajectory with an equal distance of 5 units between the red star points on its circumference like in the below image.
vertspacing = 10;
horzspacing = 10;
thetamax = 10*pi;
% Calculation of (x,y) - underlying archimedean spiral.
b = vertspacing/2/pi;
theta = 0:0.01:thetamax;
x = b*theta.*cos(theta)+50;
y = b*theta.*sin(theta)+50;
% Calculation of equidistant (xi,yi) points on spiral.
smax = 0.5*b*thetamax.*thetamax;
s = 0:horzspacing:smax;
thetai = sqrt(2*s/b);
xi = b*thetai.*cos(thetai);
yi = b*thetai.*sin(thetai);
plot(x,y,'b-');
hold on
I want to get a figure that looks like the following:
This is my code for the circle trajectory:
% Initialization steps.
format long g;
format compact;
fontSize = 20;
r1 = 50;
r2 = 35;
r3= 20;
xc = 50;
yc = 50;
% Since arclength = radius * (angle in radians),
% (angle in radians) = arclength / radius = 5 / radius.
deltaAngle1 = 5 / r1;
deltaAngle2 = 5 / r2;
deltaAngle3 = 5 / r3;
theta1 = 0 : deltaAngle1 : (2 * pi);
theta2 = 0 : deltaAngle2 : (2 * pi);
theta3 = 0 : deltaAngle3 : (2 * pi);
x1 = r1*cos(theta1) + xc;
y1 = r1*sin(theta1) + yc;
x2 = r2*cos(theta2) + xc;
y2 = r2*sin(theta2) + yc;
x3 = r3*cos(theta3) + xc;
y3 = r3*sin(theta3) + yc;
plot(x1,y1,'color',[1 0.5 0])
hold on
plot(x2,y2,'color',[1 0.5 0])
hold on
plot(x3,y3,'color',[1 0.5 0])
hold on
% Connecting Line:
plot([70 100], [50 50],'color',[1 0.5 0])
% Set up figure properties:
% Enlarge figure to full screen.
set(gcf, 'Units', 'Normalized', 'OuterPosition', [0, 0, 1, 1]);
drawnow;
axis square;
for i = 1 : length(theta1)
plot(x1(i),y1(i),'r*')
pause(0.1)
end
for i = 1 : length(theta2)
plot(x2(i),y2(i),'r*')
pause(0.1)
end
for i = 1 : length(theta3)
plot(x3(i),y3(i),'r*')
pause(0.1)
end
I can't think of a way to compute distance along a spiral, so I'm approximating it with circles, in hopes that it will still be useful.
My solution relies on the InterX function from FEX, to find the intersection of circles with the spiral. I am providing an animation so it is easier to understand.
The code (tested on R2017a):
function [x,y,xi,yi] = q44916610(doPlot)
%% Input handling:
if nargin < 1 || isempty(doPlot)
doPlot = false;
end
%% Initialization:
origin = [50,50];
vertspacing = 10;
thetamax = 5*(2*pi);
%% Calculation of (x,y) - underlying archimedean spiral.
b = vertspacing/(2*pi);
theta = 0:0.01:thetamax;
x = b*theta.*cos(theta) + origin(1);
y = b*theta.*sin(theta) + origin(2);
%% Calculation of equidistant (xi,yi) points on spiral.
DST = 5; cRes = 360;
numPts = ceil(vertspacing*thetamax); % Preallocation
[xi,yi] = deal(NaN(numPts,1));
if doPlot && isHG2() % Plots are only enabled if the MATLAB version is new enough.
figure(); plot(x,y,'b-'); hold on; axis equal; grid on; grid minor;
hAx = gca; hAx.XLim = [-5 105]; hAx.YLim = [-5 105];
hP = plot(xi,yi,'r*');
else
hP = struct('XData',xi,'YData',yi);
end
hP.XData(1) = origin(1); hP.YData(1) = origin(2);
for ind = 2:numPts
P = InterX([x;y], makeCircle([hP.XData(ind-1),hP.YData(ind-1)],DST/2,cRes));
[~,I] = max(abs(P(1,:)-origin(1)+1i*(P(2,:)-origin(2))));
if doPlot, pause(0.1); end
hP.XData(ind) = P(1,I); hP.YData(ind) = P(2,I);
if doPlot, pause(0.1); delete(hAx.Children(1)); end
end
xi = hP.XData(~isnan(hP.XData)); yi = hP.YData(~isnan(hP.YData));
%% Nested function(s):
function [XY] = makeCircle(cnt, R, nPts)
P = (cnt(1)+1i*cnt(2))+R*exp(linspace(0,1,nPts)*pi*2i);
if doPlot, plot(P,'Color',lines(1)); end
XY = [real(P); imag(P)];
end
end
%% Local function(s):
function tf = isHG2()
try
tf = ~verLessThan('MATLAB', '8.4');
catch
tf = false;
end
end
function P = InterX(L1,varargin)
% DOCUMENTATION REMOVED. For a full version go to:
% https://www.mathworks.com/matlabcentral/fileexchange/22441-curve-intersections
narginchk(1,2);
if nargin == 1
L2 = L1; hF = #lt; %...Avoid the inclusion of common points
else
L2 = varargin{1}; hF = #le;
end
%...Preliminary stuff
x1 = L1(1,:)'; x2 = L2(1,:);
y1 = L1(2,:)'; y2 = L2(2,:);
dx1 = diff(x1); dy1 = diff(y1);
dx2 = diff(x2); dy2 = diff(y2);
%...Determine 'signed distances'
S1 = dx1.*y1(1:end-1) - dy1.*x1(1:end-1);
S2 = dx2.*y2(1:end-1) - dy2.*x2(1:end-1);
C1 = feval(hF,D(bsxfun(#times,dx1,y2)-bsxfun(#times,dy1,x2),S1),0);
C2 = feval(hF,D((bsxfun(#times,y1,dx2)-bsxfun(#times,x1,dy2))',S2'),0)';
%...Obtain the segments where an intersection is expected
[i,j] = find(C1 & C2);
if isempty(i), P = zeros(2,0); return; end
%...Transpose and prepare for output
i=i'; dx2=dx2'; dy2=dy2'; S2 = S2';
L = dy2(j).*dx1(i) - dy1(i).*dx2(j);
i = i(L~=0); j=j(L~=0); L=L(L~=0); %...Avoid divisions by 0
%...Solve system of eqs to get the common points
P = unique([dx2(j).*S1(i) - dx1(i).*S2(j), ...
dy2(j).*S1(i) - dy1(i).*S2(j)]./[L L],'rows')';
function u = D(x,y)
u = bsxfun(#minus,x(:,1:end-1),y).*bsxfun(#minus,x(:,2:end),y);
end
end
Result:
Note that in the animation above, the diameter of the circle (and hence the distance between the red points) is 10 and not 5.

MATLAB's lsqnonlin solver moves away from solution

I have a fitting problem that I am trying to solve using MATLAB's lsqnonlin function and it's doing a pretty poor job. In particular, if I give it the actual solution as the starting point, the solver proceeds to move away from there (despite the fitting function returning a vector of all zeroes for that input) and produces something awful. My code is below, but it's a bit long, so I apologise for that, but I'm not sure exactly what it is about this particular situation that causes this behaviour as in others it's fine.
fitting_demo.m:
% Parameters for image
imagemat = zeros(32, 32);
x_centre = 5; y_centre = -10; radius = 3; psf_sigma = 1; height = 1;
% Generate image to fit
actual_image = image_sphere_thin(x_centre, y_centre, radius, psf_sigma, height, imagemat);
figure
% Plot actual image
subplot(2, 1, 1)
imagesc(actual_image)
axis equal
title('Actual image')
% Set up fitting function
x0 = [x_centre, y_centre, radius, psf_sigma, height]; % The solver starts from the solution!
f = #(x)fit_image_sphere_thin(x, imagemat);
% Fit
options = optimoptions(#lsqnonlin, 'Display', 'iter');
[fit, resnorm, residual, exitflag, output] = lsqnonlin(f, x0, [], [], options);
% Display image generated using fitted parameters
subplot(2, 1, 2)
imagesc(image_sphere_thin(fit(1), fit(2), fit(3), fit(4), fit(5), imagemat))
axis equal
title('Fitted image')
fit_image_sphere_thin.m:
function deltas = fit_image_sphere_thin(x0, actual_image)
x_centre = x0(1);
y_centre = x0(2);
radius = x0(3);
% psf_sigma = x0(4); % Commented out to stop crazy things
psf_sigma = 1;
% height = x0(5); % Commented out to stop crazy things
height = 1;
imagemat = zeros(size(actual_image));
sim_image = image_sphere_thin(x_centre, y_centre, radius, psf_sigma, height, imagemat);
sim_vector = sim_image(:);
actual_vector = actual_image(:);
deltas = actual_vector - sim_vector;
end
image_sphere_thin.m:
function I = image_sphere_thin(x_centre, y_centre, radius, psf_sigma, height, imagemat)
image_width = size(imagemat, 2);
image_height = size(imagemat, 1);
image_centre_x = image_width / 2;
image_centre_y = image_height / 2;
x = (1:image_width) - image_centre_x;
y = -(1:image_height) + image_centre_y;
[x, y] = meshgrid(x, y);
X = [x(:) y(:)];
image_vector = cross_section_sphere_thin(x_centre, y_centre, radius, psf_sigma, height, X);
imagemat = reshape(image_vector, size(imagemat));
I = imagemat;
end
cross_section_sphere_thin.m:
function I = cross_section_sphere_thin(x_centre, y_centre, radius, psf_sigma, height, X)
r = sqrt((X(:, 1) - x_centre).^2 + (X(:, 2) - y_centre).^2);
psf_variance = psf_sigma^2;
I = height * (exp(-(r - radius).^2 / (2 * psf_sigma)) - exp(-(r + radius).^2 / (2 * psf_sigma))) ./ r;
I(r == 0) = (2 * radius * height / psf_variance) * exp(-(radius^2) / (2 * psf_variance));
end