CoastalME (Coastal Modelling Environment)
Simulates the long-term behaviour of complex coastlines
Loading...
Searching...
No Matches
create_polygons.cpp
Go to the documentation of this file.
1
10
11/* ==============================================================================================================================
12 This file is part of CoastalME, the Coastal Modelling Environment.
13
14 CoastalME is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
15
16 This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19==============================================================================================================================*/
20#include <assert.h>
21
22#include <iostream>
23using std::endl;
24
25#include <stack>
26using std::stack;
27
28#include "cme.h"
29#include "simulation.h"
30#include "coast.h"
31#include "2d_point.h"
32#include "2di_point.h"
33
34//===============================================================================================================================
36//===============================================================================================================================
38{
39 LogStream << endl << m_ulIter << ": Creating polygons" << endl;
40
41 // Do this for each coast
42 for (int nCoast = 0; nCoast < static_cast<int>(m_VCoast.size()); nCoast++)
43 {
44 int nNode = -1;
45 int nNextProfile = -1;
46 int nPolygon = -1;
47
48 // Do this for every point on the coastline (except the last point)
49 int const nCoastSize = m_VCoast[nCoast].nGetCoastlineSize();
50
51 for (int nCoastPoint = 0; nCoastPoint < nCoastSize - 1; nCoastPoint++)
52 {
53 if (! m_VCoast[nCoast].bIsProfileAtCoastPoint(nCoastPoint))
54 continue;
55
56 // OK, this coast point is the start of a coastline-normal profile
57 CGeomProfile* pThisProfile = m_VCoast[nCoast].pGetProfileAtCoastPoint(nCoastPoint);
58
59 if (pThisProfile->bOKIncStartAndEndOfCoast())
60 {
61 // This profile is OK, so we will start a polygon here and extend it down-coast (i.e. along the coast in the direction of increasing coastline point numbers)
62 int const nThisProfile = pThisProfile->nGetProfileID();
63
64 // This will be the coast ID number of the polygon, and also the polygon's along-coast sequence
65 nPolygon++;
66
67 // Now get a pointer to the next (down-coast) profile
68 CGeomProfile* pNextProfile = pThisProfile->pGetDownCoastAdjacentProfile();
69
70 bool bNextProfileIsOK = false;
71
72 do
73 {
74 // if (pNextProfile == NULL) // TODO THIS GIVES CPPCHECK ERROR
75 // {
76 // LogStream << m_ulIter << ": nThisProfile = " << nThisProfile << " invalid down-coast adjacent profile, trying next down-coast adjacent profile" << endl;
77 //
78 // // Try the next-after-next profile
79 // CGeomProfile* pNextNextProfile = pNextProfile->pGetDownCoastAdjacentProfile();
80 // pNextProfile = pNextNextProfile;
81 // continue;
82 // }
83
84 // Get the ID of the next (down-coast) profile
85 nNextProfile = pNextProfile->nGetProfileID();
86
87 // Is the next profile OK?
88 bNextProfileIsOK = pNextProfile->bOKIncStartAndEndOfCoast();
89
90 if (! bNextProfileIsOK)
91 {
92 // Nope, the next profile is not OK
93 // LogStream << m_ulIter << ": down-coast adjacent profile = " << nNextProfile << " is not OK" << endl;
94
95 // So try the following profile
96 CGeomProfile* pNextNextProfile = pNextProfile->pGetDownCoastAdjacentProfile();
97 pNextProfile = pNextNextProfile;
98 }
99
100 } while (! bNextProfileIsOK);
101
102 // LogStream << "Profile " << pNextProfile->nGetProfileID() << " is OK" << endl;
103
104 // Get the coast point at which this next profile starts
105 int const nNextProfileCoastPoint = pNextProfile->nGetCoastPoint();
106
107 // Calculate half the along-coast distance (in coast points) between this profile and the next (i.e. down-coast) profile
108 int const nDist = (nNextProfileCoastPoint - nCoastPoint) / 2;
109
110 // OK, set the node point in the coast object. We do this now, instead of earlier on, since some profiles (i.e. polygon boundaries) may have been marked as invalid
111 int const nNodePoint = nCoastPoint + nDist;
112 m_VCoast[nCoast].SetPolygonNode(nNodePoint, ++nNode);
113
114 // Get the grid CRS coordinates of the coast node
115 CGeom2DIPoint const PtiNode = *m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(nNodePoint);
116
117 // Get some defaults (assuming for now that this polygon is not approximately triangular i.e. both normals do not meet)
118 int nNextProfileEnd = pNextProfile->nGetProfileSize() - 1;
119 int nThisProfileEnd = pThisProfile->nGetProfileSize() - 1;
120 bool bMeetsAtAPoint = false;
121 CGeom2DPoint PtCoastwardTip;
122
123 // // DEBUG CODE =============================================================================================
124 // CGeom2DPoint PtNextEndTmp = *pNextProfile->pPtGetPointInProfile(nNextProfileEnd);
125 // double dXTmp = dExtCRSXToGridX(PtNextEndTmp.dGetX());
126 // double dYTmp = dExtCRSYToGridY(PtNextEndTmp.dGetY());
127 // assert(bIsWithinValidGrid(dXTmp, dYTmp));
128 //
129 // CGeom2DPoint PtThisEndTmp = *pThisProfile->pPtGetPointInProfile(nThisProfileEnd);
130 // dXTmp = dExtCRSXToGridX(PtThisEndTmp.dGetX());
131 // dYTmp = dExtCRSYToGridY(PtThisEndTmp.dGetY());
132 // assert(bIsWithinValidGrid(dXTmp, dYTmp));
133 // // DEBUG CODE =============================================================================================
134
135 // Now check to see if the two normals do meet i.e. if they are coincident
136 if (pThisProfile->bFindProfileInCoincidentProfiles(nNextProfile))
137 {
138 // Yes they do meet
139 bMeetsAtAPoint = true;
140 int nTmpThisProfileEnd;
141 int nTmpNextProfileEnd;
142
143 // Find the most coastward point at which this normal and the previous normal touch. If they do not touch, the polygon requires a 'joining line'
144 pThisProfile->GetMostCoastwardSharedLineSegment(nNextProfile, nTmpThisProfileEnd, nTmpNextProfileEnd);
145
146 if (nTmpThisProfileEnd == -1)
147 {
148 LogStream << m_ulIter << ": " << ERR << "profile " << nNextProfile << " should be coincident with profile " << nThisProfile << " but was not found" << endl;
150 }
151
152 // Safety check: make sure that nThisProfileEnd is no bigger than pThisProfile->nGetProfileSize()-1, and the same for nNextProfileEnd
153 nThisProfileEnd = tMin(nThisProfileEnd, nTmpThisProfileEnd);
154 nNextProfileEnd = tMin(nNextProfileEnd, nTmpNextProfileEnd);
155
156 PtCoastwardTip = *pThisProfile->pPtGetPointInProfile(nThisProfileEnd);
157 }
158
159 // Create the vector in which to store the polygon's boundary (external CRS). Note that these points are not in sequence
160 vector<CGeom2DPoint> PtVBoundary;
161
162 // Start appending points: begin by appending the points in this normal, in reverse order
163 for (int i = nThisProfileEnd; i >= 0; i--)
164 {
165 CGeom2DPoint const PtThis = *pThisProfile->pPtGetPointInProfile(i);
166 PtVBoundary.push_back(PtThis);
167 }
168
169 // Next add coast points: from the start point of this normal, moving down-coast as far as the down-coast norma
170 for (int i = nCoastPoint; i <= nNextProfileCoastPoint; i++)
171 {
172 CGeom2DPoint const PtThis = *m_VCoast[nCoast].pPtGetCoastlinePointExtCRS(i);
173 PtVBoundary.push_back(PtThis);
174 }
175
176 // Append the points in the down-coast (next) normal
177 for (int i = 0; i <= nNextProfileEnd; i++)
178 {
179 CGeom2DPoint const PtThis = *pNextProfile->pPtGetPointInProfile(i);
180 PtVBoundary.push_back(PtThis);
181 }
182
183 // Finally, append the end point of this normal
184 CGeom2DPoint const PtThis = *pThisProfile->pPtGetPointInProfile(nThisProfileEnd);
185 PtVBoundary.push_back(PtThis);
186
187 // Now identify the 'anti-node', this is the seaward point 'opposite' the polygon's coastal node
188 CGeom2DIPoint PtiAntiNode;
189
190 if (bMeetsAtAPoint)
191 PtiAntiNode = PtiExtCRSToGridRound(&PtCoastwardTip);
192 else
193 {
194 CGeom2DPoint const PtAvg = PtAverage(pThisProfile->pPtGetPointInProfile(nThisProfileEnd), pNextProfile->pPtGetPointInProfile(nNextProfileEnd));
195 PtiAntiNode = PtiExtCRSToGridRound(&PtAvg);
196 }
197
198 // Is this a start-of-coast or an end-of-coast polygon?
199 bool bStartCoast = false;
200 bool bEndCoast = false;
201
202 if (pThisProfile->bStartOfCoast())
203 bStartCoast = true;
204
205 if (pNextProfile->bEndOfCoast())
206 bEndCoast = true;
207
208 // Create the coast polygon object, store it, and get a pointer to it
209 CGeomCoastPolygon* pPolygon = m_VCoast[nCoast].pPolyCreateAndAppendPolygon(nPolygon, nNodePoint, &PtiNode, &PtiAntiNode, nThisProfile, nNextProfile, &PtVBoundary, nThisProfileEnd + 1, nNextProfileEnd + 1, bStartCoast, bEndCoast);
210
211 // Save the profile-end vertices (but omit the last one if the profiles meet at a point)
212 pPolygon->AppendVertex(pThisProfile->pPtiGetStartPoint());
213 pPolygon->AppendVertex(pThisProfile->pPtiGetEndPoint());
214 pPolygon->AppendVertex(pNextProfile->pPtiGetStartPoint());
215
216 if (! bMeetsAtAPoint)
217 pPolygon->AppendVertex(pNextProfile->pPtiGetEndPoint());
218
219 // // DEBUG CODE =================================================================================
220 // LogStream << m_ulIter << ": vertices for coast " << nCoast << " polygon = " << nPolygon << endl;
221 // for (int n = 0; n < pPolygon->nGetNumVertices(); n++)
222 // LogStream << "[" << pPolygon->PtiGetVertex(n).nGetX() << "][" << pPolygon->PtiGetVertex(n).nGetY() << "]\t";
223 // LogStream << endl;
224 // // DEBUG CODE =================================================================================
225
226 // assert(nPolygon < m_VCoast[nCoast].nGetNumPolygons());
227
228 // Now rasterize the polygon boundaries: first, the coastline. This is necessary so that sand/coarse sediment derived from platform erosion of the coast cells is correctly added to the containing polygon's unconsolidated sediment
229 for (int i = nCoastPoint; i <= nNextProfileCoastPoint; i++)
230 {
231 CGeom2DIPoint const PtiToMark = *m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(i);
232 m_pRasterGrid->m_Cell[PtiToMark.nGetX()][PtiToMark.nGetY()].SetCoastAndPolygonID(nCoast, nPolygon);
233 }
234
235 // Do the down-coast normal profile (does the whole length, including any shared line segments. So some cells are marked twice, however this is not a problem)
236 int nCellsInProfile = pNextProfile->nGetNumCellsInProfile();
237
238 for (int i = 0; i < nCellsInProfile; i++)
239 {
240 CGeom2DIPoint const PtiToMark = *pNextProfile->pPtiGetCellInProfile(i);
241 m_pRasterGrid->m_Cell[PtiToMark.nGetX()][PtiToMark.nGetY()].SetCoastAndPolygonID(nCoast, nPolygon);
242 }
243
244 // Do this normal profile (again does the whole length, including any shared line segments)
245 nCellsInProfile = pThisProfile->nGetNumCellsInProfile();
246
247 for (int i = 0; i < nCellsInProfile; i++)
248 {
249 CGeom2DIPoint const PtiToMark = *pThisProfile->pPtiGetCellInProfile(i);
250 m_pRasterGrid->m_Cell[PtiToMark.nGetX()][PtiToMark.nGetY()].SetCoastAndPolygonID(nCoast, nPolygon);
251 }
252
253 // If the polygon doesn't meet at a point at its seaward end, also need to rasterize the 'joining line'
254 if (! bMeetsAtAPoint)
255 {
256 CGeom2DIPoint const PtiDownCoastNormalEnd = *pNextProfile->pPtiGetEndPoint(); // Grid CRS
257 CGeom2DIPoint const PtiUpCoastNormalEnd = *pThisProfile->pPtiGetEndPoint(); // Grid CRS
258
259 RasterizePolygonJoiningLine(nCoast, &PtiUpCoastNormalEnd, &PtiDownCoastNormalEnd, nPolygon);
260
261 // pPolygon->SetNotPointed();
262 }
263
264 // }
265
266 // nNextProfile = nThisProfile;
267 nCoastPoint = nNextProfileCoastPoint - 1;
268
269 if (bEndCoast)
270 break;
271 }
272 }
273 }
274
275 return RTN_OK;
276}
277
278//===============================================================================================================================
280//===============================================================================================================================
281void CSimulation::RasterizePolygonJoiningLine(int nCoast, CGeom2DIPoint const* pPt1, CGeom2DIPoint const* pPt2, int const nPoly)
282{
283 // The start point of the line (grid CRS)
284 int const nXStart = pPt1->nGetX();
285 int const nYStart = pPt1->nGetY();
286
287 // The end point of the line (grid CRS)
288 int const nXEnd = pPt2->nGetX();
289 int const nYEnd = pPt2->nGetY();
290
291 // Safety check, in case the two points are identical (can happen due to rounding errors)
292 if ((nXStart == nXEnd) && (nYStart == nYEnd))
293 return;
294
295 // Interpolate between cells by a simple DDA line algorithm, see http://en.wikipedia.org/wiki/Digital_differential_analyzer_(graphics_algorithm) Note that Bresenham's algorithm gave occasional gaps
296 double dXInc = nXEnd - nXStart;
297 double dYInc = nYEnd - nYStart;
298 double const dLength = tMax(tAbs(dXInc), tAbs(dYInc));
299
300 dXInc /= dLength;
301 dYInc /= dLength;
302
303 double dX = nXStart;
304 double dY = nYStart;
305
306 // Process each interpolated point
307 for (int m = 0; m <= nRound(dLength); m++)
308 {
309 int nX = nRound(dX);
310 int nY = nRound(dY);
311
312 // Safety check
313 if (! bIsWithinValidGrid(nX, nY))
314 KeepWithinValidGrid(nXStart, nYStart, nX, nY);
315
316 // assert(nPoly < m_VCoast[0].nGetNumPolygons());
317
318 // Mark this point on the raster grid
319 m_pRasterGrid->m_Cell[nX][nY].SetCoastAndPolygonID(nCoast, nPoly);
320
321 // And increment for next time
322 dX += dXInc;
323 dY += dYInc;
324 }
325}
326
327//===============================================================================================================================
329//===============================================================================================================================
331{
332 // // DEBUG CODE =================================================================================
333 // vector<CGeom2DIPoint> VPtiCentroids;
334 // vector<int> VnID;
335 //
336 // // Do this for each coast
337 // for (int nCoast = 0; nCoast < static_cast<int>(m_VCoast.size()); nCoast++)
338 // {
339 // // Do this for every coastal polygon
340 // for (int nPoly = 0; nPoly < m_VCoast[nCoast].nGetNumPolygons(); nPoly++)
341 // {
342 // CGeomCoastPolygon* pPolygon = m_VCoast[nCoast].pGetPolygon(nPoly);
343 //
344 // int nPolyID = pPolygon->nGetPolygonCoastID();
345 // VnID.push_back(nPolyID);
346 //
347 // CGeom2DIPoint PtiStart = pPolygon->PtiGetFillStartPoint();
348 // VPtiCentroids.push_back(PtiStart);
349 // }
350 // }
351 //
352 // string strOutFile = m_strOutPath;
353 // strOutFile += "00_polygon_flood_fill_start_point_";
354 // strOutFile += to_string(m_ulIter);
355 // strOutFile += ".tif";
356 //
357 // GDALDriver* pDriver = GetGDALDriverManager()->GetDriverByName("gtiff");
358 // GDALDataset* pDataSet = pDriver->Create(strOutFile.c_str(), m_nXGridSize, m_nYGridSize, 1, GDT_Float64, m_papszGDALRasterOptions);
359 // pDataSet->SetProjection(m_strGDALBasementDEMProjection.c_str());
360 // pDataSet->SetGeoTransform(m_dGeoTransform);
361 //
362 // int nn = 0;
363 // double* pdRaster = new double[m_nXGridSize * m_nYGridSize];
364 // for (int nY = 0; nY < m_nYGridSize; nY++)
365 // {
366 // for (int nX = 0; nX < m_nXGridSize; nX++)
367 // {
368 // pdRaster[nn] = INT_NODATA;
369 //
370 // for (int n = 0; n < static_cast<int>(VPtiCentroids.size()); n++)
371 // {
372 // if ((VPtiCentroids[n].nGetX() == nX) && (VPtiCentroids[n].nGetY() == nY))
373 // {
374 // pdRaster[nn] = VnID[n];
375 // LogStream << m_ulIter << ": cell-by-cell fill start point for polygon " << VnID[n] << " is [" << nX << "][" << nY << "]" << endl;
376 // break;
377 // }
378 // }
379 // nn++;
380 // }
381 // }
382 //
383 // GDALRasterBand* pBand = pDataSet->GetRasterBand(1);
384 // pBand->SetNoDataValue(m_dMissingValue);
385 // int nRet = pBand->RasterIO(GF_Write, 0, 0, m_nXGridSize, m_nYGridSize, pdRaster, m_nXGridSize, m_nYGridSize, GDT_Float64, 0, 0, NULL);
386 //
387 // if (nRet == CE_Failure)
388 // LogStream << nRet << endl;
389 //
390 // GDALClose(pDataSet);
391 // delete[] pdRaster;
392 // // DEBUG CODE ===========================================================================================================
393
394 // Do this for each coast
395 for (int nCoast = 0; nCoast < static_cast<int>(m_VCoast.size()); nCoast++)
396 {
397 // Do this for every coastal polygon, in along-coast sequence
398 int const nPolygons = m_VCoast[nCoast].nGetNumPolygons();
399
400 for (int nPoly = 0; nPoly < nPolygons; nPoly++)
401 {
402 int nCellsInPolygon = 0;
403 double dTotDepth = 0;
404 double dStoredUnconsFine = 0;
405 double dStoredUnconsSand = 0;
406 double dStoredUnconsCoarse = 0;
407 double dStoredConsFine = 0;
408 double dStoredConsSand = 0;
409 double dStoredConsCoarse = 0;
410 double dSedimentInputFine = 0;
411 double dSedimentInputSand = 0;
412 double dSedimentInputCoarse = 0;
413
414 CGeomCoastPolygon* pPolygon = m_VCoast[nCoast].pGetPolygon(nPoly);
415 int const nPolyID = pPolygon->nGetPolygonCoastID();
416
417 // LogStream << m_ulIter << ": in MarkPolygonCells() nPoly = " << nPoly << " nPolyID = " << nPolyID << endl;
418
419 // Create an empty stack
420 stack<CGeom2DIPoint> PtiStack;
421
422 // // Since the polygon's vector boundary does not coincide exactly with the polygon's raster boundary, and the point-in-polygon check gives an indeterminate result if the point is exactly on the polygon's boundary, for safety we must construct a vector 'inner buffer' which is smaller than, and inside, the vector boundary TODO *** STILL NEEDED?
423 // int nHand = m_VCoast[nCoast].nGetSeaHandedness();
424 // int nSize = pPolygon->nGetBoundarySize();
425 // vector<CGeom2DPoint> PtVInnerBuffer;
426 //
427 // for (int i = 0; i < nSize-1; i++)
428 // {
429 // int j = i + 1;
430 // if (i == nSize-2) // We must ignore the duplicated node point
431 // j = 0;
432 //
433 // CGeom2DPoint PtThis = *pPolygon->pPtGetBoundaryPoint(i);
434 // CGeom2DPoint PtNext = *pPolygon->pPtGetBoundaryPoint(j);
435 //
436 // // Safety check
437 // if (PtThis == PtNext)
438 // continue;
439 //
440 // CGeom2DPoint PtBuffer = PtGetPerpendicular(&PtThis, &PtNext, m_dCellSide, nHand);
441 //
442 // PtVInnerBuffer.push_back(PtBuffer);
443 // }
444
445 // // DEBUG CODE ==============================================================================================
446 // LogStream << endl << m_ulIter << ": coast " << nCoast << ", polygon " << nPoly << endl;
447 // LogStream << "Boundary\t\t\tBuffer" << endl;
448 // for (int i = 0; i < pPolygon->nGetBoundarySize()-1; i++)
449 // LogStream << "{" << pPolygon->pPtGetBoundaryPoint(i)->dGetX() << ", " << pPolygon->pPtGetBoundaryPoint(i)->dGetY() << "}\t{" << PtVInnerBuffer[i].dGetX() << ", " << PtVInnerBuffer[i].dGetY() << "}" << endl;
450 // LogStream << endl;
451 // // DEBUG CODE ==============================================================================================
452
453 // Use the centroid as the start point for the cell-by-cell fill procedure
454 CGeom2DIPoint const PtiStart = pPolygon->PtiGetFillStartPoint();
455
456 // // Is the centroid within the inner buffer?
457 // if (! bIsWithinPolygon(&PtStart, &PtVInnerBuffer))
458 // {
459 // // No, it is not: the polygon must be a concave polygon. So keep looking for a point which is definitely inside the polygon, using an alternative method
460 // PtStart = PtFindPointInPolygon(&PtVInnerBuffer, pPolygon->nGetPointInPolygonSearchStartPoint());
461 // }
462 //
463 // // Safety check (PtFindPointInPolygon() returns CGeom2DPoint(DBL_NODATA, DBL_NODATA) if it cannot find a valid start point)
464 // if (bFPIsEqual(PtStart.dGetX(), DBL_NODATA, TOLERANCE))
465 // {
466 // LogStream << m_ulIter << ": " << ERR << "could not find a cell-by-cell fill start point for coast " << nCoast << ", polygon " << nPoly << endl;
467 // break;
468 // }
469
470 // We have a cell-by-cell fill start point which is definitely within the polygon so push this point onto the stack
471 // CGeom2DIPoint PtiStart;
472 // PtiStart.SetX(nRound(PtStart.dGetX())); // Grid CRS
473 // PtiStart.SetY(nRound(PtStart.dGetY())); // Grid CRS
474
475 PtiStack.push(PtiStart);
476
477 // LogStream << m_ulIter << ": filling polygon " << nPoly << " from [" << PtiStart.nGetX() << "][" << PtiStart.nGetY() << "] = {" << dGridCentroidXToExtCRSX(PtiStart.nGetX()) << ", " << dGridCentroidYToExtCRSY(PtiStart.nGetY()) << "}" << endl;
478
479 // Then do the cell-by-cell fill: loop until there are no more cell coordinates on the stack
480 while (! PtiStack.empty())
481 {
482 CGeom2DIPoint const Pti = PtiStack.top();
483 PtiStack.pop();
484
485 int nX = Pti.nGetX();
486 int const nY = Pti.nGetY();
487
488 while ((nX >= 0) && (m_pRasterGrid->m_Cell[nX][nY].nGetPolygonID() == INT_NODATA))
489 nX--;
490
491 nX++;
492
493 bool bSpanAbove = false;
494 bool bSpanBelow = false;
495
496 while ((nX < m_nXGridSize) && (m_pRasterGrid->m_Cell[nX][nY].nGetPolygonID() == INT_NODATA))
497 {
498 // assert(nPolyID < m_VCoast[nCoast].nGetNumPolygons());
499
500 // Mark the cell as being in this polygon and this coast
501 m_pRasterGrid->m_Cell[nX][nY].SetCoastAndPolygonID(nCoast, nPolyID);
502
503 // LogStream << "Marked [" << nX << "][" << nY << "] = {" << dGridCentroidXToExtCRSX(nX) << ", " << dGridCentroidYToExtCRSY(nY) << "}" << endl;
504
505 // Increment the running totals for this polygon
506 // dCliffCollapseErosionFine += m_pRasterGrid->m_Cell[nX][nY].dGetThisIterCliffCollapseErosionFine();
507 // dCliffCollapseErosionSand += m_pRasterGrid->m_Cell[nX][nY].dGetThisIterCliffCollapseErosionSand();
508 // dCliffCollapseErosionCoarse += m_pRasterGrid->m_Cell[nX][nY].dGetThisIterCliffCollapseErosionCoarse();
509 // dCliffCollapseTalusSand += m_pRasterGrid->m_Cell[nX][nY].dGetThisIterCliffCollapseSandTalusDeposition();
510 // dCliffCollapseTalusCoarse += m_pRasterGrid->m_Cell[nX][nY].dGetThisIterCliffCollapseCoarseTalusDeposition();
511
512 // Get the number of the highest layer with non-zero thickness
513 int const nThisLayer = m_pRasterGrid->m_Cell[nX][nY].nGetTopNonZeroLayerAboveBasement();
514
515 // Safety check
516 if ((nThisLayer != NO_NONZERO_THICKNESS_LAYERS) && (nThisLayer != INT_NODATA))
517 {
518 // Increment some more running totals for this polygon TODO 066 should this be for ALL layers above the basement?
519 dStoredUnconsFine += m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nThisLayer)->pGetUnconsolidatedSediment()->dGetFineDepth();
520 dStoredUnconsSand += m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nThisLayer)->pGetUnconsolidatedSediment()->dGetSandDepth();
521 dStoredUnconsCoarse += m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nThisLayer)->pGetUnconsolidatedSediment()->dGetCoarseDepth();
522
523 dStoredConsFine += m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nThisLayer)->pGetConsolidatedSediment()->dGetFineDepth();
524 dStoredConsSand += m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nThisLayer)->pGetConsolidatedSediment()->dGetSandDepth();
525 dStoredConsCoarse += m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nThisLayer)->pGetConsolidatedSediment()->dGetCoarseDepth();
526
527 // Add to the start-iteration total of suspended fine sediment within polygons
528 m_dStartIterSuspFineInPolygons += m_pRasterGrid->m_Cell[nX][nY].dGetSuspendedSediment();
529
530 // Add to the total of sediment derived from sediment input events
531 dSedimentInputFine += m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nThisLayer)->pGetUnconsolidatedSediment()->dGetFineSedimentInputDepth();
532 dSedimentInputSand += m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nThisLayer)->pGetUnconsolidatedSediment()->dGetSandSedimentInputDepth();
533 dSedimentInputCoarse += m_pRasterGrid->m_Cell[nX][nY].pGetLayerAboveBasement(nThisLayer)->pGetUnconsolidatedSediment()->dGetCoarseSedimentInputDepth();
534 }
535
536 nCellsInPolygon++;
537 dTotDepth += m_pRasterGrid->m_Cell[nX][nY].dGetSeaDepth();
538
539 if ((! bSpanAbove) && (nY > 0) && (m_pRasterGrid->m_Cell[nX][nY - 1].nGetPolygonID() == INT_NODATA))
540 {
541 PtiStack.push(CGeom2DIPoint(nX, nY - 1));
542 bSpanAbove = true;
543 }
544
545 else if (bSpanAbove && (nY > 0) && (m_pRasterGrid->m_Cell[nX][nY - 1].nGetPolygonID() != INT_NODATA))
546 {
547 bSpanAbove = false;
548 }
549
550 if ((! bSpanBelow) && (nY < m_nYGridSize - 1) && (m_pRasterGrid->m_Cell[nX][nY + 1].nGetPolygonID() == INT_NODATA))
551 {
552 PtiStack.push(CGeom2DIPoint(nX, nY + 1));
553 bSpanBelow = true;
554 }
555
556 else if (bSpanBelow && (nY < m_nYGridSize - 1) && (m_pRasterGrid->m_Cell[nX][nY + 1].nGetPolygonID() != INT_NODATA))
557 {
558 bSpanBelow = false;
559 }
560
561 nX++;
562 }
563 }
564
565 // Store this polygon's stored unconsolidated sediment depths
566 pPolygon->SetPreExistingUnconsFine(dStoredUnconsFine);
567 pPolygon->SetPreExistingUnconsSand(dStoredUnconsSand);
568 pPolygon->SetPreExistingUnconsCoarse(dStoredUnconsCoarse);
569
570 // Store this polygon's values for unconsolidated sediment derived from sediment input event(s)
571 pPolygon->SetSedimentInputUnconsFine(dSedimentInputFine);
572 pPolygon->SetSedimentInputUnconsSand(dSedimentInputSand);
573 pPolygon->SetSedimentInputUnconsCoarse(dSedimentInputCoarse);
574
575 // Store this polygon's stored consolidated sediment depths
576 pPolygon->SetPreExistingConsFine(dStoredConsFine);
577 pPolygon->SetPreExistingConsSand(dStoredConsSand);
578 pPolygon->SetPreExistingConsCoarse(dStoredConsCoarse);
579
580 // Store the number of cells in the interior of the polygon
581 pPolygon->SetNumCellsInPolygon(nCellsInPolygon);
582 // LogStream << m_ulIter << ": in MarkPolygonCells() N cells = " << nCellsInPolygon << " in polygon " << nPolyID << endl;
583
584 // Calculate the total volume of seawater on the polygon (m3) and store it
585 double const dSeaVolume = dTotDepth * m_dCellSide;
586 pPolygon->SetSeawaterVolume(dSeaVolume);
587 }
588 }
589
590 // // DEBUG CODE ===========================================================================================================
591 // if (m_ulIter == 109)
592 // {
593 // string strOutFile = m_strOutPath + "00_polygon_fill_";
594 // strOutFile += to_string(m_ulIter);
595 // strOutFile += ".tif";
596 //
597 // GDALDriver* pDriver = GetGDALDriverManager()->GetDriverByName("gtiff");
598 // GDALDataset* pDataSet = pDriver->Create(strOutFile.c_str(), m_nXGridSize, m_nYGridSize, 1, GDT_Float64, m_papszGDALRasterOptions);
599 // pDataSet->SetProjection(m_strGDALBasementDEMProjection.c_str());
600 // pDataSet->SetGeoTransform(m_dGeoTransform);
601 // double* pdRaster = new double[m_nXGridSize * m_nYGridSize];
602 // int n = 0;
603 //
604 // int nNumPoly = m_VCoast[0].nGetNumPolygons();
605 // vector<int> nVPerPoly(nNumPoly, 0);
606 // int nNotInPoly = 0;
607 //
608 // for (int nY = 0; nY < m_nYGridSize; nY++)
609 // {
610 // for (int nX = 0; nX < m_nXGridSize; nX++)
611 // {
612 // int nID = m_pRasterGrid->m_Cell[nX][nY].nGetPolygonID();
613 // if (nID == INT_NODATA)
614 // nNotInPoly++;
615 // else
616 // nVPerPoly[nID]++;
617 //
618 // pdRaster[n++] = nID;
619 // }
620 // }
621 //
622 // GDALRasterBand* pBand = pDataSet->GetRasterBand(1);
623 // pBand->SetNoDataValue(m_dMissingValue);
624 // int nRet = pBand->RasterIO(GF_Write, 0, 0, m_nXGridSize, m_nYGridSize, pdRaster, m_nXGridSize, m_nYGridSize, GDT_Float64, 0, 0, NULL);
625 // if (nRet == CE_Failure)
626 // return;
627 //
628 // GDALClose(pDataSet);
629 // delete[] pdRaster;
630 //
631 // for (int nn = 0; nn < nNumPoly; nn++)
632 // LogStream << m_ulIter << ": polygon " << nn << " has " << nVPerPoly[nn] << " cells" << endl;
633 // LogStream << m_ulIter << " Number of cells not in any polygon = " << nNotInPoly << endl;
634 // LogStream << "==================" << endl;
635 // }
636 // // DEBUG CODE ===========================================================================================================
637}
638
639//===============================================================================================================================
641//===============================================================================================================================
643{
644 // Do this for every coast
645 for (int nCoast = 0; nCoast < static_cast<int>(m_VCoast.size()); nCoast++)
646 {
647 int const nNumPolygons = m_VCoast[nCoast].nGetNumPolygons();
648
649 // // DEBUG CODE =================
650 // for (int m = 0; m < m_VCoast[nCoast].nGetNumProfiles(); m++)
651 // {
652 // CGeomProfile* pProfile = m_VCoast[nCoast].pGetProfile(m);
653 //
654 // LogStream << m << "\t" << pProfile->nGetProfileID() << "\t";
655 //
656 // int nPointsInProfile = pProfile->nGetProfileSize();
657 //
658 // for (int nPoint = 0; nPoint < nPointsInProfile; nPoint++)
659 // {
660 // CGeom2DPoint Pt = *pProfile->pPtGetPointInProfile(nPoint);
661 // LogStream << "{" << Pt.dGetX() << ", " << Pt.dGetY() << "}";
662 // }
663 // LogStream << endl;
664 // }
665 // // DEBUG CODE =================
666
667 // Do this for every coastal polygon, in along-coast sequence
668 for (int nn = 0; nn < nNumPolygons; nn++)
669 {
670 CGeomCoastPolygon* pThisPolygon = m_VCoast[nCoast].pGetPolygon(nn);
671 int const nThisPolygon = pThisPolygon->nGetPolygonCoastID();
672
673 vector<int> nVUpCoastAdjacentPolygon;
674 vector<int> nVDownCoastAdjacentPolygon;
675
676 vector<double> dVUpCoastBoundaryShare;
677 vector<double> dVDownCoastBoundaryShare;
678
679 // First deal with down-coast adjacent polygons
680 if (pThisPolygon->bIsCoastEndPolygon())
681 {
682 // We are at the end of the coastline, no other polygon is adjacent to the down-coast profile of the end-of-coast polygon
683 nVDownCoastAdjacentPolygon.push_back(INT_NODATA);
684 dVDownCoastBoundaryShare.push_back(1);
685
686 // Store in the polygon
687 pThisPolygon->SetDownCoastAdjacentPolygons(&nVDownCoastAdjacentPolygon);
688 pThisPolygon->SetDownCoastAdjacentPolygonBoundaryShares(&dVDownCoastBoundaryShare);
689 }
690 else
691 {
692 // We are not at the end of the coastline, so there is at least one other polygon adjacent to the down-coast profile of this polygon
693 int const nDownCoastProfile = pThisPolygon->nGetDownCoastProfile();
694 int const nPointsInProfile = pThisPolygon->nGetNumPointsUsedDownCoastProfile();
695
696 double dDownCoastTotBoundaryLen = 0;
697
698 CGeomProfile* pProfile = m_VCoast[nCoast].pGetProfile(nDownCoastProfile);
699
700 for (int nPoint = 0; nPoint < nPointsInProfile - 1; nPoint++)
701 {
702 CGeom2DPoint const PtStart = *pProfile->pPtGetPointInProfile(nPoint);
703 CGeom2DPoint const PtEnd = *pProfile->pPtGetPointInProfile(nPoint + 1);
704
705 // Calculate the length of this segment of the normal profile. Note that it should not be zero, since we checked for duplicate points when creating profiles
706 double const dDistBetween = dGetDistanceBetween(&PtStart, &PtEnd);
707
708 // Find out which polygon is adjacent to each line segment of the polygon's down-coast profile boundary. The basic approach used is to count the number of coincident profiles in each line segment, and (because we are going down-coast) add this number to 'this' polygon's number. However, some of these coincident profiles may be invalid, so we must count only the valid co-incident profiles
709 int const nNumCoinc = pProfile->nGetNumCoincidentProfilesInLineSegment(nPoint);
710
711 // Safety check
712 if (nNumCoinc < 0)
713 continue;
714
715 int nNumValidCoinc = 0;
716
717 for (int nCoinc = 0; nCoinc < nNumCoinc; nCoinc++)
718 {
719 int const nProf = pProfile->nGetCoincidentProfileForLineSegment(nPoint, nCoinc);
720
721 // Safety check
722 if (nProf == -1)
723 continue;
724
725 CGeomProfile const* pProf = m_VCoast[nCoast].pGetProfile(nProf);
726
727 if (pProf->bProfileOK())
728 nNumValidCoinc++;
729 }
730
731 // First stab at calculating the number of the adjacent polygon
732 int nAdj = nThisPolygon + nNumValidCoinc;
733
734 // However, if 'this' polygon is close to the end of the coastline, we get polygon numbers greater than the number of polygons i.e. beyond the end of the coastline. If this happens, set the adjacent polygon to 'off-edge'
735 if (nAdj >= nNumPolygons)
736 nAdj = INT_NODATA;
737
738 // Safety check: is this adjacent polygon already present in the list of down-coast adjacent polygons?
739 if (pThisPolygon->bDownCoastIsAlreadyPresent(nAdj))
740 continue;
741
742 // Not already present
743 nVDownCoastAdjacentPolygon.push_back(nAdj);
744
745 dDownCoastTotBoundaryLen += dDistBetween;
746 dVDownCoastBoundaryShare.push_back(dDistBetween);
747 }
748
749 // Calculate the down-coast boundary share
750 for (unsigned int n = 0; n < dVDownCoastBoundaryShare.size(); n++)
751 {
752 // Safety check
753 if (bFPIsEqual(dDownCoastTotBoundaryLen, 0.0, TOLERANCE))
754 {
755 nVDownCoastAdjacentPolygon.pop_back();
756 dVDownCoastBoundaryShare.pop_back();
757 continue;
758 }
759
760 dVDownCoastBoundaryShare[n] /= dDownCoastTotBoundaryLen;
761 }
762
763 // Store in the polygon
764 pThisPolygon->SetDownCoastAdjacentPolygons(&nVDownCoastAdjacentPolygon);
765 pThisPolygon->SetDownCoastAdjacentPolygonBoundaryShares(&dVDownCoastBoundaryShare);
766 }
767
768 // Now deal with up-coast adjacent polygons
769 if (pThisPolygon->bIsCoastStartPolygon())
770 {
771 // We are at the start of the coastline, no other polygon is adjacent to the up-coast profile of the start-of-coast polygon
772 nVUpCoastAdjacentPolygon.push_back(INT_NODATA);
773 dVUpCoastBoundaryShare.push_back(1);
774
775 // Store in the polygon
776 pThisPolygon->SetUpCoastAdjacentPolygons(&nVUpCoastAdjacentPolygon);
777 pThisPolygon->SetUpCoastAdjacentPolygonBoundaryShares(&dVUpCoastBoundaryShare);
778 }
779
780 else
781 {
782 // We are not at the start of the coastline, so there is at least one other polygon adjacent to the up-coast profile of this polygon
783 int const nUpCoastProfile = pThisPolygon->nGetUpCoastProfile();
784 int const nPointsInProfile = pThisPolygon->nGetNumPointsUsedUpCoastProfile();
785
786 double dUpCoastTotBoundaryLen = 0;
787
788 CGeomProfile* pProfile = m_VCoast[nCoast].pGetProfile(nUpCoastProfile);
789
790 for (int nPoint = 0; nPoint < nPointsInProfile - 1; nPoint++)
791 {
792 CGeom2DPoint const PtStart = *pProfile->pPtGetPointInProfile(nPoint);
793 CGeom2DPoint const PtEnd = *pProfile->pPtGetPointInProfile(nPoint + 1);
794
795 // Safety check
796 if (PtStart == PtEnd)
797 // Should never get here, since we checked for duplicate points when creating profiles
798 continue;
799
800 // Calculate the length of this segment of the normal profile
801 double const dDistBetween = dGetDistanceBetween(&PtStart, &PtEnd);
802
803 // Find out which polygon is adjacent to each line segment of the polygon's up-coast profile boundary. The basic approach used is to count the number of coincident profiles in each line segment, and (because we are going up-coast) subtract this number from 'this' polygon's number. However, some of these coincident profiles may be invalid, so we must count only the valid co-incident profiles
804 int const nNumCoinc = pProfile->nGetNumCoincidentProfilesInLineSegment(nPoint);
805
806 // Safety check
807 if (nNumCoinc < 0)
808 continue;
809
810 int nNumValidCoinc = 0;
811
812 for (int nCoinc = 0; nCoinc < nNumCoinc; nCoinc++)
813 {
814 int const nProf = pProfile->nGetCoincidentProfileForLineSegment(nPoint, nCoinc);
815
816 // Safety check
817 if (nProf == -1)
818 continue;
819
820 CGeomProfile const* pProf = m_VCoast[nCoast].pGetProfile(nProf);
821
822 if (pProf->bProfileOK())
823 nNumValidCoinc++;
824 }
825
826 // First stab at calculating the number of the adjacent polygon
827 int nAdj = nThisPolygon - nNumValidCoinc;
828
829 // However, if 'this' polygon is close to the start of the coastline, we get polygon numbers below zero i.e. beyond the start of the coastline. If this happens, set the adjacent polygon to 'off-edge'
830 if (nAdj < 0)
831 nAdj = INT_NODATA;
832
833 // Safety check: is this adjacent polygon already present in the list of up-coast adjacent polygons?
834 if (pThisPolygon->bUpCoastIsAlreadyPresent(nAdj))
835 continue;
836
837 // Not already present
838 nVUpCoastAdjacentPolygon.push_back(nAdj);
839
840 dUpCoastTotBoundaryLen += dDistBetween;
841 dVUpCoastBoundaryShare.push_back(dDistBetween);
842 }
843
844 // Calculate the up-coast boundary share
845 for (unsigned int n = 0; n < dVUpCoastBoundaryShare.size(); n++)
846 {
847 // Safety check
848 if (bFPIsEqual(dUpCoastTotBoundaryLen, 0.0, TOLERANCE))
849 {
850 nVUpCoastAdjacentPolygon.pop_back();
851 dVUpCoastBoundaryShare.pop_back();
852 continue;
853 }
854
855 dVUpCoastBoundaryShare[n] /= dUpCoastTotBoundaryLen;
856 }
857
858 // Store in the polygon
859 pThisPolygon->SetUpCoastAdjacentPolygons(&nVUpCoastAdjacentPolygon);
860 pThisPolygon->SetUpCoastAdjacentPolygonBoundaryShares(&dVUpCoastBoundaryShare);
861 }
862
863 // Finally, calculate the distance between the coast node and the antinode of the polygon
864 double const dPolygonSeawardLen = dGetDistanceBetween(pThisPolygon->pPtiGetNode(), pThisPolygon->pPtiGetAntiNode());
865
866 // And store it
867 pThisPolygon->SetLength(dPolygonSeawardLen);
868
869 // // DEBUG CODE ======================================================================================================================
870 // assert(dVUpCoastBoundaryShare.size() == nVUpCoastAdjacentPolygon.size());
871 // assert(dVDownCoastBoundaryShare.size() == nVDownCoastAdjacentPolygon.size());
872 //
873 // LogStream << m_ulIter << ": polygon = " << nPoly << (pPolygon->bIsPointed() ? " IS TRIANGULAR" : "") << endl;
874 // LogStream << m_ulIter << ": coast " << nCoast << " polygon " << nThisPolygon << endl;
875 //
876 // int nUpCoastProfile = pThisPolygon->nGetUpCoastProfile();
877 // CGeomProfile* pUpCoastProfile = m_VCoast[0].pGetProfile(nUpCoastProfile);
878 // int nUpCoastProfileCells = pUpCoastProfile->nGetNumCellsInProfile();
879 //
880 // int nDownCoastProfile = pThisPolygon->nGetDownCoastProfile();
881 // CGeomProfile* pDownCoastProfile = m_VCoast[0].pGetProfile(nDownCoastProfile);
882 // int nDownCoastProfileCells = pDownCoastProfile->nGetNumCellsInProfile();
883 //
884 // LogStream << "\tUp-coast profile = " << nUpCoastProfile << " down-coast profile = " << nDownCoastProfile << endl;
885 // LogStream << "\tN cells in up-coast profile = " << nUpCoastProfileCells << " N cells in down-coast profile = " << nDownCoastProfileCells << endl;
886 //
887 // LogStream << "\tThere are " << nVUpCoastAdjacentPolygon.size() << " UP-COAST adjacent polygon(s) = ";
888 // for (unsigned int n = 0; n < nVUpCoastAdjacentPolygon.size(); n++)
889 // LogStream << nVUpCoastAdjacentPolygon[n] << " ";
890 // LogStream << endl;
891 //
892 // LogStream << "\tThere are " << nVDownCoastAdjacentPolygon.size() << " DOWN-COAST adjacent polygon(s) = ";
893 // for (unsigned int n = 0; n < nVDownCoastAdjacentPolygon.size(); n++)
894 // LogStream << nVDownCoastAdjacentPolygon[n] << " ";
895 // LogStream << endl;
896 //
897 // double dUpCoastTotBoundaryLen = 0;
898 // LogStream << "\tUP-COAST boundary share(s) = ";
899 // for (unsigned int n = 0; n < dVUpCoastBoundaryShare.size(); n++)
900 // {
901 // dUpCoastTotBoundaryLen += dVUpCoastBoundaryShare[n];
902 // LogStream << dVUpCoastBoundaryShare[n] << " ";
903 // }
904 // LogStream << endl;
905 // LogStream << "\tTotal UP-COAST boundary length = " << dUpCoastTotBoundaryLen << endl;
906 //
907 // double dDownCoastTotBoundaryLen = 0;
908 // LogStream << "\tDOWN-COAST boundary share(s) = ";
909 // for (unsigned int n = 0; n < dVDownCoastBoundaryShare.size(); n++)
910 // {
911 // dDownCoastTotBoundaryLen += dVDownCoastBoundaryShare[n];
912 // LogStream << dVDownCoastBoundaryShare[n] << " ";
913 // }
914 // LogStream << endl;
915 // LogStream << "\tTotal DOWN-COAST boundary length = " << dDownCoastTotBoundaryLen << endl;
916 // // DEBUG CODE ======================================================================================================================
917 }
918 }
919
920 // // DEBUG CODE =================================================================================
921 // for (int nCoast = 0; nCoast < static_cast<int>(m_VCoast.size()); nCoast++)
922 // {
923 // int nNumPoly = m_VCoast[nCoast].nGetNumPolygons();
924 // for (int nPoly = 0; nPoly < nNumPoly; nPoly++)
925 // {
926 // CGeomCoastPolygon const* pPolygon = m_VCoast[nCoast].pGetPolygon(nPoly);
927 //
928 // int nNumUpCoastPolygons = pPolygon->nGetNumUpCoastAdjacentPolygons();
929 // LogStream << "Polygon " << nPoly << " up-coast polygon(s) = ";
930 // for (int nAdj = 0; nAdj < nNumUpCoastPolygons; nAdj++)
931 // {
932 // int nAdjPoly = pPolygon->nGetUpCoastAdjacentPolygon(nAdj);
933 // LogStream << nAdjPoly;
934 // if (nAdjPoly > nNumPoly-1)
935 // LogStream << "***";
936 // }
937 //
938 // int nNumDownCoastPolygons = pPolygon->nGetNumDownCoastAdjacentPolygons();
939 // LogStream << " down-coast polygon(s) = ";
940 // for (int nAdj = 0; nAdj < nNumDownCoastPolygons; nAdj++)
941 // {
942 // int nAdjPoly = pPolygon->nGetDownCoastAdjacentPolygon(nAdj);
943 // LogStream << nAdjPoly;
944 // if (nAdjPoly > nNumPoly-1)
945 // LogStream << "***";
946 // }
947 // LogStream << endl;
948 // }
949 // }
950 // // DEBUG CODE =================================================================================
951
952 return RTN_OK;
953}
954
955// //===============================================================================================================================
956// //! Determines whether a point is within a polygon: however if the point is exactly on the edge of the polygon, then the result is indeterminate. Modified from code at http://alienryderflex.com/polygon/, our thanks to Darel Rex Finley (DarelRex@gmail.com)
957// //===============================================================================================================================
958// bool CSimulation::bIsWithinPolygon(CGeom2DPoint const* pPtStart, vector<CGeom2DPoint> const* pPtPoints)
959// {
960// bool bOddNodes = false;
961//
962// int const nPolyCorners = static_cast<int>(pPtPoints->size());
963// int j = nPolyCorners - 1;
964//
965// double const dX = pPtStart->dGetX();
966// double const dY = pPtStart->dGetY();
967//
968// for (int i = 0; i < nPolyCorners; i++)
969// {
970// double const dCorneriX = pPtPoints->at(i).dGetX();
971// double const dCorneriY = pPtPoints->at(i).dGetY();
972// double const dCornerjX = pPtPoints->at(j).dGetX();
973// double const dCornerjY = pPtPoints->at(j).dGetY();
974//
975// if ((dCorneriY < dY && dCornerjY >= dY) || (dCornerjY < dY && dCorneriY >= dY))
976// {
977// if (dCorneriX + (dY - dCorneriY) / (dCornerjY - dCorneriY) * (dCornerjX - dCorneriX) < dX)
978// {
979// bOddNodes = ! bOddNodes;
980// }
981// }
982//
983// j = i;
984// }
985//
986// return bOddNodes;
987// }
988
989// //===============================================================================================================================
990// //! Finds a point in a polygon: is guaranteed to succeed, as every strictly closed polygon has at least one triangle that is completely contained within the polygon. Derived from an algorithm at http://stackoverflow.com/questions/9797448/get-a-point-inside-the-polygon
991// //===============================================================================================================================
992// CGeom2DPoint CSimulation::PtFindPointInPolygon(vector<CGeom2DPoint> const* pPtPoints, int const nStartPoint)
993// {
994// int const nPolySize = static_cast<int>(pPtPoints->size());
995// int nOffSet = 0;
996// CGeom2DPoint PtStart;
997//
998// do
999// {
1000// // Choose three consecutive points from the polygon
1001// vector<CGeom2DPoint> nVTestPoints;
1002//
1003// for (int n = 0; n < 3; n++)
1004// {
1005// int nIndex = n + nStartPoint + nOffSet;
1006//
1007// if (nIndex > nPolySize - 1)
1008// nIndex -= nPolySize;
1009//
1010// // Safety check
1011// if (nIndex < 0)
1012// return CGeom2DPoint(DBL_NODATA, DBL_NODATA);
1013//
1014// nVTestPoints.push_back(pPtPoints->at(nIndex));
1015// }
1016//
1017// // Increment ready for next time
1018// nOffSet++;
1019//
1020// // Safety check
1021// if (nOffSet >= (nPolySize + 3))
1022// return CGeom2DPoint(DBL_NODATA, DBL_NODATA);
1023//
1024// // Check if the halfway point between the first and the third point is inside the polygon
1025// PtStart = PtAverage(&nVTestPoints[0], &nVTestPoints[2]);
1026// } while (! bIsWithinPolygon(&PtStart, pPtPoints));
1027//
1028// return PtStart;
1029// }
Contains CGeom2DPoint definitions.
Contains CGeom2DIPoint definitions.
Geometry class used to represent 2D point objects with integer coordinates.
Definition 2di_point.h:25
int nGetY(void) const
Returns the CGeom2DIPoint object's integer Y coordinate.
Definition 2di_point.cpp:51
int nGetX(void) const
Returns the CGeom2DIPoint object's integer X coordinate.
Definition 2di_point.cpp:45
Geometry class used to represent 2D point objects with floating-point coordinates.
Definition 2d_point.h:25
Geometry class used for coast polygon objects.
bool bIsCoastStartPolygon(void) const
Is this polygon the coast-start polygon?
int nGetNumPointsUsedDownCoastProfile(void) const
Return the number of points in the down-coast profile.
CGeom2DIPoint * pPtiGetAntiNode(void)
Get the anti-node (raster grid CRS) which is at other (seaward) end of the polygon from the node.
bool bIsCoastEndPolygon(void) const
Is this polygon the coast-end polygon?
void SetSedimentInputUnconsSand(double const)
Set the value of sand sediment on the polygon derived from sediment input events(s)
void SetPreExistingUnconsFine(double const)
Set the value of pre-existing unconsolidated fine sediment stored on this polygon.
void SetSedimentInputUnconsFine(double const)
Set the value of fine sediment on the polygon derived from sediment input events(s)
void SetPreExistingConsFine(double const)
Set the value of pre-existing consolidated fine sediment stored on this polygon.
void SetPreExistingUnconsSand(double const)
Set the value of pre-existing unconsolidated sand sediment stored on this polygon.
void SetSeawaterVolume(const double)
Set the volume of seawater in the coast polygon.
bool bUpCoastIsAlreadyPresent(int const)
Searches the list of up-coast adjacent polygons for a given polygon number.
int nGetNumPointsUsedUpCoastProfile(void) const
Return the number of points in the up-coast profile.
CGeom2DIPoint PtiGetFillStartPoint(void)
void SetSedimentInputUnconsCoarse(double const)
Set the value of coarse sediment on the polygon derived from sediment input events(s)
void SetDownCoastAdjacentPolygonBoundaryShares(vector< double > const *)
Sets the boundary shares for all down-coast adjacent polygons.
int nGetPolygonCoastID(void) const
Get the coast ID, this is the same as the down-coast sequence of polygons.
int nGetUpCoastProfile(void) const
Return the number of the up-coast profile.
void SetLength(double const)
Sets the polygon's length.
void SetPreExistingConsCoarse(double const)
Set the value of pre-existing consolidated coarse sediment stored on this polygon.
void SetPreExistingUnconsCoarse(double const)
Set the value of pre-existing unconsolidated coarse sediment stored on this polygon.
void AppendVertex(CGeom2DIPoint const *)
Appends the point cordinates (grid CRS) for a polygon vertex.
void SetDownCoastAdjacentPolygons(vector< int > const *)
Sets all down-coast adjacent polygons.
void SetUpCoastAdjacentPolygonBoundaryShares(vector< double > const *)
Sets the boundary shares for all up-coast adjacent polygons.
void SetUpCoastAdjacentPolygons(vector< int > const *)
Sets all up-coast adjacent polygons.
void SetPreExistingConsSand(double const)
Set the value of pre-existing consolidated sand sediment stored on this polygon.
int nGetDownCoastProfile(void) const
Return the number of the down-coast profile.
bool bDownCoastIsAlreadyPresent(int const)
Searches the list of down-coast adjacent polygons for a given polygon number.
void SetNumCellsInPolygon(int const)
Set the number of cells in the polygon.
CGeom2DIPoint * pPtiGetNode(void)
Get the grid coordinates of the cell on which the node sits.
int nGetNumCoincidentProfilesInLineSegment(int const)
Returns the count of coincident profiles in a specified line segment, or -1 if the line segment does ...
bool bFindProfileInCoincidentProfiles(int const)
Returns true if the given profile number is one of the coincident profiles of the a specified line se...
int nGetCoincidentProfileForLineSegment(int const, int const) const
Returns the numbers of coincident profiles.
void GetMostCoastwardSharedLineSegment(int const, int &, int &)
Finds the number of the most coastward line segment for which the two profiles are coincident,...
Geometry class used to represent coast profile objects.
Definition profile.h:33
int nGetProfileID(void) const
Returns the profile's this-coast ID.
Definition profile.cpp:74
int nGetCoastPoint(void) const
Returns the coast point at which the profile starts.
Definition profile.cpp:80
CGeomProfile * pGetDownCoastAdjacentProfile(void) const
Returns the down-coast adjacent profile, returns NULL if there is no down-coast adjacent profile.
Definition profile.cpp:488
CGeom2DIPoint * pPtiGetCellInProfile(int const)
Returns a single cell (grid CRS) in the profile.
Definition profile.cpp:518
int nGetNumCellsInProfile(void) const
Returns the number of cells in the profile.
Definition profile.cpp:539
bool bProfileOK(void) const
Returns true if this is a problem-free profile, and is not a start-of-coast and is not an end-of-coas...
Definition profile.cpp:227
CGeom2DIPoint * pPtiGetEndPoint(void)
Returns a pointer to the location of the cell (grid CRS) on which the profile ends.
Definition profile.cpp:92
CGeom2DPoint * pPtGetPointInProfile(int const)
Returns a single point (external CRS) from the profile.
Definition profile.cpp:364
bool bOKIncStartAndEndOfCoast(void) const
Returns true if this is a problem-free profile (however it could be a start-of-coast or an end-of-coa...
Definition profile.cpp:262
int nGetProfileSize(void) const
Returns the number of external CRS points in the profile (only two, initally; and always just two for...
Definition profile.cpp:358
CGeom2DIPoint * pPtiGetStartPoint(void)
Returns a pointer to the location of the cell (grid CRS) on which the profile starts.
Definition profile.cpp:86
bool bStartOfCoast(void) const
Returns the switch to indicate whether this is a start-of-coast profile.
Definition profile.cpp:104
bool bEndOfCoast(void) const
Returns the switch to indicate whether this is an end-of-coast profile.
Definition profile.cpp:116
CGeomRasterGrid * m_pRasterGrid
Pointer to the raster grid object.
int m_nXGridSize
The size of the grid in the x direction.
Definition simulation.h:477
CGeom2DIPoint PtiExtCRSToGridRound(CGeom2DPoint const *) const
Transforms a pointer to a CGeom2DPoint in the external CRS to the equivalent CGeom2DIPoint in the ras...
ofstream LogStream
vector< CRWCoast > m_VCoast
The coastline objects.
int m_nYGridSize
The size of the grid in the y direction.
Definition simulation.h:480
static double dGetDistanceBetween(CGeom2DPoint const *, CGeom2DPoint const *)
Returns the distance (in external CRS) between two points.
static CGeom2DPoint PtAverage(CGeom2DPoint const *, CGeom2DPoint const *)
Returns a point (external CRS) which is the average of (i.e. is midway between) two other external CR...
double m_dStartIterSuspFineInPolygons
Depth (m) of fine suspended sediment at the start of the simulation (only cells in polygons)
void KeepWithinValidGrid(int &, int &) const
Constrains the supplied point (in the grid CRS) to be a valid cell within the raster grid.
int nCreateAllPolygons(void)
Create polygons, and mark the polygon boundaries on the raster grid.
void RasterizePolygonJoiningLine(int const, CGeom2DIPoint const *, CGeom2DIPoint const *, int const)
Puts a polygon 'joining line' (the line which is the seaward boundary of the polygon,...
void MarkPolygonCells(void)
Marks cells of the raster grid that are within each coastal polygon. The cell-by-cell fill (aka 'floo...
bool bIsWithinValidGrid(int const, int const) const
Checks whether the supplied point (an x-y pair, in the grid CRS) is within the raster grid,...
unsigned long m_ulIter
The number of the current iteration (time step)
Definition simulation.h:609
double m_dCellSide
Length of a cell side (in external CRS units)
Definition simulation.h:672
int nDoPolygonSharedBoundaries(void)
For between-polygon potential sediment routing: find which are the adjacent polygons,...
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
T tMin(T a, T b)
Definition cme.h:1175
double const TOLERANCE
Definition cme.h:725
string const ERR
Definition cme.h:805
bool bFPIsEqual(const T d1, const T d2, const T dEpsilon)
Definition cme.h:1213
T tMax(T a, T b)
Definition cme.h:1162
int const RTN_ERR_BAD_MULTILINE
Definition cme.h:631
int const RTN_OK
Definition cme.h:585
T tAbs(T a)
Definition cme.h:1187
Contains CRWCoast definitions.
Contains CSimulation definitions.
int nRound(double const d)
Correctly rounds doubles, returns an int.