@@ -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
@@ -164,23 +169,9 @@ ViewshedExecutor::ViewshedExecutor(GDALRasterBand &srcBand,
164169 const Window &outExtent,
165170 const Window &curExtent, const Options &opts,
166171 Progress &progress, bool emitWarningIfNoData)
167- : m_pool(4 ), m_srcBand(srcBand), m_sdBand(srcBand), m_dstBand(dstBand),
168- m_emitWarningIfNoData(emitWarningIfNoData), oOutExtent(outExtent),
169- oCurExtent(curExtent), m_nX(nX - oOutExtent.xStart), m_nY(nY),
170- oOpts(opts), oProgress(progress),
171- m_dfMinDistance2(opts.minDistance * opts.minDistance),
172- m_dfMaxDistance2(opts.maxDistance * opts.maxDistance)
172+ : ViewshedExecutor(srcBand, m_dummyBand, dstBand, nX, nY, outExtent,
173+ curExtent, opts, progress, emitWarningIfNoData)
173174{
174- if (m_dfMaxDistance2 == 0 )
175- m_dfMaxDistance2 = std::numeric_limits<double >::max ();
176- if (opts.lowPitch != -90.0 )
177- m_lowTanPitch = std::tan (oOpts.lowPitch * (2 * M_PI / 360.0 ));
178- if (opts.highPitch != 90.0 )
179- m_highTanPitch = std::tan (oOpts.highPitch * (2 * M_PI / 360.0 ));
180- m_srcBand.GetDataset ()->GetGeoTransform (m_gt);
181- int hasNoData = false ;
182- m_noDataValue = m_srcBand.GetNoDataValue (&hasNoData);
183- m_hasNoData = hasNoData;
184175}
185176
186177// calculate the height adjustment factor.
@@ -212,9 +203,41 @@ double ViewshedExecutor::calcHeightAdjFactor()
212203// /
213204// / dfResult Reference to the result cell
214205// / dfCellVal Reference to the current cell height. Replace with observable height.
215- // / dfZ Minimum observable height at cell.
206+ // / dfSdCellVal Reference to the SD value of the cell.
207+ // / dfZ Minimum observable height at cell.
208+ // / dfSdZ Minimum possible observable height at cell.
216209void ViewshedExecutor::setOutput (double &dfResult, double &dfCellVal,
217210 double &dfSdCellVal, double dfZ, double dfSdZ)
211+ {
212+ if (!sdMode ())
213+ setOutputNormal (dfResult, dfCellVal, dfZ);
214+ else
215+ setOutputSd (dfResult, dfCellVal, dfSdCellVal, dfZ, dfSdZ);
216+ }
217+
218+ // Set the output Z value depending on the observable height and computation mode.
219+ // /
220+ // / dfResult Reference to the result cell
221+ // / dfCellVal Reference to the current cell height. Replace with observable height.
222+ // / dfZ Minimum observable height at cell.
223+ void ViewshedExecutor::setOutputNormal (double &dfResult, double &dfCellVal,
224+ double dfZ)
225+ {
226+ if (oOpts.outputMode != OutputMode::Normal)
227+ {
228+ double adjustment = dfZ - dfCellVal;
229+ if (adjustment > 0 )
230+ dfResult += adjustment;
231+ }
232+ else
233+ dfResult = (dfCellVal + oOpts.targetHeight < dfZ) ? oOpts.invisibleVal
234+ : oOpts.visibleVal ;
235+ dfCellVal = std::max (dfCellVal, dfZ);
236+ }
237+
238+ void ViewshedExecutor::setOutputSd (double &dfResult, double &dfCellVal,
239+ double &dfSdCellVal, double dfZ,
240+ double dfSdZ)
218241{
219242 if (oOpts.outputMode != OutputMode::Normal)
220243 {
@@ -225,38 +248,28 @@ void ViewshedExecutor::setOutput(double &dfResult, double &dfCellVal,
225248 }
226249 else
227250 {
228- /* *
229- std::cerr << "cell height/dfz/dfsdz/sd = " <<
230- (dfCellVal + oOpts.targetHeight) << "/" << dfZ << "/" << dfSdZ << "/" <<
231- dfSdCellVal;
232- **/
233- if (dfZ <= dfCellVal + oOpts.targetHeight )
234- {
235- // std::cerr << " - visible!\n";
236- dfResult = oOpts.visibleVal ;
237- if (dfSdCellVal > 1 ) // Changing SD to height.
238- dfSdCellVal = dfSdZ; // See-through case.
239- else
240- dfSdCellVal = dfCellVal; // Blocking case
241- }
242- else if (dfSdZ <= dfCellVal + oOpts.targetHeight )
251+ double cellHeight = dfCellVal + oOpts.targetHeight ;
252+ if (cellHeight < dfSdZ)
243253 {
244- // std::cerr << " - maybe visible!\n";
245- dfResult = oOpts.maybeVisibleVal ;
246- if (dfSdCellVal > 1 ) // Changing SD to height.
247- dfSdCellVal = dfSdZ; // See-through case.
248- else
249- dfSdCellVal = dfCellVal; // Blocking case
250- dfCellVal = dfZ;
254+ dfResult = oOpts.invisibleVal ;
255+ dfSdCellVal =
256+ dfSdZ; // SD height at cell is projected plane height.
251257 }
252258 else
253259 {
254- // std::cerr << " - not visible!\n";
255- dfResult = oOpts.invisibleVal ;
256- dfCellVal = dfZ;
257- dfSdCellVal = dfSdZ;
260+ dfResult =
261+ (cellHeight < dfZ ? oOpts.maybeVisibleVal : oOpts.visibleVal );
262+
263+ // Changing SD to height.
264+ if (dfSdCellVal > 1 )
265+ dfSdCellVal =
266+ dfSdZ; // SD height at cell is projected plane height (maybe vis).
267+ else
268+ dfSdCellVal =
269+ dfCellVal; // SD height is cell height (blocking).
258270 }
259271 }
272+ dfCellVal = std::max (dfCellVal, dfZ);
260273}
261274
262275// / Read a line of raster data.
@@ -287,25 +300,28 @@ bool ViewshedExecutor::readLine(int nLine, std::vector<Cell> &vThisLine)
287300 for (size_t i = 0 ; i < line.size (); ++i)
288301 vThisLine[i].val = line[i];
289302
290- int sdStatus = 0 ;
291- double nodata = std::numeric_limits<double >::max ();
303+ if (sdMode ())
292304 {
293- std::lock_guard g (iMutex);
294- nodata = m_sdBand.GetNoDataValue ();
295- sdStatus = m_sdBand.RasterIO (
296- GF_Read, oOutExtent.xStart , nLine, oOutExtent.xSize (), 1 ,
297- line.data (), oOutExtent.xSize (), 1 , GDT_Float64, 0 , 0 , nullptr );
298- }
299- if (sdStatus)
300- {
301- CPLError (CE_Failure, CPLE_AppDefined,
302- " RasterIO error when reading SD band at position (%d,%d), "
303- " size (%d,%d)" ,
304- oOutExtent.xStart , nLine, oOutExtent.xSize (), 1 );
305- return false ;
305+ int sdStatus = 0 ;
306+ double nodata = std::numeric_limits<double >::max ();
307+ {
308+ std::lock_guard g (iMutex);
309+ nodata = m_sdBand.GetNoDataValue ();
310+ sdStatus = m_sdBand.RasterIO (
311+ GF_Read, oOutExtent.xStart , nLine, oOutExtent.xSize (), 1 ,
312+ line.data (), oOutExtent.xSize (), 1 , GDT_Float64, 0 , 0 , nullptr );
313+ }
314+ if (sdStatus)
315+ {
316+ CPLError (CE_Failure, CPLE_AppDefined,
317+ " RasterIO error when reading SD band at position (%d,%d), "
318+ " size (%d,%d)" ,
319+ oOutExtent.xStart , nLine, oOutExtent.xSize (), 1 );
320+ return false ;
321+ }
322+ for (size_t i = 0 ; i < line.size (); ++i)
323+ vThisLine[i].sd = (line[i] == nodata ? 1000.0 : line[i]);
306324 }
307- for (size_t i = 0 ; i < line.size (); ++i)
308- vThisLine[i].sd = (line[i] == nodata ? 1000.0 : line[i]);
309325
310326 return true ;
311327}
@@ -1162,5 +1178,11 @@ bool ViewshedExecutor::run()
11621178 return true ;
11631179}
11641180
1181+ bool ViewshedExecutor::sdMode () const
1182+ {
1183+ // If the SD band isn't a dummy band, we're in SD mode.
1184+ return dynamic_cast <DummyBand *>(&m_sdBand) == nullptr ;
1185+ }
1186+
11651187} // namespace viewshed
11661188} // namespace gdal
0 commit comments