146 for (
int nCoast = 0; nCoast < static_cast<int>(
m_VCoast.size()); nCoast++)
151 nSeaHand =
m_VCoast[nCoast].nGetSeaHandedness(),
152 nCoastSize =
m_VCoast[nCoast].nGetCoastlineSize();
154 vector<int> VnPossibleShadowBoundaryCoastPoint;
156 for (
bool bDownCoast : {
true,
false})
160 bool bLastDownCoastAndOnshore =
false;
163 for (
int nShadowZoneBoundaryEndPoint = 0; nShadowZoneBoundaryEndPoint < nCoastSize; nShadowZoneBoundaryEndPoint++)
166 double dCurvature =
m_VCoast[nCoast].dGetSmoothCurvature(nShadowZoneBoundaryEndPoint);
170 double dFluxOrientation =
m_VCoast[nCoast].dGetFluxOrientation(nShadowZoneBoundaryEndPoint);
176 dWaveAngle =
m_VCoast[nCoast].dGetCoastDeepWaterWaveAngle(nShadowZoneBoundaryEndPoint);
179 dWaveAngle =
m_VCoast[nCoast].dGetBreakingWaveAngle(nShadowZoneBoundaryEndPoint);
188 if (bDownCoast && (! bOnShore))
195 if (bLastDownCoastAndOnshore)
197 VnPossibleShadowBoundaryCoastPoint.push_back(nShadowZoneBoundaryEndPoint);
198 bLastDownCoastAndOnshore =
false;
206 else if (bDownCoast && bOnShore)
208 bLastDownCoastAndOnshore =
true;
212 bLastDownCoastAndOnshore =
false;
220 bool bLastUpCoastAndOnshore =
false;
223 for (
int nShadowZoneBoundaryEndPoint = nCoastSize - 1; nShadowZoneBoundaryEndPoint >= 0; nShadowZoneBoundaryEndPoint--)
226 double dCurvature =
m_VCoast[nCoast].dGetSmoothCurvature(nShadowZoneBoundaryEndPoint);
230 double dFluxOrientation =
m_VCoast[nCoast].dGetFluxOrientation(nShadowZoneBoundaryEndPoint);
236 dWaveAngle =
m_VCoast[nCoast].dGetCoastDeepWaterWaveAngle(nShadowZoneBoundaryEndPoint);
239 dWaveAngle =
m_VCoast[nCoast].dGetBreakingWaveAngle(nShadowZoneBoundaryEndPoint);
248 if ((! bDownCoast) && (! bOnShore))
255 if (bLastUpCoastAndOnshore)
257 VnPossibleShadowBoundaryCoastPoint.push_back(nShadowZoneBoundaryEndPoint);
258 bLastUpCoastAndOnshore =
false;
266 else if ((! bDownCoast) && bOnShore)
268 bLastUpCoastAndOnshore =
true;
272 bLastUpCoastAndOnshore =
false;
279 if (VnPossibleShadowBoundaryCoastPoint.size() == 0)
289 vector<CGeomILine> VILShadowBoundary;
291 VnShadowBoundaryStartCoastPoint,
292 VnShadowBoundaryEndCoastPoint;
294 for (
int nStartPoint = 0; nStartPoint < static_cast<int>(VnPossibleShadowBoundaryCoastPoint.size()); nStartPoint++)
304 bStillInland =
false;
310 double dPrevWaveAngle;
314 dPrevWaveAngle =
m_VCoast[nCoast].dGetCoastDeepWaterWaveAngle(nStartPoint);
319 dPrevWaveAngle =
m_VCoast[nCoast].dGetBreakingWaveAngle(nStartPoint);
322 CGeom2DIPoint PtiPrev = *
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(VnPossibleShadowBoundaryCoastPoint[nStartPoint]);
323 ILShadowBoundary.
Append(&PtiPrev);
326 double dCorrection = 0;
327 deque<double> DQdPrevOrientations;
329 while ((! bHitEdge) && (! bHitCoast))
336 nXPrev = PtiPrev.
nGetX(),
337 nYPrev = PtiPrev.
nGetY();
339 if (!
m_pRasterGrid->m_Cell[nXPrev][nYPrev].bIsInActiveZone())
342 dPrevWaveAngle =
m_pRasterGrid->m_Cell[nXPrev][nYPrev].dGetWaveAngle();
350 double dAvgOrientationSoFar = accumulate(DQdPrevOrientations.begin(), DQdPrevOrientations.end(), 0.0) /
static_cast<double>(DQdPrevOrientations.size());
352 dPrevWaveAngle = dAvgOrientationSoFar;
357 dPrevWaveAngle =
m_pRasterGrid->m_Cell[nXPrev][nYPrev].dGetWaveAngle();
367 if (!
m_pRasterGrid->m_Cell[nXPrev][nYPrev].bIsInContiguousSea())
370 dPrevWaveAngle =
m_pRasterGrid->m_Cell[nXPrev][nYPrev].dGetCellDeepWaterWaveAngle();
374 double dAvgOrientationSoFar = accumulate(DQdPrevOrientations.begin(), DQdPrevOrientations.end(), 0.0) /
static_cast<double>(DQdPrevOrientations.size());
376 dPrevWaveAngle = dAvgOrientationSoFar;
381 DQdPrevOrientations.pop_front();
383 DQdPrevOrientations.push_back(dPrevWaveAngle);
430 ILShadowBoundary.
Append(&PtiNew);
483 int nShadowBoundaryCoastPoint =
m_VCoast[nCoast].nGetCoastPointGivenCell(&ILShadowBoundary.
Back());
496 VILShadowBoundary.push_back(ILShadowBoundary);
497 VnShadowBoundaryStartCoastPoint.push_back(VnPossibleShadowBoundaryCoastPoint[nStartPoint]);
498 VnShadowBoundaryEndCoastPoint.push_back(nShadowBoundaryCoastPoint);
501 LogStream <<
m_ulIter <<
": Coast " << nCoast <<
", coast " << nCoast <<
", possible shadow boundary from start point " << nStartPoint <<
" defines a valid shadow zone. Start point [" << ILShadowBoundary[0].nGetX() <<
"][" << ILShadowBoundary[0].nGetY() <<
"] = {" <<
dGridCentroidXToExtCRSX(ILShadowBoundary[0].nGetX()) <<
", " <<
dGridCentroidYToExtCRSY(ILShadowBoundary[0].nGetY()) <<
"}, hits coast at [" << ILShadowBoundary.
Back().
nGetX() <<
"][" << ILShadowBoundary.
Back().
nGetY() <<
"] = {" <<
dGridCentroidXToExtCRSX(ILShadowBoundary.
Back().
nGetX()) <<
", " <<
dGridCentroidYToExtCRSY(ILShadowBoundary.
Back().
nGetY()) <<
"} which is coast point (" << nShadowBoundaryCoastPoint <<
"). Will be shadow zone " << VnShadowBoundaryEndCoastPoint.size() - 1 << endl;
527 VILShadowBoundary.push_back(ILShadowBoundary);
528 VnShadowBoundaryStartCoastPoint.push_back(VnPossibleShadowBoundaryCoastPoint[nStartPoint]);
529 VnShadowBoundaryEndCoastPoint.push_back(nDistance);
532 LogStream <<
m_ulIter <<
": Coast " << nCoast <<
", possible shadow boundary from start point " << nStartPoint <<
" defines a valid shadow zone. Start point [" << ILShadowBoundary[0].nGetX() <<
"][" << ILShadowBoundary[0].nGetY() <<
"] = {" <<
dGridCentroidXToExtCRSX(ILShadowBoundary[0].nGetX()) <<
", " <<
dGridCentroidYToExtCRSY(ILShadowBoundary[0].nGetY()) <<
"}, hit the grid edge at [" << ILShadowBoundary.
Back().
nGetX() <<
"][" << ILShadowBoundary.
Back().
nGetY() <<
"] = {" <<
dGridCentroidXToExtCRSX(ILShadowBoundary.
Back().
nGetX()) <<
", " <<
dGridCentroidYToExtCRSY(ILShadowBoundary.
Back().
nGetY()) <<
"}. Best-guess length of the shadow boundary is " << nDistance <<
" cells. Will be shadow zone " << VnShadowBoundaryEndCoastPoint.size() - 1 << endl;
538 LogStream <<
m_ulIter <<
": Coast " << nCoast <<
", possible shadow boundary from start point " << nStartPoint <<
" hits a grid edge: ignored. It starts at [" << ILShadowBoundary[0].nGetX() <<
"][" << ILShadowBoundary[0].nGetY() <<
"]" << endl;
545 for (
unsigned int nZone = 0; nZone < VILShadowBoundary.size(); nZone++)
548 LogStream <<
m_ulIter <<
": coast " << nCoast <<
", processing shadow zone " << nZone <<
" of " << VILShadowBoundary.size() << endl;
550 int nShadowLineLen = VILShadowBoundary[nZone].nGetSize();
558 for (
int nn = 0; nn < nShadowLineLen; nn++)
561 nTmpX = VILShadowBoundary[nZone][nn].nGetX(),
562 nTmpY = VILShadowBoundary[nZone][nn].nGetY();
568 if (
m_pRasterGrid->m_Cell[nTmpX][nTmpY].bIsInContiguousSea())
569 m_pRasterGrid->m_Cell[nTmpX][nTmpY].SetShadowZoneNumber(-(nZone + 1));
582 m_VCoast[nCoast].AppendShadowBoundary(&LBoundary);
585 nStartX = VILShadowBoundary[nZone][0].nGetX(),
586 nStartY = VILShadowBoundary[nZone][0].nGetY(),
587 nEndX = VILShadowBoundary[nZone][nShadowLineLen - 1].nGetX(),
588 nEndY = VILShadowBoundary[nZone][nShadowLineLen - 1].nGetY();
592 PtiStart(nStartX, nStartY),
593 PtiEnd(nEndX, nEndY);
596 if (VnShadowBoundaryEndCoastPoint[nZone] > VnShadowBoundaryStartCoastPoint[nZone])
600 nStart =
tMax(VnShadowBoundaryStartCoastPoint[nZone], 0),
601 nEnd =
tMin(VnShadowBoundaryEndCoastPoint[nZone],
m_VCoast[nCoast].nGetCoastlineSize());
603 for (
int nn = nStart; nn < nEnd; nn++)
606 LIBoundary.
Append(
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(nn));
614 nStart =
tMin(VnShadowBoundaryEndCoastPoint[nZone],
m_VCoast[nCoast].nGetCoastlineSize() - 1),
615 nEnd =
tMax(VnShadowBoundaryStartCoastPoint[nZone], 0);
617 for (
int nn = nStart; nn >= nEnd; nn--)
620 LIBoundary.
Append(
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(nn));
647 LogStream <<
m_ulIter <<
": " <<
WARN <<
"could not find start point for flood fill of shadow zone " << nZone <<
" but continuing simulation because this is a small shadow zone (shadow line length = " << nShadowLineLen <<
" cells)" << endl;
653 LogStream <<
m_ulIter <<
": " <<
ERR <<
"could not find start point for flood fill of shadow zone " << nZone <<
" (shadow line length = " << nShadowLineLen <<
" cells)" << endl;
673 bool bStartPointOK =
true;
674 bool bAllPointNotSea =
true;
679 bStartPointOK =
false;
680 double dWeight = 0.05;
681 while ((! bStartPointOK) && (dWeight < 1))
687 if (PtiFloodFillStart == *pPtiCentroid)
705 bStartPointOK =
true;
706 bAllPointNotSea =
false;
719 if ((! bStartPointOK) && (! bAllPointNotSea))
722 LogStream <<
m_ulIter <<
": " <<
ERR <<
"could not find shadow zone flood fill start point" << endl;
731 stack<CGeom2DIPoint> PtiStack;
734 PtiStack.push(PtiFloodFillStart);
737 while (!PtiStack.empty())
758 m_pRasterGrid->m_Cell[nX][nY].SetShadowZoneNumber(-nZone - 1);
762 if ((! bSpanAbove) && (nY > 0) &&
m_pRasterGrid->m_Cell[nX][nY].bIsInContiguousSea() && (!
m_pRasterGrid->m_Cell[nX][nY-1].bIsinThisShadowZone(-nZone - 1)) && (!
m_pRasterGrid->m_Cell[nX][nY-1].bIsShadowZoneBoundary()) && (!
m_pRasterGrid->m_Cell[nX][nY-1].bIsCoastline()))
767 else if (bSpanAbove && (nY > 0) && ((!
m_pRasterGrid->m_Cell[nX][nY-1].bIsInContiguousSea()) ||
m_pRasterGrid->m_Cell[nX][nY-1].bIsinThisShadowZone(-nZone - 1) ||
m_pRasterGrid->m_Cell[nX][nY-1].bIsShadowZoneBoundary() ||
m_pRasterGrid->m_Cell[nX][nY-1].bIsCoastline()))
795 nCoastSeaHand =
m_VCoast[nCoast].nGetSeaHandedness(),
796 nShadowZoneCoastToCapeSeaHand;
804 bool bSweepDownCoast =
true;
805 if (nShadowBoundaryEndPoint < nShadowBoundaryStartPoint)
806 bSweepDownCoast =
false;
809 int nAlongCoastDistanceToShadowEndpoint =
tAbs(nShadowBoundaryEndPoint - nShadowBoundaryStartPoint - 1);
814 nTotAlongCoastDistanceToDownDriftEndpoint = 2 * nAlongCoastDistanceToShadowEndpoint;
817 nDownDriftEndPoint = nShadowBoundaryStartPoint + nTotAlongCoastDistanceToDownDriftEndpoint;
819 nDownDriftEndPoint = nShadowBoundaryStartPoint - nTotAlongCoastDistanceToDownDriftEndpoint;
825 if (nDownDriftEndPoint < 0)
828 int nStartEdge =
m_VCoast[nCoast].nGetStartEdge();
829 if (nStartEdge ==
NORTH)
831 PtiDownDriftEndPoint.
SetX(
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(0)->nGetX());
832 PtiDownDriftEndPoint.
SetY(nDownDriftEndPoint);
834 else if (nStartEdge ==
SOUTH)
836 PtiDownDriftEndPoint.
SetX(
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(0)->nGetX());
839 else if (nStartEdge ==
WEST)
841 PtiDownDriftEndPoint.
SetX(nDownDriftEndPoint);
842 PtiDownDriftEndPoint.
SetY(
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(0)->nGetY());
844 else if (nStartEdge ==
EAST)
847 PtiDownDriftEndPoint.
SetY(
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(0)->nGetY());
850 else if (nDownDriftEndPoint >=
m_VCoast[nCoast].nGetCoastlineSize())
854 nEndEdge =
m_VCoast[nCoast].nGetEndEdge(),
855 nCoastSize =
m_VCoast[nCoast].nGetCoastlineSize();
856 if (nEndEdge ==
NORTH)
858 PtiDownDriftEndPoint.
SetX(
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(nCoastSize - 1)->nGetX());
859 PtiDownDriftEndPoint.
SetY(-nDownDriftEndPoint);
861 else if (nEndEdge ==
SOUTH)
863 PtiDownDriftEndPoint.
SetX(
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(nCoastSize - 1)->nGetX());
866 else if (nEndEdge ==
WEST)
868 PtiDownDriftEndPoint.
SetX(-nDownDriftEndPoint);
869 PtiDownDriftEndPoint.
SetY(
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(nCoastSize - 1)->nGetY());
871 else if (nEndEdge ==
EAST)
874 PtiDownDriftEndPoint.
SetY(
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(nCoastSize - 1)->nGetY());
880 PtiDownDriftEndPoint = *
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(nDownDriftEndPoint);
884 CGeom2DIPoint const* pPtiDownDriftBoundaryStartPoint =
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(nShadowBoundaryStartPoint);
888 nXStart = pPtiDownDriftBoundaryStartPoint->
nGetX(),
889 nYStart = pPtiDownDriftBoundaryStartPoint->
nGetY();
895 dXInc = dXEnd - dXStart,
896 dYInc = dYEnd - dYStart,
902 int nTotDownDriftBoundaryDistance = 0;
909 for (
int m = 0; m <=
nRound(dLength); m++)
924 if ((LDownDriftBoundary.
nGetSize() == 0) || (PtThis != LDownDriftBoundary.
pPtBack()))
927 LDownDriftBoundary.
Append(&PtThis);
930 m_pRasterGrid->m_Cell[nX][nY].SetDownDriftZoneNumber(nZone + 1);
933 nTotDownDriftBoundaryDistance++;
951 m_VCoast[nCoast].AppendShadowDowndriftBoundary(&LDownDriftBoundary);
956 dAlongCoastIncrement = 1,
957 dDownDriftBoundaryIncrement = 1;
959 if (nTotAlongCoastDistanceToDownDriftEndpoint < nTotDownDriftBoundaryDistance)
962 dDownDriftBoundaryIncrement =
static_cast<double>(nTotDownDriftBoundaryDistance) / nTotAlongCoastDistanceToDownDriftEndpoint;
963 nMaxDistance = nTotDownDriftBoundaryDistance;
968 dAlongCoastIncrement =
static_cast<double>(nTotAlongCoastDistanceToDownDriftEndpoint) / nTotDownDriftBoundaryDistance;
969 nMaxDistance = nTotAlongCoastDistanceToDownDriftEndpoint;
974 dDownDriftBoundaryDistSoFar = 0;
977 for (
int n = 1; n < nMaxDistance - 1; n++)
979 dCoastDistSoFar += dAlongCoastIncrement;
980 dDownDriftBoundaryDistSoFar += dDownDriftBoundaryIncrement;
984 if ((dCoastDistSoFar >= nTotAlongCoastDistanceToDownDriftEndpoint) || (dDownDriftBoundaryDistSoFar >= nTotDownDriftBoundaryDistance))
987 bool bPastShadowEnd =
false;
991 nAlongCoast = nShadowBoundaryStartPoint +
nRound(dCoastDistSoFar);
993 if (nAlongCoast >=
m_VCoast[nCoast].nGetCoastlineSize())
996 if (nAlongCoast >= nShadowBoundaryEndPoint)
997 bPastShadowEnd =
true;
1001 nAlongCoast = nShadowBoundaryStartPoint -
nRound(dCoastDistSoFar);
1003 if (nAlongCoast < 0)
1006 if (nAlongCoast <= nShadowBoundaryEndPoint)
1007 bPastShadowEnd =
true;
1010 int nAlongDownDriftBoundary =
nRound(dDownDriftBoundaryDistSoFar);
1018 int nCoastX = pPtiCoast->
nGetX();
1019 int nCoastY = pPtiCoast->
nGetY();
1034 if ((nCoastX == nDownDriftX) && (nCoastY == nDownDriftY))
1043 dXInc = nDownDriftX - nCoastX;
1044 dYInc = nDownDriftY - nCoastY;
1045 double dLinkingLineLength =
tMax(
tAbs(dXInc),
tAbs(dYInc));
1047 dXInc /= dLinkingLineLength;
1048 dYInc /= dLinkingLineLength;
1057 nShadowZoneLength = 0;
1058 vector<int> VnShadowCellX, VnShadowCellY;
1059 for (
int m = 0; m < dLinkingLineLength; m++)
1066 if ((nX == nXLast) && (nY == nYLast))
1109 if (! bPastShadowEnd)
1112 bool bInShadowZone =
true;
1119 bInShadowZone =
false;
1122 for (
unsigned int mm = 0; mm < VnShadowCellX.size(); mm++)
1125 ProcessShadowZoneCell(VnShadowCellX[mm], VnShadowCellY[mm], nShadowZoneCoastToCapeSeaHand, pPtiCoast, VnShadowCellX.back(), VnShadowCellY.back(), nZone);
1138 ProcessShadowZoneCell(PtiRight.nGetX(), PtiRight.nGetY(), nShadowZoneCoastToCapeSeaHand, pPtiCoast, VnShadowCellX.back(), VnShadowCellY.back(), nZone);
1146 VnShadowCellX.push_back(nX);
1147 VnShadowCellY.push_back(nY);
1149 nShadowZoneLength++;
1158 ProcessDownDriftCell(nX, nY, (m - nShadowZoneLength), (dLinkingLineLength - nShadowZoneLength), nZone);
1169 ProcessDownDriftCell(PtiRight.nGetX(), PtiRight.nGetY(), (m - nShadowZoneLength), (dLinkingLineLength - nShadowZoneLength), nZone);
1182 if ((nXLast != -1) && (nYLast != -1))