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