Skip to content

Commit

Permalink
Fix Python bindings for IsLineOfSightVisible
Browse files Browse the repository at this point in the history
  • Loading branch information
rouault committed Apr 4, 2024
1 parent 70de338 commit d270659
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 30 deletions.
4 changes: 2 additions & 2 deletions alg/gdal_alg.h
Original file line number Diff line number Diff line change
Expand Up @@ -359,8 +359,8 @@ GDALDatasetH CPL_DLL GDALViewshedGenerate(

bool CPL_DLL GDALIsLineOfSightVisible(
const GDALRasterBandH, const int xA, const int yA, const double zA,
const int xB, const int yB, const double zB, int *xTerrainIntersection,
int *yTerrainIntersection, CSLConstList papszOptions);
const int xB, const int yB, const double zB, int *pnxTerrainIntersection,
int *pnyTerrainIntersection, CSLConstList papszOptions);

/************************************************************************/
/* Rasterizer API - geometries burned into GDAL raster. */
Expand Down
38 changes: 24 additions & 14 deletions alg/los.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,27 +162,31 @@ static bool IsAboveTerrain(const GDALRasterBandH hBand, const int x,
* For example, datasets referenced against geographic coordinate at high latitudes may have issues.
*
* @param hBand The band to read the DEM data from. This must NOT be null.
*
*
* @param xA The X location (raster column) of the first point to check on the raster.
*
* @param yA The Y location (raster row) of the first point to check on the raster.
*
*
* @param zA The Z location (height) of the first point to check.
*
*
* @param xB The X location (raster column) of the second point to check on the raster.
*
* @param yB The Y location (raster row) of the second point to check on the raster.
*
*
* @param zB The Z location (height) of the second point to check.
*
* @param xTerrainIntersection The X location where the LOS line intersects with terrain,
* or nullptr if it does not intersect terrain. Currently ignored.
*
* @param yTerrainIntersection The Y location where the LOS line intersects with terrain,
* or nullptr if it does not intersect terrain. Currently ignored.
*
*
* @param[out] pnxTerrainIntersection The X location where the LOS line
* intersects with terrain, or nullptr if it does not intersect
* terrain. Not implemented currently (*pnxTerrainIntersection
* is set to -1)
*
* @param[out] pnyTerrainIntersection The Y location where the LOS line
* intersects with terrain, or nullptr if it does not intersect
* terrain. Not implemented currently (*pnyTerrainIntersection
* is set to -1)
*
* @param papszOptions Options for the line of sight algorithm (currently ignored).
*
*
* @return True if the two points are within Line of Sight.
*
* @since GDAL 3.9
Expand All @@ -191,12 +195,18 @@ static bool IsAboveTerrain(const GDALRasterBandH hBand, const int x,
bool GDALIsLineOfSightVisible(const GDALRasterBandH hBand, const int xA,
const int yA, const double zA, const int xB,
const int yB, const double zB,
CPL_UNUSED int *xTerrainIntersection,
CPL_UNUSED int *yTerrainIntersection,
int *pnxTerrainIntersection,
int *pnyTerrainIntersection,
CPL_UNUSED CSLConstList papszOptions)
{
VALIDATE_POINTER1(hBand, "GDALIsLineOfSightVisible", false);

if (pnxTerrainIntersection)
*pnxTerrainIntersection = -1;

if (pnyTerrainIntersection)
*pnyTerrainIntersection = -1;

// Perform a preliminary check of the start and end points.
if (!IsAboveTerrain(hBand, xA, yA, zA))
{
Expand Down
12 changes: 8 additions & 4 deletions autotest/alg/los.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,14 @@ def test_los_basic():

mem_ds = gdal.GetDriverByName("MEM").Create("", 2, 1)

assert gdal.IsLineOfSightVisible(mem_ds.GetRasterBand(1), 0, 0, 1, 1, 0, 1)
assert gdal.IsLineOfSightVisible(mem_ds.GetRasterBand(1), 0, 0, 1, 0, 0, 1)
assert not gdal.IsLineOfSightVisible(mem_ds.GetRasterBand(1), 0, 0, -1, 1, 0, 1)
assert not gdal.IsLineOfSightVisible(mem_ds.GetRasterBand(1), 0, 0, 1, 1, 0, -1)
success, x, y = gdal.IsLineOfSightVisible(mem_ds.GetRasterBand(1), 0, 0, 1, 1, 0, 1)
assert success
assert x == -1
assert y == -1

assert gdal.IsLineOfSightVisible(mem_ds.GetRasterBand(1), 0, 0, 1, 0, 0, 1)[0]
assert not gdal.IsLineOfSightVisible(mem_ds.GetRasterBand(1), 0, 0, -1, 1, 0, 1)[0]
assert not gdal.IsLineOfSightVisible(mem_ds.GetRasterBand(1), 0, 0, 1, 1, 0, -1)[0]

with pytest.raises(Exception, match="Received a NULL pointer"):
assert gdal.IsLineOfSightVisible(None, 0, 0, 0, 0, 0, 0)
Expand Down
19 changes: 17 additions & 2 deletions swig/include/Operations.i
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,21 @@ GDALDatasetShadow *ViewshedGenerate( GDALRasterBandShadow *srcBand,
/* IsLineOfSightVisible() */
/************************************************************************/

#ifdef SWIGPYTHON
%feature( "kwargs" ) IsLineOfSightVisible;
%apply Pointer NONNULL {GDALRasterBandShadow *band};
%inline %{
void IsLineOfSightVisible(GDALRasterBandShadow *band,
int xA, int yA, double zA,
int xB, int yB, double zB,
bool *pbVisible, int *pnXIntersection, int *pnYIntersection,
char** options = NULL)
{
*pbVisible = GDALIsLineOfSightVisible(band, xA, yA, zA, xB, yB, zB, pnXIntersection, pnYIntersection, options);
}
%}
%clear GDALRasterBandShadow *band;
#else
#ifndef SWIGJAVA
%feature( "kwargs" ) IsLineOfSightVisible;
#endif
Expand All @@ -647,13 +662,13 @@ GDALDatasetShadow *ViewshedGenerate( GDALRasterBandShadow *srcBand,
bool IsLineOfSightVisible(GDALRasterBandShadow *band,
int xA, int yA, double zA,
int xB, int yB, double zB,
int *xTerrainIntersection, int *yTerrainIntersection,
char** options = NULL)
{
return GDALIsLineOfSightVisible(band, xA, yA, zA, xB, yB, zB, xTerrainIntersection, yTerrainIntersection, options);
return GDALIsLineOfSightVisible(band, xA, yA, zA, xB, yB, zB, NULL, NULL, options);
}
%}
%clear GDALRasterBandShadow *band;
#endif

/************************************************************************/
/* AutoCreateWarpedVRT() */
Expand Down
12 changes: 4 additions & 8 deletions swig/include/python/docs/gdal_operations_docs.i
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,13 @@ yB : int
The Y location (raster row) of the second point to check on the raster.
zB : float
The Z location (height) of the second point to check.
xTerrainIntersection : int
The X location where the LOS line intersects with terrain, or nullptr if it does not
intersect terrain. Currently ignored.
yTerrainIntersection : int
The Y location where the LOS line intersects with terrain, or nullptr if it does not
intersect terrain. Currently ignored.
options : dict/list, optional
A dict or list of name=value of options for the line of sight algorithm (currently ignored).
Returns
-------
bool
True if the two points are within Line of Sight.
(bool, int, int)
First value of tuple is True if the two points are within Line of Sight.
Second value is the X location where the LOS line intersects with terrain (will be set in the future, currently set to -1).
Third value is the Y location where the LOS line intersects with terrain (will be set in the future, currently set to -1).
";
19 changes: 19 additions & 0 deletions swig/include/python/typemaps_python.i
Original file line number Diff line number Diff line change
Expand Up @@ -3449,3 +3449,22 @@ OBJECT_LIST_INPUT(GDALMDArrayHS);
/* %typemap(freearg) (int nUsages, GDALRATFieldUsage *paeUsages)*/
CPLFree( $2 );
}


%typemap(in,numinputs=0) (bool *pbVisible, int *pnXIntersection, int *pnYIntersection) ( bool visible = 0, int nxintersection = 0, int nyintersection = 0 )
{
/* %typemap(in) (bool *pbVisible, int *pnXIntersection, int *pnYIntersection) */
$1 = &visible;
$2 = &nxintersection;
$3 = &nyintersection;
}

%typemap(argout) (bool *pbVisible, int *pnXIntersection, int *pnYIntersection)
{
/* %typemap(argout) (bool *pbVisible, int *pnXIntersection, int *pnYIntersection) */
PyObject *r = PyTuple_New( 3 );
PyTuple_SetItem( r, 0, PyBool_FromLong(*$1) );
PyTuple_SetItem( r, 1, PyLong_FromLong(*$2) );
PyTuple_SetItem( r, 2, PyLong_FromLong(*$3) );
$result = t_output_helper($result,r);
}

0 comments on commit d270659

Please sign in to comment.