function Angles = AnglesBetweenSuccessiveNorms( normals ) % -------------------------------------- % Angles = AnglesBetweenSuccessiveNorms( normals ) % % Find angle between each pair of segments % % Note: Normals must be unit-length, stacked on top of each other. % Note2 Angle between the last vector and no-vector is zero. A = normals(1:end-1, : ); B = normals(2:end, : ); % angle = acos(dot(A',B'))'; % Note dot() goes down columns first, but we have rows. %angle = mod( atan2(A(:,1).*B(:,2)-B(:,1).*A(:,2), A(:,1).*B(:,1)+A(:,2).*B(:,2)), 2*pi); angle = atan2(A(:,1).*B(:,2)-B(:,1).*A(:,2), A(:,1).*B(:,1)+A(:,2).*B(:,2)); % Explanation of finding angle between 2 normalized vec's: % dot(A,B) = 1*1*cos(theta), so theta = acos( dot(A,B) ) % BUT % atan is considered safer than acos when cos(theta) is near 1; % try it: a = pi*(1-1/10^8); atan2(sin(a), cos(a)) - acos(cos(a)) != 0 % SO % tan(a) = sin(a) / cos(a), so a = atan( sin, cos ): % cos = dot product, as above, % sin: cross(A,B) = |A||B| . sin(a) . n, where n = unit vector perpendicular to both A and B. % here, just need to pad A and B with z=0 to make 3-vectors. % % FINALLY, % 'atan2' function gives between-angle [-pi, +pi], and the 'mod' changes this to [0, 2*pi] % -------------------------------------- Angles = [angle;0]; % The angle between the last vector and no-vector is zero.