@@ -267,6 +267,7 @@ void ViewshedExecutor::setOutputSd(Lines &lines, int pos, double dfZ)
267267 if (cellHeight > dfZ)
268268 result = oOpts.maybeVisibleVal ;
269269 }
270+
270271 if (sd <= 1 )
271272 cur = std::max (dfZ, cur);
272273 else
@@ -505,9 +506,8 @@ bool ViewshedExecutor::processFirstLine(Lines &lines)
505506 lines.result [m_nX] = oOpts.visibleVal ;
506507 }
507508
508- auto process = [this , &ll, &lines](bool sdCalc )
509+ auto process = [this , &ll, &lines]()
509510 {
510- m_sdCalc = sdCalc;
511511 if (!oCurExtent.containsY (m_nY))
512512 processFirstLineTopOrBottom (ll, lines);
513513 else
@@ -517,14 +517,17 @@ bool ViewshedExecutor::processFirstLine(Lines &lines)
517517 pQueue->SubmitJob ([&]() { processFirstLineRight (ll, lines); });
518518 pQueue->WaitCompletion ();
519519 }
520- sdCalc = false ;
521520 };
522521
523- process (false );
522+ process ();
523+ lines.prev = lines.cur ;
524524 if (sdMode ())
525525 {
526+ m_sdCalc = true ;
526527 lines.cur = std::move (lines.input );
527- process (true );
528+ process ();
529+ lines.prevTmp = lines.cur ;
530+ m_sdCalc = false ;
528531 }
529532
530533 if (oOpts.pitchMasking ())
@@ -598,7 +601,12 @@ void ViewshedExecutor::processFirstLineLeft(const LineLimits &ll, Lines &lines)
598601 {
599602 double dfZ = lines.cur [iStart];
600603 if (oOpts.outputMode == OutputMode::Normal)
604+ {
601605 lines.result [iStart] = oOpts.visibleVal ;
606+ if (m_sdCalc)
607+ if (lines.sd [iStart] > 1 )
608+ lines.cur [iStart] = m_dfZObserver;
609+ }
602610 else
603611 setOutput (lines, iStart, dfZ);
604612 iStart--;
@@ -810,7 +818,12 @@ void ViewshedExecutor::processFirstLineRight(const LineLimits &ll, Lines &lines)
810818 {
811819 double dfZ = lines.cur [iStart];
812820 if (oOpts.outputMode == OutputMode::Normal)
821+ {
813822 lines.result [iStart] = oOpts.visibleVal ;
823+ if (m_sdCalc)
824+ if (lines.sd [iStart] > 1 )
825+ lines.cur [iStart] = m_dfZObserver;
826+ }
814827 else
815828 setOutput (lines, iStart, dfZ);
816829 iStart++;
@@ -916,8 +929,17 @@ void ViewshedExecutor::processLineRight(int nYOffset, LineLimits &ll,
916929 int nXOffset = std::abs (iPixel - m_nX);
917930 double dfZ;
918931 if (nXOffset == nYOffset)
932+ {
933+ if (m_sdCalc && nXOffset == 1 )
934+ {
935+ lines.result [iPixel] = oOpts.visibleVal ;
936+ if (lines.sd [iPixel] > 1 )
937+ lines.cur [iPixel] = m_dfZObserver;
938+ continue ;
939+ }
919940 dfZ = CalcHeightLine (nYOffset, lines.cur [iPixel],
920941 lines.prev [iPixel - 1 ]);
942+ }
921943 else
922944 dfZ = oZcalc (nXOffset, nYOffset, lines.cur [iPixel - 1 ],
923945 lines.prev [iPixel], lines.prev [iPixel - 1 ]);
@@ -927,24 +949,41 @@ void ViewshedExecutor::processLineRight(int nYOffset, LineLimits &ll,
927949 maskLineRight (lines.result , ll, nLine);
928950}
929951
930- // / Apply angular mask to the initial X position. Assumes m_nX is in the raster.
952+ // / Apply angular/distance mask to the initial X position. Assumes m_nX is in the raster.
931953// / @param vResult Raster line on which to apply mask.
954+ // / @param ll Line limits.
932955// / @param nLine Line number.
933- void ViewshedExecutor::maskInitial (std::vector<double > &vResult, int nLine)
956+ // / @return True if the initial X position was masked.
957+ bool ViewshedExecutor::maskInitial (std::vector<double > &vResult,
958+ const LineLimits &ll, int nLine)
934959{
960+ // Mask min/max.
961+ if (ll.left >= ll.right || ll.leftMin != ll.rightMin )
962+ {
963+ vResult[m_nX] = oOpts.outOfRangeVal ;
964+ return true ;
965+ }
966+
935967 if (!oOpts.angleMasking ())
936- return ;
968+ return false ;
937969
938970 if (nLine < m_nY)
939971 {
940972 if (!rayBetween (oOpts.startAngle , oOpts.endAngle , M_PI / 2 ))
973+ {
941974 vResult[m_nX] = oOpts.outOfRangeVal ;
975+ return true ;
976+ }
942977 }
943978 else if (nLine > m_nY)
944979 {
945980 if (!rayBetween (oOpts.startAngle , oOpts.endAngle , 3 * M_PI / 2 ))
981+ {
946982 vResult[m_nX] = oOpts.outOfRangeVal ;
983+ return true ;
984+ }
947985 }
986+ return false ;
948987}
949988
950989// / Process a line above or below the observer.
@@ -962,37 +1001,61 @@ bool ViewshedExecutor::processLine(int nLine, Lines &lines)
9621001 // Adjust height of the read line.
9631002 LineLimits ll = adjustHeight (nYOffset, lines);
9641003
965- // Handle the initial position on the line.
1004+ auto process = [this , nYOffset, &ll, &lines]()
1005+ {
1006+ CPLJobQueuePtr pQueue = m_pool.CreateJobQueue ();
1007+ pQueue->SubmitJob ([&]() { processLineLeft (nYOffset, ll, lines); });
1008+ pQueue->SubmitJob ([&]() { processLineRight (nYOffset, ll, lines); });
1009+ pQueue->WaitCompletion ();
1010+ };
1011+
1012+ bool masked = false ;
1013+ // Handle initial position on the line.
9661014 if (oCurExtent.containsX (m_nX))
9671015 {
968- if (ll.left < ll.right && ll.leftMin == ll.rightMin )
1016+ masked = maskInitial (lines.result , ll, nLine);
1017+ if (!masked)
9691018 {
9701019 double dfZ = CalcHeightLine (std::abs (nYOffset), lines.cur [m_nX],
9711020 lines.prev [m_nX]);
9721021 setOutput (lines, m_nX, dfZ);
9731022 }
974- else
975- lines.result [m_nX] = oOpts.outOfRangeVal ;
976-
977- maskInitial (lines.result , nLine);
9781023 }
9791024
980- auto process = [this , nYOffset, &ll, &lines](bool sdCalc)
981- {
982- m_sdCalc = sdCalc;
983- CPLJobQueuePtr pQueue = m_pool.CreateJobQueue ();
984- pQueue->SubmitJob ([&]() { processLineLeft (nYOffset, ll, lines); });
985- pQueue->SubmitJob ([&]() { processLineRight (nYOffset, ll, lines); });
986- pQueue->WaitCompletion ();
987- m_sdCalc = false ;
988- };
1025+ process ();
9891026
990- process ( false );
1027+ // Process SD mode
9911028 if (sdMode ())
9921029 {
1030+ m_sdCalc = true ;
1031+
1032+ lines.prev = std::move (lines.prevTmp );
1033+ lines.prevTmp = std::move (lines.cur );
9931034 lines.cur = std::move (lines.input );
994- process (true );
1035+ // Handle initial position on the line.
1036+ if (!masked && oCurExtent.containsX (m_nX))
1037+ {
1038+ if (std::abs (nYOffset) == 1 )
1039+ {
1040+ lines.result [m_nX] = oOpts.visibleVal ;
1041+ if (lines.sd [m_nX] > 1 )
1042+ lines.cur [m_nX] = m_dfZObserver;
1043+ }
1044+ else
1045+ {
1046+
1047+ double dfZ = CalcHeightLine (std::abs (nYOffset), lines.cur [m_nX],
1048+ lines.prev [m_nX]);
1049+ setOutput (lines, m_nX, dfZ);
1050+ }
1051+ }
1052+ process ();
1053+ lines.prev = std::move (lines.prevTmp );
1054+ lines.prevTmp = lines.cur ;
1055+ m_sdCalc = false ;
9951056 }
1057+ else
1058+ lines.prev = lines.cur ;
9961059
9971060 if (oOpts.pitchMasking ())
9981061 applyPitchMask (lines.result , lines.pitchMask );
@@ -1077,7 +1140,8 @@ bool ViewshedExecutor::run()
10771140 [&]()
10781141 {
10791142 Lines lines (oCurExtent.xSize ());
1080- lines.prev = firstLine.cur ;
1143+ lines.prev = firstLine.prev ;
1144+ lines.prevTmp = firstLine.prevTmp ;
10811145 if (oOpts.pitchMasking ())
10821146 lines.pitchMask .resize (
10831147 oOutExtent.xSize (),
@@ -1090,7 +1154,6 @@ bool ViewshedExecutor::run()
10901154 {
10911155 if (!processLine (nLine, lines))
10921156 err = true ;
1093- lines.prev = lines.cur ;
10941157 if (oOpts.pitchMasking ())
10951158 std::fill (lines.pitchMask .begin (), lines.pitchMask .end (),
10961159 std::numeric_limits<double >::quiet_NaN ());
@@ -1102,7 +1165,8 @@ bool ViewshedExecutor::run()
11021165 [&]()
11031166 {
11041167 Lines lines (oCurExtent.xSize ());
1105- lines.prev = firstLine.cur ;
1168+ lines.prev = firstLine.prev ;
1169+ lines.prevTmp = firstLine.prevTmp ;
11061170 if (oOpts.pitchMasking ())
11071171 lines.pitchMask .resize (
11081172 oOutExtent.xSize (),
@@ -1115,7 +1179,6 @@ bool ViewshedExecutor::run()
11151179 {
11161180 if (!processLine (nLine, lines))
11171181 err = true ;
1118- lines.prev = lines.cur ;
11191182 if (oOpts.pitchMasking ())
11201183 std::fill (lines.pitchMask .begin (), lines.pitchMask .end (),
11211184 std::numeric_limits<double >::quiet_NaN ());
0 commit comments