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