0001 classdef QuadTreePURBFInterpolant < Interpolant
0002
0003
0004
0005
0006 properties
0007 root;
0008 weightingRBF;
0009 distFun;
0010 end
0011
0012 methods
0013 function obj = QuadTreePURBFInterpolant(x, y, z, varargin)
0014
0015
0016
0017 obj@Interpolant(x, y, z);
0018
0019
0020 paramsToDelete = {'PolynomialDegree', 'RBF', 'RBFEpsilon', 'Smooth', 'Regularization'};
0021 vararginA = deleteParamsFromVarargin(paramsToDelete, varargin);
0022
0023 p = inputParser;
0024 validOverlap = @(x) isscalar(x) && x >= 0;
0025 validDistanceType = @(x) ischar(x) && strcmpi(x, 'euclidean') || strcmpi(x, 'haversine');
0026 validMinCellSizePercent = @(x) isscalar(x) && x <= 1 && x >= 0;
0027 validDomain = @(x) numel(x) == 4;
0028 addParameter(p, 'MinPointsInCell', 25, @isscalar);
0029 addParameter(p, 'MinCellSizePercent', 0.1, validMinCellSizePercent);
0030 addParameter(p, 'Overlap', 0.25, validOverlap);
0031 addParameter(p, 'DistanceType', 'euclidean', validDistanceType);
0032 addParameter(p, 'Domain', [], validDomain);
0033 parse(p, vararginA{:});
0034
0035 minPts = p.Results.MinPointsInCell;
0036 overlap = p.Results.Overlap;
0037 domain = p.Results.Domain;
0038 minCellSizePercent = p.Results.MinCellSizePercent;
0039
0040 distanceType = p.Results.DistanceType;
0041 if strcmpi(distanceType, 'euclidean')
0042 obj.distFun = @(x, y) vecnorm(x-y, 2, 2);
0043 elseif strcmpi(distanceType, 'haversine')
0044 obj.distFun = @haversine;
0045 else
0046 error('Unknown DistanceType');
0047 end
0048
0049
0050
0051 paramsToDelete = {'MinPointsInCell', 'MinCellSizePercent', 'Overlap', 'Domain'};
0052 vararginB = deleteParamsFromVarargin(paramsToDelete, varargin);
0053
0054
0055 if isempty(domain)
0056
0057
0058 minX = min(obj.data(:, 1)); maxX = max(obj.data(:, 1));
0059 minY = min(obj.data(:, 2)); maxY = max(obj.data(:, 2));
0060 w = maxX-minX;
0061 h = maxY-minY;
0062 else
0063 minX = domain(1);
0064 minY = domain(2);
0065 w = domain(3);
0066 h = domain(4);
0067 end
0068
0069
0070
0071 wh = max([w, h]);
0072
0073 obj.root = QTNode(minX, minY, wh, wh, obj.data, obj.distFun, overlap);
0074
0075
0076 obj.root = obj.root.subdivide(minPts, wh*minCellSizePercent);
0077
0078
0079
0080 obj.root.freeMemory();
0081
0082
0083 obj.root = obj.root.computeRBFAtLeafs(vararginB{:});
0084 end
0085
0086 function plot(obj, newFigure)
0087
0088 if nargin < 2
0089 newFigure = false;
0090 end
0091 if newFigure
0092 figure();
0093 end
0094 hold on;
0095 nodes = getLeaves(obj.root);
0096 for i = 1:numel(nodes)
0097 hold on;
0098 rectangle('Position', [nodes(i).x, nodes(i).y, nodes(i).w, nodes(i).h]);
0099 hold off;
0100 cx = nodes(i).x + (nodes(i).w/2);
0101 cy = nodes(i).y + (nodes(i).h/2);
0102 r = nodes(i).getEuclideanRadius();
0103
0104 plotCircle(cx, cy, r);
0105
0106
0107
0108
0109 end
0110 hold on;
0111 plot(obj.data(:, 1), obj.data(:, 2), '.k');
0112 hold off;
0113 axis equal;
0114 end
0115
0116 function z = interpolate(obj, x, y)
0117
0118
0119
0120
0121
0122 Interpolant.checkSizes(x, y);
0123
0124
0125 orSize = size(x);
0126 x = x(:);
0127 y = y(:);
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153 leaves = getLeaves(obj.root);
0154
0155
0156 numLeaves = numel(leaves);
0157 centers = zeros(numLeaves, 2);
0158 radius = zeros(numLeaves, 1);
0159 for i = 1:numLeaves
0160 centers(i, :) = leaves(i).getCenter();
0161 radius(i) = leaves(i).getRadius();
0162 end
0163
0164 dists = pdist2([x, y], centers, obj.distFun);
0165
0166
0167 f = zeros(numel(x), 1);
0168 w = zeros(numel(x), 1);
0169 for i = 1:numLeaves
0170
0171 ind = dists(:, i) <= radius(i);
0172
0173
0174 rbfEval = leaves(i).rbfInterp.interpolate(x(ind), y(ind));
0175
0176
0177 weights = leaves(i).weightingRBF(dists(ind, i));
0178
0179
0180
0181 f(ind) = f(ind) + rbfEval.*weights;
0182
0183
0184 w(ind) = w(ind)+weights;
0185 end
0186 z = f./w;
0187
0188
0189 z = reshape(z, orSize);
0190 end
0191 end
0192 end
0193