public List <Coordinate> GenerateBootstrapRoute(Geofence geofence, double circleSize = 70)
        {
            var geometryFactory = GeometryFactory.Default;
            var xMod            = Math.Sqrt(0.75);
            var yMod            = Math.Sqrt(0.568);
            var points          = new List <Coordinate>();

            var polygon       = geofence.Feature.Geometry.Coordinates;
            var line          = geometryFactory.CreateLineString(polygon);
            var coords        = geofence.BBox.Coordinates;
            var minLat        = coords.Min(x => x.X);
            var minLon        = coords.Min(x => x.Y);
            var maxLat        = coords.Max(x => x.X);
            var maxLon        = coords.Max(x => x.Y);
            var currentLatLng = new NetTopologySuite.Geometries.Coordinate(maxLat, maxLon);
            var lastLatLng    = new NetTopologySuite.Geometries.Coordinate(minLat, minLon);
            var startLatLng   = Destination(currentLatLng, 90, circleSize * 1.5);
            var endLatLng     = Destination(Destination(lastLatLng, 270, circleSize * 1.5), 180, circleSize);
            var row           = 0;
            var heading       = 270;
            var i             = 0;

            while (currentLatLng.X > endLatLng.X)
            {
                do
                {
                    var point    = new Point(currentLatLng);
                    var distance = point.Distance(line);
                    if (distance <= circleSize || distance == 0 || polygon.Contains(currentLatLng))
                    {
                        points.Add(new Coordinate(currentLatLng.X, currentLatLng.Y));
                    }
                    currentLatLng = Destination(currentLatLng, heading, xMod * circleSize * 2);
                    i++;
                } while ((heading == 270 && currentLatLng.Y > endLatLng.Y) || (heading == 90 && currentLatLng.Y < startLatLng.Y));

                currentLatLng = Destination(currentLatLng, 180, yMod * circleSize * 2);
                heading       = row % 2 == 1
                    ? 270
                    : 90;
                currentLatLng = Destination(currentLatLng, heading, xMod * circleSize * 3);
                row++;
            }
            return(points);
        }
        /// <summary>
        /// Returns the point that is a distance and heading away from
        /// the given origin point.
        /// </summary>
        /// <param name="latlng">Origin coordinate</param>
        /// <param name="heading">Heading in degrees, clockwise from 0 degrees north.</param>
        /// <param name="distance">Distance in meters</param>
        /// <returns>The destination coordinate</returns>
        private static NetTopologySuite.Geometries.Coordinate Destination(NetTopologySuite.Geometries.Coordinate latlng, double heading, double distance)
        {
            heading = (heading + 360) % 360;
            const double rad      = Math.PI / 180;
            const double radInv   = 180 / Math.PI;
            const int    r        = 6378137; // approximation of Earth's radius
            var          lon1     = latlng.Y * rad;
            var          lat1     = latlng.X * rad;
            var          rheading = heading * rad;
            var          sinLat1  = Math.Sin(lat1);
            var          cosLat1  = Math.Cos(lat1);
            var          cosDistR = Math.Cos(distance / r);
            var          sinDistR = Math.Sin(distance / r);
            var          lat2     = Math.Asin((sinLat1 * cosDistR) + (cosLat1 *
                                                                      sinDistR * Math.Cos(rheading)));
            var lon2 = lon1 + Math.Atan2(Math.Sin(rheading) * sinDistR *
                                         cosLat1, cosDistR - (sinLat1 * Math.Sin(lat2)));

            lon2 *= radInv;
            lon2  = lon2 > 180 ? lon2 - 360 : lon2 < -180 ? lon2 + 360 : lon2;
            return(new NetTopologySuite.Geometries.Coordinate(lat2 * radInv, lon2));
        }