0001 function hh = show_fem_enhanced(mdl, options)
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
0062
0063
0064
0065
0066
0067
0068
0069 switch nargin
0070 case 0
0071 error('Insufficient parameters for show_fem');
0072 case 1
0073 if ischar(mdl) && strcmp(mdl,'UNIT_TEST');
0074 do_unit_test;
0075 return;
0076 end
0077 if (isstruct(mdl) && isfield(mdl, 'show_fem'))
0078 options = mdl.show_fem;
0079 else
0080 options = [];
0081 end
0082 case 2
0083
0084 otherwise
0085 error('Too many parameters for show_fem');
0086 end
0087
0088 [img, mdl, opts] = proc_params(mdl, options);
0089
0090 if ~ishold
0091 cla;
0092 end
0093
0094 mdl = find_sub_elements(mdl);
0095
0096
0097 mdl.nodes = mdl.nodes*eye(size(mdl.nodes, 2), 3);
0098
0099 hh = draw_all(img, mdl, opts);
0100
0101
0102 if (opts.edge.significant.viewpoint_dependent.callback)
0103 if ~exist('OCTAVE_VERSION');
0104 h3d = rotate3d;
0105 set(gca, 'UserData', struct('name', 'show_fem_data', 'img', img, 'mdl', mdl, 'opts', opts));
0106 set(h3d, 'ActionPostCallback' , @refresh_current_axis)
0107 end
0108 end
0109
0110 if (nargout == 0)
0111 clear hh;
0112 end
0113
0114 function [img, mdl, opts] = proc_params(mdl, src_opts)
0115
0116
0117 opts.viewpoint.az = -37.5;
0118 opts.viewpoint.el = 30.0;
0119
0120
0121 opts.edge.color = [0 0 0];
0122 opts.edge.width = 0.5;
0123 opts.edge.significant.show = true;
0124 opts.edge.significant.color = [0 0 0];
0125 opts.edge.significant.width = 2;
0126 opts.edge.significant.angle = 45;
0127 opts.edge.significant.viewpoint_dependent.show = true;
0128 opts.edge.significant.viewpoint_dependent.color = [0 0 0];
0129 opts.edge.significant.viewpoint_dependent.width = 2;
0130 opts.edge.significant.viewpoint_dependent.callback = true;
0131
0132
0133 opts.colorbar.show = false;
0134
0135
0136 opts.electrode.number.show = false;
0137 opts.electrode.number.font_size = 10;
0138 opts.electrode.number.font_weight = 'bold';
0139 opts.electrode.number.color = [.6 0 0];
0140 opts.electrode.number.background_color = 'none';
0141 opts.electrode.number.scale_position = 1.15;
0142
0143
0144 opts.element.number.show = false;
0145 opts.element.number.font_size = 7;
0146 opts.element.number.font_weight = 'normal';
0147 opts.element.number.color = [0 0 0];
0148 opts.element.number.background_color = 'none';
0149
0150
0151 opts.node.number.show = false;
0152 opts.node.number.font_size = 7;
0153 opts.node.number.font_weight = 'normal';
0154 opts.node.number.color = [0 0 0.5];
0155 opts.node.number.background_color = [1 1 1];
0156
0157
0158 if mdl_dim( mdl ) == 2
0159 opts.viewpoint.az = 0;
0160 opts.viewpoint.el = 90;
0161 opts.electrode.number.scale_position= 1.05;
0162 end
0163
0164 if (nargin == 2)
0165 if (isstruct(src_opts))
0166 opts = copy_field(opts, src_opts, 'viewpoint', 'az');
0167 opts = copy_field(opts, src_opts, 'viewpoint', 'el');
0168 opts = copy_field(opts, src_opts, 'edge', 'color');
0169 opts = copy_field(opts, src_opts, 'edge', 'width');
0170
0171 if (isfield(src_opts, 'edge'))
0172 opts.edge = copy_field(opts.edge, src_opts.edge, 'significant', 'show');
0173 opts.edge = copy_field(opts.edge, src_opts.edge, 'significant', 'color');
0174 opts.edge = copy_field(opts.edge, src_opts.edge, 'significant', 'width');
0175 opts.edge = copy_field(opts.edge, src_opts.edge, 'significant', 'angle');
0176 if (isfield(src_opts.edge, 'significant'))
0177 opts.edge.significant = copy_field(opts.edge.significant, src_opts.edge.significant, 'viewpoint_dependent', 'show');
0178 opts.edge.significant = copy_field(opts.edge.significant, src_opts.edge.significant, 'viewpoint_dependent', 'color');
0179 opts.edge.significant = copy_field(opts.edge.significant, src_opts.edge.significant, 'viewpoint_dependent', 'width');
0180 opts.edge.significant = copy_field(opts.edge.significant, src_opts.edge.significant, 'viewpoint_dependent', 'callback');
0181 end
0182 end
0183
0184 opts = copy_field(opts, src_opts, 'colorbar', 'show');
0185
0186 if (isfield(src_opts, 'electrode'))
0187 opts.electrode = copy_field(opts.electrode, src_opts.electrode, 'number', 'show');
0188 opts.electrode = copy_field(opts.electrode, src_opts.electrode, 'number', 'font_size');
0189 opts.electrode = copy_field(opts.electrode, src_opts.electrode, 'number', 'font_weight');
0190 opts.electrode = copy_field(opts.electrode, src_opts.electrode, 'number', 'color');
0191 opts.electrode = copy_field(opts.electrode, src_opts.electrode, 'number', 'background_color');
0192 opts.electrode = copy_field(opts.electrode, src_opts.electrode, 'number', 'scale_position');
0193 end
0194
0195 if (isfield(src_opts, 'element'))
0196 opts.element = copy_field(opts.element, src_opts.element, 'number', 'show');
0197 opts.element = copy_field(opts.element, src_opts.element, 'number', 'font_size');
0198 opts.element = copy_field(opts.element, src_opts.element, 'number', 'font_weight');
0199 opts.element = copy_field(opts.element, src_opts.element, 'number', 'color');
0200 opts.element = copy_field(opts.element, src_opts.element, 'number', 'background_color');
0201 end
0202
0203 if (isfield(src_opts, 'node'))
0204 opts.node = copy_field(opts.node, src_opts.node, 'number', 'show');
0205 opts.node = copy_field(opts.node, src_opts.node, 'number', 'font_size');
0206 opts.node = copy_field(opts.node, src_opts.node, 'number', 'font_weight');
0207 opts.node = copy_field(opts.node, src_opts.node, 'number', 'color');
0208 opts.node = copy_field(opts.node, src_opts.node, 'number', 'background_color');
0209 end
0210
0211
0212 else
0213
0214 optionstr = zeros(1, 100);
0215 optionstr(1:length(src_opts)) = src_opts;
0216
0217 opts.colorbar.show = optionstr(1);
0218 opts.electrode.number.show = optionstr(2);
0219 switch optionstr(3)
0220 case 1
0221 opts.element.number.show = 1;
0222 case 2
0223 opts.node.number.show = 1;
0224 case 3
0225 opts.element.number.show = 1;
0226 opts.node.number.show = 1;
0227 end
0228 end
0229 end
0230
0231
0232 if (numel(mdl) > 1)
0233 eidors_msg('warning: show_fem only shows first image',1);
0234 mdl = mdl(1);
0235 end
0236
0237
0238 if strcmp(mdl(1).type , 'image' )
0239 img = mdl;
0240 mdl = img.fwd_model;
0241 else
0242 img = [];
0243 end
0244
0245 function refresh_current_axis(obj, evd)
0246 UserData = get(gca, 'UserData');
0247 if (all(isfield(UserData, {'name', 'img', 'mdl', 'opts'})) && ...
0248 strcmp(UserData.name, 'show_fem_data'))
0249 [az, el] = view(gca);
0250 if (az ~= UserData.opts.viewpoint.az || el ~= UserData.opts.viewpoint.el)
0251 UserData.opts.viewpoint.az = az;
0252 UserData.opts.viewpoint.el = el;
0253 cla;
0254 draw_all(UserData.img, UserData.mdl, UserData.opts);
0255 set(gca, 'UserData', UserData);
0256 end
0257 end
0258
0259 function hh = draw_all(img, mdl, opts)
0260
0261 hh = draw_fem(img, mdl, opts);
0262
0263
0264 if (opts.element.number.show)
0265 draw_numbers(interp_mesh(mdl), opts.element.number);
0266 end
0267
0268
0269 if (opts.node.number.show)
0270 draw_numbers(mdl.nodes, opts.node.number);
0271 end
0272
0273
0274 if (opts.electrode.number.show && isfield(mdl, 'electrode'))
0275 n_elec = numel(mdl.electrode);
0276 mesh_center = ones(n_elec, 1)*mean(mdl.nodes, 1);
0277
0278 elec_pos = zeros(n_elec, size(mesh_center, 2));
0279
0280 for i = 1:n_elec
0281 if (isfield(mdl.electrode(i), 'nodes'))
0282 elec_pos(i, :) = mean(mdl.nodes(mdl.electrode(i).nodes, :), 1);
0283 elseif (isfield(mdl.electrode(i), 'pos'))
0284 elec_pos(i, :) = mean(mdl.electrode(i).pos, 1)*eye(size(...
0285 elec_pos(i, :), 2), 3);
0286 end
0287 end
0288
0289 draw_numbers(opts.electrode.number.scale_position*(elec_pos - mesh_center) + mesh_center, opts.electrode.number);
0290 end
0291
0292 if (size(mdl.elems, 2) == 4)
0293 view(opts.viewpoint.az, opts.viewpoint.el);
0294 end
0295
0296 axis image;
0297
0298 function hh = draw_fem(img, mdl, opts)
0299
0300
0301 if (size(mdl.elems, 2) == 4)
0302 if ~isempty(img)
0303 elems = mdl.sub_elements;
0304 electrode_field = 'sub_elements';
0305 else
0306 elems = mdl.boundary;
0307 electrode_field = 'boundary';
0308 end
0309 triangle_alpha = 0.5*ones(size(elems, 1), 1);
0310 triangle_edge_color = 'none';
0311 triangle_edge_width = 0.5;
0312
0313
0314 edge_edges = mdl.boundary_edges;
0315 edge_width = ones(size(edge_edges, 1), 1)*opts.edge.width;
0316 edge_color = ones(size(edge_edges, 1), 1)*opts.edge.color;
0317
0318 if opts.edge.significant.show
0319 if opts.edge.significant.viewpoint_dependent.show
0320 if exist('viewmtx')
0321
0322 T = viewmtx(opts.viewpoint.az, opts.viewpoint.el);
0323 else
0324 T = ones(4);
0325 end
0326 transformed_boundary_normal_vector = mdl.boundary_normal_vector*T(1:3,1:3)';
0327 boundary_edges_idx2 = (transformed_boundary_normal_vector(mdl.edge2boundary(:, 1), 3).*transformed_boundary_normal_vector(mdl.edge2boundary(:, 2), 3) <= 0);
0328
0329 edge_width(boundary_edges_idx2) = opts.edge.significant.viewpoint_dependent.width;
0330 edge_color(boundary_edges_idx2, :) = ones(sum(boundary_edges_idx2), 1)*opts.edge.significant.viewpoint_dependent.color;
0331 end
0332
0333
0334
0335 boundary_edges_idx = dot(mdl.boundary_normal_vector(...
0336 mdl.edge2boundary(:, 1), :), ...
0337 mdl.boundary_normal_vector(...
0338 mdl.edge2boundary(:, 2), :), 2) ...
0339 <= cosd(opts.edge.significant.angle);
0340 edge_width(boundary_edges_idx) = opts.edge.significant.width;
0341 edge_color(boundary_edges_idx, :) = ones(sum(boundary_edges_idx), 1)*opts.edge.significant.color;
0342 end
0343 else
0344 elems = mdl.elems;
0345 electrode_field = 'boundary';
0346 triangle_alpha = ones(size(elems, 1), 1);
0347 triangle_edge_color = opts.edge.color;
0348 triangle_edge_width = opts.edge.width;
0349
0350
0351 if opts.edge.significant.show
0352 edge_edges = mdl.boundary;
0353 edge_width = opts.edge.significant.width*ones(size(edge_edges, 1), 1);
0354 edge_color = ones(size(edge_edges, 1), 1)*opts.edge.significant.color;
0355 else
0356 edge_edges = [];
0357 end
0358 end
0359
0360 if ~isempty(img)
0361 if (size(mdl.elems, 2) == 4)
0362 triangle_color = calc_colours(mdl.element2sub_element*...
0363 get_img_data(img), img);
0364
0365 factor = 3/8;
0366
0367 alpha_map = zeros(size(colormap, 1), 1);
0368 alpha = linspace(0, 1, round(size(colormap, 1)*factor))';
0369 alpha_map(1:size(alpha, 1)) = alpha(end:-1:1);
0370 alpha_map(end:-1:(end-size(alpha, 1)+1)) = alpha(end:-1:1);
0371
0372 factor = 3/8;
0373 alpha_map2 = ones(size(colormap, 1), 1);
0374 alpha2 = linspace(0, 1, round(size(colormap, 1)*factor))';
0375 alpha_map2((1:size(alpha2, 1)) + size(colormap, 1)/2) = alpha2;
0376 alpha_map2((end:-1:(end-size(alpha2, 1)+1)) - size(colormap, 1)/2) = alpha2;
0377
0378 factor = 3/8;
0379 alpha_map3 = ones(size(colormap, 1), 1);
0380 alpha3 = linspace(0, 1, round(size(colormap, 1)*factor))';
0381 idx1 = (size(colormap, 1)/2 - size(alpha3, 1))/2;
0382 alpha_map3((-idx1:idx1) + size(colormap, 1)/2) = 0;
0383 alpha_map3((1:size(alpha3, 1)) + size(colormap, 1)/2 + (size(colormap, 1)/2 - size(alpha3, 1))/2) = alpha3;
0384 alpha_map3((end:-1:(end-size(alpha3, 1)+1)) - size(colormap, 1)/2 - (size(colormap, 1)/2 - size(alpha3, 1))/2) = alpha3;
0385
0386 triangle_alpha = alpha_map3(triangle_color);
0387
0388
0389 alpha_idx = triangle_alpha(mdl.boundary_to_sub_element_idx, :) < 0.5;
0390 triangle_alpha(mdl.boundary_to_sub_element_idx(alpha_idx), :) = 0.5;
0391 else
0392 triangle_color = calc_colours(img);
0393 end
0394 triangle_color = squeeze(triangle_color(:, 1, :));
0395 else
0396 triangle_color = ones(size(elems, 1), 1)*[1 1 1];
0397 end
0398
0399
0400 marker_position = [];
0401 marker_color = [];
0402
0403 if (isfield(mdl, 'electrode'))
0404 for i = 1:numel(mdl.electrode)
0405 if (isfield(mdl.electrode(i), electrode_field) && ...
0406 ~isempty(mdl.electrode(i).(electrode_field)))
0407
0408 if (size(mdl.elems, 2) == 4)
0409 triangle_color(...
0410 mdl.electrode(i).(electrode_field), :) = ...
0411 ones(numel(mdl.electrode(i).(electrode_field)), ...
0412 1)*electr_colour(i, size(triangle_color, 2));
0413
0414 triangle_alpha(mdl.electrode(i).(electrode_field), ...
0415 :) = 1;
0416
0417 boundary_edges = [mdl.electrode(i).boundary_inner_edges;
0418 mdl.electrode(i).boundary_outer_edges];
0419 edge_color(boundary_edges, :) = 0.5*ones(size(...
0420 boundary_edges, 1), 1)*electr_colour(i, 3);
0421 edge_width(mdl.electrode(i).boundary_outer_edges) = 1;
0422 else
0423
0424 edge_width(mdl.electrode(i).(electrode_field), :) = 3;
0425 edge_color(mdl.electrode(i).(electrode_field), :) = ...
0426 ones(numel(mdl.electrode(i).(electrode_field)), ...
0427 1)*electr_colour(i, 3);
0428 end
0429 else
0430 if (isfield(mdl.electrode(i), 'nodes'))
0431 marker_position(end + 1, :) = mean(mdl.nodes(...
0432 mdl.electrode(i).nodes, :), 1);
0433 elseif (isfield(mdl.electrode(i), 'pos'))
0434 marker_position(end + 1, :) = mean(...
0435 mdl.electrode(i).pos, 1)*...
0436 eye(size(marker_position(end, :), 2), 3);
0437 end
0438 marker_color(end + 1, :) = electr_colour(i, 3);
0439 end
0440 end
0441 end
0442
0443
0444 hh = draw_triangles(elems, mdl.nodes, ...
0445 triangle_color, triangle_alpha, ...
0446 triangle_edge_color, triangle_edge_width);
0447
0448
0449 if (~isempty(edge_edges))
0450 draw_edges(edge_edges, mdl.nodes, edge_width, edge_color);
0451 end
0452
0453
0454 if (~isempty(marker_position))
0455 draw_markers(marker_position, marker_color, 9);
0456 end
0457
0458 if opts.colorbar.show && ~isempty( img )
0459
0460 eidors_colourbar( img );
0461
0462 end
0463
0464 function draw_numbers(positions, opts)
0465 text(positions(:,1), positions(:,2), positions(:,3), ...
0466 arrayfun(@(x){int2str(x)}, 1:size(positions, 1)), ...
0467 'HorizontalAlignment', 'center', ...
0468 'VerticalAlignment', 'middle', ...
0469 'FontSize', opts.font_size, ...
0470 'FontWeight', opts.font_weight, ...
0471 'Color', opts.color, ...
0472 'BackgroundColor', opts.background_color);
0473
0474 function hh = draw_markers(points, colour, marker_size)
0475 [unique_colour, unused, colour_idx] = unique(colour, 'rows');
0476
0477 for i = 1:size(unique_colour, 1)
0478 points_idx = colour_idx == i;
0479 hh = line(points(points_idx, 1), points(points_idx, 2), ...
0480 points(points_idx, 3), ...
0481 'LineStyle', 'none', ...
0482 'Marker', 'o', 'MarkerSize', marker_size, ...
0483 'MarkerFaceColor', unique_colour(i, :), ...
0484 'MarkerEdgeColor', unique_colour(i, :));
0485 end
0486
0487 function hh = draw_edges(edges, vertices, width_data, color_data)
0488 [unique_width_color_data, unused, width_color_idx] = ...
0489 unique([width_data color_data], 'rows');
0490 for i = 1:size(unique_width_color_data, 1)
0491 if (unique_width_color_data(i, 1) > 0)
0492 edge_idx = (width_color_idx == i);
0493 points_list = [];
0494 points_list(1:3:3*size(edges(edge_idx, :), 1), :) = ...
0495 vertices(edges(edge_idx, 1), :);
0496 points_list(2:3:3*size(edges(edge_idx, :), 1), :) = ...
0497 vertices(edges(edge_idx, 2), :);
0498 points_list(3:3:3*size(edges(edge_idx, :), 1), :) = ...
0499 nan(size(edges(edge_idx, :), 1), 3);
0500 hh = line(points_list(:, 1), points_list(:, 2), ...
0501 points_list(:, 3), 'LineWidth', ...
0502 unique_width_color_data(i, 1), 'LineStyle', '-', ...
0503 'Color', unique_width_color_data(i, 2:end));
0504 end
0505 end
0506
0507 function hh = draw_triangles(faces, vertices, color_data, alpha_data, ...
0508 edge_color, edge_width)
0509
0510 if (size(color_data, 1) == 1)
0511 color_data = ones(size(faces, 1), 1)*color_data;
0512 face_color = 'flat';
0513 elseif (size(color_data, 1) == size(faces, 1))
0514 face_color = 'flat';
0515 elseif (size(color_data, 1) == size(vertices, 1))
0516 face_color = 'interp';
0517 else
0518 eidors_msg('warning: color data and mesh do not match. Showing grey', 1);
0519 color_data = 0.5*ones(size(faces, 1), 3);
0520 face_color = 'flat';
0521 end
0522
0523 if (size(alpha_data, 1) == 1)
0524 alpha_data = ones(size(faces, 1), 1)*alpha_data;
0525 face_color = 'flat';
0526 elseif (size(alpha_data, 1) == size(faces, 1))
0527 face_alpha = 'flat';
0528 elseif (size(alpha_data, 1) == size(vertices, 1))
0529 face_alpha = 'interp';
0530 else
0531 eidors_msg('warning: alpha data and mesh do not match. Showing opaque', 1);
0532 alpha_data = 1;
0533 face_alpha = 'flat';
0534 end
0535
0536 hh = patch('Faces', faces, 'Vertices', vertices, ...
0537 'AlphaDataMapping', 'none', ...
0538 'CDataMapping', 'direct', ...
0539 'FaceVertexCData', color_data, ...
0540 'FaceVertexAlphaData', alpha_data, ...
0541 'FaceColor', face_color, 'FaceAlpha', face_alpha, ...
0542 'EdgeColor', edge_color, 'FaceLighting', 'flat', ...
0543 'LineWidth', edge_width);
0544
0545 function colour = electr_colour(e, colormap_width)
0546 switch (e)
0547 case 1
0548 desired_colour = [0 .7 0];
0549 case 2
0550 desired_colour = [0 .5 0];
0551 otherwise
0552 desired_colour = [0 .3 0];
0553 end
0554
0555 switch(colormap_width)
0556 case 1
0557 map = colormap;
0558 colormap_idx = find(all(map == ones(size(map, 1), 1)* ...
0559 desired_colour, 2));
0560 if ~isempty(colormap_idx)
0561 colour = colormap_idx;
0562 else
0563 map = [map; desired_colour];
0564 colormap(map);
0565 colour = size(map, 1);
0566 end
0567 case 3
0568 colour = desired_colour;
0569 otherwise
0570 error('Invalid colormap width.');
0571 end
0572
0573 function mdl = find_sub_elements(mdl)
0574 if (~isfield(mdl, 'sub_elements'))
0575
0576 n_nodes_per_elem = size(mdl.elems, 2);
0577
0578
0579 combos= nchoosek(1:n_nodes_per_elem, n_nodes_per_elem - 1);
0580 mdl.sub_elements = sort( ...
0581 reshape(mdl.elems(:, combos')', ...
0582 n_nodes_per_elem - 1, []), ...
0583 1)';
0584
0585
0586
0587 sub_element_idx = reshape(ones(n_nodes_per_elem, 1) ...
0588 *(1:size(mdl.elems, 1)),[] , 1);
0589
0590 sub_element_other_node_idx = reshape((n_nodes_per_elem:-1:1)'...
0591 *ones(1, size(mdl.elems, 1)), [] , 1);
0592
0593 sub_element_other_node = mdl.elems(sub2ind(size(mdl.elems), sub_element_idx, sub_element_other_node_idx));
0594
0595
0596
0597
0598 [mdl.sub_elements, ia, ic] = unique(...
0599 mdl.sub_elements, 'rows');
0600
0601 sub_element_other_node = sub_element_other_node(ia, :);
0602
0603
0604
0605 mdl.element2sub_element = sparse(ic, sub_element_idx, ...
0606 ones(n_nodes_per_elem*size(mdl.elems, 1), 1));
0607
0608
0609
0610 mdl.element2sub_element = spdiags(1./sum(...
0611 mdl.element2sub_element, 2), ...
0612 0, size(mdl.sub_elements, 1), ...
0613 size(mdl.sub_elements, 1))*mdl.element2sub_element;
0614
0615
0616 mdl.boundary = mdl.sub_elements;
0617 boundary_other_node = sub_element_other_node;
0618 mdl.boundary_to_sub_element_idx = (1:size(mdl.sub_elements, 1))';
0619
0620 sorted_ic = sort(ic);
0621
0622 mdl.boundary(sorted_ic(diff(sorted_ic) == 0), :) = [];
0623 boundary_other_node(sorted_ic(diff(sorted_ic) == 0), :) = [];
0624 mdl.boundary_to_sub_element_idx(sorted_ic(diff(sorted_ic) == 0)) = [];
0625
0626 if (size(mdl.boundary, 2) == 3)
0627
0628 Node1 = mdl.nodes(mdl.boundary(:, 1), :);
0629 Node2 = mdl.nodes(mdl.boundary(:, 2), :);
0630 Node3 = mdl.nodes(mdl.boundary(:, 3), :);
0631 Node4 = mdl.nodes(boundary_other_node, :);
0632 mdl.boundary_normal_vector = cross(Node1 - Node2, ...
0633 Node3 - Node2, 2);
0634
0635
0636 norm = 1./sqrt(sum(mdl.boundary_normal_vector ...
0637 .*mdl.boundary_normal_vector, 2));
0638 mdl.boundary_normal_vector = mdl.boundary_normal_vector ...
0639 .*[norm norm norm];
0640
0641
0642 normal_vector_idx = dot(mdl.boundary_normal_vector, ...
0643 Node4 - Node2, 2) > 0;
0644 mdl.boundary_normal_vector(normal_vector_idx, :) = ...
0645 -mdl.boundary_normal_vector(normal_vector_idx, :);
0646
0647
0648 mdl.boundary_edges = sort(reshape(mdl.boundary(:, ...
0649 nchoosek(1:3, 2)')', 2, []), 1)';
0650
0651
0652
0653 sub_boundary_edges_idx = reshape(ones(3, 1) ...
0654 *(1:size(mdl.boundary, 1)), [] , 1);
0655
0656 [mdl.boundary_edges, sorted_idx] = sortrows(mdl.boundary_edges);
0657
0658 mdl.boundary_edges = mdl.boundary_edges(1:2:end, :);
0659
0660 mdl.edge2boundary = reshape(sub_boundary_edges_idx(...
0661 sorted_idx), 2, [])';
0662 end
0663
0664
0665 if (isfield(mdl, 'electrode'))
0666 for i = 1:numel(mdl.electrode)
0667 mdl.electrode(i).boundary = find(all(ismember(...
0668 mdl.boundary, mdl.electrode(i).nodes), 2));
0669 mdl.electrode(i).sub_elements = ...
0670 mdl.boundary_to_sub_element_idx( ...
0671 mdl.electrode(i).boundary);
0672
0673
0674 if (isfield(mdl, 'boundary_edges'))
0675 edge_candidates = sum(ismember(mdl.edge2boundary, ...
0676 mdl.electrode(i).boundary), 2);
0677 mdl.electrode(i).boundary_inner_edges = find(...
0678 edge_candidates == 2);
0679 mdl.electrode(i).boundary_outer_edges = find(...
0680 edge_candidates == 1);
0681 end
0682 end
0683 end
0684 end
0685
0686 function dest_struct = copy_field(dest_struct, src_struct, parent_field_name, child_field_name)
0687 if (isfield(src_struct, parent_field_name) && ...
0688 isfield(dest_struct, parent_field_name) && ...
0689 isfield(src_struct.(parent_field_name), child_field_name))
0690 dest_struct.(parent_field_name).(child_field_name) = ...
0691 src_struct.(parent_field_name).(child_field_name);
0692 end
0693
0694
0695 function do_unit_test
0696 ver= eidors_obj('interpreter_version');
0697 clf
0698
0699 img=calc_jacobian_bkgnd(mk_common_model('a2c0',8));
0700 img.elem_data= 3*sin(linspace(-2,2,num_elems(img))');
0701 subplot(3,4,1); show_fem(img.fwd_model,[0,0,1])
0702 title('regular mesh numbered');
0703
0704 if ~ver.isoctave
0705 imgn = rmfield(img,'elem_data');
0706 imgn.node_data= 3*sin(linspace(-5,5,num_nodes(img))');
0707 subplot(3,4,9); show_fem(imgn)
0708 title('interpolated node colours');
0709 end
0710
0711 img2(1) = img; img2(2) = img;
0712 subplot(3,4,2); show_fem(img,[1]);
0713 title('colours with legend');
0714 subplot(3,4,3); show_fem(img2,[0,1]);
0715 title('colours with legend');
0716 img.calc_colours.mapped_colour = 0;
0717 subplot(3,4,4); show_fem(img,[0,1,1]);
0718 title('RGB colours');
0719 subplot(3,4,4); show_fem(img);
0720 title('RGB colours');
0721
0722 img.elem_data = [1:10];
0723 subplot(3,4,12);show_fem(img);
0724 title('error -> show grey');
0725
0726 if ~ver.isoctave
0727 imgn.calc_colours.mapped_colour = 0;
0728 subplot(3,4,10);show_fem(imgn,[0,1])
0729 title('interpolated node colours');
0730
0731
0732 subplot(3,4,11);hh=show_fem(imgn); set(hh,'EdgeColor',[0,0,1]);
0733 title('with edge colours');
0734
0735 end
0736
0737 img3=calc_jacobian_bkgnd(mk_common_model('n3r2',[16,2]));
0738 img3.elem_data= randn(828,1);
0739 subplot(3,4,5); show_fem(img3.fwd_model)
0740 subplot(3,4,6); show_fem(img3,[1])
0741 subplot(3,4,7); show_fem(img3,[1,1])
0742 subplot(3,4,8); show_fem(img3,[1,1,1])