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