classdef LineProfile < handle
properties (GetAccess=public, SetAccess=private)
FigHandle
Handle
TextLabel
Axesh
Imageh
ImSize
StartPoint
EndPoint
Color
LineWidth=2
StoredNumber
ContextMenu
ContextMenuItem
end
properties (GetAccess=public, SetAccess=public)
DeleteOnClick
end
properties (Dependent = true, GetAccess=public, SetAccess = public)
Number
x
y
Profile
end
events
DestroyObject
end
methods
function obj=LineProfile(ImSize,StartPoint,color,number,axesh)
obj.CreateMenu;
obj.ImSize=ImSize;
obj.StartPoint=round(StartPoint);
obj.EndPoint=round(StartPoint+[10 10]);
obj.Color=color;
obj.Axesh=axesh;
obj.FigHandle=get(obj.Axesh,'Parent');
childobj=get(obj.Axesh,'Children');
obj.Imageh=childobj(strcmpi(get(childobj,'Type'),'image'));
obj.Handle=line(obj.x,obj.y,'Color',obj.Color,'LineWidth',obj.LineWidth);
obj.Number=number;
set(obj.Handle,'ButtonDownFcn',{@obj.ButtonDown,'Resize'});
set(obj.TextLabel,'ButtonDownFcn',{@obj.ButtonDown,'Move'});
set(obj.FigHandle,'WindowButtonMotionFcn',{@obj.MouseMove,'EndPoint'});
set(obj.FigHandle,'WindowButtonUpFcn',@obj.ButtonUp);
obj.Number=number;
end
function obj=update(obj)
X=obj.x;Y=obj.y;
X(X<1)=1;Y(Y<1)=1;
X(X>obj.ImSize(1))=obj.ImSize(1);
Y(Y>obj.ImSize(2))=obj.ImSize(2);
obj.x=X;obj.y=Y;
set(obj.Handle,'XData',obj.x,'YData',obj.y);
center=(obj.StartPoint+obj.EndPoint)./2;
set(obj.TextLabel,'Position',center);
end
function obj=ButtonDown(obj,~,~,Action)
if obj.DeleteOnClick;obj.Destroy;return;end
SelectionType=get(gcbf,'Selectiontype');
switch SelectionType
case 'normal'
cp=get(obj.Axesh,'CurrentPoint');
ReferencePoint=[cp(1,1), cp(1,2)];
[~,I]=min([norm(ReferencePoint-obj.StartPoint) norm(ReferencePoint-obj.EndPoint)]);
set(obj.FigHandle,'WindowButtonMotionFcn',{@obj.MouseMove,Action,ReferencePoint,obj.x,obj.y,I(1)});
set(obj.FigHandle,'WindowButtonUpFcn',@obj.ButtonUp);
case 'open'
figure;plot(squeeze(obj.Profile(3,:)));
end
end
function obj=ButtonUp(obj,~,~)
set(obj.FigHandle,'WindowButtonMotionFcn','');
obj.Number=obj.StoredNumber;
end
function MouseMove(obj,~,~,Action,RP,X,Y,Point)
switch lower(Action)
case 'endpoint'
cp=get(obj.Axesh,'CurrentPoint');
obj.EndPoint=[cp(1,1), cp(1,2)];
case 'move'
cp=get(obj.Axesh,'CurrentPoint');
dx=cp(1,1)-RP(1);dy=cp(1,2)-RP(2);
obj.x=X+dx;obj.y=Y+dy;
case 'resize'
cp=get(obj.Axesh,'CurrentPoint');
if Point==1;
obj.StartPoint=[cp(1,1), cp(1,2)];
else
obj.EndPoint=[cp(1,1), cp(1,2)];
end
end
obj.update;
end
function set.Number(obj,Value)
figure(obj.FigHandle);
if ishandle(obj.TextLabel);delete(obj.TextLabel);end
center=(obj.StartPoint+obj.EndPoint)./2;
obj.TextLabel=text('Position',center,'String',num2str(Value),'BackgroundColor',obj.Color);
set(obj.TextLabel,'uicontextmenu',obj.ContextMenu);
set(obj.TextLabel,'ButtonDownFcn',{@obj.ButtonDown,'Move'});
obj.StoredNumber=Value;
end
function Number=get.Number(obj)
Number=obj.StoredNumber;
end
function x=get.x(obj)
x=[obj.StartPoint(1) obj.EndPoint(1)];
end
function y=get.y(obj)
y=[obj.StartPoint(2) obj.EndPoint(2)];
end
function set.x(obj,Value)
obj.StartPoint(1)=Value(1);
obj.EndPoint(1)=Value(2);
end
function set.y(obj,Value)
obj.StartPoint(2)=Value(1);
obj.EndPoint(2)=Value(2);
end
function Profile=get.Profile(obj)
%determine lineprofile by nearest neighbour interpolation
image=get(obj.Imageh,'CData');
Rescale=get(obj.Imageh,'UserData');
image=image*Rescale(2)+Rescale(1);
L=round(norm(obj.EndPoint-obj.StartPoint));
dx=(obj.x(2)-obj.x(1))./L;
dy=(obj.y(2)-obj.y(1))./L;
Z=zeros(1,L);
Y=zeros(1,L);
X=zeros(1,L);
for i=1:L
Xi=round(obj.StartPoint(1)+(dx*i));
Yi=round(obj.StartPoint(2)+(dy*i));
Z(i)=image(Yi,Xi);
X(i)=Xi;
Y(i)=Yi;
end
Profile=[X; Y; Z];
end
function SendToWorkspace(obj,~,~)
varname=['Profile_' num2str(obj.Number)];
assignin('base',varname,obj.Profile)
end
function obj=Destroy(obj,~,~)
notify(obj,'DestroyObject',ROIDestruction(obj.Number))
set(obj.FigHandle,'WindowButtonMotionFcn','');
set(obj.FigHandle,'WindowButtonUpFcn','');
if ishandle(obj.Handle)
delete(obj.Handle);
end
if ishandle(obj.TextLabel)
delete(obj.TextLabel);
end
delete(obj);
end
function CreateMenu(obj)
obj.ContextMenu=uicontextmenu;
obj.ContextMenuItem(1)=uimenu(obj.ContextMenu, 'Label', 'Delete','Callback',@obj.Destroy);
obj.ContextMenuItem(2)=uimenu(obj.ContextMenu, 'Label', 'Send Data to Workspace','Callback',{@obj.SendToWorkspace});
end
end
end