/// <summary> /// _polyfillInternal traces the provided geoPolygon data structure with hexagons /// and then iteratively searches through these hexagons and their immediate /// neighbors to see if they are contained within the polygon or not. Those that /// are found are added to the out array as well as the found array. Once all /// hexagons to search are checked, the found hexagons become the new search /// array and the found array is wiped and the process repeats until no new /// hexagons can be found. /// </summary> /// <remarks> /// This comes at it a little differently using C#'s internal HashSet rather /// than a collision bucket. I've tweaked it to where it matches the speed /// of the original in benchmark tests, but it liekly could be made faster. /// </remarks> /// <param name="polygon">The geofence and holes defining the relevant area</param> /// <param name="res">The Hexagon resolution (0-15)</param> /// <returns> /// Tuple /// Item1 - Status code /// Item2 - List of H3Index values /// </returns> /// <!-- /// algos.c /// int _polyfillInternal /// --> public static (int, List <H3Index>) PolyFillInternal(this GeoPolygon polygon, int res) { // Get bounding boxes var bboxes = polygon.ToBBoxes(); // Get the traced hexagons around the outer polygon; var geofence = polygon.GeoFence; var preSearch = new List <H3Index>(); var search = geofence.GetEdgeHexagons(res); preSearch.AddRange(search); // Check inner holes for (var i = 0; i < polygon.NumHoles; i++) { var hole = polygon.Holes[i]; var innerHex = hole.GetEdgeHexagons(res); preSearch.AddRange(innerHex); } search = new HashSet <H3Index>(); search.UnionWith(preSearch); var found = new HashSet <H3Index>(); var results = new HashSet <H3Index>(); int numSearchHexes = search.Count; var numFoundHexes = 0; while (numSearchHexes > 0) { var currentSearchNum = 0; while (currentSearchNum < numSearchHexes) { foreach (var ring in search .Select ( index => index.KRing(1) .Where(h => h != Constants.H3Index.H3_NULL) )) { foreach ( var hex in ring .Where ( hex => !results.Contains(hex) && !found.Contains(hex) && polygon.PointInside(bboxes, hex.ToGeoCoord()) )) { found.Add(hex); numFoundHexes++; } currentSearchNum++; } } search = new HashSet <H3Index>(found); numSearchHexes = numFoundHexes; numFoundHexes = 0; results.UnionWith(found); found.Clear(); } return(0, results.ToList()); }