Example #1
0
        public List <GeoPoint> GetLineGeometryElevation(IGeometry lineStringGeometry, DEMDataSet dataSet, InterpolationMode interpolationMode = InterpolationMode.Bilinear)
        {
            if (lineStringGeometry == null || lineStringGeometry.IsEmpty)
            {
                return(null);
            }
            if (lineStringGeometry.OgcGeometryType != OgcGeometryType.LineString)
            {
                throw new Exception("Geometry must be a linestring");
            }
            if (lineStringGeometry.SRID != 4326)
            {
                throw new Exception("Geometry SRID must be set to 4326 (WGS 84)");
            }

            BoundingBox         bbox  = lineStringGeometry.GetBoundingBox();
            List <FileMetadata> tiles = this.GetCoveringFiles(bbox, dataSet);

            // Init interpolator
            IInterpolator interpolator = GetInterpolator(interpolationMode);

            var      ptStart       = lineStringGeometry.Coordinates[0];
            var      ptEnd         = lineStringGeometry.Coordinates.Last();
            GeoPoint start         = new GeoPoint(ptStart.Y, ptStart.X);
            GeoPoint end           = new GeoPoint(ptEnd.Y, ptEnd.X);
            double   lengthMeters  = start.DistanceTo(end);
            int      demResolution = dataSet.ResolutionMeters;
            int      totalCapacity = 2 * (int)(lengthMeters / demResolution);

            List <GeoPoint> geoPoints = new List <GeoPoint>(totalCapacity);

            using (RasterFileDictionary adjacentRasters = new RasterFileDictionary())
            {
                bool isFirstSegment = true; // used to return first point only for first segments, for all other segments last point will be returned
                foreach (GeoSegment segment in lineStringGeometry.Segments())
                {
                    List <FileMetadata> segTiles = this.GetCoveringFiles(segment.GetBoundingBox(), dataSet, tiles);

                    // Find all intersection with segment and DEM grid
                    IEnumerable <GeoPoint> intersections = this.FindSegmentIntersections(segment.Start.Longitude
                                                                                         , segment.Start.Latitude
                                                                                         , segment.End.Longitude
                                                                                         , segment.End.Latitude
                                                                                         , segTiles
                                                                                         , isFirstSegment
                                                                                         , true);

                    // Get elevation for each point
                    intersections = this.GetElevationData(intersections, adjacentRasters, segTiles, interpolator);

                    // Add to output list
                    geoPoints.AddRange(intersections);

                    isFirstSegment = false;
                }
                //Debug.WriteLine(adjacentRasters.Count);
            }  // Ensures all rasters are properly closed

            return(geoPoints);
        }
Example #2
0
        /// <summary>
        /// Return visibility report from first point to last point. We assume that all points are aligned.
        /// WARNING: those calculations are not spherical (yet) and are not accurate for long distances.
        /// <see cref="IntervisibilityMetrics"/>
        /// </summary>
        /// <param name="points">Input list of points, visibility is calculated for first and last points (ie: are they visible or is there a relief standing in between)</param>
        /// <returns><see cref="IntervisibilityMetrics"/> object</returns>
        internal static IntervisibilityMetrics ComputeVisibilityMetrics(IList <GeoPoint> points, bool visibilityCheck = true, double sourceVerticalOffset = 0d, double targetVerticalOffset = 0, double?noDataValue = null)
        {
            IntervisibilityMetrics metrics = new IntervisibilityMetrics();

            if (points.Count == 0)
            {
                return(metrics);
            }

            GeoPoint A = points.First(), B = points.Last();
            double   hA = A.Elevation ?? 0d, hB = B.Elevation ?? 0d;

            hA += sourceVerticalOffset;
            hB += targetVerticalOffset;
            double AB = A.DistanceTo(B);

            visibilityCheck = visibilityCheck && (AB > double.Epsilon);
            if (hA < hB)
            {
                MathHelper.Swap(ref A, ref B);
                MathHelper.Swap(ref hA, ref hB);
            }

            double   total = 0, minElevation = double.MaxValue, maxElevation = double.MinValue, totalClimb = 0, totalDescent = 0;
            GeoPoint firstPoint = points[0];

            firstPoint.DistanceFromOriginMeters = 0; // force at 0. If null, ignored in json responses
            double lastElevation = firstPoint.Elevation ?? 0;

            IntervisibilityObstacle obstacle = null;
            double lastPeakElevation         = 0;
            int    numNoDataPoints           = 0;

            for (int i = 1; i < points.Count; i++)
            {
                #region metrics
                GeoPoint curPoint = points[i];
                double   v_dist   = DistanceTo(curPoint, points[i - 1]);
                total += v_dist;
                curPoint.DistanceFromOriginMeters = total;

                minElevation = Math.Min(minElevation, curPoint.Elevation ?? double.MaxValue);
                maxElevation = Math.Max(maxElevation, curPoint.Elevation ?? double.MinValue);

                numNoDataPoints += curPoint.Elevation == noDataValue ? 1 : 0;

                double currentElevation = curPoint.Elevation ?? lastElevation;
                double diff             = currentElevation - lastElevation;
                if (diff > 0)
                {
                    totalClimb += diff;
                }
                else
                {
                    totalDescent += diff;
                }
                #endregion

                #region visibility checks
                // Visibility check
                // If obstacle hit, add it and
                if (visibilityCheck)
                {
                    double distToLowestPoint            = curPoint.DistanceTo(B);
                    double visibilityElevationThreshold = (distToLowestPoint * (hA - hB)) / AB + hB;
                    if (currentElevation >= visibilityElevationThreshold)
                    {
                        if (obstacle == null)
                        {
                            obstacle           = new IntervisibilityObstacle(curPoint, visibilityElevationThreshold);
                            lastPeakElevation  = currentElevation;
                            obstacle.PeakPoint = curPoint;
                        }
                        else
                        {
                            // still inside obstacle, find peak
                            if (currentElevation > lastPeakElevation)
                            {
                                lastPeakElevation  = currentElevation;
                                obstacle.PeakPoint = curPoint;
                            }
                        }
                    }
                    else
                    {
                        if (obstacle != null) // out of obstacle, register it
                        {
                            obstacle.ExitPoint = curPoint;
                            metrics.AddObstacle(obstacle);
                            obstacle = null;
                        }
                    }
                }

                if (i == points.Count - 1 && obstacle != null)
                {
                    // Edge case: last point is exit point. We still have an active obstacle instance
                    // If obstacle entry is curPoint, this is the same point and this is not an obstacle
                    if (!obstacle.EntryPoint.Equals(curPoint))
                    {
                        obstacle.ExitPoint = curPoint;
                        metrics.AddObstacle(obstacle);
                        obstacle = null;
                    }
                }
                #endregion


                lastElevation = currentElevation;
            }

            metrics.Climb         = totalClimb;
            metrics.Descent       = totalDescent;
            metrics.NumPoints     = points.Count;
            metrics.Distance      = total;
            metrics.MinElevation  = minElevation;
            metrics.MaxElevation  = maxElevation;
            metrics.HasVoids      = numNoDataPoints > 0;
            metrics.NumVoidPoints = numNoDataPoints;
            return(metrics);
        }