As you can see, in the first picture I have two subplots, two the same, with the same curve position. But I need to change the curve position/or view angle of one of the subplot (doesn't matter now if the left one or the right one). The only working command is CameraViewAngle but it changes for both of it, I don't know why, and I need to be able to change for each one seperately.
As you can see in picture two, the view angle changes for both of it. I would rather chagne only the curve position.
The code I'm using is:
function [pointsQRS, pointsP, pointsT] = VCG (pointsQRS,pointsP,pointsT)
global ax1 ax2 h
figure('Name','Vektorkardiogram','NumberTitle','off','Color',[0.8 0.8 0.8])
ax1=subplot(1,2,1)
set(ax1,'Position',[0.10,0.11,0.3346590909090909,0.815],'CameraPosition',
[50.197132152696216,49.50150052184264,-7.57531754730548],'CameraTarget',
[0.4, 0.7, -0.33],'View',[-184.4219, -8.9326],'CameraViewAngle',
[9.256133109732078])
title('Vektorkardiogram')
hold on
grid on
view(3)
for i=2:size(pointsQRS,1)
if mod(i,2)==0
QRS=plot3(pointsQRS([i-1:i],1),pointsQRS([i-1:i],2),pointsQRS([i-
1:i],3),'-g','LineWidth',1);
else
plot3(pointsQRS([i-1:i],1),pointsQRS([i-1:i],2),pointsQRS([i-
1:i],3),'Color',[0 0 0],'LineWidth',1);
end
end
for i=2:size(pointsT,1)
if mod(i,2)==0
T=plot3(pointsT([i-1:i],1),pointsT([i-1:i],2),pointsT([i-1:i],3),'-
r','LineWidth',1);
else
plot3(pointsT([i-1:i],1),pointsT([i-1:i],2),pointsT([i-1:i],3),'Color',
[0 0 0],'LineWidth',1);
end
end
for i=2:size(pointsP,1)
if mod(i,2)==0
P=plot3(pointsP([i-1:i],1),pointsP([i-1:i],2),pointsP([i-1:i],3),'-
b','LineWidth',1);
else
plot3(pointsP([i-1:i],1),pointsP([i-1:i],2),pointsP([i-1:i],3),'Color',
[0 0 0],'LineWidth',1);
end
end
xlabel('Vx');ylabel('Vy');zlabel('Vz');
mArrow3([1.5 2 -1],[-0.5, 2, -1], 'stemWidth',
0.005,'color','red','facealpha',0.3);
mArrow3([1.5 2 -1],[1.5, -0.5, -1], 'stemWidth',
0.005,'color','red','facealpha',0.3);
mArrow3([1.5 2 -1],[1.5, 2, 1], 'stemWidth',
0.005,'color','red','facealpha',0.3);
text(-0.5, 2, -1, 'Vx','FontSize',12);
text(1.5, -0.5, -1, 'Vy','FontSize',12);
text(1.5, 2, 1, 'Vz','FontSize',12);
ax2=subplot(1,2,2)
set(ax2,'Position',[0.565,0.11,0.33465909090909096,0.815],'CameraPosition',
[-13.197132152696216,-59.50150052184264,10.57531754730548])
title('Vektorkardiogram')
hold on
grid on
h=linkprop([ax1, ax2],
{'CameraPosition','CameraUpVector','XTick','YTick','ZTick'});
for i=2:size(pointsQRS,1)
if mod(i,2)==0
QRS=plot3(pointsQRS([i-1:i],1),pointsQRS([i-1:i],2),pointsQRS([i-
1:i],3),'-g','LineWidth',1);
else
plot3(pointsQRS([i-1:i],1),pointsQRS([i-1:i],2),pointsQRS([i-
1:i],3),'Color',[0 0 0],'LineWidth',1);
end
end
for i=2:size(pointsT,1)
if mod(i,2)==0
T=plot3(pointsT([i-1:i],1),pointsT([i-1:i],2),pointsT([i-1:i],3),'-
r','LineWidth',1);
else
plot3(pointsT([i-1:i],1),pointsT([i-1:i],2),pointsT([i-1:i],3),'Color',
[0 0 0],'LineWidth',1);
end
end
for i=2:size(pointsP,1)
if mod(i,2)==0
P=plot3(pointsP([i-1:i],1),pointsP([i-1:i],2),pointsP([i-1:i],3),'-
b','LineWidth',1);
else
plot3(pointsP([i-1:i],1),pointsP([i-1:i],2),pointsP([i-1:i],3),'Color',
[0 0 0],'LineWidth',1);
end
end
xlabel('Vx');ylabel('Vy');zlabel('Vz');
mArrow3([1.5 2 -1],[-0.5, 2, -1], 'stemWidth',
0.005,'color','red','facealpha',0.3);
mArrow3([1.5 2 -1],[1.5, -0.5, -1], 'stemWidth',
0.005,'color','red','facealpha',0.3);
mArrow3([1.5 2 -1],[1.5, 2, 1], 'stemWidth',
0.005,'color','red','facealpha',0.3);
text(-0.5, 2, -1, 'Vx','FontSize',12);
text(1.5, -0.5, -1, 'Vy','FontSize',12);
text(1.5, 2, 1, 'Vz','FontSize',12);
linkaxes([ax1, ax2])
I need it to change it in order to achieve 3D stereoscopic view using Google Cardboard.
Thank you in advance for any help!
PS: For example I want to achieve something as in the picture 3
But in the picture three the 3D curves are not connected, by connected I mean that while I move with one of them, the other one will be moved in the same way.
I managed to partially solve it.
Changing CameraViewAngle, modifies the size of the curve, so I decided to keep it unmodified.
Instead of setting the angle, set CameraPosition of ax2 to be different than ax1, but keeping the same distance from the target.
Instead of using linkprop, I used addlistener, and implemented a callback function that sets the CameraPosition of ax2 when CameraPosition of ax1 is modified.
Read the following reference pages:
addlistener
View Control with the Camera Toolbar
Camera Graphics Terminology
Axes Properties
Share Data Among Callbacks
Here is the code:
function [pointsQRS, pointsP, pointsT] = VCG (pointsQRS,pointsP,pointsT)
%Clear global varabiles - for testing, we don't want any leftovers of ax1 and ax2.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clear global
close all
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Set some input data.
pointsQRS = 1:3:78;
pointsP = 1:2:92;
pointsT = 1:1:85;
%global ax1 ax2 h
fig1 = figure('Name','Vektorkardiogram','NumberTitle','off','Color',[0.8 0.8 0.8]);
ax1=subplot(1,2,1);
%Don't use view command, fill all parameters manually.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%view(ax1, 3)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Set ax1 parameters values to be same as result as after executing view(ax1, 3)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
set(ax1, 'XLim', [-0.5, 2.0], 'YLim', [-1, 3.0], 'ZLim', [-1.5, 1.0]);
set(ax1, 'Position',[0.13, 0.11, 0.3346590909090909, 0.815]);
set(ax1, 'CameraViewAngle', 10.339584907201974);
set(ax1, 'CameraTarget', [0.75, 1.0, -0.25]);
set(ax1, 'View',[-184.4219, -8.9326]);
set(ax1, 'DataAspectRatio', [1, 1.6, 1.0]);
set(ax1, 'PlotBoxAspectRatio', [1, 0.95521169259094, 0.8871534463389812], 'PlotBoxAspectRatioMode', 'Manual');
set(ax1, 'CameraPosition', [-10.664276793913514,-22.800600208737055,10.57531754730548]);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
ax2 = subplot(1,2,2);
%Set ax2 parameters values to be same as result as after executing view(ax2, 3)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
set(ax2, 'XLim', [-0.5, 2.0], 'YLim', [-1, 3.0], 'ZLim', [-1.5, 1.0]);
set(ax2, 'Position',[0.5703409090909091, 0.11, 0.3346590909090909, 0.815]);
set(ax2, 'CameraViewAngle', 10.339584907201974);
set(ax2, 'CameraTarget', [0.75, 1.0, -0.25]);
set(ax2, 'View',[-184.4219, -8.9326]);
set(ax2, 'DataAspectRatio', [1, 1.6, 1.0]);
set(ax2, 'PlotBoxAspectRatio', [1, 0.95521169259094, 0.8871534463389812], 'PlotBoxAspectRatioMode', 'Manual');
set(ax2, 'CameraPosition', [-10.664276793913514,-22.800600208737055,10.57531754730548]);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Move the camera of ax2 to be in different position compared to ax1, but keep the same distance from the Target.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
cameraTarget = [0.75, 1.0, -0.25];
cameraPosition = [-10.664276793913514,-22.800600208737055,10.57531754730548];
V = cameraPosition - cameraTarget;
newV = V + [-10, 0, 0];
newV = newV/norm(newV)*norm(V);
newCameraPosition = cameraTarget + newV;
set(ax2, 'CameraPosition', newCameraPosition);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Store ax1 and ax2 in figure UserData
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
set(fig1, 'UserData', [ax1, ax2]);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Set axes ax1 as active axes.
axes(ax1);
title('Vektorkardiogram')
hold on
grid on
%Move view(3) up
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%view(3)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Use plot3 from Matlab example (fill curve with some data).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%t = -3*pi:pi/50:3*pi;st = sin(t)*2;ct = cos(t)*2;plot3(st,ct,t/6)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
for i=2:size(pointsQRS,1)
if mod(i,2)==0
QRS=plot3(pointsQRS([i-1:i],1),pointsQRS([i-1:i],2),pointsQRS([i-1:i],3),'-g','LineWidth',1);
else
plot3(pointsQRS([i-1:i],1),pointsQRS([i-1:i],2),pointsQRS([i-1:i],3),'Color',[0 0 0],'LineWidth',1);
end
end
for i=2:size(pointsT,1)
if mod(i,2)==0
T=plot3(pointsT([i-1:i],1),pointsT([i-1:i],2),pointsT([i-1:i],3),'-r','LineWidth',1);
else
plot3(pointsT([i-1:i],1),pointsT([i-1:i],2),pointsT([i-1:i],3),'Color',[0 0 0],'LineWidth',1);
end
end
for i=2:size(pointsP,1)
if mod(i,2)==0
P=plot3(pointsP([i-1:i],1),pointsP([i-1:i],2),pointsP([i-1:i],3),'-b','LineWidth',1);
else
plot3(pointsP([i-1:i],1),pointsP([i-1:i],2),pointsP([i-1:i],3),'Color',[0 0 0],'LineWidth',1);
end
end
xlabel('Vx');ylabel('Vy');zlabel('Vz');
mArrow3([1.5 2 -1],[-0.5, 2, -1], 'stemWidth', 0.005,'color','red','facealpha',0.3);
mArrow3([1.5 2 -1],[1.5, -0.5, -1], 'stemWidth', 0.005,'color','red','facealpha',0.3);
mArrow3([1.5 2 -1],[1.5, 2, 1], 'stemWidth', 0.005,'color','red','facealpha',0.3);
text(-0.5, 2, -1, 'Vx','FontSize',12);
text(1.5, -0.5, -1, 'Vy','FontSize',12);
text(1.5, 2, 1, 'Vz','FontSize',12);
%ax2 = subplot(1,2,2); Moved up, axes(ax2) is used instead.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%ax2 = subplot(1,2,2);
axes(ax2)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
title('Vektorkardiogram')
hold on
grid on
%Move linkprop to the end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%h=linkprop([ax1, ax2],{'CameraPosition', 'CameraUpVector', 'XTick', 'YTick', 'ZTick'});
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
for i=2:size(pointsQRS,1)
if mod(i,2)==0
QRS=plot3(pointsQRS([i-1:i],1),pointsQRS([i-1:i],2),pointsQRS([i-1:i],3),'-g','LineWidth',1);
else
plot3(pointsQRS([i-1:i],1),pointsQRS([i-1:i],2),pointsQRS([i-1:i],3),'Color',[0 0 0],'LineWidth',1);
end
end
for i=2:size(pointsT,1)
if mod(i,2)==0
T=plot3(pointsT([i-1:i],1),pointsT([i-1:i],2),pointsT([i-1:i],3),'-r','LineWidth',1);
else
plot3(pointsT([i-1:i],1),pointsT([i-1:i],2),pointsT([i-1:i],3),'Color',[0 0 0],'LineWidth',1);
end
end
for i=2:size(pointsP,1)
if mod(i,2)==0
P=plot3(pointsP([i-1:i],1),pointsP([i-1:i],2),pointsP([i-1:i],3),'-b','LineWidth',1);
else
plot3(pointsP([i-1:i],1),pointsP([i-1:i],2),pointsP([i-1:i],3),'Color',[0 0 0],'LineWidth',1);
end
end
%Use plot3 from Matlab example (fill curve with some data).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%t = -3*pi:pi/50:3*pi;st = sin(t)*2;ct = cos(t)*2;plot3(ax2, st,ct,t/6)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
xlabel('Vx');ylabel('Vy');zlabel('Vz');
mArrow3([1.5 2 -1],[-0.5, 2, -1], 'stemWidth', 0.005,'color','red','facealpha',0.3);
mArrow3([1.5 2 -1],[1.5, -0.5, -1], 'stemWidth', 0.005,'color','red','facealpha',0.3);
mArrow3([1.5 2 -1],[1.5, 2, 1], 'stemWidth', 0.005,'color','red','facealpha',0.3);
text(-0.5, 2, -1, 'Vx','FontSize',12);
text(1.5, -0.5, -1, 'Vy','FontSize',12);
text(1.5, 2, 1, 'Vz','FontSize',12);
%view(ax1, 3)
%view(ax2, 3)
%Matalb gives warning message: linkaxes requires 2-D axes as input. Use linkprop for generic property linking.
%call linkprop here instead.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%linkaxes([ax1, ax2])
%h=linkprop([ax1, ax2],{'CameraPosition', 'CameraUpVector', 'XTick', 'YTick', 'ZTick'});
%Don't link CameraPosition - it is linked by "listener" implementation
linkprop([ax1, ax2],{'CameraUpVector', 'XTick', 'YTick', 'ZTick'});
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Add "listener", instead of using linkprop
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
addlistener(ax1, 'CameraPosition', 'PostSet', #Ax1CameraPositionCallback);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Display cameratoolbar
cameratoolbar
function Ax1CameraPositionCallback(src, evnt, ~)
ax1 = evnt.AffectedObject;
fig1 = get(ax1, 'Parent');
userData = get(fig1, 'UserData');
ax2 = userData(2);
%Move the camera of ax2 to be in different position compared to ax1, but keep the same distance from the Target.
cameraTarget = get(ax1, 'CameraTarget');
cameraPosition = get(ax1, 'CameraPosition');
V = cameraPosition - cameraTarget;
newV = V + [-10, 0, 0];
newV = newV/norm(newV)*norm(V);
newCameraPosition = cameraTarget + newV;
set(ax2, 'CameraPosition', newCameraPosition);
I have to plot 5 lines that overlap in some regions, and I need to be able to see all the lines.
I can think of shifting the lines a bit to allow them to be displayed, but this doesn't seem a very elegante solution. Even so, how could I code such a thing?
Is there any other way to plot multiple overlapping lines while being able to distinguish them at every point?
For exemple, here is one exemple with 3 overlapping lines:
Thank you in advance!
Another way is to use transparency.
Unfortunatelly, line objects do not obey
transparency commands :(
A workaround is to:
1. download patchline (<-- link to Matlab Central)
2. use it to plot patchline with transparency
Once you have patchline, you can try something like:
% create some lines:
l1 = [1, 1, 1, 0, 0, 0.25, 1, 1, 0, 0, 0, 0, 1 1];
l2 = [0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1];
l3 = [1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0];
% plot with patchline (notice the use of 'EdgeAlpha'):
figure;
patchline(1:length(l1), l1, [], 'EdgeColor', [0.8, 0.2, 0.35],...
'LineWidth', 5, 'EdgeAlpha', 0.5 );
hold on;
patchline(1:length(l1), l2, 'EdgeColor', [0.2, 0.7, 0.55],...
'LineWidth', 5, 'EdgeAlpha', 0.5 );
patchline(1:length(l1), l3, 'EdgeColor', [0.1, 0.2, 0.95],...
'LineWidth', 5, 'EdgeAlpha', 0.5);
% change y limits to see line overlap clearly
set(gca, 'YLim', [-0.5, 1.5]);
Not an ideal way to do it - the rough 'cracks' will stay this way,
but you can experiment with different line widths or moving the
lines in y axis by a value that would correspond to an image with each
line covering only half of it closest neighbour...
You may play with EraseMode property of the plot line. The following code example shows how to shift the lines and EraseMode effect:
% First we generate some data
NLines = 2;
NPoints = 50;
LineWidth = 3;
ShiftStep = 1.1;
XData = linspace(0,1,NPoints);
YData = rand(NPoints,NLines);
for k=1:NLines
YData(:,k) = YData(:,k) > (k/(NLines+1));
end
% Then we create plot
figure('color','w');
subplot(3,1,1); plot(XData,YData, 'LineWidth',LineWidth);
ylim([-0.1 1.1]);
title('simple')
subplot(3,1,2); plot(XData,YData+repmat((0:NLines-1)*ShiftStep,NPoints,1), 'LineWidth',LineWidth, 'EraseMode','xor');
ylim([-0.1 1.1+ShiftStep*(NLines-1)]);
title('Shifted vertically')
subplot(3,1,3); plot(XData,YData, 'LineWidth',LineWidth, 'EraseMode','xor');
ylim([-0.1 1.1]);
title('EraseMode = xor')
In my opinion if you have more than three lines similar to your plot, shifting is visually more attractive. Also you may create several axes (Like I did) and plot each line in its own axes, so they will have y-labels set accordingly, but their X-labels will be essentially the same.
You can use plot3 and assign different Z values to different overlapping lines. However, it'll look more like you expect (Z being the "up" direction) if you swap the Y and Z axes:
Example:
Y1 = randn(1,100);
Y2 = randn(1,100);
X = 1:100;
Z1 = 1*ones(size(X));
Z2 = 2*ones(size(X));
plot3(X,Z1,Y1);
hold on;
plot3(X,Z2,Y2);