0001 function [c2f, m] = mk_grid_c2f(fmdl, rmdl, opt)
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061 persistent save_memory;
0062
0063 if ischar(fmdl) && strcmp(fmdl,'UNIT_TEST'), do_unit_test; return; end
0064 if ischar(fmdl) && strcmp(fmdl,'PROFILE'), do_small_test; return; end
0065 if ischar(fmdl) && strcmp(fmdl,'save_memory')
0066 if nargin ~= 2, error('Expected a value for save_memory option'); end
0067 if ischar(rmdl), rmdl = str2double(rmdl); end
0068 save_memory = rmdl;
0069 return
0070 end
0071 if nargin < 3
0072 opt = struct;
0073 end
0074 if ~isempty(save_memory)
0075 try
0076 opt.save_memory;
0077 catch
0078 opt.save_memory = save_memory;
0079 end
0080 end
0081
0082 [fmdl,rmdl] = eidors_cache(@center_scale_models,{fmdl,rmdl, opt});
0083
0084 opt = eidors_cache(@parse_opts,{fmdl,rmdl, opt});
0085
0086 copt.cache_obj = {fmdl.nodes,
0087 fmdl.elems,
0088 rmdl.nodes,
0089 rmdl.elems,
0090 rmfield(opt,'save_memory')};
0091
0092 copt.fstr = 'mk_grid_c2f';
0093
0094 [c2f, m] = eidors_cache(@do_mk_grid_c2f,{fmdl,rmdl,opt},copt);
0095
0096
0097
0098
0099
0100 function [c2f, m]= do_mk_grid_c2f(fmdl0,rmdl0,opt0)
0101 eidors_msg('@@@',2);
0102
0103 m = [];
0104 c2f = sparse(opt0.nTet,opt0.nVox);
0105
0106 progress_msg('Prepare tet model...');
0107 fmdl0 = prepare_fmdl(fmdl0);
0108 progress_msg(Inf);
0109
0110 if opt0.save_memory == 0
0111 relem_idx = ones(opt0.nVox,1);
0112 [fmdl, rmdl, opt, felem_idx] = crop_models(fmdl0,rmdl0,opt0,relem_idx);
0113 if any(felem_idx)
0114 [tmp, m] = separable_calculations(fmdl,rmdl0,opt);
0115 c2f = combine_c2f(c2f, tmp,felem_idx,relem_idx);
0116 end
0117 elseif opt0.save_memory == 10
0118
0119
0120
0121 logmsg(' Saving memory mode level %d\n',opt0.save_memory);
0122 n_elems = num_elems(fmdl0); step = 5e4;
0123 max_iter = floor(n_elems/step);
0124 pmopt.final_msg = '';
0125 ctr = interp_mesh(fmdl0);
0126 [~,xidx] = sort(ctr(:,1));
0127 [xl] = ndgrid(opt0.xvec(1:end-1),opt0.yvec(1:end-1),opt0.zvec(1:end-1)); xl=xl(:);
0128 [xu] = ndgrid(opt0.xvec(2:end-0),opt0.yvec(2:end-0),opt0.zvec(2:end-0)); xu=xu(:);
0129 progress_msg('Progress:',0,max_iter+1,pmopt);
0130 progress = 0;
0131 for k = 0:max_iter;
0132 eidx = true(n_elems,1);
0133 eidx( xidx((k*step+1):min((k+1)*step,n_elems)) ) = false;
0134 fmdl = fmdl0; fmdl.elems(eidx,:) = [];
0135 fmdl.edge2elem(:,eidx)= [];
0136 fmdl.node2elem(:,eidx)= [];
0137 fmdl.elem2face(eidx,:)= [];
0138 opt = opt0; opt.nTet = sum(eidx==0);
0139 if 1
0140 xvals = fmdl.nodes(fmdl.elems(:),1);
0141 ridx = true(size(xu));
0142 ridx(xl>max(xvals)) = false;
0143 ridx(xu<min(xvals)) = false;
0144 rmdl = rmdl0;
0145 idx = rmdl0.coarse2fine * ridx > 0;
0146 rmdl.elems = rmdl0.elems(idx,:);
0147 [node_idx, ~,Nn] = unique(rmdl.elems(:));
0148 rmdl.elems = reshape(Nn,size(rmdl.elems));
0149 rmdl.nodes = rmdl0.nodes(node_idx,:);
0150 opt.xvec = unique(rmdl.nodes( rmdl.elems(:), 1));
0151 opt.Xsz = length(opt.xvec)-1;
0152 opt.ystep = opt.xstep*opt.Xsz+1;
0153 opt.zstep = opt.ystep*(opt.Ysz+1);
0154 opt.nVox = opt.Xsz*opt.Ysz*opt.Zsz;
0155
0156 if 0
0157 fmdl.boundary = find_boundary(fmdl);
0158 rmdl.boundary = find_boundary(rmdl);
0159 hh=show_fem(rmdl); set(hh,'EdgeColor',[0,0,1]);
0160 hold on; show_fem(fmdl); hold off; keyboard
0161 end
0162 else
0163 rmdl = rmdl0; ridx= true(opt.nVox,1);
0164 end
0165 if isempty(rmdl.elems); continue; end
0166
0167 eidors_msg('log_level',eidors_msg('log_level')-2);
0168 c2f(~eidx,ridx) = separable_calculations(fmdl,rmdl,opt);
0169 eidors_msg('log_level',eidors_msg('log_level')+2);
0170 progress_msg(k+1, max_iter+1);
0171 end
0172 progress_msg(Inf);
0173 else
0174 logmsg(' Saving memory mode level %d\n',opt0.save_memory);
0175 max_iter = opt0.Zsz;
0176 if opt0.save_memory >= 2, max_iter = max_iter * opt0.Ysz; end
0177 if opt0.save_memory == 3, max_iter = max_iter * opt0.Xsz; end
0178 pmopt.final_msg = '';
0179 progress_msg('Progress:',0,max_iter,pmopt);
0180 progress = 0;
0181 opt = opt0;
0182 m = prepare_vox_mdl(rmdl0,opt0);
0183 for z = 1:opt0.Zsz
0184 opt.Zsz = 1;
0185 opt.zvec = opt0.zvec(z:z+1);
0186 opt.xplane = opt0.xplane(z,:);
0187 opt.yplane = opt0.yplane(z,:);
0188 relem_idx = false(opt0.Xsz*opt0.Ysz*opt0.Zsz,1);
0189 relem_idx((z-1)*opt0.Xsz*opt0.Ysz + (1:opt0.Xsz*opt0.Ysz)) = true;
0190 if opt0.save_memory > 1
0191 for y = 1:opt0.Ysz
0192 opt.Ysz = 1;
0193 opt.yvec = opt0.yvec(y:y+1);
0194 opt.zplane = opt0.zplane(y,:);
0195 opt.xplane = opt0.xplane(z,y);
0196 opt.zstep = opt.ystep*(opt.Ysz+1);
0197 relem_idx_y = false(opt0.Xsz*opt0.Ysz,1);
0198 relem_idx_y((y-1)*opt0.Xsz + (1:opt0.Xsz)) = true;
0199 relem_idx_y = relem_idx & repmat(relem_idx_y,opt0.Zsz,1);
0200 if opt0.save_memory > 2
0201 for x = 1:opt0.Xsz
0202 opt.Xsz = 1;
0203 opt.xvec = opt0.xvec(x:x+1);
0204 opt.yplane = opt0.yplane(z,x);
0205 opt.zplane = opt0.zplane(y,x);
0206 opt.ystep = opt.xstep*opt.Xsz+1;
0207 opt.zstep = opt.ystep*(opt.Ysz+1);
0208 relem_idx_x = false(opt0.Xsz,1);
0209 relem_idx_x(x) = true;
0210 relem_idx_x = relem_idx_y & repmat(relem_idx_x,opt0.Ysz*opt0.Zsz,1);
0211 [fmdl, rmdl, opt, felem_idx] = crop_models(fmdl0,rmdl0,opt,relem_idx_x);
0212 if any(felem_idx)
0213 eidors_msg('log_level',eidors_msg('log_level')-2);
0214 tmp = separable_calculations(fmdl,rmdl,opt);
0215 eidors_msg('log_level',eidors_msg('log_level')+2);
0216 c2f = combine_c2f(c2f, tmp,felem_idx,relem_idx_x);
0217 end
0218 progress = progress + 1;
0219 progress_msg(progress,max_iter);
0220 end
0221 else
0222 [fmdl, rmdl, opt, felem_idx] = crop_models(fmdl0,rmdl0,opt,relem_idx_y);
0223 if any(felem_idx)
0224 eidors_msg('log_level',eidors_msg('log_level')-2);
0225 tmp = separable_calculations(fmdl,rmdl,opt);
0226 eidors_msg('log_level',eidors_msg('log_level')+2);
0227 c2f = combine_c2f(c2f, tmp,felem_idx,relem_idx_y);
0228 end
0229 progress = progress + 1;
0230 progress_msg(progress, max_iter);
0231 end
0232 end
0233
0234 else
0235 [fmdl, rmdl, opt, felem_idx] = crop_models(fmdl0,rmdl0,opt,relem_idx);
0236 if any(felem_idx)
0237 eidors_msg('log_level',eidors_msg('log_level')-2);
0238 tmp = separable_calculations(fmdl,rmdl,opt);
0239 eidors_msg('log_level',eidors_msg('log_level')+2);
0240 c2f = combine_c2f(c2f, tmp,felem_idx,relem_idx);
0241 end
0242 progress = progress + 1;
0243 progress_msg(progress, max_iter);
0244 end
0245
0246
0247 end
0248 progress_msg(Inf);
0249 end
0250
0251
0252
0253 function c2f = combine_c2f(c2f, tmp,felem_idx,relem_idx)
0254 fidx = find(felem_idx);
0255 ridx = find(relem_idx);
0256 c2f(fidx,ridx) = c2f(fidx,ridx) + tmp;
0257
0258
0259
0260 function [c2f, m] = separable_calculations(fmdl,rmdl,opt)
0261 DEBUG = eidors_debug('query','mk_grid_c2f');
0262
0263 progress_msg('Prepare vox model...');
0264 m = prepare_vox_mdl(rmdl,opt);
0265 progress_msg(Inf);
0266
0267 try
0268
0269
0270 progress_msg('Find tet_edge2vox_face intersections...')
0271 [intpts1, rec2tedge, rec2intpt1, tedge2intpt1] = get_voxel_intersection_points(fmdl,m.faces,opt);
0272 progress_msg(sprintf('Found %d', size(intpts1,1)), Inf);
0273
0274
0275 progress_msg('Find vox_edge2tet_face intersections...',0,3)
0276 [intpts2, tri2vedge, tri2intpt2, vedge2intpt2] = get_tet_intersection_points(fmdl,m,opt);
0277 progress_msg(sprintf('Found %d', size(intpts2,1)), Inf);
0278
0279
0280
0281
0282
0283
0284
0285 pmopt.final_msg = 'none';
0286 progress_msg('Find tet_edge2vox_edge intersections...',-1,pmopt)
0287 [intpts3, tedge2vedge, tedge2intpt3, vedge2intpt3] =find_edge2edge_intersections(fmdl.edges,fmdl.nodes,m.edges,rmdl.nodes, opt.tol_edge2edge);
0288 progress_msg(sprintf('Found %d',size(intpts3,1)),Inf);
0289
0290
0291 progress_msg('Find tet_nodes in voxels...')
0292 [fnode2vox] = get_nodes_in_voxels(fmdl,rmdl);
0293 progress_msg(sprintf('Found %d', nnz(fnode2vox)), Inf);
0294
0295
0296 progress_msg('Find vox_nodes in tets...');
0297 vnode2tet = get_nodes_in_tets(fmdl,rmdl, opt);
0298 progress_msg(sprintf('Found %d', nnz(vnode2tet)), Inf);
0299
0300
0301 progress_msg('Find vox contained in tet...')
0302 vox_in_tet = (m.node2vox' * vnode2tet) == 8;
0303 progress_msg(sprintf('Found %d',nnz(vox_in_tet)), Inf);
0304
0305
0306 progress_msg('Find tets contained in vox...');
0307 tet_in_vox = (double(fmdl.node2elem') * fnode2vox) == 4;
0308 progress_msg(sprintf('Found %d',nnz(tet_in_vox)), Inf);
0309
0310
0311
0312 progress_msg('Find total vox v. tet intersections...');
0313 vox2intTet = m.vox2face * (rec2tedge>0) * fmdl.edge2elem ...
0314 | m.vox2edge * (tri2vedge>0)' * fmdl.elem2face' ...
0315 | m.vox2edge * tedge2vedge' * fmdl.edge2elem;
0316
0317 vox2intTet = vox2intTet & ~vox_in_tet & ~tet_in_vox';
0318 progress_msg(sprintf('Found %d',nnz(vox2intTet)), Inf);
0319
0320 catch err
0321 if (strcmp(err.identifier,'MATLAB:nomem'))
0322 msg = sprintf('%s', ...
0323 'Matlab ran out of memory. Consider setting save_memory > 0.\n', ...
0324 'See HELP MK_GRID_C2F for details.');
0325 error('EIDORS:mk_grid_c2f:nomem',msg);
0326 else
0327 rethrow(err);
0328 end
0329 end
0330
0331 progress_msg('Calculate intersection volumes...');
0332
0333 vox2intpt1 = logical(m.vox2face*rec2intpt1)';
0334 tet2intpt1 = logical(fmdl.edge2elem'*tedge2intpt1)';
0335
0336 tet2intpt2 = logical(fmdl.elem2face*tri2intpt2)';
0337 vox2intpt2 = logical(m.vox2edge*vedge2intpt2)';
0338
0339 tet2intpt3 = logical(fmdl.edge2elem'*tedge2intpt3)';
0340 vox2intpt3 = logical(m.vox2edge*vedge2intpt3)';
0341
0342 vox_todo = find(sum(vox2intTet,2)>0);
0343 C = []; F = []; V = [];
0344
0345 id = 0; lvox = length(vox_todo);
0346 mint = ceil(lvox/100);
0347 for v = vox_todo'
0348 id = id+1;
0349 if mod(id,mint)==0, progress_msg(id/lvox); end
0350 tet_todo = find(vox2intTet(v,:));
0351 common_intpts1 = bsxfun(@and,vox2intpt1(:,v), tet2intpt1(:,tet_todo));
0352 common_intpts2 = bsxfun(@and,vox2intpt2(:,v), tet2intpt2(:,tet_todo));
0353 common_intpts3 = bsxfun(@and,vox2intpt3(:,v), tet2intpt3(:,tet_todo));
0354 tet_nodes = bsxfun(@and,fnode2vox(:,v), fmdl.node2elem(:,tet_todo));
0355 vox_nodes = bsxfun(@and,vnode2tet(:,tet_todo), m.node2vox(:,v));
0356
0357 C = [C; v*ones(numel(tet_todo),1)];
0358 F = [F; tet_todo'];
0359 last_v = numel(V);
0360 V = [V; zeros(numel(tet_todo),1)];
0361
0362 for t = 1:numel(tet_todo)
0363 pts = [ intpts1(common_intpts1(:,t),:);
0364 intpts2(common_intpts2(:,t),:);
0365 intpts3(common_intpts3(:,t),:);
0366 fmdl.nodes(tet_nodes(:,t),:);
0367 rmdl.nodes(vox_nodes(:,t),:)];
0368 last_v = last_v + 1;
0369 ok = false;
0370 if size(pts,1) < 4
0371
0372
0373 continue
0374 end
0375 if size(pts,1) < 4
0376
0377
0378 E = fmdl.edges(fmdl.elem2edge(tet_todo(t),:),:);
0379 P1 = fmdl.nodes(E(:,1),:);
0380 P2 = fmdl.nodes(E(:,2),:);
0381
0382
0383
0384 D = P1-P2;
0385 ok = any(abs(D(:)) <= eps);
0386 end
0387 if ok; continue, end
0388 try
0389
0390
0391 ctr = mean(pts);
0392 pts = bsxfun(@minus,pts,ctr);
0393 scale = max(abs(pts(:)));
0394 if scale == 0
0395 continue
0396 end
0397
0398 pts = pts ./ scale;
0399
0400
0401 [~, V(last_v)] = convhulln_clean(pts);
0402 V(last_v) = V(last_v) * scale^3;
0403 catch err
0404 ok = false;
0405 switch err.identifier
0406 case {'MATLAB:qhullmx:DegenerateData'}
0407
0408 ok = 1;
0409
0410 case {'MATLAB:qhullmx:DegenerateData', 'MATLAB:qhullmx:UndefinedError', ...
0411 'MATLAB:cgprechecks:NotEnoughPts'}
0412
0413
0414 E = fmdl.edges(fmdl.elem2edge(tet_todo(t),:),:);
0415 P1 = fmdl.nodes(E(:,1),:);
0416 P2 = fmdl.nodes(E(:,2),:);
0417
0418
0419
0420 D = P1-P2;
0421 ok = any(abs(D) < 10*eps);
0422
0423
0424
0425 u = uniquetol(pts*scale,10*eps,'ByRows',true,'DataScale', 1);
0426 ok = ok | size(u,1) < 4;
0427 end
0428 if ~ok & size(u,1) == 4
0429 ok = ok | det([ones(4,1),u])<eps;
0430 end
0431 if ~ok
0432 if DEBUG || eidors_debug('query','mk_grid_c2f:convhulln')
0433 tet.nodes = fmdl.nodes;
0434 vox.nodes = rmdl.nodes;
0435 tet.type = 'fwd_model';
0436 vox.type = 'fwd_model';
0437 vox.elems = m.faces(logical(m.vox2face(v,:)),:);
0438 vox.boundary = vox.elems;
0439 tet.elems = fmdl.elems(tet_todo(t),:);
0440
0441 clf
0442 show_fem(vox)
0443 hold on
0444 h = show_fem(tet);
0445 set(h,'EdgeColor','b')
0446 pts = bsxfun(@plus,pts*scale,ctr);
0447 plot3(pts(:,1),pts(:,2),pts(:,3),'o');
0448
0449
0450 hold off
0451 axis auto
0452 keyboard
0453 else
0454 fprintf('\n');
0455 eidors_msg(['convhulln has thrown an error. ' ...
0456 'Enable eidors_debug on mk_grid_c2f:convhulln and re-run to see a debug plot'],0);
0457 rethrow(err);
0458 end
0459 end
0460 end
0461 end
0462 end
0463 progress_msg(Inf);
0464 c2f = sparse(F,C,V,opt.nTet,opt.nVox);
0465
0466
0467 c2f = c2f + bsxfun(@times, sparse(vox_in_tet), m.volume)';
0468
0469
0470 vol = get_elem_volume(fmdl, 'no_c2f');
0471 c2f = bsxfun(@rdivide,c2f,vol);
0472
0473
0474
0475 c2f = c2f + tet_in_vox;
0476
0477
0478
0479 function [fmdl, rmdl, opt, felem_idx] = crop_models(fmdl0,rmdl0,opt, relem_idx)
0480
0481 fmdl = fmdl0;
0482 rmdl = rmdl0;
0483
0484 opt.nVox = opt.Xsz*opt.Ysz*opt.Zsz;
0485 idx = rmdl0.coarse2fine * relem_idx > 0;
0486 rmdl.elems = rmdl0.elems(idx,:);
0487 [node_idx, m,n] = unique(rmdl.elems(:));
0488 rmdl.elems = reshape(n,size(rmdl.elems));
0489 rmdl.nodes = rmdl0.nodes(node_idx,:);
0490
0491 fnode_above = fmdl0.nodes(:,3) > opt.zvec(end);
0492
0493 felem_above = all(reshape(fnode_above(fmdl0.elems), size(fmdl0.elems)),2);
0494
0495 fnode_below = fmdl0.nodes(:,3) < opt.zvec(1);
0496 felem_below = all(reshape(fnode_below(fmdl0.elems), size(fmdl0.elems)),2);
0497
0498 felem_idx = ~(felem_below | felem_above);
0499 fmdl.elems = fmdl0.elems(felem_idx,:);
0500 fnode_idx = unique(fmdl.elems(:));
0501 fnode_idx_map = zeros(size(fmdl0.nodes,1),1);
0502 fnode_idx_map(fnode_idx) = 1:length(fnode_idx);
0503 fmdl.elems = reshape(fnode_idx_map(fmdl.elems),size(fmdl.elems));
0504 fmdl.edges = reshape(fnode_idx_map(fmdl0.edges),size(fmdl0.edges));
0505 fmdl.nodes = fmdl0.nodes(fnode_idx,:);
0506 fmdl.node2elem = fmdl0.node2elem(fnode_idx,felem_idx);
0507
0508
0509 fface_idx = sum(fmdl0.elem2face(felem_idx,:),1)>0;
0510 fmdl.elem2face = fmdl0.elem2face(felem_idx,fface_idx);
0511 felem_idx_map = zeros(size(felem_idx));
0512 felem_idx_map(felem_idx) = 1:nnz(felem_idx);
0513 felem_idx_map = [0; felem_idx_map];
0514 fmdl.face2elem = fmdl0.face2elem(fface_idx,:);
0515 fmdl.face2elem = reshape(felem_idx_map(fmdl.face2elem + 1),size(fmdl.face2elem));
0516 fmdl.normals = fmdl0.normals(fface_idx,:);
0517 fmdl.faces = fmdl0.faces(fface_idx,:);
0518 fmdl.faces = reshape(fnode_idx_map(fmdl.faces),size(fmdl.faces));
0519
0520 fedge_idx = unique(fmdl0.elem2edge(felem_idx,:));
0521 fedge_idx_map = zeros(size(fmdl0.edges,1),1);
0522 fedge_idx_map(fedge_idx) = 1:length(fedge_idx);
0523 fmdl.elem2edge = fedge_idx_map(fmdl0.elem2edge(felem_idx,:));
0524 fmdl.edge2elem = fmdl0.edge2elem(fedge_idx,felem_idx);
0525 fmdl.edges = fmdl.edges(fedge_idx,:);
0526
0527 opt.nTet = size(fmdl.elems,1);
0528
0529
0530
0531 function fmdl = prepare_fmdl(fmdl)
0532 fmopt.elem2edge = true;
0533 fmopt.edge2elem = true;
0534 fmopt.face2elem = true;
0535 fmopt.node2elem = true;
0536 fmopt.normals = true;
0537 fmopt.linear_reorder = false;
0538 ll = eidors_msg('log_level',1);
0539 fmdl = fix_model(fmdl,fmopt);
0540 eidors_msg('log_level',ll);
0541 fmdl.node2elem = logical(fmdl.node2elem);
0542 nElem = size(fmdl.elems,1);
0543 nFace = size(fmdl.faces,1);
0544 fmdl.elem2face = sparse(repmat((1:nElem)',1,4),double(fmdl.elem2face),true,nElem,nFace);
0545
0546
0547
0548
0549 function m = prepare_vox_mdl(rmdl,opt)
0550
0551 DEBUG = eidors_debug('query','mk_grid_c2f');
0552
0553 [voxels, m.node2vox] = mk_voxels(opt);
0554 if DEBUG || eidors_debug('query','mk_grid_c2f:mk_voxels')
0555 show_voxels(rmdl,voxels); title('mk\_voxels');
0556 end
0557
0558 m.faces = mk_faces(voxels,opt);
0559 if DEBUG || eidors_debug('query','mk_grid_c2f:mk_faces')
0560 test_faces(rmdl,m.faces,opt); title('mk\_faces');
0561 end
0562
0563 m.vox2face = mk_vox2face(opt);
0564 if DEBUG || eidors_debug('query','mk_grid_c2f:mk_vox2face')
0565
0566 show_voxels(rmdl,m.faces(any(m.vox2face),:));title('mk\_vox2face');
0567 end
0568 m.edges = mk_edges(voxels,opt);
0569
0570 m.edge_length = rmdl.nodes(m.edges(:,1),:) - rmdl.nodes(m.edges(:,2),:);
0571 m.edge_length = sqrt(sum(m.edge_length.^2,2));
0572
0573 [m.vox2edge, m.volume]= mk_vox2edge(m,opt);
0574
0575
0576
0577
0578
0579 function rnode2tet = get_nodes_in_tets(fmdl,rmdl, opt)
0580
0581 [A,b] = tet_to_inequal(fmdl.nodes,fmdl.elems);
0582 progress_msg(.01);
0583
0584 rnode2tet = (bsxfun(@minus, A(1:4:end,:)*rmdl.nodes',b(1:4:end)) <= opt.tol_node2tet)';
0585 progress_msg(.21);
0586 for i = 2:4
0587 rnode2tet = rnode2tet & (bsxfun(@minus, A(i:4:end,:)*rmdl.nodes',b(i:4:end)) <= opt.tol_node2tet)';
0588 progress_msg(.21 + (i-1)*.23);
0589 end
0590
0591
0592 ex= bsxfun(@eq,rmdl.nodes(:,1),fmdl.nodes(:,1)') & ...
0593 bsxfun(@eq,rmdl.nodes(:,2),fmdl.nodes(:,2)') & ...
0594 bsxfun(@eq,rmdl.nodes(:,3),fmdl.nodes(:,3)');
0595 progress_msg(.94);
0596 rnode2tet(any(ex,2),:) = 0;
0597 progress_msg(1);
0598
0599
0600
0601
0602
0603 function [insnode] = get_nodes_in_voxels(fmdl,rmdl)
0604
0605 E = reshape(rmdl.elems',4*6,[])';
0606 E = E(:,[1 2 3 4 8 12 16 23]);
0607
0608 NE = size(E,1);
0609 xnodes = reshape(rmdl.nodes(E,1),NE,[]);
0610 ynodes = reshape(rmdl.nodes(E,2),NE,[]);
0611 znodes = reshape(rmdl.nodes(E,3),NE,[]);
0612 minx = min(xnodes,[],2);
0613 maxx = max(xnodes,[],2);
0614 miny = min(ynodes,[],2);
0615 maxy = max(ynodes,[],2);
0616 minz = min(znodes,[],2);
0617 maxz = max(znodes,[],2);
0618
0619 leftof = bsxfun(@lt, fmdl.nodes(:,1)+eps, minx');
0620 rightof = bsxfun(@gt, fmdl.nodes(:,1)-eps, maxx');
0621 infront = bsxfun(@lt, fmdl.nodes(:,2)+eps, miny');
0622 behind = bsxfun(@gt, fmdl.nodes(:,2)-eps, maxy');
0623 below = bsxfun(@lt, fmdl.nodes(:,3)+eps, minz');
0624 above = bsxfun(@gt, fmdl.nodes(:,3)-eps, maxz');
0625
0626 outnode = leftof | rightof | behind | infront | below | above;
0627 insnode = sparse(~outnode);
0628
0629
0630
0631 function [intpts, face2edge, face2intpt, edge2intpt] = get_voxel_intersection_points(fmdl,faces,opt)
0632 edges = fmdl.edges;
0633 nodes = fmdl.nodes;
0634 dir = nodes(edges(:,2),:) - nodes(edges(:,1),:);
0635 intpts = [];
0636 F = []; E = []; I = [];
0637
0638 SZ = [opt.Xsz, opt.Ysz, opt.Zsz];
0639 VEC = {opt.xvec, opt.yvec, opt.zvec};
0640
0641
0642
0643
0644
0645 todo = sum(SZ)+3;
0646 id = 0;
0647 step = ceil(todo/100);
0648
0649 for d = 1:3
0650 for x = 0:SZ(d)
0651 id = id+1;
0652 if mod(id,step)==0, progress_msg(id/todo); end
0653
0654 t = (VEC{d}(x+1) - nodes(edges(:,1),d)) ./ dir(:,d);
0655 crossing = t>0 & t<1;
0656 crossed = find(crossing);
0657 if isempty(crossed), continue, end;
0658
0659 tmp = nodes(edges(crossing,1),:) + bsxfun(@times,t(crossing),dir(crossing,:));
0660 face_coord = zeros(length(crossed),3);
0661 rmv = false(length(crossed),1);
0662 for i = 1:3
0663 if i == d
0664 face_coord(:,i) = x+1;
0665 else
0666 face_coord(:,i) = sum(bsxfun(@times,diff(bsxfun(@lt, tmp(:,i), VEC{i}'),1,2),(1:SZ(i))),2);
0667 rmv = rmv | face_coord(:,i) == 0;
0668 end
0669 end
0670
0671 same_x = any(bsxfun(@eq,tmp(:,1),opt.xvec'),2);
0672 same_y = any(bsxfun(@eq,tmp(:,2),opt.yvec'),2);
0673 same_z = any(bsxfun(@eq,tmp(:,3),opt.zvec'),2);
0674 rmv = rmv | (same_x + same_y + same_z) > 1;
0675 if nnz(rmv) == numel(rmv), continue, end
0676 tmp(rmv,:) = [];
0677 face_coord(rmv,:) = [];
0678 crossed(rmv) = [];
0679 face_coord = face_coord - 1;
0680 face_idx = d + face_coord(:,1)*opt.xstep + face_coord(:,2)*opt.ystep + face_coord(:,3)*opt.zstep;
0681 I = [I; (1:size(tmp,1))' + size(I,1)];
0682 F = [F; face_idx];
0683 E = [E; crossed];
0684 intpts = [intpts; tmp];
0685
0686
0687
0688
0689
0690
0691
0692
0693
0694
0695
0696
0697
0698
0699
0700
0701
0702 end
0703 end
0704 face2edge = sparse(F,E,I,size(faces,1),size(edges,1));
0705 face2intpt = sparse(F,I,ones(size(I)),size(faces,1),size(I,1));
0706 edge2intpt = sparse(E,I,ones(size(I)),size(edges,1),size(I,1));
0707
0708
0709
0710 function [intpts, tri2edge, tri2intpt, edge2intpt] = get_tet_intersection_points(fmdl,m,opt)
0711
0712 intpts = [];
0713 T = []; E = []; I = [];
0714 Xsz = opt.Xsz; Ysz = opt.Ysz; Zsz = opt.Zsz;
0715 SZ = [opt.Xsz, opt.Ysz, opt.Zsz];
0716 VEC = {opt.xvec, opt.yvec, opt.zvec};
0717 STEP(1) = opt.xstep;
0718 STEP(2) = STEP(1)*(Xsz+1);
0719 STEP(3) = STEP(2)*(Ysz+1);
0720
0721 d = sum(fmdl.normals .* fmdl.nodes(fmdl.faces(:,1),:),2);
0722
0723 line_axis = [3 1 2];
0724 for i = 1:3
0725 progress_msg(i,3);
0726
0727 idx = 1:3;
0728 op = line_axis(i);
0729 idx(op) = [];
0730
0731 pts = [repmat(VEC{idx(1)},SZ(idx(2))+1,1) kron(VEC{idx(2)},ones(SZ(idx(1))+1,1)) ];
0732 pt_idx = uint32(repmat((0:SZ(idx(1)))',SZ(idx(2))+1,1)*STEP(idx(1)) ...
0733 + kron((0:SZ(idx(2)))', ones(SZ(idx(1))+1,1))*STEP(idx(2)));
0734
0735
0736
0737 z = repmat(d,1,size(pts,1));
0738 for j = 1:2
0739 z = z - bsxfun(@times,fmdl.normals(:,idx(j)),pts(:,j)');
0740 end
0741 z = z ./ repmat(fmdl.normals(:,op),1,size(pts,1));
0742 in = point_in_triangle(pts,fmdl.faces,fmdl.nodes(:,idx),2*opt.tol_edge2tri)';
0743
0744
0745
0746 v = VEC{op}';
0747 in = in & ~reshape(any(bsxfun(@eq,z(:),v),2),size(in));
0748 M = bsxfun(@lt, z(:),v);
0749 M = xor(M(:,1:end-1), M(:,2:end));
0750
0751 edge_num = reshape(uint32(M*(1:SZ(op))'), size(z));
0752
0753 in = in & edge_num > 0;
0754 if nnz(in) == 0, continue, end
0755 edge_num(~in) = 0;
0756
0757 edge_num(in) = (edge_num(in)-1) * STEP(op);
0758 edge_idx = edge_num + bsxfun(@times,uint32(full(in)), uint32(i) + pt_idx');
0759
0760 [t, p] = find(in);
0761 tmp = zeros(length(p),3);
0762 tmp(:,idx) = pts(p,1:2);
0763 tmp(:,op) = z(in);
0764
0765 I = [I; (1:size(tmp,1))' + size(I,1)];
0766 T = [T; t];
0767 E = [E; edge_idx(in)];
0768 intpts = [intpts; tmp];
0769 end
0770
0771 E = double(E);
0772 tri2edge = sparse(T,E,I,size(fmdl.faces,1),size(m.edges,1));
0773 tri2intpt = sparse(T,I,ones(size(I)),size(fmdl.faces,1),size(I,1));
0774 edge2intpt = sparse(E,I,ones(size(I)),size(m.edges,1),size(I,1));
0775
0776
0777
0778
0779 function [voxels, node2vox] = mk_voxels(opt)
0780 Xsz = opt.Xsz; Ysz = opt.Ysz; Zsz = opt.Zsz;
0781 Xp = Xsz+1; Yp = Ysz+1; Zp = Zsz+1;
0782
0783 up = Xp*Yp;
0784 vox = [ 1 1+up 1+up+Xp 1+Xp;
0785 1 2 2+up 1+up;
0786 1 1+Xp 2+Xp 2;
0787 2 2+up 2+up+Xp 2+Xp;
0788 1+Xp 2+Xp 2+up+Xp 1+up+Xp;
0789 1+up 1+Xp+up 2+Xp+up 2+up];
0790
0791 voxrow = bsxfun(@plus, repmat(vox, Xsz,1), kron(0:Xsz-1 ,ones(1,6))');
0792 voxplane = bsxfun(@plus, repmat(voxrow, Ysz,1), kron(Xp*(0:Ysz-1) , ones(1, 6*Xsz))');
0793 voxels = bsxfun(@plus, repmat(voxplane,Zsz,1), kron(up*(0:Zsz-1) , ones(1, 6*Xsz*Ysz))');
0794 nVox = Xsz * Ysz * Zsz;
0795 node2vox = sparse(voxels(1:3:end,:),kron((1:nVox)',ones(2,4)),1);
0796
0797
0798
0799 function faces = mk_faces(voxels,opt)
0800 Xsz = opt.Xsz; Ysz = opt.Ysz; Zsz = opt.Zsz;
0801
0802 facerow = [nonzeros(bsxfun(@plus,(1:3)',0:6:(Xsz-1)*6)); (Xsz-1)*6+4];
0803 faceplane = bsxfun(@plus,facerow,0:6*Xsz:6*Xsz*(Ysz-1));
0804
0805 cap = kron(ones(3,1),faceplane(2:3:end,end)')+3;
0806 faceplane = [faceplane,[ cap(:); cap(end)]];
0807 faces = bsxfun(@plus, faceplane(:), 0:6*Xsz*Ysz:6*Xsz*Ysz*(Zsz-1));
0808
0809 cap = reshape(kron(ones(3,1), 3:3:3*Xsz*Ysz'),3*Xsz,[]);
0810 cap = bsxfun(@plus, cap, 0:Ysz-1);
0811 cap(end+1,:)= cap(end,:);
0812 faces = [faces(:); faces(cap(:),end)+3];
0813 faces = voxels(faces,:);
0814
0815
0816
0817 function edges = mk_edges(voxels, opt)
0818 Xsz = opt.Xsz; Ysz = opt.Ysz; Zsz = opt.Zsz;
0819
0820 edgerow = voxels([nonzeros(bsxfun(@plus,(1:3)',0:6:(Xsz-1)*6)); (Xsz-1)*6+4],1:2);
0821 edgerow(end+1,:) = edgerow(end,:);
0822 edgerow(end+1,:) = voxels((Xsz-1)*6+4, [1 4]);
0823 edgeplane = repmat(edgerow,Ysz+1,1) + kron((Xsz+1)*(0:Ysz)', ones(size(edgerow)));
0824
0825 edgeplane((size(edgerow,1)*Ysz +3):3:end,:) = edgeplane((size(edgerow,1)*Ysz +2):3:end,:);
0826
0827 up = (Xsz+1)*(Ysz+1);
0828 edges = repmat(edgeplane,Zsz+1,1) + kron((0:Zsz)'*up, ones(size(edgeplane)));
0829
0830
0831 start = (size(edgeplane,1)*Zsz);
0832 edges( (start +1):3:end,:) = edges( (start +2):3:end,:);
0833 start = (size(edgeplane,1)*Zsz) + 3*Xsz;
0834 step = size(edgerow,1);
0835 edges( (start +1):step:end,:) = edges( (start +3):step:end,:);
0836 edges( (start +2):step:end,:) = edges( (start +3):step:end,:);
0837 edges( end-2:end,:) = edges(end-5:end-3,:);
0838
0839
0840
0841 function vox2face = mk_vox2face(opt)
0842 Xsz = opt.Xsz; Ysz = opt.Ysz; Zsz = opt.Zsz;
0843 xstep = opt.xstep; ystep = opt.ystep; zstep = opt.zstep;
0844
0845 vox = [1 2 3 1+xstep 2+ystep 3+zstep];
0846 voxrow = bsxfun(@plus,(0:Xsz-1)'*xstep,vox)';
0847 voxplane = bsxfun(@plus,(0:Ysz-1)*ystep,voxrow(:));
0848 voxvol = bsxfun(@plus,(0:Zsz-1)*zstep,voxplane(:));
0849 voxvol = reshape(voxvol, 6, [])';
0850 I = kron((1:size(voxvol,1))',ones(1,6));
0851 nFaces = Zsz*(Ysz+1)*(3*Xsz+1) + Ysz*(3*Xsz+1);
0852 nVox = Xsz*Ysz*Zsz;
0853 vox2face = sparse(I,voxvol,ones(size(I)),nVox,nFaces);
0854
0855
0856
0857 function [vox2edge, vol] = mk_vox2edge(m,opt)
0858 Xsz = opt.Xsz; Ysz = opt.Ysz; Zsz = opt.Zsz;
0859 xstep = opt.xstep; ystep = xstep*(Xsz+1); zstep = ystep*(Ysz+1);
0860
0861 vox = [1 2 3 1+xstep 3+xstep 1+ystep 2+ystep 1+ystep+xstep ...
0862 2+zstep 3+zstep 3+zstep+xstep 2+zstep+ystep];
0863 voxrow = bsxfun(@plus,(0:Xsz-1)'*xstep,vox)';
0864 voxplane = bsxfun(@plus,(0:Ysz-1)*ystep,voxrow(:));
0865 voxvol = bsxfun(@plus,(0:Zsz-1)*zstep,voxplane(:));
0866 voxvol = reshape(voxvol, 12, [])';
0867 I = kron((1:size(voxvol,1))',ones(1,12));
0868 nEdges = 3*(Zsz+1)*(Ysz+1)*(Xsz+1);
0869 nVox = Xsz*Ysz*Zsz;
0870 vox2edge = sparse(I,voxvol,ones(size(I)),nVox,nEdges);
0871 vol = m.edge_length(voxvol(:,1)) ...
0872 .* m.edge_length(voxvol(:,2)) ...
0873 .* m.edge_length(voxvol(:,3));
0874
0875
0876
0877
0878 function show_voxels(rmdl,voxels)
0879 mdl=rmdl;
0880 mdl.elems = voxels;
0881 mdl.boundary = mdl.elems;
0882 clf
0883 show_fem(mdl,[0 0 1]);
0884
0885
0886
0887 function test_faces(rmdl, faces, opt)
0888 mdl = rmdl;
0889 mdl.elems = faces;
0890 mdl.boundary = mdl.elems;
0891 img = mk_image(mdl,0);
0892 img.elem_data(opt.xplane + (randi(opt.Xsz+1)-1)*opt.xstep) = 1;
0893 img.elem_data(opt.yplane + (randi(opt.Ysz+1)-1)*opt.ystep) = 2;
0894 img.elem_data(opt.zplane + (randi(opt.Zsz+1)-1)*opt.zstep) = 3;
0895 show_fem(img,[0 0 1]);
0896
0897
0898
0899 function [fmdl,rmdl] = center_scale_models(fmdl,rmdl, opt)
0900
0901 if size(rmdl.nodes,2)==2;
0902 rmdl = rmdl_3D(rmdl, fmdl);
0903 end
0904 ctr = mean([min(rmdl.nodes);max(rmdl.nodes)]);
0905 rmdl.nodes = bsxfun(@minus,rmdl.nodes,ctr);
0906 fmdl.nodes = bsxfun(@minus,fmdl.nodes,ctr);
0907 if isfield(opt,'do_not_scale') && opt.do_not_scale
0908 return
0909 end
0910 maxnode = min( max(abs(rmdl.nodes(:))), max(abs(fmdl.nodes(:))));
0911 scale = 1/maxnode;
0912 rmdl.nodes = scale*rmdl.nodes;
0913 fmdl.nodes = scale*fmdl.nodes;
0914 eidors_msg('@@ models scaled by %g', scale,2);
0915
0916
0917
0918
0919 function rmdl = rmdl_3D(rmdl, fmdl)
0920 fzmax = max(fmdl.nodes(:,3));
0921 fzmin = min(fmdl.nodes(:,3));
0922 rm_nodes = rmdl.nodes;
0923 oo = 0*rm_nodes(:,1) + 1;
0924 N = num_nodes(rmdl);
0925
0926 rmdl.nodes = [ ...
0927 rmdl.nodes,oo*fzmin;
0928 rmdl.nodes,oo*fzmax];
0929 rme = [
0930 rmdl.elems(:,[1,2,3,1]) + [N,0,0,0];
0931 rmdl.elems(:,[1,2,3,2]) + [N,N,0,0];
0932 rmdl.elems(:,[1,2,3,3]) + [N,N,N,0]];
0933
0934 rme = reshape(rme,[],3,4);
0935 rme = permute(rme,[2,1,3]);
0936 rmdl.elems = reshape(rme,[],4);
0937 rmdl.coarse2fine = kron( ...
0938 rmdl.coarse2fine,[1;1;1]);
0939 return
0940
0941 x = ones(6,1);
0942 rmdl.boundary = find_boundary(rmdl);
0943 x(3) = 2;
0944 img = mk_image(rmdl,x);
0945 show_fem(img);
0946
0947
0948
0949 function opt = parse_opts(fmdl,rmdl, opt)
0950 opt.xvec = unique(rmdl.nodes(:,1));
0951 opt.yvec = unique(rmdl.nodes(:,2));
0952 opt.zvec = unique(rmdl.nodes(:,3));
0953 opt.Xsz = numel(opt.xvec)-1;
0954 opt.Ysz = numel(opt.yvec)-1;
0955 opt.Zsz = numel(opt.zvec)-1;
0956 opt.xstep = 3;
0957 opt.ystep = opt.xstep*opt.Xsz+1;
0958 opt.zstep = opt.ystep*(opt.Ysz+1);
0959 xrow = 1 + (0:opt.Ysz-1)*opt.ystep;
0960 opt.xplane = bsxfun(@plus, (0:opt.Zsz-1)'*opt.zstep,xrow);
0961 yrow = 2 + (0:opt.Xsz-1)*opt.xstep;
0962 opt.yplane = bsxfun(@plus, (0:opt.Zsz-1)'*opt.zstep,yrow);
0963 zrow = 3 + (0:opt.Xsz-1)*opt.xstep;
0964 opt.zplane = bsxfun(@plus, (0:opt.Ysz-1)'*opt.ystep,zrow);
0965 opt.nVox = opt.Xsz*opt.Ysz*opt.Zsz;
0966 opt.nTet = size(fmdl.elems,1);
0967
0968 if ~isfield(opt, 'tol_node2tet');
0969 opt.tol_node2tet = eps;
0970 end
0971 if ~isfield(opt, 'tol_edge2edge')
0972 opt.tol_edge2edge = 6*sqrt(3)*eps(min(max(abs(fmdl.nodes(:))),max(abs(rmdl.nodes(:)))));
0973 end
0974 if ~isfield(opt, 'tol_edge2tri')
0975 opt.tol_edge2tri = eps;
0976 end
0977 if ~isfield(opt, 'save_memory')
0978 opt.save_memory = 0;
0979 end
0980 eidors_msg('@@ node2tet tolerance = %g', opt.tol_node2tet,3);
0981 eidors_msg('@@ edge2edge tolerance = %g', opt.tol_edge2edge,3);
0982 eidors_msg('@@ edge2tri tolerance = %g', opt.tol_edge2tri,3);
0983
0984
0985
0986 function logmsg(varargin)
0987 if eidors_msg('log_level') >= 2
0988 fprintf(varargin{:});
0989 end
0990
0991
0992
0993
0994
0995 function do_unit_test
0996 mk_grid_c2f('save_memory',0); do_small_test;
0997 mk_grid_c2f('save_memory',1); do_small_test;
0998 mk_grid_c2f('save_memory',10); do_small_test;
0999 clf
1000 do_case_tests;
1001 return
1002 do_realistic_test;
1003 do_edge2edge_timing_test;
1004
1005
1006
1007 function do_case_tests
1008 ll = eidors_msg('log_level');
1009 eidors_msg('log_level',1);
1010 vox = mk_grid_model([],0:1,0:1,0:1);
1011 tet.type = 'fwd_model';
1012 tet.elems = [1 2 3 4];
1013
1014 X = 4; Y = 6;
1015 for i = 1:30
1016 tet.nodes = [0 0 0; 0 1 0; 1 0 0; 0 0 1];
1017 fprintf('%d\n',i);
1018 switch i
1019 case 1
1020 txt = 'Nothing in common';
1021 tet.nodes = tet.nodes + 2;
1022 subplot(X,Y,i), show_test(vox,tet);
1023 [intpts, face2edge, face2intpt, edge2intpt] = test_rec_tedge_intersections(vox,tet);
1024 unit_test_cmp(txt,size(intpts,1),0,0);
1025 [intpts, face2edge, face2intpt, edge2intpt] = test_tet_vedge_intersections(vox,tet);
1026 unit_test_cmp(txt,size(intpts,1),0,0);
1027 [intpts, face2edge, face2intpt, edge2intpt] = test_tedge2vedge_intersections(vox,tet);
1028 unit_test_cmp(txt,size(intpts,1),0,0);
1029 mk_grid_c2f(tet,vox);
1030
1031 case 2
1032 tet.nodes = tet.nodes + 1;
1033 subplot(X,Y,i), show_test(vox,tet);
1034 [intpts, face2edge, face2intpt, edge2intpt] = test_rec_tedge_intersections(vox,tet);
1035 unit_test_cmp('Comm node tedge2rec',size(intpts,1),0,0);
1036 [intpts, face2edge, face2intpt, edge2intpt] = test_tet_vedge_intersections(vox,tet);
1037 unit_test_cmp('Comm node vedge2tri',size(intpts,1),0,0);
1038 [intpts, face2edge, face2intpt, edge2intpt] = test_tedge2vedge_intersections(vox,tet);
1039 unit_test_cmp('Comm node edge2edge',size(intpts,1),0,0);
1040 [fnode2vox] = test_tnode_in_vox(vox,tet);
1041 unit_test_cmp('Comm node tnode2vox',fnode2vox,[1;0;0;0],0);
1042 rnode2tet = test_vnode_in_tet(vox,tet);
1043 unit_test_cmp('Comm node vnode2tet',nnz(rnode2tet),0,0);
1044 mk_grid_c2f(tet,vox);
1045
1046 case 3
1047 txt = 'tet_edge v vox_node';
1048 tet.nodes(:,1:2) = tet.nodes(:,1:2) - 0.5;
1049 subplot(X,Y,i), show_test(vox,tet);
1050 [intpts, face2edge, face2intpt, edge2intpt] = test_rec_tedge_intersections(vox,tet);
1051 unit_test_cmp(txt,size(intpts,1),0,0);
1052 [intpts, face2edge, face2intpt, edge2intpt] = test_tet_vedge_intersections(vox,tet);
1053 unit_test_cmp(txt,size(intpts,1),0,0);
1054 [intpts, face2edge, face2intpt, edge2intpt] = test_tedge2vedge_intersections(vox,tet);
1055 unit_test_cmp(txt,size(intpts,1),0,0);
1056 [fnode2vox] = test_tnode_in_vox(vox,tet);
1057 unit_test_cmp(txt,nnz(fnode2vox),0,0);
1058 rnode2tet = test_vnode_in_tet(vox,tet);
1059 res = zeros(8,1); res(1) = 1;
1060 unit_test_cmp(txt,rnode2tet,res,0);
1061 mk_grid_c2f(tet,vox);
1062
1063 case 4
1064 txt = 'tet_edge v vox_edge';
1065 tet.nodes(:,1:2) = tet.nodes(:,1:2) - 0.5;
1066 tet.nodes(:,3) = tet.nodes(:,3) + 0.5;
1067 subplot(X,Y,i), show_test(vox,tet);
1068 [intpts, face2edge, face2intpt, edge2intpt] = test_rec_tedge_intersections(vox,tet);
1069 unit_test_cmp(txt,size(intpts,1),0,0);
1070 [intpts, face2edge, face2intpt, edge2intpt] = test_tet_vedge_intersections(vox,tet);
1071 unit_test_cmp(txt,size(unique(intpts,'rows'),1),1,0);
1072 [intpts, face2edge, face2intpt, edge2intpt] = test_tedge2vedge_intersections(vox,tet);
1073 unit_test_cmp(txt,size(intpts,1),1,0);
1074 [fnode2vox] = test_tnode_in_vox(vox,tet);
1075 unit_test_cmp(txt,nnz(fnode2vox),0,0);
1076 rnode2tet = test_vnode_in_tet(vox,tet);
1077 unit_test_cmp(txt,nnz(rnode2tet),0,0);
1078 mk_grid_c2f(tet,vox);
1079
1080 case 5
1081 txt = 'tet_edge on vox_face';
1082 tet.nodes(:,1:2) = tet.nodes(:,1:2) - 0.3;
1083 subplot(X,Y,i), show_test(vox,tet);
1084 [intpts, face2edge, face2intpt, edge2intpt] = test_rec_tedge_intersections(vox,tet);
1085 unit_test_cmp(txt,size(intpts,1),0,0);
1086 [intpts, face2edge, face2intpt, edge2intpt] = test_tet_vedge_intersections(vox,tet);
1087 unit_test_cmp(txt,size(unique(intpts,'rows'),1),3,0);
1088 [intpts, face2edge, face2intpt, edge2intpt] = test_tedge2vedge_intersections(vox,tet);
1089 unit_test_cmp(txt,size(intpts,1),2,0);
1090 [fnode2vox] = test_tnode_in_vox(vox,tet);
1091 unit_test_cmp(txt,nnz(fnode2vox),0,0);
1092 rnode2tet = test_vnode_in_tet(vox,tet);
1093 unit_test_cmp(txt,nnz(rnode2tet),1,0);
1094 mk_grid_c2f(tet,vox);
1095
1096 case 6
1097 txt = 'vox_node on tet_face';
1098 tet.nodes(:,1:2) = tet.nodes(:,1:2) - 0.3;
1099 tet.nodes(:,3) = tet.nodes(:,3) -0.4;
1100 subplot(X,Y,i), show_test(vox,tet);
1101 [intpts, face2edge, face2intpt, edge2intpt] = test_rec_tedge_intersections(vox,tet);
1102 unit_test_cmp(txt,size(intpts,1),0,0);
1103 [intpts, face2edge, face2intpt, edge2intpt] = test_tet_vedge_intersections(vox,tet);
1104 unit_test_cmp(txt,size(intpts,1),0,0);
1105 [intpts, face2edge, face2intpt, edge2intpt] = test_tedge2vedge_intersections(vox,tet);
1106 unit_test_cmp(txt,size(intpts,1),0,0);
1107 [fnode2vox] = test_tnode_in_vox(vox,tet);
1108 unit_test_cmp(txt,nnz(fnode2vox),0,0);
1109 rnode2tet = test_vnode_in_tet(vox,tet);
1110 unit_test_cmp(txt,nnz(rnode2tet),1,0);
1111 mk_grid_c2f(tet,vox);
1112
1113 case 7
1114 txt = 'tet_node on vox_face';
1115 tet.nodes(:,1) = tet.nodes(:,1) - 1;
1116 tet.nodes(:,2:3) = tet.nodes(:,2:3) + .5;
1117 subplot(X,Y,i), show_test(vox,tet);
1118 [intpts, face2edge, face2intpt, edge2intpt] = test_rec_tedge_intersections(vox,tet);
1119 unit_test_cmp(txt,size(intpts,1),0,0);
1120 [intpts, face2edge, face2intpt, edge2intpt] = test_tet_vedge_intersections(vox,tet);
1121 unit_test_cmp(txt,size(intpts,1),0,0);
1122 [intpts, face2edge, face2intpt, edge2intpt] = test_tedge2vedge_intersections(vox,tet);
1123 unit_test_cmp(txt,size(intpts,1),0,0);
1124 [fnode2vox] = test_tnode_in_vox(vox,tet);
1125 unit_test_cmp(txt,nnz(fnode2vox),1,0);
1126 rnode2tet = test_vnode_in_tet(vox,tet);
1127 unit_test_cmp(txt,nnz(rnode2tet),0,0);
1128 mk_grid_c2f(tet,vox);
1129
1130
1131 case 8
1132 txt = 'tet_node on vox_edge';
1133 tet.nodes(:,1) = tet.nodes(:,1) - 1;
1134 tet.nodes(:,2) = tet.nodes(:,2) + .5;
1135 subplot(X,Y,i), show_test(vox,tet);
1136 [intpts, face2edge, face2intpt, edge2intpt] = test_rec_tedge_intersections(vox,tet);
1137 unit_test_cmp(txt,size(intpts,1),0,0);
1138 [intpts, face2edge, face2intpt, edge2intpt] = test_tet_vedge_intersections(vox,tet);
1139 unit_test_cmp(txt,size(uniquetol(intpts,eps,'ByRows',true),1),1,0);
1140 [intpts, face2edge, face2intpt, edge2intpt] = test_tedge2vedge_intersections(vox,tet);
1141 unit_test_cmp(txt,size(intpts,1),0,0);
1142 [fnode2vox] = test_tnode_in_vox(vox,tet);
1143 unit_test_cmp(txt,nnz(fnode2vox),1,0);
1144 rnode2tet = test_vnode_in_tet(vox,tet);
1145 unit_test_cmp(txt,nnz(rnode2tet),0,0);
1146 mk_grid_c2f(tet,vox);
1147
1148 case 9
1149 txt = 'all nodes common';
1150 subplot(X,Y,i), show_test(vox,tet);
1151 [intpts, face2edge, face2intpt, edge2intpt] = test_rec_tedge_intersections(vox,tet);
1152 unit_test_cmp(txt,size(intpts,1),0,0);
1153 [intpts, face2edge, face2intpt, edge2intpt] = test_tet_vedge_intersections(vox,tet);
1154 unit_test_cmp(txt,size(intpts,1),0,0);
1155 [intpts, face2edge, face2intpt, edge2intpt] = test_tedge2vedge_intersections(vox,tet);
1156 unit_test_cmp(txt,size(intpts,1),0,0);
1157 [fnode2vox] = test_tnode_in_vox(vox,tet);
1158 unit_test_cmp(txt,nnz(fnode2vox),4,0);
1159 rnode2tet = test_vnode_in_tet(vox,tet);
1160 unit_test_cmp(txt,nnz(rnode2tet),0,0);
1161 mk_grid_c2f(tet,vox);
1162
1163 case 10
1164 txt = 'tet in vox';
1165 tet.nodes = .25 + .5*tet.nodes;
1166 subplot(X,Y,i), show_test(vox,tet);
1167 [intpts, face2edge, face2intpt, edge2intpt] = test_rec_tedge_intersections(vox,tet);
1168 unit_test_cmp(txt,size(intpts,1),0,0);
1169 [intpts, face2edge, face2intpt, edge2intpt] = test_tet_vedge_intersections(vox,tet);
1170 unit_test_cmp(txt,size(intpts,1),0,0);
1171 [intpts, face2edge, face2intpt, edge2intpt] = test_tedge2vedge_intersections(vox,tet);
1172 unit_test_cmp(txt,size(intpts,1),0,0);
1173 [fnode2vox] = test_tnode_in_vox(vox,tet);
1174 unit_test_cmp(txt,nnz(fnode2vox),4,0);
1175 rnode2tet = test_vnode_in_tet(vox,tet);
1176 unit_test_cmp(txt,nnz(rnode2tet),0,0);
1177 mk_grid_c2f(tet,vox);
1178 c2f = mk_grid_c2f(tet,vox);
1179 max_vox = max(vox.nodes);
1180 min_vox = min(vox.nodes);
1181 edges = max_vox-min_vox;
1182 vox_vol = edges(:,1) .* edges(:,2) .* edges(:,3);
1183 tet_vol = get_elem_volume(tet);
1184 unit_test_cmp(txt,c2f, 1, 0);
1185
1186 case 11
1187 txt = 'vox in tet';
1188 tet.nodes = 4*tet.nodes - .25;
1189 subplot(X,Y,i), show_test(vox,tet);
1190 [intpts, face2edge, face2intpt, edge2intpt] = test_rec_tedge_intersections(vox,tet);
1191 unit_test_cmp(txt,size(intpts,1),0,0);
1192 [intpts, face2edge, face2intpt, edge2intpt] = test_tet_vedge_intersections(vox,tet);
1193 unit_test_cmp(txt,size(intpts,1),0,0);
1194 [intpts, face2edge, face2intpt, edge2intpt] = test_tedge2vedge_intersections(vox,tet);
1195 unit_test_cmp(txt,size(intpts,1),0,0);
1196 [fnode2vox] = test_tnode_in_vox(vox,tet);
1197 unit_test_cmp(txt,nnz(fnode2vox),0,0);
1198 rnode2tet = test_vnode_in_tet(vox,tet);
1199 unit_test_cmp(txt,nnz(rnode2tet),8,0);
1200 c2f = mk_grid_c2f(tet,vox);
1201 max_vox = max(vox.nodes);
1202 min_vox = min(vox.nodes);
1203 edges = max_vox-min_vox;
1204 vox_vol = edges(:,1) .* edges(:,2) .* edges(:,3);
1205 tet_vol = get_elem_volume(tet);
1206 unit_test_cmp(txt,c2f, vox_vol / tet_vol, 0);
1207
1208
1209 case 12
1210 txt = 'tet_edge v. vox_face';
1211 tet.nodes(:,1:2) = tet.nodes(:,1:2) - 0.3;
1212 tet.nodes(:,3) = tet.nodes(:,3) + .4;
1213 subplot(X,Y,i), show_test(vox,tet);
1214 [intpts, face2edge, face2intpt, edge2intpt] = test_rec_tedge_intersections(vox,tet);
1215 unit_test_cmp(txt,size(intpts,1),2,0);
1216 [intpts, face2edge, face2intpt, edge2intpt] = test_tet_vedge_intersections(vox,tet);
1217 unit_test_cmp(txt,size(intpts,1),2,0);
1218 [intpts, face2edge, face2intpt, edge2intpt] = test_tedge2vedge_intersections(vox,tet);
1219 unit_test_cmp(txt,size(intpts,1),0,0);
1220 [fnode2vox] = test_tnode_in_vox(vox,tet);
1221 unit_test_cmp(txt,nnz(fnode2vox),0,0);
1222 rnode2tet = test_vnode_in_tet(vox,tet);
1223 unit_test_cmp(txt,nnz(rnode2tet),0,0);
1224 mk_grid_c2f(tet,vox);
1225
1226
1227 case 13
1228 txt = 'everything';
1229 tet.nodes = tet.nodes + 0.7;
1230 subplot(X,Y,i), show_test(vox,tet);
1231 [intpts, face2edge, face2intpt, edge2intpt] = test_rec_tedge_intersections(vox,tet);
1232 unit_test_cmp(txt,size(intpts,1),3,0);
1233 [intpts, face2edge, face2intpt, edge2intpt] = test_tet_vedge_intersections(vox,tet);
1234 unit_test_cmp(txt,size(intpts,1),3,0);
1235 [intpts, face2edge, face2intpt, edge2intpt] = test_tedge2vedge_intersections(vox,tet);
1236 unit_test_cmp(txt,size(intpts,1),0,0);
1237 [fnode2vox] = test_tnode_in_vox(vox,tet);
1238 unit_test_cmp(txt,nnz(fnode2vox),1,0);
1239 rnode2tet = test_vnode_in_tet(vox,tet);
1240 unit_test_cmp(txt,nnz(rnode2tet),1,0);
1241 mk_grid_c2f(tet,vox);
1242
1243
1244 case 14
1245 txt = 'DG1: Common edge';
1246 tet.nodes(:,1:2) = tet.nodes(:,1:2) + 1;
1247 subplot(X,Y,i), show_test(vox,tet);
1248 [intpts, face2edge, face2intpt, edge2intpt] = test_rec_tedge_intersections(vox,tet);
1249 unit_test_cmp(txt,size(intpts,1),0,0);
1250 [intpts, face2edge, face2intpt, edge2intpt] = test_tet_vedge_intersections(vox,tet);
1251 unit_test_cmp(txt,size(intpts,1),0,0);
1252 [intpts, face2edge, face2intpt, edge2intpt] = test_tedge2vedge_intersections(vox,tet);
1253 unit_test_cmp(txt,size(intpts,1),0,0);
1254 [fnode2vox] = test_tnode_in_vox(vox,tet);
1255 unit_test_cmp(txt,fnode2vox,[1;0;0;1],0);
1256 rnode2tet = test_vnode_in_tet(vox,tet);
1257 unit_test_cmp(txt,nnz(rnode2tet),0,0);
1258 mk_grid_c2f(tet,vox);
1259
1260 case 15
1261 txt = 'DG2: Common edge';
1262 tet.nodes(:,1:2) = tet.nodes(:,1:2) + 1;
1263 tet.nodes(:,3) = tet.nodes(:,3) + 0.5;
1264 subplot(X,Y,i), show_test(vox,tet);
1265 [intpts, face2edge, face2intpt, edge2intpt] = test_rec_tedge_intersections(vox,tet);
1266 unit_test_cmp(txt,size(intpts,1),0,0);
1267 [intpts, face2edge, face2intpt, edge2intpt] = test_tet_vedge_intersections(vox,tet);
1268 unit_test_cmp(txt,size(unique(intpts,'rows'),1),1,1);
1269 [intpts, face2edge, face2intpt, edge2intpt] = test_tedge2vedge_intersections(vox,tet);
1270 unit_test_cmp(txt,size(intpts,1),0,0);
1271 [fnode2vox] = test_tnode_in_vox(vox,tet);
1272 unit_test_cmp(txt,nnz(fnode2vox),1,0);
1273 rnode2tet = test_vnode_in_tet(vox,tet);
1274 unit_test_cmp(txt,nnz(rnode2tet),1,0);
1275 mk_grid_c2f(tet,vox);
1276
1277 case 16
1278 txt = 'DG3: Common edge';
1279 tet.nodes(:,1:2) = tet.nodes(:,1:2) + 1;
1280 z = tet.nodes(:,3) == 0;
1281 tet.nodes(z,3) = -.5;
1282 tet.nodes(~z,3) = 1.5;
1283 subplot(X,Y,i), show_test(vox,tet);
1284 [intpts, face2edge, face2intpt, edge2intpt] = test_rec_tedge_intersections(vox,tet);
1285 unit_test_cmp(txt,size(intpts,1),0,0);
1286 [intpts, face2edge, face2intpt, edge2intpt] = test_tet_vedge_intersections(vox,tet);
1287 unit_test_cmp(txt,size(intpts,1),0,0);
1288 [intpts, face2edge, face2intpt, edge2intpt] = test_tedge2vedge_intersections(vox,tet);
1289 unit_test_cmp(txt,size(intpts,1),0,0);
1290 [fnode2vox] = test_tnode_in_vox(vox,tet);
1291 unit_test_cmp(txt,nnz(fnode2vox),0,0);
1292 rnode2tet = test_vnode_in_tet(vox,tet);
1293 unit_test_cmp(txt,nnz(rnode2tet),2,0);
1294 mk_grid_c2f(tet,vox);
1295
1296 case 17
1297 txt = 'DG4: edge on face';
1298 tet.nodes = [0 0 0; 1 .5 0; 0 1 0; 1 .5 1];
1299 tet.nodes(:,1) = tet.nodes(:,1) - 1;
1300 subplot(X,Y,i), show_test(vox,tet);
1301 [intpts, face2edge, face2intpt, edge2intpt] = test_rec_tedge_intersections(vox,tet);
1302 unit_test_cmp(txt,size(intpts,1),0,0);
1303 [intpts, face2edge, face2intpt, edge2intpt] = test_tet_vedge_intersections(vox,tet);
1304 unit_test_cmp(txt,size(unique(intpts,'rows'),1),2,0);
1305 [intpts, face2edge, face2intpt, edge2intpt] = test_tedge2vedge_intersections(vox,tet);
1306 unit_test_cmp(txt,size(intpts,1),0,0);
1307 [fnode2vox] = test_tnode_in_vox(vox,tet);
1308 unit_test_cmp(txt,nnz(fnode2vox),2,0);
1309 rnode2tet = test_vnode_in_tet(vox,tet);
1310 unit_test_cmp(txt,nnz(rnode2tet),0,0);
1311 mk_grid_c2f(tet,vox);
1312
1313 case 18
1314 txt = 'DG5: edge2edge only';
1315 tet.nodes = [0 0 0; 1 .5 0; 0 1 0; 1 .5 1];
1316 tet.nodes(:,1) = tet.nodes(:,1) - 1;
1317 z = tet.nodes(:,3) == 0;
1318 tet.nodes(z,3) = -.5;
1319 tet.nodes(~z,3) = 1.5;
1320 subplot(X,Y,i), show_test(vox,tet);
1321 [intpts, face2edge, face2intpt, edge2intpt] = test_rec_tedge_intersections(vox,tet);
1322 unit_test_cmp(txt,size(intpts,1),0,0);
1323 [intpts, face2edge, face2intpt, edge2intpt] = test_tet_vedge_intersections(vox,tet);
1324 unit_test_cmp(txt,size(unique(intpts,'rows'),1),2,0);
1325 [intpts, face2edge, face2intpt, edge2intpt] = test_tedge2vedge_intersections(vox,tet);
1326 unit_test_cmp(txt,size(intpts,1),2,0);
1327 [fnode2vox] = test_tnode_in_vox(vox,tet);
1328 unit_test_cmp(txt,nnz(fnode2vox),0,0);
1329 rnode2tet = test_vnode_in_tet(vox,tet);
1330 unit_test_cmp(txt,nnz(rnode2tet),0,0);
1331 mk_grid_c2f(tet,vox);
1332
1333 case 19
1334 txt = 'DG6: edge on face';
1335 tet.nodes = [0 0 0; 1 .5 0; 0 1 0; 1 .5 1];
1336 tet.nodes(:,1) = tet.nodes(:,1) - 1;
1337 tet.nodes(:,3) = tet.nodes(:,3) - .5;
1338 subplot(X,Y,i), show_test(vox,tet);
1339 [intpts, face2edge, face2intpt, edge2intpt] = test_rec_tedge_intersections(vox,tet);
1340 unit_test_cmp(txt,size(intpts,1),0,0);
1341 [intpts, face2edge, face2intpt, edge2intpt] = test_tet_vedge_intersections(vox,tet);
1342 unit_test_cmp(txt,size(unique(intpts,'rows'),1),1,0);
1343 [intpts, face2edge, face2intpt, edge2intpt] = test_tedge2vedge_intersections(vox,tet);
1344 unit_test_cmp(txt,size(intpts,1),1,0);
1345 [fnode2vox] = test_tnode_in_vox(vox,tet);
1346 unit_test_cmp(txt,nnz(fnode2vox),1,0);
1347 rnode2tet = test_vnode_in_tet(vox,tet);
1348 unit_test_cmp(txt,nnz(rnode2tet),0,0);
1349 mk_grid_c2f(tet,vox);
1350
1351 case 20
1352 txt = 'DG7: face on face';
1353 tet.nodes(:,1) = tet.nodes(:,1) + 1;
1354 tet.nodes(:,2) = tet.nodes(:,2) + 0.5;
1355 tet.nodes(:,3) = tet.nodes(:,3) + 0.5;
1356 subplot(X,Y,i), show_test(vox,tet);
1357 [intpts, face2edge, face2intpt, edge2intpt] = test_rec_tedge_intersections(vox,tet);
1358 unit_test_cmp(txt,size(intpts,1),0,0);
1359 [intpts, face2edge, face2intpt, edge2intpt] = test_tet_vedge_intersections(vox,tet);
1360 unit_test_cmp(txt,size(uniquetol(intpts,2*eps,'ByRows',true),1),3,0);
1361 [intpts, face2edge, face2intpt, edge2intpt] = test_tedge2vedge_intersections(vox,tet);
1362 unit_test_cmp(txt,size(unique(intpts,'rows'),1),2,0);
1363 [fnode2vox] = test_tnode_in_vox(vox,tet);
1364 unit_test_cmp(txt,nnz(fnode2vox),1,0);
1365 rnode2tet = test_vnode_in_tet(vox,tet);
1366 unit_test_cmp(txt,nnz(rnode2tet),1,0);
1367 mk_grid_c2f(tet,vox);
1368
1369 case 21
1370 txt = 'DG8: face on face';
1371 tet.nodes(:,1) = tet.nodes(:,1) + 1;
1372 tet.nodes(:,2) = tet.nodes(:,2) + 0.4;
1373 tet.nodes(:,3) = tet.nodes(:,3) - 0.6;
1374 subplot(X,Y,i), show_test(vox,tet);
1375 [intpts, face2edge, face2intpt, edge2intpt] = test_rec_tedge_intersections(vox,tet);
1376 unit_test_cmp(txt,size(intpts,1),0,0);
1377 [intpts, face2edge, face2intpt, edge2intpt] = test_tet_vedge_intersections(vox,tet);
1378 unit_test_cmp(txt,size(unique(intpts,'rows'),1),2,0);
1379 [intpts, face2edge, face2intpt, edge2intpt] = test_tedge2vedge_intersections(vox,tet);
1380 unit_test_cmp(txt,size(unique(intpts,'rows'),1),2,0);
1381 [fnode2vox] = test_tnode_in_vox(vox,tet);
1382 unit_test_cmp(txt,nnz(fnode2vox),1,0);
1383 rnode2tet = test_vnode_in_tet(vox,tet);
1384 unit_test_cmp(txt,nnz(rnode2tet),0,0);
1385 mk_grid_c2f(tet,vox);
1386
1387 otherwise
1388 break;
1389 end
1390 end
1391 eidors_msg('log_level',ll);
1392
1393 function do_small_test
1394 fmdl= ng_mk_cyl_models([2,2,.1],[16,1],[.1,0,.025]);
1395 xvec = [-1.5:1:1.5];
1396 yvec = [-1.6:.8:1.6];
1397 zvec = -1:1:2;
1398 rmdl = mk_grid_model([],xvec,yvec,zvec);
1399
1400 eidors_cache clear
1401 tic
1402 c2f_a = mk_grid_c2f(fmdl, rmdl);
1403 toc
1404 eidors_cache clear
1405 tic
1406 opt.save_memory = 2;
1407 c2f_b = mk_grid_c2f(fmdl, rmdl, opt);
1408 toc
1409 eidors_cache clear
1410 tic
1411 c2f_c = mk_approx_c2f(fmdl, rmdl);
1412 toc
1413 assert(any(c2f_a(:) ~= c2f_b(:)) == 0);
1414
1415
1416
1417
1418 function do_realistic_test
1419 fmdl= ng_mk_cyl_models([2,2,.1],[16,1],[.1,0,.025]);
1420 xvec = [-1.5 -.5:.2:.5 1.5];
1421 yvec = [-1.6 -1:.2:1 1.6];
1422 zvec = 0:.25:2;
1423 rmdl = mk_grid_model([],xvec,yvec,zvec);
1424
1425 tic
1426 opt.save_memory = 0;
1427 c2f_a = mk_grid_c2f(fmdl, rmdl,opt);
1428 t = toc;
1429 fprintf('Analytic: t=%f s\n',t);
1430
1431 tic
1432 c2f_n = mk_approx_c2f(fmdl,rmdl);
1433 t = toc;
1434 fprintf('Approximate: t=%f s\n',t);
1435
1436
1437 tetvol = get_elem_volume(fmdl);
1438 opt = parse_opts(fmdl,rmdl);
1439 m = prepare_vox_mdl(rmdl,opt);
1440
1441
1442 f2c_a = bsxfun(@times, c2f_a, tetvol);
1443 f2c_a = bsxfun(@rdivide,f2c_a', m.volume);
1444 img = mk_image(rmdl,0);
1445 img.elem_data = f2c_a*ones(size(fmdl.elems,1),1);
1446 subplot(132)
1447 show_fem(img);
1448
1449 f2c_n = bsxfun(@times, c2f_n, tetvol);
1450 f2c_n = bsxfun(@rdivide,f2c_n', m.volume);
1451 img = mk_image(rmdl,0);
1452 img.elem_data = f2c_n*ones(size(fmdl.elems,1),1);
1453 subplot(133)
1454 show_fem(img);
1455 subplot(131);
1456 h = show_fem(fmdl);
1457 set(h,'LineWidth',0.1)
1458 hold on
1459 h = show_fem(rmdl);
1460 set(h,'EdgeColor','b','LineWidth',2);
1461 hold off
1462
1463 function do_edge2edge_timing_test
1464 fmdl= ng_mk_cyl_models([2,2],[8,1],[.15,0,.05]);
1465 xvec = linspace(-2,2,33);
1466 yvec = linspace(-2,2,33);
1467 zvec = 0:.5:2;
1468 rmdl = mk_grid_model([],xvec,yvec,zvec);
1469 tic
1470 test_tedge2vedge_intersections(rmdl,fmdl);
1471 toc
1472
1473 function rnode2tet = test_vnode_in_tet(rmdl,fmdl)
1474 opt = parse_opts(fmdl,rmdl);
1475 fmdl = prepare_fmdl(fmdl);
1476 rnode2tet = get_nodes_in_tets(fmdl,rmdl, opt);
1477
1478 function [fnode2vox] = test_tnode_in_vox(rmdl,fmdl)
1479 fmdl = prepare_fmdl(fmdl);
1480 [fnode2vox] = get_nodes_in_voxels(fmdl,rmdl);
1481
1482 function [intpts, face2edge, face2intpt, edge2intpt] = test_rec_tedge_intersections(rmdl,fmdl)
1483 opt = parse_opts(fmdl,rmdl);
1484 m = prepare_vox_mdl(rmdl,opt);
1485 fmdl = prepare_fmdl(fmdl);
1486 [intpts, face2edge, face2intpt, edge2intpt] = get_voxel_intersection_points(fmdl,m.faces,opt);
1487
1488 function [intpts, face2edge, face2intpt, edge2intpt] = test_tet_vedge_intersections(rmdl,fmdl)
1489 opt = parse_opts(fmdl,rmdl);
1490 m = prepare_vox_mdl(rmdl,opt);
1491 fmdl = prepare_fmdl(fmdl);
1492 [intpts, face2edge, face2intpt, edge2intpt] = get_tet_intersection_points(fmdl,m,opt);
1493
1494 function [intpts, tedge2vedge, tedge2intpt, vedge2intpt] = test_tedge2vedge_intersections(rmdl,fmdl)
1495 opt = parse_opts(fmdl,rmdl);
1496 m = prepare_vox_mdl(rmdl,opt);
1497 fmdl = prepare_fmdl(fmdl);
1498 [intpts, tedge2vedge, tedge2intpt, vedge2intpt] = find_edge2edge_intersections(fmdl.edges,fmdl.nodes,m.edges,rmdl.nodes, opt.tol_node2tet);
1499
1500 function show_test(vox,tet)
1501 show_fem(vox);
1502 hold on
1503 h = show_fem(tet);
1504 set(h, 'EdgeColor','b');
1505 hold off
1506 axis auto