CoastalME (Coastal Modelling Environment)
Simulates the long-term behaviour of complex coastlines
Loading...
Searching...
No Matches
locate_coast.cpp
Go to the documentation of this file.
1
10
11/* ==============================================================================================================================
12 This file is part of CoastalME, the Coastal Modelling Environment.
13
14 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.
15
16 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.
17
18 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.
19==============================================================================================================================*/
20#include <assert.h>
21
22#include <iostream>
23using std::cerr;
24using std::endl;
25using std::ios;
26
27#include <ios>
28using std::fixed;
29
30#include <iomanip>
31using std::setprecision;
32
33#include <stack>
34using std::stack;
35
36#include "cme.h"
37#include "2di_point.h"
38#include "i_line.h"
39#include "line.h"
40#include "simulation.h"
41#include "raster_grid.h"
42#include "coast.h"
43
44//===============================================================================================================================
46//===============================================================================================================================
48{
49 // Find all connected sea cells
51
52 // Find every coastline on the raster grid, mark raster cells, then create the vector coastline
53 int const nRet = nTraceAllCoasts();
54 if (nRet != RTN_OK)
55 return nRet;
56
57 // Have we created any coasts?
58 if (m_VCoast.empty())
59 {
60 cerr << m_ulIter << ": " << ERR << "no coastline located: this iteration SWL = " << m_dThisIterSWL << ", maximum DEM top surface elevation = " << m_dThisIterTopElevMax << ", minimum DEM top surface elevation = " << m_dThisIterTopElevMin << endl;
61
62 return RTN_ERR_NO_COAST;
63 }
64
65 // Is this the highest SWL so far? If so, save this for all coasts
67 {
69
70 for (int nCoast = 0; nCoast < static_cast<int>(m_VCoast.size()); nCoast++)
71 {
72 CGeomLine LCoast;
73
74 LCoast = *m_VCoast[nCoast].pLGetCoastlineExtCRS();
75 m_VHighestSWLCoastLine.push_back(LCoast);
76 }
77 }
78
79 // Is this the lowest SWL so far? If so, save this for all coasts
81 {
83
84 for (int nCoast = 0; nCoast < static_cast<int>(m_VCoast.size()); nCoast++)
85 {
86 CGeomLine LCoast;
87
88 LCoast = *m_VCoast[nCoast].pLGetCoastlineExtCRS();
89 m_VLowestSWLCoastLine.push_back(LCoast);
90 }
91 }
92
93 return RTN_OK;
94}
95
96//===============================================================================================================================
98//===============================================================================================================================
100{
101 // Go along the list of edge cells
102 for (unsigned int n = 0; n < m_VEdgeCell.size(); n++)
103 {
105 continue;
106
108 continue;
109
111 continue;
112
114 continue;
115
116 int const nX = m_VEdgeCell[n].nGetX();
117 int const nY = m_VEdgeCell[n].nGetY();
118
119 if ((m_pRasterGrid->m_Cell[nX][nY].bIsInundated()) && (bFPIsEqual(m_pRasterGrid->m_Cell[nX][nY].dGetSeaDepth(), 0.0, TOLERANCE)))
120 // This edge cell is below SWL and sea depth remains set to zero
121 CellByCellFillSea(nX, nY);
122 }
123}
124
125//===============================================================================================================================
127//===============================================================================================================================
128void CSimulation::CellByCellFillSea(int const nXStart, int const nYStart)
129{
130 // For safety check
131 int const nRoundLoopMax = m_nXGridSize * m_nYGridSize;
132
133 // Create an empty stack
134 stack<CGeom2DIPoint> PtiStack;
135
136 // Start at the given edge cell, push this onto the stack
137 PtiStack.push(CGeom2DIPoint(nXStart, nYStart));
138
139 // Then do the cell-by-cell fill loop until there are no more cell coordinates on the stack
140 int nRoundLoop = 0;
141
142 while (! PtiStack.empty())
143 {
144 // Safety check
145 if (nRoundLoop++ > nRoundLoopMax)
146 break;
147
148 CGeom2DIPoint const Pti = PtiStack.top();
149 PtiStack.pop();
150
151 int nX = Pti.nGetX();
152 int const nY = Pti.nGetY();
153
154 while ((nX >= 0) && (!m_pRasterGrid->m_Cell[nX][nY].bBasementElevIsMissingValue()) && (m_pRasterGrid->m_Cell[nX][nY].bIsInundated()))
155 nX--;
156
157 nX++;
158
159 bool bSpanAbove = false;
160 bool bSpanBelow = false;
161
162 while ((nX < m_nXGridSize) && (!m_pRasterGrid->m_Cell[nX][nY].bBasementElevIsMissingValue()) && (m_pRasterGrid->m_Cell[nX][nY].bIsInundated()) && (bFPIsEqual(m_pRasterGrid->m_Cell[nX][nY].dGetSeaDepth(), 0.0, TOLERANCE)))
163 {
164 // Set the sea depth for this cell
165 m_pRasterGrid->m_Cell[nX][nY].SetSeaDepth();
166
167 CRWCellLandform* pLandform = m_pRasterGrid->m_Cell[nX][nY].pGetLandform();
168 int const nCat = pLandform->nGetLFCategory();
169
170 // Have we had sediment input here?
172 {
173 if (m_pRasterGrid->m_Cell[nX][nY].bIsInundated())
174 {
175 m_pRasterGrid->m_Cell[nX][nY].SetInContiguousSea();
176
177 // Set this sea cell to have deep water (off-shore) wave orientation and height, will change this later for cells closer to the shoreline if we have on-shore waves
178 m_pRasterGrid->m_Cell[nX][nY].SetWaveValuesToDeepWaterWaveValues();
179 }
180 }
181 else
182 {
183 // No sediment input here, just mark as sea
184 m_pRasterGrid->m_Cell[nX][nY].SetInContiguousSea();
185 pLandform->SetLFCategory(LF_SEA);
186
187 // Set this sea cell to have deep water (off-shore) wave orientation and height, will change this later for cells closer to the shoreline if we have on-shore waves
188 m_pRasterGrid->m_Cell[nX][nY].SetWaveValuesToDeepWaterWaveValues();
189 }
190
191 // Now sort out the x-y extremities of the contiguous sea for the bounding box (used later in wave propagation)
192 if (nX < m_nXMinBoundingBox)
194
195 if (nX > m_nXMaxBoundingBox)
197
198 if (nY < m_nYMinBoundingBox)
200
201 if (nY > m_nYMaxBoundingBox)
203
204 // Update count
206
207 if ((! bSpanAbove) && (nY > 0) && (!m_pRasterGrid->m_Cell[nX][nY - 1].bBasementElevIsMissingValue()) && (m_pRasterGrid->m_Cell[nX][nY - 1].bIsInundated()))
208 {
209 PtiStack.push(CGeom2DIPoint(nX, nY - 1));
210 bSpanAbove = true;
211 }
212 else if (bSpanAbove && (nY > 0) && (!m_pRasterGrid->m_Cell[nX][nY - 1].bBasementElevIsMissingValue()) && (!m_pRasterGrid->m_Cell[nX][nY - 1].bIsInundated()))
213 {
214 bSpanAbove = false;
215 }
216
217 if ((! bSpanBelow) && (nY < m_nYGridSize - 1) && (!m_pRasterGrid->m_Cell[nX][nY + 1].bBasementElevIsMissingValue()) && (m_pRasterGrid->m_Cell[nX][nY + 1].bIsInundated()))
218 {
219 PtiStack.push(CGeom2DIPoint(nX, nY + 1));
220 bSpanBelow = true;
221 }
222 else if (bSpanBelow && (nY < m_nYGridSize - 1) && (!m_pRasterGrid->m_Cell[nX][nY + 1].bBasementElevIsMissingValue()) && (!m_pRasterGrid->m_Cell[nX][nY + 1].bIsInundated()))
223 {
224 bSpanBelow = false;
225 }
226
227 nX++;
228 }
229 }
230
231 // // DEBUG CODE ===========================================================================================================
232 // string strOutFile = m_strOutPath + "is_contiguous_sea_";
233 // strOutFile += to_string(m_ulIter);
234 // strOutFile += ".tif";
235 //
236 // GDALDriver* pDriver = GetGDALDriverManager()->GetDriverByName("gtiff");
237 // GDALDataset* pDataSet = pDriver->Create(strOutFile.c_str(), m_nXGridSize, m_nYGridSize, 1, GDT_Float64, m_papszGDALRasterOptions);
238 // pDataSet->SetProjection(m_strGDALBasementDEMProjection.c_str());
239 // pDataSet->SetGeoTransform(m_dGeoTransform);
240 // double* pdRaster = new double[m_nXGridSize * m_nYGridSize];
241 // int n = 0;
242 // for (int nY = 0; nY < m_nYGridSize; nY++)
243 // {
244 // for (int nX = 0; nX < m_nXGridSize; nX++)
245 // {
246 // pdRaster[n++] = m_pRasterGrid->m_Cell[nX][nY].bIsInContiguousSea();
247 // }
248 // }
249 //
250 // GDALRasterBand* pBand = pDataSet->GetRasterBand(1);
251 // pBand->SetNoDataValue(m_dMissingValue);
252 // int nRet = pBand->RasterIO(GF_Write, 0, 0, m_nXGridSize, m_nYGridSize, pdRaster, m_nXGridSize, m_nYGridSize, GDT_Float64, 0, 0, NULL);
253 // if (nRet == CE_Failure)
254 // return;
255 //
256 // GDALClose(pDataSet);
257 // delete[] pdRaster;
258 // // DEBUG CODE ===========================================================================================================
259
260 // // DEBUG CODE ===========================================================================================================
261 // string strOutFile = m_strOutPath + "is_inundated_";
262 // strOutFile += to_string(m_ulIter);
263 // strOutFile += ".tif";
264 //
265 // GDALDriver* pDriver = GetGDALDriverManager()->GetDriverByName("gtiff");
266 // GDALDataset* pDataSet = pDriver->Create(strOutFile.c_str(), m_nXGridSize, m_nYGridSize, 1, GDT_Float64, m_papszGDALRasterOptions);
267 // pDataSet->SetProjection(m_strGDALBasementDEMProjection.c_str());
268 // pDataSet->SetGeoTransform(m_dGeoTransform);
269 // double* pdRaster = new double[m_nXGridSize * m_nYGridSize];
270 //
271 // pDataSet = pDriver->Create(strOutFile.c_str(), m_nXGridSize, m_nYGridSize, 1, GDT_Float64, m_papszGDALRasterOptions);
272 // pDataSet->SetProjection(m_strGDALBasementDEMProjection.c_str());
273 // pDataSet->SetGeoTransform(m_dGeoTransform);
274 //
275 // pdRaster = new double[m_nXGridSize * m_nYGridSize];
276 // int n = 0;
277 // for (int nY = 0; nY < m_nYGridSize; nY++)
278 // {
279 // for (int nX = 0; nX < m_nXGridSize; nX++)
280 // {
281 // pdRaster[n++] = m_pRasterGrid->m_Cell[nX][nY].bIsInundated();
282 // }
283 // }
284 //
285 // GDALRasterBand* pBand = pDataSet->GetRasterBand(1);
286 // pBand = pDataSet->GetRasterBand(1);
287 // pBand->SetNoDataValue(m_dMissingValue);
288 // int nRet = pBand->RasterIO(GF_Write, 0, 0, m_nXGridSize, m_nYGridSize, pdRaster, m_nXGridSize, m_nYGridSize, GDT_Float64, 0, 0, NULL);
289 // if (nRet == CE_Failure)
290 // return;
291 //
292 // GDALClose(pDataSet);
293 // delete[] pdRaster;
294 // // DEBUG CODE ===========================================================================================================
295
296 // // DEBUG CODE ===========================================================================================================
297 // LogStream << m_ulIter << ": cell-by-cell fill of sea from [" << nXStart << "][" << nYStart << "] = {" << dGridCentroidXToExtCRSX(nXStart) << ", " << dGridCentroidYToExtCRSY(nYStart) << "} with SWL = " << m_dThisIterSWL << ", " << m_ulThisIterNumSeaCells << " of " << m_ulNumCells << " cells now marked as sea (" << fixed << setprecision(3) << 100.0 * m_ulThisIterNumSeaCells / m_ulNumCells << " %)" << endl;
298 //
299 // LogStream << " m_nXMinBoundingBox = " << m_nXMinBoundingBox << " m_nXMaxBoundingBox = " << m_nXMaxBoundingBox << " m_nYMinBoundingBox = " << m_nYMinBoundingBox << " m_nYMaxBoundingBox = " << m_nYMaxBoundingBox << endl;
300 // // DEBUG CODE ===========================================================================================================
301}
302
303//===============================================================================================================================
305//===============================================================================================================================
307{
309 LogStream << m_ulIter << ": Tracing coasts" << endl;
310
311// /*
312// // TEST ================================================================
313// int const BUFFER = 10;
314// int const DUMMY_COAST_NUMBER = 99;
315// int nValidCoast = -1;
316// int nXCoastMin = tMax(m_nXMinBoundingBox + BUFFER, 0);
317// int nXCoastMax = tMin(m_nXMaxBoundingBox + BUFFER, m_nXGridSize);
318// int nYCoastMin = tMax(m_nYMinBoundingBox + BUFFER, 0);
319// int nYCoastMax = tMin(m_nYMaxBoundingBox + BUFFER, m_nYGridSize);
320//
321// for (int nX = nXCoastMin; nX < nXCoastMax; nX++)
322// {
323// for (int nY = nYCoastMin; nY < nYCoastMax; nY++)
324// {
325// for (int nSearchDirection = NORTH; nSearchDirection <= NORTH_WEST; nSearchDirection++)
326// {
327// int nXAdj;
328// int nYAdj;
329//
330// switch (nSearchDirection)
331// {
332// case NORTH:
333// nXAdj = nX - 1;
334// nYAdj = nY;
335//
336// if (bIsWithinValidGrid(nXAdj, nYAdj))
337// {
338// if (m_pRasterGrid->m_Cell[nXAdj][nYAdj].bIsInContiguousSea())
339// {
340// m_pRasterGrid->m_Cell[nXAdj][nYAdj].SetAsCoastline(DUMMY_COAST_NUMBER);
341// break;
342// }
343// }
344//
345// break;
346//
347// case NORTH_EAST:
348// nXAdj = nX;
349// nYAdj = nY - 1;
350//
351// if (bIsWithinValidGrid(nXAdj, nYAdj))
352// {
353// if (m_pRasterGrid->m_Cell[nXAdj][nYAdj].bIsInContiguousSea())
354// {
355// m_pRasterGrid->m_Cell[nXAdj][nYAdj].SetAsCoastline(DUMMY_COAST_NUMBER);
356// break;
357// }
358// }
359//
360// break;
361//
362// case EAST:
363// nXAdj = nX;
364// nYAdj = nY - 1;
365//
366// if (bIsWithinValidGrid(nXAdj, nYAdj))
367// {
368// if (m_pRasterGrid->m_Cell[nXAdj][nYAdj].bIsInContiguousSea())
369// {
370// m_pRasterGrid->m_Cell[nXAdj][nYAdj].SetAsCoastline(DUMMY_COAST_NUMBER);
371// break;
372// }
373// }
374//
375// break;
376//
377// case SOUTH_EAST:
378// nXAdj = nX + 1;
379// nYAdj = nY;
380//
381// if (bIsWithinValidGrid(nXAdj, nYAdj))
382// {
383// if (m_pRasterGrid->m_Cell[nXAdj][nYAdj].bIsInContiguousSea())
384// {
385// m_pRasterGrid->m_Cell[nXAdj][nYAdj].SetAsCoastline(DUMMY_COAST_NUMBER);
386// break;
387// }
388// }
389//
390// break;
391//
392// case SOUTH:
393// nXAdj = nX + 1;
394// nYAdj = nY;
395//
396// if (bIsWithinValidGrid(nXAdj, nYAdj))
397// {
398// if (m_pRasterGrid->m_Cell[nXAdj][nYAdj].bIsInContiguousSea())
399// {
400// m_pRasterGrid->m_Cell[nXAdj][nYAdj].SetAsCoastline(DUMMY_COAST_NUMBER);
401// break;
402// }
403// }
404//
405// break;
406//
407// case SOUTH_WEST:
408// nXAdj = nX + 1;
409// nYAdj = nY;
410//
411// if (bIsWithinValidGrid(nXAdj, nYAdj))
412// {
413// if (m_pRasterGrid->m_Cell[nXAdj][nYAdj].bIsInContiguousSea())
414// {
415// m_pRasterGrid->m_Cell[nXAdj][nYAdj].SetAsCoastline(DUMMY_COAST_NUMBER);
416// break;
417// }
418// }
419//
420// break;
421//
422// case WEST:
423// nXAdj = nX;
424// nYAdj = nY + 1;
425//
426// if (bIsWithinValidGrid(nXAdj, nYAdj))
427// {
428// if (m_pRasterGrid->m_Cell[nXAdj][nYAdj].bIsInContiguousSea())
429// {
430// m_pRasterGrid->m_Cell[nXAdj][nYAdj].SetAsCoastline(DUMMY_COAST_NUMBER);
431// break;
432// }
433// }
434//
435// break;
436//
437// case NORTH_WEST:
438// nXAdj = nX;
439// nYAdj = nY + 1;
440//
441// if (bIsWithinValidGrid(nXAdj, nYAdj))
442// {
443// if (m_pRasterGrid->m_Cell[nXAdj][nYAdj].bIsInContiguousSea())
444// {
445// m_pRasterGrid->m_Cell[nXAdj][nYAdj].SetAsCoastline(DUMMY_COAST_NUMBER);
446// break;
447// }
448// }
449//
450// break;
451// }
452// }
453// }
454// }
455//
456// // Now go along the list of edge cells, look for DUMMY_COAST_NUMBER
457// bool bFound = false;
458// do
459// {
460// for (unsigned int n = 0; n < m_VEdgeCell.size(); n++)
461// {
462// if (m_bOmitSearchNorthEdge && m_VEdgeCellEdge[n] == NORTH)
463// continue;
464//
465// if (m_bOmitSearchSouthEdge && m_VEdgeCellEdge[n] == SOUTH)
466// continue;
467//
468// if (m_bOmitSearchWestEdge && m_VEdgeCellEdge[n] == WEST)
469// continue;
470//
471// if (m_bOmitSearchEastEdge && m_VEdgeCellEdge[n] == EAST)
472// continue;
473//
474// int const nX = m_VEdgeCell[n].nGetX();
475// int const nY = m_VEdgeCell[n].nGetY();
476//
477// if (m_pRasterGrid->m_Cell[nX][nY].nGetCoastline() == DUMMY_COAST_NUMBER)
478// {
479// bFound = true;
480// nValidCoast++;
481//
482// // Set this edge cell
483// m_pRasterGrid->m_Cell[nX][nY].SetAsCoastline(nValidCoast);
484//
485// CGeomILine ILTempGridCRS;
486//
487// int nXNext = nX;
488// int nYNext = nX;
489//
490// // Now look for other cells
491// do
492// {
493// for (int nSearchDirection = NORTH; nSearchDirection <= NORTH_WEST; nSearchDirection++)
494// {
495// int nXAdj;
496// int nYAdj;
497//
498// switch (nSearchDirection)
499// {
500// case NORTH:
501// nXAdj = nX - 1;
502// nYAdj = nY;
503//
504// if (bIsWithinValidGrid(nXAdj, nYAdj))
505// {
506// if (m_pRasterGrid->m_Cell[nXAdj][nYAdj].nGetCoastline() == DUMMY_COAST_NUMBER)
507// {
508// m_pRasterGrid->m_Cell[nXAdj][nYAdj].SetAsCoastline(nValidCoast);
509//
510//
511// break;
512// }
513// }
514//
515// break;
516//
517// case NORTH_EAST:
518// nXAdj = nX;
519// nYAdj = nY - 1;
520//
521// if (bIsWithinValidGrid(nXAdj, nYAdj))
522// {
523// if (m_pRasterGrid->m_Cell[nXAdj][nYAdj].bIsInContiguousSea())
524// {
525// m_pRasterGrid->m_Cell[nXAdj][nYAdj].SetAsCoastline(DUMMY_COAST_NUMBER);
526// break;
527// }
528// }
529//
530// break;
531//
532// case EAST:
533// nXAdj = nX;
534// nYAdj = nY - 1;
535//
536// if (bIsWithinValidGrid(nXAdj, nYAdj))
537// {
538// if (m_pRasterGrid->m_Cell[nXAdj][nYAdj].bIsInContiguousSea())
539// {
540// m_pRasterGrid->m_Cell[nXAdj][nYAdj].SetAsCoastline(DUMMY_COAST_NUMBER);
541// break;
542// }
543// }
544//
545// break;
546//
547// case SOUTH_EAST:
548// nXAdj = nX + 1;
549// nYAdj = nY;
550//
551// if (bIsWithinValidGrid(nXAdj, nYAdj))
552// {
553// if (m_pRasterGrid->m_Cell[nXAdj][nYAdj].bIsInContiguousSea())
554// {
555// m_pRasterGrid->m_Cell[nXAdj][nYAdj].SetAsCoastline(DUMMY_COAST_NUMBER);
556// break;
557// }
558// }
559//
560// break;
561//
562// case SOUTH:
563// nXAdj = nX + 1;
564// nYAdj = nY;
565//
566// if (bIsWithinValidGrid(nXAdj, nYAdj))
567// {
568// if (m_pRasterGrid->m_Cell[nXAdj][nYAdj].bIsInContiguousSea())
569// {
570// m_pRasterGrid->m_Cell[nXAdj][nYAdj].SetAsCoastline(DUMMY_COAST_NUMBER);
571// break;
572// }
573// }
574//
575// break;
576//
577// case SOUTH_WEST:
578// nXAdj = nX + 1;
579// nYAdj = nY;
580//
581// if (bIsWithinValidGrid(nXAdj, nYAdj))
582// {
583// if (m_pRasterGrid->m_Cell[nXAdj][nYAdj].bIsInContiguousSea())
584// {
585// m_pRasterGrid->m_Cell[nXAdj][nYAdj].SetAsCoastline(DUMMY_COAST_NUMBER);
586// break;
587// }
588// }
589//
590// break;
591//
592// case WEST:
593// nXAdj = nX;
594// nYAdj = nY + 1;
595//
596// if (bIsWithinValidGrid(nXAdj, nYAdj))
597// {
598// if (m_pRasterGrid->m_Cell[nXAdj][nYAdj].bIsInContiguousSea())
599// {
600// m_pRasterGrid->m_Cell[nXAdj][nYAdj].SetAsCoastline(DUMMY_COAST_NUMBER);
601// break;
602// }
603// }
604//
605// break;
606//
607// case NORTH_WEST:
608// nXAdj = nX;
609// nYAdj = nY + 1;
610//
611// if (bIsWithinValidGrid(nXAdj, nYAdj))
612// {
613// if (m_pRasterGrid->m_Cell[nXAdj][nYAdj].bIsInContiguousSea())
614// {
615// m_pRasterGrid->m_Cell[nXAdj][nYAdj].SetAsCoastline(DUMMY_COAST_NUMBER);
616// break;
617// }
618// }
619//
620// break;
621// }
622// }
623//
624// } while xxx;
625//
626//
627//
628//
629//
630//
631// }
632//
633//
634// }
635// }
636// while (bFound);
637//
638//
639//
640//
641//
642//
643//
644//
645// // ============================================================*/
646
647
648 int const TOOCLOSE = 1;
649 int nValidCoast = 0;
650 vector<bool> VbPossibleStartCellLHEdge;
651 vector<bool> VbTraced;
652 vector<int> VnSearchDirection;
653 vector<CGeom2DIPoint> V2DIPossibleStartCell;
654
655 // Go along the list of edge cells and look for possible coastline start/finish cells
656 for (unsigned int n = 0; n < m_VEdgeCell.size() - 1; n++)
657 {
659 continue;
660
662 continue;
663
665 continue;
666
668 continue;
669
670 int const nXThis = m_VEdgeCell[n].nGetX();
671 int const nYThis = m_VEdgeCell[n].nGetY();
672 int const nXNext = m_VEdgeCell[n + 1].nGetX();
673 int const nYNext = m_VEdgeCell[n + 1].nGetY();
674
675 // Get "Is it sea?" information for 'this' and 'next' cells
676 bool const bThisCellIsSea = m_pRasterGrid->m_Cell[nXThis][nYThis].bIsInContiguousSea();
677 bool const bNextCellIsSea = m_pRasterGrid->m_Cell[nXNext][nYNext].bIsInContiguousSea();
678
679 // Is one cell land and the sea?
680 if ((! bThisCellIsSea) && bNextCellIsSea)
681 {
682 // Yes, we are at a possible coastline start cell with 'this' cell just above the sea. Has 'this' cell already been flagged as a possible start for a coastline (even if this subsequently 'failed' as a coastline)?
683 if (m_pRasterGrid->m_Cell[nXThis][nYThis].bIsPossibleCoastStartCell())
684 continue;
685
686 // Is 'this' cell too close to a cell that has previously been flagged as a possible coast start cell? Search first in one direction
687 bool bTooClose = false;
688 for (int nn = 1; nn <= TOOCLOSE; nn++)
689 {
690 int const nTmp = n + nn;
691 if (nTmp == static_cast<int>(m_VEdgeCell.size()))
692 break;
693
694 int const nXTmp = m_VEdgeCell[nTmp].nGetX();
695 int const nYTmp = m_VEdgeCell[nTmp].nGetY();
696
697 if (m_pRasterGrid->m_Cell[nXTmp][nYTmp].bIsPossibleCoastStartCell())
698 {
699 bTooClose = true;
700 break;
701 }
702 }
703 if (bTooClose)
704 continue;
705
706 // Now search in the other direction
707 for (int nn = 1; nn <= TOOCLOSE; nn++)
708 {
709 int const nTmp = n - nn;
710 if (nTmp < 0)
711 break;
712
713 int const nXTmp = m_VEdgeCell[nTmp].nGetX();
714 int const nYTmp = m_VEdgeCell[nTmp].nGetY();
715
716 if (m_pRasterGrid->m_Cell[nXTmp][nYTmp].bIsPossibleCoastStartCell())
717 {
718 bTooClose = true;
719 break;
720 }
721 }
722 if (bTooClose)
723 continue;
724
725 // All OK, so flag 'this' cell
726 m_pRasterGrid->m_Cell[nXThis][nYThis].SetPossibleCoastStartCell();
727
729 LogStream << m_ulIter << ": \tflagging [" << nXThis << "][" << nYThis << "] = {" << dGridCentroidXToExtCRSX(nXThis) << ", " << dGridCentroidYToExtCRSY(nYThis) << "} as possible coast start cell (left_handed edge)" << endl;
730
731 // And save it as a possible coastline start cell
732 V2DIPossibleStartCell.push_back(CGeom2DIPoint(nXThis, nYThis));
733 VbPossibleStartCellLHEdge.push_back(true);
734 VnSearchDirection.push_back(nGetOppositeDirection(m_VEdgeCellEdge[n]));
735 VbTraced.push_back(false);
736 }
737 else if (bThisCellIsSea && (! bNextCellIsSea))
738 {
739 // We are at a possible coastline start cell with the 'next' cell just above the sea. Has the 'next' cell already been flagged as a possible start for a coastline (even if this subsequently 'failed' as a coastline)?
740 if (m_pRasterGrid->m_Cell[nXNext][nYNext].bIsPossibleCoastStartCell())
741 continue;
742
743 // Is the 'next' cell too close to a cell that has previously been flagged as a possible coast start cell? Search first in one direction
744 bool bTooClose = false;
745 for (int nn = 1; nn <= TOOCLOSE; nn++)
746 {
747 int const nTmp = n + 1 + nn;
748 if (nTmp == static_cast<int>(m_VEdgeCell.size()))
749 break;
750
751 int const nXTmp = m_VEdgeCell[nTmp].nGetX();
752 int const nYTmp = m_VEdgeCell[nTmp].nGetY();
753
754 if (m_pRasterGrid->m_Cell[nXTmp][nYTmp].bIsPossibleCoastStartCell())
755 {
756 bTooClose = true;
757 break;
758 }
759 }
760 if (bTooClose)
761 continue;
762
763 // Now search in the other direction
764 for (int nn = 1; nn <= TOOCLOSE; nn++)
765 {
766 int const nTmp = n + 1 - nn;
767 if (nTmp < 0)
768 break;
769
770 int const nXTmp = m_VEdgeCell[nTmp].nGetX();
771 int const nYTmp = m_VEdgeCell[nTmp].nGetY();
772
773 if (m_pRasterGrid->m_Cell[nXTmp][nYTmp].bIsPossibleCoastStartCell())
774 {
775 bTooClose = true;
776 break;
777 }
778 }
779 if (bTooClose)
780 continue;
781
782 // All OK, so flag the 'next' cell
783 m_pRasterGrid->m_Cell[nXNext][nYNext].SetPossibleCoastStartCell();
784
786 LogStream << m_ulIter << ": \tflagging [" << nXNext << "][" << nYNext << "] = {" << dGridCentroidXToExtCRSX(nXNext) << ", " << dGridCentroidYToExtCRSY(nYNext) << "} as possible coast start cell (right_handed edge)" << endl;
787
788 // And save it as a possible coastline start cell
789 V2DIPossibleStartCell.push_back(CGeom2DIPoint(nXNext, nYNext));
790 VbPossibleStartCellLHEdge.push_back(false);
791 VnSearchDirection.push_back(nGetOppositeDirection(m_VEdgeCellEdge[n + 1]));
792 VbTraced.push_back(false);
793 }
794 }
795
796 // Any possible coastline start/finish cells found?
797 if (V2DIPossibleStartCell.size() == 0)
798 {
799 LogStream << m_ulIter << ": no coastline start/finish points found after grid edges searched.";
800
802 {
803 LogStream << " Note that the following grid edges were not searched: " << (m_bOmitSearchNorthEdge ? "N " : "") << (m_bOmitSearchSouthEdge ? "S " : "") << (m_bOmitSearchWestEdge ? "W " : "") << (m_bOmitSearchEastEdge ? "E " : "");
804 }
805
806 LogStream << endl;
807
809 }
810
811 // Some possible coastline start/finish points were found
812 // LogStream << m_ulIter << ": " << V2DIPossibleStartCell.size() << " possible coastline start/finish points found" << endl;
813
814 // // Are any of the possible start/finsh points adjacent?
815 // vector<bool> VbToRemove(V2DIPossibleStartCell.size(), false);
816 // for (int nThisPoint = 0; nThisPoint < static_cast<int>(V2DIPossibleStartCell.size()); nThisPoint++)
817 // {
818 // for (int nOtherPoint = 0; nOtherPoint < static_cast<int>(V2DIPossibleStartCell.size()); nOtherPoint++)
819 // {
820 // if ((nThisPoint == nOtherPoint) || VbToRemove[nThisPoint] || VbToRemove[nOtherPoint])
821 // continue;
822 //
823 // if (bIsAdjacentEdgeCell(&V2DIPossibleStartCell[nThisPoint], &V2DIPossibleStartCell[nOtherPoint]))
824 // VbToRemove[nOtherPoint] = true;
825 // }
826 // }
827
828 // // Remove each start/finish point which has been flagged as adjacent
829 // for (int nPoint = 0; nPoint < static_cast<int>(VbToRemove.size()); nPoint++)
830 // {
831 // if (VbToRemove[nPoint])
832 // {
833 // V2DIPossibleStartCell.erase(V2DIPossibleStartCell.begin() + nPoint);
834 // VbPossibleStartCellLHEdge.erase(VbPossibleStartCellLHEdge.begin() + nPoint);
835 // VnSearchDirection.erase(VnSearchDirection.begin() + nPoint);
836 // VbTraced.erase(VbTraced.begin() + nPoint);
837 // }
838 // }
839
840 // All OK, now trace from each of these possible start/finish points
841 for (int n = static_cast<int>(V2DIPossibleStartCell.size())-1; n >= 0; n--)
842 {
843 if (! VbTraced[n])
844 {
845 int nRet = 0;
846
847 if (VbPossibleStartCellLHEdge[n])
848 nRet = nTraceCoastLine(n, VnSearchDirection[n], LEFT_HANDED, &VbTraced, &V2DIPossibleStartCell);
849 else
850 nRet = nTraceCoastLine(n, VnSearchDirection[n], RIGHT_HANDED, &VbTraced, &V2DIPossibleStartCell);
851
852 if (nRet == RTN_OK)
853 {
854 // We have a valid coastline starting from this possible start cell
855 VbTraced[n] = true;
856 nValidCoast++;
857 }
858 }
859 }
860
861 if (nValidCoast == 0)
862 {
863 // No valid coasts found so try again, this time working through the possible start/finish points in reverse order
864 for (int n = 0; n < static_cast<int>(VbTraced.size()); n++)
865 VbTraced[n] = false;
866
867 for (int n = 0; n < static_cast<int>(V2DIPossibleStartCell.size()); n++)
868 {
869 if (! VbTraced[n])
870 {
871 int nRet = 0;
872
873 if (VbPossibleStartCellLHEdge[n])
874 nRet = nTraceCoastLine(n, VnSearchDirection[n], LEFT_HANDED, &VbTraced, &V2DIPossibleStartCell);
875 else
876 nRet = nTraceCoastLine(n, VnSearchDirection[n], RIGHT_HANDED, &VbTraced, &V2DIPossibleStartCell);
877
878 if (nRet == RTN_OK)
879 {
880 // We have a valid coastline starting from this possible start cell
881 VbTraced[n] = true;
882 nValidCoast++;
883 }
884 }
885 }
886 }
887
888 if (nValidCoast == 0)
889 {
890 // Still no valid coasts found, so we have to give up
891 cerr << m_ulIter << ": no valid coasts found, see " << m_strLogFile << " for more information" << endl;
893 }
894
895 return RTN_OK;
896}
897
898//===============================================================================================================================
900//===============================================================================================================================
901int CSimulation::nTraceCoastLine(unsigned int const nTraceFromStartCellIndex, int const nStartSearchDirection, int const nHandedness, vector<bool>* pVbTraced, vector<CGeom2DIPoint> const* pV2DIPossibleStartCell)
902{
903 bool bHitStartCell = false;
904 bool bAtCoast = false;
905 bool bHasLeftStartEdge = false;
906 bool bTooLong = false;
907 bool bOffEdge = false;
908 bool bRepeating = false;
909
910 int const nStartX = pV2DIPossibleStartCell->at(nTraceFromStartCellIndex).nGetX();
911 int const nStartY = pV2DIPossibleStartCell->at(nTraceFromStartCellIndex).nGetY();
912 int nX = nStartX;
913 int nY = nStartY;
914 int nSearchDirection = nStartSearchDirection;
915 int nRoundLoop = -1;
916 // nThisLen = 0;
917 // nLastLen = 0,
918 // nPreLastLen = 0;
919
920 // Temporary coastline as integer points (grid CRS)
921 CGeomILine ILTempGridCRS;
922
923 // Add the start cell to the vector
924 CGeom2DIPoint const PtiStart(nStartX, nStartY);
925 ILTempGridCRS.Append(&PtiStart);
926
927 // Start at this grid-edge point and trace the rest of the coastline using the 'wall follower' rule for maze traversal, trying to keep next to cells flagged as sea
928 do
929 {
930 // // DEBUG CODE ==============================================================================================================
931 // LogStream << "Now at [" << nX << "][" << nY << "] = {" << dGridCentroidXToExtCRSX(nX) << ", " << dGridCentroidYToExtCRSY(nY) << "}" << endl;
932 // LogStream << "ILTempGridCRS is now:" << endl;
933 // for (int n = 0; n < ILTempGridCRS.nGetSize(); n++)
934 // LogStream << "[" << ILTempGridCRS[n].nGetX() << "][" << ILTempGridCRS[n].nGetY() << "] = {" << dGridCentroidXToExtCRSX(ILTempGridCRS[n].nGetX()) << ", " << dGridCentroidYToExtCRSY(ILTempGridCRS[n].nGetY()) << "}" << endl;
935 // LogStream << "=================" << endl;
936 // // DEBUG CODE ==============================================================================================================
937
938 // Safety check
939 if (++nRoundLoop > m_nCoastMax)
940 {
941 bTooLong = true;
942
943 LogStream << m_ulIter << ": \tabandoning possible coastline, traced from [" << nStartX << "][" << nStartY << "] = {" << dGridCentroidXToExtCRSX(nStartX) << ", " << dGridCentroidYToExtCRSY(nStartY) << "}, exceeded maximum search length (" << m_nCoastMax << ")" << endl;
944
945 // for (int n = 0; n < ILTempGridCRS.nGetSize(); n++)
946 // LogStream << "[" << ILTempGridCRS[n].nGetX() << "][" << ILTempGridCRS[n].nGetY() << "] = {" << dGridCentroidXToExtCRSX(ILTempGridCRS[n].nGetX()) << ", " << dGridCentroidYToExtCRSY(ILTempGridCRS[n].nGetY()) << "}" << endl;
947 // LogStream << endl;
948
949 break;
950 }
951
952 // Another safety check
953 if ((nRoundLoop > 10) && (ILTempGridCRS.nGetSize() < 2))
954 {
955 // We've been 10 times round the loop but the coast is still less than 2 coastline points in length, so we must be repeating
956 bRepeating = true;
957
958 LogStream << m_ulIter << ": \tabandoning possible coastline, traced from [" << nStartX << "][" << nStartY << "] = {" << dGridCentroidXToExtCRSX(nStartX) << ", " << dGridCentroidYToExtCRSY(nStartY) << "}, is looping" << endl;
959
960 break;
961 }
962
963 // OK so far: so have we left the start edge?
964 if (! bHasLeftStartEdge)
965 {
966 // We have not yet left the start edge
967 if (((nStartSearchDirection == SOUTH) && (nY > nStartY)) || ((nStartSearchDirection == NORTH) && (nY < nStartY)) || ((nStartSearchDirection == EAST) && (nX > nStartX)) || ((nStartSearchDirection == WEST) && (nX < nStartX)))
968 bHasLeftStartEdge = true;
969
970 // Flag this cell to ensure that it is not chosen as a coastline start cell later
971 m_pRasterGrid->m_Cell[nX][nY].SetPossibleCoastStartCell();
972 // LogStream << "Flagging [" << nX << "][" << nY << "] as possible coast start cell NOT YET LEFT EDGE" << endl;
973 }
974
975 // If the vector coastline has left the start edge, and we hit a possible coast start point from which a coastline has not yet been traced, then leave the loop
976 // LogStream << "bHasLeftStartEdge = " << bHasLeftStartEdge << " bAtCoast = " << bAtCoast << endl;
977 if (bHasLeftStartEdge && bAtCoast)
978 {
979 for (unsigned int nn = 0; nn < pVbTraced->size(); nn++)
980 {
981 bool const bTraced = pVbTraced->at(nn);
982 if ((nn != nTraceFromStartCellIndex) && (! bTraced))
983 {
984 int const nXPoss = pV2DIPossibleStartCell->at(nn).nGetX();
985 int const nYPoss = pV2DIPossibleStartCell->at(nn).nGetY();
986
987 // LogStream << "In 'Leave the edge' loop for [" << nX << "][" << nY << "] bTraced = " << bTraced << " nn = " << nn << " nTraceFromStartCellIndex = " << nTraceFromStartCellIndex << " possible start cell = [" << nXPoss << "][" << nYPoss << "]" << endl;
988
989 if ((nX == nXPoss) && (nY == nYPoss))
990 {
992 LogStream << m_ulIter << ": \tpossible coastline found, traced from [" << nStartX << "][" << nStartY << "] = {" << dGridCentroidXToExtCRSX(nStartX) << ", " << dGridCentroidYToExtCRSY(nStartY) << "}, ended at possible coast start cell at [" << nX << "][" << nY << "] = {" << dGridCentroidXToExtCRSX(nX) << ", " << dGridCentroidYToExtCRSY(nY) << "}" << endl;
993
994 pVbTraced->at(nn) = true;
995 bHitStartCell = true;
996 break;
997 }
998 }
999 }
1000 }
1001
1002 if (bHitStartCell)
1003 break;
1004
1005 // OK now sort out the next iteration of the search
1006 int nXSeaward = 0;
1007 int nYSeaward = 0;
1008 int nSeawardNewDirection = 0;
1009 int nXStraightOn = 0;
1010 int nYStraightOn = 0;
1011 int nXAntiSeaward = 0;
1012 int nYAntiSeaward = 0;
1013 int nAntiSeawardNewDirection = 0;
1014 int nXGoBack = 0;
1015 int nYGoBack = 0;
1016 int nGoBackNewDirection = 0;
1017
1018 CGeom2DIPoint const Pti(nX, nY);
1019
1020 // Set up the variables
1021 switch (nHandedness)
1022 {
1023 case RIGHT_HANDED:
1024 // The sea is to the right-hand side of the coast as we traverse it. We are just inland, so we need to keep heading right to find the sea
1025 switch (nSearchDirection)
1026 {
1027 case NORTH:
1028 // The sea is towards the RHS (E) of the coast, so first try to go right (to the E)
1029 nXSeaward = nX + 1;
1030 nYSeaward = nY;
1031 nSeawardNewDirection = EAST;
1032
1033 // If can't do this, try to go straight on (to the N)
1034 nXStraightOn = nX;
1035 nYStraightOn = nY - 1;
1036
1037 // If can't do either of these, try to go anti-seaward i.e. towards the LHS (W)
1038 nXAntiSeaward = nX - 1;
1039 nYAntiSeaward = nY;
1040 nAntiSeawardNewDirection = WEST;
1041
1042 // As a last resort, go back (to the S)
1043 nXGoBack = nX;
1044 nYGoBack = nY + 1;
1045 nGoBackNewDirection = SOUTH;
1046
1047 break;
1048
1049 case EAST:
1050 // The sea is towards the RHS (S) of the coast, so first try to go right (to the S)
1051 nXSeaward = nX;
1052 nYSeaward = nY + 1;
1053 nSeawardNewDirection = SOUTH;
1054
1055 // If can't do this, try to go straight on (to the E)
1056 nXStraightOn = nX + 1;
1057 nYStraightOn = nY;
1058
1059 // If can't do either of these, try to go anti-seaward i.e. towards the LHS (N)
1060 nXAntiSeaward = nX;
1061 nYAntiSeaward = nY - 1;
1062 nAntiSeawardNewDirection = NORTH;
1063
1064 // As a last resort, go back (to the W)
1065 nXGoBack = nX - 1;
1066 nYGoBack = nY;
1067 nGoBackNewDirection = WEST;
1068
1069 break;
1070
1071 case SOUTH:
1072 // The sea is towards the RHS (W) of the coast, so first try to go right (to the W)
1073 nXSeaward = nX - 1;
1074 nYSeaward = nY;
1075 nSeawardNewDirection = WEST;
1076
1077 // If can't do this, try to go straight on (to the S)
1078 nXStraightOn = nX;
1079 nYStraightOn = nY + 1;
1080
1081 // If can't do either of these, try to go anti-seaward i.e. towards the LHS (E)
1082 nXAntiSeaward = nX + 1;
1083 nYAntiSeaward = nY;
1084 nAntiSeawardNewDirection = EAST;
1085
1086 // As a last resort, go back (to the N)
1087 nXGoBack = nX;
1088 nYGoBack = nY - 1;
1089 nGoBackNewDirection = NORTH;
1090
1091 break;
1092
1093 case WEST:
1094 // The sea is towards the RHS (N) of the coast, so first try to go right (to the N)
1095 nXSeaward = nX;
1096 nYSeaward = nY - 1;
1097 nSeawardNewDirection = NORTH;
1098
1099 // If can't do this, try to go straight on (to the W)
1100 nXStraightOn = nX - 1;
1101 nYStraightOn = nY;
1102
1103 // If can't do either of these, try to go anti-seaward i.e. towards the LHS (S)
1104 nXAntiSeaward = nX;
1105 nYAntiSeaward = nY + 1;
1106 nAntiSeawardNewDirection = SOUTH;
1107
1108 // As a last resort, go back (to the E)
1109 nXGoBack = nX + 1;
1110 nYGoBack = nY;
1111 nGoBackNewDirection = EAST;
1112
1113 break;
1114 }
1115
1116 break;
1117
1118 case LEFT_HANDED:
1119
1120 // The sea is to the left-hand side of the coast as we traverse it. We are just inland, so we need to keep heading left to find the sea
1121 switch (nSearchDirection)
1122 {
1123 case NORTH:
1124 // The sea is towards the LHS (W) of the coast, so first try to go left (to the W)
1125 nXSeaward = nX - 1;
1126 nYSeaward = nY;
1127 nSeawardNewDirection = WEST;
1128
1129 // If can't do this, try to go straight on (to the N)
1130 nXStraightOn = nX;
1131 nYStraightOn = nY - 1;
1132
1133 // If can't do either of these, try to go anti-seaward i.e. towards the RHS (E)
1134 nXAntiSeaward = nX + 1;
1135 nYAntiSeaward = nY;
1136 nAntiSeawardNewDirection = EAST;
1137
1138 // As a last resort, go back (to the S)
1139 nXGoBack = nX;
1140 nYGoBack = nY + 1;
1141 nGoBackNewDirection = SOUTH;
1142
1143 break;
1144
1145 case EAST:
1146 // The sea is towards the LHS (N) of the coast, so first try to go left (to the N)
1147 nXSeaward = nX;
1148 nYSeaward = nY - 1;
1149 nSeawardNewDirection = NORTH;
1150
1151 // If can't do this, try to go straight on (to the E)
1152 nXStraightOn = nX + 1;
1153 nYStraightOn = nY;
1154
1155 // If can't do either of these, try to go anti-seaward i.e. towards the RHS (S)
1156 nXAntiSeaward = nX;
1157 nYAntiSeaward = nY + 1;
1158 nAntiSeawardNewDirection = SOUTH;
1159
1160 // As a last resort, go back (to the W)
1161 nXGoBack = nX - 1;
1162 nYGoBack = nY;
1163 nGoBackNewDirection = WEST;
1164
1165 break;
1166
1167 case SOUTH:
1168 // The sea is towards the LHS (E) of the coast, so first try to go left (to the E)
1169 nXSeaward = nX + 1;
1170 nYSeaward = nY;
1171 nSeawardNewDirection = EAST;
1172
1173 // If can't do this, try to go straight on (to the S)
1174 nXStraightOn = nX;
1175 nYStraightOn = nY + 1;
1176
1177 // If can't do either of these, try to go anti-seaward i.e. towards the RHS (W)
1178 nXAntiSeaward = nX - 1;
1179 nYAntiSeaward = nY;
1180 nAntiSeawardNewDirection = WEST;
1181
1182 // As a last resort, go back (to the N)
1183 nXGoBack = nX;
1184 nYGoBack = nY - 1;
1185 nGoBackNewDirection = NORTH;
1186
1187 break;
1188
1189 case WEST:
1190 // The sea is towards the LHS (S) of the coast, so first try to go left (to the S)
1191 nXSeaward = nX;
1192 nYSeaward = nY + 1;
1193 nSeawardNewDirection = SOUTH;
1194
1195 // If can't do this, try to go straight on (to the W)
1196 nXStraightOn = nX - 1;
1197 nYStraightOn = nY;
1198
1199 // If can't do either of these, try to go anti-seaward i.e. towards the RHS (N)
1200 nXAntiSeaward = nX;
1201 nYAntiSeaward = nY - 1;
1202 nAntiSeawardNewDirection = NORTH;
1203
1204 // As a last resort, go back (to the E)
1205 nXGoBack = nX + 1;
1206 nYGoBack = nY;
1207 nGoBackNewDirection = EAST;
1208
1209 break;
1210 }
1211
1212 break;
1213 }
1214
1215 // Now do the actual search for this timestep: first try going in the direction of the sea. Is this seaward cell still within the grid?
1216 if (bIsWithinValidGrid(nXSeaward, nYSeaward))
1217 {
1218 // It is, so check if the cell in the seaward direction is a sea cell
1219 if (m_pRasterGrid->m_Cell[nXSeaward][nYSeaward].bIsInContiguousSea())
1220 {
1221 // There is sea in this seaward direction, so we are on the coast
1222 bAtCoast = true;
1223
1224 // Has the current cell already marked been marked as a coast cell?
1225 if (! m_pRasterGrid->m_Cell[nX][nY].bIsCoastline())
1226 {
1227 // Not already marked, is this an intervention cell with the top above SWL?
1228 if ((bIsInterventionCell(nX, nY)) && (m_pRasterGrid->m_Cell[nX][nY].dGetInterventionTopElev() >= m_dThisIterSWL))
1229 {
1230 // It is, so add it to the vector
1231 ILTempGridCRS.AppendIfNotPrevious(&Pti);
1232 }
1233 else if (m_pRasterGrid->m_Cell[nX][nY].dGetAllSedTopElevIncTalus() >= m_dThisIterSWL)
1234 {
1235 // The sediment top (inc any talus) is above SWL so add it to the vector object
1236 ILTempGridCRS.AppendIfNotPrevious(&Pti);
1237 }
1238 }
1239 }
1240 else
1241 {
1242 // The seaward cell is not a sea cell, so we will move to it next time
1243 nX = nXSeaward;
1244 nY = nYSeaward;
1245
1246 // And set a new search direction, to keep turning seaward
1247 nSearchDirection = nSeawardNewDirection;
1248 continue;
1249 }
1250 }
1251
1252 // OK, we couldn't move seaward (but we may have marked the current cell as coast) so next try to move straight on. Is this straight-ahead cell still within the grid?
1253 if (bIsWithinValidGrid(nXStraightOn, nYStraightOn))
1254 {
1255 // It is, so check if there is sea immediately in front
1256 if (m_pRasterGrid->m_Cell[nXStraightOn][nYStraightOn].bIsInContiguousSea())
1257 {
1258 // Sea is in front, so we are on the coast
1259 bAtCoast = true;
1260
1261 // Has the current cell already marked been marked as a coast cell?
1262 if (! m_pRasterGrid->m_Cell[nX][nY].bIsCoastline())
1263 {
1264 // Not already marked, is this an intervention cell with the top above SWL?
1265 if ((bIsInterventionCell(nX, nY)) && (m_pRasterGrid->m_Cell[nX][nY].dGetInterventionTopElev() >= m_dThisIterSWL))
1266 {
1267 // It is, so add it to the vector object
1268 ILTempGridCRS.AppendIfNotPrevious(&Pti);
1269 }
1270 else if (m_pRasterGrid->m_Cell[nX][nY].dGetAllSedTopElevIncTalus() >= m_dThisIterSWL)
1271 {
1272 // The sediment top (inc any talus) is above SWL so add it to the vector object
1273 ILTempGridCRS.AppendIfNotPrevious(&Pti);
1274 }
1275 }
1276 }
1277 else
1278 {
1279 // The straight-ahead cell is not a sea cell, so we will move to it next time
1280 nX = nXStraightOn;
1281 nY = nYStraightOn;
1282
1283 // The search direction remains unchanged
1284 continue;
1285 }
1286 }
1287
1288 // Couldn't move either seaward or straight on (but we may have marked the current cell as coast) so next try to move in the anti-seaward direction. Is this anti-seaward cell still within the grid?
1289 if (bIsWithinValidGrid(nXAntiSeaward, nYAntiSeaward))
1290 {
1291 // It is, so check if there is sea in this anti-seaward cell
1292 if (m_pRasterGrid->m_Cell[nXAntiSeaward][nYAntiSeaward].bIsInContiguousSea())
1293 {
1294 // There is sea on the anti-seaward side, so we are on the coast
1295 bAtCoast = true;
1296
1297 // Has the current cell already marked been marked as a coast cell?
1298 if (! m_pRasterGrid->m_Cell[nX][nY].bIsCoastline())
1299 {
1300 // Not already marked, is this an intervention cell with the top above SWL?
1301 if ((bIsInterventionCell(nX, nY)) && (m_pRasterGrid->m_Cell[nX][nY].dGetInterventionTopElev() >= m_dThisIterSWL))
1302 {
1303 // It is, so add it to the vector object
1304 ILTempGridCRS.AppendIfNotPrevious(&Pti);
1305 }
1306 else if (m_pRasterGrid->m_Cell[nX][nY].dGetAllSedTopElevIncTalus() >= m_dThisIterSWL)
1307 {
1308 // The sediment top (inc any talus) is above SWL so add it to the vector object
1309 ILTempGridCRS.AppendIfNotPrevious(&Pti);
1310 }
1311 }
1312 }
1313 else
1314 {
1315 // The anti-seaward cell is not a sea cell, so we will move to it next time
1316 nX = nXAntiSeaward;
1317 nY = nYAntiSeaward;
1318
1319 // And set a new search direction, to keep turning seaward
1320 nSearchDirection = nAntiSeawardNewDirection;
1321 continue;
1322 }
1323 }
1324
1325 // Could not move to the seaward side, move straight ahead, or move to the anti-seaward side, so we must be in a single-cell dead end! As a last resort, turn round and move back to where we just came from, but first check that this is a valid cell
1326 if (bIsWithinValidGrid(nXGoBack, nYGoBack))
1327 {
1328 nX = nXGoBack;
1329 nY = nYGoBack;
1330
1331 // And change the search direction
1332 nSearchDirection = nGoBackNewDirection;
1333 }
1334 else
1335 {
1336 // Our final choice is not a valid cell, so give up
1337 bOffEdge = true;
1338 break;
1339 }
1340 } while (true);
1341
1342 // OK, we have a coastline. So is the coastline too long or too short?
1343 int nCoastSize = ILTempGridCRS.nGetSize();
1344
1345 if (bOffEdge)
1346 {
1348 LogStream << m_ulIter << ": \t**** TEST abandoning possible coastline from [" << nStartX << "][" << nStartY << "] = {" << dGridCentroidXToExtCRSX(nStartX) << ", " << dGridCentroidYToExtCRSY(nStartY) << "} since hit off-edge cell at [" << nX << "][" << nY << "] = {" << dGridCentroidXToExtCRSX(nX) << ", " << dGridCentroidYToExtCRSY(nY) << "}, coastline size is " << nCoastSize << endl;
1349
1350 // return RTN_ERR_IGNORING_COAST;
1351 }
1352
1353 if (bTooLong)
1354 {
1355 // Around loop too many times, so abandon this coastline
1357 {
1358 LogStream << m_ulIter << ": \tabandoning possible coastline from [" << nStartX << "][" << nStartY << "] = {" << dGridCentroidXToExtCRSX(nStartX) << ", " << dGridCentroidYToExtCRSY(nStartY) << "} since round loop " << nRoundLoop << " times, coastline size is " << nCoastSize;
1359
1360 if (nCoastSize > 0)
1361 LogStream << ", ended at [" << ILTempGridCRS[nCoastSize - 1].nGetX() << "][" << ILTempGridCRS[nCoastSize - 1].nGetY() << "] = {" << dGridCentroidXToExtCRSX(ILTempGridCRS[nCoastSize - 1].nGetX()) << ", " << dGridCentroidYToExtCRSY(ILTempGridCRS[nCoastSize - 1].nGetY()) << "}";
1362
1363 LogStream << endl;
1364 }
1365
1367 }
1368
1369 if (bRepeating)
1370 {
1372 {
1373 LogStream << m_ulIter << ": abandon possible coastline from [" << nStartX << "][" << nStartY << "] = {" << dGridCentroidXToExtCRSX(nStartX) << ", " << dGridCentroidYToExtCRSY(nStartY) << "} since repeating, coastline size is " << nCoastSize;
1374
1375 if (nCoastSize > 0)
1376 LogStream << ", it ended at [" << ILTempGridCRS[nCoastSize - 1].nGetX() << "][" << ILTempGridCRS[nCoastSize - 1].nGetY() << "] = {" << dGridCentroidXToExtCRSX(ILTempGridCRS[nCoastSize - 1].nGetX()) << ", " << dGridCentroidYToExtCRSY(ILTempGridCRS[nCoastSize - 1].nGetY()) << "}";
1377
1378 LogStream << endl;
1379 }
1380
1382 }
1383
1384 if (nCoastSize == 0)
1385 {
1386 // Zero-length coastline, so abandon it
1388 LogStream << m_ulIter << ": abandoning zero-length coastline from [" << nStartX << "][" << nStartY << "] = {" << dGridCentroidXToExtCRSX(nStartX) << ", " << dGridCentroidYToExtCRSY(nStartY) << "}" << endl;
1389
1391 }
1392
1393 if (nCoastSize < m_nCoastMin)
1394 {
1395 // The vector coastline is too small, so abandon it
1397 LogStream << m_ulIter << ": \tabandoning possible coastline from [" << nStartX << "][" << nStartY << "] = {" << dGridCentroidXToExtCRSX(nStartX) << ", " << dGridCentroidYToExtCRSY(nStartY) << "} to [" << ILTempGridCRS[nCoastSize - 1].nGetX() << "][" << ILTempGridCRS[nCoastSize - 1].nGetY() << "] = {" << dGridCentroidXToExtCRSX(ILTempGridCRS[nCoastSize - 1].nGetX()) << ", " << dGridCentroidYToExtCRSY(ILTempGridCRS[nCoastSize - 1].nGetY()) << "} since size (" << nCoastSize << ") is less than minimum (" << m_nCoastMin << ")" << endl;
1398
1400 }
1401
1402 // OK this new coastline is fine
1403 int const nEndX = nX;
1404 int const nEndY = nY;
1405 int const nCoastEndX = ILTempGridCRS[nCoastSize - 1].nGetX();
1406 int const nCoastEndY = ILTempGridCRS[nCoastSize - 1].nGetY();
1407
1408 if ((nCoastEndX != nEndX) || (nCoastEndY != nEndY))
1409 {
1410 // The grid-edge cell at nEndX, nEndY is not already at end of ILTempGridCRS. But is the final cell in ILTempGridCRS already at the edge of the grid?
1411 if (! m_pRasterGrid->m_Cell[nCoastEndX][nCoastEndY].bIsBoundingBoxEdge())
1412 {
1413 // The final cell in ILTempGridCRS is not a grid-edge cell, so add the grid-edge cell and mark the cell as coastline
1414 ILTempGridCRS.AppendIfNotPrevious(nEndX, nEndY);
1415 nCoastSize++;
1416 }
1417 }
1418
1419 // Need to specify start edge and end edge for smoothing routines
1420 int const nStartEdge = m_pRasterGrid->m_Cell[nStartX][nStartY].nGetBoundingBoxEdge();
1421 int const nEndEdge = m_pRasterGrid->m_Cell[nEndX][nEndY].nGetBoundingBoxEdge();
1422
1423 // Next, convert the grid coordinates in ILTempGridCRS (integer values stored as doubles) to external CRS coordinates (which will probably be non-integer, again stored as doubles). This is done now, so that smoothing is more effective
1424 CGeomLine LTempExtCRS;
1425
1426 for (int j = 0; j < nCoastSize; j++)
1427 LTempExtCRS.Append(dGridCentroidXToExtCRSX(ILTempGridCRS[j].nGetX()), dGridCentroidYToExtCRSY(ILTempGridCRS[j].nGetY()));
1428
1429 // Now do some smoothing of the vector output, if desired
1431 LTempExtCRS = LSmoothCoastRunningMean(&LTempExtCRS);
1433 LTempExtCRS = LSmoothCoastSavitzkyGolay(&LTempExtCRS, nStartEdge, nEndEdge);
1434
1435 // // DEBUG CODE ==================================================================================================
1436 // LogStream << "==================================" << endl;
1437 // for (int j = 0; j < nCoastSize; j++)
1438 // {
1439 // LogStream << "{" << dGridCentroidXToExtCRSX(ILTempGridCRS[j].nGetX()) << ", " << dGridCentroidYToExtCRSY(ILTempGridCRS[j].nGetY()) << "}" << "\t{" << LTempExtCRS.dGetXAt(j) << ", " << LTempExtCRS.dGetYAt(j) << "}" << endl;
1440 // }
1441 // LogStream << "==================================" << endl;
1442 // // DEBUG CODE ==================================================================================================
1443
1444 // Create a new coastline object and append to it the vector of coastline objects
1445 CRWCoast const CoastTmp(this);
1446 m_VCoast.push_back(CoastTmp);
1447 int const nCoast = static_cast<int>(m_VCoast.size()) - 1;
1448
1449 // Now mark the coastline on the grid
1450 for (int n = 0; n < nCoastSize; n++)
1451 m_pRasterGrid->m_Cell[ILTempGridCRS[n].nGetX()][ILTempGridCRS[n].nGetY()].SetAsCoastline(nCoast);
1452
1453 // Set the coastline (Ext CRS)
1454 m_VCoast[nCoast].SetCoastlineExtCRS(&LTempExtCRS);
1455
1456 // Set the coastline (Grid CRS)
1457 m_VCoast[nCoast].SetCoastlineGridCRS(&ILTempGridCRS);
1458
1459 // CGeom2DPoint PtLast(DBL_MIN, DBL_MIN);
1460 // for (int j = 0; j < nCoastSize; j++)
1461 // {
1462 // // Store the smoothed points (in external CRS) in the coast's m_LCoastlineExtCRS object, also append dummy values to the other attribute vectors
1463 // if (PtLast != &LTempExtCRS[j]) // Avoid duplicate points
1464 // {
1465 // m_VCoast[nCoast].AppendPointToCoastlineExtCRS(LTempExtCRS[j].dGetX(), LTempExtCRS[j].dGetY());
1466 //
1467 // // Also store the locations of the corresponding unsmoothed points (in raster grid CRS) in the coast's m_ILCellsMarkedAsCoastline vector
1468 // m_VCoast[nCoast].AppendCellMarkedAsCoastline(&ILTempGridCRS[j]);
1469 // }
1470 //
1471 // PtLast = LTempExtCRS[j];
1472 // }
1473
1474 // Set values for the coast's other attributes: set the coast's handedness, and start and end edges
1475 m_VCoast[nCoast].SetSeaHandedness(nHandedness);
1476 m_VCoast[nCoast].SetStartEdge(nStartEdge);
1477 m_VCoast[nCoast].SetEndEdge(nEndEdge);
1478
1480 {
1481 LogStream << m_ulIter << ": \tvalid coast " << nCoast << " created, from [" << nStartX << "][" << nStartY << "] to [" << nEndX << "][" << nEndY << "] = {" << dGridCentroidXToExtCRSX(nStartX) << ", " << dGridCentroidYToExtCRSY(nStartY) << "} to {" << dGridCentroidXToExtCRSX(nEndX) << ", " << dGridCentroidYToExtCRSY(nEndY) << "} with " << nCoastSize << " points, handedness = " << (nHandedness == LEFT_HANDED ? "left" : "right") << endl;
1482
1483 LogStream << m_ulIter << ": \tsmoothed coastline " << nCoast << " runs from {" << LTempExtCRS[0].dGetX() << ", " << LTempExtCRS[0].dGetY() << "} to {" << LTempExtCRS[nCoastSize - 1].dGetX() << ", " << LTempExtCRS[nCoastSize - 1].dGetY() << "} i.e. from the ";
1484
1485 if (nStartEdge == NORTH)
1486 LogStream << "north";
1487 else if (nStartEdge == SOUTH)
1488 LogStream << "south";
1489 else if (nStartEdge == WEST)
1490 LogStream << "west";
1491 else if (nStartEdge == EAST)
1492 LogStream << "east";
1493
1494 LogStream << " edge to the ";
1495 if (nEndEdge == NORTH)
1496 LogStream << "north";
1497 else if (nEndEdge == SOUTH)
1498 LogStream << "south";
1499 else if (nEndEdge == WEST)
1500 LogStream << "west";
1501 else if (nEndEdge == EAST)
1502 LogStream << "east";
1503 LogStream << " edge" << endl;
1504 }
1505
1506 // LogStream << "-----------------" << endl;
1507 // for (int kk = 0; kk < m_VCoast.back().nGetCoastlineSize(); kk++)
1508 // LogStream << kk << " [" << m_VCoast.back().pPtiGetCellMarkedAsCoastline(kk)->nGetX() << "][" << m_VCoast.back().pPtiGetCellMarkedAsCoastline(kk)->nGetY() << "] = {" << dGridCentroidXToExtCRSX(m_VCoast.back().pPtiGetCellMarkedAsCoastline(kk)->nGetX()) << ", " << dGridCentroidYToExtCRSY(m_VCoast.back().pPtiGetCellMarkedAsCoastline(kk)->nGetY()) << "}" << endl;
1509 // LogStream << "-----------------" << endl;
1510
1511 // Next calculate the curvature of the vector coastline
1512 DoCoastCurvature(nCoast, nHandedness);
1513
1514 // Calculate values for the coast's flux orientation vector
1515 CalcCoastTangents(nCoast);
1516
1517 // And create the vector of pointers to coastline-normal objects
1518 m_VCoast[nCoast].CreateProfilesAtCoastPoints();
1519
1520 return RTN_OK;
1521}
1522
1523//===============================================================================================================================
1525//===============================================================================================================================
1527{
1528 // Find all connected sea cells
1530
1531 // Find every coastline on the raster grid, mark raster cells, then create the vector coastline
1532 int const nRet = nTraceAllFloodCoasts();
1533
1534 if (nRet != RTN_OK)
1535 return nRet;
1536
1537 // Have we created any coasts?
1538 switch (m_nLevel)
1539 {
1540 case 0: // WAVESETUP + SURGE:
1541 {
1542 if (m_VFloodWaveSetupSurge.empty())
1543 {
1544 cerr << m_ulIter << ": " << ERR << "no flood coastline located: this iteration SWL = " << m_dThisIterSWL << ", maximum DEM top surface elevation = " << m_dThisIterTopElevMax << ", minimum DEM top surface elevation = " << m_dThisIterTopElevMin << endl;
1545 return RTN_ERR_NO_COAST;
1546 }
1547
1548 break;
1549 }
1550
1551 case 1: // WAVESETUP + SURGE + RUNUP:
1552 {
1553 if (m_VFloodWaveSetupSurgeRunup.empty())
1554 {
1555 cerr << m_ulIter << ": " << ERR << "no flood coastline located: this iteration SWL = " << m_dThisIterSWL << ", maximum DEM top surface elevation = " << m_dThisIterTopElevMax << ", minimum DEM top surface elevation = " << m_dThisIterTopElevMin << endl;
1556 return RTN_ERR_NO_COAST;
1557 }
1558
1559 break;
1560 }
1561 }
1562
1563 return RTN_OK;
1564}
1565
1566//===============================================================================================================================
1568//===============================================================================================================================
1570{
1571 for (int nX = 0; nX < m_nXGridSize; nX++)
1572 {
1573 for (int nY = 0; nY < m_nYGridSize; nY++)
1574 {
1575 m_pRasterGrid->m_Cell[nX][nY].UnSetCheckFloodCell();
1576 m_pRasterGrid->m_Cell[nX][nY].UnSetInContiguousFlood();
1577 m_pRasterGrid->m_Cell[nX][nY].SetAsFloodline(false);
1578 }
1579 }
1580
1581 // Go along the list of edge cells
1582 for (unsigned int n = 0; n < m_VEdgeCell.size(); n++)
1583 {
1585 continue;
1586
1588 continue;
1589
1591 continue;
1592
1594 continue;
1595
1596 int const nX = m_VEdgeCell[n].nGetX();
1597 int const nY = m_VEdgeCell[n].nGetY();
1598
1599 if ((! m_pRasterGrid->m_Cell[nX][nY].bIsCellFloodCheck()) && (m_pRasterGrid->m_Cell[nX][nY].bIsInundated()))
1600 {
1601 // This edge cell is below SWL and sea depth remains set to zero
1602 FloodFillLand(nX, nY);
1603 }
1604 }
1605
1606 return RTN_OK;
1607}
Contains CGeom2DIPoint definitions.
int nGetSize(void) const
Returns the number of integer point in the vector which represents this 2D shape.
Definition 2di_shape.cpp:65
void AppendIfNotPrevious(int const, int const)
Appends a new integer point to the vector which represents this 2D shape, but only if the point is no...
Definition 2di_shape.cpp:88
void Append(CGeom2DIPoint const *)
Appends a new integer point to the vector which represents this 2D shape.
Definition 2di_shape.cpp:76
void Append(CGeom2DPoint const *)
Appends a point to this 2D shape.
Definition 2d_shape.cpp:64
Geometry class used to represent 2D point objects with integer coordinates.
Definition 2di_point.h:25
int nGetY(void) const
Returns the CGeom2DIPoint object's integer Y coordinate.
Definition 2di_point.cpp:51
int nGetX(void) const
Returns the CGeom2DIPoint object's integer X coordinate.
Definition 2di_point.cpp:45
Geometry class used to represent 2D vector integer line objects.
Definition i_line.h:27
Geometry class used to represent 2D vector line objects.
Definition line.h:28
Real-world class used to represent the landform of a cell.
int nGetLFCategory(void) const
Get the landform category.
void SetLFCategory(int const)
Set the landform category.
Real-world class used to represent coastline objects.
Definition coast.h:39
int m_nLogFileDetail
The level of detail in the log file output. Can be LOG_FILE_LOW_DETAIL, LOG_FILE_MIDDLE_DETAIL,...
Definition simulation.h:585
int m_nYMinBoundingBox
The minimum y value of the bounding box.
Definition simulation.h:555
void FindAllSeaCells(void)
Finds and flags all sea areas which have at least one cell at a grid edge (i.e. does not flag 'inland...
CGeomLine LSmoothCoastRunningMean(CGeomLine *) const
Does running-mean smoothing of a CGeomLine coastline vector (is in external CRS coordinates)
double m_dThisIterSWL
The still water level for this timestep (this includes tidal changes and any long-term SWL change)
Definition simulation.h:723
CGeomRasterGrid * m_pRasterGrid
Pointer to the raster grid object.
int m_nXGridSize
The size of the grid in the x direction.
Definition simulation.h:474
static int nGetOppositeDirection(int const)
Returns the opposite direction.
ofstream LogStream
vector< CRWCoast > m_VFloodWaveSetupSurgeRunup
TODO 007 Finish surge and runup stuff.
vector< CRWCoast > m_VCoast
The coastline objects.
int nLocateFloodAndCoasts(void)
First find all connected sea areas, then locate the vector coastline(s), then put these onto the rast...
int nTraceCoastLine(unsigned int const, int const, int const, vector< bool > *, vector< CGeom2DIPoint > const *)
Traces a coastline (which is defined to be just above still water level) on the grid using the 'wall ...
int nTraceAllFloodCoasts(void)
Locates all the potential coastline start points on the edges of the raster grid, then traces vector ...
void FloodFillLand(int const, int const)
Use the sealevel, wave set-up and run-up to evaluate flood hydraulically connected TODO 007 Finish su...
int m_nYGridSize
The size of the grid in the y direction.
Definition simulation.h:477
double m_dThisIterTopElevMin
This-iteration lowest elevation of DEM.
Definition simulation.h:984
void CalcCoastTangents(int const)
Calculates tangents to a coastline: the tangent is assumed to be the orientation of energy/sediment f...
vector< CGeomLine > m_VLowestSWLCoastLine
Coastline (external CRS) at the lowest SWL so far during this simulation.
vector< CRWCoast > m_VFloodWaveSetupSurge
TODO 007 Finish surge and runup stuff.
int m_nCoastMax
Maximum valid coast length when searching for coasts.
Definition simulation.h:525
int m_nXMaxBoundingBox
The maximum x value of the bounding box.
Definition simulation.h:552
bool m_bLowestSWLSoFar
Do we have the lowest SWL so far?
Definition simulation.h:465
vector< CGeomLine > m_VHighestSWLCoastLine
Coastline (external CRS) at the highest SWL so far during this simulation.
string m_strLogFile
Name of output log file.
bool m_bOmitSearchWestEdge
Omit the west edge of the grid from coast-end searches?
Definition simulation.h:354
double dGridCentroidYToExtCRSY(int const) const
Given the integer Y-axis ordinate of a cell in the raster grid CRS, returns the external CRS Y-axis o...
Definition gis_utils.cpp:74
int m_nCoastMin
Minimum valid coast length when searching for coasts.
Definition simulation.h:528
bool m_bOmitSearchNorthEdge
Omit the north edge of the grid from coast-end searches?
Definition simulation.h:348
vector< CGeom2DIPoint > m_VEdgeCell
Edge cells.
bool m_bHighestSWLSoFar
Do we have the highest SWL so far?
Definition simulation.h:462
int m_nYMaxBoundingBox
The maximum y value of the bounding box.
Definition simulation.h:558
unsigned long m_ulThisIterNumSeaCells
The number of grid cells which are marked as sea, for this iteration.
Definition simulation.h:618
CGeomLine LSmoothCoastSavitzkyGolay(CGeomLine *, int const, int const) const
Does smoothing of a CGeomLine coastline vector (is in external CRS coordinates) using a Savitzky-Gola...
int nLocateSeaAndCoasts(void)
First find all connected sea areas, then locate the vector coastline(s), then put these onto the rast...
int m_nXMinBoundingBox
The minimum x value of the bounding box.
Definition simulation.h:549
bool bIsWithinValidGrid(int const, int const) const
Checks whether the supplied point (an x-y pair, in the grid CRS) is within the raster grid,...
int m_nCoastSmooth
Which method to use for coast smoothing.
Definition simulation.h:483
void DoCoastCurvature(int const, int const)
Calculates both detailed and smoothed curvature for every point on a coastline.
int nTraceAllCoasts(void)
Locates all the potential coastline start/finish points on the edges of the raster grid,...
bool m_bOmitSearchSouthEdge
Omit the south edge of the grid from coast-end searches?
Definition simulation.h:351
unsigned long m_ulIter
The number of the current iteration (time step)
Definition simulation.h:606
double dGridCentroidXToExtCRSX(int const) const
Given the integer X-axis ordinate of a cell in the raster grid CRS, returns the external CRS X-axis o...
Definition gis_utils.cpp:65
void CellByCellFillSea(int const, int const)
Cell-by-cell fills all sea cells starting from a given cell. The cell-by-cell fill (aka 'floodfill') ...
bool bIsInterventionCell(int const, int const) const
Returns true if the cell is an intervention.
Definition utils.cpp:3055
double m_dThisIterTopElevMax
This-iteration highest elevation of DEM.
Definition simulation.h:981
int FindAllInundatedCells(void)
Finds and flags all sea areas which have at least one cell at a grid edge (i.e. does not flag 'inland...
int m_nLevel
TODO 007 Used in WAVESETUP + SURGE + RUNUP Finish surge and runup stuff.
Definition simulation.h:591
bool m_bOmitSearchEastEdge
Omit the east edge of the grid from coast-end searches?
Definition simulation.h:357
vector< int > m_VEdgeCellEdge
The grid edge that each edge cell belongs to.
This file contains global definitions for CoastalME.
double const TOLERANCE
Definition cme.h:722
int const LF_SEA
Definition cme.h:434
string const ERR
Definition cme.h:802
int const RTN_ERR_NO_COAST
Definition cme.h:615
int const LF_SEDIMENT_INPUT_CONSOLIDATED
Definition cme.h:444
int const RTN_ERR_TOO_LONG_TRACING_COAST
Definition cme.h:658
int const LOG_FILE_MIDDLE_DETAIL
Definition cme.h:391
bool bFPIsEqual(const T d1, const T d2, const T dEpsilon)
Definition cme.h:1207
int const LOG_FILE_HIGH_DETAIL
Definition cme.h:392
int const RTN_ERR_NO_START_FINISH_POINTS_TRACING_COAST
Definition cme.h:652
int const SMOOTH_SAVITZKY_GOLAY
Definition cme.h:674
int const LF_SEDIMENT_INPUT_UNCONSOLIDATED
Definition cme.h:443
int const SMOOTH_RUNNING_MEAN
Definition cme.h:673
int const SOUTH
Definition cme.h:401
int const LOG_FILE_ALL
Definition cme.h:393
int const EAST
Definition cme.h:399
int const RTN_OK
Definition cme.h:582
int const RTN_ERR_COAST_TOO_SMALL
Definition cme.h:656
int const RTN_ERR_NO_VALID_COAST
Definition cme.h:653
int const RTN_ERR_ZERO_LENGTH_COAST
Definition cme.h:655
int const RTN_ERR_REPEATING_WHEN_TRACING_COAST
Definition cme.h:654
int const RIGHT_HANDED
Definition cme.h:411
int const NORTH
Definition cme.h:397
int const LEFT_HANDED
Definition cme.h:412
int const WEST
Definition cme.h:403
Contains CRWCoast definitions.
Contains CGeomILine definitions.
Contains CGeomLine definitions.
Contains CGeomRasterGrid definitions.
Contains CSimulation definitions.