Skip to content

Commit d920792

Browse files
committed
Make standard processing work and tests pass.
1 parent 96dd287 commit d920792

File tree

3 files changed

+94
-61
lines changed

3 files changed

+94
-61
lines changed

alg/viewshed/viewshed_executor.cpp

Lines changed: 82 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ namespace gdal
2626
namespace viewshed
2727
{
2828

29+
CPLErr DummyBand::IReadBlock(int, int, void *)
30+
{
31+
return static_cast<CPLErr>(CPLE_NotSupported);
32+
}
33+
2934
namespace
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.
216209
void 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

alg/viewshed/viewshed_executor.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ namespace gdal
2727
namespace viewshed
2828
{
2929

30+
class DummyBand : public GDALRasterBand
31+
{
32+
virtual CPLErr IReadBlock(int, int, void *) override;
33+
};
34+
3035
class Progress;
3136

3237
/// Executes a viewshed computation on a source band, placing the result
@@ -60,6 +65,7 @@ class ViewshedExecutor
6065

6166
private:
6267
CPLWorkerThreadPool m_pool;
68+
DummyBand m_dummyBand; // Something to point at when there's no SD band.
6369
GDALRasterBand &m_srcBand;
6470
GDALRasterBand &m_sdBand;
6571
GDALRasterBand &m_dstBand;
@@ -85,6 +91,9 @@ class ViewshedExecutor
8591
double calcHeightAdjFactor();
8692
void setOutput(double &dfResult, double &dfCellVal, double &sdCellVal,
8793
double dfZ, double dfSdZ);
94+
void setOutputSd(double &dfResult, double &dfCellVal, double &sdCellVal,
95+
double dfZ, double dfSdZ);
96+
void setOutputNormal(double &dfResult, double &dfCellVal, double dfZ);
8897
bool readLine(int nLine, std::vector<Cell> &vThisLine);
8998
bool writeLine(int nLine, std::vector<Cell> &vThisLine);
9099
bool processLine(int nLine, std::vector<Cell> &vLastLine);
@@ -121,6 +130,7 @@ class ViewshedExecutor
121130
void applyPitchMask(std::vector<Cell> &vThisLine,
122131
const std::vector<double> &vPitchMaskVal);
123132
void calcTestAngles();
133+
bool sdMode() const;
124134
};
125135

126136
} // namespace viewshed

autotest/cpp/test_viewshed.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,8 @@ TEST(Viewshed, high_mask)
304304
{
305305
for (int x = 0; x < 15; ++x)
306306
{
307-
EXPECT_EQ(*e, *o);
307+
EXPECT_EQ(*e, *o) << "X/Y exp/act = " << x << "/" << y << "/"
308+
<< (int)*e << "/" << (int)*o << "!\n";
308309
e++;
309310
o++;
310311
}

0 commit comments

Comments
 (0)