123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111 |
- function [ROIS] = dicomrt_rasterizeVoi(VOI, ct, ct_xmesh, ct_ymesh, ct_zmesh)
- % See also: dicomrt_build3dVOI()
- % Check input
- % % % Commented for ease of downsample
- % % % [ct_temp,type_ct,label,PatientPosition]=dicomrt_checkinput(ct);
- % % % ct=dicomrt_varfilter(ct_temp);
- [VOI_temp]=dicomrt_checkinput(VOI);
- VOI=dicomrt_varfilter(VOI_temp);
- % TODO check VOI has to be 2D and along z
- % TODO(?) check x,y,zmesh has to be monotonic and unique
- % assistant variables
- xdim = length(ct_xmesh);
- ydim = length(ct_ymesh);
- zdim = length(ct_zmesh);
- voi2use = 1:size(VOI,1);
- [XMESH YMESH] = meshgrid(ct_xmesh, ct_ymesh);
- % Progress bar data
- h = waitbar(0, 'Rasterizing', 'Name', 'dicomrt_rasterizeVoi');
- for kk = 1:length(voi2use)
- waitbar(kk./length(voi2use), h, ['Rasterizing: ', VOI{kk,1}]);
-
- % For each voi create a matrix with just 1 and 0
- rasterVOI = zeros(xdim, ydim, zdim, 'int8');
- num_curves = numel(VOI{kk,2});
- for k = 1:num_curves
- % the N x 3 curve matrix
- curve = VOI{kk,2}{k};
- % skip empty curves
- numPoints = size(curve,1);
- if numPoints < 3
- continue;
- end
- % z coordinate of current VOI
- voi_z = VOI{kk,2}{k}(1,3);
- % find the appropriate slice
- % TODO can simplify this once I'm more confident
- dist_z = abs(ct_zmesh-voi_z);
- slice = find(dist_z == min(dist_z));
- % slice = find(abs(ct_zmesh-voi_z) < dz);
- if isempty(slice)
- warning('Can not find matching slice');
- error('Closest slice found at %f cm', min(abs(ct_zmesh-voi_z)));
- elseif numel(slice) > 1
- warning('Multiple matching slices found');
- elseif dist_z(slice) >= abs(ct_zmesh(1)-ct_zmesh(2))
- error('Closest slice found at %f cm', min(abs(ct_zmesh-voi_z)));
- end
- % binary mask of current curve
- if exist('InPolygon', 'file') == 3
- % favor the mex function for performance
- BW = InPolygon(XMESH,YMESH,curve(:,1),curve(:,2));
- else
- BW = inpolygon(XMESH,YMESH,curve(:,1),curve(:,2));
- end
-
- % merge with existing curve
- rasterVOI(:,:,slice) = int8(xor(BW, rasterVOI(:,:,slice)));
- end
-
- % Create contour polygon on X and Y plane
- Xcurves = cell(0);
- for slice = 1:size(rasterVOI, 1)
- B = bwboundaries(squeeze(rasterVOI(slice,:,:)));
- if ~isempty(B)
- for ii = 1:numel(B)
- % Here x, y, z vertices means coordinate along 1st, 2nd and 3rd dimension,
- % respectively as in line Xcurves{end+1} = cat(2, x, y, z);
- x_vertices = ct_xmesh(slice) * ones(size(B{ii}, 1), 1);
- y_vertices = interp1(1:numel(ct_ymesh), ct_ymesh, B{ii}(:,1));
- z_vertices = interp1(1:numel(ct_zmesh), ct_zmesh, B{ii}(:,2));
- Xcurves{end+1} = cat(2, x_vertices, y_vertices, z_vertices);
- end
- end
- end
-
- Ycurves = cell(0);
- for slice = 1:size(rasterVOI, 2)
- B = bwboundaries(squeeze(rasterVOI(:,slice,:)));
- if ~isempty(B)
- for ii = 1:numel(B)
- y_vertices = ct_ymesh(slice) * ones(size(B{ii}, 1), 1);
- x_vertices = interp1(1:numel(ct_xmesh), ct_xmesh, B{ii}(:,1));
- z_vertices = interp1(1:numel(ct_zmesh), ct_zmesh, B{ii}(:,2));
- Ycurves{end+1} = cat(2, x_vertices, y_vertices, z_vertices);
- end
- end
- end
-
- % Save the ROIs struct
- % ROIS{kk}.BW = rasterVOI;
- ROIS{kk}.name = VOI{kk,1};
- ROIS{kk}.Xcurves = Xcurves;
- ROIS{kk}.Ycurves = Ycurves;
- % legacy nomenclature: num_curves and curves both refer to Z dimension
- ROIS{kk}.num_curves = num_curves;
- for k = 1:num_curves
- ROIS{kk}.curves{k} = VOI{kk,2}{k};
- end
- ROIS{kk}.ind = int32(find(rasterVOI));
- ROIS{kk}.dim = [xdim ydim zdim];
- ROIS{kk}.pixdim = [abs(ct_xmesh(2)-ct_xmesh(1)) abs(ct_ymesh(2)-ct_ymesh(1)) abs(ct_zmesh(2)-ct_zmesh(1))];
- ROIS{kk}.start = [ct_xmesh(1) ct_ymesh(1) ct_zmesh(1)];
- ROIS{kk}.start_ind = '(1,1,1)';
- end
- delete(h);
|