📄 srf_combine.m
字号:
function [nfile1, nfile2] = srf_Combine(hfile, hfile2, cbopt)
% SRF::Combine - combines two SRFs into one
%
% FORMAT: [csrf [, csmp]] = srf1.Combine(srf2, cbopt);
%
% Input fields:
%
% srf2 surface to use to combine given SRF with
% cbopt struct with mandatory field
% .type one of
% 'backtoback' - rotate one mesh 180 in XY plane
% 'custom' - build custom scene, see below
% 'gapped' - join contents with a gap
% 'wholebrain' - simply join contents
% and optional fields
% .color1 1x4 double for .Color1 field in SRF options
% .color2 1x4 double for .Color2 field in SRF options
% .filename store combined under new filename
% .gap 1x1 double, mm to insert between two meshes
% (applied for all types accordingly, defaults:
% backtoback: 25, gapped: 100, outandin: 20,
% outintb: 25, patched: 25, spm2: 25, wholebrain: 0)
% .linkedmtc filename of linked MTC, set to empty if not given
% .smp1 BVQXfile object representing the SMP for the first and
% .smp2 the second Surface MaP object for the given SRFs
% .transform 1x2 cell array with 4x4 double transformation matrices,
% needed for custom scenaries
%
% Output fields:
%
% csrf combined SRF
% csmp combined SMP (if given in cbopt)
% Version: v0.7b
% Build: 7090215
% Date: Sep-02 2007, 3:54 PM CEST
% Author: Jochen Weber, Brain Innovation, B.V., Maastricht, NL
% URL/Info: http://wiki.brainvoyager.com/BVQXtools
% check arguments
if nargin < 3 || ...
numel(hfile) ~= 1 || ...
numel(hfile2) ~= 1 || ...
~isBVQXfile(hfile, 'srf') || ...
~isBVQXfile(hfile2, 'srf') || ...
~isstruct(cbopt) || ...
numel(cbopt) ~= 1 || ...
~isfield(cbopt, 'type') || ...
~ischar(cbopt.type)
error( ...
'BVQXfile:BadArguments', ...
'Invalid call to %s.', ...
mfilename ...
);
end
bc1 = bvqxfile_getcont(hfile.L);
bc2 = bvqxfile_getcont(hfile2.L);
% argument check
tavail = {'backtoback', 'custom', 'gapped', 'outandin', 'outintb', 'spm2', 'wholebrain'};
if ~any(strcmpi(cbopt.type, tavail))
error( ...
'BVQXtools:BadArgument', ...
'Bad argument in call.' ...
);
end
if isfield(cbopt, 'smp1') && ...
isfield(cbopt, 'smp2') && ...
numel(cbopt.smp1) == 1 && ...
numel(cbopt.smp2) == 1 && ...
isBVQXfile(cbopt.smp1, 'smp') && ...
isBVQXfile(cbopt.smp2, 'smp')
smpin = true;
sbc1 = bvqxfile_getcont(cbopt.smp1.L);
sbc2 = bvqxfile_getcont(cbopt.smp2.L);
if sbc1.NrOfVertices ~= bc1.NrOfVertices || ...
sbc2.NrOfVertices ~= bc2.NrOfVertices || ...
numel(sbc1.Map) ~= numel(sbc2.Map)
error( ...
'BVQXfile:BadArgument', ...
'NrOfVertices and NrOfMaps must match.' ...
);
end
nfile2 = aft_CopyObject(cbopt.smp1);
sfile2 = bvqxfile_getscont(nfile2.L);
sfile2.F = '';
else
smpin = false;
end
nfile1 = aft_CopyObject(hfile);
sfile1 = bvqxfile_getscont(nfile1.L);
sfile1.F = '';
% check some more things for custom type
cbtype = lower(cbopt.type);
if strcmp(cbtype, 'custom')
if ~isfield(cbopt, 'transform') || ...
~iscell(cbopt.transform) || ...
numel(cbopt.transform) ~= 2
bvqxfile_clear(nfile1.L);
bvqxfile_clear(nfile2.L);
error( ...
'BVQXtools:BadArgument', ...
'Missing or bad transformation matrices for input SRF''s.' ...
);
end
try
if ~all(size(cbopt.transform{1}) == 4)
srf_t1 = tfmatrix(cbopt.transform{1});
else
srf_t1 = cbopt.transform{1}(:,:,1);
end
if ~all(size(cbopt.transform{2}) == 4)
srf_t2 = tfmatrix(cbopt.transform{2});
else
srf_t2 = cbopt.transform{2}(:,:,1);
end
catch
bvqxfile_clear(nfile1.L);
bvqxfile_clear(nfile2.L);
error( ...
'BVQXtools:BadArgument', ...
'Bad transformation matrix for input SRF %d.', ...
tc ...
);
end
end
if isfield(cbopt, 'color1') && ...
isa(cbopt.color1, 'double') && ...
numel(cbopt.color1) == 4 && ...
~any(isnan(cbopt.color1(:)) | isinf(cbopt.color1(:)) | ...
cbopt.color1(:) < 0 | cbopt.color1(:) > 1)
sfile1.C.ConvexColor = cbopt.color1(:)';
end
if isfield(cbopt, 'color2') && ...
isa(cbopt.color2, 'double') && ...
numel(cbopt.color2) == 4 && ...
~any(isnan(cbopt.color2(:)) | isinf(cbopt.color2(:) | ...
cbopt.color2(:) < 0 | cbopt.color2(:) > 1))
sfile1.C.ConcaveColor = cbopt.color2(:)';
end
if ~isfield(cbopt, 'gap') || ...
~isa(cbopt.gap, 'double') || ...
numel(cbopt.gap) ~= 1 || ...
isnan(cbopt.gap) || ...
isinf(cbopt.gap) || ...
cbopt.gap < -512 || ...
cbopt.gap > 512
cbopt.gap = [];
end
if isfield(cbopt, 'linkedmtc') && ...
ischar(cbopt.linkedmtc) && ...
~isempty(cbopt.linkedmtc)
sfile1.C.AutoLinkedMTC = cbopt.linkedmtc(:)';
end
if smpin
for mc = 1:numel(sbc1.Map)
sfile2.C.Map(mc).SMPData = [sbc1.Map(mc).SMPData; sbc2.Map(mc).SMPData];
end
sfile2.C.NrOfVertices = size(sfile2.C.Map(1).SMPData, 1);
bvqxfile_setscont(nfile2.L, sfile2);
end
% get coordinates, etc.
srf_p1 = bc1.VertexCoordinate;
srf_n1 = bc1.VertexNormal;
srf_np1 = size(srf_p1, 1);
srf_nt1 = size(bc1.TriangleVertex, 1);
srf_p2 = bc2.VertexCoordinate;
srf_n2 = bc2.VertexNormal;
srf_np2 = size(srf_p2, 1);
srf_nt2 = size(bc2.TriangleVertex, 1);
% summary
srf_np = srf_np1 + srf_np2;
srf_nt = srf_nt1 + srf_nt2;
% wholebrain is special (zero) gap case
if strcmp(cbtype, 'wholebrain')
if isempty(cbopt.gap), cbopt.gap = 0; end
cbtype = 'gapped';
end
% for new center
cpos = (bc1.MeshCenter + bc2.MeshCenter) / 2;
% which type
switch cbtype, case {'backtoback'}
if isempty(cbopt.gap)
cbopt.gap = 25;
end
srf_p1(:, 2) = srf_p1(:, 2) - min(srf_p1(:, 2)) + cbopt.gap / 2;
srf_p2(:, 2) = srf_p2(:, 2) - min(srf_p2(:, 2)) + cbopt.gap / 2;
srf_p2(:, 1:2) = -srf_p2(:, 1:2);
srf_n2(:, 1:2) = -srf_n2(:, 1:2);
cpos = [256, 128, 128];
case {'custom'}
% prepare points and normals matrices
srf_p1(:, 4) = 1;
srf_p2(:, 4) = 1;
% apply transformation matrices to points and normals
srf_p1 = (srf_t1 * srf_p1')';
srf_n1 = (srf_t1(1:3, 1:3) * srf_n1')';
srf_p2 = (srf_t2 * srf_p2')';
srf_n2 = (srf_t2(1:3, 1:3) * srf_n2')';
% remove fourth coordinate again
srf_p1(:, 4) = [];
srf_p2(:, 4) = [];
case {'gapped'}
if isempty(cbopt.gap)
cbopt.gap = 100;
end
srf_p1(:, 3) = srf_p1(:, 3) - cbopt.gap / 2;
srf_p2(:, 3) = srf_p2(:, 3) + cbopt.gap / 2;
end
% build neighbors and triangle strip lists
neigh = [bc1.Neighbors; bc2.Neighbors];
for nc = (srf_np1 + 1):srf_np
neigh{nc, 2} = neigh{nc, 2} + srf_np1;
end
trist = bc2.TriangleStripSequence;
rtrist = (trist > 0);
trist(rtrist) = trist(rtrist) + srf_np1;
% set fields correctly
sfile1.C.NrOfVertices = srf_np;
sfile1.C.NrOfTriangles = srf_nt;
sfile1.C.VertexCoordinate = [srf_p1; srf_p2];
sfile1.C.VertexNormal = [srf_n1; srf_n2];
sfile1.C.MeshCenter = cpos;
sfile1.C.VertexColor = [bc1.VertexColor; bc2.VertexColor];
sfile1.C.Neighbors = neigh;
sfile1.C.TriangleVertex = [bc1.TriangleVertex; (bc2.TriangleVertex + srf_np1)];
sfile1.C.TriangleStripSequence = [bc1.TriangleStripSequence; trist];
sfile1.C.NrOfTriangleStrips = numel(sfile1.C.TriangleStripSequence);
bvqxfile_setscont(nfile1.L, sfile1);
% write output?
if isfield(cbopt, 'filename') && ...
ischar(cbopt.filename) && ...
~isempty(cbopt.filename)
try
aft_SaveAs(nfile1, cbopt.filename);
if smpin && ...
numel(cbopt.filename) > 4 && ...
strcmpi(cbopt.filename(end-3:end), '.srf')
aft_SaveAs(nfile2, [cbopt.filename(1:end-4) '.smp']);
end
catch
warning( ...
'BVQXfile:ErrorWritingFile', ...
'Couldn''t write new SRF/SMP file: ''%s''.', ...
cbopt.filename ...
);
end
end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -