CoastalME (Coastal Modelling Environment)
Simulates the long-term behaviour of complex coastlines
Loading...
Searching...
No Matches
do_surge_flood.cpp
Go to the documentation of this file.
1
13
14/* ==============================================================================================================================
15
16 This file is part of CoastalME, the Coastal Modelling Environment.
17
18 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.
19
20 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.
21
22 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.
23
24==============================================================================================================================*/
25#include <assert.h>
26#include <cfloat>
27
28#include <iostream>
29using std::cerr;
30using std::cout;
31using std::endl;
32using std::ios;
33
34#include <iomanip>
35using std::resetiosflags;
36using std::setiosflags;
37using std::setprecision;
38using std::setw;
39
40#include <string>
41using std::to_string;
42
43#include <stack>
44using std::stack;
45
46#include "cme.h"
47#include "i_line.h"
48#include "line.h"
49#include "simulation.h"
50#include "raster_grid.h"
51#include "coast.h"
52
53//===============================================================================================================================
55//===============================================================================================================================
56void CSimulation::FloodFillLand(int const nXStart, int const nYStart)
57{
58 // The flood is at a user-specified location. So get the location from values read from the shapefile
59 long unsigned int nLocIDs = m_VdFloodLocationX.size();
60 double dDiffTotWaterLevel = 0;
61
62 double dAuxWaterLevelDiff = 0;
63
64 if (nLocIDs == 0)
65 {
66 int pointCounter = 0;
67
68 for (int nCoast = 0; nCoast < static_cast<int>(m_VCoast.size()); nCoast++)
69 {
70 int nCoastSize = m_VCoast[nCoast].pLGetCoastlineExtCRS()->nGetSize();
71
72 for (int nCoastPoint = 0; nCoastPoint < nCoastSize; nCoastPoint++)
73 {
74 dAuxWaterLevelDiff = m_VCoast[nCoast].dGetLevel(nCoastPoint, m_nLevel);
75
76 if (! isnan(dAuxWaterLevelDiff))
77 {
78 if (tAbs(dAuxWaterLevelDiff) < 1) // Limiting the maximum value that can be found (dAuxWaterLevelDiff != DBL_NODATA)
79 {
80 pointCounter++;
81 dDiffTotWaterLevel += dAuxWaterLevelDiff;
82 }
83 }
84 }
85 }
86
87 if (pointCounter > 0)
88 dDiffTotWaterLevel /= pointCounter;
89
90 else
91 dDiffTotWaterLevel = 0;
92 }
93
94 else
95 {
96 for (long unsigned int n = 0; n < nLocIDs; n++)
97 {
98 double dPointGridXExtCRS = m_VdFloodLocationX[n];
99 double dPointGridYExtCRS = m_VdFloodLocationY[n];
100 double dMinDiffTotWaterLevelAtCoast = 1e10;
101
102 for (int nCoast = 0; nCoast < static_cast<int>(m_VCoast.size()); nCoast++)
103 {
104 int nCoastSize = m_VCoast[nCoast].pLGetCoastlineExtCRS()->nGetSize();
105 double dMinDistSquare = 1e10;
106
107 for (int nCoastPoint = 0; nCoastPoint < nCoastSize; nCoastPoint++)
108 {
109 double dCoastPointXExtCRS = m_VCoast[nCoast].pPtGetCoastlinePointExtCRS(nCoastPoint)->dGetX();
110 double dCoastPointYExtCRS = m_VCoast[nCoast].pPtGetCoastlinePointExtCRS(nCoastPoint)->dGetY();
111
112 double dDistSquare = (dCoastPointXExtCRS - dPointGridXExtCRS) * (dCoastPointXExtCRS - dPointGridXExtCRS) + (dCoastPointYExtCRS - dPointGridYExtCRS) * (dCoastPointYExtCRS - dPointGridYExtCRS);
113
114 if (dDistSquare < dMinDistSquare)
115 {
116 dAuxWaterLevelDiff = m_VCoast[nCoast].dGetLevel(nCoastPoint, m_nLevel);
117
118 if (! isnan(dAuxWaterLevelDiff))
119 {
120 dMinDistSquare = dDistSquare;
121 dMinDiffTotWaterLevelAtCoast = dAuxWaterLevelDiff;
122 }
123 }
124 }
125 }
126
127 dDiffTotWaterLevel += dMinDiffTotWaterLevelAtCoast;
128 }
129
130 dDiffTotWaterLevel /= static_cast<double>(nLocIDs);
131 }
132
133 m_dThisIterDiffTotWaterLevel = dDiffTotWaterLevel;
134
135 switch (m_nLevel)
136 {
137 case 0: // WAVESETUP + STORMSURGE:
139 break;
140
141 case 1: // WAVESETUP + STORMSURGE + RUNUP:
143 break;
144 }
145
146 // Create an empty stack
147 stack<CGeom2DIPoint> PtiStackFlood;
148
149 // Start at the given edge cell, push this onto the stack
150 PtiStackFlood.push(CGeom2DIPoint(nXStart, nYStart));
151
152 // Then do the cell-by-cell fill loop until there are no more cell coordinates on the stack
153 while (! PtiStackFlood.empty())
154 {
155 CGeom2DIPoint Pti = PtiStackFlood.top();
156 PtiStackFlood.pop();
157
158 int nX = Pti.nGetX();
159 int nY = Pti.nGetY();
160
161 while (nX >= 0)
162 {
163 if (m_pRasterGrid->m_Cell[nX][nY].bIsCellFloodCheck())
164 break;
165
166 if (! m_pRasterGrid->m_Cell[nX][nY].bIsElevLessThanWaterLevel())
167 break;
168
169 nX--;
170 }
171
172 nX++;
173
174 bool bSpanAbove = false;
175 bool bSpanBelow = false;
176
177 while (nX < m_nXGridSize)
178 {
179 if (m_pRasterGrid->m_Cell[nX][nY].bIsCellFloodCheck())
180 break;
181
182 if (! m_pRasterGrid->m_Cell[nX][nY].bIsElevLessThanWaterLevel())
183 break;
184
185 // Flood this cell
186 m_pRasterGrid->m_Cell[nX][nY].SetCheckFloodCell();
187 m_pRasterGrid->m_Cell[nX][nY].SetInContiguousFlood();
188
189 switch (m_nLevel)
190 {
191 case 0: // WAVESETUP + STORMSURGE:
192 m_pRasterGrid->m_Cell[nX][nY].SetFloodBySetupSurge();
193 break;
194
195 case 1: // WAVESETUP + STORMSURGE + RUNUP:
196 m_pRasterGrid->m_Cell[nX][nY].SetFloodBySetupSurgeRunup();
197 break;
198 }
199
200 if ((! bSpanAbove) && (nY > 0) && (m_pRasterGrid->m_Cell[nX][nY - 1].bIsElevLessThanWaterLevel()) && (! m_pRasterGrid->m_Cell[nX][nY - 1].bIsCellFloodCheck()))
201 {
202 PtiStackFlood.push(CGeom2DIPoint(nX, nY - 1));
203 bSpanAbove = true;
204 }
205
206 else if (bSpanAbove && (nY > 0) && (! m_pRasterGrid->m_Cell[nX][nY - 1].bIsElevLessThanWaterLevel()))
207 {
208 bSpanAbove = false;
209 }
210
211 if ((! bSpanBelow) && (nY < m_nYGridSize - 1) && (m_pRasterGrid->m_Cell[nX][nY + 1].bIsElevLessThanWaterLevel()) && (! m_pRasterGrid->m_Cell[nX][nY + 1].bIsCellFloodCheck()))
212 {
213 PtiStackFlood.push(CGeom2DIPoint(nX, nY + 1));
214 bSpanBelow = true;
215 }
216
217 else if (bSpanBelow && (nY < m_nYGridSize - 1) && (! m_pRasterGrid->m_Cell[nX][nY + 1].bIsElevLessThanWaterLevel()))
218 {
219 bSpanBelow = false;
220 }
221
222 nX++;
223 }
224 }
225}
226
227//===============================================================================================================================
229//===============================================================================================================================
231{
232 vector<bool> VbPossibleStartCellLHEdge;
233 vector<bool> VbTraced;
234 vector<int> VnSearchDirection;
235 vector<CGeom2DIPoint> V2DIPossibleStartCell;
236
237 // Go along the list of edge cells and look for possible coastline start cells
238 for (unsigned int n = 0; n < m_VEdgeCell.size() - 1; n++)
239 {
241 continue;
242
244 continue;
245
247 continue;
248
250 continue;
251
252 int nXThis = m_VEdgeCell[n].nGetX();
253 int nYThis = m_VEdgeCell[n].nGetY();
254 int nXNext = m_VEdgeCell[n + 1].nGetX();
255 int nYNext = m_VEdgeCell[n + 1].nGetY();
256
257 // Get "Is it sea?" information for 'this' and 'next' cells
258 bool bThisCellIsSea = m_pRasterGrid->m_Cell[nXThis][nYThis].bIsInContiguousSeaArea();
259 bool bNextCellIsSea = m_pRasterGrid->m_Cell[nXNext][nYNext].bIsInContiguousSeaArea();
260
261 // Are we at a coast?
262 if ((! bThisCellIsSea) && bNextCellIsSea)
263 {
264 // 'This' cell is just inland, has it already been flagged as a possible start for a coastline (even if this subsequently 'failed' as a coastline)?
265 // if (! m_pRasterGrid->m_Cell[nXThis][nYThis].bIsPossibleCoastStartCell())
266 {
267 // It has not, so flag it
268 m_pRasterGrid->m_Cell[nXThis][nYThis].SetPossibleFloodStartCell();
269
270 // And save it
271 V2DIPossibleStartCell.push_back(CGeom2DIPoint(nXThis, nYThis));
272 VbPossibleStartCellLHEdge.push_back(true);
273 VnSearchDirection.push_back(nGetOppositeDirection(m_VEdgeCellEdge[n]));
274 VbTraced.push_back(false);
275 }
276 }
277
278 else if (bThisCellIsSea && (! bNextCellIsSea))
279 {
280 // The 'next' cell is just inland, has it already been flagged as a possible start for a coastline (even if this subsequently 'failed' as a coastline)?
281 // if (! m_pRasterGrid->m_Cell[nXNext][nYNext].bIsPossibleCoastStartCell())
282 {
283 // It has not, so flag it
284 m_pRasterGrid->m_Cell[nXNext][nYNext].SetPossibleFloodStartCell();
285
286 // And save it
287 V2DIPossibleStartCell.push_back(CGeom2DIPoint(nXNext, nYNext));
288 VbPossibleStartCellLHEdge.push_back(false);
289 VnSearchDirection.push_back(nGetOppositeDirection(m_VEdgeCellEdge[n + 1]));
290 VbTraced.push_back(false);
291 }
292 }
293 }
294
295 bool bAtLeastOneCoastTraced = false;
296
297 for (unsigned int n = 0; n < V2DIPossibleStartCell.size(); n++)
298 {
299 if (! VbTraced[n])
300 {
301 int nRet = 0;
302
303 if (VbPossibleStartCellLHEdge[n])
304 {
305 nRet = nTraceFloodCoastLine(n, VnSearchDirection[n], LEFT_HANDED, &VbTraced, &V2DIPossibleStartCell);
306 }
307
308 else
309 {
310 nRet = nTraceFloodCoastLine(n, VnSearchDirection[n], RIGHT_HANDED, &VbTraced, &V2DIPossibleStartCell);
311 }
312
313 if (nRet == RTN_OK)
314 {
315 // We have a valid coastline starting from this possible start cell
316 VbTraced[n] = true;
317 bAtLeastOneCoastTraced = true;
318 }
319 }
320 }
321
322 if (bAtLeastOneCoastTraced)
323 return RTN_OK;
324
325 else
327}
328
329//===============================================================================================================================
331//===============================================================================================================================
332int CSimulation::nTraceFloodCoastLine(unsigned int const nTraceFromStartCellIndex, int const nStartSearchDirection, int const nHandedness, vector<bool>*pVbTraced, vector<CGeom2DIPoint> const* pV2DIPossibleStartCell)
333{
334 bool bHitStartCell = false;
335 bool bAtCoast = false;
336 bool bHasLeftStartEdge = false;
337 bool bTooLong = false;
338 bool bOffEdge = false;
339 bool bRepeating = false;
340
341 int nStartX = pV2DIPossibleStartCell->at(nTraceFromStartCellIndex).nGetX();
342 int nStartY = pV2DIPossibleStartCell->at(nTraceFromStartCellIndex).nGetY();
343 int nX = nStartX;
344 int nY = nStartY;
345 int nSearchDirection = nStartSearchDirection;
346 int nRoundLoop = -1;
347 // nThisLen = 0;
348 // nLastLen = 0,
349 // nPreLastLen = 0;
350
351 // Temporary coastline as integer points (grid CRS)
352 CGeomILine ILTempGridCRS;
353
354 // Mark the start cell as coast and add it to the vector object
355 m_pRasterGrid->m_Cell[nStartX][nStartY].SetAsFloodLine(true);
356 CGeom2DIPoint PtiStart(nStartX, nStartY);
357 ILTempGridCRS.Append(&PtiStart);
358
359 // 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
360 do
361 {
362 // // DEBUG CODE ==============================================================================================================
363 // LogStream << "Now at [" << nX << "][" << nY << "] = {" << dGridCentroidXToExtCRSX(nX) << ", " << dGridCentroidYToExtCRSY(nY) << "}" << endl;
364 // LogStream << "ILTempGridCRS is now:" << endl;
365 // for (int n = 0; n < ILTempGridCRS.nGetSize(); n++)
366 // LogStream << "[" << ILTempGridCRS[n].nGetX() << "][" << ILTempGridCRS[n].nGetY() << "] = {" << dGridCentroidXToExtCRSX(ILTempGridCRS[n].nGetX()) << ", " << dGridCentroidYToExtCRSY(ILTempGridCRS[n].nGetY()) << "}" << endl;
367 // LogStream << "=================" << endl;
368 // // DEBUG CODE ==============================================================================================================
369
370 // Safety check
371 if (++nRoundLoop > m_nCoastMax)
372 {
373 bTooLong = true;
374
375 // LogStream << m_ulIter << ": abandoning coastline tracing from [" << nStartX << "][" << nStartY << "] = {" << dGridCentroidXToExtCRSX(nStartX) << ", " << dGridCentroidYToExtCRSY(nStartY) << "}, exceeded maximum search length (" << m_nCoastMax << ")" << endl;
376
377 // for (int n = 0; n < ILTempGridCRS.nGetSize(); n++)
378 // LogStream << "[" << ILTempGridCRS[n].nGetX() << "][" << ILTempGridCRS[n].nGetY() << "] = {" << dGridCentroidXToExtCRSX(ILTempGridCRS[n].nGetX()) << ", " << dGridCentroidYToExtCRSY(ILTempGridCRS[n].nGetY()) << "}" << endl;
379 // LogStream << endl;
380
381 break;
382 }
383
384 // Another safety check
385 if ((nRoundLoop > 10) && (ILTempGridCRS.nGetSize() < 2))
386 {
387 // 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
388 bRepeating = true;
389
390 break;
391 }
392
393 // OK so far: so have we left the start edge?
394 if (! bHasLeftStartEdge)
395 {
396 // We have not yet left the start edge
397 if (((nStartSearchDirection == SOUTH) && (nY > nStartY)) || ((nStartSearchDirection == NORTH) && (nY < nStartY)) ||
398 ((nStartSearchDirection == EAST) && (nX > nStartX)) || ((nStartSearchDirection == WEST) && (nX < nStartX)))
399 bHasLeftStartEdge = true;
400
401 // Flag this cell to ensure that it is not chosen as a coastline start cell later
402 m_pRasterGrid->m_Cell[nX][nY].SetPossibleFloodStartCell();
403 // LogStream << "Flagging [" << nX << "][" << nY << "] as possible coast start cell NOT YET LEFT EDGE" << endl;
404 }
405
406 // Leave the loop if the vector coastline has left the start edge, then we find a coast cell which is a possible start cell from which a coastline has not yet been traced
407 // if (bHasLeftStartEdge && bAtCoast)
408 {
409 for (unsigned int nn = 0; nn < pVbTraced->size(); nn++)
410 {
411 if ((nn != nTraceFromStartCellIndex) && (! pVbTraced->at(nn)))
412 {
413 // LogStream << "[" << pV2DIPossibleStartCell->at(nn).nGetX() << "][" << pV2DIPossibleStartCell->at(nn).nGetY() << "]" << endl;
414
415 if (bAtCoast && (nX == pV2DIPossibleStartCell->at(nn).nGetX()) && (nY == pV2DIPossibleStartCell->at(nn).nGetY()))
416 {
418 LogStream << m_ulIter << ": Possible flood coastline found, traced from [" << nStartX << "][" << nStartY << "] and hit another coast start cell at [" << nX << "][" << nY << "]" << endl;
419
420 pVbTraced->at(nn) = true;
421 bHitStartCell = true;
422 break;
423 }
424 }
425 }
426
427 // LogStream << endl;
428 }
429
430 if (bHitStartCell)
431 break;
432
433 // OK now sort out the next iteration of the search
434 int nXSeaward = 0;
435 int nYSeaward = 0;
436 int nSeawardNewDirection = 0;
437 int nXStraightOn = 0;
438 int nYStraightOn = 0;
439 int nXAntiSeaward = 0;
440 int nYAntiSeaward = 0;
441 int nAntiSeawardNewDirection = 0;
442 int nXGoBack = 0;
443 int nYGoBack = 0;
444 int nGoBackNewDirection = 0;
445
446 CGeom2DIPoint Pti(nX, nY);
447
448 // Set up the variables
449 switch (nHandedness)
450 {
451 case RIGHT_HANDED:
452
453 // 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
454 switch (nSearchDirection)
455 {
456 case NORTH:
457 // The sea is towards the RHS (E) of the coast, so first try to go right (to the E)
458 nXSeaward = nX + 1;
459 nYSeaward = nY;
460 nSeawardNewDirection = EAST;
461
462 // If can't do this, try to go straight on (to the N)
463 nXStraightOn = nX;
464 nYStraightOn = nY - 1;
465
466 // If can't do either of these, try to go anti-seaward i.e. towards the LHS (W)
467 nXAntiSeaward = nX - 1;
468 nYAntiSeaward = nY;
469 nAntiSeawardNewDirection = WEST;
470
471 // As a last resort, go back (to the S)
472 nXGoBack = nX;
473 nYGoBack = nY + 1;
474 nGoBackNewDirection = SOUTH;
475
476 break;
477
478 case EAST:
479 // The sea is towards the RHS (S) of the coast, so first try to go right (to the S)
480 nXSeaward = nX;
481 nYSeaward = nY + 1;
482 nSeawardNewDirection = SOUTH;
483
484 // If can't do this, try to go straight on (to the E)
485 nXStraightOn = nX + 1;
486 nYStraightOn = nY;
487
488 // If can't do either of these, try to go anti-seaward i.e. towards the LHS (N)
489 nXAntiSeaward = nX;
490 nYAntiSeaward = nY - 1;
491 nAntiSeawardNewDirection = NORTH;
492
493 // As a last resort, go back (to the W)
494 nXGoBack = nX - 1;
495 nYGoBack = nY;
496 nGoBackNewDirection = WEST;
497
498 break;
499
500 case SOUTH:
501 // The sea is towards the RHS (W) of the coast, so first try to go right (to the W)
502 nXSeaward = nX - 1;
503 nYSeaward = nY;
504 nSeawardNewDirection = WEST;
505
506 // If can't do this, try to go straight on (to the S)
507 nXStraightOn = nX;
508 nYStraightOn = nY + 1;
509
510 // If can't do either of these, try to go anti-seaward i.e. towards the LHS (E)
511 nXAntiSeaward = nX + 1;
512 nYAntiSeaward = nY;
513 nAntiSeawardNewDirection = EAST;
514
515 // As a last resort, go back (to the N)
516 nXGoBack = nX;
517 nYGoBack = nY - 1;
518 nGoBackNewDirection = NORTH;
519
520 break;
521
522 case WEST:
523 // The sea is towards the RHS (N) of the coast, so first try to go right (to the N)
524 nXSeaward = nX;
525 nYSeaward = nY - 1;
526 nSeawardNewDirection = NORTH;
527
528 // If can't do this, try to go straight on (to the W)
529 nXStraightOn = nX - 1;
530 nYStraightOn = nY;
531
532 // If can't do either of these, try to go anti-seaward i.e. towards the LHS (S)
533 nXAntiSeaward = nX;
534 nYAntiSeaward = nY + 1;
535 nAntiSeawardNewDirection = SOUTH;
536
537 // As a last resort, go back (to the E)
538 nXGoBack = nX + 1;
539 nYGoBack = nY;
540 nGoBackNewDirection = EAST;
541
542 break;
543 }
544
545 break;
546
547 case LEFT_HANDED:
548
549 // 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
550 switch (nSearchDirection)
551 {
552 case NORTH:
553 // The sea is towards the LHS (W) of the coast, so first try to go left (to the W)
554 nXSeaward = nX - 1;
555 nYSeaward = nY;
556 nSeawardNewDirection = WEST;
557
558 // If can't do this, try to go straight on (to the N)
559 nXStraightOn = nX;
560 nYStraightOn = nY - 1;
561
562 // If can't do either of these, try to go anti-seaward i.e. towards the RHS (E)
563 nXAntiSeaward = nX + 1;
564 nYAntiSeaward = nY;
565 nAntiSeawardNewDirection = EAST;
566
567 // As a last resort, go back (to the S)
568 nXGoBack = nX;
569 nYGoBack = nY + 1;
570 nGoBackNewDirection = SOUTH;
571
572 break;
573
574 case EAST:
575 // The sea is towards the LHS (N) of the coast, so first try to go left (to the N)
576 nXSeaward = nX;
577 nYSeaward = nY - 1;
578 nSeawardNewDirection = NORTH;
579
580 // If can't do this, try to go straight on (to the E)
581 nXStraightOn = nX + 1;
582 nYStraightOn = nY;
583
584 // If can't do either of these, try to go anti-seaward i.e. towards the RHS (S)
585 nXAntiSeaward = nX;
586 nYAntiSeaward = nY + 1;
587 nAntiSeawardNewDirection = SOUTH;
588
589 // As a last resort, go back (to the W)
590 nXGoBack = nX - 1;
591 nYGoBack = nY;
592 nGoBackNewDirection = WEST;
593
594 break;
595
596 case SOUTH:
597 // The sea is towards the LHS (E) of the coast, so first try to go left (to the E)
598 nXSeaward = nX + 1;
599 nYSeaward = nY;
600 nSeawardNewDirection = EAST;
601
602 // If can't do this, try to go straight on (to the S)
603 nXStraightOn = nX;
604 nYStraightOn = nY + 1;
605
606 // If can't do either of these, try to go anti-seaward i.e. towards the RHS (W)
607 nXAntiSeaward = nX - 1;
608 nYAntiSeaward = nY;
609 nAntiSeawardNewDirection = WEST;
610
611 // As a last resort, go back (to the N)
612 nXGoBack = nX;
613 nYGoBack = nY - 1;
614 nGoBackNewDirection = NORTH;
615
616 break;
617
618 case WEST:
619 // The sea is towards the LHS (S) of the coast, so first try to go left (to the S)
620 nXSeaward = nX;
621 nYSeaward = nY + 1;
622 nSeawardNewDirection = SOUTH;
623
624 // If can't do this, try to go straight on (to the W)
625 nXStraightOn = nX - 1;
626 nYStraightOn = nY;
627
628 // If can't do either of these, try to go anti-seaward i.e. towards the RHS (N)
629 nXAntiSeaward = nX;
630 nYAntiSeaward = nY - 1;
631 nAntiSeawardNewDirection = NORTH;
632
633 // As a last resort, go back (to the E)
634 nXGoBack = nX + 1;
635 nYGoBack = nY;
636 nGoBackNewDirection = EAST;
637
638 break;
639 }
640
641 break;
642 }
643
644 // 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?
645 if (bIsWithinValidGrid(nXSeaward, nYSeaward))
646 {
647 // It is, so check if the cell in the seaward direction is a sea cell
648 if (m_pRasterGrid->m_Cell[nXSeaward][nYSeaward].bIsInContiguousSeaArea())
649 {
650 // There is sea in this seaward direction, so we are on the coast
651 bAtCoast = true;
652
653 // Has the current cell already marked been marked as a coast cell?
654 if (! m_pRasterGrid->m_Cell[nX][nY].bIsFloodLine())
655 {
656 // Not already marked, is this an intervention cell with the top above SWL?
657 if ((bIsInterventionCell(nX, nY)) && (! m_pRasterGrid->m_Cell[nX][nY].bIsElevLessThanWaterLevel()))
658 {
659 // It is, so mark as coast and add it to the vector object
660 m_pRasterGrid->m_Cell[nX][nY].SetAsFloodLine(true);
661 ILTempGridCRS.Append(&Pti);
662 }
663
664 else if (! m_pRasterGrid->m_Cell[nX][nY].bIsElevLessThanWaterLevel())
665 {
666 // The sediment top is above SWL so mark as coast and add it to the vector object
667 m_pRasterGrid->m_Cell[nX][nY].SetAsFloodLine(true);
668 ILTempGridCRS.Append(&Pti);
669 }
670 }
671 }
672
673 else
674 {
675 // The seaward cell is not a sea cell, so we will move to it next time
676 nX = nXSeaward;
677 nY = nYSeaward;
678
679 // And set a new search direction, to keep turning seaward
680 nSearchDirection = nSeawardNewDirection;
681 continue;
682 }
683 }
684
685 // 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?
686 if (bIsWithinValidGrid(nXStraightOn, nYStraightOn))
687 {
688 // It is, so check if there is sea immediately in front
689 if (m_pRasterGrid->m_Cell[nXStraightOn][nYStraightOn].bIsInContiguousSeaArea())
690 {
691 // Sea is in front, so we are on the coast
692 bAtCoast = true;
693
694 // Has the current cell already marked been marked as a coast cell?
695 if (! m_pRasterGrid->m_Cell[nX][nY].bIsFloodLine())
696 {
697 // Not already marked, is this an intervention cell with the top above SWL?
698 if ((bIsInterventionCell(nX, nY)) && (! m_pRasterGrid->m_Cell[nX][nY].bIsElevLessThanWaterLevel()))
699 {
700 // It is, so mark as coast and add it to the vector object
701 m_pRasterGrid->m_Cell[nX][nY].SetAsFloodLine(true);
702 ILTempGridCRS.Append(&Pti);
703 }
704
705 else if (! m_pRasterGrid->m_Cell[nX][nY].bIsElevLessThanWaterLevel())
706 {
707 // The sediment top is above SWL so mark as coast and add it to the vector object
708 m_pRasterGrid->m_Cell[nX][nY].SetAsFloodLine(true);
709 ILTempGridCRS.Append(&Pti);
710 }
711 }
712 }
713
714 else
715 {
716 // The straight-ahead cell is not a sea cell, so we will move to it next time
717 nX = nXStraightOn;
718 nY = nYStraightOn;
719
720 // The search direction remains unchanged
721 continue;
722 }
723 }
724
725 // 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?
726 if (bIsWithinValidGrid(nXAntiSeaward, nYAntiSeaward))
727 {
728 // It is, so check if there is sea in this anti-seaward cell
729 if (m_pRasterGrid->m_Cell[nXAntiSeaward][nYAntiSeaward].bIsInContiguousSeaArea())
730 {
731 // There is sea on the anti-seaward side, so we are on the coast
732 bAtCoast = true;
733
734 // Has the current cell already marked been marked as a coast cell?
735 if (! m_pRasterGrid->m_Cell[nX][nY].bIsFloodLine())
736 {
737 // Not already marked, is this an intervention cell with the top above SWL?
738 if ((bIsInterventionCell(nX, nY)) && (! m_pRasterGrid->m_Cell[nX][nY].bIsElevLessThanWaterLevel()))
739 {
740 // It is, so mark as coast and add it to the vector object
741 m_pRasterGrid->m_Cell[nX][nY].SetAsFloodLine(true);
742 ILTempGridCRS.Append(&Pti);
743 }
744
745 else if (! m_pRasterGrid->m_Cell[nX][nY].bIsElevLessThanWaterLevel())
746 {
747 // The sediment top is above SWL so mark as coast and add it to the vector object
748 m_pRasterGrid->m_Cell[nX][nY].SetAsFloodLine(true);
749 ILTempGridCRS.Append(&Pti);
750 }
751 }
752 }
753
754 else
755 {
756 // The anti-seaward cell is not a sea cell, so we will move to it next time
757 nX = nXAntiSeaward;
758 nY = nYAntiSeaward;
759
760 // And set a new search direction, to keep turning seaward
761 nSearchDirection = nAntiSeawardNewDirection;
762 continue;
763 }
764 }
765
766 // 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
767 if (bIsWithinValidGrid(nXGoBack, nYGoBack))
768 {
769 nX = nXGoBack;
770 nY = nYGoBack;
771
772 // And change the search direction
773 nSearchDirection = nGoBackNewDirection;
774 }
775
776 else
777 {
778 // Our final choice is not a valid cell, so give up
779 bOffEdge = true;
780 break;
781 }
782 } while (true);
783
784 // OK, we have finished tracing this coastline on the grid. But is the coastline too long or too short?
785 int nCoastSize = ILTempGridCRS.nGetSize();
786
787 if (bOffEdge)
788 {
790 LogStream << m_ulIter << ": Ignoring possible flood 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;
791
792 // Unmark these cells as coast cells
793 for (int n = 0; n < nCoastSize; n++)
794 m_pRasterGrid->m_Cell[ILTempGridCRS[n].nGetX()][ILTempGridCRS[n].nGetY()].SetAsFloodLine(false);
795
797 }
798
799 if (bTooLong)
800 {
801 // Around loop too many times, so abandon this coastline
803 {
804 LogStream << m_ulIter << ": Ignoring possible flood coastline from [" << nStartX << "][" << nStartY << "] = {" << dGridCentroidXToExtCRSX(nStartX) << ", " << dGridCentroidYToExtCRSY(nStartY) << "} since round loop " << nRoundLoop << " times (m_nCoastMax = " << m_nCoastMax << "), coastline size is " << nCoastSize;
805
806 if (nCoastSize > 0)
807 LogStream << ", it ended at [" << ILTempGridCRS[nCoastSize - 1].nGetX() << "][" << ILTempGridCRS[nCoastSize - 1].nGetY() << "] = {" << dGridCentroidXToExtCRSX(ILTempGridCRS[nCoastSize - 1].nGetX()) << ", " << dGridCentroidYToExtCRSY(ILTempGridCRS[nCoastSize - 1].nGetY()) << "}";
808
809 LogStream << endl;
810 }
811
812 // Unmark these cells as coast cells
813 for (int n = 0; n < nCoastSize; n++)
814 m_pRasterGrid->m_Cell[ILTempGridCRS[n].nGetX()][ILTempGridCRS[n].nGetY()].SetAsFloodLine(false);
815
817 }
818
819 if (bRepeating)
820 {
822 {
823 LogStream << m_ulIter << ": Ignoring possible flood coastline from [" << nStartX << "][" << nStartY << "] = {" << dGridCentroidXToExtCRSX(nStartX) << ", " << dGridCentroidYToExtCRSY(nStartY) << "} since repeating, coastline size is " << nCoastSize;
824
825 if (nCoastSize > 0)
826 LogStream << ", it ended at [" << ILTempGridCRS[nCoastSize - 1].nGetX() << "][" << ILTempGridCRS[nCoastSize - 1].nGetY() << "] = {" << dGridCentroidXToExtCRSX(ILTempGridCRS[nCoastSize - 1].nGetX()) << ", " << dGridCentroidYToExtCRSY(ILTempGridCRS[nCoastSize - 1].nGetY()) << "}";
827
828 LogStream << endl;
829 }
830
831 // Unmark these cells as coast cells
832 for (int n = 0; n < nCoastSize; n++)
833 m_pRasterGrid->m_Cell[ILTempGridCRS[n].nGetX()][ILTempGridCRS[n].nGetY()].SetAsFloodLine(false);
834
836 }
837
838 if (nCoastSize == 0)
839 {
840 // Zero-length coastline, so abandon it
842 LogStream << m_ulIter << ": abandoning zero-length flood coastline from [" << nStartX << "][" << nStartY << "] = {" << dGridCentroidXToExtCRSX(nStartX) << ", " << dGridCentroidYToExtCRSY(nStartY) << "}" << endl;
843
845 }
846
847 if (nCoastSize < m_nCoastMin)
848 {
849 // The vector coastline is too small, so abandon it
851 LogStream << m_ulIter << ": Ignoring possible flood 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;
852
853 // Unmark these cells as coast cells
854 for (int n = 0; n < nCoastSize; n++)
855 m_pRasterGrid->m_Cell[ILTempGridCRS[n].nGetX()][ILTempGridCRS[n].nGetY()].SetAsFloodLine(false);
856
858 }
859
860 // OK this new coastline is fine
861 int nEndX = nX;
862 int nEndY = nY;
863 int nCoastEndX = ILTempGridCRS[nCoastSize - 1].nGetX();
864 int nCoastEndY = ILTempGridCRS[nCoastSize - 1].nGetY();
865
866 if ((nCoastEndX != nEndX) || (nCoastEndY != nEndY))
867 {
868 // 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?
869 if (! m_pRasterGrid->m_Cell[nCoastEndX][nCoastEndY].bIsBoundingBoxEdge())
870 {
871 // The final cell in ILTempGridCRS is not a grid-edge cell, so add the grid-edge cell and mark the cell as coastline
872 ILTempGridCRS.Append(nEndX, nEndY);
873 nCoastSize++;
874
875 m_pRasterGrid->m_Cell[nEndX][nEndY].SetAsFloodLine(true);
876 }
877 }
878
879 // Need to specify start edge and end edge for smoothing routines
880 // int
881 // nStartEdge = m_pRasterGrid->m_Cell[nStartX][nStartY].nGetBoundingBoxEdge(),
882 // nEndEdge = m_pRasterGrid->m_Cell[nEndX][nEndY].nGetBoundingBoxEdge();
883
884 // 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
885 CGeomLine LTempExtCRS;
886
887 for (int j = 0; j < nCoastSize; j++)
888 {
889 LTempExtCRS.Append(dGridCentroidXToExtCRSX(ILTempGridCRS[j].nGetX()), dGridCentroidYToExtCRSY(ILTempGridCRS[j].nGetY()));
890 }
891
892 // Now do some smoothing of the vector output, if desired
893 // if (m_nCoastSmooth == SMOOTH_RUNNING_MEAN)
894 // LTempExtCRS = LSmoothCoastRunningMean(&LTempExtCRS);
895 // else if (m_nCoastSmooth == SMOOTH_SAVITZKY_GOLAY)
896 // LTempExtCRS = LSmoothCoastSavitzkyGolay(&LTempExtCRS, nStartEdge, nEndEdge);
897
898 // // DEBUG CODE ==================================================================================================
899 // LogStream << "==================================" << endl;
900 // for (int j = 0; j < nCoastSize; j++)
901 // {
902 // LogStream << "{" << dGridCentroidXToExtCRSX(ILTempGridCRS[j].nGetX()) << ", " << dGridCentroidYToExtCRSY(ILTempGridCRS[j].nGetY()) << "}" << "\t{" << LTempExtCRS.dGetXAt(j) << ", " << LTempExtCRS.dGetYAt(j) << "}" << endl;
903 // }
904 // LogStream << "==================================" << endl;
905 // // DEBUG CODE ==================================================================================================
906
907 // Create a new coastline object and append to it the vector of coastline objects
908 CRWCoast CoastTmp(this);
909 int nCoast;
910
911 switch (m_nLevel)
912 {
913 case 0:
914 m_VFloodWaveSetupSurge.push_back(CoastTmp);
915 nCoast = static_cast<int>(m_VFloodWaveSetupSurge.size()) - 1;
916 m_VFloodWaveSetupSurge[nCoast].SetCoastlineExtCRS(&LTempExtCRS);
917 break;
918
919 case 1:
920 m_VFloodWaveSetupSurgeRunup.push_back(CoastTmp);
921 nCoast = static_cast<int>(m_VFloodWaveSetupSurgeRunup.size()) - 1;
922 m_VFloodWaveSetupSurgeRunup[nCoast].SetCoastlineExtCRS(&LTempExtCRS);
923 }
924
925 return RTN_OK;
926}
int nGetSize(void) const
Returns the number of integer point in the vector which represents this 2D shape.
Definition 2di_shape.cpp:70
void Append(CGeom2DIPoint const *)
Appends a new integer point to the vector which represents this 2D shape.
Definition 2di_shape.cpp:81
void Append(CGeom2DPoint const *)
Appends a point to this 2D shape.
Definition 2d_shape.cpp:67
Geometry class used to represent 2D point objects with integer coordinates.
Definition 2di_point.h:29
int nGetY(void) const
Returns the CGeom2DIPoint object's integer Y coordinate.
Definition 2di_point.cpp:48
int nGetX(void) const
Returns the CGeom2DIPoint object's integer X coordinate.
Definition 2di_point.cpp:42
Geometry class used to represent 2D vector integer line objects.
Definition i_line.h:31
Geometry class used to represent 2D vector line objects.
Definition line.h:31
Real-world class used to represent coastline objects.
Definition coast.h:40
int m_nLogFileDetail
Definition simulation.h:591
CGeomRasterGrid * m_pRasterGrid
Pointer to the raster grid object.
int m_nXGridSize
The size of the grid in the x direction.
Definition simulation.h:462
static int nGetOppositeDirection(int const)
Returns the opposite direction.
ofstream LogStream
vector< CRWCoast > m_VFloodWaveSetupSurgeRunup
TODO 007 Info needed.
vector< CRWCoast > m_VCoast
The coastline objects.
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 Not clear...
double m_dThisIterDiffWaveSetupSurgeWaterLevel
TODO 007 Info needed.
Definition simulation.h:771
int m_nYGridSize
The size of the grid in the y direction.
Definition simulation.h:465
vector< CRWCoast > m_VFloodWaveSetupSurge
TODO 007 Info needed.
vector< double > m_VdFloodLocationX
X coordinate (grid CRS) for total water level flooding.
bool m_bOmitSearchWestEdge
Omit the west edge of the grid from coast-end searches?
Definition simulation.h:355
int nTraceFloodCoastLine(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 ...
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:70
bool m_bOmitSearchNorthEdge
Omit the north edge of the grid from coast-end searches?
Definition simulation.h:349
vector< CGeom2DIPoint > m_VEdgeCell
Edge cells.
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,...
bool m_bOmitSearchSouthEdge
Omit the south edge of the grid from coast-end searches?
Definition simulation.h:352
unsigned long m_ulIter
The number of the current iteration (time step)
Definition simulation.h:618
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:62
double m_dThisIterDiffWaveSetupSurgeRunupWaterLevel
TODO 007 Info needed.
Definition simulation.h:774
bool bIsInterventionCell(int const, int const) const
Returns true if the cell is an intervention.
Definition utils.cpp:2918
vector< double > m_VdFloodLocationY
X coordinate (grid CRS) for total water level flooding.
double m_dThisIterDiffTotWaterLevel
TODO 007 Info needed.
Definition simulation.h:765
int m_nLevel
TODO 007 Used in WAVESETUP + SURGE + RUNUP.
Definition simulation.h:597
bool m_bOmitSearchEastEdge
Omit the east edge of the grid from coast-end searches?
Definition simulation.h:358
vector< int > m_VEdgeCellEdge
The grid edge that each edge cell belongs to.
This file contains global definitions for CoastalME.
int const LOG_FILE_HIGH_DETAIL
Definition cme.h:490
int const SOUTH
Definition cme.h:499
int const EAST
Definition cme.h:497
int const RTN_OK
Definition cme.h:692
int const RIGHT_HANDED
Definition cme.h:509
int const RTN_ERR_TRACING_COAST
Definition cme.h:725
T tAbs(T a)
Definition cme.h:1261
int const NORTH
Definition cme.h:495
int const LEFT_HANDED
Definition cme.h:510
int const WEST
Definition cme.h:501
Contains CRWCoast definitions.
Contains CGeomILine definitions.
Contains CGeomLine definitions.
Contains CGeomRasterGrid definitions.
Contains CSimulation definitions.