1## Copyright (C) 2018 Martin Janda <janda.martin1@gmail.com>
2##
3## This program is free software: you can redistribute it and/or modify it
4## under the terms of the GNU General Public License as published by
5## the Free Software Foundation, either version 3 of the License, or
6## (at your option) any later version.
7##
8## This program is distributed in the hope that it will be useful, but
9## WITHOUT ANY WARRANTY; without even the implied warranty of
10## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11## GNU General Public License for more details.
12##
13## You should have received a copy of the GNU General Public License
14## along with this program.  If not, see
15## <https://www.gnu.org/licenses/>.
16
17## -*- texinfo -*-
18## @deftypefn {} {[@var{xIntrinsic}, @var{yIntrinsic}] =} worldToIntrinsic (@var{r}, @var{xWorld}, @var{yWorld})
19## Convert from world to intrinsic coordinates.
20##
21## Converts world coordinates @var{xWorld} and @var{yWorld} to intrinsic
22## coordinates @var{xIntrinsic} and @var{yIntrinsic} of an image associated
23## with the spatial referencing object @var{r}.  If a point
24## (@var{xWorld}(i), @var{yWorld}(i)) falls outside the bounds of the image,
25## its intrinsic coordinates are extrapolated, possibly resulting in
26## negative values.
27##
28## @seealso{imref2d, imref3d, intrinsicToWorld}
29## @end deftypefn
30
31function [xIntrinsic, yIntrinsic] = worldToIntrinsic (r, xWorld, yWorld)
32  if (nargin != 3)
33    print_usage ();
34  endif
35
36  validateattributes (xWorld, {"numeric"}, ...
37  {"real"}, "imref2d", "xWorld");
38  validateattributes (yWorld, {"numeric"}, ...
39  {"real"}, "imref2d", "yWorld");
40
41  if (! all (size (xWorld) == size (yWorld)))
42    error ("Octave:invalid-input-arg", ...
43    "xWorld and yWorld must be of the same size");
44  endif
45
46  xIntrinsicLimits = r.XIntrinsicLimits;
47  yIntrinsicLimits = r.YIntrinsicLimits;
48  xWorldLimits = r.XWorldLimits;
49  yWorldLimits = r.YWorldLimits;
50  xIntrinsic = xIntrinsicLimits(1) + (xWorld  - xWorldLimits(1)) ...
51  / r.PixelExtentInWorldX;
52  yIntrinsic = yIntrinsicLimits(1) + (yWorld  - yWorldLimits(1)) ...
53  / r.PixelExtentInWorldY;
54endfunction
55
56%!error id=Octave:invalid-fun-call worldToIntrinsic (imref2d)
57%!error id=Octave:invalid-fun-call worldToIntrinsic (imref2d, 1, 2, 3)
58%!error id=Octave:expected-real worldToIntrinsic (imref2d, 1j, 2)
59%!error id=Octave:expected-real worldToIntrinsic (imref2d, 1, 2j)
60%!error id=Octave:invalid-input-arg worldToIntrinsic (imref2d, [1, 2], 3)
61%!error id=Octave:invalid-input-arg worldToIntrinsic (imref2d, [1], [2, 3])
62
63%!test
64%! r = imref2d ([512, 512], 0.3125, 0.3125);
65%! xW = [38.44, 39.44, 38.44, -0.2];
66%! yW = [68.75, 68.75, 75.75, -1];
67%! [xI, yI] = worldToIntrinsic (r, xW, yW);
68%! assert (xI, [123.008, 126.208, 123.008, -0.64], 1e-6)
69%! assert (yI, [220, 220, 242.4, -3.2], 1e-6)