% % % Camera Set Angle Function for Imaris % % Copyright Bitplane AG 2006 % % % Installation: % % - Copy this file into the XTensions folder in the Imaris installation directory % - You will find this function in the Image Processing menu % % % % % % Matlab::BPCameraSetAngle(%i) % % % % % % % Description: % % The angle of the camera is defined using the % [Azimuth, Elevation, Angle] coordinates. % The camera is rotated around axis Y by Angle, then around axis X by % Elevation, then around axis Y by Azimuth. % Coordinates can be ambiguous: Different Azimuth, Elevation, Angle can % determine the same camera orientation. % The user can specify the coordinates through 3 sliders. % % function BPCameraSetAngle(aImarisApplicationID) global vImarisApplication; global vSliderAzimuth vSliderElevation vSliderAngle; global vEditAzimuth vEditElevation vEditAngle; % slider callbacks if aImarisApplicationID==-1 clear global vImarisApplication; clear global vSliderAzimuth vSliderElevation vSliderAngle; clear global vEditAzimuth vEditElevation vEditAngle; return; elseif aImarisApplicationID==-2 SliderMove; return; elseif aImarisApplicationID==-3 EditChange; return; elseif aImarisApplicationID==-4 ButtonPush; return; end % connect to Imaris Com interface if ~isa(aImarisApplicationID, 'COM.Imaris_Application') vImarisServer = actxserver('ImarisServer.Server'); vImarisApplication = vImarisServer.GetObject(aImarisApplicationID); else vImarisApplication = aImarisApplicationID; end uicontrol('Style', 'text', 'String', 'Angle', 'Position', [10,70,90,20]); vEditAngle = uicontrol('Style', 'edit', 'String', '0', 'Position', [410,70,90,20], ... 'Callback', 'BPCameraSetAngle(-3)'); vSliderAngle = uicontrol('Style', 'slider', 'Position', [100,70,300,20], ... 'Min', -180, 'Max', 180, 'Value', 0, 'SliderStep', [0.01,0.1], ... 'Callback', 'BPCameraSetAngle(-2)'); uicontrol('Style', 'text', 'String', 'Elevation', 'Position', [10,40,90,20]); vEditElevation = uicontrol('Style', 'edit', 'String', '0', 'Position', [410,40,90,20], ... 'Callback', 'BPCameraSetAngle(-3)'); vSliderElevation = uicontrol('Style', 'slider', 'Position', [100,40,300,20], ... 'Min', -180, 'Max', 180, 'Value', 0, 'SliderStep', [0.01,0.1], ... 'Callback', 'BPCameraSetAngle(-2)'); uicontrol('Style', 'text', 'String', 'Azimuth', 'Position', [10,10,90,20]) vEditAzimuth = uicontrol('Style', 'edit', 'String', '0', 'Position', [410,10,90,20], ... 'Callback', 'BPCameraSetAngle(-3)'); vSliderAzimuth = uicontrol('Style', 'slider', 'Position', [100,10,300,20], ... 'Min', -180, 'Max', 180, 'Value', 0, 'SliderStep', [0.01,0.1], ... 'Callback', 'BPCameraSetAngle(-2)'); uicontrol('Style', 'pushbutton', 'String', 'Get angles from Imaris', ... 'Position', [320,100,180,25], 'Callback', 'BPCameraSetAngle(-4)', ... 'DeleteFcn', 'BPCameraSetAngle(-1)'); vWindow = get(vSliderAzimuth, 'Parent'); vWindowPosition = get(vWindow, 'Position'); vWindowPosition(3:4) = [510, 130]; set(vWindow, 'Position', vWindowPosition); function SliderMove() % slider global vSliderAzimuth vSliderElevation vSliderAngle; global vEditAzimuth vEditElevation vEditAngle; vAngle = get(vSliderAngle, 'Value'); vElevation = get(vSliderElevation, 'Value'); vAzimuth = get(vSliderAzimuth, 'Value'); set(vEditAngle, 'String', num2str(vAngle)); set(vEditElevation, 'String', num2str(vElevation)); set(vEditAzimuth, 'String', num2str(vAzimuth)); CameraSetAngle(vAzimuth, vElevation, vAngle); function EditChange() % edit global vSliderAzimuth vSliderElevation vSliderAngle; global vEditAzimuth vEditElevation vEditAngle; vAngle = str2double(get(vEditAngle, 'String')); vElevation = str2double(get(vEditElevation, 'String')); vAzimuth = str2double(get(vEditAzimuth, 'String')); while vAngle>180, vAngle = vAngle-360; end; while vAngle<-180, vAngle = vAngle+360; end; while vElevation>180, vElevation = vElevation-360; end; while vElevation<-180, vElevation = vElevation+360; end; while vAzimuth>180, vAzimuth = vAzimuth-360; end; while vAzimuth<-180, vAzimuth = vAzimuth+360; end; set(vSliderAngle, 'Value', vAngle); set(vSliderElevation, 'Value', vElevation); set(vSliderAzimuth, 'Value', vAzimuth); CameraSetAngle(vAzimuth, vElevation, vAngle); function ButtonPush() % get global vImarisApplication; global vSliderAzimuth vSliderElevation vSliderAngle; global vEditAzimuth vEditElevation vEditAngle; % get the camera vCamera = vImarisApplication.mSurpassCamera; [vOrientationX, vOrientationY, vOrientationZ, vCameraAngle] = vCamera.GetOrientationAxisAngle; vAxis = [vOrientationX; vOrientationY; vOrientationZ]; vAxis = vAxis/norm(vAxis); vDirectionX = RotateVA([1;0;0],vAxis,vCameraAngle); vDirectionY = RotateVA([0;1;0],vAxis,vCameraAngle); % vDirectionZ = RotateVA([0;0;1],vAxis,vCameraAngle); % computes the angle if vDirectionY(2)==1 % ambiguous situation vAngle = acos(vDirectionX(1)); if vDirectionX(1)<0 vAngle = -vAngle; end else vAngle = acos(vDirectionY(3)/norm(vDirectionY([1,3]))); if vDirectionY(1)<0 vAngle = -vAngle; end end vDirectionX = RotateVA(vDirectionX,[0;1;0],-vAngle); vDirectionY = RotateVA(vDirectionY,[0;1;0],-vAngle); % computes the elevation vElevation = acos(vDirectionY(2)); if vDirectionY(3)<0 vElevation = -vElevation; end vDirectionX = RotateVA(vDirectionX,[1;0;0],-vElevation); % computes the azimuth vAzimuth = acos(vDirectionX(1)); if vDirectionX(3)>0 vAzimuth = -vAzimuth; end % converts from radiants to degrees vAngle = vAngle*180/pi; vElevation = vElevation*180/pi; vAzimuth = vAzimuth*180/pi; set(vSliderAngle, 'Value', vAngle); set(vSliderElevation, 'Value', vElevation); set(vSliderAzimuth, 'Value', vAzimuth); set(vEditAngle, 'String', num2str(vAngle)); set(vEditElevation, 'String', num2str(vElevation)); set(vEditAzimuth, 'String', num2str(vAzimuth)); function CameraSetAngle(vAzimuth, vElevation, vAngle) % set global vImarisApplication; % converts from degrees to radiants vAzimuth = vAzimuth*pi/180; vElevation = vElevation*pi/180; vAngle = vAngle*pi/180; % get the camera vCamera = vImarisApplication.mSurpassCamera; [vPositionX, vPositionY, vPositionZ] = vCamera.GetPosition; vPosition = [vPositionX; vPositionY; vPositionZ]; [vOrientationX, vOrientationY, vOrientationZ, vCameraAngle] = vCamera.GetOrientationAxisAngle; vAxis = [vOrientationX; vOrientationY; vOrientationZ]; vAxis = vAxis/norm(vAxis); vFocus = vCamera.mFocus; vDirection = RotateVA([0;0;1],vAxis,vCameraAngle); vCenter = vPosition-vFocus*vDirection; % computes the coordinates of the axis after the desired rotations vAxis = eye(3); vNewAxisX = RotateVA(vAxis(:,1),[0;1;0],vAzimuth); vNewAxisX = RotateVA(vNewAxisX,[1;0;0],vElevation); vNewAxisX = RotateVA(vNewAxisX,[0;1;0],vAngle); vNewAxisY = RotateVA(vAxis(:,2),[0;1;0],vAzimuth); vNewAxisY = RotateVA(vNewAxisY,[1;0;0],vElevation); vNewAxisY = RotateVA(vNewAxisY,[0;1;0],vAngle); vNewAxisZ = RotateVA(vAxis(:,3),[0;1;0],vAzimuth); vNewAxisZ = RotateVA(vNewAxisZ,[1;0;0],vElevation); vNewAxisZ = RotateVA(vNewAxisZ,[0;1;0],vAngle); vNewAxis = [vNewAxisX,vNewAxisY,vNewAxisZ]; vDelta = vNewAxis-vAxis; % computes the axis of rotation % find and discard the less significant dimension % cross(vDelta(:,1),vDelta(:,2))==cross(vDelta(:,2),vDelta(:,3))== % cross(vDelta(:,3),vDelta(:,1)), for ~(vDelta(:,i)==0) [vMin, vDim] = min(sum(vDelta.^2)); vAxis = vDelta(:,[1:vDim-1,vDim+1:3]); vAxis = cross(vAxis(:,1),vAxis(:,2)); if norm(vAxis)>0 vAxis = vAxis/norm(vAxis); end % computes the angle using the most significant dimension [vMax, vDim] = max(sum(vDelta.^2)); vStart = [0;0;0]; vStart(vDim) = 1; vEnd = vNewAxis(:,vDim); vStartProjected = dot(vStart,vAxis)*vAxis; vEndProjected = dot(vEnd,vAxis)*vAxis; vStart = vStart-vStartProjected; vEnd = vEnd-vEndProjected; vCameraAngle = acos(dot(vStart,vEnd)/(norm(vStart)*norm(vEnd))); if dot(vAxis,cross(vStart,vEnd))<0 vCameraAngle = -vCameraAngle; end vDirection = RotateVA([0;0;1],vAxis,vCameraAngle); vPos = vCenter+vFocus*vDirection; vCamera.SetPosition(vPos(1), vPos(2), vPos(3)); vCamera.SetOrientationAxisAngle(vAxis(1), vAxis(2), vAxis(3), vCameraAngle); function aResult = RotateVA(aVector, aAxis, aAngle) % rotate aVector around aAxis by aAngle aResult = aVector .* cos(aAngle) + aAxis.*dot(aAxis,aVector) .* (1-cos(aAngle)) + ... cross(aAxis,aVector) .* sin(aAngle);