Description
Is your feature request related to a problem? Please describe.
The use-case I have is to determine if two aircraft have line of sight to each other. Each aircraft's position is defined by their Latitude, Longitude and Altitude above Mean Sea Level (MSL)
I have been messing around with the Intervisibility report and it doesn't quite support this use-case. I believe what is happening is:
Currently when you perform an intervisibility report you can pass in GeoPoints with elevation specified but that field is ignored since the LineString
used in the method only provides 2D points and then the elevation is calculated based on those points
You can optionally specify a verticalOffset from that elevation for both the source and the target in GetIntervisibilityReport
but that doesn't allow you to specify an arbitrary altitude, only an offset from the ground elevation which we do not know in advance for this use-case
Describe the solution you'd like
For this use-case all I actually need is a simple bool ElevationService.HasLineOfSight(sourcePoint, targetPoint, dataSet)
as even the Intervisibility report is overkill as all I need is the boolean "yes/no" which means we could stop the calculation the first time an obstacle is detected which may same some processing time.
However, I will assume we keep using the Intervisibility report method since it is already written and easily (I think) modified
I would like the Intervisibility report to support the elevation/altitude field in the GeoPoints passed to it.
var sourcePoint = new GeoPoint(source.Latitude, source.Longitude, source.Altitude);
var targetPoint = new GeoPoint(target.Latitude, target.Longitude, target.Altitude);
var report = ElevationService.GetIntervisibilityReport(sourcePoint, targetPoint)
And I think it could be done very easily but since this is all new to me I would like to confirm here.
In the GetIntervisibilityReport
method we need to reset the elevation of the source and target points, if they are provided, before performing the visibility calculations.
public IntervisibilityReport GetIntervisibilityReport(GeoPoint source, GeoPoint target, DEMDataSet dataSet
, bool downloadMissingFiles = true
, double sourceVerticalOffset = 0d
, double targetVerticalOffset = 0d
, InterpolationMode interpolationMode = InterpolationMode.Bilinear)
{
try
{
var elevationLine = GeometryService.ParseGeoPointAsGeometryLine(source, target);
if (downloadMissingFiles)
this.DownloadMissingFiles(dataSet, elevationLine.GetBoundingBox());
var geoPoints = this.GetLineGeometryElevation(elevationLine, dataSet);
// New code
if (source.Elevation != null)
{
geoPoints[0].Elevation = source.Elevation;
}
if (target.Elevation != null && geoPoints.Count > 1)
{
geoPoints[geoPoints.Count -1].Elevation = target.Elevation;
}
// End new code
if (dataSet.SRID != Reprojection.SRID_GEODETIC)
geoPoints = geoPoints.ReprojectTo(dataSet.SRID, Reprojection.SRID_GEODETIC).ToList();
var metrics = geoPoints.ComputeVisibilityMetrics(sourceVerticalOffset, targetVerticalOffset, dataSet.NoDataValue);
return new IntervisibilityReport(geoPoints, metrics, originVerticalOffset: sourceVerticalOffset, targetVerticalOffset: targetVerticalOffset);
}
catch (Exception ex)
{
_logger.LogError($"{nameof(GetIntervisibilityReport)} error: {ex.Message}");
throw;
}
Describe alternatives you've considered
I haven't tried it yet but looking at the code I think I could do this myself by cutting bits of code out and stitching it together myself then calling GetIntervisibilityReport(List<GeoPoint> ... )
but this seems a not-great solution since I am duplicating code in the library that could get out of sync.
One other thing to consider is that this change might not be considered backwards compatible if people are passing in GeoPoints to this method that have altitudes which are currently being ignored.
Additional context
Intervisibility report highlighting the issue where I was doing some experimenting with specifying vertical offsets etc.
var sourcePoint = new GeoPoint(source.Location.Coordinate.Latitude, source.Location.Coordinate.Longitude, source.Altitude);
var targetPoint = new GeoPoint(target.Location.Coordinate.Latitude, target.Location.Coordinate.Longitude, target.Altitude);
var report = ElevationService.GetIntervisibilityReport(sourcePoint, targetPoint, DataSet, true, source.Altitude, target.Altitude);
LOS report:
Source: E-3A 'USA air 3 unit1', Lat/Lon: 44.9440589/37.5337401 at 9138.08 meters
Target: Su-33 'RUSSIA air 21 unit1', Lat/Lon: 42.802319/41.0292858 at 2029.22 meters
Report:
Origin: Lat/Lon 44.9440589/37.5337401. elevation 458.7944641113281, vertical offset 9138.08
Target: Lat/Lon 42.802319/41.0292858. elevation 6991.50341796875, vertical offset 2029.22
Obstructed: True
Obstacles count: 552
Metrics: Min/Max: -32517.84 / 32522.96, Distance: 368135.30 m, Climb/Descent: 23523479.52 / -23516946.82