CoastalME (Coastal Modelling Environment)
Simulates the long-term behaviour of complex coastlines
Loading...
Searching...
No Matches
interpolate.cpp
Go to the documentation of this file.
1
9
10/* ===============================================================================================================================
11 This file is part of CoastalME, the Coastal Modelling Environment.
12
13 CoastalME 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.
14
15 This program 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.
16
17 You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18===============================================================================================================================*/
19#include <assert.h>
20
21#include <cfloat>
22
23#include <vector>
24using std::vector;
25
26#include "cme.h"
27#include "simulation.h"
28
29//===============================================================================================================================
32//===============================================================================================================================
33double CSimulation::dGetInterpolatedValue(vector<double> const* pVdXdata, vector<double> const* pVdYdata, double dX, bool bExtrapolate)
34{
35 int const size = static_cast<int>(pVdXdata->size());
36
37 int i = 0; // Find left end of interval for interpolation
38
39 if (dX >= pVdXdata->at(size - 2)) // Special case: beyond right end
40 {
41 i = size - 2;
42 }
43
44 else
45 {
46 while (dX > pVdXdata->at(i + 1))
47 i++;
48 }
49
50 double const dXL = pVdXdata->at(i);
51 double dYL = pVdYdata->at(i);
52 double const dXR = pVdXdata->at(i + 1);
53 double dYR = pVdYdata->at(i + 1); // Points on either side (unless beyond ends)
54
55 if (! bExtrapolate) // If beyond ends of array and not extrapolating
56 {
57 if (dX < dXL)
58 dYR = dYL;
59
60 if (dX > dXR)
61 dYL = dYR;
62 }
63
64 double const ddYdX = (dYR - dYL) / (dXR - dXL); // Gradient
65
66 return (dYL + ddYdX * (dX - dXL)); // Linear interpolation
67}
68
69//===============================================================================================================================
72//===============================================================================================================================
73double CSimulation::dGetInterpolatedValue(vector<int> const* pVnXdata, vector<double> const* pVdYdata, int nX, bool bExtrapolate)
74{
75 unsigned int const nSize = static_cast<unsigned int>(pVnXdata->size());
76
77 int i = 0; // Find left end of interval for interpolation
78
79 if (nX >= pVnXdata->at(nSize - 2)) // Special case: beyond right end
80 {
81 i = nSize - 2;
82 }
83
84 else
85 {
86 while (nX > pVnXdata->at(i + 1))
87 i++;
88 }
89
90 int const nXL = pVnXdata->at(i);
91 int const nXR = pVnXdata->at(i + 1);
92
93 double dYL = pVdYdata->at(i);
94 double dYR = pVdYdata->at(i + 1); // Points on either side (unless beyond ends)
95
96 if (! bExtrapolate) // If beyond ends of array and not extrapolating
97 {
98 if (nX < nXL)
99 dYR = dYL;
100
101 if (nX > nXR)
102 dYL = dYR;
103 }
104
105 double const ddYdX = (dYR - dYL) / static_cast<double>(nXR - nXL); // Gradient
106
107 return dYL + ddYdX * static_cast<double>(nX - nXL); // Linear interpolation
108}
109
110//===============================================================================================================================
112//===============================================================================================================================
113int CSimulation::nFindIndex(vector<double> const* pVdX, double const dValueIn)
114{
115 double dLastValue = DBL_MAX;
116 int nIndexFound = 0;
117
118 for (unsigned int i = 0; i < pVdX->size(); ++i)
119 {
120 double const dThisValue = tAbs(dValueIn - pVdX->at(i));
121
122 if (dThisValue <= dLastValue)
123 {
124 dLastValue = dThisValue;
125 nIndexFound = i;
126 }
127 }
128
129 return nIndexFound;
130}
131
132//===============================================================================================================================
134//===============================================================================================================================
135vector<double> CSimulation::VdInterpolateCShoreProfileOutput(vector<double> const* pVdX, vector<double> const* pVdY, vector<double> const* pVdXNew)
136{
137 int const nXSize = static_cast<int>(pVdX->size());
138 int const nXNewSize = static_cast<int>(pVdXNew->size());
139
140 // assert(nXSize > 0);
141 // assert(nXNewSize > 0);
142
143 double dX;
144 double dY;
145 vector<double> VdYNew(nXNewSize, 0.0);
146
147 for (int i = 0; i < nXNewSize; ++i)
148 {
149 int const idx = nFindIndex(pVdX, pVdXNew->at(i));
150
151 if (pVdX->at(idx) > pVdXNew->at(i))
152 {
153 if (idx > 0)
154 {
155 dX = pVdX->at(idx) - pVdX->at(idx - 1);
156 dY = pVdY->at(idx) - pVdY->at(idx - 1);
157 }
158
159 else
160 {
161 dX = pVdX->at(idx + 1) - pVdX->at(idx);
162 dY = pVdY->at(idx + 1) - pVdY->at(idx);
163 }
164 }
165
166 else
167 {
168 if (idx < nXSize - 1)
169 {
170 dX = pVdX->at(idx + 1) - pVdX->at(idx);
171 dY = pVdY->at(idx + 1) - pVdY->at(idx);
172 }
173
174 else
175 {
176 dX = pVdX->at(idx) - pVdX->at(idx - 1);
177 dY = pVdY->at(idx) - pVdY->at(idx - 1);
178 }
179 }
180
181 // Safety check: this crashes (divide by zero) if there are identical consecutive values in pVdX, and thus if dX becomes 0. To prevent this, if dX is near zero, set to a small non-zero number
182 if (bFPIsEqual(dX, 0.0, TOLERANCE))
183 dX = 1e-10;
184
185 double const dM = dY / dX;
186 double const dB = pVdY->at(idx) - pVdX->at(idx) * dM;
187
188 // VdYNew[i] = (pVdXNew->at(i) * dM) + dB;
189 VdYNew[nXNewSize - 1 - i] = (pVdXNew->at(i) * dM) + dB;
190 }
191
192 return VdYNew;
193}
vector< double > VdInterpolateCShoreProfileOutput(vector< double > const *, vector< double > const *, vector< double > const *)
Returns a linearly interpolated vector of doubles, to make CShore profile output compatible with CME....
int nFindIndex(vector< double > const *, double const)
This is used by VdInterpolateCShoreProfileOutput, it returns the index of the value in pVdX which is ...
double dGetInterpolatedValue(vector< double > const *, vector< double > const *, double, bool)
This file contains global definitions for CoastalME.
double const TOLERANCE
Definition cme.h:725
bool bFPIsEqual(const T d1, const T d2, const T dEpsilon)
Definition cme.h:1213
T tAbs(T a)
Definition cme.h:1187
Contains CSimulation definitions.