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