-
Notifications
You must be signed in to change notification settings - Fork 31
/
discinter.m
143 lines (131 loc) · 4.81 KB
/
discinter.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
function [newval,req,dispos,avma]=discinter(pos,val,req)
% [newval,req,dispos,avma]=DISCINTER(pos,val,req)
%
% For non-monotonous vectors (such as with discontinuities, specified
% by two or three times the same value), interpolates, i.e. finds the
% interpolated value of input values.
% Returns different values than requested!
%
% Returns NaN outside the range, as in regular interpolation.
% Also for regular interpolation, i.e. without discontinuities.
% 'pos' must not start with a discontinuity
%
% The 'newval' belong to an upgoing sorted 'req', possibly with
% fewer entries than the input 'req', if the latter was discontinuous
% either as 2p or 3p.
%
% Discontinuities at zero are treated as normal ones, so they might
% end up having negative values. So when doing inner products
% and stuff, make sure to specify values a little bit out of the range.
%
% Everything discontinuity related will get differences (intervals)
% of 0.5 and 1.5 times smint10, all the rest are real intervals.
% Changed smint/10 to smallest of 1 m or smint/10.
%
% Also returns the vector 'dispos' from DISCIDENT(POS)
% Also returns the averaging matrix 'avma' from DISCIDENT(POS)
%
% See DISCINTEREX, and NODINTER
%
% For example, an request vector [15 30 80 140 200 300 400 400] has
% a discontinuity at 400. But the position/value pair has discons at
% 15 80 and 400, specified as a repeated value (2p).
% The one at 400 is common, but 15 and 80 aren't
% The result is: you get values at
% [14 14.5 16 30 79 80.5 81 140 200 300 399 401]
% If you ask what the value at 15 is, you can't get a straight answer, but
% get three values instead.
% If you ask what the value is at 400 and 400, you get the values at 399 and 401
%
% Last updated by fjsimons-at-alum.mit.edu, October 18th, 2002
[pos,val,req]=deal(pos(:),val(:),req(:));
if pos(1)>pos(end)
pos=flipud(pos);
val=flipud(val);
fli=1;
else
fli=0;
end
% If requested values are 2p-3p-discontinuities in the request array, then
% destroy, not even leaving the middle value intact for 3p.
difreq=diff(req);
smint=min(difreq(~~difreq));
smint10=min(1,smint/10);
if sum(~difreq)
[a,b]=discident(req);
% Leave quasi-3p for quadrature; work with NaN's
% Smallest interval of req
req(~isnan(a))=req(~isnan(a))-(smint10)*a(~isnan(a));
% For 3p, adjust the middle value, for 2p, leave intact
req(~b)=req(~b)-(smint10)/2;
end
% This makes [400 400] into [399 401]
req=sort(req);
outsid=req<min(pos) | req>max(pos);
reqout=req(outsid);
req=req(~outsid);
outvol=repmat(NaN,sum(outsid),1);
% What are the discontinuities of 'pos'?
[c,d,posdisc,avma]=discident(pos);
dispos=c;
% If it was flipped, unflip for output
if fli==1
dispos=flipud(dispos);
avma=flipud(avma);
end
% So now the requested vector 'req' is free of discontinuities.
% Now need to make sure that the values of 'req'
% that would be equal to an element of 'pos' are treated
% properly. But 'req' can still have values equal to a discontinuity in pos
% this was the original point of this program.
flag1=0;
if ~isempty(intersect(pos,req))
[pdi,inp,inr]=intersect(posdisc,req);
if ~isempty(pdi)
% Remediate in the request vector, make it want a "3p-discontinuity"
% 3p for integration purposes
req(inr)=pdi(:)-repmat(smint10,length(pdi),1);
req=[req ; pdi(:)+repmat(smint10,length(pdi),1)];
req=[req ; pdi(:)+repmat(smint10/2,length(pdi),1)];
req=sort(req);
end
flag1=1;
% Else you treat those values
% I can take them out, knowing they are not discs in either
% vector, lookup their unambiguous value and put them in at
% the end, knowing the output was sorted anyway.
[reqvol,posinpos,posinreq]=intersect(pos,req);
newvol=val(posinpos);
req=req(~ismember(1:length(req),posinreq));
end
% If there are 2p or 3p discontinuities in the positions
if sum(~diff(pos))
posorg=pos;
% This removes the discontinuities from 'pos';
% it is assumed that 'pos' and 'req' have no common members.
% This is where 'req' gets sorted!
pos=unique([pos ; req]);
ins=[1:length(pos)]';
% reqpos is the index of req in [pos-disc+req]
reqpos=ins(ismember(pos,req));
% reqpos is index of one above req in [pos-disc]
reqpos=reqpos-[0:length(reqpos)-1]';
% This need to be the position shift needed to translate
% the original pos index into pos-disc
[a,ind,c]=degamini(posorg);
ind=cumsum([0 ind-1]); ind=ind(:);
% What is the index, in the original value matrix, of the
% parameter just down the one we are requesting?
% And then ups-1 is the one right below
ups=reqpos+ind(reqpos);
newval=val(ups-1)+(req-posorg(ups-1))./...
(posorg(ups)-posorg(ups-1)).*(val(ups)-val(ups-1));
else
newval=interp1(pos,val,req,'linear');
end
if flag1==1
outrows=sortrows([req newval ; reqvol newvol ; reqout outvol]);
else
outrows=sortrows([req newval ; reqout outvol]);
end
[req,newval]=deal(outrows(:,1),outrows(:,2));