Hi, Dr. Treeby,
I found that the same interpolation results given by 'gridDataFast' are slightly different from the ones from 'TriScatteredInterp'. And, as you mentioned in the previous post, 'TriScatteredInterp' cannot be used with 'single' or 'gsingle' data type.
So I modified the 'gridDataFast' so that it will give the exact same interpolation results as 'TriScatteredInterp', and it supports 'DataCast', which means we can use GPUs to accelerate the computation in 3D case if 'CartInterp' is set to be 'linear'.
In 2D case, the modified version is:
function [tri, bc] = gridDataFast2D(x, y, xi, yi)
% enforce x, y, xi, yi to be column vectors
x = x(:);
y = y(:);
xi = xi(:);
yi = yi(:);
% triangulize the data
tri = DelaunayTri(x, y);
% catch trinagulation error
if isempty(tri)
error('Data cannot be triangulated.');
end
% find the nearest triangle and the corresponding Barycentric coordinates
[t, bc] = pointLocation(tri,[xi yi]);
tri = tri(t,:);
After the 'tri' and 'bc' are computed in 'kspaceFirstOrder_createStorageVariables', the 'sensor_data' can be calculated by sensor_data(:, t_index) = sum(p(sensor.tri) .* sensor.bc, 2) in the kspaceFirstOrder2D.
Likely, the 3D version is:
function [tri, bc] = gridDataFast3D(x, y, z, xi, yi, zi)
% enforce x, y, z, xi, yi, zi to be column vectors
x = x(:);
y = y(:);
z = z(:);
xi = xi(:);
yi = yi(:);
zi = zi(:);
% triangulize the data
tri = DelaunayTri(x, y, z);
% catch trinagulation error
if isempty(tri)
error('Data cannot be triangulated.');
end
% find the nearest triangle and the corresponding Barycentric coordinates
[t, bc] = pointLocation(tri,[xi yi zi]);
tri = tri(t,:);
Similarly, After the 'tri' and 'bc' are computed in 'kspaceFirstOrder_createStorageVariables', the 'sensor_data' can be calculated by sensor_data(:, t_index) = sum(p(sensor.tri) .* sensor.bc, 2) in the kspaceFirstOrder3D.
Also, I found the modified 'gridDataFast2D' and 'gridDataFast3D' are faster than 'gridDataFast' and 'TriScatteredInterp'. For example, in 2D case, we had:
tic;
[tri, bc] = gridDataFast2D(kgrid.x, kgrid.y, sensor.mask(1,:), sensor.mask(2,:));
i1 = sum(source.p0(tri) .* bc,2);
toc
Elapsed time is 1.072967 seconds.
tic;
[zi, del_tri] = gridDataFast(kgrid.x, kgrid.y, zeros(kgrid.Nx, kgrid.Ny), sensor.mask(1,:), sensor.mask(2,:));
i2 = gridDataFast(kgrid.x, kgrid.y, source.p0, sensor.mask(1,:), sensor.mask(2,:), del_tri);
toc
Elapsed time is 5.227701 seconds.
tic;
F_interp = TriScatteredInterp(reshape(kgrid.x, [], 1), reshape(kgrid.y, [], 1), reshape(zeros(kgrid.Nx, kgrid.Ny), [], 1));
F_interp.V = reshape(source.p0, [], 1);
i3 = F_interp(sensor.mask(1, :), sensor.mask(2, :));
toc
Elapsed time is 2.090216 seconds.
In 3D:
tic;
[tri, bc] = gridDataFast3D(kgrid.x, kgrid.y, kgrid.z, sensor.mask(1,:), sensor.mask(2,:), sensor.mask(3,:));
i1 = sum(source.p0(tri) .* bc,2);
toc
Elapsed time is 98.273495 seconds.
tic;
F_interp = TriScatteredInterp(reshape(kgrid.x, [], 1), reshape(kgrid.y, [], 1), reshape(kgrid.z, [], 1), reshape(zeros(kgrid.Nx, kgrid.Ny, kgrid.Nz), [], 1));
F_interp.V = reshape(source.p0, [], 1);
i2 = F_interp(sensor.mask(1,:), sensor.mask(2,:), sensor.mask(3,:));
toc
Elapsed time is 135.914373 seconds.
Best,
Chao