function [KJC_axes] = findkneeaxes(fname,knee) % read in trc file mkr_data = dlmread(fname,'\t',6,2); if knee == 'L' % create xyz 3D column arrays for each marker TH1 = mkr_data(:,37:39); TH2 = mkr_data(:,40:42); TH3 = mkr_data(:,43:45); TB1 = mkr_data(:,46:48); TB2 = mkr_data(:,49:51); TB3 = mkr_data(:,52:54); else TH1 = mkr_data(:,10:12); TH2 = mkr_data(:,13:15); TH3 = mkr_data(:,16:18); TB1 = mkr_data(:,19:21); TB2 = mkr_data(:,22:24); TB3 = mkr_data(:,25:27); end % define the thigh origin originThigh=TH2; %calculate unit vectors of Thigh segment relative to global [e1Thigh,e2Thigh,e3Thigh]=segmentorientationV2V1(originThigh-TH1,TH3-originThigh); %now transform the marker points into the Thigh coordinate system for i=1:length(e1Thigh) rotationmatrix=[e1Thigh(i,:);e2Thigh(i,:);e3Thigh(i,:)]; originThighvector=originThigh(i,:)'; TH1Thigh(i,:)=(rotationmatrix*(TH1(i,:)')-rotationmatrix*originThighvector)'; TH2Thigh(i,:)=(rotationmatrix*(TH2(i,:)')-rotationmatrix*originThighvector)'; TH3Thigh(i,:)=(rotationmatrix*(TH3(i,:)')-rotationmatrix*originThighvector)'; TB1Thigh(i,:)=(rotationmatrix*(TB1(i,:)')-rotationmatrix*originThighvector)'; TB2Thigh(i,:)=(rotationmatrix*(TB2(i,:)')-rotationmatrix*originThighvector)'; TB3Thigh(i,:)=(rotationmatrix*(TB3(i,:)')-rotationmatrix*originThighvector)'; end TibMarkersInThighCS=[TB1Thigh TB2Thigh TB3Thigh] % use hip centre code to find knee centre [KJC_location]=calc_HJC(ThighMarkersInPelvisCS) % decompose arrays to [x y z] TH1xThigh=TH1Thigh(:,1); TH1yThigh=TH1Thigh(:,2); TH1zThigh=TH1Thigh(:,3); TH2xThigh=TH2Thigh(:,1); TH2yThigh=TH2Thigh(:,2); TH2zThigh=TH2Thigh(:,3); TH3xThigh=TH3Thigh(:,1); TH3yThigh=TH3Thigh(:,2); TH3zThigh=TH3Thigh(:,3); TB1xThigh=TB1Thigh(:,1); TB1yThigh=TB1Thigh(:,2); TB1zThigh=TB1Thigh(:,3); TB2xThigh=TB2Thigh(:,1); TB2yThigh=TB2Thigh(:,2); TB2zThigh=TB2Thigh(:,3); TB3xThigh=TB3Thigh(:,1); TB3yThigh=TB3Thigh(:,2); TB3zThigh=TB3Thigh(:,3); close; scatter3(TH1xThigh,TH1yThigh,TH1zThigh); hold; scatter3(TH2xThigh,TH2yThigh,TH2zThigh); scatter3(TH3xThigh,TH3yThigh,TH3zThigh); scatter3(TB1xThigh,TB1yThigh,TB1zThigh,'r'); scatter3(TB3xThigh,TB3yThigh,TB3zThigh,'r'); scatter3(TB2xThigh,TB2yThigh,TB2zThigh,'r'); text(TH1xThigh(1),TH1yThigh(1),TH1zThigh(1),'TH1'); text(TH2xThigh(1),TH2yThigh(1),TH2zThigh(1),'TH2'); text(TH3xThigh(1),TH3yThigh(1),TH3zThigh(1),'TH3'); if knee == 'L' title('Left Knee Joint Instantaneous and Optimal Helical Axes. Enter to continue'); else title('Right Knee Joint Instantaneous and Optimal Helical Axes. Enter to continue'); end axis equal; axis manual; % create input matrix of tibia markers relative to thigh segment for calculation of helical axis. % Use soder.m and screw.m from Reinschmidt, Calgary (1996). vectlength = size(TB1Thigh,1); count = 0; I=eye(3,3); Q=zeros(3,3); Qsum=zeros(3,3); Qn=zeros(3,1); Qnsum=zeros(3,1); Qssum=zeros(3,1); threshold = 5; while count ==0 threshold = threshold-0.5; for i=1:vectlength-4 input1= TB1Thigh(i:i+3,1:3); input2= TB2Thigh(i:i+3,1:3); input3= TB3Thigh(i:i+3,1:3); input = [input1 input2 input3]; % create transformation matrix using singular value decomposition [T,res]=soder(input); % find helical axis using this transformation matrix intersect = 1; % location of the screw axis where it intersects either the x=0 (intersect=1), % the y=0 (intersect=2), or the z=0 (intersect=3) plane. [n,point,phi,t]=screw(T,intersect); % only use helical axes that are predicted with phi greater than 5 degrees if phi>threshold scatter3(point(1),point(2),point(3),'r') % text(point(1),point(2),point(3),'point') % create another 2 points along the helical axis approx the width of a knee (100 mm) vect=(50/n(1))*n; point2=point-vect; point3=point+vect; axisline=[point point2 point3]; plot3(axisline(1,:),axisline(2,:),axisline(3,:),'k') s=point; count=count+1; Q=I-n*n'; Qn=Q*n; Qs=Q*s; Qsum=Q+Qsum; Qnsum=Qn+Qnsum; Qssum=Qs+Qssum; end end end Qnmean=Qnsum/count; Qsmean=Qssum/count; Qmean=Qsum/count; Nopt=inv(Qmean)*Qnmean; Sopt=inv(Qmean)*Qsmean; half_knee_width = 50; %distance(LLFC,LMFC)/2; % epicondylar_axis=LLFC-LMFC; % v % knee_centre = (LLFC+LMFC)/2; %P helical_axis_vector=(half_knee_width/Nopt(1))*Nopt; HA1=Sopt-helical_axis_vector; HA2=Sopt+helical_axis_vector; axisline=[Sopt HA1 HA2]; HA1x=HA1(1); HA1y=HA1(2); HA1z=HA1(3); HA2x=HA2(1); HA2y=HA2(2); HA2z=HA2(3); plot3(axisline(1,:),axisline(2,:),axisline(3,:),'b','LineWidth',3) pause; close; KJC_axes = [HA1 HA2]; % given that we have two axes defined, and the centre of the knee joint, we can define a plane perpendicular % to the Epicondyle axis that intersects the centre of the knee joint. The point that this plane intersects onto % the helical axis is defined as the new joint centre, and the helical axis can be redefined in body builder using % two new virtual markers. % The line of the optimal helical axis defined as: % x = xo + at % y = yo + bt Eq(1) % z = zo + ct % where xo,yo,zo describe a point along the line (such as Sopt) and describe the unit vector of the line (helical_axis_vector) % %The plane perpendicular to the epicondylar axis and running through the centre of the knee is defined by: % a(x-xo)+b(y-yo)+c(z-zo)=0 Eq(2) % where xo,yo,zo define a point on the plane (knee_centre) and define the unit vector of the perpendicular plane (epicondylar_axis) % % need to join Eq (1) and (2) to solve for t, then substitute this value back into eq (1) % t = (dot(epicondylar_axis,knee_centre)-dot(epicondylar_axis,Sopt))/dot(epicondylar_axis,helical_axis_vector); % % new_knee_centre_x = Sopt(1)+helical_axis_vector(1)*t; % new_knee_centre_y = Sopt(2)+helical_axis_vector(2)*t; % new_knee_centre_z = Sopt(3)+helical_axis_vector(3)*t; % new_knee_centre=[new_knee_centre_x;new_knee_centre_y;new_knee_centre_z]; % define new virtual markers on the helical axis (make them roughly the width of the knee). % LHA1=new_knee_centre+helical_axis_vector; % LHA2=new_knee_centre-helical_axis_vector; % % axisline=[LHA1 LHA2]; % plot3(axisline(1,:),axisline(2,:),axisline(3,:),'b','LineWidth',3) % scatter3(new_knee_centre(1),new_knee_centre(2),new_knee_centre(3),'bo') % text(new_knee_centre(1),new_knee_centre(2),new_knee_centre(3),'new knee centre') % scatter3(LHA1(1),LHA1(2),LHA1(3),'ko') % text(LHA2(1),LHA2(2),LHA2(3),'LHA 2') % scatter3(LHA2(1),LHA2(2),LHA2(3),'ko') % text(LHA1(1),LHA1(2),LHA1(3),'LHA 1') % % title('Left Knee Joint Instantaneous and Optimal Helical Axes') % LeftKneeCentre=new_knee_centre;