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 bEdgeFound = 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// bEdgeFound = true;
480// nValidCoast++;
481//
482// // Set this edge cell
483// m_pRasterGrid->m_Cell[nX][nY].SetAsCoastline(nValidCoast);
484//
485// // Create the coast vector
486// CGeomILine ILTempGridCRS;
487// CGeom2DIPoint const PtiStart(nX, nY);
488// ILTempGridCRS.Append(&PtiStart);
489//
490// bool bAdjFound = false;
491//
492// // Now look for other cells
493// do
494// {
495// for (int nSearchDirection = NORTH; nSearchDirection <= NORTH_WEST; nSearchDirection++)
496// {
497// int nXAdj;
498// int nYAdj;
499//
500// switch (nSearchDirection)
501// {
502// case NORTH:
503// nXAdj = nX - 1;
504// nYAdj = nY;
505//
506// if (bIsWithinValidGrid(nXAdj, nYAdj))
507// {
508// if (m_pRasterGrid->m_Cell[nXAdj][nYAdj].nGetCoastline() == DUMMY_COAST_NUMBER)
509// {
510// m_pRasterGrid->m_Cell[nXAdj][nYAdj].SetAsCoastline(nValidCoast);
511//
512// CGeom2DIPoint const PtiPoint(nX, nY);
513// ILTempGridCRS.Append(&PtiPoint);
514//
515// bAdjFound = true;
516//
517// break;
518// }
519// }
520//
521// break;
522//
523// case NORTH_EAST:
524// nXAdj = nX;
525// nYAdj = nY - 1;
526//
527// if (bIsWithinValidGrid(nXAdj, nYAdj))
528// {
529// if (m_pRasterGrid->m_Cell[nXAdj][nYAdj].nGetCoastline() == DUMMY_COAST_NUMBER)
530// {
531// m_pRasterGrid->m_Cell[nXAdj][nYAdj].SetAsCoastline(nValidCoast);
532//
533// CGeom2DIPoint const PtiPoint(nX, nY);
534// ILTempGridCRS.Append(&PtiPoint);
535//
536// bAdjFound = true;
537//
538// break;
539// }
540// }
541//
542// break;
543//
544// case EAST:
545// nXAdj = nX;
546// nYAdj = nY - 1;
547//
548// if (bIsWithinValidGrid(nXAdj, nYAdj))
549// {
550// if (m_pRasterGrid->m_Cell[nXAdj][nYAdj].nGetCoastline() == DUMMY_COAST_NUMBER)
551// {
552// m_pRasterGrid->m_Cell[nXAdj][nYAdj].SetAsCoastline(nValidCoast);
553//
554// CGeom2DIPoint const PtiPoint(nX, nY);
555// ILTempGridCRS.Append(&PtiPoint);
556//
557// bAdjFound = true;
558//
559// break;
560// }
561// }
562//
563// break;
564//
565// case SOUTH_EAST:
566// nXAdj = nX + 1;
567// nYAdj = nY;
568//
569// if (bIsWithinValidGrid(nXAdj, nYAdj))
570// {
571// if (m_pRasterGrid->m_Cell[nXAdj][nYAdj].nGetCoastline() == DUMMY_COAST_NUMBER)
572// {
573// m_pRasterGrid->m_Cell[nXAdj][nYAdj].SetAsCoastline(nValidCoast);
574//
575// CGeom2DIPoint const PtiPoint(nX, nY);
576// ILTempGridCRS.Append(&PtiPoint);
577//
578// bAdjFound = true;
579//
580// break;
581// }
582// }
583//
584// break;
585//
586// case SOUTH:
587// nXAdj = nX + 1;
588// nYAdj = nY;
589//
590// if (bIsWithinValidGrid(nXAdj, nYAdj))
591// {
592// if (m_pRasterGrid->m_Cell[nXAdj][nYAdj].nGetCoastline() == DUMMY_COAST_NUMBER)
593// {
594// m_pRasterGrid->m_Cell[nXAdj][nYAdj].SetAsCoastline(nValidCoast);
595//
596// CGeom2DIPoint const PtiPoint(nX, nY);
597// ILTempGridCRS.Append(&PtiPoint);
598//
599// bAdjFound = true;
600//
601// break;
602// }
603// }
604//
605// break;
606//
607// case SOUTH_WEST:
608// nXAdj = nX + 1;
609// nYAdj = nY;
610//
611// if (bIsWithinValidGrid(nXAdj, nYAdj))
612// {
613// if (m_pRasterGrid->m_Cell[nXAdj][nYAdj].nGetCoastline() == DUMMY_COAST_NUMBER)
614// {
615// m_pRasterGrid->m_Cell[nXAdj][nYAdj].SetAsCoastline(nValidCoast);
616//
617// CGeom2DIPoint const PtiPoint(nX, nY);
618// ILTempGridCRS.Append(&PtiPoint);
619//
620// bAdjFound = true;
621//
622// break;
623// }
624// }
625//
626// break;
627//
628// case WEST:
629// nXAdj = nX;
630// nYAdj = nY + 1;
631//
632// if (bIsWithinValidGrid(nXAdj, nYAdj))
633// {
634// if (m_pRasterGrid->m_Cell[nXAdj][nYAdj].nGetCoastline() == DUMMY_COAST_NUMBER)
635// {
636// m_pRasterGrid->m_Cell[nXAdj][nYAdj].SetAsCoastline(nValidCoast);
637//
638// CGeom2DIPoint const PtiPoint(nX, nY);
639// ILTempGridCRS.Append(&PtiPoint);
640//
641// bAdjFound = true;
642//
643// break;
644// }
645// }
646//
647// break;
648//
649// case NORTH_WEST:
650// nXAdj = nX;
651// nYAdj = nY + 1;
652//
653// if (bIsWithinValidGrid(nXAdj, nYAdj))
654// {
655// if (m_pRasterGrid->m_Cell[nXAdj][nYAdj].nGetCoastline() == DUMMY_COAST_NUMBER)
656// {
657// m_pRasterGrid->m_Cell[nXAdj][nYAdj].SetAsCoastline(nValidCoast);
658//
659// CGeom2DIPoint const PtiPoint(nX, nY);
660// ILTempGridCRS.Append(&PtiPoint);
661//
662// bAdjFound = true;
663//
664// break;
665// }
666// }
667//
668// break;
669// }
670// }
671//
672// } while (bAdjFound);
673//
674//
675//
676//
677//
678//
679// }
680//
681//
682// }
683// }
684// while (bEdgeFound);
685//
686//
687//
688//
689//
690//
691//
692//
693// // ============================================================*/
694
695
696 int const TOOCLOSE = 1;
697 int nValidCoast = 0;
698 vector<bool> VbPossibleStartCellLHEdge;
699 vector<bool> VbTraced;
700 vector<int> VnSearchDirection;
701 vector<CGeom2DIPoint> V2DIPossibleStartCell;
702
703 // Go along the list of edge cells and look for possible coastline start/finish cells
704 for (unsigned int n = 0; n < m_VEdgeCell.size() - 1; n++)
705 {
707 continue;
708
710 continue;
711
713 continue;
714
716 continue;
717
718 int const nXThis = m_VEdgeCell[n].nGetX();
719 int const nYThis = m_VEdgeCell[n].nGetY();
720 int const nXNext = m_VEdgeCell[n + 1].nGetX();
721 int const nYNext = m_VEdgeCell[n + 1].nGetY();
722
723 // Get "Is it sea?" information for 'this' and 'next' cells
724 bool const bThisCellIsSea = m_pRasterGrid->m_Cell[nXThis][nYThis].bIsInContiguousSea();
725 bool const bNextCellIsSea = m_pRasterGrid->m_Cell[nXNext][nYNext].bIsInContiguousSea();
726
727 // Is one cell land and the sea?
728 if ((! bThisCellIsSea) && bNextCellIsSea)
729 {
730 // 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)?
731 if (m_pRasterGrid->m_Cell[nXThis][nYThis].bIsPossibleCoastStartCell())
732 continue;
733
734 // Is 'this' cell too close to a cell that has previously been flagged as a possible coast start cell? Search first in one direction
735 bool bTooClose = false;
736 for (int nn = 1; nn <= TOOCLOSE; nn++)
737 {
738 int const nTmp = n + nn;
739 if (nTmp == static_cast<int>(m_VEdgeCell.size()))
740 break;
741
742 int const nXTmp = m_VEdgeCell[nTmp].nGetX();
743 int const nYTmp = m_VEdgeCell[nTmp].nGetY();
744
745 if (m_pRasterGrid->m_Cell[nXTmp][nYTmp].bIsPossibleCoastStartCell())
746 {
747 bTooClose = true;
748 break;
749 }
750 }
751 if (bTooClose)
752 continue;
753
754 // Now search in the other direction
755 for (int nn = 1; nn <= TOOCLOSE; nn++)
756 {
757 int const nTmp = n - nn;
758 if (nTmp < 0)
759 break;
760
761 int const nXTmp = m_VEdgeCell[nTmp].nGetX();
762 int const nYTmp = m_VEdgeCell[nTmp].nGetY();
763
764 if (m_pRasterGrid->m_Cell[nXTmp][nYTmp].bIsPossibleCoastStartCell())
765 {
766 bTooClose = true;
767 break;
768 }
769 }
770 if (bTooClose)
771 continue;
772
773 // All OK, so flag 'this' cell
774 m_pRasterGrid->m_Cell[nXThis][nYThis].SetPossibleCoastStartCell();
775
777 LogStream << m_ulIter << ": \tflagging [" << nXThis << "][" << nYThis << "] = {" << dGridCentroidXToExtCRSX(nXThis) << ", " << dGridCentroidYToExtCRSY(nYThis) << "} as possible coast start cell (left_handed edge)" << endl;
778
779 // And save it as a possible coastline start cell
780 V2DIPossibleStartCell.push_back(CGeom2DIPoint(nXThis, nYThis));
781 VbPossibleStartCellLHEdge.push_back(true);
782 VnSearchDirection.push_back(nGetOppositeDirection(m_VEdgeCellEdge[n]));
783 VbTraced.push_back(false);
784 }
785 else if (bThisCellIsSea && (! bNextCellIsSea))
786 {
787 // 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)?
788 if (m_pRasterGrid->m_Cell[nXNext][nYNext].bIsPossibleCoastStartCell())
789 continue;
790
791 // 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
792 bool bTooClose = false;
793 for (int nn = 1; nn <= TOOCLOSE; nn++)
794 {
795 int const nTmp = n + 1 + nn;
796 if (nTmp == static_cast<int>(m_VEdgeCell.size()))
797 break;
798
799 int const nXTmp = m_VEdgeCell[nTmp].nGetX();
800 int const nYTmp = m_VEdgeCell[nTmp].nGetY();
801
802 if (m_pRasterGrid->m_Cell[nXTmp][nYTmp].bIsPossibleCoastStartCell())
803 {
804 bTooClose = true;
805 break;
806 }
807 }
808 if (bTooClose)
809 continue;
810
811 // Now search in the other direction
812 for (int nn = 1; nn <= TOOCLOSE; nn++)
813 {
814 int const nTmp = n + 1 - nn;
815 if (nTmp < 0)
816 break;
817
818 int const nXTmp = m_VEdgeCell[nTmp].nGetX();
819 int const nYTmp = m_VEdgeCell[nTmp].nGetY();
820
821 if (m_pRasterGrid->m_Cell[nXTmp][nYTmp].bIsPossibleCoastStartCell())
822 {
823 bTooClose = true;
824 break;
825 }
826 }
827 if (bTooClose)
828 continue;
829
830 // All OK, so flag the 'next' cell
831 m_pRasterGrid->m_Cell[nXNext][nYNext].SetPossibleCoastStartCell();
832
834 LogStream << m_ulIter << ": \tflagging [" << nXNext << "][" << nYNext << "] = {" << dGridCentroidXToExtCRSX(nXNext) << ", " << dGridCentroidYToExtCRSY(nYNext) << "} as possible coast start cell (right_handed edge)" << endl;
835
836 // And save it as a possible coastline start cell
837 V2DIPossibleStartCell.push_back(CGeom2DIPoint(nXNext, nYNext));
838 VbPossibleStartCellLHEdge.push_back(false);
839 VnSearchDirection.push_back(nGetOppositeDirection(m_VEdgeCellEdge[n + 1]));
840 VbTraced.push_back(false);
841 }
842 }
843
844 // Any possible coastline start/finish cells found?
845 if (V2DIPossibleStartCell.size() == 0)
846 {
847 LogStream << m_ulIter << ": no coastline start/finish points found after grid edges searched.";
848
850 {
851 LogStream << " Note that the following grid edges were not searched: " << (m_bOmitSearchNorthEdge ? "N " : "") << (m_bOmitSearchSouthEdge ? "S " : "") << (m_bOmitSearchWestEdge ? "W " : "") << (m_bOmitSearchEastEdge ? "E " : "");
852 }
853
854 LogStream << endl;
855
857 }
858
859 // Some possible coastline start/finish points were found
860 // LogStream << m_ulIter << ": " << V2DIPossibleStartCell.size() << " possible coastline start/finish points found" << endl;
861
862 // // Are any of the possible start/finsh points adjacent?
863 // vector<bool> VbToRemove(V2DIPossibleStartCell.size(), false);
864 // for (int nThisPoint = 0; nThisPoint < static_cast<int>(V2DIPossibleStartCell.size()); nThisPoint++)
865 // {
866 // for (int nOtherPoint = 0; nOtherPoint < static_cast<int>(V2DIPossibleStartCell.size()); nOtherPoint++)
867 // {
868 // if ((nThisPoint == nOtherPoint) || VbToRemove[nThisPoint] || VbToRemove[nOtherPoint])
869 // continue;
870 //
871 // if (bIsAdjacentEdgeCell(&V2DIPossibleStartCell[nThisPoint], &V2DIPossibleStartCell[nOtherPoint]))
872 // VbToRemove[nOtherPoint] = true;
873 // }
874 // }
875
876 // // Remove each start/finish point which has been flagged as adjacent
877 // for (int nPoint = 0; nPoint < static_cast<int>(VbToRemove.size()); nPoint++)
878 // {
879 // if (VbToRemove[nPoint])
880 // {
881 // V2DIPossibleStartCell.erase(V2DIPossibleStartCell.begin() + nPoint);
882 // VbPossibleStartCellLHEdge.erase(VbPossibleStartCellLHEdge.begin() + nPoint);
883 // VnSearchDirection.erase(VnSearchDirection.begin() + nPoint);
884 // VbTraced.erase(VbTraced.begin() + nPoint);
885 // }
886 // }
887
888 // All OK, now trace from each of these possible start/finish points
889 for (int n = static_cast<int>(V2DIPossibleStartCell.size())-1; n >= 0; n--)
890 {
891 if (! VbTraced[n])
892 {
893 int nRet = 0;
894
895 if (VbPossibleStartCellLHEdge[n])
896 nRet = nTraceCoastLine(n, VnSearchDirection[n], LEFT_HANDED, &VbTraced, &V2DIPossibleStartCell);
897 else
898 nRet = nTraceCoastLine(n, VnSearchDirection[n], RIGHT_HANDED, &VbTraced, &V2DIPossibleStartCell);
899
900 if (nRet == RTN_OK)
901 {
902 // We have a valid coastline starting from this possible start cell
903 VbTraced[n] = true;
904 nValidCoast++;
905 }
906 }
907 }
908
909 if (nValidCoast == 0)
910 {
911 // No valid coasts found so try again, this time working through the possible start/finish points in reverse order
912 for (int n = 0; n < static_cast<int>(VbTraced.size()); n++)
913 VbTraced[n] = false;
914
915 for (int n = 0; n < static_cast<int>(V2DIPossibleStartCell.size()); n++)
916 {
917 if (! VbTraced[n])
918 {
919 int nRet = 0;
920
921 if (VbPossibleStartCellLHEdge[n])
922 nRet = nTraceCoastLine(n, VnSearchDirection[n], LEFT_HANDED, &VbTraced, &V2DIPossibleStartCell);
923 else
924 nRet = nTraceCoastLine(n, VnSearchDirection[n], RIGHT_HANDED, &VbTraced, &V2DIPossibleStartCell);
925
926 if (nRet == RTN_OK)
927 {
928 // We have a valid coastline starting from this possible start cell
929 VbTraced[n] = true;
930 nValidCoast++;
931 }
932 }
933 }
934 }
935
936 if (nValidCoast == 0)
937 {
938 // Still no valid coasts found, so we have to give up
939 cerr << m_ulIter << ": no valid coasts found, see " << m_strLogFile << " for more information" << endl;
941 }
942
943 return RTN_OK;
944}
945
946//===============================================================================================================================
948//===============================================================================================================================
949int CSimulation::nTraceCoastLine(unsigned int const nTraceFromStartCellIndex, int const nStartSearchDirection, int const nHandedness, vector<bool>* pVbTraced, vector<CGeom2DIPoint> const* pV2DIPossibleStartCell)
950{
951 bool bHitStartCell = false;
952 bool bAtCoast = false;
953 bool bHasLeftStartEdge = false;
954 bool bTooLong = false;
955 bool bOffEdge = false;
956 bool bRepeating = false;
957
958 int const nStartX = pV2DIPossibleStartCell->at(nTraceFromStartCellIndex).nGetX();
959 int const nStartY = pV2DIPossibleStartCell->at(nTraceFromStartCellIndex).nGetY();
960 int nX = nStartX;
961 int nY = nStartY;
962 int nSearchDirection = nStartSearchDirection;
963 int nRoundLoop = -1;
964 // nThisLen = 0;
965 // nLastLen = 0,
966 // nPreLastLen = 0;
967
968 // Temporary coastline as integer points (grid CRS)
969 CGeomILine ILTempGridCRS;
970
971 // Add the start cell to the vector
972 CGeom2DIPoint const PtiStart(nStartX, nStartY);
973 ILTempGridCRS.Append(&PtiStart);
974
975 // 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
976 do
977 {
978 // // DEBUG CODE ==============================================================================================================
979 // LogStream << "Now at [" << nX << "][" << nY << "] = {" << dGridCentroidXToExtCRSX(nX) << ", " << dGridCentroidYToExtCRSY(nY) << "}" << endl;
980 // LogStream << "ILTempGridCRS is now:" << endl;
981 // for (int n = 0; n < ILTempGridCRS.nGetSize(); n++)
982 // LogStream << "[" << ILTempGridCRS[n].nGetX() << "][" << ILTempGridCRS[n].nGetY() << "] = {" << dGridCentroidXToExtCRSX(ILTempGridCRS[n].nGetX()) << ", " << dGridCentroidYToExtCRSY(ILTempGridCRS[n].nGetY()) << "}" << endl;
983 // LogStream << "=================" << endl;
984 // // DEBUG CODE ==============================================================================================================
985
986 // Safety check
987 if (++nRoundLoop > m_nCoastMax)
988 {
989 bTooLong = true;
990
991 LogStream << m_ulIter << ": \tabandoning possible coastline, traced from [" << nStartX << "][" << nStartY << "] = {" << dGridCentroidXToExtCRSX(nStartX) << ", " << dGridCentroidYToExtCRSY(nStartY) << "}, exceeded maximum search length (" << m_nCoastMax << ")" << endl;
992
993 // for (int n = 0; n < ILTempGridCRS.nGetSize(); n++)
994 // LogStream << "[" << ILTempGridCRS[n].nGetX() << "][" << ILTempGridCRS[n].nGetY() << "] = {" << dGridCentroidXToExtCRSX(ILTempGridCRS[n].nGetX()) << ", " << dGridCentroidYToExtCRSY(ILTempGridCRS[n].nGetY()) << "}" << endl;
995 // LogStream << endl;
996
997 break;
998 }
999
1000 // Another safety check
1001 if ((nRoundLoop > 10) && (ILTempGridCRS.nGetSize() < 2))
1002 {
1003 // 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
1004 bRepeating = true;
1005
1006 LogStream << m_ulIter << ": \tabandoning possible coastline, traced from [" << nStartX << "][" << nStartY << "] = {" << dGridCentroidXToExtCRSX(nStartX) << ", " << dGridCentroidYToExtCRSY(nStartY) << "}, is looping" << endl;
1007
1008 break;
1009 }
1010
1011 // OK so far: so have we left the start edge?
1012 if (! bHasLeftStartEdge)
1013 {
1014 // We have not yet left the start edge
1015 if (((nStartSearchDirection == SOUTH) && (nY > nStartY)) || ((nStartSearchDirection == NORTH) && (nY < nStartY)) || ((nStartSearchDirection == EAST) && (nX > nStartX)) || ((nStartSearchDirection == WEST) && (nX < nStartX)))
1016 bHasLeftStartEdge = true;
1017
1018 // Flag this cell to ensure that it is not chosen as a coastline start cell later
1019 m_pRasterGrid->m_Cell[nX][nY].SetPossibleCoastStartCell();
1020 // LogStream << "Flagging [" << nX << "][" << nY << "] as possible coast start cell NOT YET LEFT EDGE" << endl;
1021 }
1022
1023 // 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
1024 // LogStream << "bHasLeftStartEdge = " << bHasLeftStartEdge << " bAtCoast = " << bAtCoast << endl;
1025 if (bHasLeftStartEdge && bAtCoast)
1026 {
1027 for (unsigned int nn = 0; nn < pVbTraced->size(); nn++)
1028 {
1029 bool const bTraced = pVbTraced->at(nn);
1030 if ((nn != nTraceFromStartCellIndex) && (! bTraced))
1031 {
1032 int const nXPoss = pV2DIPossibleStartCell->at(nn).nGetX();
1033 int const nYPoss = pV2DIPossibleStartCell->at(nn).nGetY();
1034
1035 // LogStream << "In 'Leave the edge' loop for [" << nX << "][" << nY << "] bTraced = " << bTraced << " nn = " << nn << " nTraceFromStartCellIndex = " << nTraceFromStartCellIndex << " possible start cell = [" << nXPoss << "][" << nYPoss << "]" << endl;
1036
1037 if ((nX == nXPoss) && (nY == nYPoss))
1038 {
1040 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;
1041
1042 pVbTraced->at(nn) = true;
1043 bHitStartCell = true;
1044 break;
1045 }
1046 }
1047 }
1048 }
1049
1050 if (bHitStartCell)
1051 break;
1052
1053 // OK now sort out the next iteration of the search
1054 int nXSeaward = 0;
1055 int nYSeaward = 0;
1056 int nSeawardNewDirection = 0;
1057 int nXStraightOn = 0;
1058 int nYStraightOn = 0;
1059 int nXAntiSeaward = 0;
1060 int nYAntiSeaward = 0;
1061 int nAntiSeawardNewDirection = 0;
1062 int nXGoBack = 0;
1063 int nYGoBack = 0;
1064 int nGoBackNewDirection = 0;
1065
1066 CGeom2DIPoint const Pti(nX, nY);
1067
1068 // Set up the variables
1069 switch (nHandedness)
1070 {
1071 case RIGHT_HANDED:
1072 // 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
1073 switch (nSearchDirection)
1074 {
1075 case NORTH:
1076 // The sea is towards the RHS (E) of the coast, so first try to go right (to the E)
1077 nXSeaward = nX + 1;
1078 nYSeaward = nY;
1079 nSeawardNewDirection = EAST;
1080
1081 // If can't do this, try to go straight on (to the N)
1082 nXStraightOn = nX;
1083 nYStraightOn = nY - 1;
1084
1085 // If can't do either of these, try to go anti-seaward i.e. towards the LHS (W)
1086 nXAntiSeaward = nX - 1;
1087 nYAntiSeaward = nY;
1088 nAntiSeawardNewDirection = WEST;
1089
1090 // As a last resort, go back (to the S)
1091 nXGoBack = nX;
1092 nYGoBack = nY + 1;
1093 nGoBackNewDirection = SOUTH;
1094
1095 break;
1096
1097 case EAST:
1098 // The sea is towards the RHS (S) of the coast, so first try to go right (to the S)
1099 nXSeaward = nX;
1100 nYSeaward = nY + 1;
1101 nSeawardNewDirection = SOUTH;
1102
1103 // If can't do this, try to go straight on (to the E)
1104 nXStraightOn = nX + 1;
1105 nYStraightOn = nY;
1106
1107 // If can't do either of these, try to go anti-seaward i.e. towards the LHS (N)
1108 nXAntiSeaward = nX;
1109 nYAntiSeaward = nY - 1;
1110 nAntiSeawardNewDirection = NORTH;
1111
1112 // As a last resort, go back (to the W)
1113 nXGoBack = nX - 1;
1114 nYGoBack = nY;
1115 nGoBackNewDirection = WEST;
1116
1117 break;
1118
1119 case SOUTH:
1120 // The sea is towards the RHS (W) of the coast, so first try to go right (to the W)
1121 nXSeaward = nX - 1;
1122 nYSeaward = nY;
1123 nSeawardNewDirection = WEST;
1124
1125 // If can't do this, try to go straight on (to the S)
1126 nXStraightOn = nX;
1127 nYStraightOn = nY + 1;
1128
1129 // If can't do either of these, try to go anti-seaward i.e. towards the LHS (E)
1130 nXAntiSeaward = nX + 1;
1131 nYAntiSeaward = nY;
1132 nAntiSeawardNewDirection = EAST;
1133
1134 // As a last resort, go back (to the N)
1135 nXGoBack = nX;
1136 nYGoBack = nY - 1;
1137 nGoBackNewDirection = NORTH;
1138
1139 break;
1140
1141 case WEST:
1142 // The sea is towards the RHS (N) of the coast, so first try to go right (to the N)
1143 nXSeaward = nX;
1144 nYSeaward = nY - 1;
1145 nSeawardNewDirection = NORTH;
1146
1147 // If can't do this, try to go straight on (to the W)
1148 nXStraightOn = nX - 1;
1149 nYStraightOn = nY;
1150
1151 // If can't do either of these, try to go anti-seaward i.e. towards the LHS (S)
1152 nXAntiSeaward = nX;
1153 nYAntiSeaward = nY + 1;
1154 nAntiSeawardNewDirection = SOUTH;
1155
1156 // As a last resort, go back (to the E)
1157 nXGoBack = nX + 1;
1158 nYGoBack = nY;
1159 nGoBackNewDirection = EAST;
1160
1161 break;
1162 }
1163
1164 break;
1165
1166 case LEFT_HANDED:
1167
1168 // 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
1169 switch (nSearchDirection)
1170 {
1171 case NORTH:
1172 // The sea is towards the LHS (W) of the coast, so first try to go left (to the W)
1173 nXSeaward = nX - 1;
1174 nYSeaward = nY;
1175 nSeawardNewDirection = WEST;
1176
1177 // If can't do this, try to go straight on (to the N)
1178 nXStraightOn = nX;
1179 nYStraightOn = nY - 1;
1180
1181 // If can't do either of these, try to go anti-seaward i.e. towards the RHS (E)
1182 nXAntiSeaward = nX + 1;
1183 nYAntiSeaward = nY;
1184 nAntiSeawardNewDirection = EAST;
1185
1186 // As a last resort, go back (to the S)
1187 nXGoBack = nX;
1188 nYGoBack = nY + 1;
1189 nGoBackNewDirection = SOUTH;
1190
1191 break;
1192
1193 case EAST:
1194 // The sea is towards the LHS (N) of the coast, so first try to go left (to the N)
1195 nXSeaward = nX;
1196 nYSeaward = nY - 1;
1197 nSeawardNewDirection = NORTH;
1198
1199 // If can't do this, try to go straight on (to the E)
1200 nXStraightOn = nX + 1;
1201 nYStraightOn = nY;
1202
1203 // If can't do either of these, try to go anti-seaward i.e. towards the RHS (S)
1204 nXAntiSeaward = nX;
1205 nYAntiSeaward = nY + 1;
1206 nAntiSeawardNewDirection = SOUTH;
1207
1208 // As a last resort, go back (to the W)
1209 nXGoBack = nX - 1;
1210 nYGoBack = nY;
1211 nGoBackNewDirection = WEST;
1212
1213 break;
1214
1215 case SOUTH:
1216 // The sea is towards the LHS (E) of the coast, so first try to go left (to the E)
1217 nXSeaward = nX + 1;
1218 nYSeaward = nY;
1219 nSeawardNewDirection = EAST;
1220
1221 // If can't do this, try to go straight on (to the S)
1222 nXStraightOn = nX;
1223 nYStraightOn = nY + 1;
1224
1225 // If can't do either of these, try to go anti-seaward i.e. towards the RHS (W)
1226 nXAntiSeaward = nX - 1;
1227 nYAntiSeaward = nY;
1228 nAntiSeawardNewDirection = WEST;
1229
1230 // As a last resort, go back (to the N)
1231 nXGoBack = nX;
1232 nYGoBack = nY - 1;
1233 nGoBackNewDirection = NORTH;
1234
1235 break;
1236
1237 case WEST:
1238 // The sea is towards the LHS (S) of the coast, so first try to go left (to the S)
1239 nXSeaward = nX;
1240 nYSeaward = nY + 1;
1241 nSeawardNewDirection = SOUTH;
1242
1243 // If can't do this, try to go straight on (to the W)
1244 nXStraightOn = nX - 1;
1245 nYStraightOn = nY;
1246
1247 // If can't do either of these, try to go anti-seaward i.e. towards the RHS (N)
1248 nXAntiSeaward = nX;
1249 nYAntiSeaward = nY - 1;
1250 nAntiSeawardNewDirection = NORTH;
1251
1252 // As a last resort, go back (to the E)
1253 nXGoBack = nX + 1;
1254 nYGoBack = nY;
1255 nGoBackNewDirection = EAST;
1256
1257 break;
1258 }
1259
1260 break;
1261 }
1262
1263 // 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?
1264 if (bIsWithinValidGrid(nXSeaward, nYSeaward))
1265 {
1266 // It is, so check if the cell in the seaward direction is a sea cell
1267 if (m_pRasterGrid->m_Cell[nXSeaward][nYSeaward].bIsInContiguousSea())
1268 {
1269 // There is sea in this seaward direction, so we are on the coast
1270 bAtCoast = true;
1271
1272 // Has the current cell already marked been marked as a coast cell?
1273 if (! m_pRasterGrid->m_Cell[nX][nY].bIsCoastline())
1274 {
1275 // Not already marked, is this an intervention cell with the top above SWL?
1276 if ((bIsInterventionCell(nX, nY)) && (m_pRasterGrid->m_Cell[nX][nY].dGetInterventionTopElev() >= m_dThisIterSWL))
1277 {
1278 // It is, so add it to the vector
1279 ILTempGridCRS.AppendIfNotPrevious(&Pti);
1280 }
1281 else if (m_pRasterGrid->m_Cell[nX][nY].dGetAllSedTopElevIncTalus() >= m_dThisIterSWL)
1282 {
1283 // The sediment top (inc any talus) is above SWL so add it to the vector object
1284 ILTempGridCRS.AppendIfNotPrevious(&Pti);
1285 }
1286 }
1287 }
1288 else
1289 {
1290 // The seaward cell is not a sea cell, so we will move to it next time
1291 nX = nXSeaward;
1292 nY = nYSeaward;
1293
1294 // And set a new search direction, to keep turning seaward
1295 nSearchDirection = nSeawardNewDirection;
1296 continue;
1297 }
1298 }
1299
1300 // 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?
1301 if (bIsWithinValidGrid(nXStraightOn, nYStraightOn))
1302 {
1303 // It is, so check if there is sea immediately in front
1304 if (m_pRasterGrid->m_Cell[nXStraightOn][nYStraightOn].bIsInContiguousSea())
1305 {
1306 // Sea is in front, so we are on the coast
1307 bAtCoast = true;
1308
1309 // Has the current cell already marked been marked as a coast cell?
1310 if (! m_pRasterGrid->m_Cell[nX][nY].bIsCoastline())
1311 {
1312 // Not already marked, is this an intervention cell with the top above SWL?
1313 if ((bIsInterventionCell(nX, nY)) && (m_pRasterGrid->m_Cell[nX][nY].dGetInterventionTopElev() >= m_dThisIterSWL))
1314 {
1315 // It is, so add it to the vector object
1316 ILTempGridCRS.AppendIfNotPrevious(&Pti);
1317 }
1318 else if (m_pRasterGrid->m_Cell[nX][nY].dGetAllSedTopElevIncTalus() >= m_dThisIterSWL)
1319 {
1320 // The sediment top (inc any talus) is above SWL so add it to the vector object
1321 ILTempGridCRS.AppendIfNotPrevious(&Pti);
1322 }
1323 }
1324 }
1325 else
1326 {
1327 // The straight-ahead cell is not a sea cell, so we will move to it next time
1328 nX = nXStraightOn;
1329 nY = nYStraightOn;
1330
1331 // The search direction remains unchanged
1332 continue;
1333 }
1334 }
1335
1336 // 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?
1337 if (bIsWithinValidGrid(nXAntiSeaward, nYAntiSeaward))
1338 {
1339 // It is, so check if there is sea in this anti-seaward cell
1340 if (m_pRasterGrid->m_Cell[nXAntiSeaward][nYAntiSeaward].bIsInContiguousSea())
1341 {
1342 // There is sea on the anti-seaward side, so we are on the coast
1343 bAtCoast = true;
1344
1345 // Has the current cell already marked been marked as a coast cell?
1346 if (! m_pRasterGrid->m_Cell[nX][nY].bIsCoastline())
1347 {
1348 // Not already marked, is this an intervention cell with the top above SWL?
1349 if ((bIsInterventionCell(nX, nY)) && (m_pRasterGrid->m_Cell[nX][nY].dGetInterventionTopElev() >= m_dThisIterSWL))
1350 {
1351 // It is, so add it to the vector object
1352 ILTempGridCRS.AppendIfNotPrevious(&Pti);
1353 }
1354 else if (m_pRasterGrid->m_Cell[nX][nY].dGetAllSedTopElevIncTalus() >= m_dThisIterSWL)
1355 {
1356 // The sediment top (inc any talus) is above SWL so add it to the vector object
1357 ILTempGridCRS.AppendIfNotPrevious(&Pti);
1358 }
1359 }
1360 }
1361 else
1362 {
1363 // The anti-seaward cell is not a sea cell, so we will move to it next time
1364 nX = nXAntiSeaward;
1365 nY = nYAntiSeaward;
1366
1367 // And set a new search direction, to keep turning seaward
1368 nSearchDirection = nAntiSeawardNewDirection;
1369 continue;
1370 }
1371 }
1372
1373 // 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
1374 if (bIsWithinValidGrid(nXGoBack, nYGoBack))
1375 {
1376 nX = nXGoBack;
1377 nY = nYGoBack;
1378
1379 // And change the search direction
1380 nSearchDirection = nGoBackNewDirection;
1381 }
1382 else
1383 {
1384 // Our final choice is not a valid cell, so give up
1385 bOffEdge = true;
1386 break;
1387 }
1388 } while (true);
1389
1390 // OK, we have a coastline. So is the coastline too long or too short?
1391 int nCoastSize = ILTempGridCRS.nGetSize();
1392
1393 if (bOffEdge)
1394 {
1396 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;
1397
1398 // return RTN_ERR_IGNORING_COAST;
1399 }
1400
1401 if (bTooLong)
1402 {
1403 // Around loop too many times, so abandon this coastline
1405 {
1406 LogStream << m_ulIter << ": \tabandoning possible coastline from [" << nStartX << "][" << nStartY << "] = {" << dGridCentroidXToExtCRSX(nStartX) << ", " << dGridCentroidYToExtCRSY(nStartY) << "} since round loop " << nRoundLoop << " times, coastline size is " << nCoastSize;
1407
1408 if (nCoastSize > 0)
1409 LogStream << ", ended at [" << ILTempGridCRS[nCoastSize - 1].nGetX() << "][" << ILTempGridCRS[nCoastSize - 1].nGetY() << "] = {" << dGridCentroidXToExtCRSX(ILTempGridCRS[nCoastSize - 1].nGetX()) << ", " << dGridCentroidYToExtCRSY(ILTempGridCRS[nCoastSize - 1].nGetY()) << "}";
1410
1411 LogStream << endl;
1412 }
1413
1415 }
1416
1417 if (bRepeating)
1418 {
1420 {
1421 LogStream << m_ulIter << ": abandon possible coastline from [" << nStartX << "][" << nStartY << "] = {" << dGridCentroidXToExtCRSX(nStartX) << ", " << dGridCentroidYToExtCRSY(nStartY) << "} since repeating, coastline size is " << nCoastSize;
1422
1423 if (nCoastSize > 0)
1424 LogStream << ", it ended at [" << ILTempGridCRS[nCoastSize - 1].nGetX() << "][" << ILTempGridCRS[nCoastSize - 1].nGetY() << "] = {" << dGridCentroidXToExtCRSX(ILTempGridCRS[nCoastSize - 1].nGetX()) << ", " << dGridCentroidYToExtCRSY(ILTempGridCRS[nCoastSize - 1].nGetY()) << "}";
1425
1426 LogStream << endl;
1427 }
1428
1430 }
1431
1432 if (nCoastSize == 0)
1433 {
1434 // Zero-length coastline, so abandon it
1436 LogStream << m_ulIter << ": abandoning zero-length coastline from [" << nStartX << "][" << nStartY << "] = {" << dGridCentroidXToExtCRSX(nStartX) << ", " << dGridCentroidYToExtCRSY(nStartY) << "}" << endl;
1437
1439 }
1440
1441 if (nCoastSize < m_nCoastMin)
1442 {
1443 // The vector coastline is too small, so abandon it
1445 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;
1446
1448 }
1449
1450 // OK this new coastline is fine
1451 int const nEndX = nX;
1452 int const nEndY = nY;
1453 int const nCoastEndX = ILTempGridCRS[nCoastSize - 1].nGetX();
1454 int const nCoastEndY = ILTempGridCRS[nCoastSize - 1].nGetY();
1455
1456 if ((nCoastEndX != nEndX) || (nCoastEndY != nEndY))
1457 {
1458 // 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?
1459 if (! m_pRasterGrid->m_Cell[nCoastEndX][nCoastEndY].bIsBoundingBoxEdge())
1460 {
1461 // The final cell in ILTempGridCRS is not a grid-edge cell, so add the grid-edge cell and mark the cell as coastline
1462 ILTempGridCRS.AppendIfNotPrevious(nEndX, nEndY);
1463 nCoastSize++;
1464 }
1465 }
1466
1467 // Need to specify start edge and end edge for smoothing routines
1468 int const nStartEdge = m_pRasterGrid->m_Cell[nStartX][nStartY].nGetBoundingBoxEdge();
1469 int const nEndEdge = m_pRasterGrid->m_Cell[nEndX][nEndY].nGetBoundingBoxEdge();
1470
1471 // 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
1472 CGeomLine LTempExtCRS;
1473
1474 for (int j = 0; j < nCoastSize; j++)
1475 LTempExtCRS.Append(dGridCentroidXToExtCRSX(ILTempGridCRS[j].nGetX()), dGridCentroidYToExtCRSY(ILTempGridCRS[j].nGetY()));
1476
1477 // Now do some smoothing of the vector output, if desired
1479 LTempExtCRS = LSmoothCoastRunningMean(&LTempExtCRS);
1481 LTempExtCRS = LSmoothCoastSavitzkyGolay(&LTempExtCRS, nStartEdge, nEndEdge);
1482
1483 // // DEBUG CODE ==================================================================================================
1484 // LogStream << "==================================" << endl;
1485 // for (int j = 0; j < nCoastSize; j++)
1486 // {
1487 // LogStream << "{" << dGridCentroidXToExtCRSX(ILTempGridCRS[j].nGetX()) << ", " << dGridCentroidYToExtCRSY(ILTempGridCRS[j].nGetY()) << "}" << "\t{" << LTempExtCRS.dGetXAt(j) << ", " << LTempExtCRS.dGetYAt(j) << "}" << endl;
1488 // }
1489 // LogStream << "==================================" << endl;
1490 // // DEBUG CODE ==================================================================================================
1491
1492 // Create a new coastline object and append to it the vector of coastline objects
1493 CRWCoast const CoastTmp(this);
1494 m_VCoast.push_back(CoastTmp);
1495 int const nCoast = static_cast<int>(m_VCoast.size()) - 1;
1496
1497 // Now mark the coastline on the grid
1498 for (int n = 0; n < nCoastSize; n++)
1499 m_pRasterGrid->m_Cell[ILTempGridCRS[n].nGetX()][ILTempGridCRS[n].nGetY()].SetAsCoastline(nCoast);
1500
1501 // Set the coastline (Ext CRS)
1502 m_VCoast[nCoast].SetCoastlineExtCRS(&LTempExtCRS);
1503
1504 // Set the coastline (Grid CRS)
1505 m_VCoast[nCoast].SetCoastlineGridCRS(&ILTempGridCRS);
1506
1507 // CGeom2DPoint PtLast(DBL_MIN, DBL_MIN);
1508 // for (int j = 0; j < nCoastSize; j++)
1509 // {
1510 // // Store the smoothed points (in external CRS) in the coast's m_LCoastlineExtCRS object, also append dummy values to the other attribute vectors
1511 // if (PtLast != &LTempExtCRS[j]) // Avoid duplicate points
1512 // {
1513 // m_VCoast[nCoast].AppendPointToCoastlineExtCRS(LTempExtCRS[j].dGetX(), LTempExtCRS[j].dGetY());
1514 //
1515 // // Also store the locations of the corresponding unsmoothed points (in raster grid CRS) in the coast's m_ILCellsMarkedAsCoastline vector
1516 // m_VCoast[nCoast].AppendCellMarkedAsCoastline(&ILTempGridCRS[j]);
1517 // }
1518 //
1519 // PtLast = LTempExtCRS[j];
1520 // }
1521
1522 // Set values for the coast's other attributes: set the coast's handedness, and start and end edges
1523 m_VCoast[nCoast].SetSeaHandedness(nHandedness);
1524 m_VCoast[nCoast].SetStartEdge(nStartEdge);
1525 m_VCoast[nCoast].SetEndEdge(nEndEdge);
1526
1528 {
1529 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;
1530
1531 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 ";
1532
1533 if (nStartEdge == NORTH)
1534 LogStream << "north";
1535 else if (nStartEdge == SOUTH)
1536 LogStream << "south";
1537 else if (nStartEdge == WEST)
1538 LogStream << "west";
1539 else if (nStartEdge == EAST)
1540 LogStream << "east";
1541
1542 LogStream << " edge to the ";
1543 if (nEndEdge == NORTH)
1544 LogStream << "north";
1545 else if (nEndEdge == SOUTH)
1546 LogStream << "south";
1547 else if (nEndEdge == WEST)
1548 LogStream << "west";
1549 else if (nEndEdge == EAST)
1550 LogStream << "east";
1551 LogStream << " edge" << endl;
1552 }
1553
1554 // LogStream << "-----------------" << endl;
1555 // for (int kk = 0; kk < m_VCoast.back().nGetCoastlineSize(); kk++)
1556 // 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;
1557 // LogStream << "-----------------" << endl;
1558
1559 // Next calculate the curvature of the vector coastline
1560 DoCoastCurvature(nCoast, nHandedness);
1561
1562 // Calculate values for the coast's flux orientation vector
1563 CalcCoastTangents(nCoast);
1564
1565 // And create the vector of pointers to coastline-normal objects
1566 m_VCoast[nCoast].CreateProfilesAtCoastPoints();
1567
1568 return RTN_OK;
1569}
1570
1571//===============================================================================================================================
1573//===============================================================================================================================
1575{
1576 // Find all connected sea cells
1578
1579 // Find every coastline on the raster grid, mark raster cells, then create the vector coastline
1580 int const nRet = nTraceAllFloodCoasts();
1581
1582 if (nRet != RTN_OK)
1583 return nRet;
1584
1585 // Have we created any coasts?
1586 switch (m_nLevel)
1587 {
1588 case 0: // WAVESETUP + SURGE:
1589 {
1590 if (m_VFloodWaveSetupSurge.empty())
1591 {
1592 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;
1593 return RTN_ERR_NO_COAST;
1594 }
1595
1596 break;
1597 }
1598
1599 case 1: // WAVESETUP + SURGE + RUNUP:
1600 {
1601 if (m_VFloodWaveSetupSurgeRunup.empty())
1602 {
1603 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;
1604 return RTN_ERR_NO_COAST;
1605 }
1606
1607 break;
1608 }
1609 }
1610
1611 return RTN_OK;
1612}
1613
1614//===============================================================================================================================
1616//===============================================================================================================================
1618{
1619 for (int nX = 0; nX < m_nXGridSize; nX++)
1620 {
1621 for (int nY = 0; nY < m_nYGridSize; nY++)
1622 {
1623 m_pRasterGrid->m_Cell[nX][nY].UnSetCheckFloodCell();
1624 m_pRasterGrid->m_Cell[nX][nY].UnSetInContiguousFlood();
1625 m_pRasterGrid->m_Cell[nX][nY].SetAsFloodline(false);
1626 }
1627 }
1628
1629 // Go along the list of edge cells
1630 for (unsigned int n = 0; n < m_VEdgeCell.size(); n++)
1631 {
1633 continue;
1634
1636 continue;
1637
1639 continue;
1640
1642 continue;
1643
1644 int const nX = m_VEdgeCell[n].nGetX();
1645 int const nY = m_VEdgeCell[n].nGetY();
1646
1647 if ((! m_pRasterGrid->m_Cell[nX][nY].bIsCellFloodCheck()) && (m_pRasterGrid->m_Cell[nX][nY].bIsInundated()))
1648 {
1649 // This edge cell is below SWL and sea depth remains set to zero
1650 FloodFillLand(nX, nY);
1651 }
1652 }
1653
1654 return RTN_OK;
1655}
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:588
int m_nYMinBoundingBox
The minimum y value of the bounding box.
Definition simulation.h:558
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:726
CGeomRasterGrid * m_pRasterGrid
Pointer to the raster grid object.
int m_nXGridSize
The size of the grid in the x direction.
Definition simulation.h:477
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:480
double m_dThisIterTopElevMin
This-iteration lowest elevation of DEM.
Definition simulation.h:990
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:528
int m_nXMaxBoundingBox
The maximum x value of the bounding box.
Definition simulation.h:555
bool m_bLowestSWLSoFar
Do we have the lowest SWL so far?
Definition simulation.h:468
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:357
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:531
bool m_bOmitSearchNorthEdge
Omit the north edge of the grid from coast-end searches?
Definition simulation.h:351
vector< CGeom2DIPoint > m_VEdgeCell
Edge cells.
bool m_bHighestSWLSoFar
Do we have the highest SWL so far?
Definition simulation.h:465
int m_nYMaxBoundingBox
The maximum y value of the bounding box.
Definition simulation.h:561
unsigned long m_ulThisIterNumSeaCells
The number of grid cells which are marked as sea, for this iteration.
Definition simulation.h:621
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:552
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:486
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:354
unsigned long m_ulIter
The number of the current iteration (time step)
Definition simulation.h:609
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:3066
double m_dThisIterTopElevMax
This-iteration highest elevation of DEM.
Definition simulation.h:987
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:594
bool m_bOmitSearchEastEdge
Omit the east edge of the grid from coast-end searches?
Definition simulation.h:360
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:725
int const LF_SEA
Definition cme.h:436
string const ERR
Definition cme.h:805
int const RTN_ERR_NO_COAST
Definition cme.h:618
int const LF_SEDIMENT_INPUT_CONSOLIDATED
Definition cme.h:446
int const RTN_ERR_TOO_LONG_TRACING_COAST
Definition cme.h:661
int const LOG_FILE_MIDDLE_DETAIL
Definition cme.h:393
bool bFPIsEqual(const T d1, const T d2, const T dEpsilon)
Definition cme.h:1213
int const LOG_FILE_HIGH_DETAIL
Definition cme.h:394
int const RTN_ERR_NO_START_FINISH_POINTS_TRACING_COAST
Definition cme.h:655
int const SMOOTH_SAVITZKY_GOLAY
Definition cme.h:677
int const LF_SEDIMENT_INPUT_UNCONSOLIDATED
Definition cme.h:445
int const SMOOTH_RUNNING_MEAN
Definition cme.h:676
int const SOUTH
Definition cme.h:403
int const LOG_FILE_ALL
Definition cme.h:395
int const EAST
Definition cme.h:401
int const RTN_OK
Definition cme.h:585
int const RTN_ERR_COAST_TOO_SMALL
Definition cme.h:659
int const RTN_ERR_NO_VALID_COAST
Definition cme.h:656
int const RTN_ERR_ZERO_LENGTH_COAST
Definition cme.h:658
int const RTN_ERR_REPEATING_WHEN_TRACING_COAST
Definition cme.h:657
int const RIGHT_HANDED
Definition cme.h:413
int const NORTH
Definition cme.h:399
int const LEFT_HANDED
Definition cme.h:414
int const WEST
Definition cme.h:405
Contains CRWCoast definitions.
Contains CGeomILine definitions.
Contains CGeomLine definitions.
Contains CGeomRasterGrid definitions.
Contains CSimulation definitions.