145 for (
int nCoast = 0; nCoast < static_cast<int>(
m_VCoast.size()); nCoast++)
150 nSeaHand =
m_VCoast[nCoast].nGetSeaHandedness(),
151 nCoastSize =
m_VCoast[nCoast].nGetCoastlineSize();
153 vector<int> VnPossibleShadowBoundaryCoastPoint;
155 for (
bool bDownCoast : {
true,
false})
159 bool bLastDownCoastAndOnshore =
false;
162 for (
int nShadowZoneBoundaryEndPoint = 0; nShadowZoneBoundaryEndPoint < nCoastSize; nShadowZoneBoundaryEndPoint++)
165 double dCurvature =
m_VCoast[nCoast].dGetSmoothCurvature(nShadowZoneBoundaryEndPoint);
169 double dFluxOrientation =
m_VCoast[nCoast].dGetFluxOrientation(nShadowZoneBoundaryEndPoint);
175 dWaveAngle =
m_VCoast[nCoast].dGetCoastDeepWaterWaveAngle(nShadowZoneBoundaryEndPoint);
178 dWaveAngle =
m_VCoast[nCoast].dGetBreakingWaveAngle(nShadowZoneBoundaryEndPoint);
187 if (bDownCoast && (! bOnShore))
194 if (bLastDownCoastAndOnshore)
196 VnPossibleShadowBoundaryCoastPoint.push_back(nShadowZoneBoundaryEndPoint);
197 bLastDownCoastAndOnshore =
false;
205 else if (bDownCoast && bOnShore)
207 bLastDownCoastAndOnshore =
true;
211 bLastDownCoastAndOnshore =
false;
219 bool bLastUpCoastAndOnshore =
false;
222 for (
int nShadowZoneBoundaryEndPoint = nCoastSize - 1; nShadowZoneBoundaryEndPoint >= 0; nShadowZoneBoundaryEndPoint--)
225 double dCurvature =
m_VCoast[nCoast].dGetSmoothCurvature(nShadowZoneBoundaryEndPoint);
229 double dFluxOrientation =
m_VCoast[nCoast].dGetFluxOrientation(nShadowZoneBoundaryEndPoint);
235 dWaveAngle =
m_VCoast[nCoast].dGetCoastDeepWaterWaveAngle(nShadowZoneBoundaryEndPoint);
238 dWaveAngle =
m_VCoast[nCoast].dGetBreakingWaveAngle(nShadowZoneBoundaryEndPoint);
247 if ((! bDownCoast) && (! bOnShore))
254 if (bLastUpCoastAndOnshore)
256 VnPossibleShadowBoundaryCoastPoint.push_back(nShadowZoneBoundaryEndPoint);
257 bLastUpCoastAndOnshore =
false;
265 else if ((! bDownCoast) && bOnShore)
267 bLastUpCoastAndOnshore =
true;
271 bLastUpCoastAndOnshore =
false;
278 if (VnPossibleShadowBoundaryCoastPoint.size() == 0)
288 vector<CGeomILine> VILShadowBoundary;
290 VnShadowBoundaryStartCoastPoint,
291 VnShadowBoundaryEndCoastPoint;
293 for (
int nStartPoint = 0; nStartPoint < static_cast<int>(VnPossibleShadowBoundaryCoastPoint.size()); nStartPoint++)
303 bStillInland =
false;
309 double dPrevWaveAngle;
313 dPrevWaveAngle =
m_VCoast[nCoast].dGetCoastDeepWaterWaveAngle(nStartPoint);
318 dPrevWaveAngle =
m_VCoast[nCoast].dGetBreakingWaveAngle(nStartPoint);
321 CGeom2DIPoint PtiPrev = *
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(VnPossibleShadowBoundaryCoastPoint[nStartPoint]);
322 ILShadowBoundary.
Append(&PtiPrev);
325 double dCorrection = 0;
326 deque<double> DQdPrevOrientations;
328 while ((! bHitEdge) && (! bHitCoast))
335 nXPrev = PtiPrev.
nGetX(),
336 nYPrev = PtiPrev.
nGetY();
338 if (!
m_pRasterGrid->m_Cell[nXPrev][nYPrev].bIsInActiveZone())
341 dPrevWaveAngle =
m_pRasterGrid->m_Cell[nXPrev][nYPrev].dGetWaveAngle();
349 double dAvgOrientationSoFar = accumulate(DQdPrevOrientations.begin(), DQdPrevOrientations.end(), 0.0) /
static_cast<double>(DQdPrevOrientations.size());
351 dPrevWaveAngle = dAvgOrientationSoFar;
356 dPrevWaveAngle =
m_pRasterGrid->m_Cell[nXPrev][nYPrev].dGetWaveAngle();
366 if (!
m_pRasterGrid->m_Cell[nXPrev][nYPrev].bIsInContiguousSea())
369 dPrevWaveAngle =
m_pRasterGrid->m_Cell[nXPrev][nYPrev].dGetCellDeepWaterWaveAngle();
373 double dAvgOrientationSoFar = accumulate(DQdPrevOrientations.begin(), DQdPrevOrientations.end(), 0.0) /
static_cast<double>(DQdPrevOrientations.size());
375 dPrevWaveAngle = dAvgOrientationSoFar;
380 DQdPrevOrientations.pop_front();
382 DQdPrevOrientations.push_back(dPrevWaveAngle);
429 ILShadowBoundary.
Append(&PtiNew);
482 int nShadowBoundaryCoastPoint =
m_VCoast[nCoast].nGetCoastPointGivenCell(&ILShadowBoundary.
Back());
495 VILShadowBoundary.push_back(ILShadowBoundary);
496 VnShadowBoundaryStartCoastPoint.push_back(VnPossibleShadowBoundaryCoastPoint[nStartPoint]);
497 VnShadowBoundaryEndCoastPoint.push_back(nShadowBoundaryCoastPoint);
500 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;
526 VILShadowBoundary.push_back(ILShadowBoundary);
527 VnShadowBoundaryStartCoastPoint.push_back(VnPossibleShadowBoundaryCoastPoint[nStartPoint]);
528 VnShadowBoundaryEndCoastPoint.push_back(nDistance);
531 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;
537 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;
544 for (
unsigned int nZone = 0; nZone < VILShadowBoundary.size(); nZone++)
547 LogStream <<
m_ulIter <<
": coast " << nCoast <<
", processing shadow zone " << nZone <<
" of " << VILShadowBoundary.size() << endl;
549 int nShadowLineLen = VILShadowBoundary[nZone].nGetSize();
557 for (
int nn = 0; nn < nShadowLineLen; nn++)
560 nTmpX = VILShadowBoundary[nZone][nn].nGetX(),
561 nTmpY = VILShadowBoundary[nZone][nn].nGetY();
567 if (
m_pRasterGrid->m_Cell[nTmpX][nTmpY].bIsInContiguousSea())
568 m_pRasterGrid->m_Cell[nTmpX][nTmpY].SetShadowZoneNumber(-(nZone + 1));
581 m_VCoast[nCoast].AppendShadowBoundary(&LBoundary);
584 nStartX = VILShadowBoundary[nZone][0].nGetX(),
585 nStartY = VILShadowBoundary[nZone][0].nGetY(),
586 nEndX = VILShadowBoundary[nZone][nShadowLineLen - 1].nGetX(),
587 nEndY = VILShadowBoundary[nZone][nShadowLineLen - 1].nGetY();
591 PtiStart(nStartX, nStartY),
592 PtiEnd(nEndX, nEndY);
595 if (VnShadowBoundaryEndCoastPoint[nZone] > VnShadowBoundaryStartCoastPoint[nZone])
599 nStart =
tMax(VnShadowBoundaryStartCoastPoint[nZone], 0),
600 nEnd =
tMin(VnShadowBoundaryEndCoastPoint[nZone],
m_VCoast[nCoast].nGetCoastlineSize());
602 for (
int nn = nStart; nn < nEnd; nn++)
605 LIBoundary.
Append(
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(nn));
613 nStart =
tMin(VnShadowBoundaryEndCoastPoint[nZone],
m_VCoast[nCoast].nGetCoastlineSize() - 1),
614 nEnd =
tMax(VnShadowBoundaryStartCoastPoint[nZone], 0);
616 for (
int nn = nStart; nn >= nEnd; nn--)
619 LIBoundary.
Append(
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(nn));
646 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;
652 LogStream <<
m_ulIter <<
": " <<
ERR <<
"could not find start point for flood fill of shadow zone " << nZone <<
" (shadow line length = " << nShadowLineLen <<
" cells)" << endl;
672 bool bStartPointOK =
true;
673 bool bAllPointNotSea =
true;
678 bStartPointOK =
false;
679 double dWeight = 0.05;
680 while ((! bStartPointOK) && (dWeight < 1))
686 if (PtiFloodFillStart == *pPtiCentroid)
704 bStartPointOK =
true;
705 bAllPointNotSea =
false;
718 if ((! bStartPointOK) && (! bAllPointNotSea))
721 LogStream <<
m_ulIter <<
": " <<
ERR <<
"could not find shadow zone flood fill start point" << endl;
730 stack<CGeom2DIPoint> PtiStack;
733 PtiStack.push(PtiFloodFillStart);
736 while (!PtiStack.empty())
757 m_pRasterGrid->m_Cell[nX][nY].SetShadowZoneNumber(-nZone - 1);
761 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()))
766 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()))
794 nCoastSeaHand =
m_VCoast[nCoast].nGetSeaHandedness(),
795 nShadowZoneCoastToCapeSeaHand;
803 bool bSweepDownCoast =
true;
804 if (nShadowBoundaryEndPoint < nShadowBoundaryStartPoint)
805 bSweepDownCoast =
false;
808 int nAlongCoastDistanceToShadowEndpoint =
tAbs(nShadowBoundaryEndPoint - nShadowBoundaryStartPoint - 1);
813 nTotAlongCoastDistanceToDownDriftEndpoint = 2 * nAlongCoastDistanceToShadowEndpoint;
816 nDownDriftEndPoint = nShadowBoundaryStartPoint + nTotAlongCoastDistanceToDownDriftEndpoint;
818 nDownDriftEndPoint = nShadowBoundaryStartPoint - nTotAlongCoastDistanceToDownDriftEndpoint;
824 if (nDownDriftEndPoint < 0)
827 int nStartEdge =
m_VCoast[nCoast].nGetStartEdge();
828 if (nStartEdge ==
NORTH)
830 PtiDownDriftEndPoint.
SetX(
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(0)->nGetX());
831 PtiDownDriftEndPoint.
SetY(nDownDriftEndPoint);
833 else if (nStartEdge ==
SOUTH)
835 PtiDownDriftEndPoint.
SetX(
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(0)->nGetX());
838 else if (nStartEdge ==
WEST)
840 PtiDownDriftEndPoint.
SetX(nDownDriftEndPoint);
841 PtiDownDriftEndPoint.
SetY(
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(0)->nGetY());
843 else if (nStartEdge ==
EAST)
846 PtiDownDriftEndPoint.
SetY(
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(0)->nGetY());
849 else if (nDownDriftEndPoint >=
m_VCoast[nCoast].nGetCoastlineSize())
853 nEndEdge =
m_VCoast[nCoast].nGetEndEdge(),
854 nCoastSize =
m_VCoast[nCoast].nGetCoastlineSize();
855 if (nEndEdge ==
NORTH)
857 PtiDownDriftEndPoint.
SetX(
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(nCoastSize - 1)->nGetX());
858 PtiDownDriftEndPoint.
SetY(-nDownDriftEndPoint);
860 else if (nEndEdge ==
SOUTH)
862 PtiDownDriftEndPoint.
SetX(
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(nCoastSize - 1)->nGetX());
865 else if (nEndEdge ==
WEST)
867 PtiDownDriftEndPoint.
SetX(-nDownDriftEndPoint);
868 PtiDownDriftEndPoint.
SetY(
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(nCoastSize - 1)->nGetY());
870 else if (nEndEdge ==
EAST)
873 PtiDownDriftEndPoint.
SetY(
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(nCoastSize - 1)->nGetY());
879 PtiDownDriftEndPoint = *
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(nDownDriftEndPoint);
883 CGeom2DIPoint const* pPtiDownDriftBoundaryStartPoint =
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(nShadowBoundaryStartPoint);
887 nXStart = pPtiDownDriftBoundaryStartPoint->
nGetX(),
888 nYStart = pPtiDownDriftBoundaryStartPoint->
nGetY();
894 dXInc = dXEnd - dXStart,
895 dYInc = dYEnd - dYStart,
901 int nTotDownDriftBoundaryDistance = 0;
908 for (
int m = 0; m <=
nRound(dLength); m++)
923 if ((LDownDriftBoundary.
nGetSize() == 0) || (PtThis != LDownDriftBoundary.
pPtBack()))
926 LDownDriftBoundary.
Append(&PtThis);
929 m_pRasterGrid->m_Cell[nX][nY].SetDownDriftZoneNumber(nZone + 1);
932 nTotDownDriftBoundaryDistance++;
950 m_VCoast[nCoast].AppendShadowDowndriftBoundary(&LDownDriftBoundary);
955 dAlongCoastIncrement = 1,
956 dDownDriftBoundaryIncrement = 1;
958 if (nTotAlongCoastDistanceToDownDriftEndpoint < nTotDownDriftBoundaryDistance)
961 dDownDriftBoundaryIncrement =
static_cast<double>(nTotDownDriftBoundaryDistance) / nTotAlongCoastDistanceToDownDriftEndpoint;
962 nMaxDistance = nTotDownDriftBoundaryDistance;
967 dAlongCoastIncrement =
static_cast<double>(nTotAlongCoastDistanceToDownDriftEndpoint) / nTotDownDriftBoundaryDistance;
968 nMaxDistance = nTotAlongCoastDistanceToDownDriftEndpoint;
973 dDownDriftBoundaryDistSoFar = 0;
976 for (
int n = 1; n < nMaxDistance - 1; n++)
978 dCoastDistSoFar += dAlongCoastIncrement;
979 dDownDriftBoundaryDistSoFar += dDownDriftBoundaryIncrement;
983 if ((dCoastDistSoFar >= nTotAlongCoastDistanceToDownDriftEndpoint) || (dDownDriftBoundaryDistSoFar >= nTotDownDriftBoundaryDistance))
986 bool bPastShadowEnd =
false;
990 nAlongCoast = nShadowBoundaryStartPoint +
nRound(dCoastDistSoFar);
992 if (nAlongCoast >=
m_VCoast[nCoast].nGetCoastlineSize())
995 if (nAlongCoast >= nShadowBoundaryEndPoint)
996 bPastShadowEnd =
true;
1000 nAlongCoast = nShadowBoundaryStartPoint -
nRound(dCoastDistSoFar);
1002 if (nAlongCoast < 0)
1005 if (nAlongCoast <= nShadowBoundaryEndPoint)
1006 bPastShadowEnd =
true;
1009 int nAlongDownDriftBoundary =
nRound(dDownDriftBoundaryDistSoFar);
1017 int nCoastX = pPtiCoast->
nGetX();
1018 int nCoastY = pPtiCoast->
nGetY();
1033 if ((nCoastX == nDownDriftX) && (nCoastY == nDownDriftY))
1042 dXInc = nDownDriftX - nCoastX;
1043 dYInc = nDownDriftY - nCoastY;
1044 double dLinkingLineLength =
tMax(
tAbs(dXInc),
tAbs(dYInc));
1046 dXInc /= dLinkingLineLength;
1047 dYInc /= dLinkingLineLength;
1056 nShadowZoneLength = 0;
1057 vector<int> VnShadowCellX, VnShadowCellY;
1058 for (
int m = 0; m < dLinkingLineLength; m++)
1065 if ((nX == nXLast) && (nY == nYLast))
1108 if (! bPastShadowEnd)
1111 bool bInShadowZone =
true;
1118 bInShadowZone =
false;
1121 for (
unsigned int mm = 0; mm < VnShadowCellX.size(); mm++)
1124 ProcessShadowZoneCell(VnShadowCellX[mm], VnShadowCellY[mm], nShadowZoneCoastToCapeSeaHand, pPtiCoast, VnShadowCellX.back(), VnShadowCellY.back(), nZone);
1137 ProcessShadowZoneCell(PtiRight.nGetX(), PtiRight.nGetY(), nShadowZoneCoastToCapeSeaHand, pPtiCoast, VnShadowCellX.back(), VnShadowCellY.back(), nZone);
1145 VnShadowCellX.push_back(nX);
1146 VnShadowCellY.push_back(nY);
1148 nShadowZoneLength++;
1157 ProcessDownDriftCell(nX, nY, (m - nShadowZoneLength), (dLinkingLineLength - nShadowZoneLength), nZone);
1168 ProcessDownDriftCell(PtiRight.nGetX(), PtiRight.nGetY(), (m - nShadowZoneLength), (dLinkingLineLength - nShadowZoneLength), nZone);
1181 if ((nXLast != -1) && (nYLast != -1))