158 for (
int nCoast = 0; nCoast < static_cast<int>(
m_VCoast.size()); nCoast++)
162 int const nSeaHand =
m_VCoast[nCoast].nGetSeaHandedness();
163 int const nCoastSize =
m_VCoast[nCoast].nGetCoastlineSize();
165 vector<int> VnPossibleShadowBoundaryCoastPoint;
167 for (
bool bDownCoast :
173 bool bLastDownCoastAndOnshore =
false;
176 for (
int nShadowZoneBoundaryEndPoint = 0; nShadowZoneBoundaryEndPoint < nCoastSize; nShadowZoneBoundaryEndPoint++)
179 double const dCurvature =
m_VCoast[nCoast].dGetSmoothCurvature(nShadowZoneBoundaryEndPoint);
184 double const dFluxOrientation =
m_VCoast[nCoast].dGetFluxOrientation(nShadowZoneBoundaryEndPoint);
191 dWaveAngle =
m_VCoast[nCoast].dGetCoastDeepWaterWaveAngle(nShadowZoneBoundaryEndPoint);
195 dWaveAngle =
m_VCoast[nCoast].dGetBreakingWaveAngle(nShadowZoneBoundaryEndPoint);
204 if (bDownCoast && (!bOnShore))
211 if (bLastDownCoastAndOnshore)
213 VnPossibleShadowBoundaryCoastPoint.push_back(nShadowZoneBoundaryEndPoint);
214 bLastDownCoastAndOnshore =
false;
223 else if (bDownCoast && bOnShore)
225 bLastDownCoastAndOnshore =
true;
230 bLastDownCoastAndOnshore =
false;
239 bool bLastUpCoastAndOnshore =
false;
242 for (
int nShadowZoneBoundaryEndPoint = nCoastSize - 1; nShadowZoneBoundaryEndPoint >= 0; nShadowZoneBoundaryEndPoint--)
245 double const dCurvature =
m_VCoast[nCoast].dGetSmoothCurvature(nShadowZoneBoundaryEndPoint);
250 double const dFluxOrientation =
m_VCoast[nCoast].dGetFluxOrientation(nShadowZoneBoundaryEndPoint);
257 dWaveAngle =
m_VCoast[nCoast].dGetCoastDeepWaterWaveAngle(nShadowZoneBoundaryEndPoint);
261 dWaveAngle =
m_VCoast[nCoast].dGetBreakingWaveAngle(nShadowZoneBoundaryEndPoint);
270 if ((!bDownCoast) && (!bOnShore))
277 if (bLastUpCoastAndOnshore)
279 VnPossibleShadowBoundaryCoastPoint.push_back(nShadowZoneBoundaryEndPoint);
280 bLastUpCoastAndOnshore =
false;
289 else if ((!bDownCoast) && bOnShore)
291 bLastUpCoastAndOnshore =
true;
296 bLastUpCoastAndOnshore =
false;
303 if (VnPossibleShadowBoundaryCoastPoint.size() == 0)
313 vector<CGeomILine> VILShadowBoundary;
314 vector<int> VnShadowBoundaryStartCoastPoint;
315 vector<int> VnShadowBoundaryEndCoastPoint;
317 for (
int nStartPoint = 0; nStartPoint < static_cast<int>(VnPossibleShadowBoundaryCoastPoint.size()); nStartPoint++)
322 bool bHitEdge =
false;
323 bool bHitCoast =
false;
324 bool bHitSea =
false;
325 bool bInLoop =
false;
326 bool bStillInland =
false;
332 double dPrevWaveAngle;
337 dPrevWaveAngle =
m_VCoast[nCoast].dGetCoastDeepWaterWaveAngle(nStartPoint);
343 dPrevWaveAngle =
m_VCoast[nCoast].dGetBreakingWaveAngle(nStartPoint);
346 CGeom2DIPoint PtiPrev = *
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(VnPossibleShadowBoundaryCoastPoint[nStartPoint]);
347 ILShadowBoundary.
Append(&PtiPrev);
350 double dCorrection = 0;
351 deque<double> DQdPrevOrientations;
353 while ((!bHitEdge) && (!bHitCoast))
359 int const nXPrev = PtiPrev.
nGetX();
360 int const nYPrev = PtiPrev.
nGetY();
362 if (!
m_pRasterGrid->m_Cell[nXPrev][nYPrev].bIsInActiveZone())
365 dPrevWaveAngle =
m_pRasterGrid->m_Cell[nXPrev][nYPrev].dGetWaveAngle();
374 double const dAvgOrientationSoFar = accumulate(DQdPrevOrientations.begin(), DQdPrevOrientations.end(), 0.0) /
static_cast<double>(DQdPrevOrientations.size());
376 dPrevWaveAngle = dAvgOrientationSoFar;
382 dPrevWaveAngle =
m_pRasterGrid->m_Cell[nXPrev][nYPrev].dGetWaveAngle();
392 if (!
m_pRasterGrid->m_Cell[nXPrev][nYPrev].bIsInContiguousSea())
395 dPrevWaveAngle =
m_pRasterGrid->m_Cell[nXPrev][nYPrev].dGetCellDeepWaterWaveAngle();
400 double const dAvgOrientationSoFar = accumulate(DQdPrevOrientations.begin(), DQdPrevOrientations.end(), 0.0) /
static_cast<double>(DQdPrevOrientations.size());
402 dPrevWaveAngle = dAvgOrientationSoFar;
407 DQdPrevOrientations.pop_front();
409 DQdPrevOrientations.push_back(dPrevWaveAngle);
416 int const nX = PtiNew.
nGetX();
417 int const nY = PtiNew.
nGetY();
456 ILShadowBoundary.
Append(&PtiNew);
510 int const nShadowBoundaryCoastPoint =
m_VCoast[nCoast].nGetCoastPointGivenCell(&ILShadowBoundary.
Back());
524 VILShadowBoundary.push_back(ILShadowBoundary);
525 VnShadowBoundaryStartCoastPoint.push_back(VnPossibleShadowBoundaryCoastPoint[nStartPoint]);
526 VnShadowBoundaryEndCoastPoint.push_back(nShadowBoundaryCoastPoint);
529 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;
556 VILShadowBoundary.push_back(ILShadowBoundary);
557 VnShadowBoundaryStartCoastPoint.push_back(VnPossibleShadowBoundaryCoastPoint[nStartPoint]);
558 VnShadowBoundaryEndCoastPoint.push_back(nDistance);
561 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;
568 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;
575 for (
unsigned int nZone = 0; nZone < VILShadowBoundary.size(); nZone++)
578 LogStream <<
m_ulIter <<
": coast " << nCoast <<
", processing shadow zone " << nZone <<
" of " << VILShadowBoundary.size() << endl;
580 int const nShadowLineLen = VILShadowBoundary[nZone].nGetSize();
588 for (
int nn = 0; nn < nShadowLineLen; nn++)
590 int const nTmpX = VILShadowBoundary[nZone][nn].nGetX();
591 int const nTmpY = VILShadowBoundary[nZone][nn].nGetY();
597 if (
m_pRasterGrid->m_Cell[nTmpX][nTmpY].bIsInContiguousSea())
598 m_pRasterGrid->m_Cell[nTmpX][nTmpY].SetShadowZoneNumber(-(nZone + 1));
611 m_VCoast[nCoast].AppendShadowBoundary(&LBoundary);
613 int const nStartX = VILShadowBoundary[nZone][0].nGetX();
614 int const nStartY = VILShadowBoundary[nZone][0].nGetY();
615 int const nEndX = VILShadowBoundary[nZone][nShadowLineLen - 1].nGetX();
616 int const nEndY = VILShadowBoundary[nZone][nShadowLineLen - 1].nGetY();
623 if (VnShadowBoundaryEndCoastPoint[nZone] > VnShadowBoundaryStartCoastPoint[nZone])
626 int const nStart =
tMax(VnShadowBoundaryStartCoastPoint[nZone], 0);
627 int const nEnd =
tMin(VnShadowBoundaryEndCoastPoint[nZone],
m_VCoast[nCoast].nGetCoastlineSize());
629 for (
int nn = nStart; nn < nEnd; nn++)
632 LIBoundary.
Append(
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(nn));
640 int const nStart =
tMin(VnShadowBoundaryEndCoastPoint[nZone],
m_VCoast[nCoast].nGetCoastlineSize() - 1);
641 int const nEnd =
tMax(VnShadowBoundaryStartCoastPoint[nZone], 0);
643 for (
int nn = nStart; nn >= nEnd; nn--)
646 LIBoundary.
Append(
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(nn));
674 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;
681 LogStream <<
m_ulIter <<
": " <<
ERR <<
"could not find start point for cell-by-cell fill of shadow zone " << nZone <<
" (shadow line length = " << nShadowLineLen <<
" cells)" << endl;
701 bool bStartPointOK =
true;
702 bool bAllPointNotSea =
true;
708 bStartPointOK =
false;
709 double dWeight = 0.05;
711 while ((!bStartPointOK) && (dWeight < 1))
717 if (PtiFloodFillStart == *pPtiCentroid)
735 bStartPointOK =
true;
736 bAllPointNotSea =
false;
750 if ((!bStartPointOK) && (!bAllPointNotSea))
753 LogStream <<
m_ulIter <<
": " <<
ERR <<
"could not find shadow zone cell-by-cell fill start point" << endl;
762 stack<CGeom2DIPoint> PtiStack;
765 PtiStack.push(PtiFloodFillStart);
768 while (!PtiStack.empty())
789 m_pRasterGrid->m_Cell[nX][nY].SetShadowZoneNumber(-nZone - 1);
793 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()))
799 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()))
827 int const nCoastSeaHand =
m_VCoast[nCoast].nGetSeaHandedness();
828 int nShadowZoneCoastToCapeSeaHand;
837 bool bSweepDownCoast =
true;
839 if (nShadowBoundaryEndPoint < nShadowBoundaryStartPoint)
840 bSweepDownCoast =
false;
843 int const nAlongCoastDistanceToShadowEndpoint =
tAbs(nShadowBoundaryEndPoint - nShadowBoundaryStartPoint - 1);
846 int nDownDriftEndPoint;
847 int const nTotAlongCoastDistanceToDownDriftEndpoint = 2 * nAlongCoastDistanceToShadowEndpoint;
850 nDownDriftEndPoint = nShadowBoundaryStartPoint + nTotAlongCoastDistanceToDownDriftEndpoint;
853 nDownDriftEndPoint = nShadowBoundaryStartPoint - nTotAlongCoastDistanceToDownDriftEndpoint;
859 if (nDownDriftEndPoint < 0)
862 int const nStartEdge =
m_VCoast[nCoast].nGetStartEdge();
864 if (nStartEdge ==
NORTH)
866 PtiDownDriftEndPoint.
SetX(
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(0)->nGetX());
867 PtiDownDriftEndPoint.
SetY(nDownDriftEndPoint);
870 else if (nStartEdge ==
SOUTH)
872 PtiDownDriftEndPoint.
SetX(
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(0)->nGetX());
876 else if (nStartEdge ==
WEST)
878 PtiDownDriftEndPoint.
SetX(nDownDriftEndPoint);
879 PtiDownDriftEndPoint.
SetY(
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(0)->nGetY());
882 else if (nStartEdge ==
EAST)
885 PtiDownDriftEndPoint.
SetY(
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(0)->nGetY());
889 else if (nDownDriftEndPoint >=
m_VCoast[nCoast].nGetCoastlineSize())
892 int const nEndEdge =
m_VCoast[nCoast].nGetEndEdge();
893 int const nCoastSize =
m_VCoast[nCoast].nGetCoastlineSize();
895 if (nEndEdge ==
NORTH)
897 PtiDownDriftEndPoint.
SetX(
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(nCoastSize - 1)->nGetX());
898 PtiDownDriftEndPoint.
SetY(-nDownDriftEndPoint);
901 else if (nEndEdge ==
SOUTH)
903 PtiDownDriftEndPoint.
SetX(
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(nCoastSize - 1)->nGetX());
907 else if (nEndEdge ==
WEST)
909 PtiDownDriftEndPoint.
SetX(-nDownDriftEndPoint);
910 PtiDownDriftEndPoint.
SetY(
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(nCoastSize - 1)->nGetY());
913 else if (nEndEdge ==
EAST)
916 PtiDownDriftEndPoint.
SetY(
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(nCoastSize - 1)->nGetY());
923 PtiDownDriftEndPoint = *
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(nDownDriftEndPoint);
927 CGeom2DIPoint const* pPtiDownDriftBoundaryStartPoint =
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(nShadowBoundaryStartPoint);
930 int const nXStart = pPtiDownDriftBoundaryStartPoint->
nGetX();
931 int const nYStart = pPtiDownDriftBoundaryStartPoint->
nGetY();
932 int const nXEnd = PtiDownDriftEndPoint.
nGetX();
933 int const nYEnd = PtiDownDriftEndPoint.
nGetY();
936 if ((nXStart == nXEnd) && (nYStart == nYEnd))
943 double dXInc = dXEnd - dXStart;
944 double dYInc = dYEnd - dYStart;
950 int nTotDownDriftBoundaryDistance = 0;
957 for (
int m = 0; m <=
nRound(dLength); m++)
959 int const nX =
nRound(dX);
960 int const nY =
nRound(dY);
972 if ((LDownDriftBoundary.
nGetSize() == 0) || (PtThis != LDownDriftBoundary.
pPtBack()))
975 LDownDriftBoundary.
Append(&PtThis);
978 m_pRasterGrid->m_Cell[nX][nY].SetDownDriftZoneNumber(nZone + 1);
981 nTotDownDriftBoundaryDistance++;
1001 m_VCoast[nCoast].AppendShadowDowndriftBoundary(&LDownDriftBoundary);
1005 double dAlongCoastIncrement = 1;
1006 double dDownDriftBoundaryIncrement = 1;
1008 if (nTotAlongCoastDistanceToDownDriftEndpoint < nTotDownDriftBoundaryDistance)
1011 dDownDriftBoundaryIncrement =
static_cast<double>(nTotDownDriftBoundaryDistance) / nTotAlongCoastDistanceToDownDriftEndpoint;
1012 nMaxDistance = nTotDownDriftBoundaryDistance;
1018 dAlongCoastIncrement =
static_cast<double>(nTotAlongCoastDistanceToDownDriftEndpoint) / nTotDownDriftBoundaryDistance;
1019 nMaxDistance = nTotAlongCoastDistanceToDownDriftEndpoint;
1022 double dCoastDistSoFar = 0;
1023 double dDownDriftBoundaryDistSoFar = 0;
1026 for (
int n = 1; n < nMaxDistance - 1; n++)
1028 dCoastDistSoFar += dAlongCoastIncrement;
1029 dDownDriftBoundaryDistSoFar += dDownDriftBoundaryIncrement;
1033 if ((dCoastDistSoFar >= nTotAlongCoastDistanceToDownDriftEndpoint) || (dDownDriftBoundaryDistSoFar >= nTotDownDriftBoundaryDistance))
1036 bool bPastShadowEnd =
false;
1039 if (bSweepDownCoast)
1041 nAlongCoast = nShadowBoundaryStartPoint +
nRound(dCoastDistSoFar);
1043 if (nAlongCoast >=
m_VCoast[nCoast].nGetCoastlineSize())
1046 if (nAlongCoast >= nShadowBoundaryEndPoint)
1047 bPastShadowEnd =
true;
1052 nAlongCoast = nShadowBoundaryStartPoint -
nRound(dCoastDistSoFar);
1054 if (nAlongCoast < 0)
1057 if (nAlongCoast <= nShadowBoundaryEndPoint)
1058 bPastShadowEnd =
true;
1061 int const nAlongDownDriftBoundary =
nRound(dDownDriftBoundaryDistSoFar);
1069 int const nCoastX = pPtiCoast->
nGetX();
1070 int const nCoastY = pPtiCoast->
nGetY();
1072 int const nDownDriftX =
nRound(
dExtCRSXToGridX(LDownDriftBoundary[nAlongDownDriftBoundary].dGetX()));
1078 int const nDownDriftY =
nRound(
dExtCRSYToGridY(LDownDriftBoundary[nAlongDownDriftBoundary].dGetY()));
1085 if ((nCoastX == nDownDriftX) && (nCoastY == nDownDriftY))
1094 dXInc = nDownDriftX - nCoastX;
1095 dYInc = nDownDriftY - nCoastY;
1096 double const dLinkingLineLength =
tMax(
tAbs(dXInc),
tAbs(dYInc));
1098 dXInc /= dLinkingLineLength;
1099 dYInc /= dLinkingLineLength;
1107 int nShadowZoneLength = 0;
1108 vector<int> VnShadowCellX, VnShadowCellY;
1110 for (
int m = 0; m < dLinkingLineLength; m++)
1112 int const nX =
nRound(dX);
1113 int const nY =
nRound(dY);
1116 if ((nX == nXLast) && (nY == nYLast))
1159 if (!bPastShadowEnd)
1162 bool bInShadowZone =
true;
1169 bInShadowZone =
false;
1172 for (
unsigned int mm = 0; mm < VnShadowCellX.size(); mm++)
1175 ProcessShadowZoneCell(VnShadowCellX[mm], VnShadowCellY[mm], nShadowZoneCoastToCapeSeaHand, pPtiCoast, VnShadowCellX.back(), VnShadowCellY.back(), nZone);
1187 ProcessShadowZoneCell(PtiRight.
nGetX(), PtiRight.
nGetY(), nShadowZoneCoastToCapeSeaHand, pPtiCoast, VnShadowCellX.back(), VnShadowCellY.back(), nZone);
1195 VnShadowCellX.push_back(nX);
1196 VnShadowCellY.push_back(nY);
1198 nShadowZoneLength++;
1208 ProcessDownDriftCell(nX, nY, (m - nShadowZoneLength), (dLinkingLineLength - nShadowZoneLength), nZone);
1232 if ((nXLast != -1) && (nYLast != -1))