1212 ****************************************************************************/
1313
1414#include < algorithm>
15- // ABELL
16- #include < iostream>
17- #include < iomanip>
1815
1916#include " gdal_alg.h"
2017#include " gdal_priv_templates.hpp"
@@ -229,61 +226,45 @@ void shrinkWindowForAngles(Window &oOutExtent, int nX, int nY,
229226
230227 // Set the X boundaries for the angles
231228 // ABELL - Verify for out-of-raster.
232- int xStart = hIntersect (startAngle, nX, nY, win.yStart );
233- if (xStart == std::numeric_limits<int >::max ())
234- xStart = hIntersect (startAngle, nX, nY, win.yStop );
235-
236- int xStop = hIntersect (endAngle, nX, nY, win.yStart );
237- if (xStop == std::numeric_limits<int >::max ())
238- xStop = hIntersect (endAngle, nX, nY, win.yStop );
229+ int startAngleX = hIntersect (startAngle, nX, nY, win);
230+ int stopAngleX = hIntersect (endAngle, nX, nY, win);
239231
240232 int xmax = nX;
241233 if (!rayBetween (startAngle, endAngle, 0 ))
242234 {
243- if (xStart != (std::numeric_limits<int >::max)())
244- xmax = std::max (xmax, xStart);
245- if (xStop != (std::numeric_limits<int >::max)())
246- xmax = std::max (xmax, xStop);
247- oOutExtent.xStop = std::min (oOutExtent.xStop , xmax);
235+ xmax = std::max (xmax, startAngleX);
236+ xmax = std::max (xmax, stopAngleX);
237+ // Add one to xmax since we want one past the stop. [start, stop)
238+ oOutExtent.xStop = std::min (oOutExtent.xStop , xmax + 1 );
248239 }
249240
250241 int xmin = nX;
251242 if (!rayBetween (startAngle, endAngle, M_PI))
252243 {
253- if (!isnan (xStart))
254- xmin = std::min (xmin, xStart);
255- if (!isnan (xStop))
256- xmin = std::min (xmin, xStop);
244+ xmin = std::min (xmin, startAngleX);
245+ xmin = std::min (xmin, stopAngleX);
257246 oOutExtent.xStart = std::max (oOutExtent.xStart , xmin);
258247 }
259248
260249 // Set the Y boundaries for the angles
261250 // ABELL - Verify for out-of-raster.
262- int yStart = vIntersect (startAngle, nX, nY, win.xStart );
263- if (yStart == std::numeric_limits<int >::max ())
264- yStart = vIntersect (startAngle, nX, nY, win.xStop );
265-
266- int yStop = vIntersect (endAngle, nX, nY, win.xStart );
267- if (yStop == std::numeric_limits<int >::max ())
268- yStop = vIntersect (endAngle, nX, nY, win.xStop );
251+ int startAngleY = vIntersect (startAngle, nX, nY, win);
252+ int stopAngleY = vIntersect (endAngle, nX, nY, win);
269253
270254 int ymin = nY;
271255 if (!rayBetween (startAngle, endAngle, M_PI / 2 ))
272256 {
273- if (yStart != std::numeric_limits<int >::max ())
274- ymin = std::min (ymin, yStart);
275- if (yStop != std::numeric_limits<int >::max ())
276- ymin = std::min (ymin, yStop);
257+ ymin = std::min (ymin, startAngleY);
258+ ymin = std::min (ymin, stopAngleY);
277259 oOutExtent.yStart = std::max (oOutExtent.yStart , ymin);
278260 }
279261 int ymax = nY;
280262 if (!rayBetween (startAngle, endAngle, 3 * M_PI / 2 ))
281263 {
282- if (yStart != std::numeric_limits<int >::max ())
283- ymax = std::max (ymax, yStart);
284- if (yStop != std::numeric_limits<int >::max ())
285- ymax = std::max (ymax, yStop);
286- oOutExtent.yStop = std::min (oOutExtent.yStop , ymax);
264+ ymax = std::max (ymax, startAngleY);
265+ ymax = std::max (ymax, stopAngleY);
266+ // Add one to ymax since we want one past the stop. [start, stop)
267+ oOutExtent.yStop = std::min (oOutExtent.yStop , ymax + 1 );
287268 }
288269}
289270
@@ -307,8 +288,17 @@ bool Viewshed::calcExtents(int nX, int nY,
307288 oOutExtent.yStop = GDALGetRasterBandYSize (pSrcBand);
308289
309290 if (!oOutExtent.contains (nX, nY))
291+ {
292+ if (oOpts.startAngle != oOpts.endAngle )
293+ {
294+ CPLError (CE_Failure, CPLE_AppDefined,
295+ " Angle masking is not supported with an out-of-raster "
296+ " observer." );
297+ return false ;
298+ }
310299 CPLError (CE_Warning, CPLE_AppDefined,
311300 " NOTE: The observer location falls outside of the DEM area" );
301+ }
312302
313303 constexpr double EPSILON = 1e-8 ;
314304 if (oOpts.maxDistance > 0 )
@@ -321,6 +311,10 @@ bool Viewshed::calcExtents(int nX, int nY,
321311 int nXStop = static_cast <int >(
322312 std::ceil (nX + adfInvTransform[1 ] * oOpts.maxDistance - EPSILON) +
323313 1 );
314+ // ABELL - These seem to be wrong. The transform of 1 is no transform, so not
315+ // sure why we're adding one in the first case. Really, the transformed distance
316+ // should add EPSILON. Not sure what the change should be for a negative transform,
317+ // which is what I think is being handled with the 1/0 addition/subtraction.
324318 int nYStart =
325319 static_cast <int >(std::floor (
326320 nY - std::fabs (adfInvTransform[5 ]) * oOpts.maxDistance +
@@ -399,11 +393,35 @@ bool Viewshed::run(GDALRasterBandH band, GDALProgressFunc pfnProgress,
399393 int nY = static_cast <int >(dfY);
400394
401395 if (oOpts.startAngle < 0 || oOpts.startAngle >= 360 )
396+ {
402397 CPLError (CE_Failure, CPLE_AppDefined,
403398 " Start angle out of range. Must be [0, 360)." );
399+ return false ;
400+ }
404401 if (oOpts.endAngle < 0 || oOpts.endAngle >= 360 )
402+ {
405403 CPLError (CE_Failure, CPLE_AppDefined,
406404 " End angle out of range. Must be [0, 360)." );
405+ return false ;
406+ }
407+ if (oOpts.maxPitch > 90 )
408+ {
409+ CPLError (CE_Failure, CPLE_AppDefined,
410+ " Invalid maxPitch. Cannot be greater than 90." );
411+ return false ;
412+ }
413+ if (oOpts.minPitch < -90 )
414+ {
415+ CPLError (CE_Failure, CPLE_AppDefined,
416+ " Invalid maxPitch. Cannot be less than -90." );
417+ return false ;
418+ }
419+ if (oOpts.maxPitch <= oOpts.minPitch )
420+ {
421+ CPLError (CE_Failure, CPLE_AppDefined,
422+ " Invalid pitch. maxPitch must be > minPitch" );
423+ return false ;
424+ }
407425
408426 // Normalize angle to radians and standard math arrangement.
409427 oOpts.startAngle = normalizeAngle (oOpts.startAngle );
0 commit comments