154 for (
int nCoast = 0; nCoast < static_cast<int>(
m_VCoast.size()); nCoast++)
158 int nSeaHand =
m_VCoast[nCoast].nGetSeaHandedness();
159 int nCoastSize =
m_VCoast[nCoast].nGetCoastlineSize();
161 vector<int> VnPossibleShadowBoundaryCoastPoint;
163 for (
bool bDownCoast :
170 bool bLastDownCoastAndOnshore =
false;
173 for (
int nShadowZoneBoundaryEndPoint = 0; nShadowZoneBoundaryEndPoint < nCoastSize; nShadowZoneBoundaryEndPoint++)
176 double dCurvature =
m_VCoast[nCoast].dGetSmoothCurvature(nShadowZoneBoundaryEndPoint);
181 double dFluxOrientation =
m_VCoast[nCoast].dGetFluxOrientation(nShadowZoneBoundaryEndPoint);
188 dWaveAngle =
m_VCoast[nCoast].dGetCoastDeepWaterWaveAngle(nShadowZoneBoundaryEndPoint);
192 dWaveAngle =
m_VCoast[nCoast].dGetBreakingWaveAngle(nShadowZoneBoundaryEndPoint);
201 if (bDownCoast && (! bOnShore))
208 if (bLastDownCoastAndOnshore)
210 VnPossibleShadowBoundaryCoastPoint.push_back(nShadowZoneBoundaryEndPoint);
211 bLastDownCoastAndOnshore =
false;
220 else if (bDownCoast && bOnShore)
222 bLastDownCoastAndOnshore =
true;
227 bLastDownCoastAndOnshore =
false;
236 bool bLastUpCoastAndOnshore =
false;
239 for (
int nShadowZoneBoundaryEndPoint = nCoastSize - 1; nShadowZoneBoundaryEndPoint >= 0; nShadowZoneBoundaryEndPoint--)
242 double dCurvature =
m_VCoast[nCoast].dGetSmoothCurvature(nShadowZoneBoundaryEndPoint);
247 double dFluxOrientation =
m_VCoast[nCoast].dGetFluxOrientation(nShadowZoneBoundaryEndPoint);
254 dWaveAngle =
m_VCoast[nCoast].dGetCoastDeepWaterWaveAngle(nShadowZoneBoundaryEndPoint);
258 dWaveAngle =
m_VCoast[nCoast].dGetBreakingWaveAngle(nShadowZoneBoundaryEndPoint);
267 if ((! bDownCoast) && (! bOnShore))
274 if (bLastUpCoastAndOnshore)
276 VnPossibleShadowBoundaryCoastPoint.push_back(nShadowZoneBoundaryEndPoint);
277 bLastUpCoastAndOnshore =
false;
286 else if ((! bDownCoast) && bOnShore)
288 bLastUpCoastAndOnshore =
true;
293 bLastUpCoastAndOnshore =
false;
300 if (VnPossibleShadowBoundaryCoastPoint.size() == 0)
310 vector<CGeomILine> VILShadowBoundary;
311 vector<int> VnShadowBoundaryStartCoastPoint;
312 vector<int> VnShadowBoundaryEndCoastPoint;
314 for (
int nStartPoint = 0; nStartPoint < static_cast<int>(VnPossibleShadowBoundaryCoastPoint.size()); nStartPoint++)
319 bool bHitEdge =
false;
320 bool bHitCoast =
false;
321 bool bHitSea =
false;
322 bool bInLoop =
false;
323 bool bStillInland =
false;
329 double dPrevWaveAngle;
334 dPrevWaveAngle =
m_VCoast[nCoast].dGetCoastDeepWaterWaveAngle(nStartPoint);
340 dPrevWaveAngle =
m_VCoast[nCoast].dGetBreakingWaveAngle(nStartPoint);
343 CGeom2DIPoint PtiPrev = *
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(VnPossibleShadowBoundaryCoastPoint[nStartPoint]);
344 ILShadowBoundary.
Append(&PtiPrev);
347 double dCorrection = 0;
348 deque<double> DQdPrevOrientations;
350 while ((! bHitEdge) && (! bHitCoast))
356 int nXPrev = PtiPrev.
nGetX();
357 int nYPrev = PtiPrev.
nGetY();
359 if (!
m_pRasterGrid->m_Cell[nXPrev][nYPrev].bIsInActiveZone())
362 dPrevWaveAngle =
m_pRasterGrid->m_Cell[nXPrev][nYPrev].dGetWaveAngle();
371 double dAvgOrientationSoFar = accumulate(DQdPrevOrientations.begin(), DQdPrevOrientations.end(), 0.0) /
static_cast<double>(DQdPrevOrientations.size());
373 dPrevWaveAngle = dAvgOrientationSoFar;
379 dPrevWaveAngle =
m_pRasterGrid->m_Cell[nXPrev][nYPrev].dGetWaveAngle();
389 if (!
m_pRasterGrid->m_Cell[nXPrev][nYPrev].bIsInContiguousSea())
392 dPrevWaveAngle =
m_pRasterGrid->m_Cell[nXPrev][nYPrev].dGetCellDeepWaterWaveAngle();
397 double dAvgOrientationSoFar = accumulate(DQdPrevOrientations.begin(), DQdPrevOrientations.end(), 0.0) /
static_cast<double>(DQdPrevOrientations.size());
399 dPrevWaveAngle = dAvgOrientationSoFar;
404 DQdPrevOrientations.pop_front();
406 DQdPrevOrientations.push_back(dPrevWaveAngle);
413 int nX = PtiNew.
nGetX();
414 int nY = PtiNew.
nGetY();
453 ILShadowBoundary.
Append(&PtiNew);
507 int nShadowBoundaryCoastPoint =
m_VCoast[nCoast].nGetCoastPointGivenCell(&ILShadowBoundary.
Back());
521 VILShadowBoundary.push_back(ILShadowBoundary);
522 VnShadowBoundaryStartCoastPoint.push_back(VnPossibleShadowBoundaryCoastPoint[nStartPoint]);
523 VnShadowBoundaryEndCoastPoint.push_back(nShadowBoundaryCoastPoint);
526 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;
553 VILShadowBoundary.push_back(ILShadowBoundary);
554 VnShadowBoundaryStartCoastPoint.push_back(VnPossibleShadowBoundaryCoastPoint[nStartPoint]);
555 VnShadowBoundaryEndCoastPoint.push_back(nDistance);
558 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;
565 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;
572 for (
unsigned int nZone = 0; nZone < VILShadowBoundary.size(); nZone++)
575 LogStream <<
m_ulIter <<
": coast " << nCoast <<
", processing shadow zone " << nZone <<
" of " << VILShadowBoundary.size() << endl;
577 int nShadowLineLen = VILShadowBoundary[nZone].nGetSize();
585 for (
int nn = 0; nn < nShadowLineLen; nn++)
588 nTmpX = VILShadowBoundary[nZone][nn].nGetX(),
589 nTmpY = VILShadowBoundary[nZone][nn].nGetY();
595 if (
m_pRasterGrid->m_Cell[nTmpX][nTmpY].bIsInContiguousSea())
596 m_pRasterGrid->m_Cell[nTmpX][nTmpY].SetShadowZoneNumber(-(nZone + 1));
609 m_VCoast[nCoast].AppendShadowBoundary(&LBoundary);
611 int nStartX = VILShadowBoundary[nZone][0].nGetX();
612 int nStartY = VILShadowBoundary[nZone][0].nGetY();
613 int nEndX = VILShadowBoundary[nZone][nShadowLineLen - 1].nGetX();
614 int nEndY = VILShadowBoundary[nZone][nShadowLineLen - 1].nGetY();
621 if (VnShadowBoundaryEndCoastPoint[nZone] > VnShadowBoundaryStartCoastPoint[nZone])
624 int nStart =
tMax(VnShadowBoundaryStartCoastPoint[nZone], 0);
625 int nEnd =
tMin(VnShadowBoundaryEndCoastPoint[nZone],
m_VCoast[nCoast].nGetCoastlineSize());
627 for (
int nn = nStart; nn < nEnd; nn++)
630 LIBoundary.
Append(
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(nn));
638 int nStart =
tMin(VnShadowBoundaryEndCoastPoint[nZone],
m_VCoast[nCoast].nGetCoastlineSize() - 1);
639 int nEnd =
tMax(VnShadowBoundaryStartCoastPoint[nZone], 0);
641 for (
int nn = nStart; nn >= nEnd; nn--)
644 LIBoundary.
Append(
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(nn));
672 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;
679 LogStream <<
m_ulIter <<
": " <<
ERR <<
"could not find start point for cell-by-cell fill of shadow zone " << nZone <<
" (shadow line length = " << nShadowLineLen <<
" cells)" << endl;
699 bool bStartPointOK =
true;
700 bool bAllPointNotSea =
true;
706 bStartPointOK =
false;
707 double dWeight = 0.05;
709 while ((! bStartPointOK) && (dWeight < 1))
715 if (PtiFloodFillStart == * pPtiCentroid)
733 bStartPointOK =
true;
734 bAllPointNotSea =
false;
748 if ((! bStartPointOK) && (! bAllPointNotSea))
751 LogStream <<
m_ulIter <<
": " <<
ERR <<
"could not find shadow zone cell-by-cell fill start point" << endl;
760 stack<CGeom2DIPoint> PtiStack;
763 PtiStack.push(PtiFloodFillStart);
766 while (! PtiStack.empty())
787 m_pRasterGrid->m_Cell[nX][nY].SetShadowZoneNumber(-nZone - 1);
791 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()))
797 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()))
825 int nCoastSeaHand =
m_VCoast[nCoast].nGetSeaHandedness();
826 int nShadowZoneCoastToCapeSeaHand;
835 bool bSweepDownCoast =
true;
837 if (nShadowBoundaryEndPoint < nShadowBoundaryStartPoint)
838 bSweepDownCoast =
false;
841 int nAlongCoastDistanceToShadowEndpoint =
tAbs(nShadowBoundaryEndPoint - nShadowBoundaryStartPoint - 1);
844 int nDownDriftEndPoint;
845 int nTotAlongCoastDistanceToDownDriftEndpoint = 2 * nAlongCoastDistanceToShadowEndpoint;
848 nDownDriftEndPoint = nShadowBoundaryStartPoint + nTotAlongCoastDistanceToDownDriftEndpoint;
851 nDownDriftEndPoint = nShadowBoundaryStartPoint - nTotAlongCoastDistanceToDownDriftEndpoint;
857 if (nDownDriftEndPoint < 0)
860 int nStartEdge =
m_VCoast[nCoast].nGetStartEdge();
862 if (nStartEdge ==
NORTH)
864 PtiDownDriftEndPoint.
SetX(
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(0)->nGetX());
865 PtiDownDriftEndPoint.
SetY(nDownDriftEndPoint);
868 else if (nStartEdge ==
SOUTH)
870 PtiDownDriftEndPoint.
SetX(
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(0)->nGetX());
874 else if (nStartEdge ==
WEST)
876 PtiDownDriftEndPoint.
SetX(nDownDriftEndPoint);
877 PtiDownDriftEndPoint.
SetY(
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(0)->nGetY());
880 else if (nStartEdge ==
EAST)
883 PtiDownDriftEndPoint.
SetY(
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(0)->nGetY());
887 else if (nDownDriftEndPoint >=
m_VCoast[nCoast].nGetCoastlineSize())
890 int nEndEdge =
m_VCoast[nCoast].nGetEndEdge();
891 int nCoastSize =
m_VCoast[nCoast].nGetCoastlineSize();
893 if (nEndEdge ==
NORTH)
895 PtiDownDriftEndPoint.
SetX(
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(nCoastSize - 1)->nGetX());
896 PtiDownDriftEndPoint.
SetY(-nDownDriftEndPoint);
899 else if (nEndEdge ==
SOUTH)
901 PtiDownDriftEndPoint.
SetX(
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(nCoastSize - 1)->nGetX());
905 else if (nEndEdge ==
WEST)
907 PtiDownDriftEndPoint.
SetX(-nDownDriftEndPoint);
908 PtiDownDriftEndPoint.
SetY(
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(nCoastSize - 1)->nGetY());
911 else if (nEndEdge ==
EAST)
914 PtiDownDriftEndPoint.
SetY(
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(nCoastSize - 1)->nGetY());
921 PtiDownDriftEndPoint = *
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(nDownDriftEndPoint);
925 CGeom2DIPoint const* pPtiDownDriftBoundaryStartPoint =
m_VCoast[nCoast].pPtiGetCellMarkedAsCoastline(nShadowBoundaryStartPoint);
928 int nXStart = pPtiDownDriftBoundaryStartPoint->
nGetX();
929 int nYStart = pPtiDownDriftBoundaryStartPoint->
nGetY();
930 int nXEnd = PtiDownDriftEndPoint.
nGetX();
931 int nYEnd = PtiDownDriftEndPoint.
nGetY();
934 if ((nXStart == nXEnd) && (nYStart == nYEnd))
941 double dXInc = dXEnd - dXStart;
942 double dYInc = dYEnd - dYStart;
948 int nTotDownDriftBoundaryDistance = 0;
955 for (
int m = 0; m <=
nRound(dLength); m++)
970 if ((LDownDriftBoundary.
nGetSize() == 0) || (PtThis != LDownDriftBoundary.
pPtBack()))
973 LDownDriftBoundary.
Append(&PtThis);
976 m_pRasterGrid->m_Cell[nX][nY].SetDownDriftZoneNumber(nZone + 1);
979 nTotDownDriftBoundaryDistance++;
999 m_VCoast[nCoast].AppendShadowDowndriftBoundary(&LDownDriftBoundary);
1003 double dAlongCoastIncrement = 1;
1004 double dDownDriftBoundaryIncrement = 1;
1006 if (nTotAlongCoastDistanceToDownDriftEndpoint < nTotDownDriftBoundaryDistance)
1009 dDownDriftBoundaryIncrement =
static_cast<double>(nTotDownDriftBoundaryDistance) / nTotAlongCoastDistanceToDownDriftEndpoint;
1010 nMaxDistance = nTotDownDriftBoundaryDistance;
1016 dAlongCoastIncrement =
static_cast<double>(nTotAlongCoastDistanceToDownDriftEndpoint) / nTotDownDriftBoundaryDistance;
1017 nMaxDistance = nTotAlongCoastDistanceToDownDriftEndpoint;
1020 double dCoastDistSoFar = 0;
1021 double dDownDriftBoundaryDistSoFar = 0;
1024 for (
int n = 1; n < nMaxDistance - 1; n++)
1026 dCoastDistSoFar += dAlongCoastIncrement;
1027 dDownDriftBoundaryDistSoFar += dDownDriftBoundaryIncrement;
1031 if ((dCoastDistSoFar >= nTotAlongCoastDistanceToDownDriftEndpoint) || (dDownDriftBoundaryDistSoFar >= nTotDownDriftBoundaryDistance))
1034 bool bPastShadowEnd =
false;
1037 if (bSweepDownCoast)
1039 nAlongCoast = nShadowBoundaryStartPoint +
nRound(dCoastDistSoFar);
1041 if (nAlongCoast >=
m_VCoast[nCoast].nGetCoastlineSize())
1044 if (nAlongCoast >= nShadowBoundaryEndPoint)
1045 bPastShadowEnd =
true;
1050 nAlongCoast = nShadowBoundaryStartPoint -
nRound(dCoastDistSoFar);
1052 if (nAlongCoast < 0)
1055 if (nAlongCoast <= nShadowBoundaryEndPoint)
1056 bPastShadowEnd =
true;
1059 int nAlongDownDriftBoundary =
nRound(dDownDriftBoundaryDistSoFar);
1067 int nCoastX = pPtiCoast->
nGetX();
1068 int nCoastY = pPtiCoast->
nGetY();
1083 if ((nCoastX == nDownDriftX) && (nCoastY == nDownDriftY))
1092 dXInc = nDownDriftX - nCoastX;
1093 dYInc = nDownDriftY - nCoastY;
1094 double dLinkingLineLength =
tMax(
tAbs(dXInc),
tAbs(dYInc));
1096 dXInc /= dLinkingLineLength;
1097 dYInc /= dLinkingLineLength;
1105 int nShadowZoneLength = 0;
1106 vector<int> VnShadowCellX, VnShadowCellY;
1108 for (
int m = 0; m < dLinkingLineLength; m++)
1114 if ((nX == nXLast) && (nY == nYLast))
1157 if (! bPastShadowEnd)
1160 bool bInShadowZone =
true;
1167 bInShadowZone =
false;
1170 for (
unsigned int mm = 0; mm < VnShadowCellX.size(); mm++)
1173 ProcessShadowZoneCell(VnShadowCellX[mm], VnShadowCellY[mm], nShadowZoneCoastToCapeSeaHand, pPtiCoast, VnShadowCellX.back(), VnShadowCellY.back(), nZone);
1185 ProcessShadowZoneCell(PtiRight.
nGetX(), PtiRight.
nGetY(), nShadowZoneCoastToCapeSeaHand, pPtiCoast, VnShadowCellX.back(), VnShadowCellY.back(), nZone);
1193 VnShadowCellX.push_back(nX);
1194 VnShadowCellY.push_back(nY);
1196 nShadowZoneLength++;
1206 ProcessDownDriftCell(nX, nY, (m - nShadowZoneLength), (dLinkingLineLength - nShadowZoneLength), nZone);
1230 if ((nXLast != -1) && (nYLast != -1))