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
11
12/* ===============================================================================================================================
13
14 This file is part of CoastalME, the Coastal Modelling Environment.
15
16 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.
17
18 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.
19
20 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.
21
22===============================================================================================================================*/
23#include <assert.h>
24
25#include <cfloat>
26
27// #include <iostream>
28// #include <iomanip>
29
30#include <vector>
31using std::vector;
32
33#include "cme.h"
34#include "simulation.h"
35
36//===============================================================================================================================
39//===============================================================================================================================
40double CSimulation::dGetInterpolatedValue(vector<double> const* pVdXdata, vector<double> const* pVdYdata, double dX, bool bExtrapolate)
41{
42 int const size = static_cast<int>(pVdXdata->size());
43
44 int i = 0; // Find left end of interval for interpolation
45
46 if (dX >= pVdXdata->at(size - 2)) // Special case: beyond right end
47 {
48 i = size - 2;
49 }
50
51 else
52 {
53 while (dX > pVdXdata->at(i + 1))
54 i++;
55 }
56
57 double const dXL = pVdXdata->at(i);
58 double dYL = pVdYdata->at(i);
59 double const dXR = pVdXdata->at(i + 1);
60 double dYR = pVdYdata->at(i + 1); // Points on either side (unless beyond ends)
61
62 if (!bExtrapolate) // If beyond ends of array and not extrapolating
63 {
64 if (dX < dXL)
65 dYR = dYL;
66
67 if (dX > dXR)
68 dYL = dYR;
69 }
70
71 double const ddYdX = (dYR - dYL) / (dXR - dXL); // Gradient
72
73 return (dYL + ddYdX * (dX - dXL)); // Linear interpolation
74}
75
76//===============================================================================================================================
79//===============================================================================================================================
80double CSimulation::dGetInterpolatedValue(vector<int> const* pVnXdata, vector<double> const* pVdYdata, int nX, bool bExtrapolate)
81{
82 unsigned int const nSize = static_cast<unsigned int>(pVnXdata->size());
83
84 int i = 0; // Find left end of interval for interpolation
85
86 if (nX >= pVnXdata->at(nSize - 2)) // Special case: beyond right end
87 {
88 i = nSize - 2;
89 }
90
91 else
92 {
93 while (nX > pVnXdata->at(i + 1))
94 i++;
95 }
96
97 int const nXL = pVnXdata->at(i);
98 int const nXR = pVnXdata->at(i + 1);
99
100 double dYL = pVdYdata->at(i);
101 double dYR = pVdYdata->at(i + 1); // Points on either side (unless beyond ends)
102
103 if (!bExtrapolate) // If beyond ends of array and not extrapolating
104 {
105 if (nX < nXL)
106 dYR = dYL;
107
108 if (nX > nXR)
109 dYL = dYR;
110 }
111
112 double const ddYdX = (dYR - dYL) / static_cast<double>(nXR - nXL); // Gradient
113
114 return dYL + ddYdX * static_cast<double>(nX - nXL); // Linear interpolation
115}
116
117//===============================================================================================================================
119//===============================================================================================================================
120int CSimulation::nFindIndex(vector<double> const* pVdX, double const dValueIn)
121{
122 double dLastValue = DBL_MAX;
123 int nIndexFound = 0;
124
125 for (unsigned int i = 0; i < pVdX->size(); ++i)
126 {
127 double const dThisValue = tAbs(dValueIn - pVdX->at(i));
128
129 if (dThisValue <= dLastValue)
130 {
131 dLastValue = dThisValue;
132 nIndexFound = i;
133 }
134 }
135
136 return nIndexFound;
137}
138
139//===============================================================================================================================
141//===============================================================================================================================
142vector<double> CSimulation::VdInterpolateCShoreProfileOutput(vector<double> const* pVdX, vector<double> const* pVdY, vector<double> const* pVdXNew)
143{
144 int const nXSize = static_cast<int>(pVdX->size());
145 int const nXNewSize = static_cast<int>(pVdXNew->size());
146
147 // assert(nXSize > 0);
148 // assert(nXNewSize > 0);
149
150 double dX;
151 double dY;
152 vector<double> VdYNew(nXNewSize, 0.0);
153
154 for (int i = 0; i < nXNewSize; ++i)
155 {
156 int const idx = nFindIndex(pVdX, pVdXNew->at(i));
157
158 if (pVdX->at(idx) > pVdXNew->at(i))
159 {
160 if (idx > 0)
161 {
162 dX = pVdX->at(idx) - pVdX->at(idx - 1);
163 dY = pVdY->at(idx) - pVdY->at(idx - 1);
164 }
165
166 else
167 {
168 dX = pVdX->at(idx + 1) - pVdX->at(idx);
169 dY = pVdY->at(idx + 1) - pVdY->at(idx);
170 }
171 }
172
173 else
174 {
175 if (idx < nXSize - 1)
176 {
177 dX = pVdX->at(idx + 1) - pVdX->at(idx);
178 dY = pVdY->at(idx + 1) - pVdY->at(idx);
179 }
180
181 else
182 {
183 dX = pVdX->at(idx) - pVdX->at(idx - 1);
184 dY = pVdY->at(idx) - pVdY->at(idx - 1);
185 }
186 }
187
188 // 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
189 if (bFPIsEqual(dX, 0.0, TOLERANCE))
190 dX = 1e-10;
191
192 double const dM = dY / dX;
193 double const dB = pVdY->at(idx) - pVdX->at(idx) * dM;
194
195 // VdYNew[i] = (pVdXNew->at(i) * dM) + dB;
196 VdYNew[nXNewSize - 1 - i] = (pVdXNew->at(i) * dM) + dB;
197 }
198
199 return VdYNew;
200}
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:813
bool bFPIsEqual(const T d1, const T d2, const T dEpsilon)
Definition cme.h:1293
T tAbs(T a)
Definition cme.h:1267
Contains CSimulation definitions.