144 for (
int nCoast = 0; nCoast < static_cast<int>(
m_VCoast.size()); nCoast++)
148 int const nSeaHand =
m_VCoast[nCoast].nGetSeaHandedness();
149 int const nCoastSize =
m_VCoast[nCoast].nGetCoastlineSize();
150 vector<int> VnPossibleShadowBoundaryCoastPoint;
152 for (
bool bDownCoast : {
true,
false})
156 bool bLastDownCoastAndOnshore =
false;
159 for (
int nCoastPoint = 0; nCoastPoint < nCoastSize; nCoastPoint++)
162 double const dCurvature =
m_VCoast[nCoast].dGetSmoothCurvature(nCoastPoint);
166 double const dFluxOrientation =
m_VCoast[nCoast].dGetFluxOrientation(nCoastPoint);
173 dWaveAngle =
m_VCoast[nCoast].dGetCoastDeepWaterWaveAngle(nCoastPoint);
176 dWaveAngle =
m_VCoast[nCoast].dGetBreakingWaveAngle(nCoastPoint);
188 if (bDownCoast && (! bOnShore))
198 if (bLastDownCoastAndOnshore)
200 VnPossibleShadowBoundaryCoastPoint.push_back(nCoastPoint);
201 bLastDownCoastAndOnshore =
false;
210 else if (bDownCoast && bOnShore)
212 bLastDownCoastAndOnshore =
true;
216 bLastDownCoastAndOnshore =
false;
224 bool bLastUpCoastAndOnshore =
false;
227 for (
int nCoastPoint = nCoastSize - 1; nCoastPoint >= 0; nCoastPoint--)
230 double const dCurvature =
m_VCoast[nCoast].dGetSmoothCurvature(nCoastPoint);
234 double const dFluxOrientation =
m_VCoast[nCoast].dGetFluxOrientation(nCoastPoint);
241 dWaveAngle =
m_VCoast[nCoast].dGetCoastDeepWaterWaveAngle(nCoastPoint);
244 dWaveAngle =
m_VCoast[nCoast].dGetBreakingWaveAngle(nCoastPoint);
256 if ((! bDownCoast) && (! bOnShore))
266 if (bLastUpCoastAndOnshore)
268 VnPossibleShadowBoundaryCoastPoint.push_back(nCoastPoint);
269 bLastUpCoastAndOnshore =
false;
278 else if ((! bDownCoast) && bOnShore)
280 bLastUpCoastAndOnshore =
true;
284 bLastUpCoastAndOnshore =
false;
291 if (VnPossibleShadowBoundaryCoastPoint.size() == 0)
303 vector<CGeomILine> VILShadowBoundary;
304 vector<int> VnShadowBoundaryStartCoastPoint;
305 vector<int> VnShadowBoundaryEndCoastPoint;
307 for (
int nStartPoint = 0; nStartPoint < static_cast<int>(VnPossibleShadowBoundaryCoastPoint.size()); nStartPoint++)
312 bool bHitEdge =
false;
313 bool bHitCoast =
false;
314 bool bHitSea =
false;
315 bool bInLoop =
false;
316 bool bStillInland =
false;
322 double dPrevWaveAngle;
327 dPrevWaveAngle =
m_VCoast[nCoast].dGetCoastDeepWaterWaveAngle(nStartPoint);
332 dPrevWaveAngle =
m_VCoast[nCoast].dGetBreakingWaveAngle(nStartPoint);
335 CGeom2DIPoint PtiPrev = *
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(VnPossibleShadowBoundaryCoastPoint[nStartPoint]);
336 ILShadowBoundary.
Append(&PtiPrev);
339 double dCorrection = 0;
340 deque<double> DQdPrevOrientations;
342 while ((! bHitEdge) && (! bHitCoast))
348 int const nXPrev = PtiPrev.
nGetX();
349 int const nYPrev = PtiPrev.
nGetY();
351 if (!
m_pRasterGrid->m_Cell[nXPrev][nYPrev].bIsInActiveZone())
354 dPrevWaveAngle =
m_pRasterGrid->m_Cell[nXPrev][nYPrev].dGetWaveAngle();
362 double const dAvgOrientationSoFar = accumulate(DQdPrevOrientations.begin(), DQdPrevOrientations.end(), 0.0) /
static_cast<double>(DQdPrevOrientations.size());
364 dPrevWaveAngle = dAvgOrientationSoFar;
369 dPrevWaveAngle =
m_pRasterGrid->m_Cell[nXPrev][nYPrev].dGetWaveAngle();
379 if (!
m_pRasterGrid->m_Cell[nXPrev][nYPrev].bIsInContiguousSea())
382 dPrevWaveAngle =
m_pRasterGrid->m_Cell[nXPrev][nYPrev].dGetCellDeepWaterWaveAngle();
386 double const dAvgOrientationSoFar = accumulate(DQdPrevOrientations.begin(), DQdPrevOrientations.end(), 0.0) /
static_cast<double>(DQdPrevOrientations.size());
388 dPrevWaveAngle = dAvgOrientationSoFar;
393 DQdPrevOrientations.pop_front();
395 DQdPrevOrientations.push_back(dPrevWaveAngle);
402 int const nX = PtiNew.
nGetX();
403 int const nY = PtiNew.
nGetY();
441 ILShadowBoundary.
Append(&PtiNew);
495 int const nShadowBoundaryCoastPoint =
m_VCoast[nCoast].nGetCoastPointGivenCell(&ILShadowBoundary.
Back());
509 VILShadowBoundary.push_back(ILShadowBoundary);
510 VnShadowBoundaryStartCoastPoint.push_back(VnPossibleShadowBoundaryCoastPoint[nStartPoint]);
511 VnShadowBoundaryEndCoastPoint.push_back(nShadowBoundaryCoastPoint);
514 LogStream <<
m_ulIter <<
": \tcoast " << nCoast <<
" coast " << nCoast <<
" shadow boundary start point " << nStartPoint <<
" is valid shadow zone. Start [" << 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()) <<
"} coast point " << nShadowBoundaryCoastPoint <<
" is shadow zone " << VnShadowBoundaryEndCoastPoint.size() - 1 << endl;
541 VILShadowBoundary.push_back(ILShadowBoundary);
542 VnShadowBoundaryStartCoastPoint.push_back(VnPossibleShadowBoundaryCoastPoint[nStartPoint]);
543 VnShadowBoundaryEndCoastPoint.push_back(nDistance);
552 LogStream <<
m_ulIter <<
": \tcoast " << nCoast <<
" possible shadow boundary from start point " << nStartPoint <<
" hits a grid edge: ignored. Sarts at [" << ILShadowBoundary[0].nGetX() <<
"][" << ILShadowBoundary[0].nGetY() <<
"]" << endl;
559 for (
unsigned int nZone = 0; nZone < VILShadowBoundary.size(); nZone++)
564 int const nShadowLineLen = VILShadowBoundary[nZone].nGetSize();
572 for (
int nn = 0; nn < nShadowLineLen; nn++)
574 int const nTmpX = VILShadowBoundary[nZone][nn].nGetX();
575 int const nTmpY = VILShadowBoundary[nZone][nn].nGetY();
581 if (
m_pRasterGrid->m_Cell[nTmpX][nTmpY].bIsInContiguousSea())
582 m_pRasterGrid->m_Cell[nTmpX][nTmpY].SetShadowZoneNumber(-(nZone + 1));
595 m_VCoast[nCoast].AppendShadowBoundary(&LBoundary);
597 int const nStartX = VILShadowBoundary[nZone][0].nGetX();
598 int const nStartY = VILShadowBoundary[nZone][0].nGetY();
599 int const nEndX = VILShadowBoundary[nZone][nShadowLineLen - 1].nGetX();
600 int const nEndY = VILShadowBoundary[nZone][nShadowLineLen - 1].nGetY();
607 if (VnShadowBoundaryEndCoastPoint[nZone] > VnShadowBoundaryStartCoastPoint[nZone])
610 int const nStart =
tMax(VnShadowBoundaryStartCoastPoint[nZone], 0);
611 int const nEnd =
tMin(VnShadowBoundaryEndCoastPoint[nZone],
m_VCoast[nCoast].nGetCoastlineSize());
613 for (
int nn = nStart; nn < nEnd; nn++)
616 LIBoundary.
Append(
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(nn));
624 int const nStart =
tMin(VnShadowBoundaryEndCoastPoint[nZone],
m_VCoast[nCoast].nGetCoastlineSize() - 1);
625 int const nEnd =
tMax(VnShadowBoundaryStartCoastPoint[nZone], 0);
627 for (
int nn = nStart; nn >= nEnd; nn--)
630 LIBoundary.
Append(
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(nn));
658 LogStream <<
m_ulIter <<
": " <<
WARN <<
"could not find start point for cell-by-cell fill of shadow zone " << nZone <<
" but continuing simulation because this is a small shadow zone (shadow line length = " << nShadowLineLen <<
" cells)" << endl;
665 LogStream <<
m_ulIter <<
": " <<
ERR <<
"could not find start point for cell-by-cell fill of shadow zone " << nZone <<
" (shadow line length = " << nShadowLineLen <<
" cells)" << endl;
685 bool bStartPointOK =
true;
686 bool bAllPointNotSea =
true;
692 bStartPointOK =
false;
693 double dWeight = 0.05;
695 while ((! bStartPointOK) && (dWeight < 1))
701 if (PtiFloodFillStart == *pPtiCentroid)
719 bStartPointOK =
true;
720 bAllPointNotSea =
false;
733 if ((! bStartPointOK) && (! bAllPointNotSea))
736 LogStream <<
m_ulIter <<
": \tcoast " << nCoast <<
" " <<
ERR <<
"could not find shadow zone cell-by-cell fill start point" << endl;
745 stack<CGeom2DIPoint> PtiStack;
748 PtiStack.push(PtiFloodFillStart);
751 while (! PtiStack.empty())
772 m_pRasterGrid->m_Cell[nX][nY].SetShadowZoneNumber(-nZone - 1);
776 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()))
782 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()))
810 int const nCoastSeaHand =
m_VCoast[nCoast].nGetSeaHandedness();
811 int nShadowZoneCoastToCapeSeaHand;
820 bool bSweepDownCoast =
true;
822 if (nShadowBoundaryEndPoint < nShadowBoundaryStartPoint)
823 bSweepDownCoast =
false;
826 int const nAlongCoastDistanceToShadowEndpoint =
tAbs(nShadowBoundaryEndPoint - nShadowBoundaryStartPoint - 1);
829 int nDownDriftEndPoint;
830 int const nTotAlongCoastDistanceToDownDriftEndpoint = 2 * nAlongCoastDistanceToShadowEndpoint;
833 nDownDriftEndPoint = nShadowBoundaryStartPoint + nTotAlongCoastDistanceToDownDriftEndpoint;
836 nDownDriftEndPoint = nShadowBoundaryStartPoint - nTotAlongCoastDistanceToDownDriftEndpoint;
842 if (nDownDriftEndPoint < 0)
845 int const nStartEdge =
m_VCoast[nCoast].nGetStartEdge();
847 if (nStartEdge ==
NORTH)
849 PtiDownDriftEndPoint.
SetX(
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(0)->nGetX());
850 PtiDownDriftEndPoint.
SetY(nDownDriftEndPoint);
853 else if (nStartEdge ==
SOUTH)
855 PtiDownDriftEndPoint.
SetX(
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(0)->nGetX());
859 else if (nStartEdge ==
WEST)
861 PtiDownDriftEndPoint.
SetX(nDownDriftEndPoint);
862 PtiDownDriftEndPoint.
SetY(
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(0)->nGetY());
865 else if (nStartEdge ==
EAST)
868 PtiDownDriftEndPoint.
SetY(
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(0)->nGetY());
872 else if (nDownDriftEndPoint >=
m_VCoast[nCoast].nGetCoastlineSize())
875 int const nEndEdge =
m_VCoast[nCoast].nGetEndEdge();
876 int const nCoastSize =
m_VCoast[nCoast].nGetCoastlineSize();
878 if (nEndEdge ==
NORTH)
880 PtiDownDriftEndPoint.
SetX(
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(nCoastSize - 1)->nGetX());
881 PtiDownDriftEndPoint.
SetY(-nDownDriftEndPoint);
884 else if (nEndEdge ==
SOUTH)
886 PtiDownDriftEndPoint.
SetX(
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(nCoastSize - 1)->nGetX());
890 else if (nEndEdge ==
WEST)
892 PtiDownDriftEndPoint.
SetX(-nDownDriftEndPoint);
893 PtiDownDriftEndPoint.
SetY(
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(nCoastSize - 1)->nGetY());
896 else if (nEndEdge ==
EAST)
899 PtiDownDriftEndPoint.
SetY(
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(nCoastSize - 1)->nGetY());
906 PtiDownDriftEndPoint = *
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(nDownDriftEndPoint);
910 CGeom2DIPoint const* pPtiDownDriftBoundaryStartPoint =
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(nShadowBoundaryStartPoint);
913 int const nXStart = pPtiDownDriftBoundaryStartPoint->
nGetX();
914 int const nYStart = pPtiDownDriftBoundaryStartPoint->
nGetY();
915 int const nXEnd = PtiDownDriftEndPoint.
nGetX();
916 int const nYEnd = PtiDownDriftEndPoint.
nGetY();
919 if ((nXStart == nXEnd) && (nYStart == nYEnd))
926 double dXInc = dXEnd - dXStart;
927 double dYInc = dYEnd - dYStart;
933 int nTotDownDriftBoundaryDistance = 0;
940 for (
int m = 0; m <=
nRound(dLength); m++)
942 int const nX =
nRound(dX);
943 int const nY =
nRound(dY);
955 if ((LDownDriftBoundary.
nGetSize() == 0) || (PtThis != LDownDriftBoundary.
pPtBack()))
958 LDownDriftBoundary.
Append(&PtThis);
961 m_pRasterGrid->m_Cell[nX][nY].SetDownDriftZoneNumber(nZone + 1);
964 nTotDownDriftBoundaryDistance++;
984 m_VCoast[nCoast].AppendShadowDowndriftBoundary(&LDownDriftBoundary);
988 double dAlongCoastIncrement = 1;
989 double dDownDriftBoundaryIncrement = 1;
991 if (nTotAlongCoastDistanceToDownDriftEndpoint < nTotDownDriftBoundaryDistance)
994 dDownDriftBoundaryIncrement =
static_cast<double>(nTotDownDriftBoundaryDistance) / nTotAlongCoastDistanceToDownDriftEndpoint;
995 nMaxDistance = nTotDownDriftBoundaryDistance;
1001 dAlongCoastIncrement =
static_cast<double>(nTotAlongCoastDistanceToDownDriftEndpoint) / nTotDownDriftBoundaryDistance;
1002 nMaxDistance = nTotAlongCoastDistanceToDownDriftEndpoint;
1005 double dCoastDistSoFar = 0;
1006 double dDownDriftBoundaryDistSoFar = 0;
1009 for (
int n = 1; n < nMaxDistance - 1; n++)
1011 dCoastDistSoFar += dAlongCoastIncrement;
1012 dDownDriftBoundaryDistSoFar += dDownDriftBoundaryIncrement;
1016 if ((dCoastDistSoFar >= nTotAlongCoastDistanceToDownDriftEndpoint) || (dDownDriftBoundaryDistSoFar >= nTotDownDriftBoundaryDistance))
1019 bool bPastShadowEnd =
false;
1022 if (bSweepDownCoast)
1024 nAlongCoast = nShadowBoundaryStartPoint +
nRound(dCoastDistSoFar);
1026 if (nAlongCoast >=
m_VCoast[nCoast].nGetCoastlineSize())
1029 if (nAlongCoast >= nShadowBoundaryEndPoint)
1030 bPastShadowEnd =
true;
1035 nAlongCoast = nShadowBoundaryStartPoint -
nRound(dCoastDistSoFar);
1037 if (nAlongCoast < 0)
1040 if (nAlongCoast <= nShadowBoundaryEndPoint)
1041 bPastShadowEnd =
true;
1044 int const nAlongDownDriftBoundary =
nRound(dDownDriftBoundaryDistSoFar);
1052 int const nCoastX = pPtiCoast->
nGetX();
1053 int const nCoastY = pPtiCoast->
nGetY();
1055 int const nDownDriftX =
nRound(
dExtCRSXToGridX(LDownDriftBoundary[nAlongDownDriftBoundary].dGetX()));
1061 int const nDownDriftY =
nRound(
dExtCRSYToGridY(LDownDriftBoundary[nAlongDownDriftBoundary].dGetY()));
1068 if ((nCoastX == nDownDriftX) && (nCoastY == nDownDriftY))
1077 dXInc = nDownDriftX - nCoastX;
1078 dYInc = nDownDriftY - nCoastY;
1079 double const dLinkingLineLength =
tMax(
tAbs(dXInc),
tAbs(dYInc));
1081 dXInc /= dLinkingLineLength;
1082 dYInc /= dLinkingLineLength;
1090 int nShadowZoneLength = 0;
1091 vector<int> VnShadowCellX, VnShadowCellY;
1093 for (
int m = 0; m < dLinkingLineLength; m++)
1095 int const nX =
nRound(dX);
1096 int const nY =
nRound(dY);
1099 if ((nX == nXLast) && (nY == nYLast))
1142 if (! bPastShadowEnd)
1145 bool bInShadowZone =
true;
1152 bInShadowZone =
false;
1155 for (
unsigned int mm = 0; mm < VnShadowCellX.size(); mm++)
1158 ProcessShadowZoneCell(VnShadowCellX[mm], VnShadowCellY[mm], nShadowZoneCoastToCapeSeaHand, pPtiCoast, VnShadowCellX.back(), VnShadowCellY.back(), nZone);
1170 ProcessShadowZoneCell(PtiRight.
nGetX(), PtiRight.
nGetY(), nShadowZoneCoastToCapeSeaHand, pPtiCoast, VnShadowCellX.back(), VnShadowCellY.back(), nZone);
1178 VnShadowCellX.push_back(nX);
1179 VnShadowCellY.push_back(nY);
1181 nShadowZoneLength++;
1190 ProcessDownDriftCell(nX, nY, (m - nShadowZoneLength), (dLinkingLineLength - nShadowZoneLength), nZone);
1213 if ((nXLast != -1) && (nYLast != -1))