CoastalME (Coastal Modelling Environment)
Simulates the long-term behaviour of complex coastlines
Loading...
Searching...
No Matches
locate_cliff_toe.cpp
Go to the documentation of this file.
1
12
13/* ==============================================================================================================================
14
15 This file is part of CoastalME, the Coastal Modelling Environment.
16
17 CoastalME is free software; you can redistribute it and/or modify it under
18the terms of the GNU General Public License as published by the Free Software
19Foundation; either version 3 of the License, or (at your option) any later
20version.
21
22 This program is distributed in the hope that it will be useful, but WITHOUT
23ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
24FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
25
26 You should have received a copy of the GNU General Public License along with
27this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave,
28Cambridge, MA 02139, USA.
29
30==============================================================================================================================*/
31#include <assert.h>
32#include <cfloat>
33
34#include <cpl_port.h>
35#include <iostream>
36using std::cerr;
37using std::cout;
38using std::endl;
39
40#include <iomanip>
41using std::resetiosflags;
42using std::setiosflags;
43using std::setprecision;
44using std::setw;
45
46#include <stdint.h>
47
48#include <sstream>
49using std::stringstream;
50
51#include "cme.h"
52#include "raster_grid.h"
53#include "simulation.h"
54
55/*===============================================================================================================================
56
57 Calculates slope at every cell throughout the grid using finite difference
58method
59
60===============================================================================================================================*/
62 for (int nX = 0; nX < m_nXGridSize; nX++) {
63 for (int nY = 0; nY < m_nYGridSize; nY++) {
64
65 // Now lets look at surounding cells
66 if (nX > 0 && nX < m_nXGridSize - 1 && nY > 0 && nY < m_nYGridSize - 1) {
67 double dElevLeft =
68 m_pRasterGrid->m_Cell[nX - 1][nY].dGetSedimentTopElev();
69 double dElevRight =
70 m_pRasterGrid->m_Cell[nX + 1][nY].dGetSedimentTopElev();
71 double dElevUp =
72 m_pRasterGrid->m_Cell[nX][nY - 1].dGetSedimentTopElev();
73 double dElevDown =
74 m_pRasterGrid->m_Cell[nX][nY + 1].dGetSedimentTopElev();
75 // Calculate slope using finite difference method
76 double dSlopeX = (dElevRight - dElevLeft) / (2.0 * m_dCellSide);
77 double dSlopeY = (dElevDown - dElevUp) / (2.0 * m_dCellSide);
78 double dSlope = sqrt(dSlopeX * dSlopeX + dSlopeY * dSlopeY);
79 m_pRasterGrid->m_Cell[nX][nY].SetSlope(dSlope);
80 }
81 }
82 }
83}
84
85/*===============================================================================================================================
86
87Highligts cells with slope greater than threshold
88
89===============================================================================================================================*/
91 for (int nX = 0; nX < m_nXGridSize; nX++) {
92 for (int nY = 0; nY < m_nYGridSize; nY++) {
93 double dSlope = m_pRasterGrid->m_Cell[nX][nY].dGetSlope();
94 if (dSlope >= m_dCliffSlopeLimit) {
95 m_pRasterGrid->m_Cell[nX][nY].SetAsCliff(true);
96 }
97 }
98 }
99}
100/*===============================================================================================================================
101
102Removes small cliff islands below a given number of cellsusing flood fill
103algorithm
104
105===============================================================================================================================*/
106void CSimulation::nRemoveSmallCliffIslands(int const dMinCliffCellThreshold) {
107 // unsigned int m_nXGridSize = static_cast<unsigned int>(m_nXGridSize);
108 // unsigned int m_nYGridSize = static_cast<unsigned int>(m_nYGridSize);
109
110 // Create a 2D array to track which cells have been visited during flood fill
111 vector<vector<bool>> bVisited(static_cast<unsigned int>(m_nXGridSize),
112 vector<bool>(static_cast<unsigned int>(m_nYGridSize), false));
113
114 // Vector to store cells that belong to small cliff islands to be removed
115 vector<pair<int, int>> VSmallIslandCells;
116
117 // Loop through all cells to find unvisited cliff cells
118 for (unsigned int nX = 0; nX < static_cast<unsigned int>(m_nXGridSize); nX++) {
119 for (unsigned int nY = 0; nY < static_cast<unsigned int>(m_nYGridSize); nY++) {
120 // Check if this is an unvisited cliff cell
121 if (!bVisited[nX][nY] && m_pRasterGrid->m_Cell[nX][nY].bIsCliff()) {
122 // Found the start of a new cliff region - use flood fill to find all
123 // connected cliff cells
124 vector<pair<int, int>> VCurrentCliffRegion;
125
126 // Stack for iterative flood fill algorithm
127 vector<pair<int, int>> VStack;
128 VStack.push_back(std::make_pair(nX, nY));
129
130 // Flood fill to find all connected cliff cells
131 while (!VStack.empty()) {
132 pair<int, int> currentCell = VStack.back();
133 VStack.pop_back();
134
135 size_t nCurX = static_cast<size_t>(currentCell.first);
136 size_t nCurY = static_cast<size_t>(currentCell.second);
137
138 // Skip if already visited or out of bounds
139 if (nCurX >= static_cast<unsigned int>(m_nXGridSize) ||
140 nCurY >= static_cast<unsigned int>(m_nYGridSize) || bVisited[nCurX][nCurY] ||
141 !m_pRasterGrid->m_Cell[nCurX][nCurY].bIsCliff()) {
142 continue;
143 }
144
145 // Mark as visited and add to current cliff region
146 bVisited[nCurX][nCurY] = true;
147 VCurrentCliffRegion.push_back(std::make_pair(nCurX, nCurY));
148
149 // Add neighboring cells to stack (8-connectivity: N, NE, E, SE, S,
150 // SW, W, NW)
151 VStack.push_back(std::make_pair(nCurX - 1, nCurY)); // North
152 VStack.push_back(std::make_pair(nCurX - 1, nCurY + 1)); // Northeast
153 VStack.push_back(std::make_pair(nCurX, nCurY + 1)); // East
154 VStack.push_back(std::make_pair(nCurX + 1, nCurY + 1)); // Southeast
155 VStack.push_back(std::make_pair(nCurX + 1, nCurY)); // South
156 VStack.push_back(std::make_pair(nCurX + 1, nCurY - 1)); // Southwest
157 VStack.push_back(std::make_pair(nCurX, nCurY - 1)); // West
158 VStack.push_back(std::make_pair(nCurX - 1, nCurY - 1)); // Northwest
159 }
160
161 // Calculate area of this cliff region (number of cells * cell area)
162 int dCliffRegionArea = static_cast<int>(VCurrentCliffRegion.size());
163
164 // If area is below threshold, mark all cells in this region for removal
165 if (dCliffRegionArea < dMinCliffCellThreshold) {
166 VSmallIslandCells.insert(VSmallIslandCells.end(),
167 VCurrentCliffRegion.begin(),
168 VCurrentCliffRegion.end());
169 }
170 }
171 }
172 }
173
174 // Remove cliff designation from all small island cells
175 for (const auto &cell : VSmallIslandCells) {
176 m_pRasterGrid->m_Cell[cell.first][cell.second].SetAsCliff(false);
177 }
178}
179
180/*===============================================================================================================================
181
182Traces the seaward extent of cliff cells using wall following algorithm
183
184===============================================================================================================================*/
186 // Clear previous cliff edges
187 m_VCliffEdge.clear();
188
189 // Find all possible cliff edge start points by scanning for cliff/non-cliff
190 // transitions
191 vector<CGeom2DIPoint> V2DIPossibleStartCell;
192 vector<bool> VbPossibleStartCellHandedness;
193 vector<int> VnSearchDirection;
194
195 // Scan all cells to find cliff toe edges by checking elevation patterns
196 for (int nX = 2; nX < m_nXGridSize - 2; nX++) {
197 for (int nY = 2; nY < m_nYGridSize - 2; nY++) {
198 if (m_pRasterGrid->m_Cell[nX][nY].bIsCliff()) {
199
200 // East direction (check if this is a seaward-facing cliff toe)
201 if (!m_pRasterGrid->m_Cell[nX][nY + 1].bIsCliff()) {
202 V2DIPossibleStartCell.push_back(CGeom2DIPoint(nX, nY));
203 VbPossibleStartCellHandedness.push_back(true);
204 VnSearchDirection.push_back(EAST);
205 }
206
207 // South direction
208 if (!m_pRasterGrid->m_Cell[nX + 1][nY].bIsCliff()) {
209 V2DIPossibleStartCell.push_back(CGeom2DIPoint(nX, nY));
210 VbPossibleStartCellHandedness.push_back(true);
211 VnSearchDirection.push_back(SOUTH);
212 }
213
214 // West direction
215 if (!m_pRasterGrid->m_Cell[nX][nY - 1].bIsCliff()) {
216 V2DIPossibleStartCell.push_back(CGeom2DIPoint(nX, nY));
217 VbPossibleStartCellHandedness.push_back(true);
218 VnSearchDirection.push_back(WEST);
219 }
220
221 // North direction
222 if (!m_pRasterGrid->m_Cell[nX - 1][nY].bIsCliff()) {
223 V2DIPossibleStartCell.push_back(CGeom2DIPoint(nX, nY));
224 VbPossibleStartCellHandedness.push_back(true);
225 VnSearchDirection.push_back(NORTH);
226 }
227 }
228 }
229 }
230
231 // Create a 2D array to track which cells have been used in cliff edge tracing
232 vector<vector<bool>> bUsedInCliffTrace(m_nXGridSize,
233 vector<bool>(m_nYGridSize, false));
234
235 int nCliffEdgesTraced = 0;
236
237 // For each possible start point, attempt to trace a cliff edge
238 for (size_t nStartPoint = 0; nStartPoint < V2DIPossibleStartCell.size();
239 nStartPoint++) {
240 int nXStart = V2DIPossibleStartCell[nStartPoint].nGetX();
241 int nYStart = V2DIPossibleStartCell[nStartPoint].nGetY();
242
243 // Skip if this cell has already been used in another cliff trace
244 if (bUsedInCliffTrace[nXStart][nYStart]) {
245 continue;
246 }
247
248 // Begin cliff edge tracing using wall following algorithm
249 vector<CGeom2DIPoint> VCliffEdge;
250 int nSearchDirection = VnSearchDirection[nStartPoint];
251
252 int nX = nXStart;
253 int nY = nYStart;
254 int nLength = 0;
255 const int nMaxLength = m_nXGridSize * m_nYGridSize; // Safety limit
256
257 do {
258 // Add current point to cliff edge
259 VCliffEdge.push_back(CGeom2DIPoint(nX, nY));
260 bUsedInCliffTrace[nX][nY] = true;
261 nLength++;
262
263 // Find next cell using wall following algorithm (right-hand rule)
264 int nXSeaward, nYSeaward, nXStraightOn, nYStraightOn;
265 int nXAntiSeaward, nYAntiSeaward, nXGoBack, nYGoBack;
266
267 // Calculate candidate positions based on search direction
268 switch (nSearchDirection) {
269 case NORTH:
270 nXSeaward = nX + 1;
271 nYSeaward = nY; // Right (East)
272 nXStraightOn = nX;
273 nYStraightOn = nY - 1; // Straight (North)
274 nXAntiSeaward = nX - 1;
275 nYAntiSeaward = nY; // Left (West)
276 nXGoBack = nX;
277 nYGoBack = nY + 1; // Back (South)
278 break;
279 case EAST:
280 nXSeaward = nX;
281 nYSeaward = nY + 1; // Right (South)
282 nXStraightOn = nX + 1;
283 nYStraightOn = nY; // Straight (East)
284 nXAntiSeaward = nX;
285 nYAntiSeaward = nY - 1; // Left (North)
286 nXGoBack = nX - 1;
287 nYGoBack = nY; // Back (West)
288 break;
289 case SOUTH:
290 nXSeaward = nX - 1;
291 nYSeaward = nY; // Right (West)
292 nXStraightOn = nX;
293 nYStraightOn = nY + 1; // Straight (South)
294 nXAntiSeaward = nX + 1;
295 nYAntiSeaward = nY; // Left (East)
296 nXGoBack = nX;
297 nYGoBack = nY - 1; // Back (North)
298 break;
299 case WEST:
300 nXSeaward = nX;
301 nYSeaward = nY - 1; // Right (North)
302 nXStraightOn = nX - 1;
303 nYStraightOn = nY; // Straight (West)
304 nXAntiSeaward = nX;
305 nYAntiSeaward = nY + 1; // Left (South)
306 nXGoBack = nX + 1;
307 nYGoBack = nY; // Back (East)
308 break;
309 default:
310 nXSeaward = nXStraightOn = nXAntiSeaward = nXGoBack = nX;
311 nYSeaward = nYStraightOn = nYAntiSeaward = nYGoBack = nY;
312 break;
313 }
314
315 // Try to move using wall following priority: seaward, straight,
316 // anti-seaward, back
317 bool bFoundNextCell = false;
318
319 // 1. Try seaward (right turn)
320 if (bIsWithinValidGrid(nXSeaward, nYSeaward) &&
321 m_pRasterGrid->m_Cell[nXSeaward][nYSeaward].bIsCliff()) {
322 nX = nXSeaward;
323 nY = nYSeaward;
324 // Update search direction (turn right)
325 switch (nSearchDirection) {
326 case NORTH:
327 nSearchDirection = EAST;
328 break;
329 case EAST:
330 nSearchDirection = SOUTH;
331 break;
332 case SOUTH:
333 nSearchDirection = WEST;
334 break;
335 case WEST:
336 nSearchDirection = NORTH;
337 break;
338 }
339 bFoundNextCell = true;
340 }
341 // 2. Try straight ahead
342 else if (bIsWithinValidGrid(nXStraightOn, nYStraightOn) &&
343 m_pRasterGrid->m_Cell[nXStraightOn][nYStraightOn].bIsCliff()) {
344 nX = nXStraightOn;
345 nY = nYStraightOn;
346 // Direction stays the same
347 bFoundNextCell = true;
348 }
349 // 3. Try anti-seaward (left turn)
350 else if (bIsWithinValidGrid(nXAntiSeaward, nYAntiSeaward) &&
351 m_pRasterGrid->m_Cell[nXAntiSeaward][nYAntiSeaward].bIsCliff()) {
352 nX = nXAntiSeaward;
353 nY = nYAntiSeaward;
354 // Update search direction (turn left)
355 switch (nSearchDirection) {
356 case NORTH:
357 nSearchDirection = WEST;
358 break;
359 case EAST:
360 nSearchDirection = NORTH;
361 break;
362 case SOUTH:
363 nSearchDirection = EAST;
364 break;
365 case WEST:
366 nSearchDirection = SOUTH;
367 break;
368 }
369 bFoundNextCell = true;
370 }
371 // 4. Try going back (U-turn)
372 else if (bIsWithinValidGrid(nXGoBack, nYGoBack) &&
373 m_pRasterGrid->m_Cell[nXGoBack][nYGoBack].bIsCliff()) {
374 nX = nXGoBack;
375 nY = nYGoBack;
376 // Update search direction (U-turn)
377 nSearchDirection = nGetOppositeDirection(nSearchDirection);
378 bFoundNextCell = true;
379 }
380
381 if (!bFoundNextCell) {
382 break; // No valid next cell found, end this cliff edge trace
383 }
384
385 } while ((nX != nXStart || nY != nYStart) && nLength < nMaxLength);
386
387 // Only keep cliff edges that have a reasonable length
388 if (VCliffEdge.size() > 2) {
389 nCliffEdgesTraced++;
390
391 // Convert grid coordinates to external CRS for smoothing
392 CGeomLine CliffEdgeExtCRS;
393 for (const auto &point : VCliffEdge) {
394 CliffEdgeExtCRS.Append(dGridCentroidXToExtCRSX(point.nGetX()),
395 dGridCentroidYToExtCRSY(point.nGetY()));
396 bUsedInCliffTrace[point.nGetX()][point.nGetY()] = true;
397 }
398
399 // Apply cliff edge specific smoothing
401 CliffEdgeExtCRS = LSmoothCoastRunningMean(&CliffEdgeExtCRS);
403 CliffEdgeExtCRS = LSmoothCoastSavitzkyGolay(&CliffEdgeExtCRS, 0, 0);
404
405 // Store the smoothed cliff edge in external CRS
406 m_VCliffEdge.push_back(CliffEdgeExtCRS);
407 }
408 }
409}
410
411/*===============================================================================================================================
412
413Validates cliff edges to ensure they represent cliff toes, truncating edges that
414trace cliff tops
415
416===============================================================================================================================*/
418 vector<CGeomLine> ValidatedCliffEdges;
419
420 // Process each traced cliff edge
421 for (size_t nEdge = 0; nEdge < m_VCliffEdge.size(); nEdge++) {
422 CGeomLine &CliffEdge = m_VCliffEdge[nEdge];
423
424 // Try validating in forward direction first
425 CGeomLine ForwardValidated = nValidateCliffToeDirection(CliffEdge, false);
426
427 // If we got a very short result (broke early), try reverse direction
428 CGeomLine ReverseValidated;
429 if (ForwardValidated.nGetSize() < CliffEdge.nGetSize() * 0.2) {
430 ReverseValidated = nValidateCliffToeDirection(CliffEdge, true);
431 }
432
433 // Use whichever result is longer
434 CGeomLine BestValidated;
435 if (ReverseValidated.nGetSize() > ForwardValidated.nGetSize()) {
436 BestValidated = ReverseValidated;
437 } else {
438 BestValidated = ForwardValidated;
439 }
440
441 // Only keep edges that have a reasonable length after validation
442 if (BestValidated.nGetSize() > 2) {
443 ValidatedCliffEdges.push_back(BestValidated);
444 }
445 }
446
447 // Replace the original cliff edges with the validated ones
448 m_VCliffEdge = ValidatedCliffEdges;
449}
450
452 CGeomLine ValidatedEdge;
453
454 int nConsecutiveFailures = 0;
455 const int nMaxConsecutiveFailures = 2;
456
457 int nSize = CliffEdge.nGetSize();
458
459 // Check each point along the cliff edge
460 for (int i = 0; i < nSize - 1; i++) {
461 // Determine which point to process based on direction
462 int nPoint = bReverse ? (nSize - 1 - i) : i;
463 int nNextPoint = bReverse ? (nSize - 2 - i) : (i + 1);
464
465 // Skip if we've gone beyond bounds
466 if (nNextPoint < 0 || nNextPoint >= nSize)
467 continue;
468
469 // Get current and next point in grid coordinates
470 int nX =
471 static_cast<int>((CliffEdge.dGetXAt(nPoint) - m_dGeoTransform[0]) /
472 m_dGeoTransform[1]);
473 int nY =
474 static_cast<int>((CliffEdge.dGetYAt(nPoint) - m_dGeoTransform[3]) /
475 m_dGeoTransform[5]);
476
477 int nNextX = static_cast<int>(
478 (CliffEdge.dGetXAt(nNextPoint) - m_dGeoTransform[0]) /
479 m_dGeoTransform[1]);
480 int nNextY = static_cast<int>(
481 (CliffEdge.dGetYAt(nNextPoint) - m_dGeoTransform[3]) /
482 m_dGeoTransform[5]);
483
484 // Ensure coordinates are within grid bounds
485 nX = std::max(0, std::min(m_nXGridSize - 1, nX));
486 nY = std::max(0, std::min(m_nYGridSize - 1, nY));
487 nNextX = std::max(0, std::min(m_nXGridSize - 1, nNextX));
488 nNextY = std::max(0, std::min(m_nYGridSize - 1, nNextY));
489
490 // Calculate direction of travel
491 int nDirX = nNextX - nX;
492 int nDirY = nNextY - nY;
493
494 // Get perpendicular directions (90 degrees to travel direction)
495 int nLeftX = nX - nDirY; // Rotate direction 90 degrees counter-clockwise
496 int nLeftY = nY + nDirX;
497 int nRightX = nX + nDirY; // Rotate direction 90 degrees clockwise
498 int nRightY = nY - nDirX;
499
500 bool bIsValidToe = true;
501
502 // Check if perpendicular cells are within bounds
503 if (bIsWithinValidGrid(nLeftX, nLeftY) &&
504 bIsWithinValidGrid(nRightX, nRightY)) {
505 bool bLeftIsCliff = m_pRasterGrid->m_Cell[nLeftX][nLeftY].bIsCliff();
506 bool bRightIsCliff = m_pRasterGrid->m_Cell[nRightX][nRightY].bIsCliff();
507
508 // One should be cliff and one should be not cliff for a valid cliff
509 // edge
510 if (bLeftIsCliff != bRightIsCliff) {
511 // Get the elevation of these two adjacent cells
512 double dLeftElev =
513 m_pRasterGrid->m_Cell[nLeftX][nLeftY].dGetSedimentTopElev();
514 double dRightElev =
515 m_pRasterGrid->m_Cell[nRightX][nRightY].dGetSedimentTopElev();
516
517 // Determine which is the cliff side and which is the non-cliff side
518 double dCliffElev, dNonCliffElev;
519 if (bLeftIsCliff) {
520 dCliffElev = dLeftElev;
521 dNonCliffElev = dRightElev;
522 } else {
523 dCliffElev = dRightElev;
524 dNonCliffElev = dLeftElev;
525 }
526
527 // If the non-cliff cell is higher than the cliff cell, this is not
528 // the toe
529 if (dNonCliffElev > dCliffElev) {
530 bIsValidToe = false;
531 }
532 }
533 }
534
535 if (bIsValidToe) {
536 // Reset consecutive failure counter
537 nConsecutiveFailures = 0;
538 // Add this point to the validated edge
539 ValidatedEdge.Append(CliffEdge.dGetXAt(nPoint),
540 CliffEdge.dGetYAt(nPoint));
541 } else {
542 // Increment consecutive failure counter
543 nConsecutiveFailures++;
544
545 // If we haven't hit the threshold yet, still add the point
546 if (nConsecutiveFailures < nMaxConsecutiveFailures) {
547 ValidatedEdge.Append(CliffEdge.dGetXAt(nPoint),
548 CliffEdge.dGetYAt(nPoint));
549 } else {
550 // Too many consecutive failures - truncate here
551 break;
552 }
553 }
554 }
555
556 return ValidatedEdge;
557}
558
559/*===============================================================================================================================
560
561 Locates and traces the cliff toe
562
563===============================================================================================================================*/
565 // First step: calculate slope at every cell throughout the grid
571
572 return RTN_OK;
573}
void Append(CGeom2DPoint const *)
Appends a point to this 2D shape.
Definition 2d_shape.cpp:67
int nGetSize(void) const
Definition 2d_shape.cpp:56
Geometry class used to represent 2D point objects with integer coordinates.
Definition 2di_point.h:29
Geometry class used to represent 2D vector line objects.
Definition line.h:31
double dGetYAt(int const)
Returns the Y value at a given place in the line.
Definition line.cpp:67
double dGetXAt(int const)
Returns the X value at a given place in the line.
Definition line.cpp:61
CGeomLine LSmoothCoastRunningMean(CGeomLine *) const
Does running-mean smoothing of a CGeomLine coastline vector (is in external CRS coordinates)
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.
void nCalcSlopeAtAllCells(void)
int m_nYGridSize
The size of the grid in the y direction.
Definition simulation.h:465
int nLocateCliffToe(void)
double m_dGeoTransform[6]
Definition simulation.h:731
vector< CGeomLine > m_VCliffEdge
The traced cliff edge lines (in external CRS)
void nTraceSeawardCliffEdge(void)
int m_nCliffEdgeSmooth
Which method to use for cliff edge smoothing.
Definition simulation.h:481
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
void nLocateCliffCell(void)
CGeomLine nValidateCliffToeDirection(CGeomLine &CliffEdge, bool bReverse)
void nRemoveSmallCliffIslands(int const)
CGeomLine LSmoothCoastSavitzkyGolay(CGeomLine *, int const, int const) const
Does smoothing of a CGeomLine coastline vector (is in external CRS coordinates) using a Savitzky-Gola...
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,...
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_dCliffSlopeLimit
Slope limit for cliff toe detection.
Definition simulation.h:491
double m_dCellSide
Length of a cell side (in external CRS units)
Definition simulation.h:689
void nValidateCliffToeEdges(void)
This file contains global definitions for CoastalME.
int const SMOOTH_SAVITZKY_GOLAY
Definition cme.h:772
int const SMOOTH_RUNNING_MEAN
Definition cme.h:771
int const SOUTH
Definition cme.h:499
int const EAST
Definition cme.h:497
int const RTN_OK
Definition cme.h:692
int const NORTH
Definition cme.h:495
int const WEST
Definition cme.h:501
Contains CGeomRasterGrid definitions.
Contains CSimulation definitions.