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
11
12/* ===============================================================================================================================
13 This file is part of CoastalME, the Coastal Modelling Environment.
14
15 CoastalME is free software; you can redistribute it and/or modify it under
16the terms of the GNU General Public License as published by the Free Software
17Foundation; either version 3 of the License, or (at your option) any later
18version.
19
20 This program is distributed in the hope that it will be useful, but WITHOUT
21ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
22FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
23
24 You should have received a copy of the GNU General Public License along with
25this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave,
26Cambridge, MA 02139, USA.
27===============================================================================================================================*/
28#include <assert.h>
29
30#include <cstdio>
31
32#include <cmath>
33using std::atan2;
34using std::hypot;
35using std::isfinite;
36using std::isnan;
37using std::sqrt;
38
39#include <vector>
40using std::vector;
41
42#include <iostream>
43using std::cerr;
44using std::endl;
45using std::ios;
46
47#include <fstream>
48using std::ifstream;
49
50#include <sstream>
51using std::stringstream;
52
53#include <string>
54using std::to_string;
55
56#include <cpl_conv.h>
57#include <cpl_error.h>
58#include <cpl_string.h>
59#include <gdal.h>
60#include <gdal_alg.h>
61#include <gdal_priv.h>
62
63#include "2di_point.h"
64#include "cme.h"
65#include "coast.h"
66#include "simulation.h"
68
69//===============================================================================================================================
71//===============================================================================================================================
73 // Configure GDAL for optimal performance
74 // Enable GDAL threading - use all available CPU cores
75#ifdef _OPENMP
76 CPLSetConfigOption("GDAL_NUM_THREADS", "ALL_CPUS");
77#else
78 CPLSetConfigOption("GDAL_NUM_THREADS", "4"); // Fallback for non-OpenMP builds
79#endif
80
81 // Optimize GDAL memory usage and caching
82 CPLSetConfigOption("GDAL_CACHEMAX",
83 "1.5GB"); // 2GB cache for large grids (was 1GB)
84 CPLSetConfigOption("GDAL_DISABLE_READDIR_ON_OPEN",
85 "EMPTY_DIR"); // Faster file access
86 CPLSetConfigOption("VSI_CACHE", "TRUE"); // Enable virtual file system cache
87 CPLSetConfigOption("VSI_CACHE_SIZE", "512MB"); // 256MB VSI cache
88
89 // Block and chunk optimizations for raster operations
90 CPLSetConfigOption("GDAL_TIFF_INTERNAL_MASK_TO_8BIT", "YES");
91 CPLSetConfigOption("GDAL_RASTERIO_RESAMPLING",
92 "CUBIC"); // Better for coastal DEM data
93
94 // Grid creation optimizations (for GDALGridCreate performance)
95 CPLSetConfigOption("GDAL_GRID_MAX_POINTS_PER_QUADTREE_LEAF", "1024");
96 // Increased from 512
97 CPLSetConfigOption("GDAL_GRID_POINT_COUNT_THRESHOLD",
98 "100"); // New 2024 option
99
100 // Thread-safe dataset access (GDAL 3.10+)
101 CPLSetConfigOption("GDAL_DATASET_CACHE_SIZE", "64"); // Cache more datasets
102
103 // Compression optimizations for output
104 CPLSetConfigOption("GDAL_TIFF_OVR_BLOCKSIZE",
105 "512"); // Optimal for coastal data
106
107 // Memory allocator optimization for multi-threading
108 CPLSetConfigOption("CPL_VSIL_USE_TEMP_FILE_FOR_RANDOM_WRITE", "YES");
109
110 // Disable GDAL warnings for cleaner output (optional)
111 // CPLSetConfigOption("CPL_LOG", "/dev/null");
112 // Debugging (remove in production)
113 // CPLSetConfigOption("CPL_DEBUG", "ON");
114 // CPLSetConfigOption("GDAL_DEBUG", "ON");
115
117}
118
119 //===============================================================================================================================
121//===============================================================================================================================
123{
124 // Initialize GDAL performance settings (only needs to be done once)
125 static bool bGDALInitialized = false;
126
127 if (! bGDALInitialized)
128 {
130 bGDALInitialized = true;
131 }
132
133 // Use GDAL to create a dataset object, which then opens the DEM file
134 GDALDataset *pGDALDataset = static_cast<GDALDataset*>(GDALOpen(m_strInitialBasementDEMFile.c_str(), GA_ReadOnly));
135
136 if (NULL == pGDALDataset)
137 {
138 // Can't open file (note will already have sent GDAL error message to stdout)
139 cerr << ERR << "cannot open " << m_strInitialBasementDEMFile << " for input: " << CPLGetLastErrorMsg() << endl;
140 return RTN_ERR_DEMFILE;
141 }
142
143 // Opened OK, so get GDAL basement DEM dataset information
144 m_strGDALBasementDEMDriverCode = pGDALDataset->GetDriver()->GetDescription();
145 m_strGDALBasementDEMDriverDesc = pGDALDataset->GetDriver()->GetMetadataItem(GDAL_DMD_LONGNAME);
146 m_strGDALBasementDEMProjection = pGDALDataset->GetProjectionRef();
147
149 {
150 // TODO
152 // pGDALDataset->SetProjectionRef(m_strGDALBasementDEMProjection);
153
154// ENGCRS["Plane",
155// EDATUM["Unknown engineering datum"],
156// CS[Cartesian,2],
157// AXIS["(E)",east,
158// ORDER[1],
159// LENGTHUNIT["Meter",1]],
160// AXIS["(N)",north,
161// ORDER[2],
162// LENGTHUNIT["Meter",1]]]
163 }
164 else
165 {
166 // We have reference units, so check that they are in metres (note US spelling)
167 if (! m_strGDALBasementDEMProjection.empty())
168 {
169 string const strTmp = strToLower(&m_strGDALBasementDEMProjection);
170
171 if ((strTmp.find("meter") == string::npos) && (strTmp.find("metre") == string::npos))
172 {
173 // error: x-y values must be in metres
174 cerr << ERR << "GIS file x-y values (" << m_strGDALBasementDEMProjection << ") in " << m_strInitialBasementDEMFile << " must be in metres" << endl;
175 return RTN_ERR_DEMFILE;
176 }
177 }
178 }
179
180 // Now get dataset size, and do some rudimentary checks
181 m_nXGridSize = pGDALDataset->GetRasterXSize();
182
183 if (m_nXGridSize == 0)
184 {
185 // Error: silly number of columns specified
186 cerr << ERR << "invalid number of columns (" << m_nXGridSize << ") in " << m_strInitialBasementDEMFile << endl;
187 return RTN_ERR_DEMFILE;
188 }
189
190 m_nYGridSize = pGDALDataset->GetRasterYSize();
191
192 if (m_nYGridSize == 0)
193 {
194 // Error: silly number of rows specified
195 cerr << ERR << "invalid number of rows (" << m_nYGridSize << ") in " << m_strInitialBasementDEMFile << endl;
196 return RTN_ERR_DEMFILE;
197 }
198
199 // Get geotransformation info (see http://www.gdal.org/classGDALDataset.html)
200 if (CE_Failure == pGDALDataset->GetGeoTransform(m_dGeoTransform))
201 {
202 // Can't get geotransformation (note will already have sent GDAL error message to stdout)
203 cerr << ERR << CPLGetLastErrorMsg() << " in " << m_strInitialBasementDEMFile << endl;
204 return RTN_ERR_DEMFILE;
205 }
206
207 // 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
208 if ((! bFPIsEqual(m_dGeoTransform[2], 0.0, TOLERANCE)) || (! bFPIsEqual(m_dGeoTransform[4], 0.0, TOLERANCE)))
209 {
210 // Error: not oriented NS and W-E
211 cerr << ERR << m_strInitialBasementDEMFile << " is not oriented N-S and W-E. Row rotation = " << m_dGeoTransform[2] << " and column rotation = " << m_dGeoTransform[4] << endl;
213 }
214
215 // 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
216 double const dCellSideX = tAbs(m_dGeoTransform[1]);
217 double const dCellSideY = tAbs(m_dGeoTransform[5]);
218
219 // Check that the cell is more or less square
220 if (! bFPIsEqual(dCellSideX, dCellSideY, 1e-2))
221 {
222 // Error: cell is not square enough
223 cerr << ERR << "cell is not square in " << m_strInitialBasementDEMFile << ", is " << dCellSideX << " x " << dCellSideY << endl;
225 }
226
227 // Calculate the average length of cell side, the cell's diagonal, and the area of a cell (in external CRS units)
228 m_dCellSide = (dCellSideX + dCellSideY) / 2.0;
231
232 // And calculate the inverse values
235
236 // Save some values in external CRS
241
242 // And calc the grid area in external CRS units
244
245 // Now get GDAL raster band information
246 GDALRasterBand *pGDALBand = pGDALDataset->GetRasterBand(1);
247 int nBlockXSize = 0, nBlockYSize = 0;
248 pGDALBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
249 m_strGDALBasementDEMDataType = GDALGetDataTypeName(pGDALBand->GetRasterDataType());
250
251 // If we have value units, then check them
252 string const strUnits = pGDALBand->GetUnitType();
253
254 if ((!strUnits.empty()) && (strUnits.find('m') == string::npos))
255 {
256 // Error: value units must be m
257 cerr << ERR << "DEM vertical units are (" << strUnits << " ) in " << m_strInitialBasementDEMFile << ", should be 'm'" << endl;
258 return RTN_ERR_DEMFILE;
259 }
260
261 // If present, get the missing value (NODATA) setting
262 CPLPushErrorHandler(CPLQuietErrorHandler); // Needed to get next line to fail silently, if it fails
263 double const dMissingValue = pGDALBand->GetNoDataValue(); // Will fail for some formats
264 CPLPopErrorHandler();
265
266 if (! bFPIsEqual(dMissingValue, m_dMissingValue, TOLERANCE))
267 {
268 cerr << " " << NOTE << "NODATA value in " << m_strInitialBasementDEMFile << " is " << dMissingValue << "\n instead using CoastalME's default floating-point NODATA value " << m_dMissingValue << endl;
269 }
270
271 // Next allocate memory for a 2D array of raster cell objects: tell the user what is happening
273 int const nRet = m_pRasterGrid->nCreateGrid();
274
275 if (nRet != RTN_OK)
276 return nRet;
277
278 // Allocate memory for a 1D floating-point array, to hold the scan line for GDAL
279 double *pdScanline = new double[m_nXGridSize];
280
281 if (NULL == pdScanline)
282 {
283 // Error, can't allocate memory
284 cerr << ERR << "cannot allocate memory for " << m_nXGridSize << " x 1D array" << endl;
285 return (RTN_ERR_MEMALLOC);
286 }
287
288 // Now read in the data
289 for (int j = 0; j < m_nYGridSize; j++)
290 {
291 // Read scanline
292 if (CE_Failure == pGDALBand->RasterIO(GF_Read, 0, j, m_nXGridSize, 1, pdScanline, m_nXGridSize, 1, GDT_Float64, 0, 0, NULL))
293 {
294 // Error while reading scanline
295 cerr << ERR << CPLGetLastErrorMsg() << " in " << m_strInitialBasementDEMFile << endl;
296 return RTN_ERR_DEMFILE;
297 }
298
299 // All OK, so read scanline into cell elevations (including any missing values)
300 for (int i = 0; i < m_nXGridSize; i++)
301 {
302 double dTmp = pdScanline[i];
303
304 if ((isnan(dTmp)) || (bFPIsEqual(dTmp, m_dGISMissingValue, TOLERANCE)))
305 dTmp = m_dMissingValue;
306
307 m_pRasterGrid->m_Cell[i][j].SetBasementElev(dTmp);
308 }
309 }
310
311 // Finished, so get rid of dataset object
312 GDALClose(pGDALDataset);
313
314 // Get rid of memory allocated to this array
315 delete[] pdScanline;
316
317 return RTN_OK;
318}
319
320//===============================================================================================================================
326//===============================================================================================================================
328 // The bounding box must touch the edge of the grid at least once on each side
329 // of the grid, so store these points. Search in a clockwise direction around
330 // the edge of the grid
331 vector<CGeom2DIPoint> VPtiBoundingBoxCorner;
332
333 // Start with the top (north) edge
334 bool bFound = false;
335
336 for (int nX = 0; nX < m_nXGridSize; nX++) {
337 if (bFound)
338 break;
339
340 for (int nY = 0; nY < m_nYGridSize; nY++) {
341 if (!m_pRasterGrid->m_Cell[nX][nY].bBasementElevIsMissingValue()) {
342 CGeom2DIPoint const PtiTmp(nX, nY);
343 VPtiBoundingBoxCorner.push_back(PtiTmp);
344 bFound = true;
345 break;
346 }
347 }
348 }
349
350 if (!bFound) {
352 LogStream << m_ulIter << ": north (top) edge of bounding box not found"
353 << endl;
354
356 }
357
358 // Do the same for the right (east) edge
359 bFound = false;
360
361 for (int nY = 0; nY < m_nYGridSize; nY++) {
362 if (bFound)
363 break;
364
365 for (int nX = m_nXGridSize - 1; nX >= 0; nX--) {
366 if (!m_pRasterGrid->m_Cell[nX][nY].bBasementElevIsMissingValue()) {
367 CGeom2DIPoint const PtiTmp(nX, nY);
368 VPtiBoundingBoxCorner.push_back(PtiTmp);
369 bFound = true;
370 break;
371 }
372 }
373 }
374
375 if (!bFound) {
377 LogStream << m_ulIter << ": east (right) edge of bounding box not found"
378 << endl;
379
381 }
382
383 // Do the same for the south (bottom) edge
384 bFound = false;
385
386 for (int nX = m_nXGridSize - 1; nX >= 0; nX--) {
387 if (bFound)
388 break;
389
390 for (int nY = m_nYGridSize - 1; nY >= 0; nY--) {
391 if (!m_pRasterGrid->m_Cell[nX][nY].bBasementElevIsMissingValue()) {
392 CGeom2DIPoint const PtiTmp(nX, nY);
393 VPtiBoundingBoxCorner.push_back(PtiTmp);
394 bFound = true;
395 break;
396 }
397 }
398 }
399
400 if (!bFound) {
402 LogStream << m_ulIter << ": south (bottom) edge of bounding box not found"
403 << endl;
404
406 }
407
408 // And finally repeat for the west (left) edge
409 bFound = false;
410
411 for (int nY = m_nYGridSize - 1; nY >= 0; nY--) {
412 if (bFound)
413 break;
414
415 for (int nX = 0; nX < m_nXGridSize; nX++) {
416 if (!m_pRasterGrid->m_Cell[nX][nY].bBasementElevIsMissingValue()) {
417 CGeom2DIPoint const PtiTmp(nX, nY);
418 VPtiBoundingBoxCorner.push_back(PtiTmp);
419 bFound = true;
420 break;
421 }
422 }
423 }
424
425 if (!bFound) {
427 LogStream << m_ulIter << ": west (left) edge of bounding box not found"
428 << endl;
429
431 }
432
433 // OK, so we have a point on each side of the grid, so start at this point and
434 // find the edges of the bounding box. Go round in a clockwise direction: top
435 // (north) edge first
436 for (int nX = VPtiBoundingBoxCorner[0].nGetX();
437 nX <= VPtiBoundingBoxCorner[1].nGetX(); nX++) {
438 bFound = false;
439
440 for (int nY = VPtiBoundingBoxCorner[0].nGetY(); nY < m_nYGridSize; nY++) {
441 if (m_pRasterGrid->m_Cell[nX][nY].bBasementElevIsMissingValue()) {
443 continue;
444 }
445
446 // Found a bounding box edge cell
447 m_pRasterGrid->m_Cell[nX][nY].SetBoundingBoxEdge(NORTH);
448
449 m_VEdgeCell.push_back(CGeom2DIPoint(nX, nY));
450 m_VEdgeCellEdge.push_back(NORTH);
451
452 bFound = true;
453 break;
454 }
455
456 if (!bFound) {
459 << m_ulIter
460 << ": could not find a bounding box edge cell for grid column "
461 << nX << endl;
462
464 }
465 }
466
467 // Right (east) edge
468 for (int nY = VPtiBoundingBoxCorner[1].nGetY();
469 nY <= VPtiBoundingBoxCorner[2].nGetY(); nY++) {
470 bFound = false;
471
472 for (int nX = VPtiBoundingBoxCorner[1].nGetX(); nX >= 0; nX--) {
473 if (m_pRasterGrid->m_Cell[nX][nY].bBasementElevIsMissingValue()) {
475 continue;
476 }
477
478 // Found a bounding box edge cell
479 m_pRasterGrid->m_Cell[nX][nY].SetBoundingBoxEdge(EAST);
480
481 m_VEdgeCell.push_back(CGeom2DIPoint(nX, nY));
482 m_VEdgeCellEdge.push_back(EAST);
483
484 bFound = true;
485 break;
486 }
487
488 if (!bFound) {
491 << ": could not find a bounding box edge cell for grid row "
492 << nY << endl;
493
495 }
496 }
497
498 // Bottom (south) edge
499 for (int nX = VPtiBoundingBoxCorner[2].nGetX();
500 nX >= VPtiBoundingBoxCorner[3].nGetX(); nX--) {
501 bFound = false;
502
503 for (int nY = VPtiBoundingBoxCorner[2].nGetY(); nY >= 0; nY--) {
504 if (m_pRasterGrid->m_Cell[nX][nY].bBasementElevIsMissingValue()) {
506 continue;
507 }
508
509 // Found a bounding box edge cell
510 m_pRasterGrid->m_Cell[nX][nY].SetBoundingBoxEdge(SOUTH);
511
512 m_VEdgeCell.push_back(CGeom2DIPoint(nX, nY));
513 m_VEdgeCellEdge.push_back(SOUTH);
514
515 bFound = true;
516 break;
517 }
518
519 if (!bFound) {
522 << m_ulIter
523 << ": could not find a bounding box edge cell for grid column "
524 << nX << endl;
525
527 }
528 }
529
530 // Left (west) edge
531 for (int nY = VPtiBoundingBoxCorner[3].nGetY();
532 nY >= VPtiBoundingBoxCorner[0].nGetY(); nY--) {
533 for (int nX = VPtiBoundingBoxCorner[3].nGetX(); nX < m_nXGridSize - 1; nX++)
534 // for (int nX = VPtiBoundingBoxCorner[3].nGetX(); nX <
535 // VPtiBoundingBoxCorner[3].nGetX(); nX++)
536 {
537 if (m_pRasterGrid->m_Cell[nX][nY].bBasementElevIsMissingValue()) {
539 continue;
540 }
541
542 // Found a bounding box edge cell
543 m_pRasterGrid->m_Cell[nX][nY].SetBoundingBoxEdge(WEST);
544
545 m_VEdgeCell.push_back(CGeom2DIPoint(nX, nY));
546 m_VEdgeCellEdge.push_back(WEST);
547
548 bFound = true;
549 break;
550 }
551
552 if (!bFound) {
555 << ": could not find a bounding box edge cell for grid row "
556 << nY << endl;
557
559 }
560 }
561
562 return RTN_OK;
563}
564
565//===============================================================================================================================
567//===============================================================================================================================
568int CSimulation::nReadRasterGISFile(int const nDataItem, int const nLayer) {
569 string strGISFile;
570 string strDriverCode;
571 string strDriverDesc;
572 string strProjection;
573 string strDataType;
574
575 switch (nDataItem) {
576 case (LANDFORM_RASTER):
577 // Initial Landform Class GIS data
578 strGISFile = m_strInitialLandformFile;
579 break;
580
582 // Intervention class
583 strGISFile = m_strInterventionClassFile;
584 break;
585
587 // Intervention height
588 strGISFile = m_strInterventionHeightFile;
589 break;
590
591 case (SUSP_SED_RASTER):
592 // Initial Suspended Sediment GIS data
593 strGISFile = m_strInitialSuspSedimentFile;
594 break;
595
596 case (FINE_UNCONS_RASTER):
597 // Initial Unconsolidated Fine Sediment GIS data
598 strGISFile = m_VstrInitialFineUnconsSedimentFile[nLayer];
599 break;
600
601 case (SAND_UNCONS_RASTER):
602 // Initial Unconsolidated Sand Sediment GIS data
603 strGISFile = m_VstrInitialSandUnconsSedimentFile[nLayer];
604 break;
605
607 // Initial Unconsolidated Coarse Sediment GIS data
608 strGISFile = m_VstrInitialCoarseUnconsSedimentFile[nLayer];
609 break;
610
611 case (FINE_CONS_RASTER):
612 // Initial Consolidated Fine Sediment GIS data
613 strGISFile = m_VstrInitialFineConsSedimentFile[nLayer];
614 break;
615
616 case (SAND_CONS_RASTER):
617 // Initial Consolidated Sand Sediment GIS data
618 strGISFile = m_VstrInitialSandConsSedimentFile[nLayer];
619 break;
620
621 case (COARSE_CONS_RASTER):
622 // Initial Consolidated Coarse Sediment GIS data
623 strGISFile = m_VstrInitialCoarseConsSedimentFile[nLayer];
624 break;
625 }
626
627 // Use GDAL to create a dataset object, which then opens the GIS file
628 GDALDataset *pGDALDataset =
629 static_cast<GDALDataset *>(GDALOpen(strGISFile.c_str(), GA_ReadOnly));
630
631 if (NULL == pGDALDataset) {
632 // Can't open file (note will already have sent GDAL error message to
633 // stdout)
634 cerr << ERR << "cannot open " << strGISFile
635 << " for input: " << CPLGetLastErrorMsg() << endl;
637 }
638
639 // Opened OK, so get dataset information
640 strDriverCode = pGDALDataset->GetDriver()->GetDescription();
641 strDriverDesc = pGDALDataset->GetDriver()->GetMetadataItem(GDAL_DMD_LONGNAME);
642 strProjection = pGDALDataset->GetProjectionRef();
643
644 // Get geotransformation info
645 double dGeoTransform[6];
646 if (CE_Failure == pGDALDataset->GetGeoTransform(dGeoTransform)) {
647 // Can't get geotransformation (note will already have sent GDAL error
648 // message to stdout)
649 cerr << ERR << CPLGetLastErrorMsg() << " in " << strGISFile << endl;
651 }
652
653 // Now get dataset size, and do some checks
654 int const nTmpXSize = pGDALDataset->GetRasterXSize();
655 if (nTmpXSize != m_nXGridSize) {
656 // Error: incorrect number of columns specified
657 cerr << ERR << "different number of columns in " << strGISFile << " ("
658 << nTmpXSize << ") and " << m_strInitialBasementDEMFile << "("
659 << m_nXGridSize << ")" << endl;
661 }
662
663 int const nTmpYSize = pGDALDataset->GetRasterYSize();
664 if (nTmpYSize != m_nYGridSize) {
665 // Error: incorrect number of rows specified
666 cerr << ERR << "different number of rows in " << strGISFile << " ("
667 << nTmpYSize << ") and " << m_strInitialBasementDEMFile << " ("
668 << m_nYGridSize << ")" << endl;
670 }
671
672 double dTmp = m_dGeoTransform[0] - (m_dGeoTransform[1] / 2);
674 // Error: different min x from DEM file
675 cerr << ERR << "different min x values in " << strGISFile << " (" << dTmp
676 << ") and " << m_strInitialBasementDEMFile << " ("
677 << m_dNorthWestXExtCRS << ")" << endl;
679 }
680
681 dTmp = m_dGeoTransform[3] - (m_dGeoTransform[5] / 2);
683 // Error: different min x from DEM file
684 cerr << ERR << "different min y values in " << strGISFile << " (" << dTmp
685 << ") and " << m_strInitialBasementDEMFile << " ("
686 << m_dNorthWestYExtCRS << ")" << endl;
688 }
689
690 double const dTmpResX = tAbs(dGeoTransform[1]);
691 if (!bFPIsEqual(dTmpResX, m_dCellSide, 1e-2)) {
692 // Error: different cell size in X direction: note that due to rounding
693 // errors in some GIS packages, must expect some discrepancies
694 cerr << ERR << "cell size in X direction (" << dTmpResX << ") in "
695 << strGISFile << " differs from cell size in of basement DEM ("
696 << m_dCellSide << ")" << endl;
698 }
699
700 double const dTmpResY = tAbs(dGeoTransform[5]);
701 if (!bFPIsEqual(dTmpResY, m_dCellSide, 1e-2)) {
702 // Error: different cell size in Y direction: note that due to rounding
703 // errors in some GIS packages, must expect some discrepancies
704 cerr << ERR << "cell size in Y direction (" << dTmpResY << ") in "
705 << strGISFile << " differs from cell size of basement DEM ("
706 << m_dCellSide << ")" << endl;
708 }
709
710 // Now get GDAL raster band information
711 GDALRasterBand *pGDALBand = pGDALDataset->GetRasterBand(
712 1); // TODO 028 Give a message if there are several bands
713 int nBlockXSize = 0, nBlockYSize = 0;
714 pGDALBand->GetBlockSize(&nBlockXSize, &nBlockYSize);
715 strDataType = GDALGetDataTypeName(pGDALBand->GetRasterDataType());
716
717 switch (nDataItem) {
718 case (LANDFORM_RASTER):
719 // Initial Landform Class GIS data
720 m_strGDALLDriverCode = strDriverCode;
721 m_strGDALLDriverDesc = strDriverDesc;
722 m_strGDALLProjection = strProjection;
723 m_strGDALLDataType = strDataType;
724 break;
725
727 // Intervention class
728 m_strGDALICDriverCode = strDriverCode;
729 m_strGDALICDriverDesc = strDriverDesc;
730 m_strGDALICProjection = strProjection;
731 m_strGDALICDataType = strDataType;
732 break;
733
735 // Intervention height
736 m_strGDALIHDriverCode = strDriverCode;
737 m_strGDALIHDriverDesc = strDriverDesc;
738 m_strGDALIHProjection = strProjection;
739 m_strGDALIHDataType = strDataType;
740 break;
741
742 case (SUSP_SED_RASTER):
743 // Initial Suspended Sediment GIS data
744 m_strGDALISSDriverCode = strDriverCode;
745 m_strGDALISSDriverDesc = strDriverDesc;
746 m_strGDALISSProjection = strProjection;
747 m_strGDALISSDataType = strDataType;
748 break;
749
750 case (FINE_UNCONS_RASTER):
751 // Initial Unconsolidated Fine Sediment GIS data
752 m_VstrGDALIUFDriverCode[nLayer] = strDriverCode;
753 m_VstrGDALIUFDriverDesc[nLayer] = strDriverDesc;
754 m_VstrGDALIUFProjection[nLayer] = strProjection;
755 m_VstrGDALIUFDataType[nLayer] = strDataType;
756 break;
757
758 case (SAND_UNCONS_RASTER):
759 // Initial Unconsolidated Sand Sediment GIS data
760 m_VstrGDALIUSDriverCode[nLayer] = strDriverCode;
761 m_VstrGDALIUSDriverDesc[nLayer] = strDriverDesc;
762 m_VstrGDALIUSProjection[nLayer] = strProjection;
763 m_VstrGDALIUSDataType[nLayer] = strDataType;
764 break;
765
767 // Initial Unconsolidated Coarse Sediment GIS data
768 m_VstrGDALIUCDriverCode[nLayer] = strDriverCode;
769 m_VstrGDALIUCDriverDesc[nLayer] = strDriverDesc;
770 m_VstrGDALIUCProjection[nLayer] = strProjection;
771 m_VstrGDALIUCDataType[nLayer] = strDataType;
772 break;
773
774 case (FINE_CONS_RASTER):
775 // Initial Consolidated Fine Sediment GIS data
776 m_VstrGDALICFDriverCode[nLayer] = strDriverCode;
777 m_VstrGDALICFDriverDesc[nLayer] = strDriverDesc;
778 m_VstrGDALICFProjection[nLayer] = strProjection;
779 m_VstrGDALICFDataType[nLayer] = strDataType;
780 break;
781
782 case (SAND_CONS_RASTER):
783 // Initial Consolidated Sand Sediment GIS data
784 m_VstrGDALICSDriverCode[nLayer] = strDriverCode;
785 m_VstrGDALICSDriverDesc[nLayer] = strDriverDesc;
786 m_VstrGDALICSProjection[nLayer] = strProjection;
787 m_VstrGDALICSDataType[nLayer] = strDataType;
788 break;
789
790 case (COARSE_CONS_RASTER):
791 // Initial Consolidated Coarse Sediment GIS data
792 m_VstrGDALICCDriverCode[nLayer] = strDriverCode;
793 m_VstrGDALICCDriverDesc[nLayer] = strDriverDesc;
794 m_VstrGDALICCProjection[nLayer] = strProjection;
795 m_VstrGDALICCDataType[nLayer] = strDataType;
796 break;
797 }
798
799 // If present, get the missing value setting
800 string const strTmp = strToLower(&strDataType);
801 if (strTmp.find("int") != string::npos) {
802 // This is an integer layer
803 CPLPushErrorHandler(CPLQuietErrorHandler); // Needed to get next line to
804 // fail silently, if it fails
805 m_nGISMissingValue = static_cast<int>(
806 pGDALBand->GetNoDataValue()); // Note will fail for some formats
807 CPLPopErrorHandler();
808
810 cerr
811 << " " << NOTE << "NODATA value in " << strGISFile << " is "
813 << "\n instead using CoatalME's default integer NODATA value "
814 << m_nMissingValue << endl;
815 }
816 } else {
817 // This is a floating point layer
818 CPLPushErrorHandler(CPLQuietErrorHandler); // Needed to get next line to
819 // fail silently, if it fails
821 pGDALBand->GetNoDataValue(); // Note will fail for some formats
822 CPLPopErrorHandler();
823
825 cerr << " " << NOTE << "NODATA value in " << strGISFile << " is "
827 << "\n instead using CoastalME's default floating-point "
828 "NODATA value "
829 << m_dMissingValue << endl;
830 }
831 }
832
833 // Allocate memory for a 1D array, to hold the scan line for GDAL
834 double *pdScanline = new double[m_nXGridSize];
835 if (NULL == pdScanline) {
836 // Error, can't allocate memory
837 cerr << ERR << "cannot allocate memory for " << m_nXGridSize
838 << " x 1D array" << endl;
839 return (RTN_ERR_MEMALLOC);
840 }
841
842 // Now read in the data
843 int nMissing = 0;
844
845 for (int nY = 0; nY < m_nYGridSize; nY++) {
846 // Read scanline
847 if (CE_Failure == pGDALBand->RasterIO(GF_Read, 0, nY, m_nXGridSize, 1,
848 pdScanline, m_nXGridSize, 1,
849 GDT_Float64, 0, 0, NULL)) {
850 // Error while reading scanline
851 cerr << ERR << CPLGetLastErrorMsg() << " in " << strGISFile << endl;
853 }
854
855 // All OK, so read scanline into cells (including any missing values)
856 for (int nX = 0; nX < m_nXGridSize; nX++) {
857 int nTmp;
858
859 switch (nDataItem) {
860 case (LANDFORM_RASTER):
861 // Initial Landform Class GIS data, is integer TODO 030 Do we also need
862 // a landform sub-category input?
863 nTmp = static_cast<int>(pdScanline[nX]);
864
865 if ((isnan(nTmp)) || (nTmp == m_nGISMissingValue)) {
866 nTmp = m_nMissingValue;
867 nMissing++;
868 }
869
870 m_pRasterGrid->m_Cell[nX][nY].pGetLandform()->SetLFCategory(nTmp);
871 break;
872
874 // Intervention class, is integer. If not an intervention, show INT_NODATA
875 nTmp = static_cast<int>(pdScanline[nX]);
876
877 if ((isnan(nTmp)) || (nTmp == m_nGISMissingValue))
878 {
879 nTmp = m_nMissingValue;
880 nMissing++;
881 }
882
883 m_pRasterGrid->m_Cell[nX][nY].pGetLandform()->SetLFCategory(nTmp);
884 break;
885
887 // Intervention height
888 dTmp = pdScanline[nX];
889
890 if ((isnan(dTmp)) ||
892 dTmp = m_dMissingValue;
893 nMissing++;
894 }
895
896 m_pRasterGrid->m_Cell[nX][nY].SetInterventionHeight(dTmp);
897 break;
898
899 case (SUSP_SED_RASTER):
900 // Initial Suspended Sediment GIS data
901 dTmp = pdScanline[nX];
902
903 if ((isnan(dTmp)) ||
905 dTmp = m_dMissingValue;
906 nMissing++;
907 }
908
909 m_pRasterGrid->m_Cell[nX][nY].SetSuspendedSediment(dTmp);
910 break;
911
912 case (FINE_UNCONS_RASTER):
913 // Initial Unconsolidated Fine Sediment GIS data
914 dTmp = pdScanline[nX];
915
916 if ((isnan(dTmp)) ||
918 dTmp = m_dMissingValue;
919 nMissing++;
920 }
921
922 m_pRasterGrid->m_Cell[nX][nY]
923 .pGetLayerAboveBasement(nLayer)
924 ->pGetUnconsolidatedSediment()
925 ->SetFineDepth(dTmp);
926 break;
927
928 case (SAND_UNCONS_RASTER):
929 // Initial Unconsolidated Sand Sediment GIS data
930 dTmp = pdScanline[nX];
931
932 if ((isnan(dTmp)) ||
934 dTmp = m_dMissingValue;
935 nMissing++;
936 }
937
938 m_pRasterGrid->m_Cell[nX][nY]
939 .pGetLayerAboveBasement(nLayer)
940 ->pGetUnconsolidatedSediment()
941 ->SetSandDepth(dTmp);
942 break;
943
945 // Initial Unconsolidated Coarse Sediment GIS data
946 dTmp = pdScanline[nX];
947
948 if ((isnan(dTmp)) ||
950 dTmp = m_dMissingValue;
951 nMissing++;
952 }
953
954 m_pRasterGrid->m_Cell[nX][nY]
955 .pGetLayerAboveBasement(nLayer)
956 ->pGetUnconsolidatedSediment()
957 ->SetCoarseDepth(dTmp);
958 break;
959
960 case (FINE_CONS_RASTER):
961 // Initial Consolidated Fine Sediment GIS data
962 dTmp = pdScanline[nX];
963
964 if ((isnan(dTmp)) ||
966 dTmp = m_dMissingValue;
967 nMissing++;
968 }
969
970 m_pRasterGrid->m_Cell[nX][nY]
971 .pGetLayerAboveBasement(nLayer)
972 ->pGetConsolidatedSediment()
973 ->SetFineDepth(dTmp);
974 break;
975
976 case (SAND_CONS_RASTER):
977 // Initial Consolidated Sand Sediment GIS data
978 dTmp = pdScanline[nX];
979
980 if ((isnan(dTmp)) ||
982 dTmp = m_dMissingValue;
983 nMissing++;
984 }
985
986 m_pRasterGrid->m_Cell[nX][nY]
987 .pGetLayerAboveBasement(nLayer)
988 ->pGetConsolidatedSediment()
989 ->SetSandDepth(dTmp);
990 break;
991
992 case (COARSE_CONS_RASTER):
993 // Initial Consolidated Coarse Sediment GIS data
994 dTmp = pdScanline[nX];
995
996 if ((isnan(dTmp)) ||
998 dTmp = m_dMissingValue;
999 nMissing++;
1000 }
1001
1002 m_pRasterGrid->m_Cell[nX][nY]
1003 .pGetLayerAboveBasement(nLayer)
1004 ->pGetConsolidatedSediment()
1005 ->SetCoarseDepth(dTmp);
1006 break;
1007 }
1008 }
1009 }
1010
1011 // Finished, so get rid of dataset object
1012 GDALClose(pGDALDataset);
1013
1014 // Get rid of memory allocated to this array
1015 delete[] pdScanline;
1016
1017 if (nMissing > 0) {
1018 cerr << WARN << nMissing << " missing values in " << strGISFile << endl;
1019 LogStream << WARN << nMissing << " missing values in " << strGISFile
1020 << endl;
1021 }
1022
1023 return RTN_OK;
1024}
1025
1026//===============================================================================================================================
1028//===============================================================================================================================
1029bool CSimulation::bWriteRasterGISFile(int const nDataItem,
1030 string const *strPlotTitle,
1031 int const nLayer, double const dElev) {
1032 bool bIsInteger = false;
1033 bool bIsUnsignedLong = false;
1034
1035 // Begin constructing the file name for this save
1036 string strFilePathName(m_strOutPath);
1037 string strLayer = "_layer_";
1038
1039 stringstream ststrTmp;
1040
1041 strLayer.append(to_string(nLayer + 1));
1042
1043 switch (nDataItem) {
1045 strFilePathName.append(RASTER_BASEMENT_ELEVATION_NAME);
1046 break;
1047
1049 strFilePathName.append(RASTER_SEDIMENT_TOP_ELEVATION_NAME);
1050 break;
1051
1053 strFilePathName.append(RASTER_TOP_ELEVATION_INC_SEA_NAME);
1054 break;
1055
1056 case (RASTER_PLOT_TALUS):
1057 strFilePathName.append(RASTER_TALUS_NAME);
1058 break;
1059
1061 strFilePathName.append(RASTER_SLOPE_OF_CONSOLIDATED_SEDIMENT_NAME);
1062 break;
1063
1065 strFilePathName.append(RASTER_SLOPE_FOR_CLIFF_TOE_NAME);
1066 break;
1067
1068 case (RASTER_PLOT_CLIFF_TOE):
1069 strFilePathName.append(RASTER_CLIFF_TOE_NAME);
1070 break;
1071
1072 case (RASTER_PLOT_SEA_DEPTH):
1073 strFilePathName.append(RASTER_SEA_DEPTH_NAME);
1074 break;
1075
1077 strFilePathName.append(RASTER_AVG_SEA_DEPTH_NAME);
1078 break;
1079
1081 strFilePathName.append(RASTER_WAVE_HEIGHT_NAME);
1082 break;
1083
1085 strFilePathName.append(RASTER_AVG_WAVE_HEIGHT_NAME);
1086 break;
1087
1089 strFilePathName.append(RASTER_WAVE_ORIENTATION_NAME);
1090 break;
1091
1093 strFilePathName.append(RASTER_AVG_WAVE_ORIENTATION_NAME);
1094 break;
1095
1097 strFilePathName.append(RASTER_BEACH_PROTECTION_NAME);
1098 break;
1099
1101 strFilePathName.append(RASTER_POTENTIAL_PLATFORM_EROSION_NAME);
1102 break;
1103
1105 strFilePathName.append(RASTER_ACTUAL_PLATFORM_EROSION_NAME);
1106 break;
1107
1109 strFilePathName.append(RASTER_TOTAL_POTENTIAL_PLATFORM_EROSION_NAME);
1110 break;
1111
1113 strFilePathName.append(RASTER_TOTAL_ACTUAL_PLATFORM_EROSION_NAME);
1114 break;
1115
1117 strFilePathName.append(RASTER_POTENTIAL_BEACH_EROSION_NAME);
1118 break;
1119
1121 strFilePathName.append(RASTER_ACTUAL_BEACH_EROSION_NAME);
1122 break;
1123
1125 strFilePathName.append(RASTER_TOTAL_POTENTIAL_BEACH_EROSION_NAME);
1126 break;
1127
1129 strFilePathName.append(RASTER_TOTAL_ACTUAL_BEACH_EROSION_NAME);
1130 break;
1131
1133 strFilePathName.append(RASTER_BEACH_DEPOSITION_NAME);
1134 break;
1135
1137 strFilePathName.append(RASTER_TOTAL_BEACH_DEPOSITION_NAME);
1138 break;
1139
1141 strFilePathName.append(RASTER_SUSP_SED_NAME);
1142 break;
1143
1145 strFilePathName.append(RASTER_AVG_SUSP_SED_NAME);
1146 break;
1147
1149 strFilePathName.append(RASTER_FINE_UNCONS_NAME);
1150 strFilePathName.append(strLayer);
1151 break;
1152
1154 strFilePathName.append(RASTER_SAND_UNCONS_NAME);
1155 strFilePathName.append(strLayer);
1156 break;
1157
1159 strFilePathName.append(RASTER_COARSE_UNCONS_NAME);
1160 strFilePathName.append(strLayer);
1161 break;
1162
1164 strFilePathName.append(RASTER_FINE_CONS_NAME);
1165 strFilePathName.append(strLayer);
1166 break;
1167
1169 strFilePathName.append(RASTER_SAND_CONS_NAME);
1170 strFilePathName.append(strLayer);
1171 break;
1172
1174 strFilePathName.append(RASTER_COARSE_CONS_NAME);
1175 strFilePathName.append(strLayer);
1176 break;
1177
1179 strFilePathName.append(RASTER_CLIFF_COLLAPSE_EROSION_FINE_NAME);
1180 break;
1181
1183 strFilePathName.append(RASTER_CLIFF_COLLAPSE_EROSION_SAND_NAME);
1184 break;
1185
1187 strFilePathName.append(RASTER_CLIFF_COLLAPSE_EROSION_COARSE_NAME);
1188 break;
1189
1191 strFilePathName.append(RASTER_TOTAL_CLIFF_COLLAPSE_EROSION_FINE_NAME);
1192 break;
1193
1195 strFilePathName.append(RASTER_TOTAL_CLIFF_COLLAPSE_EROSION_SAND_NAME);
1196 break;
1197
1200 break;
1201
1203 strFilePathName.append(RASTER_CLIFF_COLLAPSE_DEPOSITION_SAND_NAME);
1204 break;
1205
1207 strFilePathName.append(RASTER_CLIFF_COLLAPSE_DEPOSITION_COARSE_NAME);
1208 break;
1209
1212 break;
1213
1216 break;
1217
1218 case (RASTER_PLOT_CLIFF_COLLAPSE_TIMESTEP):
1219 strFilePathName.append(RASTER_CLIFF_COLLAPSE_TIMESTEP_NAME);
1220 break;
1221
1223 strFilePathName.append(RASTER_CLIFF_NOTCH_ALL_NAME);
1224 break;
1225
1227 strFilePathName.append(RASTER_INTERVENTION_HEIGHT_NAME);
1228 break;
1229
1231 strFilePathName.append(RASTER_DEEP_WATER_WAVE_ORIENTATION_NAME);
1232 break;
1233
1235 strFilePathName.append(RASTER_DEEP_WATER_WAVE_HEIGHT_NAME);
1236 break;
1237
1239 strFilePathName.append(RASTER_POLYGON_GAIN_OR_LOSS_NAME);
1240 break;
1241
1243 strFilePathName.append(RASTER_WAVE_PERIOD_NAME);
1244 break;
1245
1247 strFilePathName.append(RASTER_SEDIMENT_INPUT_EVENT_NAME);
1248 break;
1249
1251 bIsInteger = true;
1252 strFilePathName.append(RASTER_BEACH_MASK_NAME);
1253 break;
1254
1256 bIsInteger = true;
1257 strFilePathName.append(RASTER_POTENTIAL_PLATFORM_EROSION_MASK_NAME);
1258 break;
1259
1261 bIsInteger = true;
1262 strFilePathName.append(RASTER_INUNDATION_MASK_NAME);
1263 break;
1264
1265 case (RASTER_PLOT_SLICE):
1266 bIsInteger = true;
1267 ststrTmp.str("");
1268 ststrTmp.clear();
1269
1270 // TODO 031 Get working for multiple slices
1271 strFilePathName.append(RASTER_SLICE_NAME);
1272 ststrTmp << "_" << dElev << "_";
1273 strFilePathName.append(ststrTmp.str());
1274 break;
1275
1276 case (RASTER_PLOT_LANDFORM):
1277 bIsInteger = true;
1278 strFilePathName.append(RASTER_LANDFORM_NAME);
1279 break;
1280
1282 bIsInteger = true;
1283 strFilePathName.append(RASTER_INTERVENTION_CLASS_NAME);
1284 break;
1285
1286 case (RASTER_PLOT_COAST):
1287 bIsInteger = true;
1288 strFilePathName.append(RASTER_COAST_NAME);
1289 break;
1290
1292 bIsInteger = true;
1293 strFilePathName.append(RASTER_COAST_NORMAL_NAME);
1294 break;
1295
1297 bIsInteger = true;
1298 strFilePathName.append(RASTER_ACTIVE_ZONE_NAME);
1299 break;
1300
1301 case (RASTER_PLOT_POLYGON):
1302 bIsInteger = true;
1303 strFilePathName.append(RASTER_POLYGON_NAME);
1304 break;
1305
1307 bIsInteger = true;
1308 strFilePathName.append(RASTER_SHADOW_ZONE_NAME);
1309 break;
1310
1312 bIsInteger = true;
1313 strFilePathName.append(RASTER_SHADOW_DOWNDRIFT_ZONE_NAME);
1314 break;
1315
1317 bIsInteger = true;
1318 strFilePathName.append(RASTER_POLYGON_UPDRIFT_OR_DOWNDRIFT_NAME);
1319 break;
1320
1322 bIsInteger = true;
1323 strFilePathName.append(RASTER_SETUP_SURGE_FLOOD_MASK_NAME);
1324 break;
1325
1327 bIsInteger = true;
1328 strFilePathName.append(RASTER_SETUP_SURGE_RUNUP_FLOOD_MASK_NAME);
1329 break;
1330
1332 bIsInteger = true;
1333 strFilePathName.append(RASTER_WAVE_FLOOD_LINE_NAME);
1334 break;
1335 }
1336
1337 // Append the 'save number' to the filename, and prepend zeros to the save
1338 // number
1339 ststrTmp.str("");
1340 ststrTmp.clear();
1341
1342 strFilePathName.append("_");
1343
1345 // Save number is m_bGISSaveDigitsSequential
1346 ststrTmp << FillToWidth('0', m_nGISMaxSaveDigits) << m_nGISSave;
1347 } else {
1348 // Save number is iteration
1349 ststrTmp << FillToWidth('0', m_nGISMaxSaveDigits) << m_ulIter;
1350 }
1351
1352 strFilePathName.append(ststrTmp.str());
1353
1354 // Finally, maybe append the extension
1356 strFilePathName.append(".");
1357 strFilePathName.append(m_strGDALRasterOutputDriverExtension);
1358 }
1359
1360 // TODO 065 Used to try to debug floating point exception in pDriver->Create()
1361 // below CPLSetConfigOption("CPL_DEBUG", "ON");
1362 // CPLSetConfigOption("GDAL_NUM_THREADS", "1");
1363
1364 GDALDriver *pDriver;
1365 GDALDataset *pDataSet;
1366
1367 if (m_bGDALCanCreate) {
1368 // The user-requested raster driver supports the Create() method
1369 pDriver = GetGDALDriverManager()->GetDriverByName(
1370 m_strRasterGISOutFormat.c_str());
1371
1372 if (bIsInteger) {
1373 pDataSet =
1374 pDriver->Create(strFilePathName.c_str(), m_nXGridSize, m_nYGridSize,
1375 1, GDT_Int16, m_papszGDALRasterOptions);
1376 } else if (bIsUnsignedLong) {
1377 pDataSet =
1378 pDriver->Create(strFilePathName.c_str(), m_nXGridSize, m_nYGridSize,
1379 1, GDT_UInt32, m_papszGDALRasterOptions);
1380
1381 } else if (m_strRasterGISOutFormat == "gpkg") {
1382 // TODO 065 Floating point exception here
1383 pDataSet =
1384 pDriver->Create(strFilePathName.c_str(), m_nXGridSize, m_nYGridSize,
1385 1, GDT_Byte, m_papszGDALRasterOptions);
1386 } else {
1387 pDataSet = pDriver->Create(strFilePathName.c_str(), m_nXGridSize,
1390 }
1391
1392 if (NULL == pDataSet) {
1393 // Error, couldn't create file
1394 cerr << ERR << "cannot create " << m_strRasterGISOutFormat
1395 << " file named " << strFilePathName << endl;
1396 return false;
1397 }
1398 }
1399 else
1400 {
1401 // The user-requested raster driver does not support the Create() method, so we must first create a memory-file dataset
1402 pDriver = GetGDALDriverManager()->GetDriverByName("MEM");
1403 pDataSet = pDriver->Create("", m_nXGridSize, m_nYGridSize, 1, m_GDALWriteFloatDataType, NULL);
1404
1405 if (NULL == pDataSet)
1406 {
1407 // Couldn't create in-memory file dataset
1408 cerr << ERR << "cannot create in-memory file for " << m_strRasterGISOutFormat << " file named " << strFilePathName << endl
1409 << CPLGetLastErrorMsg() << endl;
1410 return false;
1411 }
1412 }
1413
1414 // Set projection info for output dataset (will be same as was read in from basement DEM)
1415 CPLPushErrorHandler(CPLQuietErrorHandler); // Needed to get next line to fail silently, if it fails
1416 pDataSet->SetProjection(m_strGDALBasementDEMProjection.c_str()); // Will fail for some formats
1417 CPLPopErrorHandler();
1418
1419 // Set geotransformation info for output dataset (will be same as was read in from DEM)
1420 if (CE_Failure == pDataSet->SetGeoTransform(m_dGeoTransform))
1421 LogStream << WARN << "cannot write geotransformation information to " << m_strRasterGISOutFormat << " file named " << strFilePathName << endl << CPLGetLastErrorMsg() << endl;
1422
1423 // Allocate memory for a 1D array, to hold the floating point raster band data for GDAL
1424 double *pdRaster = new double[m_ulNumCells];
1425 if (NULL == pdRaster)
1426 {
1427 // Error, can't allocate memory
1428 cerr << ERR << "cannot allocate memory for " << m_ulNumCells << " x 1D floating-point array for " << m_strRasterGISOutFormat << " file named " << strFilePathName << endl;
1429 return (RTN_ERR_MEMALLOC);
1430 }
1431
1432 bool bScaleOutput = false;
1433 double dRangeScale = 0;
1434 double dDataMin = 0;
1435
1437 {
1438 double dDataMax = 0;
1439
1440 // The output file format cannot handle floating-point numbers, so we may need to scale the output
1441 GetRasterOutputMinMax(nDataItem, dDataMin, dDataMax, nLayer, 0);
1442
1443 double const dDataRange = dDataMax - dDataMin;
1444 double const dWriteRange = static_cast<double>(m_lGDALMaxCanWrite - m_lGDALMinCanWrite);
1445
1446 if (dDataRange > 0)
1447 dRangeScale = dWriteRange / dDataRange;
1448
1449 // 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
1450 if (((dDataMin < static_cast<double>(m_lGDALMinCanWrite)) || (dDataMax > static_cast<double>(m_lGDALMaxCanWrite))) && m_bScaleRasterOutput)
1451 bScaleOutput = true;
1452 }
1453
1454 // Fill the array
1455 int n = 0;
1456 int nPoly = 0;
1457 int nPolyCoast = 0;
1458 int nTopLayer = 0;
1459 double dTmp = 0;
1460
1461 for (int nY = 0; nY < m_nYGridSize; nY++)
1462 {
1463 for (int nX = 0; nX < m_nXGridSize; nX++)
1464 {
1465 switch (nDataItem)
1466 {
1468 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetBasementElev();
1469 break;
1470
1472 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetAllSedTopElevIncTalus();
1473 break;
1474
1476 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetTopElevIncSea();
1477 break;
1478
1479 case (RASTER_PLOT_TALUS):
1480 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetTalusDepth();
1481 break;
1482
1484 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetConsSedSlope();
1485 break;
1486
1488 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetSlopeForCliffToe();
1489 break;
1490
1491 case (RASTER_PLOT_CLIFF_TOE):
1492 dTmp = static_cast<double>(m_pRasterGrid->m_Cell[nX][nY].bIsCliffToe());
1493 break;
1494
1495 case (RASTER_PLOT_SEA_DEPTH):
1496 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetSeaDepth();
1497 break;
1498
1500 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetTotSeaDepth() / static_cast<double>(m_ulIter);
1501 break;
1502
1504 if (m_pRasterGrid->m_Cell[nX][nY].bIsInundated())
1505 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetWaveHeight();
1506 else
1507 dTmp = 0;
1508 break;
1509
1511 if (m_pRasterGrid->m_Cell[nX][nY].bIsInundated())
1512 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetTotWaveHeight() / static_cast<double>(m_ulIter);
1513 else
1514 dTmp = 0;
1515 break;
1516
1518 if (m_pRasterGrid->m_Cell[nX][nY].bIsInundated())
1519 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetWaveAngle();
1520 else
1521 dTmp = 0;
1522 break;
1523
1525 if (m_pRasterGrid->m_Cell[nX][nY].bIsInundated())
1526 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetTotWaveAngle() / static_cast<double>(m_ulIter);
1527 else
1528 dTmp = 0;
1529 break;
1530
1532 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetBeachProtectionFactor();
1533
1534 if (bFPIsEqual(dTmp, DBL_NODATA, TOLERANCE))
1535 dTmp = m_dMissingValue;
1536 else
1537 dTmp = 1 - dTmp; // Output the inverse, seems more intuitive
1538 break;
1539
1541 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetPotentialPlatformErosion();
1542 break;
1543
1545 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetActualPlatformErosion();
1546 break;
1547
1549 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetTotPotentialPlatformErosion();
1550 break;
1551
1553 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetTotActualPlatformErosion();
1554 break;
1555
1557 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetPotentialBeachErosion();
1558 break;
1559
1561 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetActualBeachErosion();
1562 break;
1563
1565 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetTotPotentialBeachErosion();
1566 break;
1567
1569 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetTotActualBeachErosion();
1570 break;
1571
1573 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetBeachDeposition();
1574 break;
1575
1577 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetTotBeachDeposition();
1578 break;
1579
1581 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetSuspendedSediment();
1582 break;
1583
1585 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetTotSuspendedSediment() / static_cast<double>(m_ulIter);
1586 break;
1587
1589 dTmp = m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nLayer)->pGetUnconsolidatedSediment()->dGetFineDepth();
1590 break;
1591
1593 dTmp = m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nLayer)->pGetUnconsolidatedSediment()->dGetSandDepth();
1594 break;
1595
1597 dTmp = m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nLayer)->pGetUnconsolidatedSediment()->dGetCoarseDepth();
1598 break;
1599
1601 dTmp = m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nLayer)->pGetConsolidatedSediment()->dGetFineDepth();
1602 break;
1603
1605 dTmp = m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nLayer)->pGetConsolidatedSediment()->dGetSandDepth();
1606 break;
1607
1609 dTmp = m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nLayer)->pGetConsolidatedSediment()->dGetCoarseDepth();
1610 break;
1611
1613 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetThisIterCliffCollapseErosionFine();
1614 break;
1615
1617 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetThisIterCliffCollapseErosionSand();
1618 break;
1619
1621 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetThisIterCliffCollapseErosionCoarse();
1622 break;
1623
1625 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetTotCliffCollapseFine();
1626 break;
1627
1629 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetTotCliffCollapseSand();
1630 break;
1631
1633 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetTotCliffCollapseCoarse();
1634 break;
1635
1637 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetThisIterCliffCollapseSandTalusDeposition();
1638 break;
1639
1641 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetThisIterCliffCollapseCoarseTalusDeposition();
1642 break;
1643
1645 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetTotSandTalusDeposition();
1646 break;
1647
1649 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetTotCoarseTalusDeposition();
1650 break;
1651
1653 dTmp = m_pRasterGrid->m_Cell[nX][nY].pGetLandform()->dGetCliffNotchIncisionDepth();
1654 break;
1655
1656#ifdef _DEBUG
1657 case (RASTER_PLOT_CLIFF_COLLAPSE_TIMESTEP):
1658 dTmp = static_cast<double>(m_pRasterGrid->m_Cell[nX][nY].pGetLandform()->ulGetCliffCollapseTimestep());
1659 bIsUnsignedLong = true;
1660 break;
1661#endif
1662
1664 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetInterventionHeight();
1665 break;
1666
1668 if (m_pRasterGrid->m_Cell[nX][nY].bIsInundated())
1669 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetCellDeepWaterWaveAngle();
1670 else
1671 dTmp = 0;
1672 break;
1673
1675 if (m_pRasterGrid->m_Cell[nX][nY].bIsInundated())
1676 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetCellDeepWaterWaveHeight();
1677 else
1678 dTmp = 0;
1679 break;
1680
1682 if (m_pRasterGrid->m_Cell[nX][nY].bIsInundated())
1683 dTmp = m_pRasterGrid->m_Cell[nX][nY].dGetCellDeepWaterWavePeriod();
1684 else
1685 dTmp = 0;
1686 break;
1687
1689 nPoly = m_pRasterGrid->m_Cell[nX][nY].nGetPolygonID();
1690 nPolyCoast = m_pRasterGrid->m_Cell[nX][nY].nGetPolygonCoastID();
1691
1692 if (nPoly == INT_NODATA)
1693 dTmp = m_dMissingValue;
1694 else
1695 {
1696 // Get total volume (all sediment size classes) of change in sediment for this polygon for this timestep (-ve erosion, +ve deposition)
1697 dTmp = m_VCoast[nPolyCoast].pGetPolygon(nPoly)->dGetBeachDepositionAndSuspensionAllUncons() * m_dCellArea;
1698
1699 // Calculate the rate in m^3 / sec
1700 dTmp /= (m_dTimeStep * 3600);
1701 }
1702 break;
1703
1705 // cppcheck-suppress assignBoolToFloat
1706 dTmp = m_pRasterGrid->m_Cell[nX][nY].bPotentialPlatformErosion();
1707 break;
1708
1710 // cppcheck-suppress assignBoolToFloat
1711 dTmp = m_pRasterGrid->m_Cell[nX][nY].bIsInContiguousSea();
1712 break;
1713
1715 dTmp = 0;
1716 nTopLayer = m_pRasterGrid->m_Cell[nX][nY].nGetTopNonZeroLayerAboveBasement();
1717
1718 if ((nTopLayer == INT_NODATA) || (nTopLayer == NO_NONZERO_THICKNESS_LAYERS))
1719 break;
1720
1721 if ((m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nTopLayer)->dGetAllUnconsDepth() > 0) && (m_pRasterGrid->m_Cell[nX][nY].dGetAllSedTopElevIncTalus() > m_dThisIterSWL))
1722 dTmp = 1;
1723
1724 break;
1725
1726 case (RASTER_PLOT_SLICE):
1727 dTmp = m_pRasterGrid->m_Cell[nX][nY].nGetLayerAtElev(dElev);
1728 break;
1729
1730 case (RASTER_PLOT_LANDFORM):
1731 dTmp = m_pRasterGrid->m_Cell[nX][nY].pGetLandform()->nGetLFCategory();
1732 bIsInteger = true;
1733 break;
1734
1736 dTmp = m_pRasterGrid->m_Cell[nX][nY].nGetInterventionClass();
1737 bIsInteger = true;
1738 break;
1739
1740 case (RASTER_PLOT_COAST):
1741 dTmp = (m_pRasterGrid->m_Cell[nX][nY].bIsCoastline() ? 1 : 0);
1742 break;
1743
1745 // dTmp = (m_pRasterGrid->m_Cell[nX][nY].bIsProfile() ? 1 : 0);
1746 dTmp = m_pRasterGrid->m_Cell[nX][nY].nGetProfileID();
1747 bIsInteger = true;
1748 break;
1749
1751 dTmp = (m_pRasterGrid->m_Cell[nX][nY].bIsInActiveZone() ? 1 : 0);
1752 break;
1753
1754 case (RASTER_PLOT_POLYGON):
1755 dTmp = m_pRasterGrid->m_Cell[nX][nY].nGetPolygonID();
1756 bIsInteger = true;
1757 break;
1758
1760 dTmp = m_pRasterGrid->m_Cell[nX][nY].nGetShadowZoneNumber();
1761 bIsInteger = true;
1762 break;
1763
1765 dTmp = m_pRasterGrid->m_Cell[nX][nY].nGetDownDriftZoneNumber();
1766 bIsInteger = true;
1767 break;
1768
1770 nPoly = m_pRasterGrid->m_Cell[nX][nY].nGetPolygonID();
1771 nPolyCoast = m_pRasterGrid->m_Cell[nX][nY].nGetPolygonCoastID();
1772 bIsInteger = true;
1773
1774 if (nPoly == INT_NODATA)
1775 dTmp = m_nMissingValue;
1776 else
1777 {
1778 if (m_VCoast[nPolyCoast].pGetPolygon(nPoly)->bDownCoastThisIter())
1779 dTmp = 1;
1780 else
1781 dTmp = 0;
1782 }
1783 break;
1784
1786 dTmp = m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nTopLayer)->pGetUnconsolidatedSediment()->dGetTotAllSedimentInputDepth();
1787 break;
1788
1790 dTmp = (m_pRasterGrid->m_Cell[nX][nY].bIsFloodBySetupSurge() ? 1 : 0);
1791 break;
1792
1794 dTmp = (m_pRasterGrid->m_Cell[nX][nY].bIsFloodBySetupSurgeRunup() ? 1 : 0);
1795 break;
1796
1798 dTmp = (m_pRasterGrid->m_Cell[nX][nY].bIsFloodline() ? 1 : 0);
1799 break;
1800 }
1801
1802 // If necessary, scale this value
1803 if (bScaleOutput)
1804 {
1805 if (bFPIsEqual(dTmp, DBL_NODATA, TOLERANCE))
1806 dTmp = 0; // TODO 032 Improve this
1807 else
1808 dTmp = dRound(static_cast<double>(m_lGDALMinCanWrite) + (dRangeScale * (dTmp - dDataMin)));
1809 }
1810
1811 // Write this value to the array
1812 pdRaster[n++] = dTmp;
1813 }
1814 }
1815
1816 // Create a single raster band
1817 GDALRasterBand *pBand = pDataSet->GetRasterBand(1);
1818
1819 // And fill it with the NODATA value
1820 if (bIsInteger)
1821 pBand->Fill(m_nMissingValue);
1822 else if (bIsUnsignedLong)
1823 pBand->Fill(static_cast<double>(m_ulMissingValue));
1824 else
1825 pBand->Fill(m_dMissingValue);
1826
1827 // Set value units for this band
1828 string strUnits;
1829
1830 switch (nDataItem)
1831 {
1855 case (RASTER_PLOT_SEA_DEPTH):
1859 case (RASTER_PLOT_TALUS):
1872 strUnits = "m";
1873 break;
1874
1876 strUnits = "m/m";
1877 break;
1878
1879 strUnits = "degrees";
1882 break;
1883
1885 strUnits = "cumecs";
1886 break;
1887
1889 strUnits = "secs";
1890 break;
1891
1892 strUnits = "none";
1895#ifdef _DEBUG
1896 case (RASTER_PLOT_CLIFF_COLLAPSE_TIMESTEP):
1897#endif
1898 case (RASTER_PLOT_COAST):
1901 case (RASTER_PLOT_LANDFORM):
1903 case (RASTER_PLOT_POLYGON):
1910 case (RASTER_PLOT_SLICE):
1912 break;
1913 }
1914
1915 CPLPushErrorHandler(CPLQuietErrorHandler); // Needed to get next line to fail silently, if it fails
1916 pBand->SetUnitType(strUnits.c_str()); // Not supported for some GIS formats
1917 CPLPopErrorHandler();
1918
1919 // Tell the output dataset about NODATA (missing values)
1920 CPLPushErrorHandler(CPLQuietErrorHandler); // Needed to get next line to fail silently, if it fails
1921
1922 if (bIsInteger)
1923 pBand->SetNoDataValue(m_nMissingValue); // Will fail for some formats
1924 if (bIsUnsignedLong)
1925 pBand->SetNoDataValueAsUInt64(m_ulMissingValue); // Will fail for some formats
1926 else
1927 pBand->SetNoDataValue(m_dMissingValue); // Will fail for some formats
1928
1929 CPLPopErrorHandler();
1930
1931 // Construct the description
1932 string strDesc(*strPlotTitle);
1933
1934 if (nDataItem == RASTER_PLOT_SLICE)
1935 {
1936 ststrTmp.clear();
1937 ststrTmp << dElev << "m, ";
1938 strDesc.append(ststrTmp.str());
1939 }
1940
1941 strDesc.append(" at ");
1942 strDesc.append(strDispTime(m_dSimElapsed, false, false));
1943
1944 // Set the GDAL description
1945 pBand->SetDescription(strDesc.c_str());
1946
1947 // Set raster category names
1948 char **papszCategoryNames = NULL;
1949
1950 switch (nDataItem)
1951 {
1952 case (RASTER_PLOT_SLICE):
1953 papszCategoryNames = CSLAddString(papszCategoryNames, "Basement");
1954 papszCategoryNames = CSLAddString(papszCategoryNames, "Layer 0");
1955 papszCategoryNames = CSLAddString(papszCategoryNames, "Layer 1");
1956 papszCategoryNames = CSLAddString(papszCategoryNames, "Layer 2");
1957 papszCategoryNames = CSLAddString(papszCategoryNames, "Layer 3");
1958 papszCategoryNames = CSLAddString(papszCategoryNames, "Layer 4");
1959 papszCategoryNames = CSLAddString(papszCategoryNames, "Layer 5");
1960 papszCategoryNames = CSLAddString(papszCategoryNames, "Layer 6");
1961 papszCategoryNames = CSLAddString(papszCategoryNames, "Layer 7");
1962 papszCategoryNames = CSLAddString(papszCategoryNames, "Layer 8");
1963 papszCategoryNames = CSLAddString(papszCategoryNames, "Layer 9");
1964 break;
1965
1966 case (RASTER_PLOT_LANDFORM):
1967 papszCategoryNames = CSLAddString(papszCategoryNames, "None");
1968 papszCategoryNames = CSLAddString(papszCategoryNames, "Hinterland");
1969 papszCategoryNames = CSLAddString(papszCategoryNames, "Sea");
1970 papszCategoryNames = CSLAddString(papszCategoryNames, "Cliff");
1971 papszCategoryNames = CSLAddString(papszCategoryNames, "Drift");
1972 papszCategoryNames = CSLAddString(papszCategoryNames, "Intervention");
1973
1974 papszCategoryNames = CSLAddString(papszCategoryNames, "Cliff on Coastline");
1975 papszCategoryNames = CSLAddString(papszCategoryNames, "Inland Cliff");
1976
1977 papszCategoryNames = CSLAddString(papszCategoryNames, "Mixed Drift");
1978 papszCategoryNames = CSLAddString(papszCategoryNames, "Talus");
1979 papszCategoryNames = CSLAddString(papszCategoryNames, "Beach");
1980 papszCategoryNames = CSLAddString(papszCategoryNames, "Dunes");
1981 break;
1982
1984 papszCategoryNames = CSLAddString(papszCategoryNames, "None");
1985 papszCategoryNames = CSLAddString(papszCategoryNames, "Structural");
1986 papszCategoryNames = CSLAddString(papszCategoryNames, "Non-Structural");
1987 break;
1988
1989 case (RASTER_PLOT_COAST):
1990 papszCategoryNames = CSLAddString(papszCategoryNames, "Not coastline");
1991 papszCategoryNames = CSLAddString(papszCategoryNames, "Coastline");
1992 break;
1993
1995 papszCategoryNames = CSLAddString(papszCategoryNames, "Not coastline-normal profile");
1996 papszCategoryNames = CSLAddString(papszCategoryNames, "Coastline-normal profile");
1997 break;
1998
2000 papszCategoryNames = CSLAddString(papszCategoryNames, "Not in active zone");
2001 papszCategoryNames = CSLAddString(papszCategoryNames, "In active zone");
2002 break;
2003
2004 case (RASTER_PLOT_POLYGON):
2005 papszCategoryNames = CSLAddString(papszCategoryNames, "Not polygon");
2006 papszCategoryNames = CSLAddString(papszCategoryNames, "In polygon");
2007 break;
2008
2010 papszCategoryNames = CSLAddString(papszCategoryNames, "Not in shadow zone");
2011 papszCategoryNames = CSLAddString(papszCategoryNames, "In shadow zone");
2012 break;
2013
2015 papszCategoryNames = CSLAddString(papszCategoryNames, "Not in shadow downdrift zone");
2016 papszCategoryNames = CSLAddString(papszCategoryNames, "In shadow downdrift zone");
2017 break;
2018
2020 papszCategoryNames = CSLAddString(papszCategoryNames, "Updrift movement of unconsolidated sediment ");
2021 papszCategoryNames = CSLAddString(papszCategoryNames, "Downdrift movement of unconsolidated sediment");
2022 break;
2023
2025 papszCategoryNames = CSLAddString(papszCategoryNames, "Inundated by swl setup and surge ");
2026 papszCategoryNames = CSLAddString(papszCategoryNames, "Not inundated by swl setup and surge");
2027 break;
2028
2030 papszCategoryNames = CSLAddString(papszCategoryNames, "Inundated by swl setup, surge and runup ");
2031 papszCategoryNames = CSLAddString(papszCategoryNames, "Not inundated by swl setup, surge and runup");
2032 break;
2033
2035 papszCategoryNames = CSLAddString(papszCategoryNames, "Intersection line of inundation ");
2036 papszCategoryNames = CSLAddString(papszCategoryNames, "Not inundated by swl waves and runup");
2037 break;
2038 }
2039
2040 CPLPushErrorHandler(CPLQuietErrorHandler); // Needed to get next line to fail silently, if it fails
2041 pBand->SetCategoryNames(papszCategoryNames); // Not supported for some GIS formats
2042 CPLPopErrorHandler();
2043
2044 // Now write the data with optimized I/O
2045 // Enable multi-threaded compression for faster writing
2046 CPLSetThreadLocalConfigOption("GDAL_NUM_THREADS", "ALL_CPUS");
2047
2048 if (CE_Failure == pBand->RasterIO(GF_Write, 0, 0, m_nXGridSize, m_nYGridSize, pdRaster, m_nXGridSize, m_nYGridSize, GDT_Float64, 0, 0, NULL))
2049 {
2050 // Write error, better error message
2051 cerr << ERR << "cannot write data for " << m_strRasterGISOutFormat << " file named " << strFilePathName << endl
2052 << CPLGetLastErrorMsg() << endl;
2053 delete[] pdRaster;
2054 return false;
2055 }
2056
2057 // Calculate statistics for this band
2058 double dMin, dMax, dMean, dStdDev;
2059 CPLPushErrorHandler(CPLQuietErrorHandler); // Needed to get next line to fail
2060 // silently, if it fails
2061 pBand->ComputeStatistics(false, &dMin, &dMax, &dMean, &dStdDev, NULL, NULL);
2062 CPLPopErrorHandler();
2063
2064 // And then write the statistics
2065 CPLPushErrorHandler(CPLQuietErrorHandler); // Needed to get next line to fail
2066 // silently, if it fails
2067 pBand->SetStatistics(dMin, dMax, dMean, dStdDev);
2068 CPLPopErrorHandler();
2069
2070 if (!m_bGDALCanCreate) {
2071 // Since the user-selected raster driver cannot use the Create() method, we
2072 // have been writing to a dataset created by the in-memory driver. So now we
2073 // need to use CreateCopy() to copy this in-memory dataset to a file in the
2074 // user-specified raster driver format
2075 GDALDriver *pOutDriver = GetGDALDriverManager()->GetDriverByName(
2076 m_strRasterGISOutFormat.c_str());
2077 GDALDataset *pOutDataSet =
2078 pOutDriver->CreateCopy(strFilePathName.c_str(), pDataSet, false,
2079 m_papszGDALRasterOptions, NULL, NULL);
2080
2081 if (NULL == pOutDataSet) {
2082 // Couldn't create file
2083 cerr << ERR << "cannot create " << m_strRasterGISOutFormat
2084 << " file named " << strFilePathName << endl
2085 << CPLGetLastErrorMsg() << endl;
2086 return false;
2087 }
2088
2089 // Get rid of this user-selected dataset object
2090 GDALClose(pOutDataSet);
2091 }
2092
2093 // Get rid of dataset object
2094 GDALClose(pDataSet);
2095
2096 // Also get rid of memory allocated to this array
2097 delete[] pdRaster;
2098
2099 return true;
2100}
2101
2102//===============================================================================================================================
2146//===============================================================================================================================
2148 vector<TransectWaveData> const *pVTransects,
2149 vector<double> const *pVdDeepWaterX,
2150 vector<double> const *pVdDeepWaterY,
2151 vector<double> const *pVdDeepWaterHeightX,
2152 vector<double> const *pVdDeepWaterHeightY) {
2153
2154 // ============================================================================
2155 // STEP 1: Calculate grid dimensions and initialize variables
2156 // ============================================================================
2157
2158 int nXSize = 0;
2159 int nYSize = 0;
2160
2161 // Average values used as fallback when interpolation fails or returns NaN
2162 double dXAvg = 0;
2163 double dYAvg = 0;
2164
2165 // Calculate bounding box size
2168 int const nGridSize = nXSize * nYSize;
2169
2170 // Count total points across all transects plus deep water points
2171 unsigned int nPoints = 0;
2172 for (const auto& transect : *pVTransects) {
2173 nPoints += static_cast<unsigned int>(transect.VdX.size());
2174 }
2175 nPoints += static_cast<unsigned int>(pVdDeepWaterX->size());
2176
2177 // Initialize output arrays (will hold interpolated X and Y wave components)
2178 vector<double> VdOutX(nGridSize, 0);
2179 vector<double> VdOutY(nGridSize, 0);
2180
2181 // ============================================================================
2182 // STEP 2: Prepare input data for spatial interpolation
2183 // ============================================================================
2184
2185 // Flatten transect data and deep water data into contiguous arrays for the interpolator
2186 std::vector<Point2D> points;
2187 std::vector<double> VdHeightX;
2188 std::vector<double> VdHeightY;
2189
2190 points.reserve(nPoints);
2191 VdHeightX.reserve(nPoints);
2192 VdHeightY.reserve(nPoints);
2193
2194 // Add profile/transect points
2195 for (const auto& transect : *pVTransects) {
2196 for (size_t i = 0; i < transect.VdX.size(); i++) {
2197 points.emplace_back(transect.VdX[i], transect.VdY[i]);
2198 VdHeightX.push_back(transect.VdHeightX[i]);
2199 VdHeightY.push_back(transect.VdHeightY[i]);
2200 }
2201 }
2202
2203 // Add deep water grid edge points
2204 for (size_t i = 0; i < pVdDeepWaterX->size(); i++) {
2205 points.emplace_back((*pVdDeepWaterX)[i], (*pVdDeepWaterY)[i]);
2206 VdHeightX.push_back((*pVdDeepWaterHeightX)[i]);
2207 VdHeightY.push_back((*pVdDeepWaterHeightY)[i]);
2208 }
2209
2210 // ============================================================================
2211 // STEP 3: Create spatial interpolator
2212 // ============================================================================
2213 //
2214 // DualSpatialInterpolator parameters:
2215 // - points: Input point coordinates (from profiles/transects)
2216 // - VdHeightX, VdHeightY: Wave height X and Y components at those points
2217 // - k_neighbors = 12: Use 12 nearest neighbors for interpolation
2218 // ** ADJUST THIS to change smoothness vs local detail **
2219 // - power = 2.0: Inverse distance weighting power
2220 // ** ADJUST THIS to change influence of nearby vs distant points **
2221 //
2222 // The interpolator builds a k-d tree for fast nearest neighbor search
2223 // and shares it between X and Y interpolation for efficiency
2224 DualSpatialInterpolator interp(points, VdHeightX, VdHeightY, 6, 2.0);
2225
2226 // ============================================================================
2227 // STEP 4: Build query points (grid cells where we want interpolated values)
2228 // ============================================================================
2229
2230 std::vector<Point2D> query_points;
2231 query_points.reserve(nGridSize);
2232 for (int nY = m_nYMinBoundingBox; nY <= m_nYMaxBoundingBox; nY++) {
2233 for (int nX = m_nXMinBoundingBox; nX <= m_nXMaxBoundingBox; nX++) {
2234 query_points.emplace_back(static_cast<double>(nX),
2235 static_cast<double>(nY));
2236 }
2237 }
2238
2239 // ============================================================================
2240 // STEP 5: Perform batch interpolation
2241 // ============================================================================
2242 //
2243 // This does the actual interpolation for all grid points at once
2244 // Uses OpenMP parallelization if available (see spatial_interpolation.cpp)
2245 // Interpolates both X and Y components simultaneously using shared k-d tree
2246 interp.Interpolate(query_points, VdOutX, VdOutY);
2247
2248 // ============================================================================
2249 // STEP 6: Validate results and calculate average values for fallback
2250 // ============================================================================
2251 //
2252 // Check for NaN or unreasonably large values and replace with missing value marker
2253 // Also calculate average of valid values to use as fallback
2254
2255 int nXValid = 0;
2256 int nYValid = 0;
2257
2258 // Validate X component
2259 for (unsigned int n = 0; n < VdOutX.size(); n++) {
2260 if (isnan(VdOutX[n]))
2261 VdOutX[n] = m_dMissingValue;
2262 else if (tAbs(VdOutX[n]) > 1e10) // Sanity check for unreasonably large values
2263 VdOutX[n] = m_dMissingValue;
2264 else {
2265 dXAvg += VdOutX[n];
2266 nXValid++;
2267 }
2268 }
2269
2270 // Validate Y component
2271 for (unsigned int n = 0; n < VdOutY.size(); n++) {
2272 if (isnan(VdOutY[n]))
2273 VdOutY[n] = m_dMissingValue;
2274 else if (tAbs(VdOutY[n]) > 1e10) // Sanity check for unreasonably large values
2275 VdOutY[n] = m_dMissingValue;
2276 else {
2277 dYAvg += VdOutY[n];
2278 nYValid++;
2279 }
2280 }
2281
2282 // Calculate averages (for use as fallback when individual cells have missing values)
2283 if (nXValid > 0)
2284 dXAvg /= nXValid;
2285 if (nYValid > 0)
2286 dYAvg /= nYValid;
2287
2288 // ============================================================================
2289 // STEP 7: Update grid cells with interpolated wave properties
2290 // ============================================================================
2291 //
2292 // Convert X and Y components back to magnitude and direction,
2293 // then update each cell's wave attributes
2294
2295 int n = 0;
2296
2297 for (int nY = 0; nY < nYSize; nY++) {
2298 for (int nX = 0; nX < nXSize; nX++) {
2299 int const nActualX = nX + m_nXMinBoundingBox;
2300 int const nActualY = nY + m_nYMinBoundingBox;
2301
2302 if (m_pRasterGrid->m_Cell[nActualX][nActualY]
2303 .bIsInContiguousSea()) {
2304 // Only update sea cells
2305
2306 if (m_pRasterGrid->m_Cell[nActualX][nActualY].nGetPolygonID() ==
2307 INT_NODATA) {
2308 // --------------------------------------------------------------------
2309 // Deep water cell (NOT in a polygon)
2310 // --------------------------------------------------------------------
2311 // Use the cell's pre-assigned deep water wave values
2312 // (these cells are beyond the coastal zone, so don't need interpolation)
2313
2314 double const dDeepWaterWaveHeight =
2315 m_pRasterGrid->m_Cell[nActualX][nActualY]
2316 .dGetCellDeepWaterWaveHeight();
2317 m_pRasterGrid->m_Cell[nActualX][nActualY].SetWaveHeight(
2318 dDeepWaterWaveHeight);
2319
2320 double const dDeepWaterWaveAngle =
2321 m_pRasterGrid->m_Cell[nActualX][nActualY]
2322 .dGetCellDeepWaterWaveAngle();
2323 m_pRasterGrid->m_Cell[nActualX][nActualY].SetWaveAngle(
2324 dDeepWaterWaveAngle);
2325 } else {
2326 // --------------------------------------------------------------------
2327 // Coastal zone cell (IN a polygon)
2328 // --------------------------------------------------------------------
2329 // Use the interpolated wave values calculated above
2330
2331 double dWaveHeightX;
2332 double dWaveHeightY;
2333
2334 // Get interpolated X component (use average as fallback if missing/invalid)
2335 if ((isnan(VdOutX[n])) ||
2336 (bFPIsEqual(VdOutX[n], m_dMissingValue, TOLERANCE)))
2337 dWaveHeightX = dXAvg;
2338 else
2339 dWaveHeightX = VdOutX[n];
2340
2341 // Get interpolated Y component (use average as fallback if missing/invalid)
2342 if ((isnan(VdOutY[n])) ||
2343 (bFPIsEqual(VdOutY[n], m_dMissingValue, TOLERANCE)))
2344 dWaveHeightY = dYAvg;
2345 else
2346 dWaveHeightY = VdOutY[n];
2347
2348 // Convert X/Y components to magnitude and direction
2349 double const dWaveHeight = sqrt((dWaveHeightX * dWaveHeightX) +
2350 (dWaveHeightY * dWaveHeightY));
2351 double const dWaveDir =
2352 atan2(dWaveHeightX, dWaveHeightY) * (180 / PI);
2353
2354 // Update the cell's wave attributes
2355 m_pRasterGrid->m_Cell[nActualX][nActualY].SetWaveHeight(
2356 dWaveHeight);
2357 m_pRasterGrid->m_Cell[nActualX][nActualY].SetWaveAngle(
2358 dKeepWithin360(dWaveDir));
2359
2360 // Calculate wave height-to-depth ratio and update active zone status
2361 // (active zone = where waves are breaking or near-breaking)
2362 double const dSeaDepth =
2363 m_pRasterGrid->m_Cell[nActualX][nActualY].dGetSeaDepth();
2364
2365 if ((dWaveHeight / dSeaDepth) >=
2367 m_pRasterGrid->m_Cell[nActualX][nActualY].SetInActiveZone(
2368 true);
2369
2370 // LogStream << " nX = " << nX << " nY = " << nY << " [" <<
2371 // nActualX
2372 // << "][" << nActualY << "] waveheight = " << dWaveHeight << "
2373 // dWaveDir = " << dWaveDir << " dKeepWithin360(dWaveDir) = " <<
2374 // dKeepWithin360(dWaveDir) << endl;
2375 }
2376 }
2377
2378 // Increment with safety check
2379 n++;
2380 n = tMin(n, static_cast<int>(VdOutX.size() - 1));
2381 }
2382 }
2383
2384 return RTN_OK;
2385}
2386
2387//===============================================================================================================================
2390//===============================================================================================================================
2392 // Interpolate deep water height and orientation from multiple
2393 // user-supplied values
2394 unsigned int const nUserPoints =
2395 static_cast<unsigned int>(m_VdDeepWaterWaveStationX.size());
2396
2397 // Performance optimization: Enable GDAL threading for interpolation
2398 CPLSetThreadLocalConfigOption("GDAL_NUM_THREADS", "ALL_CPUS");
2399
2400 // Call GDALGridCreate() with the GGA_InverseDistanceToAPower
2401 // interpolation algorithm. It has following parameters: radius1 is the
2402 // first radius (X axis if rotation angle is 0) of the search ellipse,
2403 // set this to zero (the default) to use the whole point array; radius2
2404 // is the second radius (Y axis if rotation angle is 0) of the search
2405 // ellipse, again set this parameter to zero (the default) to use the
2406 // whole point array; angle is the angle of the search ellipse rotation
2407 // in degrees (counter clockwise, default 0.0); nodata is the NODATA
2408 // marker to fill empty points (default 0.0) TODO 086
2409 GDALGridInverseDistanceToAPowerOptions *pOptions =
2410 new GDALGridInverseDistanceToAPowerOptions();
2411 pOptions->dfAngle = 0;
2412 pOptions->dfAnisotropyAngle = 0;
2413 pOptions->dfAnisotropyRatio = 0;
2414 pOptions->dfPower = 2; // Reduced from 3 to 2 for faster computation
2415 pOptions->dfSmoothing =
2416 50; // Reduced from 100 to 50 for faster computation
2417 pOptions->dfRadius1 = 0;
2418 pOptions->dfRadius2 = 0;
2419 pOptions->nMaxPoints =
2420 12; // Limit points for faster computation (was 0 = unlimited)
2421 pOptions->nMinPoints = 3; // Minimum points needed for interpolation
2422 pOptions->dfNoDataValue = m_nMissingValue;
2423
2424 // CPLSetConfigOption("CPL_DEBUG", "ON");
2425 // CPLSetConfigOption("GDAL_NUM_THREADS", "1");
2426
2427 // OK, now create a gridded version of wave height: first create the
2428 // GDAL context TODO 086 GDALGridContext* pContext =
2429 // GDALGridContextCreate(GGA_InverseDistanceToAPower, pOptions,
2430 // nUserPoints, &m_VdDeepWaterWaveStationX[0],
2431 // &m_VdDeepWaterWaveStationY[0],
2432 // &m_VdThisIterDeepWaterWaveStationHeight[0], true);
2433 GDALGridContext *pContext = GDALGridContextCreate(
2434 GGA_InverseDistanceToAPower, pOptions, nUserPoints,
2437
2438 if (pContext == NULL) {
2439 delete pOptions;
2440 return RTN_ERR_GRIDCREATE;
2441 }
2442
2443 // Now process the context
2444 double *dHeightOut = new double[m_ulNumCells];
2445 int nRet = GDALGridContextProcess(
2446 pContext, 0, m_nXGridSize - 1, 0, m_nYGridSize - 1, m_nXGridSize,
2447 m_nYGridSize, GDT_Float64, dHeightOut, NULL, NULL);
2448
2449 if (nRet == CE_Failure) {
2450 delete[] dHeightOut;
2451 delete pOptions;
2452 return RTN_ERR_GRIDCREATE;
2453 }
2454
2455 // Get rid of the context
2456 GDALGridContextFree(pContext);
2457
2458 // Next create a gridded version of wave orientation: first create the
2459 // GDAL context pContext =
2460 // GDALGridContextCreate(GGA_InverseDistanceToAPower, pOptions,
2461 // nUserPoints, &(m_VdDeepWaterWaveStationX[0]),
2462 // &(m_VdDeepWaterWaveStationY[0]),
2463 // (&m_VdThisIterDeepWaterWaveStationAngle[0]), true);
2464 pContext = GDALGridContextCreate(
2465 GGA_InverseDistanceToAPower, pOptions, nUserPoints,
2468
2469 if (pContext == NULL) {
2470 delete[] dHeightOut;
2471 delete pOptions;
2472 return RTN_ERR_GRIDCREATE;
2473 }
2474
2475 // Now process the context TODO 086
2476 double *dAngleOut = new double[m_ulNumCells];
2477 nRet = GDALGridContextProcess(
2478 pContext, 0, m_nXGridSize - 1, 0, m_nYGridSize - 1, m_nXGridSize,
2479 m_nYGridSize, GDT_Float64, dAngleOut, NULL, NULL);
2480
2481 if (nRet == CE_Failure) {
2482 delete[] dHeightOut;
2483 delete[] dAngleOut;
2484 delete pOptions;
2485 return RTN_ERR_GRIDCREATE;
2486 }
2487
2488 // Get rid of the context
2489 GDALGridContextFree(pContext);
2490
2491 // OK, now create a gridded version of wave period: first create the
2492 // GDAL context pContext =
2493 // GDALGridContextCreate(GGA_InverseDistanceToAPower, pOptions,
2494 // nUserPoints, &m_VdDeepWaterWaveStationX[0],
2495 // &m_VdDeepWaterWaveStationY[0],
2496 // &m_VdThisIterDeepWaterWaveStationPeriod[0], true);
2497 pContext = GDALGridContextCreate(
2498 GGA_InverseDistanceToAPower, pOptions, nUserPoints,
2501
2502 if (pContext == NULL) {
2503 delete pOptions;
2504 return RTN_ERR_GRIDCREATE;
2505 }
2506
2507 // Now process the context TODO 086
2508 double *dPeriopdOut = new double[m_ulNumCells];
2509 nRet = GDALGridContextProcess(
2510 pContext, 0, m_nXGridSize - 1, 0, m_nYGridSize - 1, m_nXGridSize,
2511 m_nYGridSize, GDT_Float64, dPeriopdOut, NULL, NULL);
2512
2513 if (nRet == CE_Failure) {
2514 delete[] dPeriopdOut;
2515 delete pOptions;
2516 return RTN_ERR_GRIDCREATE;
2517 }
2518
2519 // Get rid of the context
2520 GDALGridContextFree(pContext);
2521
2522 // The output from GDALGridCreate() is in dHeightOut, dAngleOut and
2523 // dPeriopdOut but must be reversed
2524 vector<double> VdHeight;
2525 vector<double> VdAngle;
2526 vector<double> VdPeriod;
2527
2528 int n = 0;
2529 int nValidHeight = 0;
2530 int nValidAngle = 0;
2531 int nValidPeriod = 0;
2532
2533 double dAvgHeight = 0;
2534 double dAvgAngle = 0;
2535 double dAvgPeriod = 0;
2536
2537 for (int nY = m_nYGridSize - 1; nY >= 0; nY--) {
2538 for (int nX = 0; nX < m_nXGridSize; nX++) {
2539 if (isfinite(dHeightOut[n])) {
2540 VdHeight.push_back(dHeightOut[n]);
2541
2542 dAvgHeight += dHeightOut[n];
2543 nValidHeight++;
2544 }
2545
2546 else {
2547 VdHeight.push_back(m_dMissingValue);
2548 }
2549
2550 if (isfinite(dAngleOut[n])) {
2551 VdAngle.push_back(dAngleOut[n]);
2552
2553 dAvgAngle += dAngleOut[n];
2554 nValidAngle++;
2555 }
2556
2557 else {
2558 VdAngle.push_back(m_dMissingValue);
2559 }
2560
2561 if (isfinite(dPeriopdOut[n])) {
2562 VdPeriod.push_back(dPeriopdOut[n]);
2563
2564 dAvgPeriod += dPeriopdOut[n];
2565 nValidPeriod++;
2566 }
2567
2568 else {
2569 VdPeriod.push_back(m_dMissingValue);
2570 }
2571
2572 // LogStream << " nX = " << nX << " nY = " << nY << " n = " << n <<
2573 // " dHeightOut[n] = " << dHeightOut[n] << " dAngleOut[n] = " <<
2574 // dAngleOut[n] << endl;
2575 n++;
2576 }
2577 }
2578
2579 // Calculate averages
2580 dAvgHeight /= nValidHeight;
2581 dAvgAngle /= nValidAngle;
2582 dAvgPeriod /= nValidPeriod;
2583
2584 // Tidy
2585 delete pOptions;
2586 delete[] dHeightOut;
2587 delete[] dAngleOut;
2588 delete[] dPeriopdOut;
2589
2590 // Now update all raster cells
2591 n = 0;
2592
2593 for (int nY = 0; nY < m_nYGridSize; nY++) {
2594 for (int nX = 0; nX < m_nXGridSize; nX++) {
2595 if (bFPIsEqual(VdHeight[n], m_dMissingValue, TOLERANCE))
2596 m_pRasterGrid->m_Cell[nX][nY].SetCellDeepWaterWaveHeight(
2597 dAvgHeight);
2598
2599 else
2600 m_pRasterGrid->m_Cell[nX][nY].SetCellDeepWaterWaveHeight(
2601 VdHeight[n]);
2602
2603 if (bFPIsEqual(VdAngle[n], m_dMissingValue, TOLERANCE))
2604 m_pRasterGrid->m_Cell[nX][nY].SetCellDeepWaterWaveAngle(
2605 dAvgAngle);
2606
2607 else
2608 m_pRasterGrid->m_Cell[nX][nY].SetCellDeepWaterWaveAngle(
2609 VdAngle[n]);
2610
2611 if (bFPIsEqual(VdPeriod[n], m_dMissingValue, TOLERANCE))
2612 m_pRasterGrid->m_Cell[nX][nY].SetCellDeepWaterWavePeriod(
2613 dAvgPeriod);
2614
2615 else
2616 m_pRasterGrid->m_Cell[nX][nY].SetCellDeepWaterWavePeriod(
2617 VdPeriod[n]);
2618
2619 // LogStream << " [" << nX << "][" << nY << "] deep water wave
2620 // height = "
2621 // << m_pRasterGrid->m_Cell[nX][nY].dGetCellDeepWaterWaveHeight() <<
2622 // " deep water wave angle = " <<
2623 // m_pRasterGrid->m_Cell[nX][nY].dGetCellDeepWaterWaveAngle() <<
2624 // endl;
2625 n++;
2626 }
2627 }
2628
2629 // // DEBUG CODE
2630 // ===========================================================================================================
2631 // string strOutFile = m_strOutPath;
2632 // strOutFile += "init_deep_water_wave_height_";
2633 // strOutFile += to_string(m_ulIter);
2634 // strOutFile += ".tif";
2635 // GDALDriver* pDriver =
2636 // GetGDALDriverManager()->GetDriverByName("gtiff"); GDALDataset*
2637 // pDataSet = pDriver->Create(strOutFile.c_str(), m_nXGridSize,
2638 // m_nYGridSize, 1, GDT_Float64, m_papszGDALRasterOptions);
2639 // pDataSet->SetProjection(m_strGDALBasementDEMProjection.c_str());
2640 // pDataSet->SetGeoTransform(m_dGeoTransform);
2641 // double* pdRaster = new double[m_ulNumCells];
2642 // int nn = 0;
2643 // for (int nY = 0; nY < m_nYGridSize; nY++)
2644 // {
2645 // for (int nX = 0; nX < m_nXGridSize; nX++)
2646 // {
2647 // // Write this value to the array
2648 // pdRaster[nn] =
2649 // m_pRasterGrid->m_Cell[nX][nY].dGetCellDeepWaterWaveHeight(); nn++;
2650 // }
2651 // }
2652 //
2653 // GDALRasterBand* pBand = pDataSet->GetRasterBand(1);
2654 // pBand->SetNoDataValue(m_nMissingValue);
2655 // nRet = pBand->RasterIO(GF_Write, 0, 0, m_nXGridSize, m_nYGridSize,
2656 // pdRaster, m_nXGridSize, m_nYGridSize, GDT_Float64, 0, 0, NULL);
2657 //
2658 // if (nRet == CE_Failure)
2659 // return RTN_ERR_GRIDCREATE;
2660 //
2661 // GDALClose(pDataSet);
2662 // // DEBUG CODE
2663 // ===========================================================================================================
2664
2665 // // DEBUG CODE
2666 // ===========================================================================================================
2667 // strOutFile = m_strOutPath;
2668 // strOutFile += "init_deep_water_wave_angle_";
2669 // strOutFile += to_string(m_ulIter);
2670 // strOutFile += ".tif";
2671 // pDataSet = pDriver->Create(strOutFile.c_str(), m_nXGridSize,
2672 // m_nYGridSize, 1, GDT_Float64, m_papszGDALRasterOptions);
2673 // pDataSet->SetProjection(m_strGDALBasementDEMProjection.c_str());
2674 // pDataSet->SetGeoTransform(m_dGeoTransform);
2675 // nn = 0;
2676 // for (int nY = 0; nY < m_nYGridSize; nY++)
2677 // {
2678 // for (int nX = 0; nX < m_nXGridSize; nX++)
2679 // {
2680 // // Write this value to the array
2681 // pdRaster[nn] =
2682 // m_pRasterGrid->m_Cell[nX][nY].dGetCellDeepWaterWaveAngle(); nn++;
2683 // }
2684 // }
2685 //
2686 // pBand = pDataSet->GetRasterBand(1);
2687 // pBand->SetNoDataValue(m_nMissingValue);
2688 // nRet = pBand->RasterIO(GF_Write, 0, 0, m_nXGridSize, m_nYGridSize,
2689 // pdRaster, m_nXGridSize, m_nYGridSize, GDT_Float64, 0, 0, NULL);
2690 //
2691 // if (nRet == CE_Failure)
2692 // return RTN_ERR_GRIDCREATE;
2693 //
2694 // GDALClose(pDataSet);
2695 // delete[] pdRaster;
2696 // // DEBUG CODE
2697 // ===========================================================================================================
2698
2699 return RTN_OK;
2700 }
Contains CGeom2DIPoint definitions.
Geometry class used to represent 2D point objects with integer coordinates.
Definition 2di_point.h:25
int m_nLogFileDetail
The level of detail in the log file output. Can be LOG_FILE_LOW_DETAIL, LOG_FILE_MIDDLE_DETAIL,...
Definition simulation.h:588
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:516
int m_nYMinBoundingBox
The minimum y value of the bounding box.
Definition simulation.h:558
string m_strGDALISSProjection
GDAL projection string for the initial suspended sediment raster file.
string m_strInitialSuspSedimentFile
Name of initial suspended sediment file.
void GetRasterOutputMinMax(int const, double &, double &, int const, double const)
Finds the max and min values in order to scale raster output if we cannot write doubles.
vector< string > m_VstrInitialCoarseUnconsSedimentFile
The name of the initial coarse-sized unconsolidated sediment GIS file.
double m_dThisIterSWL
The still water level for this timestep (this includes tidal changes and any long-term SWL change)
Definition simulation.h:726
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:477
vector< double > m_VdDeepWaterWaveStationY
Y coordinate (grid CRS) for deep water wave station.
vector< string > m_VstrGDALICFDataType
GDAL data type for the initial consolidated fine sediment GIS data.
ofstream LogStream
vector< string > m_VstrGDALICCDriverCode
GDAL driver code for the initial consolidated coarse sediment GIS data.
int m_nGISMissingValue
The value for integer missing values, as read from GIS input files.
Definition simulation.h:546
int nReadRasterGISFile(int const, int const)
Reads raster GIS datafiles into the RasterGrid array.
vector< CRWCoast > m_VCoast
The coastline objects.
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:978
long m_lGDALMaxCanWrite
The maximum integer value which GDAL can write, can be UINT8_MAX, INT16_MAX, UINT16_MAX,...
Definition simulation.h:603
double m_dSouthEastXExtCRS
The south-east x coordinate, in the external coordinate reference system (CRS)
Definition simulation.h:663
int m_nMissingValue
Used by CoastalME for integer missing values.
Definition simulation.h:549
int m_nYGridSize
The size of the grid in the y direction.
Definition simulation.h:480
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:711
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:981
double m_dInvCellDiagonal
Inverse of m_dCellDiagonal.
Definition simulation.h:684
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:618
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:372
string m_strGDALLDataType
GDAL data type for the initial landform class raster file.
string m_strRasterGISOutFormat
Raster GIS output format.
bool m_bGDALOptimisations
GDAL optimisations enabled?
Definition simulation.h:459
int m_nXMaxBoundingBox
The maximum x value of the bounding box.
Definition simulation.h:555
unsigned long m_ulMissingValue
Used by CoastalME for unsigned long integer missing values.
Definition simulation.h:651
double m_dNorthWestYExtCRS
The north-west y coordinate, in the external coordinate reference system (CRS)
Definition simulation.h:660
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:2539
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:648
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:765
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:678
double m_dInvCellSide
Inverse of m_dCellSide.
Definition simulation.h:681
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:693
vector< string > m_VstrGDALICCProjection
GDAL projection for the initial consolidated coarse sediment GIS data.
int nInterpolateWavesToPolygonCells(vector< TransectWaveData > const *, vector< double > const *, vector< double > const *, vector< double > const *, vector< double > const *)
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:657
vector< CGeom2DIPoint > m_VEdgeCell
Edge cells.
int nInterpolateAllDeepWaterWaveValues(void)
double m_dSouthEastYExtCRS
The south-east y coordinate, in the external coordinate reference system (CRS)
Definition simulation.h:666
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:453
vector< string > m_VstrGDALIUSDriverDesc
GDAL driver description for the initial unconsolidated sand sediment GIS data.
vector< string > m_VstrInitialFineUnconsSedimentFile
The name of the initial fine-sized unconsolidated sediment GIS file.
string m_strOutPath
Path for all output files.
int m_nYMaxBoundingBox
The maximum y value of the bounding box.
Definition simulation.h:561
vector< string > m_VstrGDALICFDriverDesc
GDAL driver description for the initial consolidated fine sediment GIS data.
vector< string > m_VstrGDALIUFDriverDesc
GDAL driver description for the initial unconsolidated fine sediment GIS data.
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:519
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:606
string m_strGDALISSDriverDesc
GDAL description for the initial suspended sediment raster file.
double m_dTimeStep
The length of an iteration (a timestep) in hours.
Definition simulation.h:690
static void AnnounceAllocateMemory(void)
Tells the user that we are now allocating memory.
Definition utils.cpp:508
int m_nXMinBoundingBox
The minimum x value of the bounding box.
Definition simulation.h:552
vector< string > m_VstrGDALIUCDriverCode
GDAL driver code for the initial unconsolidated coarse sediment GIS data.
double m_dCellArea
Area of a cell (in external CRS units)
Definition simulation.h:675
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:1682
string m_strGDALBasementDEMDriverDesc
GDAL description of the basement DEM raster file type.
string m_strInitialLandformFile
Name of initial landform file.
string m_strInterventionHeightFile
Name of intervention height file.
vector< string > m_VstrGDALICSDataType
GDAL data type for the initial consolidated sand sediment GIS data.
bool m_bScaleRasterOutput
Scale raster output?
Definition simulation.h:381
vector< string > m_VstrGDALICSProjection
GDAL dprojection for the initial consolidated sand sediment GIS data.
string m_strGDALRasterOutputDriverExtension
GDAL raster output driver file extension.
string m_strGDALBasementDEMProjection
GDAL projection string for the basement DEM raster file.
unsigned long m_ulIter
The number of the current iteration (time step)
Definition simulation.h:609
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:669
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:672
vector< string > m_VstrGDALIUCDriverDesc
GDAL driver description for the initial unconsolidated coarse sediment GIS data.
int nMarkBoundingBoxEdgeCells(void)
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:600
bool m_bGDALCanWriteFloat
Is the selected GDAL output file format capable of writing floating-point values to files?
Definition simulation.h:375
char ** m_papszGDALRasterOptions
Options for GDAL when handling raster files.
Definition simulation.h:471
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.
void Interpolate(std::vector< Point2D > const &query_points, std::vector< double > &results_x, std::vector< double > &results_y) const
This file contains global definitions for CoastalME.
int const NO_NONZERO_THICKNESS_LAYERS
Definition cme.h:672
int const INT_NODATA
Definition cme.h:380
int const RASTER_PLOT_POLYGON
Definition cme.h:522
int const RASTER_PLOT_CONS_SED_SLOPE
Definition cme.h:539
string const RASTER_SEA_DEPTH_NAME
Definition cme.h:919
T tMin(T a, T b)
Definition cme.h:1175
double const TOLERANCE
Definition cme.h:725
string const RASTER_CLIFF_COLLAPSE_TIMESTEP_NAME
Definition cme.h:872
string const RASTER_SHADOW_DOWNDRIFT_ZONE_NAME
Definition cme.h:929
string const RASTER_POTENTIAL_BEACH_EROSION_NAME
Definition cme.h:909
string const RASTER_BEACH_MASK_NAME
Definition cme.h:858
string const RASTER_TOTAL_CLIFF_COLLAPSE_DEPOSITION_SAND_NAME
Definition cme.h:952
string const RASTER_POLYGON_UPDRIFT_OR_DOWNDRIFT_NAME
Definition cme.h:907
int const RASTER_PLOT_TOTAL_ACTUAL_BEACH_EROSION
Definition cme.h:542
int const RASTER_PLOT_CLIFF_COLLAPSE_DEPOSITION_SAND
Definition cme.h:499
int const RASTER_PLOT_BEACH_DEPOSITION
Definition cme.h:495
int const RASTER_PLOT_SUSPENDED_SEDIMENT
Definition cme.h:540
string const RASTER_FINE_CONS_NAME
Definition cme.h:891
string const RASTER_SLOPE_FOR_CLIFF_TOE_NAME
Definition cme.h:934
string const RASTER_SLICE_NAME
Definition cme.h:933
int const RTN_ERR_DEMFILE
Definition cme.h:598
int const RASTER_PLOT_FINE_UNCONSOLIDATED_SEDIMENT
Definition cme.h:515
string const RASTER_BEACH_DEPOSITION_NAME
Definition cme.h:856
int const SAND_CONS_RASTER
Definition cme.h:450
string const RASTER_BEACH_PROTECTION_NAME
Definition cme.h:860
int const RTN_ERR_MEMALLOC
Definition cme.h:601
string const ERR
Definition cme.h:805
int const RASTER_PLOT_INUNDATION_MASK
Definition cme.h:518
string const RASTER_SAND_UNCONS_NAME
Definition cme.h:917
int const RASTER_PLOT_ACTUAL_BEACH_EROSION
Definition cme.h:488
string const RASTER_INUNDATION_MASK_NAME
Definition cme.h:899
string const RASTER_WAVE_PERIOD_NAME
Definition cme.h:971
int const RASTER_PLOT_POTENTIAL_PLATFORM_EROSION_MASK
Definition cme.h:527
int const RTN_ERR_GRIDCREATE
Definition cme.h:640
int const RASTER_PLOT_SAND_CONSOLIDATED_SEDIMENT
Definition cme.h:528
int const RASTER_PLOT_AVG_WAVE_HEIGHT
Definition cme.h:492
string const RASTER_CLIFF_COLLAPSE_EROSION_SAND_NAME
Definition cme.h:870
string const RASTER_FINE_UNCONS_NAME
Definition cme.h:893
string const RASTER_COAST_NAME
Definition cme.h:881
int const RASTER_PLOT_FINE_CONSOLIDATED_SEDIMENT
Definition cme.h:514
string const RASTER_CLIFF_COLLAPSE_EROSION_FINE_NAME
Definition cme.h:868
string const RASTER_SEDIMENT_INPUT_EVENT_NAME
Definition cme.h:921
int const RASTER_PLOT_TOP_ELEV_INC_SEA
Definition cme.h:521
string const RASTER_CLIFF_COLLAPSE_DEPOSITION_SAND_NAME
Definition cme.h:864
int const RASTER_PLOT_ACTIVE_ZONE
Definition cme.h:487
string const RASTER_ACTIVE_ZONE_NAME
Definition cme.h:839
int const LOG_FILE_MIDDLE_DETAIL
Definition cme.h:393
string const RASTER_INTERVENTION_HEIGHT_NAME
Definition cme.h:897
string const RASTER_SHADOW_ZONE_NAME
Definition cme.h:931
int const RASTER_PLOT_DEEP_WATER_WAVE_PERIOD
Definition cme.h:513
int const RTN_ERR_RASTER_FILE_READ
Definition cme.h:599
string const RASTER_COARSE_CONS_NAME
Definition cme.h:877
int const RASTER_PLOT_TALUS
Definition cme.h:541
int const RASTER_PLOT_TOTAL_CLIFF_COLLAPSE_DEPOSITION_SAND
Definition cme.h:546
string const RASTER_TOTAL_CLIFF_COLLAPSE_EROSION_SAND_NAME
Definition cme.h:958
double const PI
Definition cme.h:707
int const RASTER_PLOT_COAST
Definition cme.h:510
string const RASTER_ACTUAL_BEACH_EROSION_NAME
Definition cme.h:841
string const RASTER_SETUP_SURGE_RUNUP_FLOOD_MASK_NAME
Definition cme.h:927
bool bFPIsEqual(const T d1, const T d2, const T dEpsilon)
Definition cme.h:1213
string const RASTER_CLIFF_TOE_NAME
Definition cme.h:875
string const RASTER_AVG_WAVE_ORIENTATION_NAME
Definition cme.h:852
string const RASTER_TOTAL_BEACH_DEPOSITION_NAME
Definition cme.h:948
int const RASTER_PLOT_POLYGON_UPDRIFT_OR_DOWNDRIFT
Definition cme.h:524
string const RASTER_TOTAL_CLIFF_COLLAPSE_DEPOSITION_COARSE_NAME
Definition cme.h:950
string const RASTER_CLIFF_NOTCH_ALL_NAME
Definition cme.h:874
int const RASTER_PLOT_POLYGON_GAIN_OR_LOSS
Definition cme.h:523
int const RASTER_PLOT_DEEP_WATER_WAVE_ORIENTATION
Definition cme.h:512
int const RASTER_PLOT_TOTAL_CLIFF_COLLAPSE_EROSION_COARSE
Definition cme.h:547
int const RTN_ERR_BOUNDING_BOX
Definition cme.h:646
string const RASTER_SLOPE_OF_CONSOLIDATED_SEDIMENT_NAME
Definition cme.h:936
int const RASTER_PLOT_COARSE_UNCONSOLIDATED_SEDIMENT
Definition cme.h:509
int const RASTER_PLOT_AVG_WAVE_ORIENTATION
Definition cme.h:493
int const RASTER_PLOT_WAVE_ORIENTATION
Definition cme.h:554
string const RASTER_SUSP_SED_NAME
Definition cme.h:938
int const RASTER_PLOT_BEACH_MASK
Definition cme.h:496
string const RASTER_AVG_SEA_DEPTH_NAME
Definition cme.h:846
int const RASTER_PLOT_WAVE_FLOOD_LINE
Definition cme.h:552
int const RASTER_PLOT_SEDIMENT_INPUT
Definition cme.h:531
int const RASTER_PLOT_POTENTIAL_BEACH_EROSION
Definition cme.h:525
int const RASTER_PLOT_AVG_SUSPENDED_SEDIMENT
Definition cme.h:491
string const RASTER_AVG_WAVE_HEIGHT_NAME
Definition cme.h:850
string const RASTER_SEDIMENT_TOP_ELEVATION_NAME
Definition cme.h:923
int const RASTER_PLOT_TOTAL_POTENTIAL_PLATFORM_EROSION
Definition cme.h:551
int const RASTER_PLOT_SLOPE_FOR_CLIFF_TOE
Definition cme.h:538
string const RASTER_WAVE_FLOOD_LINE_NAME
Definition cme.h:965
string const RASTER_POTENTIAL_PLATFORM_EROSION_NAME
Definition cme.h:913
int const INTERVENTION_CLASS_RASTER
Definition cme.h:457
string const RASTER_ACTUAL_PLATFORM_EROSION_NAME
Definition cme.h:843
string const RASTER_COARSE_UNCONS_NAME
Definition cme.h:879
int const RASTER_PLOT_INTERVENTION_CLASS
Definition cme.h:516
string const WARN
Definition cme.h:806
int const RASTER_PLOT_BEACH_PROTECTION
Definition cme.h:497
int const RASTER_PLOT_AVG_SEA_DEPTH
Definition cme.h:490
int const RASTER_PLOT_TOTAL_BEACH_DEPOSITION
Definition cme.h:544
string const RASTER_SETUP_SURGE_FLOOD_MASK_NAME
Definition cme.h:925
string const RASTER_TOP_ELEVATION_INC_SEA_NAME
Definition cme.h:942
string const RASTER_INTERVENTION_CLASS_NAME
Definition cme.h:895
int const RASTER_PLOT_TOTAL_CLIFF_COLLAPSE_EROSION_FINE
Definition cme.h:548
string const RASTER_WAVE_ORIENTATION_NAME
Definition cme.h:969
int const RASTER_PLOT_TOTAL_CLIFF_COLLAPSE_EROSION_SAND
Definition cme.h:549
string const RASTER_DEEP_WATER_WAVE_ORIENTATION_NAME
Definition cme.h:887
int const RASTER_PLOT_CLIFF_TOE
Definition cme.h:507
string const RASTER_POTENTIAL_PLATFORM_EROSION_MASK_NAME
Definition cme.h:912
int const RASTER_PLOT_CLIFF_COLLAPSE_EROSION_FINE
Definition cme.h:501
int const SOUTH
Definition cme.h:403
int const RASTER_PLOT_ACTUAL_PLATFORM_EROSION
Definition cme.h:489
int const LOG_FILE_ALL
Definition cme.h:395
int const EAST
Definition cme.h:401
int const RASTER_PLOT_SED_TOP_INC_TALUS_ELEV
Definition cme.h:532
int const RTN_OK
Definition cme.h:585
string const RASTER_WAVE_HEIGHT_NAME
Definition cme.h:967
int const RASTER_PLOT_INTERVENTION_HEIGHT
Definition cme.h:517
int const SAND_UNCONS_RASTER
Definition cme.h:453
int const RASTER_PLOT_TOTAL_POTENTIAL_BEACH_EROSION
Definition cme.h:550
string const RASTER_TOTAL_POTENTIAL_BEACH_EROSION_NAME
Definition cme.h:960
int const RASTER_PLOT_SAND_UNCONSOLIDATED_SEDIMENT
Definition cme.h:529
string const RASTER_SAND_CONS_NAME
Definition cme.h:915
int const RASTER_PLOT_POTENTIAL_PLATFORM_EROSION
Definition cme.h:526
string const RASTER_BASEMENT_ELEVATION_NAME
Definition cme.h:854
int const FINE_UNCONS_RASTER
Definition cme.h:452
int const COARSE_UNCONS_RASTER
Definition cme.h:454
int const RASTER_PLOT_NORMAL_PROFILE
Definition cme.h:520
double const DBL_NODATA
Definition cme.h:736
int const RASTER_PLOT_CLIFF_NOTCH_ALL
Definition cme.h:506
int const RASTER_PLOT_CLIFF_COLLAPSE_DEPOSITION_COARSE
Definition cme.h:498
int const RASTER_PLOT_WAVE_HEIGHT
Definition cme.h:553
int const RASTER_PLOT_SHADOW_ZONE
Definition cme.h:536
int const RASTER_PLOT_DEEP_WATER_WAVE_HEIGHT
Definition cme.h:511
string const RASTER_COAST_NORMAL_NAME
Definition cme.h:883
string const NOTE
Definition cme.h:807
string const RASTER_CLIFF_COLLAPSE_EROSION_COARSE_NAME
Definition cme.h:866
int const RASTER_PLOT_COARSE_CONSOLIDATED_SEDIMENT
Definition cme.h:508
string const RASTER_LANDFORM_NAME
Definition cme.h:901
int const RASTER_PLOT_TOTAL_ACTUAL_PLATFORM_EROSION
Definition cme.h:543
int const SUSP_SED_RASTER
Definition cme.h:455
int const FINE_CONS_RASTER
Definition cme.h:449
int const COARSE_CONS_RASTER
Definition cme.h:451
int const RASTER_PLOT_SETUP_SURGE_RUNUP_FLOOD_MASK
Definition cme.h:534
int const RASTER_PLOT_BASEMENT_ELEVATION
Definition cme.h:494
int const RASTER_PLOT_LANDFORM
Definition cme.h:519
string const RASTER_TOTAL_ACTUAL_PLATFORM_EROSION_NAME
Definition cme.h:946
string const RASTER_POLYGON_NAME
Definition cme.h:905
int const RASTER_PLOT_CLIFF_COLLAPSE_EROSION_COARSE
Definition cme.h:500
T tAbs(T a)
Definition cme.h:1187
string const RASTER_TOTAL_CLIFF_COLLAPSE_EROSION_FINE_NAME
Definition cme.h:956
int const LANDFORM_RASTER
Definition cme.h:456
int const RASTER_PLOT_SHADOW_DOWNDRIFT_ZONE
Definition cme.h:535
string const RASTER_TALUS_NAME
Definition cme.h:940
int const RASTER_PLOT_SLICE
Definition cme.h:537
string const RASTER_TOTAL_POTENTIAL_PLATFORM_EROSION_NAME
Definition cme.h:962
string const RASTER_AVG_SUSP_SED_NAME
Definition cme.h:848
string const RASTER_DEEP_WATER_WAVE_HEIGHT_NAME
Definition cme.h:885
int const INTERVENTION_HEIGHT_RASTER
Definition cme.h:458
string const RASTER_TOTAL_CLIFF_COLLAPSE_EROSION_COARSE_NAME
Definition cme.h:954
string const RASTER_POLYGON_GAIN_OR_LOSS_NAME
Definition cme.h:904
int const RASTER_PLOT_TOTAL_CLIFF_COLLAPSE_DEPOSITION_COARSE
Definition cme.h:545
string const RASTER_TOTAL_ACTUAL_BEACH_EROSION_NAME
Definition cme.h:944
int const RASTER_PLOT_CLIFF_COLLAPSE_EROSION_SAND
Definition cme.h:502
int const RASTER_PLOT_SEA_DEPTH
Definition cme.h:530
int const NORTH
Definition cme.h:399
string const RASTER_CLIFF_COLLAPSE_DEPOSITION_COARSE_NAME
Definition cme.h:862
int const RASTER_PLOT_SETUP_SURGE_FLOOD_MASK
Definition cme.h:533
int const WEST
Definition cme.h:405
Contains CRWCoast definitions.
Contains CSimulation definitions.
double dRound(double const d)
Correctly rounds doubles.