## Copyright (C) 2014-2022 Carnë Draug ## ## This program is free software; you can redistribute it and/or modify it ## under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or (at ## your option) any later version. ## ## This program is distributed in the hope that it will be useful, but ## WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; see the file COPYING. If not, see ## . ## -*- texinfo -*- ## @deftypefn {Function File} {} degrees2dm (@var{deg}) ## Convert decimal degrees to its degrees and minutes components. ## ## Separates the fractional part of an angle in decimal degrees and converts ## it into minutes. Each row of the output corresponds to one angle, ## the first column to the degree component (an integer), and the second ## to the minutes (which may have a fractional part). ## ## @example ## @group ## degrees2dm (10 + 20/60) ## @result{} [ 10 20 ] ## ## degrees2dm (10 + pi) ## @result{} [ 10 8.4956 ] ## @end group ## @end example ## ## The sign of the first non-zero component indicates the sign of ## the angle, i.e., if the degree component is zero, the sign of the minutes ## indicates the sign of the angle, but if the degree component is non-zero, ## the minute component will be positive independently of the sign of the ## angle. For example: ## ## @example ## @group ## angles = [ 10.5 ## -10.5 ## -0.5 ## 0.5 ]; ## degrees2dm (angless) ## @result{} ## 10 30 ## -10 30 ## -0 -30 ## 0 30 ## @end group ## @end example ## ## @seealso{degrees2dms, dm2degrees, dms2degrees} ## @end deftypefn ## Author: Carnë Draug function dm = degrees2dm (deg) if (nargin != 1) print_usage (); endif if (! iscolumn (deg)) warning ("Octave:array-to-vector", "degrees2dm: DEG reshaped into column vector"); endif if (isinteger (deg)) ## If the angles are integers, there is no decimal part ## so this is easy. Also, class must be conserved. dm = [deg(:) zeros(numel (deg), 1, class (deg))]; else ## Everything else is valid and will be converted to double (including ## text and logical). Only class single will be conserved. d = fix (deg(:)); m = rem (deg(:) * 60, 60); dm = [d m]; ## We could have also calculated the seconds part with ## (deg(:) - d) * 60 ## but while that performs almost twice as fast, it also ## leads to some precision errors. ## remove sign from any minute where its degree part is non-zero nn = ~isnan (dm(:,1)); nnzd = false (rows (dm), 1); nnzd(nn) = logical (dm(nn,1)); dm(nnzd, 2) = abs (dm(nnzd, 2)); endif endfunction %!test %! deg = [10 10.5 -10.5 -0.5 0.5]'; %! dm = [ 10 0 %! 10 30 %! -10 30 %! 0 -30 %! 0 30]; %! for i = 1:rows (deg) %! assert (degrees2dm (deg(i)), dm(i,:)); %! assert (degrees2dm (single (deg(i))), single (dm(i,:))); %! endfor %! assert (degrees2dm (deg), dm); %! assert (degrees2dm (single (deg)), single (dm)); %! %! warning ("error", "Octave:array-to-vector", "local") %! got_warn = false; %! try %! degrees2dm (deg'); %! catch %! got_warn = true; %! end_try_catch %! assert (got_warn, true) %!assert (degrees2dm ("f"), [102 0]) %!assert (degrees2dm ("fm"), [102 0; 109 0]) %!assert (degrees2dm (true), [1 0]) %!assert (degrees2dm ([true false]), [1 0; 0 0]) %!assert (degrees2dm (uint8 ([5 48 9]')), uint8 ([5 0; 48 0; 9 0]))