0001 classdef MLSInterpolant < Interpolant
0002
0003
0004 properties
0005 polyDeg;
0006 rbfFun;
0007 searchObj;
0008 minSamples;
0009 end
0010
0011 methods
0012 function obj = MLSInterpolant(x, y, z, varargin)
0013
0014
0015
0016
0017 obj@Interpolant(x, y, z);
0018
0019
0020 validDistanceType = @(x) ischar(x) && strcmpi(x, 'euclidean') || strcmpi(x, 'haversine');
0021 validPolynomialDegree = @(x) isscalar(x) && x >= 0 && x < 3;
0022 validRBFType = @(x) isa(x, 'function_handle') || ...
0023 (ischar(x) && strcmpi(x, 'wendland'));
0024 validMinNumSamples = @(x) isscalar(x) && x > 0;
0025
0026
0027 p = inputParser;
0028 addParameter(p, 'DistanceType', 'euclidean', validDistanceType);
0029 addParameter(p, 'PolynomialDegree', 0, validPolynomialDegree);
0030 addParameter(p, 'RBF', 'wendland', validRBFType);
0031 addParameter(p, 'RBFEpsilon', 1, @isscalar);
0032 addParameter(p, 'MinSamples', 10, validMinNumSamples);
0033 parse(p, varargin{:});
0034
0035
0036 obj.rbfFun = rbfTypeToFunctor(p.Results.RBF, p.Results.RBFEpsilon);
0037
0038
0039 obj.polyDeg = p.Results.PolynomialDegree;
0040
0041
0042 obj.minSamples = p.Results.MinSamples;
0043
0044
0045
0046
0047 coeffs = bivariatePolynomialTerms(obj.polyDeg, 1, 1);
0048 if obj.minSamples < numel(coeffs)
0049 warning('The minimum number of samples set (%d) is less than the minimum number of samples that correspond to the selected polynomial degree. Settin the minimum number of samples to %d!', obj.minSamples, numel(coeffs));
0050 obj.minSamples = numel(coeffs);
0051 end
0052
0053
0054 obj.searchObj = QueryNeighborhood(obj.data, 'Radius', p.Results.RBFEpsilon, ...
0055 'SearchType', 'radial', ...
0056 'DistanceType', p.Results.DistanceType);
0057 end
0058
0059 function z = interpolate(obj, x, y)
0060
0061
0062
0063 Interpolant.checkSizes(x, y);
0064
0065
0066 [ind, distances] = obj.searchObj.getNeighbors(x, y);
0067
0068 z = zeros(size(x));
0069 for i = 1:numel(ind)
0070
0071 neighData = obj.data(ind{i}, :);
0072
0073
0074
0075 if size(neighData, 1) < obj.minSamples
0076 z(i) = NaN;
0077 continue;
0078 end
0079
0080
0081 polyCoeffs = obj.solveSingleMLS(neighData(:, 1), neighData(:, 2), neighData(:, 3), distances{i});
0082
0083
0084 polyTerms = bivariatePolynomialTerms(obj.polyDeg, x(i), y(i));
0085 z(i) = polyTerms*polyCoeffs;
0086 end
0087 end
0088
0089 function polyCoeffs = solveSingleMLS(obj, x, y, z, dist)
0090
0091 numSamples = size(x, 1);
0092
0093
0094 P = bivariatePolynomialTerms(obj.polyDeg, x(:), y(:));
0095
0096
0097 W = zeros(numSamples);
0098 W(logical(eye(numSamples))) = obj.rbfFun(dist);
0099
0100
0101 A = P'*W*P;
0102 B = P'*W;
0103 polyCoeffs = inv(A)*B*z;
0104
0105 end
0106 end
0107 end
0108