Mercurial > hg > human-echolocation
changeset 0:90220f7249fc
Initial commit
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/pick_ir.m Sat Nov 16 18:25:24 2013 +0000 @@ -0,0 +1,34 @@ +function picked_ir = pick_ir(simdata, dist, azim, orient, dirweight) +%Picks a 2-row matrix of binaural responses for specified geometry and source directivity from simulated_echo.m output +% +% - simdata input argument must be a structure as outputed from simulate_echo.m +% - dist input argument must be the distance in meters +% - azim input argument must be the azimuthal angle of the board center in degrees with 0 corresponding to dead front, +% positive values to left and negative values to right +% - orient input argument must be either 'horz' or 'angled' +% - dirweight input argument must be a nonnegative real scalar determining what is the relative weight of the emission path +% to the echo path (i.e. due to directivity focus in the frontal direction of the source, the emission which is directed +% upwards and backwards in our specific geometry is significantly attenuated, typically by factor in the vicinity of 0.1) +% +% picked_ir output is a 2-row matrix of binaural responses (left ear in the top row and right ear in the bottom row) +% +% If any of the specified dist, azim, orient values are not among the cases included in the specified simdata stucture, +% then an error is returned. +% +% picked_ir = pick_ir(simdata, dist, azim, orient, dirweight) +% + +dist_ind = find(dist == simdata.params.board_dist); +azim_ind = find(mod(90+azim,360)*pi/180 == simdata.params.board_azim); +orient_ind = find(strcmp(orient,simdata.params.board_orientation)); + +try + dist_ind = dist_ind(1); + azim_ind = azim_ind(1); + orient_ind = orient_ind(1); +catch %#ok<CTCH> + error('at least on of specified distance, azimuth, orientation does not exist in this dataset') +end + +picked_ir = dirweight*simdata.emission{dist_ind,azim_ind,orient_ind} + simdata.echo{dist_ind,azim_ind,orient_ind}; +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/private/Contents.m Sat Nov 16 18:25:24 2013 +0000 @@ -0,0 +1,69 @@ +% Edge diffraction toolbox +% Version EDB11 15-Apr-2012 +% +% From version EDB11, all functions will start EDB11 rather than EDB1. The 1 will indicate +% version number. +% +% Main programs +% EDB1main - Calculates the specular and edge diffraction IRs and saves them in files. +% +% Read CAD file and geometry pre-processing +% EDB1readsetup - Runs the EDsetup m-file and saves all the settings in a mat-file. +% EDB1readcad - Reads a file of type .CAD and saves all the geometry data in a mat-file. +% EDB1readac - EDB1readac - Reads a file of type .AC (made by e.g. Invis AC3D) and saves all the geometry data in a mat-file. +% EDB1ed2geox - Calculates 2nd- and higher-order edge-related geom. parameters. +% EDB1edgeox - Calculates some plane- and edge-related geometrical parameters. +% EDB1SorRgeo - Calculates some source- or receiver-related geometrical parameters. +% +% Find sound paths +% EDB1findpathsISESx - Finds all possible paths that include direct sound, specular, diffraction. +% EDB1diff2ISES - Gives list of paths that includes a 2nd-order diff. combination. +% EDB1diffISESx - Gives list of paths that includes a 1st-order diff. combination. +% EDB1diffNISES - Gives list of paths that includes an N-order diff. combination. +% EDB1directsound - Checks if the direct sound is valid. +% EDB1findISEStree - Constructs a list ("an ISES tree") of all possible specular-diffraction combinations. +% EDB1findis - Returns the image source coordinates. +% EDB1checkobstrpaths - Checks obstruction for a list of paths, or check if specular reflections are valid. +% EDB1checkobstr_pointtoedge - Checks obstruction for a list of point-to-edge paths. +% EDB1checkobstr_edgetoedge - Checks obstruction for a list of edge-to-edge paths. +% EDB1chkISvisible - Checks if paths from a set of IS to a set of R pass through their refl. planes. +% EDB1chkISvisiblex - Checks if paths from a set of IS to a set of R pass through their refl. planes. Extended version. +% EDB1getedgepoints - Calculates a number of edge coordinates. +% EDB1infrontofplane - Checks if a point is in front of, in plane with, or behind a list of planes. +% EDB1poinpla - Detects if one or more points are inside a number of finite planes. +% EDB1poinplax - Detects if one or more points are inside a number of finite planes. Extended version. +% EDB1speculISES - Finds the valid specular reflections by checking visibility and obstruction. +% +% Create impulse responses +% EDB1makeirs - Constructs IRs from a list of paths in an edpathsfile. +% EDB1betaoverml - Integrand function which is called for num. int. of ED IR. +% EDB1irfromslotlist - Creates an IR from a list of sample numbers and amplitudes +% EDB1wedge1st_int - Computes the 1st-order diffraction impulse response. +% EDB1wedge2nd - Computes the second-order diffraction impulse responses. +% EDB1wedgeN - Computes the Nth-order diffraction impulse responses. +% EDB1quadstep - Recursive numerical integration routine for EDB1wedge1st_int. +% +% Various plot functions +% EDB1makemovie - Makes a movie based on IRs. +% EDB1makesnapshot - Makes a snapshot of a sound field based on IRs. +% EDB1plotmodel - Plots a model which is given in an eddatafile. +% EDB1plotstackedIRs - Plots a number of IRs in a stacked way. +% EDB1plotstackedTFs - Plots a number of TFs in a stacked way. +% EDB1plotpath - Plots a model which is given in an eddatafile and one or more of the paths in an edreflpathsfile. +% +% Various string functions +% EDB1extrnums - Extracts the numerical values in a text-string, separated by a given delimiter. +% EDB1fistr - Reads a text file, line by line, until a given textstring is found. +% EDB1myvalueinput - Prints a text on the screen and waits for a numerical to be input. +% EDB1strpend - Removes a specified ending from a filename. +% +% Various numerical functions +% EDB1calcdist - Gives distances between sets of points in 3D space. +% EDB1compress7 - +% EDB1coordtrans1 - Transforms one set of cartesian coordinates to edge-related cylindrical coordinates. +% EDB1coordtrans2 - Transforms two sets of cartesian coordinates to edge-related cylindrical coordinates. +% EDB1creindexmatrix - Creates a matrix with index numbers. +% EDB1cross - Stripped down version of Matlab's built in function cross. +% +% Function for editing paths +% EDB1editpathlist - Does some semi-automatic editing of an edpathsfile.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/private/EDB1SorRgeo.m Sat Nov 16 18:25:24 2013 +0000 @@ -0,0 +1,961 @@ +function outputfile = EDB1SorRgeo(eddatafile,outputfile,pointcoords,typeofcoords,difforder,nedgesubs) +% EDB1SorRgeo - Calculates some source- or receiver-related geometrical parameters. +% Calculates some source- or receiver-related geometrical parameters +% based on corners,edges and planes in an eddata-file +% and on a list of source/receiver coordinates. +% The output is saved in a .mat-file. +% +% Input parameters: +% eddatafile (optional) The .mat file with the corner,edge and plane data. +% If it is not specified, a file opening window is presented. +% outputfile (optional) The .mat file where the output data will be stored. +% If it is not specified, an automatic file name is constructed +% using the same filename stem as the eddatafile, but ending with '_srdata'. +% pointcoords Matrix, [nrec,3], of source or receiver coordinates. +% typeofcoords 'S' or 'R' - specifying if the point coordinates are sources +% or receivers. This determines what the output data in the output +% file will be called. +% difforder The highest order of diffraction that will be calculated. +% nedgesubs (optional) The number of subdivisions that each edge will be +% subdivided into for visibility/obstruction tests. Default: 2 +% NB! When nedgesubs = 2, the two end points will be checked. +% SHOWTEXT (global) An integer value; if it is 4 or higher, then messages will be printed on the +% screen during calculations. +% Output parameters: +% outputfile The name of the outputfile, generated either automatically or specified as +% an input parameter. +% +% Data in the outputfile: +% sources/receivers (renamed) copy of the input parameter 'pointcoords' +% visplanesfroms/visplanesfromr Matrix, [nplanes,nsources]/[nplanes/nreceivers] +% with integer values 0-5: +% 0 means S/R behind a plane which is reflective or totabs +% 1 means S/R is aligned with a plane, but outside it +% 2 means S/R is in front of a plane which is reflective +% 3 means S/R is in front of a plane which is totabs +% 4 means S/R is inside a plane which is reflective +% 5 means S/R is inside a plane which is totabs +% vispartedgesfroms/vispartedgesfromr Matrix, [nedges,nsources]/[nedges/nreceivers] +% with integer values 0-2^nedgesubs-1 indicating +% part-visibility of the edge. +% soutsidemodel/routsidemodel List, [nsources,1]/[nreceivers,1], with values +% 1 or 0 indicating whether the S/R is outside (1) +% the model or not (0). +% NB! Only simple tests are done, so an S/R could still +% be outside the model even if the value here is 0. +% +% NB! The text on the screeen, and in the code refers to 'R' or 'receivers' but it should be S or R. +% +% Uses the functions EDB1strpend, EDB1infrontofplane, EDB1poinpla, +% EDB1getedgepoints, EDB1checkobstr_pointtoedge +% +% ---------------------------------------------------------------------------------------------- +% This file is part of the Edge Diffraction Toolbox by Peter Svensson. +% +% The Edge Diffraction Toolbox is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) any later version. +% +% The Edge Diffraction Toolbox is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +% FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License along with the +% Edge Diffraction Toolbox. If not, see <http://www.gnu.org/licenses/>. +% ---------------------------------------------------------------------------------------------- +% Peter Svensson (svensson@iet.ntnu.no) 060601 +% +% outputfile = EDB1SorRgeo(eddatafile,outputfile,pointcoords,typeofcoords,difforder,nedgesubs); + +global SHOWTEXT + +geomacc = 1e-10; + +if nargin < 6 + nedgesubs = 2; + if nargin < 4 + error('ERROR: The input parameter pointcoords must be specified') + end +else + if isempty(nedgesubs), nedgesubs = 2; end +end + +typeofcoords = lower(typeofcoords(1)); +if typeofcoords~='r' & typeofcoords~='s' + error(['ERROR: The input parameter typeofcoords must have the value S or R']) +end + +%--------------------------------------------------------------- +% If no eddatafile was specified, present a file opening window + +if exist('eddatafile')~=1 + eddatafile = ''; +end +if isempty(eddatafile) + [eddatafile,filepath] = uigetfile('*.mat','Please select the eddatafile'); + [filepath,temp1,temp2] = fileparts(filepath); + if ~isstr(eddatafile) + return + end + [temp1,filestem,temp2] = fileparts(eddatafile); + eddatafile = [[filepath,filesep],filestem,'.mat']; +else + [filepath,filestem,fileext] = fileparts(eddatafile); + eddatafile = [[filepath,filesep],filestem,'.mat']; +end + + +%--------------------------------------------------------------- +% If no output file was specified, construct an automatic file name + +if exist('outputfile')~=1 + outputfile = ''; +end +if isempty(outputfile) + filestem = EDB1strpend(filestem,'_eddata'); + outputfile = [[filepath,filesep],filestem,'_rdata.mat']; +end + +%--------------------------------------------------------------- + +eval(['load ',eddatafile]) +clear cornerinfrontofplane + +[ncorners,slask] = size(corners); +[nplanes,slask] = size(planecorners); +maxncornersperplane = double(max(ncornersperplanevec)); +[nedges,slask] = size(edgecorners); +[nreceivers,slask] = size(pointcoords); + +[n1,n2] = size(canplaneobstruct); +if n2>1 + canplaneobstruct = canplaneobstruct.'; +end + +totalmodelmin = min(minvals); +totalmodelmax = max(maxvals); + +zerosvecE1 = zeros(nedges,1); +zerosvec1P = zeros(1,nplanes); +onesvec1R = uint8(ones(1,nreceivers)); +onesvec1ES = ones(1,nedgesubs); +onesvecP1 = ones(nplanes,1); +onesvec1Max = ones(1,maxncornersperplane); + +%################################################################## +%################################################################## +%################################################################## +% +% PLANE RELATED PARAMETERS +% +%################################################################## + +activeplanelist = find(reflfactors ~= 0); +totabsplanelist = find(reflfactors == 0); +ntotabsplanes = length(totabsplanelist); +nthinplanes = length(find(planeisthin)); + +if SHOWTEXT >= 3 + if lower(typeofcoords(1)) == 'r' + disp(' Checking visible planes from R') + else + disp(' Checking visible planes from S') + end +end + +%-------------------------------------------------------------- +% +% visplanesfromr [nplanes,nrec] uint8 +% +% 0 means S/R behind a plane which is reflective or totabs +% 1 means S/R is aligned with a plane +% 2 means S/R is in front of a plane which is reflective +% 3 means S/R is in front of a plane which is totabs +% 4 means S/R is inside a plane which is reflective +% 5 means S/R is inside a plane which is totabs +% +% We can call EDB1infrontofplane with a single call by extracting receiver +% numbers and plane numbers for the [nplanes,nsources] matrix. +% +% EDB1infrontofplane returns -1 for behind, 0 for in-plane with and 1 for in +% front of so if we add the value 1 we get close to the final value we want +% to have. Another modification is to give totabs planes the value 3 +% instead of 2. A last modification is to find which S/R are inside the +% plane. + +iv = [1:nplanes*nreceivers].'; +if nreceivers < 256 + colnumb = uint8(ceil(iv/nplanes)); % This is the receiver number +elseif nreceivers < 65536 + colnumb = uint16(ceil(iv/nplanes)); % This is the receiver number +else + colnumb = uint32(ceil(iv/nplanes)); % This is the receiver number +end +if nplanes < 256 + rownumb = uint8(iv - (double(colnumb)-1)*nplanes); % This is the plane number +elseif nplanes < 65536 + rownumb = uint16(iv - (double(colnumb)-1)*nplanes); % This is the plane number +else + rownumb = uint32(iv - (double(colnumb)-1)*nplanes); % This is the plane number +end +clear iv +visplanesfromr = EDB1infrontofplane(pointcoords(colnumb,:),planenvecs(rownumb,:),corners(planecorners(rownumb,1),:),corners(planecorners(rownumb,2),:)) + 1; +clear rownumb colnumb + +if ntotabsplanes > 0 + colvec = [0:nreceivers-1]*nplanes; + iv = uint32(totabsplanelist(:,onesvec1R) + colvec(ones(ntotabsplanes,1),:)); + visplanesfromr(iv) = uint8(visplanesfromr(iv) + (visplanesfromr(iv)==2)); + clear iv colvec + visplanesfromr = uint8(visplanesfromr); +end + +% For all the planes that the S/R are aligned with +% check if the S/R is inside or outside the plane. +% +% We can call EDB1poinpla with a single call by extracting S/R coordinates +% (=colnumb) and planenumbers (=rownumb). + +ivec_visR1 = find(visplanesfromr==1); +if ~isempty(ivec_visR1) + if nreceivers < 256 + colnumb = uint8(ceil(ivec_visR1/nplanes)); % This is the receiver number + elseif nreceivers < 65536 + colnumb = uint16(ceil(ivec_visR1/nplanes)); % This is the receiver number + else + colnumb = uint32(ceil(ivec_visR1/nplanes)); % This is the receiver number + end + if nplanes < 256 + rownumb = uint8(ivec_visR1 - (double(colnumb)-1)*nplanes); % This is the plane number + elseif nplanes < 65536 + rownumb = uint16(ivec_visR1 - (double(colnumb)-1)*nplanes); % This is the plane number + else + rownumb = uint32(ivec_visR1 - (double(colnumb)-1)*nplanes); % This is the plane number + end + hitvec = find(EDB1poinpla(pointcoords(colnumb,:),rownumb,minvals,maxvals,planecorners,corners,ncornersperplanevec,planenvecs)); + if ~isempty(hitvec) + visplanesfromr(ivec_visR1(hitvec)) = uint8(ones(size(hitvec))*4); + if ntotabsplanes > 0 + insidetotabsplane = (reflfactors(rownumb(hitvec))==0); + ivec2 = find(insidetotabsplane); + if ~isempty(ivec2) + visplanesfromr(ivec_visR1(hitvec(ivec2))) = uint8(ones(size(hitvec(ivec2)))*5); + end + end + ivec_visR1(hitvec) = []; + if nthinplanes > 0 + insidethinplane = planeisthin(rownumb(hitvec)); + ivec2 = find(insidethinplane); + if ~isempty(ivec2) + recinthinplane = colnumb(hitvec(ivec2)); + thinplanenumber = rownumb(hitvec(ivec2)); + error(['ERROR: R number ',int2str(double(recinthinplane(:).')),' has been placed exactly on the thin plane ',int2str(double(thinplanenumber(:).')),... + ' so it is undefined which side of the plane the R is. Move the R a short distance away']) + end + end + end +end + +visplanesfromr = reshape(visplanesfromr,nplanes,nreceivers); + +%-------------------------------------------------------------- +% +% routsidemodel (0 or 1, size [1,nrec]) +% +% We make a simple check: if the S/R is outside the big cube defined by all +% the planes, and we have an interior problem, then S/R must be outside the +% model. + +routsidemodel = uint8(zeros(1,nreceivers)); +if int_or_ext_model == 'i' + ivec = find(pointcoords(:,1)<totalmodelmin(1) | pointcoords(:,2)<totalmodelmin(2) | pointcoords(:,3)<totalmodelmin(3) | ... + pointcoords(:,1)>totalmodelmax(1) | pointcoords(:,2)>totalmodelmax(2) | pointcoords(:,3)>totalmodelmax(3)); + if ~isempty(ivec) + routsidemodel(ivec) = ones(size(ivec)); + end + routsidemodel = uint8(routsidemodel); + + % If we have a convex model, then the obstruction check is turned off + % so we must check here if the source/receiver is inside. + if sum(closwedangvec<pi) == 0 + + nplanesvisible = sum(sign(visplanesfromr)); + ivec = find(nplanesvisible < nplanes); + if ~isempty(ivec) + routsidemodel(ivec) = ones(size(ivec)); + end + end +end + +%################################################################## +%################################################################## +%################################################################## +% +% EDGE RELATED PARAMETERS +% +%################################################################## + +if difforder == 0 + if typeofcoords=='r' + vispartedgesfromr = []; + receivers = pointcoords; + Varlist = [' visplanesfromr receivers ']; + Varlist = [Varlist,' vispartedgesfromr routsidemodel ']; + eval(['save ',outputfile,Varlist]) + return + else + vispartedgesfroms = []; + sources = pointcoords; + visplanesfroms = visplanesfromr; + soutsidemodel = routsidemodel; + Varlist = [' visplanesfroms sources ']; + Varlist = [Varlist,' vispartedgesfroms soutsidemodel ']; + eval(['save ',outputfile,Varlist]) + return + end +end + +closwedlargerthanpi = closwedangvec>pi; +closwedsmallerthanpi = closwedangvec<pi; + +if SHOWTEXT >= 3 + if lower(typeofcoords(1)) == 'r' + disp(' Checking which edges are seen from R') + else + disp(' Checking which edges are seen from S') + end +end + +nbigcombs = nplanes*nreceivers; + +%-------------------------------------------------------------- +% +% visedgesfromr [nedges,nrec] uint8 +% +% 6 Edge belongs to a plane which is aligned with R and thin and +% rigid (but R is not inside the plane) +% 5 Edge belongs to a plane which is aligned with R and not thin +% +% These can be derived from the cases where visplanesfromr = 1 + +visedgesfromr = uint8(ones(nedges,nreceivers)); + +if ~isempty(ivec_visR1) + if nreceivers < 256 + colnumb = uint8(ceil(ivec_visR1/nplanes)); % This is the receiver number + elseif nreceivers < 65536 + colnumb = uint16(ceil(ivec_visR1/nplanes)); % This is the receiver number + else + colnumb = uint32(ceil(ivec_visR1/nplanes)); % This is the receiver number + end + if nplanes < 256 + rownumb = uint8(ivec_visR1 - (double(colnumb)-1)*nplanes); % This is the plane number + elseif nplanes < 65536 + rownumb = uint16(ivec_visR1 - (double(colnumb)-1)*nplanes); % This is the plane number + else + rownumb = uint32(ivec_visR1 - (double(colnumb)-1)*nplanes); % This is the plane number + end + + % Divide these lists into two categories: thin planes and non-thin + % planes. + + iv2 = find(planeisthin(rownumb)); + if ~isempty(iv2) + colnumb_thin = colnumb(iv2); + rownumb_thin = rownumb(iv2); + colnumb(iv2) = []; + rownumb(iv2) = []; + else + colnumb_thin = []; + rownumb_thin = []; + end + + if ~isempty(colnumb) + % Select all the edges that are connected to these planes + + if nedges < 256 + edgeselection = uint8(edgesatplane(rownumb,1:maxncornersperplane)); + elseif nedges < 65536 + edgeselection = uint16(edgesatplane(rownumb,1:maxncornersperplane)); + else + edgeselection = uint32(edgesatplane(rownumb,1:maxncornersperplane)); + end + if length(rownumb) > 1 + maxcols = sum(sign(sum(double(edgeselection)))); + else + maxcols = sum(sign(double(edgeselection))); + end + edgeselection = edgeselection(:,1:maxcols); + colnumb = colnumb(:,ones(1,maxcols)); + + indexvec = uint32(double(edgeselection) + (double(colnumb)-1)*nedges); + indexvec(find(edgeselection==0)) = []; + + visedgesfromr(indexvec) = uint8(5*ones(size(indexvec))); + + end + + if ~isempty(colnumb_thin) + % Select all the edges that are connected to these planes + + if nedges < 256 + edgeselection = uint8(edgesatplane(rownumb_thin,1:maxncornersperplane)); + elseif nedges < 65536 + edgeselection = uint16(edgesatplane(rownumb_thin,1:maxncornersperplane)); + else + edgeselection = uint32(edgesatplane(rownumb_thin,1:maxncornersperplane)); + end + if length(rownumb_thin) > 1 + maxcols = sum(sign(sum(edgeselection))); + else + maxcols = sum(sign(edgeselection)); + end + edgeselection = edgeselection(:,1:maxcols); + colnumb_thin = colnumb_thin(:,ones(1,maxcols)); + + indexvec = uint32(double(edgeselection) + (double(colnumb_thin)-1)*nedges); + indexvec(find(edgeselection==0)) = []; + + visedgesfromr(indexvec) = uint8(6*ones(size(indexvec))); + end +end + +% 4 Edge belongs to a plane which the S/R is inside +% and the plane is totabs +% 3 Edge belongs to a plane which the S/R is inside +% and the plane has indents +% 2 Edge belongs to a plane which the S/R is inside +% and the plane has no indents +% +% These can be derived from the cases where visplanesfromr = 4 and 5 + +ivec = find(visplanesfromr==5); +if ~isempty(ivec) + colnumb = ceil(ivec/nplanes); % This is the receiver number + if nreceivers < 256 + colnumb = uint8(ceil(ivec/nplanes)); % This is the receiver number + elseif nreceivers < 65536 + colnumb = uint16(ceil(ivec/nplanes)); % This is the receiver number + else + colnumb = uint32(ceil(ivec/nplanes)); % This is the receiver number + end + rownumb = ivec - (double(colnumb)-1)*nplanes; % This is the plane number + if nplanes < 256 + rownumb = uint8(ivec - (double(colnumb)-1)*nplanes); % This is the plane number + elseif nplanes < 65536 + rownumb = uint16(ivec - (double(colnumb)-1)*nplanes); % This is the plane number + else + rownumb = uint32(ivec - (double(colnumb)-1)*nplanes); % This is the plane number + end + clear ivec + + % Select all the edges that are connected to these planes + + if nedges < 256 + edgeselection = uint8(edgesatplane(rownumb,1:maxncornersperplane)); + elseif nedges < 65536 + edgeselection = uint16(edgesatplane(rownumb,1:maxncornersperplane)); + else + edgeselection = uint32(edgesatplane(rownumb,1:maxncornersperplane)); + end + if length(rownumb) > 1 + maxcols = sum(sign(sum(edgeselection))); + else + maxcols = sum(sign(edgeselection)); + end + edgeselection = edgeselection(:,1:maxcols); + colnumb = colnumb(:,ones(1,maxcols)); + + indexvec = uint32(double(edgeselection) + (double(colnumb)-1)*nedges); + indexvec(find(edgeselection==0)) = []; + + visedgesfromr(indexvec) = uint8(4*ones(size(indexvec))); +end + +ivec = find(visplanesfromr==4); +if ~isempty(ivec) + if nreceivers < 256 + colnumb = uint8(ceil(ivec/nplanes)); % This is the receiver number + elseif nreceivers < 65536 + colnumb = uint16(ceil(ivec/nplanes)); % This is the receiver number + else + colnumb = uint32(ceil(ivec/nplanes)); % This is the receiver number + end + if nplanes < 256 + rownumb = uint8(ivec - (double(colnumb)-1)*nplanes); % This is the plane number + elseif nplanes < 65536 + rownumb = uint16(ivec - (double(colnumb)-1)*nplanes); % This is the plane number + else + rownumb = uint32(ivec - (double(colnumb)-1)*nplanes); % This is the plane number + end + clear ivec + + % Divide these lists into two categories: planes with indents and + % planes without + + iv2 = find(planehasindents(rownumb)); + if ~isempty(iv2) + colnumb_ind = colnumb(iv2); + rownumb_ind = rownumb(iv2); + colnumb(iv2) = []; + rownumb(iv2) = []; + else + colnumb_ind = []; + rownumb_ind = []; + end + if ~isempty(colnumb) + % Select all the edges that are connected to these planes + + % edgeselection = edgesatplane(rownumb,1:maxncornersperplane); + if nedges < 256 + edgeselection = uint8(edgesatplane(rownumb,1:maxncornersperplane)); + elseif nedges < 65536 + edgeselection = uint16(edgesatplane(rownumb,1:maxncornersperplane)); + else + edgeselection = uint32(edgesatplane(rownumb,1:maxncornersperplane)); + end + if length(rownumb) > 1 + maxcols = sum(sign(sum(double(edgeselection)))); + else + maxcols = sum(sign(double(edgeselection))); + end + edgeselection = edgeselection(:,1:maxcols); + colnumb = colnumb(:,ones(1,maxcols)); + + indexvec = uint32(double(edgeselection) + (double(colnumb)-1)*nedges); + indexvec(find(edgeselection==0)) = []; + + visedgesfromr(indexvec) = uint8(2*ones(size(indexvec))); + end + if ~isempty(colnumb_ind) + % Select all the edges that are connected to these planes + + edgeselection = edgesatplane(rownumb,1:maxncornersperplane); + if length(rownumb) > 1 + maxcols = sum(sign(sum(edgeselection))); + else + maxcols = sum(sign(edgeselection)); + end + edgeselection = edgeselection(:,1:maxcols); + colnumb_ind = colnumb_ind(:,ones(1,maxcols)); + + indexvec = uint32(edgeselection + (colnumb_ind-1)*nedges); + indexvec(find(edgeselection==0)) = []; + + visedgesfromr(indexvec) = uint8(3*ones(size(indexvec))); + end +end + +% 0 R can never see the edge because it is behind the edge-planes. +% NB! If the closwedang > pi, then it is enough if R is behind +% one plane. If the closwedang <= pi, then R must be behind both +% planes in order not to see the edge. + +ivec = find(visplanesfromr==0); + +if ~isempty(ivec) + if nreceivers < 256 + colnumb = uint8(ceil(ivec/nplanes)); % This is the receiver number + elseif nreceivers < 65536 + colnumb = uint16(ceil(ivec/nplanes)); % This is the receiver number + else + colnumb = uint32(ceil(ivec/nplanes)); % This is the receiver number + end + if nplanes < 256 + rownumb = uint8(ivec - (double(colnumb)-1)*nplanes); % This is the plane number + elseif nplanes < 65536 + rownumb = uint16(ivec - (double(colnumb)-1)*nplanes); % This is the plane number + else + rownumb = uint32(ivec - (double(colnumb)-1)*nplanes); % This is the plane number + end + clear ivec + + % Select all the edges that are connected to these planes + + if nedges < 256 + edgeselection = uint8(edgesatplane(rownumb,1:maxncornersperplane)); + elseif nedges < 65536 + edgeselection = uint16(edgesatplane(rownumb,1:maxncornersperplane)); + else + edgeselection = uint32(edgesatplane(rownumb,1:maxncornersperplane)); + end + if length(rownumb) > 1 + maxcols = sum(sign(sum(double(edgeselection)))); + else + maxcols = sum(sign(double(edgeselection))); + end + edgeselection = edgeselection(:,1:maxcols); + colnumb = colnumb(:,ones(1,maxcols)); + ntot2 = length(rownumb)*maxcols; + + indexvec = uint32(double(edgeselection) + (double(colnumb)-1)*nedges); + indexvec = reshape(indexvec,ntot2,1); + edgeselection = reshape(edgeselection,ntot2,1); + + iv2 = find(edgeselection==0); + indexvec(iv2) = []; + edgeselection(iv2) = []; + ntot2 = ntot2 - length(iv2); + + [indexvec,sortvec] = sort(indexvec); + edgeselection = edgeselection(sortvec); + clear sortvec + + markdoubles = [edgeselection(1:ntot2-1)==edgeselection(2:ntot2)]; + markdoubles = sign([markdoubles;0] + [0;markdoubles]); + iv2 = uint32(find(markdoubles)); + clear markdoubles + visedgesfromr(indexvec(iv2)) = 0; + indexvec(iv2) = []; + edgeselection(iv2) = []; + iv2 = uint32(find(closwedangvec(edgeselection)<=pi)); + indexvec(iv2) = []; + visedgesfromr(indexvec) = 0; + clear indexvec +end + +clear edgeselection iv2 + +%################################################################## +% +% Mask out edges that should be switched off + +mask = (ones(nedges,1)); +mask(offedges) = mask(offedges) & 0; + +visedgesfromr = uint8(double(visedgesfromr).*mask(:,onesvec1R)); + +clear onesvec1R + +%################################################################## +%################################################################## +%################################################################## +% +% CHECK OBSTRUCTION OF R-TO-EDGE PATHS +% +% vispartedgesfromr 0-2^nedgesubs-1, [nedges,nrec] +% telling which segments of an edge that +% are visible +% +% A. If visedgesfromr = 6 then check aligned-plane obstructions +% If OK, set visedgesfromr = 1 (check ordinary obst.) +% If not OK, set visedgesfromr = 0 +% +% B. If visedgesfromr = 3 then check within-plane obstructions +% Set visedgesfromr = 0 and +% set vispartedgesfromr = 0-full +% +% C. If visedgesfromr = 2 then +% Set visedgesfromr = 0 and +% set vispartedgesfromr = Full +% +% D. If visedgesfromr = 1 then check ordinary obstructions +% Set visedgesfromr = 0 and +% set vispartedgesfromr = 0-full + +edgedividervec = [0:nedgesubs-1].'; +weightvec = 2.^edgedividervec; +maxvisibilityval = 2^nedgesubs-1; + +if SHOWTEXT >= 3 + if lower(typeofcoords(1)) == 'r' + disp([' Checking for obstructing planes between R and edges']) + else + disp([' Checking for obstructing planes between S and edges']) + end +end + +if nedgesubs<8 + vispartedgesfromr = uint8(zeros(size(visedgesfromr))); +elseif nedgesubs<16 + vispartedgesfromr = uint16(zeros(size(visedgesfromr))); +else + vispartedgesfromr = uint32(zeros(size(visedgesfromr))); +end + +%################################################################## +% +% The receiver related quantities + +iv = uint32(find(visedgesfromr>=5)); +if ~isempty(iv) + disp(' We check aligned-edge obstructions') + + % All edges must be checked vs all other edges? + % Make subdivision of edges. If a line from R to edge segments + % pass through a plane that is constructed by an edge and perpendicular to + % the studied plane, then that edge is obstructing. + + combnumbers = double(iv); + recnumbers = ceil(combnumbers/nedges); + if nedges < 256 + edgenumbers = uint8(combnumbers - (recnumbers-1)*nedges); + elseif nedges < 65536 + edgenumbers = uint16(combnumbers - (recnumbers-1)*nedges); + else + edgenumbers = uint32(combnumbers - (recnumbers-1)*nedges); + end + + nedgesperreceiver = histc(recnumbers,[1:nreceivers]); + iv1 = find(nedgesperreceiver >= 2); + if isempty(iv1) + visedgesfromr(iv) = ones(size(iv)); + else + disp([' Several edges are in-plane with the receiver']) + disp([' If possible, move the receivers a little bit']) + [uniquerecs,exampleindex] = unique(recnumbers); + for jj = 1:length(uniquerecs) + problemrec = uniquerecs(jj); + iv1 = find(recnumbers==problemrec); + disp(' ') + disp(' Receiver with coordinates') + disp([' ',num2str(pointcoords(problemrec,1)),' ',num2str(pointcoords(problemrec,2)),' ',num2str(pointcoords(problemrec,3))]) + disp(' is aligned with edges') + numvec = [int2str(edgenumbers(iv1(1))),' ',int2str(edgenumbers(iv1(2)))]; + for kk = 3:length(iv1) + numvec = [numvec,' ', int2str(edgenumbers(iv1(kk)))]; + end + disp([' ',numvec]) + end + error('ERROR: Obstruction check of aligned-edges not implemented yet!') + end + end + +iv = uint32(find(visedgesfromr==3)); +if ~isempty(iv) + disp(' We check within-plane obstructions') + + visedgesfromr(iv) = zeros(size(iv)); + error('ERROR: Obstruction check of within-same-plane-edges not implemented yet!') +end + +iv = uint32(find(visedgesfromr==2)); +if ~isempty(iv) + disp(' Edge fully visible') + visedgesfromr(iv) = zeros(size(iv)); + vispartedgesfromr(iv) = maxvisibilityval*ones(size(iv)); + +end + +iv = uint32(find(visedgesfromr==4)); +if ~isempty(iv) + disp(' Edge in totabs plane') + visedgesfromr(iv) = zeros(size(iv)); + vispartedgesfromr(iv) = zeros(size(iv)); + +end + +% Below is the main part of the obstruction test. In the matrix +% visedgesfromr, values 1 indicate that edge-receiver combos should be +% tested. visedgesfromr has the size [nedges,nreceivers]. + +iv = uint32(find(visedgesfromr==1)); +if ~isempty(iv) + + visedgesfromr(iv) = zeros(size(iv)); + combnumbers = double(iv); + clear iv + + % combnumbers is a list of the "combined" values for edge and receiver. + + if nreceivers < 256 + recnumbers = uint8(ceil(combnumbers/nedges)); + elseif nreceivers < 65536 + recnumbers = uint16(ceil(combnumbers/nedges)); + else + recnumbers = uint32(ceil(combnumbers/nedges)); + end + if nedges < 256 + edgenumbers = uint8(combnumbers - (double(recnumbers)-1)*nedges); + elseif nedges < 65536 + edgenumbers = uint16(combnumbers - (double(recnumbers)-1)*nedges); + else + edgenumbers = uint32(combnumbers - (double(recnumbers)-1)*nedges); + end + combnumbers = uint32(combnumbers); + ncombs = length(recnumbers); + ntot = ncombs*nplanes; + + % Mark, in a big matrix, which planes can at all obstruct. + % Planes that can obstruct must be seen by the receiver or the edge but + % not both - because then they would be on the same side! + % NB! Also totabs planes can obstruct. + % The big matrix will have nedges*nplanes rows. The vector planenumb + % will have values such as [1 1 1 1... 2 2 2 2 .....] + + iv = [1:ncombs*nplanes].'; + % Plane number is given by the col no. + if nplanes < 256 + planenumb = uint8(ceil(iv/ncombs)); + elseif nplanes < 65536 + planenumb = uint16(ceil(iv/ncombs)); + else + planenumb = uint32(ceil(iv/ncombs)); + end + indexvec = planenumb; + + % The rownumber will simply have values [1 2 3... N 1 2 3 ... N 1 2 3 + % ... N] where N is the number of combinations. + if ncombs < 256 + rownumber = uint8(iv - (double(planenumb)-1)*ncombs); + elseif ncombs < 65536 + rownumber = uint16(iv - (double(planenumb)-1)*ncombs); + else + rownumber = uint32(iv - (double(planenumb)-1)*ncombs); + end + clear planenumb iv + + % The peak in the memory need might be after the two indexvec lines + % below + + % indexvec2 will point to the right location in an [nplanes,nedges] matrix + % indexvec will point to the right location in an [nplanes,nreceivers] matrix + indexvec2 = uint32(double(indexvec) + (double(edgenumbers(rownumber))-1)*nplanes); + indexvec = uint32(double(indexvec) + (double(recnumbers(rownumber))-1)*nplanes); + clear rownumber + + % The big matrix checkplane, size [1,ncombs*nplanes], will contain the + % value 1 if a plane should be checked for obstruction. + % The index order of checkplane is: + % [Plane1&comb1 Plane1&comb2 Plane1&comb3 ...] where comb1 is the first + % combination of receiver and edge in the recnumbers & edgenumbers + % lists. + % Only planes that are seen by the S/R *or* the edge, but not both + % should be checked for obstruction!! + % We remove combinations where: + % ... S/R is aligned with a plane (visplanesfromr == 1) + % ... edge belongs to a plane or is aligned with a plane (edgeseesplane <0) + % ... S/R is behind and edge is behind a plane (visplanesfromr == 0 & edgeseesplane == 0) + % ... S/R is in front of and edge is in front of a plane ( (visplanesfromr == 2 | visplanesfromr == 3) & edgeseesplane == 1) + % + % Comment 050116 (PS): + % We would actually need a matrix called planeseesedge. Here we use + % edgeseesplane instead, and it is not completely clear if that works + % fine. + + checkplane = (visplanesfromr(indexvec)~=1) & (edgeseesplane(indexvec2)>=0) & not(visplanesfromr(indexvec)==0 & edgeseesplane(indexvec2)==0 ) & not( (visplanesfromr(indexvec)==2 | visplanesfromr(indexvec)==3) & edgeseesplane(indexvec2)==1 ); + if size(checkplane,1) > size(checkplane,2) + checkplane = checkplane.'; + end + + if size(checkplane,1) == 1 | size(checkplane,2) == 1 + checkplane = reshape(checkplane,ncombs,nplanes); + end + + clear indexvec indexvec2 edgeseesplane + + % If there are some R-edge combos that have no planes to check + % obstruction for, we can mark those combos ("combsnottocheck") as fully visible. + % + % The remaining ones ("combstocheck") still need to be checked. + + [n1,n2] = size(checkplane); + if n1 < 65536 + combstocheck = uint16(find( sum(checkplane.') )); + elseif n1 < 4e9 + combstocheck = uint32(find( sum(checkplane.') )); + end + combsnottocheck = [1:ncombs]; + combsnottocheck(combstocheck) = []; + if ~isempty(combsnottocheck) + vispartedgesfromr(combnumbers(combsnottocheck)) = maxvisibilityval*ones(size(combsnottocheck)); + end + + if ~isempty(combstocheck) + + checkplane = checkplane(combstocheck,:); + recnumbers = recnumbers(combstocheck); + maxrec = max(recnumbers); + if maxrec < 256 + recnumbers = uint8(recnumbers); + elseif maxrec < 65536 + recnumbers = uint16(recnumbers); + else + recnumbers = uint32(recnumbers); + end + edgenumbers = edgenumbers(combstocheck); + combnumbers = combnumbers(combstocheck); + ncombs = length(combstocheck); + + % Now, checkplane is a matrix of size [ncombs,nplanes] where each + % row corresponds to one path (from one receiver to one edge) that needs + % an obstruction check. For that row, checkplane has the value 1 for + % each plane that needs to be checked. + % + % Expand all edges into their edge segment/subdivision + % We treat all the little edge subdivisions as separate edges + + nposs = ncombs*nedgesubs; + + expandedrecnumbers = recnumbers(:,onesvec1ES); + clear recnumbers + expandedrecnumbers = reshape(expandedrecnumbers.',nposs,1); + expandedcombnumbers = combnumbers(:,onesvec1ES); + clear combnumbers + expandedcombnumbers = reshape(expandedcombnumbers.',nposs,1); + if nposs < 65536 + okcombs = uint16(zeros(size(expandedrecnumbers))); + elseif nposs < 4e9 + okcombs = uint32(zeros(size(expandedrecnumbers))); + end + + [tocoords,expandededgeweightlist,expandededgenumbers] = EDB1getedgepoints(edgestartcoords(edgenumbers,:),... + edgeendcoords(edgenumbers,:),edgelengthvec(edgenumbers,:),nedgesubs,1); + expandededgenumbers = edgenumbers(expandededgenumbers); + + [nonobstructedpaths,nobstructions,edgehits,cornerhits] = EDB1checkobstr_pointtoedge(pointcoords,expandedrecnumbers,tocoords,reshape(repmat(checkplane.',[nedgesubs,1]),nplanes,nposs).',planeseesplane,... + planeeqs,planenvecs,minvals,maxvals,planecorners,corners,ncornersperplanevec,rearsideplane); + clear checkplane planeseesplane + + expandedcombnumbers = expandedcombnumbers(nonobstructedpaths); + expandededgeweightlist = expandededgeweightlist(nonobstructedpaths); + expandedrecnumbers = expandedrecnumbers(nonobstructedpaths); + expandededgenumbers = expandededgenumbers(nonobstructedpaths); + + % Pack all non-obstructed edge segments together and add their weights together + + test = [double(expandedrecnumbers) double(expandededgenumbers)]; + ncombs = length(expandedrecnumbers); + dtest = diff([0;prod( double(test(1:ncombs-1,:)==test(2:ncombs,:)).' ).']); + ivremove = find(dtest==1); + + while ~isempty(ivremove) + expandededgeweightlist(ivremove+1) = double(expandededgeweightlist(ivremove+1)) + double(expandededgeweightlist(ivremove)); + expandededgeweightlist(ivremove) = []; + expandedrecnumbers(ivremove) = []; + expandededgenumbers(ivremove,:) = []; + + test = [double(expandedrecnumbers) double(expandededgenumbers)]; + ncombs = length(expandedrecnumbers); + dtest = diff([0;prod( double(test(1:ncombs-1,:)==test(2:ncombs,:)).' ).']); + ivremove = find(dtest==1); + end + + indexvec = uint32(nedges*(double(expandedrecnumbers)-1)+double(expandededgenumbers)); + vispartedgesfromr(indexvec) = expandededgeweightlist; + clear indexvec + end +end + +%---------------------------------------------------------------------------- +% +% SAVE THE VARIABLES +% +%-------------------------------------------------------------------------- + +if typeofcoords=='r' + receivers = pointcoords; + Varlist = [' visplanesfromr receivers ']; + Varlist = [Varlist,' vispartedgesfromr routsidemodel ']; + eval(['save ',outputfile,Varlist]) + return +else + sources = pointcoords; + visplanesfroms = visplanesfromr; + vispartedgesfroms = vispartedgesfromr; + soutsidemodel = routsidemodel; + Varlist = [' visplanesfroms sources ']; + Varlist = [Varlist,' vispartedgesfroms soutsidemodel ']; + eval(['save ',outputfile,Varlist]) + return +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/private/EDB1betaoverml.m Sat Nov 16 18:25:24 2013 +0000 @@ -0,0 +1,46 @@ +function outval = EDB1betaoverml(zvec,rs,rr,zs,zr,ny,sinnyfivec,cosnyfivec) +% EDB1betaoverml - Integrand function which is called for num. int. of ED IR. +% EDB1betaoverml is copied directly +% into the numerical integration function EDB1quadstep for faster operation +% but EDB1betaoverml is also called directly by EDbwedge1st_int. +% +% Uses no special functions. +% +% ---------------------------------------------------------------------------------------------- +% This file is part of the Edge Diffraction Toolbox by Peter Svensson. +% +% The Edge Diffraction Toolbox is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) any later version. +% +% The Edge Diffraction Toolbox is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +% FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License along with the +% Edge Diffraction Toolbox. If not, see <http://www.gnu.org/licenses/>. +% ---------------------------------------------------------------------------------------------- +% Peter Svensson 20040323 (svensson@iet.ntnu.no) +% +% outval = EDB1betaoverml(zvec,rs,rr,zs,zr,ny,sinnyfivec,cosnyfivec); + +ml = sqrt( (zvec-zs).^2 + rs.^2 ).*sqrt( (zvec-zr).^2 + rr.^2 ); + +%------------------------------------------------ +% We would have liked to use the following code: +% y = (ml + (zvec-zs).*(zvec-zr))./(rs*rr); +% expnyeta = real((real(sqrt(y.^2-1)) + y).^ny); +% coshnyeta = 0.5*( expnyeta + 1./expnyeta); +% but to save three vectors, zvec will be re-used for +% y and expnyeta and coshnyeta + +zvec = (ml + (zvec-zs).*(zvec-zr))./(rs*rr); +zvec = real((real(sqrt(zvec.^2-1) + zvec)).^ny); +zvec = 0.5*( zvec + 1./zvec); + +outval = sinnyfivec(1)./(zvec - cosnyfivec(1)); +outval = outval + sinnyfivec(2)./(zvec - cosnyfivec(2)); +outval = outval + sinnyfivec(3)./(zvec - cosnyfivec(3)); +outval = outval + sinnyfivec(4)./(zvec - cosnyfivec(4)); + +outval = outval./ml;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/private/EDB1calcdist.m Sat Nov 16 18:25:24 2013 +0000 @@ -0,0 +1,58 @@ +function distances = EDB1calcdist(x1,x2) +% EDB1calcdist - Gives distances between sets of points in 3D space. +% EDB1calcdist returns a matrix of distances from all n1 points +% in x1 to all n2 points in x2. +% +% Input parameters: +% x1 Matrix, [n1,3], with the coordinates of n1 points. +% x2 Matrix, [n2,3], with the coordinates of n2 points. +% +% Output parameters: +% distances Matrix, [n1,n2], with the distances from all +% points in x1 to all points in x2. +% +% Uses no special functions. +% +% ---------------------------------------------------------------------------------------------- +% This file is part of the Edge Diffraction Toolbox by Peter Svensson. +% +% The Edge Diffraction Toolbox is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) any later version. +% +% The Edge Diffraction Toolbox is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +% FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License along with the +% Edge Diffraction Toolbox. If not, see <http://www.gnu.org/licenses/>. +% ---------------------------------------------------------------------------------------------- +% Peter Svensson (svensson@iet.ntnu.no) 20001010 +% +% distances = EDB1calcdist(x1,x2); + +[n11,n12] = size(x1); +[n21,n22] = size(x2); + +if n12 ~= 3 | n22 ~= 3 + disp('Coordinates must be specified as [x y z]') +else + if n11 == 1 + x1 = x1(ones(n21,1),:); + d1 = x1-x2; + distances = sqrt(sum( (d1.').^2 )); + elseif n21 == 1 + x2 = x2(ones(n11,1),:); + d1 = x1-x2; + distances = sqrt(sum( (d1.').^2 )).'; + else + distances = zeros(n11,n21); + for ii = 1:n21 + x2point = x2(ii,:); + x2point = x2point(ones(n11,1),:); + d1 = x1 - x2point; + distances(:,ii) = sqrt(sum( (d1.').^2 )).'; + end + end +end +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/private/EDB1checkobstr_edgetoedge.m Sat Nov 16 18:25:24 2013 +0000 @@ -0,0 +1,326 @@ +function [nonobstructedpaths,nobstructions,edgehits,cornerhits] = EDB1checkobstr_edgetoedge(canplaneobstruct,planeseesplane,... + planeeqs,planenvecs,minvals,maxvals,planecorners,corners,ncornersperplanevec,rearsideplane) +% EDB1checkobstr_edgetoedge - Checks obstruction for a list of edge-to-edge paths. +% Checks if the paths from N starting points (fromcoords) to +% N ending points (tocoords) pass through any of M planes (those marked by 1 in +% canplaneobstruct), i.e., if they are obstructed. +% +% Input parameters: +% canplaneobstruct,planeseesplane,planeeqs,planenvecs,minvals,maxvals,... +% planecorners,corners,ncornersperplanevec,rearsideplane +% Data that should have been passed on from the +% eddatafile. See EDB1edgeo for more information. +% global: +% FROMCOORDS Matrix, [N,3] or [1,3], with the coordinates of the +% N (or 1) starting points of the N paths to check. +% TOCOORDS Matrix, [N,3] or [1,3], with the coordinates of the +% N (or 1) ending points of the N paths to check. +% STARTPLANES Matrix, [N,1] or [N,2] or [0,0], with the plane +% numbers that the starting points are positioned directly at. +% The size is determined by: +% [N,1] fromcoords are specular reflection points +% [N,2] fromcoords are edge points +% [0,0] fromcoords are image sources or receiver +% positions. +% ENDPLANES Matrix with the plane numbers that the ending points are +% positioned directly at. +% +% Output parameters: +% nonobstructedpaths A list, [N_nobstructions,1] of the indices of paths that are not +% obstructed. The indices refer to the input +% lists fromcoords, tocoords, startplanes +% endplanes +% nobstructions The number of paths (of the N input paths) that +% were not obstructed. +% edgehits A list, [N_edgehits,1] of the indicies of paths that hit a +% plane right at an edge. +% cornerhits A list, [N_cornerhits,1] of the indicies of paths that hit a +% plane right at a corner. +% +% Uses no special functions. +% +% ---------------------------------------------------------------------------------------------- +% This file is part of the Edge Diffraction Toolbox by Peter Svensson. +% +% The Edge Diffraction Toolbox is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) any later version. +% +% The Edge Diffraction Toolbox is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +% FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License along with the +% Edge Diffraction Toolbox. If not, see <http://www.gnu.org/licenses/>. +% ---------------------------------------------------------------------------------------------- +% Peter Svensson (svensson@iet.ntnu.no) 20050922 +% +% [nonobstructedpaths,nobstructions,edgehits,cornerhits] = EDB1checkobstr_edgetoedge(canplaneobstruct,planeseesplane,... +% planeeqs,planenvecs,minvals,maxvals,planecorners,corners,ncornersperplanevec,rearsideplane) + +global FROMCOORDSSHORTLIST REFTOFROMCOSHO TOCOORDSSHORTLIST REFTOTOCOSHO STARTPLANES ENDPLANES +global BIGTOCOORDS BIGFROMCOORDS BIGSTARTPLANES BIGENDPLANES + +[nstartpoints,slask] = size(REFTOFROMCOSHO); +[nendpoints,slask] = size(REFTOTOCOSHO); +npaths = max(max([nstartpoints nendpoints])); +nplanes = length(canplaneobstruct); + +% The startplanes and endplanes can either be one-column or two-column +% lists depending on if paths are between specular reflections or edges. + +[slask,nplanecols1] = size(STARTPLANES); +[slask,nplanecols2] = size(ENDPLANES); + +% In addition, we only need to check planes for which canplaneobstruct = 1. + +if nplanes < 256 + maxlistofplanestocheck = uint8(find( canplaneobstruct>0).'); +elseif nplanes < 65536 + maxlistofplanestocheck = uint16(find( canplaneobstruct>0).'); +else + maxlistofplanestocheck = uint32(find( canplaneobstruct>0).'); +end +nplanestocheck = length(maxlistofplanestocheck); + +if nplanestocheck > 0 + + ntot = nplanestocheck*npaths; + + % Make one long list of planes to check obstruction for. It will be aligned + % with expanded lists of path startpoints and endpoints in addition to startplanes and + % endplanes. We need to construct a ref. list because some of the + % combinations will be thrown away and we must be able to refer back to the + % rectangular, complete matrix of size [nplanestocheck,npaths]. + + bigplanelist = maxlistofplanestocheck(:,ones(1,npaths)); + bigplanelist = reshape(bigplanelist,ntot,1); + + reftoorigmatrix = uint32([1:npaths*nplanestocheck].'); + + % Don't check the one or two planes that are involved in each path for obstruction + % or, their respective rearside planes, if they happen to be thin. + + if ~isempty(BIGSTARTPLANES) + if nplanecols1 == 1 + iv = find(bigplanelist==BIGSTARTPLANES | bigplanelist==rearsideplane(BIGSTARTPLANES)); + bigplanelist(iv) = []; + BIGSTARTPLANES(iv) = []; + reftoorigmatrix(iv) = []; + if ~isempty(BIGENDPLANES) + BIGENDPLANES(iv,:) = []; + end + BIGTOCOORDS(iv,:) = []; + BIGFROMCOORDS(iv,:) = []; + else + + iv = find(bigplanelist==BIGSTARTPLANES(:,1) | bigplanelist==BIGSTARTPLANES(:,2) | ... + bigplanelist==rearsideplane(BIGSTARTPLANES(:,1)) | bigplanelist==rearsideplane(BIGSTARTPLANES(:,2))); + bigplanelist(iv) = []; + BIGSTARTPLANES(iv,:) = []; + reftoorigmatrix(iv) = []; + if ~isempty(BIGENDPLANES) + BIGENDPLANES(iv,:) = []; + end + BIGTOCOORDS(iv,:) = []; + BIGFROMCOORDS(iv,:) = []; + end + end + + if ~isempty(BIGENDPLANES) + if nplanecols2 == 1 + iv = find(bigplanelist==BIGENDPLANES | bigplanelist==rearsideplane(BIGENDPLANES)); + bigplanelist(iv) = []; + if ~isempty(BIGSTARTPLANES) + BIGSTARTPLANES(iv,:) = []; + end + BIGENDPLANES(iv,:) = []; + reftoorigmatrix(iv) = []; + BIGTOCOORDS(iv,:) = []; + BIGFROMCOORDS(iv,:) = []; + else + iv = find(bigplanelist==BIGENDPLANES(:,1) | bigplanelist==BIGENDPLANES(:,2) | ... + bigplanelist==rearsideplane(BIGENDPLANES(:,1)) | bigplanelist==rearsideplane(BIGENDPLANES(:,2))); + bigplanelist(iv) = []; + if ~isempty(BIGSTARTPLANES) + BIGSTARTPLANES(iv,:) = []; + end + BIGENDPLANES(iv,:) = []; + reftoorigmatrix(iv) = []; + BIGTOCOORDS(iv,:) = []; + BIGFROMCOORDS(iv,:) = []; + end + end + +% [hitplanes,reflpoints,edgehits,edgehitpoints,cornerhits,cornerhitpoints] = EDB1chkISvisible(BIGFROMCOORDS,BIGTOCOORDS,planeeqs(bigplanelist,4),planenvecs(bigplanelist,:),minvals(bigplanelist,:),... +% maxvals(bigplanelist,:),planecorners(bigplanelist,:),corners,ncornersperplanevec(bigplanelist)); +% +% 20050922: The entire EDB1chkISvisible is pasted in here. + +%########################################################################## +%########################################################################## +%########################################################################## +%########################################################################## + + +nsou = size(BIGFROMCOORDS,1); +nplanes = length(bigplanelist); + +[nrec,slask] = size(BIGTOCOORDS); +if nrec == 1 + onesvec = uint8(ones(nplanes,1)); + BIGTOCOORDS = BIGTOCOORDS(onesvec,:); + clear onesvec +end + +planenvecsexpanded = planenvecs(bigplanelist,:).'; + +%---------------------------------------------------------------- +% First we check if the IS and R are on the same side of the +% respective planes. Then the path can not pass through the plane. + +tempmatrix = corners(planecorners(bigplanelist,1),:); +sseesplanes = sum( ((BIGFROMCOORDS - tempmatrix).').*planenvecsexpanded ).'; +rseesplanes = sum( ((BIGTOCOORDS - tempmatrix).').*planenvecsexpanded ).'; +iv1 = uint32(find( (sseesplanes>= (-eps*30) )~=(rseesplanes>= (-eps*30) ) )); +clear sseesplanes rseesplanes + + +%-------------------------------------------------------------------------- +% Next tests (if there were any planes that had IS and R at different sides) +% 1. Are the vectors IS -> R parallel to the planes? +% 2. Are the reflpoints inside the planes? + +if ~isempty(iv1) + npossible = length(iv1); + % Below tempmatrix is the direction vector + tempmatrix = BIGTOCOORDS - BIGFROMCOORDS; + BIGTOCOORDS = []; + dirveclengths = sqrt(sum(tempmatrix.'.^2)).' + eps*100; + tempmatrix = tempmatrix./dirveclengths(:,ones(1,3)); + + % If test == 0, then the vector S -> R runs along the + % plane. + + iv1 = iv1(find(sum( planenvecsexpanded(:,iv1).*(tempmatrix(iv1,:).') ).'~=0)); + + if ~isempty(iv1) + + % The last test is if the hitpoint is inside the plane + + % Step 1: calculate the hit point using u = the line parameter (with + % unit meters) from the source towards the receiver. + + udir = ( planeeqs(bigplanelist(iv1),4) - sum( planenvecsexpanded(:,iv1).*(BIGFROMCOORDS(iv1,:).') ).' ); + + udir = udir./( sum( planenvecsexpanded(:,iv1).*(tempmatrix(iv1,:).') ).'); + + % Step 2: check that the hit point is at a shorter distance than + % the receiver point, and that the hit point is not in the opposite + % direction than the receiver. + + iv2 = find( udir<(dirveclengths(iv1)*1.001) & udir>=0 ); + clear dirveclengths + if length(iv2) < length(iv1) + iv1 = iv1(iv2); + udir = udir(iv2); + clear iv2 + end + + if ~isempty(iv1) + % Step 3: calculate the actual xyz coordinates of the hit points + % Now tempmatrix gets the values of the hit points + tempmatrix = BIGFROMCOORDS(iv1,:) + udir(:,ones(1,3)).*tempmatrix(iv1,:); + + clear udir + BIGFROMCOORDS = []; + + [hitvec,edgehitvec,cornerhitvec] = EDB1poinpla(tempmatrix,iv1,minvals(bigplanelist,:),maxvals(bigplanelist,:),planecorners(bigplanelist,:),corners,ncornersperplanevec(bigplanelist),planenvecsexpanded.'); + + hitplanes = []; + reflpoints = []; + edgehits = []; + edgehitpoints = []; + cornerhits = []; + cornerhitpoints = []; + if any(any(hitvec)) ~=0 + ivhit = find(hitvec==1); + hitplanes = iv1( ivhit ); + reflpoints = tempmatrix(ivhit,:); + end + if ~isempty(edgehitvec) + ivhit = find(edgehitvec==1); + edgehits = iv1( ivhit ); + edgehitpoints = tempmatrix(ivhit,:); + end + if ~isempty(cornerhitvec) + ivhit = find(cornerhitvec==1); + cornerhits = iv1( ivhit ); + cornerhitpoints = tempmatrix(ivhit,:); + end + else + hitplanes = []; + reflpoints = []; + edgehits = []; + edgehitpoints = []; + cornerhits = []; + cornerhitpoints = []; + end + else + hitplanes = []; + reflpoints = []; + edgehits = []; + edgehitpoints = []; + cornerhits = []; + cornerhitpoints = []; + end +else + hitplanes = []; + reflpoints = []; + edgehits = []; + edgehitpoints = []; + cornerhits = []; + cornerhitpoints = []; +end + +%########################################################################## +%########################################################################## +%########################################################################## +%########################################################################## + + zerosvec1 = zeros(nplanestocheck,npaths); + + obstructionoccurrence = zerosvec1; + obstructionoccurrence(reftoorigmatrix(hitplanes)) = ones(size(hitplanes)); + if nplanestocheck > 1 + obstructionoccurrence = sum(obstructionoccurrence); + end + nonobstructedpaths = find(obstructionoccurrence==0); + + if ~isempty(edgehits) + edgehitoccurrence = zerosvec1; + edgehitoccurrence(reftoorigmatrix(edgehits)) = ones(size(edgehits)); + if nplanestocheck > 1 + edgehitoccurrence = sum(edgehitoccurrence); + end + edgehits = find(edgehitoccurrence~=0); + end + + if ~isempty(cornerhits) + cornerhitoccurrence = zerosvec1; + cornerhitoccurrence(reftoorigmatrix(cornerhits)) = ones(size(cornerhits)); + if nplanestocheck > 1 + cornerhitoccurrence = sum(cornerhitoccurrence); + end + cornerhits = find(cornerhitoccurrence~=0); + end + + nobstructions = npaths-length(nonobstructedpaths); +else + npaths + nonobstructedpaths = [1:npaths].' + pause + nobstructions = 0; + edgehits = []; + cornerhits = []; +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/private/EDB1checkobstr_pointtoedge.m Sat Nov 16 18:25:24 2013 +0000 @@ -0,0 +1,189 @@ +function [nonobstructedpaths,nobstructions,edgehits,cornerhits] = EDB1checkobstr_pointtoedge(fromcoordsshortlist,reftoshortlist,tocoords,canplaneobstruct,planeseesplane,... + planeeqs,planenvecs,minvals,maxvals,planecorners,corners,ncornersperplanevec,rearsideplane) +% EDB1checkobstr_pointtoedge - Checks obstruction for a list of paths from points to edges. +% Checks if the paths from N starting points (reftoshortlist -> fromcoordsshortlist) to +% N ending points on edges (tocoords) pass through any of M planes (those marked by 1 in +% canplaneobstruct), i.e., if they are obstructed. +% +% Input parameters: +% fromcoordsshortlist Matrix with the unique coordinates of the N +% starting points. +% reftoshortlist List, [N,1], with the N indices to fromcoordsshortlist. +% tocoords Matrix, [N,3], with the coordinates of the +% N ending points (on edges) of the N paths to check. +% canplaneobstruct,planeseesplane,planeeqs,planenvecs,minvals,maxvals,... +% planecorners,corners,ncornersperplanevec,rearsideplane +% Data that should have been passed on from the +% eddatafile. See EDB1edgeo for more information. +% +% Output parameters: +% nonobstructedpaths A list, [N_nobstructions,1] of the indices of paths that are not +% obstructed. The indices refer to the input +% lists fromcoords, tocoords, startplanes +% endplanes +% nobstructions The number of paths (of the N input paths) that +% were not obstructed. +% edgehits A list, [N_edgehits,1] of the indicies of paths that hit a +% plane right at an edge. +% cornerhits A list, [N_cornerhits,1] of the indicies of paths that hit a +% plane right at a corner. +% +% Uses function EDB1poinpla +% +% ---------------------------------------------------------------------------------------------- +% This file is part of the Edge Diffraction Toolbox by Peter Svensson. +% +% The Edge Diffraction Toolbox is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) any later version. +% +% The Edge Diffraction Toolbox is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +% FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License along with the +% Edge Diffraction Toolbox. If not, see <http://www.gnu.org/licenses/>. +% ---------------------------------------------------------------------------------------------- +% Peter Svensson (svensson@iet.ntnu.no) 20050922 +% +% [nonobstructedpaths,nobstructions,edgehits,cornerhits] = EDB1checkobstr_pointtoedge(fromcoordsshortlist,reftoshortlist,tocoords,canplaneobstruct,planeseesplane,... +% planeeqs,planenvecs,minvals,maxvals,planecorners,corners,ncornersperplanevec,rearsideplane) + +npaths = size(tocoords,1); +nplanes = size(canplaneobstruct,2); + +% We only need to check planes for which canplaneobstruct = 1. + +if nplanes < 256 + maxlistofplanestocheck = uint8( find( sum(canplaneobstruct) ).' ); +elseif nplanes < 65536 + maxlistofplanestocheck = uint16( find( sum(canplaneobstruct) ).' ); +else + maxlistofplanestocheck = uint32( find( sum(canplaneobstruct) ).' ); +end + +nplanestocheck = length(maxlistofplanestocheck); + +if nplanestocheck > 0 + ntot = nplanestocheck*npaths; + + nmaxcorners = double(max(ncornersperplanevec(maxlistofplanestocheck))); + planecorners = planecorners(:,1:nmaxcorners); + + % For the obstruction test, we create expanded matrices/lists where the + % plane-number is the fastest varying variable. We calculate + % the direction vectors, from point to point, before the expanding. + + dirvec = tocoords - fromcoordsshortlist(reftoshortlist,:); + clear tocoords + dirveclengths = sqrt(sum(dirvec.'.^2)).' + eps*100; + dirvec = dirvec./dirveclengths(:,ones(1,3)); + + % Create the expanded matrices, by duplicating each path with the + % number of planes that need to be checked obstruction against. + % Immediately select only those individual combinations where + % canplaneobstruct = 1. This selection is done both for bigplanelist + % and for the reftoshortlist, and for the reftodirvec (which points to + % the shorter dirvec matrix). + + iv1 = (find(canplaneobstruct(:,maxlistofplanestocheck))); + + bigplanelist = maxlistofplanestocheck(ceil((iv1)/npaths)); + if ntot < 65536 + iv1 = uint16(iv1); + elseif ntot < 4.29e9 + iv1 = uint32(iv1); + end + + reftoshortlist = reftoshortlist(:,ones(1,nplanestocheck)); + reftoshortlist = reftoshortlist(iv1); + + if npaths*nplanestocheck < 65536 + reftodirvec = uint16([1:npaths].'); + else + reftodirvec = uint32([1:npaths].'); + end + reftodirvec = reftodirvec(:,ones(1,nplanestocheck)); + reftodirvec = reftodirvec(iv1); + + %-------------------------------------------------------------------------- + % Tests + % (Earlier, it was first tested if the IS and R were on the same side of a plane. This is checked at another place). + % (Earlier, test 2 was: Are the vectors IS -> R parallel to the planes? + % This shold not be needed now). + % + % Are the hitpoints inside the planes? + % 1. Calculate the hit points' coordinates. + % 2. Check that the hit point is not further away than the receiver + % point, and that the hit point is not in the wrong direction! + % 3. Check if the hit points are inside the plane that is checked. + + % Step 1 + udir_bigplanenvecs = ( planeeqs(bigplanelist,4) - sum( planenvecs(bigplanelist,:).'.*(fromcoordsshortlist(reftoshortlist,:).') ).' )./( sum( planenvecs(bigplanelist,:).'.*(dirvec(reftodirvec,:).') ).'); + + % Step 2 + iv2 = find( udir_bigplanenvecs<dirveclengths(reftodirvec) & udir_bigplanenvecs>0 ); + clear dirveclengths + iv1 = iv1(iv2); + bigplanelist = bigplanelist(iv2); + reftoshortlist = reftoshortlist(iv2); + reftodirvec = reftodirvec(iv2); + udir_bigplanenvecs = udir_bigplanenvecs(iv2,:); + clear iv2 + + if ~isempty(iv1) + % Step 3 + xhit_list = fromcoordsshortlist(reftoshortlist,:) + udir_bigplanenvecs(:,ones(1,3)).*dirvec(reftodirvec,:); + + clear udir_bigplanenvecs dirvec reftoshortlist + + + [hitvec,edgehit,cornerhit] = EDB1poinpla(xhit_list,bigplanelist,minvals,maxvals,planecorners,corners,ncornersperplanevec,planenvecs); + clear xhit_list + + % We recycle canplaneobstruct since we need to compile how many hits + % that occurred. + canplaneobstruct = zeros(size(canplaneobstruct(:,maxlistofplanestocheck))); + ivhits = find(hitvec); + if ~isempty(ivhits) + indexvec = iv1(ivhits); + canplaneobstruct(iv1(ivhits)) = canplaneobstruct(iv1(ivhits))+1; + end + edgehits = []; + ivhits = find(edgehit); + if ~isempty(ivhits) + disp('WARNING: Edge hit. This is treated as an obstruction.') + indexvec = iv1(ivhits); + canplaneobstruct(iv1(ivhits)) = canplaneobstruct(iv1(ivhits))+1; + end + + cornerhits = []; + ivhits = find(cornerhit); + if ~isempty(ivhits) + disp('WARNING: Corner hit. This is treated as an obstruction.') + indexvec = iv1(ivhits); + canplaneobstruct(iv1(ivhits)) = canplaneobstruct(iv1(ivhits))+1; + end + + % Here was a bug: erroneous summing when there was a single plane that + % could obstruct (PS 041127) + if size(canplaneobstruct,2) > 1 + canplaneobstruct = 1-sign(sum(canplaneobstruct.')); + else + canplaneobstruct = 1-canplaneobstruct; + end + nonobstructedpaths = find(canplaneobstruct); + + nobstructions = npaths-length(nonobstructedpaths); + else + nonobstructedpaths = [1:npaths].'; + nobstructions = 0; + edgehits = []; + cornerhits = []; + end +else + nonobstructedpaths = [1:npaths].'; + nobstructions = 0; + edgehits = []; + cornerhits = []; +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/private/EDB1checkobstrpaths.m Sat Nov 16 18:25:24 2013 +0000 @@ -0,0 +1,374 @@ +function [nonobstructedpaths,nobstructions,edgehits,cornerhits] = EDB1checkobstrpaths(fromcoords,tocoords,startplanes,endplanes,canplaneobstruct,planeseesplane,... + planeeqs,planenvecs,minvals,maxvals,planecorners,corners,ncornersperplanevec,rearsideplane) +% EDB1checkobstrpaths - Checks obstruction for a list of paths, or check if specular reflections are valid. +% Checks if the paths from N starting points (fromcoords) to +% N ending points (tocoords) pass through any of M planes (those marked by 1 in +% canplaneobstruct), i.e., if they are obstructed. +% +% Instead of testing for N to N points, it is possible to specify +% 1 starting point and N ending points or the other way around. +% Also, it is possible to specify, for each individual starting or ending point +% one or two planes that the respective point is directly at +% because then, those planes will be excluded from the list of planes to check for. +% +% Input parameters: +% fromcoords Matrix, [N,3] or [1,3], with the coordinates of the +% N (or 1) starting points of the N paths to check. +% tocoords Matrix, [N,3] or [1,3], with the coordinates of the +% N (or 1) ending points of the N paths to check. +% startplanes Matrix, [N,1] or [N,2] or [0,0], with the plane +% numbers that the starting points are positioned directly at. +% The size is determined by: +% [N,1] fromcoords are specular reflection points +% [N,2] fromcoords are edge points +% [0,0] fromcoords are image sources or receiver +% positions. +% endplanes Matrix with the plane numbers that the ending points are +% positioned directly at. +% canplaneobstruct,planeseesplane,planeeqs,planenvecs,minvals,maxvals,.. +% planecorners,corners,ncornersperplanevec,rearsideplane +% Data that should have been passed on from the +% eddatafile. See EDB1edgeo for more information. +% +% Output parameters: +% nonobstructedpaths A list, [N_nobstructions,1] of the indices of paths that are not +% obstructed. The indices refer to the input +% lists fromcoords, tocoords, startplanes +% endplanes +% nobstructions The number of paths (of the N input paths) that +% were not obstructed. +% edgehits A list, [N_edgehits,1] of the indicies of paths that hit a +% plane right at an edge. +% cornerhits A list, [N_cornerhits,1] of the indicies of paths that hit a +% plane right at a corner. +% +% Uses function EDB1chkISvisiblex +% +% ---------------------------------------------------------------------------------------------- +% This file is part of the Edge Diffraction Toolbox by Peter Svensson. +% +% The Edge Diffraction Toolbox is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) any later version. +% +% The Edge Diffraction Toolbox is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +% FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License along with the +% Edge Diffraction Toolbox. If not, see <http://www.gnu.org/licenses/>. +% ---------------------------------------------------------------------------------------------- +% Peter Svensson (svensson@iet.ntnu.no) 20060621 +% +% [nonobstructedpaths,nobstructions,edgehits,cornerhits] = EDB1checkobstrpaths(fromcoords,tocoords,startplanes,endplanes,canplaneobstruct,planeseesplane,... +% planeeqs,planenvecs,minvals,maxvals,planecorners,corners,ncornersperplanevec,rearsideplane) + +global BIGFROMCOORDSSHORTLIST REFTOFROMSHORTLIST BIGTOCOORDSSHORTLIST REFTOTOSHORTLIST + +[nstartpoints,slask] = size(fromcoords); +[nendpoints,slask] = size(tocoords); +npaths = max(max([nstartpoints nendpoints])); +nplanes = length(canplaneobstruct); + +% The startplanes and endplanes can either be one-column or two-column +% lists depending on if paths are between specular reflections or edges. + +[nplanes1,nplanecols1] = size(startplanes); +[nplanes2,nplanecols2] = size(endplanes); + +% If startplanes and/or endplanes have been specified, then we should only +% need to check planes that are seen by the start- or end-plane. + +if ~isempty(startplanes) & ~isempty(endplanes) + if nplanecols1 == 1 & nplanecols2 == 1 + planesareseen = ( sum( planeseesplane(endplanes,:) > 0 ) + sum( planeseesplane(startplanes,:) > 0 ) ) > 0; + elseif nplanecols1 == 2 & nplanecols2 == 2 + planesareseen = ( sum( planeseesplane(endplanes(:,1),:) > 0 ) + sum( planeseesplane(endplanes(:,2),:) > 0 ) + ... + sum( planeseesplane(startplanes(:,1),:) > 0 ) + sum( planeseesplane(startplanes(:,2),:) > 0 ) ) > 0; + elseif nplanecols1 == 2 & nplanecols2 == 1 + planesareseen = ( sum( planeseesplane(endplanes,:) > 0 ) + ... + sum( planeseesplane(startplanes(:,1),:) > 0 ) + sum( planeseesplane(startplanes(:,2),:) > 0 ) ) > 0; + elseif nplanecols1 == 1 & nplanecols2 == 2 + planesareseen = ( sum( planeseesplane(endplanes(:,1),:) > 0 ) + sum( planeseesplane(endplanes(:,2),:) > 0 ) + ... + sum( planeseesplane(startplanes,:) > 0 ) ) > 0; + end +else + if ~isempty(startplanes) + if nplanes1 > 1 + planesareseen = sum( planeseesplane(startplanes,:) > 0 ) > 0; + else + planesareseen = planeseesplane(startplanes,:) > 0; + end + elseif ~isempty(endplanes) + if nplanes2 > 1 + planesareseen = sum( planeseesplane(endplanes,:) > 0 ) > 0; + else + planesareseen = planeseesplane(endplanes,:) > 0; + end + else + planesareseen = ones(1,nplanes); + end +end + +% In addition, we only need to check planes for which canplaneobstruct = 1. + +if nplanes <= 255 + maxlistofplanestocheck = uint8(find((planesareseen & canplaneobstruct)>0).'); +elseif nplanes <= 65535 + maxlistofplanestocheck = uint16(find((planesareseen & canplaneobstruct)>0).'); +else + maxlistofplanestocheck = uint32(find((planesareseen & canplaneobstruct)>0).'); +end + +nplanestocheck = length(maxlistofplanestocheck); + +if nplanestocheck > 0 + onesvec1 = ones(1,nplanestocheck); + onesvec2 = ones(npaths*nplanestocheck,1); + ntot = nplanestocheck*npaths; + + % Make one long list of planes to check obstruction for. It will be aligned + % with expanded lists of path startpoints and endpoints in addition to startplanes and + % endplanes. We need to construct a ref. list because some of the + % combinations will be thrown away and we must be able to refer back to the + % rectangular, complete matrix of size [nplanestocheck,npaths]. + + bigplanelist = maxlistofplanestocheck(:,ones(1,npaths)); + bigplanelist = reshape(bigplanelist,ntot,1); + + reftoorigmatrix = uint32([1:npaths*nplanestocheck].'); + + if nstartpoints == 1 & nendpoints ~= 1, + speedyalgorithm = 1; + else + speedyalgorithm = 0; + end + + % Make one long matrix of path endpoints and path endplanes + + if nendpoints > 1 + if speedyalgorithm == 0 + BIGTOCOORDSSHORTLIST = tocoords; + if npaths < 65536 + REFTOTOSHORTLIST = uint16([1:npaths]); + else + REFTOTOSHORTLIST = uint32([1:npaths]); + end + REFTOTOSHORTLIST = reshape(REFTOTOSHORTLIST(ones(nplanestocheck,1),:),ntot,1); + end + + if isempty(endplanes) + bigendplanes = []; + else + if nplanecols2 == 1 + bigendplanes = endplanes(:,onesvec1); + bigendplanes = reshape(bigendplanes.',ntot,1); + else + bigendplanes = reshape(repmat(endplanes.',[nplanestocheck,1]),2,ntot).'; + end + end + else + if speedyalgorithm == 0 + BIGTOCOORDSSHORTLIST = tocoords; + REFTOTOSHORTLIST = int8(onesvec2); + end + if isempty(endplanes) + bigendplanes = []; + else + if length(endplanes) > 2 + error('ERROR: Some strange error here!') + end + if nplanecols2 == 1 + bigendplanes = endplanes(onesvec2,:); + else + bigendplanes = [endplanes(1) endplanes(2)]; + bigendplanes = bigendplanes(onesvec2,:); + end + end + end + + % Make one long matrix of path startplanes and startpoints + + if nstartpoints > 1 + if speedyalgorithm == 0 + BIGFROMCOORDSSHORTLIST = fromcoords; + if npaths < 65536 + REFTOFROMSHORTLIST = uint16([1:npaths]); + else + REFTOFROMSHORTLIST = uint32([1:npaths]); + end + REFTOFROMSHORTLIST = reshape(REFTOFROMSHORTLIST(ones(nplanestocheck,1),:),ntot,1); + end + if isempty(startplanes) + bigstartplanes = []; + else + if nplanecols1 == 1 + bigstartplanes = startplanes(:,onesvec1); + bigstartplanes = reshape(bigstartplanes.',ntot,1); + else + bigstartplanes = reshape(repmat(startplanes.',[nplanestocheck,1]),2,ntot).'; + end + end + else + if speedyalgorithm == 0 + BIGFROMCOORDSSHORTLIST = fromcoords; + REFTOFROMSHORTLIST = int8(onesvec2); + end + if isempty(startplanes) + bigstartplanes = []; + else + if nplanecols1 == 1 + bigstartplanes = startplanes(onesvec2,:); + else + bigstartplanes = [startplanes(1) startplanes(2)]; + bigstartplanes = bigstartplanes(onesvec2,:); + end + end + end + + if speedyalgorithm == 0 + clear onesvec2 + end + + % Now we can clear all combinations where neither the startplane or the + % endplane sees the obstructing plane! + % + % After a number of combinations have been cleared, the fromcoords and + % tocoords can be expanded and then pruned. + % + % This is the speedy algorithm... + + if nstartpoints == 1 & nendpoints ~= 1, + if size(bigendplanes,2) == 1 + iv = uint32(find(planeseesplane(uint32(double(bigendplanes) + (double(bigplanelist)-1)*nplanes))==0)); + bigplanelist(iv) = []; + bigendplanes(iv,:) = []; + reftoorigmatrix(iv) = []; + + BIGFROMCOORDSSHORTLIST = fromcoords; + REFTOFROMSHORTLIST = int8(onesvec2(1:length(reftoorigmatrix))); + clear onesvec2 + BIGTOCOORDSSHORTLIST = tocoords; + if npaths < 65536 + REFTOTOSHORTLIST = uint16([1:npaths]); + else + REFTOTOSHORTLIST = uint32([1:npaths]); + end + REFTOTOSHORTLIST = reshape(REFTOTOSHORTLIST(ones(nplanestocheck,1),:),ntot,1); + REFTOTOSHORTLIST(iv) = []; + clear iv + else + ref1to_planeseesplane = uint32(double(bigendplanes,1) + (double(bigplanelist)-1)*nplanes); + ref2to_planeseesplane = uint32(double(bigendplanes,2) + (double(bigplanelist)-1)*nplanes); + iv = uint32(find(planeseesplane(ref1to_planeseesplane)==0 & planeseesplane(ref2to_planeseesplane)==0)); + clear refto_planeseesplane + bigplanelist(iv) = []; + bigendplanes(iv,:) = []; + reftoorigmatrix(iv) = []; + + BIGFROMCOORDSSHORTLIST = fromcoords; + REFTOFROMSHORTLIST = int8(onesvec2(1:length(reftoorigmatrix))); + clear onesvec2 + + BIGTOCOORDSSHORTLIST = tocoords; + if npaths < 65536 + REFTOTOSHORTLIST = uint16([1:npaths]); + else + REFTOTOSHORTLIST = uint32([1:npaths]); + end + REFTOTOSHORTLIST = reshape(REFTOTOSHORTLIST(ones(nplanestocheck,1),:),ntot,1); + REFTOTOSHORTLIST(iv) = []; + clear iv + end + end + if nstartpoints ~= 1 & nendpoints ~= 1, + + end + + + % Don't check the one or two planes that are involved in each path for obstruction + % or, their respective rearside planes, if they happen to be thin. + + if ~isempty(bigstartplanes) + if nplanecols1 == 1 + iv = find(bigplanelist==bigstartplanes | bigplanelist==rearsideplane(bigstartplanes)); + clear bigstartplanes + bigplanelist(iv) = []; + reftoorigmatrix(iv) = []; + if ~isempty(bigendplanes) + bigendplanes(iv,:) = []; + end + REFTOTOSHORTLIST(iv) = []; + REFTOFROMSHORTLIST(iv) = []; + else + iv = find(bigplanelist==bigstartplanes(:,1) | bigplanelist==bigstartplanes(:,2) | ... + bigplanelist==rearsideplane(bigstartplanes(:,1)) | bigplanelist==rearsideplane(bigstartplanes(:,2))); + clear bigstartplanes + bigplanelist(iv) = []; + reftoorigmatrix(iv) = []; + if ~isempty(bigendplanes) + bigendplanes(iv,:) = []; + end + REFTOTOSHORTLIST(iv) = []; + REFTOFROMSHORTLIST(iv) = []; + end + end + + if ~isempty(bigendplanes) + if nplanecols2 == 1 + + iv = find(bigplanelist==bigendplanes | bigplanelist==rearsideplane(bigendplanes)); + + clear bigendplanes + bigplanelist(iv) = []; + reftoorigmatrix(iv) = []; + REFTOTOSHORTLIST(iv) = []; + REFTOFROMSHORTLIST(iv) = []; + else + iv = find(bigplanelist==bigendplanes(:,1) | bigplanelist==bigendplanes(:,2) | ... + bigplanelist==rearsideplane(bigendplanes(:,1)) | bigplanelist==rearsideplane(bigendplanes(:,2))); + clear bigendplanes + bigplanelist(iv) = []; + reftoorigmatrix(iv) = []; + REFTOTOSHORTLIST(iv) = []; + REFTOFROMSHORTLIST(iv) = []; + end + end + +[hitplanes,reflpoints,edgehits,edgehitpoints,cornerhits,cornerhitpoints] = EDB1chkISvisiblex(bigplanelist,planeeqs(:,4),planenvecs,minvals,... + maxvals,planecorners,corners,ncornersperplanevec); + + zerosvec1 = zeros(nplanestocheck,npaths); + + obstructionoccurrence = zerosvec1; + obstructionoccurrence(reftoorigmatrix(hitplanes)) = ones(size(hitplanes)); + if nplanestocheck > 1 + obstructionoccurrence = sum(obstructionoccurrence); + end + nonobstructedpaths = find(obstructionoccurrence==0); + + if ~isempty(edgehits) + edgehitoccurrence = zerosvec1; + edgehitoccurrence(reftoorigmatrix(edgehits)) = ones(size(edgehits)); + if nplanestocheck > 1 + edgehitoccurrence = sum(edgehitoccurrence); + end + edgehits = find(edgehitoccurrence~=0); + end + + if ~isempty(cornerhits) + cornerhitoccurrence = zerosvec1; + cornerhitoccurrence(reftoorigmatrix(cornerhits)) = ones(size(cornerhits)); + if nplanestocheck > 1 + cornerhitoccurrence = sum(cornerhitoccurrence); + end + cornerhits = find(cornerhitoccurrence~=0); + end + + nobstructions = npaths-length(nonobstructedpaths); +else + nonobstructedpaths = [1:npaths].'; + nobstructions = 0; + edgehits = []; + cornerhits = []; +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/private/EDB1chkISvisible.m Sat Nov 16 18:25:24 2013 +0000 @@ -0,0 +1,174 @@ +function [hitplanes,hitpoints,edgehits,edgehitpoints,cornerhits,cornerhitpoints] = EDB1chkISvisible(ISlist,R,planeeqs_lastvalue,planenvecs,minvals,maxvals,planecorners,corners,ncornersperplanevec) +% EDB1chkISvisible - Checks if paths from a set of IS to a set of R pass through their refl. planes. +% EDB1chkISvisible checks if the paths between a number of IS and a single R, or a number of R, +% pass through their respective reflecting planes. +% +% Input parameters: +% ISlist Matrix, [nIS,3], of the nIS image source coordinates +% R Receiver coordinates, [1,3] or [nIS,3] +% planeeqs_lastvalue List [nIS,1] of the fourth value of the plane +% equations. +% planenvecs,minvals, maxvals, planecorners, corners, ncornersperplanevec +% Data that should have been taken from the corresponding +% variables in the eddatafile,see EDB1edgeo for more information. +% NB!! The matrices planeeqs, minvals, maxvals +% have been rearranged so that they have nIS rows, and each +% row contain the data for one specific plane: the reflecting +% plane for the IS. +% +% Output parameters: +% hitplanes List, [nhits,1], of the planes that have been hit. The values +% in this list refer to the index numbers of the input list ISlist +% hitpoints List, [nhits,3] of the hitpoint coordinates, for the planes that have been hit +% edgehits List, [nedgehits,1] of the planes that were hit right at an edge. +% These combinations were marked as hit in the list hitplanes, +% but the extra information in edgehits can possibly be used. +% edgehitpoints List, [nedgehits,3] of the hitpoint coordinates for the +% planes that were hit at an edge. +% cornerhits List, [ncornerhits,1] of the planes that were hit right at a corner. +% These combinations were marked as hit in the list hitplanes, +% but the extra information in edgehits can possibly be used. +% cornerhitpoints List, [ncornerhits,3] of the hitpoint coordinates for the +% planes that were hit at a corner. +% +% Uses the function EDB1poinpla. +% +% ---------------------------------------------------------------------------------------------- +% This file is part of the Edge Diffraction Toolbox by Peter Svensson. +% +% The Edge Diffraction Toolbox is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) any later version. +% +% The Edge Diffraction Toolbox is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +% FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License along with the +% Edge Diffraction Toolbox. If not, see <http://www.gnu.org/licenses/>. +% ---------------------------------------------------------------------------------------------- +% Peter Svensson (svensson@iet.ntnu.no) 20050116 +% +% [hitplanes,hitpoints,edgehits,edgehitpoints,cornerhits,cornerhitpoints] = EDB1chkISvisible(ISlist,R,planeeqs_lastvalue,planenvecs,minvals,maxvals,planecorners,corners,ncornersperplanevec) + +nsou = size(ISlist,1); +nplanes = size(planeeqs_lastvalue,1); + +if size(planeeqs_lastvalue,2) > 1 + error(['Fix the call to EDB1chkISvisible!!!']) +end + +[nrec,slask] = size(R); +if nrec == 1 + onesvec = uint8(ones(nplanes,1)); + R = R(onesvec,:); + clear onesvec +end + +planenvecs = planenvecs.'; + +%---------------------------------------------------------------- +% First we check if the IS and R are on the same side of the +% respective planes. Then the path can not pass through the plane. + +tempmatrix = corners(planecorners(:,1),:); +sseesplanes = sum( ((ISlist - tempmatrix).').*planenvecs ).'; +rseesplanes = sum( ((R - tempmatrix).').*planenvecs ).'; +iv1 = uint32(find( (sseesplanes>= (-eps*30) )~=(rseesplanes>= (-eps*30) ) )); +clear sseesplanes rseesplanes + + +%-------------------------------------------------------------------------- +% Next tests (if there were any planes that had IS and R at different sides) +% 1. Are the vectors IS -> R parallel to the planes? +% 2. Are the hitpoints inside the planes? + +if ~isempty(iv1) + npossible = length(iv1); + % Below tempmatrix is the direction vector + tempmatrix = R - ISlist; + clear R + dirveclengths = sqrt(sum(tempmatrix.'.^2)).' + eps*100; + tempmatrix = tempmatrix./dirveclengths(:,ones(1,3)); + + % If test == 0, then the vector S -> R runs along the + % plane. + + iv1 = iv1(find(sum( planenvecs(:,iv1).*(tempmatrix(iv1,:).') ).'~=0)); + + if ~isempty(iv1) + + % The last test is if the hitpoint is inside the plane + + % Step 1: calculate the hit point using u = the line parameter (with + % unit meters) from the source towards the receiver. + udir = ( planeeqs_lastvalue(iv1) - sum( planenvecs(:,iv1).*(ISlist(iv1,:).') ).' ); + clear planeeqs_lastvalue + udir = udir./( sum( planenvecs(:,iv1).*(tempmatrix(iv1,:).') ).'); + + % Step 2: check that the hit point is at a shorter distance than + % the receiver point, and that the hit point is not in the opposite + % direction than the receiver. + + iv2 = find( udir<(dirveclengths(iv1)*1.001) & udir>=0 ); + clear dirveclengths + if length(iv2) < length(iv1) + iv1 = iv1(iv2); + udir = udir(iv2); + clear iv2 + end + + if ~isempty(iv1) + % Step 3: calculate the actual xyz coordinates of the hit points + % Now tempmatrix gets the values of the hit points + tempmatrix = ISlist(iv1,:) + udir(:,ones(1,3)).*tempmatrix(iv1,:); + + clear ISlist udir + + [hitvec,edgehitvec,cornerhitvec] = EDB1poinpla(tempmatrix,iv1,minvals,maxvals,planecorners,corners,ncornersperplanevec,planenvecs.'); + + hitplanes = []; + hitpoints = []; + edgehits = []; + edgehitpoints = []; + cornerhits = []; + cornerhitpoints = []; + if any(any(hitvec)) ~=0 + ivhit = find(hitvec==1); + hitplanes = iv1( ivhit ); + hitpoints = tempmatrix(ivhit,:); + end + if ~isempty(edgehitvec) + ivhit = find(edgehitvec==1); + edgehits = iv1( ivhit ); + edgehitpoints = tempmatrix(ivhit,:); + end + if ~isempty(cornerhitvec) + ivhit = find(cornerhitvec==1); + cornerhits = iv1( ivhit ); + cornerhitpoints = tempmatrix(ivhit,:); + end + else + hitplanes = []; + hitpoints = []; + edgehits = []; + edgehitpoints = []; + cornerhits = []; + cornerhitpoints = []; + end + else + hitplanes = []; + hitpoints = []; + edgehits = []; + edgehitpoints = []; + cornerhits = []; + cornerhitpoints = []; + end +else + hitplanes = []; + hitpoints = []; + edgehits = []; + edgehitpoints = []; + cornerhits = []; + cornerhitpoints = []; +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/private/EDB1chkISvisiblex.m Sat Nov 16 18:25:24 2013 +0000 @@ -0,0 +1,186 @@ +function [hitplanes,hitpoints,edgehits,edgehitpoints,cornerhits,cornerhitpoints] = EDB1chkISvisiblex(bigplanelist,planeeqs_lastvalue,planenvecs,minvals,maxvals,planecorners,corners,ncornersperplanevec) +% EDB1chkISvisiblex - Checks if paths from a set of IS to a set of R pass through resp. refl. planes. Extended version +% EDB1chkISvisiblex checks if the paths between a number of IS and a single R, or a number of R, +% pass through their respective reflecting planes. +% +% Input parameters: +% bigplanelist List, [nIS,1], of the plane numbers in a long list of +% combinations to check. +% planeeqs_lastvalue List [nplanes,1] of the fourth value of the plane +% equations. +% planenvecs,minvals, maxvals, planecorners, corners, ncornersperplanevec +% Data that should have been taken from the corresponding +% variables in the eddatafile,see EDB1edgeo for more information. +% NB!! The matrices planeeqs, minvals, maxvals +% have been rearranged so that they have nIS rows, and each +% row contain the data for one specific plane: the reflecting +% plane for the IS. +% BIGFROMCOORDSSHORTLIST,REFTOFROMSHORTLIST,BIGTOCOORDSSHORTLIST,REFTOTOSHORTLIST +% (GLOBAL) +% +% Output parameters: +% hitplanes List, [nhits,1], of the planes that have been hit. The values +% in this list refer to the index numbers of the input list ISlist +% hitpoints List, [nhits,3] of the hitpoint coordinates, for the planes that have been hit +% edgehits List, [nedgehits,1] of the planes that were hit right at an edge. +% These combinations were marked as hit in the list hitplanes, +% but the extra information in edgehits can possibly be used. +% edgehitpoints List, [nedgehits,3] of the hitpoint coordinates for the +% planes that were hit at an edge. +% cornerhits List, [ncornerhits,1] of the planes that were hit right at a corner. +% These combinations were marked as hit in the list hitplanes, +% but the extra information in edgehits can possibly be used. +% cornerhitpoints List, [ncornerhits,3] of the hitpoint coordinates for the +% planes that were hit at a corner. +% +% Uses the function EDB1poinplax. +% +% ---------------------------------------------------------------------------------------------- +% This file is part of the Edge Diffraction Toolbox by Peter Svensson. +% +% The Edge Diffraction Toolbox is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) any later version. +% +% The Edge Diffraction Toolbox is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +% FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License along with the +% Edge Diffraction Toolbox. If not, see <http://www.gnu.org/licenses/>. +% ---------------------------------------------------------------------------------------------- +% Peter Svensson (svensson@iet.ntnu.no) 20050116 +% +% [hitplanes,hitpoints,edgehits,edgehitpoints,cornerhits,cornerhitpoints] = EDB1chkISvisiblex(bigplanelist,planeeqs_lastvalue,planenvecs,minvals,maxvals,planecorners,corners,ncornersperplanevec) + +global BIGFROMCOORDSSHORTLIST REFTOFROMSHORTLIST BIGTOCOORDSSHORTLIST REFTOTOSHORTLIST + +if isempty(bigplanelist) + hitplanes = []; + hitpoints = []; + edgehits = []; + edgehitpoints = []; + cornerhits = []; + cornerhitpoints = []; + return +end + +nsou = size(REFTOFROMSHORTLIST,1); +npaths = size(bigplanelist,1); + +if size(planeeqs_lastvalue,2) > 1 + error(['Fix the call to EDB1chkISvisible!!!']) +end + +[nrec,slask] = size(REFTOTOSHORTLIST); + +planenvecs = planenvecs.'; + +%---------------------------------------------------------------- +% First we check if the IS and R are on the same side of the +% respective planes. Then the path can not pass through the plane. + +if nrec == 1 + iv1 = uint32(find( (sum( ((BIGFROMCOORDSSHORTLIST(REFTOFROMSHORTLIST,:) - corners(planecorners(bigplanelist,1),:)).').*planenvecs(:,bigplanelist) ).' >= (-eps*30) )~=( sum( ((BIGTOCOORDSSHORTLIST(ones(npaths,1),:) - corners(planecorners(bigplanelist,1),:)).').*planenvecs(:,bigplanelist) ).'>= (-eps*30) ) )); +else + iv1 = uint32(find( (sum( ((BIGFROMCOORDSSHORTLIST(REFTOFROMSHORTLIST,:) - corners(planecorners(bigplanelist,1),:)).').*planenvecs(:,bigplanelist) ).' >= (-eps*30) )~=( sum( ((BIGTOCOORDSSHORTLIST(REFTOTOSHORTLIST,:) - corners(planecorners(bigplanelist,1),:)).').*planenvecs(:,bigplanelist) ).'>= (-eps*30) ) )); +end + +%-------------------------------------------------------------------------- +% Next tests (if there were any planes that had IS and R at different sides) +% 1. Are the vectors IS -> R parallel to the planes? +% 2. Are the hitpoints inside the planes? + +if ~isempty(iv1) + npossible = length(iv1); + % Below tempmatrix is the direction vector + + if nrec == 1 + tempmatrix = BIGTOCOORDSSHORTLIST(ones(npaths,1),:) - BIGFROMCOORDSSHORTLIST(REFTOFROMSHORTLIST,:); + else + tempmatrix = BIGTOCOORDSSHORTLIST(REFTOTOSHORTLIST,:) - BIGFROMCOORDSSHORTLIST(REFTOFROMSHORTLIST,:); + end + dirveclengths = sqrt(sum(tempmatrix.'.^2)).' + eps*100; + tempmatrix = tempmatrix./dirveclengths(:,ones(1,3)); + + % If test == 0, then the vector S -> R runs along the + % plane. + + iv1 = iv1(find(sum( planenvecs(:,bigplanelist(iv1)).*(tempmatrix(iv1,:).') ).'~=0)); + + if ~isempty(iv1) + + % The last test is if the hitpoint is inside the plane + + % Step 1: calculate the hit point using u = the line parameter (with + % unit meters) from the source towards the receiver. + ISlist = BIGFROMCOORDSSHORTLIST(REFTOFROMSHORTLIST(iv1),:); + udir = ( planeeqs_lastvalue(bigplanelist(iv1)) - sum( planenvecs(:,bigplanelist(iv1)).*(ISlist.') ).' ); + clear planeeqs_lastvalue + udir = udir./( sum( planenvecs(:,bigplanelist(iv1)).*(tempmatrix(iv1,:).') ).'); + + % Step 2: check that the hit point is at a shorter distance than + % the receiver point, and that the hit point is not in the opposite + % direction than the receiver. + iv2 = find(udir < -eps*1e4); + if ~isempty(iv2) + disp(['Lowest value (should always be > 0)']) + min(udir(iv2)) + error('WARNING!!! Check EDB1chkISvisiblex; some hit point is in the wrong direction from the receiver. Check the plane warping tolerances etc.') + end + + iv2 = find( (udir - dirveclengths(iv1)) > eps*1e4); + if ~isempty(iv2) + disp(['Lowest value (should always be > eps*1e4):']) + min(udir(iv2) - dirveclengths(iv1(iv2))) + disp(['Problematic hit point is related to plane ',int2str(bigplanelist(iv1(iv2(1)))),' and IS w coords: ']) + ISlist(iv2(1),:) + error('WARNING!!! Check EDB1chkISvisiblex; some hit point was at a shorter distance than the IS-receiver distance. Check the plane warping tolerances etc.') + end + + + % Step 3: calculate the actual xyz coordinates of the hit points + % Now tempmatrix gets the values of the hit points + tempmatrix = ISlist + udir(:,ones(1,3)).*tempmatrix(iv1,:); + + clear ISlist udir + [hitvec,edgehitvec,cornerhitvec] = EDB1poinplax(bigplanelist,tempmatrix,iv1,minvals,maxvals,planecorners,corners,ncornersperplanevec,planenvecs.'); + + hitplanes = []; + hitpoints = []; + edgehits = []; + edgehitpoints = []; + cornerhits = []; + cornerhitpoints = []; + if any(any(hitvec)) ~=0 + ivhit = find(hitvec==1); + hitplanes = iv1( ivhit ); + hitpoints = tempmatrix(ivhit,:); + end + if ~isempty(edgehitvec) + ivhit = find(edgehitvec==1); + edgehits = iv1( ivhit ); + edgehitpoints = tempmatrix(ivhit,:); + end + if ~isempty(cornerhitvec) + ivhit = find(cornerhitvec==1); + cornerhits = iv1( ivhit ); + cornerhitpoints = tempmatrix(ivhit,:); + end + + else + hitplanes = []; + hitpoints = []; + edgehits = []; + edgehitpoints = []; + cornerhits = []; + cornerhitpoints = []; + end +else + hitplanes = []; + hitpoints = []; + edgehits = []; + edgehitpoints = []; + cornerhits = []; + cornerhitpoints = []; +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/private/EDB1compress7.m Sat Nov 16 18:25:24 2013 +0000 @@ -0,0 +1,202 @@ +function [reftoshort,sho1,sho2,sho3,sho4,sho5,sho6,sho7,examplecombination] = ... +EDB1compress7(Big1,Big2,Big3,Big4,Big5,Big6,Big7) +% EDB1compress7 - +% This function looks for combinations of N edges-to-N edges that have identical +% values for 7 [N,N] matrices. The values are rounded to a relative +% accuracy of 1e-12. +% +% Input parameters: +% Big1, Big2,...,Big 7 Seven matrices, [N,N], of data. +% +% Output parameters: +% reftoshort Matrix, [N,N], of pointer values to seven short +% lists. +% sho1, sho2,...,sho7 Seven shortlists, [nshort,1], with values that +% are taken from the seven input matrices. +% examplecombination Vector of pointers from the short lists, back +% to the input matrices. +% +% Uses no special functions +% +% ---------------------------------------------------------------------------------------------- +% This file is part of the Edge Diffraction Toolbox by Peter Svensson. +% +% The Edge Diffraction Toolbox is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) any later version. +% +% The Edge Diffraction Toolbox is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +% FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License along with the +% Edge Diffraction Toolbox. If not, see <http://www.gnu.org/licenses/>. +% ---------------------------------------------------------------------------------------------- +% Peter Svensson (svensson@iet.ntnu.no) 20030503 +% +% [reftoshort,sho1,sho2,sho3,sho4,sho5,sho6,sho7,examplecombination] = ... +% EDB1compress7(Big1,Big2,Big3,Big4,Big5,Big6,Big7) + +accuracy = 1e-12; + +[n1,n2] = size(Big1); + +Big1 = reshape(Big1,n1*n2,1); +Big2 = reshape(Big2,n1*n2,1); +Big3 = reshape(Big3,n1*n2,1); +Big4 = reshape(Big4,n1*n2,1); +Big5 = reshape(Big5,n1*n2,1); +Big6 = reshape(Big6,n1*n2,1); +Big7 = reshape(Big7,n1*n2,1); + +maxamp = max(abs(Big1)); +if maxamp ~= 0 + Big1 = round( Big1/maxamp/accuracy)*accuracy*maxamp; +end +maxamp = max(abs(Big2)); +if maxamp ~= 0 + Big2 = round( Big2/maxamp/accuracy)*accuracy*maxamp; +end +maxamp = max(abs(Big3)); +if maxamp ~= 0 + Big3 = round( Big3/maxamp/accuracy)*accuracy*maxamp; +end +maxamp = max(abs(Big4)); +if maxamp ~= 0 + Big4 = round( Big4/maxamp/accuracy)*accuracy*maxamp; +end +maxamp = max(abs(Big5)); +if maxamp ~= 0 + Big5 = round( Big5/maxamp/accuracy)*accuracy*maxamp; +end +maxamp = max(abs(Big6)); +if maxamp ~= 0 + Big6 = round( Big6/maxamp/accuracy)*accuracy*maxamp; +end +maxamp = max(abs(Big7)); +if maxamp ~= 0 + Big7 = round( Big7/maxamp/accuracy)*accuracy*maxamp; +end + +%--------------------------------------- +% sort + +[Big1,sortvec] = sort(Big1); +Big2 = Big2(sortvec); +Big3 = Big3(sortvec); +Big4 = Big4(sortvec); +Big5 = Big5(sortvec); +Big6 = Big6(sortvec); +Big7 = Big7(sortvec); + +[Big2,sortvec2] = sort(Big2); +Big1 = Big1(sortvec2); +Big3 = Big3(sortvec2); +Big4 = Big4(sortvec2); +Big5 = Big5(sortvec2); +Big6 = Big6(sortvec2); +Big7 = Big7(sortvec2); +sortvec = sortvec(sortvec2); + +[Big3,sortvec2] = sort(Big3); +Big1 = Big1(sortvec2); +Big2 = Big2(sortvec2); +Big4 = Big4(sortvec2); +Big5 = Big5(sortvec2); +Big6 = Big6(sortvec2); +Big7 = Big7(sortvec2); +sortvec = sortvec(sortvec2); + +[Big4,sortvec2] = sort(Big4); +Big1 = Big1(sortvec2); +Big2 = Big2(sortvec2); +Big3 = Big3(sortvec2); +Big5 = Big5(sortvec2); +Big6 = Big6(sortvec2); +Big7 = Big7(sortvec2); +sortvec = sortvec(sortvec2); + +[Big5,sortvec2] = sort(Big5); +Big1 = Big1(sortvec2); +Big2 = Big2(sortvec2); +Big3 = Big3(sortvec2); +Big4 = Big4(sortvec2); +Big6 = Big6(sortvec2); +Big7 = Big7(sortvec2); +sortvec = sortvec(sortvec2); + +[Big6,sortvec2] = sort(Big6); +Big1 = Big1(sortvec2); +Big2 = Big2(sortvec2); +Big3 = Big3(sortvec2); +Big4 = Big4(sortvec2); +Big5 = Big5(sortvec2); +Big7 = Big7(sortvec2); +sortvec = sortvec(sortvec2); + +[Big7,sortvec2] = sort(Big7); +Big1 = Big1(sortvec2); +Big2 = Big2(sortvec2); +Big3 = Big3(sortvec2); +Big4 = Big4(sortvec2); +Big5 = Big5(sortvec2); +Big6 = Big6(sortvec2); +sortvec = sortvec(sortvec2); + +ivec1 = find( abs(diff(Big1)) > accuracy ); +ivec2 = find( abs(diff(Big2)) > accuracy ); +ivec3 = find( abs(diff(Big3)) > accuracy ); +ivec4 = find( abs(diff(Big4)) > accuracy ); +ivec5= find( abs(diff(Big5)) > accuracy ); +ivec6= find( abs(diff(Big6)) > accuracy ); +ivec7= find( abs(diff(Big7)) > accuracy ); + +ivec = [0;sort([ivec1;ivec2;ivec3;ivec4;ivec5;ivec6;ivec7])]; + +if length(ivec) > 1 + ivec = ivec( find(diff(ivec) ~= 0) + 1 ); + ivec = [1;ivec + 1;n1*n2+1]; + + sho1 = Big1( ivec(1:length(ivec)-1)); + sho2 = Big2( ivec(1:length(ivec)-1)); + sho3 = Big3( ivec(1:length(ivec)-1)); + sho4 = Big4( ivec(1:length(ivec)-1)); + sho5 = Big5( ivec(1:length(ivec)-1)); + sho6 = Big6( ivec(1:length(ivec)-1)); + sho7 = Big7( ivec(1:length(ivec)-1)); + + if length(ivec) < 256 + reftoshort = uint8(zeros( size(Big1) )); + elseif length(ivec) < 65536 + reftoshort = uint16(zeros( size(Big1) )); + else + reftoshort = uint32(zeros( size(Big1) )); + end + numberofoccurences = zeros( size(sho1) ); + examplecombination = zeros( size(sho1) ); + + for ii = 1:length(ivec)-1 + sameblock = sortvec( [ivec(ii):ivec(ii+1)-1] ); + reftoshort(sameblock) = ii*ones(size(sameblock)); + numberofoccurences(ii) = length( sameblock ); + examplecombination(ii) = sameblock(1); + patchcomb = sameblock(1); + end + + reftoshort = reshape(reftoshort,n1,n2); + +else % All IRs are the same + % The extra zero is added to give the right dimensions of the output + % vector when the shortlists are used. + + reftoshort = ones(n1,n2); + sho1 = [Big1(1,1);0]; + sho2 = [Big2(1,1);0]; + sho3 = [Big3(1,1);0]; + sho4 = [Big4(1,1);0]; + sho5 = [Big5(1,1);0]; + sho6 = [Big6(1,1);0]; + sho7 = [Big7(1,1);0]; + examplecombination = 1; + +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/private/EDB1coordtrans1.m Sat Nov 16 18:25:24 2013 +0000 @@ -0,0 +1,89 @@ +function [rs,thetas,zs] = EDB1coordtrans1(xsou,xwedge,nvec1) +% EDB1coordtrans1 - Transforms one set of cartesian coordinates to edge-related cylindrical coordinates. +% The cyl. coord. system is defined so that: +% A z-axis is placed along the edge, from the given endpoint 1 to the given +% endpoint 2. +% The origo of the cyl. syst. will be edge endpoint 1. +% The theta-angles of the cyl. coord. syst. will refer to the +% reference plane of the edge. +% The ref. plane of the edge is described by its normal vector. +% NB! The order of the edge points is important!! +% The vector going from xwedge(1,:) to xwedge(2,:) must be +% oriented so that if the RH thumb is along this vector, the tips +% of the fingers "come out of" the open face of plane1, i.e. where nvec1 +% is the normal vector. +% +% Input parameters: +% xsou Matrix, [n1,3] of cartesian coordinates of n1 points. +% xwedge Matrix, [2,3], with the cartesian coordinates of the two +% wedge end points: [xw1 yw1 zw1;xw2 yw2 zw2]. +% nvec1 List, [1,3], with the normal vector of the reference plane +% of the edge. +% +% Output parameters: +% rs, thetas, zs cyl. coord. of the points in xsou +% +% Uses the function EDB1cross +% +% ---------------------------------------------------------------------------------------------- +% This file is part of the Edge Diffraction Toolbox by Peter Svensson. +% +% The Edge Diffraction Toolbox is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) any later version. +% +% The Edge Diffraction Toolbox is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +% FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License along with the +% Edge Diffraction Toolbox. If not, see <http://www.gnu.org/licenses/>. +% ---------------------------------------------------------------------------------------------- +% Peter Svensson (svensson@iet.ntnu.no) 20061118 +% +% [rs,thetas,zs] = EDB1coordtrans1(xsou,xwedge,nvec1) + +npoints = size(xsou,1); +if npoints == 1 + xneworigo = xwedge(1,:); + + xknown1 = xwedge(2,:) - xneworigo; + xknown1 = xknown1 / norm(xknown1); + + A = [nvec1(2)*xknown1(3)-nvec1(3)*xknown1(2) ; nvec1(3)*xknown1(1)-nvec1(1)*xknown1(3) ; nvec1(1)*xknown1(2)-nvec1(2)*xknown1(1)]; + A = inv([xknown1.' A nvec1.']); + + xsou = (A([2 3 1],:)*( xsou.' - xneworigo.' )).'; + + rs = norm(xsou(1:2)); + zs = xsou(:,3); + thetas = 0; + if rs > 0 + thetas = real( acos( xsou(1)./rs ).*( xsou(2) ~= 0) ); + thetas = thetas + pi*( (xsou(2)==0) & xsou(1) < 0 ); + thetas = thetas.*( xsou(2) >=0 ) + (2*pi - thetas).*( xsou(2) < 0 ); + end + +else + xneworigo = xwedge(1,:); + + xknown1 = xwedge(2,:) - xneworigo; + xknown1 = xknown1 / sqrt( sum( xknown1.^2 )); + + + A = [0 1 0;0 0 1;1 0 0]*inv([xknown1.' EDB1cross(nvec1.',xknown1.') nvec1.']); + + [npoints,slask] = size(xsou); + xsou = (A*( xsou.' - xneworigo(ones(npoints,1),:).' )).'; + + rs = sqrt( sum(xsou(:,1:2).'.^2) ).'; + zs = xsou(:,3); + thetas = zeros(npoints,1); + iv = find(rs>0); + if ~isempty(iv) + thetas(iv) = real( acos( xsou(iv,1)./rs(iv) ).*( xsou(iv,2) ~= 0) ); + thetas(iv) = thetas(iv) + pi*( (xsou(iv,2)==0) & xsou(iv,1) < 0 ); + thetas(iv) = thetas(iv).*( xsou(iv,2) >=0 ) + (2*pi - thetas(iv)).*( xsou(iv,2) < 0 ); + end + +end \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/private/EDB1coordtrans2.m Sat Nov 16 18:25:24 2013 +0000 @@ -0,0 +1,82 @@ +function [rs,thetas,zs,rr,thetar,zr] = EDB1coordtrans2(xsou,xrec,xwedge,nvec1) +% EDB1coordtrans2 - Transforms two sets of cartesian coordinates to edge-related cylindrical coordinates. +% The cyl. coord. system is defined so that: +% ¥ A z-axis is placed along the edge, from the given endpoint 1 to the given +% endpoint 2. +% ¥ The origo of the cyl. syst. will be edge endpoint 1. +% ¥ The theta-angles of the cyl. coord. syst. will refer to the +% reference plane of the edge. +% The ref. plane of the edge is described by its normal vector. +% NB! The order of the edge points is important!! +% The vector going from xwedge(1,:) to xwedge(2,:) must be +% oriented so that if the RH thumb is along this vector, the tips +% of the fingers "come out of" the open face of plane1, i.e. where nvec1 +% is the normal vector. +% +% Input parameters: +% xsou Matrix, [n1,3] of cartesian coordinates of n1 points. +% xrec Matrix, [n2,3] of cartesian coordinates of n2 other points. +% xwedge Matrix, [2,3], with the cartesian coordinates of the two +% wedge end points: [xw1 yw1 zw1;xw2 yw2 zw2]. +% nvec1 List, [1,3], with the normal vector of the reference plane +% of the edge. +% +% Output parameters: +% rs, thetas, zs cyl. coord. of the points in xsou +% rr, thetar, zr cyl. coord. of the points in xrec +% +% Uses the function EDB1cross +% +% ---------------------------------------------------------------------------------------------- +% This file is part of the Edge Diffraction Toolbox by Peter Svensson. +% +% The Edge Diffraction Toolbox is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) any later version. +% +% The Edge Diffraction Toolbox is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +% FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License along with the +% Edge Diffraction Toolbox. If not, see <http://www.gnu.org/licenses/>. +% ---------------------------------------------------------------------------------------------- +% Peter Svensson (svensson@iet.ntnu.no) 20050922 +% +% [rs,thetas,zs,rr,thetar,zr] = EDB1coordtrans2(xsou,xrec,xwedge,nvec1) + +xneworigo = xwedge(1,:); + +xknown1 = xwedge(2,:) - xneworigo; +xknown1 = xknown1 / sqrt( sum( xknown1.^2 )); + +A = [0 1 0;0 0 1;1 0 0]*inv([xknown1.' EDB1cross(nvec1.',xknown1.') nvec1.']); + +[npoints,slask] = size(xsou); +xsou = (A*( xsou.' - xneworigo(ones(npoints,1),:).' )).'; + +rs = sqrt( sum(xsou(:,1:2).'.^2) ).'; +zs = xsou(:,3); +thetas = zeros(npoints,1); +iv = find(rs>0); +if ~isempty(iv) + thetas(iv) = real( acos( xsou(iv,1)./rs(iv) ).*( xsou(iv,2) ~= 0) ); + thetas(iv) = thetas(iv) + pi*( (xsou(iv,2)==0) & xsou(iv,1) < 0 ); + thetas(iv) = thetas(iv).*( xsou(iv,2) >=0 ) + (2*pi - thetas(iv)).*( xsou(iv,2) < 0 ); +end + +[npoints,slask] = size(xrec); +if npoints >0 + xrec = (A*( xrec.' - xneworigo(ones(npoints,1),:).' )).'; + rr = sqrt( sum(xrec(:,1:2).'.^2) ).'; + zr = xrec(:,3); + thetar = zeros(npoints,1); + iv = find(rr>0); + if ~isempty(iv), + thetar(iv) = real( acos( xrec(iv,1)./rr(iv) ).*( xrec(iv,2) ~= 0) ); + thetar(iv) = thetar(iv) + pi*( (xrec(iv,2)==0) & xrec(iv,1) < 0 ); + thetar(iv) = thetar(iv).*( xrec(iv,2) >=0 ) + (2*pi - thetar(iv)).*( xrec(iv,2) < 0 ); + end +else + rr = []; thetar =[]; zr = []; +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/private/EDB1creindexmatrix.m Sat Nov 16 18:25:24 2013 +0000 @@ -0,0 +1,51 @@ +function ivmatrix = EDB1creindexmatrix(ndivvec) +% EDB1creindeixmatrix creates a matrix with index numbers. +% +% Input parameters: +% ndivvec A matrix, [1,specorder], with the maximum counter +% number for each dimension. +% +% Output parameters: +% ivmatrix A matrix, [prod(ndivvec),specorder] of all possible +% combinations of the integers +% +% ---------------------------------------------------------------------------------------------- +% This file is part of the Edge Diffraction Toolbox by Peter Svensson. +% +% The Edge Diffraction Toolbox is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) any later version. +% +% The Edge Diffraction Toolbox is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +% FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License along with the +% Edge Diffraction Toolbox. If not, see <http://www.gnu.org/licenses/>. +% ---------------------------------------------------------------------------------------------- +% Peter Svensson (svensson@iet.ntnu.no) 20050505 +% +% ivmatrix = EDB1creindexmatrix(ndivvec) + +n = length(ndivvec); + +maxval = max(ndivvec); +if maxval > 2^32 + error(['ERROR: This version of EDB1creindexmatrix can not create such large matrics']) +end + +if n == 2 + iv1 = uint32([1:ndivvec(1)].'); + iv2 = uint32([1:ndivvec(2)]); + iv1 = iv1(:,uint8(ones(1,ndivvec(2)))); + iv2 = iv2(uint8(ones(ndivvec(1),1)),:); + + ivmatrix = [reshape(iv1.',prod(ndivvec),1) reshape(iv2.',prod(ndivvec),1)]; +elseif n >= 3 + ivmatrix = EDB1creindexmatrix(ndivvec(2:n)); + ivmatrix = repmat(ivmatrix,[ndivvec(1),1]); + ivfirstcol = uint32([1:ndivvec(1)].'); + ivfirstcol = ivfirstcol(:,uint8(ones(1,prod(ndivvec(2:n))))); + ivfirstcol = reshape(ivfirstcol.',prod(ndivvec),1); + ivmatrix = [ivfirstcol ivmatrix]; +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/private/EDB1cross.m Sat Nov 16 18:25:24 2013 +0000 @@ -0,0 +1,45 @@ +function c = EDB1cross(a,b) +% EDB1cross - Stripped down version of Matlab's built in function cross. +% +% ---------------------------------------------------------------------------------------------- +% This file is part of the Edge Diffraction Toolbox by Peter Svensson. +% +% The Edge Diffraction Toolbox is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) any later version. +% +% The Edge Diffraction Toolbox is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +% FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License along with the +% Edge Diffraction Toolbox. If not, see <http://www.gnu.org/licenses/>. +% ---------------------------------------------------------------------------------------------- +% c = EDB1cross(a,b) + +%CROSS Vector cross product. +% C = CROSS(A,B) returns the cross product of the vectors +% A and B. That is, C = A x B. A and B must be 3 element +% vectors. +% +% C = CROSS(A,B) returns the cross product of A and B along the +% first dimension of length 3. +% + +% Clay M. Thompson +% updated 12-21-94, Denise Chen +% Copyright 1984-2002 The MathWorks, Inc. +% $Revision: 5.18 $ $Date: 2002/04/09 00:29:46 $ + +% Special case: A and B are vectors +%rowvec = 0; +%if ndims(a)==2 & ndims(b)==2 +% if size(a,1)==1, a = a(:); rowvec = 1; end +% if size(b,1)==1, b = b(:); rowvec = 1; end +%end; + +% Calculate cross product +c = [a(2,:).*b(3,:)-a(3,:).*b(2,:) + a(3,:).*b(1,:)-a(1,:).*b(3,:) + a(1,:).*b(2,:)-a(2,:).*b(1,:)]; +c = reshape(c,size(a));
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/private/EDB1diff2ISES.m Sat Nov 16 18:25:24 2013 +0000 @@ -0,0 +1,1514 @@ +function [edgedifflist,startandendpoints,prespeclist,midspeclist,postspeclist,validIScoords,validIRcoords,listguide,... + listofallspecs] = EDB1diff2ISES(eddatafile,S,R,ivNdiffmatrix,... + lengthNdiffmatrix,specorder,visplanesfromR,vispartedgesfromS,vispartedgesfromR,nedgesubs,... + ndecimaldivider,edgedifflistin,postspeclistin,bigedgeweightlistin,validEDIRcoords,edgeplaneperptoplane1,edgeplaneperptoplane2) +% EDB1diff2ISES - Gives list of paths that includes a 2nd-order diff. combination. +% EDB1diff2ISES gives the list of possible diffraction paths that includes one +% second-order diffraction path, and possibly specular reflections before +% and after. +% +% Input parameters: +% eddatafile,S,R,ivNdiffmatrix,... +% lengthNdiffmatrix,specorder,visplanesfromR,vispartedgesfromS,vispartedgesfromR,nedgesubs,... +% ndecimaldivider,edgeplaneperptoplane1,edgeplaneperptoplane2 +% All these are taken from the ISEStreefile or the +% setup file. +% edgedifflistin List [nd1combs,1] of edges involved in all +% first-order diffraction combs that have already +% been found +% postspeclistin Matrix [nd1combs,specorder-1] of all specular reflections +% following the diffraction for all first-order diff combs +% that have already been found +% bigedgeweightlistin List [nd1combs,1] of visibility for edges involved in all +% first-order diffraction combs that have already been found +% validEDIRcoords Matrix [nd1combs,3] of image receiver coordinates for all +% first-order diff combs that have already been found +% GLOBAL parameters: +% POTENTIALISES,ISCOORDS,ORIGINSFROM,ISESVISIBILITY,REFLORDER See EDB1findISEStree +% SHOWTEXT JJ JJnumbofchars See EDB1mainISES +% +% Output parameters: +% edgedifflist List [ncombs,2] of the edge numbers involved in each +% spec-diff-diff-spec combination. +% startandendpoints Matrix [ncombs,4] of the relative start and end +% points of each edge. The values, [0,1], indicate +% which part of the two edges that are visible. +% prespeclist Matrix [ncombs,specorder-2] of the specular +% reflections that precede every diffraction. +% midspeclist Matrix [ncombs,specorder-2] of the specular +% reflections inbetween the two diffractions. +% postspeclist Matrix [ncombs,specorder-2] of the specular +% reflections that follow every diffraction. +% validIScoords Matrix [ncombs,3] of the image source for each +% multiple-spec that precedes the diffraction. If +% there is no spec refl before the diffraction, the +% value [0 0 0] is given. +% validIRcoords Matrix [ncombs,3] of the image receiver for each +% multiple-spec that follows the diffraction. If +% there is no spec refl after the diffraction, the +% value [0 0 0] is given. +% listguide Matrix [nuniquecombs,3] which for each row gives +% 1. The number of examples in edgefdifflist etc that +% are the same type of spec-diff-diff-spec comb. +% 2. The first row number and 3. The last row number. +% listofallspecs Matrix [nuniquecombs,3] which for each row gives +% 1. The number of pre-specular reflections for the spec-diff-spec-diff-spec comb +% in the same row in listguide. +% 2. The number of mid-specular reflections for the spec-diff-spec-diff-spec comb +% in the same row in listguide. +% 3. The number of post-specular reflections for the spec-diff-spec-diff-spec comb +% in the same row in listguide. +% +% Uses functions EDB1findis EDB1getedgepoints EDB1chkISvisible EDB1checkobstrpaths +% +% ---------------------------------------------------------------------------------------------- +% This file is part of the Edge Diffraction Toolbox by Peter Svensson. +% +% The Edge Diffraction Toolbox is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) any later version. +% +% The Edge Diffraction Toolbox is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +% FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License along with the +% Edge Diffraction Toolbox. If not, see <http://www.gnu.org/licenses/>. +% ---------------------------------------------------------------------------------------------- +% Peter Svensson (svensson@iet.ntnu.no) 20050202 +% +% [edgedifflist,startandendpoints,prespeclist,midspeclist,postspeclist,validIScoords,validIRcoords,listguide,... +% listofallspecs] = EDB1diff2ISES(eddatafile,S,R,... +% ivNdiffmatrix,lengthNdiffmatrix,specorder,visplanesfromR,vispartedgesfromS,... +% vispartedgesfromR,nedgesubs,ndecimaldivider,edgedifflistin,postspeclistin,bigedgeweightlist,validEDIRcoords,edgeplaneperptoplane1,edgeplaneperptoplane2) + +global SHOWTEXT JJ JJnumbofchars +global POTENTIALISES ISCOORDS ORIGINSFROM ISESVISIBILITY REFLORDER + +eval(['load ',eddatafile]) + +[nedges,slask] = size(planesatedge); +[nplanes,slask] = size(planecorners); +multfac = 10^(ceil(log10(max([nedges nplanes])))); + +edgedifflist = []; +prespeclist = []; +midspeclist = []; +postspeclist = []; +startandendpoints = []; +bigedgeweightlist = []; +validIScoords = []; +validIRcoords = []; + +[n1,n2] = size(POTENTIALISES); +if n2 < specorder + specorder = n2; +end + +maxvisibilityvalue = 2^nedgesubs-1; +zerosvec1 = zeros(1,specorder-2); +zerosvec2 = zeros(1,3); +listguide = zeros(specorder*2-1,3); +bitmultvec = 2.^[0:nedgesubs-1]; + +obstructtestneeded = (sum(canplaneobstruct)~=0); +onesvec = ones(1,nedgesubs); +onesvec3 = ones(1,3); + +npostspecs = sum(double(postspeclistin.'>0)).'; +planesatedge = double(planesatedge); + +if specorder >= 3 + coplanarsviaflatedge = sparse(zeros(nplanes,nplanes)); + listofflatedges = find(closwedangvec==pi); + if ~isempty(listofflatedges) + ivreftomatrix = planesatedge(listofflatedges,1) + (planesatedge(listofflatedges,2)-1)*nplanes; + coplanarsviaflatedge(ivreftomatrix) = ones(size(ivreftomatrix)); + coplanarsviaflatedge = sign(coplanarsviaflatedge + coplanarsviaflatedge.'); + end +end + +if specorder >= 4 + cateyeplanecombs = sparse(zeros(nplanes,nplanes)); + listof90edges = find(closwedangvec==3*pi/2); + if ~isempty(listof90edges) + ivreftomatrix = planesatedge(listof90edges,1) + (planesatedge(listof90edges,2)-1)*nplanes; + cateyeplanecombs(ivreftomatrix) = ones(size(ivreftomatrix)); + cateyeplanecombs = sign(cateyeplanecombs + cateyeplanecombs.'); + end + +end + +% ########################################### +% # # +% # S - edge - edge - R cases # +% # # +% ########################################### +% +% Possible edges for S-E-E-R are seen (at least partly) by the source and by the receiver. +% +% The visibility by the source is taken care of by the findISEStree +% so we must check which ones are visible by the receiver. +% Also, the active edge segment(s) must be selected but this is done +% further down together with the S-spec-spec-edge-R cases + +ivNdiff = ivNdiffmatrix(1:lengthNdiffmatrix(2),2); +ivsinglediff = ivNdiffmatrix(1:lengthNdiffmatrix(1),1); + +ivSEER = ivNdiff(find(REFLORDER(ivNdiff)==2)); + +possibleedgepairs = double(POTENTIALISES(ivSEER,1:2))-nplanes; +ivnotvisiblefromr = find(vispartedgesfromR(possibleedgepairs(:,2))==0); +if ~isempty(ivnotvisiblefromr) + possibleedgepairs(ivnotvisiblefromr,:) = []; +end + +edgedifflist = [edgedifflist;possibleedgepairs]; +bigedgeweightlist = [bigedgeweightlist;[vispartedgesfromS(edgedifflist(:,1)) vispartedgesfromR(edgedifflist(:,2))]]; + +[nedgesadded,slask] = size(edgedifflist); +zerosvec3 = zeros(nedgesadded,1); +ndiffonly = nedgesadded; + +prespeclist = [prespeclist; zerosvec3(:,ones(1,max(specorder-2,1)))]; +midspeclist = [midspeclist; zerosvec3(:,ones(1,max(specorder-2,1)))]; +postspeclist = [postspeclist; zerosvec3(:,ones(1,max(specorder-2,1)))]; +validIScoords = [validIScoords;S(ones(nedgesadded,1),:)]; +validIRcoords = [validIRcoords;R(ones(nedgesadded,1),:)]; + +if SHOWTEXT >= 3 + disp([' ',int2str(nedgesadded),' double diff valid']) +end + +% ########################################### +% # # +% # S - spec - edge - edge - R cases # +% # # +% # Prespec cases # +% # # +% ########################################### +% +% Possible edges for S-spec-E-E-R are seen (at least partly) by the receiver. +% +% The visibility doesn't need to be checked since the source-to-edge paths +% were checked in the ISEStree, and the visibility from the receiver also +% has been checked. + +% The vector ivmultidiff will always refer to the original data vector +% i.e. POTENTIALISES, ORIGINSFROM, REFLORDER etc +% +% We should remove the combinations that involve an edge which the +% receiver can not see, but since the edge number is in different columns +% we do that in the for loop. + +% The ii-loop will go through: spec-diff, spec-spec-diff +% spec-spec-spec-diff etc + +for ii = 1:specorder-2 + + if SHOWTEXT >= 3 + disp([' Checking for ',JJ(ii,1:JJnumbofchars(ii)),' spec refl before the double edge diff']) + end + + % Select the combinations where the reflection order == ii+2 + % which means ii specular reflections before the diffraction + + iv = find(REFLORDER(ivNdiff) == ii+2 & POTENTIALISES(ivNdiff,ii+1)>nplanes & POTENTIALISES(ivNdiff,ii+2)>nplanes); + masterivlist = ivNdiff(iv); + possibleedgepairs = double(POTENTIALISES(masterivlist,ii+1:ii+2)) - nplanes; + + % Keep only combinations for which the receiver can see the edge + + ivnotvisiblefromr = find(vispartedgesfromR(possibleedgepairs(:,2))==0); + if ~isempty(ivnotvisiblefromr) + masterivlist(ivnotvisiblefromr) = []; + possibleedgepairs(ivnotvisiblefromr,:) = []; + end + + possiblecombs = POTENTIALISES(masterivlist,1:ii); + + edgeweightlist = [ISESVISIBILITY(masterivlist) vispartedgesfromR(possibleedgepairs(:,2))]; + + nposs = length(masterivlist); + + if SHOWTEXT >= 3 + disp([' ',int2str(nposs),' IS+edge pairs valid']) + end + + edgedifflist = [edgedifflist;possibleedgepairs]; + prespeclist = [prespeclist;[possiblecombs zeros(nposs,specorder-2-ii)]]; + midspeclist = [midspeclist;zerosvec1(ones(nposs,1),:)]; + postspeclist = [postspeclist;zerosvec1(ones(nposs,1),:)]; + bigedgeweightlist = [bigedgeweightlist;edgeweightlist]; + + % NB! It is correct below that the indices for the ISCOORDS should be + % ORIGINSFROM(ORIGINSFROM(masterivlist)), rather than masterivlist. + % The combinations in POTENTIALISES(masterivlist,:) all have + % spec-spec-...-diff-diff combinations and then + % ISCOORDS(masterivlist,:) are zeros since a comb. that + % ends with a diff has no image source. + % Also, two recursive references are needed since we need to get back + % through the two last diffractions to reach the last specular + % reflection. + + validIScoords = [validIScoords;ISCOORDS(ORIGINSFROM(ORIGINSFROM(masterivlist)),:)]; + validIRcoords = [validIRcoords;R(ones(nposs,1),:)]; + +end + +% ####################################################################### +% ####################################################################### +% ####################################################################### +% ####################################################################### +% ####################################################################### + +% ############################################# +% # # +% # S - edge - edge -spec - R cases # +% # # +% # Postspec cases # +% # # +% ############################################# +% +% Possible edges for S-E-E-spec-spec-R are seen (at least partly) by the receiver. +% +% For some of the combos, we have the IR coords and the edge visibility +% from the single-diffraction run. For potential combos that were not +% included there, they are either invisible/obstructed or were not tested. +% We can figure out which ones were tested because they can be found in the +% POTENTIALISES under edge-spec-spec but not in the final valid list. + +% The vector masterivlist will always refer to the original data vector +% i.e. PotentialIR, OriginsfromIR, reflorderIR etc +% +% First we pick out those indices where there was a single diffraction, but +% skip those with only diffraction (because we dealt with them already). +% Also, select only those where the diffraction is the first in the sequence +% of reflections. + +for ii = 1:specorder-2 + + if SHOWTEXT >= 3 + disp([' Checking for ',JJ(ii,1:JJnumbofchars(ii)),' spec refl after the double edge diff']) + end + + % Select the combinations where the reflection order == ii+2 + % (which means ii specular reflections in addition to the diffraction) + % and where the first two columns in POTENTIALISES contain edges. + + iv = find(REFLORDER(ivNdiff) == ii+2 & POTENTIALISES(ivNdiff,1)>nplanes & POTENTIALISES(ivNdiff,2)>nplanes); + masterivlist = ivNdiff(iv); + possibleedgepairs = double(POTENTIALISES(masterivlist,1:2)) - nplanes; + possiblecombs = POTENTIALISES(masterivlist,3:2+ii); + possibleweights = ISESVISIBILITY(masterivlist); + + % Compare with those combinations that were found OK + % in the first-order diffraction step (EDB1diffISES), + % and that were input matrices to EDB1diff2ISES. + % The index vector ivOK refers to these input matrices + % (edgedifflistin,posspeclistin,validEDIRcoords,bigedgeweightlistin) + % npostspecs is a list that was calculated inside EDB1diff2ISES but + % refers to the input matrices. + + ivOK = find(npostspecs==ii); + if ~isempty(ivOK) + patternOK = [edgedifflistin(ivOK) postspeclistin(ivOK,1:ii)]; + + % Find out which ones, of all the possible first-order diffraction combos + % in POTENTIALISES, that were indeed tested and found + % invisible/obstructed in EDB1diffISES. + + ivallcombs = ivsinglediff(find( POTENTIALISES(ivsinglediff,1)>nplanes & REFLORDER(ivsinglediff) == ii+1)); + patternALL = [double(POTENTIALISES(ivallcombs,1))-nplanes double(POTENTIALISES(ivallcombs,2:1+ii))]; + if ~isempty(patternOK) & ~isempty(patternALL) + patternNOTOK = setdiff(patternALL,patternOK,'rows'); + else + if isempty(patternOK) + patternNOTOK = patternALL; + else % Then patternALL must be empty + patternNOTOK = []; + end + end + + % Now, the patterns in patternNOTOK can be removed from + % masterivlist. + + patterntocompare = [possibleedgepairs(:,2) possiblecombs(:,1:ii)]; + + ivtocancel = find(ismember(patterntocompare,patternNOTOK,'rows')); + masterivlist(ivtocancel) = []; + possibleedgepairs(ivtocancel,:) = []; + possiblecombs(ivtocancel,:) = []; + possibleweights(ivtocancel,:) = []; + patterntocompare(ivtocancel,:) = []; + + [ivcompletelyOK,ivreftoindata] = ismember(patterntocompare,patternOK,'rows'); + ivmustbechecked = find(ivcompletelyOK==0); + ivcompletelyOK = find(ivcompletelyOK); + + if ~isempty(ivmustbechecked) + masterlisttocheckmore = masterivlist(ivmustbechecked); + ntocheckmore = length(masterlisttocheckmore); + + %---------------------------------------------- + % Must carry out a visibility and obstruction check for the special + % combinations here. + % These combinations have a postspec-combination that hasn't been + % encountered in the single diffraction cases, so no visibility + % test has been made for these. + + lastedgenumbers = double(POTENTIALISES(masterlisttocheckmore,2))-nplanes; + newIRcoords = R; + reflplanesexpand = zeros(ntocheckmore*nedgesubs,ii); + for jj = 1:ii + reflplanes = POTENTIALISES(masterlisttocheckmore,3+ii-jj); + reflplanesexpand(:,jj) = reshape(reflplanes(:,onesvec).',ntocheckmore*nedgesubs,1); + newIRcoords = EDB1findis(newIRcoords,reflplanes,planeeqs,1,onesvec3); + newIRcoordsexpand = reshape(repmat(newIRcoords.',nedgesubs,1),3,ntocheckmore*nedgesubs).'; + eval(['newIRcoords',JJ(jj,1:JJnumbofchars(jj)),' = newIRcoordsexpand;']) + end + [toedgecoords,edgeweightlist,edgenumberlist] = EDB1getedgepoints(edgestartcoords(lastedgenumbers,:),edgeendcoords(lastedgenumbers,:),edgelengthvec(lastedgenumbers,:),nedgesubs); + tocoords = toedgecoords; + lastedgenumbers = lastedgenumbers(:,onesvec); + lastedgenumbers = reshape(lastedgenumbers.',ntocheckmore*nedgesubs,1); + masterlisttocheckmore = masterlisttocheckmore(:,onesvec); + masterlisttocheckmore = reshape(masterlisttocheckmore.',ntocheckmore*nedgesubs,1); + + ntocheckmore = length(masterlisttocheckmore); + if SHOWTEXT >= 3 + disp([' ',int2str(ntocheckmore),' special edge+edge+IR combinations to check']) + end + + for jj = ii:-1:1 + if length(masterlisttocheckmore) > 0 + eval(['fromcoords = newIRcoords',JJ(jj,1:JJnumbofchars(jj)),';']); + if jj < ii + eval(['tocoords = reflpoints',JJ(jj+1,1:JJnumbofchars(jj+1)),';']) + end + + [hitplanes,reflpoints,edgehits,edgehitpoints,cornerhits,cornerhitpoints] = EDB1chkISvisible(fromcoords,tocoords,planeeqs(reflplanesexpand(:,jj),4),planenvecs(reflplanesexpand(:,jj),:),minvals(reflplanesexpand(:,jj),:),... + maxvals(reflplanesexpand(:,jj),:),planecorners(reflplanesexpand(:,jj),:),corners,ncornersperplanevec(reflplanesexpand(:,jj))); + if ~isempty(edgehits) | ~isempty(cornerhits) + disp('WARNING! An edgehit or cornerhit occurred during the visibility test but this is not') + disp(' handled correctly yet.') + end + eval(['reflpoints',JJ(jj,1:JJnumbofchars(jj)),' = reflpoints;']) + + masterlisttocheckmore = masterlisttocheckmore(hitplanes); + edgeweightlist = edgeweightlist(hitplanes); + lastedgenumbers = lastedgenumbers(hitplanes); + reflplanesexpand = reflplanesexpand(hitplanes,:); + toedgecoords = toedgecoords(hitplanes,:); + + for kk = 1:ii + eval(['newIRcoords',JJ(kk,1:JJnumbofchars(kk)),' = newIRcoords',JJ(kk,1:JJnumbofchars(kk)),'(hitplanes,:);']); + if kk > jj + eval(['reflpoints',JJ(kk,1:JJnumbofchars(kk)),' = reflpoints',JJ(kk,1:JJnumbofchars(kk)),'(hitplanes,:);']); + end + end + ntocheckmore = length(masterlisttocheckmore); + + end + + if SHOWTEXT >= 3 + disp([' ',int2str(ntocheckmore),' of the special edge+edge+IR combinations survived the visibility test in refl plane ',int2str(jj)]) + end + end + + % Obstruction test of all the involved paths: R -> + % reflplane1 -> reflplane2 -> ... -> last edge + + if obstructtestneeded & ntocheckmore > 0 + + for jj = 1:ii+1 + if ntocheckmore > 0 + if jj == 1 + fromcoords = R; + startplanes = []; + else + eval(['fromcoords = reflpoints',JJ(jj-1,1:JJnumbofchars(jj-1)),';']) + startplanes = reflplanesexpand(:,jj-1); + end + if jj == ii+1, + tocoords = toedgecoords; + endplanes = [planesatedge(lastedgenumbers,1) planesatedge(lastedgenumbers,2)]; + else + eval(['tocoords = reflpoints',JJ(jj,1:JJnumbofchars(jj)),';']) + endplanes = reflplanesexpand(:,jj); + end + + [nonobstructedpaths,nobstructions] = EDB1checkobstrpaths(fromcoords,tocoords,startplanes,endplanes,canplaneobstruct,planeseesplane,... + planeeqs,planenvecs,minvals,maxvals,planecorners,corners,ncornersperplanevec,rearsideplane); + + if nobstructions > 0 + masterlisttocheckmore = masterlisttocheckmore(nonobstructedpaths); + edgeweightlist = edgeweightlist(nonobstructedpaths); + lastedgenumbers = lastedgenumbers(nonobstructedpaths); + reflplanesexpand = reflplanesexpand(nonobstructedpaths,:); + toedgecoords = toedgecoords(nonobstructedpaths,:); + for kk = 1:ii + eval(['reflpoints',JJ(kk,1:JJnumbofchars(kk)),' = reflpoints',JJ(kk,1:JJnumbofchars(kk)),'(nonobstructedpaths,:);']); + eval(['newIRcoords',JJ(kk,1:JJnumbofchars(kk)),' = newIRcoords',JJ(kk,1:JJnumbofchars(kk)),'(nonobstructedpaths,:);']); + end + + end + ntocheckmore = length(masterlisttocheckmore); + + end + + end + if SHOWTEXT >= 3 + disp([' ',int2str(ntocheckmore),' of the special edge+edge+IR combinations survived the obstruction test']) + end + + end + + % Add the found special combinations to the outdata list + + edgedifflist = [edgedifflist;double(POTENTIALISES(masterlisttocheckmore,1:2))-nplanes]; + prespeclist = [prespeclist;zerosvec1(ones(ntocheckmore,1),:)]; + midspeclist = [midspeclist;zerosvec1(ones(ntocheckmore,1),:)]; + postspeclist = [postspeclist;[reflplanesexpand zeros(ntocheckmore,specorder-2-ii)]]; + bigedgeweightlist = [bigedgeweightlist;[ ISESVISIBILITY(masterlisttocheckmore) edgeweightlist]]; + + eval(['validIRcoords = [validIRcoords;newIRcoords',JJ(ii,1:JJnumbofchars(ii)),'];']); + validIScoords = [validIScoords;S(ones(ntocheckmore,1),:)]; + + end + + masterivlist = masterivlist(ivcompletelyOK); + possibleedgepairs = possibleedgepairs(ivcompletelyOK,:); + possiblecombs = possiblecombs(ivcompletelyOK,:); + possibleweights = possibleweights(ivcompletelyOK,:); + + nposs = length(ivcompletelyOK); + + if SHOWTEXT >= 3 + disp([' ',int2str(nposs),' Edge+edge+IR segments (non-special combinations) survived the obstruction test']) + end + + % Add the found "standard" combinations to the outdata list + + edgedifflist = [edgedifflist;possibleedgepairs]; + prespeclist = [prespeclist;zerosvec1(ones(nposs,1),:)]; + midspeclist = [midspeclist;zerosvec1(ones(nposs,1),:)]; + postspeclist = [postspeclist;[possiblecombs zeros(nposs,specorder-2-ii)]]; + bigedgeweightlist = [bigedgeweightlist;[possibleweights bigedgeweightlistin(ivOK(ivreftoindata(ivcompletelyOK)))]]; + validIRcoords = [validIRcoords;validEDIRcoords(ivOK(ivreftoindata(ivcompletelyOK)),:)]; + validIScoords = [validIScoords;S(ones(nposs,1),:)]; + +end +end + + +% ####################################################################### +% ####################################################################### +% ####################################################################### +% ####################################################################### +% ####################################################################### + +% #################################################### +% # # +% # S - spec - edge - edge - spec - R cases # +% # # +% # Pre and postspec cases # +% # # +% #################################################### + + +% The ii- and jj-loops will go through all combinations of specular +% reflection before and after the double diffraction. +% +% Unlike before, we will look in the list of already found combinations +% (edgedifflist etc) + +for ii = 1:specorder-3 + + for jj = 1:specorder-ii-2 + + if SHOWTEXT >= 3 + disp([' Checking for ',JJ(ii,1:JJnumbofchars(ii)),' spec refl before and ',JJ(jj,1:JJnumbofchars(jj)),' spec refl after the double edge diff']) + end + + % Select the combinations where the reflection order == ii+jj+2 + % (which means ii+jj specular reflections in addition to the + % diffraction), and where columns ii+1 and ii+2 of POTENTIALISES + % contain edges. + + iv = find(REFLORDER(ivNdiff) == ii+jj+2 & POTENTIALISES(ivNdiff,ii+1)>nplanes & POTENTIALISES(ivNdiff,ii+2)>nplanes); + masterivlist = ivNdiff(iv); + possibleedgepairs = double(POTENTIALISES(masterivlist,ii+1:ii+2)) - nplanes; + possibleprespecs = POTENTIALISES(masterivlist,1:ii); + possiblepostspecs = POTENTIALISES(masterivlist,ii+3:ii+2+jj); + possibleweights = ISESVISIBILITY(masterivlist); + + % Compare with those that have already been found OK + ivOK = find(npostspecs==jj); + if ~isempty(ivOK) + patternOK = [edgedifflistin(ivOK) postspeclistin(ivOK,1:jj)]; + else + patternOK = []; + end + + % Find out which ones have been checked and found invisible/obstructed + ivallcombs = ivsinglediff(find( POTENTIALISES(ivsinglediff,1)>nplanes & REFLORDER(ivsinglediff) == jj+1)); + patternALL = [double(POTENTIALISES(ivallcombs,1))-nplanes double(POTENTIALISES(ivallcombs,2:1+jj))]; + if ~isempty(patternOK) & ~isempty(patternALL) + patternNOTOK = setdiff(patternALL,patternOK,'rows'); + else + if isempty(patternOK) + patternNOTOK = patternALL; + else % Then patternALL must be empty + patternNOTOK = []; + end + end + + patterntocompare = [possibleedgepairs(:,2) possiblepostspecs(:,1:jj)]; + + ivtocancel = find(ismember(patterntocompare,patternNOTOK,'rows')); + masterivlist(ivtocancel) = []; + possibleedgepairs(ivtocancel,:) = []; + possibleprespecs(ivtocancel,:) = []; + possiblepostspecs(ivtocancel,:) = []; + possibleweights(ivtocancel,:) = []; + patterntocompare(ivtocancel,:) = []; + + [ivcompletelyOK,ivreftoindata] = ismember(patterntocompare,patternOK,'rows'); + ivmustbechecked = find(ivcompletelyOK==0); + ivcompletelyOK = find(ivcompletelyOK); + if ~isempty(ivmustbechecked) + masterlisttocheckmore = masterivlist(ivmustbechecked); + ntocheckmore = length(masterlisttocheckmore); + + %---------------------------------------------- + % Must carry out a visibility and obstruction check for the special + % combinations here. + % + % NB! toedgecoords are the coordinates of the last edge in the sequence. + % This name is because for post-specular reflections, the propagation + % is viewed from the receiver towards the last edge! + + lastedgenumbers = double(POTENTIALISES(masterlisttocheckmore,ii+2))-nplanes; + newIRcoords = R; + reflplanesexpand = zeros(ntocheckmore*nedgesubs,ii); + for kk = 1:jj + reflplanes = POTENTIALISES(masterlisttocheckmore,3+ii+jj-kk); + reflplanesexpand(:,kk) = reshape(reflplanes(:,onesvec).',ntocheckmore*nedgesubs,1); + newIRcoords = EDB1findis(newIRcoords,reflplanes,planeeqs,1,onesvec3); + newIRcoordsexpand = reshape(repmat(newIRcoords.',nedgesubs,1),3,ntocheckmore*nedgesubs).'; + eval(['newIRcoords',JJ(kk,1:JJnumbofchars(kk)),' = newIRcoordsexpand;']) + end + [toedgecoords,edgeweightlist,edgenumberlist] = EDB1getedgepoints(edgestartcoords(lastedgenumbers,:),edgeendcoords(lastedgenumbers,:),edgelengthvec(lastedgenumbers,:),nedgesubs); + tocoords = toedgecoords; + lastedgenumbers = lastedgenumbers(:,onesvec); + lastedgenumbers = reshape(lastedgenumbers.',ntocheckmore*nedgesubs,1); + masterlisttocheckmore = masterlisttocheckmore(:,onesvec); + masterlisttocheckmore = reshape(masterlisttocheckmore.',ntocheckmore*nedgesubs,1); + + ntocheckmore = length(masterlisttocheckmore); + if SHOWTEXT >= 3 + disp([' ',int2str(ntocheckmore),' special IS+edge+edge+IR combinations to check']) + end + + for kk = jj:-1:1 + if length(masterlisttocheckmore) > 0 + eval(['fromcoords = newIRcoords',JJ(kk,1:JJnumbofchars(kk)),';']); + if kk < jj + eval(['tocoords = reflpoints',JJ(kk+1,1:JJnumbofchars(kk+1)),';']) + end + + [hitplanes,reflpoints,edgehits,edgehitpoints,cornerhits,cornerhitpoints] = EDB1chkISvisible(fromcoords,tocoords,planeeqs(reflplanesexpand(:,kk),4),planenvecs(reflplanesexpand(:,kk),:),minvals(reflplanesexpand(:,kk),:),... + maxvals(reflplanesexpand(:,kk),:),planecorners(reflplanesexpand(:,kk),:),corners,ncornersperplanevec(reflplanesexpand(:,kk))); + if ~isempty(edgehits) | ~isempty(cornerhits) + disp('WARNING! An edgehit or cornerhit occurred during the visibility test but this is not') + disp(' handled correctly yet.') + end + eval(['reflpoints',JJ(kk,1:JJnumbofchars(kk)),' = reflpoints;']) + + masterlisttocheckmore = masterlisttocheckmore(hitplanes); + edgeweightlist = edgeweightlist(hitplanes); + lastedgenumbers = lastedgenumbers(hitplanes); + reflplanesexpand = reflplanesexpand(hitplanes,:); + toedgecoords = toedgecoords(hitplanes,:); + + for ll = 1:jj + eval(['newIRcoords',JJ(ll,1:JJnumbofchars(ll)),' = newIRcoords',JJ(ll,1:JJnumbofchars(ll)),'(hitplanes,:);']); + if ll > kk + eval(['reflpoints',JJ(ll,1:JJnumbofchars(ll)),' = reflpoints',JJ(ll,1:JJnumbofchars(ll)),'(hitplanes,:);']); + end + end + ntocheckmore = length(masterlisttocheckmore); + + end + + if SHOWTEXT >= 3 + disp([' ',int2str(ntocheckmore),' of the special IS+edge+edge+IR combinations survived the visibility test in refl plane ',int2str(jj)]) + end + + end + + % Obstruction test of all the involved paths: R -> + % reflplane1 -> reflplane2 -> ... -> last edge + + if obstructtestneeded & ntocheckmore > 0 + + for kk = 1:jj+1 + if ntocheckmore > 0 + if kk == 1 + fromcoords = R; + startplanes = []; + else + eval(['fromcoords = reflpoints',JJ(kk-1,1:JJnumbofchars(kk-1)),';']) + startplanes = reflplanesexpand(:,kk-1); + end + if kk == jj+1, + tocoords = toedgecoords; + endplanes = [planesatedge(lastedgenumbers,1) planesatedge(lastedgenumbers,2)]; + else + eval(['tocoords = reflpoints',JJ(kk,1:JJnumbofchars(kk)),';']) + endplanes = reflplanesexpand(:,kk); + end + + [nonobstructedpaths,nobstructions] = EDB1checkobstrpaths(fromcoords,tocoords,startplanes,endplanes,canplaneobstruct,planeseesplane,... + planeeqs,planenvecs,minvals,maxvals,planecorners,corners,ncornersperplanevec,rearsideplane); + + if nobstructions > 0 + masterlisttocheckmore = masterlisttocheckmore(nonobstructedpaths); + edgeweightlist = edgeweightlist(nonobstructedpaths); + lastedgenumbers = lastedgenumbers(nonobstructedpaths); + reflplanesexpand = reflplanesexpand(nonobstructedpaths,:); + toedgecoords = toedgecoords(nonobstructedpaths,:); + for ll = 1:jj + eval(['reflpoints',JJ(ll,1:JJnumbofchars(ll)),' = reflpoints',JJ(ll,1:JJnumbofchars(ll)),'(nonobstructedpaths,:);']); + eval(['newIRcoords',JJ(ll,1:JJnumbofchars(ll)),' = newIRcoords',JJ(ll,1:JJnumbofchars(ll)),'(nonobstructedpaths,:);']); + end + + end + ntocheckmore = length(masterlisttocheckmore); + + end + + end + if SHOWTEXT >= 3 + disp([' ',int2str(ntocheckmore),' of the special IS+edge+edge+IR combinations survived the obstruction test']) + end + + end + + % Add the found special combinations to the outdata list + + edgedifflist = [edgedifflist;double(POTENTIALISES(masterlisttocheckmore,ii+1:ii+2))-nplanes]; + prespeclist = [prespeclist;[double(POTENTIALISES(masterlisttocheckmore,1:ii)) zeros(ntocheckmore,specorder-2-ii)]]; + midspeclist = [midspeclist;zerosvec1(ones(ntocheckmore,1),:)]; + postspeclist = [postspeclist;[reflplanesexpand zeros(ntocheckmore,specorder-2-ii)]]; + bigedgeweightlist = [bigedgeweightlist;[ ISESVISIBILITY(masterlisttocheckmore) edgeweightlist]]; + eval(['validIRcoords = [validIRcoords;newIRcoords',JJ(jj,1:JJnumbofchars(jj)),'];']); + % NB!! In the same way as earlier, we must a recursive reference + % method to find the image source of the last specular reflection. + ivref = ORIGINSFROM(ORIGINSFROM(ORIGINSFROM(masterlisttocheckmore))); + for kk = 2:jj + ivref = ORIGINSFROM(ivref); + end + validIScoords = [validIScoords;ISCOORDS(ivref,:)]; + end + + masterivlist = masterivlist(ivcompletelyOK); + possibleedgepairs = possibleedgepairs(ivcompletelyOK,:); + possibleprespecs = possibleprespecs(ivcompletelyOK,:); + possiblepostspecs = possiblepostspecs(ivcompletelyOK,:); + possibleweights = possibleweights(ivcompletelyOK,:); + + nposs = length(ivcompletelyOK); + + if SHOWTEXT >= 3 + disp([' ',int2str(nposs),' IS+Edge+edge+IR segments (non-special) survived the obstruction test']) + end + + % Add the found "standard" combinations to the outdata list + + edgedifflist = [edgedifflist;possibleedgepairs]; + prespeclist = [prespeclist; [possibleprespecs zeros(nposs,specorder-2-ii)]]; + midspeclist = [midspeclist;zerosvec1(ones(nposs,1),:)]; + postspeclist = [postspeclist;[possiblepostspecs zeros(nposs,specorder-2-jj)]]; + bigedgeweightlist = [bigedgeweightlist;[possibleweights bigedgeweightlistin(ivOK(ivreftoindata(ivcompletelyOK)))]]; + validIRcoords = [validIRcoords;validEDIRcoords(ivOK(ivreftoindata(ivcompletelyOK)),:)]; + % NB!! In the same way as earlier, we must a recursive reference + % method to find the image source of the last specular reflection. + ivref = ORIGINSFROM(ORIGINSFROM(ORIGINSFROM(masterivlist))); + for kk = 2:jj + ivref = ORIGINSFROM(ivref); + end + validIScoords = [validIScoords;ISCOORDS(ivref,:)]; + + end + +end + +% ####################################################################### +% ####################################################################### +% ####################################################################### +% ####################################################################### +% ####################################################################### + +% ####################################################################### +% # +% # Midspec cases, with prespecs and postspecs +% # +% # S - spec - edge - spec - edge - R +% # +% ####################################################################### + +for iipre = 0:specorder-3 + for jjmid = 1:specorder-2-iipre + for kkpost = 0:specorder-iipre-jjmid-2 + + if SHOWTEXT >= 3 + if iipre > 0 + JJpre = JJ(iipre,1:JJnumbofchars(iipre)); + else + JJpre = '0'; + end + if kkpost > 0 + JJpost = JJ(kkpost,1:JJnumbofchars(kkpost)); + else + JJpost = '0'; + end + disp([' Checking for ',JJpre,' spec refl before, ',JJ(jjmid,1:JJnumbofchars(jjmid)),' spec refl between the double edge diff, and']) + disp([' ',JJpost,' spec refl after the double edge diff.']) + end + iv = find(REFLORDER(ivNdiff) == iipre+jjmid+kkpost+2 & POTENTIALISES(ivNdiff,iipre+1)>nplanes & POTENTIALISES(ivNdiff,iipre+jjmid+2)>nplanes); + masterivlist = ivNdiff(iv); + possibleedgepairs = double(POTENTIALISES(masterivlist,[iipre+1 iipre+jjmid+2])) - nplanes; + nfast = 0; + + if kkpost == 0 + possiblepostspecs = []; + + % Keep only combinations for which the receiver can see the edge + ivnotvisiblefromr = find(vispartedgesfromR(possibleedgepairs(:,2))==0); + if ~isempty(ivnotvisiblefromr) + masterivlist(ivnotvisiblefromr) = []; + possibleedgepairs(ivnotvisiblefromr,:) = []; + end + else + possiblepostspecs = POTENTIALISES(masterivlist,iipre+jjmid+3:iipre+jjmid+2+kkpost); + + % Compare with those that have already been found OK + ivOK = find(npostspecs==kkpost); + if ~isempty(ivOK) + patternOK = [edgedifflistin(ivOK) postspeclistin(ivOK,1:kkpost)]; + else + patternOK = []; + end + % Find out which ones have been checked and found invisible/obstructed + ivallcombs = ivsinglediff(find( POTENTIALISES(ivsinglediff,1)>nplanes & REFLORDER(ivsinglediff) == kkpost+1)); + patternALL = [double(POTENTIALISES(ivallcombs,1))-nplanes double(POTENTIALISES(ivallcombs,2:1+kkpost))]; + + if ~isempty(patternOK) & ~isempty(patternALL) + patternNOTOK = setdiff(patternALL,patternOK,'rows'); + else + if isempty(patternOK) + patternNOTOK = patternALL; + else % Then patternALL must be empty + patternNOTOK = []; + end + end + + patterntocompare = [possibleedgepairs(:,2) possiblepostspecs(:,1:kkpost)]; + + if ~isempty(patternNOTOK) + ivtocancel = find(ismember(patterntocompare,patternNOTOK,'rows')); + masterivlist(ivtocancel) = []; + possibleedgepairs(ivtocancel,:) = []; + possiblepostspecs(ivtocancel,:) = []; + patterntocompare(ivtocancel,:) = []; + end + + [ivcompletelyOK,ivreftoindata] = ismember(patterntocompare,patternOK,'rows'); + ivmustbechecked = find(ivcompletelyOK==0); + ivcompletelyOK = find(ivcompletelyOK); + + if ~isempty(ivmustbechecked) & SHOWTEXT > 0 + disp('WARNING!! For midspec and postspec case, all checks have not been implemented yet!!') + end + + masterivlist = masterivlist(ivcompletelyOK); + possibleedgepairs = possibleedgepairs(ivcompletelyOK,:); + possiblepostspecs = possiblepostspecs(ivcompletelyOK,:); + + nposs = length(ivcompletelyOK); + + end + + if iipre > 0 + possibleprespecs = POTENTIALISES(masterivlist,1:iipre); + else + possibleprespecs = []; + end + + % NB!! possiblemidspecs is numbered in reverse order + % since we view the propagation by starting to mirror the last edge + % and move towards the first edge. + + possiblemidspecs = POTENTIALISES(masterivlist,iipre+1+jjmid:-1:iipre+2); + + if kkpost > 0 + edgeweightlist = [ISESVISIBILITY(masterivlist) bigedgeweightlistin(ivOK(ivreftoindata(ivcompletelyOK)))]; + else + edgeweightlist = [ISESVISIBILITY(masterivlist) vispartedgesfromR(possibleedgepairs(:,2))]; + end + + % Expand the various lists and matrices to represent the + % sub-divided edges. + + nposs = length(masterivlist); + if nposs > 0 + if iipre == 1 + possibleprespecs = reshape(possibleprespecs(:,onesvec).',nposs*nedgesubs,1); + elseif iipre > 1 + possibleprespecs = reshape(repmat(possibleprespecs.',nedgesubs,1),iipre,nposs*nedgesubs).'; + end + if jjmid == 1 + possiblemidspecs = reshape(possiblemidspecs(:,onesvec).',nposs*nedgesubs,1); + elseif jjmid > 1 + possiblemidspecs = reshape(repmat(possiblemidspecs.',nedgesubs,1),jjmid,nposs*nedgesubs).'; + end + if kkpost == 1 + possiblepostspecs = reshape(possiblepostspecs(:,onesvec).',nposs*nedgesubs,1); + elseif kkpost > 1 + possiblepostspecs = reshape(repmat(possiblepostspecs.',nedgesubs,1),kkpost,nposs*nedgesubs).'; + end + + expandedmasterivlist = reshape(masterivlist(:,onesvec).',nposs*nedgesubs,1); + if kkpost > 0 + expandedivcompletelyOK = reshape(ivcompletelyOK(:,onesvec).',nposs*nedgesubs,1); + end + + edgeweightlist = reshape(repmat(edgeweightlist.',[nedgesubs 1]),2,nposs*nedgesubs).'; + + for ll = 1:nedgesubs + edgeweightlist(ll:nedgesubs:end,1) = double(bitget(edgeweightlist(ll:nedgesubs:end,1),ll))*bitmultvec(ll); + edgeweightlist(ll:nedgesubs:end,2) = double(bitget(edgeweightlist(ll:nedgesubs:end,2),ll))*bitmultvec(ll); + end + + %---------------------------------------------- + % Must carry out a visibility and obstruction check for the + % edge-spec-edge paths + % + % NB! toedgecoords are the coordinates of the first edge in the sequence + % and fromedgecoords refers to the last edge, after the mid-specular + % reflections. + % This name is because for mid-specular reflections, the propagation + % is viewed from the last edge towards the first edge! + + [toedgecoords,firstedgeweightlist,slask] = EDB1getedgepoints(edgestartcoords(possibleedgepairs(:,2),:),edgeendcoords(possibleedgepairs(:,2),:),edgelengthvec(possibleedgepairs(:,1),:),nedgesubs); + tocoords = toedgecoords; + [fromedgecoords,lastedgeweightlist,slask] = EDB1getedgepoints(edgestartcoords(possibleedgepairs(:,1),:),edgeendcoords(possibleedgepairs(:,1),:),edgelengthvec(possibleedgepairs(:,2),:),nedgesubs); + fromcoords = fromedgecoords; + + possibleedgepairs = reshape(repmat(possibleedgepairs.',nedgesubs,1),2,nposs*nedgesubs).'; + + edgeimagecoords = fromedgecoords; + for ll = 1:jjmid + edgeimagecoords = EDB1findis(edgeimagecoords,possiblemidspecs(:,ll),planeeqs,size(fromedgecoords,1),onesvec3); + eval(['bigedgeimagecoords',JJ(ll,1:JJnumbofchars(ll)),' = edgeimagecoords;']) + end + + % Some cases do not need to be checked, when jjmid = 2: the + % cateye cases. For these, we will have doubles (both, e.g. + % 3-7 and 7-3) and one should be tossed then. The non-doubles + % can be kept in a "fast lane" so that visibility isn't + % checked, but obstruction is. + + if jjmid == 2 + specpattern = double(possiblemidspecs); + ivreftomatrix = specpattern(:,1) + ( specpattern(:,2)-1)*nplanes; + ivcateyes = find( cateyeplanecombs(ivreftomatrix) ); + + if ~isempty(ivcateyes), + specpattern = specpattern(ivcateyes,:); + fliporder = specpattern(:,2)<specpattern(:,1); + ivfliporder = find(fliporder); + specpattern(ivfliporder,:) = specpattern(ivfliporder,[2 1]); + [uniquepatterns,ivec,jvec] = unique(specpattern,'rows'); + + countcases = histc(jvec,[1:max(jvec)]); + ivtossone = find(fliporder & countcases(jvec)==nedgesubs*2); + + ivfastlane = ivcateyes; + ivfastlane(ivtossone) = []; + if ~isempty(ivfastlane) + expandedmasterivlistfast = expandedmasterivlist(ivfastlane); + possibleedgepairsfast = possibleedgepairs(ivfastlane,:); + fromedgecoordsfast = fromedgecoords(ivfastlane,:); + toedgecoordsfast = toedgecoords(ivfastlane,:); + if ~isempty(possibleprespecs) + possibleprespecsfast = possibleprespecs(ivfastlane,:); + end + possiblemidspecsfast = possiblemidspecs(ivfastlane,:); + if ~isempty(possiblepostspecs) + possiblepostspecsfast = possiblepostspecs(ivfastlane,:); + end + edgeweightlistfast = edgeweightlist(ivfastlane,:); + for mm = 1:jjmid + eval(['bigedgeimagecoords',JJ(mm,1:JJnumbofchars(mm)),'fast = bigedgeimagecoords',JJ(mm,1:JJnumbofchars(mm)),'(ivfastlane,:);']); + end + reflpoints2fast = 0.5*(bigedgeimagecoords2fast-fromedgecoordsfast) + fromedgecoordsfast; + reflpoints1fast = reflpoints2fast; + nfast = length(edgeweightlistfast); + end + + if ~isempty(ivtossone) + ivtossone = ivcateyes; + expandedmasterivlist((ivtossone)) = []; + edgeweightlist((ivtossone),:) = []; + possibleedgepairs((ivtossone),:) = []; + if ~isempty(possibleprespecs) + possibleprespecs((ivtossone),:) = []; + end + possiblemidspecs((ivtossone),:) = []; + if ~isempty(possiblepostspecs) + possiblepostspecs((ivtossone),:) = []; + end + fromcoords((ivtossone),:) = []; + tocoords((ivtossone),:) = []; + for mm = 1:jjmid + eval(['bigedgeimagecoords',JJ(mm,1:JJnumbofchars(mm)),'((ivtossone),:) = [];']); + end + nposs = length(expandedmasterivlist); + end + + end + + end + + nposs = length(expandedmasterivlist); + end + + if SHOWTEXT >= 3 + if jjmid ~= 2 + disp([' ',int2str(nposs),' edge+spec+edge combos found initially:']) + else + disp([' ',int2str(nposs),' edge+spec+edge combos found initially, + ',int2str(nfast),' cateye combos']) + end + end + + %-------------------------------------------------------------- + % Check the visibility through all the reflection planes + % + + for ll = 1:jjmid + eval(['reflpoints',JJ(ll,1:JJnumbofchars(ll)),' = [];']) + end + for ll = jjmid:-1:1 + if nposs > 0 + eval(['fromcoords = bigedgeimagecoords',JJ(ll,1:JJnumbofchars(ll)),';']) + if ll < jjmid + eval(['tocoords = reflpoints',JJ(ll+1,1:JJnumbofchars(ll+1)),';']) + end + + [hitplanes,reflpoints,edgehits,edgehitpoints,cornerhits,cornerhitpoints] = EDB1chkISvisible(fromcoords,tocoords,planeeqs(possiblemidspecs(:,ll),4),planenvecs(possiblemidspecs(:,ll),:),minvals(possiblemidspecs(:,ll),:),... + maxvals(possiblemidspecs(:,ll),:),planecorners(possiblemidspecs(:,ll),:),corners,ncornersperplanevec(possiblemidspecs(:,ll))); + + % Make a special treatment for the cases with the + % specular reflection point right on an edge since some + % of these are special cases: + % "edgeplaneperptoplane1" indicates that edge-plane-edge + % travels along the edge's plane and is reflected at a + % 90 degree corner (which is an inactive edge). + % These are treated as good hits. + % "edgeplaneperptoplane2" indicates that edge-plane-edge + % has a specular reflection right at a flat edge + % between two coplanar planes. + % These come in pairs; one half-hit in the two + % coplanar planes. Only one in each pair should be + % kept. + + if jjmid == 1 & ~isempty(edgehits) + edge1 = possibleedgepairs(edgehits,1); + edge2 = possibleedgepairs(edgehits,2); + midspec = possiblemidspecs(edgehits,1); + ivreftomatrix1 = double(midspec) + double(edge1-1)*nplanes; + ivreftomatrix2 = double(midspec) + double(edge2-1)*nplanes; + + specialhit = edgeplaneperptoplane1(ivreftomatrix1).*edgeplaneperptoplane1(ivreftomatrix1); + ivspecial = find(specialhit); + if ~isempty(ivspecial) + hitplanes = [hitplanes;edgehits(ivspecial)]; + reflpoints = [reflpoints;edgehitpoints(ivspecial,:)]; + edgehits(ivspecial) = []; + edgehitpoints(ivspecial,:) = []; + ivreftomatrix1(ivspecial) = []; + ivreftomatrix2(ivspecial) = []; + end + + specialhit = edgeplaneperptoplane2(ivreftomatrix1).*edgeplaneperptoplane2(ivreftomatrix1); + ivspecial = find(specialhit); + if ~isempty(ivspecial) + patternlist = double([possibleedgepairs(edgehits(ivspecial),1) possiblemidspecs(edgehits(ivspecial),1) possibleedgepairs(edgehits(ivspecial),1)]); + [uniquepatterns,ivec,jvec] = unique(patternlist,'rows'); + keeppattern = zeros(size(ivec)); + for mm = 1:length(ivec) + ivreftomatrix = uniquepatterns(mm,2) + (uniquepatterns(mm+1:end,2)-1)*nplanes; + coplanarindicator = coplanarsviaflatedge(ivreftomatrix); + ivcoplanars = find(uniquepatterns(mm+1:end,1)==uniquepatterns(mm,1) & uniquepatterns(mm+1:end,3)==uniquepatterns(mm,3) & coplanarindicator); + if ~isempty(ivcoplanars) + keeppattern(mm) = 1; + end + end + ivkeepers = find(keeppattern(jvec)); + hitplanes = [hitplanes;edgehits(ivspecial(ivkeepers))]; + reflpoints = [reflpoints;edgehitpoints(ivspecial(ivkeepers),:)]; + + end + end + + eval(['reflpoints',JJ(ll,1:JJnumbofchars(ll)),' = reflpoints;']) + + expandedmasterivlist = expandedmasterivlist(hitplanes); + edgeweightlist = edgeweightlist(hitplanes,:); + possibleedgepairs = possibleedgepairs(hitplanes,:); + if ~isempty(possibleprespecs) + possibleprespecs = possibleprespecs(hitplanes,:); + end + possiblemidspecs = possiblemidspecs(hitplanes,:); + if ~isempty(possiblepostspecs) + possiblepostspecs = possiblepostspecs(hitplanes,:); + end + fromedgecoords = fromedgecoords(hitplanes,:); + toedgecoords = toedgecoords(hitplanes,:); + if kkpost > 0 + expandedivcompletelyOK = expandedivcompletelyOK(hitplanes); + end + + for mm = 1:jjmid + eval(['bigedgeimagecoords',JJ(mm,1:JJnumbofchars(mm)),' = bigedgeimagecoords',JJ(mm,1:JJnumbofchars(mm)),'(hitplanes,:);']); + if mm > ll + eval(['reflpoints',JJ(mm,1:JJnumbofchars(mm)),' = reflpoints',JJ(mm,1:JJnumbofchars(mm)),'(hitplanes,:);']); + end + end + nposs = length(expandedmasterivlist); + + if SHOWTEXT >= 3 + if jjmid ~= 2 + disp([' ',int2str(nposs),' edge+spec+edge combos survived the visibility test in reflection plane ',int2str(ll)]) + else + disp([' ',int2str(nposs),' edge+spec+edge combos survived the visibility test in reflection plane ',int2str(ll),' + ',int2str(nfast),' cateye combos']) + end + end + end + end + + %-------------------------------------------------------------- + % Check for obstructions for all the paths, starting from edge number 2 + % towards edge number 1. + % + % Reinsert the "fast lane" cases, i.e., the cateye reflections. + + if jjmid == 2 + if nfast > 0, + expandedmasterivlist = [expandedmasterivlist;expandedmasterivlistfast]; + edgeweightlist = [edgeweightlist;edgeweightlistfast]; + possibleedgepairs = [possibleedgepairs;possibleedgepairsfast]; + if ~isempty(possibleprespecs) + possibleprespecs = [possibleprespecs;possibleprespecsfast]; + end + possiblemidspecs = [possiblemidspecs;possiblemidspecsfast]; + if ~isempty(possiblepostspecs) + possiblepostspecs = [possiblepostspecs;possiblepostspecsfast]; + end + fromedgecoords = [fromedgecoords;fromedgecoordsfast]; + toedgecoords = [toedgecoords;toedgecoordsfast]; + for mm = 1:jjmid + eval(['bigedgeimagecoords',JJ(mm,1:JJnumbofchars(mm)),' = [bigedgeimagecoords',JJ(mm,1:JJnumbofchars(mm)),';bigedgeimagecoords',JJ(mm,1:JJnumbofchars(mm)),'fast];']); + eval(['reflpoints',JJ(mm,1:JJnumbofchars(mm)), ' = [reflpoints',JJ(mm,1:JJnumbofchars(mm)), ';reflpoints',JJ(mm,1:JJnumbofchars(mm)),'fast];']); + end + nposs = length(expandedmasterivlist); + end + end + + if nposs > 0 & obstructtestneeded + + for ll = 1:jjmid+1 + if nposs > 0 + if ll == 1 + fromcoords = fromedgecoords; + startplanes = [planesatedge(possibleedgepairs(:,2),1) planesatedge(possibleedgepairs(:,2),2)]; + else + eval(['fromcoords = reflpoints',JJ(ll-1,1:JJnumbofchars(ll-1)),';']) + startplanes = possiblemidspecs(:,ll-1); + end + if ll == jjmid+1, + tocoords = toedgecoords; + endplanes = [planesatedge(possibleedgepairs(:,1),1) planesatedge(possibleedgepairs(:,1),2)]; + else + eval(['tocoords = reflpoints',JJ(ll,1:JJnumbofchars(ll)),';']) + endplanes = possiblemidspecs(:,ll); + end + [nonobstructedpaths,nobstructions,edgehits,cornerhits] = EDB1checkobstrpaths(fromcoords,tocoords,startplanes,endplanes,canplaneobstruct,planeseesplane,... + planeeqs,planenvecs,minvals,maxvals,planecorners,corners,ncornersperplanevec,rearsideplane); + + if ~isempty(edgehits) + nonobstructedpaths = setdiff(nonobstructedpaths,edgehits); + nobstructions = nposs - length(nonobstructedpaths); + end + + if nobstructions > 0 + expandedmasterivlist = expandedmasterivlist(nonobstructedpaths); + + edgeweightlist = edgeweightlist(nonobstructedpaths,:); + possibleedgepairs = possibleedgepairs(nonobstructedpaths,:); + if ~isempty(possibleprespecs) + possibleprespecs = possibleprespecs(nonobstructedpaths,:); + end + possiblemidspecs = possiblemidspecs(nonobstructedpaths,:); + if ~isempty(possiblepostspecs) + possiblepostspecs = possiblepostspecs(nonobstructedpaths,:); + end + fromedgecoords = fromedgecoords(nonobstructedpaths,:); + toedgecoords = toedgecoords(nonobstructedpaths,:); + if kkpost > 0 + expandedivcompletelyOK = expandedivcompletelyOK(nonobstructedpaths,:); + end + + for mm = 1:jjmid + eval(['bigedgeimagecoords',JJ(mm,1:JJnumbofchars(mm)),' = bigedgeimagecoords',JJ(mm,1:JJnumbofchars(mm)),'(nonobstructedpaths,:);']); + if mm > ll + eval(['reflpoints',JJ(mm,1:JJnumbofchars(mm)),' = reflpoints',JJ(mm,1:JJnumbofchars(mm)),'(nonobstructedpaths,:);']); + end + end + + end + nposs = length(expandedmasterivlist); + + end + end + + if SHOWTEXT >= 3 + if jjmid == 2 + disp([' ',int2str(nposs),' edge+spec+edge combos survived the obstruction test (including cateye cases)']) + else + disp([' ',int2str(nposs),' edge+spec+edge combos survived the obstruction test']) + end + end + + end + + if nposs > 0 + edgedifflist = [edgedifflist;possibleedgepairs]; + if iipre == 0 + possibleprespecs = zeros(nposs,1); + end + if specorder <= 4 + if specorder == 3 + prespeclist = [prespeclist;[possibleprespecs]]; + else + prespeclist = [prespeclist;[possibleprespecs zeros(nposs,1)]]; + end + else + [n1,n2] = size(prespeclist); + [n3,n4] = size(possibleprespecs); + if n1 > 0 +% Error found 20050202 PS +% Old wrong version prespeclist = [prespeclist;[possibleprespecs zeros(nposs,n4-n2)]]; + prespeclist = [prespeclist;[possibleprespecs zeros(nposs,n2-n4)]]; + else +% Error found 20050202 PS +% Old wrong version prespeclist = [possibleprespecs zeros(nposs,n4-n2)]; + prespeclist = [possibleprespecs zeros(nposs,n2-n4)]; + end + end + if jjmid == specorder-2 + midspeclist = [midspeclist;possiblemidspecs]; + else + midspeclist = [midspeclist;[possiblemidspecs zeros(nposs,specorder-2-jjmid) ]]; + end + if kkpost == 0 + possiblepostspecs = zeros(nposs,1); + end + if specorder <= 4 + if specorder == 3 + postspeclist = [postspeclist;[possiblepostspecs]]; + else + postspeclist = [postspeclist;[possiblepostspecs zeros(nposs,1)]]; + end + else + if kkpost == 0 + postspeclist = [postspeclist;[possiblepostspecs zeros(nposs,specorder-3)]]; + else + postspeclist = [postspeclist;[possiblepostspecs zeros(nposs,specorder-2-kkpost)]]; + end + end + bigedgeweightlist = [bigedgeweightlist;edgeweightlist]; + + % NB! It is correct below that the indices for the ISCOORDS should be + % ORIGINSFROM(ORIGINSFROM(masterivlist)), rather than masterivlist. + % The combinations in POTENTIALISES(masterivlist,:) all have + % spec-spec-...-diff-diff combinations and then + % ISCOORDS(masterivlist,:) are zeros since a comb. that + % ends with a diff has no image source. + % Also, two recursive references are needed since we need to get back + % through the two last diffractions to reach the last specular + % reflection. + + ivref = ORIGINSFROM(ORIGINSFROM(ORIGINSFROM(expandedmasterivlist))); + for kk = 2:jjmid+kkpost + ivref = ORIGINSFROM(ivref); + end + validIScoords = [validIScoords;ISCOORDS(ivref,:)]; + if kkpost == 0 + validIRcoords = [validIRcoords;R(ones(nposs,1),:)]; + else + if jjmid ~= 2 + validIRcoords = [validIRcoords;validEDIRcoords(ivOK(ivreftoindata(expandedivcompletelyOK)),:)]; + else + error(['ERROR: Calculation of IR coords for midspec = 2 and postspec not implemented yet!']); + end + end + end + end + end +end + +% ####################################################################### +% # +% # Pack the edge segments together because every little edge segment +% # is present as a separate edge +% # This can be done for all combinations at once. +% # +% ####################################################################### + +test = [prespeclist edgedifflist(:,1) midspeclist edgedifflist(:,2) postspeclist]; + +if ~isempty(test) + + [ncombs,slask] = size(edgedifflist); + dtest = diff([0;prod( double(test(1:ncombs-1,:)==test(2:ncombs,:)).' ).']); + ivremove = find(dtest==1); + + while ~isempty(ivremove) + bigedgeweightlist(ivremove+1,:) = double(bigedgeweightlist(ivremove+1,:)) + double(bigedgeweightlist(ivremove,:)); + bigedgeweightlist(ivremove,:) = []; + edgedifflist(ivremove,:) = []; + prespeclist(ivremove,:) = []; + midspeclist(ivremove,:) = []; + postspeclist(ivremove,:) = []; + validIScoords(ivremove,:) = []; + validIRcoords(ivremove,:) = []; + + test = [prespeclist edgedifflist(:,1) midspeclist edgedifflist(:,2) postspeclist]; + [ncombs,slask] = size(edgedifflist); + dtest = diff([0;prod( double(test(1:ncombs-1,:)==test(2:ncombs,:)).' ).']); + ivremove = find(dtest==1); + + end + +end + +% ####################################################################### +% # +% # The weights of the visible edge segments should be +% # translated into start and end points, together with the visibility +% # weights from the receiver. +% # This can be done for all combinations at once! +% # +% ####################################################################### + +% As a start we set the start and end values to 0 and 1, i.e. assuming full +% visibility. + +startandendpoints = [startandendpoints;... + [zeros(length(edgedifflist),1),ones(length(edgedifflist),1),... + zeros(length(edgedifflist),1),ones(length(edgedifflist),1)]]; + +% Treat edge 1 + +ivtoaccountfor = [1:size(edgedifflist,1)].'; + +ivwholeedge1 = find( bigedgeweightlist(:,1) == maxvisibilityvalue); +if ~isempty(ivwholeedge1) + ivtoaccountfor(ivwholeedge1) = []; +end + +if ~isempty(ivtoaccountfor) + ncombs = length(ivtoaccountfor); + bitpattern = zeros(ncombs,nedgesubs); + for ii=1:nedgesubs + bitpattern(:,ii) = bitget(bigedgeweightlist(ivtoaccountfor,1),ii); + end + dbit1 = diff([zeros(ncombs,1) bitpattern].').'; + dbit2 = [dbit1 -bitpattern(:,nedgesubs)]; + + nsegments = ceil((sum(abs(dbit1.')).')/2); + ivonesegments = find(nsegments==1); + + if ~isempty(ivonesegments) + + nonesegments = length(ivonesegments); + multvec = 2.^[0:nedgesubs]; + segstartpos = round(log(sum( ((dbit2(ivonesegments,:)== 1).*multvec(ones(nonesegments,1),:)).').')/log(2))+1; + segendpos = round(log(sum( ((dbit2(ivonesegments,:)==-1).*multvec(ones(nonesegments,1),:)).').')/log(2))+1; + + ivmodify = find(segstartpos==1); + segstartpos(ivmodify) = ones(size(ivmodify))*1.5; + ivmodify = find(segendpos>nedgesubs); + segendpos(ivmodify) = ones(size(ivmodify))*(nedgesubs+0.5); + + startandendpoints(ivtoaccountfor(ivonesegments),1) = (segstartpos-1.5)/(nedgesubs-1); + startandendpoints(ivtoaccountfor(ivonesegments),2) = (segendpos-1.5)/(nedgesubs-1); + + end + + % If we have some two-or-more-subsegments cases, they will be + % discovered by the if-condition below + + if length(ivonesegments) < ncombs + for nsegmentstocheck = 2:ceil(nedgesubs/2) + disp(['Checking for ',int2str(nsegmentstocheck),' sub-segments']) + ivNsegments = find(nsegments==nsegmentstocheck); + if ~isempty(ivNsegments) + [n1,n2] = size(startandendpoints); + if n2 < 4*nsegmentstocheck + startandendpoints = [startandendpoints zeros(n1,4*nsegmentstocheck-n2)]; + end + for jj = 1:length(ivNsegments) + ivstartbits = find(dbit2(ivNsegments(jj),:) == 1); + ivstartbits = (ivstartbits==1)*1.5 + (ivstartbits~=1).*ivstartbits; + ivendbits = find(dbit2(ivNsegments(jj),:) == -1); + ivendbits = (ivendbits>nedgesubs)*(nedgesubs+0.5) + (ivendbits<=nedgesubs).*ivendbits; + + for kk = 1:nsegmentstocheck, + startandendpoints(ivtoaccountfor(ivNsegments(jj)),(kk-1)*4+1) = (ivstartbits(kk)-1.5)/(nedgesubs-1); + startandendpoints(ivtoaccountfor(ivNsegments(jj)),(kk-1)*4+2) = (ivendbits(kk)-1.5)/(nedgesubs-1); + end + end + end + + end + end +end + +% Treat edge 2 + +ivtoaccountfor = [1:size(edgedifflist,1)].'; + +ivwholeedge2 = find( bigedgeweightlist(:,2) == maxvisibilityvalue); +if ~isempty(ivwholeedge2) + ivtoaccountfor(ivwholeedge2) = []; +end + +if ~isempty(ivtoaccountfor) + ncombs = length(ivtoaccountfor); + bitpattern = zeros(ncombs,nedgesubs); + for ii=1:nedgesubs + bitpattern(:,ii) = bitget(bigedgeweightlist(ivtoaccountfor,2),ii); + end + dbit1 = diff([zeros(ncombs,1) bitpattern].').'; + dbit2 = [dbit1 -bitpattern(:,nedgesubs)]; + + nsegments = ceil((sum(abs(dbit1.')).')/2); + ivonesegments = find(nsegments==1); + + if ~isempty(ivonesegments) + + nonesegments = length(ivonesegments); + multvec = 2.^[0:nedgesubs]; + segstartpos = round(log(sum( ((dbit2(ivonesegments,:)== 1).*multvec(ones(nonesegments,1),:)).').')/log(2))+1; + segendpos = round(log(sum( ((dbit2(ivonesegments,:)==-1).*multvec(ones(nonesegments,1),:)).').')/log(2))+1; + + ivmodify = find(segstartpos==1); + segstartpos(ivmodify) = ones(size(ivmodify))*1.5; + ivmodify = find(segendpos>nedgesubs); + segendpos(ivmodify) = ones(size(ivmodify))*(nedgesubs+0.5); + + startandendpoints(ivtoaccountfor(ivonesegments),3) = (segstartpos-1.5)/(nedgesubs-1); + startandendpoints(ivtoaccountfor(ivonesegments),4) = (segendpos-1.5)/(nedgesubs-1); + + end + + % If we have some two-or-more-subsegments cases, they will be + % discovered by the if-condition below + + if length(ivonesegments) < ncombs + for nsegmentstocheck = 2:ceil(nedgesubs/2) + + ivNsegments = find(nsegments==nsegmentstocheck); + if ~isempty(ivNsegments) + [n1,n2] = size(startandendpoints); + if n2 < 4*nsegmentstocheck + startandendpoints = [startandendpoints zeros(n1,4*nsegmentstocheck-n2)]; + end + for jj = 1:length(ivNsegments) + ivstartbits = find(dbit2(ivNsegments(jj),:) == 1); + ivstartbits = (ivstartbits==1)*1.5 + (ivstartbits~=1).*ivstartbits; + ivendbits = find(dbit2(ivNsegments(jj),:) == -1); + ivendbits = (ivendbits>nedgesubs)*(nedgesubs+0.5) + (ivendbits<=nedgesubs).*ivendbits; + + for kk = 1:nsegmentstocheck, + startandendpoints(ivtoaccountfor(ivNsegments(jj)),(kk-1)*4+3) = (ivstartbits(kk)-1.5)/(nedgesubs-1); + startandendpoints(ivtoaccountfor(ivNsegments(jj)),(kk-1)*4+4) = (ivendbits(kk)-1.5)/(nedgesubs-1); + end + end + end + + end + end +end + +% ####################################################################### +% # +% # Construct a list guide, which will tell which rows have only +% # dd, which rows have sdd etc +% # Syntax: dd,sdd,ssdd,sssdd,...,dds,ddss,ddsss,... +% # (should also continue with sdds, sddss,... +% # +% ####################################################################### + +[n1,n2] = size(prespeclist); +if n2 > 1 + nprespecs = sum(prespeclist.' > 0).'; +else + nprespecs = (prespeclist>0); +end +[n1,n2] = size(midspeclist); +if n2 > 1 + nmidspecs = sum(midspeclist.' > 0).'; +else + nmidspecs = (midspeclist>0); +end +[n1,n2] = size(postspeclist); +if n2 > 1 + npostspecs = sum(postspeclist.' > 0).'; +else + npostspecs = (postspeclist>0); +end + +[B,ivec,jvec] = unique([nprespecs nmidspecs npostspecs],'rows'); +nuniquecombs = length(ivec); +ntotcombs = length(jvec); + +listguide = zeros(nuniquecombs,3); +listofallspecs = zeros(nuniquecombs,3); +sortvec = zeros(ntotcombs,1); +for ii = 1:length(ivec) + ivfindcombs = find(jvec==ii); + listguide(ii,1) = length(ivfindcombs); + if ii > 1 + listguide(ii,2) = listguide(ii-1,3)+1; + else + listguide(ii,2) = 1; + end + listguide(ii,3) = listguide(ii,2)+listguide(ii,1)-1; + listofallspecs(ii,:) = [B(ii,:)]; + + sortvec(listguide(ii,2):listguide(ii,3)) = ivfindcombs; + +end + +prespeclist = prespeclist(sortvec,:); +midspeclist = midspeclist(sortvec,:); +postspeclist = postspeclist(sortvec,:); +validIScoords = validIScoords(sortvec,:); +validIRcoords = validIRcoords(sortvec,:); +edgedifflist = edgedifflist(sortvec,:); +startandendpoints = startandendpoints(sortvec,:);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/private/EDB1diffISESx.m Sat Nov 16 18:25:24 2013 +0000 @@ -0,0 +1,879 @@ +function [edgedifflist,startandendpoints,prespeclist,postspeclist,validIScoords,validIRcoords,listguide,listoforders,... + bigedgeweightlist] = EDB1diffISESx(eddatafile,S,R,... + ivsinglediff,singlediffcol,startindicessinglediff,endindicessinglediff,... + specorder,visplanesfromR,vispartedgesfromS,vispartedgesfromR,nedgesubs,ndecimaldivider,... + PointertoIRcombs,IRoriginsfrom) +% EDB1diffISESx - Gives list of paths that includes a 1st-order diff. combination. +% Gives the list of possible first-order diffraction paths, possibly with specular +% reflections before and after. +% +% Input parameters: +% eddatafile The name of the file that contains all edge related data. +% This file will be loaded. +% S,R,ivsinglediff,... +% singlediffcol,startindicessinglediff,endindicessinglediff,specorder,visplanesfromR,... +% vispartedgesfromS,vispartedgesfromR,nedgesubs,ndecimaldivider,PointertoIRcombs,IRoriginsfrom +% Data that should have been passed from the srdatafile +% (S,R,visplanesfromR,vispartedgesfromS,vispartedgesfromR +% ) +% from the ISEStreefile +% (ivsinglediff +% singlediffcol,startindicessinglediff,endindicessinglediff +% ndecimaldivider,PointertoIRcombs,IRoriginsfrom) +% and from the setupfile +% (specorder,nedgesubs) +% POTENTIALISES (global) +% ISCOORDS (global) +% ORIGINSFROM (global) +% ISESVISIBILITY (global) +% REFLORDER (global) +% +% Global parameters: +% SHOWTEXT,JJ,JJnumbofchars See EDB1mainISES +% POTENTIALISES,ISCOORDS +% +% Output parameters: +% edgedifflist List [ncombs,1] of the edge number involved in each +% spec-diff-spec combination. +% startandendpoints Matrix [ncombs,2] of the relative start and end +% points of each edge. The values, [0,1], indicate +% which part of the edge that is visible. +% prespeclist Matrix [ncombs,specorder-1] of the specular +% reflections that precede every diffraction. +% postspeclist Matrix [ncombs,specorder-1] of the specular +% reflections that follow every diffraction. +% validIScoords Matrix [ncombs,3] of the image source for each +% multiple-spec that precedes the diffraction. If +% there is no spec refl before the diffraction, the +% value [0 0 0] is given. +% validIRcoords Matrix [ncombs,3] of the image receiver for each +% multiple-spec that follows the diffraction. If +% there is no spec refl after the diffraction, the +% value [0 0 0] is given. +% listguide Matrix [nuniquecombs,3] which for each row gives +% 1. The number of examples in edgefdifflist etc that +% are the same type of spec-diff-spec comb. +% 2. The first row number and 3. The last row number. +% listoforders Matrix [nuniquecombs,2] which for each row gives +% 1. The reflection order for the spec-diff-spec comb +% in the same row in listguide. +% 2. The order of the diffraction in the +% spec-diff-spec comb. +% bigedgeweightlist List [ncombs,1] of the visibility of each edge +% expressed as a number 0 to 2^nedgesubs-1. +% +% Uses functions EDB1findis EDB1getedgepoints EDB1chkISvisible EDB1checkobstrpaths +% +% ---------------------------------------------------------------------------------------------- +% This file is part of the Edge Diffraction Toolbox by Peter Svensson. +% +% The Edge Diffraction Toolbox is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) any later version. +% +% The Edge Diffraction Toolbox is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +% FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License along with the +% Edge Diffraction Toolbox. If not, see <http://www.gnu.org/licenses/>. +% ---------------------------------------------------------------------------------------------- +% Peter Svensson (svensson@iet.ntnu.no) 20061118 +% +% [edgedifflist,startandendpoints,prespeclist,postspeclist,validIScoords,validIRcoords,listguide,listoforders,... +% bigedgeweightlist] = EDB1diffISESx(eddatafile,S,R,... +% ivsinglediff,singlediffcol,startindicessinglediff,endindicessinglediff,... +% specorder,visplanesfromR,vispartedgesfromS,vispartedgesfromR,nedgesubs,ndecimaldivider,... +% PointertoIRcombs,IRoriginsfrom) + +global SHOWTEXT JJ JJnumbofchars +global POTENTIALISES ISCOORDS ORIGINSFROM REFLORDER ISESVISIBILITY + +eval(['load ',eddatafile]) +clear edgeseesplane cornerinfrontofplane + +[nedges,slask] = size(planesatedge); +[nplanes,slask] = size(planecorners); + +edgedifflist = []; +prespeclist = []; +postspeclist = []; +startandendpoints = []; +bigedgeweightlist = []; +validIScoords = []; +validIRcoords = []; + +[n1,n2] = size(POTENTIALISES); +if n2 < specorder + specorder = n2; +end + +maxvisibilityvalue = 2^nedgesubs-1; +zerosvec1 = zeros(1,max([specorder-1 1])); +zerosvec2 = zeros(1,3); +listguide = zeros(specorder*2-1,3); +listoforders = zeros(specorder*2-1,2); + +obstructtestneeded = (sum(canplaneobstruct)~=0); +onesvec = ones(1,nedgesubs); +onesvec3 = ones(1,3); + +% ########################################### +% # # +% # S - spec-spec- edge - R cases # +% # # +% # Prespec cases # +% # # +% ########################################### +% +% Possible edges for S-spec-spec-E-R are seen (at least partly) by the receiver. +% +% The visibility doesn't need to be checked since this was done in the +% ISEStree. + +% The vector masterivlist will always refer to the original data vector +% i.e. POTENTIALISES, ORIGINSFROM, REFLORDER etc +% +% First we pick out those indices where there was a single diffraction, but +% skip those with only diffraction (because we dealt with them already). +% Also, select only those where the diffraction is the last in the sequence +% of reflections. + +for ii = 1:specorder, % NB!!! ii = 1 corresponds to zero spec. refl before the diff. + % ii = 2 corresponds to one spec refl. + % before the diff etc + + if SHOWTEXT >= 3 + if ii > 1 + disp([' Checking for ',JJ(ii-1,1:JJnumbofchars(ii-1)),' spec refl before the edge diff']) + else + disp([' Checking for 0 spec refl before the edge diff']) + end + end + + iv = uint32(startindicessinglediff(ii):endindicessinglediff(ii)); + + if ~isempty(iv) + + ivkeep = find(singlediffcol(iv)==ii); + iv = iv(ivkeep); + masterivlist = ivsinglediff(iv); + possibleedges = double(POTENTIALISES(masterivlist,ii)) - nplanes; + + % Keep only combinations for which the receiver can see the edge + + ivnotvisiblefromr = find(vispartedgesfromR(possibleedges)==0); + if ~isempty(ivnotvisiblefromr) + masterivlist(ivnotvisiblefromr) = []; + possibleedges(ivnotvisiblefromr) = []; + end + % Pick out the pre-specs + + nposs = length(masterivlist); + + if nposs > 0 + + if ii > 1 + possiblecombs = POTENTIALISES(masterivlist,1:ii-1); + reftoIScoords = ORIGINSFROM(masterivlist); + edgeweightlist = bitand((ISESVISIBILITY(masterivlist)),(vispartedgesfromR(possibleedges))); + prespeclist = [prespeclist;[possiblecombs zeros(nposs,specorder-ii)]]; + % NB! It is correct below that the indices for the IScoords should be + % ORIGINSFROM(masterivlist), rather than masterivlist. + % The combinations in POTENTIALISES(masterivlist,:) all have + % spec-spec-...-diff combinations and then + % ISCOORDS(masterivlist,:) are zeros since a comb. that + % ends with a diff has no image source. + validIScoords = [validIScoords;ISCOORDS(ORIGINSFROM(masterivlist),:)]; + else + edgeweightlist = bitand((vispartedgesfromS(possibleedges)),(vispartedgesfromR(possibleedges))); + prespeclist = [prespeclist;[zeros(nposs,max([specorder-1 1]))]]; + % For the case of no spec refl before the diffraction, we + % let the IS get the S coordinates. + validIScoords = [validIScoords;S(ones(nposs,1),:)]; + end + + if SHOWTEXT >= 3 + disp([' ',int2str(nposs),' IS+edges valid']) + end + + edgedifflist = [edgedifflist;possibleedges]; + postspeclist = [postspeclist;zerosvec1(ones(nposs,1),:)]; + bigedgeweightlist = [bigedgeweightlist;edgeweightlist]; + validIRcoords = [validIRcoords;R(ones(nposs,1),:)]; + + end + + end +end + +iv = uint32(find(bigedgeweightlist==0)); +if ~isempty(iv) + edgedifflist(iv) = []; + bigedgeweightlist(iv) = []; + prespeclist(iv,:) = []; + postspeclist(iv,:) = []; + validIScoords(iv,:) = []; + validIRcoords(iv,:) = []; +end + +% ####################################################################### +% ####################################################################### +% ####################################################################### +% ####################################################################### +% ####################################################################### + +% ############################################# +% # # +% # Build an IR tree # +% # # +% ############################################# +% +% For all cases with a specular reflection after an edge diffraction +% we build an IR tree, analogous to the IS tree + +if specorder > 1 + + if SHOWTEXT >= 3 + disp([' For the edge+spec combs, an IR tree is built']) + end + + % Select all combinations with a single diffraction, anywhere except in + % the last column, and store the useful data for these (which column + % is the diffraction, what reflection order, how many specular + % reflections?) + + ivselect = uint32(find( singlediffcol~=REFLORDER(ivsinglediff) )); + masterivlistorig = ivsinglediff(ivselect); + singlediffcol_select = singlediffcol(ivselect); + reflorder_select = REFLORDER(ivsinglediff(ivselect)); + clear ivsinglediff + nspecular_select = uint32(double(reflorder_select) - double(singlediffcol_select)); + nspecular_select_not_empty = 1; + + % Now we remove all those with a last reflection plane which can not be + % seen by the receiver + + if nplanes + nedges < 65536 + lastreflplane = uint16(zeros(length(ivselect),1)); + else + lastreflplane = uint32(zeros(length(ivselect),1)); + end + clear ivselect + for ii = 2:specorder + iv = find(reflorder_select==ii); + lastreflplane(iv) = POTENTIALISES(masterivlistorig(iv),ii); + end + ivremove = uint32(find(visplanesfromR(lastreflplane)~=2 & visplanesfromR(lastreflplane)~=4 & visplanesfromR(lastreflplane)~=5)); + if ~isempty(ivremove) + masterivlistorig(ivremove) = []; + singlediffcol_select(ivremove) = []; + reflorder_select(ivremove) = []; + nspecular_select(ivremove) = []; + lastreflplane(ivremove) = []; + clear ivremove + end + + % Start by calculating all the first-order IR coordinates for + % all the planes that are visible from the receiver + IRcoordsstart = zeros(nplanes,3); + iv = uint32(find(visplanesfromR==2 | visplanesfromR==4 | visplanesfromR==5)); + IRcoordsstart(iv,:) = EDB1findis(R,iv,planeeqs,1,onesvec3); + + bigIRcoords = (zeros(size(ISCOORDS))); + IRreflist = zeros(size(iv)); + + % IMPROVE: Not necessary to calculate the IR coordinates for all + % combinations since many are the same! + + % Now we make a temporary copy of POTENTIALISES which is displaced to + % the right since this will make it easier to align the postspec + % combos. + + PotentialISESshift = POTENTIALISES; + for ii = 2:specorder-1 + iv = uint32(find(reflorder_select==ii)); + PotentialISESshift(masterivlistorig(iv),:) = [zeros(length(iv),specorder-ii) PotentialISESshift(masterivlistorig(iv),1:ii)]; + end + + % Go through ii, which is the number of specular reflections after + % the diffraction. + + if ~isempty(nspecular_select) + for ii = 1:specorder-1 + if SHOWTEXT >= 3 + disp([' order ',int2str(ii)]) + end + + % We save the index vectors from the different orders so they can + % be reused in the next stage. + + iv = uint32(find(nspecular_select == ii)); + listselect = masterivlistorig(iv); + nlist = length(listselect); + eval(['iv',JJ(ii,1:JJnumbofchars(ii)),' = iv;']) + + if ii == 1 + bigIRcoords(listselect,:) = IRcoordsstart( PotentialISESshift(listselect,specorder),:); + + elseif ii == 2 + bigIRcoords(listselect,:) = EDB1findis(IRcoordsstart(PotentialISESshift(listselect,specorder),:),... + PotentialISESshift(listselect,specorder-1),planeeqs,nlist,onesvec3); + + elseif ii >= 3 + ivcombo = double(PotentialISESshift(listselect,specorder)); + for jj = 1:ii-2 + ivcombo = ivcombo + double(PotentialISESshift(listselect,specorder-jj))*ndecimaldivider^(jj); + end + IRreflist = PointertoIRcombs(ivcombo); + ivsimple = find(IRreflist~=0); + ivnotsimple = find(IRreflist==0); + newIRcoordssimple = EDB1findis(bigIRcoords(IRreflist(ivsimple),:),... + PotentialISESshift(listselect(ivsimple),specorder-(ii-1)),planeeqs,size(ivsimple,1),onesvec3); + newIRcoordsnotsimple = EDB1findis(IRcoordsstart(PotentialISESshift(listselect(ivnotsimple),specorder),:),... + PotentialISESshift(listselect(ivnotsimple),specorder-1),planeeqs,size(ivnotsimple,1),onesvec3); + for jj = 2:ii-1 + newIRcoordsnotsimple = EDB1findis(newIRcoordsnotsimple,... + PotentialISESshift(listselect(ivnotsimple),specorder-jj),planeeqs,size(ivnotsimple,1),onesvec3); + end + newIRcoordstoadd = zeros(length(listselect),3); + newIRcoordstoadd(ivsimple,:) = newIRcoordssimple; + newIRcoordstoadd(ivnotsimple,:) = newIRcoordsnotsimple; + bigIRcoords(listselect,:) = newIRcoordstoadd; + + end + + end + clear nspecular_select + else + nspecular_select_not_empty = 0; + end +end + +% ####################################################################### +% ####################################################################### +% ####################################################################### +% ####################################################################### +% ####################################################################### + +% ################################################## +% # # +% # S - (spec) - edge - spec - spec - R cases # +% # # +% # (Pre- and) Postspec cases # +% # # +% ################################################## +% +% Possible edges for S-E-spec-spec-R are seen (at least partly) by the receiver. +% +% The visibility must be checked, and also obstructions, but only +% for the paths between the edge and the receiver + +% The vector masterivlist will always refer to the original data vector +% i.e. PotentialIR, OriginsfromIR, reflorderIR etc +% +% First we pick out those indices where there was a single diffraction, +% which wasn't last in the sequence + +if specorder > 1 & nspecular_select_not_empty == 1 + + % The ii-value refers to the number of specular reflections after the + % diffraction + + for ii = 1:specorder-1 + + if SHOWTEXT >= 3 + disp([' Checking for ',JJ(ii,1:JJnumbofchars(ii)),' spec refl after the edge diff']) + end + + % The selection of cases with ii specular reflection after one + % diffraction have already been done, in the IR-building process. + + eval(['masterivlist = masterivlistorig(iv',JJ(ii,1:JJnumbofchars(ii)),');']) + + if nedges < 256 + possibleedges = uint8(double(PotentialISESshift(masterivlist,specorder-ii)) - nplanes); + elseif nedges < 65536 + possibleedges = uint16(double(PotentialISESshift(masterivlist,specorder-ii)) - nplanes); + else + possibleedges = uint32(double(PotentialISESshift(masterivlist,specorder-ii)) - nplanes); + end + + % NB! possiblecombs will contain the specular sequences after the + % diffraction but they appear in reversed order! + possiblecombs = PotentialISESshift(masterivlist,specorder-ii+1:specorder); + + % Specular combinations before the diffraction + nmaxprespecs = specorder-1-ii; + if nmaxprespecs == 0 + if nedges+nplanes < 256 + prespeccombs = uint8(zeros(length(masterivlist),1)); + elseif nedges+nplanes < 65536 + prespeccombs = uint16(zeros(length(masterivlist),1)); + else + prespeccombs = uint32(zeros(length(masterivlist),1)); + end + nmaxprespecs = 1; + else + prespeccombs = PotentialISESshift(masterivlist,1:nmaxprespecs); + end + % Visibility of the edge in each sequence, seen from the source + edgeweightsfromsou = ISESVISIBILITY(masterivlist); + + %-------------------------------------------------------------- + % Expand to take the edge subdivisions into account - + % treat all the edge subdivisions as separate edges for the + % visibility and obstruction test. + + nposs = length(masterivlist); + nposs = nposs*nedgesubs; + + expandedposscombs = repmat(possiblecombs,[1,nedgesubs]); + expandedposscombs = reshape(expandedposscombs.',ii,nposs).'; + + expandedprespecs = repmat(prespeccombs,[1,nedgesubs]); + expandedprespecs = reshape(expandedprespecs.',nmaxprespecs,nposs).'; + + expandededgeweightsfromsou = repmat(edgeweightsfromsou,[1,nedgesubs]); + expandededgeweightsfromsou = reshape(expandededgeweightsfromsou.',1,nposs).'; + + expandedpossedges = repmat(possibleedges,[1,nedgesubs]); + expandedpossedges = reshape(expandedpossedges.',1,nposs).'; + + expandedmasterivlist = repmat(masterivlist,[1,nedgesubs]); + expandedmasterivlist = reshape(expandedmasterivlist.',1,nposs).'; + + if SHOWTEXT >= 3 + disp([' ',int2str(nposs),' Edge+IR segments found initially ']) + end + + % Go through, iteratively, and check if the path from edge to R passes + % through all reflection planes along the way + + for jj = ii:-1:1 + + if nposs > 0 + + if jj == ii + fromcoords = full(bigIRcoords(expandedmasterivlist,:)); + [toedgecoords,edgeweightlist,edgenumberlist] = EDB1getedgepoints(edgestartcoords(possibleedges,:),edgeendcoords(possibleedges,:),edgelengthvec(possibleedges,:),nedgesubs); + tocoords = toedgecoords; + else + eval(['tocoords = reflpoints',JJ(jj+1,1:JJnumbofchars(jj+1)),';']) + startlistvec = [1:length(expandedmasterivlist)]; + ivref = IRoriginsfrom(expandedmasterivlist); + for kk = jj:ii-2 + ivnoIRexist = find(ivref==0); + if ~isempty(ivnoIRexist) + ivIRexist = startlistvec; + ivIRexist(ivnoIRexist) = []; + ivref(ivIRexist) = IRoriginsfrom(ivref(ivIRexist)); + else + ivref = IRoriginsfrom(ivref); + end + end + ivnoIRexist = find(ivref==0); + if isempty(ivnoIRexist) + fromcoords = full(bigIRcoords(ivref,:)); + else + ivIRexist = startlistvec; + ivIRexist(ivnoIRexist) = []; + fromcoords = zeros(length(ivref),3); + fromcoords(ivIRexist,:) = full(bigIRcoords(ivref(ivIRexist),:)); + + ISEScutout = PotentialISESshift(expandedmasterivlist(ivnoIRexist),specorder-ii+1:specorder); + newIRcoords = EDB1findis(R,ISEScutout(:,ii),planeeqs,1,onesvec3); + for kk = 2:jj + newIRcoords = EDB1findis(newIRcoords,ISEScutout(:,ii-kk+1),planeeqs,size(newIRcoords,1),onesvec3); + end + fromcoords(ivnoIRexist,:) = newIRcoords; + + end + + end + + colno = ii-jj+1; + + [hitplanes,reflpoints,edgehits,edgehitpoints,cornerhits,cornerhitpoints] = EDB1chkISvisible(fromcoords,tocoords,planeeqs(expandedposscombs(:,colno),4),planenvecs(expandedposscombs(:,colno),:),minvals(expandedposscombs(:,colno),:),... + maxvals(expandedposscombs(:,colno),:),planecorners(expandedposscombs(:,colno),:),corners,ncornersperplanevec(expandedposscombs(:,colno))); + if ~isempty(edgehits) | ~isempty(cornerhits) + disp('WARNING! An edgehit or cornerhit occurred during the visibility test but this is not') + disp(' handled correctly yet.') + end + eval(['reflpoints',JJ(jj,1:JJnumbofchars(jj)),' = reflpoints;']) + + expandedmasterivlist = expandedmasterivlist(hitplanes); + expandedposscombs = expandedposscombs(hitplanes,:); + expandedpossedges = expandedpossedges(hitplanes); + expandedprespecs = expandedprespecs(hitplanes,:); + edgeweightlist = edgeweightlist(hitplanes); + expandededgeweightsfromsou = expandededgeweightsfromsou(hitplanes); + toedgecoords = toedgecoords(hitplanes,:); + + if jj < ii + for kk = jj+1:ii + eval(['reflpoints',JJ(kk,1:JJnumbofchars(kk)),' = reflpoints',JJ(kk,1:JJnumbofchars(kk)),'(hitplanes,:);']) + end + end + + nposs = length(expandedmasterivlist); + + end + if SHOWTEXT >= 3 + disp([' ',int2str(nposs),' Edge+IR segments survived the visibility test in refl plane ',JJ(jj,1:JJnumbofchars(jj))]) + if SHOWTEXT >= 5 + POTENTIALISES(expandedmasterivlist,:) + end + end + + end + + if obstructtestneeded & nposs > 0 + + % Check obstructions for all the paths: edge -> plane1 -> plane2 -> ... + % -> edge (S to edge is not needed!) + for jj = 1:ii+1 + if nposs > 0 + if jj==1 + fromcoords = R; + startplanes = []; + else + startplanes = expandedposscombs(:,ii-jj+2); + eval(['fromcoords = reflpoints',JJ(jj-1,1:JJnumbofchars(jj-1)),';']) + end + if jj == ii+1 + tocoords = toedgecoords; + endplanes = [planesatedge(expandedpossedges,1) planesatedge(expandedpossedges,2)]; + else + eval(['tocoords = reflpoints',JJ(jj,1:JJnumbofchars(jj)),';']) + endplanes = expandedposscombs(:,ii-jj+1); + end + + [nonobstructedpaths,nobstructions,edgehits,cornerhits] = EDB1checkobstrpaths(fromcoords,tocoords,startplanes,endplanes,canplaneobstruct,planeseesplane,... + planeeqs,planenvecs,minvals,maxvals,planecorners,corners,ncornersperplanevec,rearsideplane); + if ~isempty(edgehits) | ~isempty(cornerhits) + disp('WARNING! An edgehit or cornerhit occurred during the obstruction test but this is not') + disp(' handled correctly yet.') + end + + if nobstructions > 0 + expandedmasterivlist = expandedmasterivlist(nonobstructedpaths); + expandedposscombs = expandedposscombs(nonobstructedpaths,:); + expandedpossedges = expandedpossedges(nonobstructedpaths); + expandedprespecs = expandedprespecs(nonobstructedpaths,:); + edgeweightlist = edgeweightlist(nonobstructedpaths); + expandededgeweightsfromsou = expandededgeweightsfromsou(nonobstructedpaths); + toedgecoords = toedgecoords(nonobstructedpaths,:); + nposs = length(expandedmasterivlist); + + for kk = 1:ii + eval(['reflpoints',JJ(kk,1:JJnumbofchars(kk)),' = reflpoints',JJ(kk,1:JJnumbofchars(kk)),'(nonobstructedpaths,:);']) + end + + end + + end + if SHOWTEXT >= 3 + disp([' ',int2str(nposs),' Edge+IR segments survived the obstruction test for path segment ',int2str(jj)]) + if SHOWTEXT >= 5 + POTENTIALISES(expandedmasterivlist,:) + end + end + end + + end + + if nposs > 0 + + % Visibility of edge segments is given by bitand-ing the + % edge visibility from the (image) source and from the receiver + + edgeweightlist = bitand(edgeweightlist,expandededgeweightsfromsou); + iv = find(edgeweightlist==0); + + if ~isempty(iv) + expandedpossedges(iv) = []; + expandedposscombs(iv,:) = []; + expandedprespecs(iv,:) = []; + edgeweightlist(iv) = []; + expandedmasterivlist(iv) = []; + nposs = length(edgeweightlist); + + end + + % Add the newly found combinations to the outdata list + + [nnew,slask] = size(expandedprespecs); + if nnew == 1 + colstoclear = find( expandedprespecs==0 ); + else + colstoclear = find(sum(expandedprespecs>0)==0); + end + if ~isempty(colstoclear) + expandedprespecs(:,colstoclear) = []; + end + + [slask,ncolsexist] = size(prespeclist); + [slask,ncolsnew] = size(expandedprespecs); + ncolstoadd = ncolsexist - ncolsnew; + if ncolstoadd > 0 + prespeclist = [prespeclist; [expandedprespecs zeros(nposs,ncolstoadd)]]; + else + prespeclist = [prespeclist; expandedprespecs]; + end + edgedifflist = [edgedifflist;expandedpossedges]; + postspeclist = [postspeclist;[expandedposscombs zeros(nposs,specorder-1-ii)]]; + bigedgeweightlist = [bigedgeweightlist;edgeweightlist]; + validIRcoords = [validIRcoords;bigIRcoords(expandedmasterivlist,:)]; + % NB! It is correct below that the indices for the ISCOORDS should be + % ORIGINSFROM(masterivlist), rather than masterivlist. + % The combinations in POTENTIALISES(masterivlist,:) all have + % spec-spec-...-diff combinations and then + % ISCOORDS(masterivlist,:) are zeros since a comb. that + % ends with a diff has no image source. + % If we have a spec-spec-...-diff-spec comb., then we must + % use ORIGINSFROM(ORIGINSFROM(masterivlist)) etc. + ivref = ORIGINSFROM(expandedmasterivlist); + for kk = 1:ii + ivref = ORIGINSFROM(ivref); + end + validIScoords = [validIScoords;ISCOORDS(ivref,:)]; + + end + end + +% clear PotentialISESshift IScoords bigIRcoords + clear PotentialISESshift bigIRcoords +end + +% ####################################################################### +% # +% # Pack the edge segments together because every little edge segment +% # is present as a separate edge +% # This can be done for all combinations at once. +% # +% ####################################################################### + +test = [prespeclist edgedifflist postspeclist]; + +if ~isempty(test) + + ncombs = length(edgedifflist); + dtest = diff([0;prod( double(test(1:ncombs-1,:)==test(2:ncombs,:)).' ).']); + ivremove = find(dtest==1); + + while ~isempty(ivremove) + bigedgeweightlist(ivremove+1) = double(bigedgeweightlist(ivremove+1)) + double(bigedgeweightlist(ivremove)); + bigedgeweightlist(ivremove) = []; + edgedifflist(ivremove) = []; + prespeclist(ivremove,:) = []; + postspeclist(ivremove,:) = []; + validIScoords(ivremove,:) = []; + validIRcoords(ivremove,:) = []; + + test = [prespeclist edgedifflist postspeclist]; + ncombs = length(edgedifflist); + dtest = diff([0;prod( double(test(1:ncombs-1,:)==test(2:ncombs,:)).' ).']); + ivremove = find(dtest==1); + end +end + +% ####################################################################### +% # +% # The weights of the visible edge segments should be +% # translated into start and end points, together with the visibility +% # weights from the receiver. +% # This can be done for all combinations at once. +% # +% ####################################################################### + +% As a start we set the start and end values to 0 and 1, i.e. assuming full +% visibility. + +if specorder >= 1 & ~isempty(edgedifflist) + startandendpoints = [startandendpoints;[zeros(length(edgedifflist),1) ones(length(edgedifflist),1)]]; + + totvisibility = bigedgeweightlist; + + ivnovisibility = find(totvisibility==0); + if ~isempty(ivnovisibility) + disp('Clearing some cases.') + edgedifflist(ivnovisibility) = []; + prespeclist(ivnovisibility,:) = []; + postspeclist(ivnovisibility,:) = []; + bigedgeweightlist(ivnovisibility) = []; + totvisibility(ivnovisibility) = []; + validIScoords(ivnovisibility,:) = []; + validIRcoords(ivnovisibility,:) = []; + end + + ivtoaccountfor = [1:length(totvisibility)].'; + + % If there are edges with full visibility we don't need to do anything to + % the start and end values, but we remove the edges from the list to + % process. + + ivwholeedges = find( totvisibility == maxvisibilityvalue); + if ~isempty(ivwholeedges) + ivtoaccountfor(ivwholeedges) = []; + end + + if ~isempty(ivtoaccountfor) + ncombs = length(ivtoaccountfor); + bitpattern = zeros(ncombs,nedgesubs); + for ii=1:nedgesubs + bitpattern(:,ii) = bitget(totvisibility(ivtoaccountfor),ii); + end + dbit1 = diff([zeros(ncombs,1) bitpattern].').'; + dbit2 = [dbit1 -bitpattern(:,nedgesubs)]; + + nsegments = ceil((sum(abs(dbit1.')).')/2); + + ivonesegments = find(nsegments==1); + if ~isempty(ivonesegments) + + nonesegments = length(ivonesegments); + multvec = 2.^[0:nedgesubs]; + segstartpos = round(log(sum( ((dbit2(ivonesegments,:)== 1).*multvec(ones(nonesegments,1),:)).').')/log(2))+1; + segendpos = round(log(sum( ((dbit2(ivonesegments,:)==-1).*multvec(ones(nonesegments,1),:)).').')/log(2))+1; + + ivmodify = find(segstartpos==1); + segstartpos(ivmodify) = ones(size(ivmodify))*1.5; + ivmodify = find(segendpos>nedgesubs); + segendpos(ivmodify) = ones(size(ivmodify))*(nedgesubs+0.5); + + startandendpoints(ivtoaccountfor(ivonesegments),1) = (segstartpos-1.5)/(nedgesubs-1); + startandendpoints(ivtoaccountfor(ivonesegments),2) = (segendpos-1.5)/(nedgesubs-1); + + end + + % If we have some two-or-more-subsegments cases, they will be + % discovered by the if-condition below + + if length(ivonesegments) < ncombs + for nsegmentstocheck = 2:ceil(nedgesubs/2) + + ivNsegments = find(nsegments==nsegmentstocheck); + if ~isempty(ivNsegments) + [n1,n2] = size(startandendpoints); + if n2 < 2*nsegmentstocheck + startandendpoints = [startandendpoints zeros(n1,2*nsegmentstocheck-n2)]; + end + for jj = 1:length(ivNsegments) + ivstartbits = find(dbit2(ivNsegments(jj),:) == 1); + ivstartbits = (ivstartbits==1)*1.5 + (ivstartbits~=1).*ivstartbits; + ivendbits = find(dbit2(ivNsegments(jj),:) == -1); + ivendbits = (ivendbits>nedgesubs)*(nedgesubs+0.5) + (ivendbits<=nedgesubs).*ivendbits; + + for kk = 1:nsegmentstocheck, + startandendpoints(ivtoaccountfor(ivNsegments(jj)),(kk-1)*2+1) = (ivstartbits(kk)-1.5)/(nedgesubs-1); + startandendpoints(ivtoaccountfor(ivNsegments(jj)),(kk-1)*2+2) = (ivendbits(kk)-1.5)/(nedgesubs-1); + end + end + end + + end + end + end +end + +% ####################################################################### +% # +% # Construct a list guide, which will tell which rows have only +% # d, which rows have sd etc +% # +% ####################################################################### + +[n1,n2] = size(prespeclist); +if n1 ~= 0 + if n2 == 0 + prespeclist = zeros(n1,1); + end + + if n2 > 1 + nprespecs = sum(prespeclist.' > 0).'; + else + nprespecs = (prespeclist>0); + end + [n1,n2] = size(postspeclist); + if n2 > 1 + npostspecs = sum(postspeclist.' > 0).'; + else + npostspecs = (postspeclist>0); + end + + listofdiffcol = 1 + nprespecs; + listofreflorder = listofdiffcol + npostspecs; + + [B,ivec,jvec] = unique([listofreflorder listofdiffcol],'rows'); + nuniquecombs = length(ivec); + ntotcombs = length(jvec); + + listguide = zeros(nuniquecombs,3); + listoforders = zeros(nuniquecombs,2); + sortvec = zeros(ntotcombs,1); + for ii = 1:length(ivec) + ivfindcombs = find(jvec==ii); + listguide(ii,1) = length(ivfindcombs); + if ii > 1 + listguide(ii,2) = listguide(ii-1,3)+1; + else + listguide(ii,2) = 1; + end + listguide(ii,3) = listguide(ii,2)+listguide(ii,1)-1; + listoforders(ii,:) = [B(ii,1) B(ii,2)]; + + sortvec(listguide(ii,2):listguide(ii,3)) = ivfindcombs; + + end + + prespeclist = prespeclist(sortvec,:); + postspeclist = postspeclist(sortvec,:); + validIScoords = validIScoords(sortvec,:); + validIRcoords = validIRcoords(sortvec,:); + edgedifflist = edgedifflist(sortvec,:); + startandendpoints = startandendpoints(sortvec,:); + bigedgeweightlist = bigedgeweightlist(sortvec,:); + + % The prespeclist needs to be shifted back to the left because it is + % "right-aligned" + + [ncombs,ncols] = size(prespeclist); + if ncols > 1 + if ncombs > 1 + iv = find( ( prespeclist(:,1)==0 ) & ( prespeclist(:,2)~=0 ) ); + if ~isempty(iv) + prespeclist(iv,1:ncols-1) = prespeclist(iv,2:ncols); + prespeclist(iv,ncols) = 0; + end + + for jj = 3:ncols + iv = find( ( sum(prespeclist(:,1:jj-1).').' == 0 ) & ( prespeclist(:,jj)~=0 ) ); + if ~isempty(iv) + prespeclist(iv,1:ncols-(jj-1)) = prespeclist(iv,jj:ncols); + prespeclist(iv,ncols-(jj-2):ncols) = 0; + end + end + else + if prespeclist(1,1) == 0, + ninitialzeros = find(diff(cumsum(prespeclist))); + if ~isempty(ninitialzeros) + ninitialzeros = ninitialzeros(1); + prespeclist(1:ncols-ninitialzeros) = prespeclist(ninitialzeros+1:ncols); + prespeclist(ncols-ninitialzeros+1:ncols) = 0; + end + end + end + end + +else + prespeclist = []; + postspeclist = []; + validIScoords = []; + validIRcoords = []; + edgedifflist = []; + startandendpoints = []; + bigedgeweightlist = []; + listguide = []; + +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/private/EDB1diffNISES.m Sat Nov 16 18:25:24 2013 +0000 @@ -0,0 +1,747 @@ +function [edgedifflist,startandendpoints,prespeclist,postspeclist,validIScoords,validIRcoords,listguide,... + listoforders] = EDB1diffNISES(eddatafile,S,R,... + ivNdiffmatrix,lengthNdiffmatrix,Ndifforder,specorder,visplanesfromR,vispartedgesfromS,... + vispartedgesfromR,nedgesubs,ndecimaldivider,edgedifflistin,postspeclistin,bigedgeweightlistin,validEDIRcoords) +% EDB1diffNISES - Gives a list of paths that includes an N-order diffraction path. +% Gives the list of visible N-diffraction paths, possibly with specular reflections before and after. +% +% Input parameters: +% eddatafile,S,R,ivsinglediff,... +% singlediffcol,startindicessinglediff,endindicessinglediff,specorder,visplanesfromR,... +% vispartedgesfromS,vispartedgesfromR,nedgesubs,ndecimaldivider,PointertoIRcombs,IRoriginsfrom; +% +% GLOBAL parameters: +% SHOWTEXT JJ JJnumbofchars See EDB1mainISES +% POTENTIALISES,ISCOORDS,ORIGINSFROM,ISESVISIBILITY,REFLORDER See EDB1findISEStree +% +% Output parameters: +% edgedifflist List [ncombs,N] of the edge numbers involved in each +% spec-diff-...-diff-spec combination. +% startandendpoints Matrix [ncombs,4] of the relative start and end +% points of each edge. The values, [0,1], indicate +% which part of the two edges that are visible. +% prespeclist Matrix [ncombs,specorder-N] of the specular +% reflections that precede every diffraction. +% postspeclist Matrix [ncombs,specorder-N] of the specular +% reflections that follow every diffraction. +% validIScoords Matrix [ncombs,3] of the image source for each +% multiple-spec that precedes the diffraction. If +% there is no spec refl before the diffraction, the +% value [0 0 0] is given. +% validIRcoords Matrix [ncombs,3] of the image receiver for each +% multiple-spec that follows the diffraction. If +% there is no spec refl after the diffraction, the +% value [0 0 0] is given. +% listguide Matrix [nuniquecombs,3] which for each row gives +% 1. The number of examples in edgefdifflist etc that +% are the same type of spec-diff-...-diff-spec comb. +% 2. The first row number and 3. The last row number. +% listoforders Matrix [nuniquecombs,2] which for each row gives +% 1. The reflection order for the spec-diff-spec comb +% in the same row in listguide. +% 2. The order of the diffraction in the +% spec-diff-...-diff-spec comb. +% +% Uses functions EDB1findis EDB1getedgepoints EDB1chkISvisible EDB1checkobstrpaths +% +% ---------------------------------------------------------------------------------------------- +% This file is part of the Edge Diffraction Toolbox by Peter Svensson. +% +% The Edge Diffraction Toolbox is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) any later version. +% +% The Edge Diffraction Toolbox is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +% FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License along with the +% Edge Diffraction Toolbox. If not, see <http://www.gnu.org/licenses/>. +% ---------------------------------------------------------------------------------------------- +% Peter Svensson (svensson@iet.ntnu.no) 20031018 +% +% [edgedifflist,startandendpoints,prespeclist,postspeclist,validIScoords,validIRcoords,... +% listguide] = EDB1diff3ISES(eddatafile,S,R,... +% ivNdiffmatrix,lengthNdiffmatrix,Ndifforder,specorder,visplanesfromR,vispartedgesfromS,... +% vispartedgesfromR,nedgesubs,ndecimaldivider,edgedifflistin,postspeclistin,bigedgeweightlist,validEDIRcoords); + +global SHOWTEXT JJ JJnumbofchars +global POTENTIALISES ISCOORDS ORIGINSFROM ISESVISIBILITY REFLORDER + +eval(['load ',eddatafile]) + +[nedges,slask] = size(planesatedge); +[nplanes,slask] = size(planecorners); +multfac = 10^(ceil(log10(max([nedges nplanes])))); + +edgedifflist = []; +prespeclist = []; +postspeclist = []; +startandendpoints = []; +bigedgeweightlist = []; +validIScoords = []; +validIRcoords = []; + +[n1,n2] = size(POTENTIALISES); +if n2 < specorder + specorder = n2; +end + +maxvisibilityvalue = 2^nedgesubs-1; +zerosvec1 = zeros(1,specorder-Ndifforder); +zerosvec2 = zeros(1,3); +listguide = zeros(specorder*2-1,3); + +obstructtestneeded = (sum(canplaneobstruct)~=0); +onesvec = ones(1,nedgesubs); +onesvec3 = ones(1,3); + +npostspecs = sum(double(postspeclistin.'>0)).'; + +% ########################################### +% # # +% # S - edge - edge - edge -R cases # +% # # +% ########################################### +% +% Possible edges for S-E-E-E-R are seen (at least partly) by the source and by the receiver. +% +% The visibility by the source is taken care of by the findISEStree +% so we must check which ones are visible by the receiver. +% Also, the active edge segment(s) must be selected but this is done +% further down together with the S-spec-spec-edge-R cases + +ivNdiff = ivNdiffmatrix(1:lengthNdiffmatrix(Ndifforder),Ndifforder); +ivsinglediff = ivNdiffmatrix(1:lengthNdiffmatrix(1),1); + +ivSEEER = ivNdiff(find(REFLORDER(ivNdiff)==Ndifforder)); + +possibleedgecombs = double(POTENTIALISES(ivSEEER,1:Ndifforder))-nplanes; +ivnotvisiblefromr = find(vispartedgesfromR(possibleedgecombs(:,Ndifforder))==0); +if ~isempty(ivnotvisiblefromr) + possibleedgecombs(ivnotvisiblefromr,:) = []; +end + +edgedifflist = [edgedifflist;possibleedgecombs]; +bigedgeweightlist = [bigedgeweightlist;[vispartedgesfromS(edgedifflist(:,1)) vispartedgesfromR(edgedifflist(:,Ndifforder))]]; + +[nedgesadded,slask] = size(edgedifflist); +zerosvec3 = zeros(nedgesadded,1); +ndiffonly = nedgesadded; + +prespeclist = [prespeclist;zerosvec3(:,ones(1,max(specorder-Ndifforder,1)))]; +postspeclist = [postspeclist;zerosvec3(:,ones(1,max(specorder-Ndifforder,1)))]; +validIScoords = [validIScoords;S(ones(nedgesadded,1),:)]; +validIRcoords = [validIRcoords;R(ones(nedgesadded,1),:)]; + +if SHOWTEXT >= 3 + disp([' ',int2str(nedgesadded),' Nth diff valid']) +end + +% ########################################### +% ########################################### +% ########################################### +% ########################################### +% # # +% # Prespec cases # +% # # +% ########################################### +% +% Possible edges for S-spec-spec-E-R are seen (at least partly) by the receiver. +% +% The visibility doesn't need to be checked since the source-to-edge paths +% were checked in the ISEStree, and the visibility from the receiver also +% has been checked. + +% The vector ivmultidiff will always refer to the original data vector +% i.e. POTENTIALISES, ORIGINSFROM, REFLORDER etc +% +% We should remove the combinations which involve an edge that the +% receiver can not see, but since the edge number is in different columns +% we do that in the for loop. + +% The ii-loop will go through: spec-diff, spec-spec-diff +% spec-spec-spec-diff etc + +for ii = 1:specorder-Ndifforder + + if SHOWTEXT >= 3 + disp([' Checking for ',JJ(ii,1:JJnumbofchars(ii)),' spec refl before the Nth edge diff']) + end + + % Select the combinations where the reflection order == ii+Ndifforder + % (which means ii specular reflections in addition to the diffraction) + % and where the last Ndifforder columns contain edges. + + iv = find((REFLORDER(ivNdiff)==ii+Ndifforder) & prod( double( POTENTIALISES(ivNdiff,ii+1:ii+Ndifforder)>nplanes).' ).' ); + masterivlist = ivNdiff(iv); + possibleedgecombs = double(POTENTIALISES(masterivlist,ii+1:ii+Ndifforder)) - nplanes; + + % Keep only combinations for which the receiver can see the edge + + ivnotvisiblefromr = find(vispartedgesfromR(possibleedgecombs(:,Ndifforder))==0); + if ~isempty(ivnotvisiblefromr) + masterivlist(ivnotvisiblefromr) = []; + possibleedgecombs = double(POTENTIALISES(masterivlist,ii+1:ii+Ndifforder)) - nplanes; + end + + possibleprespecs = POTENTIALISES(masterivlist,1:ii); + + reftoIScoords = ORIGINSFROM(masterivlist); + edgeweightlist = [ISESVISIBILITY(masterivlist) vispartedgesfromR(possibleedgecombs(:,Ndifforder))]; + + nposs = length(masterivlist); + + if SHOWTEXT >= 3 + disp([' ',int2str(nposs),' IS+edge multiples valid']) + end + + edgedifflist = [edgedifflist;possibleedgecombs]; + prespeclist = [prespeclist;[possibleprespecs zeros(nposs,specorder-Ndifforder-ii)]]; + postspeclist = [postspeclist;zeros(nposs,specorder-Ndifforder)]; + bigedgeweightlist = [bigedgeweightlist;edgeweightlist]; + % The ref. to ISCOORDS must be nested the correct number of time to + % come back to the image source coords of the last spec. refl. + ivref = ORIGINSFROM(ORIGINSFROM(ORIGINSFROM(masterivlist))); + for jj = 4:Ndifforder + ivref = ORIGINSFROM(ivref); + end + validIScoords = [validIScoords;ISCOORDS(ivref,:)]; + validIRcoords = [validIRcoords;R(ones(nposs,1),:)]; + +end + +% ####################################################################### +% ####################################################################### +% ####################################################################### +% ####################################################################### +% ####################################################################### + +% ############################################# +% # # +% # S - edge - edge -spec - R cases # +% # # +% # Postspec cases # +% # # +% ############################################# +% +% Possible edges for S-E-E-spec-spec-R are seen (at least partly) by the receiver. +% +% For some of the combos, we have the IR coords and the edge visibility +% from the single-diffraction run. For potential combos that were not +% included there, they are either invisible/obstructed or were not tested. +% We can figure out which ones were tested because they can be found in the +% POTENTIALISES under edge-spec-spec but not in the final valid list. + +% The vector masterivlist will always refer to the original data vector +% i.e. PotentialIR, ORIGINSFROMIR, reflorderIR etc +% +% First we pick out those indices where there was a single diffraction, but +% skip those with only diffraction (because we dealt with them already). +% Also, select only those where the diffraction is the first in the sequence +% of reflections. + +for ii = 1:specorder-Ndifforder + + if SHOWTEXT >= 3 + disp([' Checking for ',JJ(ii,1:JJnumbofchars(ii)),' spec refl after the multiple edge diff']) + end + + % Select the combinations where the reflection order == ii+Ndifforder + % (which means ii specular reflections in addition to the diffraction) + % and where the first Ndifforder columns contain edges. + + iv = find((REFLORDER(ivNdiff)==ii+Ndifforder) & prod( double( POTENTIALISES(ivNdiff,1:Ndifforder)>nplanes).' ).' ); + masterivlist = ivNdiff(iv); + possibleedgecombs = double(POTENTIALISES(masterivlist,1:Ndifforder)) - nplanes; + possiblepostspecs = POTENTIALISES(masterivlist,Ndifforder+1:specorder); + possibleweights = ISESVISIBILITY(masterivlist); + + % Compare with those that have already been found OK + ivOK = find(npostspecs==ii); + if ~isempty(ivOK) + patternOK = [edgedifflistin(ivOK) postspeclistin(ivOK,1:ii)]; + else + patternOK = []; + end + % Find out which ones have been checked and found invisible/obstructed + ivallcombs = ivsinglediff(find( POTENTIALISES(ivsinglediff,1)>nplanes & REFLORDER(ivsinglediff) == ii+1)); + patternALL = [double(POTENTIALISES(ivallcombs,1))-nplanes double(POTENTIALISES(ivallcombs,2:1+ii))]; + if ~isempty(patternOK) + patternNOTOK = setdiff(patternALL,patternOK,'rows'); + else + patternNOTOK = patternALL; + end + patterntocompare = [possibleedgecombs(:,Ndifforder) possiblepostspecs(:,1:ii)]; + + ivtocancel = find(ismember(patterntocompare,patternNOTOK,'rows')); + masterivlist(ivtocancel) = []; + possibleedgecombs(ivtocancel,:) = []; + possiblepostspecs(ivtocancel,:) = []; + possibleweights(ivtocancel,:) = []; + patterntocompare(ivtocancel,:) = []; + + [ivcompletelyOK,ivreftoindata] = ismember(patterntocompare,patternOK,'rows'); + ivmustbechecked = find(ivcompletelyOK==0); + ivcompletelyOK = find(ivcompletelyOK); + if ~isempty(ivmustbechecked) + masterlisttocheckmore = masterivlist(ivmustbechecked); + ntocheckmore = length(masterlisttocheckmore); + + %---------------------------------------------- + % Must carry out a visibility and obstruction check for the special + % combinations here. + % These combinations have a postspec-combination that hasn't been + % encountered in the single diffraction cases, so no visibility + % test has been made for these. + + lastedgenumbers = double(POTENTIALISES(masterlisttocheckmore,Ndifforder))-nplanes; + newIRcoords = R; + reflplanesexpand = zeros(ntocheckmore*nedgesubs,ii); + for jj = 1:ii + reflplanes = POTENTIALISES(masterlisttocheckmore,Ndifforder+1+ii-jj); + reflplanesexpand(:,jj) = reshape(reflplanes(:,onesvec).',ntocheckmore*nedgesubs,1); + newIRcoords = EDB1findis(newIRcoords,reflplanes,planeeqs,size(newIRcoords,1),onesvec3); + newIRcoordsexpand = reshape(repmat(newIRcoords.',nedgesubs,1),3,ntocheckmore*nedgesubs).'; + eval(['newIRcoords',JJ(jj,1:JJnumbofchars(jj)),' = newIRcoordsexpand;']) + end + [toedgecoords,edgeweightlist,edgenumberlist] = EDB1getedgepoints(edgestartcoords(lastedgenumbers,:),edgeendcoords(lastedgenumbers,:),edgelengthvec(lastedgenumbers,:),nedgesubs); + tocoords = toedgecoords; + lastedgenumbers = lastedgenumbers(:,onesvec); + lastedgenumbers = reshape(lastedgenumbers.',ntocheckmore*nedgesubs,1); + masterlisttocheckmore = masterlisttocheckmore(:,onesvec); + masterlisttocheckmore = reshape(masterlisttocheckmore.',ntocheckmore*nedgesubs,1); + + ntocheckmore = length(masterlisttocheckmore); + if SHOWTEXT >= 3 + disp([' ',int2str(ntocheckmore),' special N-edge - IR combinations to check']) + end + + for jj = ii:-1:1 + if length(masterlisttocheckmore) > 0 + eval(['fromcoords = newIRcoords',JJ(jj,1:JJnumbofchars(jj)),';']); + if jj < ii + eval(['tocoords = reflpoints',JJ(jj+1,1:JJnumbofchars(jj+1)),';']) + end + + [hitplanes,reflpoints,edgehits,edgehitpoints,cornerhits,cornerhitpoints] = EDB1chkISvisible(fromcoords,tocoords,planeeqs(reflplanesexpand(:,jj),4),planenvecs(reflplanesexpand(:,jj),:),minvals(reflplanesexpand(:,jj),:),... + maxvals(reflplanesexpand(:,jj),:),planecorners(reflplanesexpand(:,jj),:),corners,ncornersperplanevec(reflplanesexpand(:,jj))); + if ~isempty(edgehits) | ~isempty(cornerhits) + disp('WARNING! An edgehit or cornerhit occurred during the visibility test but this is not') + disp(' implemented.') + end + eval(['reflpoints',JJ(jj,1:JJnumbofchars(jj)),' = reflpoints;']) + + masterlisttocheckmore = masterlisttocheckmore(hitplanes); + edgeweightlist = edgeweightlist(hitplanes); + lastedgenumbers = lastedgenumbers(hitplanes); + reflplanesexpand = reflplanesexpand(hitplanes,:); + toedgecoords = toedgecoords(hitplanes,:); + + for kk = 1:ii + eval(['newIRcoords',JJ(kk,1:JJnumbofchars(kk)),' = newIRcoords',JJ(kk,1:JJnumbofchars(kk)),'(hitplanes,:);']); + if kk > jj + eval(['reflpoints',JJ(kk,1:JJnumbofchars(kk)),' = reflpoints',JJ(kk,1:JJnumbofchars(kk)),'(hitplanes,:);']); + end + end + ntocheckmore = length(masterlisttocheckmore); + + end + + if SHOWTEXT >= 3 + disp([' ',int2str(ntocheckmore),' of the special N-edge - IR combinations survived the visibility test in refl plane ',int2str(jj)]) + end + end + + if obstructtestneeded & ntocheckmore > 0 + + for jj = 1:ii+1 + if ntocheckmore > 0 + if jj == 1 + fromcoords = R; + startplanes = []; + else + eval(['fromcoords = reflpoints',JJ(jj-1,1:JJnumbofchars(jj-1)),';']) + startplanes = reflplanesexpand(:,jj-1); + end + if jj == ii+1, + tocoords = toedgecoords; + endplanes = [planesatedge(lastedgenumbers,1) planesatedge(lastedgenumbers,2)]; + else + eval(['tocoords = reflpoints',JJ(jj,1:JJnumbofchars(jj)),';']) + endplanes = reflplanesexpand(:,jj); + end + + [nonobstructedpaths,nobstructions,edgehits,cornerhits] = EDB1checkobstrpaths(fromcoords,tocoords,startplanes,endplanes,canplaneobstruct,planeseesplane,... + planeeqs,planenvecs,minvals,maxvals,planecorners,corners,ncornersperplanevec,rearsideplane); + if ~isempty(edgehits) | ~isempty(cornerhits) + disp('WARNING! An edgehit or cornerhit occurred during the obstruction test but this is not') + disp(' implemented.') + end + + if nobstructions > 0 + masterlisttocheckmore = masterlisttocheckmore(nonobstructedpaths); + edgeweightlist = edgeweightlist(nonobstructedpaths); + lastedgenumbers = lastedgenumbers(nonobstructedpaths); + reflplanesexpand = reflplanesexpand(nonobstructedpaths,:); + toedgecoords = toedgecoords(nonobstructedpaths,:); + for kk = 1:ii + eval(['reflpoints',JJ(kk,1:JJnumbofchars(kk)),' = reflpoints',JJ(kk,1:JJnumbofchars(kk)),'(nonobstructedpaths,:);']); + eval(['newIRcoords',JJ(kk,1:JJnumbofchars(kk)),' = newIRcoords',JJ(kk,1:JJnumbofchars(kk)),'(nonobstructedpaths,:);']); + end + + end + ntocheckmore = length(masterlisttocheckmore); + + end + + end + if SHOWTEXT >= 3 + disp([' ',int2str(ntocheckmore),' of the special N-edge - IR combinations survived the obstruction test']) + end + + end + + % Add the found special combinations to the outdata list + + edgedifflist = [edgedifflist;double(POTENTIALISES(masterlisttocheckmore,1:Ndifforder))-nplanes]; + prespeclist = [prespeclist;zerosvec1(ones(ntocheckmore,1),:)]; + postspeclist = [postspeclist;[reflplanesexpand zeros(ntocheckmore,specorder-Ndifforder-ii)]]; + bigedgeweightlist = [bigedgeweightlist;[ ISESVISIBILITY(masterlisttocheckmore) edgeweightlist]]; + eval(['validIRcoords = [validIRcoords;newIRcoords',JJ(ii,1:JJnumbofchars(ii)),'];']); + validIScoords = [validIScoords;S(ones(ntocheckmore,1),:)]; + + end + + masterivlist = masterivlist(ivcompletelyOK); + possibleedgecombs = possibleedgecombs(ivcompletelyOK,:); + possiblepostspecs = possiblepostspecs(ivcompletelyOK,:); + possibleweights = possibleweights(ivcompletelyOK,:); + + nposs = length(ivcompletelyOK); + + if SHOWTEXT >= 3 + disp([' ',int2str(nposs),' Edge,Nth-order + IR segments (non-special) survived the obstruction test']) + end + + % Add the found "standard" combinations to the outdata list + + edgedifflist = [edgedifflist;possibleedgecombs]; + prespeclist = [prespeclist;zeros(nposs,specorder-Ndifforder)]; + postspeclist = [postspeclist;possiblepostspecs ]; + bigedgeweightlist = [bigedgeweightlist;[possibleweights bigedgeweightlistin(ivOK(ivreftoindata(ivcompletelyOK)))]]; + validIRcoords = [validIRcoords;validEDIRcoords(ivOK(ivreftoindata(ivcompletelyOK)),:)]; + validIScoords = [validIScoords;S(ones(nposs,1),:)]; + +end + + +% ####################################################################### +% ####################################################################### +% ####################################################################### +% ####################################################################### +% ####################################################################### + +% ############################################# +% # # +% # S - spec - edge - spec - R cases # +% # #s +% # Pre and postspec cases # +% # # +% ############################################# + +% The ii- and jj-loops will go through all combinations of spec before and after +% the Ndifforder diffractions. +% +% Unlike before, we will look in the list of already found combinations +% (edgedifflist etc) + + +for ii = 1:specorder-Ndifforder-1 + + for jj = 1:specorder-ii-Ndifforder + + if SHOWTEXT >= 3 + disp([' Checking for ',JJ(ii,1:JJnumbofchars(ii)),' spec refl before and ',JJ(jj,1:JJnumbofchars(jj)),' spec refl after the N-order edge diff']) + end + + % Select the combinations where the reflection order == + % ii+jj+Ndifforder + % (which means ii+jj specular reflections in addition to the + % diffraction), and where columns ii+1:ii+Ndifforder of POTENTIALISES + % contain edges. + + iv = find((REFLORDER(ivNdiff) == ii+jj+Ndifforder) & prod( double( POTENTIALISES(ivNdiff,ii+1:ii+Ndifforder)>nplanes).' ).' ); + masterivlist = ivNdiff(iv); + possibleedgecombs = double(POTENTIALISES(masterivlist,ii+1:ii+Ndifforder)) - nplanes; + possibleprespecs = POTENTIALISES(masterivlist,1:ii); + possiblepostspecs = POTENTIALISES(masterivlist,ii+Ndifforder+1:ii+Ndifforder+jj); + possibleweights = ISESVISIBILITY(masterivlist); + + % Compare with those that have already been found OK + ivOK = find(npostspecs==jj); + if ~isempty(ivOK) + patternOK = [edgedifflistin(ivOK) postspeclistin(ivOK,1:jj)]; + else + patternOK = []; + end + + % Find out which ones have been checked and found invisible/obstructed + ivallcombs = ivsinglediff(find( POTENTIALISES(ivsinglediff,1)>nplanes & REFLORDER(ivsinglediff) == jj+1)); + patternALL = [double(POTENTIALISES(ivallcombs,1))-nplanes double(POTENTIALISES(ivallcombs,2:1+jj))]; + if ( (~isempty(patternOK)) & (~isempty(patternALL)) ) + patternNOTOK = setdiff(patternALL,patternOK,'rows'); + else + if ( (~isempty(patternOK)) ) + patternNOTOK = patternOK; + else + patternNOTOK = patternALL; + end + end + patterntocompare = [possibleedgecombs(:,Ndifforder) possiblepostspecs(:,1:jj)]; + + ivtocancel = find(ismember(patterntocompare,patternNOTOK,'rows')); + masterivlist(ivtocancel) = []; + possibleedgecombs(ivtocancel,:) = []; + possibleprespecs(ivtocancel,:) = []; + possiblepostspecs(ivtocancel,:) = []; + possibleweights(ivtocancel,:) = []; + patterntocompare(ivtocancel,:) = []; + + [ivcompletelyOK,ivreftoindata] = ismember(patterntocompare,patternOK,'rows'); + ivmustbechecked = find(ivcompletelyOK==0); + ivcompletelyOK = find(ivcompletelyOK); + if ~isempty(ivmustbechecked) + masterlisttocheckmore = masterivlist(ivmustbechecked); + ntocheckmore = length(masterlisttocheckmore); + + %---------------------------------------------- + % Must carry out a visibility and obstruction check for the special + % combinations here. + + lastedgenumbers = double(POTENTIALISES(masterlisttocheckmore,ii+Ndifforder))-nplanes; + newIRcoords = R; + reflplanesexpand = zeros(ntocheckmore*nedgesubs,ii); + for kk = 1:jj + reflplanes = POTENTIALISES(masterlisttocheckmore,Ndifforder+1+ii+jj-kk); + reflplanesexpand(:,kk) = reshape(reflplanes(:,onesvec).',ntocheckmore*nedgesubs,1); + newIRcoords = EDB1findis(newIRcoords,reflplanes,planeeqs,size(newIRcoords,1),onesvec3); + newIRcoordsexpand = reshape(repmat(newIRcoords.',nedgesubs,1),3,ntocheckmore*nedgesubs).'; + eval(['newIRcoords',JJ(kk,1:JJnumbofchars(kk)),' = newIRcoordsexpand;']) + end + [toedgecoords,edgeweightlist,edgenumberlist] = EDB1getedgepoints(edgestartcoords(lastedgenumbers,:),edgeendcoords(lastedgenumbers,:),edgelengthvec(lastedgenumbers,:),nedgesubs); + tocoords = toedgecoords; + lastedgenumbers = lastedgenumbers(:,onesvec); + lastedgenumbers = reshape(lastedgenumbers.',ntocheckmore*nedgesubs,1); + masterlisttocheckmore = masterlisttocheckmore(:,onesvec); + masterlisttocheckmore = reshape(masterlisttocheckmore.',ntocheckmore*nedgesubs,1); + + ntocheckmore = length(masterlisttocheckmore); + if SHOWTEXT >= 3 + disp([' ',int2str(ntocheckmore),' special IS - N-edge - IR combinations to check']) + end + + for kk = jj:-1:1 + if length(masterlisttocheckmore) > 0 + eval(['fromcoords = newIRcoords',JJ(kk,1:JJnumbofchars(kk)),';']); + if kk < jj + eval(['tocoords = reflpoints',JJ(kk+1,1:JJnumbofchars(kk+1)),';']) + end + + [hitplanes,reflpoints,edgehits,edgehitpoints,cornerhits,cornerhitpoints] = EDB1chkISvisible(fromcoords,tocoords,planeeqs(reflplanesexpand(:,kk),4),planenvecs(reflplanesexpand(:,kk),:),minvals(reflplanesexpand(:,kk),:),... + maxvals(reflplanesexpand(:,kk),:),planecorners(reflplanesexpand(:,kk),:),corners,ncornersperplanevec(reflplanesexpand(:,kk))); + if ~isempty(edgehits) | ~isempty(cornerhits) + disp('WARNING! An edgehit or cornerhit occurred during the visibility test but this is not') + disp(' implemented.') + end + eval(['reflpoints',JJ(kk,1:JJnumbofchars(kk)),' = reflpoints;']) + + masterlisttocheckmore = masterlisttocheckmore(hitplanes); + edgeweightlist = edgeweightlist(hitplanes); + lastedgenumbers = lastedgenumbers(hitplanes); + reflplanesexpand = reflplanesexpand(hitplanes,:); + toedgecoords = toedgecoords(hitplanes,:); + + for ll = 1:jj + eval(['newIRcoords',JJ(ll,1:JJnumbofchars(ll)),' = newIRcoords',JJ(ll,1:JJnumbofchars(ll)),'(hitplanes,:);']); + if ll > kk + eval(['reflpoints',JJ(ll,1:JJnumbofchars(ll)),' = reflpoints',JJ(ll,1:JJnumbofchars(ll)),'(hitplanes,:);']); + end + end + ntocheckmore = length(masterlisttocheckmore); + + end + + if SHOWTEXT >= 3 + disp([' ',int2str(ntocheckmore),' of the special IS - N-edge - IR combinations survived the visibility test in refl plane ',int2str(kk)]) + end + + end + + % Obstruction test of all the involved paths: R -> + % reflplane1 -> reflplane2 -> ... -> last edge + + if obstructtestneeded & ntocheckmore > 0 + + for kk = 1:jj+1 + if ntocheckmore > 0 + if kk == 1 + fromcoords = R; + startplanes = []; + else + eval(['fromcoords = reflpoints',JJ(kk-1,1:JJnumbofchars(kk-1)),';']) + startplanes = reflplanesexpand(:,kk-1); + end + if kk == jj+1, + tocoords = toedgecoords; + endplanes = [planesatedge(lastedgenumbers,1) planesatedge(lastedgenumbers,2)]; + else + eval(['tocoords = reflpoints',JJ(kk,1:JJnumbofchars(kk)),';']) + endplanes = reflplanesexpand(:,kk); + end + + [nonobstructedpaths,nobstructions] = EDB1checkobstrpaths(fromcoords,tocoords,startplanes,endplanes,canplaneobstruct,planeseesplane,... + planeeqs,planenvecs,minvals,maxvals,planecorners,corners,ncornersperplanevec,rearsideplane); + + if nobstructions > 0 + masterlisttocheckmore = masterlisttocheckmore(nonobstructedpaths); + edgeweightlist = edgeweightlist(nonobstructedpaths); + lastedgenumbers = lastedgenumbers(nonobstructedpaths); + reflplanesexpand = reflplanesexpand(nonobstructedpaths,:); + toedgecoords = toedgecoords(nonobstructedpaths,:); + for ll = 1:jj + eval(['reflpoints',JJ(ll,1:JJnumbofchars(ll)),' = reflpoints',JJ(ll,1:JJnumbofchars(ll)),'(nonobstructedpaths,:);']); + eval(['newIRcoords',JJ(ll,1:JJnumbofchars(ll)),' = newIRcoords',JJ(ll,1:JJnumbofchars(ll)),'(nonobstructedpaths,:);']); + end + + end + ntocheckmore = length(masterlisttocheckmore); + + end + + end + if SHOWTEXT >= 3 + disp([' ',int2str(ntocheckmore),' of the special IS - N-edge - IR combinations survived the obstruction test']) + end + + end + + % Add the found special combinations to the outdata list + + edgedifflist = [edgedifflist;double(POTENTIALISES(masterlisttocheckmore,ii+1:ii+Ndifforder))-nplanes]; + prespeclist = [prespeclist;[double(POTENTIALISES(masterlisttocheckmore,1:ii)) zeros(ntocheckmore,specorder-Ndifforder-ii)]]; + postspeclist = [postspeclist;[reflplanesexpand zeros(ntocheckmore,specorder-Ndifforder-ii)]]; + bigedgeweightlist = [bigedgeweightlist;[ ISESVISIBILITY(masterlisttocheckmore) edgeweightlist]]; + eval(['validIRcoords = [validIRcoords;newIRcoords',JJ(jj,1:JJnumbofchars(jj)),'];']); + % NB!! In the same way as earlier, we must a recursive reference + % method to find the image source of the last specular reflection. + ivref = ORIGINSFROM(ORIGINSFROM(ORIGINSFROM(masterlisttocheckmore))); + for kk = 2:jj + ivref = ORIGINSFROM(ivref); + end + validIScoords = [validIScoords;ISCOORDS(ivref,:)]; + + end + + masterivlist = masterivlist(ivcompletelyOK); + possibleedgecombs = possibleedgecombs(ivcompletelyOK,:); + possibleprespecs = possibleprespecs(ivcompletelyOK,:); + possiblepostspecs = possiblepostspecs(ivcompletelyOK,:); + possibleweights = possibleweights(ivcompletelyOK,:); + + nposs = length(ivcompletelyOK); + + if SHOWTEXT >= 3 + disp([' ',int2str(nposs),' IS + Edge (Nth-order) + IR segments (non-special combinations) survived the obstruction test']) + end + + % Add the found "standard" combinations to the outdata list + + edgedifflist = [edgedifflist;possibleedgecombs]; + prespeclist = [prespeclist; [possibleprespecs zeros(nposs,specorder-Ndifforder-ii)]]; + postspeclist = [postspeclist;[possiblepostspecs zeros(nposs,specorder-Ndifforder-jj)]]; + bigedgeweightlist = [bigedgeweightlist;[possibleweights bigedgeweightlistin(ivOK(ivreftoindata(ivcompletelyOK)))]]; + validIRcoords = [validIRcoords;validEDIRcoords(ivOK(ivreftoindata(ivcompletelyOK)),:)]; + % NB!! In the same way as earlier, we must a recursive reference + % method to find the image source of the last specular reflection. + ivref = ORIGINSFROM(ORIGINSFROM(ORIGINSFROM(ORIGINSFROM(ORIGINSFROM(masterivlist))))); + for kk = 6:jj+Ndifforder + ivref = ORIGINSFROM(ivref); + end + validIScoords = [validIScoords;ISCOORDS(ivref,:)]; + + end +end + + +% ####################################################################### +% # +% # The weights of the visible edge segments should be +% # translated into start and end points, together with the visibility +% # weights from the receiver. +% # This can be done for all combinations at once! +% # +% ####################################################################### + +% As a start we set the start and end values to 0 and 1, i.e. assuming full +% visibility. + +addvec = []; +for ii = 1:Ndifforder + addvec = [addvec,zeros(length(edgedifflist),1),ones(length(edgedifflist),1)]; +end +startandendpoints = [startandendpoints addvec]; + +% ####################################################################### +% # +% # Construct a list guide, which will tell which rows have only +% # dd, which rows have sdd etc +% # Syntax: dd,sdd,ssdd,sssdd,...,dds,ddss,ddsss,... +% # (should also continue with sdds, sddss,... +% # +% ####################################################################### + +[n1,n2] = size(prespeclist); +if n2 > 1 + nprespecs = sum(prespeclist.' > 0).'; +else + nprespecs = (prespeclist>0); +end +[n1,n2] = size(postspeclist); +if n2 > 1 + npostspecs = sum(postspeclist.' > 0).'; +else + npostspecs = (postspeclist>0); +end + +listofdiffcol = 1 + nprespecs; +listofreflorder = listofdiffcol + npostspecs + Ndifforder - 1; + +[B,ivec,jvec] = unique([listofreflorder listofdiffcol],'rows'); +nuniquecombs = length(ivec); +ntotcombs = length(jvec); + +listguide = zeros(nuniquecombs,3); +listoforders = zeros(nuniquecombs,2); +sortvec = zeros(ntotcombs,1); +for ii = 1:length(ivec) + ivfindcombs = find(jvec==ii); + listguide(ii,1) = length(ivfindcombs); + if ii > 1 + listguide(ii,2) = listguide(ii-1,3)+1; + else + listguide(ii,2) = 1; + end + listguide(ii,3) = listguide(ii,2)+listguide(ii,1)-1; + listoforders(ii,:) = [B(ii,1) B(ii,2)]; + + sortvec(listguide(ii,2):listguide(ii,3)) = ivfindcombs; + +end + +prespeclist = prespeclist(sortvec,:); +postspeclist = postspeclist(sortvec,:); +validIScoords = validIScoords(sortvec,:); +validIRcoords = validIRcoords(sortvec,:); +edgedifflist = edgedifflist(sortvec,:); +startandendpoints = startandendpoints(sortvec,:);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/private/EDB1directsound.m Sat Nov 16 18:25:24 2013 +0000 @@ -0,0 +1,79 @@ +function dirsoundok = EDB1directsound(eddatafile,S,R,visplanesfroms,visplanesfromr) +% EDB1directsound - Checks if the direct sound is valid. +% Checks if the direct sound path from a number of source +% points to a number of receiver points are obstructed by any planes. +% +% Input parameters: +% eddatafile The name of the file that contains all edge related data. +% This file will be loaded. +% S, R, visplanesfroms, visplanesfromr +% Data that should have been passed directly from the +% srdatafile. +% +% Global parameter: +% SHOWTEXT See EDB1mainISES +% +% Output parameter: +% dirsoundok 1 or 0, telling if the sound path is unobstructed or not. +% +% ---------------------------------------------------------------------------------------------- +% This file is part of the Edge Diffraction Toolbox by Peter Svensson. +% +% The Edge Diffraction Toolbox is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) any later version. +% +% The Edge Diffraction Toolbox is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +% FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License along with the +% Edge Diffraction Toolbox. If not, see <http://www.gnu.org/licenses/>. +% ---------------------------------------------------------------------------------------------- +% Peter Svensson (svensson@iet.ntnu.no) 20030929 +% +% Uses the function EDB1chkISvisible +% +% dirsoundok = EDB1directsound(eddatafile,S,R,visplanesfroms,visplanesfromr); + +global SHOWTEXT + +eval(['load ',eddatafile]) + +[ncorners,slask] = size(corners); +[nplanes,ncornersperplane] = size(planecorners); + +%---------------------------------------------------------- +% Check if the direct sound is obscured +% +% Pick out the planes that are possible. Only potentially obstructing planes are necessary to check. +% Planes that are seen by the source or by the receiver, but not both +% are potentially obstructing. + +planesareseen = full( (double(visplanesfroms)==0 | double(visplanesfromr)==0) & (double(visplanesfroms)+double(visplanesfromr)~=0) ); +planestocheck = find(planesareseen.*canplaneobstruct.'); +nplanestocheck = length(planestocheck); +onesvec = ones(nplanestocheck,1); + +[hitplanes,reflpoints,edgehits,edgehitpoints,cornerhits,cornerhitpoints] = EDB1chkISvisible(S(onesvec,:),R(onesvec,:),planeeqs(planestocheck,4),planenvecs(planestocheck,:),minvals(planestocheck,:),... + maxvals(planestocheck,:),planecorners(planestocheck,:),corners,ncornersperplanevec(planestocheck)); + +if isempty(hitplanes) + dirsoundok = 1; + if SHOWTEXT >= 3 + disp(' direct sound OK') + end +else + dirsoundok = 0; + if SHOWTEXT >= 3 + disp(' direct sound obscured') + if SHOWTEXT >= 4, + printvec = int2str(planestocheck(hitplanes(1))); + for iiprint = 2:length(hitplanes); + printvec = [printvec,' ',int2str(planestocheck(hitplanes(iiprint)))]; + end + disp([' by:']) + disp([' ',printvec]) + end + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/private/EDB1ed2geox.m Sat Nov 16 18:25:24 2013 +0000 @@ -0,0 +1,1205 @@ +function outputfile = EDB1ed2geox(eddatafile,sdatafile,rdatafile,doSbatches,doRbatches,specorder,difforder,nedgesubs,ndiff2batches) +% EDB1ed2geox - Calculates 2nd- and higher-order edge-related geom. parameters. +% EDB1ed2geox calculates some plane- and edge-related geometrical parameters +% based on corners and planes in a .mat-file generated by EDB1readcad +% but only data that is independent of the source and receiver. +% The output is saved in a .mat-file. +% +% Input parameters: +% eddatafile The .mat file where the output data will be stored. +% If it is not specified, an automatic file name is constructed +% using the same filename stem as the cadgeofile, but ending +% with '_edgeo'. +% sdatafile +% rdatafile +% doSbatches +% doRbatches +% specorder The highest order of any reflection kind (specular and/or diffraction). +% difforder The highest order of diffraction. If it is 0 or 1 then the parameter +% edgeseespartialedge is not calculated. Default: 1 +% nedgesubs +% ndiff2batches +% SHOWTEXT (global) An integer value; if it is 4 or higher, then messages will be printed on the +% screen during calculations. +% Output parameters: +% outputfile The name of the outputfile, generated either automatically or specified as +% an input parameter. +% +% Output parameters in the outputfile: +% (Taken directly from the cadgeo-file:) +% corners planecorners planeeqs planenvecs ncornersperplanevec +% minvals maxvals +% (Taken directly from the setup-file:) +% int_or_ext_model +% (Calculated by EDB1edgeo:) +% edgecorners Matrix [nedges,2] with the corner numbers that +% define each edge, in the reference order. +% edgestartcoords Matrix [nedges,3] with the coordinates of the +% start corner for each edge. +% edgeendcoords Matrix [nedges,3] with the coordinates of the +% end corner for each edge. +% edgelengthvec List [nedges,1] with the lengths of each edge. +% planesatedge Matrix [nedges,2] with the plane numbers of the +% two planes that connect to each edge. The first +% plane is considered as the reference plane for +% each edge. Rule: if the RH thumb is placed +% along the edge, from start to end, and the hand +% is rotated, the fingers should "come up +% through" the reference plane. +% closwedangvec List [nedges,1] with the angles in radians of +% each edge - for the closed part of each edge. +% edgenvecs Matrix [nedges,3] with the normal vectors of +% the reference plane for each edge. +% offedges List [nlength,1] where nlength = 0-nedges +% containing the edge numbers that should not +% used. +% reflfactors List [nplanes,1] with the reflection factors +% of each plane. The only supported values are +% +1 for rigid planes, 0 for perfectlt absorbing +% planes and -1 for pressure-release planes. The +% pressure-release cases might not be implemented +% fully. +% planeisthin List [nplanes,1] with the value 1 or 0 stating +% whether the plane is thin or not. +% rearsideplane List [nplanes,1] with the plane number that is at +% the rear side. If a plane is non-thin, the +% value in this list is zero. +% planehasindents List [nplanes,1] with the value 1 or 0 stating +% whether a plane has indents or not. +% canplaneobstruct List [nplanes,1] with the value 1 or 0 stating +% whether a plane has the potential to obstruct +% or not. +% planeseesplane A matrix, [nplanes,nplanes], with the value 1 +% 0,-1,-2 stating: +% 1 A plane is front of another plane and could +% then potentially see it. +% 0 A plane is completely behind another plane +% but they are not aligned +% -1 A plane is aligned with another plane +% -2 A plane is back-to-back with another plane. +% edgesatplane A matrix, [nplanes,nmaxedgesperplane] which for +% row N contains the edge numbers that connect to +% to plane N. +% edgeseesplane A matrix, [nplanes,nedges], which contains the +% values 0,1,-2 or -2, meaning: +% 0 The edge can never see the plane +% -1 The edge can never see the plane and the +% edge is aligned with the plane +% -2 The edge can never see the plane and the +% edge belongs to the plane +% 1 The edge can potentially see the plane. +% +% (Calculated by EDB1edgeo, but only for diffraction order >= 2:) +% edgeseespartialedge A sparse matrix, [nedges,nedges], with the +% values 0, pos. integer or neg. integer: +% 0 Two edges can not see each other (or one +% of the edges is inactive) +% pos.int. A value from 1 to 2^nedgesubs-1 +% indicating how much of the edges +% see each other. A pos. value +% indicates that the edge-to-edge +% path runs along a plane. +% NB! A complete visibility test is +% not made; subsegment 1 on edge 1 is only +% checked against subsegment 1 on +% edge 2, not against all other +% subsegments of edge 2. +% neg.int. Same as for the pos.int. except +% that the edge-to-edge path does not +% run along a plane. +% +% reftoshortlistE +% re1sho, re2sho +% thetae1sho, thetae2sho +% ze1sho, ze2sho +% examplecombE +% edgealignedwithedge A sparse matrix, [nedges,nedges], with the value 1 +% or 0 stating whether an (active) edge is aligned +% with another (active) edge or not. +% edgeperptoplane A sparse matrix, [nplanes,nedges], with the value 1 +% or 0 stating whether an (active) edge is perpendicular +% to an active plane or not. +% edgeplaneperptoplane1 A sparse matrix, [nplanes,nedges], with the value 1 +% or 0 stating whether an (active) edge has one +% of its two defining planes perpendicular to +% another plane with which it shares an edge. +% edgeplaneperptoplane2 A sparse matrix, [nplanes,nedges], with the value 1 +% or 0 stating whether an (active) edge has one +% of its two defining planes perpendicular to +% another plane which has a flat edge (i.e., a 180 degree edge). +% +% Uses the functions EDB1coordtrans1, EDB1coordtrans2 +% EDB1infrontofplane, EDB1compress7, EDB1strpend, EDB1cross +% EDB1checkobstr_edgetoedge +% +% ---------------------------------------------------------------------------------------------- +% This file is part of the Edge Diffraction Toolbox by Peter Svensson. +% +% The Edge Diffraction Toolbox is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) any later version. +% +% The Edge Diffraction Toolbox is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +% FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License along with the +% Edge Diffraction Toolbox. If not, see <http://www.gnu.org/licenses/>. +% ---------------------------------------------------------------------------------------------- +% Peter Svensson (svensson@iet.ntnu.no) 20110822 +% +% outputfile = EDB1ed2geox(eddatafile,sdatafile,rdatafile,doSbatches,doRbatches,specorder,difforder,nedgesubs,ndiff2batches); + +% 20110822 Bug found and fixed, giving the wrong amplitude for second- and higher-order +% diffraction, but only for diffraction paths that do not travel along a surface. + +global SHOWTEXT + +geomacc = 1e-10; + +eval(['load ',eddatafile]) +edgestartcoordsnudge = edgedata.edgestartcoordsnudge; +edgeendcoordsnudge = edgedata.edgeendcoordsnudge; +edgenormvecs = edgedata.edgenormvecs; + +[sfilepath,sfilestem,temp1] = fileparts(sdatafile); +sdatafile = [sfilepath,filesep,sfilestem]; +if doSbatches == 0 + eval(['load ',sdatafile,'.mat']) +else + eval(['load ',sdatafile,'_1.mat']) +end +[rfilepath,rfilestem,temp1] = fileparts(rdatafile); +rdatafile = [rfilepath,filesep,rfilestem]; +if doRbatches == 0 + eval(['load ',rdatafile,'.mat']) +else + eval(['load ',rdatafile,'_1.mat']) +end + +outputfile = eddatafile; + +nplanes = size(planecorners,1); +nedges = size(edgecorners,1); + +zerosvec1 = zeros(nplanes,1); + +%--------------------------------------------------------------- +% We check right away which edges that can not be seen by either the source +% or the receiver. We don't need to check edgeseesedge for combinations +% that involve any of these. +% +% Note that this is true only for difforder = 2! If difforder >= 3, then we +% can not exclude any edges based on this! (It could be possible to exclude +% edges, if we managed to "unwind" the +% edge-sees-an-edge-which-sees-an-edge-which-can-be-seen-by-the-source. + +if difforder == 2 + edgesthatareseen = any( [vispartedgesfroms vispartedgesfromr].' ); + edgesnottoworryabout = [1:nedges]; + edgesnottoworryabout(edgesthatareseen) = []; + clear vispartedgesfroms vispartedgesfromr visplanesfroms visplanesfromr +else + edgesnottoworryabout = []; +end + +%--------------------------------------------------------------- +% +% edgeperptoplane +% +%--------------------------------------------------------------- +% Make matrices over: +% 1. Which edges are perpendicular to planes ("edgeperptoplane") +% 2. Which edges can give combinations with edge1-plane-edge1 +% where plane is perpendicular to one of the two planes that +% defines the edge ("edgeplaneperptoplane1") +% 3. Which edges can give combinations with edge1-plane-edge1 +% where plane is a part of a (unnecessarily) divided plane +% ("edgeplaneperptoplane2") +% +% NB! Only active edges and active planes can get +% such combinations. +% +% These are needed for diff-spec-diff combos, so only when +% difforder >= 2 (and specorder >= 3). + +edgeperptoplane = []; +edgeplaneperptoplane1 = []; +edgeplaneperptoplane2 = []; +if specorder >= 3 + edgeperptoplane = sparse(zeros(nplanes,nedges)); + edgeplaneperptoplane1 = sparse(zeros(nplanes,nedges)); + edgeplaneperptoplane2 = sparse(zeros(nplanes,nedges)); + if SHOWTEXT >= 4 + disp(' checking which edges are perpendicular to planes ...') + end + + iv = find(edgeseesplane == 1); + if ~isempty(iv) + edgelist = floor((iv-1)/nplanes)+1; + planelist = iv - (edgelist-1)*nplanes; + + % Check first which edges have vectors that are parallel to plane + % normal vectors. These are "edgeperptoplane" cases. Clear them + % afterwards from the edgelist and planelist. + + vec1 = edgenormvecs(edgelist,:); + vec2 = planenvecs(planelist,:); + ivperp = find( abs( sum( (vec1.*vec2).' ) )==1); + if ~isempty(ivperp) + edgeperptoplane(iv(ivperp)) = ones(size(ivperp)); + clear iv + edgelist(ivperp) = []; + planelist(ivperp) = []; + vec2(ivperp,:) = []; + else + clear iv + end + + % Now check which edges have plane1 or plane2 perpendicular to + % other planes. + + if ~isempty(planelist) + + vec1 = planenvecs(planesatedge(edgelist,1),:); + ivplaneperp1 = find( abs( sum( (vec1.*vec2).' ) )==0); + vec1 = planenvecs(planesatedge(edgelist,2),:); + ivplaneperp2 = find( abs( sum( (vec1.*vec2).' ) )==0); + ivplaneperp = [ivplaneperp1 ivplaneperp2]; + if ~isempty(ivplaneperp) + ivplaneperp = unique(ivplaneperp); + edgelist = edgelist(ivplaneperp); + planelist = planelist(ivplaneperp); + edgeplane1 = planesatedge(edgelist,1); + edgeplane2 = planesatedge(edgelist,2); + + % Check which of these other perpendicular planes that connnect + % to one of the edge planes via a 90 deg. corner. + + ivtoclear = []; + [ivfoundcombos,loc] = ismember([planelist edgeplane1],planesatedge,'rows'); + ivperp = find(ivfoundcombos); + if ~isempty(ivperp) + edgenumb = loc(ivperp); + ivfinalcomb = ivperp(find(closwedangvec(edgenumb)==3*pi/2)); + if ~isempty(ivfinalcomb) + ivreftomatrix = planelist(ivfinalcomb) + (edgelist(ivfinalcomb)-1)*nplanes; + edgeplaneperptoplane1(ivreftomatrix) = ones(size(ivreftomatrix)); + ivtoclear = ivfinalcomb; + end + end + [ivfoundcombos,loc] = ismember([edgeplane1 planelist],planesatedge,'rows'); + ivperp = find(ivfoundcombos); + if ~isempty(ivperp) + edgenumb = loc(ivperp); + ivfinalcomb = ivperp(find(closwedangvec(edgenumb)==3*pi/2)); + if ~isempty(ivfinalcomb) + ivreftomatrix = planelist(ivfinalcomb) + (edgelist(ivfinalcomb)-1)*nplanes; + edgeplaneperptoplane1(ivreftomatrix) = ones(size(ivreftomatrix)); + + ivtoclear = ivtoclear.'; + ivfinalcomb = ivfinalcomb.'; + ivtoclear = [ivtoclear ivfinalcomb]; + end + end + + [ivfoundcombos,loc] = ismember([planelist edgeplane2],planesatedge,'rows'); + ivperp = find(ivfoundcombos); + if ~isempty(ivperp) + edgenumb = loc(ivperp); + ivfinalcomb = ivperp(find(closwedangvec(edgenumb)==3*pi/2)); + if ~isempty(ivfinalcomb) + ivreftomatrix = planelist(ivfinalcomb) + (edgelist(ivfinalcomb)-1)*nplanes; + edgeplaneperptoplane1(ivreftomatrix) = ones(size(ivreftomatrix)); + + if size(ivtoclear,2) == size(ivfinalcomb,2) + ivtoclear = [ivtoclear;ivfinalcomb]; + elseif size(ivtoclear,1) == size(ivfinalcomb,1), + ivfinalcomb = ivfinalcomb.'; + ivtoclear = [ivtoclear ivfinalcomb]; + elseif isempty(ivtoclear) + error('ERROR: Unexpected error involving sizes of ivtoclear and ivfinalcomb') + end + end + end + + + [ivfoundcombos,loc] = ismember([edgeplane2 planelist],planesatedge,'rows'); + ivperp = find(ivfoundcombos); + if ~isempty(ivperp) + edgenumb = loc(ivperp); + ivfinalcomb = ivperp(find(closwedangvec(edgenumb)==3*pi/2)); + if ~isempty(ivfinalcomb) + ivreftomatrix = planelist(ivfinalcomb) + (edgelist(ivfinalcomb)-1)*nplanes; + edgeplaneperptoplane1(ivreftomatrix) = ones(size(ivreftomatrix)); + + if size(ivtoclear,2) == size(ivfinalcomb,2) + ivtoclear = [ivtoclear;ivfinalcomb]; + elseif size(ivtoclear,1) == size(ivfinalcomb,1), + ivfinalcomb = ivfinalcomb.'; + ivtoclear = [ivtoclear ivfinalcomb]; + elseif isempty(ivtoclear) + error('ERROR: Unexpected error involving sizes of ivtoclear and ivfinalcomb') + end + end + end + + % Finally check which edges have plane1 or plane2 perpendicular to + % two other planes that connnect via a 180 deg. corner. + + if ~isempty(ivtoclear) + ivtoclear = unique(ivtoclear); + edgelist(ivtoclear) = []; + planelist(ivtoclear) = []; + if ~isempty(edgelist) + + ivflatedges = find(closwedangvec==pi); + if ~isempty(ivflatedges) + planecombos = planesatedge(ivflatedges,:); + for ii = 1:length(ivflatedges) + iv1 = find(planelist == planecombos(ii,1)); + if ~isempty(iv1) + ivreftomatrix = double(planecombos(ii,1)) + (edgelist(iv1)-1)*nplanes; + edgeplaneperptoplane2(ivreftomatrix) = ones(size(ivreftomatrix)); + end + iv2 = find(planelist == planecombos(ii,2)); + if ~isempty(iv2) + ivreftomatrix = planecombos(ii,2) + (edgelist(iv2)-1)*nplanes; + edgeplaneperptoplane2(ivreftomatrix) = ones(size(ivreftomatrix)); + end + + end + end + + end + end + + end + end + + end + +end + +%--------------------------------------------------------------- +% +% edgealignedwithedge +% +%--------------------------------------------------------------- + +edgealignedwithedge = []; + +if specorder >= 2 + edgealignedwithedge = sparse(eye(nedges)); + if SHOWTEXT >= 4 + disp(' checking which edges are aligned with other edges ...') + end + + listofactiveedges = [1:nedges].'; + listofactiveedges(offedges) = []; + vecstocheck = edgenormvecs(listofactiveedges,:); + iv = find(vecstocheck(:,1)<0); + vecstocheck(iv,:) = -vecstocheck(iv,:); + iv = find(vecstocheck(:,1)==0 & vecstocheck(:,2)<0); + vecstocheck(iv,:) = -vecstocheck(iv,:); + iv = find(vecstocheck(:,1)==0 & vecstocheck(:,2)==0 & vecstocheck(:,3)<0); + vecstocheck(iv,:) = -vecstocheck(iv,:); + if ~isempty(listofactiveedges) + [uniquevecs,II,JJ] = unique(vecstocheck,'rows'); + N = histc(JJ,[1:length(listofactiveedges)]); + iv = find(N>1); + for ii = 1:length(iv) + iv2 = find(JJ==iv(ii)); + edgestocheck = listofactiveedges(iv2); + ntocheck = length(edgestocheck); + cornernumberstocheck = edgecorners(edgestocheck,:); + expandedstartcornermatrix = [reshape(repmat(cornernumberstocheck(:,1).',[ntocheck 1]),ntocheck^2,1) repmat(cornernumberstocheck(:,1),[ntocheck 1])]; + expandedendcornermatrix = [reshape(repmat(cornernumberstocheck(:,2).',[ntocheck 1]),ntocheck^2,1) repmat(cornernumberstocheck(:,2),[ntocheck 1])]; + toexpandededgestocheck = repmat(edgestocheck, [ntocheck 1]); + fromexpandededgestocheck = reshape(repmat(edgestocheck.',[ntocheck 1]),ntocheck^2,1); + + % Now we don't need to check edges against themselves, or edge1 + % vs edge2 if edge2 vs edge1 has already been tested. + + indmat = reshape([1:ntocheck^2],ntocheck,ntocheck); + indmat = triu(indmat,1); + indmat = indmat(find(indmat)); + + expandedstartcornermatrix = expandedstartcornermatrix(indmat,:); + expandedendcornermatrix = expandedendcornermatrix(indmat,:); + fromexpandededgestocheck = fromexpandededgestocheck(indmat,:); + toexpandededgestocheck = toexpandededgestocheck(indmat,:); + + % We make the easiest check first: if two edges with the same + % direction vector share one corner, they must be aligned. + + A = [expandedstartcornermatrix expandedendcornermatrix]; + A = sort(A.').'; + A = diff(A.').'; + iv3 = find(sum(A.'==0).'); + validcombs = [fromexpandededgestocheck(iv3) toexpandededgestocheck(iv3)]; + if ~isempty(validcombs) + indexvals = (validcombs(:,2)-1)*nedges + validcombs(:,1); + edgealignedwithedge(indexvals) = edgealignedwithedge(indexvals) + 1; + indexvals = (validcombs(:,1)-1)*nedges + validcombs(:,2); + edgealignedwithedge(indexvals) = edgealignedwithedge(indexvals) + 1; + fromexpandededgestocheck(iv3) = []; + toexpandededgestocheck(iv3) = []; + expandedstartcornermatrix(iv3,:) = []; + expandedendcornermatrix(iv3,:) = []; + end + + % For the other edge-pair combinations we must check if the two + % edges are really aligned. We do this by checking if two + % vectors are aligned: edge1-vector and the vector from + % edge1start to edge2start. + + direcvec = corners(expandedstartcornermatrix(:,2),:) - corners(expandedstartcornermatrix(:,1),:); + direcveclengths = sqrt( sum(direcvec.'.^2) ).'; + direcvec = direcvec./(direcveclengths(:,ones(1,3)) + eps*10); + test = abs(sum( (direcvec.*edgenormvecs(fromexpandededgestocheck,:)).' )); + iv3 = find(abs(test-1)< 1e-8); + validcombs = [fromexpandededgestocheck(iv3) toexpandededgestocheck(iv3)]; + if ~isempty(validcombs) + indexvals = (validcombs(:,2)-1)*nedges + validcombs(:,1); + edgealignedwithedge(indexvals) = edgealignedwithedge(indexvals) + 1; + indexvals = (validcombs(:,1)-1)*nedges + validcombs(:,2); + edgealignedwithedge(indexvals) = edgealignedwithedge(indexvals) + 1; + fromexpandededgestocheck(iv3) = []; + toexpandededgestocheck(iv3) = []; + expandedstartcornermatrix(iv3,:) = []; + expandedendcornermatrix(iv3,:) = []; + end + end + end + +end + +%--------------------------------------------------------------- +% +% edgeseesedge +% +%--------------------------------------------------------------- +% +% Make a matrix of which edges can see which edges +% +% Planes that are in front of the edge-planes might have visible edges. +% If closwedang = 0, then all other edges are potentially visible. +% If closwedang < pi, then all planes in front of plane1 or plane2 are OK +% If closwedang > pi, then all planes in front of plane1 and plane2 are OK + +if SHOWTEXT >= 4 + disp(' checking which edges see which edges...') +end + +edgeseesedge = int8(zeros(nedges,nedges)); +for ii = 1:nedges + closwed = closwedangvec(ii); + if closwed == 0 + edgeseesedge(:,ii) = ones(nedges,1); + else + plane1 = planesatedge(ii,1); + plane2 = planesatedge(ii,2); + okplanelist1 = find(planeseesplane(:,plane1)==1); + okplanelist2 = find(planeseesplane(:,plane2)==1); + + if closwed < pi + okplanes = [okplanelist1;okplanelist2]; + okplanes = sort(okplanes); + else + okplanes = zerosvec1; + okplanes(okplanelist1) = okplanes(okplanelist1)+1; + okplanes(okplanelist2) = okplanes(okplanelist2)+1; + okplanes = find(okplanes==2); + end + + okedges = edgesatplane(okplanes,:); + [n1,n2] = size(okedges); + okedges = reshape(okedges,n1*n2,1); + + if ~isempty(okedges) + okedges = okedges(find(okedges~=0)); + edgeseesedge(okedges,ii) = int8(double(edgeseesedge(okedges,ii)) + 1); + end + + edgesatplane1 = edgesatplane(plane1,:); + edgesatplane2 = edgesatplane(plane2,:); + okedges = [edgesatplane1 edgesatplane2].'; + okedges = okedges(find(okedges~=0)); + edgeseesedge(okedges,ii) = int8(double(edgeseesedge(okedges,ii)) + 1); + + end % else ..... if closwed == 0 + +end % for ii = 1:nedges + +% Mask out all edge pairs that are aligned +edgeseesedge = double(edgeseesedge) - double(edgealignedwithedge); + +% Make sure the edge-to-same-edge combos are masked out +% edgeseesedge = sign(edgeseesedge.*(edgeseesedge.')).*(1-eye(nedges)); +edgeseesedge = int8( ( (edgeseesedge & (edgeseesedge.'))>0).*(1-eye(nedges))); + +% Mask out all edges that should be switched off + +mask = ones(nedges,nedges); +mask(offedges,:) = mask(offedges,:)*0; +mask(:,offedges.') = mask(:,offedges.')*0; + +edgeseesedge = edgeseesedge & mask; +clear mask + + +%----------------------------------------------------------- +% Go through all edgeseesedge combinations. If two edges see +% each other without belonging to the same plane, there should +% be a gain factor of 2. + +if SHOWTEXT >= 4 + disp(' checking which edge-to-edge paths that run along planes') +end + +edgetoedgestrength = 2*edgeseesedge; +for ii = 1:nedges + if sum(edgetoedgestrength(:,ii)) ~= 0 + plane1 = planesatedge(ii,1); + plane2 = planesatedge(ii,2); + edgesatplane1 = edgesatplane(plane1,:); + edgesatplane2 = edgesatplane(plane2,:); + sameplaneedges = [edgesatplane1 edgesatplane2].'; + sameplaneedges = sameplaneedges(find(sameplaneedges~=0)); + edgetoedgestrength(sameplaneedges,ii) = edgetoedgestrength(sameplaneedges,ii)*0 + 1; + end % % if sum(edge +end + +% an edge can not contribute to itself + +edgetoedgestrength = edgetoedgestrength.*(1-eye(nedges)); + +% The edges belonging to the same planes, but that are inactive (90 degrees etc) +% must be switched off here too. +% 011021 This is redundant. + edgetoedgestrength = edgetoedgestrength.*(edgeseesedge>0); +edgetoedgestrength = int8(edgetoedgestrength); + +%---------------------------------------------------------------------------- +% +% CHECK OBSTRUCTION OF EDGE-TO-EDGE PATHS +% +%---------------------------------------------------------------------------- +% +% We construct two long lists: 'from-edges' and 'to-edges' for which +% obstruction should be tested. These lists are made up of all the +% combinations in edgeseesedge that have a value 1. +% NB! We use symmetry - if edge 1 can see edge 2, then edge 2 can also see +% edge 1. +% +% Both edges should be subdivided into nedgesubs segments. So, the long +% lists must be expanded so that each from-edge/to-edge combination is +% replaced by nedgesubs^2 as many. +% For efficiency, we make a shortlist of the actual edge subdivisions and +% we then expand long lists with pointers to this shortlist. +% +% The final matrix, edgeseespartialedge, will have an integer value which +% tells whether two edges see each other: +% +% 0 Edges can not see each other, or one of the edges is inactive +% (an inactive edge has an integer wedge index, or has one plane +% which is TOTABS) +% 2^nedgesubs-1 Two edges see each other completely. +% Other integers Two edges see each other partly. +% Neg. integer As above, but in addition, the edges do not belong +% to the same plane. +% +% We check in the visedgesfroms and visedgesfromr lists to check which +% combinations we don't need to check. + +if SHOWTEXT >= 3 + disp([' Checking for obstructing planes between edges and edges']) + disp(' ') + disp('NB!!! The value of nedgesubs is temporarily set to 1 for the edge-to-edge vis. test') +end + +obstructtestneeded = (sum(canplaneobstruct)~=0); +maxedgetoedgevisvalue = 2^(2*nedgesubs)-1; + +if obstructtestneeded + + nedgesubsorig = nedgesubs; + nedgesubs = 1; + edgeseesedge = triu(edgeseesedge); + + iv = full(find(edgeseesedge~=0)); + + if ~isempty(iv) + fromedges = floor(iv/nedges)+1; + toedges = iv - (fromedges-1)*nedges; + ncombs = length(fromedges); + + ivcancel = find(ismember(fromedges,edgesnottoworryabout)); + fromedges(ivcancel) = []; + toedges(ivcancel) = []; + + ivcancel = find(ismember(toedges,edgesnottoworryabout)); + toedges(ivcancel) = []; + fromedges(ivcancel) = []; + clear ivcancel + + % Some of these fromedges-toedges combos might involve two + % neighboring edges that form an indent. Those should be + % removed before we start checking fro obstructions. + % + % We check the [fromedges toedges] matrix against the + % indentingedgepairs matrix. + + [tf,loc]= ismember(indentingedgepairs,sort([fromedges toedges].').','rows'); + if ~isempty(loc) + ivmatch = find(loc); + fromedges(loc(ivmatch)) = []; + toedges(loc(ivmatch)) = []; + end + ncombs = length(fromedges); + + [uniqueedges,iunique,junique] = unique([fromedges toedges]); + clear fromedges toedges + + % The lists edgesubcoords are the shortlists. + + [edgesubcoords,edgeweightlist,edgenumberlist] = EDB1getedgepoints(edgestartcoords(uniqueedges,:),edgeendcoords(uniqueedges,:),edgelengthvec(uniqueedges,:),nedgesubs,1); + + % The two lists below contain pointers to the first edge segment in the + % shortlist. + + fromcoords_refp1 = nedgesubs*(junique(1:ncombs)-1)+1; + tocoords_refp1 = nedgesubs*(junique(ncombs+1:2*ncombs)-1)+1; + clear junique + + % Now the original [fromedges toedges] could be recovered by: + % uniqueedges([edgenumberlist(fromcoords_refp1) edgenumberlist(tocoords_refp1)]) + % reshape(uniqueedges([edgenumberlist(fromcoords_refp1) edgenumberlist(tocoords_refp1)]),6,2) +% uniqueedges([edgenumberlist(fromcoords_refp1) edgenumberlist(tocoords_refp1)]); +% npairs = length(uniqueedges([edgenumberlist(fromcoords_refp1) edgenumberlist(tocoords_refp1)])); +% reshape(uniqueedges([edgenumberlist(fromcoords_refp1) edgenumberlist(tocoords_refp1)]),npairs/2,2) + + addmask = [0:nedgesubs-1]; + onesvec1 = ones(1,nedgesubs); + ntot1 = ncombs*nedgesubs; + + % First, the from-list gets repetitions of the same values + expandfrom_ref = fromcoords_refp1(:,onesvec1); + clear fromcoords_refp1; + expandfrom_ref = reshape(expandfrom_ref.',ntot1,1); + + % Second, the expanded from-list gets repetitions that are + % incremented in steps of 1 (because the shortlists have the + % edge segments placed after each other). + expandfrom_ref = expandfrom_ref(:,onesvec1); + expandfrom_ref = expandfrom_ref + addmask(ones(ntot1,1),:); + expandfrom_ref = reshape(expandfrom_ref.',ncombs*nedgesubs^2,1); + + % Same thing for the to-list except that the first expansion + % gives repetitions that are incremented in steps of 1. + expandto_ref = tocoords_refp1(:,onesvec1); + clear tocoords_refp1; + expandto_ref = expandto_ref + addmask(ones(ncombs,1),:); + expandto_ref = reshape(expandto_ref.',ntot1,1); + + % Second expansion for the to-list: repetitions + expandto_ref = expandto_ref(:,onesvec1); + expandto_ref = reshape(expandto_ref.',ncombs*nedgesubs^2,1); + + % Now we have expanded lists of all combinations, and we can + % make lists with the coordinates, the edge numbers, and the weights of + % the segments. + + % edgesubcoords(expandfrom_ref,:) will give all the starting points + % "fromcoords" + % edgesubcoords(expandto_ref,:) will give all the ending points + % "tocoords" + % uniqueedges(edgenumberlist(expandfrom_ref)) will give all + % the starting edges, "fromedges" + % uniqueedges(edgenumberlist(expandto_ref)) will give all + % the ending edges, "toedges" + % We can make a simple test of which planes that could be excluded + % from the obstruction test by checking the edgeseesplane for the + % relevant edges. It can be multiplied by the canplaneobstruct list + % when calling the findobstructedpaths function. + isplaneactiveforobstruction = (sum(edgeseesplane(:,uniqueedges).'==1)>0); + + global STARTPLANES ENDPLANES + global BIGFROMCOORDS BIGTOCOORDS BIGSTARTPLANES BIGENDPLANES + global REFTOFROMCOSHO REFTOTOCOSHO + + FROMCOORDSSHORTLIST = edgesubcoords; + REFTOFROMCOSHO = uint32(expandfrom_ref); + TOCOORDSSHORTLIST = edgesubcoords; + REFTOTOCOSHO = uint32(expandto_ref); + if nedges < 256 + bigfromedge = uint8(uniqueedges(edgenumberlist(expandfrom_ref)).'); + else + bigfromedge = uint16(uniqueedges(edgenumberlist(expandfrom_ref)).'); + end + clear expandfrom_ref + bigfromedge = bigfromedge(:); + if nedges < 256 + bigtoedge = uint8(uniqueedges(edgenumberlist(expandto_ref)).'); + else + bigtoedge = uint16(uniqueedges(edgenumberlist(expandto_ref)).'); + end + clear expandto_ref + bigtoedge = bigtoedge(:); + STARTPLANES = [planesatedge(bigfromedge,1) planesatedge(bigfromedge,2)]; + ENDPLANES = [planesatedge(bigtoedge,1) planesatedge(bigtoedge,2)]; + shouldplanebechecked = canplaneobstruct.*isplaneactiveforobstruction; + nplanesperbatch = ceil(sum(shouldplanebechecked)/ndiff2batches); + if nplanesperbatch > 0 + temp = cumsum(shouldplanebechecked); + diff2batchlist = zeros(ndiff2batches,2); + diff2batchlist(1,1) = 1; + loopisfinished = 0; + for ii = 1:ndiff2batches-1 + ivtemp = find(temp==nplanesperbatch*ii); + if ~isempty(ivtemp) + diff2batchlist(ii,2) = ivtemp(1); + diff2batchlist(ii+1,1) = ivtemp(1)+1; + else + loopisfinished = 1; + end + end + diff2batchlist(ii,2) = nplanes; + ivtemp = find(diff2batchlist(:,1)>0); + diff2batchlist = diff2batchlist(ivtemp,:); + ndiff2batches = size(diff2batchlist,1); + + npathstocheck = size(REFTOFROMCOSHO,1); + for ii = 1:ndiff2batches + if npathstocheck > 0 + maskedchkpla = shouldplanebechecked; + if ii > 1 + maskedchkpla(1:diff2batchlist(ii,1)-1) = maskedchkpla(1:diff2batchlist(ii,1)-1)*0; + end + if ii < ndiff2batches + maskedchkpla(diff2batchlist(ii,2)+1:end) = maskedchkpla(diff2batchlist(ii,2)+1:end)*0; + end + nplanestocheck = sum(maskedchkpla); + if SHOWTEXT >= 3, + if round(ii/1)*1==ii + disp([' Batch ',int2str(ii),' of ',int2str(ndiff2batches),': ']) + disp([' ',int2str(npathstocheck),' paths to check, ',int2str(nplanestocheck),' planes to check obstruction for']) + end + end + + % We create the BIGFROMCOORDS matrices and BIGTOCOORDS matrices + % outside since they need to be exactly identical from batch to + % batch as long as nplanestocheck is the same. + + npathstocheck = size(REFTOFROMCOSHO,1); + + ntot = nplanestocheck*npathstocheck; + + BIGFROMCOORDS = reshape(repmat(FROMCOORDSSHORTLIST(REFTOFROMCOSHO,:).',[nplanestocheck,1]),3,ntot).'; + BIGTOCOORDS = reshape(repmat(TOCOORDSSHORTLIST(REFTOTOCOSHO,:).',[nplanestocheck,1]),3,ntot).'; + BIGSTARTPLANES = reshape(repmat(STARTPLANES.',[nplanestocheck,1]),2,ntot).'; + BIGENDPLANES = reshape(repmat(ENDPLANES.',[nplanestocheck,1]),2,ntot).'; + + [nonobstructedpaths,nobstructions,edgehits,cornerhits] = EDB1checkobstr_edgetoedge(maskedchkpla,planeseesplane,... + planeeqs,planenvecs,minvals,maxvals,planecorners,corners,ncornersperplanevec,rearsideplane); + + + if ~isempty(edgehits) + % Look for the edge-to-edge combos that share a + % plane. When such combos have hit an edge, it + % must mean that they are planes with indents. + wasedgehitnotindent = prod(double(diff(sort([STARTPLANES(edgehits,:) ENDPLANES(edgehits,:)].')))).'; + indentedgehits = find(wasedgehitnotindent==0); + if ~isempty(indentedgehits) + nonobstructedpaths = setdiff(nonobstructedpaths,edgehits(indentedgehits)); + end + + end + + if ~isempty(nonobstructedpaths) + REFTOFROMCOSHO = REFTOFROMCOSHO(nonobstructedpaths); + REFTOTOCOSHO = REFTOTOCOSHO(nonobstructedpaths); + STARTPLANES = STARTPLANES(nonobstructedpaths,:); + ENDPLANES = ENDPLANES(nonobstructedpaths,:); + bigfromedge = bigfromedge(nonobstructedpaths); + bigtoedge = bigtoedge(nonobstructedpaths); + npathstocheck = size(REFTOFROMCOSHO,1); + else + REFTOFROMCOSHO = []; + REFTOTOCOSHO = []; + STARTPLANES = []; + ENDPLANES = []; + bigfromedge = []; + bigtoedge = []; + npathstocheck = 0; + end + + end % if npathstocheck > 0 + + end % for ii = 1:ndiff2batches + else + nonobstructedpaths = 1; + + end %if nplanesperbatch > 0 + + clear REFTOFROMCOSHO REFTOTOCOSHO STARTPLANES ENDPLANES + + + if ~isempty(nonobstructedpaths) + + % Add the segment pieces together + % NB! We don't try to implement the correct way to do it since + % we would need nedgesubs^2 bits to represent all edge-segment + % to edge-segment visibility possibilities. + % Instead we just establish whether the two edges see each + % other fully or partly. + + visiblesegmentscounter = ones(size(bigfromedge)); + test = [bigfromedge bigtoedge]; + + ncombs = length(bigfromedge); + dtest = diff([0;prod( double(test(1:ncombs-1,:)==test(2:ncombs,:)).' ).']); + ivremove = find(dtest==1); + + while ~isempty(ivremove) + visiblesegmentscounter(ivremove+1) = visiblesegmentscounter(ivremove+1) + visiblesegmentscounter(ivremove); + visiblesegmentscounter(ivremove) = []; + bigfromedge(ivremove) = []; + bigtoedge(ivremove,:) = []; + + test = [bigfromedge bigtoedge]; + ncombs = length(bigfromedge); + dtest = diff([0;prod( double(test(1:ncombs-1,:)==test(2:ncombs,:)).' ).']); + ivremove = find(dtest==1); + + end + + indexvec = uint32((double(bigfromedge)-1)*nedges + double(bigtoedge)); + if maxedgetoedgevisvalue < 128 + edgeseespartialedge = int8(zeros(nedges,nedges)); + elseif maxedgetoedgevisvalue < 32768 + edgeseespartialedge = int16(zeros(nedges,nedges)); + else + edgeseespartialedge = int32(zeros(nedges,nedges)); + end + + iv = find(visiblesegmentscounter==nedgesubs^2); + edgeseespartialedge(indexvec(iv)) = maxedgetoedgevisvalue*ones(size(iv)); + iv = find(visiblesegmentscounter>0 & visiblesegmentscounter<nedgesubs^2); + edgeseespartialedge(indexvec(iv)) = maxedgetoedgevisvalue/2*ones(size(iv)); + + if maxedgetoedgevisvalue < 128 + edgeseespartialedge = int8(double(edgeseespartialedge) + double(triu(edgeseespartialedge)).'); + elseif maxedgetoedgevisvalue < 32768 + edgeseespartialedge = int16(double(edgeseespartialedge) + double(triu(edgeseespartialedge)).'); + else + edgeseespartialedge = int32(double(edgeseespartialedge) + double(triu(edgeseespartialedge)).'); + end + else + edgeseespartialedge = sparse(zeros(nedges,nedges)); + end + else + edgeseespartialedge = []; + end +else + if maxedgetoedgevisvalue < 128 + edgeseespartialedge = int8((edgeseesedge*maxedgetoedgevisvalue)); + elseif maxedgetoedgevisvalue < 32768 + edgeseespartialedge = int16((edgeseesedge*maxedgetoedgevisvalue)); + else + edgeseespartialedge = int32((edgeseesedge*maxedgetoedgevisvalue)); + end + disp(' No obstruction tests needed!') + +end %(obstructtestneeded) + +% For the special case of thin planes that are all in the same plane, only +% edge pairs that belong to the same plane should be included. That is +% when edgeseespartialedge is negative, then we should set +% edgeseespartialedge to zero. + +% Bug detected 20110822 PS +% Old: allthinplanes = sign(1-sum(~planeisthin)); +allthinplanes = sign(1-sign(sum(~planeisthin))); + +% Bug detected 20110822 PS +% Old: allplanesinsameplane = 1 - sum(sum(planeseesplane==1)) +allplanesinsameplane = 1 - sign(sum(sum(planeseesplane==1))); + +multfactor = 1 - allthinplanes*allplanesinsameplane; + +iv = find(edgetoedgestrength==2); +if ~isempty(iv) + if maxedgetoedgevisvalue < 128 + edgeseespartialedge(iv) = int8(-double(edgeseespartialedge(iv))*multfactor); + elseif maxedgetoedgevisvalue < 32768 + edgeseespartialedge(iv) = int16(-double(edgeseespartialedge(iv))*multfactor); + else + edgeseespartialedge(iv) = int32(-double(edgeseespartialedge(iv))*multfactor); + end +end + +clear edgeseesedge edgetoedgestrength + +%---------------------------------------------------------------------------- +% +% CYLINDRICAL EDGE-TO-EDGE PARAMETERS +% +%---------------------------------------------------------------------------- +% +% For each edge, calculate the cylindrical coordinates of the starting +% and ending points of all other edges relative to the first edge. + +if difforder >= 2 & ~isempty(edgeseespartialedge) + + if SHOWTEXT >= 4 + disp(' E2E') + end + + zerosvec4 = zeros(nedges,nedges); + Bigre1 = (zerosvec4); + Bigthetae1 = (zerosvec4); + Bigze1 = (zerosvec4); + Bigre2 = (zerosvec4); + Bigthetae2 = (zerosvec4); + Bigze2 = (zerosvec4); + clear zerosvec4 + + for edge1 = 1:nedges + if SHOWTEXT >= 4 + if round(edge1/1)*1 == edge1 + disp([' Edge no. ',int2str(edge1)]) + end + end + edge1coords = [edgestartcoords(edge1,:);edgeendcoords(edge1,:)]; + iv = find(edgeseespartialedge(edge1,:)~=0).'; + + if ~isempty(iv), + % First find the subset of edges which belong to the same plane as the + % edge itself. These should be treated separately for higher accuracy + + % iv1 will be the edges on the reference plane. They should have theta = 0. + + + refplane = planesatedge(edge1,1); + ncornersperplanevec = double(ncornersperplanevec); + iv1 = edgesatplane( refplane,1:ncornersperplanevec( refplane )); + iv1 = iv1( find(iv1~= edge1)).'; + + edgestart = edgestartcoordsnudge(iv1,:); + edgeend = edgeendcoordsnudge(iv1,:); + + [rs,slask,zs,rr,slask,zr] = ... + EDB1coordtrans2(edgestart,edgeend,edge1coords,edgenvecs(edge1,:)); + Bigre1(iv1,edge1) = rs; + Bigthetae1(iv1,edge1) = 0*iv1; + Bigze1(iv1,edge1) = zs; + Bigre2(iv1,edge1) = rr; + Bigthetae2(iv1,edge1) = 0*iv1; + Bigze2(iv1,edge1) = zr; + + [samevalues,iivec,jjvec] = intersect(iv,iv1); +% Bug found 20050421!! PS +% % % Old wrong version: +% % % % sameedges = [iivec jjvec]; +% % % if sum(sum(sameedges)) ~= 0 +% % % iv( sameedges(1,:).' ) = []; +% % % end + if ~isempty(samevalues) + iv(iivec) = []; + end + + % iv2 will be the edges on the non-reference plane. + % They should have theta = 2*pi - closthetavec. + + if ~isempty(iv) + + if planesatedge(edge1,2) > 0 + secplane = planesatedge(edge1,2); + + iv2 = edgesatplane( secplane,1:ncornersperplanevec(secplane)); + iv2 = iv2( find(iv2~= edge1)).'; + + if ~isempty(iv2) + edgestart = edgestartcoordsnudge(iv2,:); + edgeend = edgeendcoordsnudge(iv2,:); + + [rs,slask,zs,rr,slask,zr] = ... + EDB1coordtrans2(edgestart,edgeend,edge1coords,edgenvecs(edge1,:)); + Bigre1(iv2,edge1) = rs; + Bigthetae1(iv2,edge1) = (2*pi-closwedangvec(edge1))*ones(size(iv2)); + Bigze1(iv2,edge1) = zs; + Bigre2(iv2,edge1) = rr; + Bigthetae2(iv2,edge1) = (2*pi-closwedangvec(edge1))*ones(size(iv2)); + Bigze2(iv2,edge1) = zr; + +% sameedges = EDB1findsame(iv,iv2); +% Bug found 20050421!!! PS +% % % % Old wrong version: +% % % % [samevalues,iivec,jjvec] = intersect(iv,iv1); +% % % % sameedges = [iivec;jjvec]; +% % % % if sum(sum(sameedges)) ~= 0 +% % % % iv( sameedges(1,:).' ) = []; +% % % % end + + [samevalues,iivec,jjvec] = intersect(iv,iv2); + if ~isempty(samevalues) + iv(iivec) = []; + end + end + end + end + if ~isempty(iv) + + % Move the edge coordinates to be checked a short distance away + + edgestart = edgestartcoordsnudge(iv,:); + edgeend = edgeendcoordsnudge(iv,:); + + [rs,thetas,zs,rr,thetar,zr] = ... + EDB1coordtrans2(edgestart,edgeend,edge1coords,edgenvecs(edge1,:)); + Bigre1(iv,edge1) = rs; + Bigthetae1(iv,edge1) = thetas; + Bigze1(iv,edge1) = zs; + Bigre2(iv,edge1) = rr; + Bigthetae2(iv,edge1) = thetar; + Bigze2(iv,edge1) = zr; + + end + end + end + + %----------------------------------------------------------- + % Go through all edges that are in-plane with each other, that is, two + % edges have at least one plane each that are in-plane with each other. + + % First we identify all planes that have at least one more co-planar + % plane + + planehascoplanar = any(planeseesplane == -1); + + % Then we go through the list of edges and every edge with a connected + % plane that has another co-planar plane must also have potential + % in-plane edges. + + % For each edge, we check if there are other edges (that don't belong to the same plane!!) + % with thetaangle = 0 or thetaangle = 2*pi. If there are other such + % edges, those edge-to-edge combinations should be shut off. + % + % After all such edge-to-edge combinations have been shut off, we still + % need another pass to cancel edge-to-edge paths that pass entirely + % across other edges. + + ivedges = 1:nedges; + ivedges(offedges) = []; + + for ii = ivedges + if any( planehascoplanar(planesatedge(1,:)) ) + + ivcancelcombs = find( (edgeseespartialedge(:,ii) == -maxedgetoedgevisvalue) & ( (Bigthetae1(:,ii) == 0) | (Bigthetae1(:,ii) == 2*pi) ) ); + if ~isempty(ivcancelcombs) + edgeseespartialedge(ivcancelcombs,ii) = 0; + edgeseespartialedge(ii,ivcancelcombs.') = 0; + end + + end + + end + + % The only edge-to-edge combinations that we can easily discard are + % those for which edges are aligned with each other (same zstart and + % zend): only the closest of those should be kept! + + for ii = ivedges + if any( planehascoplanar(planesatedge(1,:)) ) + + + ivotheredges = find( (edgeseespartialedge(:,ii) == -maxedgetoedgevisvalue) & ((Bigthetae1(:,ii) == pi)) ); + if ~isempty(ivotheredges) + + nudgeval = 1e-10*edgelengthvec(ii)*100; + ivselectedges = find( abs(Bigze1(ivotheredges,ii))<nudgeval | abs(Bigze2(ivotheredges,ii))<nudgeval); + if length(ivselectedges) > 1 + disp(['Edge no. ',int2str(ii)]) + + lengthok = abs([Bigze1(ivotheredges(ivselectedges),ii) Bigze2(ivotheredges(ivselectedges),ii)] - edgelengthvec(ii)) < nudgeval; + ivstillok = find(any(lengthok.')); + + if ~isempty(ivstillok) + ivotheredges = ivotheredges(ivselectedges(ivstillok)); + else + ivotheredges = []; + end + + meanradialdist = mean( [Bigre1(ivotheredges,ii) Bigre2(ivotheredges,ii)].' ); + + ivshutoff = ivotheredges; + noshutoff = find(meanradialdist == min(meanradialdist)); + ivshutoff(noshutoff) = []; + + if ~isempty(ivshutoff) + edgeseespartialedge(ivshutoff,ii) = 0; + edgeseespartialedge(ii,ivshutoff) = 0; + end + + end + + end + + end + + end + + %----------------------------------------------------------------------- + % Find identical combinations + + if SHOWTEXT >= 3 + disp(' Looking for identical combinations') + end + [reftoshortlistE,re1sho,re2sho,thetae1sho,thetae2sho,... + ze1sho,ze2sho,edgelengthsho,examplecombE] = EDB1compress7(Bigre1,Bigre2,... + Bigthetae1,Bigthetae2,Bigze1,Bigze2, edgelengthvec(:,ones(1,nedges)).'); + +else + reftoshortlistE = []; + re1sho = []; + re2sho = []; + thetae1sho = []; + thetae2sho = []; + ze1sho = []; + ze2sho = []; + examplecombE = []; +end + +%---------------------------------------------------------------------------- +% +% SAVE THE VARIABLES +% +%---------------------------------------------------------------------------- +% +% Also the variables from cadgeo?? +% Yes: planeeqs planenvecs ncornersperplanevec planecorners corners +% minvals maxvals + +edgeseesplane = int8(edgeseesplane); +planeseesplane = int8(planeseesplane); + +ncorners = size(corners,1); +if ncorners < 256 + planecorners = uint8(planecorners); +elseif ncorners < 65536 + planecorners = uint16(planecorners); +end +planeisthin = uint8(planeisthin); + +Varlist = [ ' edgecorners planesatedge closwedangvec planehasindents']; +Varlist = [Varlist,' planeisthin planeseesplane rearsideplane edgeseesplane canplaneobstruct']; +Varlist = [Varlist,' corners planecorners planeeqs planenvecs ncornersperplanevec']; +Varlist = [Varlist,' edgestartcoords edgeendcoords edgenvecs reflfactors edgesatplane edgelengthvec']; +Varlist = [Varlist,' minvals maxvals offedges edgestartcoordsnudge edgeendcoordsnudge']; +Varlist = [Varlist,' reftoshortlistE re1sho re2sho thetae1sho thetae2sho ze1sho ze2sho examplecombE']; +Varlist = [Varlist,' edgeseespartialedge int_or_ext_model']; +Varlist = [Varlist,' edgealignedwithedge edgeperptoplane edgeplaneperptoplane1 edgeplaneperptoplane2']; + +eval(['save ',outputfile,Varlist])
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/private/EDB1edgeox.m Sat Nov 16 18:25:24 2013 +0000 @@ -0,0 +1,1470 @@ +function outputfile = EDB1edgeox(cadgeofile,outputfile,open_or_closed_model,int_or_ext_model,specorder,difforder,nedgesubs,firstskipcorner,planeseesplanestrategy) +% EDB1edgeox - Calculates some plane- and edge-related geometrical parameters. +% EDB1edgeo calculates some plane- and edge-related geometrical parameters +% based on corners and planes in a .mat-file generated by EDB1readcad +% but only data that is independent of the source and receiver. +% The output is saved in a .mat-file. +% +% Input parameters: +% cadgeofile (optional) The .mat file with the corners and plane data. +% If it is not specified, a file opening window is presented. +% outputfile (optional) The .mat file where the output data will be stored. +% If it is not specified, an automatic file name is constructed +% using the same filename stem as the cadgeofile, but ending +% with '_edgeo'. +% open_or_closed_model 'o' or 'c' defining whether the model is open or closed. +% int_or_ext_model 'i' or 'e' defining whether the model is interior or exterior. +% specorder The highest order of any reflection kind (specular and/or diffraction). +% difforder (optional) The highest order of diffraction. If it is 0 or 1 then the parameter +% edgeseespartialedge is not calculated. Default: 1 +% nedgesubs (optional) The number of segments that each edge will be +% subdivided into for visibility/obstruction tests. Default: 2 +% NB! When nedgesubs = 2, only the two end points will be checked. +% firstskipcorner (optional) All edges including at least one corner with this number or +% higher will be excluded from the calculations. Default: 1e6 +% planeseesplanestrategy (optional) If this parameter is given the value 1, a plane-to-plane +% visibility check is done by checking the plane-midpoint to plane-midpoint +% for obstructions, which might be enough for some geometries. +% SHOWTEXT (global) An integer value; if it is 4 or higher, then messages will be printed on the +% screen during calculations. +% Output parameters: +% outputfile The name of the outputfile, generated either automatically or specified as +% an input parameter. +% +% Output parameters in the outputfile: +% (Taken directly from the cadgeo-file:) +% corners planecorners planeeqs planenvecs ncornersperplanevec +% minvals maxvals planehasindents indentingcorners +% (Taken directly from the setup-file:) +% int_or_ext_model +% (Calculated by EDB1edgeo:) +% edgecorners Matrix [nedges,2] with the corner numbers that +% define each edge, in the reference order. +% edgestartcoords Matrix [nedges,3] with the coordinates of the +% start corner for each edge. +% edgeendcoords Matrix [nedges,3] with the coordinates of the +% end corner for each edge. +% edgelengthvec List [nedges,1] with the lengths of each edge. +% planesatedge Matrix [nedges,2] with the plane numbers of the +% two planes that connect to each edge. The first +% plane is considered as the reference plane for +% each edge. Rule: if the RH thumb is placed +% along the edge, from start to end, and the hand +% is rotated, the fingers should "come up +% through" the reference plane. +% closwedangvec List [nedges,1] with the angles in radians of +% each edge - for the closed part of each edge. +% edgenvecs Matrix [nedges,3] with the normal vectors of +% the reference plane for each edge. +% offedges List [nlength,1] where nlength = 0-nedges +% containing the edge numbers that should not +% used. +% reflfactors List [nplanes,1] with the reflection factors +% of each plane. The only supported values are +% +1 for rigid planes, 0 for perfectlt absorbing +% planes and -1 for pressure-release planes. The +% pressure-release cases might not be implemented +% fully. +% planeisthin List [nplanes,1] with the value 1 or 0 stating +% whether the plane is thin or not. +% rearsideplane List [nplanes,1] with the plane number that is at +% the rear side. If a plane is non-thin, the +% value in this list is zero. +% planehasindents List [nplanes,1] with the value 1 or 0 stating +% whether a plane has indents or not. +% indentingedgepairs Matrix [nindentingedgepairs,2] where each row +% gives two connected edges that form an indent +% in the shared plane. Consequently, those two +% edges can never see each other. +% canplaneobstruct List [nplanes,1] with the value 1 or 0 stating +% whether a plane has the potential to obstruct +% or not. +% planeseesplane A matrix, [nplanes,nplanes], with the value 1 +% 0,-1,-2 stating: +% 1 A plane is front of another plane and could +% then potentially see it. +% 0 A plane is completely behind another plane +% but they are not aligned +% -1 A plane is aligned with another plane +% -2 A plane is back-to-back with another plane. +% edgesatplane A matrix, [nplanes,nmaxedgesperplane] which for +% row N contains the edge numbers that connect to +% to plane N. +% edgeseesplane A matrix, [nplanes,nedges], which contains the +% values 0,1,-2 or -2, meaning: +% 0 The edge is completely behind a plane +% -1 The edge can never see the plane and the +% edge is aligned with the plane +% -2 The edge can never see the plane and the +% edge belongs to the plane +% 1 The edge has at least one point in front of the plane. +% +% Uses the functions EDB1coordtrans1 +% EDB1infrontofplane, EDB1strpend, EDB1cross +% +% ---------------------------------------------------------------------------------------------- +% This file is part of the Edge Diffraction Toolbox by Peter Svensson. +% +% The Edge Diffraction Toolbox is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) any later version. +% +% The Edge Diffraction Toolbox is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +% FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License along with the +% Edge Diffraction Toolbox. If not, see <http://www.gnu.org/licenses/>. +% ---------------------------------------------------------------------------------------------- +% Peter Svensson (svensson@iet.ntnu.no) 20090709 +% +% outputfile = EDB1edgeox(cadgeofile,outputfile,open_or_closed_model,int_or_ext_model,specorder,difforder,nedgesubs,firstskipcorner,planeseesplanestrategy); + +global SHOWTEXT + +geomacc = 1e-10; + +if nargin < 9 + planeseesplanestrategy = 0; + if nargin < 8 + firstskipcorner = 1e6; + if nargin < 7 + nedgesubs = 2; + if nargin < 6 + difforder = 1; + else + if isempty(difforder), difforder = 1; end + end + else + if isempty(nedgesubs), nedgesubs = 2; end + end + else + if isempty(firstskipcorner), firstskipcorner = 1e6; end + end +end + +%--------------------------------------------------------------- +% If no cadgeofile was specified, present a file opening window + +if isempty(cadgeofile) + [cadgeofile,filepath] = uigetfile('*.mat','Please select the cadgeofile'); + [filepath,temp1,temp2] = fileparts(filepath); + if ~isstr(cadgeofile) + return + end + [temp1,filestem,fileext,temp2] = fileparts(cadgeofile); + cadgeofile = [filepath,filestem,'.mat']; +else + [filepath,filestem,fileext] = fileparts(cadgeofile); + if ~isempty(filepath) + cadgeofile = [[filepath,filesep],filestem,'.mat']; + else + cadgeofile = [filestem,'.mat']; + end +end + + +%--------------------------------------------------------------- +% If no output file was specified, construct an automatic file name + +if isempty(outputfile) + filestem = EDB1strpend(filestem,'_cadgeo'); + outputfile = [[filepath,filesep],filestem,'_eddata.mat']; +end + +%--------------------------------------------------------------- + +eval(['load ',cadgeofile]) + +ncorners = length(cornernumbers); +[nplanes,maxncornersperplane] = size(planecorners); +minncornersperplane = min(ncornersperplanevec); +nedgesperplanevec = double(ncornersperplanevec); +ncornersperplanevec = double(ncornersperplanevec); + +switchoffcorners = find( cornernumbers >= firstskipcorner ); + +onesvec2 = ones(nplanes,1); +zerosvec1 = zeros(nplanes,1); +zerosvec2 = int8(zeros(nplanes,nplanes)); + +%---------------------------------------------------------------------------- +% +% GEOMETRICAL ACOUSTICS PARAMETERS +% +%---------------------------------------------------------------------------- +% +% Go through all planeabstypes. If it is: +% 'SOFT' or 'soft' then reflfactors should be -1. +% 'TOTA' or 'tota' then reflfactors should be 0 (short for TOTABS) +% Otherwise it is assumed to be rigid, so reflfactors = 1. + +if SHOWTEXT >= 4 + disp(' Check abstypes') +end + +[slask,nchars] = size(planeabstypes); +reflfactors = ones(nplanes,1); +if nchars >= 4 + planeabstypes = lower(full(planeabstypes(:,1:min([4,nchars])))); + + comptxt = 'soft'; + ivpotential = find(planeabstypes(:,1)==comptxt(1)); + if ~isempty(ivpotential) + comptxt = 'oft'; + compmat = comptxt(ones(length(ivpotential),1),:); + ivsoft = ivpotential(find(prod( (planeabstypes(ivpotential,2:4).*compmat).' ).')); + reflfactors(ivsoft) = -1*ones(size(ivsoft)); + end + + comptxt = 'tota'; + ivpotential = find(planeabstypes(:,1)==comptxt(1)); + if ~isempty(ivpotential) + comptxt = 'ota'; + compmat = comptxt(ones(length(ivpotential),1),:); + ivtotabs = ivpotential(find(prod( double(planeabstypes(ivpotential,2:4)==compmat).' ).')); + reflfactors(ivtotabs) = zeros(size(ivtotabs)); + end +end + +%---------------------------------------------------------------------------- +% +% EDGE PARAMETERS +% +%---------------------------------------------------------------------------- +% +% Check that the planecorners matrix contains no zeros. In such case +% add the circular repetition of coordinates. + +if SHOWTEXT >= 4 + disp(' Circular') +end +if sum(sum( planecorners == 0 )) ~= 0 + for ii = 1:nplanes + iv = find( planecorners(ii,:) ~= 0); + ncornersatplane = length(iv); + if ncornersatplane ~= maxncornersperplane + pattern = planecorners(ii,iv); + nrepeatings = ceil(maxncornersperplane/ncornersatplane); + for jj = 1:nrepeatings-1 + pattern = [pattern planecorners(ii,iv)]; + end + planecorners(ii,:) = pattern(1:maxncornersperplane); + end + end +end + +%-------------------------------------------------------------------------------- +% +% Find all edges +% +% Go through all planes. All consecutive pairs of corners form an edge. +% The list planesatedge gives the one or two planes that connect +% to each edge. If the second plane number, for a certain edge +% is zero, then that specific edge is a plate edge. + +edgesatplane = zeros( size(planecorners) ); + +if SHOWTEXT >= 4 + disp(' Defining edges...') +end + +nedgesguess = sum(ncornersperplanevec); +edgecorners = zeros(nedgesguess,2); +tempplanesatedge = zeros(nedgesguess,1); +nedges = 0; +thirdpoint = []; +edgecounter = 0; +multfac = round(10^(floor(log10(nedgesguess))+2)); + +% First go through all planes, and construct edges from the list of corners +% that define every plane. This way, many edges will occur twice, unless +% a thin plane has no rear side (then the edge occurs a single time) +% or if two thin planes are connected (then the edge occurs four times) + +for ii = 1:nplanes + for jj = 1:nedgesperplanevec(ii) + edgecounter = edgecounter + 1; + corner1 = planecorners(ii,jj); + if jj + 1 <= ncornersperplanevec(ii) + corner2 = planecorners(ii,jj+1); + else + corner2 = planecorners(ii,1); + end + edgecorners(edgecounter,:) = [corner1 corner2]; + tempplanesatedge(edgecounter) = ii; + end + +end + +if edgecounter < nedgesguess + edgecorners(edgecounter+1:nedgesguess,:) = []; + tempplanesatedge(edgecounter+1:nedgesguess,:) = []; +end + +% To find all duplicates, the edge list is sorted in numerical order +% If an edge is defined twice or four times, then this is an OK edge. +% If an edge is defined a single time, it is connected to a plane which is not connected, and then the +% edge should be switched off. +% If an edge is defined three times, there must be something like a reflector array where one of +% the rear planes is missing. + +[test,flipvec] = sort(edgecorners.'); +test = test.'; +flipvec = flipvec(1,:).'; + +test = test(:,1)*multfac + test(:,2); +[test,sortvec] = sort(test); +tempplanesatedge = tempplanesatedge(sortvec); +flipvec = flipvec(sortvec); +planesatedge = [tempplanesatedge.*(flipvec==1) tempplanesatedge.*(flipvec==2)]; + +% Check if there are loners; remove and give a warning. + +dtest = diff([0;test;test(length(test))+100]); +ntest = length(dtest); +loners = find(dtest(1:ntest-1)~=0 & dtest(2:ntest)~=0); + +if ~isempty(loners) + disp('WARNING! Some edges had only one plane connected and they will be excluded.') + disp(' Check if they should be corrected. ') + disp(' Remember that reflectors must have a plane at the rear side too') + disp(' Set SHOWTEXT to 4 or higher to get a list of these edges') + if SHOWTEXT >= 4 + disp(' The edges are (EDB1 corner numbers for the two edge point are given):') + nloners = length(loners); + for jjdisp = 1:nloners + indlon = loners(jjdisp); + disp([' ',int2str( floor(test(indlon)/multfac) ),' ',int2str( test(indlon)-floor(test(indlon)/multfac)*multfac )]) + disp([' CATT: ',int2str( cornernumbers(floor(test(indlon)/multfac) )),' ',int2str( cornernumbers(test(indlon)-floor(test(indlon)/multfac)*multfac ))]) + end + end + + test(loners) = []; + planesatedge(loners,:) = []; + +end + +ntest = length(test); +if ntest >= 2 + if test(ntest) ~= test(ntest-1) + test(ntest) = []; + planesatedge(ntest,:) = []; + end +end + +% Check if there are triplets + +triptest = test(1:2:length(test))-test(2:2:length(test)); +triplets = find(triptest~=0); + +if ~isempty(triplets) + disp('ERROR: Triplets: some edges are defined three times which means that two thin planes have a correct') + disp(' definition but some error on the rear side. You must correct these. ') + disp(' Only the first one can be detected; it is:') + disp(' (EDB1 corner numbers for the two edge points are given)') + [floor(test(triplets(1)*2-1)/multfac) test(triplets(1)*2-1)-floor(test(triplets(1)*2-1)/multfac)*multfac] + save ~/Documents/Temp/test.mat + error +end + +edgecounter = length(test); + +iv1 = find(planesatedge(:,1)~=0); +iv2 = 1:edgecounter; +iv2(iv1) = []; + +edgecorners = [floor(test(iv1)/multfac) test(iv1)-floor(test(iv1)/multfac)*multfac]; +planesatedge = planesatedge(iv1,:) + planesatedge(iv2,:); + +[nedges,slask] = size(edgecorners); + +zerosvec3 = zeros(nedges,1); +zerosvec5 = zeros(nedges,3); + +if SHOWTEXT >= 4 + disp([' ',int2str(nedges),' edges found']) +end +thirdpoint = zerosvec5; +for ii = 1:nedges + refplane = planesatedge(ii,1); + secondplane = planesatedge(ii,2); + if secondplane ~= 0 + edgeco1 = corners(edgecorners(ii,1),:); + edgeco2 = corners(edgecorners(ii,2),:); + edgemidpoint = edgeco1 + (edgeco2-edgeco1)/2; + intoplanevec = EDB1cross( (edgeco2-edgeco1).',(planenvecs(secondplane,:)).').'; + inplanepoint = edgemidpoint + intoplanevec*0.1; + if sum(abs(inplanepoint)) == 0 + inplanepoint = edgemidpoint + intoplanevec*0.2; + end + thirdpoint(ii,:) = inplanepoint; + end +end + + +%--------------------------------------------------------------- +% Calculate the closwedang values for all edges + +if SHOWTEXT >= 4 + disp(' wedge angles...') +end +closwedangvec = zerosvec3; + +ivec = find( planesatedge(:,1).*planesatedge(:,2) ~= 0); +xwedgevec = [corners(edgecorners(ivec,1),:) corners(edgecorners(ivec,2),:)]; +nvec1vec = planenvecs( planesatedge(ivec,1),: ); +xsouvec = thirdpoint(ivec,:); + +for jj = 1:length(ivec) + + ii = ivec(jj); + [slask,thetas,slask] = EDB1coordtrans1(xsouvec(jj,:),[xwedgevec(jj,1:3);xwedgevec(jj,4:6)],nvec1vec(jj,:)); + if thetas == 0 + closwedangvec(ii) = 0; + else + closwedangvec(ii) = 2*pi - thetas; + end + +end + +%------------------------------------------------------------------- +% Now we check for duplicates of the edge definitions +% Some edge definitions might need to be swapped: if there are duplicate edges, +% and one of them has closwedangvec = 0 +% then there is a mistake in the edge definition, so a swap will be made. + +edgecosinglelist = edgecorners(:,1)*multfac + edgecorners(:,2); +nsteps = diff([0;edgecosinglelist]); +ivduplicates = find(nsteps == 0); +nduplicates = length(ivduplicates); +if nduplicates > 0 + if SHOWTEXT >= 4 + disp([' ',int2str(nduplicates),' edges formed by connected thin plates']) + end + for ii = 1:nduplicates + comb1 = ivduplicates(ii)-1; + comb2 = comb1+1; + if closwedangvec(comb1) == 0 | closwedangvec(comb2) == 0, % edge definitions should be swapped + plane1 = planesatedge(comb1,2); + plane2 = planesatedge(comb2,2); + planesatedge(comb1,2) = plane2; + planesatedge(comb2,2) = plane1; + temp1 = thirdpoint(comb1,:); + temp2 = thirdpoint(comb2,:); + thirdpoint(comb1,:) = temp2; + thirdpoint(comb2,:) = temp1; + if SHOWTEXT >= 4 + disp([' Swapping an edge definition']) + disp([' Planes ',int2str(planesatedge(comb1,1)),' and ',int2str(planesatedge(comb1,2))]) + disp([' CATT: ',int2str(planenumbers(planesatedge(comb1,1))),' and ',int2str(planenumbers(planesatedge(comb1,2)))]) + disp([' Planes ',int2str(planesatedge(comb2,1)),' and ',int2str(planesatedge(comb2,2))]) + disp([' CATT: ',int2str(planenumbers(planesatedge(comb2,1))),' and ',int2str(planenumbers(planesatedge(comb2,2)))]) + end + + xwedge = [corners(edgecorners(comb1,1),:);corners(edgecorners(comb1,2),:)]; + nvec1 = planenvecs( planesatedge(comb1,1),: ); + xsou = thirdpoint(comb1,:); + [slask,thetas,slask] = EDB1coordtrans1(xsou,xwedge,nvec1); + if thetas == 0 + closwedangvec(comb1) = 0; + else + closwedangvec(comb1) = 2*pi - thetas; + end + + xwedge = [corners(edgecorners(comb2,1),:);corners(edgecorners(comb2,2),:)]; + nvec1 = planenvecs( planesatedge(comb2,1),: ); + xsou = thirdpoint(comb2,:); + [slask,thetas,slask] = EDB1coordtrans1(xsou,xwedge,nvec1); + if thetas == 0 + closwedangvec(comb2) = 0; + else + closwedangvec(comb2) = 2*pi - thetas; + end + + end % if closwedangvec(comb1) == 0 | + + end % for ii = 1:nduplicates +end + +if nplanes < 256 + planesatedge = uint8(planesatedge); +elseif nplanes < 65535 + planesatedge = uint16(planesatedge); +else + planesatedge = uint32(planesatedge); +end + +%------------------------------------------------------------------- +% Find which edges each plane is connected to + +if SHOWTEXT >= 4 + disp(' find edgesatplane') +end + +edgesatplane = zeros(nplanes,double(max(ncornersperplanevec))); + +for ii= 1:nplanes + iv = find(planesatedge==ii); + iv = iv - floor((iv-1)/nedges)*nedges; + if ~isempty(iv) + edgesatplane(ii,1:length(iv)) = iv.'; + end +end + +% Check how many edges are defined for each plane. There must be at +% least three edges per plane. + +tempnedgesperplanevec = sum(edgesatplane.'~=0).'; + +iv = find(tempnedgesperplanevec<3); + +if ~isempty(iv) + + disp(' ') + if SHOWTEXT >= 4 + for ii = 1:length(iv) + disp([' Plane ',int2str(iv(ii)),' has only ',int2str(tempnedgesperplanevec(iv(ii))),' edges connected to it']) + end + error(['ERROR: The planes above have less than three edges.']) + else + error(['ERROR: Some planes have less than three edges. Set SHOWTEXT >= 4 to see a list of those planes.']) + end + +end + + + +%------------------------------------------------------------------- +% Make a special list of thin planes + +planeisthin = zerosvec1; +rearsideplane = zerosvec1; + +iv = find(closwedangvec==0); +if ~isempty(iv) + planenumberlist = planesatedge(iv,1); + planeisthin(planenumberlist) = planeisthin(planenumberlist) + 1; + rearsideplane(planenumberlist) = planesatedge(iv,2); +end + +iv = find(closwedangvec == 0 & planesatedge(:,2)~=0); +if ~isempty(iv) + planenumberlist = planesatedge(iv,2); + planeisthin(planenumberlist) = planeisthin(planenumberlist) + 1; + rearsideplane(planenumberlist) = planesatedge(iv,1); +end + +planeisthin = sign(planeisthin); +listofthinplanes = find(planeisthin); + +%--------------------------------------------------------------- +% Closwedangvec should be calculated into nyvec + +nyvec = pi./(2*pi - closwedangvec); +integerny = ( abs(nyvec - round(nyvec)) < 1e-10 ); + +%----------------------------------------------------------- +% Construct some other useful edge variables + +if difforder >= 1 + edgestartcoords = zerosvec5; + edgestartcoordsnudge = zerosvec5; + edgeendcoords = zerosvec5; + edgeendcoordsnudge = zerosvec5; + edgemidcoords = zerosvec5; + edgenvecs = zerosvec5; + + edgestartcoords = [corners(edgecorners(:,1),:)]; + edgeendcoords = [corners(edgecorners(:,2),:)]; + edgemidcoords = (edgestartcoords+edgeendcoords)/2; + edgenvecs = planenvecs(planesatedge(:,1),:); + + edgenormvecs = edgeendcoords - edgestartcoords; + + edgestartcoordsnudge = edgestartcoords + 1e-10*edgenormvecs; + edgeendcoordsnudge = edgeendcoords - 1e-10*edgenormvecs; + + edgelengthvec = sqrt(sum( ((edgenormvecs).^2).' )).'; + edgenormvecs = edgenormvecs./edgelengthvec(:,ones(1,3)); + +else + edgestartcoords = []; + edgeendcoords = []; + edgenvecs = []; + edgelengthvec = []; +end + + +%--------------------------------------------------------------- +% +% BACK TO SOME PURE PLANE RELATED PARAMETERS +% +%--------------------------------------------------------------- +% +% First, make a list of which planes that are absorbing/non-reflective + +planeisabsorbing = zerosvec1; + +listofactiveplanes = find(reflfactors~=0); +listofabsorbingplanes = find(reflfactors == 0); +planeisabsorbing(listofabsorbingplanes) = ones(size(listofabsorbingplanes)); + +%--------------------------------------------------------------- +% Help variables: planealignedwplane and planeconnectstoplane +% +% Preparatory for the check of which planes see which plane: check +% if any planes are aligned with each other. If two planes are aligned +% then planealignedwplane = 1 for that combination. +% However, if two planes are back-to back (thin planes), then +% planealignedwplane = 2 for that combination. +% +% Also make a matrix of which planes connect to which planes and via +% which edges. + +planealignedwplane = zerosvec2; + +% First, check which planes are aligned with each other + +for ii = 1:nplanes-1 + if planeisabsorbing(ii) ~= 1 + oneplaneeq = planeeqs(ii,:); + diffvec1 = oneplaneeq(ones(nplanes-ii,1),:) - planeeqs(ii+1:nplanes,:); + diffvec2 = oneplaneeq(ones(nplanes-ii,1),:) + planeeqs(ii+1:nplanes,:); + diffvec = min( [sum( diffvec1.'.^2 ).' sum( diffvec2.'.^2 ).'].' ).'; + alignedplanes = find(diffvec < geomacc) + ii; + if ~isempty(alignedplanes) + planealignedwplane(alignedplanes,ii) = int8(double(planealignedwplane(alignedplanes,ii)) + double((planeisabsorbing(alignedplanes)~=1))); + end + end +end + +planealignedwplane = (sparse(sign(double(planealignedwplane) + double(planealignedwplane).'))); + +% Second, check which planes are back to back + +if ~isempty(listofthinplanes) + for ii = 1:length(listofthinplanes) + plane = listofthinplanes(ii); + rearplane = rearsideplane(plane); + if planeisabsorbing(plane) ~= 1 & planeisabsorbing(rearplane) ~= 1 + planealignedwplane(plane,rearplane) = 2; + planealignedwplane(rearplane,plane) = 2; + end + end +end + +planeconnectstoplane = zerosvec2; +clear zerosvec2 + +for ii = 1:nplanes + if planeisabsorbing(ii) ~= 1 + edgelist = edgesatplane(ii,:); + edgelist = edgesatplane(ii,1:double(ncornersperplanevec(ii))); + ivec = planesatedge(edgelist,:); + ivec = reshape(ivec.',length(edgelist)*2,1); + ivec = ivec(find(ivec~=ii)); + okplanes = find(planeisabsorbing(ivec)~=1); + ivec = ivec(okplanes); + if ~isempty(ivec) + planeconnectstoplane(ii,ivec) = edgelist(okplanes); + end + end +end + +%--------------------------------------------------------------- +% +% planeseesplane +% +%--------------------------------------------------------------- +% Check which planes see which planes: +% 1. If one of the planes has reflfactors = 0, then the two can't see each other. +% 2. Reflective planes that are aligned with each other can not reach each other +% 3. Reflective planes that are not aligned but have the same normal vectors +% can not reach each other +% 4. Planes that have all its corners behind another plane can not be seen by that plane. +% +% planeseesplane = 0 means that either, one of the planes is non-reflective or, that +% two planes never can see each other, but they are not aligned with each other. +% planeseesplane = 1 means that two reflective planes might see each other, but there could +% be obstructions +% planeseesplane = -1 means that two reflective planes are aligned (but they are not back-to-back) +% and thus they can never see each other. +% planeseesplane = -2 means that two reflective planes are back-to-back with each other and thus +% they can never see each other. + +if SHOWTEXT >= 4 + disp(' Check which planes see which planes') +end + +% First an auxilliary matrix which can be used for edgeseesplane later: +% cornerinfrontofplane, size [nplanes,ncorners] +% Values are the same as given by EDB1infrontofplane: +% 1 means that a point is in front of the plane +% 0 means that a point is aligned with a plane +% -1 means that a point is behind a plane +% All corners that belong to a plane will have the value 0. + +% Corner number is given by the col no. +if ncorners < 256 + cornernumb = uint8([1:ncorners]); +elseif ncorners < 65536 + cornernumb = uint16([1:ncorners]); +else + cornernumb = uint32([1:ncorners]); +end + +% Plane numbers is given by the row no. +if nplanes < 256 + planenumb = uint8([1:nplanes].'); +elseif nplanes < 65536 + planenumb = uint16([1:nplanes].'); +else + planenumb = uint32([1:nplanes].'); +end + +cornerinfrontofplane = int8(EDB1infrontofplane(corners,planenvecs,planecorners,[],cornernumb,planenumb)); +clear planenumb cornernumb +cornerinfrontofplane = reshape(cornerinfrontofplane,nplanes,ncorners); + +planeseesplane = int8(ones(nplanes,nplanes)); + +% 1. If one of the planes has reflfactors = 0, then the two can't see each other. + +if ~isempty(listofabsorbingplanes) + zerosvec = zeros(length(listofabsorbingplanes),nplanes); + planeseesplane(listofabsorbingplanes,:) = zerosvec; + planeseesplane(:,listofabsorbingplanes) = zerosvec.'; +end + +% 2. Reflective planes that are aligned with each other can not reach each other + +ivec = find( planealignedwplane == 1); +if ~isempty(ivec) + planeseesplane(ivec) = - 1*ones(size(ivec)); +end + +ivec = find( planealignedwplane == 2); +if ~isempty(ivec) + planeseesplane(ivec) = - 2*ones(size(ivec)); +end + +% 3. Reflective planes that have the same normal vectors can not reach each other + +numvec = [1:nplanes]; +for ii = 1:nplanes + if planeisabsorbing(ii) ~= 1 + nvec1 = planenvecs(ii,:); + ivec = find(planealignedwplane(ii,:)==0 & planeisabsorbing.'==0 & numvec>ii); + if ~isempty(ivec) + similarvec = abs( nvec1(ones(length(ivec),1),:) - planenvecs(ivec,:)) < geomacc; + similarvec = prod( double(similarvec.') ).'; + ivec2 = ivec(find(similarvec==1)); + if ~isempty(ivec2) + zerosvec = zeros(size(ivec2)); + planeseesplane(ii,ivec2) = zerosvec; + planeseesplane(ivec2,ii) = zerosvec.'; + end + end + end +end + +% 3.5 A plane does not see itself + +iv = [0:nplanes-1]*nplanes + [1:nplanes]; +planeseesplane(iv) = zeros(size(iv)); + +% 4. Planes that have all its corners behind another plane can not be seen by that plane. +% First, we construct a list referring to the complete matrix of size [nplanes,nplanes] +% The index vector is called iv. Then we find which combinations that +% could be cleared. After having cleared a number of combinations (in +% iv, fromplanenumb and toplanenumb) we pick out out only the non-zero +% indices in iv. + +if nplanes*nplanes < 128 + iv = int8([1:nplanes*nplanes].'); +elseif nplanes*nplanes < 32768 + iv = int16([1:nplanes*nplanes].'); +else + iv = int32([1:nplanes*nplanes].'); +end +iv = reshape(iv,nplanes,nplanes); + +% If there are any absorbing planes, we zero all plane-to-plane +% combinations that involve such a plane + +if ~isempty(listofabsorbingplanes) + nabsorbingplanes = length(listofabsorbingplanes); + iv(listofabsorbingplanes,:) = zeros(nabsorbingplanes,nplanes); + iv(:,listofabsorbingplanes) = zeros(nplanes,nabsorbingplanes); +end + +% Check connecting planes first: if two planes are connected and their +% shared edge has a closwedangvec > pi, then the two planes can see each +% other. So, we can zero the plane-pair combinations where closwedangvec +% <= pi but larger than zero. + +edgecombstozero = find(closwedangvec<=pi & closwedangvec > 0); +if ~isempty(edgecombstozero) + ivzerocombs = (double(planesatedge(edgecombstozero,1))-1)*nplanes + double(planesatedge(edgecombstozero,2)); + iv(ivzerocombs) = zeros(size(ivzerocombs)); + ivzerocombs = (double(planesatedge(edgecombstozero,2))-1)*nplanes + double(planesatedge(edgecombstozero,1)); + iv(ivzerocombs) = zeros(size(ivzerocombs)); +end + +% Now we should keep only the index numbers in iv that are still non-zero +% We also take the chance to zero planeseesplane for the combinations that +% could be cleared. +ivclear = uint32(find(iv==0)); +planeseesplane(ivclear) = zeros(size(ivclear)); +iv(ivclear) = []; + +% Of the remaining plane-to-plane combinations, we pick out the ones +% for which we need to check if the "to-plane" is in front of the "from-plane" +iv = iv(find(planeseesplane(iv)==1 & planeconnectstoplane(iv)==0)); + +% We create full matrices, fromplanenumb and toplanenumb, and then keep +% only the combinations that remain in iv +% to keep fromplanenumb and toplanenumb aligned with iv. + +% To-plane numbers is given by the row no. +if nplanes < 256 + toplanenumb = uint8([1:nplanes].'); +elseif nplanes < 65536 + toplanenumb = uint16([1:nplanes].'); +else + toplanenumb = uint32([1:nplanes].'); +end +toplanenumb = reshape(toplanenumb(:,ones(1,nplanes)),nplanes*nplanes,1); +toplanenumb = toplanenumb(iv); + +% From-plane numbers is given by the col no. +if nplanes < 256 + fromplanenumb = uint8([1:nplanes]); +elseif nplanes < 65536 + fromplanenumb = uint16([1:nplanes]); +else + fromplanenumb = uint32([1:nplanes]); +end +fromplanenumb = reshape(fromplanenumb(ones(nplanes,1),:),nplanes*nplanes,1); +fromplanenumb = fromplanenumb(iv); + +% Now, if a plane has *all* its corners behind another plane, those two +% planes can not see each other. +% We check the corners of the "to-plane" (columns) and check if they are in front of +% the "from-plane" (rows). +% The ivreftocoplamatrix is the index number to the +% cornerinfrontofplanematrix, which has the size [nplanes,ncorners]. +% NB! In order to save some space, we don't construct the ivreftocoplamatrix specifically. + +% First we check the first 3 corners since all planes have at least 3 +% corners. + +% Plane corner 1 +cornersbehind = cornerinfrontofplane(double(fromplanenumb) + ( double(planecorners( toplanenumb,1 ))-1 )*nplanes)<1; + +% Plane corner 2 +cornersbehind = cornersbehind &(cornerinfrontofplane(double(fromplanenumb) + ( double(planecorners( toplanenumb,2 ))-1 )*nplanes) < 1); + +% Plane corner 3 +cornersbehind = cornersbehind &(cornerinfrontofplane(double(fromplanenumb) + ( double(planecorners( toplanenumb,3 ))-1 )*nplanes) < 1); + +if minncornersperplane == 4 & maxncornersperplane == 4 +% Plane corner 4 + cornersbehind = cornersbehind &(cornerinfrontofplane(double(fromplanenumb) + ( double(planecorners( toplanenumb,4 ))-1 )*nplanes) < 1); +elseif not(minncornersperplane == 3 & maxncornersperplane == 3) + ivall = uint32([1:length(fromplanenumb)].'); + if minncornersperplane == 3 + iv3cornerplanes = find(ncornersperplanevec(toplanenumb)==3); + ivall(iv3cornerplanes) = []; + end + if maxncornersperplane == 4 +% Plane corner 4 + cornersbehind(ivall) = cornersbehind(ivall) &(cornerinfrontofplane(double(fromplanenumb(ivall)) + ( double(planecorners( toplanenumb(ivall),4 ))-1 )*nplanes) < 1); + else + ivmorethan4 = find(ncornersperplanevec(toplanenumb(ivall))>4); + temp = ivall(ivmorethan4); + ivall(ivmorethan4) = []; + ivmorethan4 = temp; + cornersbehind(ivall) = cornersbehind(ivall) &(cornerinfrontofplane(double(fromplanenumb(ivall)) + ( double(planecorners( toplanenumb(ivall),4 ))-1 )*nplanes) < 1); + for ii = 5:maxncornersperplane + ivselection = find(ncornersperplanevec(toplanenumb(ivmorethan4))>=ii); + cornersbehind(ivmorethan4(ivselection)) = cornersbehind(ivmorethan4(ivselection)) &(cornerinfrontofplane(double(fromplanenumb(ivmorethan4(ivselection))) + ( double(planecorners( toplanenumb(ivmorethan4(ivselection)),ii ))-1 )*nplanes) < 1); + end + clear ivselection + end +end +clear toplanenumb fromplanenumb + +ivclear = iv(find(cornersbehind==1)); +clear iv + +planeseesplane(ivclear) = zeros(size(ivclear)); +clear ivclear + +temp1 = (planeseesplane~=0); +temp2 = (planeseesplane.'~=0); +planeseesplane = int8(double(planeseesplane).*(temp1.*temp2)); + +% New addition: +% If the user has asked for it, check plane-mid-point to plane-mid-point +% for obstruction. If there are obstructions, set planeseesplane to 0 for +% that combination. + +if planeseesplanestrategy == 1 + ivorig = uint32(find(planeseesplane==1)); + iv = ivorig; + fromplane = ceil(double(iv)/nplanes); + toplane = uint16(double(iv) - (fromplane-1)*nplanes); + fromplane = uint16(fromplane); + listofplanesthatcanobscure = find( sum(planeseesplane==1) ); + + iv4planes = find(ncornersperplanevec == 4); + planemidpoints = zeros(nplanes,3); + + if any(ncornersperplanevec~=4) + disp('WARNING: planeseesplanestrategy 1 not implemented for models with non-4-corner planes') + planeseesplanestrategy = 0; + else + xvalues = corners(planecorners.',1); + xvalues = reshape(xvalues,4,length(xvalues)/4); + yvalues = corners(planecorners.',2); + yvalues = reshape(yvalues,4,length(yvalues)/4); + zvalues = corners(planecorners.',3); + zvalues = reshape(zvalues,4,length(zvalues)/4); + planemidpoints = [mean(xvalues).' mean(yvalues).' mean(zvalues).']; + end +end + +if planeseesplanestrategy == 1 + for ii = listofplanesthatcanobscure + planeobsc = ii; + ivcheckvis1 = uint32( planeobsc + (double(fromplane)-1)*nplanes); + ivcheckvis2 = uint32( planeobsc + (double(toplane)-1)*nplanes); + iv3 = find(toplane~=planeobsc & fromplane~=planeobsc & ((planeseesplane(ivcheckvis1) == 1) | (planeseesplane(ivcheckvis2) == 1)) & (planeseesplane(ivcheckvis1) >= 0) & (planeseesplane(ivcheckvis2) >= 0) ); + tempcanplaneobstruct = zerosvec1.'; + tempcanplaneobstruct(planeobsc) = 1; + [nonobstructedpaths,nobstructions,edgehits,cornerhits] = EDB1checkobstrpaths(planemidpoints(fromplane(iv3),:),planemidpoints(toplane(iv3),:),[],[],tempcanplaneobstruct,planeseesplane,... + planeeqs,planenvecs,minvals,maxvals,planecorners,corners,ncornersperplanevec,rearsideplane); + if length(iv3) > length(nonobstructedpaths) + iv3(nonobstructedpaths) = []; + iv(iv3) = []; + toplane(iv3) = []; + fromplane(iv3) = []; + end + end + planeseesplane(ivorig) = 0; + planeseesplane(iv) = 1; + clear iv ivorig toplane fromplane ivcheckvis ivcheckvis2 +end + +%--------------------------------------------------------------- +% +% EDGE RELATED PARAMETERS AGAIN +% +%--------------------------------------------------------------- +% +% Which edges should be switched off? +% (1) Go through the list edgecorners. If any edge contains one of the +% corners, whose numbers are in switchoffcorners, then that edge should be +% stored in the list offedges. +% (2) If an edge has an integer ny-value, then it should be switched off. +% (3) If one of the two connecting planes has reflfactors = 0, then it should +% be switched off. + +% disp(' switching off possibly unwanted edges...') + +offedges = zerosvec3; + +% (1) Go through the list edgecorners. If any edge contains one of the +% corners, whose numbers are in switchoffcorners, then that edge should be +% stored in the list offedges. + +if ~isempty(switchoffcorners) + for ii = 1:nedges + corner1 = edgecorners(ii,1); + corner2 = edgecorners(ii,2); + remove = sum( corner1 == switchoffcorners ) + sum( corner2 == switchoffcorners ); + offedges(ii) = sign(remove); + end +end + +% (2) If an edge has an integer ny-value, then it should be switched off. + +offedges = offedges + integerny; + +% (3) If one of the two connecting planes has reflfactors = 0, then it should +% be switched off. + +reflectingedges = reshape(reflfactors(planesatedge),nedges,2); +reflectingedges = reflectingedges(:,1).*reflectingedges(:,2); +offedges = offedges + (1-reflectingedges); + +offedges = find(offedges ~= 0); + +%-------------------------------------------------------------------------------- +% +% edgeseesplane +% +%-------------------------------------------------------------------------------- +% +% Now check which planes each edge can see. +% 1. Set all combinations with reflfactors = 0 to -3 +% 2. Switch off all combinations with offedges +% 3. For all edges that are aligned with a plane, set edgeseesplane to: +% -1 if the edge doesn't belong to the plane +% -2 if the edge does belong to the plane +% 4. If at least one edge end point is in front of a plane, then the +% plane is potentially visible (edgeseesplane = 1) +% 5. If at least one corner point is in front of: +% *one* of the two edge planes, when closwedang < pi +% *both* edge planes, when closwedangvec > pi + +if SHOWTEXT >= 4 + disp(' Check which edges see which planes') +end + +edgeseesplane = int8(ones(nplanes,nedges)); + +% % % 20120414 PS: Why has this first stage been shut off? CHECK +% 1. Set all edges belonging to planes with reflfactors = 0 to +% edgeseesplane = -3. + +% % if ~isempty(listofabsorbingplanes) +% % edgeseesplane(listofabsorbingplanes,:) = -3*ones(length(listofabsorbingplanes),nedges); +% % end + +% 2. Switch off all combinations with offedges + +if ~isempty(offedges) + edgeseesplane(:,offedges) = zeros(nplanes,length(offedges)); +end + +% 3. For all edges that belong to a plane, set edgeseesplane to -2 +% Also, for all other edges that are aligned with a plane, set +% edgeseesplane to -1 + +edgelist = [1:nedges].'; +edgelist(offedges) = []; + +plane1list = planesatedge(edgelist,1); +plane2list = planesatedge(edgelist,2); +indexvec = uint32( double(plane1list) + (edgelist-1)*nplanes); +edgeseesplane(indexvec) = -2*(reflfactors(plane1list)~=0); +indexvec = uint32( double(plane2list) + (edgelist-1)*nplanes); +edgeseesplane(indexvec) = -2*(reflfactors(plane2list)~=0); + +for ii = 1:length(edgelist) + + aligners1 = find(planealignedwplane(:,plane1list(ii))==1); + if ~isempty(aligners1) + edgeseesplane(aligners1,edgelist(ii)) = -1*ones(size(aligners1)); + end + + aligners2 = find(planealignedwplane(:,plane2list(ii))==1); + if ~isempty(aligners2) + edgeseesplane(aligners2,edgelist(ii)) = -1*ones(size(aligners2)); + end + +end + +% 4. If at least one edge end point is in front of a plane, then the +% plane is potentially visible. +% Do this for all plane-edge combinations for which edgeseesplane = 1 +% up til now. +% 5. If at least one corner point is in front of: +% *one* of the two edge planes, when closwedang < pi +% *both* edge planes, when closwedangvec > pi + +ntot = nplanes*nedges; +ivclear = find(edgeseesplane~=1); +% Edge number is given by the col no. +if nedges < 256 + edgenumb = uint8([1:nedges]); +elseif nedges < 65536 + edgenumb = uint16([1:nedges]); +else + edgenumb = uint32([1:nedges]); +end +edgenumb = reshape(edgenumb(ones(nplanes,1),:),nplanes*nedges,1); +edgenumb(ivclear) = []; +% Plane numbers is given by the row no. +if nplanes < 256 + planenumb = uint8([1:nplanes].'); +elseif nplanes < 65536 + planenumb = uint16([1:nplanes].'); +else + planenumb = uint32([1:nplanes].'); +end +planenumb = reshape(planenumb(:,ones(1,nedges)),nplanes*nedges,1); +planenumb(ivclear) = []; + +if nplanes*nedges < 128 + iv = int8([1:nplanes*nedges].'); +elseif nplanes*nedges < 32768 + iv = int16([1:nplanes*nedges].'); +else + iv = int32([1:nplanes*nedges].'); +end +iv(ivclear) = []; + +if ~isempty(edgenumb) + % For the "edgecorners in front of plane"-test + % we can use the cornerinfrontofplane matrix, but we need to construct + % index vectors, based on the planenumb and edgenumb values. + + edgeinfrontofplane = cornerinfrontofplane( double(planenumb) + ( double( edgecorners(edgenumb,1) )-1 )*nplanes ); + edgeinfrontofplane = (edgeinfrontofplane==1) | (cornerinfrontofplane( double(planenumb) + ( double( edgecorners(edgenumb,2) )-1 )*nplanes )==1); + edgeseesplane(iv) = int8(double(edgeseesplane(iv)).*double(edgeinfrontofplane)); + clear edgeinfrontofplane +end + +if ~isempty(edgenumb) + % For the "planecorners in front of edge-plane"-test + % we can use the cornerinfrontofplane matrix, but we need to construct + % index vectors, based on the planenumb and edgenumb values. + % + % First we split up the iv into two halves: the one with edges < pi and the + % one with edges > pi; + + ivsmaller = uint32(find(closwedangvec(edgenumb)<pi)); + ivlarger = uint32([1:length(edgenumb)].'); + ivlarger(ivsmaller) = []; + + if ~isempty(ivsmaller) + % First the edges smaller than pi (closwedang < pi): at least one plane corner needs + % to be in front of one or the other plane. + % Plane corner 1 + ivreftocoplamatrix = double( planesatedge(edgenumb(ivsmaller),1) ) + ( double(planecorners( planenumb(ivsmaller),1 ))-1 )*nplanes; + planecornerinfrontofedge = cornerinfrontofplane(ivreftocoplamatrix)==1; + ivreftocoplamatrix = double( planesatedge(edgenumb(ivsmaller),2) ) + ( double(planecorners( planenumb(ivsmaller),1 ))-1 )*nplanes; + planecornerinfrontofedge = planecornerinfrontofedge | (cornerinfrontofplane(ivreftocoplamatrix)==1); + % Plane corner 2 + ivreftocoplamatrix = double( planesatedge(edgenumb(ivsmaller),1) ) + ( double(planecorners( planenumb(ivsmaller),2 ))-1 )*nplanes; + planecornerinfrontofedge = planecornerinfrontofedge | (cornerinfrontofplane(ivreftocoplamatrix)==1); + ivreftocoplamatrix = double( planesatedge(edgenumb(ivsmaller),2) ) + ( double(planecorners( planenumb(ivsmaller),2 ))-1 )*nplanes; + planecornerinfrontofedge = planecornerinfrontofedge | (cornerinfrontofplane(ivreftocoplamatrix)==1); + % Plane corner 3 + ivreftocoplamatrix = double( planesatedge(edgenumb(ivsmaller),1) ) + ( double(planecorners( planenumb(ivsmaller),3 ))-1 )*nplanes; + planecornerinfrontofedge = planecornerinfrontofedge | (cornerinfrontofplane(ivreftocoplamatrix)==1); + ivreftocoplamatrix = double( planesatedge(edgenumb(ivsmaller),2) ) + ( double(planecorners( planenumb(ivsmaller),3 ))-1 )*nplanes; + planecornerinfrontofedge = planecornerinfrontofedge | (cornerinfrontofplane(ivreftocoplamatrix)==1); + + if minncornersperplane == 4 & maxncornersperplane == 4 + % Plane corner 4 + ivreftocoplamatrix = double( planesatedge(edgenumb(ivsmaller),1) ) + ( double(planecorners( planenumb(ivsmaller),4 ))-1 )*nplanes; + planecornerinfrontofedge = planecornerinfrontofedge | (cornerinfrontofplane(ivreftocoplamatrix)==1); + ivreftocoplamatrix = double( planesatedge(edgenumb(ivsmaller),2) ) + ( double(planecorners( planenumb(ivsmaller),4 ))-1 )*nplanes; + planecornerinfrontofedge = planecornerinfrontofedge | (cornerinfrontofplane(ivreftocoplamatrix)==1); + elseif not(minncornersperplane == 3 & maxncornersperplane == 3) + ivall = uint32(1:length(ivsmaller)); + if minncornersperplane == 3 + iv3cornerplanes = find(ncornersperplanevec(planenumb(ivsmaller))==3); + ivall(iv3cornerplanes) = []; + end + if maxncornersperplane == 4 + % Plane corner 4 + ivreftocoplamatrix = double( planesatedge(edgenumb(ivsmaller(ivall)),1) ) + ( double(planecorners( planenumb(ivsmaller(ivall)),4 ))-1 )*nplanes; + planecornerinfrontofedge(ivall) = planecornerinfrontofedge(ivall) | (cornerinfrontofplane(ivreftocoplamatrix)==1); + ivreftocoplamatrix = double( planesatedge(edgenumb(ivsmaller(ivall)),2) ) + ( double(planecorners( planenumb(ivsmaller(ivall)),4 ))-1 )*nplanes; + planecornerinfrontofedge(ivall) = planecornerinfrontofedge(ivall) | (cornerinfrontofplane(ivreftocoplamatrix)==1); + else + ivmorethan4 = find(ncornersperplanevec(planenumb(ivsmaller(ivall)))>4); + temp = ivall(ivmorethan4); + ivall(ivmorethan4) = []; + ivmorethan4 = temp; + % Plane corner 4 + ivreftocoplamatrix = double( planesatedge(edgenumb(ivsmaller(ivall)),1) ) + ( double(planecorners( planenumb(ivsmaller(ivall)),4 ))-1 )*nplanes; + planecornerinfrontofedge(ivall) = planecornerinfrontofedge(ivall) | (cornerinfrontofplane(ivreftocoplamatrix)==1); + ivreftocoplamatrix = double( planesatedge(edgenumb(ivsmaller(ivall)),2) ) + ( double(planecorners( planenumb(ivsmaller(ivall)),4 ))-1 )*nplanes; + planecornerinfrontofedge(ivall) = planecornerinfrontofedge(ivall) | (cornerinfrontofplane(ivreftocoplamatrix)==1); + for ii = 5:maxncornersperplane + % Plane corner 5,6,7,etc + ivselection = find(ncornersperplanevec(planenumb(ivsmaller(ivmorethan4)))>=ii); + ivreftocoplamatrix = double( planesatedge(edgenumb(ivsmaller(ivmorethan4)),1) ) + ( double(planecorners( planenumb(ivsmaller(ivmorethan4)),4 ))-1 )*nplanes; + planecornerinfrontofedge(ivmorethan4) = planecornerinfrontofedge(ivmorethan4) | (cornerinfrontofplane(ivreftocoplamatrix)==1); + ivreftocoplamatrix = double( planesatedge(edgenumb(ivsmaller(ivmorethan4)),2) ) + ( double(planecorners( planenumb(ivsmaller(ivmorethan4)),4 ))-1 )*nplanes; + planecornerinfrontofedge(ivmorethan4) = planecornerinfrontofedge(ivmorethan4) | (cornerinfrontofplane(ivreftocoplamatrix)==1); + end + clear ivselection + end + end + clear ivreftocoplamatrix + + ivclear = ivsmaller(find(planecornerinfrontofedge==0)); + edgeseesplane(iv(ivclear)) = 0; + end + + if ~isempty(ivlarger) + % Second the edges larger than pi (closwedang > pi): at least one plane corner needs + % to be in front of *both* edge planes. + % Plane corner 1 + ivreftocoplamatrix = double( planesatedge(edgenumb(ivlarger),1) ) + ( double(planecorners( planenumb(ivlarger),1 ))-1 )*nplanes; + planecornerinfrontofedge = cornerinfrontofplane(ivreftocoplamatrix)==1; + ivreftocoplamatrix = double( planesatedge(edgenumb(ivlarger),2) ) + ( double(planecorners( planenumb(ivlarger),1 ))-1 )*nplanes; + planecornerinfrontofedge = planecornerinfrontofedge & (cornerinfrontofplane(ivreftocoplamatrix)==1); + % Plane corner 2 + ivreftocoplamatrix = double( planesatedge(edgenumb(ivlarger),1) ) + ( double(planecorners( planenumb(ivlarger),2 ))-1 )*nplanes; + temp = cornerinfrontofplane(ivreftocoplamatrix)==1; + ivreftocoplamatrix = double( planesatedge(edgenumb(ivlarger),2) ) + ( double(planecorners( planenumb(ivlarger),2 ))-1 )*nplanes; + planecornerinfrontofedge = planecornerinfrontofedge | (temp & (cornerinfrontofplane(ivreftocoplamatrix)==1)); + % Plane corner 3 + ivreftocoplamatrix = double( planesatedge(edgenumb(ivlarger),1) ) + ( double(planecorners( planenumb(ivlarger),3 ))-1 )*nplanes; + temp = cornerinfrontofplane(ivreftocoplamatrix)==1; + ivreftocoplamatrix = double( planesatedge(edgenumb(ivlarger),2) ) + ( double(planecorners( planenumb(ivlarger),3 ))-1 )*nplanes; + planecornerinfrontofedge = planecornerinfrontofedge | (temp & (cornerinfrontofplane(ivreftocoplamatrix)==1)); + + if minncornersperplane == 4 & maxncornersperplane == 4 + % Plane corner 4 + ivreftocoplamatrix = double( planesatedge(edgenumb(ivlarger),1) ) + ( double(planecorners( planenumb(ivlarger),4 ))-1 )*nplanes; + temp = cornerinfrontofplane(ivreftocoplamatrix)==1; + ivreftocoplamatrix = double( planesatedge(edgenumb(ivlarger),2) ) + ( double(planecorners( planenumb(ivlarger),4 ))-1 )*nplanes; + planecornerinfrontofedge = planecornerinfrontofedge | (temp & (cornerinfrontofplane(ivreftocoplamatrix)==1)); + elseif not(minncornersperplane == 3 & maxncornersperplane == 3) + ivall = uint32(1:length(ivlarger)); + if minncornersperplane == 3 + iv3cornerplanes = find(ncornersperplanevec(planenumb(ivlarger))==3); + ivall(iv3cornerplanes) = []; + end + if maxncornersperplane == 4 + % Plane corner 4 + ivreftocoplamatrix = double( planesatedge(edgenumb(ivlarger(ivall)),1) ) + ( double(planecorners( planenumb(ivlarger(ivall)),4 ))-1 )*nplanes; + temp = cornerinfrontofplane(ivreftocoplamatrix)==1; + ivreftocoplamatrix = double( planesatedge(edgenumb(ivlarger(ivall)),2) ) + ( double(planecorners( planenumb(ivlarger(ivall)),4 ))-1 )*nplanes; + planecornerinfrontofedge(ivall) = planecornerinfrontofedge(ivall) | (temp & (cornerinfrontofplane(ivreftocoplamatrix)==1)); + else + ivmorethan4 = find(ncornersperplanevec(planenumb(ivlarger(ivall)))>4); + temp = ivall(ivmorethan4); + ivall(ivmorethan4) = []; + ivmorethan4 = temp; + % Plane corner 4 + ivreftocoplamatrix = double( planesatedge(edgenumb(ivlarger(ivall)),1) ) + ( double(planecorners( planenumb(ivlarger(ivall)),4 ))-1 )*nplanes; + temp = cornerinfrontofplane(ivreftocoplamatrix)==1; + ivreftocoplamatrix = double( planesatedge(edgenumb(ivlarger(ivall)),2) ) + ( double(planecorners( planenumb(ivlarger(ivall)),4 ))-1 )*nplanes; + planecornerinfrontofedge(ivall) = planecornerinfrontofedge(ivall) | (temp & (cornerinfrontofplane(ivreftocoplamatrix)==1)); + for ii = 5:maxncornersperplane + % Plane corner 5,6,7,etc + ivselection = find(ncornersperplanevec(planenumb(ivlarger(ivmorethan4)))>=ii); + ivreftocoplamatrix = double( planesatedge(edgenumb(ivlarger(ivmorethan4)),1) ) + ( double(planecorners( planenumb(ivlarger(ivmorethan4)),4 ))-1 )*nplanes; + temp = cornerinfrontofplane(ivreftocoplamatrix)==1; + ivreftocoplamatrix = double( planesatedge(edgenumb(ivlarger(ivmorethan4)),2) ) + ( double(planecorners( planenumb(ivlarger(ivmorethan4)),4 ))-1 )*nplanes; + planecornerinfrontofedge(ivmorethan4) = planecornerinfrontofedge(ivmorethan4) | (temp & (cornerinfrontofplane(ivreftocoplamatrix)==1)); + end + clear ivselection + end + end + + ivclear = ivlarger(find(planecornerinfrontofedge==0)); + edgeseesplane(iv(ivclear)) = 0; + end +end + +clear ivlarger ivsmaller ivreftocoplamatrix edgenumb planenumb iv + +%---------------------------------------------------------------------------- +% +% indentingedgepairs +% +%-------------------------------------------------------------------------------- +% +% If there are any planes with indents, make a list of all consecutive edge pairs that +% form an indent, because such edge pairs could never see each other. + +indentingedgepairs = []; + +if any(planehasindents) + iv = find(indentingcorners); + indentingedgepairs = zeros(length(iv),2); + indentingplanenumbers = mod(iv,nplanes); + ivzeros = find(indentingplanenumbers==0); + if ~isempty(ivzeros) + indentingplanenumbers(ivzeros) = nplanes; + end + conumbers = (iv - indentingplanenumbers)/nplanes+1; + + % We expand planecorners temporarily, cyclically + planecorners = [planecorners planecorners(:,1:2)]; + + for ii = 1:length(iv) + edge1cornerpair = sort(planecorners(indentingplanenumbers(ii),conumbers(ii):conumbers(ii)+1)); + edge2cornerpair = sort(planecorners(indentingplanenumbers(ii),conumbers(ii)+1:conumbers(ii)+2)); + + [slask,edge1] = ismember(edge1cornerpair,edgecorners,'rows'); + [slask,edge2] = ismember(edge2cornerpair,edgecorners,'rows'); + + edgepair = sort([edge1 edge2]); + indentingedgepairs(ii,:) = edgepair; + + end + + % Remove the temporary expansion + + planecorners = planecorners(:,1:size(planecorners,2)-2); +end + +%---------------------------------------------------------------------------- +% +% canplaneobstruct +% +%-------------------------------------------------------------------------------- +% +% Check which planes that are potentially obstructing: +% +% If **all** closwedangvec are < pi and we have an exterior problem => +% the scatterer is without indents. +% +% If **all** closwedangvec are > pi and we have an interior problem => +% the room is without any indents so there can be no obstructions. +% +% For exterior problems, all active planes can potentially obstruct. +% +% If these simple checks give a results that conflict with the input +% parameters open_or_closed_model or int_or_ext_model, give an +% error message. + +canplaneobstruct = []; +if sum(closwedangvec<pi) == 0 + if SHOWTEXT >= 2 + disp(' ') + disp(' The model is an interior problem, and the room has no indents') + disp(' so no obstruction tests will be necessary.') + end + if int_or_ext_model == 'e' + disp( 'ERROR: In the setup file this model was defined as an exterior problem, but it is clearly an interior problem.') + error(' Please check the orientation of the planes.') + end + canplaneobstruct = zeros(1,nplanes); +elseif sum(closwedangvec>0) == 0 + if SHOWTEXT >= 2 + disp(' ') + disp(' The model is an exterior problem (scattering)') + disp(' with only thin planes.') + end + if int_or_ext_model == 'i' + disp( 'ERROR: In the setup file this model was defined as an interior problem, but it is clearly an exterior problem.') + error(' Please check the orientation of the planes.') + end + canplaneobstruct = ones(1,nplanes); +elseif sum(closwedangvec>pi) == 0 + if SHOWTEXT >= 2 + disp(' ') + disp(' The model is an exterior problem (scattering)') + disp(' and the scatterer has no indents.') + end + if int_or_ext_model == 'i' + disp( 'ERROR: In the setup file this model was defined as an interior problem, but it is clearly an exterior problem.') + error(' Please check the orientation of the planes.') + end + canplaneobstruct = ones(1,nplanes); +end + +% For an interior problem we know for sure that if a plane +% has all other points in front of itself, it can not obstruct. +% NB! We need to check only points that do not belong to planes +% that are aligned with the plane, or planes that are non-active. + +if int_or_ext_model == 'e' + canplaneobstruct = (reflfactors.'~=0); +elseif isempty(canplaneobstruct) + + canplaneobstruct = (reflfactors.'~=0); + maskvec1 = canplaneobstruct.'; + listofactiveplanes = find(canplaneobstruct); + zerosvec = zeros(nplanes,1); + + for ii = 1:length(listofactiveplanes) + iplane = listofactiveplanes(ii); + maskvec2 = zerosvec; + maskvec2(iplane) = 1; + otherplanestocheck = find((double(planeseesplane(:,iplane))+maskvec2)~=1 & planeseesplane(:,iplane)~=-1 & maskvec1~=0); + if ~isempty(otherplanestocheck), + cornerstocheck = unique(planecorners(otherplanestocheck,:)); + cornerstocheck = setdiff(unique(cornerstocheck),planecorners(iplane,1:ncornersperplanevec(iplane))); + pointinfront = EDB1infrontofplane(corners(cornerstocheck,:),planenvecs(iplane,:),corners(planecorners(iplane,1),:),corners(planecorners(iplane,2),:)); + if isempty(find(pointinfront==-1)) + canplaneobstruct(iplane) = 0; + end + else + canplaneobstruct(iplane) = 0; + end + + end +end + +%--------------------------------------------------------------- +% For each thin plane, make sure that all edges have the same normal +% vector. If not, switch the direction of that edge, and all the other +% relevant parameters. + +if difforder >= 1 + ivthin = find(planeisthin); + + for ii = 1:length(ivthin) + plane = ivthin(ii); + if rearsideplane(plane) > plane + edgelist = unique(edgesatplane(plane,1:nedgesperplanevec(plane))); + iv = find(closwedangvec(edgelist,:)==0); + if ~isempty(iv) + edgelist = edgelist(iv); + nedgestemp = length(edgelist); + edgenveclist = edgenvecs(edgelist,:); + refnvec = edgenveclist(1,:); + nvecdiff = edgenveclist(2:nedgestemp,:) - refnvec(ones(nedgestemp-1,1),:); + nvecdiff = sum(abs(nvecdiff.')).'; + ivswitch = find(nvecdiff)+1; + if ~isempty(ivswitch) + edgenumber = edgelist(ivswitch); + edgecorners(edgenumber,:) = [edgecorners(edgenumber,2) edgecorners(edgenumber,1)]; + planesatedge(edgenumber,:) = [planesatedge(edgenumber,2) planesatedge(edgenumber,1)]; + edgenvecs(edgenumber,:) = -edgenvecs(edgenumber,:); + edgestartcoords(edgenumber,:) = corners(edgecorners(edgenumber,1),:); + edgeendcoords(edgenumber,:) = corners(edgecorners(edgenumber,2),:); + tempvec = edgeendcoordsnudge(edgenumber,:); + edgeendcoordsnudge(edgenumber,:) = edgestartcoordsnudge(edgenumber,:); + edgestartcoordsnudge(edgenumber,:) = tempvec; + end + end + end + + end +end + +%---------------------------------------------------------------------------- +% +% SAVE THE VARIABLES +% +%---------------------------------------------------------------------------- +% +% Also the variables from cadgeo?? +% Yes: planeeqs planenvecs ncornersperplanevec planecorners corners +% minvals maxvals + +edgeseesplane = int8(edgeseesplane); +planeseesplane = int8(planeseesplane); + +if ncorners < 256 + planecorners = uint8(planecorners); +elseif ncorners < 65536 + planecorners = uint16(planecorners); +end +planeisthin = uint8(planeisthin); + +if max(ncornersperplanevec) <= 255 + ncornersperplanevec = uint8(ncornersperplanevec); +else + ncornersperplanevec = uint16(ncornersperplanevec); +end + +Varlist = [ ' edgecorners planesatedge closwedangvec planehasindents indentingedgepairs']; +Varlist = [Varlist,' planeisthin planeseesplane rearsideplane edgeseesplane canplaneobstruct']; +Varlist = [Varlist,' corners planecorners planeeqs planenvecs ncornersperplanevec cornerinfrontofplane']; +Varlist = [Varlist,' edgestartcoords edgeendcoords edgenvecs reflfactors edgesatplane edgelengthvec']; +Varlist = [Varlist,' minvals maxvals offedges ']; +Varlist = [Varlist,' int_or_ext_model']; +if difforder >= 1 + edgedata.edgestartcoordsnudge = edgestartcoordsnudge; + edgedata.edgeendcoordsnudge = edgeendcoordsnudge; + edgedata.edgenormvecs = edgenormvecs; + Varlist = [Varlist, ' edgedata ']; +end +eval(['save ',outputfile,Varlist])
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/private/EDB1editpathlist.m Sat Nov 16 18:25:24 2013 +0000 @@ -0,0 +1,135 @@ +function EDB1editpathlist(edpathsfile,useedges,symmetricedges,pathstokeep) +% EDB1editpathlist - Does some semi-automatic editing of an edpathsfile. +% A vector, 'multfactors' is introduced, which will boost or +% keep or switch off paths in the list of paths. +% +% Input parameters: +% edpathsfile An edpaths file that should be modified. +% useedges (optional) A list of edges that should be used. All +% paths that contain an edge which is not this edge will +% be switched off. +% symmetricedges (optional) A matrix of edge pairs that are symmetrical +% around a symmetry plane. If, e.g., edges 2 and 3 are symmetric around the +% source/receiver plane, then symmetricedges = [2 3]. Several pairs are +% possible; symmetricedges = [2 3;7 8;9 12]; +% pathstokeep (optional) A matrix of specific diffraction paths to +% keep. +% SHOWTEXT (global) +% +% ---------------------------------------------------------------------------------------------- +% This file is part of the Edge Diffraction Toolbox by Peter Svensson. +% +% The Edge Diffraction Toolbox is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) any later version. +% +% The Edge Diffraction Toolbox is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +% FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License along with the +% Edge Diffraction Toolbox. If not, see <http://www.gnu.org/licenses/>. +% ---------------------------------------------------------------------------------------------- +% Peter Svensson (svensson@iet.ntnu.no) 20050510 +% +% EDB1editpathlist(edpathsfile,useedges,symmetricedges,pathstokeep); + +global SHOWTEXT + +if isempty(symmetricedges) + dosymmetry = 0; +else + dosymmetry = 1; +end + +if isempty(pathstokeep) + dopathpruning = 0; +else + dopathpruning = 1; +end + +if ~isempty(useedges) + error(['ERROR: Sorry, the useedges option has not been implemented yet!']) +end + +%------------------------------------------------------------------------- + +nsymmetricedgepairs = size(symmetricedges,1); + +Varlist = [' S R allspecrows firstdiffrow mainlistguidepattern mainlistguide reflpaths pathtypevec']; +Varlist = [Varlist,' Sinsideplanenumber Rinsideplanenumber directsoundrow specextradata edgeextradata']; +if dosymmetry | dopathpruning + Varlist = [Varlist,' multfactors']; +end + +%------------------------------------------------------------------------- + +eval(['load ',edpathsfile]) +disp(' ') +disp(['Modifying ',edpathsfile]) +[ncombs,ncols] = size(reflpaths); +multfactors = ones(ncombs,1); + +%------------------------------------------------------------------------- + +if dosymmetry + + onesvec = ones(ncombs,1); + for kkk = 1:ncols + if SHOWTEXT >= 1 + disp([' Diffraction order ',int2str(kkk)]) + end + irow = sum((mainlistguidepattern=='d').').' == kkk; + if sum(irow) > 0 + ivselection = [double(mainlistguide(irow,2)):double(mainlistguide(irow,3))].'; + for mmm = 1:nsymmetricedgepairs + if SHOWTEXT >= 1 + disp([' Symmetry pair ',int2str(mmm)]) + end + iv = any(reflpaths(ivselection,:).'==symmetricedges(mmm,1)); + if ~isempty(iv) + iv = ivselection(iv); + for nnn=1:length(iv) + reflpathsmatch = reflpaths(iv(nnn),:); + if multfactors(iv(nnn)) ~= 0 + colstoswitch1 = find(reflpathsmatch==symmetricedges(mmm,1)); + colstoswitch2 = find(reflpathsmatch==symmetricedges(mmm,2)); + reflpathsmatch(colstoswitch1) = symmetricedges(mmm,2); + reflpathsmatch(colstoswitch2) = symmetricedges(mmm,1); + + reflpathsmatch = reflpathsmatch(onesvec,:); + + ivmatch = find(sum( (reflpaths==reflpathsmatch).' ).'==ncols); + if ~isempty(ivmatch) & multfactors(ivmatch) ~= 0 + multfactors(iv(nnn)) = 2*multfactors(iv(nnn)); + multfactors(ivmatch) = 0; + if SHOWTEXT >= 2 + disp([' Found symmetric edge pair:']) + disp([' ',int2str(iv(nnn)),': ',int2str(double(reflpaths(iv(nnn),:)))]) + disp([' ',int2str(ivmatch),': ',int2str(double(reflpaths(ivmatch,:)))]) + end + end + end % ... if multfactors(iv(nnn)) ~= 0, + + end % ... for nnn=1:length(iv) + end % ... if ~isempty(iv) + end % for mmm = 1:nsymmetricedgepairs + end % ...if sum(irow) > 0 + end % ... for kkk = 1:ncols +end % ...if dosymmetry + +%------------------------------------------------------------------------- + +if dopathpruning + multfactors = multfactors*0; + for ii = 1:size(pathstokeep,1) + pathtomatch = pathstokeep(ii,:); + pathtomatch = pathtomatch(ones(ncombs,1),:); + ivmatch = find(sum( (reflpaths==pathtomatch).' ).'==ncols); + multfactors(ivmatch) = 1; + end +end + +%------------------------------------------------------------------------- + +eval(['save ',edpathsfile,Varlist])
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/private/EDB1extrnums.m Sat Nov 16 18:25:24 2013 +0000 @@ -0,0 +1,81 @@ +function numvect = EDB1extrnums(Str,delim) +% EDB1extrnums - Extracts the numerical values in a text-string, separated by a given delimiter. +% Periods (.) are interpreted as decimal points. +% +% Input parameters: +% Str Text string, [nchars,1]. +% delim The delimiter to look for, e.g., comma, space, slash etc. +% Can be specified as the ASCII value or as the character: +% '/' +% +% Output parameters: +% numvect A list, [1,nnums], of the numerical values that were found. +% +% Uses no special functions +% +% ---------------------------------------------------------------------------------------------- +% This file is part of the Edge Diffraction Toolbox by Peter Svensson. +% +% The Edge Diffraction Toolbox is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) any later version. +% +% The Edge Diffraction Toolbox is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +% FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License along with the +% Edge Diffraction Toolbox. If not, see <http://www.gnu.org/licenses/>. +% ---------------------------------------------------------------------------------------------- +% Peter Svensson (svensson@iet.ntnu.no) 20090719 +% +% numvect = EDB1extrnums(Str,delim); + +if isempty(Str) + numvect = []; + return +end +if nargin < 2 + iv = find( (Str>=48 & Str<=57) | (Str==46) | (Str==45) | (Str==101) | (Str==69) == 1); +else + iv = find( Str ~= delim ); +end +diffiv = diff(iv); + +if ~isempty(diffiv) + startindices = find(diffiv ~= 1); +else + startindices = []; +end + +if length(startindices) >= 1 + startpos = [iv(1) iv(startindices+1)]; + + numvect = zeros(1,length(startpos)); + for ii = 1:length(startpos)-1 + shortstr = Str(startpos(ii):startpos(ii+1)-1); + if nargin < 2 + shortstr = shortstr( find( (shortstr>=48 & shortstr<=57) | (shortstr==46) | (shortstr==45) | (shortstr==101) | (shortstr==69) == 1)); + else + shortstr = shortstr( find (shortstr ~= delim) ); + end + numvect(ii) = str2num(shortstr); + end + shortstr = Str(startpos(ii+1):length(Str)); + if nargin < 2 + shortstr = shortstr( find( (shortstr>=48 & shortstr<=57) | (shortstr==46) | (shortstr==45) | (shortstr==101) | (shortstr==69) == 1)); + else + shortstr = shortstr( find (shortstr ~= delim) ); + end + numvect(ii+1) = str2num(shortstr); +elseif length(iv) >= 1 + shortstr = Str(iv(1):length(Str)); + if nargin < 2 + shortstr = shortstr( find( (shortstr>=48 & shortstr<=57) | (shortstr==46) | (shortstr==45) | (shortstr==101) | (shortstr==69) == 1)); + else + shortstr = shortstr( find (shortstr ~= delim) ); + end + numvect = str2num(shortstr); +else + numvect = []; +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/private/EDB1findISEStree.m Sat Nov 16 18:25:24 2013 +0000 @@ -0,0 +1,1432 @@ +function ISEStreefile = EDB1findISEStree(eddatafile,S,isou,specorder,difforder,visplanesfromS,vispartedgesfromS,nedgesubs) +% EDB1findISEStree - Constructs a list ("an ISES tree") of all possible specular-diffraction combinations. +% EDB1findISEStree constructs a list ("an ISES tree") of all possible specular-diffraction combinations that +% are possible for the given source. This list is based on the visibility +% matrices from source to planes/edges and between planes/edges. Visibility +% checks are employed wherever possibble. NB! Visibility checks that depend +% on the receiver position are not used at this stage. +% Planes are numbered 1-nplanes, and edges have numbers +% [nplanes+1:nplanes+nedges]. +% +% Input parameters: +% eddatafile See a description in EDB1edgeo, EDB1srgeo and EDB1mainISES +% S +% isou +% specorder +% difforder +% visplanesfromS +% vispartedgesfromS +% nedgesubs +% +% GLOBAL parameters +% SHOWTEXT JJ JJnumbofchars See EDB1mainISES +% SUPPRESSFILES If this global parameter has the value 1 +% then the results from this function will be returned in a struct +% rather than in a file. +% +% Output parameters: +% ISEStreefile The name of the output file which contains +% the output data below. +% +% Global output data: +% POTENTIALISES A matrix, [npossiblecombs,specorder], of all the +% possible specular-diffraction combos that are possible for the +% given source. The combos are denoted by +% plane numbers and edge numbers, but edge +% numbers have a constant number (=nplanes) +% added to them, i.e., if there are 20 planes +% in the model, edge number 1 will be denoted +% by number 21. +% ORIGINSFROM A list, [npossiblecombs,1], where the value +% in row N states which other row in ISCOORDS that +% the image source in row N originates from. +% ISCOORDS A matrix, [npossiblecombs,3], containing +% the image source coordinates, where this is applicable +% i.e., where the combo starts with a specular reflection. +% ISESVISIBILITY A list, [npossiblecombs,1], containing the visibility of +% the first edge in a sequence, seen from the source. +% IVNSPECMATRIX A matrix, [nspeccombs,specorder], where each column contains +% the row numbers in POTENTIALISES that contain combos with +% 1 or 2 or... or "specorder" purely specular reflections. +% REFLORDER A list, [npossiblecombs,1], containing the +% order of reflection for each row of POTENTIALISES +% IVNDIFFMATRIX A matrix, [ndiffcombs,specorder], where each column contains +% the row numbers in POTENTIALISES that contain combos with +% 1 or 2 or... or "specorder" diffractions. +% Output data in the ISEStreefile: +% lengthNspecmatrix A list, [1,specorder], with the number of +% entries in each column of IVNSPECMATRIX. +% lengthNdiffmatrix A list, [1,specorder], with the number of +% entries in each column of IVNDIFFMATRIX. +% singlediffcol A list, [nfirstorderdiff,1], containing the column number +% that the first-order diffracted component can be found in (in +% POTENTIALISES). +% startindicessinglediff A list, [specorder,1], where the value in position N contains +% which row in IVNDIFFMATRIX(:,1) that has the first combination +% of order N and with one diffraction component. +% endindicessinglediff A list, [specorder,1], where the value in position N contains +% which row in IVNDIFFMATRIX(:,1) that has the last combination +% of order N and with one diffraction +% ndecimaldivider See below. +% PointertoIRcombs A sparse list which for position N contains a row number +% (in POTENTIALISES) that has a combination +% that ends with a specular reflection in +% plane N, after a diffraction. A row with one of the specular +% reflections M,N after a diffraction can be +% found in position M*ndecimaldivider+N etc +% for higher orders. +% IRoriginsfrom A list, [npossiblecombs,1], where the value in position N +% states which other row number (in POTENTIALISES) that the +% image receiver in row N origins from. +% +% Uses functions EDB1strpend EDB1findis EDB1getedgepoints EDB1chkISvisible EDB1checkobstrpaths +% +% ---------------------------------------------------------------------------------------------- +% This file is part of the Edge Diffraction Toolbox by Peter Svensson. +% +% The Edge Diffraction Toolbox is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) any later version. +% +% The Edge Diffraction Toolbox is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +% FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License along with the +% Edge Diffraction Toolbox. If not, see <http://www.gnu.org/licenses/>. +% ---------------------------------------------------------------------------------------------- +% Peter Svensson (svensson@iet.ntnu.no) 20100210 +% +% ISEStreefile = EDB1findISEStree(eddatafile,S,isou,specorder,difforder,visplanesfroms,vispartedgesfroms,nedgesubs); + +global SHOWTEXT JJ JJnumbofchars +global POTENTIALISES ISCOORDS IVNDIFFMATRIX +global IVNSPECMATRIX ORIGINSFROM ISESVISIBILITY REFLORDER SUPPRESSFILES + +GEOMACC = 1e-10; + +eval(['load ',eddatafile]) +clear cornerinfrontofplane + +[filepath,filestem,fileext] = fileparts(eddatafile); +ISEStreefile = [[filepath,filesep],EDB1strpend(filestem,'_eddata'),'_',int2str(isou),'_ISEStree.mat']; + +ncorners = size(corners,1); +nplanes = length(planeisthin); +nedges = length(closwedangvec); +nhighval = nplanes + nedges; + +onesvec1 = ones(1,nedgesubs); +obstructtestneeded = (sum(canplaneobstruct)~=0); +onesvec3 = ones(1,3); + +doconetrace = 0; +if SHOWTEXT >= 3 + disp('WARNING: doconetrace is switched off') +end + +%-------------------------------------------------------------------------- +% We modify edgeseesplane because in EDB1edgeo, edgeseesplane was set to 1 +% for totabs planes (this was necessary for EDB1srgeo). + +% Set all edges belonging to planes with reflfactors = 0 to edgeseesplane = 0. + +listofabsorbingplanes = find(reflfactors == 0); + +if ~isempty(listofabsorbingplanes) + edgeseesplane(listofabsorbingplanes,:) = zeros(length(listofabsorbingplanes),nedges); +end + +% If we should do cone tracing, then we need plane midpoints and plane +% sizes. + +if doconetrace == 1 + planemidpoints = zeros(nplanes,3); + maxdisttocorner = zeros(nplanes,1); + + iv4planes = find(ncornersperplanevec==4); + if any(iv4planes) + xvalues = corners(planecorners(iv4planes,1:4).',1); + xvalues = reshape(xvalues,4,length(xvalues)/4); + yvalues = corners(planecorners(iv4planes,1:4).',2); + yvalues = reshape(yvalues,4,length(yvalues)/4); + zvalues = corners(planecorners(iv4planes,1:4).',3); + zvalues = reshape(zvalues,4,length(zvalues)/4); + planemidpoints(iv4planes,:) = [mean(xvalues).' mean(yvalues).' mean(zvalues).']; + + dist1 = sqrt(sum((corners(planecorners(iv4planes,1),:) - planemidpoints(iv4planes,:)).'.^2)).'; + dist2 = sqrt(sum((corners(planecorners(iv4planes,2),:) - planemidpoints(iv4planes,:)).'.^2)).'; + dist3 = sqrt(sum((corners(planecorners(iv4planes,3),:) - planemidpoints(iv4planes,:)).'.^2)).'; + dist4 = sqrt(sum((corners(planecorners(iv4planes,4),:) - planemidpoints(iv4planes,:)).'.^2)).'; + maxdisttocorner(iv4planes) = max([dist1 dist2 dist3 dist4].'); + + end + + iv3planes = find(ncornersperplanevec==3); + if any(iv3planes) + xvalues = corners(planecorners(iv3planes,1:3).',1); + xvalues = reshape(xvalues,3,length(xvalues)/3); + yvalues = corners(planecorners(iv3planes,1:3).',2); + yvalues = reshape(yvalues,3,length(yvalues)/3); + zvalues = corners(planecorners(iv3planes,1:3).',3); + zvalues = reshape(zvalues,3,length(zvalues)/3); + planemidpoints(iv3planes,:) = [mean(xvalues).' mean(yvalues).' mean(zvalues).']; + + dist1 = sqrt(sum((corners(planecorners(iv3planes,1),:) - planemidpoints(iv3planes,:)).'.^2)).'; + dist2 = sqrt(sum((corners(planecorners(iv3planes,2),:) - planemidpoints(iv3planes,:)).'.^2)).'; + dist3 = sqrt(sum((corners(planecorners(iv3planes,3),:) - planemidpoints(iv3planes,:)).'.^2)).'; + maxdisttocorner(iv3planes) = max([dist1 dist2 dist3].'); + + end + + iv5planes = find(ncornersperplanevec==5); + if any(iv5planes) + xvalues = corners(planecorners(iv5planes,1:5).',1); + xvalues = reshape(xvalues,5,length(xvalues)/5); + yvalues = corners(planecorners(iv5planes,1:5).',2); + yvalues = reshape(yvalues,5,length(yvalues)/5); + zvalues = corners(planecorners(iv5planes,1:5).',3); + zvalues = reshape(zvalues,5,length(zvalues)/5); + planemidpoints(iv5planes,:) = [mean(xvalues).' mean(yvalues).' mean(zvalues).']; + + dist1 = sqrt(sum((corners(planecorners(iv5planes,1),:) - planemidpoints(iv5planes,:)).'.^2)).'; + dist2 = sqrt(sum((corners(planecorners(iv5planes,2),:) - planemidpoints(iv5planes,:)).'.^2)).'; + dist3 = sqrt(sum((corners(planecorners(iv5planes,3),:) - planemidpoints(iv5planes,:)).'.^2)).'; + dist4 = sqrt(sum((corners(planecorners(iv5planes,4),:) - planemidpoints(iv5planes,:)).'.^2)).'; + dist5 = sqrt(sum((corners(planecorners(iv5planes,5),:) - planemidpoints(iv5planes,:)).'.^2)).'; + maxdisttocorner(iv5planes) = max([dist1 dist2 dist3 dist4 dist5].'); + + end + + iv6planes = find(ncornersperplanevec==6); + if any(iv6planes) + xvalues = corners(planecorners(iv6planes,1:6).',1); + xvalues = reshape(xvalues,6,length(xvalues)/6); + yvalues = corners(planecorners(iv6planes,1:6).',2); + yvalues = reshape(yvalues,6,length(yvalues)/6); + zvalues = corners(planecorners(iv6planes,1:6).',3); + zvalues = reshape(zvalues,6,length(zvalues)/6); + planemidpoints(iv6planes,:) = [mean(xvalues).' mean(yvalues).' mean(zvalues).']; + + dist1 = sqrt(sum((corners(planecorners(iv6planes,1),:) - planemidpoints(iv6planes,:)).'.^2)).'; + dist2 = sqrt(sum((corners(planecorners(iv6planes,2),:) - planemidpoints(iv6planes,:)).'.^2)).'; + dist3 = sqrt(sum((corners(planecorners(iv6planes,3),:) - planemidpoints(iv6planes,:)).'.^2)).'; + dist4 = sqrt(sum((corners(planecorners(iv6planes,4),:) - planemidpoints(iv6planes,:)).'.^2)).'; + dist5 = sqrt(sum((corners(planecorners(iv6planes,5),:) - planemidpoints(iv6planes,:)).'.^2)).'; + dist6 = sqrt(sum((corners(planecorners(iv6planes,6),:) - planemidpoints(iv6planes,:)).'.^2)).'; + maxdisttocorner(iv6planes) = max([dist1 dist2 dist3 dist4 dist5 dist6].'); + + end + +end + +%-------------------------------------------------------------------------- +% Combine planeseesplane with edgeseesplane +% and visplanesfroms with vispartedgesfroms +% so that edges appear as planes + +if difforder > 0 + visPLANESfroms = [visplanesfromS;2*sign(double(vispartedgesfromS))]; + % source sees planes that have visplanesfroms: + % 2 => in front of reflective planes + % 4 => inside plane which is reflective + % old version: sousees = (visPLANESfroms==1 | visPLANESfroms==-2); + sousees = (visPLANESfroms==2 | visPLANESfroms==4); + + if exist('edgeseespartialedge') ~= 1 + edgeseesedge = int8(zeros(nedges,nedges)); + else + if ~isempty(edgeseespartialedge) + + edgeseesedge = int8(full(abs(double(edgeseespartialedge))>0)); + + else + edgeseesedge = int8(zeros(nedges,nedges)); + end + end + + PLANEseesPLANE = [[planeseesplane edgeseesplane];[edgeseesplane.' edgeseesedge]]; + + clear edgeseesplane edgeseesedge +else + visPLANESfroms = visplanesfromS; + PLANEseesPLANE = planeseesplane; + sousees = (visPLANESfroms==2 | visPLANESfroms==4); + + clear visplanesfromS +end + +startindices = zeros(specorder,1); +endindices = zeros(specorder,1); + +%-------------------------------------------------------------------------- +% Construct a list of which planes a plane sees so that a search isn't +% needed later. + +nPLANES = size(PLANEseesPLANE,1); +listofvisPLANES = zeros(nPLANES,nPLANES-1); +nvisPLANES = zeros(nPLANES,1); +for ii = 1:nPLANES + visPLANES = find(PLANEseesPLANE(ii,:)==1); + nvisPLANES(ii) = length(visPLANES); + listofvisPLANES(ii,1:nvisPLANES(ii)) = visPLANES; +end + +%################################################################## +%################################################################## +%################################################################## +% +% First order +% +%------------------------------------------------------------------ + +startindices(1) = 1; + +possiblefirsts = find( sousees ); +npossiblefirsts = length(possiblefirsts); + +if nhighval < 255 + POTENTIALISES = uint8( [[possiblefirsts ] zeros(npossiblefirsts,specorder-1)] ); +else + POTENTIALISES = uint16( [[possiblefirsts ] zeros(npossiblefirsts,specorder-1)] ); +end + +ORIGINSFROM = uint32(zeros(npossiblefirsts,1)); +if nedgesubs < 8 + ISESVISIBILITY = uint8(zeros(npossiblefirsts,1)); +elseif nedgesubs < 16 + ISESVISIBILITY = uint16(zeros(npossiblefirsts,1)); +else + ISESVISIBILITY = uint32(zeros(npossiblefirsts,1)); +end +iv = find(possiblefirsts>nplanes); +if ~isempty(iv) + ISESVISIBILITY(iv) = vispartedgesfromS(possiblefirsts(iv)-nplanes); +end + +endindices(1) = npossiblefirsts; + +% Compute the IS coords + +ivdiff = [startindices(1):endindices(1)]; +ivspec = find(POTENTIALISES(ivdiff,1)<=nplanes); +ivdiff(ivspec) = []; + +ISCOORDS = zeros(npossiblefirsts,3); +ISCOORDS(ivspec,:) = EDB1findis(S,POTENTIALISES(ivspec,1),planeeqs,1,onesvec3); + +%################################################################## +%################################################################## +%################################################################## +% +% Second order +% +%--------------------------------------------------------------------------------------------- + +startindices(2) = startindices(1) + length(possiblefirsts); + +if specorder > 1 + if SHOWTEXT >= 3 + disp([' Order number 2']) + end + + if nhighval < 255 + startplanes = uint8(possiblefirsts); + else + startplanes = uint16(possiblefirsts); + end + + addtocomb = startplanes; + nadds = size(addtocomb,1); + if nadds > 0 + + maxnumberofvispla = max(sum(PLANEseesPLANE(:,startplanes)==1)); + + addtocomb = (reshape(addtocomb(:,ones(1,maxnumberofvispla)).',length(addtocomb)*maxnumberofvispla,1)); + addtocomb = [addtocomb zeros(size(addtocomb))]; + + addtoISESVISIBILITY = reshape(ISESVISIBILITY(:,ones(1,maxnumberofvispla)).',nadds*maxnumberofvispla,1); + + startpos = [[1:maxnumberofvispla:length(addtocomb)] length(addtocomb)+1 ].'; + + for ii = 1:length(startpos)-1 + if nvisPLANES(addtocomb(startpos(ii))) > 0 + possibleplanes = listofvisPLANES(addtocomb(startpos(ii)),1:nvisPLANES(addtocomb(startpos(ii)))).'; + nposs = length(possibleplanes); + addtocomb( startpos(ii):startpos(ii)+nposs-1,2) = possibleplanes; + end + + end + + addtooriginsfrom = uint32([1:startindices(2)-1].'); + addtooriginsfrom = addtooriginsfrom(:,ones(1,maxnumberofvispla)); + addtooriginsfrom = reshape(addtooriginsfrom.',maxnumberofvispla*(startindices(2)-1),1); + + cutout = find(addtocomb(:,2)==0); + addtocomb(cutout,:) = []; + addtooriginsfrom(cutout) = []; + addtoISESVISIBILITY(cutout) = []; + clear cutout + nadds = size(addtocomb,1); + + if nadds > 0 + + %-------------------------------------------------------------------------- + % Try to get rid of some combinations that we know can not be propagated + + % Find those combinations of specular-specular where the IS is behind the second reflecting plane + % because they can then never ever be propagated, or valid + + if difforder > 0 + ivss = uint32(find(addtocomb(:,1)<=nplanes & addtocomb(:,2)<=nplanes)); + else + ivss = uint32([1:nadds].'); + end + + imsoucheck = dot((ISCOORDS(addtooriginsfrom(ivss),1:3) - corners(planecorners(addtocomb(ivss,2),1),:)).',planenvecs(addtocomb(ivss,2),:).').'; + imsounotOK = find(imsoucheck < GEOMACC); + addtocomb(ivss(imsounotOK),:) = []; + addtooriginsfrom(ivss(imsounotOK),:) = []; + addtoISESVISIBILITY(ivss(imsounotOK)) = []; + + nadds = size(addtocomb,1); + + if nadds > 0 & doconetrace == 1 + + if difforder > 0 + ivss = uint32(find(addtocomb(:,1)<=nplanes & addtocomb(:,2)<=nplanes)); + else + ivss = uint32([1:nadds].'); + end + + beamdirection1 = planemidpoints(addtocomb(ivss,1),:) - ISCOORDS(addtocomb(ivss,1),:); + beamlength = sqrt( sum( beamdirection1.'.^2 ) ).'; + beamdirection1 = beamdirection1./beamlength(:,ones(1,3)); + maxprojradius = maxdisttocorner(addtocomb(ivss,1)); + % The maxdisttocorner below should be multiplied + % by sine of the angle between the plane normal vector and the + % beam direction. + iv = find(beamlength<maxprojradius); + if ~isempty(iv) + beamlength(iv) = beamlength(iv)*0+ eps*1e6; + end + beamangle1 = atan(maxprojradius./beamlength); + + % Now we calculate the beam-widths to the second reflection + % plane, seen from the first-order image source. If this + % beamwidth is outside the previously calculated beam of + % reflection plane 1, then plane 2 can never be seen + % through plane 1. + + beamdirection2 = planemidpoints(addtocomb(ivss,2),:) - ISCOORDS(addtocomb(ivss,1),:); + beamlength = sqrt( sum( beamdirection2.'.^2 ) ).'; + beamdirection2 = beamdirection2./beamlength(:,ones(1,3)); + maxprojradius = maxdisttocorner(addtocomb(ivss,2)); + % The maxdisttocorner below should be multiplied + % by sine of the angle between the plane normal vector and the + % beam direction. + iv = find(beamlength<maxprojradius); + if ~isempty(iv) + beamlength(iv) = beamlength(iv)*0+ eps*10; + end + beamangle2 = atan(maxprojradius./beamlength); + anglebetweenbeams = acos(sum( (beamdirection1.*beamdirection2).' ).'); + ivcutout = find( (beamangle1 + beamangle2 < anglebetweenbeams) & (beamangle1 <1.56) & (beamangle2 < 1.56)); + if ~isempty(ivcutout) + addtocomb(ivss(ivcutout),:) = []; + addtooriginsfrom(ivss(ivcutout),:) = []; + addtoISESVISIBILITY(ivss(ivcutout)) = []; + nadds = size(addtocomb,1); + end + + end + + % Combinations of diffraction-specular don't need to be checked because + % 'edgeseesplane' should have taken care of this. + %%%%ivds = find(addtocomb(:,1)>nplanes & addtocomb(:,2)<=nplanes); + + %-------------------------------------------------------------------------- + % Combinations of specular-diffraction: check if the IS is behind both of + % the two planes that the reflecting edge connects to. + % + % Bug found 20080711 PS: The visibility test must be split into two, depending on the wedge angle!! + % If the open wedge angle > pi, then it is correct to check if the IS behind both of the planes. + % If the open wedge angle < pi, then it should be checked if the IS behind one of the planes!! + + if difforder > 0 & nadds > 0 + + % First we check the sd combinations where the open wedge angle > pi + % For those cases, we can exclude combinations where the IS + % is behind both planes + + ivsd = uint32(find(addtocomb(:,1)<=nplanes & addtocomb(:,2)>nplanes)); + ivsd1 = ivsd( find( closwedangvec( double(addtocomb(ivsd,2))-nplanes ) < pi )); + + if ~isempty(ivsd1) + imsoucheck1 = dot((ISCOORDS(addtooriginsfrom(ivsd1),1:3) - corners(planecorners( planesatedge(double(addtocomb(ivsd1,2))-nplanes,1) ,1),:)).',planenvecs( planesatedge(double(addtocomb(ivsd1,2))-nplanes,1) ,:).').'; + imsoucheck2 = dot((ISCOORDS(addtooriginsfrom(ivsd1),1:3) - corners(planecorners( planesatedge(double(addtocomb(ivsd1,2))-nplanes,2) ,1),:)).',planenvecs( planesatedge(double(addtocomb(ivsd1,2))-nplanes,2) ,:).').'; + GEOMACC = 1e-10; + imsounotOK = find(imsoucheck1 < GEOMACC & imsoucheck2 < GEOMACC); + clear imsoucheck1 imsoucheck2 + + addtocomb(ivsd1(imsounotOK),:) = []; + addtooriginsfrom(ivsd1(imsounotOK),:) = []; + addtoISESVISIBILITY(ivsd1(imsounotOK)) = []; + end + + % Second we check the sd combinations where the open wedge angle < pi + % For those cases, we can exclude combinations where the IS + % is behind one of the two planes + + ivsd = uint32(find(addtocomb(:,1)<=nplanes & addtocomb(:,2)>nplanes)); + if ~isempty(ivsd) + ivsd1 = ivsd( find( closwedangvec( double(addtocomb(ivsd,2))-nplanes ) > pi )); + + if ~isempty(ivsd1) + imsoucheck1 = dot((ISCOORDS(addtooriginsfrom(ivsd1),1:3) - corners(planecorners( planesatedge(double(addtocomb(ivsd1,2))-nplanes,1) ,1),:)).',planenvecs( planesatedge(double(addtocomb(ivsd1,2))-nplanes,1) ,:).').'; + imsoucheck2 = dot((ISCOORDS(addtooriginsfrom(ivsd1),1:3) - corners(planecorners( planesatedge(double(addtocomb(ivsd1,2))-nplanes,2) ,1),:)).',planenvecs( planesatedge(double(addtocomb(ivsd1,2))-nplanes,2) ,:).').'; + GEOMACC = 1e-10; + imsounotOK = find(imsoucheck1 < GEOMACC | imsoucheck2 < GEOMACC); + clear imsoucheck1 imsoucheck2 + + addtocomb(ivsd1(imsounotOK),:) = []; + addtooriginsfrom(ivsd1(imsounotOK),:) = []; + addtoISESVISIBILITY(ivsd1(imsounotOK)) = []; + end + end + + nadds = size(addtocomb,1); + + ivsd = uint32(find(addtocomb(:,1)<=nplanes & addtocomb(:,2)>nplanes)); + + if ~isempty(ivsd) + + %---------------------------------------------------------------------- + % Combinations of specular-diffraction that are not visible at + % all should be removed and then they are not propagated either. + + if nedges < 255 + possibleedges = uint8(double(addtocomb(ivsd,2)) - nplanes); + else + possibleedges = uint16(double(addtocomb(ivsd,2)) - nplanes); + end + + possiblecombs = addtocomb(ivsd,1); + reftoISCOORDS = addtooriginsfrom(ivsd); + + % Expand to take the edge subdivisions into account + + nposs = length(ivsd); + nposs = nposs*nedgesubs; % We treat all the little edge subdivisions as separate edges + + expandedposscombs = possiblecombs(:,onesvec1); + clear possiblecombs + expandedposscombs = reshape(expandedposscombs.',nposs,1); + + expandedreftoISCOORDS = reftoISCOORDS(:,onesvec1); + expandedreftoISCOORDS = reshape(expandedreftoISCOORDS.',nposs,1); + expandedpossedges = possibleedges(:,onesvec1); + expandedpossedges = reshape(expandedpossedges.',nposs,1); + expandedivsd = ivsd(:,onesvec1); + expandedivsd = reshape(expandedivsd.',nposs,1); + + if SHOWTEXT >= 3 + disp([' ',int2str(nposs),' IS+edge segments found initially ']) + end + + if nposs > 0 + + fromcoords = ISCOORDS(expandedreftoISCOORDS,:); + [tocoords,edgeweightlist,edgenumberlist] = EDB1getedgepoints(edgestartcoords(possibleedges,:),edgeendcoords(possibleedges,:),edgelengthvec(possibleedges,:),nedgesubs); + clear possibleedges + + [hitplanes,reflpoints,edgehits,edgehitpoints,cornerhits,cornerhitpoints] = EDB1chkISvisible(fromcoords,tocoords,planeeqs(expandedposscombs(:,1),4),planenvecs(expandedposscombs(:,1),:),minvals(expandedposscombs(:,1),:),... + maxvals(expandedposscombs(:,1),:),planecorners(expandedposscombs(:,1),:),corners,ncornersperplanevec(expandedposscombs(:,1))); + if ~isempty(edgehits) | ~isempty(cornerhits) + disp('WARNING! An edgehit or cornerhit occurred during the visibility test but this is not') + disp(' handled correctly yet.') + end + + eval(['reflpoints',JJ(1,1),' = reflpoints;']) + + expandedivsd = expandedivsd(hitplanes); + expandedposscombs = expandedposscombs(hitplanes,:); + expandedreftoISCOORDS = expandedreftoISCOORDS(hitplanes); + expandedpossedges = expandedpossedges(hitplanes); + edgeweightlist = edgeweightlist(hitplanes); + toedgecoords = tocoords(hitplanes,:); + + nposs = length(expandedivsd); + + end + + if SHOWTEXT >= 3 + disp([' ',int2str(nposs),' IS+edge segments visible ']) + end + + if obstructtestneeded & nposs > 0 + + for jj = 1:2 + if nposs > 0 + if jj==1 + fromcoords = S; + startplanes = []; + else + startplanes = expandedposscombs(:,jj-1); + eval(['fromcoords = reflpoints',JJ(jj-1,1:JJnumbofchars(jj-1)),';']) + end + if jj == 2 + tocoords = toedgecoords; + endplanes = [planesatedge(expandedpossedges,1) planesatedge(expandedpossedges,2)]; + else + eval(['tocoords = reflpoints',JJ(jj,1:JJnumbofchars(jj)),';']) + endplanes = expandedposscombs(:,jj); + end + + [nonobstructedpaths,nobstructions] = EDB1checkobstrpaths(fromcoords,tocoords,startplanes,endplanes,canplaneobstruct,planeseesplane,... + planeeqs,planenvecs,minvals,maxvals,planecorners,corners,ncornersperplanevec,rearsideplane); + + if nobstructions > 0 + expandedivsd = expandedivsd(nonobstructedpaths); + expandedposscombs = expandedposscombs(nonobstructedpaths,:); + expandedreftoISCOORDS = expandedreftoISCOORDS(nonobstructedpaths); + expandedpossedges = expandedpossedges(nonobstructedpaths); + edgeweightlist = edgeweightlist(nonobstructedpaths); + toedgecoords = tocoords(nonobstructedpaths,:); + nposs = length(expandedivsd); + + for kk = 1:1, %norder + eval(['reflpoints',JJ(kk,1:JJnumbofchars(kk)),' = reflpoints',JJ(kk,1:JJnumbofchars(kk)),'(nonobstructedpaths,:);']) + end + + end + end + + end + end + + if SHOWTEXT >= 3 + disp([' ',int2str(nposs),' IS+edge segments survived the obstruction test']) + end + + % There are repetitions of each combination since each edge segment has + % been treated separately. Pack them together now + + test = [expandedposscombs expandedpossedges]; + ncombs = length(expandedpossedges); + dtest = diff([0;prod( double(test(1:ncombs-1,:)==test(2:ncombs,:)).' ).']); + ivremove = find(dtest==1); + + while ~isempty(ivremove) & ~isempty(edgeweightlist), + edgeweightlist(ivremove+1) = double(edgeweightlist(ivremove+1)) + double(edgeweightlist(ivremove)); + edgeweightlist(ivremove) = []; + expandedpossedges(ivremove) = []; + expandedposscombs(ivremove,:) = []; + expandedivsd(ivremove) = []; + nposs = length(expandedivsd); + + test = [expandedposscombs expandedpossedges]; + ncombs = length(expandedpossedges); + dtest = diff([0;prod( double(test(1:ncombs-1,:)==test(2:ncombs,:)).' ).']); + ivremove = find(dtest==1); + + end + + if SHOWTEXT >= 3 + disp([' ',int2str(nposs),' IS+edge combinations after edge segments are packed together']) + end + combstoremove = setdiff(ivsd,expandedivsd); + addtocomb(combstoremove,:) = []; + addtooriginsfrom(combstoremove) = []; + addtoISESVISIBILITY(combstoremove) = []; + nadds = length(addtooriginsfrom); + end + + end + + % Combinations of diffraction-diffraction don't need to be checked because + % 'edgeseesedge' should have taken care of this. + + %---------------------------------------------------------------------- + % Add the new combinations to the master list + + if nadds > 0 + POTENTIALISES = [POTENTIALISES;[addtocomb zeros(nadds,specorder-2)]]; + ORIGINSFROM = [ORIGINSFROM;addtooriginsfrom]; + + if difforder > 0 + ivtemp = find(addtocomb(:,1)<=nplanes & addtocomb(:,2)>nplanes); + if ~isempty(ivtemp), + addtoISESVISIBILITY(ivtemp) = edgeweightlist; + end + ivtemp = find(addtocomb(:,1)>nplanes); + end + ISESVISIBILITY = [ISESVISIBILITY;addtoISESVISIBILITY]; + + endindices(2) = length(ORIGINSFROM); + + % Compute the IS coords of the combinations with only specular reflections + + ISCOORDStoadd = zeros(nadds,3); + if difforder > 0 + ivss = uint32(find(addtocomb(:,1)<=nplanes & addtocomb(:,2)<=nplanes)); + else + ivss = uint32([1:nadds].'); + end + soutoreflect = ISCOORDS(ORIGINSFROM(double(ivss)+endindices(1)),1:3); + ISCOORDStoadd(ivss,:) = EDB1findis(soutoreflect,POTENTIALISES(double(ivss)+endindices(1),2),planeeqs,size(soutoreflect,1),onesvec3); + clear soutoreflect + ISCOORDS = [ISCOORDS;ISCOORDStoadd]; + + end + end + end +end + +%################################################################## +%################################################################## +%################################################################## +% +% Third order and higher +% +%--------------------------------------------------------------------------------------------- + +for ordernum = 3:specorder + if SHOWTEXT >= 3 + disp([' Order number ',int2str(ordernum)]) + end + + startindices(ordernum) = startindices(ordernum-1) + length(addtocomb); + + % The lines below could use + % planestoprop = unique(addtocomb(:,ordernum-1)); + + planelist = sort(addtocomb(:,ordernum-1)); + + if ~isempty(planelist), + planestoprop = planelist([1;find(diff(double(planelist))~=0)+1]); + else + planestoprop = []; + end + clear planelist + + maxnumberofvispla = max(sum(PLANEseesPLANE(:,planestoprop)==1)); + oldaddtocomb = addtocomb; + + nadds = size(addtocomb,1); + if nhighval < 255 + addtocomb = uint8(zeros(nadds*maxnumberofvispla,ordernum)); + else + addtocomb = uint16(zeros(nadds*maxnumberofvispla,ordernum)); + end + + onesvec2 = ones(1,maxnumberofvispla); + for ii = 1:ordernum-1 + temp = oldaddtocomb(:,ii); + addtocomb(:,ii) = reshape(temp(:,onesvec2).',length(temp)*maxnumberofvispla,1); + end + nrows = size(addtocomb,1); + clear oldaddtocomb temp + + if nrows > 0 + startpos = [[1:maxnumberofvispla:nrows] nrows+1 ].'; + else + startpos = 1; + end + + for ii = 1:length(startpos)-1 + if nvisPLANES(addtocomb(startpos(ii),ordernum-1)) > 0 + possibleplanes = listofvisPLANES(addtocomb(startpos(ii),ordernum-1),1:nvisPLANES(addtocomb(startpos(ii),ordernum-1))).'; + nposs = length(possibleplanes); + addtocomb( startpos(ii):startpos(ii)+nposs-1,ordernum) = possibleplanes; + end + end + + addtooriginsfrom = uint32([1:nadds].' + startindices(ordernum-1)-1); + addtooriginsfrom = addtooriginsfrom(:,ones(1,maxnumberofvispla)); + addtooriginsfrom = reshape(addtooriginsfrom.',maxnumberofvispla*nadds,1); + + addtoISESVISIBILITY = reshape(addtoISESVISIBILITY(:,ones(1,maxnumberofvispla)).',nadds*maxnumberofvispla,1); + + clear startpos + cutout = find(addtocomb(:,ordernum)==0); + addtocomb(cutout,:) = []; + addtooriginsfrom(cutout) = []; + addtoISESVISIBILITY(cutout) = []; + nadds = size(addtocomb,1); + + if ordernum == specorder + clear cutout + end + + %-------------------------------------------------------------------------- + % Try to get rid of some combinations that we know can not be propagated + + % Find those combinations of specular-specular where the IS is behind the second reflecting plane + % because they can then never ever be propagated. + + if difforder > 0 + ivss = uint32(find(prod( double(addtocomb<=nplanes).' ).')); + else + ivss = uint32([1:nadds].'); + end + + imsoucheck = dot((ISCOORDS(addtooriginsfrom(ivss),1:3) - corners(planecorners(addtocomb(ivss,ordernum),1),:)).',planenvecs(addtocomb(ivss,ordernum),:).').'; + GEOMACC = 1e-10; + imsounotOK = uint32(find(imsoucheck < GEOMACC)); + clear imsoucheck + addtocomb(ivss(imsounotOK),:) = []; + addtooriginsfrom(ivss(imsounotOK),:) = []; + addtoISESVISIBILITY(ivss(imsounotOK)) = []; + clear imsounotOK + + % Addition 20100210 PS: we should check all combinations with dss in the + % three last orders of addtocomb: if the edge in the first 'd' belongs to the + % plane of the last 's' *and* the two 's' planes form a 90 degree + % corner, then these combos should be removed. + % + % As a first step, we check if there are any interior-90-degree + % corners/edges of the model, because only then can these combos occur. + + if ordernum == 3 + deg90edges = find( abs(closwedangvec-3*pi/2) < GEOMACC ); + if any(deg90edges) + deg90planepairs = planesatedge(deg90edges,:); + end + end + + if difforder > 0 & any(deg90edges) + ivdss = uint32(find( double(addtocomb(:,ordernum-2)>nplanes).*double(addtocomb(:,ordernum-1)<=nplanes).*double(addtocomb(:,ordernum)<=nplanes) )); + else + ivdss = []; + end + + if ~isempty(ivdss) + + % First we check if the 'd' (the edge) belongs to the last 's' + A = addtocomb(ivdss,ordernum-2:ordernum); + + ivsubset = find( (planesatedge(A(:,1)-nplanes,1) == A(:,3)) | (planesatedge(A(:,1)-nplanes,2) == A(:,3)) ); + ivdss = ivdss(ivsubset); + + if ~isempty(ivdss) + % Second, we check if the two 's' planes form a 90 deg corner + planesare90degpairs = ismember( A(:,2),deg90planepairs(:,1) ).*ismember( A(:,3),deg90planepairs(:,2) ) + ismember( A(:,2),deg90planepairs(:,2) ).*ismember( A(:,3),deg90planepairs(:,1) ); + ivsubset = find(planesare90degpairs); + ivdss = ivdss(ivsubset); + + if ~isempty(ivdss) + addtocomb(ivdss,:) = []; + addtooriginsfrom(ivdss,:) = []; + addtoISESVISIBILITY(ivdss) = []; + clear ivdss ivsubset planesare90degpairs + end + end + end + + nadds = size(addtocomb,1); + + if nadds > 0 & doconetrace == 1 + + if difforder > 0 + ivss = uint32(find(prod( double(addtocomb<=nplanes).' ).')); + else + ivss = uint32([1:nadds].'); + end + + beamdirection1 = planemidpoints(addtocomb(ivss,ordernum-1),:) - ISCOORDS(addtooriginsfrom(ivss),1:3); + beamlength = sqrt( sum( beamdirection1.'.^2 ) ).'; + beamdirection1 = beamdirection1./beamlength(:,ones(1,3)); + maxprojradius = maxdisttocorner(addtocomb(ivss,ordernum-1)); + iv = find(beamlength<maxprojradius); + if ~isempty(iv) + beamlength(iv) = beamlength(iv)*0+ eps*1e6; + end + beamangle1 = atan(maxprojradius./beamlength); + + % Now we calculate the beam-widths to the second reflection + % plane, seen from the first-order image source. If this + % beamwidth is outside the previously calculated beam of + % reflection plane 1, then plane 2 can never be seen + % through plane 1. + + beamdirection2 = planemidpoints(addtocomb(ivss,ordernum),:) - ISCOORDS(addtooriginsfrom(ivss),1:3); + beamlength = sqrt( sum( beamdirection2.'.^2 ) ).'; + beamdirection2 = beamdirection2./beamlength(:,ones(1,3)); + maxprojradius = maxdisttocorner(addtocomb(ivss,ordernum)); + iv = find(beamlength<maxprojradius); + if ~isempty(iv) + beamlength(iv) = beamlength(iv)*0+ eps*10; + end + beamangle2 = atan(maxprojradius./beamlength); + clear maxprojradius beamlength + + ivcutout = find( (beamangle1 + beamangle2 < acos(sum( (beamdirection1.*beamdirection2).' ).')) & (beamangle1 <1.56) & (beamangle2 < 1.56)); + clear beamdirection1 beamdirection2 beamangle1 beamangle2 + + if ~isempty(ivcutout) + addtocomb(ivss(ivcutout),:) = []; + addtooriginsfrom(ivss(ivcutout),:) = []; + addtoISESVISIBILITY(ivss(ivcutout)) = []; + nadds = size(addtocomb,1); + end + + end + + % Combinations with all-specular plus diffraction as the last one: + % check if the IS is behind both of the two planes that the reflecting edge connects to. + % + % Bug found 080711: The visibility test must be split into two, depending on the wedge angle!! + % If the open wedge angle > pi, then it is correct to check if the IS behind both of the planes. + % If the open wedge angle < pi, then it should be checked if the IS behind one of the planes!! + + if difforder > 0 + + ivsd = uint32(find(prod( double(addtocomb(:,1:ordernum-1)<=nplanes).' ).' & (addtocomb(:,ordernum)>nplanes))); + + if ~isempty(ivsd) + + % First we check the sssssd combinations where the open wedge angle > pi + % For those cases, we can exclude combinations where the IS + % is behind both planes + + ivsd1 = ivsd( find( closwedangvec( double(addtocomb(ivsd,ordernum))-nplanes ) < pi )); + + if ~isempty(ivsd1) + imsoucheck1 = dot((ISCOORDS(addtooriginsfrom(ivsd1),1:3) - corners(planecorners( planesatedge(double(addtocomb(ivsd1,ordernum))-nplanes,1) ,1),:)).',planenvecs( planesatedge(double(addtocomb(ivsd1,ordernum))-nplanes,1) ,:).').'; + imsoucheck2 = dot((ISCOORDS(addtooriginsfrom(ivsd1),1:3) - corners(planecorners( planesatedge(double(addtocomb(ivsd1,ordernum))-nplanes,2) ,1),:)).',planenvecs( planesatedge(double(addtocomb(ivsd1,ordernum))-nplanes,2) ,:).').'; + GEOMACC = 1e-10; + imsounotOK = find(imsoucheck1 < GEOMACC & imsoucheck2 < GEOMACC); + clear imsoucheck1 imsoucheck2 + addtocomb(ivsd1(imsounotOK),:) = []; + addtooriginsfrom(ivsd1(imsounotOK),:) = []; + addtoISESVISIBILITY(ivsd1(imsounotOK)) = []; + clear imsounotOK + end + + % Second we check the sssssd combinations where the open wedge angle < pi + % For those cases, we can exclude combinations where the IS + % is behind one of the two planes + + ivsd = uint32(find(prod( double(addtocomb(:,1:ordernum-1)<=nplanes).' ).' & (addtocomb(:,ordernum)>nplanes))); + if ~isempty(ivsd) + ivsd1 = ivsd( find( closwedangvec( double(addtocomb(ivsd,ordernum))-nplanes ) > pi )); + + if ~isempty(ivsd1) + imsoucheck1 = dot((ISCOORDS(addtooriginsfrom(ivsd1),1:3) - corners(planecorners( planesatedge(double(addtocomb(ivsd1,ordernum))-nplanes,1) ,1),:)).',planenvecs( planesatedge(double(addtocomb(ivsd1,ordernum))-nplanes,1) ,:).').'; + imsoucheck2 = dot((ISCOORDS(addtooriginsfrom(ivsd1),1:3) - corners(planecorners( planesatedge(double(addtocomb(ivsd1,ordernum))-nplanes,2) ,1),:)).',planenvecs( planesatedge(double(addtocomb(ivsd1,ordernum))-nplanes,2) ,:).').'; + GEOMACC = 1e-10; + imsounotOK = find(imsoucheck1 < GEOMACC | imsoucheck2 < GEOMACC); + clear imsoucheck1 imsoucheck2 + addtocomb(ivsd1(imsounotOK),:) = []; + addtooriginsfrom(ivsd1(imsounotOK),:) = []; + addtoISESVISIBILITY(ivsd1(imsounotOK)) = []; + clear imsounotOK + end + end + + % For combinations including dsd, if the two diff. edges are + % aligned and the intermediate specular reflections are + % caused by planes that are perpendicular to the edges + % remove these combinations + + if difforder >= 2 + for kk = 1:ordernum-2 + ncombs = size(addtocomb,1); + matchvec = ones(ncombs,1); + nprespecs = kk-1; + nmidspecs = ordernum-1-kk; + matchvec = matchvec.*(addtocomb(:,ordernum)>nplanes).*(addtocomb(:,kk)>nplanes); + if nmidspecs == 1 + matchvec = matchvec.*(addtocomb(:,2)<=nplanes); + elseif nmidspecs >= 2 + matchvec = matchvec.*prod( double(addtocomb(:,kk+1:ordernum-1)<=nplanes).' ).'; + end + ivdsd = uint32(find( matchvec )); + if ~isempty(ivdsd) + edge1 = double(addtocomb(ivdsd,kk)) - nplanes; + edge2 = double(addtocomb(ivdsd,ordernum)) - nplanes; + midspecs = double(addtocomb(ivdsd,kk+1:ordernum-1)); + + lookupindmat1 = (edge1-1)*nedges + edge2; + matrixcolnumbers = (edge1-1)*nplanes; + lookupindmat2 = matrixcolnumbers(:,ones(1,nmidspecs)) + midspecs; + + if nmidspecs == 1 + ivinvalid = find(edgealignedwithedge(lookupindmat1) & edgeperptoplane(lookupindmat2)); + else + ivinvalid = find(edgealignedwithedge(lookupindmat1) & prod(edgeperptoplane(lookupindmat2).').'); + end + addtocomb(ivdsd(ivinvalid),:) = []; + addtooriginsfrom(ivdsd(ivinvalid),:) = []; + addtoISESVISIBILITY(ivdsd(ivinvalid)) = []; + end + end + end + + % We need to find the valid combinations again after we have removed a + % number of combinations + + ivsd = uint32(find(prod( double(addtocomb(:,1:ordernum-1)<=nplanes).' ).' & (addtocomb(:,ordernum)>nplanes))); + + %---------------------------------------------------------------------- + % Combinations of specular-diffraction that are not visible at + % all should be removed and then they are not propagated either. + + if nhighval < 255 + possibleedges = uint8(double(addtocomb(ivsd,ordernum)) - nplanes); + possiblecombs = uint8(double(addtocomb(ivsd,1:ordernum-1))); + else + possibleedges = uint16(double(addtocomb(ivsd,ordernum)) - nplanes); + possiblecombs = uint16(double(addtocomb(ivsd,1:ordernum-1))); + end + reftoISCOORDS = addtooriginsfrom(ivsd); + + % Expand to take the edge subdivisions into account + + nposs = length(ivsd); + nposs = nposs*nedgesubs; % We treat all the little edge subdivisions as separate edges + + expandedposscombs = reshape(repmat(possiblecombs.',[nedgesubs,1]),ordernum-1,nposs).'; + clear possiblecombs + expandedreftoISCOORDS = reftoISCOORDS(:,onesvec1); + expandedreftoISCOORDS = reshape(expandedreftoISCOORDS.',nposs,1); + expandedpossedges = possibleedges(:,onesvec1); + expandedpossedges = reshape(expandedpossedges.',nposs,1); + expandedivsd = ivsd(:,onesvec1); + expandedivsd = reshape(expandedivsd.',nposs,1); + + if SHOWTEXT >= 3 + disp([' ',int2str(nposs),' IS+edge segments found initially ']) + end + + % Go through, iteratively, and check if the path from S to edge passes + % through all reflection planes along the way + + for jj = ordernum-1:-1:1 + + if nposs > 0 + + if jj == ordernum-1 + fromcoords = ISCOORDS(expandedreftoISCOORDS,:); + [tocoords,edgeweightlist,edgenumberlist] = EDB1getedgepoints(edgestartcoords(possibleedges,:),edgeendcoords(possibleedges,:),edgelengthvec(possibleedges,:),nedgesubs); + clear possibleedges + else + eval(['tocoords = reflpoints',JJ(jj+1,1:JJnumbofchars(jj+1)),';']) + ivlist = ORIGINSFROM(expandedreftoISCOORDS); + for kk = jj:ordernum-3 + ivlist = ORIGINSFROM(ivlist); + end + fromcoords = ISCOORDS(ivlist,:); + + end + + [hitplanes,reflpoints,edgehits,edgehitpoints,cornerhits,cornerhitpoints] = EDB1chkISvisible(fromcoords,tocoords,planeeqs(expandedposscombs(:,jj),4),planenvecs(expandedposscombs(:,jj),:),minvals(expandedposscombs(:,jj),:),... + maxvals(expandedposscombs(:,jj),:),planecorners(expandedposscombs(:,jj),:),corners,ncornersperplanevec(expandedposscombs(:,jj))); + if ~isempty(edgehits) | ~isempty(cornerhits) + disp('WARNING! An edgehit or cornerhit occurred during the visibility test but this is not') + disp(' handled correctly yet.') + end + eval(['reflpoints',JJ(jj,1:JJnumbofchars(jj)),' = reflpoints;']) + + expandedivsd = expandedivsd(hitplanes); + expandedposscombs = expandedposscombs(hitplanes,:); + expandedreftoISCOORDS = expandedreftoISCOORDS(hitplanes); + expandedpossedges = expandedpossedges(hitplanes); + edgeweightlist = edgeweightlist(hitplanes); + toedgecoords = tocoords(hitplanes,:); + if jj < ordernum-1 + for kk = jj+1:ordernum-1 + eval(['reflpoints',JJ(kk,1:JJnumbofchars(kk)),' = reflpoints',JJ(kk,1:JJnumbofchars(kk)),'(hitplanes,:);']) + end + end + + nposs = length(expandedivsd); + + end + if SHOWTEXT >= 3 + disp([' ',int2str(nposs),' IS+edge segments survived the visibility test in refl plane ',JJ(jj,1:JJnumbofchars(jj))]) + end + + end + + if obstructtestneeded & nposs > 0 + for jj = 1:ordernum + if nposs > 0 + + if jj==1 + fromcoords = S; + startplanes = []; + else + startplanes = expandedposscombs(:,jj-1); + eval(['fromcoords = reflpoints',JJ(jj-1,1:JJnumbofchars(jj-1)),';']) + end + if jj == ordernum + tocoords = toedgecoords; + endplanes = [planesatedge(expandedpossedges,1) planesatedge(expandedpossedges,2)]; + else + eval(['tocoords = reflpoints',JJ(jj,1:JJnumbofchars(jj)),';']) + endplanes = expandedposscombs(:,jj); + end + + [nonobstructedpaths,nobstructions] = EDB1checkobstrpaths(fromcoords,tocoords,startplanes,endplanes,canplaneobstruct,planeseesplane,... + planeeqs,planenvecs,minvals,maxvals,planecorners,corners,ncornersperplanevec,rearsideplane); + + if nobstructions > 0 + expandedivsd = expandedivsd(nonobstructedpaths); + expandedposscombs = expandedposscombs(nonobstructedpaths,:); + expandedreftoISCOORDS = expandedreftoISCOORDS(nonobstructedpaths); + expandedpossedges = expandedpossedges(nonobstructedpaths); + edgeweightlist = edgeweightlist(nonobstructedpaths); + toedgecoords = tocoords(nonobstructedpaths,:); + nposs = length(expandedivsd); + for kk = 1:ordernum-1 + eval(['reflpoints',JJ(kk,1:JJnumbofchars(kk)),' = reflpoints',JJ(kk,1:JJnumbofchars(kk)),'(nonobstructedpaths,:);']) + end + + end + end + end + end + + if SHOWTEXT >= 3 + disp([' ',int2str(nposs),' IS+edge segments survived the obstruction test']) + end + + % There are repetitions of each combination since each edge segment has + % been treated separately. Pack them together now + + test = [expandedposscombs expandedpossedges]; + ncombs = length(expandedpossedges); + dtest = diff([0;prod( double(test(1:ncombs-1,:)==test(2:ncombs,:)).' ).']); + ivremove = find(dtest==1); + + while ~isempty(ivremove) + + edgeweightlist(ivremove+1) = double(edgeweightlist(ivremove+1)) + double(edgeweightlist(ivremove)); + edgeweightlist(ivremove) = []; + expandedpossedges(ivremove) = []; + expandedposscombs(ivremove,:) = []; + expandedivsd(ivremove) = []; + nposs = length(expandedivsd); + + test = [expandedposscombs expandedpossedges]; + ncombs = length(expandedpossedges); + dtest = diff([0;prod( double(test(1:ncombs-1,:)==test(2:ncombs,:)).' ).']); + ivremove = find(dtest==1); + + end + + if SHOWTEXT >= 3 + disp([' ',int2str(nposs),' IS+edge segments after edge segments are packed together']) + end + + combstoremove = setdiff(ivsd,expandedivsd); + addtocomb(combstoremove,:) = []; + addtooriginsfrom(combstoremove) = []; + addtoISESVISIBILITY(combstoremove) = []; + nadds = length(addtooriginsfrom); + end + end + + POTENTIALISES = [POTENTIALISES;[addtocomb zeros(nadds,specorder-ordernum)]]; + ORIGINSFROM = [ORIGINSFROM;addtooriginsfrom]; + + ivtemp = find(prod( double(addtocomb(:,1:ordernum-1)<=nplanes).' ).' & (addtocomb(:,ordernum)>nplanes)); + if difforder > 0 + if ~isempty(ivtemp) + addtoISESVISIBILITY(ivtemp) = edgeweightlist; + end + end + ISESVISIBILITY = [ISESVISIBILITY;addtoISESVISIBILITY]; + + endindices(ordernum) = length(ORIGINSFROM); + + % Compute the IS coords + + ISCOORDStoadd = zeros(nadds,3); + if difforder > 0 + ivss = uint32(find(prod( double(addtocomb<=nplanes).' ).')); + else + ivss = uint32([1:nadds].'); + end + soutoreflect = ISCOORDS(ORIGINSFROM(double(ivss)+endindices(ordernum-1)),1:3); + ISCOORDStoadd(ivss,:) = EDB1findis(soutoreflect,POTENTIALISES(double(ivss)+endindices(ordernum-1),ordernum),planeeqs,size(soutoreflect,1),onesvec3); + clear soutoreflect + ISCOORDS = [ISCOORDS;ISCOORDStoadd]; + clear ISCOORDStoadd + +end + +ntot = size(POTENTIALISES,1); + +%------------------------------------------------------- +% Add the direct sound to the start of the list + +POTENTIALISES = [zeros(1,specorder);POTENTIALISES]; +ORIGINSFROM = [0;ORIGINSFROM]; +startindices = startindices+1; +endindices = endindices+1; +ORIGINSFROM = uint32(double(ORIGINSFROM)+1); + +ISCOORDS = [S;ISCOORDS]; +ISESVISIBILITY = [0;ISESVISIBILITY]; + +%------------------------------------------------------- +% Trim the list if there are zeros-only in the last column(s) + +[n1,n2] = size(POTENTIALISES); +if n2 > 1 + columnstokeep = find(sum(POTENTIALISES)~=0); + POTENTIALISES = POTENTIALISES(:,columnstokeep); + [n1,n2new] = size(POTENTIALISES); + if n2new < n2 + specorderold = specorder; + specorder = n2new; + end +end + +%------------------------------------------------------- +% Create index lists + +% First, the total reflection order + +[n1,n2] = size(POTENTIALISES); + +lengthNspecmatrix = []; +lengthNdiffmatrix = []; +singlediffcol = []; +startindicessinglediff = []; +endindicessinglediff = []; + +if n1 > 0 & n2 > 0 +if n2 > 1 + REFLORDER = uint8(sum(POTENTIALISES.'>0).'); +else + REFLORDER = uint8(POTENTIALISES>0); +end + +if difforder > 0 + if specorder > 1 + ivss = uint32(find(prod( double(POTENTIALISES<=nplanes).' ).')); + else + ivss = uint32(find( POTENTIALISES<=nplanes )); + end + + ivother = uint32([1:length(ORIGINSFROM)].'); + ivother(ivss) = []; + ivss(1) = []; + IVNDIFFMATRIX = uint32(zeros(2,specorder)); + lengthNdiffmatrix = zeros(1,specorder); + nrowsdiff = 2; + IVNSPECMATRIX = uint32(zeros(2,specorder)); + lengthNspecmatrix = zeros(1,specorder); + nrowsspec = 2; + + for ii = 1:specorder + if specorder > 1 + ivreftoNdiff = uint32(find(sum( double(POTENTIALISES(ivother,:)> nplanes).' ).'==ii)); + else + ivreftoNdiff = uint32(find(( double(POTENTIALISES(ivother,:)> nplanes).' ).'==ii)); + end + ivreftoNspec = uint32(find(REFLORDER(ivss)==ii)); + + ivNdiff = ivother(ivreftoNdiff); + if ~isempty(ivNdiff) + lengthNdiffmatrix(ii) = length(ivNdiff); + if lengthNdiffmatrix(ii) > nrowsdiff + IVNDIFFMATRIX = [IVNDIFFMATRIX;uint32(zeros(lengthNdiffmatrix(ii)-nrowsdiff,specorder))]; + nrowsdiff = lengthNdiffmatrix(ii); + end + IVNDIFFMATRIX(1: lengthNdiffmatrix(ii),ii) = ivNdiff; + end + ivother(ivreftoNdiff) = []; + + ivNspec = ivss(ivreftoNspec); + if ~isempty(ivNspec) + lengthNspecmatrix(ii) = length(ivNspec); + if lengthNspecmatrix(ii) > nrowsspec + IVNSPECMATRIX = [IVNSPECMATRIX;uint32(zeros(lengthNspecmatrix(ii)-nrowsspec,specorder))]; + nrowsspec = lengthNspecmatrix(ii); + end + IVNSPECMATRIX(1: lengthNspecmatrix(ii),ii) = ivNspec; + end + end + + % Determine which column the single diffraction is in + + test = POTENTIALISES(IVNDIFFMATRIX(1:lengthNdiffmatrix(1),1),:)>nplanes; + + colweight = [1:specorder]; + nsingles = length(IVNDIFFMATRIX(1:lengthNdiffmatrix(1),1)); + if specorder > 1 + singlediffcol = uint8(sum( (test.*colweight(ones(nsingles,1),:)).').'); + else + singlediffcol = uint8(ones(nsingles,1)); + end + + startindicessinglediff = zeros(specorder,1); + endindicessinglediff = zeros(specorder,1); + startindicessinglediff(1) = 1; + for ii = 1:specorder-1 + iv = find(IVNDIFFMATRIX(1:lengthNdiffmatrix(1),1)<=endindices(ii)); + if ~isempty(iv) + endindicessinglediff(ii) = iv(length(iv)); + else + endindicessinglediff(ii) = 0; + end + startindicessinglediff(ii+1) = endindicessinglediff(ii)+1; + end + endindicessinglediff(specorder) = lengthNdiffmatrix(1); +else + ivss = uint32([2:endindices(length(endindices))].'); + IVNSPECMATRIX = uint32(zeros(2,specorder)); + lengthNspecmatrix = zeros(1,specorder); + nrowsspec = 2; + + for ii = 1:specorder + ivreftoNspec = uint32(find(REFLORDER(ivss)==ii)); + + ivNspec = ivss(ivreftoNspec); + lengthNspecmatrix(ii) = length(ivNspec); + if lengthNspecmatrix(ii) > nrowsspec + IVNSPECMATRIX = [IVNSPECMATRIX;uint32(zeros(lengthNspecmatrix(ii)-nrowsspec,specorder))]; + nrowsspec = lengthNspecmatrix(ii); + end + IVNSPECMATRIX(1: lengthNspecmatrix(ii),ii) = ivNspec; + + end + + IVNDIFFMATRIX = []; + lengthNdiffmatrix = []; + + singlediffcol = []; + startindicessinglediff = []; + endindicessinglediff = []; +end + +end + +%------------------------------------------------------- +% Create a pointer list so that it is possible to find a combination +% that ends with edge-plane2, given an edge-plane1-plane2 combination +% +% NB!! The list points to the original POTENTIALISES (and related lists) + +if difforder > 0 & specorder > 1 + + if SHOWTEXT >= 3 + disp([' Building a pointer list for image receiver combinations']) + end + + % First select only those that have a single diff combo and that + % start with the diffraction + + ndecimaldivider = (nplanes+2); + PointertoIRcombs = sparse(zeros(ndecimaldivider^(specorder-1),1)); + IRoriginsfrom = uint32(zeros(size(ORIGINSFROM))); + + for ii = 1:specorder-1 + if SHOWTEXT >= 3 + disp([' order ',int2str(ii)]) + end + + if ii == 1 + ivrange = uint32([startindicessinglediff(2):endindicessinglediff(2)]); + masterivlistselect = IVNDIFFMATRIX(ivrange,1); + masterivlistselect = masterivlistselect(find(singlediffcol(ivrange)==1)); + + % IRoriginsfrom should be given the value zero for these + % first-order specular combos (after one diff) so we don't + % bother assigning any value + + [B,IA,JA] = unique(POTENTIALISES(masterivlistselect,2)); + PointertoIRcombs(B) = masterivlistselect(IA); + + % Now we check if there any active wall numbers that don't + % occur in an edge-spec combination. For those combinations + % we can point to a specular combos instead, that ends with the + % same plane number. + + wallist = POTENTIALISES(IVNSPECMATRIX(1:lengthNspecmatrix(1),1),1); + ivnotincludedyet = find(~ismember(wallist,B)); + if ~isempty(ivnotincludedyet) + PointertoIRcombs(wallist(ivnotincludedyet)) = IVNSPECMATRIX(ivnotincludedyet,1); + end + + elseif ii >= 2 + ivrange = uint32([startindicessinglediff(ii+1):endindicessinglediff(ii+1)]); + masterivlistselect = IVNDIFFMATRIX(ivrange,1); + masterivlistselect = masterivlistselect(find(singlediffcol(ivrange)==1)); + + ivlist = 0; + for jj = 3:ii+1 + ivlist = ivlist + double(POTENTIALISES(masterivlistselect,jj))*ndecimaldivider^(ii+1-jj); + end + + IRoriginsfrom(masterivlistselect) = uint32(full(PointertoIRcombs(ivlist))); + + ivlist = ivlist + double(POTENTIALISES(masterivlistselect,2))*ndecimaldivider^(ii-1); + A = uint32(ivlist); + [B,IA,JA] = unique(A); + PointertoIRcombs(B) = masterivlistselect(IA); + + % Now we check if there any active wall numbers that don't + % occur as spec1 in an edge-spec1-spec2-spec3 combination. + + wallist = 0; + for jj = 1:ii + wallist = wallist + double(POTENTIALISES(IVNSPECMATRIX(1:lengthNspecmatrix(ii),ii),jj))*ndecimaldivider^(ii-jj); + end + + ivnotincludedyet = find(~ismember(wallist,B)); + + if ~isempty(ivnotincludedyet) + PointertoIRcombs(wallist(ivnotincludedyet)) = IVNSPECMATRIX(ivnotincludedyet,ii); + end + + end + + end + +else + ndecimaldivider = 0; + PointertoIRcombs = []; + IRoriginsfrom = []; +end + +%------------------------------------------------------- +% Save the output data + +maxval = max(IRoriginsfrom); +if maxval < 256 + IRoriginsfrom = uint8(IRoriginsfrom); +elseif maxval < 65536 + IRoriginsfrom = uint16(IRoriginsfrom); +end +maxval = max(ORIGINSFROM); +if maxval < 256 + ORIGINSFROM = uint8(ORIGINSFROM); +elseif maxval < 65536 + ORIGINSFROM = uint16(ORIGINSFROM); +end + +if SUPPRESSFILES == 0 + % The complete variable set could be saved if one wanted to. + Varlist = [' POTENTIALISES ORIGINSFROM ISCOORDS ISESVISIBILITY IVNSPECMATRIX lengthNspecmatrix IVNDIFFMATRIX lengthNdiffmatrix ']; + Varlist = [Varlist,' singlediffcol REFLORDER startindicessinglediff endindicessinglediff ndecimaldivider PointertoIRcombs IRoriginsfrom']; + + % Varlist = [' lengthNspecmatrix lengthNdiffmatrix ']; + % Varlist = [Varlist,' singlediffcol startindicessinglediff endindicessinglediff ndecimaldivider PointertoIRcombs IRoriginsfrom']; + + eval(['save ',ISEStreefile,Varlist]) +else + ISEStreefile = struct('POTENTIALISES',POTENTIALISES,'ORIGINSFROM',ORIGINSFROM,'ISCOORDS',ISCOORDS,'ISESVISIBILITY',ISESVISIBILITY,'IVNSPECMATRIX',IVNSPECMATRIX,... + 'lengthNspecmatrix',lengthNspecmatrix,'IVNDIFFMATRIX',IVNDIFFMATRIX,'lengthNdiffmatrix',lengthNdiffmatrix,'singlediffcol',singlediffcol,... + 'REFLORDER',REFLORDER,'startindicessinglediff',startindicessinglediff,'endindicessinglediff',endindicessinglediff,'ndecimaldivider',ndecimaldivider,... + 'PointertoIRcombs',PointertoIRcombs,'IRoriginsfrom',IRoriginsfrom); +end + + + + \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/private/EDB1findis.m Sat Nov 16 18:25:24 2013 +0000 @@ -0,0 +1,49 @@ +function [xis] = EDB1findis(xsou,ivec,planeeqs,nsou,onesvec) +% EDB1findis - Returns the image source coordinates +% Returns the image source coordinates +% via mirroring one or N sources in a list of planes. +% +% Input parameters: +% xsou Matrix, [N,3], of the source coordinates. +% ivec List, [nplanes,1], of plane numbers that the source +% should be mirrored in. If N ~= 1, then nplanes must +% be = N. +% planeeqs Matrix [nplanes,4] of the plane equations. +% nsou The value N. +% onesvec A list that should be = [1 1 1]. +% +% Output paramaters: +% xis Matrix [N,3] of all image sources to the source(s) +% via all the planes specified in ivec and planeeqs. +% +% Uses no special functions +% +% ---------------------------------------------------------------------------------------------- +% This file is part of the Edge Diffraction Toolbox by Peter Svensson. +% +% The Edge Diffraction Toolbox is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) any later version. +% +% The Edge Diffraction Toolbox is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +% FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License along with the +% Edge Diffraction Toolbox. If not, see <http://www.gnu.org/licenses/>. +% ---------------------------------------------------------------------------------------------- +% Peter Svensson (svensson@iet.ntnu.no) 20030706 +% +% [xis] = EDB1findis(xsou,ivec,planeeqs,nsou,onesvec); + +if nsou == 1 + Sbig = xsou(ones(length(ivec),1),:); + t = planeeqs(ivec,4) - sum((planeeqs(ivec,1:3).').*(Sbig.')).'; + + xis = Sbig + 2*t(:,onesvec).*planeeqs(ivec,1:3); +else + t = planeeqs(ivec,4) - sum((planeeqs(ivec,1:3).').*(xsou.')).'; + + xis = xsou + 2*t(:,onesvec).*planeeqs(ivec,1:3); +end +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/private/EDB1findpathsISESx.m Sat Nov 16 18:25:24 2013 +0000 @@ -0,0 +1,443 @@ +function edpathsfile = EDB1findpathsISESx(eddatafile,lengthNspecmatrix,lengthNdiffmatrix,... + singlediffcol,startindicessinglediff,endindicessinglediff,... + ndecimaldivider,PointertoIRcombs,IRoriginsfrom,S,R,isou,irec,... + directsound,specorder,difforder,nedgesubs,visplanesfromS,visplanesfromR,... + vispartedgesfromS,vispartedgesfromR,desiredfilename) +% EDB1findpathsISESx - Finds all possible paths that include direct sound, specular, diffraction. +% Finds all possible paths of types direct sound, specular, diffraction +% combinations of specular and diffraction. +% +% Input parameters: +% eddatafile Taken directly from the setup-file or created automatically +% lengthNspecmatrix, lengthNdiffmatrix +% singlediffcol, startindicessinglediff, endindicessinglediff +% ndecimaldivider, PointertoIRcombs, IRoriginsfrom +% Taken directly from the ISEStree-file +% S, R, isou, irec Coordinates and counter number of source and receiver, taken +% from the setup file. +% directsound, specorder, difforder +% Taken directly from the setup-file. +% nedgesubs Taken directly from the setup-file. +% visplanesfromS, visplanesfromR, vispartedgesfromS, vispartedgesfromR +% Taken directly from the srdatafile. +% desiredfilename (optional) The desired name of the output file. +% ISCOORDS (global) The matrix ISCOORDS from the ISEStreefile +% POTENTIALISES (global) The matrix POTENTIALISES from the ISEStreefile +% ORIGINSFROM (global) +% ISESVISIBILITY (global) +% IVNDIFFMATRIX (global) The list IVNDIFFMATRIX from the ISEStreefile +% IVNSPECMATRIX (global) +% REFLORDER (global) +% +% See descriptions in EDB1findISEStree, EDB1srgeo and EDB1mainISES +% +% Output parameters: +% edpathsfile The output file name, where the output data is +% stored. If the optional input parameter desiredfilename, +% is given, then edpathsfile will simple repeat +% this name. If desiredfilename was not specified +% a file name is created by extracting the file +% stem from the input parameter eddatafile, and +% with '_edpaths' added. +% +% Output data in the edpathsfile: +% pathtypevec A matrix, [ncombs,specorder], describing the +% type of reflection, using 'f' for the direct +% sound, 's' for specular reflection and 'd' for +% diffraction. +% reflpaths A matrix, [ncombs,specorder], giving the plane +% and edge numbers involved in each refl. comb. +% specextradata A sparse matrix, [ncombs,(specorder+1)*3] +% containing the coordinates of the image source +% (col 1-3), the image receiver (col 4-6) +% and the coordinates of all specular hit points +% (only for purely specular combinations). +% edgeextradata A sparse matrix, [ncombs,(specorder*2)], with +% the visibility of the involved edge, denoted +% by two values between 0 and 1. +% S The coordinates of the source. +% R The coordinates of the receiver. +% mainlistguide A matrix, [nposscombs,3], which for each row gives +% 1. the number of rows in "reflpaths" and +% "pathtypevec" that have one type of combination. +% 2. the first row and 3. the last row +% mainlistguidepattern A matrix, [nposscombs,specorder] which for each +% row gives the description of each possible combination +% using 'f', 's' and 'd'. +% directsoundrow The value 0 or 1 indicating whether the first row in +% mainlistguide & mainlistguidepattern & reflpaths & pathtypevec +% contains the direct sound or not. +% allspecrows A list, [1,2], containing the first and last row numbers +% of mainlistguide & mainlistguidepattern that contain specular +% reflections. If there are no specular reflections, allspecrows +% contains [0 0]. +% firstdiffrow A number indicating which is the first row of mainlistguide & +% mainlistguidepattern that contain a diffraction component. If +% there are no diffraction components, firstdiffrow = 0. +% Sinsideplanenumber The plane number that the source is directly at. If the +% source is not placed directly at a plane, then +% souinsideplanenumber = []; +% Rinsideplanenumber The plane number that the receiver is directly at. If the +% receiver is not placed directly at a plane, then +% recinsideplanenumber = []; +% +% Uses the functions EDB1strpend EDB1directsound +% EDB1speculISES EDB1diffISESx EDB1diff2ISES EDB1diffNISES +% +% ---------------------------------------------------------------------------------------------- +% This file is part of the Edge Diffraction Toolbox by Peter Svensson. +% +% The Edge Diffraction Toolbox is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) any later version. +% +% The Edge Diffraction Toolbox is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +% FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License along with the +% Edge Diffraction Toolbox. If not, see <http://www.gnu.org/licenses/>. +% ---------------------------------------------------------------------------------------------- +% Peter Svensson (svensson@iet.ntnu.no) 20050404 +% +% edpathsfile = EDB1findpathsISES(eddatafile,... +% lengthNspecmatrix,lengthNdiffmatrix,singlediffcol,startindicessinglediff,... +% endindicessinglediff,ndecimaldivider,PointertoIRcombs,IRoriginsfrom,S,R,isou,irec,... +% directsound,specorder,difforder,nedgesubs,visplanesfromS,visplanesfromR,... +% vispartedgesfromS,vispartedgesfromR,desiredfilename); + +global SHOWTEXT +global POTENTIALISES ISCOORDS IVNDIFFMATRIX +global IVNSPECMATRIX ORIGINSFROM ISESVISIBILITY REFLORDER + +eval(['load ',eddatafile]) +clear cornerinfrontofplane edgeseesplane planeseesplane + +if nargin < 22 + [filepath,filestem,fileext] = fileparts(eddatafile); + edpathsfile = [[filepath,filesep],EDB1strpend(filestem,'_eddata'),'_',int2str(isou),'_',int2str(irec),'_edpaths.mat']; +else + edpathsfile = desiredfilename; +end + +nplanes = length(planeisthin); + +pathtypevec = []; +reflpaths = []; +specextradata = []; +edgeextradata = []; +mainlistguide = []; +mainlistguidepattern = []; + +%------------------------------------------------------- +% ############################# +% ## DIRECT SOUND ## +% ############################# + +if directsound == 1 + if SHOWTEXT >= 2 + disp(' Direct sound') + end + dirsoundok = EDB1directsound(eddatafile,S,R,visplanesfromS,visplanesfromR); + if dirsoundok == 1 + pathtypevec = [pathtypevec;['f',zeros(1,specorder-1)]]; + reflpaths = [reflpaths;zeros(1,specorder)]; + if specorder > 0 + specextradata = [specextradata;[S R zeros(1,(specorder-1)*3)]]; + else + specextradata = [specextradata;[S R]]; + end + edgeextradata = [edgeextradata;zeros(1,specorder*2)]; + mainlistguide = [1 1 1]; + mainlistguidepattern = ['f' ' '*ones(1,specorder-1)]; + directsoundrow = 1; + else + directsoundrow = 0; + end +else + directsoundrow = 0; +end + +%------------------------------------------------------- +% ############################# +% ## SPECULAR ## +% ############################# + +if specorder >= 1 + if SHOWTEXT >= 2 + disp(' SPECULAR reflections') + end + [validISlist,validIScoords,allreflpoints,listguide,listofreflorder] = EDB1speculISES(eddatafile,... + S,R,lengthNspecmatrix,specorder,visplanesfromR); + [nvalidreflorders,slask] = size(listguide); + for ii = 1:nvalidreflorders + ncombs = listguide(ii,1); + norder = listofreflorder(ii); + + if ncombs > 0 + pathtypevec = [pathtypevec;['s'*ones(ncombs,norder) zeros(ncombs,specorder-norder)]]; + reflpaths = [reflpaths;validISlist(listguide(ii,2):listguide(ii,3),:)]; + if size(pathtypevec,2) > size(reflpaths,2) + reflpaths = [reflpaths zeros(size(reflpaths,1),size(pathtypevec,2)-size(reflpaths,2))]; + end + specextradata = [specextradata;[validIScoords(listguide(ii,2):listguide(ii,3),1:3) allreflpoints(listguide(ii,2):listguide(ii,3),:)]]; + if size(specextradata,2) < (size(pathtypevec,2)+1)*3 + specextradata = [specextradata zeros(size(specextradata,1),(size(pathtypevec,2)+1)*3-size(specextradata,2))]; + end + edgeextradata = [edgeextradata;zeros(ncombs,specorder*2)]; + end + + mainlistguidepattern = [mainlistguidepattern;['s'*ones(1,norder) ' '*ones(1,specorder-norder)]]; + + end + + [nprevious,slask] = size(mainlistguide); + if nprevious > 0 + listguide(:,2:3) = listguide(:,2:3)+mainlistguide(nprevious,3); + end + mainlistguide = [mainlistguide;listguide]; + if nvalidreflorders == 0 + allspecrows = [0 0]; + else + allspecrows = [min([1 nvalidreflorders]) nvalidreflorders]+directsoundrow; + end + firstdiffrow = nvalidreflorders + directsoundrow + 1; + +else + allspecrows = [0 0]; + firstdiffrow = directsoundrow + 1; +end + +%------------------------------------------------------- +% #################################### +% ## SINGLE DIFFRACTION ## +% #################################### + +if difforder >=1 & ~isempty(lengthNdiffmatrix) + if SHOWTEXT >= 2 + disp(' SINGLE DIFFRACTION combined with any order specular') + end + [edgedifflist,startandendpoints,prespeclist,postspeclist,validISEDcoords,validEDIRcoords,listguide,listoforders,... + bigedgeweightlist] = EDB1diffISESx(eddatafile,S,R,... + IVNDIFFMATRIX(1:lengthNdiffmatrix(1),1),singlediffcol,startindicessinglediff,endindicessinglediff,... + specorder,visplanesfromR,vispartedgesfromS,vispartedgesfromR,nedgesubs,ndecimaldivider,PointertoIRcombs,IRoriginsfrom); + [nvalidcombs,slask] = size(listguide); + nprespecs = listoforders(:,2) - 1; + npostspecs = listoforders(:,1) - nprespecs - 1; + + [nrows,nsubsegmentcols] = size(startandendpoints); + nsubsegments = uint8( (startandendpoints(:,2:2:nsubsegmentcols))~=0 ); + + if nrows > 1 & nsubsegmentcols > 2 + nsubsegments = sum(nsubsegments.').'; + end + nmaxsubsegments = max(nsubsegments); + + expandedlistguide = listguide; + for ii = 1:nvalidcombs + ncombs = listguide(ii,1); + iv = [listguide(ii,2):listguide(ii,3)]; + + pathtypevec = [pathtypevec; ['s'*ones(ncombs,nprespecs(ii)) 'd'*ones(ncombs,1) 's'*ones(ncombs,npostspecs(ii)) zeros(ncombs,specorder-listoforders(ii)) ]]; + reflpaths = [reflpaths; [prespeclist(iv,1:nprespecs(ii)) edgedifflist(iv) postspeclist(iv,1:npostspecs(ii)) zeros(ncombs,specorder-listoforders(ii)) ]]; + specextradata = [specextradata;[ validISEDcoords(iv,1:3) validEDIRcoords(iv,1:3) zeros(ncombs,(specorder-1)*3) ]]; + edgeextradata = [edgeextradata;[startandendpoints(iv,1:2) zeros(ncombs,(specorder-1)*2) ]]; + mainlistguidepattern = [mainlistguidepattern;['s'*ones(1,nprespecs(ii)) 'd' 's'*ones(1,npostspecs(ii)) zeros(1,specorder-listoforders(ii))]]; + if nmaxsubsegments > 2 + for jj = 2:nmaxsubsegments + ivsub = find(nsubsegments(iv)>=jj); + ncombssubset = length(ivsub); + if ncombssubset > 0 + pathtypevec = [pathtypevec; ['s'*ones(ncombssubset,nprespecs(ii)) 'd'*ones(ncombssubset,1) 's'*ones(ncombssubset,npostspecs(ii)) zeros(ncombssubset,specorder-listoforders(ii)) ]]; + reflpaths = [reflpaths; [prespeclist(iv(ivsub),1:nprespecs(ii)) edgedifflist(iv(ivsub)) postspeclist(iv(ivsub),1:npostspecs(ii)) zeros(ncombssubset,specorder-listoforders(ii)) ]]; + specextradata = [specextradata;[ validISEDcoords(iv(ivsub),1:3) validEDIRcoords(iv(ivsub),1:3) zeros(ncombssubset,(specorder-1)*3) ]]; + edgeextradata = [edgeextradata;[startandendpoints(iv(ivsub),(jj-1)*2+1:(jj-1)*2+2) zeros(ncombssubset,(specorder-1)*2) ]]; + expandedlistguide(ii,1) = expandedlistguide(ii,1) + ncombssubset; + expandedlistguide(ii,3) = expandedlistguide(ii,3) + ncombssubset; + for kk = ii+1:nvalidcombs + expandedlistguide(kk,2:3) = expandedlistguide(kk,2:3) + ncombssubset; + end + end + end + end + end + [n1,n2] = size(mainlistguide); + if n1 > 0 + listoffset = mainlistguide(n1,3); + else + listoffset = 0; + end + if size(expandedlistguide,1) > 0 + mainlistguide = [mainlistguide;[expandedlistguide(:,1) expandedlistguide(:,2:3)+listoffset]]; + end +end + +%------------------------------------------------------- +% ################################################ +% ## DOUBLE AND HIGHER DIFFRACTION ## +% ################################################ + +for kk = 2:min([specorder difforder]) + + if ~isempty(lengthNdiffmatrix) + + if SHOWTEXT >= 2 + disp([' DIFFRACTION, ORDER ',int2str(kk),' combined with any order specular']) + end + + nmaxsubsegments = 0; + + % We will use the spec-edge-spec combs that were found valid for + % first-order diffraction, because if higher-order diffraction combs + % end with the same edge-spec-spec-... comb we know the visibility + % already. + % First, pick out only the combs that have postspecs. Second, keep + % only a unique set because there will be many repeated combinations. + + + if kk == 2 + iv = find(sum(postspeclist.')>0 ); + edgedifflist = edgedifflist(iv,:); + postspeclist = postspeclist(iv,:); + bigedgeweightlist = bigedgeweightlist(iv,:); + validEDIRcoords = validEDIRcoords(iv,:); + + patternthatisOK = [edgedifflist postspeclist]; + [patternthatisOK,iv,slask] = unique(patternthatisOK,'rows'); + edgedifflistin = edgedifflist(iv,:); + postspeclistin = postspeclist(iv,:); + bigedgeweightlistin = bigedgeweightlist(iv,:); + validEDIRcoordsin = validEDIRcoords(iv,:); + + end + + if kk == 2 + maxrownumber = max(lengthNdiffmatrix(1:2)); + [edgedifflist,startandendpoints,prespeclist,midspeclist,postspeclist,validISEDcoords,validEDIRcoords,listguide,listofallspecs] = EDB1diff2ISES(eddatafile,S,R,... + IVNDIFFMATRIX(1:maxrownumber,1:2),lengthNdiffmatrix(1:2),... + specorder,visplanesfromR,vispartedgesfromS,vispartedgesfromR,nedgesubs,ndecimaldivider,edgedifflistin,postspeclistin,... + bigedgeweightlistin,validEDIRcoordsin,edgeplaneperptoplane1,edgeplaneperptoplane2); + + [nrows,nsubsegmentcols] = size(startandendpoints); + nsubsegments = uint8((startandendpoints(:,2:4:nsubsegmentcols))~=0); + if nrows > 1 & nsubsegmentcols > 4 + nsubsegments = sum(nsubsegments.').'; + end + nmaxsubsegments = max(nsubsegments); + + elseif kk >= 3 + maxrownumber = max(lengthNdiffmatrix(1:kk)); + + [edgedifflist,startandendpoints,prespeclist,postspeclist,validISEDcoords,validEDIRcoords,listguide,listoforders] = EDB1diffNISES(eddatafile,S,R,... + IVNDIFFMATRIX(1:maxrownumber,1:kk),lengthNdiffmatrix(1:kk),kk,... + specorder,visplanesfromR,vispartedgesfromS,vispartedgesfromR,nedgesubs,ndecimaldivider,edgedifflistin,postspeclistin,... + bigedgeweightlistin,validEDIRcoordsin); + end + + [nvalidcombs,slask] = size(listguide); + if kk >= 3 + nprespecs = listoforders(:,2) - 1; + npostspecs = listoforders(:,1) - nprespecs - kk; + else + nprespecs = listofallspecs(:,1); + nmidspecs = listofallspecs(:,2); + npostspecs = listofallspecs(:,3); + listoforders = nprespecs+nmidspecs+npostspecs+2; + end + + for ii = 1:nvalidcombs + ncombs = listguide(ii,1); + i1 = listguide(ii,2); i2 = listguide(ii,3); + if kk == 2 + pathtypevec = [pathtypevec; ['s'*ones(ncombs,nprespecs(ii)) 'd'*ones(ncombs,1) 's'*ones(ncombs,nmidspecs(ii)) 'd'*ones(ncombs,1) 's'*ones(ncombs,npostspecs(ii)) zeros(ncombs,specorder-listoforders(ii)) ]]; + else + pathtypevec = [pathtypevec; ['s'*ones(ncombs,nprespecs(ii)) 'd'*ones(ncombs,kk) 's'*ones(ncombs,npostspecs(ii)) zeros(ncombs,specorder-listoforders(ii)) ]]; + end + + if kk == 2 + reflpaths = [reflpaths; [prespeclist(i1:i2,1:nprespecs(ii)) edgedifflist(i1:i2,1) midspeclist(i1:i2,1:nmidspecs(ii)) edgedifflist(i1:i2,2) postspeclist(i1:i2,1:npostspecs(ii)) zeros(ncombs,specorder-listoforders(ii)) ]]; + else + reflpaths = [reflpaths; [prespeclist(i1:i2,1:nprespecs(ii)) edgedifflist(i1:i2,1:kk) postspeclist(i1:i2,1:npostspecs(ii)) zeros(ncombs,specorder-listoforders(ii)) ]]; + end + + specextradata = [specextradata;[ validISEDcoords(i1:i2,1:3) validEDIRcoords(i1:i2,1:3) zeros(ncombs,(specorder-1)*3) ]]; + edgeextradata = [edgeextradata;[startandendpoints(i1:i2,1:kk*2) zeros(ncombs,(specorder-kk)*2) ]]; + if kk == 2 + mainlistguidepattern = [mainlistguidepattern;['s'*ones(1,nprespecs(ii)) 'd' 's'*ones(1,nmidspecs(ii)) 'd' 's'*ones(1,npostspecs(ii)) zeros(1,specorder-listoforders(ii))]]; + else + mainlistguidepattern = [mainlistguidepattern;['s'*ones(1,nprespecs(ii)) 'd'*ones(1,kk) 's'*ones(1,npostspecs(ii)) zeros(1,specorder-listoforders(ii))]]; + end + + for jj = 2:nmaxsubsegments + ivsub = find(nsubsegments(iv)>=jj); + ncombssubset = length(ivsub); + if ncombssubset > 0 + pathtypevec = [pathtypevec; ['s'*ones(ncombssubset,nprespecs(ii)) 'd'*ones(ncombssubset,1) 's'*ones(ncombssubset,nmidspecs(ii)) 'd'*ones(ncombssubset,1) 's'*ones(ncombssubset,npostspecs(ii)) zeros(ncombssubset,specorder-listoforders(ii)) ]]; + reflpaths = [reflpaths; [prespeclist(iv(ivsub),1:nprespecs(ii)) edgedifflist(iv(ivsub),1) midspeclist(iv(ivsub),1:nmidspecs(ii)) edgedifflist(iv(ivsub),2) postspeclist(iv(ivsub),1:npostspecs(ii)) zeros(ncombssubset,specorder-listoforders(ii)) ]]; + specextradata = [specextradata;[ validISEDcoords(iv(ivsub),1:3) validEDIRcoords(iv(ivsub),1:3) zeros(ncombssubset,(specorder-1)*3) ]]; + edgeextradata = [edgeextradata;[startandendpoints(iv(ivsub),(jj-1)*4+1:(jj-1)*4+4) zeros(ncombssubset,(specorder-1)*4) ]]; + expandedlistguide(ii,1) = expandedlistguide(ii,1) + ncombssubset; + expandedlistguide(ii,3) = expandedlistguide(ii,3) + ncombssubset; + for kk = ii+1:nvalidcombs + expandedlistguide(kk,2:3) = expandedlistguide(kk,2:3) + ncombssubset; + end + end + end + + end + + [n1,n2] = size(mainlistguide); + if n1 > 0 + listoffset = mainlistguide(n1,3); + else + listoffset = 0; + end + mainlistguide = [mainlistguide;[listguide(:,1) listguide(:,2:3)+listoffset]]; + + end + +end + +[n1,n2] = size(mainlistguide); +if firstdiffrow > n1 + firstdiffrow = 0; +end + +%------------------------------------------------------- +% Is the source or receiver directly at a plane? + +Sinsideplanenumber = find(visplanesfromS==4); + +Rinsideplanenumber = find(visplanesfromR==4); + +%------------------------------------------------------- +% Get rid of empty columns + +if ~isempty(pathtypevec) + checksum = sum(pathtypevec); + ncols = length(checksum); + while checksum(ncols) == 0 + pathtypevec(:,ncols) = []; + checksum = sum(pathtypevec); + ncols = length(checksum); + end +end + +%------------------------------------------------------- +% Save the output data + +specextradata = sparse(specextradata); +edgeextradata = sparse(edgeextradata); +pathtypevec = uint8(pathtypevec); +[ncombs,slask] = size(reflpaths); +if ncombs+1 < 256 + mainlistguide = uint8(mainlistguide); +elseif ncombs+1 < 65536 + mainlistguide = uint16(mainlistguide); +else + mainlistguide = uint32(mainlistguide); +end + +Varlist = [' pathtypevec reflpaths specextradata edgeextradata S R mainlistguide mainlistguidepattern directsoundrow allspecrows firstdiffrow Sinsideplanenumber Rinsideplanenumber']; + +eval(['save ',edpathsfile,Varlist])
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/private/EDB1fistr.m Sat Nov 16 18:25:24 2013 +0000 @@ -0,0 +1,56 @@ +function iline = EDB1fistr(longtextstring,iline,linestartvec,CRpositionvec,textstring) +% EDB1fistr - Reads a text file, line by line, until a given textstring is found. +% Reads line by line in a long textstring 'longtextstring' +% until the text in 'textstring' has been found. +% +% Input parameters: +% longtextstring The long textstring ot search in +% iline The line number to start searching at +% linestartvec A vector with the starting positions of all lines +% CRpositionvec A vector with the ending positions of all lines (inlcudes CR) +% textstring The textstring to search for. +% Output parameters: +% iline The line number which contains the text in textstring. +% If the text doesn't occur, the value -1 is returned. +% +% Uses no special functions +% +% ---------------------------------------------------------------------------------------------- +% This file is part of the Edge Diffraction Toolbox by Peter Svensson. +% +% The Edge Diffraction Toolbox is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) any later version. +% +% The Edge Diffraction Toolbox is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +% FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License along with the +% Edge Diffraction Toolbox. If not, see <http://www.gnu.org/licenses/>. +% ---------------------------------------------------------------------------------------------- +% Peter Svensson (svensson@iet.ntnu.no) 20001010 +% +% iline = EDB1fistr(longtextstring,iline,linestartvec,CRpositionvec,textstring); + +nlines = length(linestartvec); + +foundtext = 0; +foundend = 0; +nchar = length(textstring); + +iline = iline - 1; +while foundtext == 0 & foundend == 0 + iline = iline + 1; + if iline > nlines + foundend = 1; + iline = -1; + else + Str = longtextstring( linestartvec(iline):CRpositionvec(iline)-1 ); + if length(Str) >= nchar, + if Str(1:nchar) == textstring + foundtext = 1; + end + end + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/private/EDB1getedgepoints.m Sat Nov 16 18:25:24 2013 +0000 @@ -0,0 +1,134 @@ +function [edgepointcoords,weightvec,edgenumberlist] = EDB1getedgepoints(edgestartcoords,edgeendcoords,edgelengths,nedgesubs,returnedgenumbers) +% EDB1getedgepoints - Calculates a number of edge coordinates. +% +% Input parameters: +% edgestartcoords Matrix, [nedges,3], of the startpoint coordinates of nedges edges. +% edgeendcoords Matrix, [nedges,3], of the endpoint coordinates of nedges edges. +% edgelengths List, [nedges,1], of edge lengths. +% nedgesubs The desired number of subdivisions per edge. +% returnedgenumbers (optional) If this optional parameter is given the +% value 1, the output parameter edgenumberlist will be non-empty. +% +% NB! The input parameters edgestartcoords, edgeendcoords and edgelengths +% should have been passed on directly from the eddata file. +% The parameter nedgesubs should have been taken from the setup file. +% +% Output parameters: +% edgepointcoords Matrix, [nedges*nedgesubs,3], of the midpoints +% of the edge subdivision segments. +% weightvec List, [nedges*nedgesubs,3], with the weights +% (1,2,4,8,...) per edge subdivision segment. +% edgenumberlist List, [nedges*nedgesubs,1], of which edge +% number each subdivision segment originated from. +% See also the input parameter returnedgenumbers. +% +% ---------------------------------------------------------------------------------------------- +% This file is part of the Edge Diffraction Toolbox by Peter Svensson. +% +% The Edge Diffraction Toolbox is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) any later version. +% +% The Edge Diffraction Toolbox is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +% FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License along with the +% Edge Diffraction Toolbox. If not, see <http://www.gnu.org/licenses/>. +% ---------------------------------------------------------------------------------------------- +% Peter Svensson (svensson@iet.ntnu.no) 20030503 +% +% [edgepointcoords,weightvec,edgenumberlist] = EDB1getedgepoints(edgestartcoords,edgeendcoords,edgelengths,nedgesubs,returnedgenumbers); + +if nargin < 5 + returnedgenumbers = 0; +end + +[nedges,slask] = size(edgestartcoords); + +if nedgesubs == 1 + edgepointcoords = (edgestartcoords+edgeendcoords)/2; + weightvec = uint8(ones(nedges,1)); + if returnedgenumbers == 1 + if nedges < 256 + edgenumberlist = uint8([1:nedges]); + elseif nedges < 65536 + edgenumberlist = uint16([1:nedges]); + else + edgenumberlist = uint32([1:nedges]); + end + else + edgenumberlist = []; + end + return +end + +ntot = nedges*nedgesubs; + +edgestart = zeros(ntot,3); +edgeend = zeros(ntot,3); + +onesvec1 = ones(nedgesubs,1); +onesvec2 = ones(1,3); +onesvec3 = ones(1,nedges); + +%------------------------------------------------- +% Start points + +A = edgestartcoords(:,1).'; +edgestart(:,1) = reshape(A(onesvec1,:),ntot,1); + +A = edgestartcoords(:,2).'; +edgestart(:,2) = reshape(A(onesvec1,:),ntot,1); + +A = edgestartcoords(:,3).'; +edgestart(:,3) = reshape(A(onesvec1,:),ntot,1); + +%------------------------------------------------- +% End points + +A = edgeendcoords(:,1).'; +edgeend(:,1) = reshape(A(onesvec1,:),ntot,1); + +A = edgeendcoords(:,2).'; +edgeend(:,2) = reshape(A(onesvec1,:),ntot,1); + +A = edgeendcoords(:,3).'; +edgeend(:,3) = reshape(A(onesvec1,:),ntot,1); + +%------------------------------------------------------------ +% Spread the edge points along the edge, including the end +% points, but nudge them in a bit. + +displacement = 1e-1; + +edgedividervec = [displacement 1:nedgesubs-2 nedgesubs-1-displacement].'/(nedgesubs-1); +edgedividervec = reshape(edgedividervec(:,onesvec3),ntot,1); + +edgepointcoords = edgestart + (edgeend - edgestart).*edgedividervec(:,onesvec2); + +%------------------------------------------------------------ +% Extra output data + +if nedgesubs < 8 + weightvec = uint8(2.^[0:nedgesubs-1].'); +elseif nedgesubs < 16 + weightvec = uint16(2.^[0:nedgesubs-1].'); +else + weightvec = uint32(2.^[0:nedgesubs-1].'); +end + +weightvec = reshape(weightvec(:,onesvec3),ntot,1); + +if returnedgenumbers == 1 + if nedges < 256 + edgenumberlist = uint8([1:nedges]); + elseif nedges < 65536 + edgenumberlist = uint16([1:nedges]); + else + edgenumberlist = uint32([1:nedges]); + end + edgenumberlist = reshape(edgenumberlist(onesvec1,:),ntot,1); +else + edgenumberlist = []; +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/private/EDB1infrontofplane.m Sat Nov 16 18:25:24 2013 +0000 @@ -0,0 +1,157 @@ +function pointinfront = EDB1infrontofplane(pointcoords,planenvecs,planecoco,backupplanecoco,cornernumb,planenumb) +% EDB1infrontofplane - Checks if a point is in front of, in plane with, or behind a list of planes. +% Alternatively, a single plane is checked versus a list of points. +% Alternatively, it checks n points versus n planes. +% +% Input parameters: +% pointcoords A list of points, or a single point, as [x1 y1 z1;x2 y2 z2;...] +% planenvecs A single planenvec, or a list of planenvecs, as +% [nx1,ny1,nz1;nx2,ny2,nz2;...] +% planecoco A single, or a list of, points belonging to the plane +% backupplanecoco A single, or a list of, points belonging to the plane, but different +% points than in planecoco +% cornernumb (optional) A list of the values [1:ncorners] for huge problems. +% If this list is used, the other input parameters pointcoords etc must be expanded. +% planenumb (optional) A list of the values [1:nplanes] for huge problems. +% If this list is used, the other input parameters pointcoords etc must be expanded. +% +% Output parameters: +% pointinfront A list of values, +1 (in front) 0 (in plane) or -1 (behind) +% +% ---------------------------------------------------------------------------------------------- +% This file is part of the Edge Diffraction Toolbox by Peter Svensson. +% +% The Edge Diffraction Toolbox is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) any later version. +% +% The Edge Diffraction Toolbox is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +% FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License along with the +% Edge Diffraction Toolbox. If not, see <http://www.gnu.org/licenses/>. +% ---------------------------------------------------------------------------------------------- +% Peter Svensson (svensson@iet.ntnu.no) 20090103 +% +% pointinfront = EDB1infrontofplane(pointcoords,planenvecs,planecoco,backupplanecoco,cornernumb,planenumb); + +geomacc = 1e-6; +batchsize = 2.5e6; + +[nplanes,slask] = size(planenvecs); +[npoints,slask] = size(pointcoords); + +if npoints == 1 + + onesvec = ones(nplanes,1); + bigpointcoords = pointcoords(onesvec,:); + + vectors = bigpointcoords - planecoco; + lvectors = sqrt(sum( (vectors.').^2 )).'; + iv = find( lvectors < geomacc ); + if ~isempty(iv) + vectors(iv,:) = bigpointcoords(iv,:) - backupplanecoco(iv,:); + if length(iv) > 1 + lvectors(iv) = sqrt(sum( (vectors(iv,:).').^2 )).'; + else + lvectors(iv) = norm(vectors(iv,:)); + end + end + + pointrelplane = sum((vectors.').*(planenvecs.')); + pointinfront = double(pointrelplane > geomacc); + iv = find(pointrelplane < -geomacc); + if ~isempty(iv) + pointinfront(iv) = -1*ones(size(iv)); + end +elseif npoints > 1 & nplanes==1 + onesvec = ones(npoints,1); + bigplanenvecs = planenvecs(onesvec,:); + bigplanecoco = planecoco(onesvec,:); + vectors = pointcoords - bigplanecoco; + lvectors = sqrt(sum( (vectors.').^2 )).'; + iv = find( lvectors < geomacc ); + if ~isempty(iv) + bigbackupplanecoco = backupplanecoco(onesvec,:); + vectors(iv,:) = pointcoords(iv,:) - bigbackupplanecoco(iv,:); + end + pointrelplane = sum((vectors.').*(bigplanenvecs.')); + pointinfront = double(pointrelplane > geomacc); + iv = find(pointrelplane < -geomacc); + if ~isempty(iv) + pointinfront(iv) = -1*ones(size(iv)); + end +else + if nargin == 4 + vectors = pointcoords - planecoco; + lvectors = sqrt(sum( (vectors.').^2 )).'; + iv = find( lvectors < geomacc ); + if ~isempty(iv) + vectors(iv,:) = pointcoords(iv,:) - backupplanecoco(iv,:); + end + pointrelplane = sum((vectors.').*(planenvecs.')); + pointinfront = double(pointrelplane > geomacc); + iv = find(pointrelplane < -geomacc); + if ~isempty(iv) + pointinfront(iv) = -1*ones(size(iv)); + end + elseif nargin == 6 + nplanes = length(planenumb); + ncorners = length(cornernumb); + corners = pointcoords; clear pointcoords + planecorners = planecoco; clear planecoco + + planenumb = reshape(planenumb(:,ones(1,ncorners)),nplanes*ncorners,1); + + cornernumb = reshape(cornernumb(ones(nplanes,1),:),nplanes*ncorners,1); + + nproblemsize = size(cornernumb,1); + + if nproblemsize <= batchsize + vectors = corners(cornernumb,:) - corners(planecorners(planenumb,1),:); + iv = find( sqrt(sum( (vectors.').^2 )).' < geomacc ); + else + nbatches = ceil(nproblemsize/batchsize); + vectors = zeros(nproblemsize,3); + lengthvec = zeros(nproblemsize,1); + for ii = 1:nbatches + ivbatch = [1+(ii-1)*batchsize : min([ii*batchsize nproblemsize])]; + vectors(ivbatch,:) = corners(cornernumb(ivbatch),:) - corners(planecorners(planenumb(ivbatch),1),:); + lengthvec(ivbatch) = sqrt(sum( (vectors(ivbatch,:).').^2 )); + end + + iv = find( lengthvec.' < geomacc ); + + end + + if ~isempty(iv) + backupplanecoco = corners(planecorners(planenumb(iv),2),:); + cornernumb = cornernumb(iv); + vectors(iv,:) = corners(cornernumb,:) - backupplanecoco; + clear backupplanecoco corners + end + + % Here vectors doubles so that vectors gets the value of + % pointrelplane. For the batches case, only column 1 is reused. + + if nproblemsize <= batchsize + vectors = sum((vectors.').*(planenvecs(planenumb,:).')); + else + for ii = 1:nbatches + ivbatch = [1+(ii-1)*batchsize : min([ii*batchsize nproblemsize])]; + vectors(ivbatch,1) = sum((vectors(ivbatch,:).').*(planenvecs(planenumb(ivbatch),:).')); + end + vectors = vectors(:,1); + end + clear planenumb planenvecs + + pointinfront = double(vectors > geomacc); + iv = find(vectors < -geomacc); + if ~isempty(iv) + pointinfront(iv) = -1*ones(size(iv)); + end + end +end + +pointinfront = pointinfront.';
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/private/EDB1irfromslotlist.m Sat Nov 16 18:25:24 2013 +0000 @@ -0,0 +1,103 @@ +function ir = EDB1irfromslotlist(slotnumbervec,ampvec,method) +% EDB1irfromslotlist - Creates an IR from a list of sample numbers and amplitudes +% +% Input parameters: +% slotnumbervec List of sample numbers which don't need to be integers. +% For non-integers, each pulse is divided into two +% neighboring sample slots. This gives an accurate phase +% response, but a high-frequency roll-off. +% ampvec List of corresponding amplitudes +% method (optional) 'oneslot' or 'twoslot'. Default is 'twoslot'. +% 'oneslot' means that each pulse is placed in the +% nearest sample slot. +% 'twoslot' means that each pulse is divided between +% two neighbour sample slots. +% +% Output parameters: +% ir A list containing the impulse response that is created +% by a number of pulses in the input lists. +% +% ---------------------------------------------------------------------------------------------- +% This file is part of the Edge Diffraction Toolbox by Peter Svensson. +% +% The Edge Diffraction Toolbox is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) any later version. +% +% The Edge Diffraction Toolbox is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +% FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License along with the +% Edge Diffraction Toolbox. If not, see <http://www.gnu.org/licenses/>. +% ---------------------------------------------------------------------------------------------- +% Peter Svensson (svensson@iet.ntnu.no) 20041201 +% +% ir = EDB1irfromslotlist(slotnumbervec,ampvec,method); + +if nargin < 3 + method = 'twoslots'; +end +if method(1) == 'o' | method(1) == 'O' + slotnumbervec = round(slotnumbervec); +end + +[n1,n2] = size(slotnumbervec); +if n2 ~= 1 + slotnumbervec = reshape(slotnumbervec,n1*n2,1); +end +[n1,n2] = size(ampvec); +if n2 ~= 1 + ampvec = reshape(ampvec,n1*n2,1); +end + +% B1 is the sampleslot numbers in integer number +B1 = floor(slotnumbervec); + +% slotnumbervec is a value between 0 and 1 stating how much of dir that should be added +% to the first sample slot, i.e. the one given in B1. The rest of dir should +% be added to the following sample slot. +slotnumbervec = slotnumbervec - B1; + +% Sort the values in B1, because the values occur many times. +% The slotnumbervec and ampvec values must be sorted in the same order. +% The isteps vactor will contain the occurences of a step in slotnumbervec. + +[B1,sortvec] = sort(B1); +isteps = find(diff(B1) ~= 0) +1; + +slotnumbervec = slotnumbervec(sortvec); +ampvec = ampvec(sortvec); + +nelems = length(B1); +nir = B1(nelems) + 2; +ir = zeros( nir,1 ); + +% Now we can sum all the contributions that should end up in the same +% sample slot. There is a for loop over the steps given in isteps, but +% the first and last values are treated outside the for loop. + +slotnumber = B1(1); + +if isempty(isteps) | nelems == 1 + ir(slotnumber) = ir(slotnumber) + sum( ampvec.*(1-slotnumbervec) ); + ir(slotnumber+1) = ir(slotnumber+1) + sum( ampvec.*slotnumbervec ); +else + ir(slotnumber) = ir(slotnumber) + sum( ampvec(1:isteps(1)-1).*(1-slotnumbervec(1:isteps(1)-1)) ); + ir(slotnumber+1) = ir(slotnumber+1) + sum( ampvec(1:isteps(1)-1).*slotnumbervec(1:isteps(1)-1) ); + + slotnumbers = B1( isteps ); + for jj = 1:length(isteps)-1 + ir(slotnumbers(jj)) = ir(slotnumbers(jj)) + ... + sum(ampvec(isteps(jj):isteps(jj+1)-1).*(1-slotnumbervec(isteps(jj):isteps(jj+1)-1)) ); + ir(slotnumbers(jj)+1) = ir(slotnumbers(jj)+1) + ... + sum( ampvec(isteps(jj):isteps(jj+1)-1).*slotnumbervec(isteps(jj):isteps(jj+1)-1) ); + end + + startindex = isteps(length(isteps)); + slotnumber = B1( startindex ); + ir(slotnumber) = ir(slotnumber) + ... + sum( ampvec(startindex:nelems).*(1-slotnumbervec(startindex:nelems)) ); + ir(slotnumber+1) = ir(slotnumber+1) + ... + sum( ampvec(startindex:nelems).*slotnumbervec(startindex:nelems) ); +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/private/EDB1main.m Sat Nov 16 18:25:24 2013 +0000 @@ -0,0 +1,1053 @@ +function EDB1main(EDsetupfile) +% EDB1main - Calculates the specular and edge diffraction IRs and saves them in a file. +% Calculates the specular and edge diffraction IRs and saves them in a file or +% a series of files, if there are many sources and receivers.The +% calculation goes through three stages: +% 1. Geometrical precalculations: define edges and determine visibility +% between edges, planes, sources and receivers. +% 2. Find the valid sound paths and save a list of them +% 3. Go through the list and construct IRs +% +% This version, EDB1main, includes the option of dividing the +% calculations into batches. When there are many receivers, the geometrical +% precalculations might overload the available memory since all receivers +% are treated simulataneously for each source. +% +% Input parameters: +% EDsetupfile (optional) This file contains all parameter settings for the calculations. +% If no filename is given, a file open window will appear and the +% desired EDsetupfile can be chosen. +% The file could either be a .m file (the "EDsetupfile") +% or a .mat file (the "setupmatfile"). +% Input parameters in the EDsetupfile: +% FSAMP, CAIR, RHOAIR, SHOWTEXT +% (global) The sampling frequency, speed of sound, density of air +% and the control of how much text should +% be plotted (SHOWTEXT could be 0,1,2,3,4). +% SUPPRESSFILES (global, optional) If this variable is introduced in the +% setupfile as a global variable, with the value 1, then the files +% 'xxx_ISEStree.mat' will not be generated. Instead values are passed +% directly. +% Filepath The path to the folder where all output data files will be stored. +% Filestem The first part of the output data files will be given this name +% CADfile The name of the .CAD file where the geometry is given, including path +% open_or_closed_model Specifies whether the geometrical model is open or closed: +% 'o' Open model +% 'c' Closed model +% int_or_ext_model Specifies whether the geometrical model is interior or exterior: +% 'i' Interior model (NB! An interior model must be closed, +% otherwise it should be called an exterior model) +% 'e' Exterior model +% EDcalcmethod Specifies the edge diffraction method. Must have one of the following values: +% 'v' Vanderkooy +% 'n' Svensson et al +% 'k' Kirchhoff approximation NB! The Kirchhoff +% approximation gives only first-order diffraction. +% directsound 0 or 1 +% specorder The maximum order of specular reflections. (To get all possible combinations +% specorder and difforder should be given the same value). +% difforder The maximum order of diffraction components. (difforder can never be higher +% than specorder, i.e., if you want difforder = 2, you must set specorder to 2 or higher) +% elemsize A vector of size [1,difforder] which specifies the size of the edge subdivision +% for edge diffraction calculations. A value of 0.2 means that the edge elements +% are 5 times (1/0.2 =5) the wavelength at FSAMP. +% A higher value gives more accurate edge diffraction but is also more time consuming. +% Larger and larger elements could be employed for higher-order diffraction. +% Suggested values for high accuracy: elemsize = [1 0.5 0.25 0.125 ....]. +% nedgesubs All edges are subdivided very coarsely into edge segments, for visibility checks. +% The value of nedgesubs states how many such segments each edge will be divided into. +% The minimum value is 2. NB! All edges will be divided into equally many segments +% in order to employ efficient Matlab vector-based processing. +% sources A vector of the source coordinates, size [nsources,3], or source names/numbers +% size [nsources,1] or [nsources,2] (if they should be taken from the CADfile.) +% receivers A vector of the receiver coordinates or receiver numbers (if they should be taken +% from the CADfile. Same syntax as for sources. +% nSbatches,nRbatches +% (optional) An integer >= 1 which defines how many chunks the number of sources/receivers +% will be divided into. Default = 1. nSbatches/nRbatches = 1 means that all sources/receivers are +% treated simultaneously. nSbatches/nRbatches = 2 means that the list of sources/receivers +% is divided into two chunks etc. It is fastest with nSbatches/nRbatches = 1 but it also +% requires the largest amount of memory. (For large problems, there might even be no time +% penalty in choosing nRbatches = the number of receivers!) +% soulist_for_findpaths/reclist_for_findpaths +% (optional) A list of integers that specifies which of the sources/receivers that +% should be run for the "find paths" stage. Default = [1:nsources]/[1:nreceivers]. +% This is useful for huge problems where one might want to stop (with CTRL-C) and restart calculations. +% soulist_for_calcirs/reclist_for_calcirs +% (optional) A list of integers that specifies which of the sources/receivers that +% should be run for the "calc irs" stage. Default = [1:nsources]/[1:nreceivers]. +% This is useful for huge problems where one might want to stop (with CTRL-C) and restart calculations. +% firstskipcorner (optional) All edges including at least one corner with this number or +% higher will be excluded from the calculations. Default: 1e6 +% Rstart (optional) The distance that should correspond to the time zero for +% all IRs. Default = 0. NB! With Rstart = 0, all IRs will include the initial time +% delay that is caused by the propagation time from the source to the receiver. For +% long distances and high FSAMP, this can lead to many initial samples that are zero. +% If you know that all source-receiver combinations have a certain minimum +% distance, this minimum distance (or a value slightly below) can be given as Rstart. +% If Rstart is given a value which is smaller than the shortest distance encountered, +% an error will occur. +% +% Optional input parameters in the EDsetupfile: +% cadgeofile If this parameter is specified, this file will be read rather than the CADfile. +% Saves some time for big geometries. +% eddatafile If this parameter is specified, the function EDB1edgeo is not called. Saves +% some time. +% srdatafile If this parameter is specified, the function EDB1srgeo is not called. Saves +% some time. +% restartnumber If this parameter is specified, the calculations will start at receiver number +% restartnumber, rather than number 1. This is useful if a calculation for many +% receivers can not be completed in one run. +% stopnumber If this parameter is specified, the calculations will stop for receiver number +% stopnumber. +% saveindividualdiffirs A vector with two values, 0 or 1. +% If the first value is given the value 1, the diffraction +% IR will have one column for each order. Default is that +% all orders are summed into a single irdiff. +% If the second value is given the value 1, all individual diffraction irs +% will be saved on individual lines in a large matrix called 'alldiffirs'. +% This matrix has only single precision. +% Default value: [0 0] +% doaddsources 0 or 1, (default value 0) indicating whether: +% 0: every individual S-to-R IR should be saved +% 1: a single IR is saved for each R, which is +% constructed by first computing all individual +% S-to-R IRs, saving them in a temp file, and then +% add IRs from all sources together. This way a +% loudspeaker element can be simulated by a +% distribution of point sources. +% dobackscatter 0 or 1, (default value 0), indicating whether: +% 0: every individual S-to-R IR should be saved +% 1: only S1 to R1, S2 to R2, S3 to R3 combos +% are calculated. +% +% Output parameters: +% The following IRs are calculated and saved in the output file(s). Any of them can be +% excluded from the calculations by setting the parameters in the setup file. +% +% irtot the total impulse response +% irdirect the direct sound +% irgeom the purely geometrical acoustics components, i.e. specular reflections. +% irdiff the diffracted components. This will innclude all combinations of specular and +% diffraction, and first-order as well as higher-order combinations. +% +% Note that these variables, together with those in the EDsetupfile are saved in a results file +% which gets the name in Filestem (see below) + '_SS_RR_ir.mat' (if addsources = 0) or +% '_RR_ir.mat' (if addsources = 1). +% +% Note also that the impulse responses are scaled such that the direct sound gets an amplitude of +% 1/distance. This means that the impulse response represents a system with the sound pressure as +% output signal and an input signal = RHOAIR*Volumeacc(t)/(4*pi) where Volumeacc(t) is +% the volume acceleration of the monopole source. +% +% A logfile containing the computation time for the three stages is +% created, with the name Filestem + '_log.mat' +% +% Uses functions EDB1readcad EDB1readsetup EDB1edgeo +% EDB1Sgeo EDB1Rgeo EDB1findISEStree EDB1findpathsISES EDB1makeirs +% +% ---------------------------------------------------------------------------------------------- +% This file is part of the Edge Diffraction Toolbox by Peter Svensson. +% +% The Edge Diffraction Toolbox is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) any later version. +% +% The Edge Diffraction Toolbox is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +% FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License along with the +% Edge Diffraction Toolbox. If not, see <http://www.gnu.org/licenses/>. +% ---------------------------------------------------------------------------------------------- +% Peter Svensson (svensson@iet.ntnu.no) 20100211 +% +% EDB1main(EDsetupfile); + +global FSAMP CAIR RHOAIR SHOWTEXT JJ JJnumbofchars SUPPRESSFILES +global POTENTIALISES ISCOORDS IVNDIFFMATRIX +global IVNSPECMATRIX ORIGINSFROM ISESVISIBILITY REFLORDER + +global IRDIFFVEC + +FSAMP = []; CAIR = []; RHOAIR = []; SHOWTEXT = []; + +%-------------------------------------------------------------- +% First run the setup m file, just to get access to the CAD-file name +% so that the CAD-file can be converted into a cadgeofile. +% (This conversion must be done before the setup m-file is converted +% to a setup mat-file since the source and receiver coordinates should +% be specified in the setupmatfile, and the sources and receivers might +% have to be read from the CAD-file). +% +% First we make a little check of a common mistake: check if the paths +% seem to be for the correct computer type. +% The EDsetupfile-path does not need to be checked if a file window is +% presented. The CAD-file path always needs to be checked. + +% We check if the type of setupfile: +% .m setupfiletype = 1; +% .mat setupfiletype = 2; + +setupfiletype = 1; + +if nargin == 0 + [EDsetupfile,EDsetupfilepath] = uigetfile('*.m','Please select the EDsetupfile'); + [temp1,EDsetupfile,temp2] = fileparts([EDsetupfilepath,EDsetupfile]); + + EDsetupfile = [EDsetupfilepath,EDsetupfile]; + + if ~isstr(EDsetupfile) | isempty(EDsetupfile) + return + end +else + [EDsetupfilepath,tempfilestem,fileext] = fileparts(EDsetupfile); + EDsetupfilepath = [EDsetupfilepath,filesep]; + if length(fileext) == 4 + if fileext == '.mat' + setupfiletype = 2; + end + end +end + +eval(['cd ''',EDsetupfilepath,'''']) + +if setupfiletype == 1 + comptype = computer; + if length(comptype) == 3 + comptype = [comptype,'P']; + end + if comptype(1:4) == 'MACI', + [temp1,tempfilestem,temp2] = fileparts(EDsetupfile); + eval([tempfilestem]) + else + eval(['run ''',EDsetupfile,'''']) + end +else + eval(['load ''',EDsetupfile,'''']) +end + +if SHOWTEXT >= 1 + disp(' ') + disp('####################################################################') + disp('#') + disp('# EDB1mainISESx, version 11 February 2010') + disp('#') +end + +if SHOWTEXT >= 2 + disp('#') + disp('# This version does the following:') + disp('# * Caclulates impulse responses that include specular reflections up to any order and') + disp('# multiple diffraction up to order 6. Combinations are also taken into account, such as') + disp('# specular-diffraction-specular but higher-order diffractions must be') + disp('# in a single sequence, possibly with specular reflections before and after.') + disp('# There will be memory problems for higher-order specular reflections due to a') + disp('# memory-hungry vectorized version of the image source method.') + disp('# * Combinations with two diffractions that have specular reflections inbetween') + disp('# are handled, but not with any specular reflections after the last diffraction.') + disp('# * Partly visible edges are handled in first-order diffraction') + disp('# calculations. The accuracy depends on how high value of') + disp('# nedgesubs that is chosen. Edges that are split into two or more subedges are handled properly.') + disp('# * Specular reflections in the IR are handled by splitting a pulse between two consecutive time slots.') + disp('# This gives quite a severe low-pass filter roll-off, but zero phase-error.') + disp('# Choose a high over-sampling ratio to minimize this magnitude error.') + disp('# In addition, the low-pass filter effect can be avoided altogether for the direct sound by setting') + disp('# Rstart to exactly the source-receiver distance. Thereby the direct sound pulse will occur exactly in the') + disp('# first time sample. For more tweaking, the three values Rstart and CAIR and FSAMP should be possible') + disp('# to adjust so that one, two or three geometrical pulses arrive exactly at sample times.') + disp('# * An accurate integration technique is used for first-order diffraction so that receiver positions close') + disp('# to zone boundaries are handled without problem. Exactly at the zone boundary the specular reflection') + disp('# or direct sound gets half the amplitude (See below though).') + disp('#') + disp('# Limitations with this version:') + disp('# 1. Some, but not all, possible combinations where two or more diffracted') + disp('# reflections have specular reflections in-between are calculated. ') + disp('# This requires a bit of work to complete.') + disp('# 3. In-plane visibility of edges is only partly checked, i.e., if a plane has indents') + disp('# so that an edge can not see all other edges of its own plane.') + disp('# 4. Part-visibility of higher-order diffraction is not checked. These components are treated') + disp('# as fully visible or totally invisible. However, if the first or last edge in the') + disp('# sequence is partly visible, this will be used.') + disp('# 5. Non-rigid specular reflections or edge diffraction for non-rigid planes are not implemented. ') + disp('# Pressure-release surfaces would be quite easy to implement.') + disp('# Other surface impedances could be implemented since the hitpoints for all specular') + disp('# reflections are stored in the edpaths output file.') + disp('# 6. Other receivers than omnidirectional microphones are not implemented. HRTFs or directional microphones') + disp('# could be implemented since the hitpoints for all specular reflections are stored in the edpaths') + disp('# so the incidence angles are easy to calculate. Reflections that end with a diffraction need some') + disp('# more consideration.') + disp('# 7. The special cases where the receiver is exactly at a zone boundary is handled correctly only') + disp('# for first-order diffraction. This takes a bit of work to implement for higher-order diffraction.') + disp('# 8. Sources and receivers can not be place directly at a surface. They must be raised by 1 mm or so.') + disp('#') + disp('# This version could be made more efficient by:') + disp('# 1. Employing ray-tracing or beam-tracing for finding the visibility of') + disp('# plane to plane etc. Now, a simple plane-to-plane visibility check') + disp('# is performed: are planes in front of each other? The final visibility') + disp('# check is done for each image source to each receiver. An improved method would be more efficient') + disp('# for geometries with lots of indents and obscuring planes, e.g., as in a city') + disp('# geometry.') + disp('# 2. Developing an algorithm that calculates the diffraction IR in an iterative process') + disp('# instead of restarting for each new order of diffraction.') + disp('# 3. The direct sound visibility test could be done earlier (in EDB1SRgeo).') + disp('# 4. Calculation of Image Receiver coordinates could probably be made more efficiently.') + disp('#') +end + +if SHOWTEXT >= 1 + disp(' ') + disp([' Using the setupfile: ',EDsetupfile]) + disp(' ') +end + +% ######################################################################### +% +% Geometry pre-calculations +% +% ######################################################################### + +%--------------------------------------------------------------------------------------------- +% Convert the CAD-file into a mat file - or read the cadgeofile if it is specified + +t00 = clock; + +if SHOWTEXT >= 1 + disp(' ') + disp('####################################################################') + disp('#') + disp('# Geometry pre-calculations') + disp(' ') +end + +if exist('cadgeofile') ~= 1 + desiredname = [Filepath,Filestem,'_cadgeo']; + if SHOWTEXT >= 2 + disp([' Reading CAD-file: ',CADfile,' and converting it to a cadgeofile: ',desiredname]) + end + % Edited by APO: Added support for .ac files (only geometry) + [temp1,temp2,fileext] = fileparts(CADfile); + if(strcmp(fileext,'.ac')) + cadgeofile = EDB1readac(CADfile,desiredname); + else + cadgeofile = EDB1readcad(CADfile,desiredname); + end +else + if SHOWTEXT >= 2 + disp([' Using existing cadgeofile: ',cadgeofile]) + end +end + +%-------------------------------------------------------------- +% Convert the EDsetupfile into a setupmatfile. If sources and receivers should +% be read in the CADfile, add these to the setupmatfile. +% +% This is needed only if the setupfile was of type 1, that is, a .m file. + +if setupfiletype == 1 + setupmatfile = EDB1readsetup(EDsetupfile,cadgeofile); + + eval(['load ',setupmatfile]) +end + +tcadgeo = etime(clock,t00); + +%-------------------------------------------------------------- +% Derive the edge parameters. + +t00 = clock; + +if calcpaths == 1 + + if exist('eddatafile') ~= 1 + desiredfile = [Filepath,Filestem,'_eddata']; + if SHOWTEXT >= 2 + disp([' Calculating edges and creating an eddatafile: ',desiredfile]) + end + eddatafile = EDB1edgeox(cadgeofile,desiredfile,lower(open_or_closed_model(1)),lower(int_or_ext_model(1)),... + specorder,difforder,nedgesubs,firstskipcorner,planeseesplanestrategy); + else + if SHOWTEXT >= 2 + disp([' Using existing eddatafile: ',eddatafile]) + end + end +else + if exist('eddatafile') ~= 1 + desiredfile = [Filepath,Filestem,'_eddata']; + eddatafile = desiredfile; + else + if SHOWTEXT >= 2 + disp([' Using existing eddatafile: ',eddatafile]) + end + end +end + +tedgeo = etime(clock,t00); + +%-------------------------------------------------------------- +% If batches should be used, divide the list of receivers into batches. + +nsources = size(sources,1); +nreceivers = size(receivers,1); + +if nSbatches == 1 + doSbatches = 0; +elseif nSbatches > 1 + if nSbatches > nsources + error('ERROR: nSbatches can not be larger than the number of sources') + end + doSbatches = 1; + Sbatchlist = zeros(nSbatches,2); + nperbatch = ceil(nsources/nSbatches); + Sbatchlist(:,2) = [1:nSbatches].'*nperbatch; + Sbatchlist(:,1) = [0:nSbatches-1].'*nperbatch+1; + Sbatchlist(nSbatches,2) = nsources; + reftoSbatchlist = [1:nsources].'; + reftoSbatchlist = reftoSbatchlist(:,ones(1,nSbatches)); + compvec = Sbatchlist(:,1).'; + reftoSbatchlist = reftoSbatchlist >= compvec(ones(nsources,1),:); + reftoSbatchlist = sum(reftoSbatchlist.').'; +end + +if nRbatches == 1 + doRbatches = 0; +elseif nRbatches > 1 + if nRbatches > nreceivers + error('ERROR: nRbatches can not be larger than the number of receivers') + end + doRbatches = 1; + Rbatchlist = zeros(nRbatches,2); + nperbatch = ceil(nreceivers/nRbatches); + Rbatchlist(:,2) = [1:nRbatches].'*nperbatch; + Rbatchlist(:,1) = [0:nRbatches-1].'*nperbatch+1; + Rbatchlist(nRbatches,2) = nreceivers; + reftoRbatchlist = [1:nreceivers].'; + reftoRbatchlist = reftoRbatchlist(:,ones(1,nRbatches)); + compvec = Rbatchlist(:,1).'; + reftoRbatchlist = reftoRbatchlist >= compvec(ones(nreceivers,1),:); + reftoRbatchlist = sum(reftoRbatchlist.').'; +end + +%--------------------------------------------------------------------------------------------- +% Find out the S and R related parameters, make obstruction checks etc by calling +% EDB1Sgeo/EDB1Rgeo or load existing sdata/rdata files. + +t00 = clock; + +if calcpaths == 1 + if exist('sdatafile') ~= 1 + if doSbatches == 0 + desiredname = [Filepath,Filestem,'_sdata']; + if SHOWTEXT >= 2 + disp([' Calculating S parameters and creating an sdatafile: ',desiredname]) + end + + sdatafile = EDB1SorRgeo(eddatafile,desiredname,sources,'S',difforder,nedgesubs); + else + error(['ERROR: S-batches not implemented yet']) + for ii = 1:nSbatches + desiredname = [Filepath,Filestem,'_sdata']; + if SHOWTEXT >= 2 + disp([' Calculating S parameters and creating an sdatafile: ',desiredname,'_',int2str(ii)]) + end + sdatafile = EDB1SorRgeo(eddatafile,[desiredname,'_',int2str(ii)],sources(Sbatchlist(ii,1):Sbatchlist(ii,2),:),'S',difforder,nedgesubs); + sdatafile = desiredname; % To trim off the _1 or _2 or... + end + end + else + if SHOWTEXT >= 2 + disp([' Using existing sdatafile: ',sdatafile]) + end + end +else + if exist('sdatafile') ~= 1 + desiredname = [Filepath,Filestem,'_sdata']; + sdatafile = desiredname; + else + if SHOWTEXT >= 2 + disp([' Using existing sdatafile: ',sdatafile]) + end + end +end + +tsgeo = etime(clock,t00); + +%------------------------------------ +% We check that there is not a small geometrical mistake which makes the +% source be behind all planes - but only if the user has set SHOWTEXT. + +if SHOWTEXT >= 2 + eval(['load ',sdatafile]) + if size(visplanesfroms,2) == 1 + if ~any(visplanesfroms) + disp(' ') + disp('WARNING!!! The source(s) can not see a single plane!') + disp(' Check if this is correct! ') + disp(' A common cause is that the source is placed very close to a plane,') + disp(' but behind it. (CR => continue calculations)') + disp(' ') + pause + end + else + iv = find(sum(visplanesfroms) == 0); + if ~isempty(iv) + disp(' ') + disp('WARNING!!! Some of the source(s) can not see a single plane!') + disp(' These are the sources number:') + disp([' ',int2str(iv(:).')]) + disp(' Check if this is correct! ') + disp(' A common cause is that the source is placed very close to a plane,') + disp(' but behind it. (CR => continue calculations)') + disp(' ') + end + end +end + +t00 = clock; + +if calcpaths == 1 + if exist('rdatafile') ~= 1 + if doRbatches == 0 + desiredname = [Filepath,Filestem,'_rdata']; + if SHOWTEXT >= 2 + disp([' Calculating R parameters and creating an rdatafile: ',desiredname]) + end + rdatafile = EDB1SorRgeo(eddatafile,desiredname,receivers,'R',difforder,nedgesubs); + else + for ii = 1:nRbatches + desiredname = [Filepath,Filestem,'_rdata']; + if SHOWTEXT >= 2 + disp([' Calculating R parameters and creating an rdatafile: ',desiredname,'_',int2str(ii)]) + end + + rdatafile = EDB1SorRgeo(eddatafile,[desiredname,'_',int2str(ii)],receivers(Rbatchlist(ii,1):Rbatchlist(ii,2),:),'R',difforder,nedgesubs); + rdatafile = desiredname; % To trim off the _1 or _2 or... + end + end + else + if SHOWTEXT >= 2 + disp([' Using existing rdatafile: ',rdatafile]) + end + end +else + if exist('rdatafile') ~= 1 + desiredname = [Filepath,Filestem,'_rdata']; + rdatafile = desiredname; + else + if SHOWTEXT >= 2 + disp([' Using existing rdatafile: ',rdatafile]) + end + end +end + +trgeo = etime(clock,t00); + +%------------------------------------ +% We check that there is not a small geometrical mistake which makes the +% receiver(s) be behind all planes - but only if the user has set SHOWTEXT. + +if SHOWTEXT >= 2 + if exist('nRbatches') == 0 + nRbatches = 1; + end + if nRbatches == 1 + eval(['load ',rdatafile]) + else + [temp1,rdatafilestem,temp2] = fileparts(rdatafile); + for ii = 1:nRbatches + rdatafile = [rdatafilestem,'_',int2str(ii),'.mat']; + eval(['load ',rdatafile]) + if ii == 1 + allvisplanesfromr = visplanesfromr; + else + allvisplanesfromr = [allvisplanesfromr visplanesfromr]; + end + end + visplanesfromr = allvisplanesfromr; + clear allvisplanesfromr; + rdatafile = rdatafilestem; + + end + if size(visplanesfromr,2) == 1 + if ~any(visplanesfromr) + disp(' ') + disp('WARNING!!! The receiver can not see a single plane!') + disp(' Check if this is correct! ') + disp(' A common cause is that the receiver is placed very close to a plane,') + disp(' but behind it. (CR => continue calculations)') + disp(' ') + pause + end + else + iv = find(sum(visplanesfromr) == 0); + if ~isempty(iv) + disp(' ') + disp('WARNING!!! Some of the receiver(s) can not see a single plane!') + disp(' These are the receiver numbers:') + disp([' ',int2str(iv(:).')]) + disp(' Check if this is correct! ') + disp(' A common cause is that a receiver is placed very close to a plane,') + disp(' but behind it. (CR => continue calculations)') + disp(' ') + end + end +end + +%--------------------------------------------------------------------------------------------- +% The edgeseesedge test is run separately, for the cases where difforder >= 2. +% The data is stored in the eddata file again. + +if difforder >= 2 & calcpaths == 1 + if exist('eddata2file') ~= 1 + desiredfile = [Filepath,Filestem,'_eddata']; + if SHOWTEXT >= 2 + disp([' Adding edge-to-edge visibility to the eddatafile: ',eddatafile]) + end + if exist('ndiff2batches') ~= 1 + ndiff2batches = 1; + end + eddatafile = EDB1ed2geox(eddatafile,sdatafile,rdatafile,doSbatches,doRbatches,specorder,difforder,nedgesubs,ndiff2batches); + + else + if SHOWTEXT >= 2 + disp([' Using existing eddata2file: ',eddata2file]) + end + end + +end + + +%--------------------------------------------------------------------------------------------- +% Make a big loop running through the source and receiver coordinates. + +t00 = clock; + +eval(['load ',eddatafile]) +clear cornerinfrontofplane planeseesplane edgeseesplane + +[nplanes,slask] = size(planecorners); +[nedges,slask] = size(edgecorners); + +if exist('calcpaths')~=1 + calcpaths = 1; +end +if exist('calcirs')~=1 + calcirs = 1; +end + +% Display receiver numbers with an interval that depends on the +% value of SHOWTEXT. + +if SHOWTEXT == 1 + idisp = ceil(nreceivers/20); +elseif SHOWTEXT > 1 + idisp = 1; +end + +% We construct the string version of counters and let them be global +% variables so we don't have to call int2str all the time + +ncountersneeded = max(max([specorder difforder nplanes nedges])); +if ncountersneeded < 10 + JJ = setstr(32*ones(ncountersneeded,1)); +else + JJ = setstr(32*ones(ncountersneeded,2)); +end +for jj=1:ncountersneeded + jjstr = int2str(jj); + JJ(jj,1:length(jjstr)) = jjstr; +end +[n1,n2] = size(JJ); +JJnumbofchars = ones(n1,1); +if n1>9 + JJnumbofchars(10:n1) = JJnumbofchars(10:n1)+1; + if n1 > 99 + JJnumbofchars(100:n1) = JJnumbofchars(100:n1)+1; + if n1 > 999 + JJnumbofchars(1000:n1) = JJnumbofchars(1000:n1)+1; + end + end +end + +NSOU = int2str(nsources); +NREC = int2str(nreceivers); + +tsetup = etime(clock,t00); + +% ######################################################################### +% +% Find the paths +% +% ######################################################################### + +t00 = clock; +tISEStree = zeros(nsources,1); + +if calcpaths == 1 + + if SHOWTEXT >= 1 + disp(' ') + disp('####################################################################') + disp('#') + disp('# Finding the paths') + disp(' ') + end + + % Some variables that are needed for empty combinations + + pathtypevec = []; + reflpaths = []; + pathlengthvec = []; + specextradata = []; + edgeextradata = []; + mainlistguide = []; + Sinsideplanenumber = []; + Rinsideplanenumber = []; + mainlistguide = []; + mainlistguidepattern = []; + directsoundrow = []; + allspecrows = []; + firstdiffrow = []; + Varlist = [' pathtypevec reflpaths specextradata edgeextradata S R mainlistguide']; + Varlist = [Varlist,' Sinsideplanenumber Rinsideplanenumber mainlistguide mainlistguidepattern directsoundrow allspecrows firstdiffrow']; + + if doSbatches == 0 + eval(['load ',sdatafile]) + else + latestsdatafile = reftoSbatchlist(1); + [sdatafilepath,filestem,temp1] = fileparts(sdatafile); + eval(['load ',[sdatafilepath,filesep,filestem],'_',int2str(latestsdatafile),'.mat']) + end +% % % % We create a souinsideplane matrix from the visplanesfroms matrix +% % % % for use in EDB1makeirs + + if doRbatches == 0 + eval(['load ',rdatafile]) + else + latestrdatafile = reftoRbatchlist(1) + [rdatafilepath,filestem,temp1] = fileparts(rdatafile) + if ~isempty(rdatafilepath) + txtstr = ['load ',[rdatafilepath,filesep,filestem],'_',int2str(latestrdatafile),'.mat'] + else + txtstr = ['load ',[filestem],'_',int2str(latestrdatafile),'.mat'] + end + eval(txtstr) + end +% % % % We create a recinsideplane matrix from the visplanesfromr matrix +% % % % for use in EDB1makeirs + + for isou = soulist_for_findpaths + + t00_sou = clock; + ISOU = int2str(isou); + if SHOWTEXT >= 1 + disp(['Calculating for source ',ISOU,' (of ',NSOU,') ']) + end + if doSbatches == 1 + if latestsdatafile ~= reftoSbatchlist(isou) + latestsdatafile = reftoSbatchlist(isou); + [sdatafilepath,filestem,temp1] = fileparts(sdatafile); + eval(['load ',[sdatafilepath,filesep,filestem],'_',int2str(latestsdatafile),'.mat']) + end + Scolnumber = isou-Sbatchlist(reftoSbatchlist(isou),1)+1 + else + Scolnumber = isou; + end + S = sources(Scolnumber,:); + + % ########################################################### + % # + % # Calculate the ISES tree for each source + % # IS = image sources, for specular reflections + % # ES = edge sources, for edge diffraction + % # + % ########################################################### + + if exist('ISEStreefile') ~= 1 + if SHOWTEXT >= 2 + disp([' Calculating ISES tree']) + end + if difforder >= 1 + usedISEStreefile = EDB1findISEStree(eddatafile,S,isou,specorder,difforder,visplanesfroms(:,isou),vispartedgesfroms(:,isou),nedgesubs); + else + usedISEStreefile = EDB1findISEStree(eddatafile,S,isou,specorder,difforder,visplanesfroms(:,isou),[],nedgesubs); + end + + else + [ISEStreefilepath,filestem,temp1] = fileparts(ISEStreefile); + usedISEStreefile = [[ISEStreefilepath,filesep,filestem],'_',ISOU,'_ISEStree.mat;']; + if SHOWTEXT >= 2 + disp([' Using existing ISEStreefile: ',ISEStreefile,'_',ISOU,'_ISEStree.mat']) + end + end + if SUPPRESSFILES == 0 + eval(['load ',usedISEStreefile]) + else + POTENTIALISES = usedISEStreefile.POTENTIALISES; + ORIGINSFROM = usedISEStreefile.ORIGINSFROM; + ISCOORDS = usedISEStreefile.ISCOORDS; + ISESVISIBILITY = usedISEStreefile.ISESVISIBILITY; + IVNSPECMATRIX = usedISEStreefile. IVNSPECMATRIX; + lengthNspecmatrix = usedISEStreefile.lengthNspecmatrix; + IVNDIFFMATRIX = usedISEStreefile.IVNDIFFMATRIX; + lengthNdiffmatrix = usedISEStreefile.lengthNdiffmatrix; + singlediffcol = usedISEStreefile.singlediffcol; + REFLORDER = usedISEStreefile.REFLORDER; + startindicessinglediff = usedISEStreefile.startindicessinglediff; + endindicessinglediff = usedISEStreefile.endindicessinglediff; + ndecimaldivider = usedISEStreefile.ndecimaldivider; + PointertoIRcombs = usedISEStreefile.PointertoIRcombs; + IRoriginsfrom = usedISEStreefile.IRoriginsfrom; + end + tISEStree(isou) = etime(clock,t00_sou); + + if dobackscatter ~= 1, + reclist_in_forloop = reclist_for_findpaths; + else + reclist_in_forloop = isou; + end + + for irec = reclist_in_forloop + + % ########################################################### + % # + % # Find the valid paths for each source-receiver combination + % # _edpaths files are created + % # + % ########################################################### + + IREC = int2str(irec); + if SHOWTEXT >= 1 + if round(irec/idisp)*idisp==irec, + disp(['...receiver no. ',IREC,' (of ',NREC,')']) + end + end + if doRbatches == 1 + if latestrdatafile ~= reftoRbatchlist(irec) + latestrdatafile = reftoRbatchlist(irec); + [rdatafilepath,filestem,temp1] = fileparts(rdatafile); + if ~isempty(rdatafilepath) + txtstr = ['load ',[rdatafilepath,filesep,filestem],'_',int2str(latestrdatafile),'.mat']; + else + txtstr = ['load ',[filestem],'_',int2str(latestrdatafile),'.mat']; + end + eval(txtstr) + end + Rcolnumber = irec-Rbatchlist(reftoRbatchlist(irec),1)+1; + else + Rcolnumber = irec; + end + R = receivers(Rcolnumber,:); + + if exist('edpathsfile') ~= 1 + desirededpathsfile = [Filepath,Filestem,'_',ISOU,'_',IREC,'_edpaths.mat']; + if soutsidemodel(Scolnumber) == 0 & routsidemodel(Rcolnumber) == 0, + if difforder > 0 + usededpathsfile = EDB1findpathsISESx(eddatafile,lengthNspecmatrix,lengthNdiffmatrix,singlediffcol,startindicessinglediff,... + endindicessinglediff,ndecimaldivider,PointertoIRcombs,IRoriginsfrom,... + S,R,Scolnumber,Rcolnumber,directsound,specorder,difforder,... + nedgesubs,visplanesfroms(:,Scolnumber),visplanesfromr(:,Rcolnumber),... + vispartedgesfroms(:,Scolnumber),vispartedgesfromr(:,Rcolnumber),desirededpathsfile); + else + usededpathsfile = EDB1findpathsISESx(eddatafile,lengthNspecmatrix,[],[],[],... + [],[],[],[],S,R,Scolnumber,Rcolnumber,directsound,specorder,difforder,... + nedgesubs,visplanesfroms(:,Scolnumber),visplanesfromr(:,Rcolnumber),[],[],desirededpathsfile); + end + else + usededpathsfile = desirededpathsfile; + eval(['save ',usededpathsfile,Varlist]) + end + else + if SHOWTEXT >= 2 + disp([' Using existing edpathsfile: ',edpathsfile,'_',ISOU,'_',IREC,'_edpaths.mat']) + desirededpathsfile = [edpathsfile,'_',ISOU,'_',IREC,'_edpaths.mat']; + end + end + + + end % of the for isou = + + end % of the for irec = +end + +tfindpaths = etime(clock,t00); + +% ######################################################################### +% +% Edit paths +% +% ######################################################################### + +t00 = clock; + +if ~isempty(symmetricedgepairs) & exist('edpathsfile') == 1 + + disp(['WARNING: You specified symmetric edge pairs, but path pruning is not']) + disp([' allowed when you have specified an edpaths file']) + +end +if ~isempty(symmetricedgepairs) & exist('edpathsfile') ~= 1 + + if SHOWTEXT >= 1 + disp(' ') + disp('####################################################################') + disp('#') + disp('# Pruning paths: removing redundant (symmetric) diffraction combinations') + disp(' ') + end + + for isou = soulist_for_calcirs + ISOU = int2str(isou); + if SHOWTEXT >= 1 + disp(['Pruning paths for source ',ISOU,' (of ',NSOU,') ']) + end + + if dobackscatter ~= 1, + reclist_in_forloop = reclist_for_calcirs; + else + reclist_in_forloop = isou; + end + + for irec = reclist_in_forloop + IREC = int2str(irec); + if SHOWTEXT >= 1 + if round(irec/idisp)*idisp==irec, + disp(['...receiver ',IREC,' (of ',NREC,')']) + end + end + + edpathsfiletoedit = [Filepath,Filestem,'_',ISOU,'_',IREC,'_edpaths.mat']; + + EDB1editpathlist(edpathsfiletoedit,[],symmetricedgepairs,[]); + + end + end +end + +tprunepaths = etime(clock,t00); + +% ######################################################################### +% +% Construct IRs +% +% ######################################################################### + +t00 = clock; + +approxplanemidpoints = 0.5*(maxvals+minvals); + +if calcirs == 1 + + if SHOWTEXT >= 1 + disp(' ') + disp('####################################################################') + disp('#') + disp('# Constructing IRs') + disp(' ') + end + + % If the parameter guiderowstouse wasn't specified in the setup file + % we give it the default value. + + if exist('guiderowstouse') ~= 1 + guiderowstouse = []; + end + + % Some variables that are needed for empty combinations + irgeom = []; + irtot = []; + irdirect = []; + irdiff = []; + Varlist = [' irdirect irgeom irdiff irtot FSAMP Rstart CAIR elemsize nedgesubs']; + Varlistaccum = [' irdirectaccum irgeomaccum irdiffaccum irtotaccum FSAMP Rstart CAIR elemsize nedgesubs']; + + reclist_in_forloop = reclist_for_calcirs; + + for irec = reclist_in_forloop + IREC = int2str(irec); + if SHOWTEXT >= 1 + disp(['...receiver ',IREC,' (of ',NREC,')']) + end + + irdirectaccum = []; + irgeomaccum = []; + irtotaccum = []; + irdiffaccum = []; + + if dobackscatter == 1, + soulist_for_calcirs = irec; + end + + for isou = soulist_for_calcirs + ISOU = int2str(isou); + if SHOWTEXT >= 1 + if round(isou/idisp)*idisp==isou, + disp(['Constructing IRs for source ',ISOU,' (of ',NSOU,') ']) + end + end + + if doaddsources == 1 + desiredirfile = [Filepath,Filestem,'_',IREC,'_ir.mat']; + else + desiredirfile = [Filepath,Filestem,'_',ISOU,'_',IREC,'_ir.mat']; + end + + if exist('edpathsfile') ~= 1 + usededpathsfile = [Filepath,Filestem,'_',ISOU,'_',IREC,'_edpaths.mat']; + else + if SHOWTEXT >= 2 + if round(irec/idisp)*idisp==irec, + disp([' Using existing edpathsfile: ',edpathsfile,'_',ISOU,'_',IREC,'_edpaths.mat']) + end + end + usededpathsfile = [edpathsfile,'_',ISOU,'_',IREC,'_edpaths.mat']; + end + + if difforder >= 2 + + edirfile = EDB1makeirs(usededpathsfile,specorder,... + Rstart,EDcalcmethod,edgestartcoords,edgeendcoords,edgenvecs,... + edgelengthvec,planeeqs,approxplanemidpoints,reflfactors,closwedangvec,planesatedge,elemsize,... + reftoshortlistE,re1sho,re2sho,thetae1sho,thetae2sho,ze1sho,ze2sho,edgeseespartialedge,edgeplaneperptoplane1,desiredirfile,guiderowstouse,directsound,saveindividualdiffirs); + else + + edirfile = EDB1makeirs(usededpathsfile,specorder,... + Rstart,EDcalcmethod,edgestartcoords,edgeendcoords,edgenvecs,... + edgelengthvec,planeeqs,[],reflfactors,closwedangvec,planesatedge,elemsize,[],[],[],[],[],[],[],[],[],desiredirfile,guiderowstouse,directsound,saveindividualdiffirs); + + end + + if doaddsources == 1 + eval(['load ',edirfile]) + + nirnew = length(irtot); + nirold = length(irtotaccum); + if nirnew > nirold + irtotaccum = [irtotaccum;zeros(nirnew-nirold,1)]; + irdirectaccum = [irdirectaccum;zeros(nirnew-nirold,1)]; + irgeomaccum = [irgeomaccum;zeros(nirnew-nirold,1)]; + irdiffaccum = [irdiffaccum;zeros(nirnew-nirold,size(irdiff,2))]; + end + irtotaccum(1:nirnew) = irtotaccum(1:nirnew) + irtot; + irdirectaccum(1:nirnew) = irdirectaccum(1:nirnew) + irdirect; + irgeomaccum(1:nirnew) = irgeomaccum(1:nirnew) + irgeom; + irdiffaccum(1:nirnew,:) = irdiffaccum(1:nirnew,:) + irdiff; + end + + end % of the for isou = 1:nsou + + if doaddsources == 1 + eval(['save ',edirfile,Varlistaccum]) + end + + end % of the for irec = 1:nrec +end + +%-------------------------------------------------------- +% Save the timing data + +tmakeirs = etime(clock,t00); + +logfilename = [Filepath,Filestem,'_log.mat']; +Varlist = [' tcadgeo tedgeo tsgeo trgeo tsetup tISEStree tfindpaths tmakeirs tprunepaths nsources nreceivers']; +eval(['save ',logfilename,Varlist])
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/private/EDB1makeirs.m Sat Nov 16 18:25:24 2013 +0000 @@ -0,0 +1,1330 @@ +function edirfile = EDB1makeirs(edpathsfile,specorder,Rstart,... + EDcalcmethod,edgestartcoords,edgeendcoords,edgenvecs,... + edgelengthvec,planeeqs,approxplanemidpoints,reflfactors,closwedangvec,planesatedge,elemsize,reftoshortlistE,re1sho,re2sho,... + thetae1sho,thetae2sho,ze1sho,ze2sho,edgeseespartialedge,edgeplaneperptoplane1,desiredirfile,guiderowstouse,includedirectsound,... + saveindividualdiffirs) +% EDB1makeirs - Constructs impulse responses from a list of paths in a file. +% +% Input parameters: +% edpathsfile The name of the file containing the plane and edge data +% specorder The maximum order of reflections that is calculated. +% Rstart The reference distance that the time zero of the impulse +% response refers to. +% EDcalcmethod 'n' or 'v' or 'k', meaning: +% 'n': the new method by Svensson et al +% 'v': Vanderkooys method +% 'k': the Kirchhoff diffraction approximation +% edgestartcoords A matrix [nedges,3] of the startpoint coordinates +% of +% the edges. +% edgeendcoords A matrix [nedges,3] of the endpoint coordinates of +% the edges. +% edgenvecs A matrix [nedges,3] of the normal vectors of +% the reference plane of each edge. +% edgelengthvec A list [nedge,1] of the lenghts of each edge. +% planeeqs A matrix, [nplanes,4], of all the plane equations. +% approxplanemidpoints A matrix, [nplanes,3], of all plane midpoint +% coordinates. It may be an approximate location of +% the midpoint. +% reflfactors A list [nplanes,1] of the reflection factors of +% each plane. +% closwedangvec A list [nedge,1] of the close-wedge angle of each +% edge. +% planesatedge A matrix [nedge,2] of the two planes of each edge +% with the reference plane first. +% elemsize A list [1,difforder] with the relative edge element +% sizes that will be used for each order. The first +% value, for diffraction order 1, is redundant and +% not used. For higher orders, a value of, e.g., 0.5 +% means that edges will be subdivided into elements +% such that the wavelength at half the sampling +% frequency is 0.5 times the element size. A lower +% value gives faster but less accurate results. +% reftoshortlistE A matrix, [nedges,nedges] with a pointer to the +% short lists that contain edge-to-edge data. +% re1sho A short list, [nshort,1] of the cylindrical radii +% of each edge startpoint relative to all other +% edges. +% re2sho A short list, [nshort,1] of the cylindrical radii +% of each edge endpoint relative to all other +% edges. +% thetae1sho A short list, [nshort,1] of the theta angle +% of each edge startpoint relative to all other +% edges. +% thetae2sho A short list, [nshort,1] of the theta angle +% of each edge endpoint relative to all other +% edges. +% ze1sho A short list, [nshort,1] of the z-value +% of each edge startpoint relative to all other +% edges. +% ze2sho A short list, [nshort,1] of the z-value +% of each edge endpoint relative to all other +% edges. +% edgeseespartialedge A matrix, [nedges,nedges], with edge-to-edge +% visibility values. The values are 0 (invisible) +% up to (2^(nedgesubs)-1)^2 (full visibility). +% A pos. value indicates that the edge-to-edge path +% runs along a plane; a neg. avlue indicates that it +% does not run along a plane. +% edgeplaneperptoplane1 A matrix, [nplanes,nedges], with 0 or 1. A +% value 1 indicates that one of the edge's two +% defining planes is perpendicular to another plane. +% desiredirfile The file name that will be given to the +% output file. +% guiderowstouse (optional) A list of values, indicating which rows in the +% mainlistguide and mainlistguidepattern that should +% be used. This way it is possible to select only +% diffraction, for instance. If this list is not +% specified, all components will be used. +% includedirectsound (optional) 0 or 1, indicating whether the direct +% sound should be included or not. Default: 1 +% saveindividualdiffirs (optional) Vector of length 2 with values 0 or 1 +% Pos 1 indicating whether +% 0 - all orders of diffraction IR:s will be summed +% in a single vector 'irdiff', or +% 1 - each order of diffraction IR:s will be placed +% in individual columns in a matrix 'irdiff'. +% Pos 2 indicating whether +% 0 - only the total diffraction ir will be saved in the file. +% 1 - all individual diffraction irs will be saved in a large +% matrix alldiffirs. +% Default: [0 0]. +% FSAMP, CAIR, SHOWTEXT Global parameters. +% +% Output parameters: +% edirfile The filename used for the output file that contains +% the impulse responses. +% +% Data in the output file: +% irdirect The IR containing the direct sound, size [nirlength,1]. +% irgeom The IR containing the specular reflections, size [nirlength,1]. +% irdiff The IR containing the diffracted components, size [nirlength,1]. +% irtot The IR containing the sum of all components, size [nirlength,1]. +% alldiffirs (optional) Matrix with all individual first-order diffraction IRs +% on individual lines. +% alldiffirsextradata (optional) Vector with combination number (form reflpaths) that +% matches alldiffirs. +% FSAMP Rstart CAIR Same as the input parameters. +% +% Uses functions EDB1irfromslotlist EDB1calcdist EDB1coordtrans1 EDB1coordtrans2 +% EDB1wedge1st_int EDB1wedge2nd +% +% ---------------------------------------------------------------------------------------------- +% This file is part of the Edge Diffraction Toolbox by Peter Svensson. +% +% The Edge Diffraction Toolbox is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) any later version. +% +% The Edge Diffraction Toolbox is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +% FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License along with the +% Edge Diffraction Toolbox. If not, see <http://www.gnu.org/licenses/>. +% ---------------------------------------------------------------------------------------------- +% Peter Svensson (svensson@iet.ntnu.no) 20061208 +% +% edirfile = EDB1makeirs(edpathsfile,specorder,... +% Rstart,EDcalcmethod,edgestartcoords,edgeendcoords,edgenvecs,... +% edgelengthvec,planeeqs,approxplanemidpoints,reflfactors,closwedangvec,planesatedge,elemsize,reftoshortlistE,re1sho,re2sho,... +% thetae1sho,thetae2sho,ze1sho,ze2sho,edgeseespartialedge,edgeplaneperptoplane1,desiredirfile,guiderowstouse,includedirectsound,... +% saveindividualdiffirs); + +global SHOWTEXT FSAMP CAIR BIGEDGESTEPMATRIX + +global IRDIFFVEC + +eval(['load ',edpathsfile]) + +%-------------------------------------------------------------------------- +% We look for the optional vector multfactors in the edpathsfile. +% If it was there, then those values will be used to switch off, or boost +% any reflection path. +% Those values will only be used for diffraction paths. + +if exist('multfactors') == 0 + multfactors = ones(size(reflpaths,1),1); +else + if size(multfactors,1) ~= size(reflpaths,1) + error(['The edpaths file contained a vector multfactors which does not have the same length as reflpaths.']) + end +end + +%-------------------------------------------------------------------------- + +edirfile = desiredirfile; + +Sdirection = [1 0 0]; +maxnedgesorplanes = max(max(reflpaths)); +if ~isempty(maxnedgesorplanes) + multfac = 10^ceil(log10(double(maxnedgesorplanes)+1)); +else + multfac = 0; +end + +if nargin < 27 + saveindividualdiffirs = [0 0]; +end +if nargin < 26 + includedirectsound = 1; +end +if nargin < 25 + guiderowstouse = []; +end +if isempty(guiderowstouse) + usesubset = 0; + if SHOWTEXT > 2 + disp('Using all components') + end +else + usesubset = 1; + if SHOWTEXT > 2 + disp('Using only some components') + end +end + +nyvec = pi./(2*pi - closwedangvec); +onesvec1 = ones(1,3); + +souspecboost = 1; +if ~isempty(Sinsideplanenumber) + if reflfactors(Sinsideplanenumber(1)) ~= 0 + souspecboost = 2; + end +end + +recspecboost = 1; +if ~isempty(Rinsideplanenumber) + if reflfactors(Rinsideplanenumber(1)) ~= 0 + recspecboost = 2; + end +end + +if isempty(re1sho) + userwantsdiff2 = 0; +else + userwantsdiff2 = 1; +end + +%------------------------------------------------------- + +if exist('mainlistguide') ~= 1 + mainlistguide = []; +else + mainlistguide = double(mainlistguide); +end + +[ncomponents,ncols] = size(reflpaths); +[nrowsinlist,slask] = size(mainlistguide); +if ncols > 1 + difforderinlist = sum(mainlistguidepattern.'=='d').'; +else + difforderinlist = (mainlistguidepattern=='d'); +end + +lastNdiffrow = zeros(1,specorder); +for ii = 1:specorder + iv = find(difforderinlist <= ii ); + if ~isempty(iv) + lastNdiffrow(ii) = iv(end); + end +end + +nrefltogetherwdiff = sum(mainlistguidepattern.'=='d').'.*( sum(mainlistguidepattern.'=='s').'); + +if SHOWTEXT >= 3 + disp([' Constructing IR. ',int2str(ncomponents),' components.']) +end + +irdirect = [0 0].'; +irgeom = [0 0].'; +irdiff = [0 0].'; +irtot = [0 0].'; + +Varlist = [' irdirect irgeom irdiff irtot FSAMP Rstart CAIR EDcalcmethod']; + +if ncomponents == 0 + eval(['save ',edirfile,Varlist]) + return +end + +%############################################################################## +%############################################################################## +%############################################################################## +%############################################################################## +% +% Diffraction once, possibly with pre- and post-specular reflections +% +%############################################################################## + +directsoundonboundary = 0; +specreflonboundary = zeros(size(planeeqs,1),1); + +if firstdiffrow ~= 0 + + % First we remove the 'd' for all the rows in the mainlistguidepattern that + % we do not want to use. + + if usesubset == 1 + singdiffrows = find(difforderinlist==1); + rowstoclear = setdiff(singdiffrows,guiderowstouse); + if ~isempty(rowstoclear) + mainlistguidepattern(rowstoclear,:) = mainlistguidepattern(rowstoclear,:)*0; + end + end + + % Here we can use the single-diffraction calculation for all + % combinations. The source should either be the original source or + % an image source. The receiver should either be the original + % receiver or an image receiver. + + % First we create lists that specify whether there are specular + % reflections before the edge diffraction, and after the edge + % diffraction. Also, a list which gives the column where the edge + % diffraction is present can be used to efficiently extract the + % edge number. + % NB! The lists prespeclist, postspeclist and singdiffcol all have + % the (short) length of the mainlistguide. + % The data in these lists will then be used to create the long + % lists prespecpresent and postspecpresent which simply are 0 or 1. + % A matrix called edgemask will have the same number of columns as + % the reflpaths matrix. For each row, there will be a 1 in the + % column where the edge diffraction is so we can efficiently find + % the edge number. + + multmatrix = [1:specorder]; + if size(mainlistguidepattern,2) > specorder + multmatrix = [1:size(mainlistguidepattern,2)]; + end + multmatrix = multmatrix( ones(nrowsinlist,1),: ); + + if ncols > 1 + singdiffcol = sum( (multmatrix.*(mainlistguidepattern=='d')).' ).'; + singdiffcol = singdiffcol.*(sum(mainlistguidepattern.'=='d').'<=1); + nrefl = sum( (mainlistguidepattern=='s' | mainlistguidepattern=='d').' ).'; + else + singdiffcol = mainlistguidepattern=='d'; + nrefl = singdiffcol | mainlistguidepattern=='s'; + end + + prespeclist = singdiffcol-1; + prespeclist = prespeclist.*(prespeclist>0); + postspeclist = (nrefl-singdiffcol).*(singdiffcol~=0); + + prespecpresent = zeros(ncomponents,1); + postspecpresent = zeros(ncomponents,1); + edgemask = zeros(ncomponents,specorder); + + diffrowsthatareOK = [firstdiffrow:lastNdiffrow(1)]; + if usesubset == 1 + diffrowsthatareOK = intersect(diffrowsthatareOK,guiderowstouse); + end + for ii = diffrowsthatareOK, %firstdiffrow:lastNdiffrow(1) + iv = [(mainlistguide(ii,2)):(mainlistguide(ii,3))]; + onesvec2 = ones(length(iv),1); + edgemask(iv,singdiffcol(ii)) = onesvec2; + prespecpresent(iv) = (prespeclist(ii)>0)*onesvec2; + postspecpresent(iv) = (postspeclist(ii)>0)*onesvec2; + end + prespecpresent = prespecpresent(:,onesvec1); + postspecpresent = postspecpresent(:,onesvec1); + + if ncols > 1 + edgenumb = sum( (edgemask.*double(reflpaths(:,1:specorder))).').'; + else + edgenumb = edgemask.*double(reflpaths); + end + + nedgeirs = size(edgenumb,1); + nnonzeroedgeirs = sum(edgenumb(:,1)>0); + + ircounter = 0; + edgelist = unique(edgenumb); + for ii = 1: length(edgelist) + edge = edgelist(ii); + if edge~= 0 + iv = find(edgenumb==edge); + ncombs = length(iv); + + if ncombs > 0 & any(multfactors(iv)) + if SHOWTEXT >= 4 + disp([' Edge ',int2str(edge),': ',int2str(ncombs),' combinations']) + end + + onesvec3 = ones(ncombs,1); + + IS = full(specextradata(iv,1:3)); + IR = full(specextradata(iv,4:6)); + + edgestart = full(edgeextradata(iv,1)); + edgeend = full(edgeextradata(iv,2)); + + % Calculate the cyl coordinates of all IS + % + % Calculate the cyl coord of all IR + + edgecoords = [edgestartcoords(edge,:);edgeendcoords(edge,:)]; + [rs,thetas,zs,rr,thetar,zr] = EDB1coordtrans2(IS,IR,edgecoords,edgenvecs(edge,:)); + + bc = reflfactors(planesatedge(edge,:)).'; + if prod(double(bc==[1 1])) ~= 1 + disp(' Non-rigid wedge') + end + + for jj = 1:ncombs + if multfactors(iv(jj)) > 0 + if EDcalcmethod(1) == 'n' + + [irnew,slask,singularterm] = EDB1wedge1st_int(FSAMP,closwedangvec(edge),rs(jj),thetas(jj),zs(jj),rr(jj),thetar(jj),zr(jj),... + edgelengthvec(edge)*[edgestart(jj) edgeend(jj)],EDcalcmethod,Rstart,bc); + + if any(singularterm) + if singularterm(2) | singularterm(3) + directsoundonboundary = 1; + elseif singularterm(1) + if specorder == 1 + specreflonboundary(planesatedge(edge,2)) = 1; + else + disp('WARNING! A specular refl. of order > 1 is half obscured but this is not handled yet!'); + end + elseif singularterm(4) + if specorder == 1 + specreflonboundary(planesatedge(edge,1)) = 1; + else + disp('WARNING! A specular refl. of order > 1 is half obscured but this is not handled yet!'); + end + end + end + + else % ... if EDcalcmethod(1) == 'n' + + [irnew,slask,singularterm] = EDB1wedge1stcombo(FSAMP,closwedangvec(edge),rs(jj),thetas(jj),zs(jj),rr(jj),thetar(jj),zr(jj),... + edgelengthvec(edge)*[edgestart(jj) edgeend(jj)],EDcalcmethod,Rstart,bc); + + end % ... if EDcalcmethod(1) == 'n' + + % Decide whether the IR should be boosted or not + % + % The factors souspecboost and recspecboost have + % values other than 1 if the source or receiver is directly + % at a plane, for the boosting of the direct sound, and + % specular reflections. + % + % This boost factor should be used also for edge + % diffraction if: + % 1. There are some specular reflections between the + % source and the edge + % or + % 2. There are no specular reflections between the + % source and the edge, but the source/receiver is at + % a plane which does not belong to the edge. + + if souspecboost ~= 1 | recspecboost ~= 1 + + boostfactor = 1; + if prespecpresent(iv(jj)) == 1 + boostfactor = souspecboost; + else + if ~isempty(Sinsideplanenumber) + if Sinsideplanenumber(1)~=planesatedge(edge,1) & Sinsideplanenumber(1)~=planesatedge(edge,2), + boostfactor = souspecboost; + end + end + end + if postspecpresent(iv(jj)) == 1 + boostfactor = boostfactor*recspecboost; + else + if ~isempty(Rinsideplanenumber) + if Rinsideplanenumber(1)~=planesatedge(edge,1) & Rinsideplanenumber(1)~=planesatedge(edge,2), + boostfactor = boostfactor*recspecboost; + end + end + end + if boostfactor ~= 1 + irnew = irnew*boostfactor; + end + + end % .... if souspecboost ~= 1 | recspecboost ~= 1 + + ndiff = length(irdiff); + nnew = length(irnew); + + ircounter = ircounter + 1; + + if nnew > ndiff + irdiff = [irdiff;zeros(nnew-ndiff,1)]; + end + irdiff(1:nnew) = irdiff(1:nnew) + irnew*double(multfactors(iv(jj))); + + if saveindividualdiffirs(2) == 1 + if exist('alldiffirs','var') == 0 + alldiffirs = sparse(zeros(nnonzeroedgeirs,nnew)); + alldiffirs(1,:) = irnew*double(multfactors(iv(jj))).'; + alldiffirsextradata = zeros(nnonzeroedgeirs,1); + alldiffirsextradata(1) = iv(jj); + else + if nnew > ndiff + alldiffirs = [alldiffirs zeros(nnonzeroedgeirs,nnew-ndiff)]; + end + alldiffirs(ircounter,1:nnew) = irnew*double(multfactors(iv(jj))).'; + alldiffirsextradata(ircounter) = iv(jj); + end + + end + + + if SHOWTEXT >= 7 + figure(1) + plot(irnew) + figure(2) + plot(irdiff) + save ~/Documents/Temp/irdiff2.mat + pause + end + + end % ... if multfactors(iv) > 0 + + end % ..... for jj = 1:ncombs + + end %.... if ncombs > 0 & any(multfactors(iv)) + + end % .... if edge~= 0 + + end % .... for ii = 1: length(edgelist) + +end % ...if firstdiffrow ~= 0 + +nspecreflonboundary = sum(specreflonboundary); + +%############################################################################## +%############################################################################## +%############################################################################## +%############################################################################## +% +% The direct sound +% +%############################################################################## + +if usesubset == 1 & directsoundrow == 1 + if any(guiderowstouse == 1) == 0 + directsoundrow = 0; + end +end + +if directsoundrow == 1 & includedirectsound == 1 + dist = norm(R-S); + slotnumberfrac = (dist-Rstart)/CAIR*FSAMP+1; + amp = souspecboost*recspecboost./dist; + if directsoundonboundary + amp = amp/2; + if SHOWTEXT >= 4 + disp('HALVING DIRECT SOUND') + end + end + slotnumber = floor(slotnumberfrac); + if any(slotnumber<1) + error('ERROR: Rstart is set to too low a value!') + end + slotnumberfrac = slotnumberfrac - slotnumber; + irdirect = zeros( slotnumber+2,1 ); + + irdirect(slotnumber) = amp.*(1-slotnumberfrac) ; + irdirect(slotnumber+1) = amp.*slotnumberfrac; + + if ncomponents == 1 + nnew = length(irdirect); + if nnew > 2 + irdiff = [irdiff;zeros(nnew-2,1)]; + irtot = [irtot;zeros(nnew-2,1)]; + irgeom = [irgeom;zeros(nnew-2,1)]; + end + irtot(1:nnew) = irtot(1:nnew) + irdirect; + + irtot = sparse(irtot); + irgeom = sparse(irgeom); + irdirect = sparse(irdirect); + irdiff = sparse(irdiff); + + eval(['save ',edirfile,Varlist]) + return + end +else + if directsoundonboundary == 1 + + dist = norm(R-S); + slotnumberfrac = (dist-Rstart)/CAIR*FSAMP+1; + amp = souspecboost*recspecboost./dist; + if directsoundonboundary + amp = amp/2; + if SHOWTEXT >= 4 + disp('HALVING DIRECT SOUND') + end + end + slotnumber = floor(slotnumberfrac); + if any(slotnumber<1) + error('ERROR: Rstart is set to too low a value!') + end + slotnumberfrac = slotnumberfrac - slotnumber; + irdirect = zeros( slotnumber+2,1 ); + + irdirect(slotnumber) = amp.*(1-slotnumberfrac) ; + irdirect(slotnumber+1) = amp.*slotnumberfrac; + + end + if SHOWTEXT >= 4 + disp([' No direct sound']) + end +end + +%############################################################################## +%############################################################################## +%############################################################################## +%############################################################################## +% +% All-specular s, ss, sss, etc +% +%############################################################################## + +if allspecrows(1) ~= 0 + if usesubset == 1 + specrowsthatareOK = intersect(allspecrows,guiderowstouse); + else + specrowsthatareOK = [allspecrows(1):allspecrows(2)]; + end + if ~isempty(specrowsthatareOK) + if usesubset == 1 + temp = mainlistguide(specrowsthatareOK,2:3); + ivspec = [double(mainlistguide(specrowsthatareOK(1),2)):double(mainlistguide(specrowsthatareOK(1),3))]; + for ii = 2:size(temp,1); + ivspec = [ivspec [double(mainlistguide(specrowsthatareOK(ii),2)):double(mainlistguide(specrowsthatareOK(ii),3))]]; + end + else + ivspec = [mainlistguide(allspecrows(1),2):mainlistguide(allspecrows(2),3)]; + end + + if nspecreflonboundary > 0 + listofspecreflonboundary = find(specreflonboundary); + specrefltoadd = setdiff(listofspecreflonboundary,ivspec) + if ~isempty(specrefltoadd) + error(['ERROR: We need to add some code here, to reinsert pruned spec. refl.']) + end + end + + if SHOWTEXT >= 4 + disp([' ',int2str(length(ivspec)),' specular reflections']) + end + + dist = EDB1calcdist(full(specextradata(ivspec,1:3)),R); + + if nspecreflonboundary > 0 + specamp = ones(size(souspecboost)); + amplitudeshouldbehalf = ismember(reflpaths(ivspec,1),listofspecreflonboundary); + specamp = specamp - amplitudeshouldbehalf*0.5; + irnew = specamp*souspecboost*recspecboost*EDB1irfromslotlist((dist-Rstart)/CAIR*FSAMP+1,1./dist); + else + irnew = souspecboost*recspecboost*EDB1irfromslotlist((dist-Rstart)/CAIR*FSAMP+1,1./dist); + end + ngeom = length(irgeom); + nnew = length(irnew); + if nnew > ngeom + irgeom = [irgeom;zeros(nnew-ngeom,1)]; + end + irgeom(1:nnew) = irgeom(1:nnew) + irnew; + + else + if nspecreflonboundary > 0 + listofspecreflonboundary = find(specreflonboundary); + error(['ERROR: We need to add some code here, to reinsert pruned spec. refl., pos. 2']) + end + end +else + if nspecreflonboundary > 0 + listofspecreflonboundary = find(specreflonboundary); + + [xis] = EDB1findis(S,listofspecreflonboundary,planeeqs,1,[1 1 1]); + + disp(['WARNING: We have some new code here, to reinsert pruned spec. refl., pos. 3']) + dist = EDB1calcdist(xis,R); + irnew = 0.5*souspecboost*recspecboost*EDB1irfromslotlist((dist-Rstart)/CAIR*FSAMP+1,1./dist); + ngeom = length(irgeom); + nnew = length(irnew); + if nnew > ngeom + irgeom = [irgeom;zeros(nnew-ngeom,1)]; + end + irgeom(1:nnew) = irgeom(1:nnew) + irnew; + + end +end + +%############################################################################## +%############################################################################## +%############################################################################## +%############################################################################## +% +% Multiple diffraction, possibly with pre- and post-specular reflections +% +%############################################################################## + +if userwantsdiff2 == 1 + + JJ = setstr(32*ones(specorder,1)); + for jj=1:specorder + jjstr = int2str(jj); + JJ(jj,1:length(jjstr)) = jjstr; + end + [n1,n2] = size(JJ); + + + for Ndifforder = 2:specorder + if SHOWTEXT >= 3 + disp([' Diffraction order ',int2str(Ndifforder)]) + end + + if any(difforderinlist==Ndifforder) & elemsize(Ndifforder) > 0 + + % Calculate some general parameters that are shared for all + % N-diffraction calculations + + divmin = CAIR/(FSAMP*elemsize(Ndifforder)); + ndivvec = ceil(abs( edgelengthvec.' )/divmin); + dzvec = (edgelengthvec.')./ndivvec; + + ncylrows = 4*(Ndifforder-1); + + % Here we can use the double-diffraction calculation for all + % combinations. The source should either be the original source or + % an image source. The receiver should either be the original + % receiver or an image receiver. + + noffset = lastNdiffrow(Ndifforder-1); + ivNdiff = [noffset+1:lastNdiffrow(Ndifforder)]; + ndiffcombs = length(ivNdiff); + zerosvec1 = zeros(ndiffcombs,1); + + ndoubrows = length(ivNdiff); + previousrow = lastNdiffrow(Ndifforder-1); + if previousrow > 0 + noffsetlonglist = mainlistguide(previousrow,3); + else + noffsetlonglist = 0; + end + nremaining = ncomponents - (mainlistguide(lastNdiffrow(Ndifforder),3)); + nlonglist = ncomponents-noffsetlonglist-nremaining; + ivlonglist = [mainlistguide(ivNdiff(1),2):mainlistguide(ivNdiff(end),3)].'; + + diffcols = zerosvec1(:,ones(1,Ndifforder)); + for ii = ivNdiff(1):ivNdiff(end) + diffcols(ii-ivNdiff(1)+1,:) = find(mainlistguidepattern(ii,:)=='d'); + end + + nreflorder = sum( (mainlistguidepattern(ivNdiff(1):ivNdiff(end),:)=='d'|mainlistguidepattern(ivNdiff(1):ivNdiff(end),:)=='s').').'; + nprespecs = diffcols(:,1)-1; + nmidspecs = diffcols(:,2)-diffcols(:,1)-1; + npostspecs = nreflorder-diffcols(:,Ndifforder); + + if ndiffcombs > 1 + ivreftolonglist = ivlonglist(:,ones(1,ndiffcombs)); + comppattern = mainlistguide(ivNdiff,2).'; + comppattern = comppattern(ones(nlonglist,1),:); + + rowinpatternlist = sum( (ivreftolonglist>=comppattern).' ).'; + else + rowinpatternlist = ones(size(ivlonglist)); + end + + % Construct a long matrix with the edge numbers extracted from the + % reflpaths matrix. + + longnmidspec = zeros(nlonglist,1); + iv = find(nmidspecs>0); + for ii = 1:length(iv) + ivreftolonglist = [mainlistguide(ivNdiff(iv(ii)),2):mainlistguide(ivNdiff(iv(ii)),3)] - noffsetlonglist; + longnmidspec(ivreftolonglist) = nmidspecs(iv(ii)); + end + + %------------------------------------------------------------------ + % edgepattern will be a matrix which, for each reflection combination, contains + % the 2,3,4,... edge numbers that are involved in each path + % regardless of there are specular reflections before, in the + % middle, or after. + + edgepattern = zeros(nlonglist,Ndifforder); + countvec = [1:nlonglist].'; + reflpathscut = reflpaths(ivlonglist,:); + for ii = 1:Ndifforder + ivrefcol = countvec + (diffcols(rowinpatternlist,ii)-1)*nlonglist; + edgepattern(:,ii) = reflpathscut(ivrefcol); + end + + %------------------------------------------------------------------ + % midspecpattern will be a matrix which, for each reflection combination, contains + % the 1,2,3,4,... specular reflection numbers (i.e., plane numbers) that are involved + % in each path between diffraction 1 and diffraction 2. + % First, the reflection component immediately after diffraction 1 + % is selected for every reflection. Then there is a masking which + % zeroes the midspecpattern value for all the combinations that + % don't have any midspec. + % NB! For combinations like ssssdd, the first step will point to a + % column which is outside the matrix. This is fixed by maximizing + % the column number. + + midspecpattern = zeros(nlonglist,max([specorder-Ndifforder 1])); + maxpointvalue = nlonglist*max([specorder-Ndifforder 1]); + for ii = 1:specorder-Ndifforder + ivrefcol = countvec + (diffcols(rowinpatternlist,1)+(ii-1))*nlonglist; + ivrefcol = mod(ivrefcol-1,maxpointvalue)+1; + midspecpattern(:,ii) = double(reflpathscut(ivrefcol)).*(longnmidspec>=ii); + end + diff1col = diffcols(rowinpatternlist,1); + + % Many combinations include the same edge-pair/N-let, so we extract the + % unique edge pairs/N-lets, and go through them in the ii-loop + + [edgeshortlist,ivec,jvec] = unique(edgepattern,'rows'); + lastndivcomb = zeros(1,Ndifforder); + + for ii = 1: length(ivec) + + if SHOWTEXT >= 3 + if round(ii/ceil(length(ivec)/10))*ceil(length(ivec)/10) == ii + disp([' Combination no. ',int2str(ii),' of ',int2str(length(ivec))]) + end + end + + iv = find(jvec==ii); + ncombs = length(iv); + onesvec3 = ones(ncombs,1); + + if SHOWTEXT >= 4 + numvec = int2str(edgeshortlist(ii,1)); + for ll = 2:Ndifforder + numvec = [numvec,' ', int2str(edgeshortlist(ii,ll))]; + end + disp([' Edges ',numvec]) + + end + + if Ndifforder >= 2 & any(multfactors(ivlonglist(iv))) + + newndivvec = ndivvec(edgeshortlist(ii,:)); + + if any(lastndivcomb~=newndivvec) + if Ndifforder == 2 + ivmatrix = EDB1creindexmatrix(newndivvec); + else + ivmatrix = EDB1creindexmatrix(newndivvec(2:end)); + end + [nedgeelcombs,slask] = size(ivmatrix); + if Ndifforder == 2 + BIGEDGESTEPMATRIX = (double(ivmatrix)-0.5)./newndivvec(uint8(ones(nedgeelcombs,1)),:); + else + BIGEDGESTEPMATRIX = (double(ivmatrix)-0.5)./newndivvec(uint8(ones(nedgeelcombs,1)),2:end); + end + clear ivmatrix + lastndivcomb = newndivvec; + + end + end + + pathalongplane = (edgeseespartialedge(edgeshortlist(ii,2),edgeshortlist(ii,1))>0); + for jj = 3:Ndifforder + pathalongplane = [pathalongplane,(edgeseespartialedge(edgeshortlist(ii,jj),edgeshortlist(ii,jj-1))>0)]; + end + + if any(multfactors(ivlonglist(iv))) + + IS = full(specextradata(ivlonglist(iv),1:3)); + IR = full(specextradata(ivlonglist(iv),4:6)); + + firstedgestart = full(edgeextradata(ivlonglist(iv),1)); + firstedgeend = full(edgeextradata(ivlonglist(iv),2)); + + lastedgestart = full(edgeextradata(ivlonglist(iv),3)); + lastedgeend = full(edgeextradata(ivlonglist(iv),4)); + + % Calculate the cyl coordinates of all IS/S and IR/R + + cylS = zeros(ncombs,3); + edgecoords = [edgestartcoords(edgeshortlist(ii,1),:);edgeendcoords(edgeshortlist(ii,1),:)]; + [cylS(:,1),cylS(:,2),cylS(:,3)] = EDB1coordtrans1(IS,edgecoords,edgenvecs(edgeshortlist(ii,1),:)); + + cylR = zeros(ncombs,3); + edgecoords = [edgestartcoords(edgeshortlist(ii,Ndifforder),:);edgeendcoords(edgeshortlist(ii,Ndifforder),:)]; + [cylR(:,1),cylR(:,2),cylR(:,3)] = EDB1coordtrans1(IR,edgecoords,edgenvecs(edgeshortlist(ii,Ndifforder),:)); + + bc = ones(Ndifforder,2); % Check real reflfactors!!! + bc = reshape(bc.',2*Ndifforder,1); + + % Pick out the edge-to-edge coordinates for this specific + % edge pair/N-let. + + if ~isempty(reftoshortlistE), + if Ndifforder >= 2 + index1 = reftoshortlistE(edgeshortlist(ii,2),edgeshortlist(ii,1)); + cylE2_r1 = [re1sho(index1,:) thetae1sho(index1,:) ze1sho(index1,:);re2sho(index1,:) thetae2sho(index1,:) ze2sho(index1,:)]; + index2 = reftoshortlistE(edgeshortlist(ii,1),edgeshortlist(ii,2)); + cylE1_r2 = [re1sho(index2,:) thetae1sho(index2,:) ze1sho(index2,:);re2sho(index2,:) thetae2sho(index2,:) ze2sho(index2,:)]; + end + if Ndifforder >= 3 + index1 = reftoshortlistE(edgeshortlist(ii,3),edgeshortlist(ii,2)); + cylE3_r2 = [re1sho(index1,:) thetae1sho(index1,:) ze1sho(index1,:);re2sho(index1,:) thetae2sho(index1,:) ze2sho(index1,:)]; + index2 = reftoshortlistE(edgeshortlist(ii,2),edgeshortlist(ii,3)); + cylE2_r3 = [re1sho(index2,:) thetae1sho(index2,:) ze1sho(index2,:);re2sho(index2,:) thetae2sho(index2,:) ze2sho(index2,:)]; + end + if Ndifforder >= 4 + index1 = reftoshortlistE(edgeshortlist(ii,4),edgeshortlist(ii,3)); + cylE4_r3 = [re1sho(index1,:) thetae1sho(index1,:) ze1sho(index1,:);re2sho(index1,:) thetae2sho(index1,:) ze2sho(index1,:)]; + index2 = reftoshortlistE(edgeshortlist(ii,3),edgeshortlist(ii,4)); + cylE3_r4 = [re1sho(index2,:) thetae1sho(index2,:) ze1sho(index2,:);re2sho(index2,:) thetae2sho(index2,:) ze2sho(index2,:)]; + end + if Ndifforder >= 5 + index1 = reftoshortlistE(edgeshortlist(ii,5),edgeshortlist(ii,4)); + cylE5_r4 = [re1sho(index1,:) thetae1sho(index1,:) ze1sho(index1,:);re2sho(index1,:) thetae2sho(index1,:) ze2sho(index1,:)]; + index2 = reftoshortlistE(edgeshortlist(ii,4),edgeshortlist(ii,5)); + cylE4_r5 = [re1sho(index2,:) thetae1sho(index2,:) ze1sho(index2,:);re2sho(index2,:) thetae2sho(index2,:) ze2sho(index2,:)]; + end + if Ndifforder >= 6 + index1 = reftoshortlistE(edgeshortlist(ii,6),edgeshortlist(ii,5)); + cylE6_r5 = [re1sho(index1,:) thetae1sho(index1,:) ze1sho(index1,:);re2sho(index1,:) thetae2sho(index1,:) ze2sho(index1,:)]; + index2 = reftoshortlistE(edgeshortlist(ii,5),edgeshortlist(ii,6)); + cylE5_r6 = [re1sho(index2,:) thetae1sho(index2,:) ze1sho(index2,:);re2sho(index2,:) thetae2sho(index2,:) ze2sho(index2,:)]; + end + if Ndifforder >= 7 + index1 = reftoshortlistE(edgeshortlist(ii,7),edgeshortlist(ii,6)); + cylE7_r6 = [re1sho(index1,:) thetae1sho(index1,:) ze1sho(index1,:);re2sho(index1,:) thetae2sho(index1,:) ze2sho(index1,:)]; + index2 = reftoshortlistE(edgeshortlist(ii,6),edgeshortlist(ii,7)); + cylE6_r7 = [re1sho(index2,:) thetae1sho(index2,:) ze1sho(index2,:);re2sho(index2,:) thetae2sho(index2,:) ze2sho(index2,:)]; + end + if Ndifforder >= 8 + index1 = reftoshortlistE(edgeshortlist(ii,8),edgeshortlist(ii,7)); + cylE8_r7 = [re1sho(index1,:) thetae1sho(index1,:) ze1sho(index1,:);re2sho(index1,:) thetae2sho(index1,:) ze2sho(index1,:)]; + index2 = reftoshortlistE(edgeshortlist(ii,7),edgeshortlist(ii,8)); + cylE7_r8 = [re1sho(index2,:) thetae1sho(index2,:) ze1sho(index2,:);re2sho(index2,:) thetae2sho(index2,:) ze2sho(index2,:)]; + end + + else + error('STRANGE TO END UP HERE??') + if Ndifforder == 2 + cylE1_r2 = [0 0 edgelengthvec(edgeshortlist(ii,jj));0 0 edgelengthvec(edgeshortlist(ii,jj))]; + cylE2_r1 = [0 0 edgelengthvec(edgeshortlist(ii,jj));0 0 edgelengthvec(edgeshortlist(ii,jj))]; + else + error(['ERROR: Geometries with a single edge can not handle difforder >= 3']) + end + end + + for jj = 1:ncombs + + if multfactors(ivlonglist(iv(jj))) + + if Ndifforder == 2 + + cylE1_r2frac = cylE1_r2; + e1length = edgelengthvec(edgeshortlist(ii,1)); + cylE2_r1frac = cylE2_r1; + e2length = edgelengthvec(edgeshortlist(ii,2)); + + if firstedgestart(jj) ~= 0 + cylE1_r2frac(1,3) = cylE1_r2frac(1,3) + e1length*firstedgestart(jj); + end + if firstedgeend(jj) ~= 1 + cylE1_r2frac(2,3) = cylE1_r2frac(1,3) + e1length*(1-firstedgeend(jj)); + end + if lastedgestart(jj) ~= 0 + cylE2_r1frac(1,3) = cylE2_r1frac(1,3) + e2length*lastedgestart(jj); + end + if lastedgeend(jj) ~= 1 + cylE2_r1frac(2,3) = cylE2_r1frac(1,3)+ e2length*(1-lastedgeend(jj)); + end + + if midspecpattern(iv(jj))~=0 + + % For the cases with specular reflections + % in-between a double diffraction we must + % mirror the two edges to calculate the + % relative-to-edge cylindrical coordinates. + + nspec = sum(midspecpattern(iv(jj),:)>0); + + % Mirror edge 2 in all the specular reflection + % planes, in reversed order + edgestartmirr = edgestartcoords(edgeshortlist(ii,2),:); + edgeendmirr = edgeendcoords(edgeshortlist(ii,2),:); + edgevector = edgeendmirr - edgestartmirr; + if lastedgestart(jj) ~= 0 + edgestartmirr = edgestartmirr + edgevector*lastedgestart(jj); + else + edgestartmirr = edgestartmirr + edgevector*1e-6; + end + if lastedgeend(jj) ~= 1 + edgeendmirr = edgestartmirr + edgevector*(1-lastedgeend(jj)); + else + edgeendmirr = edgestartmirr + edgevector*(1-1e-6); + end + edgerefcoords = [edgestartcoords(edgeshortlist(ii,1),:);edgeendcoords(edgeshortlist(ii,1),:)]; + edgerefnvec = edgenvecs(edgeshortlist(ii,1),:); + + % If we have a specular reflection in a plane + % which is perpendicular to the edge plane, we + % should nudge the mirrored edge out a bit so + % that there is no 0/(2*pi) mistake + if nspec == 1 & ( edgeplaneperptoplane1(midspecpattern(iv(jj),1),edgeshortlist(ii,1)) | edgeplaneperptoplane1(midspecpattern(iv(jj),1),edgeshortlist(ii,2)) ) + vectowardsmidpoint = approxplanemidpoints(midspecpattern(iv(jj),1),:) - edgestartmirr; + edgestartmirr = edgestartmirr + vectowardsmidpoint*1e-10; + vectowardsmidpoint = approxplanemidpoints(midspecpattern(iv(jj),1),:) - edgeendmirr; + edgeendmirr = edgeendmirr + vectowardsmidpoint*1e-10; + end + xis = [edgestartmirr;edgeendmirr]; + for kk = nspec:-1:1 + xis = EDB1findis(xis,[midspecpattern(iv(jj),kk);midspecpattern(iv(jj),kk)],planeeqs,2,onesvec1); + end + [rstart,thetastart,zstart,rend,thetaend,zend] = EDB1coordtrans2(xis(1,:),xis(2,:),edgerefcoords,edgerefnvec); + cylE2mirr_r1 = [rstart thetastart zstart;rend thetaend zend]; + + % Mirror edge 1 in all the specular reflection + % planes, in forward order + edgestartmirr = edgestartcoords(edgeshortlist(ii,1),:); + edgeendmirr = edgeendcoords(edgeshortlist(ii,1),:); + edgevector = edgeendmirr - edgestartmirr; + if firstedgestart(jj) ~= 0 + edgestartmirr = edgestartmirr + edgevector*firstedgestart(jj); + else + edgestartmirr = edgestartmirr + edgevector*1e-6; + end + if firstedgeend(jj) ~= 1 + edgeendmirr = edgestartmirr + edgevector*(1-firstedgeend(jj)); + else + edgeendmirr = edgestartmirr + edgevector*(1-1e-6); + end + edgerefcoords = [edgestartcoords(edgeshortlist(ii,2),:);edgeendcoords(edgeshortlist(ii,2),:)]; + edgerefnvec = edgenvecs(edgeshortlist(ii,2),:); + + % Normally, when there is a specular reflection + % in-between, the diffraction path will not be + % along a plane, unless: + % 1. The same edge is involved twice, with a + % reflection in a perpendicular plane + % in-between. + % 2. See below + pathalongplanewmidspec = 0; + if edgeshortlist(ii,1) == edgeshortlist(ii,2) + if thetastart == 0 | thetastart == (2*pi-closwedangvec(edgeshortlist(ii,2))) + pathalongplanewmidspec = 1; + end + end + + % If we have a specular reflection in a plane + % which is perpendicular to the edge plane, we + % should nudge the mirrored edge out a bit so + % that there is no 0/(2*pi) mistake + % + % We also have case 2 here (see above) for when + % we could have a pathalongplanewmidspec + % 2. When two different edges have a perpendicular reflection + % in-between + + if nspec == 1 & ( edgeplaneperptoplane1(midspecpattern(iv(jj),1),edgeshortlist(ii,1)) | edgeplaneperptoplane1(midspecpattern(iv(jj),1),edgeshortlist(ii,2)) ) + vectowardsmidpoint = approxplanemidpoints(midspecpattern(iv(jj),1),:) - edgestartmirr; + edgestartmirr = edgestartmirr + vectowardsmidpoint*1e-10; + vectowardsmidpoint = approxplanemidpoints(midspecpattern(iv(jj),1),:) - edgeendmirr; + edgeendmirr = edgeendmirr + vectowardsmidpoint*1e-10; + pathalongplanewmidspec = 1; + end + xis = [edgestartmirr;edgeendmirr]; + for kk = 1:nspec + xis = EDB1findis(xis,[midspecpattern(iv(jj),kk);midspecpattern(iv(jj),kk)],planeeqs,2,onesvec1); + end + [rstart,thetastart,zstart,rend,thetaend,zend] = EDB1coordtrans2(xis(1,:),xis(2,:),edgerefcoords,edgerefnvec); + cylE1mirr_r2 = [rstart thetastart zstart;rend thetaend zend]; + + [irnew,slask] = EDB1wedge2nd(cylS(jj,:),cylR(jj,:),cylE2mirr_r1,cylE1mirr_r2,... + nyvec(edgeshortlist(ii,:)),[edgelengthvec(edgeshortlist(ii,1))*[firstedgestart(jj) firstedgeend(jj)];edgelengthvec(edgeshortlist(ii,2))*[lastedgestart(jj) lastedgeend(jj)]],dzvec(edgeshortlist(ii,:)),... + EDcalcmethod,pathalongplanewmidspec,Rstart,bc,CAIR,FSAMP); + + else % .... if midspecpattern(iv(jj))~=0 + + [irnew,slask] = EDB1wedge2nd(cylS(jj,:),cylR(jj,:),cylE2_r1frac,cylE1_r2frac,... + nyvec(edgeshortlist(ii,:)),[edgelengthvec(edgeshortlist(ii,1))*[firstedgestart(jj) firstedgeend(jj)];edgelengthvec(edgeshortlist(ii,2))*[lastedgestart(jj) lastedgeend(jj)]],dzvec(edgeshortlist(ii,:)),... + EDcalcmethod,pathalongplane,Rstart,bc,CAIR,FSAMP); + end % .... if midspecpattern(iv(jj))~=0 + + if SHOWTEXT >= 6 + figure(1) + plot(irnew) + figure(2) + plot(irdiff) + pause + end + IRDIFFVEC = [IRDIFFVEC;sum(irnew)]; + + elseif Ndifforder == 3, % if Ndifforder == 2 + + for kk = 1:newndivvec(1) + if SHOWTEXT >= 5 + disp([' ',int2str(kk),' of ',int2str(newndivvec(1))]) + end + BIGEDGE1stvalue = (kk-0.5)./newndivvec(1); + wedgeparams = [cylE2_r1;cylE1_r2;cylE3_r2;cylE2_r3]; + + [irnewpartition,slask] = EDB1wedgeN(cylS(jj,:),cylR(jj,:),wedgeparams,ncylrows,... + nyvec(edgeshortlist(ii,:)),edgelengthvec(edgeshortlist(ii,:)).',... + dzvec(edgeshortlist(ii,:)),EDcalcmethod,pathalongplane,nedgeelcombs,Rstart,bc,CAIR,FSAMP,BIGEDGE1stvalue); + irnewpartition = real(irnewpartition); + + if kk == 1 + irnew = irnewpartition; + else + lengthaddition = length(irnewpartition); + lengthaccum = length(irnew); + if lengthaddition > lengthaccum + irnew = [irnew;zeros(lengthaddition-lengthaccum,1)]; + end + irnew(1:lengthaddition) = irnew(1:lengthaddition) + irnewpartition; + end + end + + if SHOWTEXT >= 6 + sum(irnew) + plot(irnew) + pause + end + end + if Ndifforder == 4 + wedgeparams = [cylE2_r1;cylE1_r2;cylE3_r2;cylE2_r3;cylE4_r3;cylE3_r4]; + elseif Ndifforder == 5 + wedgeparams = [cylE2_r1;cylE1_r2;cylE3_r2;cylE2_r3;cylE4_r3;cylE3_r4;cylE5_r4;cylE4_r5]; + elseif Ndifforder == 6 + wedgeparams = [cylE2_r1;cylE1_r2;cylE3_r2;cylE2_r3;cylE4_r3;cylE3_r4;cylE5_r4;cylE4_r5;cylE6_r5;cylE5_r6]; + elseif Ndifforder == 7 + wedgeparams = [cylE2_r1;cylE1_r2;cylE3_r2;cylE2_r3;cylE4_r3;cylE3_r4;cylE5_r4;cylE4_r5;cylE6_r5;cylE5_r6;cylE7_r6;cylE6_r7]; + elseif Ndifforder == 8, + wedgeparams = [cylE2_r1;cylE1_r2;cylE3_r2;cylE2_r3;cylE4_r3;cylE3_r4;cylE5_r4;cylE4_r5;cylE6_r5;cylE5_r6;cylE7_r6;cylE6_r7;cylE8_r7;cylE7_r8]; + end + + if Ndifforder >= 4, + + for kk = 1:newndivvec(1) + if SHOWTEXT >= 5 + disp([' ',int2str(kk),' of ',int2str(newndivvec(1))]) + end + BIGEDGE1stvalue = (kk-0.5)./newndivvec(1); + + [irnewpartition,slask] = EDB1wedgeN(cylS(jj,:),cylR(jj,:),wedgeparams,ncylrows,... + nyvec(edgeshortlist(ii,:)),edgelengthvec(edgeshortlist(ii,:)).',... + dzvec(edgeshortlist(ii,:)),EDcalcmethod,pathalongplane,nedgeelcombs,Rstart,bc,CAIR,FSAMP,BIGEDGE1stvalue); + irnewpartition = real(irnewpartition); + + if kk == 1 + irnew = irnewpartition; + else + lengthaddition = length(irnewpartition); + lengthaccum = length(irnew); + if lengthaddition > lengthaccum + irnew = [irnew;zeros(lengthaddition-lengthaccum,1)]; + end + irnew(1:lengthaddition) = irnew(1:lengthaddition) + irnewpartition; + end + end + end + + if SHOWTEXT >= 5 + varname = ['allirs',int2str(Ndifforder)]; + if exist(varname) == 0 + eval([varname,' = irnew;']) + else + lengthaddition = length(irnew); + eval(['lengthaccum = size(',varname,',1);']) + if lengthaddition > lengthaccum + eval([varname,' = [',varname,';zeros(lengthaddition-lengthaccum,size(',varname,',2))];']) + end + eval([varname,' = [',varname,' zeros(size(',varname,',1),1)];']) + eval([varname,'(1:length(irnew),end) = irnew;']) + end + end + + % Decide whether the IR should be boosted or not + + boostfactor = 1; + if souspecboost ~= 1 | recspecboost ~= 1 + + if prespecpresent(iv(jj)) == 1 + boostfactor = souspecboost; + else + if ~isempty(Sinsideplanenumber) + if Sinsideplanenumber(1)~=planesatedge(edgeshortlist(ii,1),1) & Sinsideplanenumber(1)~=planesatedge(edgeshortlist(ii,1),2), + boostfactor = souspecboost; + end + end + + end + if postspecpresent(iv(jj)) == 1 + boostfactor = boostfactor*recspecboost; + else + if ~isempty(Rinsideplanenumber) + if Rinsideplanenumber(1)~=planesatedge(edgeshortlist(ii,Ndifforder),1) & Rinsideplanenumber(1)~=planesatedge(edgeshortlist(ii,Ndifforder),2), + boostfactor = boostfactor*recspecboost; + end + end + end + + end % ... if souspecboost ~= 1 | recspecboost ~= 1 + + % For thin plates, we must have a boost factor! + % This is because there will be multiple equivalent + % combinations passing on the rear side of the thin plate + + if all( nyvec(edgeshortlist(ii,:)) == 0.5 ) + boostfactor = boostfactor*2^(Ndifforder-1); + end + + if boostfactor ~= 1 + irnew = irnew*boostfactor; + end + + irnew = irnew*double(multfactors(ivlonglist(iv(jj)))); + + [ndiff,ncolsdiff] = size(irdiff); + nnew = size(irnew,1); + if saveindividualdiffirs(1) == 0 + if nnew > ndiff + irdiff = [irdiff;zeros(nnew-ndiff,1)]; + end + irdiff(1:nnew) = irdiff(1:nnew) + irnew; + else + if Ndifforder > ncolsdiff + irdiff = [irdiff zeros(ndiff,Ndifforder-ncolsdiff)]; + ncolsdiff = ncolsdiff+1; + end + if nnew > ndiff + irdiff = [irdiff;zeros(nnew-ndiff,Ndifforder)]; + end + irdiff(1:nnew,Ndifforder) = irdiff(1:nnew,Ndifforder) + irnew; + end + + end % ... if multfactors(ivlonglist(iv(jj))) + + end % ....for jj = 1:ncombs + + else % ... if any(multfactors(ivlonglist(iv))) + if SHOWTEXT >= 4 + disp([' Combination not computed because of repetition']) + end + + end % ... if any(multfactors(ivlonglist(iv))) + + end % .... for ii = 1: length(ivec) + + end % ... if any(difforderinlist==Ndifforder) + + if size(irdiff,2) < Ndifforder & saveindividualdiffirs(1) == 1 + irdiff = [irdiff zeros(size(irdiff,1),Ndifforder-size(irdiff,2))]; + end + end % ... for Ndifforder = 2:specorder +end % .... if userwantsdiff2 == 1 + +ntot = length(irtot); +ndirect = length(irdirect); +ngeom = size(irgeom,1); +ndiff = size(irdiff,1); + +if ndirect > ntot + irtot = [irtot;zeros(ndirect-ntot,1)]; + ntot = length(irtot); +end +irtot(1:ndirect) = irtot(1:ndirect) + irdirect; + +if ngeom > ntot + irtot = [irtot;zeros(ngeom-ntot,1)]; + ntot = length(irtot); +end +irtot(1:ngeom) = irtot(1:ngeom) + irgeom; + +if ndiff > ntot + irtot = [irtot;zeros(ndiff-ntot,1)]; + ntot = length(irtot); +end +if saveindividualdiffirs(1) == 0 | userwantsdiff2 == 0 + irtot(1:ndiff) = irtot(1:ndiff) + irdiff; +else + irtot(1:ndiff) = irtot(1:ndiff) + sum(irdiff.').'; +end + +%------------------------------------------------------- +% Make the IRs the same length + +nmax = max([ length(irtot) size(irgeom,1) size(irdiff,1) length(irdirect)]); + +if length(irtot) < nmax + irtot = [irtot;zeros(nmax-length(irtot),1)]; +end +if length(irdirect) < nmax + irdirect = [irdirect;zeros(nmax-length(irdirect),1)]; +end +if length(irgeom) < nmax + irgeom = [irgeom;zeros(nmax-size(irgeom,1),size(irgeom,2))]; +end +if length(irdiff) < nmax + irdiff = [irdiff;zeros(nmax-size(irdiff,1),size(irdiff,2))]; +end + +%------------------------------------------------------- +% Save the IRs + +irtot = sparse(irtot); +irgeom = sparse(irgeom); +irdirect = sparse(irdirect); +irdiff = sparse(irdiff); +Varlist = [' irdirect irgeom irdiff irtot FSAMP Rstart CAIR EDcalcmethod']; + +if length(saveindividualdiffirs) > 1 + if saveindividualdiffirs(2) == 1 + Varlist = [Varlist,' alldiffirs alldiffirsextradata']; + end +end + +if SHOWTEXT >= 5 + if specorder >= 2 + if exist('allirs2') == 0 + allirs2 = []; + end + Varlist = [Varlist,' allirs2']; + end + if specorder >= 3 + if exist('allirs3') == 0 + allirs3 = []; + end + Varlist = [Varlist,' allirs3']; + end + if specorder >= 4 + if exist('allirs4') == 0 + allirs4 = []; + end + Varlist = [Varlist,' allirs4']; + end + if specorder >= 5 + if exist('allirs5') == 0 + allirs5 = []; + end + Varlist = [Varlist,' allirs5']; + end + if specorder >= 6 + if exist('allirs6') == 0 + allirs6 = []; + end + Varlist = [Varlist,' allirs6']; + end + if specorder >= 7 + if exist('allirs7') == 0 + allirs7 = []; + end + Varlist = [Varlist,' allirs7']; + end + if specorder >= 8 + if exist('allirs8') == 0 + allirs8 = []; + end + Varlist = [Varlist,' allirs8']; + end +end + +eval(['save ',edirfile,Varlist])
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/private/EDB1makemovie.m Sat Nov 16 18:25:24 2013 +0000 @@ -0,0 +1,246 @@ +function M = EDB1makemovie(firstirfile,xvec,yvec,starttimestep,ntimesteps,filtir,maxvalue,viewpoint,... + outlinecorners,noutlinepoints,sourcepoint,typeofir,windowsize,ampexp) +% EDB1makemovie - Makes a movie based on IRs. +% +% Input parameters: +% firstirfile The first of the IR files +% xvec, yvec The ranges of x- and y-values of the receiver positions +% starttimestep The time step to start from - useful if the impulse +% responses have initial zeros. +% ntimesteps The number of time steps +% filtir A window to filter with +% maxvalue [1,2] The minimum and maximum amplitude in the plot +% viewpoint The point to view from [x y z] +% outlinecorners A matrix of corners which will be plotted as an outline +% in the form [x1 y1;x2 y2;x3 y3;...] +% If the matrix has more columns than two, each pair of +% column will be plotted as a separate outline, and they +% will not be tied together. +% noutlinepoints A list with the number of points in each column pair. +% sourcepoint The [x y z] coordinates of the source. +% typeofir 't' (default), 'g' (geom), 'f' (direct sound), 'd' +% (diffracted), 'c' (direct sound + geom) +% windowsize 's', 'm' or 'l' or 'x' +% ampexp (optional) If a value is given here, the signal will be +% plotted as abs(pressure)^ampexp, so that if ampexp = +% 0.5, sqrt(abs(pressure)) will be plotted. If no value +% is given, or the value zero is given, the linear pressure will be plotted. +% +% Output parameters: +% M A movie, in the format which can be played by the +% command movie(M); +% +% Uses functions EDB1strpend +% +% ---------------------------------------------------------------------------------------------- +% This file is part of the Edge Diffraction Toolbox by Peter Svensson. +% +% The Edge Diffraction Toolbox is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) any later version. +% +% The Edge Diffraction Toolbox is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +% FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License along with the +% Edge Diffraction Toolbox. If not, see <http://www.gnu.org/licenses/>. +% ---------------------------------------------------------------------------------------------- +% Peter Svensson (svensson@iet.ntnu.no) 20050922 +% +% M = EDB1makemovie(firstirfile,xvec,yvec,starttimestep,ntimesteps,filtir,maxvalue,viewpoint +% outlinecorners,noutlinepoints,sourcepoint,typeofir,windowsize,ampexp); + +disp('*************************************') +disp('*') +disp('* Creating a movie....') +disp(' ') + + +%-------------------------------------------------------------- +% Extract the filename stem + +if nargin == 0 + [firstirfile,irfilepath] = uigetfile('*ir.mat','Please select the first irfile'); + [irfilepath,temp1,temp2] = fileparts(irfilepath); + if ~isstr(firstirfile) | isempty(firstirfile) + return + end +else + [irfilepath,firstirfile,fileext] = fileparts(firstirfile); + irfilepath = [irfilepath,filesep]; + firstirfile = [firstirfile,fileext]; +end + +if nargin < 12 + typeofir = 't'; + windowsize = 's'; + ampexp = 0; +else + typeofir = lower(typeofir(1)); + if nargin < 13 + windowsize = 's'; + ampexp = 0; + else + windowsize = lower(windowsize(1)); + if nargin < 14 + ampexp = 0; + else + if ampexp < 0 + error('ERROR: ampexp must be larger than, or equal to, zero') + end + end + end +end + +filestem = EDB1strpend(firstirfile,'_ir'); +iv = find(filestem=='_'); +iv = iv(length(iv)); +firstnumber = str2num(filestem(iv+1:length(filestem))); +filestem = filestem(1:iv); + +nx = length(xvec); +ny = length(yvec); +nfiles = nx*ny; + +%-------------------------------------------------------------- +% Read the files, filter and store + +Bigir = zeros(nfiles,ntimesteps); + +disp(' Loading the files, starting with:') +for ii = 1:nfiles + irfile = [filestem,int2str(ii+firstnumber-1),'_ir.mat']; + if ii == 1 + disp([' ',irfile]) + end + eval(['load ',irfilepath,irfile]) + if typeofir == 'f' + irtot = irdirect; + elseif typeofir == 'g' + irtot = irgeom; + elseif typeofir == 'c' + irtot = irgeom + irdirect; + elseif typeofir == 'd', + irtot = irdiff; + end + + if ~isempty(irtot) + if length(irtot) < starttimestep + disp(['WARNING: The value of starttimestep was set higher than the length of some of the IRs']) + irtot = [0 0].'; + else + irtot = irtot(starttimestep:end); + end + irtot = conv(filtir,full(irtot)); + if length(irtot) < ntimesteps + irtot = [irtot;zeros(ntimesteps-length(irtot),1)]; + end + else + irtot = zeros(ntimesteps,1); + end + + if ampexp == 0 + Bigir(ii,:) = irtot(1:ntimesteps).'; + else + Bigir(ii,:) = (abs(irtot(1:ntimesteps).')).^ampexp; + end + +end + +disp(' ... files are loaded.') + +sigvalues = sum(abs(Bigir)); +dsigvalues = diff([0 sigvalues]); +ivstart = find(dsigvalues~=0); +if isempty(ivstart) + error('ERROR: All IRs are empty. Check if you have chosen the right IRs') +end +ivstart = ivstart(1); +if ivstart > 1 + ivstart = ivstart-1; +end +Bigir = Bigir(:,ivstart:end); +[slask,ntimesteps] = size(Bigir); + +if length(maxvalue) < 2 + maxvalue = [maxvalue(1) max(max(Bigir))]; +end + +%-------------------------------------------------------------- +% Go through, time step by time step and plot + +opengl neverselect + +% Prepare the outline plotting + +[noutlinerows,ncolumns] = size(outlinecorners); +noutlines = floor(ncolumns/2); +if noutlines == 1 + outlinecorners = [outlinecorners;outlinecorners(1,:)]; + noutlinepoints = noutlinepoints+1; +end + +M = moviein(ntimesteps); + +axisvalues = [min(xvec) max(xvec) min(yvec) max(yvec) maxvalue(1) maxvalue(2)]; +figure(1) +clf + +xyaspectratio = abs(max(xvec)-min(xvec))/abs(max(yvec)-min(yvec)); + +windowheight = 675; +windowwidth = windowheight*xyaspectratio; + +if windowwidth > 800 + scaledownfactor = windowwidth/800; + windowwidth = windowwidth/scaledownfactor; + windowheight = windowheight/scaledownfactor; +end + +windowpos = [380 80]; +if windowsize == 's' + windowwidth = windowwidth/2; + windowheight = windowheight/2; +elseif windowsize == 'm' + windowwidth = windowwidth/1.41; + windowheight = windowheight/1.41; +elseif windowsize == 'x' + windowwidth = windowwidth*1.41; + windowheight = windowheight*1.41; + windowpos(1) = 100; +end + +%set(1,'Position',[380 80 530 675]) +set(1,'Position',[windowpos(1:2) windowwidth windowheight]) + +for jj=1:ntimesteps + disp(int2str(jj)) + slice = Bigir(:,jj); + slice = reshape(slice,ny,nx); + surf(xvec,yvec,slice); + + shading interp + + if noutlines > 0 + for kk = 1:noutlines + for ll = 1:noutlinepoints(kk)-1 + line([outlinecorners(ll,(kk-1)*2+1) outlinecorners(ll+1,(kk-1)*2+1)],[outlinecorners(ll,(kk-1)*2+2) outlinecorners(ll+1,(kk-1)*2+2)],[0 0]) + line([outlinecorners(ll,(kk-1)*2+1) outlinecorners(ll+1,(kk-1)*2+1)],[outlinecorners(ll,(kk-1)*2+2) outlinecorners(ll+1,(kk-1)*2+2)],[maxvalue(2) maxvalue(2)]) + line([outlinecorners(ll,(kk-1)*2+1) outlinecorners(ll,(kk-1)*2+1)],[outlinecorners(ll,(kk-1)*2+2) outlinecorners(ll,(kk-1)*2+2)],[0 maxvalue(2)]) + end + line([outlinecorners(ll+1,(kk-1)*2+1) outlinecorners(ll+1,(kk-1)*2+1)],[outlinecorners(ll+1,(kk-1)*2+2) outlinecorners(ll+1,(kk-1)*2+2)],[0 maxvalue(2)]) + end + end + if ~isempty(sourcepoint) + line([sourcepoint(1) sourcepoint(1)],[sourcepoint(2) sourcepoint(2)],[0 maxvalue(2)]) + end + + colormap('jet') + caxis([maxvalue(1) maxvalue(2)]) + brighten(0.5); + axis(axisvalues); + axis off + view(viewpoint) + M(:,jj) = getframe; +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/private/EDB1makesnapshot.m Sat Nov 16 18:25:24 2013 +0000 @@ -0,0 +1,231 @@ +function snapshot = EDB1makesnapshot(firstirfile,xvec,yvec,timestep,filtir,maxvalue,viewpoint,... + outlinecorners,noutlinepoints,sourcepoint,typeofir,windowsize,ampexp) +% EDB1makesnapshot - Makes a snapshot of a sound field based on IRs. +% +% Input parameters: +% firstirfile The first of the IR files +% xvec, yvec The ranges of x- and y-values of the receiver positions +% timestep The time step to plot +% filtir A window to filter with +% maxvalue [1,2] The minimum and maximum amplitude in the plot +% viewpoint The point to view from [x y z] +% outlinecorners A matrix of corners which will be plotted as an outline +% in the form [x1 y1;x2 y2;x3 y3;...] +% If the matrix has more columns than two, each pair of +% column will be plotted as a separate outline, and they +% will not be tied together. +% noutlinepoints A list with the number of points in each column pair. +% sourcepoint The [x y z] coordinates of the source. +% typeofir 't' (default), 'g' (geom), 'f' (direct sound), 'd' +% (diffracted), 'c' (direct sound + geom) +% windowsize 's', 'm' or 'l' or 'x' +% ampexp (optional) If a value is given here, the signal will be +% plotted as abs(pressure)^ampexp, so that if ampexp = +% 0.5, sqrt(abs(pressure)) will be plotted. If no value +% is given, or the value zero is given, the linear pressure will be plotted. +% +% Output parameters: +% snapshot A snapshot, in the format which can be played by the +% command surf(xvec,yvec,snapshot). +% +% Uses functions EDB1strpend +% +% ---------------------------------------------------------------------------------------------- +% This file is part of the Edge Diffraction Toolbox by Peter Svensson. +% +% The Edge Diffraction Toolbox is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) any later version. +% +% The Edge Diffraction Toolbox is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +% FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License along with the +% Edge Diffraction Toolbox. If not, see <http://www.gnu.org/licenses/>. +% ---------------------------------------------------------------------------------------------- +% Peter Svensson (svensson@iet.ntnu.no) 20051013 +% +% M = EDB1snapshot(firstirfile,xvec,yvec,starttimestep,ntimesteps,filtir,maxvalue,viewpoint +% outlinecorners,noutlinepoints,sourcepoint,typeofir,windowsize,ampexp); + +disp('*************************************') +disp('*') +disp('* Creating a snapshot....') +disp(' ') + + +%-------------------------------------------------------------- +% Extract the filename stem + +if nargin == 0 + [firstirfile,irfilepath] = uigetfile('*ir.mat','Please select the first irfile'); + [irfilepath,temp1,temp2] = fileparts(irfilepath); + if ~isstr(firstirfile) | isempty(firstirfile) + return + end +else + [irfilepath,firstirfile,fileext] = fileparts(firstirfile); + irfilepath = [irfilepath,filesep]; + firstirfile = [firstirfile,fileext]; +end + +if nargin < 11 + typeofir = 't'; + windowsize = 's'; + ampexp = 0; +else + typeofir = lower(typeofir(1)); + if nargin < 12 + windowsize = 's'; + ampexp = 0; + else + windowsize = lower(windowsize(1)); + if nargin < 13 + ampexp = 0; + else + if ampexp < 0 + error('ERROR: ampexp must be larger than, or equal to, zero') + end + end + end +end + +filestem = EDB1strpend(firstirfile,'_ir'); +iv = find(filestem=='_'); +iv = iv(length(iv)); +firstnumber = str2num(filestem(iv+1:length(filestem))); +filestem = filestem(1:iv); + +nx = length(xvec); +ny = length(yvec); +nfiles = nx*ny; + +loadcommandbase = ['load ',irfilepath,filestem]; + +%-------------------------------------------------------------- +% Read the files, filter and store + +Bigir = zeros(nfiles,1); + +disp(' Loading the files, starting with:') +for ii = 1:nfiles + eval([loadcommandbase,sprintf('%.0f',ii),'_ir.mat']) + if typeofir == 'f' + irtot = irdirect; + elseif typeofir == 'g' + irtot = irgeom; + elseif typeofir == 'c' + irtot = irgeom + irdirect; + elseif typeofir == 'd', + irtot = irdiff; + end + + if any(irtot) + + if length(irtot) > timestep + irtot = irtot(1:timestep); + elseif length(irtot) < timestep + irtot = [irtot;zeros(timestep-length(irtot),1)]; + end + + irsamplevalue = sum(irtot([timestep:-1:timestep-length(filtir)+1]).*filtir); + else + irsamplevalue = 0; + end + + if ampexp == 0 + Bigir(ii) = irsamplevalue; + else + Bigir(ii) = (abs(irsamplevalue)).^ampexp; + end + +end + +disp(' ... files are loaded.') + + +if length(maxvalue) < 2 + maxvalue = [maxvalue(1) max(Bigir)]; +end + +%-------------------------------------------------------------- +% Prepare the outline plotting + +opengl neverselect + +snapshot = reshape(Bigir,ny,nx); + +[noutlinerows,ncolumns] = size(outlinecorners); +noutlines = floor(ncolumns/2); +if noutlines == 1 + outlinecorners = [outlinecorners;outlinecorners(1,:)]; + noutlinepoints = noutlinepoints+1; +end + +axisvalues = [min(xvec) max(xvec) min(yvec) max(yvec) maxvalue(1) maxvalue(2)]; +figure(1) +clf + +xyaspectratio = abs(max(xvec)-min(xvec))/abs(max(yvec)-min(yvec)); + +windowheight = 675; +windowwidth = windowheight*xyaspectratio; + +if windowwidth > 800 + scaledownfactor = windowwidth/800; + windowwidth = windowwidth/scaledownfactor; + windowheight = windowheight/scaledownfactor; +end + +windowpos = [380 80]; +if windowsize == 's' + windowwidth = windowwidth/2; + windowheight = windowheight/2; +elseif windowsize == 'm' + windowwidth = windowwidth/1.41; + windowheight = windowheight/1.41; +elseif windowsize == 'x' + windowwidth = windowwidth*1.41; + windowheight = windowheight*1.41; + windowpos(1) = 100; +end + +set(1,'Position',[windowpos(1:2) windowwidth windowheight]) + +snapshot = reshape(Bigir,ny,nx); +surf(xvec,yvec,snapshot); + +shading interp +colormap('jet') +caxis([maxvalue(1) maxvalue(2)]) +axis(axisvalues); +axis off +view(viewpoint) + +if noutlines > 0 + for kk = 1:noutlines + for ll = 1:noutlinepoints(kk)-1 + H = line([outlinecorners(ll,(kk-1)*2+1) outlinecorners(ll+1,(kk-1)*2+1)],[outlinecorners(ll,(kk-1)*2+2) outlinecorners(ll+1,(kk-1)*2+2)],[0 0]); + set(H,'LineWidth',4); + set(H,'Color',[1 1 0]); + H = line([outlinecorners(ll,(kk-1)*2+1) outlinecorners(ll+1,(kk-1)*2+1)],[outlinecorners(ll,(kk-1)*2+2) outlinecorners(ll+1,(kk-1)*2+2)],2*[maxvalue(2) maxvalue(2)]); + set(H,'LineWidth',4); + set(H,'Color',[1 1 0]); + H = line([outlinecorners(ll,(kk-1)*2+1) outlinecorners(ll,(kk-1)*2+1)],[outlinecorners(ll,(kk-1)*2+2) outlinecorners(ll,(kk-1)*2+2)],[0 2*maxvalue(2)]); + set(H,'LineWidth',4); + set(H,'Color',[1 1 0]); + end + H = line([outlinecorners(ll+1,(kk-1)*2+1) outlinecorners(ll+1,(kk-1)*2+1)],[outlinecorners(ll+1,(kk-1)*2+2) outlinecorners(ll+1,(kk-1)*2+2)],[0 2*maxvalue(2)]); + set(H,'LineWidth',4); + set(H,'Color',[1 1 0]); + end +end +if ~isempty(sourcepoint) + H = line([sourcepoint(1)*0.95 sourcepoint(1)*1.05],[sourcepoint(2)*0.95 sourcepoint(2)*1.05],[maxvalue(2) maxvalue(2)]); + set(H,'LineWidth',4); + set(H,'Color',[1 0 0]); + H = line([sourcepoint(1)*0.95 sourcepoint(1)*1.05],[sourcepoint(2)*1.05 sourcepoint(2)*0.95],[maxvalue(2) maxvalue(2)]); + set(H,'LineWidth',4); + set(H,'Color',[1 0 0]); +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/private/EDB1myvalueinput.m Sat Nov 16 18:25:24 2013 +0000 @@ -0,0 +1,68 @@ +function outval = EDB1myvalueinput(textstr,nvalues,minval,maxval) +% EDB1myvalueinput - Prints a text on the screen and waits for a numerical to be input. +% Prints the text in textstr, and waits for a numerical to be input. +% It is checked if these are within the range [minval,maxval]. +% If one or both is not specified, or given as [], an open range +% is used. It is also checked if exactly nvalues are input. The +% values should be input with spaces inbetween. If a negative +% value of nvalues is input, any number will be accepted. +% +% Input parameters: +% textstr A text str which will be printed on the screen. +% nvalues The number of numerical values that should be read in from +% the keyboard. +% minval (optional) The lowest value that should be allowed. +% maxval (optional) The highest value that should be allowed. +% +% Output parameters: +% outval The nvalues numerical values that should be read in. +% +% Uses the function EDB1extrnums +% +% ---------------------------------------------------------------------------------------------- +% This file is part of the Edge Diffraction Toolbox by Peter Svensson. +% +% The Edge Diffraction Toolbox is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) any later version. +% +% The Edge Diffraction Toolbox is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +% FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License along with the +% Edge Diffraction Toolbox. If not, see <http://www.gnu.org/licenses/>. +% ---------------------------------------------------------------------------------------------- +% Peter Svensson (svensson@iet.ntnu.no) 20030602 +% +% outval = EDB1myvalueinput(textstr,nvalues,minval,maxval); + +if nargin < 4 + maxval = 1e9; + if nargin < 3 + minval = -1e9; + end +end +if isempty(maxval) + maxval = 1e9; +end +if isempty(minval) + minval = -1e9; +end +if maxval < minval + error(['ERROR: minval > maxval']) +end + +foundOKvalue = 0; +while foundOKvalue == 0 + outval = EDB1extrnums( input(textstr,'s') ); + if length(outval) ~= nvalues & nvalues >= 0 + disp('Wrong number of values!'); + else + if prod( double(outval >= minval) ) & prod( double(outval <= maxval) ) + foundOKvalue = 1; + else + disp('One value is outside the allowed range!'); + end + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/private/EDB1plotmodel.m Sat Nov 16 18:25:24 2013 +0000 @@ -0,0 +1,337 @@ +function EDB1plotmodel(eddatafile,plotoptions,plotoptions2,plotoptions3) +% EDB1plotmodel - Plots a model which is given in an eddatafile. +% +% Input parameters: +% eddatafile (optional) The input file. If not specified, a file +% opening window will be presented. +% plotoptions (optional) An integer that can give extra options: +% if bit0 = 1 (= 1) => plot sources +% if bit1 = 1 (= 2) => plot receivers +% if bit2 = 1 (= 4) => plot plane normal vectors +% if bit3 = 1 (= 8) => print plane numbers +% if bit4 = 1 (=16) => print edge numbers +% if bit5 = 1 (=32) => print corner numbers +% if bit6 = 1 (=64) => print plane numbers using the +% CAD file numbering +% if bit7 = 1 (=128)=> print corner numbers using the +% CAD file numbering +% if bit8 = 1 (=256) => offedges are not included +% if bit9 = 1 (=512) => only offedges are included +% if plotoptions == -1 => plot edge by edge +% if plotoptions == -2 => plot plane by plane +% Example: the integer 11 = 8+2+1 +% so sources, receivers, and plane numbers will be plotted. +% plotoptions2 (optional) A matrix with two columns of 1 or many integers, the first +% giving the source numbers to be plotted and the +% second giving the receiver numbers to be +% plotted. The first in the sequence will be +% plotted with a black color. +% Alternatively, if plotoptions = -1, then +% plotoptions2 can be used to give a list of +% edges to plot. +% Alternatively, if plotoptions = -2, then +% plotoptions2 can be used to give a list of +% planes to plot. +% plotoptions3 (optional) A vector with two or three values, giving the +% view position for the 3D plot view. +% +% Sources and receivers are taken from an sdatafile and an rdatafile, the file name of +% which is assumed to be similar to the eddatafile. +% +% Uses functions EDB1strpend, EDB1myvalueinput +% +% ---------------------------------------------------------------------------------------------- +% This file is part of the Edge Diffraction Toolbox by Peter Svensson. +% +% The Edge Diffraction Toolbox is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) any later version. +% +% The Edge Diffraction Toolbox is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +% FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License along with the +% Edge Diffraction Toolbox. If not, see <http://www.gnu.org/licenses/>. +% ---------------------------------------------------------------------------------------------- +% Peter Svensson (svensson@iet.ntnu.no) 20110704 +% +% EDB1plotmodel(eddatafile,plotoptions,plotoptions2,plotoptions3); + +%-------------------------------------------------------------- +% Read the eddatafile + +if nargin == 0 | (nargin >= 1 & isstr(eddatafile) ~= 1) + [eddatafile,eddatafilepath] = uigetfile('*eddata.mat','Please select the eddatafile'); + [eddatafilepath,temp1,temp2] = fileparts(eddatafilepath); + if ~isstr(eddatafile) | isempty(eddatafile) + return + end +else + [eddatafilepath,eddatafile,fileext] = fileparts(eddatafile); + eddatafile = [eddatafile,fileext]; +end +Filestem = EDB1strpend(eddatafile,'_eddata'); + +disp(['eddatafile is ',eddatafilepath,filesep,eddatafile]) + +if nargin == 1 + if isstr(eddatafile) ~= 1 + plotoptions = eddatafile; + else + plotoptions = 0; + end + plotoptions2 = []; + plotoptions3 = []; +elseif nargin == 0 + plotoptions = 0; + plotoptions2 = []; + plotoptions3 = []; +elseif nargin == 2 + plotoptions2 = []; + plotoptions3 = []; +elseif nargin == 3 + nplotoptions2 = size(plotoptions2); + plotoptions3 = []; +else + nplotoptions2 = size(plotoptions2); +end + +plotedgesequence = 0; +plotplanesequence = 0; +if plotoptions < 0 + if plotoptions == -1 + plotedgesequence = 1; + elseif plotoptions == -2 + plotplanesequence = 1; + end + plotoptions = 0; +end +plotsources = bitget(plotoptions,1); +plotreceivers = bitget(plotoptions,2); +plotnvecs = bitget(plotoptions,3); +plotplnumbers = bitget(plotoptions,4); +plotednumbers = bitget(plotoptions,5); +plotconumbers = bitget(plotoptions,6); +plotplCADnumbers = bitget(plotoptions,7); +plotcoCADnumbers = bitget(plotoptions,8); +plotnooffedges = bitget(plotoptions,9); +plotonlyoffedges = bitget(plotoptions,10); + +if plotplCADnumbers, plotplnumbers = 1; end +if plotcoCADnumbers, plotconumbers = 1; end + +%-------------------------------------------------------------------------- +% Load the needed input files + +if ~isempty(eddatafilepath) + eval(['load ',eddatafilepath,filesep,eddatafile]) +else + eval(['load ',eddatafile]) +end + +ncornersperplanevec = double(ncornersperplanevec); +if plotsources + sdatafile = [eddatafilepath,filesep,Filestem,'_sdata_1.mat']; + if exist(sdatafile) == 2 + allsources = []; + sfilecounter = 1; + while exist(sdatafile) == 2 + eval(['load ',sdatafile]) + allsources = [allsources;sources]; + sfilecounter = sfilecounter +1; + sdatafile = [eddatafilepath,filesep,Filestem,'_sdata_',int2str(sfilecounter),'.mat'] + end + sources = allsources; + else + sdatafile = [eddatafilepath,filesep,Filestem,'_sdata.mat']; + if exist(sdatafile) == 2 + eval(['load ',sdatafile]) + else + error(['ERROR: The sdata file named ',sdatafile,' could not be opened']) + end + end +end +if plotreceivers + rdatafile = [eddatafilepath,filesep,Filestem,'_rdata_1.mat']; + if exist(rdatafile) == 2 + allreceivers = []; + rfilecounter = 1; + while exist(rdatafile) == 2 + eval(['load ',rdatafile]) + allreceivers = [allreceivers;receivers]; + rfilecounter = rfilecounter +1; + rdatafile = [eddatafilepath,filesep,Filestem,'_rdata_',int2str(rfilecounter),'.mat'] + end + receivers = allreceivers; + else + rdatafile = [eddatafilepath,filesep,Filestem,'_rdata.mat']; + if exist(rdatafile) == 2 + eval(['load ',rdatafile]) + else + error(['ERROR: The rdata file named ',rdatafile,' could not be opened']) + end + end +end + +if plotplCADnumbers | plotcoCADnumbers + cadgeofile = [eddatafilepath,Filestem,'_cadgeo.mat']; + if exist(cadgeofile) == 2 + eval(['load ',cadgeofile]) + else + error(['ERROR: The cadgeo file named ',cadgeofile,' could not be opened']) + end +end + +%-------------------------------------------------------------- + +[ncorners,slask] = size(corners); +[nedges,slask] = size(edgecorners); +[nplanes,slask] = size(planenvecs); + +planelist = 1:nplanes; + +if isempty(plotoptions3) + viewpos = EDB1myvalueinput('From which point do you want to watch the model? (x y z, or az el, with spaces inbetween) ',-1); +else + viewpos = plotoptions3; +end + +hold off +for ii = 1:nedges + co1 = edgecorners(ii,1); + co2 = edgecorners(ii,2); + iv = [co1;co2]; + plot3(corners(iv,1),corners(iv,2),corners(iv,3)) + if ii ==1 + view(viewpos) + hold + end +end + +if plotedgesequence + for ii = 1:nedges + co1 = edgecorners(ii,1); + co2 = edgecorners(ii,2); + iv = [co1;co2]; + h = plot3(corners(iv,1),corners(iv,2),corners(iv,3)); + set(h,'LineWidth',2) + disp(['Edge no. ',int2str(ii),' Closed wedge angle: ',num2str(closwedangvec(ii)*180/pi)]) + pause + set(h,'LineWidth',1) + + end +end +if plotplanesequence + if ~isempty(plotoptions2) + listofplanes = plotoptions2; + else + listofplanes = [1:nplanes]; + end + for jj = listofplanes + edgelist = edgesatplane(jj,:); + edgelist = edgelist(find(edgelist)); + for ii = edgelist + co1 = edgecorners(ii,1); + co2 = edgecorners(ii,2); + iv = [co1;co2]; + h = plot3(corners(iv,1),corners(iv,2),corners(iv,3)); + set(h,'LineWidth',2) + end + disp(['Plane no. ',int2str(jj)]) + pause + + % For some reason it doesnt work to replot the same list of edges + % with a thinner linewidth; even trying out with replotting the + % edges with another color just replots one of the edges?? + % Therefore the inelegant method of replotting the whole model. + hold off + for ii = 1:nedges + co1 = edgecorners(ii,1); + co2 = edgecorners(ii,2); + iv = [co1;co2]; + plot3(corners(iv,1),corners(iv,2),corners(iv,3)) + if ii ==1 + view(viewpos) + hold + end + end + + + + end +end + +if plotnvecs + for ii = 1:nplanes + midpoint = mean(corners(planecorners(ii,1:(ncornersperplanevec(ii))),:)); + + endpoint = midpoint + planenvecs(ii,:); + bothpoints = [midpoint;endpoint]; + plot3(bothpoints(:,1),bothpoints(:,2),bothpoints(:,3)); + plot3(midpoint(1),midpoint(2),midpoint(3),'ro'); + end +end + +if plotplnumbers + for ii = 1:nplanes + midpoint = mean(corners(planecorners(ii,1:ncornersperplanevec(ii)),:)); + endpoint = midpoint + planenvecs(ii,:)*0.1; + if plotplCADnumbers == 1 + text(endpoint(1),endpoint(2),endpoint(3),int2str(planenumbers(ii))); + else + text(endpoint(1),endpoint(2),endpoint(3),int2str(ii)); + end + + end +end + +if plotednumbers + iv = [1:nedges]; + if plotnooffedges, iv(offedges) = []; end + if plotonlyoffedges, iv = offedges; end + iv = iv(:).'; + + for ii = iv + midpoint = mean(corners(edgecorners(ii,1:2),:)); + text(midpoint(1),midpoint(2),midpoint(3),int2str(ii)); + end +end + +if plotconumbers + for ii = 1:ncorners + if plotcoCADnumbers == 1 + text(corners(ii,1),corners(ii,2),corners(ii,3),int2str(cornernumbers(ii))) + else + text(corners(ii,1),corners(ii,2),corners(ii,3),int2str(ii)) + end + end + +end + +if plotsources == 1 + if isempty(plotoptions2) + plot3(sources(:,1),sources(:,2),sources(:,3),'*'); + else + if nplotoptions2 == 1 + plot3(sources(plotoptions2(1),1),sources(plotoptions2(1),2),sources(plotoptions2(1),3),'*') + else + plot3(sources(plotoptions2(1,1),1),sources(plotoptions2(1,1),2),sources(plotoptions2(1,1),3),'k*') + plot3(sources(plotoptions2(2:nplotoptions2,1),1),sources(plotoptions2(2:nplotoptions2,1),2),sources(plotoptions2(2:nplotoptions2,1),3),'*') + end + end +end + +if plotreceivers == 1 + if isempty(plotoptions2) + plot3(receivers(:,1),receivers(:,2),receivers(:,3),'ro'); + else + if nplotoptions2 == 1 + plot3(receivers(plotoptions2(2),1),receivers(plotoptions2(2),2),receivers(plotoptions2(2),3),'ro'); + else + plot3(receivers(plotoptions2(1,2),1),receivers(plotoptions2(1,2),2),receivers(plotoptions2(1,2),3),'ko'); + plot3(receivers(plotoptions2(2:nplotoptions2,2),1),receivers(plotoptions2(2:nplotoptions2,2),2),receivers(plotoptions2(2:nplotoptions2,2),3),'ro'); + + end + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/private/EDB1plotpath.m Sat Nov 16 18:25:24 2013 +0000 @@ -0,0 +1,167 @@ +function EDB1plotpath(eddatafile,reflpathsfile,plotoptions) +% EDB1plotpath - Plots a model which is given in an eddatafile +% and one or more of the paths in an edreflpathsfile. +% +% Input parameters: +% eddatafile The input file. +% reflpathsfile The file with reflpaths. +% plotoptions The row in the reflpathsfile that should be plotted. +% +% Sources and receivers are taken from an sdatafile and an rdatafile, the file name of +% which is assumed to be similar to the eddatafile. +% +% Uses functions EDB1strpend, EDB1myvalueinput +% +% ---------------------------------------------------------------------------------------------- +% This file is part of the Edge Diffraction Toolbox by Peter Svensson. +% +% The Edge Diffraction Toolbox is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) any later version. +% +% The Edge Diffraction Toolbox is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +% FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License along with the +% Edge Diffraction Toolbox. If not, see <http://www.gnu.org/licenses/>. +% ---------------------------------------------------------------------------------------------- +% Peter Svensson (svensson@iet.ntnu.no) 20090708 +% +% EDB1plotpath(eddatafile,reflpathsfile,plotoptions); + +%-------------------------------------------------------------- +% Read the input files + +[eddatafilepath,eddatafile,fileext] = fileparts(eddatafile); +eddatafile = [eddatafile,fileext]; +Filestem = EDB1strpend(eddatafile,'_eddata'); + +[reflpathsfilepath,reflpathsfile,fileext] = fileparts(reflpathsfile); +reflpathsfile = [reflpathsfile,fileext]; + +if ~isempty(eddatafilepath) + eval(['load ',eddatafilepath,filesep,eddatafile]) +else + eval(['load ',eddatafile]) +end + +if ~isempty(reflpathsfilepath) + eval(['load ',reflpathsfilepath,filesep,reflpathsfile]) +else + eval(['load ',reflpathsfile]) +end + +plotsources = 1; +plotreceivers = 1; + +%-------------------------------------------------------------- + +ncornersperplanevec = double(ncornersperplanevec); +if plotsources + sdatafile = [eddatafilepath,Filestem,'_sdata.mat']; + if exist(sdatafile) == 2 + eval(['load ',sdatafile]) + else + error(['ERROR: The sdata file named ',sdatafile,' could not be opened']) + end +end +if plotreceivers + rdatafile = [eddatafilepath,Filestem,'_rdata.mat']; + if exist(rdatafile) == 2 + eval(['load ',rdatafile]) + else + error(['ERROR: The rdata file named ',rdatafile,' could not be opened']) + end +end + +%-------------------------------------------------------------- + +[ncorners,slask] = size(corners); +[nedges,slask] = size(edgecorners); +[nplanes,slask] = size(planenvecs); + +planelist = 1:nplanes; + +% viewpos = EDB1myvalueinput('From which point do you want to watch the model? (x y z, or az el, with spaces inbetween) ',-1); +viewpos = [1 0 0]; +axis equal + +hold off +for ii = 1:nedges + co1 = edgecorners(ii,1); + co2 = edgecorners(ii,2); + iv = [co1;co2]; + plot3(corners(iv,1),corners(iv,2),corners(iv,3)) + if ii ==1 + view(viewpos) + hold + end +end + +if plotsources == 1 + plot3(sources(:,1),sources(:,2),sources(:,3),'*'); +end + +if plotreceivers == 1 + plot3(receivers(:,1),receivers(:,2),receivers(:,3),'ro'); +end + +%--------------------------------------------------------------- +% Plot the path + +pathtype = pathtypevec(plotoptions,:) +reflpath = reflpaths(plotoptions,:) +norder =sum(pathtype ~= 0); +nspecorder = sum(pathtype == 115); +speccols = find(pathtype == 115); +diffcols = find(pathtype == 100); + + +x1 = sources(1,1); +y1 = sources(1,2); +z1 = sources(1,3); + +for ii = 1:nspecorder+1 + x2 = specextradata(plotoptions,1+3*(ii-1)); + y2 = specextradata(plotoptions,2+3*(ii-1)); + z2 = specextradata(plotoptions,3+3*(ii-1)); + plot3(x2,y2,z2,'o') + line([x1;x2],[y1;y2],[z1;z2]); + x1 = x2; + y1 = y2; + z1 = z2; +end + +x2 = receivers(1,1); +y2 = receivers(1,2); +z2 = receivers(1,3); +line([x1;x2],[y1;y2],[z1;z2]); + +% Print the involved plane numbers + +reflplanes = reflpath(speccols); + +for ii = reflplanes + midpoint = mean(corners(planecorners(ii,1:ncornersperplanevec(ii)),:)); + endpoint = midpoint + planenvecs(ii,:); + text(endpoint(1),endpoint(2),endpoint(3),int2str(ii)); +end + +% Print the involved edge numbers + +if ~isempty(diffcols) + diffedges = reflpath(diffcols); + for ii = diffedges + midpoint = mean(corners(edgecorners(ii,1:2),:)); + text(midpoint(1),midpoint(2),midpoint(3),int2str(ii)); + co1 = edgecorners(ii,1); + co2 = edgecorners(ii,2); + iv = [co1;co2]; + h = plot3(corners(iv,1),corners(iv,2),corners(iv,3)); + set(h,'LineWidth',3) + + + end + +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/private/EDB1plotstackedIRs.m Sat Nov 16 18:25:24 2013 +0000 @@ -0,0 +1,133 @@ +function Bigir = EDB1plotstackedIRs(firstirfile,nfiles,offset,filtir,typeofir,startsample,endsample) +% EDB1plotstackedIRs - Plots a number of IRs in a stacked way. +% +% Input parameters: +% firstirfile The data file containing the first IR file +% nfiles The number of files +% offset The numerical offset for each file +% filtir A window to filter with +% typeofir 't' (default), 'g' (geom), 'f' (direct sound), 'd' +% (diffracted) +% startsample (optional) The first sample number that should be +% plotted for each IR (after filtering). Default: 1. +% endsample (optional) The last sample number that should be +% plotted for each IR (after filtering). Default: the +% last sample for the longest of all IRs. +% +% Output parameters: +% Bigir Matrix, [nfiles,nlength], of the IRs in the files, one +% per row. +% +% Uses functions EDB1strpend +% +% ---------------------------------------------------------------------------------------------- +% This file is part of the Edge Diffraction Toolbox by Peter Svensson. +% +% The Edge Diffraction Toolbox is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) any later version. +% +% The Edge Diffraction Toolbox is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +% FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License along with the +% Edge Diffraction Toolbox. If not, see <http://www.gnu.org/licenses/>. +% ---------------------------------------------------------------------------------------------- +% Peter Svensson (svensson@iet.ntnu.no) 20030806 +% +% EDB1plotstackedIRs(firstirfile,nfiles,offset,filtir,typeofirs,startsample,endsample); + +%-------------------------------------------------------------- +% Extract the filename stem + +if nargin == 0 + [firstirfile,irfilepath] = uigetfile('*ir.mat','Please select the first irfile'); + [irfilepath,temp1,temp2] = fileparts(irfilepath); + if ~isstr(firstirfile) | isempty(firstirfile) + return + end +else + [irfilepath,firstirfile,fileext] = fileparts(firstirfile); + irfilepath = [irfilepath,filesep]; + firstirfile = [firstirfile,fileext]; +end + +if nargin < 5 + typeofir = 't'; +else + typeofir = lower(typeofir(1)); +end + +if nargin < 6 + startsample = 1; +end +if nargin < 7 + endsample = -1; +end + +filestem = EDB1strpend(firstirfile,'_ir'); +iv = find(filestem=='_'); +iv = iv(length(iv)); +firstnumber = str2num(filestem(iv+1:length(filestem))); +filestem = filestem(1:iv) + +%-------------------------------------------------------------- +% Read the files + +offsetvec = ([1:nfiles].'-1)*offset; + +disp(' Loading files') +for ii = nfiles:-1:1 + irfile = [filestem,int2str(ii+firstnumber-1),'_ir.mat']; + eval(['load ',irfilepath,irfile]) + irtot = real(irtot); + if typeofir == 'f' + irtot = irdirect; + elseif typeofir == 'g' + irtot = irgeom + irdirect; + elseif typeofir == 's' + irtot = irgeom; + elseif typeofir == 'd' + irtot = real(irdiff); + end + + if isempty(irtot) + irtot = [0 0].'; + end + + irtot = conv(filtir,full(irtot)); + if endsample == -1 + irtot = irtot(startsample:end); + else + if endsample <= length(irtot) + irtot = irtot(startsample:endsample); + else + irtot = irtot(startsample:end); + end + end + + signvec = sign(irtot); + irtot = abs(irtot).^(1/1).*signvec; + + if ii == nfiles + Bigir = zeros(nfiles,length(irtot)); + [slask,nbigir] = size(Bigir); + Bigir = Bigir + offsetvec(:,ones(1,nbigir)); + Bigir(ii,:) = Bigir(ii,:) + (irtot).'; + else + [slask,nbigir] = size(Bigir); + nir = length(irtot); + if nir > nbigir + Bigir = [Bigir offsetvec(:,ones(1,nir-nbigir))]; + end + Bigir(ii,1:nir) = Bigir(ii,1:nir) + (irtot).'; + end + +end + +if ~isempty(Bigir) + plot(Bigir.','r') +else + error(' ERROR: The IRs were all empty. Please check that you did not specify start and end samples that were longer than the IR length!') +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/private/EDB1plotstackedTFs.m Sat Nov 16 18:25:24 2013 +0000 @@ -0,0 +1,126 @@ +function Bigtf = EDB1plotstackedTFs(firstirfile,nfiles,offset,nfft,typeofir,startsample,endsample) +% EDB1plotstackedTFs - Plots a number of TFs in a stacked way. +% +% Input parameters: +% firstirfile The data file containing the first IR file +% nfiles The number of files +% offset The numerical offset for each file [in dB] +% nfft The fft size +% typeofir 't' (default), 'g' (geom), 'f' (direct sound), 'd' +% (diffracted) +% startsample (optional) The first sample number that should be +% plotted for each IR (after filtering). Default: 1. +% endsample (optional) The last sample number that should be +% plotted for each IR (after filtering). Default: the +% last sample for the longest of all IRs. +% +% Output parameters: +% Bigtf Matrix, [nfiles,nlength], of the TFs in the files, one +% per row. +% +% Uses functions EDB1strpend +% +% ---------------------------------------------------------------------------------------------- +% This file is part of the Edge Diffraction Toolbox by Peter Svensson. +% +% The Edge Diffraction Toolbox is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) any later version. +% +% The Edge Diffraction Toolbox is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +% FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License along with the +% Edge Diffraction Toolbox. If not, see <http://www.gnu.org/licenses/>. +% ---------------------------------------------------------------------------------------------- +% Peter Svensson (svensson@iet.ntnu.no) 20050116 +% +% EDB1plotstackedTFs(firstirfile,nfiles,offset,nfft,typeofirs,startsample,endsample); + +%-------------------------------------------------------------- +% Extract the filename stem + +if nargin == 0 + [firstirfile,irfilepath] = uigetfile('*ir.mat','Please select the first irfile'); + [irfilepath,temp1,temp2] = fileparts(irfilepath); + if ~isstr(firstirfile) | isempty(firstirfile) + return + end +else + [irfilepath,firstirfile,fileext] = fileparts(firstirfile); + irfilepath = [irfilepath,filesep]; + firstirfile = [firstirfile,fileext]; +end + +if nargin < 5 + typeofir = 't'; +else + typeofir = lower(typeofir(1)); +end + +if nargin < 6 + startsample = 1; +end +if nargin < 7 + endsample = -1; +end + +filestem = EDB1strpend(firstirfile,'_ir'); +iv = find(filestem=='_'); +iv = iv(length(iv)); +firstnumber = str2num(filestem(iv+1:length(filestem))); +filestem = filestem(1:iv) + +%-------------------------------------------------------------- +% Read the files + +offsetvec = ([1:nfiles].'-1)*offset; + +disp(' Loading files') +for ii = nfiles:-1:1 + irfile = [filestem,int2str(ii+firstnumber-1),'_ir.mat']; + eval(['load ',irfilepath,irfile]) + irtot = real(irtot); + if typeofir == 'f' + irtot = irdirect; + elseif typeofir == 'g' + irtot = irgeom + irdirect; + elseif typeofir == 's' + irtot = irgeom; + elseif typeofir == 'd' + irtot = real(irdiff); + end + + if isempty(irtot) + irtot = [0 0].'; + end + + if endsample == -1 + irtot = irtot(startsample:end); + else + if endsample <= length(irtot) + irtot = irtot(startsample:endsample); + else + irtot = irtot(startsample:end); + end + end + F = fft(full(irtot),nfft); + L = 20*log10(abs(F(1:nfft/2))); + + if ii == nfiles + Bigtf = zeros(nfiles,nfft/2); + BigL = zeros(nfiles,nfft/2); + [slask,nbigtf] = size(Bigtf); + BigL = BigL + offsetvec(:,ones(1,nbigtf)); + Bigtf(ii,:) = (F(1:nfft/2)).'; + BigL(ii,:) = BigL(ii,:) + (L).'; + else + Bigtf(ii,:) = (F(1:nfft/2)).'; + BigL(ii,:) = BigL(ii,:) + (L).'; + end + +end + +fvec = FSAMP/nfft*[0:nfft/2-1]; +semilogx(fvec,BigL.','r')
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/private/EDB1poinpla.m Sat Nov 16 18:25:24 2013 +0000 @@ -0,0 +1,401 @@ +function [hitvec,edgehit,cornerhit] = EDB1poinpla(xpoints,planelist,minvals,maxvals,planecorners,corners,ncornersperplanevec,planenvecs) +% EDB1poinpla - Detects if one or more points are inside a number of finite planes. +% If one point is given as input, it will be checked against all +% planes in a list of planes. If N points are given as inputs, a list of +% planes should have the N planes, and each point will be checked against +% its corresponding plane. +% +% Input parameters: +% xpoints Matrix, [N,3], of coordinates for the N points to check +% planelist List, [nplanes,1], of planes to check the N points +% against. If N~= 1, then nplanes must be equal to N. +% NB! +% minvals, maxvals, planecorners, corners, ncornersperplanevec, planenvecs +% Data that should have been taken from the corresponding +% variables in the eddatafile,see EDB1edgeo for more information. +% NB!! All of these matrices except corners +% have been rearranged so that they have N rows, and each +% row contain the data for one specific plane, the one +% that the inside-check should be done for. +% +% Output parameters: +% hitvec List, [N,1], with 1 or 0 indicating whether a point is +% inside or outside the plane given by planelist. +% edgehit List, [N,1], with 1 or 0 indicating if a hit was right at the +% edge of a plane. These hits were not marked in hitvec. +% cornerhit List, [N,1], with 1 or 0 indicating if a hit was right at the +% corner of a plane. These hits were not marked in hitvec. +% +% Uses no special functions +% +% ---------------------------------------------------------------------------------------------- +% This file is part of the Edge Diffraction Toolbox by Peter Svensson. +% +% The Edge Diffraction Toolbox is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) any later version. +% +% The Edge Diffraction Toolbox is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +% FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License along with the +% Edge Diffraction Toolbox. If not, see <http://www.gnu.org/licenses/>. +% ---------------------------------------------------------------------------------------------- +% Peter Svensson (svensson@iet.ntnu.no) 20100204 +% +% [hitvec,edgehit] = EDB1poinpla(xpoints,planelist,minvals,maxvals,planecorners,corners,ncornersperplanevec,planenvecs); + +% 100204 Functioning version +% 111201 Fixed a bug: when the ray (from the hitpoint in the positive x-direction) passed exactly +% through a vertex, then there was an error. For those rare cases an extra ray is shot in a random direction. + +global SHOWTEXT + +geomacc = 1e-12; + +npoints = size(xpoints,1); +nplanestotest = length(planelist); +if npoints == 1 + xpoints = xpoints(ones(nplanestotest,1),:); +end + +planecorners = [planecorners planecorners(:,1)]; + +%------------------------------------------------------------ +% First test: are the points inside the cubic boxes? +% +% NB! The values in possibleones tell which entries in the lists xpoint +% and planelist that passed the first test. + +if nplanestotest <= 65535 + possibleones = uint16(1:nplanestotest); +else + possibleones = uint32(1:nplanestotest); +end +possibleones = possibleones(:); + +iv = uint32(find(xpoints(:,1) > maxvals(planelist,1))); +possibleones(iv) = []; +iv = uint32(find(xpoints(possibleones,1) < minvals(planelist(possibleones),1))); +possibleones(iv) = []; +iv = uint32(find(xpoints(possibleones,2) > maxvals(planelist(possibleones),2))); +possibleones(iv) = []; +iv = uint32(find(xpoints(possibleones,2) < minvals(planelist(possibleones),2))); +possibleones(iv) = []; +iv = uint32(find(xpoints(possibleones,3) > maxvals(planelist(possibleones),3))); +clear maxvals +possibleones(iv) = []; +iv = uint32(find(xpoints(possibleones,3) < minvals(planelist(possibleones),3))); +possibleones(iv) = []; +clear minvals iv + +hitvec = uint8(zeros(nplanestotest,1)); +hitvec(possibleones) = 1; + +nposs = length(possibleones); + +if SHOWTEXT >= 4 + disp([' Of the ',int2str(npoints),' points,']) + disp([' ',int2str(length(possibleones)),' survived the cube test:']) +end + +edgehit = uint32(zeros(nposs,1)); +cornerhit = uint32(zeros(nposs,1)); + + +%------------------------------------------------------------ +% Second test: project onto two dimensions. +% Start by finding which dimension of the planes that has the strongest +% normal vector component. That dimension should be tossed. +% +% Easiest way to handle: make three subsets: +% Combos that should be projected onto xy +% Combos that should be projected onto xz +% Combos that should be projected onto yz + +if nposs>0, + + A = abs((planenvecs(planelist(possibleones),:))); + maxA = max(A.').'; + markwhereismax = (A == maxA(:,[1 1 1])); + iv = find(markwhereismax(:,1).*markwhereismax(:,2)~=0); + if ~isempty(iv) + markwhereismax(iv,2) = 0; + end + iv = find(markwhereismax(:,1).*markwhereismax(:,3)~=0); + if ~isempty(iv) + markwhereismax(iv,1) = 0; + end + iv = find(markwhereismax(:,2).*markwhereismax(:,3)~=0); + if ~isempty(iv) + markwhereismax(iv,2) = 0; + end + colno = [1 2 3]; + finalcolno = markwhereismax.*colno(ones(nposs,1),:); + finalcolno = sum(finalcolno.').'; + + yzsubset = find(finalcolno==1); + xzsubset = find(finalcolno==2); + xysubset = find(finalcolno==3); + + %--------------------------------------------- + % First the xysubset + % + % Create a ray that starts in xpoint and extends parallel to the x-axis + % in the positive x-direction, that is: + % y = xpoints(:,2): + % xstart = xpoints(:,1); + + if ~isempty(xysubset) + if SHOWTEXT >= 4 + disp([' ',int2str(length(xysubset)),' xy-projected points:']) + end + + numberofedgestocheck = ncornersperplanevec(planelist(possibleones(xysubset))); + edgenumbers = unique(numberofedgestocheck); + + yray = xpoints(possibleones(xysubset),2); + xstart = xpoints(possibleones(xysubset),1); + edgecrossings = zeros(size(xysubset)); + + % Use a parametric representation for each edge: + % x_edge = x_1 + t*(x_2 - x_1) + % y_edge = y_1 + t*(y_2 - y_1) + % Find t by setting y_ray = y_edge + + closehits = 0; + for ii = 1:max(edgenumbers) + + y1 = corners(planecorners(planelist(possibleones(xysubset)),ii),2); + y2 = corners(planecorners(planelist(possibleones(xysubset)),ii+1),2); + tedgecrossing = (yray - y1)./(y2-y1); + + x1 = corners(planecorners(planelist(possibleones(xysubset)),ii),1); + x2 = corners(planecorners(planelist(possibleones(xysubset)),ii+1),1); + + xedge = x1 + tedgecrossing.*(x2-x1); + + edgecrossings = edgecrossings + (tedgecrossing >= 0 & tedgecrossing <= 1 & xedge > xstart).*(ii <= numberofedgestocheck); + closeones = find(abs(tedgecrossing)<geomacc | abs(tedgecrossing-1)<geomacc ); + if ~isempty(closeones) + closehits = 1; + end + end + + if closehits == 1 + if SHOWTEXT >= 4 + disp(' Very close hit: retrying with a skewed ray') + end + closehits = 0; + ystart = yray; + % Select end point of ray randomly: choose radius larger than + % plane cube, and angle randomly + + + rayradius = 2*max(sqrt( sum(corners.'.^2) )); + rayphi = 2*pi*rand(1,1); + xend = rayradius*cos(rayphi); + yend = rayradius*sin(rayphi); + + edgecrossings = zeros(size(xysubset)); + for ii = 1:max(edgenumbers) + + y1 = corners(planecorners(planelist(possibleones(xysubset)),ii),2); + y2 = corners(planecorners(planelist(possibleones(xysubset)),ii+1),2); + x1 = corners(planecorners(planelist(possibleones(xysubset)),ii),1); + x2 = corners(planecorners(planelist(possibleones(xysubset)),ii+1),1); + + tedgecrossing = ( (xend-xstart).*(y1-ystart) - (x1-xstart).*(yend-ystart) )./( (x2-x1).*(yend-ystart) - (y2-y1).*(xend-xstart) ); + xedge = x1 + tedgecrossing.*(x2-x1); + + edgecrossings = edgecrossings + (tedgecrossing >= 0 & tedgecrossing <= 1 & xedge > xstart).*(ii <= numberofedgestocheck); + closeones = find(abs(tedgecrossing)<geomacc | abs(tedgecrossing-1)<geomacc ); + if ~isempty(closeones) + closehits = 1; + end + end + + end + + hitvec(possibleones(xysubset)) = (edgecrossings==1); + + if SHOWTEXT >= 4 + disp([' ',int2str(sum((edgecrossings==1))),' survived the xyplane projections test:']) + end + + end + + %--------------------------------------------- + % Then the xzsubset + % + % Create a ray that starts in xpoint and extends parallel to the x-axis + % in the positive x-direction, that is: + % z = xpoints(:,3): + % xstart = xpoints(:,1); + + if ~isempty(xzsubset) + if SHOWTEXT >= 4 + disp([' ',int2str(length(xzsubset)),' xz-projected points:']) + end + + numberofedgestocheck = ncornersperplanevec(planelist(possibleones(xzsubset))); + edgenumbers = unique(numberofedgestocheck); + + zray = xpoints(possibleones(xzsubset),3); + xstart = xpoints(possibleones(xzsubset),1); + edgecrossings = zeros(size(xzsubset)); + + % Use a parametric representation for each edge: + % x_edge = x_1 + t*(x_2 - x_1) + % z_edge = z_1 + t*(z_2 - z_1) + % Find t by setting z_ray = z_edge + + closehits = 0; + for ii = 1:max(edgenumbers) + z1 = corners(planecorners(planelist(possibleones(xzsubset)),ii),3); + z2 = corners(planecorners(planelist(possibleones(xzsubset)),ii+1),3); + tedgecrossing = (zray - z1)./(z2-z1); + + x1 = corners(planecorners(planelist(possibleones(xzsubset)),ii),1); + x2 = corners(planecorners(planelist(possibleones(xzsubset)),ii+1),1); + + xedge = x1 + tedgecrossing.*(x2-x1); + + edgecrossings = edgecrossings + (tedgecrossing > 0 & tedgecrossing < 1 & xedge > xstart).*(ii <= numberofedgestocheck); + closeones = find(abs(tedgecrossing)<geomacc | abs(tedgecrossing-1)<geomacc ); + if ~isempty(closeones) + closehits = 1; + end + end + + if closehits == 1 + if SHOWTEXT >= 4 + disp(' Very close hit: retrying with a skewed ray') + end + closehits = 0; + zstart = zray; + % Select end point of ray randomly: choose radius larger than + % plane cube, and angle randomly + + + rayradius = 2*max(sqrt( sum(corners.'.^2) )); + rayphi = 2*pi*rand(1,1); + xend = rayradius*cos(rayphi); + zend = rayradius*sin(rayphi); + + edgecrossings = zeros(size(xzsubset)); + for ii = 1:max(edgenumbers) + + z1 = corners(planecorners(planelist(possibleones(xzsubset)),ii),3); + z2 = corners(planecorners(planelist(possibleones(xzsubset)),ii+1),3); + x1 = corners(planecorners(planelist(possibleones(xzsubset)),ii),1); + x2 = corners(planecorners(planelist(possibleones(xzsubset)),ii+1),1); + + tedgecrossing = ( (xend-xstart).*(z1-zstart) - (x1-xstart).*(zend-zstart) )./( (x2-x1).*(zend-zstart) - (z2-z1).*(xend-xstart) ); + xedge = x1 + tedgecrossing.*(x2-x1); + + edgecrossings = edgecrossings + (tedgecrossing >= 0 & tedgecrossing <= 1 & xedge > xstart).*(ii <= numberofedgestocheck); + closeones = find(abs(tedgecrossing)<geomacc | abs(tedgecrossing-1)<geomacc ); + if ~isempty(closeones) + closehits = 1; + end + end + + end + + hitvec(possibleones(xzsubset)) = (edgecrossings==1); + + if SHOWTEXT >= 4 + disp([' ',int2str(sum((edgecrossings==1))),' survived the xzplane projections test:']) + end + end + + + %--------------------------------------------- + % Third the yzsubset + % + % Create a ray that starts in xpoint and extends parallel to the y-axis + % in the positive y-direction, that is: + % z = xpoints(:,3): + % ystart = xpoints(:,2); + + if ~isempty(yzsubset) + if SHOWTEXT >= 4 + disp([' ',int2str(length(yzsubset)),' yz-projected points:']) + end + + numberofedgestocheck = ncornersperplanevec(planelist(possibleones(yzsubset))); + edgenumbers = unique(numberofedgestocheck); + + zray = xpoints(possibleones(yzsubset),3); + ystart = xpoints(possibleones(yzsubset),2); + edgecrossings = zeros(size(yzsubset)); + + % Use a parametric representation for each edge: + % y_edge = y_1 + t*(y_2 - y_1) + % z_edge = z_1 + t*(z_2 - z_1) + % Find t by setting z_ray = z_edge + + closehits = 0; + for ii = 1:max(edgenumbers) + z1 = corners(planecorners(planelist(possibleones(yzsubset)),ii),3); + z2 = corners(planecorners(planelist(possibleones(yzsubset)),ii+1),3); + tedgecrossing = (zray - z1)./(z2-z1); + + y1 = corners(planecorners(planelist(possibleones(yzsubset)),ii),2); + y2 = corners(planecorners(planelist(possibleones(yzsubset)),ii+1),2); + + yedge = y1 + tedgecrossing.*(y2-y1); + + edgecrossings = edgecrossings + (tedgecrossing > 0 & tedgecrossing < 1 & yedge > ystart).*(ii <= numberofedgestocheck); + closeones = find(abs(tedgecrossing)<geomacc | abs(tedgecrossing-1)<geomacc ); + if ~isempty(closeones) + closehits = 1; + end + + end + + if closehits == 1 + if SHOWTEXT >= 4 + disp(' Very close hit: retrying with a skewed ray') + end + closehits = 0; + zstart = zray; + % Select end point of ray randomly: choose radius larger than + % plane cube, and angle randomly + + + rayradius = 2*max(sqrt( sum(corners.'.^2) )); + rayphi = 2*pi*rand(1,1); + yend = rayradius*cos(rayphi); + zend = rayradius*sin(rayphi); + + edgecrossings = zeros(size(yzsubset)); + for ii = 1:max(edgenumbers) + + y1 = corners(planecorners(planelist(possibleones(yzsubset)),ii),2); + y2 = corners(planecorners(planelist(possibleones(yzsubset)),ii+1),2); + z1 = corners(planecorners(planelist(possibleones(yzsubset)),ii),3); + z2 = corners(planecorners(planelist(possibleones(yzsubset)),ii+1),3); + + tedgecrossing = ( (zend-zstart).*(y1-ystart) - (z1-zstart).*(yend-ystart) )./( (z2-z1).*(yend-ystart) - (y2-y1).*(zend-zstart) ); + yedge = y1 + tedgecrossing.*(y2-y1); + + edgecrossings = edgecrossings + (tedgecrossing >= 0 & tedgecrossing <= 1 & yedge > ystart).*(ii <= numberofedgestocheck); + closeones = find(abs(tedgecrossing)<geomacc | abs(tedgecrossing-1)<geomacc ); + if ~isempty(closeones) + closehits = 1; + end + end + + end + + hitvec(possibleones(yzsubset)) = (edgecrossings==1); + + if SHOWTEXT >= 4 + disp([' ',int2str(sum((edgecrossings==1))),' survived the yzplane projections test:']) + end + end + +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/private/EDB1poinplax.m Sat Nov 16 18:25:24 2013 +0000 @@ -0,0 +1,296 @@ +function [hitvec,edgehit,cornerhit] = EDB1poinplax(bigplanelist,xpoints,planelist,minvals,maxvals,planecorners,corners,ncornersperplanevec,planenvecs) +% EDB1poinplax - Detects if one or more points are inside a number of finite planes. Extended version. +% If one point is given as input, it will be checked against all +% planes in a list of planes. If N points are given as inputs, a list of +% planes should have the N planes, and each point will be checked against +% its corresponding plane. +% +% Input parameters: +% NB!!! This version is a special version, so bigplanelist and xpoints +% actually have different sizes! planelist and xpoints have the same sizes +% however. +% bigplanelist List, [N,1], of the plane numbers in all the +% N points to check. +% xpoints Matrix, [N,3], of coordinates for the N points to check +% planelist List, [nplanes,1], of planes to check the N points +% against. If N~= 1, then nplanes must be equal to N. +% NB! +% minvals, maxvals, planecorners, corners, ncornersperplanevec, planenvecs +% Data that should have been taken from the corresponding +% variables in the eddatafile,see EDB1edgeo for more information. +% NB!! All of these matrices except corners +% have been rearranged so that they have N rows, and each +% row contain the data for one specific plane, the one +% that the inside-check should be done for. +% +% Output parameters: +% hitvec List, [N,1], with 1 or 0 indicating whether a point is +% inside or outside the plane given by planelist. +% edgehit List, [N,1], with 1 or 0 indicating if a hit was right at the +% edge of a plane. These hits were not marked in hitvec. +% cornerhit List, [N,1], with 1 or 0 indicating if a hit was right at the +% corner of a plane. These hits were not marked in hitvec. +% +% Uses no special functions +% +% ---------------------------------------------------------------------------------------------- +% This file is part of the Edge Diffraction Toolbox by Peter Svensson. +% +% The Edge Diffraction Toolbox is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) any later version. +% +% The Edge Diffraction Toolbox is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +% FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License along with the +% Edge Diffraction Toolbox. If not, see <http://www.gnu.org/licenses/>. +% ---------------------------------------------------------------------------------------------- +% Peter Svensson (svensson@iet.ntnu.no) 20100204 +% +% [hitvec,edgehit] = EDB1poinplax(bigplanelist,xpoints,planelist,minvals,maxvals,planecorners,corners,ncornersperplanevec,planenvecs); + +global SHOWTEXT + +geomacc = 1e-12; + +npoints = size(xpoints,1); +nplanestotest = length(planelist); +if npoints == 1 + xpoints = xpoints(ones(nplanestotest,1),:); +end + +planecorners = [planecorners planecorners(:,1)]; + +%------------------------------------------------------------ +% First test: are the points inside the cubic boxes? +% +% NB! The values in possibleones tell which entries in the lists xpoint +% and planelist that passed the first test. + +if nplanestotest <= 65535 + possibleones = uint16(1:nplanestotest); +else + possibleones = uint32(1:nplanestotest); +end +possibleones = possibleones(:); + +iv = uint32(find(xpoints(:,1) > maxvals(bigplanelist(planelist),1))); +possibleones(iv) = []; +iv = uint32(find(xpoints(possibleones,1) < minvals(bigplanelist(planelist(possibleones)),1))); +possibleones(iv) = []; +iv = uint32(find(xpoints(possibleones,2) > maxvals(bigplanelist(planelist(possibleones)),2))); +possibleones(iv) = []; +iv = uint32(find(xpoints(possibleones,2) < minvals(bigplanelist(planelist(possibleones)),2))); +possibleones(iv) = []; +iv = uint32(find(xpoints(possibleones,3) > maxvals(bigplanelist(planelist(possibleones)),3))); +clear maxvals +possibleones(iv) = []; +iv = uint32(find(xpoints(possibleones,3) < minvals(bigplanelist(planelist(possibleones)),3))); +possibleones(iv) = []; +clear minvals iv + +hitvec = uint8(zeros(nplanestotest,1)); +hitvec(possibleones) = 1; + +nposs = length(possibleones); + +if SHOWTEXT >= 4 + disp([' Of the ',int2str(npoints),' points,']) + disp([' ',int2str(length(possibleones)),' survived the cube test:']) +end + +edgehit = uint32(zeros(nposs,1)); +cornerhit = uint32(zeros(nposs,1)); + + +%------------------------------------------------------------ +% Second test: project onto two dimensions. +% Start by finding which dimension of the planes that has the strongest +% normal vector component. That dimension should be tossed. +% +% Easiest way to handle: make three subsets: +% Combos that should be projected onto xy +% Combos that should be projected onto xz +% Combos that should be projected onto yz + +if nposs>0, + + A = abs((planenvecs(bigplanelist(planelist(possibleones)),:))); + maxA = max(A.').'; + markwhereismax = (A == maxA(:,[1 1 1])); + iv = find(markwhereismax(:,1).*markwhereismax(:,2)~=0); + if ~isempty(iv) + markwhereismax(iv,2) = 0; + end + iv = find(markwhereismax(:,1).*markwhereismax(:,3)~=0); + if ~isempty(iv) + markwhereismax(iv,1) = 0; + end + iv = find(markwhereismax(:,2).*markwhereismax(:,3)~=0); + if ~isempty(iv) + markwhereismax(iv,2) = 0; + end + colno = [1 2 3]; + finalcolno = markwhereismax.*colno(ones(nposs,1),:); + finalcolno = sum(finalcolno.').'; + + yzsubset = find(finalcolno==1); + xzsubset = find(finalcolno==2); + xysubset = find(finalcolno==3); + + %--------------------------------------------- + % First the xysubset + % + % Create a ray that starts in xpoint and extends parallel to the x-axis + % in the positive x-direction, that is: + % y = xpoints(:,2): + % xstart = xpoints(:,1); + + if ~isempty(xysubset) + if SHOWTEXT >= 4 + disp([' ',int2str(length(xysubset)),' xy-projected points:']) + end + + numberofedgestocheck = ncornersperplanevec(bigplanelist(planelist(possibleones(xysubset)))); + edgenumbers = unique(numberofedgestocheck); + + yray = xpoints(possibleones(xysubset),2); + xstart = xpoints(possibleones(xysubset),1); + edgecrossings = zeros(size(xysubset)); + + % Use a parametric representation for each edge: + % x_edge = x_1 + t*(x_2 - x_1) + % y_edge = y_1 + t*(y_2 - y_1) + % Find t by setting y_ray = y_edge + + for ii = 1:max(edgenumbers) + + y1 = corners(planecorners(bigplanelist(planelist(possibleones(xysubset))),ii),2); + y2 = corners(planecorners(bigplanelist(planelist(possibleones(xysubset))),ii+1),2); + tedgecrossing = (yray - y1)./(y2-y1); + + x1 = corners(planecorners(bigplanelist(planelist(possibleones(xysubset))),ii),1); + x2 = corners(planecorners(bigplanelist(planelist(possibleones(xysubset))),ii+1),1); + + xedge = x1 + tedgecrossing.*(x2-x1); + + edgecrossings = edgecrossings + (tedgecrossing > 0 & tedgecrossing < 1 & xedge > xstart).*(ii <= numberofedgestocheck); + + closeones = find(abs(tedgecrossing)<geomacc | abs(tedgecrossing-1)<geomacc ); + if ~isempty(closeones) + disp([' WARNING: ',int2str(length(closeones)),' very close hits']) + end + end + + hitvec(possibleones(xysubset)) = (edgecrossings==1); + + if SHOWTEXT >= 4 + disp([' ',int2str(sum((edgecrossings==1))),' survived the xyplane projections test:']) + end + + end + + %--------------------------------------------- + % Then the xzsubset + % + % Create a ray that starts in xpoint and extends parallel to the x-axis + % in the positive x-direction, that is: + % z = xpoints(:,3): + % xstart = xpoints(:,1); + + if ~isempty(xzsubset) + if SHOWTEXT >= 4 + disp([' ',int2str(length(xzsubset)),' xz-projected points:']) + end + + numberofedgestocheck = ncornersperplanevec(bigplanelist(planelist(possibleones(xzsubset)))); + edgenumbers = unique(numberofedgestocheck); + + zray = xpoints(possibleones(xzsubset),3); + xstart = xpoints(possibleones(xzsubset),1); + edgecrossings = zeros(size(xzsubset)); + + % Use a parametric representation for each edge: + % x_edge = x_1 + t*(x_2 - x_1) + % z_edge = z_1 + t*(z_2 - z_1) + % Find t by setting z_ray = z_edge + + for ii = 1:max(edgenumbers) + z1 = corners(planecorners(bigplanelist(planelist(possibleones(xzsubset))),ii),3); + z2 = corners(planecorners(bigplanelist(planelist(possibleones(xzsubset))),ii+1),3); + tedgecrossing = (zray - z1)./(z2-z1); + + x1 = corners(planecorners(bigplanelist(planelist(possibleones(xzsubset))),ii),1); + x2 = corners(planecorners(bigplanelist(planelist(possibleones(xzsubset))),ii+1),1); + + xedge = x1 + tedgecrossing.*(x2-x1); + + edgecrossings = edgecrossings + (tedgecrossing > 0 & tedgecrossing < 1 & xedge > xstart).*(ii <= numberofedgestocheck); + closeones = find(abs(tedgecrossing)<geomacc | abs(tedgecrossing-1)<geomacc ); + if ~isempty(closeones) + disp([' WARNING: ',int2str(length(closeones)),' very close hits']) + end + + end + + hitvec(possibleones(xzsubset)) = (edgecrossings==1); + + if SHOWTEXT >= 4 + disp([' ',int2str(sum((edgecrossings==1))),' survived the xzplane projections test:']) + end + end + + + %--------------------------------------------- + % Third the yzsubset + % + % Create a ray that starts in xpoint and extends parallel to the y-axis + % in the positive y-direction, that is: + % z = xpoints(:,3): + % ystart = xpoints(:,2); + + if ~isempty(yzsubset) + if SHOWTEXT >= 4 + disp([' ',int2str(length(yzsubset)),' yz-projected points:']) + end + + numberofedgestocheck = ncornersperplanevec(bigplanelist(planelist(possibleones(yzsubset)))); + edgenumbers = unique(numberofedgestocheck); + + zray = xpoints(possibleones(yzsubset),3); + ystart = xpoints(possibleones(yzsubset),2); + edgecrossings = zeros(size(yzsubset)); + + % Use a parametric representation for each edge: + % y_edge = y_1 + t*(y_2 - y_1) + % z_edge = z_1 + t*(z_2 - z_1) + % Find t by setting z_ray = z_edge + + for ii = 1:max(edgenumbers) + z1 = corners(planecorners(bigplanelist(planelist(possibleones(yzsubset))),ii),3); + z2 = corners(planecorners(bigplanelist(planelist(possibleones(yzsubset))),ii+1),3); + tedgecrossing = (zray - z1)./(z2-z1); + + y1 = corners(planecorners(bigplanelist(planelist(possibleones(yzsubset))),ii),2); + y2 = corners(planecorners(bigplanelist(planelist(possibleones(yzsubset))),ii+1),2); + + yedge = y1 + tedgecrossing.*(y2-y1); + + edgecrossings = edgecrossings + (tedgecrossing > 0 & tedgecrossing < 1 & yedge > ystart).*(ii <= numberofedgestocheck); + closeones = find(abs(tedgecrossing)<geomacc | abs(tedgecrossing-1)<geomacc ); + if ~isempty(closeones) + disp([' WARNING: ',int2str(length(closeones)),' very close hits']) + end + + end + + hitvec(possibleones(yzsubset)) = (edgecrossings==1); + + if SHOWTEXT >= 4 + disp([' ',int2str(sum((edgecrossings==1))),' survived the yzplane projections test:']) + end + end + +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/private/EDB1quadstep.m Sat Nov 16 18:25:24 2013 +0000 @@ -0,0 +1,107 @@ +function Q = EDB1quadstep(a,b,fa,fc,fb,tol,rs,rr,zs,zr,ny,sinnyfivec,cosnyfivec) +% EDB1quadstep - Recursive numerical integration routine for EDB1wedge1st_int. +% Modified from Matlabs QUADSTEP function. The EDB1quadstep version +% solves all time steps at the same time. +% +% Uses no special function +% +% ---------------------------------------------------------------------------------------------- +% This file is part of the Edge Diffraction Toolbox by Peter Svensson. +% +% The Edge Diffraction Toolbox is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) any later version. +% +% The Edge Diffraction Toolbox is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +% FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License along with the +% Edge Diffraction Toolbox. If not, see <http://www.gnu.org/licenses/>. +% ---------------------------------------------------------------------------------------------- +% Peter Svensson (svensson@iet.ntnu.no) 20040321 +% +% EDB1quadstep(a,b,fa,fc,fb,tol,rs,rr,zs,zr,ny,sinnyfivec,cosnyfivec) + +% Evaluate integrand twice in interior of subinterval [a,b]. +c = (a + b)/2; + +nslots = length(a); + +% We use the matrix x for both the x-interval values and the corresponding +% y-values + +x = [(a + c)/2, (c + b)/2]; +x = reshape(x,2*nslots,1); + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Instead of using a function call, we plug in the entire function here! +%% x = betaoverml_all(x,rs,rr,zr,ny,sinnyfivec,cosnyfivec); + +ml = sqrt( (x-zs).^2 + rs^2 ).*sqrt( (x-zr).^2 + rr^2 ); +%------------------------------------------------ +% We would have liked to use the following code: +% y = (ml + (zvec-zs).*(zvec-zr))/(rs*rr); +% expnyeta = (sqrt(y.^2-1) + y).^ny; +% coshnyeta = 0.5*( expnyeta + 1./expnyeta); +% but to save three vectors, zvec will be re-used for +% y and expnyeta and coshnyeta + +zvec = (ml + (x-zs).*(x-zr))/(rs*rr); +zvec = (real(sqrt(zvec.^2-1)) + zvec).^ny; +zvec = 0.5*( zvec + 1./zvec); +x = sinnyfivec(1)./(zvec - cosnyfivec(1)); +x = x + sinnyfivec(2)./(zvec - cosnyfivec(2)); +x = x + sinnyfivec(3)./(zvec - cosnyfivec(3)); +x = x + sinnyfivec(4)./(zvec - cosnyfivec(4)); + +x = x./ml; + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +x = reshape(x,nslots,2); + +fd = x(:,1); +fe = x(:,2); +ftemp = fa + fb + 2*fc; + +%----------------------------------------- +% We use the output vector Q for another purpose + +tempvec = (b-a)/6; + +% Three point Simpson's rule. +Q1 = tempvec.*(ftemp + 2*fc); + +% Five point double Simpson's rule. +%Q2 = (h/12).*(fa + 4*fd + 2*fc + 4*fe + fb); + +% We would have liked to use the following code: +% % % Q2 = tempvec/2.*(ftemp + 4*fd + 4*fe); +% % % % One step of Romberg extrapolation. +% % % Q = Q2 + (Q2 - Q1)/15; +% ...... but we save one vector by re-using ftemp +% for Q2 + +ftemp = tempvec/2.*(ftemp + 4*fd + 4*fe); +% ftemp = tempvec/2.*(ftemp + 4*x(:,1) + 4*x(:,2)); +% One step of Romberg extrapolation. +Q = ftemp + (ftemp - Q1)/15; + +%----------------------------------------- +% Check if all or some of the sample intervals +% have reached the tolerance. + +tempvec = find(abs(ftemp-Q)>tol); + +% Check accuracy of integral over this subinterval. + +if isempty(tempvec) + return + +% Subdivide into two subintervals. +else + Qac = EDB1quadstep(a(tempvec),c(tempvec),fa(tempvec),fd(tempvec),fc(tempvec),tol,rs,rr,zs,zr,ny,sinnyfivec,cosnyfivec); + Qcb = EDB1quadstep(c(tempvec),b(tempvec),fc(tempvec),fe(tempvec),fb(tempvec),tol,rs,rr,zs,zr,ny,sinnyfivec,cosnyfivec); + Q(tempvec) = Qac + Qcb; +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/private/EDB1readac.m Sat Nov 16 18:25:24 2013 +0000 @@ -0,0 +1,761 @@ +function [outputfile] = EDB1readac(CADfile,outputfile,planecornerstype,checkgeom) +% EDB1readac - Reads a file of type .AC (made by e.g. Invis AC3D) and saves all the geometry data in a mat-file. +% +% Input parameters: +% CADfile (optional) The input file, with or without the .AC extension. +% If this file is not specified, a file opening window will appear. +% outputfile (optional) The output file. If not specified, it will be given the +% same name as the CAD file with an '_cadgeo.mat' ending instead of the '.AC'. +% planecornerstype (optional) Could have the value 'zero' or 'circ'.Default: 'circ'. +% Affects the matrix planecorners, see below. +% checkgeom (optional) If this parameter is given the value 'check', then a few checks +% of the geometry consistency will be done: a check for duplicate corners +% for redundant corners and for corners that are connected to only one plane. +% Only warnings are given. As default, no check is done. +% SHOWTEXT (global) If this global parameter has the value 3 or higher, informative text will +% be printed on the screen. +% +% Output parameters: +% outputfile The name of the outputfile, generated either automatically or specified as +% an input parameter. +% +% Output parameters in the outputfile: +% corners Matrix [ncorners,3] with the corner coordinates +% cornernumbers Vector [ncorners,1] with the corner numbers used in the CAD-file. That is +% in the outputfile, the corners will effectively be renumbered from 1 to ncorners +% in the order they appeared in the CAD-file. +% planecorners Matrix [planes,nmaxcornersperplane] with the corner numbers that make up each plane. +% Since planes can have different numbers of corners, the number of columns is the +% maximum number of corners that any plane has. NB! The corner numbers are in the +% renumbered system, not in the CAD-file system. +% planenames Matrix [nplanes,nmaxcharacters1] (sparse), with the planenames in the CAD file. +% planeabstypes Matrix [nplanes,nmaxcharacters2] (sparse), with the absorber names in the CAD file. +% planenumbers Vector [nplanes,1] with the plane numbers used in the CAD file. +% cornercrossref Vector [nmaxnumberinCADfile,1] (sparse), which gives the matlab-file corner +% numbers for each CAD-file corner number. For instance, if a CAD-file corner +% number 1200 is translated to corner number 72 in the matlab-file, then +% cornercrossref(1000) = 72. +% Snumbers Vector [nsources,1] of the source numbers in the CAD-file. NB! Only CAD-files +% v6 use source numbers; later versions use source names instead of numbers. +% For CAD-file v7 and v8, Snumbers is empty. +% Snames Matrix [nsources,2] of the source names in the CAD-file. NB! Only CAD-files v7 +% or later use source names (such as 'A0' etc). Older versions use source numbers, +% in which case Snames is empty. +% Sdirectivitynames Matrix [nsources,nmaxcharacters3] (sparse) with the source directivity names +% in the CAD file. +% Sdelays Vector [nsources,1] of the source delays in the CAD-file, in milliseconds. +% Scoords Matrix [nsources,3] of the source coordinates. +% Sdirections Matrix [nsources,3] of the aim point coordinates for the sources. +% Srotations Vector [nsources,1] of the source rotations, in degrees. +% Slevels Matrix [nsources,6/8] of the source levels for six (CAD-files v6) or eight +% octave bands (CAD-files v7 or later). +% Rnumbers Vector [nreceivers,1] of the receiver numbers in the CAD-file. +% Rcoords Matrix [nreceivers,3] of the receiver coordinates. +% CATTversionnumber 6,7 or 8 +% planeeqs Matrix [nplanes,4] of the plane equations as derived from the plane definitions. +% Each row has the values [A B C D] of the plane equation on the form Ax + By + Cz = D +% planenvecs Matrix [nplanes,3] of the normalized normal vectors of the planes. +% ncornersperplanevec Vector [nplanes,1] which gives the number of corners for each plane. +% planesatcorners Matrix [ncorners,4] which gives the plane numbers that each corner is connected to. +% NB! Here it is assumed that each corner is connected to maximum four planes. +% nplanespercorners Vector [ncorners,1] which gives the number of planes that each corner is connected to. +% minvals Matrix [nplanes,3] which for each plane gives the smallest coordinate in the x-, y- and z-direction. +% maxvals Matrix [nplanes,3] which for each plane gives the largest coordinate in the x-, y- and z-direction. +% planehasindents Vector [nplanes,1] which for each plane gives the +% number of indeting corners +% indentingcorners Matrix [nplanes,max(ncornersperplanevec)] which for each plane gives the number to the first corner +% in a corner triplet which identifies an indenting corner. The number of the corner is the +% order given in planecorners for that plane. +% +% Uses the functions EDB1fistr, EDB1extrnums, EDB1cross +% +% ---------------------------------------------------------------------------------------------- +% This file is part of the Edge Diffraction Toolbox by Peter Svensson. +% +% The Edge Diffraction Toolbox is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) any later version. +% +% The Edge Diffraction Toolbox is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +% FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License along with the +% Edge Diffraction Toolbox. If not, see <http://www.gnu.org/licenses/>. +% ---------------------------------------------------------------------------------------------- +% Peter Svensson (svensson@iet.ntnu.no) 18Jul09 +% +% ---------------------------------------------------------------------------------------------- +% This File is created based on EDB1eadcad.m to support the Edge Diffraction Toolbox +% ---------------------------------------------------------------------------------------------- +% Alexander Pohl (alexander.pohl@hcu-hamburg.de) 25May2011 +% +% [outputfile] = EDB1readac(CADfile,outputfile,planecornerstype,checkgeom); + +% Modified by Peter Svensson on 3Dec2011 + +global SHOWTEXT + +if nargin == 0 + CADfile = ''; + outputfile = ''; + planecornerstype = ''; + checkgeom = ''; +elseif nargin == 1 + outputfile = ''; + planecornerstype = ''; + checkgeom = ''; +elseif nargin == 2 + planecornerstype = ''; + checkgeom = ''; +elseif nargin == 3 + checkgeom = ''; +end + +geomacc = 1e-10; + +%--------------------------------------------------------------- +% If no AC-file was specified, present a file opening window + +if isempty(CADfile) + [CADfile,filepath] = uigetfile('*.ac','Please select the AC3Dfile'); + + [filepath,temp1] = fileparts(filepath); + + if ~isstr(CADfile) + return + end + + [temp1,filestem] = fileparts(CADfile); + + + CADfile = [[filepath,filesep],filestem,'.ac']; +else + + [filepath,filestem,fileext] = fileparts(CADfile); + CADfile = [[filepath,filesep],filestem,fileext]; +end + + +if exist(CADfile) ~= 2 + error(['ERROR: AC3D-file: ',CADfile,' can not be found']) +end + +%--------------------------------------------------------------- +% If no output file was specified, construct an automatic file name + +if isempty(outputfile) + outputfile = [[filepath,filesep],filestem,'_cadgeo.mat']; +end + +%--------------------------------------------------------------- +% Read in the entire file into the string B +% Find the line starts and ends + +fid = fopen([CADfile],'r'); +if fid == 0 + error(['ERROR: The AC3Dfile ',CADfile,' could not be opened.']) +end + +%--------------------------------------------------------------- +% read header "AC3Db" +tline = fgetl(fid); +if (~strcmp(tline,'AC3Db')) + disp('AC3Db header missing'); +end + +% read materials +p_NumberOfMaterials=0; +while(true) + tline = fgetl(fid); + tokens = readLineToToken(tline); + + if(strcmp(tokens{1},'MATERIAL')) + p_MaterialList{p_NumberOfMaterials+1}=tokens{2}; + p_NumberOfMaterials=p_NumberOfMaterials+1; + + else + break; + end +end + +% read world object (all objects are kids of this) +m_LocalMatrix = [1.0 0.0 0.0 0.0; + 0.0 1.0 0.0 0.0; + 0.0 0.0 1.0 0.0; + 0.0 0.0 0.0 1.0]; + +% Read OBJECT world +tokens = readLineToToken(tline); +if(~strcmp(tokens{1},'OBJECT')) + disp('Section does not start with "object"'); +end +if(~strcmp(tokens{2},'world')) + disp('Section does not start with "world"'); +end + +% Read kids +tline = fgetl(fid); +tokens = readLineToToken(tline); +if(~strcmp(tokens{1},'kids')) + disp('root object section does not start with kids'); +end +p_Kids = str2num(tokens{2}); + +for i = 1:p_Kids + p_Objects{i}=read_ac3d_object(fid, m_LocalMatrix); +end + +fclose(fid); + + %% Export +eval(['save a.mat p_Objects']); +% Combine Vertices of EVERY Object to on corner list (incl. Counting PlanesPerPoly) +for i = 1:p_Kids + if(i==1) + corners=p_Objects{i}{1}'; + p_CornersPerPoly = size(p_Objects{i}{1},2); + p_PlanesPerPoly = size(p_Objects{i}{2},2); + else + corners = [corners; p_Objects{i}{1}']; + p_PlanesPerPoly = [p_PlanesPerPoly size(p_Objects{i}{2},2)]; + p_CornersPerPoly = [p_CornersPerPoly size(p_Objects{i}{1},2)]; + end +end + +% Enumerate each corner from 1:end +ncorners = size(corners,1); +cornernumbers=(1:ncorners)'; + +%Number of Planes is sum over all PlanesPerPoly +nplanes=sum(p_PlanesPerPoly); + +ncornersperplanevec=zeros(nplanes,1); +currentPlaneIndex=1; +for i = 1:p_Kids + for j=1:p_PlanesPerPoly(i); + ncornersperplanevec(currentPlaneIndex)=length(p_Objects{i}{2}{j}); + currentPlaneIndex=currentPlaneIndex+1; + end +end + +% We need to compute the maximum number of vertices for any plane +% (others are filled up with 0) +p_MaximumNumberOfVerticesOfPlane = max(ncornersperplanevec); + +% Compute indices of corners for each plane +% Simple for first Object, as here numbers are identical +% For every further object, the number of previous used corners has be be +% taken as offset +planecorners=zeros(nplanes,p_MaximumNumberOfVerticesOfPlane); +currentPlaneIndex=1; +p_Offset=0; +for i = 1:p_Kids + for j=1:p_PlanesPerPoly(i); + for k=1:length(p_Objects{i}{2}{j}) + planecorners(currentPlaneIndex,k)=p_Objects{i}{2}{j}(k)+p_Offset; + end + currentPlaneIndex=currentPlaneIndex+1; + end + p_Offset=p_Offset+p_CornersPerPoly(i); +end + +planenames=zeros(nplanes,30); +currentPlaneIndex=1; +for i = 1:p_Kids + for j=1:p_PlanesPerPoly(i); + p_Text = sparse(double(p_MaterialList{p_Objects{i}{4}{j}+1})); + + if length(p_Text) > size(planenames,2) + planenames = [planenames zeros(planenumbers(currentPlaneIndex),length(p_Text)-size(planenames,2))]; + end + planenames(currentPlaneIndex,1:length(p_Text)) = p_Text; + currentPlaneIndex=currentPlaneIndex+1; + end +end + +planeabstypes = sparse(planenames(:,1:6)); + +% Addition on 2.12.2011 by Peter Svensson +% The absorber names had an initial " which must be removed. +% We remove columns until A-Z,a-z + +if size(planeabstypes,1) > 1 + columnhasalphabet = 1 - sign( prod(sign(64-full(planeabstypes))+1)); +else + columnhasalphabet = 1 - sign( (sign(64-full(planeabstypes))+1)); +end +firstOKcolumn = find(columnhasalphabet); +if isempty(firstOKcolumn) + error('ERROR: All plane absorber types have names without any letters. They must start with a letter') +end +firstOKcolumn = firstOKcolumn(1); +planeabstypes = planeabstypes(:,firstOKcolumn:end); + + +planenumbers=1:nplanes; + +eval(['save ',outputfile,' corners planecorners ncornersperplanevec']) + +%% Begining from here, it is code based of EDB1readcad.m without changes - except SOURCE - RECIEVER Values, as not in AC3Dfile +%--------------------------------------------------------------- +% Change the numbering in the CAD file to a contiguous one + +% Corner numbers +% First we make an inelegant crossreference vector giving the +% resulting corner number in the position given by the CAD-file +% corner number. + +% PS 20120414: CHECK Corners with number zero are not handled correctly. +% Insert code from EDB1readcad here. + +maxnumb = max(cornernumbers); +cornercrossref = sparse(zeros(1,maxnumb)); +cornercrossref(cornernumbers) = [1:ncorners]; + +[nplanes,ncornersperplane] = size(planecorners); +iv = find(planecorners~=0); +planecorners(iv) = full(cornercrossref(planecorners(iv))); + +%--------------------------------------------------------------- +% Go through all planes. If there is a plane definition including +% zeros, and planecornerstype == 'circ', expand it repeating the +% same corner order again. + +if isempty(planecornerstype) + planecornerstype = 'circ'; +else + planecornerstype = setstr(lower(planecornerstype(1))); + if planecornerstype(1) == 'z' + planecornerstype = 'zero'; + else + planecornerstype = 'circ'; + end +end + +if planecornerstype == 'circ' + for ii = 1:nplanes + iv = find( planecorners(ii,:) ~= 0); + ncornersatplane = length(iv); + if ncornersatplane ~= ncornersperplane + pattern = planecorners(ii,iv); + nrepeatings = ceil(ncornersperplane/ncornersatplane); + for jj = 1:nrepeatings-1 + pattern = [pattern planecorners(ii,iv)]; + end + planecorners(ii,:) = pattern(1:ncornersperplane); + end + end +end + + +%--------------------------------------------------------------- +% Find the normal vectors to the planes using the cross products +% +% The normal vector is basically the cross product between two vectors +% connecting three consecutive points. If there are indents though +% they will cause reversed normal vectors, so one must go through all +% combinations and choose the majority normal vector. +% +% 26mar09 Use the fact described above for detecting indention corners + +planenvecs = zeros(nplanes,3); +planehasindents = zeros(nplanes,1); +indentingcorners = sparse(zeros(nplanes,max(ncornersperplanevec))); + +for ii = 1:nplanes + + iv = find(planecorners(ii,:)~=0); + cornerlist = planecorners(ii,iv); + iv = find(cornerlist == cornerlist(1)); + if length(iv) > 1 + cornerlist = cornerlist(1:iv(2)-1); + end + ncorners = length( cornerlist ); + cornerlist = [cornerlist cornerlist(1) cornerlist(2)]; + + nvectorlist = zeros(ncorners,3); + nveclen = zeros(ncorners,1); + + for jj = 1:ncorners + co1numb = cornerlist(jj); + co2numb = cornerlist(jj+1); + co3numb = cornerlist(jj+2); + vec1 = corners(co1numb,:) - corners(co2numb,:); + vec2 = corners(co3numb,:) - corners(co2numb,:); + + nvec = EDB1cross(vec1.',vec2.').'; + nveclen(jj) = norm(nvec); + if nveclen(jj) > 0 + nvectorlist(jj,:) = nvec./nveclen(jj); + end + end + + iv = find(nveclen < max(nveclen)*0.001); + nvectorlist(iv,:) = []; + nvecref = nvectorlist(1,:); + + [n1,slask] = size(nvectorlist); + nvecsigns = round(sum( (nvectorlist.').*(nvecref(ones(n1,1),:).') )); + + if sum(nvecsigns) == 0 + disp(' ') + error(['ERROR: Plane ',int2str(planenumbers(ii)),' (plane numbering as in the CAD file) seems to be twisted.']) + end + + + if abs(sum(nvecsigns)) ~= n1 + disp(['Plane ',int2str(ii),' has indents!']) + nindents = (n1 - abs(sum(nvecsigns)))/2; + planehasindents(ii) = nindents; + ivindent = find(nvecsigns == -1); + if length(ivindent) == nindents + indentingcorners(ii,ivindent) = 1; + else + if length(ivindent) == ncorners - nindents + ivindent = find(nvecsigns == 1); + indentingcorners(ii,ivindent) = 1; + else + error(['ERROR: An unexpected problem. Please report to the developer']) + end + end + + end + + nvecdiff = [nvectorlist(2:n1,1).*nvecsigns(2:n1).' nvectorlist(2:n1,2).*nvecsigns(2:n1).' nvectorlist(2:n1,3).*nvecsigns(2:n1).'] - nvecref(ones(n1-1,1),:); + + if n1 > 2 + nvecdiff = sum(nvecdiff.'.^2).'; + else + nvecdiff = norm(nvecdiff); + end + + %APO Change + if any(nvecdiff>1e-3), + nvecdiff + error(['ERROR: Normal vectors for plane ',int2str(planenumbers(ii)),' (in the CAD file, = ',int2str(ii),' in the EDB1 file), get different normal vectors for consecutive corner triplets. Check the geometry in the CAD-file']) + elseif any(nvecdiff>1e-8) + nvecdiff + disp(['WARNING: Normal vectors for plane ',int2str(planenumbers(ii)),' (in the CAD file, = ',int2str(ii),' in the EDB1 file), get somewhat different normal vectors for consecutive corner triplets. Check the geometry in the CAD-file']) + end + + if ncorners > 5 & abs(sum(nvecsigns)) <= 1 + disp(['WARNING for plane number ',int2str(planenumbers(ii)),' in the CAD-file']) + disp([' with the name ',strtrim(setstr(full(planenames(ii,:))))]) + disp(' The normal vector can not be determined for this plane because there are') + disp(' the same number of inwards and outwards corners') + disp(' This is a list of the possible normal vectors:') + [nv1,slask] = size(nvectorlist); + for kk = 1:nv1 + vecstr = [' ',int2str(kk),'. ',num2str(-nvectorlist(kk,1)),' ',num2str(-nvectorlist(kk,2)),' ',num2str(-nvectorlist(kk,3))]; + disp(vecstr) + end + disp(' ') + + preferredsign = input(' Give the number of a correct normal vector for this plane please '); + switchsign = nvecsigns.'./nvecsigns(preferredsign); + nvectorlist = nvectorlist.*switchsign(:,ones(1,3)); + else + mostcommonsign = sign(sum(nvecsigns)); + + switchsign = nvecsigns.'./mostcommonsign; + nvectorlist = nvectorlist.*switchsign(:,ones(1,3)); + end + + planenvecs(ii,:) = mean(nvectorlist); +end + +planenvecs = -planenvecs; + +%--------------------------------------------------------------- +% Plane equations, as Ax + By + Cz = D for each plane + +planeeqs = zeros(nplanes,4); +planeeqs(:,1:3) = planenvecs; +planeeqs(:,4) = sum( (planenvecs.').*(corners(planecorners(:,1),:).') ).'; + +%--------------------------------------------------------------- +% Useful data: planesatcorners, minvals and maxvals + +[ncorners,slask] = size(corners); +planesatcornerhits = zeros(ncorners,nplanes); + +for ii = 1:nplanes + cornerlist = planecorners(ii,1:ncornersperplanevec(ii)); + planesatcornerhits(cornerlist,ii) = planesatcornerhits(cornerlist,ii) + 1; +end + +maxplanespercorner = 0; +for ii = 1:ncorners + nplanes = length(find(planesatcornerhits(ii,:) ~= 0)); + if nplanes > maxplanespercorner + maxplanespercorner = nplanes; + end +end + +planesatcorners = zeros(ncorners,maxplanespercorner); +nplanespercorners = zeros(ncorners,1); +for ii = 1:ncorners + iv = find(planesatcornerhits(ii,:)~=0); + planesatcorners(ii,1:length(iv)) = iv; + nplanespercorners(ii) = length(iv); +end + +% find cubic boxes inside which the planes are placed + +[nplanes,slask] = size(planeeqs); + +minvals = zeros(nplanes,3); +maxvals = zeros(nplanes,3); + +for ii = 1:nplanes + cornerlist = planecorners(ii,:); + cornerlist = cornerlist( find(cornerlist~= 0) ); + cornercoord = corners(cornerlist,:); + minvals(ii,:) = min(cornercoord); + maxvals(ii,:) = max(cornercoord); +end + +minvals = minvals - geomacc; +maxvals = maxvals + geomacc; + +%--------------------------------------------------------------- +% Check the geometry a bit + +if isempty(checkgeom) + checkgeom = 0; +else + if setstr(checkgeom(1)) == 'c' + checkgeom = 1; + else + checkgeom = 0; + end +end + +if checkgeom + + badproblem = 0; + disp(' ') + disp(' Checking if there are corners with identical coordinates') + for ii = 1:ncorners-1 + othercorners = [ii+1:ncorners]; + iv = find((corners(othercorners,1)==corners(ii,1)) & (corners(othercorners,2)==corners(ii,2)) & (corners(othercorners,3)==corners(ii,3))); + if ~isempty(iv) + disp([' WARNING: corner ',int2str(ii),' and ',int2str(othercorners(iv(1))),' have the same coordinates']) + disp([' This should be fixed in the CAD-file or in the CATT-model']) + badproblem = 1; + end + end + + disp(' Checking if there are unused corners') + iv = find(planesatcorners(:,1)==0); + if ~isempty(iv) + disp(' WARNING: The following corners in the CAD-file are not used:') + printvec = int2str(cornernumbers(iv(1))); + for iiprint = 2:length(iv) + printvec = [printvec,' ',int2str(cornernumbers(iv(iiprint)))]; + end + disp([' ',printvec]) + disp([' This is not a big problem']) + planesatcorners(iv,:) = []; + end + + disp(' Checking if any corners seem redundant') + iv = find(planesatcorners(:,2)==0); + if ~isempty(iv) + disp(' WARNING: The following corners in the CAD-file belong to only one plane:') + printvec = int2str(cornernumbers(iv(1))); + for iiprint = 2:length(iv) + printvec = [printvec,' ',int2str(cornernumbers(iv(iiprint)))]; + end + disp([' ',printvec]) + disp([' This should be fixed in the CAD-file or in the CATT-model']) + badproblem = 1; + end + + if badproblem == 1 + disp(' '); + error(['ERROR: Problems with the geometry defined in the CAD-file: ',CADfile]) + end + +end + +%--------------------------------------------------------------- +% Save the relevant variables in the output file + +% NB! Sparse matrices can not get a non-double format + +if ncorners < 256 + planecorners = uint8(planecorners); +elseif ncorners < 65536 + planecorners = uint16(planecorners); +end + +if max(ncornersperplanevec) <= 255 + ncornersperplanevec = uint8(ncornersperplanevec); + planehasindents = uint8(planehasindents); +else + ncornersperplanevec = uint16(ncornersperplanevec); + planehasindents = uint16(planehasindents); +end + +Varlist = [' corners cornernumbers planecorners planenames planeabstypes ']; +Varlist = [Varlist,' planenumbers cornercrossref ']; +Varlist = [Varlist,' planeeqs planenvecs ncornersperplanevec planesatcorners nplanespercorners']; +Varlist = [Varlist,' minvals maxvals planehasindents indentingcorners']; +%Varlist = [Varlist,' Scoords Sdirections Srotations Slevels Rnumbers Rcoords CATTversionnumber']; + +planenames = sparse(planenames+1-1); +planeabstypes = sparse(planeabstypes+1-1); +%Sdirectivitynames = sparse(Sdirectivitynames+1-1); + +eval(['save ',outputfile,Varlist]) + +end + +function [p_Plane, p_Norm, p_Mat] = read_ac3d_surface(fid, i_Vertices) + tline = fgetl(fid); + tokens = readLineToToken(tline); + if(~strcmp(tokens{1},'SURF')) + disp(['surface section does not start with SURF',tokens{1}]); + end + if(~strcmp(tokens{2},'0x10')) + disp(['only polygons are accepted TODO?', tokens{2}]); + end + + tline = fgetl(fid); + tokens = readLineToToken(tline); + if(~strcmp(tokens{1},'mat')) + disp('missing expected token "mat"'); + end + p_Mat=str2num(tokens{2}); + + tline = fgetl(fid); + tokens = readLineToToken(tline); + + if(~strcmp(tokens{1},'refs')) + disp('surface section missing refs'); + end + + p_NumberOfRefs = str2num(tokens{2}); + + if(tokens{2}<3) + disp(['too less points in surface:',tokens{2}]); + return; + end + + p_Plane=zeros(p_NumberOfRefs,1); + + for r=1:p_NumberOfRefs + tline = fgetl(fid); + tokens = readLineToToken(tline); + p_Plane(r)=str2num(tokens{1})+1; + end + + v1 = i_Vertices(:,p_Plane(2))-i_Vertices(:,p_Plane(1)); + v2 = i_Vertices(:,p_Plane(3))-i_Vertices(:,p_Plane(1)); + p_Norm = cross(v1,v2); + p_Norm = p_Norm./norm(p_Norm); +end + +function [token] = readLineToToken(tline) + [token{1}, remain] = strtok(tline); + i=1; + while(remain~=0) + i=i+1; + tline = remain; + [token{i}, remain] = strtok(tline); + end +end + +function [p_Object] = read_ac3d_object(fid, i_LocalMatrix) + + tline = fgetl(fid); + tokens = readLineToToken(tline); + if(~strcmp(tokens{1},'OBJECT')) + disp('Section does not start with "object"'); + end + if(strcmp(tokens{2},'poly')) + p_Object = read_ac3d_poly(fid, i_LocalMatrix); + elseif(strcmp(tokens{2},'group')) + disp('GROUP not implemented yet'); + elseif(strcmp(tokens{2},'light')) + disp('LIGHT not implemented yet'); + else + disp('Section does not start with valid key'); + end +end +function [p_Polygon] = read_ac3d_poly(fid, i_LocalMatrix) + + p_LocalMatrix = [1.0 0.0 0.0 0.0; + 0.0 1.0 0.0 0.0; + 0.0 0.0 1.0 0.0; + 0.0 0.0 0.0 1.0]; + + tline = fgetl(fid); + + p_Vertices=0; + while(ischar(tline)) + tokens = readLineToToken(tline); + + if(strcmp(tokens{1},'numvert')) + + p_ResultMatrix = i_LocalMatrix * p_LocalMatrix; + + p_NumVertices=str2num(tokens{2}); + p_Vertices=zeros(3,p_NumVertices); + for l=1:p_NumVertices + tline = fgetl(fid); + tokens = readLineToToken(tline); + if(~ischar(tline)) + disp(['unexpected EOF while reading vertex (', num2str(l),'/',num2str(p_NumVertices)]); + end + if(size(tokens,2)~=3) + disp(['error while reading vertex coords (', num2str(l),'/',num2str(p_NumVertices)]); + end + + p_Vec = p_ResultMatrix * [str2num(tokens{1}); str2num(tokens{2}); str2num(tokens{3}); 1]; + p_Vertices(:,l) = p_Vec(1:3); + end + + elseif(strcmp(tokens{1},'numsurf')) + p_NumSurfaces=str2num(tokens{2}); + for s=1:p_NumSurfaces + [p_Planes{s}, p_Norms{s}, p_Mats{s}] = read_ac3d_surface(fid, p_Vertices); + end + elseif(strcmp(tokens{1},'loc')) + p_LocalMatrix(1,4)=str2num(tokens{2}); + p_LocalMatrix(2,4)=str2num(tokens{3}); + p_LocalMatrix(3,4)=str2num(tokens{4}); + elseif(strcmp(tokens{1},'rot')) + p_LocalMatrix(1,1)=str2num(tokens{2}); + p_LocalMatrix(1,2)=str2num(tokens{3}); + p_LocalMatrix(1,3)=str2num(tokens{4}); + p_LocalMatrix(2,1)=str2num(tokens{5}); + p_LocalMatrix(2,2)=str2num(tokens{6}); + p_LocalMatrix(2,3)=str2num(tokens{7}); + p_LocalMatrix(3,1)=str2num(tokens{8}); + p_LocalMatrix(3,2)=str2num(tokens{9}); + p_LocalMatrix(3,3)=str2num(tokens{10}); + elseif(strcmp(tokens{1},'kids')) + if(str2num(tokens{2})>2) + disp(['Warning: Kids of Polygon not handled yet:',tokens{2}]) + p_Polygon=0; + return; + end + p_Polygon{1}=p_Vertices; + p_Polygon{2}=p_Planes; + p_Polygon{3}=p_Norms; + p_Polygon{4}=p_Mats; + return; + else + if(strcmp(tokens{1},'name')) + % Only name of poly, irrelevant -->SKIP + elseif(strcmp(tokens{1},'crease')) + else + disp(['Warning: Ignored Entry in AC3D File: ', tokens{1}]); + end + end + tline = fgetl(fid); + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/private/EDB1readcad.m Sat Nov 16 18:25:24 2013 +0000 @@ -0,0 +1,734 @@ +function [outputfile] = EDB1readcad(CADfile,outputfile,planecornerstype,checkgeom) +% EDB1readcad - Reads a file of type .CAD (made by e.g. CATT-Acoustic) and saves all the geometry data in a mat-file. +% CAD-files v6,v7,v8 are read. +% +% Input parameters: +% CADfile (optional) The input file, with or without the .CAD extension. +% If this file is not specified, a file opening window will appear. +% outputfile (optional) The output file. If not specified, it will be given the +% same name as the CAD file with an '_cadgeo.mat' ending instead of the '.CAD'. +% planecornerstype (optional) Could have the value 'zero' or 'circ'.Default: 'circ'. +% Affects the matrix planecorners, see below. +% checkgeom (optional) If this parameter is given the value 'check', then a few checks +% of the geometry consistency will be done: a check for duplicate corners +% for redundant corners and for corners that are connected to only one plane. +% Only warnings are given. As default, no check is done. +% SHOWTEXT (global) If this global parameter has the value 3 or higher, informative text will +% be printed on the screen. +% +% Output parameters: +% outputfile The name of the outputfile, generated either automatically or specified as +% an input parameter. +% +% Output parameters in the outputfile: +% corners Matrix [ncorners,3] with the corner coordinates +% cornernumbers Vector [ncorners,1] with the corner numbers used in the CAD-file. That is +% in the outputfile, the corners will effectively be renumbered from 1 to ncorners +% in the order they appeared in the CAD-file. +% planecorners Matrix [planes,nmaxcornersperplane] with the corner numbers that make up each plane. +% Since planes can have different numbers of corners, the number of columns is the +% maximum number of corners that any plane has. NB! The corner numbers are in the +% renumbered system, not in the CAD-file system. +% planenames Matrix [nplanes,nmaxcharacters1] (sparse), with the planenames in the CAD file. +% planeabstypes Matrix [nplanes,nmaxcharacters2] (sparse), with the absorber names in the CAD file. +% planenumbers Vector [nplanes,1] with the plane numbers used in the CAD file. +% cornercrossref Vector [nmaxnumberinCADfile,1] (sparse), which gives the matlab-file corner +% numbers for each CAD-file corner number. For instance, if a CAD-file corner +% number 1200 is translated to corner number 72 in the matlab-file, then +% cornercrossref(1000) = 72. +% Snumbers Vector [nsources,1] of the source numbers in the CAD-file. NB! Only CAD-files +% v6 use source numbers; later versions use source names instead of numbers. +% For CAD-file v7 and v8, Snumbers is empty. +% Snames Matrix [nsources,2] of the source names in the CAD-file. NB! Only CAD-files v7 +% or later use source names (such as 'A0' etc). Older versions use source numbers, +% in which case Snames is empty. +% Sdirectivitynames Matrix [nsources,nmaxcharacters3] (sparse) with the source directivity names +% in the CAD file. +% Sdelays Vector [nsources,1] of the source delays in the CAD-file, in milliseconds. +% Scoords Matrix [nsources,3] of the source coordinates. +% Sdirections Matrix [nsources,3] of the aim point coordinates for the sources. +% Srotations Vector [nsources,1] of the source rotations, in degrees. +% Slevels Matrix [nsources,6/8] of the source levels for six (CAD-files v6) or eight +% octave bands (CAD-files v7 or later). +% Rnumbers Vector [nreceivers,1] of the receiver numbers in the CAD-file. +% Rcoords Matrix [nreceivers,3] of the receiver coordinates. +% CATTversionnumber 6,7 or 8 +% planeeqs Matrix [nplanes,4] of the plane equations as derived from the plane definitions. +% Each row has the values [A B C D] of the plane equation on the form Ax + By + Cz = D +% planenvecs Matrix [nplanes,3] of the normalized normal vectors of the planes. +% ncornersperplanevec Vector [nplanes,1] which gives the number of corners for each plane. +% planesatcorners Matrix [ncorners,4] which gives the plane numbers that each corner is connected to. +% NB! Here it is assumed that each corner is connected to maximum four planes. +% nplanespercorners Vector [ncorners,1] which gives the number of planes that each corner is connected to. +% minvals Matrix [nplanes,3] which for each plane gives the smallest coordinate in the x-, y- and z-direction. +% maxvals Matrix [nplanes,3] which for each plane gives the largest coordinate in the x-, y- and z-direction. +% planehasindents Vector [nplanes,1] which for each plane gives the +% number of indeting corners +% indentingcorners Matrix [nplanes,max(ncornersperplanevec)] which for each plane gives the number to the first corner +% in a corner triplet which identifies an indenting corner. The number of the corner is the +% order given in planecorners for that plane. +% +% Uses the functions EDB1extrnums, EDB1cross +% +% ---------------------------------------------------------------------------------------------- +% This file is part of the Edge Diffraction Toolbox by Peter Svensson. +% +% The Edge Diffraction Toolbox is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) any later version. +% +% The Edge Diffraction Toolbox is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +% FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License along with the +% Edge Diffraction Toolbox. If not, see <http://www.gnu.org/licenses/>. +% ---------------------------------------------------------------------------------------------- +% Peter Svensson (svensson@iet.ntnu.no) 20090718 +% +% [outputfile] = EDB1readcad(CADfile,outputfile,planecornerstype,checkgeom); + +global SHOWTEXT + +if nargin == 0 + CADfile = ''; + outputfile = ''; + planecornerstype = ''; + checkgeom = ''; +elseif nargin == 1 + outputfile = ''; + planecornerstype = ''; + checkgeom = ''; +elseif nargin == 2 + planecornerstype = ''; + checkgeom = ''; +elseif nargin == 3 + checkgeom = ''; +end + +geomacc = 1e-10; + +%--------------------------------------------------------------- +% If no CAD-file was specified, present a file opening window + +if isempty(CADfile) + [CADfile,filepath] = uigetfile('*.cad','Please select the CADfile'); + [filepath,temp1,temp2] = fileparts(filepath); + if ~isstr(CADfile) + return + end + [temp1,filestem,temp2] = fileparts(CADfile); + + CADfile = [[filepath,filesep],filestem,'.cad']; +else + [filepath,filestem,fileext] = fileparts(CADfile); + CADfile = [[filepath,filesep],filestem,fileext]; +end + +if exist(CADfile) ~= 2 + error(['ERROR: CAD-file: ',CADfile,' can not be found']) +end + +%--------------------------------------------------------------- +% If no output file was specified, construct an automatic file name + +if isempty(outputfile) + outputfile = [[filepath,filesep],filestem,'_cadgeo.mat']; +end + +%--------------------------------------------------------------- +% Read in the entire file into the string B +% Find the line starts and ends + +fid = fopen([CADfile],'r'); +if fid == 0 + error(['ERROR: The CADfile ',CADfile,' could not be opened.']) +end +B = fread(fid,inf,'char').'; +fclose(fid); + +% Cut out sequential spaces to save some space. +iv = find(B(1:length(B)-1)==32 & B(2:length(B))==32); +B(iv) = []; + +% If the text file was generated on a Mac, each line has ASCII 13 at the end. +% On a PC, each line ends with ASCII 13, and the next line starts with ASCII 10. +% In Unix, each line ends with ASCII 10. +% +% Change this to a single ASCII 13 + +% New 17 Jul 09: use the builtin function regexprep instead: + +% 1. Replace all ASCII 10 by ASCII 13 + +B = regexprep(setstr(B),'\n','\r'); + +% 2. Cut out sequential CRs (ASCII13) to save some space. +iv = find(B(1:length(B)-1)==13 & B(2:length(B))==13); +B(iv) = []; + +% 3. Cut out sequences of CR, space, CR because they "survived" the +% search for consecutive blanks. +iv = find(B(1:length(B)-1)==32 & B(2:length(B))==13); +B(iv) = []; +iv = find(B(1:length(B)-1)==13 & B(2:length(B))==13); +B(iv) = []; + +% 4. Convert all text to lower case +B = lower(setstr(B)); + +% Some special characters might give negative ASCII values +% (Comment by PS 17Jul09: Will this ever happen??) + +iv = find(B<0); +if ~isempty(iv) + B(iv) = B(iv)+256; +end + +%--------------------------------------------------------------- +% Look for the text 'CATT-Acoustic v' anywhere, and read the numerical +% value right after this text. + +iv = regexp(B,'catt-acoustic v'); + +if isempty(iv) + CATTversionnumber = []; +else + CATTversionnumber = str2num(setstr(B(iv(1)+15))); +end + +%--------------------------------------------------------------- +% Find the four sections of the file: +% %CORNERS %PLANES %SOURCES %RECEIVERS +% (or small letters) +% We assume that they come in this order + +stringposCORNERS = regexp(B,'%corners'); +if isempty(stringposCORNERS) + error('ERROR: The .cad file must contain the word %CORNERS'); +end + +stringposPLANES = regexp(B,'%planes'); +if isempty(stringposPLANES) + error('ERROR: The .cad file must contain the word %PLANES'); +end + +stringposSOURCES = regexp(B,'%sources'); + +stringposRECEIVERS = regexp(B,'%receivers'); + +%--------------------------------------------------------------- +% Look for the corners definitions between the lines containing +% %SOURCES and another keyword (%PLANES or %SOURCES or %RECEIVERS) +% The lines should look like: +% 1 -0.2000 0.34 2.3 + +if stringposPLANES < stringposCORNERS + error('ERROR: Sorry, but in the .cad file, the %CORNERS section must come before the %PLANES section') +end + +C = textscan(B(stringposCORNERS:stringposPLANES-1),'%d%f%f%f','Headerlines',1); +cornernumbers = (C{1}); +corners = [C{2} C{3} C{4}]; +ncorners = length(cornernumbers); + +%--------------------------------------------------------------- +% Look for the planes definitions between the lines containing +% %PLANES and %SOURCES, or the end +% The lines should look like: +% 1 / planename /RIGID +% 1 4 3 2 +% 2 / /RIGID + +if ~isempty(stringposSOURCES) + if stringposSOURCES < stringposPLANES + error('ERROR: Sorry, but in the .cad file, the %PLANES section must come before the %SOURCES section') + end + Str = B(stringposPLANES:stringposSOURCES-1); +else + Str = B(stringposPLANES:end); +end + +% To make it easier with textscan, we put the two types of line onto +% a single line, with a new '/' inserted. Then all lines have the same +% format. + +% Find all CR and replace every second with a '/' +ivendlines = find(Str==13); +Str(ivendlines(2:2:end)) = '/'; + +C = textscan(Str,'%d%s%s%s','Headerlines',1,'Delimiter','/','BufSize',32768); + +planenumbers = C{1}; +Str2 = C{2}; +Str3 = C{3}; +Str = C{4}; + +nplanes = size(Str,1); +ncornersperplanevec = zeros(nplanes,1); +planecorners = zeros(nplanes,4); +planenames = zeros(nplanes,30); +planeabstypes = zeros(nplanes,6); + +for ii = 1:nplanes + listofplanes = EDB1extrnums(Str{ii}); + ncornersperplanevec(ii) = length(listofplanes); + if ncornersperplanevec(ii) > size(planecorners,2) + planecorners = [planecorners zeros(nplanes, ncornersperplanevec(ii)-size(planecorners,2))]; + end + planecorners(ii,1:ncornersperplanevec(ii)) = listofplanes; + + txtstr2 = Str2{ii}; + if length(txtstr2) > size(planenames,2) + planenames = [planenames zeros(nplanes,length(txtstr2)-size(planenames,2))]; + end + planenames(ii,1:length(txtstr2)) = txtstr2; + + txtstr3 = Str3{ii}; + if length(txtstr3) > size(planeabstypes,2) + planeabstypes = [planeabstypes zeros(nplanes,length(txtstr3)-size(planeabstypes,2))]; + end + planeabstypes(ii,1:length(txtstr3)) = txtstr3; +end + +if max(max(planecorners)) > max(cornernumbers) + error('ERROR: One plane definition in the CAD-file used a higher corner number than was defined in the CORNERS section') +end + +%--------------------------------------------------------------- +% Look for the sources definitions between the lines containing +% %SOURCES and %RECEIVERS, or the end +% The lines should look like: (v6) +% 0 OMNI:SD0 +% 0.0000000 0.0000000 1.0000000 +% 0.0000000 0.0000000 0.0000000 +% 85.0 88.0 91.0 94.0 97.0 100.0 +% +% or: (v7) +% A0 OMNI:SD0 +% 0.0000000 0.0000000 1.0000000 +% 0.0000000 0.0000000 0.0000000 15.00000 +% 85.0 88.0 91.0 94.0 97.0 100.0 : 103.0 106.0 + +if ~isempty(stringposSOURCES) + + if ~isempty(stringposRECEIVERS) + if stringposRECEIVERS < stringposSOURCES + error('ERROR: Sorry, but in the .cad file, the %SOURCES section must come before the %RECEIVERS section') + end + Str = B(stringposSOURCES:stringposRECEIVERS-1); + else + Str = B(stringposSOURCES:end); + end + + % To make it easier with textscan, we put the four types of line onto + % a single line, with new '/' inserted. Then all lines have the same + % format. + % Find all CR and replace number 2,3,4, 6,7,8, etc with a '/' + + ivendlines = find(Str==13); + ivkeep = [1:4:length(ivendlines)]; + ivremove = [1:length(ivendlines)]; + ivremove(ivkeep) = []; + Str(ivendlines(ivremove)) = '/'; + + C = textscan(Str,'%s%s%s%s','Headerlines',1,'Delimiter','/'); + + nsources = size( C{1},1 ); + Scoords = zeros(nsources,3); + Sdirections = zeros(nsources,3); + Srotations = zeros(nsources,1); + Slevels = zeros(nsources,8); + Snumbers = zeros(nsources,1); + Snames = zeros(nsources,4); + Sdirectivitynames = ( zeros(nsources,30) ); + Sdelays = zeros(nsources,1); + + Str1 = C{1}; + Str2 = C{2}; + Str3 = C{3}; + Str4 = C{4}; + for ii = 1:nsources + Scoords(ii,:) = EDB1extrnums(Str2{ii}); + listofvalues3 = EDB1extrnums(Str3{ii}); + listofvalues4 = EDB1extrnums(Str4{ii}); + if ii==1 + if length(listofvalues3)==3 + CATTversionnumber = 6; + elseif length(listofvalues3)==4 + CATTversionnumber = 7; + else + error('ERROR: The source data should have three or four values for the direction') + end + end + + Sdirections(ii,1:3) = listofvalues3(1:3); + + % The first field contains three items which are a mix of text and numerical values. + % First we remove possible consecutive blanks. + textstr = Str1{ii}; + iv = find(textstr(1:length(textstr)-1)==32 & textstr(2:length(textstr))==32); + textstr(iv) = []; + iv = find(textstr==32); + + + if CATTversionnumber == 7 + Srotations(ii) = listofvalues3(4); + Snames(ii,1:length(textstr(1:iv(1)-1))) = textstr(1:iv(1)-1); + Sdirectivitynames(ii,1:iv(2)-iv(1)-1) = textstr(iv(1)+1:iv(2)-1); + Sdelays(ii) = str2num( textstr(iv(2)+1:end) ); + else + Snumbers(ii) = str2num( textstr(1:iv(1)-1) ); + Sdirectivitynames(ii,1:length(textstr(iv(1)+1:end))) = textstr(iv(1)+1:end); + end + Slevels(ii,1:length(listofvalues4)) = listofvalues4; + end + Snames = setstr(Snames); + Sdirectivitynames = setstr(Sdirectivitynames); + +else + + Scoords = []; + Sdirections = []; + Srotations = []; + Slevels = []; + Snumbers = []; + Snames = []; + Sdirectivitynames = []; + Sdelays = []; + +end + +%--------------------------------------------------------------- +% Look for the receivers definitions after the line containing +% %RECEIVERS +% The lines should look like: +% 1 -0.2000 0.34 2.3 + +if ~isempty(stringposRECEIVERS) + C = textscan(B(stringposRECEIVERS:end),'%d%f%f%f','Headerlines',1); + Rnumbers = (C{1}); + Rcoords= [C{2} C{3} C{4}]; +else + Rnumbers = []; + Rcoords = []; +end + +%--------------------------------------------------------------- +% Change the numbering in the CAD file to a contiguous one + +% Corner numbers +% First we make an inelegant crossreference vector giving the +% resulting corner number in the position given by the CAD-file +% corner number. + +maxnumb = max(cornernumbers); +cornercrossref = sparse(zeros(1,maxnumb)); + +% Temporary fix: if one corner has the number zero, then we make a +% separate crossref variable for that one. +if cornernumbers(1) == 0 + cornercrossrefzero = 1; + cornercrossref(cornernumbers(2:end)) = [2:ncorners]; +else + cornercrossrefzero = []; + cornercrossref(cornernumbers) = [1:ncorners]; +end + +[nplanes,ncornersperplane] = size(planecorners); + +planecorners_CATTnumbers = planecorners; + +iv = find(planecorners_CATTnumbers~=0); +planecorners(iv) = full(cornercrossref(planecorners(iv))); +iv = find(planecorners_CATTnumbers==0); +planecorners(iv) = cornercrossrefzero; + +%--------------------------------------------------------------- +% Go through all planes. If there is a plane definition including +% zeros, and planecornerstype == 'circ', expand it repeating the +% same corner order again. + +if isempty(planecornerstype) + planecornerstype = 'circ'; +else + planecornerstype = setstr(lower(planecornerstype(1))); + if planecornerstype(1) == 'z' + planecornerstype = 'zero'; + else + planecornerstype = 'circ'; + end +end + +if planecornerstype == 'circ' + for ii = 1:nplanes + iv = find( planecorners(ii,:) ~= 0); + ncornersatplane = length(iv); + if ncornersatplane ~= ncornersperplane + pattern = planecorners(ii,iv); + nrepeatings = ceil(ncornersperplane/ncornersatplane); + for jj = 1:nrepeatings-1 + pattern = [pattern planecorners(ii,iv)]; + end + planecorners(ii,:) = pattern(1:ncornersperplane); + end + end +end + +%--------------------------------------------------------------- +% Find the normal vectors to the planes using the cross products +% +% The normal vector is basically the cross product between two vectors +% connecting three consecutive points. If there are indents though +% they will cause reversed normal vectors, so one must go through all +% combinations and choose the majority normal vector. +% +% 26mar09 Use the fact described above for detecting indention corners + +planenvecs = zeros(nplanes,3); +planehasindents = zeros(nplanes,1); +indentingcorners = sparse(zeros(nplanes,max(ncornersperplanevec))); + +for ii = 1:nplanes + + iv = find(planecorners(ii,:)~=0); + cornerlist = planecorners(ii,iv); + iv = find(cornerlist == cornerlist(1)); + if length(iv) > 1 + cornerlist = cornerlist(1:iv(2)-1); + end + ncorners = length( cornerlist ); + cornerlist = [cornerlist cornerlist(1) cornerlist(2)]; + + nvectorlist = zeros(ncorners,3); + nveclen = zeros(ncorners,1); + + for jj = 1:ncorners + co1numb = cornerlist(jj); + co2numb = cornerlist(jj+1); + co3numb = cornerlist(jj+2); + vec1 = corners(co1numb,:) - corners(co2numb,:); + vec2 = corners(co3numb,:) - corners(co2numb,:); + nvec = EDB1cross(vec1.',vec2.').'; + nveclen(jj) = norm(nvec); + if nveclen(jj) > 0 + nvectorlist(jj,:) = nvec./nveclen(jj); + end + end + + iv = find(nveclen < max(nveclen)*0.001); + nvectorlist(iv,:) = []; + nvecref = nvectorlist(1,:); + + [n1,slask] = size(nvectorlist); + nvecsigns = round(sum( (nvectorlist.').*(nvecref(ones(n1,1),:).') )); + + if sum(nvecsigns) == 0 + disp(' ') + error(['ERROR: Plane ',int2str(planenumbers(ii)),' (plane numbering as in the CAD file) seems to be twisted.']) + end + + + if abs(sum(nvecsigns)) ~= n1 + disp(['Plane ',int2str(ii),' has indents!']) + nindents = (n1 - abs(sum(nvecsigns)))/2; + planehasindents(ii) = nindents; + ivindent = find(nvecsigns == -1); + if length(ivindent) == nindents + indentingcorners(ii,ivindent) = 1; + else + if length(ivindent) == ncorners - nindents + ivindent = find(nvecsigns == 1); + indentingcorners(ii,ivindent) = 1; + else + error(['ERROR: An unexpected problem. Please report to the developer']) + end + end + end + + nvecdiff = [nvectorlist(2:n1,1).*nvecsigns(2:n1).' nvectorlist(2:n1,2).*nvecsigns(2:n1).' nvectorlist(2:n1,3).*nvecsigns(2:n1).'] - nvecref(ones(n1-1,1),:); + + if n1 > 2 + nvecdiff = sum(nvecdiff.'.^2).'; + else + nvecdiff = norm(nvecdiff); + end + if any(nvecdiff>1e-4), + nvecdiff + error(['ERROR: Normal vectors for plane ',int2str(planenumbers(ii)),' (in the CAD file, = ',int2str(ii),' in the EDB1 file), get different normal vectors for consecutive corner triplets. Check the geometry in the CAD-file']) + elseif any(nvecdiff>1e-8) + nvecdiff + disp(['WARNING: Normal vectors for plane ',int2str(planenumbers(ii)),' (in the CAD file, = ',int2str(ii),' in the EDB1 file), get somewhat different normal vectors for consecutive corner triplets. Check the geometry in the CAD-file']) + end + + if ncorners > 5 & abs(sum(nvecsigns)) <= 1 + disp(['WARNING for plane number ',int2str(planenumbers(ii)),' in the CAD-file']) + disp([' with the name ',strtrim(setstr(full(planenames(ii,:))))]) + disp(' The normal vector can not be determined for this plane because there are') + disp(' the same number of inwards and outwards corners') + disp(' This is a list of the possible normal vectors:') + [nv1,slask] = size(nvectorlist); + for kk = 1:nv1 + vecstr = [' ',int2str(kk),'. ',num2str(-nvectorlist(kk,1)),' ',num2str(-nvectorlist(kk,2)),' ',num2str(-nvectorlist(kk,3))]; + disp(vecstr) + end + disp(' ') + + preferredsign = input(' Give the number of a correct normal vector for this plane please '); + switchsign = nvecsigns.'./nvecsigns(preferredsign); + nvectorlist = nvectorlist.*switchsign(:,ones(1,3)); + else + mostcommonsign = sign(sum(nvecsigns)); + + switchsign = nvecsigns.'./mostcommonsign; + nvectorlist = nvectorlist.*switchsign(:,ones(1,3)); + end + + planenvecs(ii,:) = mean(nvectorlist); +end + +planenvecs = -planenvecs; + +%--------------------------------------------------------------- +% Plane equations, as Ax + By + Cz = D for each plane + +planeeqs = zeros(nplanes,4); +planeeqs(:,1:3) = planenvecs; +planeeqs(:,4) = sum( (planenvecs.').*(corners(planecorners(:,1),:).') ).'; + +%--------------------------------------------------------------- +% Useful data: planesatcorners, minvals and maxvals + +[ncorners,slask] = size(corners); +planesatcornerhits = zeros(ncorners,nplanes); + +for ii = 1:nplanes + cornerlist = planecorners(ii,1:ncornersperplanevec(ii)); + planesatcornerhits(cornerlist,ii) = planesatcornerhits(cornerlist,ii) + 1; +end + +maxplanespercorner = 0; +for ii = 1:ncorners + nplanes = length(find(planesatcornerhits(ii,:) ~= 0)); + if nplanes > maxplanespercorner + maxplanespercorner = nplanes; + end +end + +planesatcorners = zeros(ncorners,maxplanespercorner); +nplanespercorners = zeros(ncorners,1); +for ii = 1:ncorners + iv = find(planesatcornerhits(ii,:)~=0); + planesatcorners(ii,1:length(iv)) = iv; + nplanespercorners(ii) = length(iv); +end + +% find cubic boxes inside which the planes are placed + +[nplanes,slask] = size(planeeqs); + +minvals = zeros(nplanes,3); +maxvals = zeros(nplanes,3); + +for ii = 1:nplanes + cornerlist = planecorners(ii,:); + cornerlist = cornerlist( find(cornerlist~= 0) ); + cornercoord = corners(cornerlist,:); + minvals(ii,:) = min(cornercoord); + maxvals(ii,:) = max(cornercoord); +end + +minvals = minvals - geomacc; +maxvals = maxvals + geomacc; + +%--------------------------------------------------------------- +% Check the geometry a bit + +if isempty(checkgeom) + checkgeom = 0; +else + if setstr(checkgeom(1)) == 'c' + checkgeom = 1; + else + checkgeom = 0; + end +end + +if checkgeom + + badproblem = 0; + disp(' ') + disp(' Checking if there are corners with identical coordinates') + for ii = 1:ncorners-1 + othercorners = [ii+1:ncorners]; + iv = find((corners(othercorners,1)==corners(ii,1)) & (corners(othercorners,2)==corners(ii,2)) & (corners(othercorners,3)==corners(ii,3))); + if ~isempty(iv) + disp([' WARNING: corner ',int2str(ii),' and ',int2str(othercorners(iv(1))),' have the same coordinates']) + disp([' This should be fixed in the CAD-file or in the CATT-model']) + badproblem = 1; + end + end + + disp(' Checking if there are unused corners') + iv = find(planesatcorners(:,1)==0); + if ~isempty(iv) + disp(' WARNING: The following corners in the CAD-file are not used:') + printvec = int2str(cornernumbers(iv(1))); + for iiprint = 2:length(iv) + printvec = [printvec,' ',int2str(cornernumbers(iv(iiprint)))]; + end + disp([' ',printvec]) + disp([' This is not a big problem']) + planesatcorners(iv,:) = []; + end + + disp(' Checking if any corners seem redundant') + iv = find(planesatcorners(:,2)==0); + if ~isempty(iv) + disp(' WARNING: The following corners in the CAD-file belong to only one plane:') + printvec = int2str(cornernumbers(iv(1))); + for iiprint = 2:length(iv) + printvec = [printvec,' ',int2str(cornernumbers(iv(iiprint)))]; + end + disp([' ',printvec]) + disp([' This should be fixed in the CAD-file or in the CATT-model']) + badproblem = 1; + end + + if badproblem == 1 + disp(' '); + error(['ERROR: Problems with the geometry defined in the CAD-file: ',CADfile]) + end + +end + +%--------------------------------------------------------------- +% Save the relevant variables in the output file + +% NB! Sparse matrices can not get a non-double format + +if ncorners < 256 + planecorners = uint8(planecorners); +elseif ncorners < 65536 + planecorners = uint16(planecorners); +end + +if max(ncornersperplanevec) <= 255 + ncornersperplanevec = uint8(ncornersperplanevec); + planehasindents = uint8(planehasindents); +else + ncornersperplanevec = uint16(ncornersperplanevec); + planehasindents = uint16(planehasindents); +end + +Varlist = [' corners cornernumbers planecorners planenames planeabstypes ']; +Varlist = [Varlist,' planenumbers cornercrossref cornercrossrefzero Snumbers Snames Sdirectivitynames Sdelays']; +Varlist = [Varlist,' Scoords Sdirections Srotations Slevels Rnumbers Rcoords CATTversionnumber']; +Varlist = [Varlist,' planeeqs planenvecs ncornersperplanevec planesatcorners nplanespercorners']; +Varlist = [Varlist,' minvals maxvals planehasindents indentingcorners']; + +planenames = sparse(planenames+1-1); +planeabstypes = sparse(planeabstypes+1-1); +Sdirectivitynames = sparse(Sdirectivitynames+1-1); + +eval(['save ',outputfile,Varlist])
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/private/EDB1readsetup.m Sat Nov 16 18:25:24 2013 +0000 @@ -0,0 +1,487 @@ +function setupmatfile = EDB1readsetup(EDsetupfile,cadgeofiletoopen) +% EDB1readsetup - Runs the EDsetup m-file and saves all the settings in a mat-file. +% If the sources and receivers should be taken from the +% CAD-file, they will be extracted and saved in the setupmatfile. +% +% Input parameters: +% EDsetupfile The name of the EDsetupfile (an m-file) that +% should be read. +% cadgeofiletoopen (optional) If the CAD file has already been read +% and stored as a cadgeofile, the cadgeofile could +% be used instead of the CAD-file. +% SHOWTEXT (global) Determines to what degree text will be printed out on the screen. +% +% Output parameters: +% setupmatfile The name of the output file. The name is created +% from the Filestem in the setupfile, with +% "_setup.mat" added. +% +% ---------------------------------------------------------------------------------------------- +% This file is part of the Edge Diffraction Toolbox by Peter Svensson. +% +% The Edge Diffraction Toolbox is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) any later version. +% +% The Edge Diffraction Toolbox is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +% FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License along with the +% Edge Diffraction Toolbox. If not, see <http://www.gnu.org/licenses/>. +% ---------------------------------------------------------------------------------------------- +% Peter Svensson (svensson@iet.ntnu.no) 20100518 +% +% setupmatfile = EDB1readsetup(EDsetupfile,cadgeofile); + +global SHOWTEXT + +if nargin == 1 + cadgeofiletoopen = []; +end + +[EDsetupfilepath,EDsetupfile,fileext] = fileparts(EDsetupfile); +EDsetupfilepath = [EDsetupfilepath,filesep]; + +eval(['cd ''',EDsetupfilepath,'''']) + +comptype = computer; +if length(comptype) == 3 + comptype = [comptype,'P']; +end + +if comptype(1:4) == 'MACI' + [temp1,tempfilestem,temp2] = fileparts(EDsetupfile); + eval([tempfilestem]) +else + if comptype(1:3) == 'MAC', % | comptype(1:3) == 'PCW' + eval([EDsetupfile]) + else + eval(['run ''',EDsetupfile,'''']) + end +end + +if exist('Filestem') ~= 1 + error(['ERROR: The setup file does not specify the Filestem']) +else + Varlist = [' Filestem']; +end + +%----------------------------------------------------------------------------------------- +% Check if the EDsetupfile specified the needed parameters + +if isempty(FSAMP) + error(['ERROR: FSAMP was not specified in ',EDsetupfile,'.m']) +else + Varlist = [Varlist,' FSAMP']; +end + +if isempty(RHOAIR) + error(['ERROR: RHOAIR was not specified in ',EDsetupfile,'.m']) +else + Varlist = [Varlist,' RHOAIR']; +end + +if isempty(CAIR) + error(['ERROR: CAIR was not specified in ',EDsetupfile,'.m']) +else + Varlist = [Varlist,' CAIR']; +end + +if exist('Filepath') ~= 1 + error(['ERROR: Filepath was not specified in ',EDsetupfile,'.m']) +else + Varlist = [Varlist,' Filepath']; +end + +if exist('Filestem') ~= 1 + error(['ERROR: Filestem was not specified in ',EDsetupfile,'.m']) +else + Varlist = [Varlist,' Filestem']; +end + +if (exist('CADfile') ~= 1) & isempty(cadgeofiletoopen) + error(['ERROR: CADfile or cadgeofile was not specified in ',EDsetupfile,'.m']) +else + if exist('CADfile') == 1 + Varlist = [Varlist,' CADfile']; + else + if exist('cadgeofiletoopen') + cadgeofile = cadgeofiletoopen; + Varlist = [Varlist,' cadgeofile']; + end + end +end + +if exist('open_or_closed_model') ~= 1 + error(['ERROR: open_or_closed_model was not specified in ',EDsetupfile,'.m',' Valid values are ''open'' and ''closed''']) +else + Varlist = [Varlist,' open_or_closed_model']; +end + +if exist('int_or_ext_model') ~= 1 + error(['ERROR: int_or_ext_model was not specified in ',EDsetupfile,'.m',' Valid values are ''int'' and ''ext''']) +else + Varlist = [Varlist,' int_or_ext_model']; +end + +if lower(open_or_closed_model(1)) == 'o' & lower(int_or_ext_model(1)) == 'i' + error(['ERROR: When a model is open, it must be an external model. int_or_ext_model was set to ''int''']) +end + +if exist('EDcalcmethod') ~= 1 + error(['ERROR: EDcalcmethod was not specified in ',EDsetupfile,'.m',' Valid values are n,k,v']) +else + Varlist = [Varlist,' EDcalcmethod']; +end + +if exist('directsound') ~= 1 + error(['ERROR: directsound was not specified in ',EDsetupfile,'.m',' Valid values are 0 and 1']) +else + Varlist = [Varlist,' directsound']; +end + +if exist('specorder') ~= 1 + error(['ERROR: specorder was not specified in ',EDsetupfile,'.m',' Valid values are integers >= 0']) +else + Varlist = [Varlist,' specorder']; +end + +if exist('difforder') ~= 1 + error(['ERROR: difforder was not specified in ',EDsetupfile,'.m',' Valid values are integers >= 0']) +else + Varlist = [Varlist,' difforder']; +end + +if specorder < difforder + error(['ERROR: specorder must be the same as, or larger than, difforder in this version of EDtoolbox!']) +end + +if difforder >=2 + if exist('elemsize') ~= 1 + error(['ERROR: elemsize was not specified in ',EDsetupfile,'.m']) + else + if min(elemsize) <= 0 + disp(['WARNING: elemsize was set smaller than zero']) + else + if length(elemsize) < difforder + error(['ERROR: elemsize must have one value for each diffraction order']) + else + Varlist = [Varlist,' elemsize']; + end + end + end +end + +if exist('sources') ~= 1 + error(['ERROR: sources were not specified in ',EDsetupfile,'.m']) +else + Varlist = [Varlist,' sources']; + [nsou,slask] = size(sources); +end + +if exist('receivers') ~= 1 + error(['ERROR: receivers were not specified in ',EDsetupfile,'.m']) +else + Varlist = [Varlist,' receivers']; +end + +%--------------------------------------------------------------------- +% Optional parameters that should get a default value + +if isempty(SHOWTEXT) + disp([' The parameter SHOWTEXT was not set. It will get the default value 0.']) + SHOWTEXT = 0; +end +Varlist = [Varlist,' SHOWTEXT']; + +if exist('SUPPRESSFILES') ~= 1 + disp([' The parameter SUPPRESSFILES was not set. It will get the default value 0.']) + SUPPRESSFILES = 0; +end +Varlist = [Varlist,' SUPPRESSFILES']; + +if exist('nedgesubs') ~= 1 + if SHOWTEXT > 0 + disp([' The parameter nedgesubs was not set. It will get the default value 2.']) + end + nedgesubs = 2; +else + if nedgesubs == 1 + nedgesubs = 2; + if SHOWTEXT > 0 + disp('WARNING! nedgesubs was set to 1 in the setup file but it is forced to 2') + end + end +end +Varlist = [Varlist,' nedgesubs']; + +if exist('saveindividualdiffirs') ~= 1 + if SHOWTEXT > 0 + disp([' The parameter saveindividualdiffirs was not set. It will get the default value [0 0].']) + end + saveindividualdiffirs = [0 0]; +else + if length(saveindividualdiffirs) == 1 + if SHOWTEXT > 0 + disp([' The parameter saveindividualdiffirs had just one value. It was expanded with a second default value 0.']) + end + saveindividualdiffirs = [saveindividualdiffirs 0]; + end +end +Varlist = [Varlist,' saveindividualdiffirs']; + +if exist('firstskipcorner') ~= 1 + if SHOWTEXT > 0 + disp([' The parameter firstskipcorner was not set. It will get the default value 1000000.']) + end + firstskipcorner = 1000000; +end +Varlist = [Varlist,' firstskipcorner']; + +if exist('doaddsources') ~= 1 + if nsou > 1 + disp([' The parameter doaddsources was not set. It will get the default value 0.']) + end + doaddsources = 0; +end +Varlist = [Varlist,' doaddsources']; + +if exist('dobackscatter') ~= 1 + dobackscatter = 0; +end +Varlist = [Varlist,' dobackscatter']; + +if dobackscatter*doaddsources == 1 + error(['ERROR: You have set both dobackscatter and doaddsources to 1. This does not make sense!']) +end + +if exist('Rstart') ~= 1 + if SHOWTEXT > 0 + disp([' The parameter Rstart was not set. It will get the default value 0.']) + end + Rstart = 0; +end +Varlist = [Varlist,' Rstart']; + +if exist('planeseesplanestrategy') ~= 1 + if SHOWTEXT > 0 + disp([' The parameter planeseesplanestrategy was not set. It will get the default value 0.']) + end + planeseesplanestrategy = 0; +end +Varlist = [Varlist,' planeseesplanestrategy']; + +%--------------------------------------------------------------------- +% Optional parameters + +if exist('eddatafile') + Varlist = [Varlist,' eddatafile']; +end +if exist('srdatafile') + Varlist = [Varlist,' srdatafile']; +end +if exist('calcpaths') + Varlist = [Varlist,' calcpaths']; +end +if exist('calcirs') + Varlist = [Varlist,' calcirs']; +end + +%--------------------------------------------------------------------------------------------- +% Find source and receiver coordinates either in the setup-file or in the CAD-file + +[nsou,nsoucols] = size(sources); +if nsoucols < 3 + if isempty(cadgeofiletoopen) + error(['ERROR: sources should be taken from the CAD file, but no cadgeofile was specified as input parameter to EDB1readsetup']) + end + eval(['load ',cadgeofiletoopen]) + [n1,n2] = size(Snames); + Snames = reshape(Snames.',1,n1*n2); + strpos = zeros(nsou,1); + for ii = 1:nsou + strpos_source = findstr(sources(ii,:),Snames); + if ~isempty(strpos_source) + strpos(ii) = strpos_source; + else + error(['ERROR: One of the sources could not be found in the CAD-file: ',sources(ii,:)]) + end + + end + if prod(strpos) == 0 + error('ERROR: One of the sources could not be found in the CAD-file') + end + sounumbers = floor(strpos/n2)+1; + sources = Scoords(sounumbers,:); +end + +[nrec,nreccols] = size(receivers); +if nreccols ~= 3 + if isempty(cadgeofiletoopen) + error(['ERROR: receivers should be taken from the CAD file, but no cadgeofile was specified as input parameter to EDB1readsetup']) + end + eval(['load ',cadgeofiletoopen]) + strpos = zeros(nrec,1); + for ii = 1:nrec + strpos_rec = find(Rnumbers==receivers(ii)); + if ~isempty(strpos_rec) + strpos(ii) = strpos_rec; + else + error(['ERROR: One of the receivers could not be found in the CAD-file: ',int2str(receivers(ii))]) + end + end + if prod(strpos) == 0 + error('ERROR: One of the receivers could not be found in the CAD-file') + end + receivers = Rcoords(strpos,:); +else + if nrec == 1 + if abs(round(receivers(1))) == receivers(1) & abs(round(receivers(2)))==receivers(2) & abs(round(receivers(3))) == receivers(3) + if SHOWTEXT > 0 + disp(['WARNING: You have specified the receivers as a row of three integer values, which is ambiguous']) + disp([' It is interpreted as one receiver, with given coordinates']) + end + end + end +end + +%--------------------------------------------------------------------------------------------- +% Check the optional parameters nSbatches etc + +nsources = size(sources,1); +nreceivers = size(receivers,1); + +if exist('soulist_for_findpaths') ~= 1 + soulist_for_findpaths = [1:nsources]; +else + if soulist_for_findpaths(1) < 1 + error('ERROR: soulist_for_findpaths must start with an integer > 0') + end + if soulist_for_findpaths(end) > nsources + error('ERROR: soulist_for_findpaths must end with an integer <= the number of sources') + end +end +if exist('reclist_for_findpaths') ~= 1 + reclist_for_findpaths = [1:nreceivers]; +else + if reclist_for_findpaths(1) < 1 + error('ERROR: reclist_for_findpaths must start with an integer > 0') + end + if reclist_for_findpaths(end) > nreceivers + error('ERROR: reclist_for_findpaths must end with an integer <= the number of receivers') + end +end +if exist('soulist_for_calcirs') ~= 1 + soulist_for_calcirs = [1:nsources]; +else + if soulist_for_calcirs(1) < 1 + error('ERROR: soulist_for_calcirs must start with an integer > 0') + end + if soulist_for_calcirs(end) > nsources + error('ERROR: soulist_for_calcirs must end with an integer <= the number of sources') + end +end +if exist('reclist_for_calcirs') ~= 1 + reclist_for_calcirs = [1:nreceivers]; +else + if reclist_for_calcirs(1) < 1 + error('ERROR: reclist_for_calcirs must start with an integer > 0') + end + if reclist_for_calcirs(end) > nreceivers + error('ERROR: reclist_for_calcirs must end with an integer <= the number of receivers') + end +end + +Varlist = [Varlist,' soulist_for_findpaths reclist_for_findpaths soulist_for_calcirs reclist_for_calcirs']; + +%--------------------------------------------------------------------- +% Optional parameters for batch processing + +eval(['load ',cadgeofiletoopen]) +batchsize = 6000; + +suggestednSbatches = ceil(size(planecorners,1)*size(sources,1)/batchsize); +suggestednRbatches = ceil(size(planecorners,1)*size(receivers,1)/batchsize); + +if exist('nRbatches') ~= 1 + if suggestednRbatches > 1 + disp(['WARNING!!! The number of planes and receivers is high enough that it is recommended']) + disp([' to set nRbatches to ',int2str(suggestednRbatches)]) + disp([' Set SHOWTEXT to 0 or 1 to skip the pause']) + if SHOWTEXT > 1 + disp(['Take the chance to stop the processing and change the value of nRbatches']) + pause + end + + else + nRbatches = 1; + end +else + if nRbatches < 0, + error('ERROR: The parameter nRbatches must be a positive integer') + else + if suggestednRbatches > nRbatches + disp(['WARNING!!! The number of planes and receivers is high enough that it is recommended']) + disp([' to set nRbatches to ',int2str(suggestednRbatches)]) + disp([' Set SHOWTEXT to 0 or 1 to skip the pause']) + if SHOWTEXT > 1 + disp(['Take the chance to stop the processing and change the value of nRbatches']) + pause + end + else + nRbatches = round(nRbatches); + end + end +end +if exist('nSbatches') ~= 1 + if suggestednSbatches > 1 + disp(['WARNING!!! The number of planes and sources is high enough that it is recommended']) + disp([' to set nSbatches to ',int2str(suggestednSbatches)]) + disp([' Set SHOWTEXT to 0 or 1 to skip the pause']) + if SHOWTEXT > 1 + disp(['Take the chance to stop the processing and change the value of nSbatches']) + pause + end + else + nSbatches = 1; + end +else + if nSbatches < 0, + error('ERROR: The parameter nSbatches must be a positive integer') + else + if suggestednSbatches > nSbatches + disp(['WARNING!!! The number of planes and sources is high enough that it is recommended']) + disp([' to set nSbatches to ',int2str(suggestednSbatches)]) + disp([' Set SHOWTEXT to 0 or 1 to skip the pause']) + if SHOWTEXT > 1 + disp(['Take the chance to stop the processing and change the value of nSbatches']) + pause + end + else + nSbatches = round(nSbatches); + end + end +end + +Varlist = [Varlist,' nSbatches nRbatches']; + +%--------------------------------------------------------------------- +% Optional parameters for path editing + +if exist('symmetricedgepairs') ~= 1 + symmetricedgepairs = []; +else + if size(symmetricedgepairs,2) ~= 2, + error('ERROR: The matrix symmetricedgepairs must have two columns') + end +end + +Varlist = [Varlist,' symmetricedgepairs']; + +%--------------------------------------------------------------------- +% Save in the output file + +setupmatfile = [Filepath,Filestem,'_setup.mat']; + +eval(['save ',setupmatfile,Varlist])
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/private/EDB1speculISES.m Sat Nov 16 18:25:24 2013 +0000 @@ -0,0 +1,260 @@ +function [validISlist,validIScoords,allreflpoints,listguide,listofreflorder] = EDB1speculISES(eddatafile,... + S,R,lengthNspecmatrix,specorder,visplanesfromoner) +% EDB1speculISES - Finds the valid specular reflections by checking visibility and obstruction. +% Finds the valid specular reflections, given a list of +% potential IS combinations, by checking visibility and obstruction. +% +% Input parameters: +% eddatafile See a description in EDB1edgeo, EDB1srgeo and EDB1mainISES +% S +% R +% lengthNspecmatrix +% specorder +% visplanesfromoner +% POTENTIALISES (global) +% ISCOORDS (global) +% ORIGINSFROM (global) +% IVNSPECMATRIX (global) +% +% GLOBAL parameters: +% SHOWTEXT JJ JJnumbofchars See EDB1mainISES +% +% Output parameters +% validISlist Matrix [nreflections,specorder] of all reflections, with one row for each reflection. +% The reflecting plane numbers are given, one for each column. +% validIScoords Matrix [nreflections,3] of all image source coordinates. +% allreflpoints Matrix [nreflections,(specorder-1)*3] of all hit points in planes. +% listguide Matrix [nactiveorders,3] which for each row gives +% 1. the number of valid reflections for one reflection order +% 2. the first, and 3. the last +% row in validISlist etc which contain reflections of that order. +% Which reflection order each row refers to is given +% by listofreflorder. +% listofreflorder List [nactiveorder,3] which for each row gives the specular +% reflection order that the corresponding row in listguide refers to. +% +% Uses functions EDB1chkISvisible EDB1checkobstrpaths +% +% ---------------------------------------------------------------------------------------------- +% This file is part of the Edge Diffraction Toolbox by Peter Svensson. +% +% The Edge Diffraction Toolbox is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) any later version. +% +% The Edge Diffraction Toolbox is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +% FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License along with the +% Edge Diffraction Toolbox. If not, see <http://www.gnu.org/licenses/>. +% ---------------------------------------------------------------------------------------------- +% Peter Svensson (svensson@iet.ntnu.no) 20041109 +% +% [validISlist,validIScoords,allreflpoints,listguide,listofreflorder] = EDB1speculISES(eddatafile,... +% S,R,lengthNspecmatrix,specorder,visplanesfromoner); + +global SHOWTEXT JJ JJnumbofchars +global POTENTIALISES ISCOORDS ORIGINSFROM IVNSPECMATRIX + +eval(['load ',eddatafile]) + +[ncorners,slask] = size(corners); +[nplanes,ncornersperplane] = size(planecorners); + +[n1,n2] = size(POTENTIALISES); +if n2 < specorder + disp([' WARNING: The ISEStree-file does not contain high enough order to support']) + disp([' spec. refl. order ',int2str(specorder)]) + specorder_maxpossible = n2; +else + specorder_maxpossible = specorder; +end + +%---------------------------------------------- +% Find all IS that can be propagated to higher order. +% These must come via planes that S can see, and will be stored in xis1. + +thinlist = find(planeisthin==1); + +% ########################################### +% # # +% # First order or higher # +% # # +% ########################################### + +validISlist = []; +validIScoords = []; +allreflpoints = []; +listguide = zeros(specorder,3); +listofreflorder = zeros(specorder,1); +listguide(1,2) = 1; + +obstructtestneeded = (sum(canplaneobstruct)~=0); + +for norder = 1:specorder_maxpossible + + if SHOWTEXT >= 3 + disp([' Reflection order ',int2str(norder)]) + end + + % Start with all the theoretically possible IS + masterivlist = IVNSPECMATRIX(1:lengthNspecmatrix(norder),norder); + possiblecombs = POTENTIALISES(masterivlist,1:norder); + + % Pick out only those IS that come via a last refl plane that the + % receiver is in front of + okcombs = find(visplanesfromoner(possiblecombs(:,norder))==2); + + masterivlist = masterivlist(okcombs); + possiblecombs = POTENTIALISES(masterivlist,1:norder); + possibleIS = ISCOORDS(masterivlist,:); + nis = length(masterivlist); + + if SHOWTEXT >= 3 + disp([' ',int2str(nis),' IS found initially for order ',int2str(norder)]) + if SHOWTEXT >= 5 + possiblecombs + end + end + + % Go through iteratively the reflection points, and check if they are + % inside the reflection plane. Start with the last reflection plane and + % work backwards. + for jj = norder:-1:1 + if nis > 0 + + if jj == norder + fromcoords = possibleIS; + tocoords = R; + else + + eval(['tocoords = reflpoints',JJ(jj+1,1:JJnumbofchars(jj+1)),';']) + ivreflist = ORIGINSFROM(masterivlist); + for kk = jj:norder-2 + ivreflist = ORIGINSFROM(ivreflist); + end + fromcoords = ISCOORDS(ivreflist,:); + end + + [hitplanes,reflpoints,edgehits,edgehitpoints,cornerhits,cornerhitpoints] = EDB1chkISvisible(fromcoords,tocoords,planeeqs(possiblecombs(:,jj),4),planenvecs(possiblecombs(:,jj),:),minvals(possiblecombs(:,jj),:),... + maxvals(possiblecombs(:,jj),:),planecorners(possiblecombs(:,jj),:),corners,ncornersperplanevec(possiblecombs(:,jj))); + if ~isempty(edgehits) | ~isempty(cornerhits) + disp('WARNING! An edgehit or cornerhit occurred during the visibility test but this is not') + disp(' handled correctly yet.') + end + eval(['reflpoints',JJ(jj,1:JJnumbofchars(jj)),' = reflpoints;']) + + masterivlist = masterivlist(hitplanes); + possiblecombs = POTENTIALISES(masterivlist,1:norder); + possibleIS = ISCOORDS(masterivlist,:); + if jj < norder + for kk = jj+1:norder + eval(['reflpoints',JJ(kk,1:JJnumbofchars(kk)),' = reflpoints',JJ(kk,1:JJnumbofchars(kk)),'(hitplanes,:);']) + end + end + nis = length(masterivlist); + + if SHOWTEXT >= 3 + disp([' ',int2str(nis),' IS survived the visibility test in refl plane number ',int2str(jj)]) + if SHOWTEXT >= 5 + possiblecombs + end + end + end + + end + + if obstructtestneeded & nis > 0 + % Check obstructions for all the paths: S -> plane1 -> plane2 -> ... + % -> planeN -> R + + for jj = 1:norder+1 + + if nis > 0 + if jj==1 + fromcoords = S; + startplanes = []; + else + startplanes = possiblecombs(:,jj-1); + eval(['fromcoords = reflpoints',JJ(jj-1,1:JJnumbofchars(jj-1)),';']) + end + if jj == norder+1 + tocoords = R; + endplanes = []; + else + eval(['tocoords = reflpoints',JJ(jj,1:JJnumbofchars(jj)),';']) + endplanes = possiblecombs(:,jj); + end + [nonobstructedpaths,nobstructions] = EDB1checkobstrpaths(fromcoords,tocoords,startplanes,endplanes,canplaneobstruct,planeseesplane,... + planeeqs,planenvecs,minvals,maxvals,planecorners,corners,ncornersperplanevec,rearsideplane); + + if nobstructions > 0 + masterivlist = masterivlist(nonobstructedpaths); + possiblecombs = POTENTIALISES(masterivlist,1:norder); + possibleIS = ISCOORDS(masterivlist,:); + for kk = 1:norder + eval(['reflpoints',JJ(kk,1:JJnumbofchars(kk)),' = reflpoints',JJ(kk,1:JJnumbofchars(kk)),'(nonobstructedpaths,:);']) + end + nis = length(masterivlist); + end + if SHOWTEXT >= 3 + disp([' ',int2str(nis),' IS survived the obstruction test for path ',int2str(jj)]) + if SHOWTEXT >= 5 + possiblecombs + end + end + end + + end + + end + if nis > 0 + if ~isempty(validISlist) + [n1,n2] = size(validISlist); + [n3,n4] = size(possiblecombs); + validISlist = [[validISlist zeros(n1,n4-n2)];(possiblecombs)]; + else + validISlist = possiblecombs; + end + validIScoords = [validIScoords;possibleIS]; + + newestreflpoints = []; + for kk = 1:norder + eval(['newestreflpoints = [newestreflpoints reflpoints',JJ(kk,1:JJnumbofchars(kk)),'];']) + end + + if ~isempty(allreflpoints) + [n1,n2] = size(allreflpoints); + [n3,n4] = size(newestreflpoints); + allreflpoints = [[allreflpoints zeros(n1,n4-n2)];newestreflpoints]; + else + allreflpoints = newestreflpoints; + end + end + + listguide(norder,1) = nis; + listguide(norder,3) = listguide(norder,2)+nis-1; + if norder < specorder + listguide(norder+1,2) = listguide(norder,3)+1; + end + listofreflorder(norder) = norder; + +end + +iv = find(listguide(:,3)==0); +listguide(iv,2) = zeros(size(iv)); + +[n1,n2] = size(validISlist); +if n2 < specorder + validISlist = [validISlist zeros(n1,specorder-n2)]; +end + +[n1,n2] = size(allreflpoints); +if n2 < specorder*3 + allreflpoints = [allreflpoints zeros(n1,specorder*3-n2)]; +end + +iv = find(listguide(:,1)==0); +listguide(iv,:) = []; +listofreflorder(iv) = [];
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/private/EDB1strpend.m Sat Nov 16 18:25:24 2013 +0000 @@ -0,0 +1,45 @@ +function Filenameout = EDB1strpend(Filenamein,striptext) +% EDB1strpend - Removes a specified ending from a filename. +% First, any extension is removed. +% +% Input parameters: +% Filenemain A text string with the filename +% stripext A text string with the ending that should +% be removed. +% +% Output parameters: +% Filenameout A text string with the extension-stripped filename +% +% Uses no special functions +% +% ---------------------------------------------------------------------------------------------- +% This file is part of the Edge Diffraction Toolbox by Peter Svensson. +% +% The Edge Diffraction Toolbox is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) any later version. +% +% The Edge Diffraction Toolbox is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +% FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License along with the +% Edge Diffraction Toolbox. If not, see <http://www.gnu.org/licenses/>. +% ---------------------------------------------------------------------------------------------- +% Peter Svensson (svensson@iet.ntnu.no) 20100812 + +[Filepath,Filenameout,temp1] = fileparts(Filenamein); + +if ~isempty(Filepath) + Filenameout = [Filepath,filesep,Filenameout]; +end + +str1 = lower(Filenameout); +str2 = lower(striptext); +n1 = length(str1); +n2 = length(str2); +if n1 >= n2 + if str1(n1-n2+1:n1) == str2 + Filenameout = Filenameout(1:n1-n2); + end +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/private/EDB1wedge1st_int.m Sat Nov 16 18:25:24 2013 +0000 @@ -0,0 +1,538 @@ +function [ir,initdelay,singularterm] = EDB1wedge1st_int(fs,closwedang,rs,thetas,zs,rr,thetar,zr,zw,Method,R_irstart,bc) +% EDB1wedge1st_int - Gives the 1st order diffraction impulse response. +% Gives the 1st order diffraction impulse response +% for a point source irradiating a finite wedge. A free-field impulse response amplitude +% of 1/r is used. An accurate integration method is used +% so receivers can be placed right at the zone boundaries. +% +% Output parameters: +% ir the impulse response +% initdelay the excluded initial time delay, from the point source switch-on until the start of ir. +% singularterm a vector, [1 4], of 0 and 1 that indicates if one or more of the four +% beta terms is singular, i.e., right on a zone boundary. +% If there is one or more elements with the value 1, the +% direct sound or a specular reflection needs to be given +% half its specular value. +% +% Input parameters: +% fs sampling frequency +% closwedang closed wedge angle +% rs, thetas, zs cyl. coordinates of the source pos. (zs = 0) +% rr, thetar, zr cyl. coordinates of the receiver pos +% zw the edge ends given as [z1 z2] +% Method 'New' (the new method by Svensson-Andersson-Vanderkooy) or 'Van' +% (Vanderkooys old method) or 'KDA' (Kirchhoff approximation). +% R_irstart (optional) if this is included, the impulse response time zero will +% correspond to this distance. Otherwise, the time zero +% corresponds to the distance R0 via the apex point. +% bc (optional) boundary condition, [1 1] (default) => rigid-rigid, [-1 -1] => soft-soft +% [1 -1] => rigid-soft. First plane should be the ref. plane. +% CAIR (global) The speed of sound +% +% Uses the functions EDB1quadstep and EDB1betaoverml for numerical integration. +% +% ---------------------------------------------------------------------------------------------- +% This file is part of the Edge Diffraction Toolbox by Peter Svensson. +% +% The Edge Diffraction Toolbox is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) any later version. +% +% The Edge Diffraction Toolbox is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +% FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License along with the +% Edge Diffraction Toolbox. If not, see <http://www.gnu.org/licenses/>. +% ---------------------------------------------------------------------------------------------- +% Peter Svensson (svensson@iet.ntnu.no) 20060607 +% +% [ir,initdelay,singularterm] = EDB1wedge1st_int(fs,closwedang,rs,thetas,zs,rr,thetar,zr,zw,Method,R_irstart,bc); + +global CAIR +localshowtext = 0; + +if localshowtext + disp(' ') + disp('Reference solution for wedge 1st') +end + +if nargin < 11 + R_irstart = 0; +end +if nargin < 12 + bc = [1 1]; +else + if bc(1)*bc(2)~=1 & bc(1) ~= 1 + error('ERROR: Only all-rigid wedges are implemented'); + end +end + +%------------------------------------------------------------------ +% If the wedge has the length zero, return a zero IR immediately + +if zw(2)-zw(1) == 0 + ir = [0 0].'; + initdelay = 0; + singularterm = [0 0 0 0]; + return +end + +%---------------------------------------------- +% Method + Some edge constants + +ny = pi/(2*pi-closwedang); + +initdelay = R_irstart/CAIR; +sampconst = CAIR/fs; + +if Method(1) == 'N' | Method(1) == 'n' + Method = 'New'; +else + error(['ERROR: The method ',Method,' has not been implemented yet!']); +end + +tol = 1e-11; % The relative accuracy for the numerical integration + % It was found that 1e-6 generated a + % substantial error for some cases (PC + % 041129) + +zrelmax = 0.1; % The part of the edge that should use the analyt. approx. + +za = (rs*zr+rr*zs)/(rs+rr); % The apex point: the point on the edge with the shortest path + +% Move the z-values so that za ends up in z = 0. + +Dz = abs(zs-zr); +zs = zs - za; +zr = zr - za; +zw = zw - za; % zw is a two-element vector +za = 0; + +rs2 = rs^2; +rr2 = rr^2; + +R0 = sqrt( (rs+rr)^2 + (zr-zs)^2 ); + +% Calculate the sinnyfi and cosnyfi values for use in the four beta-terms +% later + +fivec = pi + thetas*[1 1 -1 -1] + thetar*[1 -1 1 -1]; + +absnyfivec = abs(ny*fivec); + +sinnyfivec = sin(ny*fivec); +cosnyfivec = cos(ny*fivec); + +if localshowtext + disp(' ') + disp([' absnyfivec = ',num2str(absnyfivec)]) + disp([' cosnyfivec = ',num2str(cosnyfivec)]) +end + +%------------------------------------------------------------------ +% Check which category we have. +% +% 1. Is the apex point inside the physical wedge or not? We want to use an +% analytic approximation for a small part of the apex section (and +% possibly an ordinary numerical integration for the rest of the apex +% section. The ordinary numerical integration will be needed if the apex +% section extends further than what allows the analytic approximation to +% be used.) +% +% apexincluded 0 or 1 +% +% 2. Will the IR have a step or not? A step is caused if the path lengths +% to the two edge end points are different. If these two path lengths +% are different, then we say that the IR has a "tail". This tail has +% the amplitude 0.5 times the infinite wedge-IR, because there is no +% no corresponding wedge part on the opposite side of the apex point. +% We will use an ordinary numerical integration for the tail section. +% +% tailincluded 0 or 1 +% +% Note that if at least one of apexincluded and tailincluded must be 1. +% +% In addition to these two choices, we also want to check if we have a +% perpendicular case or a symmetrical case because these two cases can use +% a slightly simpler anaytical approximation. +% +% We call it a perpendicular case when zs = zr (which can happen only if +% apexincluded = 1!) +% +% perpcase 0 or 1 +% +% We call it a symmetrical case when rs = rr (which could also be a +% perpendicular case. A symmetrical case might not necessarily +% include the apex point. If the apex point is not included then we are not +% really interested in whether we have a symmetrical case or not since the +% analytic approximation is used only for the apex section!) +% +% symmcase 0 or 1 +% +% Since both the perpendicular case and the symmetric case can use the same +% simpler analytic approximation, we also denote those cases that are +% neither "skew cases". Again, this is relevant only when the apex is +% included. +% +% skewcase 0 or 1 + +perpcase = 0; +if zs == zr + perpcase = 1; +end + +symmcase = 0; +if rs == rr + symmcase = 1; +end + +skewcase = 0; +if perpcase == 0 & symmcase == 0 + skewcase = 1; +end + +apexincluded = 1; +if sign( zw(1)*zw(2) ) == 1 + apexincluded = 0; +end + +Rendnear = sqrt( rs2 + (zw(1)-zs)^2 ) + sqrt( rr2 + (zw(1)-zr)^2 ); +Rendfar = sqrt( rs2 + (zw(2)-zs)^2 ) + sqrt( rr2 + (zw(2)-zr)^2 ); + +if Rendnear > Rendfar + temp = Rendnear; + Rendnear = Rendfar; + Rendfar = temp; +end + +tailincluded = 1; +if abs(Rendfar-Rendnear) < eps*1e6 + tailincluded = 0; +end + +%------------------------------------------------------------------ +% Find out where the IR should start and end + +arrivalsampnumb = round((R0-R_irstart)/sampconst); +endsampnumb_apex = round((Rendnear-R_irstart)/sampconst); +if tailincluded == 1 + endsampnumb_tail = round((Rendfar-R_irstart)/sampconst); + ir = zeros(endsampnumb_tail+1,1); +else + ir = zeros(endsampnumb_apex+1,1); +end + +%------------------------------------------------------------------ +% Construct vectors with the integration intervals along the edge +% +% For the apex section, which will include one part along the negative +% branch and one part along the positive branch of the wedge +% we carry out the integration only along the positive branch and multiply +% by two. +% For the tail section of the wedge (if it is included), we will also carry +% out the numerical intregration along the positive branch - even if the +% physical wedge actually has its tail secction along the negative branch. +% +% This choice implies means that we must always find the positive solutions +% to the equation where we find z-values along the wedge that correspond to +% the integration time values. + +% Calculate the integration intervals for the apex section + +if apexincluded == 1 + + % x is the path length (m+l) which corresponds to the end of each + % integration interval = time sample. + % This is the part of the edge which is symmetrical around the apex point. + + x = sampconst*(arrivalsampnumb+[0.5:1:(endsampnumb_apex-arrivalsampnumb)+0.5]) + R_irstart; + nx = length(x); + + if x(nx) > Rendnear + x(nx) = Rendnear; + if nx > 1 + if x(nx) < x(nx-1) + error('ERROR: Strange error number 1') + end + end + end + x2 = x.^2; + % ptc note: x is the same as L which is used in other derivations + + % Convert the x-values to z-values along the edge. These z-values will + % define the integration intervals. + + % ptc new code + M02 = rs*rs + zs*zs; + L02 = rr*rr + zr*zr; + K = M02 - L02 - x2; + + diffz = (zs - zr); + denom = diffz^2 - x2; + a = (2*x2*zr - K*diffz) ./ denom; + b = ((K.^2 / 4) - x2*L02) ./ denom; + + zrange_apex = -a/2 + sqrt((a.^2)/4 - b); + + % Finally the endpoint of the integral of the analytical approximation + % (=zrangespecial) should be only up to z = 0.01 + % or whatever is specified as zrelmax for the analytic approximation + + zrangespecial = zrelmax*min([rs,rr]); + % The explicit values below were just tested to get identical results with + % another implementation + % zrangespecial = 0.01629082265142; + % zrangespecial = 0.01530922080939; %0.00521457034952; + % zrangespecial = 0.00510940311841; + % disp('End of apex range = :') + % zrange_apex(1) + + if zrangespecial > zrange_apex(1) + zrangespecial = abs(zrange_apex(1)); + splitinteg = 0; + else + splitinteg = 1; + end +end + +% Calculate the integration intervals for the tail section + +if tailincluded == 1 + + % x is the path length (m+l) which corresponds to the end of each + % integration interval = time sample. + % This is the part of the edge which is outside the symmetrical part around the apex point. + + x = sampconst*(endsampnumb_apex+[-0.5:1:(endsampnumb_tail-endsampnumb_apex)+0.5]) + R_irstart; + nx = length(x); + if x(nx) > Rendfar + x(nx) = Rendfar; + if nx > 1 + if x(nx) < x(nx-1) + error('ERROR: Strange error number 2') + end + end + end + if x(1) < Rendnear + x(1) = Rendnear; + if nx > 1 + if x(2) < x(1) + error('ERROR: Strange error number 2') + end + end + end + x2 = x.^2; + + % ptc new code + M02 = rs*rs + zs*zs; + L02 = rr*rr + zr*zr; + K = M02 - L02 - x2; + diffz = (zs - zr); + denom = diffz^2 - x2; + a = (2*x2*zr - K*diffz) ./ denom; + b = ((K.^2 / 4) - x2*L02) ./ denom; + + zrange_tail = -a/2 + sqrt((a.^2)/4 - b); +end + +if localshowtext + if apexincluded + if tailincluded + disp([int2str(length(zrange_apex)+length(zrange_tail)),' elements']) + else + disp([int2str(length(zrange_apex)),' elements']) + end + else + disp([int2str(length(zrange_tail)),' elements']) + end +end + +%---------------------------------------------------------------- +% Compute the impulse responses by carrying out a numerical integration for +% the little segments that represent each sample slot. +% +% For the apex section, there is one little part of the first sample slot +% which can employ an explicit integration based on the analytical +% approximation. Often, part of the first sample slot is done with the +% explicit integration value and another part is done with usual +% integration. + +singularterm = [0 0 0 0]; + +if apexincluded == 1 + + %----------------------------------------------------------- + % First the analytical approximation + + rho = rr/rs; + sinpsi = (rs+rr)/R0; + cospsi = (zr-zs)/R0; + if localshowtext + disp([' cospsi = ',num2str(cospsi)]) + end + + tempfact = (1+rho)^2*sinpsi^2 - 2*rho; + + useserialexp1 = absnyfivec < 0.01; + useserialexp2 = abs(absnyfivec - 2*pi) < 0.01; + useserialexp = useserialexp1 | useserialexp2; + + singularterm = absnyfivec < 10*eps | abs(absnyfivec - 2*pi) < 10*eps; + if any(singularterm) & localshowtext + disp([' Singularity for term ',int2str(find(singularterm))]) + end + + sqrtB1vec = ( sqrt( 2*(1-cosnyfivec) )*R0*rho/(1+rho)^2/ny ).*(useserialexp==0) + ... + ( fivec.*sqrt(1-(ny*fivec).^2/12)*R0*rho/(1+rho)^2 ).*(useserialexp1==1) + ... + ( (fivec-2*pi/ny).*sqrt(1-(ny*fivec-2*pi).^2/12)*R0*rho/(1+rho)^2 ).*(useserialexp2==1); + + if skewcase == 0, % Use the slightly simpler formulation of the analytical approx. + + sqrtB3 = sqrt(2)*R0*rho/(1+rho)/sqrt(tempfact); + + usespecialcase = abs(sqrtB3 - sqrtB1vec) < 1e-14; + + fifactvec = ( (1-cosnyfivec)./ny^2 ).*(useserialexp==0) + ... + ( fivec.^2/2.*(1-(ny*fivec).^2/12) ).*(useserialexp1==1) + ... + ( (fivec-2*pi/ny).^2/2.*(1-(ny*fivec-2*pi).^2/12) ).*(useserialexp2==1); + + temp1vec = sinnyfivec./( (1+rho)^2 - tempfact.*fifactvec + eps*10); + + + temp1_2vec = (sinnyfivec+ 10*eps)./( (1+rho)^2 - tempfact.*fifactvec)./(sqrtB1vec+10*eps).*atan( zrangespecial./(sqrtB1vec+eps) ); + + temp3vec = -1./sqrtB3.*atan( zrangespecial./sqrtB3 ); + + approxintvalvec = 2/ny^2*rho*(temp1_2vec + temp1vec*temp3vec); + approxintvalvec = approxintvalvec.*(sinnyfivec~=0).*(usespecialcase==0); + + if any(usespecialcase) + disp('SPECIAL CASE!') + specialcasevalue = 1/(2*sqrtB3*sqrtB3).*( zrangespecial./(zrangespecial^2 + sqrtB3*sqrtB3) + 1./sqrtB3.*atan(zrangespecial./(sqrtB3+eps)) ); + approxintvalvec = approxintvalvec + 4*R0*R0*rho*rho*rho*sinnyfivec/ny/ny/(1+rho)^4./tempfact.*specialcasevalue.*(usespecialcase==1); + end + + + else % Use the more general formulation of the analytical approx. + B3 = 2*R0*R0*rho*rho/(1+rho)/(1+rho)/tempfact; + B1vec = sqrtB1vec.^2; + B2 = -2*R0*(1-rho)*rho*cospsi/(1+rho)/tempfact; + E1vec = 4*R0^2*rho^3*sinnyfivec./ny^2/(1+rho)^4./tempfact; +% Error found 050117 by PS. The line below is wrong and should be +% replaced by the next one. +% Wrong version: multfact = E1vec.*B2./(B1vec*B2^2 + B1vec.^2 - B3.^2); + multfact = -E1vec.*B2./(B1vec*B2^2 + (B1vec - B3).^2); + +% Error found 050118 by PS: the abs in the P1 equation were missing! + P1 = 0.5*log( abs(B3)*abs(zrangespecial^2 + B1vec)./abs(B1vec)./abs(zrangespecial^2 + B2*zrangespecial + B3 ) ); + P2 = (B1vec-B3)./(sqrtB1vec+10*eps)./B2.*atan(zrangespecial./(sqrtB1vec+10*eps)); + q = 4*B3-B2^2; + + if q > 0 + sqrtq = sqrt(q); + F = 2/sqrtq*( atan( (2*zrangespecial+B2)/sqrtq ) - atan( B2/sqrtq ) ); + elseif q < 0 + sqrtminq = sqrt(-q); +% Error found 050118 by PS: the abs in the F equation were missing! + F = 1./sqrtminq.*log( abs(2*zrangespecial+B2-sqrtminq).*abs(B2+sqrtminq)./abs(2*zrangespecial+B2+sqrtminq)./abs(B2-sqrtminq) ); + else % q = 0 + F = 4*zrangespecial./B2./(2*zrangespecial+B2); + end + P3 = (2*(B3-B1vec)-B2^2)/2/B2.*F; + +% Error found 050118 by PC. The line below is wrong and should be replaced +% by the one after. +% Wrong version: approxintvalvec = sum(multfact.*(P1+P2+P3)) + approxintvalvec = multfact.*(P1+P2+P3); + end + + approxintvalvec = sum(approxintvalvec.*(1-singularterm)); + if localshowtext + disp([' Analyt. int = (final IR value) ',num2str(sum(approxintvalvec*(-ny/2/pi)),15)]) + end + + %----------------------------------------------------------- + % Numerical integration for the rest of the apex section + + % The first IR sample will either have part analytic, part numerical + % integration, or just analytic + + ir(1+arrivalsampnumb) = ir(1+arrivalsampnumb) + approxintvalvec; + + if splitinteg == 1 + h = 0.13579*(zrange_apex(1)-zrangespecial); + x = [zrangespecial zrangespecial+h zrangespecial+2*h (zrangespecial+zrange_apex(1))/2 zrange_apex(1)-2*h zrange_apex(1)-h zrange_apex(1)]; + y = EDB1betaoverml(x,rs,rr,zs,zr,ny,sinnyfivec,cosnyfivec); + + Q = [0 0 0]; + Q(:,1) = EDB1quadstep(x(:,1),x(:,3),y(:,1),y(:,2),y(:,3),tol,rs,rr,zs,zr,ny,sinnyfivec,cosnyfivec); + Q(:,2) = EDB1quadstep(x(:,3),x(:,5),y(:,3),y(:,4),y(:,5),tol,rs,rr,zs,zr,ny,sinnyfivec,cosnyfivec); + Q(:,3) = EDB1quadstep(x(:,5),x(:,7),y(:,5),y(:,6),y(:,7),tol,rs,rr,zs,zr,ny,sinnyfivec,cosnyfivec); + ir(1+arrivalsampnumb) = ir(1+arrivalsampnumb) + sum(Q); + + if localshowtext + disp([' Split: num value = (final IR value) ',num2str(sum(Q)*(-ny/2/pi)),15]) + disp([' Arrival sample = ',int2str(1+arrivalsampnumb)]) + end + end + if localshowtext + disp([' First IR value = ',num2str(ir(1+arrivalsampnumb)*(-ny/2/pi),15)]) + disp(' ') + end + + % The numerical integration for the rest of the apex section + + zstarts = zrange_apex(1:end-1).'; + zends = zrange_apex(2:end).'; + + h = 0.13579*(zends-zstarts); + nslots = length(h); + x = [zstarts zstarts+h zstarts+2*h (zstarts+zends)/2 zends-2*h zends-h zends]; + x = reshape(x,7*nslots,1); + y = EDB1betaoverml(x,rs,rr,zs,zr,ny,sinnyfivec,cosnyfivec); + y = reshape(y,nslots,7); + x = reshape(x,nslots,7); + Q = zeros(nslots,3); + + Q(:,1) = EDB1quadstep(x(:,1),x(:,3),y(:,1),y(:,2),y(:,3),tol,rs,rr,zs,zr,ny,sinnyfivec,cosnyfivec); + Q(:,2) = EDB1quadstep(x(:,3),x(:,5),y(:,3),y(:,4),y(:,5),tol,rs,rr,zs,zr,ny,sinnyfivec,cosnyfivec); + Q(:,3) = EDB1quadstep(x(:,5),x(:,7),y(:,5),y(:,6),y(:,7),tol,rs,rr,zs,zr,ny,sinnyfivec,cosnyfivec); + ir(arrivalsampnumb+[2:length(zrange_apex)]) = ir(arrivalsampnumb+[2:length(zrange_apex)]) + sum(Q.').'; + ir = ir*(-ny/2/pi); % Mult by 2 because analyt int. is half the wedge + +end + +%-------------------------------------------------------------------------- +% If we have a non-symmetrical case, then we must integrate for the long +% end of the edge as well. + +if tailincluded == 1 + zstarts = zrange_tail(1:end-1).'; + zends = zrange_tail(2:end).'; + + h = 0.13579*(zends-zstarts); + nslots = length(h); + x = [zstarts zstarts+h zstarts+2*h (zstarts+zends)/2 zends-2*h zends-h zends]; + x = reshape(x,7*nslots,1); + y = EDB1betaoverml(x,rs,rr,zs,zr,ny,sinnyfivec,cosnyfivec); + y = reshape(y,nslots,7); + x = reshape(x,nslots,7); + Q = zeros(nslots,3); + Q(:,1) = EDB1quadstep(x(:,1),x(:,3),y(:,1),y(:,2),y(:,3),tol,rs,rr,zs,zr,ny,sinnyfivec,cosnyfivec); + Q(:,2) = EDB1quadstep(x(:,3),x(:,5),y(:,3),y(:,4),y(:,5),tol,rs,rr,zs,zr,ny,sinnyfivec,cosnyfivec); + Q(:,3) = EDB1quadstep(x(:,5),x(:,7),y(:,5),y(:,6),y(:,7),tol,rs,rr,zs,zr,ny,sinnyfivec,cosnyfivec); + + ir(endsampnumb_apex+[1:length(zrange_tail)-1]) = ir(endsampnumb_apex+[1:length(zrange_tail)-1]) + (sum(Q.').')*(-ny/4/pi); + +end + +ir = real(ir); + +if localshowtext + disp([' and finally,']) + disp([' the first IR values = ',num2str(ir(0+arrivalsampnumb),15)]) + disp([' ',num2str(ir(1+arrivalsampnumb),15)]) + disp([' ',num2str(ir(2+arrivalsampnumb),15)]) + disp(' ') +end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/private/EDB1wedge2nd.m Sat Nov 16 18:25:24 2013 +0000 @@ -0,0 +1,348 @@ +function [ir,ninit] = EDB1wedge2nd(cylS,cylR,cylE2_r1,cylE1_r2,... +nyveclist,edgelengthlist,dzvec,method,pathalongplane,R_irstart,bc,cair,fs) +% EDB1wedge2nd - Gives the 2nd-order diffraction IR. +% +% NB!!! Only edges that are in-plane with each other can be handled with +% this version. A small extension is needed to handle non-in-plane edge +% pairs. +% +% NB!!! Known limitation/error: geometries like reflector clouds with +% several surfaces in the same plane will give some errors: obstruction +% checks are not done properly for edge-to-edge pairs if they are in the +% same plane. Some removal of non-allowed edge-to-edge pairs is done: if a +% path from one edge to another edges starts by crossing the first edge's +% own plane, then that edge-to-edge combination is shut off. This could be +% expressed as if a second edge is "behind" the first edge. It corresponds +% somewhat to the check for the image source method if an image source is +% behind or in front of its last potential reflection surface - a +% "validity" check. But, the subsequent "obstruction" check is not done +% yet. +% +% ir The 2nd order diffraction impulse response for two +% edges that share one plane. +% ninit The initial delay that has been cut away before the +% beginning of ir. Note that the time zero of the ir (including ninit) +% corresponds to R_irstart. +% +% with input parameters +% cylS vector containing [rS,thetaS,zS] = cyl. coordinates of the source rel. to the first edge +% cylR vector containing [rR,thetaR,zR] = cyl. coordinates of the receiver rel. to the second edge +% cylE2_r1 matrix containing [rstart_r1,thetastart_r1,zstart_r1;rend_r1,thetaend_r1,zend_r1] +% = cyl. coordinates of the start and end points of the second edge rel. to the first edge +% cylE1_r2 matrix containing [rstart_r2,thetastart_r2,zstart_r2;rend_r2,thetaend_r2,zend_r2] +% = cyl. coordinates of the start and end points of the first edge rel. to the second edge +% nyveclist +% vector with the two wedge indices of the two edges +% edgelengthlist +% Matrix, [2 2], with the start and end values of the two edges: +% Row 1 has the start and end values of edge 1 +% Row 2 has the start and end values of edge 2 +% For a fully visible/active edge, the start value = 0 and the +% end value equals the length (in meters) of the edge. +% elemsize_2nd +% the number of elements per wavelength at the sampling frequency. +% Recommended value 0.5, and this value is chosen if no other value +% has been set. One can experiment with lower values (0.25, 0.1, ...) +% for comparisons - the error increases with frequency but if first +% order diffraction and specular response is masking the second order +% diffraction, low values of elemsize_2nd might be perfectly acceptable. +% method 'n' for the New method or 'v' for Vanderkooys method +% pathalongplane 1 or 0 depending on if the path runs along a plane +% or not +% R_irstart (optional) +% a distance to which the ir time zero will correspond +% bc (optional) +% a matrix containing [refl11 refl12;refl21 refl22] where the values are +1 or -1 +% indicating the reflection coefficients of the four wedge planes involved. +% +1 means rigid and -1 means soft (pressure-release) +% refl11 is edge 1, plane 1 (refplane) +% refl12 is edge 1, plane 2 +% refl21 is edge 2, plane 1 (refplane) +% refl22 is edge 2, plane 2 +% default is all-rigid +% CAIR (global) +% the speed of sound +% FSAMP (global) +% the sampling frequency +% BIGEDGESTEPMATRIX (global) +% a matrix, size [N,2], where N = nedge1*nedge2. nedge1 is the number of edge +% elements that edge1 is sub-divided into and nedge2 is the +% number of edge elements that edge2 is sub-divided into. The +% matrix contains values between 0 and 1, representing all +% combinations of relative positions along the two edges for the +% mid-points of these edge elements. They are organized like +% below, if nedge1 = 10 and nedge2 = 25: +% BIGEDGESTEPMATRIX = +% [ 0.05 0.02; +% 0.05 0.06; +% 0.05 0.10; +% ... +% 0.05 0.98; +% 0.15 0.02; +% ... +% 0.95 0.98]; +% These values are multiplied with the lengths of the respective +% edges to give the actual position, in meters along each edge. +% +% Uses no special functions +% +% ---------------------------------------------------------------------------------------------- +% This file is part of the Edge Diffraction Toolbox by Peter Svensson. +% +% The Edge Diffraction Toolbox is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) any later version. +% +% The Edge Diffraction Toolbox is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +% FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License along with the +% Edge Diffraction Toolbox. If not, see <http://www.gnu.org/licenses/>. +% ---------------------------------------------------------------------------------------------- +% Peter Svensson (svensson@iet.ntnu.no) 20080508 +% +% [ir,ninit] = EDB1wedge2ndnew(cylS,cylR,cylE2_r1,cylE1_r2,... +% nyveclist,edgelengthlist,dzvec,method,pathalongplane,BigB,R_irstart,bc,cair,fs); + +global BIGEDGESTEPMATRIX + +multfac = 1/(pathalongplane + 1); + +%----------------------------------------------------------------------- +% Extract the individual parameters + +rS = cylS(1); +thetaS = cylS(2); +zS = cylS(3); + +rR = cylR(1); +thetaR = cylR(2); +zR = cylR(3); + +rE1_r1 = cylE2_r1(1,1); +thetaE1_r1 = cylE2_r1(1,2); +zE1_r1 = cylE2_r1(1,3); +rE2_r1 = cylE2_r1(2,1); +thetaE2_r1 = cylE2_r1(2,2); +zE2_r1 = cylE2_r1(2,3); + +rE1_r2 = cylE1_r2(1,1); +thetaE1_r2 = cylE1_r2(1,2); +zE1_r2 = cylE1_r2(1,3); +rE2_r2 = cylE1_r2(2,1); +thetaE2_r2 = cylE1_r2(2,2); +zE2_r2 = cylE1_r2(2,3); + +edgesareinplane = ( abs(thetaE1_r1 - thetaE2_r1) < 1e-6 ); + +swapbigmatrix = 0; +zmid1 = (edgelengthlist(1,1)+edgelengthlist(1,2))/2; +zmid2_re1 = ( zE1_r1 + zE2_r1 )/2; +midpointdist = sqrt( rE1_r1.^2 + (zmid2_re1-zmid1).^2); +reledgetoedgedist = midpointdist/max(dzvec); + +% % % % % % % % % % % if reledgetoedgedist < 12 +% % % % % % % % % % % refinefactor = ceil(12/reledgetoedgedist); +% % % % % % % % % % % % disp([' Refining by factor ',int2str(refinefactor)]) +% % % % % % % % % % % newndivvec = round(edgelengthlist(:,2)./dzvec.').'*refinefactor; +% % % % % % % % % % % ivmatrix = EDB1creindexmatrix(newndivvec); +% % % % % % % % % % % [nedgeelcombs,slask] = size(ivmatrix); +% % % % % % % % % % % BIGE = (double(ivmatrix)-0.5)./newndivvec(uint8(ones(nedgeelcombs,1)),:); +% % % % % % % % % % % swapbigmatrix = 1; +% % % % % % % % % % % dzvec = dzvec/refinefactor; +% % % % % % % % % % % end + +% E2E, first part + +if swapbigmatrix == 0 + B4 = edgelengthlist(1,1) + (edgelengthlist(1,2)-edgelengthlist(1,1))*BIGEDGESTEPMATRIX(:,1); % B4 is zedge1_re1 which goes, per def., from 0 to edgelength1 + zedge2_re1 = zE1_r1 + BIGEDGESTEPMATRIX(:,2)*( zE2_r1 - zE1_r1 ); % zedge2_re1 are the z-values of edge2, expressed in edge 1 + B5 = edgelengthlist(2,1) + (edgelengthlist(2,2)-edgelengthlist(2,1))*BIGEDGESTEPMATRIX(:,2); % B5 is zedge2_re2 which goes, per def., from 0 to edgelength2 + zedge1_re2 = zE1_r2 + BIGEDGESTEPMATRIX(:,1)*( zE2_r2 - zE1_r2 ); +else + B4 = edgelengthlist(1,1) + (edgelengthlist(1,2)-edgelengthlist(1,1))*BIGE(:,1); % B4 is zedge1_re1 which goes, per def., from 0 to edgelength1 + zedge2_re1 = zE1_r1 + BIGE(:,2)*( zE2_r1 - zE1_r1 ); % zedge2_re1 are the z-values of edge2, expressed in edge 1 + B5 = edgelengthlist(2,1) + (edgelengthlist(2,2)-edgelengthlist(2,1))*BIGE(:,2); % B5 is zedge2_re2 which goes, per def., from 0 to edgelength2 + zedge1_re2 = zE1_r2 + BIGE(:,1)*( zE2_r2 - zE1_r2 ); +end + +% S2E +S2Edist = sqrt( rS^2 + ( B4 - zS ).^2); + +% E2R +E2Rdist = sqrt( rR^2 + ( B5 - zR ).^2); + +% E2E, second part +if swapbigmatrix == 0 + if edgesareinplane == 0, + +% error('ERROR: r and theta calculation for non-in-plane edges not implemented yet!') + + % First we need to reconvert the cylindrical coordinates of + % edge2-re1 into cartesian! Then we can use the EDB1coordtrans. + % We define our own cartesian coord syst such that the reference + % edge has its starting point in [0 0 0], and the x-axis is along + % the reference plane. + + xE1_re1 = rE1_r1*cos(thetaE1_r1); + yE1_re1 = rE1_r1*sin(thetaE1_r1); + xE2_re1 = rE2_r1*cos(thetaE2_r1); + yE2_re1 = rE2_r1*sin(thetaE2_r1); + + xvec_re1 = xE1_re1 + (xE2_re1 - xE1_re1)*BIGEDGESTEPMATRIX(:,2); + yvec_re1 = yE1_re1 + (yE2_re1 - yE1_re1)*BIGEDGESTEPMATRIX(:,2); + zvec_re1 = zE1_r1 + (zE2_r1 - zE1_r1)*BIGEDGESTEPMATRIX(:,2); + + % NB!!! Below we need to check if really the full lengths of both + % edges should be used. If S or R see only part of the respective + % edge then the edge-to-edge contribution should be "windowed" too. + [redge2_re1,thetaedge2_re1,znewedge2_re1] = EDB1coordtrans1([xvec_re1 yvec_re1 zvec_re1],[0 0 0;0 0 edgelengthlist(1,2)],[0 1 0]); + + xE1_re2 = rE1_r2*cos(thetaE1_r2); + yE1_re2 = rE1_r2*sin(thetaE1_r2); + xE2_re2 = rE2_r2*cos(thetaE2_r2); + yE2_re2 = rE2_r2*sin(thetaE2_r2); + + xvec_re2 = xE1_re2 + (xE2_re2 - xE1_re2)*BIGEDGESTEPMATRIX(:,1); + yvec_re2 = yE1_re2 + (yE2_re2 - yE1_re2)*BIGEDGESTEPMATRIX(:,1); + zvec_re2 = zE1_r2 + (zE2_r2 - zE1_r2)*BIGEDGESTEPMATRIX(:,1); + + % NB!!! Below we need to check if really the full lengths of both + % edges should be used. If S or R see only part of the respective + % edge then the edge-to-edge contribution should be "windowed" too. + [redge1_re2,thetaedge1_re2,znewedge1_re2] = EDB1coordtrans1([xvec_re2 yvec_re2 zvec_re2],[0 0 0;0 0 edgelengthlist(2,2)],[0 1 0]); + + else + redge2_re1 = rE1_r1 + BIGEDGESTEPMATRIX(:,2)*( rE2_r1 - rE1_r1 ); + redge1_re2 = rE1_r2 + BIGEDGESTEPMATRIX(:,1)*( rE2_r2 - rE1_r2 ); + end +else + + if edgesareinplane == 0 + error('ERROR: r and theta calculation for non-in-plane edges not implemented yet, for swapbigmatrix=1!') + + else + redge2_re1 = rE1_r1 + BIGE(:,2)*( rE2_r1 - rE1_r1 ); + redge1_re2 = rE1_r2 + BIGE(:,1)*( rE2_r2 - rE1_r2 ); + end +end +if edgesareinplane == 0 +% PS 20120415: CHECK - is it correct or not for non-in-plane edges? +% % % error('ERROR: r and theta calculation for non-in-plane edges not implemented yet!') +% % % % We need to implement something like: +% % % % theta = acos(r./E2Edist); +% % % thetaedge1_re2 = thetaE1_r2 + BIGEDGESTEPMATRIX(:,1)*( thetaE2_r2 - thetaE1_r2 ); +% % % thetaedge2_re1 = thetaE1_r1 + BIGEDGESTEPMATRIX(:,2)*( thetaE2_r1 - thetaE1_r1 ); +else + thetaedge1_re2 = thetaE1_r2; + thetaedge2_re1 = thetaE1_r1; +end + +if method == 'n' + + %----------------------------------------------------------------------- + % In directivity function 2, DF2, we need the quantity + % + % ( ( ze2_re2 - ze1_re2 ) * ( ze2_re2 - zr_re2 ) + n*l )/re1_re2/rr + + % First, E2E is relative to edge 2 + E2Edist = sqrt( (B5 - zedge1_re2).^2 + redge1_re2.^2 ); + + % B2 will get the coshnyeta values for DF2 + B2 = ( ( B5 - zedge1_re2 ).*( B5 - zR ) + E2Edist.*E2Rdist )./redge1_re2/rR; + B2 = ( sqrt( B2.^2-1) + B2 ).^nyveclist(2); + B2 = real( B2 + 1./B2)/2; + + clear redge1_re2 zedge1_re2 + + %----------------------------------------------------------------------- + % In directivity function 1, DF1, we need the quantity + % + % ( ( ze1_re1 -zs_re1 )*( ze1_re1 - ze2_re1 ) + n*m )/rs/re2_re1 + + % Now, we need E2E relative to edge 1 + E2Edist = sqrt( (B4 - zedge2_re1).^2 + redge2_re1.^2 ); + + % B1 will get the coshnyeta values for DF1 + + B1 = (( B4 - zS ).*( B4 - zedge2_re1 ) + S2Edist.*E2Edist)/rS./redge2_re1; + B1 = ( real(sqrt( B1.^2-1)) + B1 ).^nyveclist(1); + B1 = ( B1 + 1./B1)/2; + + clear zedge2_re1 redge2_re1 + +else + B1 = 1; B2 = 1; +end + +% Calculate DF1.*DF2 + +if pathalongplane == 0 + + % Note that here we use E2E re. edge 1! + B3 = multfac*nyveclist(1)*nyveclist(2)/16/pi^2*dzvec(1)*dzvec(2)*... + ( sin(nyveclist(1)*(pi + thetaS + thetaedge2_re1 ))./(B1- cos(nyveclist(1)*(pi + thetaS + thetaedge2_re1 ))) + ... + sin(nyveclist(1)*(pi + thetaS - thetaedge2_re1 ))./(B1- cos(nyveclist(1)*(pi + thetaS - thetaedge2_re1 ))) + ... + sin(nyveclist(1)*(pi - thetaS + thetaedge2_re1 ))./(B1- cos(nyveclist(1)*(pi - thetaS + thetaedge2_re1 ))) + ... + sin(nyveclist(1)*(pi - thetaS - thetaedge2_re1 ))./(B1- cos(nyveclist(1)*(pi - thetaS - thetaedge2_re1 ))))./S2Edist./E2Edist; + + B3 = B3.*( sin(nyveclist(2)*(pi + thetaedge1_re2 + thetaR))./(B2-cos(nyveclist(2)*(pi + thetaedge1_re2 + thetaR))) + ... + sin(nyveclist(2)*(pi + thetaedge1_re2 - thetaR))./(B2-cos(nyveclist(2)*(pi + thetaedge1_re2 - thetaR))) + ... + sin(nyveclist(2)*(pi - thetaedge1_re2 + thetaR))./(B2-cos(nyveclist(2)*(pi - thetaedge1_re2 + thetaR))) + ... + sin(nyveclist(2)*(pi - thetaedge1_re2 - thetaR))./(B2-cos(nyveclist(2)*(pi - thetaedge1_re2 - thetaR))))./E2Rdist; + +else + + if thetaS == 0 + B3 = multfac*nyveclist(1)*nyveclist(2)/2/pi^2*dzvec(1)*dzvec(2)*... + ( sin(nyveclist(1)*(pi + thetaedge2_re1 ))./(B1- cos(nyveclist(1)*(pi + thetaedge2_re1 ))))./S2Edist./E2Edist; + else + + B3 = multfac*nyveclist(1)*nyveclist(2)/4/pi^2*dzvec(1)*dzvec(2)*... + ( sin(nyveclist(1)*(pi + thetaS + thetaedge2_re1 ))./(B1- cos(nyveclist(1)*(pi + thetaS + thetaedge2_re1 ))) + ... + sin(nyveclist(1)*(pi - thetaS + thetaedge2_re1 ))./(B1- cos(nyveclist(1)*(pi - thetaS + thetaedge2_re1 ))))./S2Edist./E2Edist; + end + + + B3 = B3.*( sin(nyveclist(2)*(pi + thetaedge1_re2 + thetaR))./(B2-cos(nyveclist(2)*(pi + thetaedge1_re2 + thetaR))) + ... + sin(nyveclist(2)*(pi + thetaedge1_re2 - thetaR))./(B2-cos(nyveclist(2)*(pi + thetaedge1_re2 - thetaR))))./E2Rdist; +end + +%------------------------------------------------------------------------- +% Determine in which sample slots the amplitude contributions should +% be added, based on the total distance. + +% B2 is number of sample slots as non-integers + +B2 = ( S2Edist + E2Edist + E2Rdist - R_irstart)/(cair/fs)+1; +clear S2Edist E2Edist E2Rdist + +% B1 is the sampleslot numbers in integer number +B1 = floor(B2); + +% B2 is a value between 0 and 1 stating how much of dh that should be added +% to the first sample slot, i.e. the one given on B1. The rest of dh should +% be added to the following sample slot. +B2 = B2 - B1; + +% New approach: simply state that the amplitudevalue, mult. by 1-B2, should +% be placed in the integer slot given in B1. In addition, the +% amplitudevalues, mult by B2, should be placed in the integer slot given +% by B1+1. + +B1 = [B1;B1+1]; +B3 = [B3.*(1-B2);B3.*B2]; + +ir = zeros(max(B1),1 ); + +[B1,sortvec] = sort(B1); +B3 = cumsum(B3(sortvec)); +ivstep = (find(diff([(B1);(B1(end))+1]))); +ir(B1(ivstep)) = diff([0;B3(ivstep)]); + +% Here we could have the possibility to save space by cutting out initial zeros and +% set the value ninit correspondingly to the number of removed zeros. However, the rest of +% the EDB1 functions have not implented support for this. + +ninit = 0;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/private/EDB1wedgeN.m Sat Nov 16 18:25:24 2013 +0000 @@ -0,0 +1,321 @@ +function [ir,ninit] = EDB1wedgeN(cylS,cylR,cylE,ncylrows,nyveclist,edgelengthlist,dzvec,method,... +pathalongplane,nedgeelcombs,R_irstart,bc,cair,fs,BIGEDGE1stvalue) +% EDB1wedgeN - Gives the Nth-order diffraction impulse response. +% ir The Nth order diffraction impulse response for a combination of edges +% ninit The initial delay that has been cut away before the +% beginning of ir. Note that the time zero of the ir (including ninit) +% corresponds to R_irstart. +% +% with input parameters +% cylS List containing [rS,thetaS,zS] = cyl. coord. of the source rel. to the first edge +% cylR List containing [rR,thetaR,zR] = cyl. coord. of the receiver rel. to the last edge +% cylE Matrix containing consecutive blocks of +% [rstartE2_r1,thetastartE2_r1,zstartE2_r1;rendE2_r1,thetaendE2_r1,zendE2_r1] +% [rstartE1_r2,thetastartE1_r2,zstartE1_r2;rendE1_r2,thetaendE1_r2,zendE1_r2] +% etc (E3_r2,E2_r3) +% ncylrows The number of rows in cylE +% nyveclist List of the wedge indices of the N edges +% edgelengthlist List of the lengths of the N edges +% dzvec List of the N edge element sizes +% method 'n' for the New method or 'v' for Vanderkooys method +% pathalongplane List of 1 or 0, depending on if the (N-1) paths run along a plane or not +% nedgeelcombs The value prod(ndiv) +% R_irstart A distance to which the ir time zero will correspond +% bc Matrix containing [refl11 refl12 refl21 refl22] where the values are +1 or -1 +% indicating the reflection coefficients of the four wedge planes involved. +% +1 means rigid and -1 means soft (pressure-release) +% refl11 is edge 1, plane 1 (refplane) +% refl12 is edge 1, plane 2 +% refl21 is edge 2, plane 1 (refplane) +% refl22 is edge 2, plane 2 +% default is all-rigid +% cair The speed of sound +% fs The sampling frequency +% BIGEDGE1stvalue The constant value that should be in the first column +% of BIGEDGESTEPMATRIX +% +% BIGEDGESTEPMATRIX (global) +% a matrix, size [Nelem,N], where Nelem = nedge1*nedge2*nedge3*.... +% nedge1 is the number of edge +% elements that edge1 is sub-divided into and nedge2 is the +% number of edge elements that edge2 is sub-divided into, etc. The +% matrix contains values between 0 and 1, representing all +% combinations of relative positions along the two edges for the +% mid-points of these edge elements. They are organized like +% below, if nedge1 = 10 and nedge2 = 10 and nedge3 = 25: +% BIGEDGESTEPMATRIX = +% [ 0.05 0.05 0.02; +% 0.05 0.05 0.06; +% 0.05 0.05 0.10; +% ... +% 0.05 0.05 0.98; +% 0.05 0.15 0.02; +% ... +% 0.95 0.95 0.98]; +% These values are multiplied with the lengths of the respective +% edges to give the actual position, in meters along each edge. +% New version: The first column isn't included in the matrix, but +% transferred separately as BIGEDGE1stvalue (see above). +% +% ---------------------------------------------------------------------------------------------- +% This file is part of the Edge Diffraction Toolbox by Peter Svensson. +% +% The Edge Diffraction Toolbox is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by the Free Software +% Foundation, either version 3 of the License, or (at your option) any later version. +% +% The Edge Diffraction Toolbox is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +% FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License along with the +% Edge Diffraction Toolbox. If not, see <http://www.gnu.org/licenses/>. +% ---------------------------------------------------------------------------------------------- +% Peter Svensson (svensson@iet.ntnu.no) 20061101 +% +% [ir,ninit] = EDB1wedgeN(cylS,cylR,cylE,ncylrows,nyveclist,edgelengthlist,dzvec,method,... +% pathalongplane,nedgeelcombs,R_irstart,bc,cair,fs,BIGEDGE1stvalue); + +global BIGEDGESTEPMATRIX + +Ndifforder = length(edgelengthlist); + +multfac = prod(1./(pathalongplane + 1)); + +%----------------------------------------------------------------------- +% Create matrices with the z-, r- and theta-values +% +% BigB is a matrix that contains relative steps, ]0,1[, along each edge +% +% All the big matrices will have one column for each "edge n rel. to edge +% m" combination: +% Column 1 E2_RE1 +% Column 2 E1_RE2 +% Column 3 E3_RE2 +% Column 4 E2_RE3 +% Column 5 E4_RE3 +% Column 6 E3_RE4 +% Column 7 E5_RE4 +% Column 8 E4_RE5 +% etc +% For Ndifforder = 2, there are 2 columns +% For Ndifforder = 3, there are 4 columns +% For Ndifforder = 4, there are 6 columns +% etc + +onesvec = uint8(ones(nedgeelcombs,1)); + +colvec = [ [2:Ndifforder].' [1:Ndifforder-1].']; +colvec = reshape(colvec.',1,(Ndifforder-1)*2); +ivecwithhole = [1 [3:length(colvec)]]; +colvec = colvec(ivecwithhole)-1; + +%----------------------------------------------------------------------- +% The z-values for each edge, relative to each own edge can be calculated +% from BIGEDGESTEPMATRIX. + +zEn_REn = BIGEDGESTEPMATRIX.*edgelengthlist(onesvec,2:end); +zEn_REn1stvalue = BIGEDGE1stvalue.*edgelengthlist(1); + +% The z-values for each edge, relative to the two neighbour edges + +zreSTA = cylE(1:2:ncylrows,3).'; +zreDIF = cylE(2:2:ncylrows,3).' - zreSTA; + +zEn_REm = zreSTA(onesvec,ivecwithhole) + BIGEDGESTEPMATRIX(:,colvec).*zreDIF(onesvec,ivecwithhole); +zEn_REm2ndvalue = zreSTA(2) + BIGEDGE1stvalue.*zreDIF(2); + +%----------------------------------------------------------------------- +% The S2E and E2R distances + +% S2E +S2Edist = sqrt( cylS(1)^2 + ( zEn_REn1stvalue - cylS(3) ).^2); + +% E2R +E2Rdist = sqrt( cylR(1)^2 + ( zEn_REn(:,Ndifforder-1) - cylR(3) ).^2); + +%----------------------------------------------------------------------- +% The r-values for each edge, relative to the two neighbour edges + +rreSTA = cylE(1:2:ncylrows,1).'; +rreDIF = cylE(2:2:ncylrows,1).' - rreSTA; + +rEn_REm = rreSTA(onesvec,ivecwithhole) + BIGEDGESTEPMATRIX(:,colvec).*rreDIF(onesvec,ivecwithhole); +rEn_REm2ndvalue = rreSTA(2) + BIGEDGE1stvalue.*rreDIF(2); + +%----------------------------------------------------------------------- +% The edge-to-edge distances + +% E2Edist will be "edge2 re 1","edge3 re 2" etc +modcols = [1 [3:2:Ndifforder*2-3]-1]; +E2Edist = sqrt( ([zEn_REn1stvalue*double(onesvec) zEn_REn(:,1:Ndifforder-2)] - zEn_REm(:,modcols)).^2 + rEn_REm(:,modcols).^2 ); + +%----------------------------------------------------------------------- +% Calculate the coshnyeta values first, to use them in the directivity +% functions + +if method(1) == 'n' + + % CH will get the coshnyeta values for the directivity functions + + CH = zeros(nedgeelcombs,Ndifforder-1); + + %----------------------------------------------------------------------- + % For the coshnyeta values we need the quantity + % + % ( ( ze1_RE1 -zs_RE1 )*( ze1_RE1 - ze2_RE1 ) + n*m )/rs/re2_RE1 + + CH(:,1) = (( zEn_REn1stvalue - cylS(3) ).*( zEn_REn1stvalue - zEn_REm(:,1) ) + S2Edist.*E2Edist(:,1))/cylS(1)./rEn_REm(:,1); + CH(:,1) = ( real(sqrt( CH(:,1).^2-1)) + CH(:,1) ).^nyveclist(1); + CH(:,1) = ( CH(:,1) + 1./CH(:,1))/2; + + for ii = 2:Ndifforder-1 + mcol1 = ii*2-3; + mcol2 = ii*2-2; + if ii == 2 + CH(:,ii) = ( ( zEn_REn(:,ii-1) - zEn_REm2ndvalue ).*( zEn_REn(:,ii-1) - zEn_REm(:,mcol2) ) + E2Edist(:,ii-1).*E2Edist(:,ii) )./rEn_REm2ndvalue./rEn_REm(:,mcol2); + else + CH(:,ii) = ( ( zEn_REn(:,ii-1) - zEn_REm(:,mcol1) ).*( zEn_REn(:,ii-1) - zEn_REm(:,mcol2) ) + E2Edist(:,ii-1).*E2Edist(:,ii) )./rEn_REm(:,mcol1)./rEn_REm(:,mcol2); + + end + CH(:,ii) = ( sqrt( CH(:,ii).^2-1) + CH(:,ii) ).^nyveclist(ii); + CH(:,ii) = real( CH(:,ii) + 1./CH(:,ii))/2; + end + + CHN = ( ( zEn_REn(:,Ndifforder-1) - zEn_REm(:,2*Ndifforder-3) ).*( zEn_REn(:,Ndifforder-1) - cylR(3) ) + E2Edist(:,Ndifforder-1).*E2Rdist )./rEn_REm(:,2*Ndifforder-3)./cylR(1); + CHN = ( sqrt( CHN.^2-1) + CHN ).^nyveclist(Ndifforder); + CHN = real( CHN + 1./CHN)/2; + +elseif method(1) == 'v' + CH = ones(1,Ndifforder-1); + CHN = 1; +else + error('Method not allowed') +end + +%----------------------------------------------------------------------- +% The theta-values for each edge, relative to the two neighbour edges + +thetareSTA = cylE(1:2:ncylrows,2).'; +thetareDIF = cylE(2:2:ncylrows,2).' - thetareSTA; + +if all(thetareDIF==0) + thetaEn_REm = thetareSTA(ivecwithhole); +else + % CHECK: Here we need to implement something like + thetaEn_REm = acos(rEn_REm./E2Edist); + disp(['ERROR: Not implemented the proper calculation of theta-values for non-parallel edge pairs yet!']) + % old version: + % thetaEn_REm = thetareSTA(onesvec,ivecwithhole) + BIGEDGESTEPMATRIX(:,colvec).*thetareDIF(onesvec,ivecwithhole); +end + +thetaEn_REm2ndvalue = thetareSTA(2) + BIGEDGE1stvalue.*thetareDIF(2); + +%------------------------------------------------------ +% Calculate the product of all directivity factors and inverse distances + +% First "leg" from source, via the first edge, to the second edge, but +% including the DF only for the first edge + +if pathalongplane(1) == 0 + AMP = multfac*prod(nyveclist)*prod(dzvec)*(-1/4/pi)^Ndifforder*(sin(nyveclist(1)*(pi + cylS(2) + thetaEn_REm(:,1) ))./(CH(:,1)- cos(nyveclist(1)*(pi + cylS(2) + thetaEn_REm(:,1) ))) + ... + sin(nyveclist(1)*(pi + cylS(2) - thetaEn_REm(:,1) ))./(CH(:,1)- cos(nyveclist(1)*(pi + cylS(2) - thetaEn_REm(:,1) ))) + ... + sin(nyveclist(1)*(pi - cylS(2) + thetaEn_REm(:,1) ))./(CH(:,1)- cos(nyveclist(1)*(pi - cylS(2) + thetaEn_REm(:,1) ))) + ... + sin(nyveclist(1)*(pi - cylS(2) - thetaEn_REm(:,1) ))./(CH(:,1)- cos(nyveclist(1)*(pi - cylS(2) - thetaEn_REm(:,1) ))))./S2Edist./E2Edist(:,1); +else + if cylS(2) == 0 + AMP = 4*multfac*prod(nyveclist)*prod(dzvec)*(-1/4/pi)^Ndifforder*(sin(nyveclist(1)*(pi + thetaEn_REm(:,1) ))./(CH(:,1)- cos(nyveclist(1)*(pi + thetaEn_REm(:,1) ))))./S2Edist./E2Edist(:,1); + else + AMP = 2*multfac*prod(nyveclist)*prod(dzvec)*(-1/4/pi)^Ndifforder*(sin(nyveclist(1)*(pi + cylS(2) + thetaEn_REm(:,1) ))./(CH(:,1)- cos(nyveclist(1)*(pi + cylS(2) + thetaEn_REm(:,1) ))) + ... + sin(nyveclist(1)*(pi - cylS(2) + thetaEn_REm(:,1) ))./(CH(:,1)- cos(nyveclist(1)*(pi - cylS(2) + thetaEn_REm(:,1) ))))./S2Edist./E2Edist(:,1); + end +end + +% Second "leg" form edge 1, via the second edge, to the third edge +% including the DF only for the second edge. We keep this out of the +% for-loop because the matrix thetaEn_REm2ndvalue gives a special +% formulation. + +for ii = 2:2 + iv2 = 2; + if pathalongplane(ii-1)*pathalongplane(ii) == 0 + AMP = AMP.*(sin(nyveclist(ii)*(pi + thetaEn_REm2ndvalue + thetaEn_REm(:,iv2)))./(CH(:,ii)-cos(nyveclist(ii)*(pi + thetaEn_REm2ndvalue + thetaEn_REm(:,iv2)))) + ... + sin(nyveclist(ii)*(pi + thetaEn_REm2ndvalue - thetaEn_REm(:,iv2)))./(CH(:,ii)-cos(nyveclist(ii)*(pi + thetaEn_REm2ndvalue - thetaEn_REm(:,iv2)))) + ... + sin(nyveclist(ii)*(pi - thetaEn_REm2ndvalue + thetaEn_REm(:,iv2)))./(CH(:,ii)-cos(nyveclist(ii)*(pi - thetaEn_REm2ndvalue + thetaEn_REm(:,iv2)))) + ... + sin(nyveclist(ii)*(pi - thetaEn_REm2ndvalue - thetaEn_REm(:,iv2)))./(CH(:,ii)-cos(nyveclist(ii)*(pi - thetaEn_REm2ndvalue - thetaEn_REm(:,iv2)))))./E2Edist(:,2); + else + AMP = 4*AMP.*(sin(nyveclist(ii)*(pi + thetaEn_REm2ndvalue + thetaEn_REm(:,iv2)))./(CH(:,ii)-cos(nyveclist(ii)*(pi + thetaEn_REm2ndvalue + thetaEn_REm(:,iv2)))))./E2Edist(:,2); + end +end + +% All the following "legs", except the last one that reaches the receiver. + +for ii = 3:Ndifforder-1 + iv1 = ii*2-3; + iv2 = iv1+1; + if pathalongplane(ii-1)*pathalongplane(ii) == 0 + AMP = AMP.*(sin(nyveclist(ii)*(pi + thetaEn_REm(:,iv1) + thetaEn_REm(:,iv2)))./(CH(:,ii)-cos(nyveclist(ii)*(pi + thetaEn_REm(:,iv1) + thetaEn_REm(:,iv2)))) + ... + sin(nyveclist(ii)*(pi + thetaEn_REm(:,iv1) - thetaEn_REm(:,iv2)))./(CH(:,ii)-cos(nyveclist(ii)*(pi + thetaEn_REm(:,iv1) - thetaEn_REm(:,iv2)))) + ... + sin(nyveclist(ii)*(pi - thetaEn_REm(:,iv1) + thetaEn_REm(:,iv2)))./(CH(:,ii)-cos(nyveclist(ii)*(pi - thetaEn_REm(:,iv1) + thetaEn_REm(:,iv2)))) + ... + sin(nyveclist(ii)*(pi - thetaEn_REm(:,iv1) - thetaEn_REm(:,iv2)))./(CH(:,ii)-cos(nyveclist(ii)*(pi - thetaEn_REm(:,iv1) - thetaEn_REm(:,iv2)))))./E2Edist(:,ii); + else + AMP = 4*AMP.*(sin(nyveclist(ii)*(pi + thetaEn_REm(:,iv1) + thetaEn_REm(:,iv2)))./(CH(:,ii)-cos(nyveclist(ii)*(pi + thetaEn_REm(:,iv1) + thetaEn_REm(:,iv2)))))./E2Edist(:,ii); + end +end + +% The last "leg" that reaches the receiver, and including the last +% directivity factor. + +if pathalongplane(Ndifforder-1) == 0 + AMP = AMP.*(sin(nyveclist(Ndifforder)*(pi + thetaEn_REm(:,2*Ndifforder-3) + cylR(2)))./(CHN-cos(nyveclist(Ndifforder)*(pi + thetaEn_REm(:,2*Ndifforder-3) + cylR(2)))) + ... + sin(nyveclist(Ndifforder)*(pi + thetaEn_REm(:,2*Ndifforder-3) - cylR(2)))./(CHN-cos(nyveclist(Ndifforder)*(pi + thetaEn_REm(:,2*Ndifforder-3) - cylR(2)))) + ... + sin(nyveclist(Ndifforder)*(pi - thetaEn_REm(:,2*Ndifforder-3) + cylR(2)))./(CHN-cos(nyveclist(Ndifforder)*(pi - thetaEn_REm(:,2*Ndifforder-3) + cylR(2)))) + ... + sin(nyveclist(Ndifforder)*(pi - thetaEn_REm(:,2*Ndifforder-3) - cylR(2)))./(CHN-cos(nyveclist(Ndifforder)*(pi - thetaEn_REm(:,2*Ndifforder-3) - cylR(2)))))./E2Rdist; +else + AMP = 2*AMP.*(sin(nyveclist(Ndifforder)*(pi + thetaEn_REm(:,2*Ndifforder-3) + cylR(2)))./(CHN-cos(nyveclist(Ndifforder)*(pi + thetaEn_REm(:,2*Ndifforder-3) + cylR(2)))) + ... + sin(nyveclist(Ndifforder)*(pi + thetaEn_REm(:,2*Ndifforder-3) - cylR(2)))./(CHN-cos(nyveclist(Ndifforder)*(pi + thetaEn_REm(:,2*Ndifforder-3) - cylR(2)))))./E2Rdist; +end + +%------------------------------------------------------------------------- +% Determine in which sample slots the amplitude contributions should +% be added, based on the total distance. + +% B2 is number of sample slots as non-integers + +if Ndifforder == 2 + B2 = ( S2Edist + E2Edist + E2Rdist - R_irstart)/(cair/fs)+1; +else + B2 = ( S2Edist + sum(E2Edist.').' + E2Rdist - R_irstart)/(cair/fs)+1; +end + +% B1 is the sampleslot numbers in integer number + +B1 = floor(B2); + +% B2 is a value between 0 and 1 stating how much of dh that should be added +% to the first sample slot, i.e. the one given on B1. The rest of dh should +% be added to the following sample slot. + +B2 = B2 - B1; + +% New approach: simply state that the amplitudevalue, mult. by 1-B2, should +% be placed in the integer slot given in B1. In addition, the +% amplitudevalues, mult by B2, should be placed in the integer slot given +% by B1+1. + +B1 = [B1;B1+1]; + +AMP = [AMP.*(1-B2);AMP.*B2]; + +ir = zeros(max(B1),1 ); + +[B1,sortvec] = sort(B1); +AMP = cumsum(AMP(sortvec)); +ivstep = (find(diff([(B1);(B1(end))+1]))); +ir(B1(ivstep)) = diff([0;AMP(ivstep)]); + +% Here we could have the possibility to save space by cutting out initial zeros and +% set the value ninit correspondingly to the number of removed zeros. However, the rest of +% the EDB1 functions have not implented support for this. + +ninit = 0;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/simulate_echo.m Sat Nov 16 18:25:24 2013 +0000 @@ -0,0 +1,512 @@ +function simulation_data = simulate_echo +%Computes binaural impulse responses for simulated echolocation experiments of Summer 2013 +% +% Center of spherical coordinates system is taken to be the center of head. The azimuth, elevation and distance +% coordinates are as in matlabs sph2cart function (azimuth and elevation are angular displacements from the positive +% x-axis and from the x-y plane, respectively) with positive x axis taken to be extending to the right of the head from +% top view, positive y axis to be extending forward of the head in top view and positive z axis to be extending upwards +% in top view. +% +% INPUTS: +% +% Board dimensions are defined as +% params.board_size_x (width in meters for the 'center' orientation of Papadopoulos et al. BSPC 2011) +% params.board_size_y (depth in meters for the 'center' orientation of Papadopoulos et al. BSPC 2011) +% params.board_size_z (height in meters for the 'center' orientation of Papadopoulos et al. BSPC 2011) +% +% Board center position is defined as +% params.board_distance (distance in meters from coords origin to center of board following coordinate system described +% above), can be row vector. +% params.board_azim (azimuth in radians of the center of the board following coordinate system described above), +% can be row vector. +% params.board_elev (elevation in radians of the center of the board following coordinate system described above), +% must be scalar +% +% params.board_orientation scalar or 1x2 cell with elements 'horz' or/and 'angled' +% Board is taken to always be vertically positioned (i.e. with its width-height plane vertical to the y coordinate) and +% two cases of orientation are considered: horizontal and angled corresponding to flat and angled descriptions in +% Papadopoulos et al. BSPC 2011. +% +% params.source_down non-negative scalar in meters +% params.source_front non-negative scalar in meters +% The source is assumed to always be in front of the chest and below the head. (params.source_down and +% params.source_front cannot both be 0) +% +% +% params.horz_disamb string which can be either 'BSPC2011' or 'collocated'. If equal to 'BSPC2011' then board distance +% for the horizontal (flat) case is as described in Papadopoulos et al. BSPC 2011, i.e. the board +% distance is the distance between the centre of the head and the PLANE OF THE BOARD. +% Alternatively, in the 'collocated' case, the board distance in the horizontal (flat) case is taken +% as the distance between the centre of the head and the centre of the board +% +% NOTE: in the 'BSPC2011' case of params.horz_disamb, it is easy to see that the geometry is ill-specified for board +% positions far away from the median plane. +% +% OUTPUTS: +% +% --- simulation_data is a structure with the following fields: +% - simulation_data.echo is a cell of dimensions +% length(params.board_dist) x length(params.board_azim) x length(params.board_orientation) +% each element of which is a 2-row matrix with the left (top row) and right (bottom row) ear responses corresponding the +% echo only. +% +% - simulation_data.emission is a cell of dimensions +% length(params.board_dist) x length(params.board_azim) x length(params.board_orientation) +% each element of which is a 2-row matrix with the left (top row) and right (bottom row) ear responses corresponding the +% direct source-to-receiver path only. (NOTE: source term (binaural_irs_emission) does not need to be computed for each +% different board distance/azimuth/orientation as it is the same irs but containing a different number of trailing zero +% samples. I include this redundancy because it simplified the computation a bit and also because this way the emission +% part is always equal in length with the corresponding echo part and can be added easier) +% +% Adding any given +% directivity_weighting * simulation_data.emission{ii,jj,kk}(1,:) + simulation_data.echo{ii,jj,kk}(1,:) +% for any given ii, jj, kk will give the total left ear IR and the same for right ear by +% directivity_weighting * simulation_data.emission{ii,jj,kk}(2,:) + simulation_data.echo{ii,jj,kk}(2,:) +% +% - simulation_data.params is the stucture params described above +% - simulation_data.board_coords is an array of dimensions +% 8 x 3 x length(params.board_dist) x length(params.board_azim) x length(params.board_orientation) +% containing the x y z coordinates (2nd dimension) of the 8 edges (1st dimension) of the board geometries for different +% board distances, azimuths and orientations. +% - simulation_data.azerr and simulation_data.elerr are arrays of dimensions +% 2 x 1+length(params.board_azim)) +% which contain the error (in degrees) between the azimuth and elevation respectively of the HRTFs that are used (as +% existing in the CIPIC spherical grid) and the actual board center azimuth and elevation. +% +% +% +% DEVELOPMENT NOTES +% +% TODO: include case of multiple boards and of non-vertically oriented boards (i.e. all cases of pitch, roll, yaw for +% board orientation) +% +% TODO: include geometrical description for all possible positions of the source +% +% TODO: include validateattributes for all parameters +% +% TODO: include parameter controls for specorder (now set to 1), difforder (now set to 1), elemsize (now set to [1]) and +% nedgesubs (now set to 2) +% +% +%% TEMPLATE OF PARAMETERS SETTING +% params.board_size_x = .55; +% params.board_size_y = .02; +% params.board_size_z = .55; +% +% params.board_azim = mod(90+[-45 -17 0 17 45],360)*pi/180; +% params.board_elev = 0*pi/180; +% params.board_dist = [0.9 1.5 3 6]; +% % +% % params.board_azim = mod(90+[-17 17],360)*pi/180; % corresponds to a board 17degress to the right and a board 17 +% % degrees to the left. The elements of the vector ([-17 17] in this example) must be in the range (-180,180] and are +% % converted by the line in this example to the coordinate system described in the help preample. +% % +% % params.board_elev = 10*pi/180; % corresponds to a board 10 degrees above the azimuthal plane. The value (0 in this +% % example) must be in the range [-90,90] and is converted by the line in this example to the coordinate system described +% % in the help preample. +% % +% % params.board_dist is in meters and it can be a vector of (strictly positive) distances as needed +% +% params.board_orientation = {'horz', 'angled'}; +% % +% % params.board_orientation must be a cell containing any or both of 'horz' and 'angled' +% +% params.source_down = 0.25; % Take the source to always be directly below the chin. +% params.source_front = 0.05; % Take the source to always be directly in front of chest. +% +% params.Fs = 44100; +% params.Cair = 344; +% params.Rhoair = 1.21; +% +% params.horz_disamb = 'BSPC2011' % 'collocated' + +%% USER EDITABLE PART +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +params.board_size_x = .55; +params.board_size_y = .02; +params.board_size_z = .55; + +params.board_azim = mod(90+[-45 -17 0 17 45],360)*pi/180; +params.board_elev = 0*pi/180; +params.board_dist = [0.9 1.5 3 6]; +% +% params.board_azim = mod(90+[-17 17],360)*pi/180; % corresponds to a board 17degress to the right and a board 17 +% degrees to the left. The elements of the vector ([-17 17] in this example) must be in the range (-180,180] and are +% converted by the line in this example to the coordinate system described in the help preample. +% +% params.board_elev = 10*pi/180; % corresponds to a board 10 degrees above the azimuthal plane. The value (0 in this +% example) must be in the range [-90,90] and is converted by the line in this example to the coordinate system described +% in the help preample. +% +% params.board_dist is in meters and it can be a vector of (strictly positive) distances as needed + +params.board_orientation = {'horz', 'angled'}; +% +% params.board_orientation must be a cell containing any or both of 'horz' and 'angled' + +params.source_down = 0.25; % Take the source to always be directly below the chin. +params.source_front = 0.05; % Take the source to always be directly in front of chest. + +params.Fs = 44100; +params.Cair = 344; +params.Rhoair = 1.21; + +params.horz_disamb = 'BSPC2011'; + +%% END OF USER EDITABLE PART +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%% Validate attributes +validateattributes(params.board_elev,{'double'},{'scalar','<=',0,'>=',0}) +validateattributes(params.horz_disamb,{'char'},{'nonempty'}) + +%% Compute free field (no head) IRs + +temp_edges = [ + +params.board_size_x/2 +params.board_size_y/2 +params.board_size_z/2 + -params.board_size_x/2 +params.board_size_y/2 +params.board_size_z/2 + -params.board_size_x/2 -params.board_size_y/2 +params.board_size_z/2 + +params.board_size_x/2 -params.board_size_y/2 +params.board_size_z/2 + +params.board_size_x/2 +params.board_size_y/2 -params.board_size_z/2 + -params.board_size_x/2 +params.board_size_y/2 -params.board_size_z/2 + -params.board_size_x/2 -params.board_size_y/2 -params.board_size_z/2 + +params.board_size_x/2 -params.board_size_y/2 -params.board_size_z/2 + ]; + +FFresp{length(params.board_dist),length(params.board_azim),length(params.board_orientation)} = []; +binaural_irs_echo{length(params.board_dist),length(params.board_azim),length(params.board_orientation)} = []; +binaural_irs_emission{length(params.board_dist),length(params.board_azim),length(params.board_orientation)} = []; +% NOTE: in the above initialisation the source term (binaural_irs_emission) does not need to be computed for each +% different board distance/azimuth/orientation as it is the same. I include this redundancy so that the emission +% binaural irs that I compute each time in in a few lines are correct, i.e. I can check that all the binaural responses +% in the binaural_irs_emission cell are equal. +board_coords(8,3,length(params.board_dist),length(params.board_azim),length(params.board_orientation)) = 0; + + +geom.Fs = params.Fs; +geom.Cair = params.Cair; +geom.Rhoair = params.Rhoair; + +geom.source_position = [0 params.source_front -params.source_down]; + +for ii = 1:length(params.board_dist) + for jj = 1:length(params.board_azim) + for kk = 1:length(params.board_orientation) + + if strcmp(params.board_orientation{kk},'angled') + theta_angled = params.board_azim(jj) - pi/2; + Rot_mat = [ + cos(theta_angled) -sin(theta_angled) 0 + sin(theta_angled) cos(theta_angled) 0 + 0 0 1 + ]; + temp2_edges = ( Rot_mat * temp_edges.' ) .' ; + % for the rotation matrix see http://en.wikipedia.org/wiki/Rotation_matrix + [trans_x, trans_y, trans_z] = sph2cart(params.board_azim(jj),params.board_elev,params.board_dist(ii)); + geom.scatterer_edges = ... + temp2_edges + repmat([trans_x, trans_y, trans_z],8,1); + board_coords(:,:,ii,jj,kk) = geom.scatterer_edges; + elseif strcmp(params.board_orientation{kk},'horz') + temp2_edges = temp_edges; + if strcmp(params.horz_disamb,'collocated') + [trans_x, trans_y, trans_z] = sph2cart(params.board_azim(jj),params.board_elev,params.board_dist(ii)); + elseif strcmp(params.horz_disamb,'BSPC2011') + [trans_x, trans_y, trans_z] = sph2cart(... + params.board_azim(jj),... + params.board_elev,... + params.board_dist(ii)/abs(cos(params.board_azim(jj)-pi/2))); + else + error('params.horz_disamb must be set to either ''BSPC2011'' or ''collocated''') + end + geom.scatterer_edges = ... + temp2_edges + repmat([trans_x, trans_y, trans_z],8,1); + board_coords(:,:,ii,jj,kk) = geom.scatterer_edges; + end + + FFresp(ii,jj,kk) = edhrir_single_cuboid(geom); + + end + end +end + + +%% Compute binaural IRs + +temp = load('hrir_final.mat'); %This is subject_165 CIPIC data +h3D_lear = temp.hrir_l; +h3D_rear = temp.hrir_r; +clear temp + +cipic_source_az = 0*180/pi; +cipic_source_el = atan(-params.source_down/params.source_front)*180/pi; +[source_lear_ir, azerr(1,1+length(params.board_azim)), elerr(1,1+length(params.board_azim))] = ... + getNearestUCDpulse(cipic_source_az,cipic_source_el,h3D_lear); +[source_rear_ir, azerr(2,1+length(params.board_azim)), elerr(2,1+length(params.board_azim))] = ... + getNearestUCDpulse(cipic_source_az,cipic_source_el,h3D_rear); + +% NOTE: in the following computation the source term (binaural_irs_emission) does not need to be computed for each +% different board distance/azimuth/orientation as it is the same. I include the redundancy as a check that the geometry +% modelling and computations are correct, i.e. I can check that all the binaural responses in the binaural_irs_emission +% cell are equal. + +for ii = 1:length(params.board_azim) + + cipic_board_az = 90-params.board_azim(ii)*180/pi; + cipic_board_el = params.board_elev*180/pi; + [lear_ir, azerr(1,ii), elerr(1,ii)] = getNearestUCDpulse(cipic_board_az,cipic_board_el,h3D_lear); + [rear_ir, azerr(2,ii), elerr(2,ii)] = getNearestUCDpulse(cipic_board_az,cipic_board_el,h3D_rear); + + for jj = 1:length(params.board_dist) + for kk = 1:length(params.board_orientation) + + binaural_irs_emission{jj,ii,kk}(1,:) = fftconv(source_lear_ir,FFresp{jj,ii,kk}(2,:)); %source term + binaural_irs_emission{jj,ii,kk}(2,:) = fftconv(source_rear_ir,FFresp{jj,ii,kk}(2,:)); %source term + + binaural_irs_echo{jj,ii,kk}(1,:) = fftconv(lear_ir,FFresp{jj,ii,kk}(1,:)+FFresp{jj,ii,kk}(3,:)); + %board echo term + binaural_irs_echo{jj,ii,kk}(2,:) = fftconv(rear_ir,FFresp{jj,ii,kk}(1,:)+FFresp{jj,ii,kk}(3,:)); + %board echo term + + end + end +end + +simulation_data.echo = binaural_irs_echo; +simulation_data.emission =binaural_irs_emission; +simulation_data.params = params; +simulation_data.board_coords = board_coords; +simulation_data.azerr = azerr; +simulation_data.elerr = elerr; + +%% Subfunctions + +function [pulse, azerr, elerr] = getNearestUCDpulse(azimuth,elevation,h3D) +azimuth = pvaldeg(azimuth); +elevation = pvaldeg(elevation); + +elmax = 50; +elindices = 1:elmax; +elevations = -45 + 5.625*(elindices - 1); +el = round((elevation + 45)/5.625 + 1); +el = max(el,1); +el = min(el,elmax); +elerr = pvaldeg(elevation - elevations(el)); + +azimuths = [-80 -65 -55 -45:5:45 55 65 80]; +[azerr, az] = min(abs(pvaldeg(abs(azimuths - azimuth)))); + +pulse = squeeze(h3D(az,el,:)); + +function angle = pvaldeg(angle) +dtr = pi/180; +angle = atan2(sin(angle*dtr),cos(angle*dtr))/dtr; +if angle < - 90 + angle = angle + 360; +end + +function out=fftconv(in1,in2) +% +% Computes the convolution output out of the input vectors in1 and in2 +% either with time-domain convolution (as implemented by conv) or by +% frequency-domain filtering (as implemented by zero-padded fftfilt). +% +% out=fftconv(in1,in2) +% +in1=in1(:).';in2=in2(:).'; + +if (length(in1)>100 && length(in2)>100) + if length(in1)>=length(in2) + out=fftfilt(in2,[in1 zeros(1,length(in2)-1)]); + else + out=fftfilt(in1,[in2 zeros(1,length(in1)-1)]); + end +else + out=conv(in1,in2); +end + +function ir_matrix=edhrir_single_cuboid(geom) +% +% Matrix of irs for a single cuboid scatterer using EDTB +% +% Works for external geometry. Definition of corners and planes in the created CAD file should be pointing outwards (in +% cartesian coordinates as defined below). +% +% x coordinate (increasing to right in top view, right hand thumb) +% y coordinate (increasing in front in top view, right hand index) +% z coordinate (increasing upwards in top view, right hand middle) +% +% For more details about geometry description see the main help preample. +% +% geom input parameter should be a structure with the following fields: +% +% geom.scatterer_edges is a 8x3 matrix with elements: +% x y z coordinates of back right top edge (point 1) +% x y z coordinates of back left top edge (point 2) +% x y z coordinates of front left top edge (point 3) +% x y z coordinates of front right top edge (point 4) +% x y z coordinates of back right bottom edge (point 1) +% x y z coordinates of back left bottom edge (point 2) +% x y z coordinates of front left bottom edge (point 3) +% x y z coordinates of front right bottom edge (point 4) +% +% (or any sequence of rotations of a cuboid with edges as above) +% +% geom.source_position (Single) source coordinates in cartesian system defined 1x3 positive real vector. (Single) +% receiver always taken to be at coordinates origin (0,0,0) +% +% geom.Fs +% geom.Cair +% geom.Rhoair +% + +%% 1 +temp_filename=['a' num2str(now*1e12,'%-24.0f')]; + +fid=fopen([temp_filename '.cad'],'w'); +fprintf(fid,'%%CORNERS\n\n'); +fprintf(fid,'%.0f %9.6f %9.6f %9.6f\n',... + 1, geom.scatterer_edges(1,1), geom.scatterer_edges(1,2), geom.scatterer_edges(1,3),... + 2, geom.scatterer_edges(2,1), geom.scatterer_edges(2,2), geom.scatterer_edges(2,3),... + 3, geom.scatterer_edges(3,1), geom.scatterer_edges(3,2), geom.scatterer_edges(3,3),... + 4, geom.scatterer_edges(4,1), geom.scatterer_edges(4,2), geom.scatterer_edges(4,3),... + 5, geom.scatterer_edges(5,1), geom.scatterer_edges(5,2), geom.scatterer_edges(5,3),... + 6, geom.scatterer_edges(6,1), geom.scatterer_edges(6,2), geom.scatterer_edges(6,3),... + 7, geom.scatterer_edges(7,1), geom.scatterer_edges(7,2), geom.scatterer_edges(7,3),... + 8, geom.scatterer_edges(8,1), geom.scatterer_edges(8,2), geom.scatterer_edges(8,3)); +fprintf(fid,'\n%%PLANES\n'); +fprintf(fid,'\n1 / /RIGID\n1 2 3 4\n'); +fprintf(fid,'\n2 / /RIGID\n5 8 7 6\n'); +fprintf(fid,'\n3 / /RIGID\n1 4 8 5\n'); +fprintf(fid,'\n4 / /RIGID\n1 5 6 2\n'); +fprintf(fid,'\n5 / /RIGID\n2 6 7 3\n'); +fprintf(fid,'\n6 / /RIGID\n7 8 4 3\n'); +fprintf(fid,'\n%%EOF'); +fclose(fid); + +fid=fopen([temp_filename '_setup.m'],'wt'); +fprintf(fid,'\n global FSAMP CAIR RHOAIR SHOWTEXT'); +fprintf(fid,['\n FSAMP = ' num2str(geom.Fs) ';']); +fprintf(fid,['\n CAIR = ' num2str(geom.Cair) ';']); +fprintf(fid,['\n RHOAIR = ' num2str(geom.Rhoair) ';']); +fprintf(fid,'\n SHOWTEXT = 0;'); +fprintf(fid,'\n SUPPRESSFILES = 0;'); +fprintf(fid,'\n Filepath=['''''''' cd '''''''' ''\\''];'); +fprintf(fid,['\n Filestem=''' temp_filename ''';']); +fprintf(fid,['\n CADfile=[cd ''\\' temp_filename '.cad''];']); +fprintf(fid,'\n open_or_closed_model = ''open'';'); +fprintf(fid,'\n int_or_ext_model = ''ext'';'); +fprintf(fid,'\n EDcalcmethod = ''n'';'); +fprintf(fid,'\n directsound = 1;'); +fprintf(fid,'\n specorder = 1;'); +fprintf(fid,'\n difforder = 1;'); +fprintf(fid,'\n elemsize = [1];'); +fprintf(fid,'\n nedgesubs = 2;'); +fprintf(fid,'\n calcpaths = 1;'); +fprintf(fid,'\n calcirs = 1;'); +fprintf(fid,'\n sources=['); +for n=1:1 + fprintf(fid,['\n' num2str(geom.source_position(1)) ' ' ... + num2str(geom.source_position(2)) ' ' ... + num2str(geom.source_position(3))]); +end +fprintf(fid,'\n ];'); +fprintf(fid,'\n receivers=['); +for n=1:1 + fprintf(fid,'\n 0 0 0'); +end +fprintf(fid,'\n ];'); +fprintf(fid,'\n skipcorners = 1000000;'); +fprintf(fid,'\n Rstart = 0;'); + +fclose(fid); + +pause(1); + +[~, ir_matrix]=myver_edtb([cd '\' temp_filename '_setup.m']); + +delete([temp_filename '.cad']); +delete([temp_filename '_setup.m']); + +function [ir,varargout]=myver_edtb(EDsetupfile) +% implements the computation of EDToolbox (by Peter Svensson) with a front-end +% designed for my needs. +% +% Takes one input which a setup file as specified by Svensson and gives +% either one vector output (which is the irtot output of Svensson's implementation for +% the first source and first receiver in the input "EDsetupfile" setup file) or +% two outputs, the first as above and the second being a {NxM} cell (N the number +% of sources and M the number of receivers) each element of which is a 4xL matrix +% with its 4 rows being the irdiff, irdirect, irgeom and irtot outputs of Svensson's +% computation for the corresponding source and receiver. +% +% The code deletes all other .mat files created by Svensson's +% implementation. +% +% [ir ir_all_data]=myver_edtb(EDsetupfile); + +%keep record of files in the current directory before computation +dir_bef=dir; +ir=1; + +%run computation +EDB1main(EDsetupfile); + +%get files list in the current directory after computation +dir_aft=dir; + +%get all genuine files (excluding other directories) in current directory +%after computation +k=1; +for n=1:size(dir_aft,1) + if(~dir_aft(n).isdir) + names_aft{k}=dir_aft(n).name;k=k+1; %#ok<AGROW> + end +end + +%get all genuine files (excluding other directories) in current directory +%before computation +k=1; +for n=1:size(dir_bef,1) + if(~dir_bef(n).isdir) + names_bef{k}=dir_bef(n).name;k=k+1; %#ok<AGROW> + end +end + +%get irtot for 1st source 1st receiver and delete files created by +%computation. +% for n=1:length(names_aft) +% if ~strcmp(names_aft(n),names_bef) +% if ~isempty(strfind(names_aft{n},'_1_1_ir.mat')) +% temp=load(names_aft{n}); +% ir=full(temp.irtot); +% clear temp +% end +% delete(names_aft{n}) +% end +% end +for n=1:length(names_aft) + if ~strcmp(names_aft(n),names_bef) + if ~isempty(strfind(names_aft{n},'_1_1_ir.mat')) + temp=load(names_aft{n}); + ir=full(temp.irtot); + clear temp + end + if nargout>1 + if ~isempty(strfind(names_aft{n},'_ir.mat')) + temp=load(names_aft{n}); + temp2=regexp(regexp(names_aft{n},'_\d*_\d*_','match'),'\d*','match'); + temp3{str2double(temp2{1}(1)),str2double(temp2{1}(2))}(4,:)=full(temp.irtot); %#ok<AGROW> + temp3{str2double(temp2{1}(1)),str2double(temp2{1}(2))}(1,:)=full(temp.irdiff); %#ok<AGROW> + temp3{str2double(temp2{1}(1)),str2double(temp2{1}(2))}(2,:)=full(temp.irdirect); %#ok<AGROW> + temp3{str2double(temp2{1}(1)),str2double(temp2{1}(2))}(3,:)=full(temp.irgeom); %#ok<AGROW> + clear temp temp2 + end + end + delete(names_aft{n}) + end +end +if nargout>1 + varargout(1)={temp3}; +end +