/// <summary> /// Internal: Create a vertex graph from a set of hexagons. It is the /// responsibility of the caller to call destroyVertexGraph on the populated /// graph, otherwise the memory in the graph nodes will not be freed. /// </summary> /// /// <param name="h3Set">Set of hexagons</param> /// <param name="numHexes">Number of hexagons in the set</param> /// <param name="graph">Output graph</param> /// <!-- Based off 3.1.1 --> public static void h3SetToVertexGraph(ref List <H3Index> h3Set, int numHexes, ref VertexGraph graph) { GeoBoundary vertices = new GeoBoundary(); GeoCoord fromVertex = new GeoCoord(); GeoCoord toVertex = new GeoCoord(); VertexGraph.VertexNode edge; if (numHexes < 1) { // We still need to init the graph, or calls to destroyVertexGraph will // fail graph = new VertexGraph(0, 0); return; } int res = H3Index.H3_GET_RESOLUTION(h3Set[0]); const int minBuckets = 6; // TODO: Better way to calculate/guess? int numBuckets = numHexes > minBuckets ? numHexes : minBuckets; graph = new VertexGraph(numBuckets, res); // Iterate through every hexagon for (int i = 0; i < numHexes; i++) { H3Index.h3ToGeoBoundary(h3Set[i], ref vertices); // iterate through every edge for (int j = 0; j < vertices.numVerts; j++) { fromVertex = new GeoCoord(vertices.verts[j].lat, vertices.verts[j].lon); //fromVtx = vertices.verts[j]; int idx = (j + 1) % vertices.numVerts; toVertex = new GeoCoord(vertices.verts[idx].lat, vertices.verts[idx].lon); //toVtx = vertices.verts[(j + 1) % vertices.numVerts]; // If we've seen this edge already, it will be reversed edge = VertexGraph.findNodeForEdge(ref graph, toVertex, fromVertex); if (edge != null) { // If we've seen it, drop it. No edge is shared by more than 2 // hexagons, so we'll never see it again. VertexGraph.removeVertexNode(ref graph, ref edge); } else { // Add a new node for this edge VertexGraph.addVertexNode(ref graph, fromVertex, toVertex); } } } }
/// <summary> /// Internal: Create a LinkedGeoPolygon from a vertex graph. It is the /// responsibility of the caller to call destroyLinkedPolygon on the /// populated linked geo structure, or the memory for that structure /// will not be freed. /// </summary> /// <param name="graph">input graph</param> /// <param name="out_polygon">output polygon</param> /// <!-- Based off 3.1.1 --> internal static void _vertexGraphToLinkedGeo(ref VertexGraph graph, ref LinkedGeo.LinkedGeoPolygon out_polygon) { out_polygon = new LinkedGeo.LinkedGeoPolygon(); VertexGraph.VertexNode edge; // Find the next unused entry point while ((edge = VertexGraph.firstVertexNode(ref graph)) != null) { var loop = LinkedGeo.addNewLinkedLoop(ref out_polygon); // Walk the graph to get the outline do { var addLinkedCoord = LinkedGeo.addLinkedCoord(ref loop, ref edge.from); var nextVertex = edge.to; // Remove frees the node, so we can't use edge after this VertexGraph.removeVertexNode(ref graph, ref edge); edge = VertexGraph.findNodeForVertex(ref graph, ref nextVertex); } while (edge != null); } }