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