@@ -26,6 +26,11 @@ namespace gdal
2626namespace viewshed
2727{
2828
29+ CPLErr DummyBand::IReadBlock (int , int , void *)
30+ {
31+ return static_cast <CPLErr>(CPLE_NotSupported);
32+ }
33+
2934namespace
3035{
3136
@@ -113,6 +118,7 @@ double doMax(int nXOffset, int nYOffset, double dfThisPrev, double dfLast,
113118
114119// / Constructor - the viewshed algorithm executor
115120// / @param srcBand Source raster band
121+ // / @param sdBand Standard-deviation raster band
116122// / @param dstBand Destination raster band
117123// / @param nX X position of observer
118124// / @param nY Y position of observer
@@ -123,11 +129,12 @@ double doMax(int nXOffset, int nYOffset, double dfThisPrev, double dfLast,
123129// / @param emitWarningIfNoData Whether a warning must be emitted if an input
124130// / pixel is at the nodata value.
125131ViewshedExecutor::ViewshedExecutor (GDALRasterBand &srcBand,
132+ GDALRasterBand &sdBand,
126133 GDALRasterBand &dstBand, int nX, int nY,
127134 const Window &outExtent,
128135 const Window &curExtent, const Options &opts,
129136 Progress &progress, bool emitWarningIfNoData)
130- : m_pool(4 ), m_srcBand(srcBand), m_dstBand(dstBand),
137+ : m_pool(4 ), m_srcBand(srcBand), m_sdBand(sdBand), m_dstBand(dstBand),
131138 m_emitWarningIfNoData (emitWarningIfNoData), oOutExtent(outExtent),
132139 oCurExtent(curExtent), m_nX(nX - oOutExtent.xStart), m_nY(nY),
133140 oOpts(opts), oProgress(progress),
@@ -146,6 +153,27 @@ ViewshedExecutor::ViewshedExecutor(GDALRasterBand &srcBand,
146153 m_hasNoData = hasNoData;
147154}
148155
156+ // / Constructor - the viewshed algorithm executor
157+ // / @param srcBand Source raster band
158+ // / @param dstBand Destination raster band
159+ // / @param nX X position of observer
160+ // / @param nY Y position of observer
161+ // / @param outExtent Extent of output raster (relative to input)
162+ // / @param curExtent Extent of active raster.
163+ // / @param opts Configuration options.
164+ // / @param progress Reference to the progress tracker.
165+ // / @param emitWarningIfNoData Whether a warning must be emitted if an input
166+ // / pixel is at the nodata value.
167+ ViewshedExecutor::ViewshedExecutor (GDALRasterBand &srcBand,
168+ GDALRasterBand &dstBand, int nX, int nY,
169+ const Window &outExtent,
170+ const Window &curExtent, const Options &opts,
171+ Progress &progress, bool emitWarningIfNoData)
172+ : ViewshedExecutor(srcBand, m_dummyBand, dstBand, nX, nY, outExtent,
173+ curExtent, opts, progress, emitWarningIfNoData)
174+ {
175+ }
176+
149177// calculate the height adjustment factor.
150178double ViewshedExecutor::calcHeightAdjFactor ()
151179{
@@ -194,22 +222,33 @@ void ViewshedExecutor::setOutput(double &dfResult, double &dfCellVal,
194222// / Read a line of raster data.
195223// /
196224// / @param nLine Line number to read.
197- // / @param line Raster line to fill.
225+ // / @param lines Raster line to fill.
198226// / @return Success or failure.
199- bool ViewshedExecutor::readLine (int nLine, std::vector< double > &line )
227+ bool ViewshedExecutor::readLine (int nLine, Lines &lines )
200228{
201229 std::lock_guard g (iMutex);
202230
203231 if (GDALRasterIO (&m_srcBand, GF_Read, oOutExtent.xStart , nLine,
204- oOutExtent.xSize (), 1 , line. data (), oOutExtent. xSize (), 1 ,
205- GDT_Float64, 0 , 0 ))
232+ oOutExtent.xSize (), 1 , lines. cur . data (),
233+ oOutExtent. xSize (), 1 , GDT_Float64, 0 , 0 ))
206234 {
207235 CPLError (CE_Failure, CPLE_AppDefined,
208236 " RasterIO error when reading DEM at position (%d,%d), "
209237 " size (%d,%d)" ,
210238 oOutExtent.xStart , nLine, oOutExtent.xSize (), 1 );
211239 return false ;
212240 }
241+
242+ if (sdMode ())
243+ lines.input = lines.cur ;
244+
245+ // Initialize the result line.
246+ // In DEM mode the base is the pre-adjustment value. In ground mode the base is zero.
247+ if (oOpts.outputMode == OutputMode::DEM)
248+ lines.result = lines.cur ;
249+ else if (oOpts.outputMode == OutputMode::Ground)
250+ std::fill (lines.result .begin (), lines.result .end (), 0 );
251+
213252 return true ;
214253}
215254
@@ -376,29 +415,23 @@ bool ViewshedExecutor::processFirstLine(Lines &lines)
376415 int nLine = oOutExtent.clampY (m_nY);
377416 int nYOffset = nLine - m_nY;
378417
379- if (!readLine (nLine, lines. cur ))
418+ if (!readLine (nLine, lines))
380419 return false ;
381420
382421 // If the observer is outside of the raster, take the specified value as the Z height,
383422 // otherwise, take it as an offset from the raster height at that location.
384423 m_dfZObserver = oOpts.observer .z ;
385424 if (oCurExtent.containsX (m_nX))
386- {
387425 m_dfZObserver += lines.cur [m_nX];
388- if (oOpts.outputMode == OutputMode::Normal)
389- lines.result [m_nX] = oOpts.visibleVal ;
390- }
391- m_dfHeightAdjFactor = calcHeightAdjFactor ();
392-
393- // In DEM mode the base is the pre-adjustment value. In ground mode the base is zero.
394- if (oOpts.outputMode == OutputMode::DEM)
395- lines.result = lines.cur ;
396- else if (oOpts.outputMode == OutputMode::Ground)
397- std::fill (lines.result .begin (), lines.result .end (), 0 );
398426
399427 LineLimits ll = adjustHeight (nYOffset, lines);
400- if (oCurExtent.containsX (m_nX) && ll.leftMin != ll.rightMin )
401- lines.result [m_nX] = oOpts.outOfRangeVal ;
428+ if (oCurExtent.containsX (m_nX))
429+ {
430+ if (ll.leftMin != ll.rightMin )
431+ lines.result [m_nX] = oOpts.outOfRangeVal ;
432+ else if (oOpts.outputMode == OutputMode::Normal)
433+ lines.result [m_nX] = oOpts.visibleVal ;
434+ }
402435
403436 if (!oCurExtent.containsY (m_nY))
404437 processFirstLineTopOrBottom (ll, lines);
@@ -866,16 +899,9 @@ bool ViewshedExecutor::processLine(int nLine, Lines &lines)
866899{
867900 int nYOffset = nLine - m_nY;
868901
869- if (!readLine (nLine, lines. cur ))
902+ if (!readLine (nLine, lines))
870903 return false ;
871904
872- // In DEM mode the base is the input DEM value.
873- // In ground mode the base is zero.
874- if (oOpts.outputMode == OutputMode::DEM)
875- lines.result = lines.cur ;
876- else if (oOpts.outputMode == OutputMode::Ground)
877- std::fill (lines.result .begin (), lines.result .end (), 0 );
878-
879905 // Adjust height of the read line.
880906 LineLimits ll = adjustHeight (nYOffset, lines);
881907
@@ -962,6 +988,8 @@ bool ViewshedExecutor::run()
962988 firstLine.pitchMask .resize (oOutExtent.xSize (),
963989 std::numeric_limits<double >::quiet_NaN ());
964990
991+ m_dfHeightAdjFactor = calcHeightAdjFactor ();
992+
965993 if (!processFirstLine (firstLine))
966994 return false ;
967995
@@ -1025,5 +1053,11 @@ bool ViewshedExecutor::run()
10251053 return true ;
10261054}
10271055
1056+ bool ViewshedExecutor::sdMode () const
1057+ {
1058+ // If the SD band isn't a dummy band, we're in SD mode.
1059+ return dynamic_cast <DummyBand *>(&m_sdBand) == nullptr ;
1060+ }
1061+
10281062} // namespace viewshed
10291063} // namespace gdal
0 commit comments