CoastalME (Coastal Modelling Environment)
Simulates the long-term behaviour of complex coastlines
Loading...
Searching...
No Matches
gis_raster.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 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.
18
19 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.
20
21 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.
22
23===============================================================================================================================*/
24#include <assert.h>
25
26#include <iostream>
27using std::cerr;
28using std::cout;
29using std::endl;
30using std::ios;
31
32#include <fstream>
33using std::ifstream;
34
35#include <sstream>
36using std::stringstream;
37
38#include <string>
39using std::to_string;
40
41#include <cpl_config.h>
42#include <gdal_alg.h>
43#include <gdal_priv.h>
44
45#include "cme.h"
46#include "coast.h"
47#include "raster_grid.h"
48#include "simulation.h"
49
50//===============================================================================================================================
52//===============================================================================================================================
54 // Configure GDAL for optimal performance
55 // Enable GDAL threading - use all available CPU cores
56#ifdef _OPENMP
57 CPLSetConfigOption("GDAL_NUM_THREADS", "ALL_CPUS");
58#else
59 CPLSetConfigOption("GDAL_NUM_THREADS", "2"); // Fallback for non-OpenMP builds
60#endif
61
62 // Optimize GDAL memory usage and caching
63 CPLSetConfigOption("GDAL_CACHEMAX", "1024"); // 1GB cache for large grids
64 CPLSetConfigOption("GDAL_DISABLE_READDIR_ON_OPEN", "TRUE"); // Faster file access
65 CPLSetConfigOption("VSI_CACHE", "TRUE"); // Enable virtual file system cache
66 CPLSetConfigOption("VSI_CACHE_SIZE", "256000000"); // 256MB VSI cache
67
68 // Optimize grid creation performance
69 CPLSetConfigOption("GDAL_GRID_MAX_POINTS_PER_QUADTREE_LEAF", "512"); // Faster spatial indexing
70
71 // Disable GDAL warnings for cleaner output (optional)
72 // CPLSetConfigOption("CPL_LOG", "/dev/null");
73
74 LogStream << "GDAL performance optimizations enabled" << endl;
75}
76
77//===============================================================================================================================
79//===============================================================================================================================
81 // Initialize GDAL performance settings (only needs to be done once)
82 static bool bGDALInitialized = false;
83
84 if (!bGDALInitialized) {
86 bGDALInitialized = true;
87 }
88
89 // Use GDAL to create a dataset object, which then opens the DEM file
90 GDALDataset *pGDALDataset = static_cast<GDALDataset *>(GDALOpen(m_strInitialBasementDEMFile.c_str(), GA_ReadOnly));
91
92 if (NULL == pGDALDataset) {
93 // Can't open file (note will already have sent GDAL error message to stdout)
94 cerr << ERR << "cannot open " << m_strInitialBasementDEMFile << " for input: " << CPLGetLastErrorMsg() << endl;
95 return RTN_ERR_DEMFILE;
96 }
97
98 // Opened OK, so get GDAL basement DEM dataset information
99 m_strGDALBasementDEMDriverCode = pGDALDataset->GetDriver()->GetDescription();
100 m_strGDALBasementDEMDriverDesc = pGDALDataset->GetDriver()->GetMetadataItem(GDAL_DMD_LONGNAME);
101 m_strGDALBasementDEMProjection = pGDALDataset->GetProjectionRef();
102
103 // If we have reference units, then check that they are in metres
104 if (!m_strGDALBasementDEMProjection.empty()) {
106
107 if ((strTmp.find("meter") == string::npos) && (strTmp.find("metre") == string::npos)) {
108 // error: x-y values must be in metres
109 cerr << ERR << "GIS file x-y values (" << m_strGDALBasementDEMProjection << ") in " << m_strInitialBasementDEMFile << " must be in metres" << endl;
110 return RTN_ERR_DEMFILE;
111 }
112 }
113
114 // Now get dataset size, and do some rudimentary checks
115 m_nXGridSize = pGDALDataset->GetRasterXSize();
116
117 if (m_nXGridSize == 0) {
118 // Error: silly number of columns specified
119 cerr << ERR << "invalid number of columns (" << m_nXGridSize << ") in " << m_strInitialBasementDEMFile << endl;
120 return RTN_ERR_DEMFILE;
121 }
122
123 m_nYGridSize = pGDALDataset->GetRasterYSize();
124
125 if (m_nYGridSize == 0) {
126 // Error: silly number of rows specified
127 cerr << ERR << "invalid number of rows (" << m_nYGridSize << ") in " << m_strInitialBasementDEMFile << endl;
128 return RTN_ERR_DEMFILE;
129 }
130
131 // Get geotransformation info (see http://www.gdal.org/classGDALDataset.html)
132 if (CE_Failure == pGDALDataset->GetGeoTransform(m_dGeoTransform)) {
133 // Can't get geotransformation (note will already have sent GDAL error message to stdout)
134 cerr << ERR << CPLGetLastErrorMsg() << " in " << m_strInitialBasementDEMFile << endl;
135 return RTN_ERR_DEMFILE;
136 }
137
138 // CoastalME can only handle rasters that are oriented N-S and W-E. (If you need to work with a raster that is oriented differently, then you must rotate it before running CoastalME). So here we check whether row rotation (m_dGeoTransform[2]) and column rotation (m_dGeoTransform[4]) are both zero. See https://gdal.org/tutorials/geotransforms_tut.html
139 if ((!bFPIsEqual(m_dGeoTransform[2], 0.0, TOLERANCE)) || (!bFPIsEqual(m_dGeoTransform[4], 0.0, TOLERANCE))) {
140 // Error: not oriented NS and W-E
141 cerr << ERR << m_strInitialBasementDEMFile << " is not oriented N-S and W-E. Row rotation = " << m_dGeoTransform[2] << " and column rotation = " << m_dGeoTransform[4] << endl;
143 }
144
145 // Get the X and Y cell sizes, in external CRS units. Note that while the cell is supposed to be square, it may not be exactly so due to oddities with some GIS calculations
146 double dCellSideX = tAbs(m_dGeoTransform[1]);
147 double dCellSideY = tAbs(m_dGeoTransform[5]);
148
149 // Check that the cell is more or less square
150 if (!bFPIsEqual(dCellSideX, dCellSideY, 1e-2)) {
151 // Error: cell is not square enough
152 cerr << ERR << "cell is not square in " << m_strInitialBasementDEMFile << ", is " << dCellSideX << " x " << dCellSideY << endl;
154 }
155
156 // Calculate the average length of cell side, the cell's diagonal, and the area of a cell (in external CRS units)
157 m_dCellSide = (dCellSideX + dCellSideY) / 2.0;
160
161 // And calculate the inverse values
164
165 // Save some values in external CRS
170
171 // And calc the grid area in external CRS units
173
174 // Now get GDAL raster band information
175 GDALRasterBand *pGDALBand = pGDALDataset->GetRasterBand(1);
176 int nBlockXSize = 0, nBlockYSize = 0;
177 pGDALBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
178 m_strGDALBasementDEMDataType = GDALGetDataTypeName(pGDALBand->GetRasterDataType());
179
180 // If we have value units, then check them
181 string strUnits = pGDALBand->GetUnitType();
182
183 if ((!strUnits.empty()) && (strUnits.find("m") == string::npos)) {
184 // Error: value units must be m
185 cerr << ERR << "DEM vertical units are (" << strUnits << " ) in " << m_strInitialBasementDEMFile << ", should be 'm'" << endl;
186 return RTN_ERR_DEMFILE;
187 }
188
189 // If present, get the missing value (NODATA) setting
190 CPLPushErrorHandler(CPLQuietErrorHandler); // Needed to get next line to fail silently, if it fails
191 double dMissingValue = pGDALBand->GetNoDataValue(); // Will fail for some formats
192 CPLPopErrorHandler();
193
194 if (!bFPIsEqual(dMissingValue, m_dMissingValue, TOLERANCE)) {
195 cerr << " " << NOTE << "NODATA value in " << m_strInitialBasementDEMFile << " is " << dMissingValue << "\n instead using CoastalME's default floating-point NODATA value " << m_dMissingValue << endl;
196 }
197
198 // Next allocate memory for a 2D array of raster cell objects: tell the user what is happening
200 int nRet = m_pRasterGrid->nCreateGrid();
201
202 if (nRet != RTN_OK)
203 return nRet;
204
205 // Allocate memory for a 1D floating-point array, to hold the scan line for GDAL
206 double *pdScanline = new double[m_nXGridSize];
207
208 if (NULL == pdScanline) {
209 // Error, can't allocate memory
210 cerr << ERR << "cannot allocate memory for " << m_nXGridSize << " x 1D array" << endl;
211 return (RTN_ERR_MEMALLOC);
212 }
213
214 // Now read in the data
215 for (int j = 0; j < m_nYGridSize; j++) {
216 // Read scanline
217 if (CE_Failure == pGDALBand->RasterIO(GF_Read, 0, j, m_nXGridSize, 1, pdScanline, m_nXGridSize, 1, GDT_Float64, 0, 0, NULL)) {
218 // Error while reading scanline
219 cerr << ERR << CPLGetLastErrorMsg() << " in " << m_strInitialBasementDEMFile << endl;
220 return RTN_ERR_DEMFILE;
221 }
222
223 // All OK, so read scanline into cell elevations (including any missing values)
224 for (int i = 0; i < m_nXGridSize; i++) {
225 double dTmp = pdScanline[i];
226
227 if ((isnan(dTmp)) || (bFPIsEqual(dTmp, m_dGISMissingValue, TOLERANCE)))
228 dTmp = m_dMissingValue;
229
230 m_pRasterGrid->m_Cell[i][j].SetBasementElev(dTmp);
231 }
232 }
233
234 // Finished, so get rid of dataset object
235 GDALClose(pGDALDataset);
236
237 // Get rid of memory allocated to this array
238 delete[] pdScanline;
239
240 return RTN_OK;
241}
242
243//===============================================================================================================================
245//===============================================================================================================================
247 // The bounding box must touch the edge of the grid at least once on each side of the grid, so store these points. Search in a clockwise direction around the edge of the grid
248 vector<CGeom2DIPoint> VPtiBoundingBoxCorner;
249
250 // Start with the top (north) edge
251 bool bFound = false;
252
253 for (int nX = 0; nX < m_nXGridSize; nX++) {
254 if (bFound)
255 break;
256
257 for (int nY = 0; nY < m_nYGridSize; nY++) {
258 if (!m_pRasterGrid->m_Cell[nX][nY].bBasementElevIsMissingValue()) {
259 CGeom2DIPoint PtiTmp(nX, nY);
260 VPtiBoundingBoxCorner.push_back(PtiTmp);
261 bFound = true;
262 break;
263 }
264 }
265 }
266
267 if (!bFound) {
269 LogStream << m_ulIter << ": north (top) edge of bounding box not found" << endl;
270
272 }
273
274 // Do the same for the right (east) edge
275 bFound = false;
276
277 for (int nY = 0; nY < m_nYGridSize; nY++) {
278 if (bFound)
279 break;
280
281 for (int nX = m_nXGridSize - 1; nX >= 0; nX--) {
282 if (!m_pRasterGrid->m_Cell[nX][nY].bBasementElevIsMissingValue()) {
283 CGeom2DIPoint PtiTmp(nX, nY);
284 VPtiBoundingBoxCorner.push_back(PtiTmp);
285 bFound = true;
286 break;
287 }
288 }
289 }
290
291 if (!bFound) {
293 LogStream << m_ulIter << ": east (right) edge of bounding box not found" << endl;
294
296 }
297
298 // Do the same for the south (bottom) edge
299 bFound = false;
300
301 for (int nX = m_nXGridSize - 1; nX >= 0; nX--) {
302 if (bFound)
303 break;
304
305 for (int nY = m_nYGridSize - 1; nY >= 0; nY--) {
306 if (!m_pRasterGrid->m_Cell[nX][nY].bBasementElevIsMissingValue()) {
307 CGeom2DIPoint PtiTmp(nX, nY);
308 VPtiBoundingBoxCorner.push_back(PtiTmp);
309 bFound = true;
310 break;
311 }
312 }
313 }
314
315 if (!bFound) {
317 LogStream << m_ulIter << ": south (bottom) edge of bounding box not found" << endl;
318
320 }
321
322 // And finally repeat for the west (left) edge
323 bFound = false;
324
325 for (int nY = m_nYGridSize - 1; nY >= 0; nY--) {
326 if (bFound)
327 break;
328
329 for (int nX = 0; nX < m_nXGridSize; nX++) {
330 if (!m_pRasterGrid->m_Cell[nX][nY].bBasementElevIsMissingValue()) {
331 CGeom2DIPoint PtiTmp(nX, nY);
332 VPtiBoundingBoxCorner.push_back(PtiTmp);
333 bFound = true;
334 break;
335 }
336 }
337 }
338
339 if (!bFound) {
341 LogStream << m_ulIter << ": west (left) edge of bounding box not found" << endl;
342
344 }
345
346 // OK, so we have a point on each side of the grid, so start at this point and find the edges of the bounding box. Go round in a clockwise direction: top (north) edge first
347 for (int nX = VPtiBoundingBoxCorner[0].nGetX(); nX <= VPtiBoundingBoxCorner[1].nGetX(); nX++) {
348 bFound = false;
349
350 for (int nY = VPtiBoundingBoxCorner[0].nGetY(); nY < m_nYGridSize; nY++) {
351 if (m_pRasterGrid->m_Cell[nX][nY].bBasementElevIsMissingValue()) {
353 continue;
354 }
355
356 // Found a bounding box edge cell
357 m_pRasterGrid->m_Cell[nX][nY].SetBoundingBoxEdge(NORTH);
358
359 m_VEdgeCell.push_back(CGeom2DIPoint(nX, nY));
360 m_VEdgeCellEdge.push_back(NORTH);
361
362 bFound = true;
363 break;
364 }
365
366 if (!bFound) {
368 LogStream << m_ulIter << ": could not find a bounding box edge cell for grid column " << nX << endl;
369
371 }
372 }
373
374 // Right (east) edge
375 for (int nY = VPtiBoundingBoxCorner[1].nGetY(); nY <= VPtiBoundingBoxCorner[2].nGetY(); nY++) {
376 bFound = false;
377
378 for (int nX = VPtiBoundingBoxCorner[1].nGetX(); nX >= 0; nX--) {
379 if (m_pRasterGrid->m_Cell[nX][nY].bBasementElevIsMissingValue()) {
381 continue;
382 }
383
384 // Found a bounding box edge cell
385 m_pRasterGrid->m_Cell[nX][nY].SetBoundingBoxEdge(EAST);
386
387 m_VEdgeCell.push_back(CGeom2DIPoint(nX, nY));
388 m_VEdgeCellEdge.push_back(EAST);
389
390 bFound = true;
391 break;
392 }
393
394 if (!bFound) {
396 LogStream << m_ulIter << ": could not find a bounding box edge cell for grid row " << nY << endl;
397
399 }
400 }
401
402 // Bottom (south) edge
403 for (int nX = VPtiBoundingBoxCorner[2].nGetX(); nX >= VPtiBoundingBoxCorner[3].nGetX(); nX--) {
404 bFound = false;
405
406 for (int nY = VPtiBoundingBoxCorner[2].nGetY(); nY >= 0; nY--) {
407 if (m_pRasterGrid->m_Cell[nX][nY].bBasementElevIsMissingValue()) {
409 continue;
410 }
411
412 // Found a bounding box edge cell
413 m_pRasterGrid->m_Cell[nX][nY].SetBoundingBoxEdge(SOUTH);
414
415 m_VEdgeCell.push_back(CGeom2DIPoint(nX, nY));
416 m_VEdgeCellEdge.push_back(SOUTH);
417
418 bFound = true;
419 break;
420 }
421
422 if (!bFound) {
424 LogStream << m_ulIter << ": could not find a bounding box edge cell for grid column " << nX << endl;
425
427 }
428 }
429
430 // Left (west) edge
431 for (int nY = VPtiBoundingBoxCorner[3].nGetY(); nY >= VPtiBoundingBoxCorner[0].nGetY(); nY--) {
432 for (int nX = VPtiBoundingBoxCorner[3].nGetX(); nX < m_nXGridSize - 1; nX++)
433 // for (int nX = VPtiBoundingBoxCorner[3].nGetX(); nX < VPtiBoundingBoxCorner[3].nGetX(); nX++)
434 {
435 if (m_pRasterGrid->m_Cell[nX][nY].bBasementElevIsMissingValue()) {
437 continue;
438 }
439
440 // Found a bounding box edge cell
441 m_pRasterGrid->m_Cell[nX][nY].SetBoundingBoxEdge(WEST);
442
443 m_VEdgeCell.push_back(CGeom2DIPoint(nX, nY));
444 m_VEdgeCellEdge.push_back(WEST);
445
446 bFound = true;
447 break;
448 }
449
450 if (!bFound) {
452 LogStream << m_ulIter << ": could not find a bounding box edge cell for grid row " << nY << endl;
453
455 }
456 }
457
458 return RTN_OK;
459}
460
461//===============================================================================================================================
463//===============================================================================================================================
464int CSimulation::nReadRasterGISFile(int const nDataItem, int const nLayer) {
465 string
466 strGISFile,
467 strDriverCode,
468 strDriverDesc,
469 strProjection,
470 strDataType;
471
472 switch (nDataItem) {
473 case (LANDFORM_RASTER):
474 // Initial Landform Class GIS data
475 strGISFile = m_strInitialLandformFile;
476 break;
477
479 // Intervention class
480 strGISFile = m_strInterventionClassFile;
481 break;
482
484 // Intervention height
485 strGISFile = m_strInterventionHeightFile;
486 break;
487
488 case (SUSP_SED_RASTER):
489 // Initial Suspended Sediment GIS data
490 strGISFile = m_strInitialSuspSedimentFile;
491 break;
492
493 case (FINE_UNCONS_RASTER):
494 // Initial Unconsolidated Fine Sediment GIS data
495 strGISFile = m_VstrInitialFineUnconsSedimentFile[nLayer];
496 break;
497
498 case (SAND_UNCONS_RASTER):
499 // Initial Unconsolidated Sand Sediment GIS data
500 strGISFile = m_VstrInitialSandUnconsSedimentFile[nLayer];
501 break;
502
504 // Initial Unconsolidated Coarse Sediment GIS data
505 strGISFile = m_VstrInitialCoarseUnconsSedimentFile[nLayer];
506 break;
507
508 case (FINE_CONS_RASTER):
509 // Initial Consolidated Fine Sediment GIS data
510 strGISFile = m_VstrInitialFineConsSedimentFile[nLayer];
511 break;
512
513 case (SAND_CONS_RASTER):
514 // Initial Consolidated Sand Sediment GIS data
515 strGISFile = m_VstrInitialSandConsSedimentFile[nLayer];
516 break;
517
518 case (COARSE_CONS_RASTER):
519 // Initial Consolidated Coarse Sediment GIS data
520 strGISFile = m_VstrInitialCoarseConsSedimentFile[nLayer];
521 break;
522 }
523
524 // Do we have a filename for this data item? If we don't then just return
525 if (!strGISFile.empty()) {
526 // We do have a filename, so use GDAL to create a dataset object, which then opens the GIS file
527 GDALDataset *pGDALDataset = static_cast<GDALDataset *>(GDALOpen(strGISFile.c_str(), GA_ReadOnly));
528
529 if (NULL == pGDALDataset) {
530 // Can't open file (note will already have sent GDAL error message to stdout)
531 cerr << ERR << "cannot open " << strGISFile << " for input: " << CPLGetLastErrorMsg() << endl;
533 }
534
535 // Opened OK, so get dataset information
536 strDriverCode = pGDALDataset->GetDriver()->GetDescription();
537 strDriverDesc = pGDALDataset->GetDriver()->GetMetadataItem(GDAL_DMD_LONGNAME);
538 strProjection = pGDALDataset->GetProjectionRef();
539
540 // Get geotransformation info
541 double dGeoTransform[6];
542
543 if (CE_Failure == pGDALDataset->GetGeoTransform(dGeoTransform)) {
544 // Can't get geotransformation (note will already have sent GDAL error message to stdout)
545 cerr << ERR << CPLGetLastErrorMsg() << " in " << strGISFile << endl;
547 }
548
549 // Now get dataset size, and do some checks
550 int nTmpXSize = pGDALDataset->GetRasterXSize();
551
552 if (nTmpXSize != m_nXGridSize) {
553 // Error: incorrect number of columns specified
554 cerr << ERR << "different number of columns in " << strGISFile << " (" << nTmpXSize << ") and " << m_strInitialBasementDEMFile << "(" << m_nXGridSize << ")" << endl;
556 }
557
558 int nTmpYSize = pGDALDataset->GetRasterYSize();
559
560 if (nTmpYSize != m_nYGridSize) {
561 // Error: incorrect number of rows specified
562 cerr << ERR << "different number of rows in " << strGISFile << " (" << nTmpYSize << ") and " << m_strInitialBasementDEMFile << " (" << m_nYGridSize << ")" << endl;
564 }
565
566 double dTmp = m_dGeoTransform[0] - (m_dGeoTransform[1] / 2);
567
569 // Error: different min x from DEM file
570 cerr << ERR << "different min x values in " << strGISFile << " (" << dTmp << ") and " << m_strInitialBasementDEMFile << " (" << m_dNorthWestXExtCRS << ")" << endl;
572 }
573
574 dTmp = m_dGeoTransform[3] - (m_dGeoTransform[5] / 2);
575
577 // Error: different min x from DEM file
578 cerr << ERR << "different min y values in " << strGISFile << " (" << dTmp << ") and " << m_strInitialBasementDEMFile << " (" << m_dNorthWestYExtCRS << ")" << endl;
580 }
581
582 double dTmpResX = tAbs(dGeoTransform[1]);
583
584 if (!bFPIsEqual(dTmpResX, m_dCellSide, 1e-2)) {
585 // Error: different cell size in X direction: note that due to rounding errors in some GIS packages, must expect some discrepancies
586 cerr << ERR << "cell size in X direction (" << dTmpResX << ") in " << strGISFile << " differs from cell size in of basement DEM (" << m_dCellSide << ")" << endl;
588 }
589
590 double dTmpResY = tAbs(dGeoTransform[5]);
591
592 if (!bFPIsEqual(dTmpResY, m_dCellSide, 1e-2)) {
593 // Error: different cell size in Y direction: note that due to rounding errors in some GIS packages, must expect some discrepancies
594 cerr << ERR << "cell size in Y direction (" << dTmpResY << ") in " << strGISFile << " differs from cell size of basement DEM (" << m_dCellSide << ")" << endl;
596 }
597
598 // Now get GDAL raster band information
599 GDALRasterBand *pGDALBand = pGDALDataset->GetRasterBand(1); // TODO 028 Give a message if there are several bands
600 int nBlockXSize = 0, nBlockYSize = 0;
601 pGDALBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
602 strDataType = GDALGetDataTypeName(pGDALBand->GetRasterDataType());
603
604 switch (nDataItem) {
605 case (LANDFORM_RASTER):
606 // Initial Landform Class GIS data
607 m_strGDALLDriverCode = strDriverCode;
608 m_strGDALLDriverDesc = strDriverDesc;
609 m_strGDALLProjection = strProjection;
610 m_strGDALLDataType = strDataType;
611 break;
612
614 // Intervention class
615 m_strGDALICDriverCode = strDriverCode;
616 m_strGDALICDriverDesc = strDriverDesc;
617 m_strGDALICProjection = strProjection;
618 m_strGDALICDataType = strDataType;
619 break;
620
622 // Intervention height
623 m_strGDALIHDriverCode = strDriverCode;
624 m_strGDALIHDriverDesc = strDriverDesc;
625 m_strGDALIHProjection = strProjection;
626 m_strGDALIHDataType = strDataType;
627 break;
628
629 case (SUSP_SED_RASTER):
630 // Initial Suspended Sediment GIS data
631 m_strGDALISSDriverCode = strDriverCode;
632 m_strGDALISSDriverDesc = strDriverDesc;
633 m_strGDALISSProjection = strProjection;
634 m_strGDALISSDataType = strDataType;
635 break;
636
637 case (FINE_UNCONS_RASTER):
638 // Initial Unconsolidated Fine Sediment GIS data
639 m_VstrGDALIUFDriverCode[nLayer] = strDriverCode;
640 m_VstrGDALIUFDriverDesc[nLayer] = strDriverDesc;
641 m_VstrGDALIUFProjection[nLayer] = strProjection;
642 m_VstrGDALIUFDataType[nLayer] = strDataType;
643 break;
644
645 case (SAND_UNCONS_RASTER):
646 // Initial Unconsolidated Sand Sediment GIS data
647 m_VstrGDALIUSDriverCode[nLayer] = strDriverCode;
648 m_VstrGDALIUSDriverDesc[nLayer] = strDriverDesc;
649 m_VstrGDALIUSProjection[nLayer] = strProjection;
650 m_VstrGDALIUSDataType[nLayer] = strDataType;
651 break;
652
654 // Initial Unconsolidated Coarse Sediment GIS data
655 m_VstrGDALIUCDriverCode[nLayer] = strDriverCode;
656 m_VstrGDALIUCDriverDesc[nLayer] = strDriverDesc;
657 m_VstrGDALIUCProjection[nLayer] = strProjection;
658 m_VstrGDALIUCDataType[nLayer] = strDataType;
659 break;
660
661 case (FINE_CONS_RASTER):
662 // Initial Consolidated Fine Sediment GIS data
663 m_VstrGDALICFDriverCode[nLayer] = strDriverCode;
664 m_VstrGDALICFDriverDesc[nLayer] = strDriverDesc;
665 m_VstrGDALICFProjection[nLayer] = strProjection;
666 m_VstrGDALICFDataType[nLayer] = strDataType;
667 break;
668
669 case (SAND_CONS_RASTER):
670 // Initial Consolidated Sand Sediment GIS data
671 m_VstrGDALICSDriverCode[nLayer] = strDriverCode;
672 m_VstrGDALICSDriverDesc[nLayer] = strDriverDesc;
673 m_VstrGDALICSProjection[nLayer] = strProjection;
674 m_VstrGDALICSDataType[nLayer] = strDataType;
675 break;
676
677 case (COARSE_CONS_RASTER):
678 // Initial Consolidated Coarse Sediment GIS data
679 m_VstrGDALICCDriverCode[nLayer] = strDriverCode;
680 m_VstrGDALICCDriverDesc[nLayer] = strDriverDesc;
681 m_VstrGDALICCProjection[nLayer] = strProjection;
682 m_VstrGDALICCDataType[nLayer] = strDataType;
683 break;
684 }
685
686 // If present, get the missing value setting
687 string strTmp = strToLower(&strDataType);
688
689 if (strTmp.find("int") != string::npos) {
690 // This is an integer layer
691 CPLPushErrorHandler(CPLQuietErrorHandler); // Needed to get next line to fail silently, if it fails
692 m_nGISMissingValue = static_cast<int>(pGDALBand->GetNoDataValue()); // Note will fail for some formats
693 CPLPopErrorHandler();
694
696 cerr << " " << NOTE << "NODATA value in " << strGISFile << " is " << m_nGISMissingValue << "\n instead using CoatalME's default integer NODATA value " << m_nMissingValue << endl;
697 }
698 }
699
700 else {
701 // This is a floating point layer
702 CPLPushErrorHandler(CPLQuietErrorHandler); // Needed to get next line to fail silently, if it fails
703 m_dGISMissingValue = pGDALBand->GetNoDataValue(); // Note will fail for some formats
704 CPLPopErrorHandler();
705
707 cerr << " " << NOTE << "NODATA value in " << strGISFile << " is " << m_dGISMissingValue << "\n instead using CoastalME's default floating-point NODATA value " << m_dMissingValue << endl;
708 }
709 }
710
711 // Allocate memory for a 1D array, to hold the scan line for GDAL
712 double *pdScanline = new double[m_nXGridSize];
713
714 if (NULL == pdScanline) {
715 // Error, can't allocate memory
716 cerr << ERR << "cannot allocate memory for " << m_nXGridSize << " x 1D array" << endl;
717 return (RTN_ERR_MEMALLOC);
718 }
719
720 // Now read in the data
721 int nMissing = 0;
722
723 for (int nY = 0; nY < m_nYGridSize; nY++) {
724 // Read scanline
725 if (CE_Failure == pGDALBand->RasterIO(GF_Read, 0, nY, m_nXGridSize, 1, pdScanline, m_nXGridSize, 1, GDT_Float64, 0, 0, NULL)) {
726 // Error while reading scanline
727 cerr << ERR << CPLGetLastErrorMsg() << " in " << strGISFile << endl;
729 }
730
731 // All OK, so read scanline into cells (including any missing values)
732 for (int nX = 0; nX < m_nXGridSize; nX++) {
733 int nTmp;
734
735 switch (nDataItem) {
736 case (LANDFORM_RASTER):
737 // Initial Landform Class GIS data, is integer TODO 030 Do we also need a landform sub-category input?
738 nTmp = static_cast<int>(pdScanline[nX]);
739
740 if ((isnan(nTmp)) || (nTmp == m_nGISMissingValue)) {
741 nTmp = m_nMissingValue;
742 nMissing++;
743 }
744
745 m_pRasterGrid->m_Cell[nX][nY].pGetLandform()->SetLFCategory(nTmp);
746 break;
747
749 // Intervention class, is integer
750 nTmp = static_cast<int>(pdScanline[nX]);
751
752 if ((isnan(nTmp)) || (nTmp == m_nGISMissingValue)) {
753 nTmp = m_nMissingValue;
754 nMissing++;
755 }
756
757 m_pRasterGrid->m_Cell[nX][nY].SetInterventionClass(nTmp);
758 break;
759
761 // Intervention height
762 dTmp = pdScanline[nX];
763
764 if ((isnan(dTmp)) || (bFPIsEqual(dTmp, m_dGISMissingValue, TOLERANCE))) {
765 dTmp = m_dMissingValue;
766 nMissing++;
767 }
768
769 m_pRasterGrid->m_Cell[nX][nY].SetInterventionHeight(dTmp);
770 break;
771
772 case (SUSP_SED_RASTER):
773 // Initial Suspended Sediment GIS data
774 dTmp = pdScanline[nX];
775
776 if ((isnan(dTmp)) || (bFPIsEqual(dTmp, m_dGISMissingValue, TOLERANCE))) {
777 dTmp = m_dMissingValue;
778 nMissing++;
779 }
780
781 m_pRasterGrid->m_Cell[nX][nY].SetSuspendedSediment(dTmp);
782 break;
783
784 case (FINE_UNCONS_RASTER):
785 // Initial Unconsolidated Fine Sediment GIS data
786 dTmp = pdScanline[nX];
787
788 if ((isnan(dTmp)) || (bFPIsEqual(dTmp, m_dGISMissingValue, TOLERANCE))) {
789 dTmp = m_dMissingValue;
790 nMissing++;
791 }
792
793 m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nLayer)->pGetUnconsolidatedSediment()->SetFineDepth(dTmp);
794 break;
795
796 case (SAND_UNCONS_RASTER):
797 // Initial Unconsolidated Sand Sediment GIS data
798 dTmp = pdScanline[nX];
799
800 if ((isnan(dTmp)) || (bFPIsEqual(dTmp, m_dGISMissingValue, TOLERANCE))) {
801 dTmp = m_dMissingValue;
802 nMissing++;
803 }
804
805 m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nLayer)->pGetUnconsolidatedSediment()->SetSandDepth(dTmp);
806 break;
807
809 // Initial Unconsolidated Coarse Sediment GIS data
810 dTmp = pdScanline[nX];
811
812 if ((isnan(dTmp)) || (bFPIsEqual(dTmp, m_dGISMissingValue, TOLERANCE))) {
813 dTmp = m_dMissingValue;
814 nMissing++;
815 }
816
817 m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nLayer)->pGetUnconsolidatedSediment()->SetCoarseDepth(dTmp);
818 break;
819
820 case (FINE_CONS_RASTER):
821 // Initial Consolidated Fine Sediment GIS data
822 dTmp = pdScanline[nX];
823
824 if ((isnan(dTmp)) || (bFPIsEqual(dTmp, m_dGISMissingValue, TOLERANCE))) {
825 dTmp = m_dMissingValue;
826 nMissing++;
827 }
828
829 m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nLayer)->pGetConsolidatedSediment()->SetFineDepth(dTmp);
830 break;
831
832 case (SAND_CONS_RASTER):
833 // Initial Consolidated Sand Sediment GIS data
834 dTmp = pdScanline[nX];
835
836 if ((isnan(dTmp)) || (bFPIsEqual(dTmp, m_dGISMissingValue, TOLERANCE))) {
837 dTmp = m_dMissingValue;
838 nMissing++;
839 }
840
841 m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nLayer)->pGetConsolidatedSediment()->SetSandDepth(dTmp);
842 break;
843
844 case (COARSE_CONS_RASTER):
845 // Initial Consolidated Coarse Sediment GIS data
846 dTmp = pdScanline[nX];
847
848 if ((isnan(dTmp)) || (bFPIsEqual(dTmp, m_dGISMissingValue, TOLERANCE))) {
849 dTmp = m_dMissingValue;
850 nMissing++;
851 }
852
853 m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nLayer)->pGetConsolidatedSediment()->SetCoarseDepth(dTmp);
854 break;
855 }
856 }
857 }
858
859 // Finished, so get rid of dataset object
860 GDALClose(pGDALDataset);
861
862 // Get rid of memory allocated to this array
863 delete[] pdScanline;
864
865 if (nMissing > 0) {
866 cerr << WARN << nMissing << " missing values in " << strGISFile << endl;
867 LogStream << WARN << nMissing << " missing values in " << strGISFile << endl;
868 }
869 }
870
871 return RTN_OK;
872}
873
874//===============================================================================================================================
876//===============================================================================================================================
877bool CSimulation::bWriteRasterGISFile(int const nDataItem, string const *strPlotTitle, int const nLayer, double const dElev) {
878 bool bIsInteger = false;
879
880 // Begin constructing the file name for this save
881 string
882 strFilePathName(m_strOutPath),
883 strLayer = "_layer_";
884
885 stringstream ststrTmp;
886
887 strLayer.append(to_string(nLayer + 1));
888
889 switch (nDataItem) {
891 strFilePathName.append(RASTER_BASEMENT_ELEVATION_NAME);
892 break;
893
895 strFilePathName.append(RASTER_SEDIMENT_TOP_NAME);
896 break;
897
899 strFilePathName.append(RASTER_TOP_NAME);
900 break;
901
903 strFilePathName.append(RASTER_LOCAL_SLOPE_NAME);
904 break;
905
906 case (RASTER_PLOT_SLOPE):
907 strFilePathName.append(RASTER_SLOPE_NAME);
908 break;
909
910 case (RASTER_PLOT_CLIFF):
911 strFilePathName.append(RASTER_CLIFF_NAME);
912 break;
913
915 strFilePathName.append(RASTER_SEA_DEPTH_NAME);
916 break;
917
919 strFilePathName.append(RASTER_AVG_SEA_DEPTH_NAME);
920 break;
921
923 strFilePathName.append(RASTER_WAVE_HEIGHT_NAME);
924 break;
925
927 strFilePathName.append(RASTER_AVG_WAVE_HEIGHT_NAME);
928 break;
929
931 strFilePathName.append(RASTER_WAVE_ORIENTATION_NAME);
932 break;
933
935 strFilePathName.append(RASTER_AVG_WAVE_ORIENTATION_NAME);
936 break;
937
939 strFilePathName.append(RASTER_BEACH_PROTECTION_NAME);
940 break;
941
943 strFilePathName.append(RASTER_POTENTIAL_PLATFORM_EROSION_NAME);
944 break;
945
947 strFilePathName.append(RASTER_ACTUAL_PLATFORM_EROSION_NAME);
948 break;
949
951 strFilePathName.append(RASTER_TOTAL_POTENTIAL_PLATFORM_EROSION_NAME);
952 break;
953
955 strFilePathName.append(RASTER_TOTAL_ACTUAL_PLATFORM_EROSION_NAME);
956 break;
957
959 strFilePathName.append(RASTER_POTENTIAL_BEACH_EROSION_NAME);
960 break;
961
963 strFilePathName.append(RASTER_ACTUAL_BEACH_EROSION_NAME);
964 break;
965
967 strFilePathName.append(RASTER_TOTAL_POTENTIAL_BEACH_EROSION_NAME);
968 break;
969
971 strFilePathName.append(RASTER_TOTAL_ACTUAL_BEACH_EROSION_NAME);
972 break;
973
975 strFilePathName.append(RASTER_BEACH_DEPOSITION_NAME);
976 break;
977
979 strFilePathName.append(RASTER_TOTAL_BEACH_DEPOSITION_NAME);
980 break;
981
983 strFilePathName.append(RASTER_SUSP_SED_NAME);
984 break;
985
987 strFilePathName.append(RASTER_AVG_SUSP_SED_NAME);
988 break;
989
991 strFilePathName.append(RASTER_FINE_UNCONS_NAME);
992 strFilePathName.append(strLayer);
993 break;
994
996 strFilePathName.append(RASTER_SAND_UNCONS_NAME);
997 strFilePathName.append(strLayer);
998 break;
999
1001 strFilePathName.append(RASTER_COARSE_UNCONS_NAME);
1002 strFilePathName.append(strLayer);
1003 break;
1004
1006 strFilePathName.append(RASTER_FINE_CONS_NAME);
1007 strFilePathName.append(strLayer);
1008 break;
1009
1011 strFilePathName.append(RASTER_SAND_CONS_NAME);
1012 strFilePathName.append(strLayer);
1013 break;
1014
1016 strFilePathName.append(RASTER_COARSE_CONS_NAME);
1017 strFilePathName.append(strLayer);
1018 break;
1019
1021 strFilePathName.append(RASTER_CLIFF_COLLAPSE_EROSION_FINE_NAME);
1022 break;
1023
1025 strFilePathName.append(RASTER_CLIFF_COLLAPSE_EROSION_SAND_NAME);
1026 break;
1027
1029 strFilePathName.append(RASTER_CLIFF_COLLAPSE_EROSION_COARSE_NAME);
1030 break;
1031
1033 strFilePathName.append(RASTER_TOTAL_CLIFF_COLLAPSE_EROSION_FINE_NAME);
1034 break;
1035
1037 strFilePathName.append(RASTER_TOTAL_CLIFF_COLLAPSE_EROSION_SAND_NAME);
1038 break;
1039
1042 break;
1043
1045 strFilePathName.append(RASTER_CLIFF_COLLAPSE_DEPOSITION_SAND_NAME);
1046 break;
1047
1049 strFilePathName.append(RASTER_CLIFF_COLLAPSE_DEPOSITION_COARSE_NAME);
1050 break;
1051
1054 break;
1055
1058 break;
1059
1061 strFilePathName.append(RASTER_INTERVENTION_HEIGHT_NAME);
1062 break;
1063
1065 strFilePathName.append(RASTER_DEEP_WATER_WAVE_ORIENTATION_NAME);
1066 break;
1067
1069 strFilePathName.append(RASTER_DEEP_WATER_WAVE_HEIGHT_NAME);
1070 break;
1071
1073 strFilePathName.append(RASTER_POLYGON_GAIN_OR_LOSS_NAME);
1074 break;
1075
1077 strFilePathName.append(RASTER_WAVE_PERIOD_NAME);
1078 break;
1079
1081 strFilePathName.append(RASTER_SEDIMENT_INPUT_EVENT_NAME);
1082 break;
1083
1085 bIsInteger = true;
1086 strFilePathName.append(RASTER_BEACH_MASK_NAME);
1087 break;
1088
1090 bIsInteger = true;
1091 strFilePathName.append(RASTER_POTENTIAL_PLATFORM_EROSION_MASK_NAME);
1092 break;
1093
1095 bIsInteger = true;
1096 strFilePathName.append(RASTER_INUNDATION_MASK_NAME);
1097 break;
1098
1099 case (RASTER_PLOT_SLICE):
1100 bIsInteger = true;
1101 ststrTmp.str("");
1102 ststrTmp.clear();
1103
1104 // TODO 031 Get working for multiple slices
1105 strFilePathName.append(RASTER_SLICE_NAME);
1106 ststrTmp << "_" << dElev << "_";
1107 strFilePathName.append(ststrTmp.str());
1108 break;
1109
1110 case (RASTER_PLOT_LANDFORM):
1111 bIsInteger = true;
1112 strFilePathName.append(RASTER_LANDFORM_NAME);
1113 break;
1114
1116 bIsInteger = true;
1117 strFilePathName.append(RASTER_INTERVENTION_CLASS_NAME);
1118 break;
1119
1120 case (RASTER_PLOT_COAST):
1121 bIsInteger = true;
1122 strFilePathName.append(RASTER_COAST_NAME);
1123 break;
1124
1126 bIsInteger = true;
1127 strFilePathName.append(RASTER_COAST_NORMAL_NAME);
1128 break;
1129
1131 bIsInteger = true;
1132 strFilePathName.append(RASTER_ACTIVE_ZONE_NAME);
1133 break;
1134
1135 case (RASTER_PLOT_POLYGON):
1136 bIsInteger = true;
1137 strFilePathName.append(RASTER_POLYGON_NAME);
1138 break;
1139
1141 bIsInteger = true;
1142 strFilePathName.append(RASTER_SHADOW_ZONE_NAME);
1143 break;
1144
1146 bIsInteger = true;
1147 strFilePathName.append(RASTER_SHADOW_DOWNDRIFT_ZONE_NAME);
1148 break;
1149
1151 bIsInteger = true;
1152 strFilePathName.append(RASTER_POLYGON_UPDRIFT_OR_DOWNDRIFT_NAME);
1153 break;
1154
1156 bIsInteger = true;
1157 strFilePathName.append(RASTER_SETUP_SURGE_FLOOD_MASK_NAME);
1158 break;
1159
1161 bIsInteger = true;
1162 strFilePathName.append(RASTER_SETUP_SURGE_RUNUP_FLOOD_MASK_NAME);
1163 break;
1164
1166 bIsInteger = true;
1167 strFilePathName.append(RASTER_WAVE_FLOOD_LINE_NAME);
1168 break;
1169 }
1170
1171 // Append the 'save number' to the filename, and prepend zeros to the save number
1172 ststrTmp.str("");
1173 ststrTmp.clear();
1174
1175 strFilePathName.append("_");
1176
1178 // Save number is m_bGISSaveDigitsSequential
1179 ststrTmp << FillToWidth('0', m_nGISMaxSaveDigits) << m_nGISSave;
1180 }
1181
1182 else {
1183 // Save number is iteration
1184 ststrTmp << FillToWidth('0', m_nGISMaxSaveDigits) << m_ulIter;
1185 }
1186
1187 strFilePathName.append(ststrTmp.str());
1188
1189 // Finally, maybe append the extension
1191 strFilePathName.append(".");
1192 strFilePathName.append(m_strGDALRasterOutputDriverExtension);
1193 }
1194
1195 // TODO 065 Used to try to debug floating point exception in pDriver->Create() below
1196 // CPLSetConfigOption("CPL_DEBUG", "ON");
1197 // CPLSetConfigOption("GDAL_NUM_THREADS", "1");
1198
1199 GDALDriver *pDriver;
1200 GDALDataset *pDataSet;
1201
1202 if (m_bGDALCanCreate) {
1203 // The user-requested raster driver supports the Create() method
1204 pDriver = GetGDALDriverManager()->GetDriverByName(m_strRasterGISOutFormat.c_str());
1205
1207 pDataSet = pDriver->Create(strFilePathName.c_str(), m_nXGridSize, m_nYGridSize, 1, GDT_Int16, m_papszGDALRasterOptions);
1208 }
1209
1210 else if (m_strRasterGISOutFormat == "gpkg") {
1211 // TODO 065 Floating point exception here
1212 pDataSet = pDriver->Create(strFilePathName.c_str(), m_nXGridSize, m_nYGridSize, 1, GDT_Byte, m_papszGDALRasterOptions);
1213 }
1214
1215 else {
1216 pDataSet = pDriver->Create(strFilePathName.c_str(), m_nXGridSize, m_nYGridSize, 1, m_GDALWriteFloatDataType, m_papszGDALRasterOptions);
1217 }
1218
1219 if (NULL == pDataSet) {
1220 // Error, couldn't create file
1221 cerr << ERR << "cannot create " << m_strRasterGISOutFormat << " file named " << strFilePathName << endl
1222 << CPLGetLastErrorMsg() << endl;
1223 return false;
1224 }
1225 }
1226
1227 else {
1228 // The user-requested raster driver does not support the Create() method, so we must first create a memory-file dataset
1229 pDriver = GetGDALDriverManager()->GetDriverByName("MEM");
1230 pDataSet = pDriver->Create("", m_nXGridSize, m_nYGridSize, 1, m_GDALWriteFloatDataType, NULL);
1231
1232 if (NULL == pDataSet) {
1233 // Couldn't create in-memory file dataset
1234 cerr << ERR << "cannot create in-memory file for " << m_strRasterGISOutFormat << " file named " << strFilePathName << endl
1235 << CPLGetLastErrorMsg() << endl;
1236 return false;
1237 }
1238 }
1239
1240 // Set projection info for output dataset (will be same as was read in from basement DEM)
1241 CPLPushErrorHandler(CPLQuietErrorHandler); // Needed to get next line to fail silently, if it fails
1242 pDataSet->SetProjection(m_strGDALBasementDEMProjection.c_str()); // Will fail for some formats
1243 CPLPopErrorHandler();
1244
1245 // Set geotransformation info for output dataset (will be same as was read in from DEM)
1246 if (CE_Failure == pDataSet->SetGeoTransform(m_dGeoTransform))
1247 LogStream << WARN << "cannot write geotransformation information to " << m_strRasterGISOutFormat << " file named " << strFilePathName << endl
1248 << CPLGetLastErrorMsg() << endl;
1249
1250 // Allocate memory for a 1D array, to hold the floating point raster band data for GDAL
1251 double *pdRaster = new double[m_ulNumCells];
1252
1253 if (NULL == pdRaster) {
1254 // Error, can't allocate memory
1255 cerr << ERR << "cannot allocate memory for " << m_ulNumCells << " x 1D floating-point array for " << m_strRasterGISOutFormat << " file named " << strFilePathName << endl;
1256 return (RTN_ERR_MEMALLOC);
1257 }
1258
1259 bool bScaleOutput = false;
1260 double dRangeScale = 0;
1261 double dDataMin = 0;
1262
1263 if (!m_bGDALCanWriteFloat) {
1264 double dDataMax = 0;
1265
1266 // The output file format cannot handle floating-point numbers, so we may need to scale the output
1267 GetRasterOutputMinMax(nDataItem, dDataMin, dDataMax, nLayer, 0);
1268
1269 double
1270 dDataRange = dDataMax - dDataMin,
1271 dWriteRange = static_cast<double>(m_lGDALMaxCanWrite - m_lGDALMinCanWrite);
1272
1273 if (dDataRange > 0)
1274 dRangeScale = dWriteRange / dDataRange;
1275
1276 // If we are attempting to write values which are outside this format's allowable range, and the user has set the option, then scale the output
1277 if (((dDataMin < static_cast<double>(m_lGDALMinCanWrite)) || (dDataMax > static_cast<double>(m_lGDALMaxCanWrite))) && m_bScaleRasterOutput)
1278 bScaleOutput = true;
1279 }
1280
1281 // Fill the array
1282 int
1283 n = 0,
1284 nPoly = 0,
1285 nTopLayer = 0;
1286 double dTmp = 0;
1287
1288 for (int nY = 0; nY < m_nYGridSize; nY++) {
1289 for (int nX = 0; nX < m_nXGridSize; nX++) {
1290 switch (nDataItem) {
1292 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetBasementElev();
1293 break;
1294
1296 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetSedimentTopElev();
1297 break;
1298
1300 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetSedimentPlusInterventionTopElev();
1301 break;
1302
1304 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetLocalConsSlope();
1305 break;
1306
1307 case (RASTER_PLOT_SLOPE):
1308 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetSlope();
1309 break;
1310
1311 case (RASTER_PLOT_CLIFF):
1312 dTmp = m_pRasterGrid->m_Cell[nX][nY].bIsCliff();
1313 break;
1314
1315 case (RASTER_PLOT_SEA_DEPTH):
1316 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetSeaDepth();
1317 break;
1318
1320 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetTotSeaDepth() / static_cast<double>(m_ulIter);
1321 break;
1322
1324 if (m_pRasterGrid->m_Cell[nX][nY].bIsInundated())
1325 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetWaveHeight();
1326
1327 else
1328 dTmp = 0;
1329
1330 break;
1331
1333 if (m_pRasterGrid->m_Cell[nX][nY].bIsInundated())
1334 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetTotWaveHeight() / static_cast<double>(m_ulIter);
1335
1336 else
1337 dTmp = 0;
1338
1339 break;
1340
1342 if (m_pRasterGrid->m_Cell[nX][nY].bIsInundated())
1343 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetWaveAngle();
1344
1345 else
1346 dTmp = 0;
1347
1348 break;
1349
1351 if (m_pRasterGrid->m_Cell[nX][nY].bIsInundated())
1352 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetTotWaveAngle() / static_cast<double>(m_ulIter);
1353
1354 else
1355 dTmp = 0;
1356
1357 break;
1358
1360 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetBeachProtectionFactor();
1361
1362 if (bFPIsEqual(dTmp, DBL_NODATA, TOLERANCE))
1363 dTmp = m_dMissingValue;
1364
1365 else
1366 dTmp = 1 - dTmp; // Output the inverse, seems more intuitive
1367
1368 break;
1369
1371 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetPotentialPlatformErosion();
1372 break;
1373
1375 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetActualPlatformErosion();
1376 break;
1377
1379 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetTotPotentialPlatformErosion();
1380 break;
1381
1383 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetTotActualPlatformErosion();
1384 break;
1385
1387 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetPotentialBeachErosion();
1388 break;
1389
1391 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetActualBeachErosion();
1392 break;
1393
1395 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetTotPotentialBeachErosion();
1396 break;
1397
1399 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetTotActualBeachErosion();
1400 break;
1401
1403 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetBeachDeposition();
1404 break;
1405
1407 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetTotBeachDeposition();
1408 break;
1409
1411 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetSuspendedSediment();
1412 break;
1413
1415 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetTotSuspendedSediment() / static_cast<double>(m_ulIter);
1416 break;
1417
1419 dTmp = m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nLayer)->pGetUnconsolidatedSediment()->dGetFineDepth();
1420 break;
1421
1423 dTmp = m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nLayer)->pGetUnconsolidatedSediment()->dGetSandDepth();
1424 break;
1425
1427 dTmp = m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nLayer)->pGetUnconsolidatedSediment()->dGetCoarseDepth();
1428 break;
1429
1431 dTmp = m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nLayer)->pGetConsolidatedSediment()->dGetFineDepth();
1432 break;
1433
1435 dTmp = m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nLayer)->pGetConsolidatedSediment()->dGetSandDepth();
1436 break;
1437
1439 dTmp = m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nLayer)->pGetConsolidatedSediment()->dGetCoarseDepth();
1440 break;
1441
1443 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetThisIterCliffCollapseErosionFine();
1444 break;
1445
1447 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetThisIterCliffCollapseErosionSand();
1448 break;
1449
1451 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetThisIterCliffCollapseErosionCoarse();
1452 break;
1453
1455 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetTotCliffCollapseFine();
1456 break;
1457
1459 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetTotCliffCollapseSand();
1460 break;
1461
1463 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetTotCliffCollapseCoarse();
1464 break;
1465
1467 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetThisIterCliffCollapseSandTalusDeposition();
1468 break;
1469
1471 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetThisIterCliffCollapseCoarseTalusDeposition();
1472 break;
1473
1475 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetTotSandTalusDeposition();
1476 break;
1477
1479 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetTotCoarseTalusDeposition();
1480 break;
1481
1483 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetInterventionHeight();
1484 break;
1485
1487 if (m_pRasterGrid->m_Cell[nX][nY].bIsInundated())
1488 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetCellDeepWaterWaveAngle();
1489
1490 else
1491 dTmp = 0;
1492
1493 break;
1494
1496 if (m_pRasterGrid->m_Cell[nX][nY].bIsInundated())
1497 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetCellDeepWaterWaveHeight();
1498
1499 else
1500 dTmp = 0;
1501
1502 break;
1503
1505 if (m_pRasterGrid->m_Cell[nX][nY].bIsInundated())
1506 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetCellDeepWaterWavePeriod();
1507
1508 else
1509 dTmp = 0;
1510
1511 break;
1512
1514 nPoly = m_pRasterGrid->m_Cell[nX][nY].nGetPolygonID();
1515
1516 if (nPoly == INT_NODATA)
1517 dTmp = m_dMissingValue;
1518
1519 else {
1520 // Get total volume (all sediment size classes) of change in sediment for this polygon for this timestep (-ve erosion, +ve deposition)
1521 dTmp = m_pVCoastPolygon[nPoly]->dGetBeachDepositionAndSuspensionAllUncons() * m_dCellArea;
1522
1523 // Calculate the rate in m^3 / sec
1524 dTmp /= (m_dTimeStep * 3600);
1525 }
1526
1527 break;
1528
1530 // cppcheck-suppress assignBoolToFloat
1531 dTmp = m_pRasterGrid->m_Cell[nX][nY].bPotentialPlatformErosion();
1532 break;
1533
1535 // cppcheck-suppress assignBoolToFloat
1536 dTmp = m_pRasterGrid->m_Cell[nX][nY].bIsInContiguousSea();
1537 break;
1538
1540 dTmp = 0;
1541 nTopLayer = m_pRasterGrid->m_Cell[nX][nY].nGetTopNonZeroLayerAboveBasement();
1542
1543 if ((nTopLayer == INT_NODATA) || (nTopLayer == NO_NONZERO_THICKNESS_LAYERS))
1544 break;
1545
1546 if ((m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nTopLayer)->dGetUnconsolidatedThickness() > 0) && (m_pRasterGrid->m_Cell[nX][nY].dGetSedimentTopElev() > m_dThisIterSWL))
1547 dTmp = 1;
1548
1549 break;
1550
1551 case (RASTER_PLOT_SLICE):
1552 dTmp = m_pRasterGrid->m_Cell[nX][nY].nGetLayerAtElev(dElev);
1553 break;
1554
1555 case (RASTER_PLOT_LANDFORM):
1556 dTmp = m_pRasterGrid->m_Cell[nX][nY].pGetLandform()->nGetLFCategory();
1557
1558 if ((static_cast<int>(dTmp) == LF_CAT_DRIFT) || (static_cast<int>(dTmp) == LF_CAT_CLIFF))
1559 dTmp = m_pRasterGrid->m_Cell[nX][nY].pGetLandform()->nGetLFSubCategory();
1560
1561 break;
1562
1564 dTmp = m_pRasterGrid->m_Cell[nX][nY].nGetInterventionClass();
1565 break;
1566
1567 case (RASTER_PLOT_COAST):
1568 dTmp = (m_pRasterGrid->m_Cell[nX][nY].bIsCoastline() ? 1 : 0);
1569 break;
1570
1572 // dTmp = (m_pRasterGrid->m_Cell[nX][nY].bIsProfile() ? 1 : 0);
1573 dTmp = m_pRasterGrid->m_Cell[nX][nY].nGetProfileID();
1574 break;
1575
1577 dTmp = (m_pRasterGrid->m_Cell[nX][nY].bIsInActiveZone() ? 1 : 0);
1578 break;
1579
1580 case (RASTER_PLOT_POLYGON):
1581 dTmp = m_pRasterGrid->m_Cell[nX][nY].nGetPolygonID();
1582 break;
1583
1585 dTmp = m_pRasterGrid->m_Cell[nX][nY].nGetShadowZoneNumber();
1586 break;
1587
1589 dTmp = m_pRasterGrid->m_Cell[nX][nY].nGetDownDriftZoneNumber();
1590 break;
1591
1593 nPoly = m_pRasterGrid->m_Cell[nX][nY].nGetPolygonID();
1594
1595 if (nPoly == INT_NODATA)
1596 dTmp = m_nMissingValue;
1597
1598 else {
1599 if (m_pVCoastPolygon[nPoly]->bDownCoastThisIter())
1600 dTmp = 1;
1601
1602 else
1603 dTmp = 0;
1604 }
1605
1606 break;
1607
1609 dTmp = m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nTopLayer)->pGetUnconsolidatedSediment()->dGetTotAllSedimentInputDepth();
1610 break;
1611
1613 dTmp = (m_pRasterGrid->m_Cell[nX][nY].bIsFloodBySetupSurge() ? 1 : 0);
1614 break;
1615
1617 dTmp = (m_pRasterGrid->m_Cell[nX][nY].bIsFloodBySetupSurgeRunup() ? 1 : 0);
1618 break;
1619
1621 dTmp = (m_pRasterGrid->m_Cell[nX][nY].bIsFloodLine() ? 1 : 0);
1622 break;
1623 }
1624
1625 // If necessary, scale this value
1626 if (bScaleOutput) {
1627 if (bFPIsEqual(dTmp, DBL_NODATA, TOLERANCE))
1628 dTmp = 0; // TODO 032 Improve this
1629
1630 else
1631 dTmp = dRound(static_cast<double>(m_lGDALMinCanWrite) + (dRangeScale * (dTmp - dDataMin)));
1632 }
1633
1634 // Write this value to the array
1635 pdRaster[n++] = dTmp;
1636 }
1637 }
1638
1639 // Create a single raster band
1640 GDALRasterBand *pBand = pDataSet->GetRasterBand(1);
1641
1642 // And fill it with the NODATA value
1643 if (bIsInteger)
1644 pBand->Fill(m_nMissingValue);
1645
1646 else
1647 pBand->Fill(m_dMissingValue);
1648
1649 // Set value units for this band
1650 string strUnits;
1651
1652 switch (nDataItem) {
1656 case (RASTER_PLOT_SEA_DEPTH):
1691 strUnits = "m";
1692 break;
1693
1695 strUnits = "m/m";
1696 break;
1697
1700 strUnits = "degrees";
1701 break;
1702
1704 strUnits = "cumecs";
1705 break;
1706
1708 strUnits = "secs";
1709 break;
1710
1714 case (RASTER_PLOT_SLICE):
1715 case (RASTER_PLOT_LANDFORM):
1717 case (RASTER_PLOT_COAST):
1720 case (RASTER_PLOT_POLYGON):
1727 strUnits = "none";
1728 break;
1729 }
1730
1731 CPLPushErrorHandler(CPLQuietErrorHandler); // Needed to get next line to fail silently, if it fails
1732 pBand->SetUnitType(strUnits.c_str()); // Not supported for some GIS formats
1733 CPLPopErrorHandler();
1734
1735 // Tell the output dataset about NODATA (missing values)
1736 CPLPushErrorHandler(CPLQuietErrorHandler); // Needed to get next line to fail silently, if it fails
1737
1738 if (bIsInteger)
1739 pBand->SetNoDataValue(m_nMissingValue); // Will fail for some formats
1740
1741 else
1742 pBand->SetNoDataValue(m_dMissingValue); // Will fail for some formats
1743
1744 CPLPopErrorHandler();
1745
1746 // Construct the description
1747 string strDesc(*strPlotTitle);
1748
1749 if (nDataItem == RASTER_PLOT_SLICE) {
1750 ststrTmp.clear();
1751 ststrTmp << dElev << "m, ";
1752 strDesc.append(ststrTmp.str());
1753 }
1754
1755 strDesc.append(" at ");
1756 strDesc.append(strDispTime(m_dSimElapsed, false, false));
1757
1758 // Set the GDAL description
1759 pBand->SetDescription(strDesc.c_str());
1760
1761 // Set raster category names
1762 char **papszCategoryNames = NULL;
1763
1764 switch (nDataItem) {
1765 case (RASTER_PLOT_SLICE):
1766 papszCategoryNames = CSLAddString(papszCategoryNames, "Basement");
1767 papszCategoryNames = CSLAddString(papszCategoryNames, "Layer 0");
1768 papszCategoryNames = CSLAddString(papszCategoryNames, "Layer 1");
1769 papszCategoryNames = CSLAddString(papszCategoryNames, "Layer 2");
1770 papszCategoryNames = CSLAddString(papszCategoryNames, "Layer 3");
1771 papszCategoryNames = CSLAddString(papszCategoryNames, "Layer 4");
1772 papszCategoryNames = CSLAddString(papszCategoryNames, "Layer 5");
1773 papszCategoryNames = CSLAddString(papszCategoryNames, "Layer 6");
1774 papszCategoryNames = CSLAddString(papszCategoryNames, "Layer 7");
1775 papszCategoryNames = CSLAddString(papszCategoryNames, "Layer 8");
1776 papszCategoryNames = CSLAddString(papszCategoryNames, "Layer 9");
1777 break;
1778
1779 case (RASTER_PLOT_LANDFORM):
1780 papszCategoryNames = CSLAddString(papszCategoryNames, "None");
1781 papszCategoryNames = CSLAddString(papszCategoryNames, "Hinterland");
1782 papszCategoryNames = CSLAddString(papszCategoryNames, "Sea");
1783 papszCategoryNames = CSLAddString(papszCategoryNames, "Cliff");
1784 papszCategoryNames = CSLAddString(papszCategoryNames, "Drift");
1785 papszCategoryNames = CSLAddString(papszCategoryNames, "Intervention");
1786
1787 papszCategoryNames = CSLAddString(papszCategoryNames, "Cliff on Coastline");
1788 papszCategoryNames = CSLAddString(papszCategoryNames, "Inland Cliff");
1789
1790 papszCategoryNames = CSLAddString(papszCategoryNames, "Mixed Drift");
1791 papszCategoryNames = CSLAddString(papszCategoryNames, "Talus");
1792 papszCategoryNames = CSLAddString(papszCategoryNames, "Beach");
1793 papszCategoryNames = CSLAddString(papszCategoryNames, "Dunes");
1794 break;
1795
1797 papszCategoryNames = CSLAddString(papszCategoryNames, "None");
1798 papszCategoryNames = CSLAddString(papszCategoryNames, "Structural");
1799 papszCategoryNames = CSLAddString(papszCategoryNames, "Non-Structural");
1800 break;
1801
1802 case (RASTER_PLOT_COAST):
1803 papszCategoryNames = CSLAddString(papszCategoryNames, "Not coastline");
1804 papszCategoryNames = CSLAddString(papszCategoryNames, "Coastline");
1805 break;
1806
1808 papszCategoryNames = CSLAddString(papszCategoryNames, "Not coastline-normal profile");
1809 papszCategoryNames = CSLAddString(papszCategoryNames, "Coastline-normal profile");
1810 break;
1811
1813 papszCategoryNames = CSLAddString(papszCategoryNames, "Not in active zone");
1814 papszCategoryNames = CSLAddString(papszCategoryNames, "In active zone");
1815 break;
1816
1817 case (RASTER_PLOT_POLYGON):
1818 papszCategoryNames = CSLAddString(papszCategoryNames, "Not polygon");
1819 papszCategoryNames = CSLAddString(papszCategoryNames, "In polygon");
1820 break;
1821
1823 papszCategoryNames = CSLAddString(papszCategoryNames, "Not in shadow zone");
1824 papszCategoryNames = CSLAddString(papszCategoryNames, "In shadow zone");
1825 break;
1826
1828 papszCategoryNames = CSLAddString(papszCategoryNames, "Not in shadow downdrift zone");
1829 papszCategoryNames = CSLAddString(papszCategoryNames, "In shadow downdrift zone");
1830 break;
1831
1833 papszCategoryNames = CSLAddString(papszCategoryNames, "Updrift movement of unconsolidated sediment ");
1834 papszCategoryNames = CSLAddString(papszCategoryNames, "Downdrift movement of unconsolidated sediment");
1835 break;
1836
1838 papszCategoryNames = CSLAddString(papszCategoryNames, "Inundated by swl setup and surge ");
1839 papszCategoryNames = CSLAddString(papszCategoryNames, "Not inundated by swl setup and surge");
1840 break;
1841
1843 papszCategoryNames = CSLAddString(papszCategoryNames, "Inundated by swl setup, surge and runup ");
1844 papszCategoryNames = CSLAddString(papszCategoryNames, "Not inundated by swl setup, surge and runup");
1845 break;
1846
1848 papszCategoryNames = CSLAddString(papszCategoryNames, "Intersection line of inundation ");
1849 papszCategoryNames = CSLAddString(papszCategoryNames, "Not inundated by swl waves and runup");
1850 break;
1851 }
1852
1853 CPLPushErrorHandler(CPLQuietErrorHandler); // Needed to get next line to fail silently, if it fails
1854 pBand->SetCategoryNames(papszCategoryNames); // Not supported for some GIS formats
1855 CPLPopErrorHandler();
1856
1857 // Now write the data with optimized I/O
1858 // Enable multi-threaded compression for faster writing
1859 CPLSetThreadLocalConfigOption("GDAL_NUM_THREADS", "ALL_CPUS");
1860
1861 if (CE_Failure == pBand->RasterIO(GF_Write, 0, 0, m_nXGridSize, m_nYGridSize, pdRaster, m_nXGridSize, m_nYGridSize, GDT_Float64, 0, 0, NULL)) {
1862 // Write error, better error message
1863 cerr << ERR << "cannot write data for " << m_strRasterGISOutFormat << " file named " << strFilePathName << endl
1864 << CPLGetLastErrorMsg() << endl;
1865 delete[] pdRaster;
1866 return false;
1867 }
1868
1869 // Calculate statistics for this band
1870 double dMin, dMax, dMean, dStdDev;
1871 CPLPushErrorHandler(CPLQuietErrorHandler); // Needed to get next line to fail silently, if it fails
1872 pBand->ComputeStatistics(false, &dMin, &dMax, &dMean, &dStdDev, NULL, NULL);
1873 CPLPopErrorHandler();
1874
1875 // And then write the statistics
1876 CPLPushErrorHandler(CPLQuietErrorHandler); // Needed to get next line to fail silently, if it fails
1877 pBand->SetStatistics(dMin, dMax, dMean, dStdDev);
1878 CPLPopErrorHandler();
1879
1880 if (!m_bGDALCanCreate) {
1881 // Since the user-selected raster driver cannot use the Create() method, we have been writing to a dataset created by the in-memory driver. So now we need to use CreateCopy() to copy this in-memory dataset to a file in the user-specified raster driver format
1882 GDALDriver *pOutDriver = GetGDALDriverManager()->GetDriverByName(m_strRasterGISOutFormat.c_str());
1883 GDALDataset *pOutDataSet = pOutDriver->CreateCopy(strFilePathName.c_str(), pDataSet, FALSE, m_papszGDALRasterOptions, NULL, NULL);
1884
1885 if (NULL == pOutDataSet) {
1886 // Couldn't create file
1887 cerr << ERR << "cannot create " << m_strRasterGISOutFormat << " file named " << strFilePathName << endl
1888 << CPLGetLastErrorMsg() << endl;
1889 return false;
1890 }
1891
1892 // Get rid of this user-selected dataset object
1893 GDALClose(pOutDataSet);
1894 }
1895
1896 // Get rid of dataset object
1897 GDALClose(pDataSet);
1898
1899 // Also get rid of memory allocated to this array
1900 delete[] pdRaster;
1901
1902 return true;
1903}
1904
1905//===============================================================================================================================
1907//===============================================================================================================================
1908int CSimulation::nInterpolateWavesToPolygonCells(vector<double> const *pVdX, vector<double> const *pVdY, vector<double> const *pVdHeightX, vector<double> const *pVdHeightY) {
1909 int nXSize = 0;
1910 int nYSize = 0;
1911
1912 double dXAvg = 0;
1913 double dYAvg = 0;
1914
1917 int nGridSize = nXSize * nYSize;
1918
1919 unsigned int nPoints = static_cast<unsigned int>(pVdX->size());
1920
1921 // // DEBUG CODE ============================================================================================================
1922 // for (int nn = 0; nn < nPoints; nn++)
1923 // {
1924 // LogStream << nn << " " << dX[nn] << " " << dY[nn] << " " << dZ[nn] << endl;
1925 // }
1926 //
1927 // m_nXMaxBoundingBox = m_nXGridSize-1;
1928 // m_nYMaxBoundingBox = m_nYGridSize-1;
1929 // m_nXMinBoundingBox = 0;
1930 // m_nYMinBoundingBox = 0;
1931 // // DEBUG CODE ============================================================================================================
1932
1933 vector<double> VdOutX(nGridSize, 0);
1934 vector<double> VdOutY(nGridSize, 0);
1935
1936 // Do first for X, then for Y
1937 for (int nDirection = 0; nDirection < 2; nDirection++) {
1938 // Use the GDALGridCreate() linear interpolation algorithm: this computes a Delaunay triangulation of the point cloud, finding in which triangle of the triangulation the point is, and by doing linear interpolation from its barycentric coordinates within the triangle. If the point is not in any triangle, depending on the radius, the algorithm will use the value of the nearest point or the nodata value. Only available in GDAL 2.1 and later TODO 086
1939
1940 // Performance optimization: Use optimized settings for large grids
1941 GDALGridLinearOptions *pOptions = new GDALGridLinearOptions();
1942 pOptions->dfNoDataValue = m_dMissingValue; // Set the no-data marker to fill empty points
1943 pOptions->dfRadius = -1; // Set the search radius to infinite
1944 pOptions->nSizeOfStructure = sizeof(GDALGridLinearOptions); // Needed for GDAL 3.6 onwards, see https://gdal.org/api/gdal_alg.html#_CPPv421GDALGridLinearOptions
1945
1946 // Performance enhancement: Enable grid threading for this specific operation
1947 CPLSetThreadLocalConfigOption("GDAL_NUM_THREADS", "ALL_CPUS");
1948
1949 // pOptions.dfRadius = static_cast<double>(nXSize + nYSize) / 2.0; // Set the search radius
1950
1951 // GDALGridNearestNeighborOptions* pOptions = new GDALGridNearestNeighborOptions();
1952 // pOptions->dfNoDataValue = m_dMissingValue; // Set the no-data marker to fill empty points
1953 // pOptions->dfRadius = -1; // Set the search radius to infinite
1954
1955 // Call GDALGridCreate() TODO 086
1956 int nRet;
1957
1958 if (nDirection == 0) {
1959 nRet = GDALGridCreate(GGA_Linear, pOptions, nPoints, pVdX->data(), pVdY->data(), pVdHeightX->data(), m_nXMinBoundingBox, m_nXMaxBoundingBox, m_nYMinBoundingBox, m_nYMaxBoundingBox, nXSize, nYSize, GDT_Float64, VdOutX.data(), NULL, NULL);
1960 }
1961
1962 else {
1963 nRet = GDALGridCreate(GGA_Linear, pOptions, nPoints, pVdX->data(), pVdY->data(), pVdHeightY->data(), m_nXMinBoundingBox, m_nXMaxBoundingBox, m_nYMinBoundingBox, m_nYMaxBoundingBox, nXSize, nYSize, GDT_Float64, VdOutY.data(), NULL, NULL);
1964 }
1965
1966 // int nRet;
1967 // if (nDirection == 0)
1968 // {
1969 // nRet = GDALGridCreate(GGA_NearestNeighbor, pOptions, nPoints, pVdX->data(), pVdY->data(), pVdHeightX->data(), m_nXMinBoundingBox, m_nXMaxBoundingBox, m_nYMinBoundingBox, m_nYMaxBoundingBox, nXSize, nYSize, GDT_Float64, VdOutX.data(), NULL, NULL);
1970 // }
1971 // else
1972 // {
1973 // nRet = GDALGridCreate(GGA_NearestNeighbor, pOptions, nPoints, pVdX->data(), pVdY->data(), pVdHeightY->data(), m_nXMinBoundingBox, m_nXMaxBoundingBox, m_nYMinBoundingBox, m_nYMaxBoundingBox, nXSize, nYSize, GDT_Float64, VdOutY.data(), NULL, NULL);
1974 // }
1975
1976 delete pOptions;
1977
1978 if (nRet == CE_Failure) {
1979 cerr << CPLGetLastErrorMsg() << endl;
1980 return RTN_ERR_GRIDCREATE;
1981 }
1982
1983 if (nDirection == 0) {
1984 int nXValid = 0;
1985
1986 // Safety check: unfortunately, GDALGridCreate(() outputs NaNs and other crazy values when the polygons are far from regular. So check for these
1987 for (unsigned int n = 0; n < VdOutX.size(); n++) {
1988 if (isnan(VdOutX[n]))
1989 VdOutX[n] = m_dMissingValue;
1990
1991 else if (tAbs(VdOutX[n]) > 1e10)
1992 VdOutX[n] = m_dMissingValue;
1993
1994 else {
1995 dXAvg += VdOutX[n];
1996 nXValid++;
1997 }
1998 }
1999
2000 dXAvg /= nXValid;
2001 }
2002
2003 else {
2004 int nYValid = 0;
2005
2006 // Safety check: unfortunately, GDALGridCreate(() outputs NaNs and other crazy values when the polygon are far from regular. So check for these
2007 for (unsigned int n = 0; n < VdOutY.size(); n++) {
2008 if (isnan(VdOutY[n]))
2009 VdOutY[n] = m_dMissingValue;
2010
2011 else if (tAbs(VdOutY[n]) > 1e10)
2012 VdOutY[n] = m_dMissingValue;
2013
2014 else {
2015 dYAvg += VdOutY[n];
2016 nYValid++;
2017 }
2018 }
2019
2020 dYAvg /= nYValid;
2021 }
2022
2023 // // DEBUG CODE ===========================================================================================================
2024 // string strOutFile = m_strOutPath;
2025 // strOutFile += "sea_wave_interpolation_";
2026 // if (nDirection == 0)
2027 // strOutFile += "X_";
2028 // else
2029 // strOutFile += "Y_";
2030 // strOutFile += to_string(m_ulIter);
2031 // strOutFile += ".tif";
2032 //
2033 // GDALDriver* pDriver = GetGDALDriverManager()->GetDriverByName("gtiff");
2034 // GDALDataset* pDataSet = pDriver->Create(strOutFile.c_str(), m_nXGridSize, m_nYGridSize, 1, GDT_Float64, m_papszGDALRasterOptions);
2035 // pDataSet->SetProjection(m_strGDALBasementDEMProjection.c_str());
2036 // pDataSet->SetGeoTransform(m_dGeoTransform);
2037 // double* pdRaster = new double[m_nXGridSize * m_nYGridSize];
2038 // int m = 0;
2039 // int n = 0;
2040 // for (int nY = 0; nY < m_nYGridSize; nY++)
2041 // {
2042 // for (int nX = 0; nX < m_nXGridSize; nX++)
2043 // {
2044 // if ((nX < m_nXMinBoundingBox) || (nY < m_nYMinBoundingBox))
2045 // {
2046 // pdRaster[n++] = DBL_NODATA;
2047 // }
2048 // else
2049 // {
2050 // // Write this value to the array
2051 // if (nDirection == 0)
2052 // {
2053 // if (m < static_cast<int>(VdOutX.size()))
2054 // {
2055 // pdRaster[n++] = VdOutX[m++];
2056 // // LogStream << "nDirection = " << nDirection << " [" << nX << "][" << nY << "] = " << VpdOutX[n] << endl;
2057 // }
2058 // }
2059 // else
2060 // {
2061 // if (m < static_cast<int>(VdOutY.size()))
2062 // {
2063 // pdRaster[n++] = VdOutY[m++];
2064 // // LogStream << "nDirection = " << nDirection << " [" << nX << "][" << nY << "] = " << VpdOutY[n] << endl;
2065 // }
2066 // }
2067 // }
2068 // }
2069 // }
2070 //
2071 // GDALRasterBand* pBand = pDataSet->GetRasterBand(1);
2072 // pBand->SetNoDataValue(m_dMissingValue);
2073 // nRet = pBand->RasterIO(GF_Write, 0, 0, m_nXGridSize, m_nYGridSize, pdRaster, m_nXGridSize, m_nYGridSize, GDT_Float64, 0, 0, NULL);
2074 //
2075 // if (nRet == CE_Failure)
2076 // return RTN_ERR_GRIDCREATE;
2077 //
2078 // GDALClose(pDataSet);
2079 // delete[] pdRaster;
2080 // // DEBUG CODE ===========================================================================================================
2081 }
2082
2083 // // DEBUG CODE ===========================================================================================================
2084 // string strOutFile = m_strOutPath;
2085 // strOutFile += "sea_wave_height_before_";
2086 // strOutFile += to_string(m_ulIter);
2087 // strOutFile += ".tif";
2088 //
2089 // GDALDriver* pDriver = GetGDALDriverManager()->GetDriverByName("gtiff");
2090 // GDALDataset* pDataSet = pDriver->Create(strOutFile.c_str(), m_nXGridSize, m_nYGridSize, 1, GDT_Float64, m_papszGDALRasterOptions);
2091 // pDataSet->SetProjection(m_strGDALBasementDEMProjection.c_str());
2092 // pDataSet->SetGeoTransform(m_dGeoTransform);
2093 //
2094 // int nn = 0;
2095 // double* pdRaster = new double[m_nXGridSize * m_nYGridSize];
2096 // for (int nY = 0; nY < m_nYGridSize; nY++)
2097 // {
2098 // for (int nX = 0; nX < m_nXGridSize; nX++)
2099 // {
2100 // pdRaster[nn++] = m_pRasterGrid->m_Cell[nX][nY].dGetWaveHeight();
2101 // }
2102 // }
2103 //
2104 // GDALRasterBand* pBand = pDataSet->GetRasterBand(1);
2105 // pBand->SetNoDataValue(m_dMissingValue);
2106 // int nRet = pBand->RasterIO(GF_Write, 0, 0, m_nXGridSize, m_nYGridSize, pdRaster, m_nXGridSize, m_nYGridSize, GDT_Float64, 0, 0, NULL);
2107 //
2108 // if (nRet == CE_Failure)
2109 // return RTN_ERR_GRIDCREATE;
2110 //
2111 // GDALClose(pDataSet);
2112 // delete[] pdRaster;
2113 // // DEBUG CODE ===========================================================================================================
2114
2115 // // DEBUG CODE ===========================================================================================================
2116 // strOutFile = m_strOutPath;
2117 // strOutFile += "sea_wave_angle_before_";
2118 // strOutFile += to_string(m_ulIter);
2119 // strOutFile += ".tif";
2120 //
2121 // pDriver = GetGDALDriverManager()->GetDriverByName("gtiff");
2122 // pDataSet = pDriver->Create(strOutFile.c_str(), m_nXGridSize, m_nYGridSize, 1, GDT_Float64, m_papszGDALRasterOptions);
2123 // pDataSet->SetProjection(m_strGDALBasementDEMProjection.c_str());
2124 // pDataSet->SetGeoTransform(m_dGeoTransform);
2125 //
2126 // nn = 0;
2127 // pdRaster = new double[m_nXGridSize * m_nYGridSize];
2128 // for (int nY = 0; nY < m_nYGridSize; nY++)
2129 // {
2130 // for (int nX = 0; nX < m_nXGridSize; nX++)
2131 // {
2132 // pdRaster[nn++] = m_pRasterGrid->m_Cell[nX][nY].dGetWaveAngle();
2133 // }
2134 // }
2135 //
2136 // pBand = pDataSet->GetRasterBand(1);
2137 // pBand->SetNoDataValue(m_dMissingValue);
2138 // nRet = pBand->RasterIO(GF_Write, 0, 0, m_nXGridSize, m_nYGridSize, pdRaster, m_nXGridSize, m_nYGridSize, GDT_Float64, 0, 0, NULL);
2139 //
2140 // if (nRet == CE_Failure)
2141 // return RTN_ERR_GRIDCREATE;
2142 //
2143 // GDALClose(pDataSet);
2144 // delete[] pdRaster;
2145 // // DEBUG CODE ===========================================================================================================
2146
2147 // Now put the X and Y directions together and update the raster cells
2148 int n = 0;
2149
2150 for (int nY = 0; nY < nYSize; nY++) {
2151 for (int nX = 0; nX < nXSize; nX++) {
2152 int nActualX = nX + m_nXMinBoundingBox;
2153 int nActualY = nY + m_nYMinBoundingBox;
2154
2155 if (m_pRasterGrid->m_Cell[nActualX][nActualY].bIsInContiguousSea()) {
2156 // Only update sea cells
2157 if (m_pRasterGrid->m_Cell[nActualX][nActualY].nGetPolygonID() == INT_NODATA) {
2158 // This is a deep water sea cell (not in a polygon)
2159 double dDeepWaterWaveHeight = m_pRasterGrid->m_Cell[nActualX][nActualY].dGetCellDeepWaterWaveHeight();
2160 m_pRasterGrid->m_Cell[nActualX][nActualY].SetWaveHeight(dDeepWaterWaveHeight);
2161
2162 double dDeepWaterWaveAngle = m_pRasterGrid->m_Cell[nActualX][nActualY].dGetCellDeepWaterWaveAngle();
2163 m_pRasterGrid->m_Cell[nActualX][nActualY].SetWaveAngle(dDeepWaterWaveAngle);
2164 }
2165
2166 else {
2167 // This is in a polygon so is not a deep water sea cell
2168 double dWaveHeightX;
2169 double dWaveHeightY;
2170
2171 // Safety checks
2172 if ((isnan(VdOutX[n])) || (bFPIsEqual(VdOutX[n], m_dMissingValue, TOLERANCE)))
2173 dWaveHeightX = dXAvg;
2174
2175 else
2176 dWaveHeightX = VdOutX[n];
2177
2178 if ((isnan(VdOutY[n])) || (bFPIsEqual(VdOutY[n], m_dMissingValue, TOLERANCE)))
2179 dWaveHeightY = dYAvg;
2180
2181 else
2182 dWaveHeightY = VdOutY[n];
2183
2184 // Now calculate wave direction
2185 double dWaveHeight = sqrt((dWaveHeightX * dWaveHeightX) + (dWaveHeightY * dWaveHeightY));
2186 double dWaveDir = atan2(dWaveHeightX, dWaveHeightY) * (180 / PI);
2187
2188 // assert(isfinite(dWaveHeight));
2189 // assert(isfinite(dWaveDir));
2190
2191 // Update the cell's wave attributes
2192 m_pRasterGrid->m_Cell[nActualX][nActualY].SetWaveHeight(dWaveHeight);
2193 m_pRasterGrid->m_Cell[nActualX][nActualY].SetWaveAngle(dKeepWithin360(dWaveDir));
2194
2195 // Calculate the wave height-to-depth ratio for this cell, then update the cell's active zone status
2196 double dSeaDepth = m_pRasterGrid->m_Cell[nActualX][nActualY].dGetSeaDepth();
2197
2198 if ((dWaveHeight / dSeaDepth) >= m_dBreakingWaveHeightDepthRatio)
2199 m_pRasterGrid->m_Cell[nActualX][nActualY].SetInActiveZone(true);
2200
2201 // LogStream << " nX = " << nX << " nY = " << nY << " [" << nActualX << "][" << nActualY << "] waveheight = " << dWaveHeight << " dWaveDir = " << dWaveDir << " dKeepWithin360(dWaveDir) = " << dKeepWithin360(dWaveDir) << endl;
2202 }
2203 }
2204
2205 // Increment with safety check
2206 n++;
2207 n = tMin(n, static_cast<int>(VdOutX.size() - 1));
2208 }
2209 }
2210
2211 // // DEBUG CODE ===========================================================================================================
2212 // strOutFile = m_strOutPath;
2213 // strOutFile += "sea_wave_height_after_";
2214 // strOutFile += to_string(m_ulIter);
2215 // strOutFile += ".tif";
2216 //
2217 // pDriver = GetGDALDriverManager()->GetDriverByName("gtiff");
2218 // pDataSet = pDriver->Create(strOutFile.c_str(), m_nXGridSize, m_nYGridSize, 1, GDT_Float64, m_papszGDALRasterOptions);
2219 // pDataSet->SetProjection(m_strGDALBasementDEMProjection.c_str());
2220 // pDataSet->SetGeoTransform(m_dGeoTransform);
2221 //
2222 // nn = 0;
2223 // pdRaster = new double[m_nXGridSize * m_nYGridSize];
2224 // for (int nY = 0; nY < m_nYGridSize; nY++)
2225 // {
2226 // for (int nX = 0; nX < m_nXGridSize; nX++)
2227 // {
2228 // pdRaster[nn++] = m_pRasterGrid->m_Cell[nX][nY].dGetWaveHeight();
2229 // }
2230 // }
2231 //
2232 // pBand = pDataSet->GetRasterBand(1);
2233 // pBand->SetNoDataValue(m_dMissingValue);
2234 // nRet = pBand->RasterIO(GF_Write, 0, 0, m_nXGridSize, m_nYGridSize, pdRaster, m_nXGridSize, m_nYGridSize, GDT_Float64, 0, 0, NULL);
2235 //
2236 // if (nRet == CE_Failure)
2237 // return RTN_ERR_GRIDCREATE;
2238 //
2239 // GDALClose(pDataSet);
2240 // delete[] pdRaster;
2241 // // DEBUG CODE ===========================================================================================================
2242
2243 // // DEBUG CODE ===========================================================================================================
2244 // strOutFile = m_strOutPath;
2245 // strOutFile += "sea_wave_angle_after_";
2246 // strOutFile += to_string(m_ulIter);
2247 // strOutFile += ".tif";
2248 //
2249 // pDriver = GetGDALDriverManager()->GetDriverByName("gtiff");
2250 // pDataSet = pDriver->Create(strOutFile.c_str(), m_nXGridSize, m_nYGridSize, 1, GDT_Float64, m_papszGDALRasterOptions);
2251 // pDataSet->SetProjection(m_strGDALBasementDEMProjection.c_str());
2252 // pDataSet->SetGeoTransform(m_dGeoTransform);
2253 //
2254 // nn = 0;
2255 // pdRaster = new double[m_nXGridSize * m_nYGridSize];
2256 // for (int nY = 0; nY < m_nYGridSize; nY++)
2257 // {
2258 // for (int nX = 0; nX < m_nXGridSize; nX++)
2259 // {
2260 // pdRaster[nn++] = m_pRasterGrid->m_Cell[nX][nY].dGetWaveAngle();
2261 // }
2262 // }
2263 //
2264 // pBand = pDataSet->GetRasterBand(1);
2265 // pBand->SetNoDataValue(m_dMissingValue);
2266 // nRet = pBand->RasterIO(GF_Write, 0, 0, m_nXGridSize, m_nYGridSize, pdRaster, m_nXGridSize, m_nYGridSize, GDT_Float64, 0, 0, NULL);
2267 //
2268 // if (nRet == CE_Failure)
2269 // return RTN_ERR_GRIDCREATE;
2270 //
2271 // GDALClose(pDataSet);
2272 // delete[] pdRaster;
2273 // // DEBUG CODE ===========================================================================================================
2274
2275 return RTN_OK;
2276}
2277
2278//===============================================================================================================================
2280//===============================================================================================================================
2282 // Interpolate deep water height and orientation from multiple user-supplied values
2283 unsigned int nUserPoints = static_cast<unsigned int>(m_VdDeepWaterWaveStationX.size());
2284
2285 // Performance optimization: Enable GDAL threading for interpolation
2286 CPLSetThreadLocalConfigOption("GDAL_NUM_THREADS", "ALL_CPUS");
2287
2288 // Call GDALGridCreate() with the GGA_InverseDistanceToAPower interpolation algorithm. It has following parameters: radius1 is the first radius (X axis if rotation angle is 0) of the search ellipse, set this to zero (the default) to use the whole point array; radius2 is the second radius (Y axis if rotation angle is 0) of the search ellipse, again set this parameter to zero (the default) to use the whole point array; angle is the angle of the search ellipse rotation in degrees (counter clockwise, default 0.0); nodata is the NODATA marker to fill empty points (default 0.0) TODO 086
2289 GDALGridInverseDistanceToAPowerOptions *pOptions = new GDALGridInverseDistanceToAPowerOptions();
2290 pOptions->dfAngle = 0;
2291 pOptions->dfAnisotropyAngle = 0;
2292 pOptions->dfAnisotropyRatio = 0;
2293 pOptions->dfPower = 2; // Reduced from 3 to 2 for faster computation
2294 pOptions->dfSmoothing = 50; // Reduced from 100 to 50 for faster computation
2295 pOptions->dfRadius1 = 0;
2296 pOptions->dfRadius2 = 0;
2297 pOptions->nMaxPoints = 12; // Limit points for faster computation (was 0 = unlimited)
2298 pOptions->nMinPoints = 3; // Minimum points needed for interpolation
2299 pOptions->dfNoDataValue = m_nMissingValue;
2300
2301 // CPLSetConfigOption("CPL_DEBUG", "ON");
2302 // CPLSetConfigOption("GDAL_NUM_THREADS", "1");
2303
2304 // OK, now create a gridded version of wave height: first create the GDAL context TODO 086
2305 // GDALGridContext* pContext = GDALGridContextCreate(GGA_InverseDistanceToAPower, pOptions, nUserPoints, &m_VdDeepWaterWaveStationX[0], &m_VdDeepWaterWaveStationY[0], &m_VdThisIterDeepWaterWaveStationHeight[0], true);
2306 GDALGridContext *pContext = GDALGridContextCreate(GGA_InverseDistanceToAPower, pOptions, nUserPoints, m_VdDeepWaterWaveStationX.data(), m_VdDeepWaterWaveStationY.data(), m_VdThisIterDeepWaterWaveStationHeight.data(), true);
2307
2308 if (pContext == NULL) {
2309 delete pOptions;
2310 return RTN_ERR_GRIDCREATE;
2311 }
2312
2313 // Now process the context
2314 double *dHeightOut = new double[m_ulNumCells];
2315 int nRet = GDALGridContextProcess(pContext, 0, m_nXGridSize - 1, 0, m_nYGridSize - 1, m_nXGridSize, m_nYGridSize, GDT_Float64, dHeightOut, NULL, NULL);
2316
2317 if (nRet == CE_Failure) {
2318 delete[] dHeightOut;
2319 delete pOptions;
2320 return RTN_ERR_GRIDCREATE;
2321 }
2322
2323 // Get rid of the context
2324 GDALGridContextFree(pContext);
2325
2326 // Next create a gridded version of wave orientation: first create the GDAL context
2327 // pContext = GDALGridContextCreate(GGA_InverseDistanceToAPower, pOptions, nUserPoints, &(m_VdDeepWaterWaveStationX[0]), &(m_VdDeepWaterWaveStationY[0]), (&m_VdThisIterDeepWaterWaveStationAngle[0]), true);
2328 pContext = GDALGridContextCreate(GGA_InverseDistanceToAPower, pOptions, nUserPoints, m_VdDeepWaterWaveStationX.data(), m_VdDeepWaterWaveStationY.data(), m_VdThisIterDeepWaterWaveStationAngle.data(), true);
2329
2330 if (pContext == NULL) {
2331 delete[] dHeightOut;
2332 delete pOptions;
2333 return RTN_ERR_GRIDCREATE;
2334 }
2335
2336 // Now process the context TODO 086
2337 double *dAngleOut = new double[m_ulNumCells];
2338 nRet = GDALGridContextProcess(pContext, 0, m_nXGridSize - 1, 0, m_nYGridSize - 1, m_nXGridSize, m_nYGridSize, GDT_Float64, dAngleOut, NULL, NULL);
2339
2340 if (nRet == CE_Failure) {
2341 delete[] dHeightOut;
2342 delete[] dAngleOut;
2343 delete pOptions;
2344 return RTN_ERR_GRIDCREATE;
2345 }
2346
2347 // Get rid of the context
2348 GDALGridContextFree(pContext);
2349
2350 // OK, now create a gridded version of wave period: first create the GDAL context
2351 // pContext = GDALGridContextCreate(GGA_InverseDistanceToAPower, pOptions, nUserPoints, &m_VdDeepWaterWaveStationX[0], &m_VdDeepWaterWaveStationY[0], &m_VdThisIterDeepWaterWaveStationPeriod[0], true);
2352 pContext = GDALGridContextCreate(GGA_InverseDistanceToAPower, pOptions, nUserPoints, m_VdDeepWaterWaveStationX.data(), m_VdDeepWaterWaveStationY.data(), m_VdThisIterDeepWaterWaveStationPeriod.data(), true);
2353
2354 if (pContext == NULL) {
2355 delete pOptions;
2356 return RTN_ERR_GRIDCREATE;
2357 }
2358
2359 // Now process the context TODO 086
2360 double *dPeriopdOut = new double[m_ulNumCells];
2361 nRet = GDALGridContextProcess(pContext, 0, m_nXGridSize - 1, 0, m_nYGridSize - 1, m_nXGridSize, m_nYGridSize, GDT_Float64, dPeriopdOut, NULL, NULL);
2362
2363 if (nRet == CE_Failure) {
2364 delete[] dPeriopdOut;
2365 delete pOptions;
2366 return RTN_ERR_GRIDCREATE;
2367 }
2368
2369 // Get rid of the context
2370 GDALGridContextFree(pContext);
2371
2372 // The output from GDALGridCreate() is in dHeightOut, dAngleOut and dPeriopdOut but must be reversed
2373 vector<double>
2374 VdHeight,
2375 VdAngle,
2376 VdPeriod;
2377
2378 int
2379 n = 0,
2380 nValidHeight = 0,
2381 nValidAngle = 0,
2382 nValidPeriod = 0;
2383
2384 double
2385 dAvgHeight = 0,
2386 dAvgAngle = 0,
2387 dAvgPeriod = 0;
2388
2389 for (int nY = m_nYGridSize - 1; nY >= 0; nY--) {
2390 for (int nX = 0; nX < m_nXGridSize; nX++) {
2391 if (isfinite(dHeightOut[n])) {
2392 VdHeight.push_back(dHeightOut[n]);
2393
2394 dAvgHeight += dHeightOut[n];
2395 nValidHeight++;
2396 }
2397
2398 else {
2399 VdHeight.push_back(m_dMissingValue);
2400 }
2401
2402 if (isfinite(dAngleOut[n])) {
2403 VdAngle.push_back(dAngleOut[n]);
2404
2405 dAvgAngle += dAngleOut[n];
2406 nValidAngle++;
2407 }
2408
2409 else {
2410 VdAngle.push_back(m_dMissingValue);
2411 }
2412
2413 if (isfinite(dPeriopdOut[n])) {
2414 VdPeriod.push_back(dPeriopdOut[n]);
2415
2416 dAvgPeriod += dPeriopdOut[n];
2417 nValidPeriod++;
2418 }
2419
2420 else {
2421 VdPeriod.push_back(m_dMissingValue);
2422 }
2423
2424 // LogStream << " nX = " << nX << " nY = " << nY << " n = " << n << " dHeightOut[n] = " << dHeightOut[n] << " dAngleOut[n] = " << dAngleOut[n] << endl;
2425 n++;
2426 }
2427 }
2428
2429 // Calculate averages
2430 dAvgHeight /= nValidHeight;
2431 dAvgAngle /= nValidAngle;
2432 dAvgPeriod /= nValidPeriod;
2433
2434 // Tidy
2435 delete pOptions;
2436 delete[] dHeightOut;
2437 delete[] dAngleOut;
2438 delete[] dPeriopdOut;
2439
2440 // Now update all raster cells
2441 n = 0;
2442
2443 for (int nY = 0; nY < m_nYGridSize; nY++) {
2444 for (int nX = 0; nX < m_nXGridSize; nX++) {
2445 if (bFPIsEqual(VdHeight[n], m_dMissingValue, TOLERANCE))
2446 m_pRasterGrid->m_Cell[nX][nY].SetCellDeepWaterWaveHeight(dAvgHeight);
2447
2448 else
2449 m_pRasterGrid->m_Cell[nX][nY].SetCellDeepWaterWaveHeight(VdHeight[n]);
2450
2451 if (bFPIsEqual(VdAngle[n], m_dMissingValue, TOLERANCE))
2452 m_pRasterGrid->m_Cell[nX][nY].SetCellDeepWaterWaveAngle(dAvgAngle);
2453
2454 else
2455 m_pRasterGrid->m_Cell[nX][nY].SetCellDeepWaterWaveAngle(VdAngle[n]);
2456
2457 if (bFPIsEqual(VdPeriod[n], m_dMissingValue, TOLERANCE))
2458 m_pRasterGrid->m_Cell[nX][nY].SetCellDeepWaterWavePeriod(dAvgPeriod);
2459
2460 else
2461 m_pRasterGrid->m_Cell[nX][nY].SetCellDeepWaterWavePeriod(VdPeriod[n]);
2462
2463 // LogStream << " [" << nX << "][" << nY << "] deep water wave height = " << m_pRasterGrid->m_Cell[nX][nY].dGetCellDeepWaterWaveHeight() << " deep water wave angle = " << m_pRasterGrid->m_Cell[nX][nY].dGetCellDeepWaterWaveAngle() << endl;
2464 n++;
2465 }
2466 }
2467
2468 // // DEBUG CODE ===========================================================================================================
2469 // string strOutFile = m_strOutPath;
2470 // strOutFile += "init_deep_water_wave_height_";
2471 // strOutFile += to_string(m_ulIter);
2472 // strOutFile += ".tif";
2473 // GDALDriver* pDriver = GetGDALDriverManager()->GetDriverByName("gtiff");
2474 // GDALDataset* pDataSet = pDriver->Create(strOutFile.c_str(), m_nXGridSize, m_nYGridSize, 1, GDT_Float64, m_papszGDALRasterOptions);
2475 // pDataSet->SetProjection(m_strGDALBasementDEMProjection.c_str());
2476 // pDataSet->SetGeoTransform(m_dGeoTransform);
2477 // double* pdRaster = new double[m_ulNumCells];
2478 // int nn = 0;
2479 // for (int nY = 0; nY < m_nYGridSize; nY++)
2480 // {
2481 // for (int nX = 0; nX < m_nXGridSize; nX++)
2482 // {
2483 // // Write this value to the array
2484 // pdRaster[nn] = m_pRasterGrid->m_Cell[nX][nY].dGetCellDeepWaterWaveHeight();
2485 // nn++;
2486 // }
2487 // }
2488 //
2489 // GDALRasterBand* pBand = pDataSet->GetRasterBand(1);
2490 // pBand->SetNoDataValue(m_nMissingValue);
2491 // nRet = pBand->RasterIO(GF_Write, 0, 0, m_nXGridSize, m_nYGridSize, pdRaster, m_nXGridSize, m_nYGridSize, GDT_Float64, 0, 0, NULL);
2492 //
2493 // if (nRet == CE_Failure)
2494 // return RTN_ERR_GRIDCREATE;
2495 //
2496 // GDALClose(pDataSet);
2497 // // DEBUG CODE ===========================================================================================================
2498
2499 // // DEBUG CODE ===========================================================================================================
2500 // strOutFile = m_strOutPath;
2501 // strOutFile += "init_deep_water_wave_angle_";
2502 // strOutFile += to_string(m_ulIter);
2503 // strOutFile += ".tif";
2504 // pDataSet = pDriver->Create(strOutFile.c_str(), m_nXGridSize, m_nYGridSize, 1, GDT_Float64, m_papszGDALRasterOptions);
2505 // pDataSet->SetProjection(m_strGDALBasementDEMProjection.c_str());
2506 // pDataSet->SetGeoTransform(m_dGeoTransform);
2507 // nn = 0;
2508 // for (int nY = 0; nY < m_nYGridSize; nY++)
2509 // {
2510 // for (int nX = 0; nX < m_nXGridSize; nX++)
2511 // {
2512 // // Write this value to the array
2513 // pdRaster[nn] = m_pRasterGrid->m_Cell[nX][nY].dGetCellDeepWaterWaveAngle();
2514 // nn++;
2515 // }
2516 // }
2517 //
2518 // pBand = pDataSet->GetRasterBand(1);
2519 // pBand->SetNoDataValue(m_nMissingValue);
2520 // nRet = pBand->RasterIO(GF_Write, 0, 0, m_nXGridSize, m_nYGridSize, pdRaster, m_nXGridSize, m_nYGridSize, GDT_Float64, 0, 0, NULL);
2521 //
2522 // if (nRet == CE_Failure)
2523 // return RTN_ERR_GRIDCREATE;
2524 //
2525 // GDALClose(pDataSet);
2526 // delete[] pdRaster;
2527 // // DEBUG CODE ===========================================================================================================
2528
2529 return RTN_OK;
2530}
Geometry class used to represent 2D point objects with integer coordinates.
Definition 2di_point.h:29
int m_nLogFileDetail
Definition simulation.h:591
string m_strGDALISSDriverCode
GDAL code for the initial suspended sediment raster file.
vector< string > m_VstrInitialSandConsSedimentFile
The name of the initial sand-sized consolidated sediment GIS file.
bool bWriteRasterGISFile(int const, string const *, int const =0, double const =0)
Writes GIS raster files using GDAL, using data from the RasterGrid array.
int m_nGISMaxSaveDigits
Definition simulation.h:509
int m_nYMinBoundingBox
The minimum y value of the bounding box.
Definition simulation.h:558
string m_strGDALISSProjection
GDAL projection string for the initial suspended sediment raster file.
string m_strInitialSuspSedimentFile
Name of initial suspended sediment file.
void GetRasterOutputMinMax(int const, double &, double &, int const, double const)
Finds the max and min values in order to scale raster output if we cannot write doubles.
vector< string > m_VstrInitialCoarseUnconsSedimentFile
The name of the initial coarse-sized unconsolidated sediment GIS file.
double m_dThisIterSWL
Definition simulation.h:748
string m_strGDALICDataType
GDAL data type of the initial intervention class raster file.
CGeomRasterGrid * m_pRasterGrid
Pointer to the raster grid object.
vector< string > m_VstrGDALICCDataType
GDAL data type for the initial consolidated coarse sediment GIS data.
int m_nXGridSize
The size of the grid in the x direction.
Definition simulation.h:462
vector< double > m_VdDeepWaterWaveStationY
Y coordinate (grid CRS) for deep water wave station.
vector< string > m_VstrGDALICFDataType
GDAL data type for the initial consolidated fine sediment GIS data.
ofstream LogStream
vector< string > m_VstrGDALICCDriverCode
GDAL driver code for the initial consolidated coarse sediment GIS data.
int m_nGISMissingValue
The value for integer missing values, as read from GIS input files.
Definition simulation.h:546
int nReadRasterGISFile(int const, int const)
Reads all other raster GIS datafiles into the RasterGrid array.
vector< string > m_VstrGDALIUFDataType
GDAL data type for the initial unconsolidated fine sediment GIS data.
double m_dGISMissingValue
The value for floating-point missing values, as read from GIS input files.
long m_lGDALMaxCanWrite
Definition simulation.h:611
double m_dSouthEastXExtCRS
Definition simulation.h:679
int m_nMissingValue
Used by CoastalME for integer missing values.
Definition simulation.h:549
vector< CGeomCoastPolygon * > m_pVCoastPolygon
int m_nYGridSize
The size of the grid in the y direction.
Definition simulation.h:465
void InitializeGDALPerformance(void)
Initialize GDAL with performance optimizations.
vector< string > m_VstrGDALIUFProjection
GDAL projection for the initial unconsolidated fine sediment GIS data.
double m_dGeoTransform[6]
Definition simulation.h:731
vector< string > m_VstrGDALICFDriverCode
GDAL driver code for the initial consolidated fine sediment GIS data.
vector< string > m_VstrInitialFineConsSedimentFile
The name of the initial fine-sized consolidated sediment GIS file.
double m_dMissingValue
Used by CoastalME for floating-point missing values.
double m_dInvCellDiagonal
Inverse of m_dCellDiagonal.
Definition simulation.h:701
string m_strGDALLDriverCode
GDAL code for the for the initial landform class raster file.
static double dKeepWithin360(double const)
Constrains the supplied angle to be within 0 and 360 degrees.
vector< string > m_VstrGDALICSDriverCode
GDAL driver code for the initial consolidated sand sediment GIS data.
unsigned long m_ulNumCells
The number of cells in the grid.
Definition simulation.h:627
string m_strGDALISSDataType
GDAL data type for the initial suspended sediment raster file.
vector< string > m_VstrGDALIUCProjection
GDAL projection for the initial unconsolidated coarse sediment GIS data.
bool m_bGDALCanCreate
Is the selected GDAL output file format capable of writing files?
Definition simulation.h:370
string m_strGDALLDataType
GDAL data type for the initial landform class raster file.
string m_strRasterGISOutFormat
Base name for CME raster GIS output files.
int m_nXMaxBoundingBox
The maximum x value of the bounding box.
Definition simulation.h:555
double m_dNorthWestYExtCRS
Definition simulation.h:675
vector< string > m_VstrGDALICSDriverDesc
static string strToLower(string const *)
Returns the lower case version of an string, leaving the original unchanged.
Definition utils.cpp:2388
int nInterpolateWavesToPolygonCells(vector< double > const *, vector< double > const *, vector< double > const *, vector< double > const *)
Interpolates wave properties from all profiles to all within-polygon sea cells, using GDALGridCreate(...
vector< double > m_VdThisIterDeepWaterWaveStationHeight
This-iteration wave height at deep water wave station.
string m_strGDALBasementDEMDriverCode
GDAL code for the basement DEM raster file type.
vector< string > m_VstrGDALIUFDriverCode
GDAL driver code for the initial unconsolidated fine sediment GIS data.
unsigned long m_ulMissingValueBasementCells
The number of basement cells marked with as missing value.
Definition simulation.h:664
string m_strInitialBasementDEMFile
Name of initial basement DEM file.
vector< double > m_VdDeepWaterWaveStationX
X coordinate (grid CRS) for deep water wave station.
double m_dBreakingWaveHeightDepthRatio
Breaking wave height-to-depth ratio.
Definition simulation.h:789
string m_strGDALLProjection
GDAL projection string for the initial landform class raster file.
vector< string > m_VstrInitialSandUnconsSedimentFile
The name of the initial sand-sized unconsolidated sediment GIS file.
string m_strGDALIHProjection
GDAL projection string for the initial intervention height raster file.
string m_strGDALICDriverDesc
GDAL description of the initial intervention class raster file.
vector< string > m_VstrGDALIUSProjection
GDAL projection for the initial unconsolidated sand sediment GIS data.
vector< double > m_VdThisIterDeepWaterWaveStationPeriod
This-iteration wave period at deep water wave station.
double m_dCellDiagonal
Length of a cell's diagonal (in external CRS units)
Definition simulation.h:695
double m_dInvCellSide
Inverse of m_dCellSide.
Definition simulation.h:698
vector< string > m_VstrGDALICFProjection
GDAL projection for the initial consolidated fine sediment GIS data.
double m_dSimElapsed
Time simulated so far, in hours.
Definition simulation.h:710
vector< string > m_VstrGDALICCProjection
GDAL projection for the initial consolidated coarse sediment GIS data.
string m_strGDALLDriverDesc
GDAL description of the initial landform class raster file.
double m_dNorthWestXExtCRS
Definition simulation.h:671
vector< CGeom2DIPoint > m_VEdgeCell
Edge cells.
int nInterpolateAllDeepWaterWaveValues(void)
If the user supplies multiple deep water wave height and angle values, this routine interplates these...
double m_dSouthEastYExtCRS
Definition simulation.h:683
bool m_bGISSaveDigitsSequential
Definition simulation.h:449
vector< string > m_VstrGDALIUSDriverDesc
vector< string > m_VstrInitialFineUnconsSedimentFile
The name of the initial fine-sized unconsolidated sediment GIS file.
string m_strOutPath
Path for all output files.
int m_nYMaxBoundingBox
The maximum y value of the bounding box.
Definition simulation.h:561
vector< string > m_VstrGDALICFDriverDesc
vector< string > m_VstrGDALIUFDriverDesc
vector< string > m_VstrGDALIUSDataType
GDAL data type for the initial unconsolidated sand sediment GIS data.
int m_nGISSave
The save number for GIS files (can be sequential, or the iteration number)
Definition simulation.h:512
string m_strInterventionClassFile
Name of intervention class file.
string m_strGDALBasementDEMDataType
GDAL data type for the basement DEM raster file.
string m_strGDALICProjection
GDAL projection string for the initial intervention class raster file.
long m_lGDALMinCanWrite
Definition simulation.h:615
string m_strGDALISSDriverDesc
GDAL description for the initial suspended sediment raster file.
double m_dTimeStep
The length of an iteration (a time step) in hours.
Definition simulation.h:707
static void AnnounceAllocateMemory(void)
Tells the user that we are now allocating memory.
Definition utils.cpp:410
int m_nXMinBoundingBox
The minimum x value of the bounding box.
Definition simulation.h:552
vector< string > m_VstrGDALIUCDriverCode
GDAL driver code for the initial unconsolidated coarse sediment GIS data.
double m_dCellArea
Area of a cell (in external CRS units)
Definition simulation.h:692
static string strDispTime(double const, bool const, bool const)
strDispTime returns a string formatted as h:mm:ss, given a parameter in seconds, with rounding and fr...
Definition utils.cpp:1569
string m_strGDALBasementDEMDriverDesc
GDAL description of the basement DEM raster file type.
string m_strInitialLandformFile
Name of initial landform file.
string m_strInterventionHeightFile
Name of intervention height file.
vector< string > m_VstrGDALICSDataType
GDAL data type for the initial consolidated sand sediment GIS data.
bool m_bScaleRasterOutput
Scale raster output?
Definition simulation.h:381
vector< string > m_VstrGDALICSProjection
GDAL dprojection for the initial consolidated sand sediment GIS data.
string m_strGDALRasterOutputDriverExtension
GDAL raster output driver file extension.
string m_strGDALBasementDEMProjection
GDAL projection string for the basement DEM raster file.
unsigned long m_ulIter
The number of the current iteration (time step)
Definition simulation.h:618
vector< string > m_VstrInitialCoarseConsSedimentFile
The name of the initial coarse-sized consolidated sediment GIS file.
int nReadRasterBasementDEM(void)
Reads a raster DEM of basement elevation data to the Cell array.
string m_strGDALIHDriverCode
GDAL code for the initial intervention height raster file.
string m_strGDALICDriverCode
GDAL code for the initial intervention class raster file.
double m_dExtCRSGridArea
The area of the grid (in external CRS units)
Definition simulation.h:686
vector< double > m_VdThisIterDeepWaterWaveStationAngle
This-iteration wave orientation at deep water wave station.
double m_dCellSide
Length of a cell side (in external CRS units)
Definition simulation.h:689
vector< string > m_VstrGDALIUCDriverDesc
int nMarkBoundingBoxEdgeCells(void)
Mark cells which are at the edge of a bounding box which represents the valid part of the grid,...
string m_strGDALIHDriverDesc
GDAL description for the initial intervention height raster file.
vector< string > m_VstrGDALICCDriverDesc
string m_strGDALIHDataType
GDAL data type for the initial intervention height raster file.
vector< string > m_VstrGDALIUCDataType
GDAL data type for the initial unconsolidated coarse sediment GIS data.
GDALDataType m_GDALWriteFloatDataType
Definition simulation.h:607
bool m_bGDALCanWriteFloat
Definition simulation.h:374
char ** m_papszGDALRasterOptions
Options for GDAL when handling raster files.
Definition simulation.h:456
vector< string > m_VstrGDALIUSDriverCode
GDAL driver code for the initial unconsolidated sand sediment GIS data.
vector< int > m_VEdgeCellEdge
The grid edge that each edge cell belongs to.
This file contains global definitions for CoastalME.
int const NO_NONZERO_THICKNESS_LAYERS
Definition cme.h:767
int const INT_NODATA
Definition cme.h:474
int const RASTER_PLOT_POLYGON
Definition cme.h:633
string const RASTER_SEA_DEPTH_NAME
Definition cme.h:938
T tMin(T a, T b)
Definition cme.h:1251
double const TOLERANCE
Definition cme.h:811
string const RASTER_SHADOW_DOWNDRIFT_ZONE_NAME
Definition cme.h:1034
string const RASTER_POTENTIAL_BEACH_EROSION_NAME
Definition cme.h:968
string const RASTER_BEACH_MASK_NAME
Definition cme.h:954
string const RASTER_TOTAL_CLIFF_COLLAPSE_DEPOSITION_SAND_NAME
Definition cme.h:1024
string const RASTER_POLYGON_UPDRIFT_OR_DOWNDRIFT_NAME
Definition cme.h:1042
int const RASTER_PLOT_LOCAL_SLOPE_OF_CONSOLIDATED_SEDIMENT
Definition cme.h:630
int const RASTER_PLOT_TOTAL_ACTUAL_BEACH_EROSION
Definition cme.h:646
int const RASTER_PLOT_CLIFF_COLLAPSE_DEPOSITION_SAND
Definition cme.h:616
int const RASTER_PLOT_BEACH_DEPOSITION
Definition cme.h:610
int const RASTER_PLOT_SUSPENDED_SEDIMENT
Definition cme.h:645
string const RASTER_FINE_CONS_NAME
Definition cme.h:996
string const RASTER_SLICE_NAME
Definition cme.h:1030
int const RTN_ERR_DEMFILE
Definition cme.h:705
int const RASTER_PLOT_FINE_UNCONSOLIDATED_SEDIMENT
Definition cme.h:625
string const RASTER_TOP_NAME
Definition cme.h:928
string const RASTER_BEACH_DEPOSITION_NAME
Definition cme.h:976
int const SAND_CONS_RASTER
Definition cme.h:566
string const RASTER_BEACH_PROTECTION_NAME
Definition cme.h:956
int const RTN_ERR_MEMALLOC
Definition cme.h:708
string const ERR
Definition cme.h:890
int const RASTER_PLOT_INUNDATION_MASK
Definition cme.h:628
int const RASTER_PLOT_SEDIMENT_TOP_ELEVATION_ELEV
Definition cme.h:641
string const RASTER_SAND_UNCONS_NAME
Definition cme.h:992
int const RASTER_PLOT_ACTUAL_BEACH_EROSION
Definition cme.h:603
string const RASTER_INUNDATION_MASK_NAME
Definition cme.h:942
string const RASTER_WAVE_PERIOD_NAME
Definition cme.h:950
int const RASTER_PLOT_POTENTIAL_PLATFORM_EROSION_MASK
Definition cme.h:658
int const RTN_ERR_GRIDCREATE
Definition cme.h:749
int const RASTER_PLOT_SAND_CONSOLIDATED_SEDIMENT
Definition cme.h:638
int const RASTER_PLOT_AVG_WAVE_HEIGHT
Definition cme.h:607
string const RASTER_CLIFF_COLLAPSE_EROSION_SAND_NAME
Definition cme.h:1010
string const RASTER_SEDIMENT_TOP_NAME
Definition cme.h:926
string const RASTER_FINE_UNCONS_NAME
Definition cme.h:990
string const RASTER_COAST_NAME
Definition cme.h:1002
int const LF_CAT_DRIFT
Definition cme.h:542
int const RASTER_PLOT_FINE_CONSOLIDATED_SEDIMENT
Definition cme.h:624
string const RASTER_CLIFF_COLLAPSE_EROSION_FINE_NAME
Definition cme.h:1008
string const RASTER_SEDIMENT_INPUT_EVENT_NAME
Definition cme.h:1046
string const RASTER_CLIFF_COLLAPSE_DEPOSITION_SAND_NAME
Definition cme.h:1020
int const RASTER_PLOT_ACTIVE_ZONE
Definition cme.h:602
string const RASTER_ACTIVE_ZONE_NAME
Definition cme.h:1006
string const RASTER_CLIFF_NAME
Definition cme.h:936
int const LOG_FILE_MIDDLE_DETAIL
Definition cme.h:489
string const RASTER_INTERVENTION_HEIGHT_NAME
Definition cme.h:984
string const RASTER_SHADOW_ZONE_NAME
Definition cme.h:1032
int const RASTER_PLOT_DEEP_WATER_WAVE_PERIOD
Definition cme.h:623
int const RTN_ERR_RASTER_FILE_READ
Definition cme.h:706
string const RASTER_COARSE_CONS_NAME
Definition cme.h:1000
int const RASTER_PLOT_TOTAL_CLIFF_COLLAPSE_DEPOSITION_SAND
Definition cme.h:652
string const RASTER_TOTAL_CLIFF_COLLAPSE_EROSION_SAND_NAME
Definition cme.h:1016
double const PI
Definition cme.h:793
int const RASTER_PLOT_COAST
Definition cme.h:620
string const RASTER_ACTUAL_BEACH_EROSION_NAME
Definition cme.h:970
string const RASTER_SETUP_SURGE_RUNUP_FLOOD_MASK_NAME
Definition cme.h:1050
bool bFPIsEqual(const T d1, const T d2, const T dEpsilon)
Definition cme.h:1284
string const RASTER_AVG_WAVE_ORIENTATION_NAME
Definition cme.h:952
string const RASTER_TOTAL_BEACH_DEPOSITION_NAME
Definition cme.h:978
int const RASTER_PLOT_POLYGON_UPDRIFT_OR_DOWNDRIFT
Definition cme.h:635
string const RASTER_TOTAL_CLIFF_COLLAPSE_DEPOSITION_COARSE_NAME
Definition cme.h:1026
int const RASTER_PLOT_POLYGON_GAIN_OR_LOSS
Definition cme.h:634
int const RASTER_PLOT_DEEP_WATER_WAVE_ORIENTATION
Definition cme.h:622
int const RASTER_PLOT_TOTAL_CLIFF_COLLAPSE_EROSION_COARSE
Definition cme.h:651
int const RTN_ERR_BOUNDING_BOX
Definition cme.h:755
int const RASTER_PLOT_SLOPE
Definition cme.h:663
int const RASTER_PLOT_COARSE_UNCONSOLIDATED_SEDIMENT
Definition cme.h:619
int const RASTER_PLOT_AVG_WAVE_ORIENTATION
Definition cme.h:608
int const RASTER_PLOT_WAVE_ORIENTATION
Definition cme.h:657
string const RASTER_SUSP_SED_NAME
Definition cme.h:986
string const RASTER_LOCAL_SLOPE_NAME
Definition cme.h:932
int const RASTER_PLOT_BEACH_MASK
Definition cme.h:611
string const RASTER_AVG_SEA_DEPTH_NAME
Definition cme.h:940
int const RASTER_PLOT_WAVE_FLOOD_LINE
Definition cme.h:662
int const RASTER_PLOT_SEDIMENT_INPUT
Definition cme.h:659
int const RASTER_PLOT_POTENTIAL_BEACH_EROSION
Definition cme.h:636
int const RASTER_PLOT_AVG_SUSPENDED_SEDIMENT
Definition cme.h:606
string const RASTER_AVG_WAVE_HEIGHT_NAME
Definition cme.h:946
int const RASTER_PLOT_TOTAL_POTENTIAL_PLATFORM_EROSION
Definition cme.h:655
string const RASTER_WAVE_FLOOD_LINE_NAME
Definition cme.h:1052
string const RASTER_POTENTIAL_PLATFORM_EROSION_NAME
Definition cme.h:960
int const INTERVENTION_CLASS_RASTER
Definition cme.h:573
string const RASTER_ACTUAL_PLATFORM_EROSION_NAME
Definition cme.h:962
string const RASTER_COARSE_UNCONS_NAME
Definition cme.h:994
int const RASTER_PLOT_INTERVENTION_CLASS
Definition cme.h:626
int const RASTER_PLOT_CLIFF
Definition cme.h:664
string const WARN
Definition cme.h:891
int const RASTER_PLOT_BEACH_PROTECTION
Definition cme.h:612
int const RASTER_PLOT_AVG_SEA_DEPTH
Definition cme.h:605
int const RASTER_PLOT_OVERALL_TOP_ELEVATION
Definition cme.h:632
int const RASTER_PLOT_TOTAL_BEACH_DEPOSITION
Definition cme.h:648
string const RASTER_SETUP_SURGE_FLOOD_MASK_NAME
Definition cme.h:1048
string const RASTER_INTERVENTION_CLASS_NAME
Definition cme.h:982
int const RASTER_PLOT_TOTAL_CLIFF_COLLAPSE_EROSION_FINE
Definition cme.h:649
string const RASTER_WAVE_ORIENTATION_NAME
Definition cme.h:948
int const RASTER_PLOT_TOTAL_CLIFF_COLLAPSE_EROSION_SAND
Definition cme.h:650
string const RASTER_DEEP_WATER_WAVE_ORIENTATION_NAME
Definition cme.h:1036
string const RASTER_POTENTIAL_PLATFORM_EROSION_MASK_NAME
Definition cme.h:958
int const RASTER_PLOT_CLIFF_COLLAPSE_EROSION_FINE
Definition cme.h:613
int const SOUTH
Definition cme.h:499
int const RASTER_PLOT_ACTUAL_PLATFORM_EROSION
Definition cme.h:604
int const LOG_FILE_ALL
Definition cme.h:491
int const EAST
Definition cme.h:497
int const RTN_OK
Definition cme.h:692
string const RASTER_WAVE_HEIGHT_NAME
Definition cme.h:944
int const RASTER_PLOT_INTERVENTION_HEIGHT
Definition cme.h:627
int const SAND_UNCONS_RASTER
Definition cme.h:569
int const RASTER_PLOT_TOTAL_POTENTIAL_BEACH_EROSION
Definition cme.h:654
string const RASTER_TOTAL_POTENTIAL_BEACH_EROSION_NAME
Definition cme.h:972
int const RASTER_PLOT_SAND_UNCONSOLIDATED_SEDIMENT
Definition cme.h:639
string const RASTER_SAND_CONS_NAME
Definition cme.h:998
int const RASTER_PLOT_POTENTIAL_PLATFORM_EROSION
Definition cme.h:637
string const RASTER_BASEMENT_ELEVATION_NAME
Definition cme.h:930
int const FINE_UNCONS_RASTER
Definition cme.h:568
int const COARSE_UNCONS_RASTER
Definition cme.h:570
int const RASTER_PLOT_NORMAL_PROFILE
Definition cme.h:631
double const DBL_NODATA
Definition cme.h:822
int const RASTER_PLOT_CLIFF_COLLAPSE_DEPOSITION_COARSE
Definition cme.h:617
int const RASTER_PLOT_WAVE_HEIGHT
Definition cme.h:656
int const RASTER_PLOT_SHADOW_ZONE
Definition cme.h:643
int const RASTER_PLOT_DEEP_WATER_WAVE_HEIGHT
Definition cme.h:621
string const RASTER_COAST_NORMAL_NAME
Definition cme.h:1004
string const NOTE
Definition cme.h:892
string const RASTER_CLIFF_COLLAPSE_EROSION_COARSE_NAME
Definition cme.h:1012
int const RASTER_PLOT_COARSE_CONSOLIDATED_SEDIMENT
Definition cme.h:618
string const RASTER_LANDFORM_NAME
Definition cme.h:980
int const RASTER_PLOT_TOTAL_ACTUAL_PLATFORM_EROSION
Definition cme.h:647
int const SUSP_SED_RASTER
Definition cme.h:571
int const FINE_CONS_RASTER
Definition cme.h:565
int const COARSE_CONS_RASTER
Definition cme.h:567
int const LF_CAT_CLIFF
Definition cme.h:541
int const RASTER_PLOT_SETUP_SURGE_RUNUP_FLOOD_MASK
Definition cme.h:661
int const RASTER_PLOT_BASEMENT_ELEVATION
Definition cme.h:609
int const RASTER_PLOT_LANDFORM
Definition cme.h:629
string const RASTER_SLOPE_NAME
Definition cme.h:934
string const RASTER_TOTAL_ACTUAL_PLATFORM_EROSION_NAME
Definition cme.h:966
string const RASTER_POLYGON_NAME
Definition cme.h:1028
int const RASTER_PLOT_CLIFF_COLLAPSE_EROSION_COARSE
Definition cme.h:615
T tAbs(T a)
Definition cme.h:1261
string const RASTER_TOTAL_CLIFF_COLLAPSE_EROSION_FINE_NAME
Definition cme.h:1014
int const LANDFORM_RASTER
Definition cme.h:572
int const RASTER_PLOT_SHADOW_DOWNDRIFT_ZONE
Definition cme.h:642
int const RASTER_PLOT_SLICE
Definition cme.h:644
string const RASTER_TOTAL_POTENTIAL_PLATFORM_EROSION_NAME
Definition cme.h:964
string const RASTER_AVG_SUSP_SED_NAME
Definition cme.h:988
string const RASTER_DEEP_WATER_WAVE_HEIGHT_NAME
Definition cme.h:1038
int const INTERVENTION_HEIGHT_RASTER
Definition cme.h:574
string const RASTER_TOTAL_CLIFF_COLLAPSE_EROSION_COARSE_NAME
Definition cme.h:1018
string const RASTER_POLYGON_GAIN_OR_LOSS_NAME
Definition cme.h:1044
int const RASTER_PLOT_TOTAL_CLIFF_COLLAPSE_DEPOSITION_COARSE
Definition cme.h:653
string const RASTER_TOTAL_ACTUAL_BEACH_EROSION_NAME
Definition cme.h:974
int const RASTER_PLOT_CLIFF_COLLAPSE_EROSION_SAND
Definition cme.h:614
int const RASTER_PLOT_SEA_DEPTH
Definition cme.h:640
int const NORTH
Definition cme.h:495
string const RASTER_CLIFF_COLLAPSE_DEPOSITION_COARSE_NAME
Definition cme.h:1022
int const RASTER_PLOT_SETUP_SURGE_FLOOD_MASK
Definition cme.h:660
int const WEST
Definition cme.h:501
Contains CRWCoast definitions.
Contains CGeomRasterGrid definitions.
Contains CSimulation definitions.
double dRound(double const d)
Correctly rounds doubles.