public async Task <bool> ExportResults(IEnumerable <Hexagon> hexagons, HexagonDefinition hexagonDefinition, MergeStrategy mergeStrategy)
        {
            foreach (Hexagon hexagon in hexagons)
            {
                string insertCommand = @"INSERT INTO HexagonLocation (U,V,PIXELX,PIXELY) VALUES (@U,@V,@PixelX,@PixelY) ON CONFLICT(U,V) DO UPDATE SET PixelX=excluded.PixelX,PixelY=excluded.PixelY";

                PointXY hexagonCenter = HexagonUtils.GetCenterPointXYOfHexagonLocationUV(hexagon.LocationUV, hexagonDefinition);

                await _connection.ExecuteAsync(insertCommand,
                                               new
                {
                    hexagon.LocationUV.U,
                    hexagon.LocationUV.V,
                    PixelX = hexagonCenter.X,
                    PixelY = hexagonCenter.Y
                });

                foreach (var key in hexagon.HexagonData.Data.Keys)
                {
                    object dataValue = hexagon.HexagonData.Data[key];

                    string insertDataCommand = @"INSERT INTO HexagonData (U,V,FIELD,VALUE) VALUES (@U,@V,@Field,@Value) ON CONFLICT(U,V,FIELD) DO ";

                    switch (mergeStrategy)
                    {
                    case MergeStrategy.BitMask:
                        insertDataCommand += "UPDATE SET VALUE=VALUE|excluded.Value";
                        break;

                    case MergeStrategy.Ignore:
                        insertDataCommand += "NOTHING";
                        break;

                    case MergeStrategy.Replace:
                        insertDataCommand += "UPDATE Set Value=excluded.Value";
                        break;

                    case MergeStrategy.Max:
                        insertDataCommand += "UPDATE Set Value=max(excluded.Value,Value)";
                        break;

                    case MergeStrategy.Min:
                        insertDataCommand += "UPDATE Set Value=min(excluded.Value,Value)";
                        break;
                    }

                    await _connection.ExecuteAsync(insertDataCommand,
                                                   new
                    {
                        hexagon.LocationUV.U,
                        hexagon.LocationUV.V,
                        Field = key,
                        Value = dataValue
                    });
                }
            }

            return(true);
        }
        /// <summary>
        /// </summary>
        /// <param name="source"></param>
        /// <param name="destination"></param>
        /// <param name="hexagonDefinition"></param>
        /// <returns></returns>
        public static int GetDistanceBetweenHexagonLocationUVs(HexagonLocationUV source, HexagonLocationUV destination,
                                                               HexagonDefinition hexagonDefinition)
        {
            var du = destination.U - source.U;
            var dv = destination.V - source.V;

            return(du * dv > 0 ? Math.Abs(du + dv) : Math.Max(Math.Abs(du), Math.Abs(dv)));
        }
        /// <summary>
        ///     Obtains the center point (x,y) of an hexagon given its LocationUv (u,v)
        /// </summary>
        /// <param name="location"></param>
        /// <param name="hexagonDefinition"></param>
        /// <returns></returns>
        public static PointXY GetCenterPointXYOfHexagonLocationUV(HexagonLocationUV location,
                                                                  HexagonDefinition hexagonDefinition)
        {
            var x = hexagonDefinition.NarrowWidth * location.U;
            var y = hexagonDefinition.Height * (location.U * 0.5 + location.V);

            return(new PointXY(x, y));
        }
Exemple #4
0
        public string GenerateMap(List <object> hexagons, HexagonDefinition hexagonDefinition, int hexagonReferenceZoom)
        {
            GeoJsonWriter writer = new GeoJsonWriter();

            FeatureCollection hexagonCollection = new FeatureCollection();

            foreach (IDictionary <string, object> hexagon in hexagons)
            {
                HexagonLocationUV locationUV = new HexagonLocationUV(Convert.ToInt32(hexagon["U"]), Convert.ToInt32(hexagon["V"]));

                IList <PointXY> points = HexagonUtils.GetPointsXYOfHexagon(locationUV, hexagonDefinition);

                LinearRing ring = new LinearRing(points.Select(pixelCoordinate =>
                {
                    var(latitude, longitude) = TileSystem.PixelXYToLatLong((int)pixelCoordinate.X, (int)pixelCoordinate.Y, hexagonReferenceZoom);

                    return(new Coordinate(longitude, latitude));
                }).ToArray());


                Polygon hexagonPolygon = new Polygon(ring);

                AttributesTable attributes = new AttributesTable(
                    new List <KeyValuePair <string, object> >
                {
                    new KeyValuePair <string, object>("U", locationUV.U),
                    new KeyValuePair <string, object>("V", locationUV.V),
                });


                foreach (var key in hexagon.Keys)
                {
                    switch (key)
                    {
                    case "U":
                    case "V":
                        break;

                    default:
                        object value = hexagon[key];
                        attributes.Add(key, value);
                        break;
                    }
                }

                Feature hexagonFeature = new Feature(hexagonPolygon, attributes);
                hexagonCollection.Add(hexagonFeature);
            }

            //4. Export Geojson just for the hexagons in this particular tile

            string result = writer.Write(hexagonCollection);

            return(result);
        }
 public Task <bool> ExportResults(IEnumerable <Hexagon> hexagons, HexagonDefinition hexagonDefinition, MergeStrategy mergeStrategy)
 {
     foreach (var hexagon in hexagons)
     {
         foreach (var key in hexagon.HexagonData.Data.Keys)
         {
             Console.WriteLine($"({hexagon.LocationUV.U}:{hexagon.LocationUV.U}) {key}:{hexagon.HexagonData[key]}");
         }
     }
     return(Task.FromResult(true));
 }
        /// <summary>
        ///     Determines if a specified point (x,y) is inside a given hexagon Location (u,v)
        /// </summary>
        /// <param name="point"></param>
        /// <param name="location"></param>
        /// <param name="hexagonDefinition"></param>
        /// <returns>True if inside the hexagon, false otherwise</returns>
        public static bool IsPointXYInsideHexagonLocationUV(PointXY point, HexagonLocationUV location,
                                                            HexagonDefinition hexagonDefinition)
        {
            var center = GetCenterPointXYOfHexagonLocationUV(location, hexagonDefinition);

            var d  = hexagonDefinition.Diameter;
            var dx = Math.Abs(point.X - center.X) / d;
            var dy = Math.Abs(point.Y - center.Y) / d;
            var a  = 0.25 * Math.Sqrt(3.0);

            return(dy <= a && a * dx + 0.25 * dy <= 0.5 * a);
        }
Exemple #7
0
        public IActionResult Get(int z, int x, int y)
        {
            using (var destinationImage = new Image <Rgba32>(TileSize, TileSize))
            {
                if (z >= 7)
                {
                    var hexSize = 500;


                    var size = (int)(hexSize / Math.Pow(2, 10 - z));

                    var hexagonDefinition = new HexagonDefinition(size, 10);

                    //Tile offset
                    var pixelX = x * TileSize;
                    var pixelY = y * TileSize;

                    var topLeft     = new PointXY(pixelX - size, pixelY - size);
                    var bottomRight = new PointXY(pixelX + TileSize + size, pixelY + TileSize + size);

                    foreach (HexagonLocationUV hexagon in HexagonUtils.GetHexagonsInsideBoundingBox(topLeft, bottomRight, hexagonDefinition))
                    {
                        PointXY center = HexagonUtils.GetCenterPointXYOfHexagonLocationUV(hexagon, hexagonDefinition);

                        IList <PointXY> hexagonPoints = HexagonUtils
                                                        .GetHexagonPixels(size, new PointXY(center.X - pixelX, center.Y - pixelY)).ToList();

                        PointF[] points = hexagonPoints.Select(p => new PointF((float)p.X, (float)p.Y)).ToArray();

                        destinationImage.Mutate(ctx => ctx

                                                .DrawLines(
                                                    new Rgba32(200, 200, 200, 200),
                                                    5,
                                                    points)
                                                .DrawLines(
                                                    new Rgba32(100, 100, 100, 200),
                                                    2,
                                                    points));
                    }
                }

                Stream outputStream = new MemoryStream();

                destinationImage.Save(outputStream, new PngEncoder());
                outputStream.Seek(0, SeekOrigin.Begin);
                return(this.File(outputStream, "image/png"));
            }
        }
Exemple #8
0
        internal static void Process(GeoDataToHexagonDataArgs opts)
        {
            Stopwatch           stopwatch     = Stopwatch.StartNew();
            LayersConfiguration layer         = opts.GetLayersConfiguration();
            MergeStrategy       mergeStrategy = opts.Merge;

            ValueHandlerFactory valueHandlerFactory = new ValueHandlerFactory();

            valueHandlerFactory.RegisterImplementation <WikimediaAltitudeHandler>("wikimedia_altitude");

            HexagonDefinition hexagonDefinition = opts.GetHexagonDefinition();
            HexagonProcessor  hexagonProcessor  = new HexagonProcessor(hexagonDefinition, valueHandlerFactory);

            BoundingBox bb = null;

            if (!string.IsNullOrEmpty(opts.East) && !string.IsNullOrEmpty(opts.West) &&
                !string.IsNullOrEmpty(opts.North) && !string.IsNullOrEmpty(opts.South))
            {
                bb = new BoundingBox
                {
                    East  = double.Parse(opts.East),
                    West  = double.Parse(opts.West),
                    North = double.Parse(opts.North),
                    South = double.Parse(opts.South)
                };
            }

            using (IGeoDataParser geoParser = opts.GetGeoDataParser())
                using (IHexagonDataExporter exporter = opts.GetResultExporter())
                {
                    IEnumerable <GeoData> geoDataList = geoParser.ParseGeodataFromSource(layer);

                    IEnumerable <Hexagon> results = hexagonProcessor.ProcessHexagonsFromGeoData(geoDataList, layer.Targets, bb);

                    ExportResults(exporter, results, hexagonDefinition, mergeStrategy);
                }

            stopwatch.Stop();

            Console.WriteLine($"Process took {stopwatch.ElapsedMilliseconds} ms");
        }
        public static IEnumerable <TileInfo> GetTilesContainingHexagon(Hexagon hexagon, int minZoomLevel, int maxZoomLevel,
                                                                       HexagonDefinition hexagonDefinition, int tileSize)
        {
            var tiles = new HashSet <TileInfo>();

            var points = GetPointsXYOfHexagon(hexagon.LocationUV, hexagonDefinition);

            var topLeft  = new PointXY(points[0].X, points[1].Y);
            var topRight = new PointXY(points[3].X, points[1].Y);

            var bottomLeft  = new PointXY(points[0].X, points[4].Y);
            var bottomRight = new PointXY(points[3].X, points[4].Y);

            for (var zoomLevel = minZoomLevel; zoomLevel <= maxZoomLevel; zoomLevel++)
            {
                tiles.Add(GetTileOfPoint(topLeft, zoomLevel, tileSize, hexagonDefinition));
                tiles.Add(GetTileOfPoint(topRight, zoomLevel, tileSize, hexagonDefinition));
                tiles.Add(GetTileOfPoint(bottomLeft, zoomLevel, tileSize, hexagonDefinition));
                tiles.Add(GetTileOfPoint(bottomRight, zoomLevel, tileSize, hexagonDefinition));
            }

            return(tiles);
        }
        public static IEnumerable <HexagonLocationUV> GetHexagonsInsideBoundingBox(PointXY topLeftCorner, PointXY bottomRightCorner,
                                                                                   HexagonDefinition hexagonDefinition)
        {
            var topLeftUV    = GetHexagonLocationUVForPointXY(topLeftCorner, hexagonDefinition);
            var bottomLeftUV =
                GetHexagonLocationUVForPointXY(new PointXY(topLeftCorner.X, bottomRightCorner.Y), hexagonDefinition);
            var bottomRightUV = GetHexagonLocationUVForPointXY(bottomRightCorner, hexagonDefinition);

            var rowsEven = bottomLeftUV.V - topLeftUV.V + 1;

            var topLeftUVCenter = GetCenterPointXYOfHexagonLocationUV(topLeftUV, hexagonDefinition);
            var minX2           = topLeftUVCenter.X + hexagonDefinition.NarrowWidth;

            var topLeftUV2    = GetHexagonLocationUVForPointXY(new PointXY(minX2, topLeftCorner.Y), hexagonDefinition);
            var bottomLeftUV2 =
                GetHexagonLocationUVForPointXY(new PointXY(minX2, bottomRightCorner.Y), hexagonDefinition);
            var rowsOdd = bottomLeftUV2.V - topLeftUV2.V + 1;

            var columns = bottomRightUV.U - topLeftUV.U + 1;

            for (var i = 0; i < columns; i++)
            {
                var rows = i % 2 == 0 ? rowsEven : rowsOdd;

                for (var j = 0; j < rows; j++)
                {
                    var offset = topLeftUV.V == topLeftUV2.V
                        ? Convert.ToInt32(Math.Floor((double)i / 2))
                        : Convert.ToInt32(Math.Ceiling((double)i / 2));

                    var u = topLeftUV.U + i;
                    var v = topLeftUV.V + j - offset;

                    yield return(new HexagonLocationUV(u, v));
                }
            }
        }
        internal static void Process(HexagonDataToMapArgs opts)
        {
            Stopwatch stopwatch = Stopwatch.StartNew();

            HexagonDefinition hexagonDefinition = opts.GetHexagonDefinition();

            //1.1. Get Bounding box coordinates

            BoundingBox bb = null;

            if (!string.IsNullOrEmpty(opts.Tile))
            {
                string[] tileSegments = opts.Tile.Split(":");

                if (tileSegments.Length != 3)
                {
                    throw new NotSupportedException($"A tile format must be supplied as z:x:y");
                }

                int zoom  = int.Parse(tileSegments[0]);
                int tileX = int.Parse(tileSegments[1]);
                int tileY = int.Parse(tileSegments[2]);

                var(pixelXLeft, pixelYTop) = TileSystem.TileXYToPixelXY(tileX, tileY);
                var(n, w) = TileSystem.PixelXYToLatLong(pixelXLeft, pixelYTop, opts.HexagonReferenceZoom);

                var(pixelXRight, pixelYBottom) = TileSystem.TileXYToPixelXY(tileX + 1, tileY + 1);
                var(s, e) = TileSystem.PixelXYToLatLong(pixelXRight, pixelYBottom, opts.HexagonReferenceZoom);

                bb = new BoundingBox
                {
                    East  = e,
                    West  = w,
                    North = n,
                    South = s
                };
            }
            else if (!string.IsNullOrEmpty(opts.East) && !string.IsNullOrEmpty(opts.West) &&
                     !string.IsNullOrEmpty(opts.North) && !string.IsNullOrEmpty(opts.South))
            {
                bb = new BoundingBox
                {
                    East  = double.Parse(opts.East),
                    West  = double.Parse(opts.West),
                    North = double.Parse(opts.North),
                    South = double.Parse(opts.South)
                };
            }

            List <object> hexagons;

            var hexagonDataReader = new SQLiteHexagonReader(opts.Input);

            if (bb == null)
            {
                hexagons = hexagonDataReader.Read(opts.DataProperties.ToArray()).ToList();
            }
            else
            {
                var(left, top)     = TileSystem.LatLongToPixelXY(bb.North, bb.West, opts.HexagonReferenceZoom);
                var(right, bottom) = TileSystem.LatLongToPixelXY(bb.South, bb.East, opts.HexagonReferenceZoom);
                hexagons           = hexagonDataReader.Read(left, right, top, bottom, opts.DataProperties.ToArray()).ToList();
            }

            using (StreamWriter outfile = new StreamWriter(opts.Output))
            {
                GeojsonExporter exporter = new GeojsonExporter();

                var result = exporter.GenerateMap(hexagons, hexagonDefinition, opts.HexagonReferenceZoom);
                outfile.Write(result);
            }


            stopwatch.Stop();

            Console.WriteLine($"Process took {stopwatch.ElapsedMilliseconds} ms");
        }
Exemple #12
0
 private static void ExportResults(IHexagonDataExporter exporter, IEnumerable <Hexagon> results, HexagonDefinition hexagonDefinition, MergeStrategy mergeStrategy)
 {
     exporter.ExportResults(results, hexagonDefinition, mergeStrategy).Wait();
 }
Exemple #13
0
 public HexagonProcessor(HexagonDefinition hexagonDefinition, ValueHandlerFactory valueHandlerFactory = null)
 {
     this.hexagonDefinition   = hexagonDefinition;
     this.valueHandlerFactory = valueHandlerFactory;
 }
        public static IList <PointXY> GetPointsXYOfHexagon(HexagonLocationUV location, HexagonDefinition hexagonDefinition)
        {
            var center = GetCenterPointXYOfHexagonLocationUV(location, hexagonDefinition);

            return(new List <PointXY>
            {
                new PointXY(center.X - hexagonDefinition.Diameter / 2.0, center.Y),
                new PointXY(center.X - hexagonDefinition.EdgeSize / 2.0, center.Y - hexagonDefinition.Height / 2.0),
                new PointXY(center.X + hexagonDefinition.EdgeSize / 2.0, center.Y - hexagonDefinition.Height / 2.0),
                new PointXY(center.X + hexagonDefinition.Diameter / 2.0, center.Y),
                new PointXY(center.X + hexagonDefinition.EdgeSize / 2.0, center.Y + hexagonDefinition.Height / 2.0),
                new PointXY(center.X - hexagonDefinition.EdgeSize / 2.0, center.Y + hexagonDefinition.Height / 2.0),
                new PointXY(center.X - hexagonDefinition.Diameter / 2.0, center.Y)
            });
        }
        /// <summary>
        ///     Obtains the Hexagon Location (u,v) for a given point (x,y)
        /// </summary>
        /// <remarks>
        ///     This algorithm follows a two step approach. The first one is very first and although doesn't have false positives
        ///     might have false negatives.
        ///     Thus, on a second iteration (if the first didn't return true) it checks the vicinity hexagons and uses a more
        ///     deterministic polygon intersection mechanism.
        /// </remarks>
        /// <param name="point">A given X,Y point</param>
        /// <param name="hexagonDefinition"></param>
        /// aaa
        /// <returns>An hexagon U,V Location</returns>
        public static HexagonLocationUV GetHexagonLocationUVForPointXY(PointXY point, HexagonDefinition hexagonDefinition)
        {
            var u = Convert.ToInt32(Math.Round(point.X / hexagonDefinition.NarrowWidth));
            var v = Convert.ToInt32(Math.Round(point.Y / hexagonDefinition.Height - u * 0.5));

            if (IsPointXYInsideHexagonLocationUV(point, new HexagonLocationUV(u, v), hexagonDefinition))
            {
                return(new HexagonLocationUV(u, v));
            }

            var surroundingHexagons = new List <HexagonLocationUV>
            {
                new HexagonLocationUV(u, v - 1),
                new HexagonLocationUV(u, v + 1),
                new HexagonLocationUV(u - 1, v),
                new HexagonLocationUV(u + 1, v),
                new HexagonLocationUV(u - 1, v + 1),
                new HexagonLocationUV(u + 1, v - 1)
            };

            foreach (var hex in surroundingHexagons)
            {
                if (IsPointXYInsideHexagonLocationUV(point, hex, hexagonDefinition))
                {
                    return(hex);
                }
            }

            return(null);
        }
        private static TileInfo GetTileOfPoint(PointXY pointXY, int zoomLevel, int tileSize, HexagonDefinition hexagonDefinition)
        {
            var pixelFactor = Math.Pow(2, zoomLevel - hexagonDefinition.ReferenceZoom);

            var tileX = Convert.ToInt32(Math.Floor(pointXY.X * pixelFactor / tileSize));
            var tileY = Convert.ToInt32(Math.Floor(pointXY.Y * pixelFactor / tileSize));

            return(new TileInfo(zoomLevel, tileX, tileY));
        }
Exemple #17
0
        public static IEnumerable <HexagonLocationUV> GetHexagonsIntersectedByLine(PointXY startPoint, PointXY endPoint, HexagonDefinition hexagonDefinition)
        {
            var startHexagon = HexagonUtils.GetHexagonLocationUVForPointXY(startPoint, hexagonDefinition);
            var endHexagon   = HexagonUtils.GetHexagonLocationUVForPointXY(endPoint, hexagonDefinition);

            var minU = new[] { startHexagon.U, endHexagon.U }.Min() - 1;
            var maxU = new[] { startHexagon.U, endHexagon.U }.Max() + 1;

            var minV = new[] { startHexagon.V, endHexagon.V }.Min() - 1;
            var maxV = new[] { startHexagon.V, endHexagon.V }.Max() + 1;

            var matchingHexagons = new List <HexagonLocationUV>();

            for (var u = minU; u <= maxU; u++)
            {
                for (var v = minV; v <= maxV; v++)
                {
                    var points = HexagonUtils.GetPointsXYOfHexagon(new HexagonLocationUV(u, v), hexagonDefinition);

                    for (var k = 0; k < points.Count() - 1; k++)
                    {
                        var p0 = points[k];
                        var p1 = points[k + 1];

                        if (GetLineIntersection(p0, p1, startPoint, endPoint) != null)
                        {
                            matchingHexagons.Add(new HexagonLocationUV(u, v));
                            break;
                        }
                    }
                }
            }

            return(matchingHexagons);
        }