Exemple #1
0
        /// <summary>
        /// Returns the radius of a given hexagon in kilometers
        /// </summary>
        /// <param name="h3Index">Index of the hexagon</param>
        /// <returns>radius of hexagon in kilometers</returns>
        /// <!-- Based off 3.1.1 -->
        static double _hexRadiusKm(H3Index h3Index)
        {
            // There is probably a cheaper way to determine the radius of a
            // hexagon, but this way is conceptually simple
            GeoCoord    h3Center   = new GeoCoord();
            GeoBoundary h3Boundary = new GeoBoundary();

            H3Index.h3ToGeo(h3Index, ref h3Center);
            H3Index.h3ToGeoBoundary(h3Index, ref h3Boundary);
            return(GeoCoord._geoDistKm(h3Center, h3Boundary.verts));
        }
Exemple #2
0
        /// <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);
                    }
                }
            }
        }
Exemple #3
0
        /// <summary>
        /// Provides the coordinates defining the unidirectional edge.
        /// </summary>
        /// <param name="edge">The unidirectional edge H3Index</param>
        /// <param name="gb">
        /// The geoboundary object to store the edge coordinates.
        /// </param>
        /// <!-- Based off 3.1.1 -->
        public static void getH3UnidirectionalEdgeBoundary(H3Index edge, ref GeoBoundary gb)
        {
            // TODO: More efficient solution :)
            GeoBoundary origin             = new GeoBoundary();
            GeoBoundary destination        = new GeoBoundary();
            GeoCoord    postponedVertex    = new GeoCoord();
            bool        hasPostponedVertex = false;

            H3Index.h3ToGeoBoundary(getOriginH3IndexFromUnidirectionalEdge(edge), ref origin);
            H3Index.h3ToGeoBoundary(getDestinationH3IndexFromUnidirectionalEdge(edge), ref destination);

            int k = 0;

            for (int i = 0; i < origin.numVerts; i++)
            {
                if (_hasMatchingVertex(origin.verts[i], destination))
                {
                    // If we are on vertex 0, we need to handle the case where it's the
                    // end of the edge, not the beginning.
                    if (i == 0 &&
                        !_hasMatchingVertex(origin.verts[i + 1], destination))
                    {
                        postponedVertex    = origin.verts[i];
                        hasPostponedVertex = true;
                    }
                    else
                    {
                        gb.verts[k] = origin.verts[i];
                        k++;
                    }
                }
            }

            // If we postponed adding the last vertex, add it now
            if (hasPostponedVertex)
            {
                gb.verts[k] = postponedVertex;
                k++;
            }
            gb.numVerts = k;
        }