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