Ejemplo n.º 1
0
 public HexEdgeType GetEdgeType(HexDirection direction)
 {
     return(HexMetrics.GetEdgeType(
                elevation,
                neighbors[(int)direction].elevation
                ));
 }
Ejemplo n.º 2
0
    public static HexEdge Build(HexCell cell1, HexCell cell2, HexDirection direction)
    {
        EdgeVertices e1 = new EdgeVertices(
            cell1.Position + HexMetrics.GetFirstSolidCorner(direction),
            cell1.Position + HexMetrics.GetSecondSolidCorner(direction)
            );
        EdgeVertices e2 = new EdgeVertices(
            cell2.Position + HexMetrics.GetSecondSolidCorner(direction.Opposite()),
            cell2.Position + HexMetrics.GetFirstSolidCorner(direction.Opposite())
            );
        HexEdge     edge;
        HexEdgeType edgeType = HexMetrics.GetEdgeType(cell1.Elevation, cell2.Elevation);

        if (edgeType == HexEdgeType.Flat)
        {
            edge = new FlatHexEdge(e1, e2, cell1.Color, cell2.Color);
        }
        else if (edgeType == HexEdgeType.Slope)
        {
            edge = new SlopeHexEdge(e1, e2, cell1.Color, cell2.Color);
        }
        else
        {
            edge = new CliffHexEdge(e1, e2, cell1.Color, cell2.Color);
        }
        return(edge);
    }
Ejemplo n.º 3
0
 ///桥洞三角化
 void TriangulateCorner(Vector3 bottom, Color bottomColor, Vector3 left, Color leftColor, Vector3 right, Color rightColor, ref DynamicBuffer <ColorBuffer> colorBuffer, ref DynamicBuffer <VertexBuffer> vertexBuffer, int bottomElevation, int leftElevation, int rightElevation)
 {
     HexMetrics.HexEdgeType leftEdgeType  = HexMetrics.GetEdgeType(bottomElevation, leftElevation);
     HexMetrics.HexEdgeType rightEdgeType = HexMetrics.GetEdgeType(bottomElevation, rightElevation);
     if (leftEdgeType == HexMetrics.HexEdgeType.Slope)
     {
         if (rightEdgeType == HexMetrics.HexEdgeType.Slope)
         {
             TriangulateCornerTerraces(bottom, bottomColor, left, leftColor, right, rightColor, ref colorBuffer, ref vertexBuffer);
         }
         else if (rightEdgeType == HexMetrics.HexEdgeType.Flat)
         {
             TriangulateCornerTerraces(left, leftColor, right, rightColor, bottom, bottomColor, ref colorBuffer, ref vertexBuffer);
         }
         else
         {
             TriangulateCornerTerracesCliff(bottom, bottomColor, left, leftColor, right, rightColor, ref colorBuffer, ref vertexBuffer, bottomElevation, leftElevation, rightElevation);
         }
     }
     else if (rightEdgeType == HexMetrics.HexEdgeType.Slope)
     {
         if (leftEdgeType == HexMetrics.HexEdgeType.Flat)
         {
             TriangulateCornerTerraces(right, rightColor, bottom, bottomColor, left, leftColor, ref colorBuffer, ref vertexBuffer);
         }
         else
         {
             TriangulateCornerCliffTerraces(bottom, bottomColor, left, leftColor, right, rightColor, ref colorBuffer, ref vertexBuffer, bottomElevation, leftElevation, rightElevation);
         }
     }
     else if (HexMetrics.GetEdgeType(leftElevation, rightElevation) == HexMetrics.HexEdgeType.Slope)
     {
         if (leftElevation < rightElevation)
         {
             TriangulateCornerCliffTerraces(right, rightColor, bottom, bottomColor, left, leftColor, ref colorBuffer, ref vertexBuffer, rightElevation, bottomElevation, leftElevation);
         }
         else
         {
             TriangulateCornerTerracesCliff(left, leftColor, right, rightColor, bottom, bottomColor, ref colorBuffer, ref vertexBuffer, leftElevation, rightElevation, bottomElevation);
         }
     }
     else
     {
         ////两个单元处于同一平面,填充桥三角补丁,添加桥三角的3个顶点
         AddTriangle(bottom, bottomColor, left, leftColor, right, rightColor, ref colorBuffer, ref vertexBuffer);
     }
 }
Ejemplo n.º 4
0
        ///峭壁镜像处理:左右对调
        void TriangulateCornerCliffTerraces(Vector3 begin, Color beginCellColor, Vector3 left, Color leftCellColor, Vector3 right, Color rightCellColor, ref DynamicBuffer <ColorBuffer> colorBuffer, ref DynamicBuffer <VertexBuffer> vertexBuffer, int bottomElevation, int leftElevation, int rightElevation)
        {
            float b = 1f / (leftElevation - bottomElevation);

            if (b < 0)
            {
                b = -b;
            }
            Vector3 boundary      = Vector3.Lerp(begin, left, b);
            Color   boundaryColor = Color.Lerp(beginCellColor, leftCellColor, b);

            TriangulateBoundaryTriangle(right, rightCellColor, begin, beginCellColor, boundary, boundaryColor, ref colorBuffer, ref vertexBuffer);
            if (HexMetrics.GetEdgeType(leftElevation, rightElevation) == HexMetrics.HexEdgeType.Slope)
            {
                TriangulateBoundaryTriangle(left, leftCellColor, right, rightCellColor, boundary, boundaryColor, ref colorBuffer, ref vertexBuffer);
            }
            else
            {
                AddTriangle(left, leftCellColor, right, rightCellColor, boundary, boundaryColor, ref colorBuffer, ref vertexBuffer);
            }
        }
Ejemplo n.º 5
0
    public override void Triangulate(HexMesh mesh)
    {
        float lerpCoef = (float)(rightCell.Elevation - beginCell.Elevation) / (leftCell.Elevation - beginCell.Elevation);

        if (lerpCoef < 0)
        {
            lerpCoef = -lerpCoef;
        }
        Vector3 boundary      = Vector3.Lerp(HexMetrics.Perturb(beginCorner), HexMetrics.Perturb(leftCorner), lerpCoef);
        Color   boundaryColor = Color.Lerp(beginCell.Color, leftCell.Color, lerpCoef);

        Corner.TriangulateBoundaryTriangle(mesh, rightCorner, rightCell, beginCorner, beginCell, boundary, boundaryColor);

        if (HexMetrics.GetEdgeType(leftCell.Elevation, rightCell.Elevation) == HexEdgeType.Slope)
        {
            TriangulateBoundaryTriangle(mesh, leftCorner, leftCell, rightCorner, rightCell, boundary, boundaryColor);
        }
        else
        {
            mesh.AddTriangle(HexMetrics.Perturb(leftCorner), HexMetrics.Perturb(rightCorner), boundary, false);
            mesh.AddTriangleColor(leftCell.Color, rightCell.Color, boundaryColor);
        }
    }
Ejemplo n.º 6
0
 public HexEdgeType GetEdgeType(HexDirectionEnum direction)
 {
     return(HexMetrics.GetEdgeType(Elevation, GetNeighbor(direction).Elevation));
 }
Ejemplo n.º 7
0
 public HexEdgeType GetEdgeType(HexCell other)
 {
     return(HexMetrics.GetEdgeType(elevation, other.elevation));
 }
Ejemplo n.º 8
0
        public void Execute(Entity entity, int index, [ReadOnly] ref Cell cellData, [ReadOnly] ref NewDataTag tag, [ReadOnly] ref Neighbors neighbors, [ReadOnly] ref NeighborsIndex neighborsIndex, [ReadOnly] ref River river)
        {
            //0.获取单元索引,Execute的index不可靠,添加动态缓存
            int cellIndex = cellData.Index;
            DynamicBuffer <ColorBuffer>  colorBuffer  = CommandBuffer.AddBuffer <ColorBuffer>(index, entity);
            DynamicBuffer <VertexBuffer> vertexBuffer = CommandBuffer.AddBuffer <VertexBuffer>(index, entity);
            //用于河流的动态缓存
            DynamicBuffer <UvBuffer>    uvBuffer     = CommandBuffer.AddBuffer <UvBuffer>(index, entity);
            DynamicBuffer <RiverBuffer> riverBuffers = CommandBuffer.AddBuffer <RiverBuffer>(index, entity);

            //1.获取当前单元的中心位置
            Vector3 currCellCenter = cellData.Position;
            //缓存当前单元的颜色
            Color currCellColor = cellData.Color;
            //当前单元的海拔
            int elevation = cellData.Elevation;

            ////保存需要混合的颜色,使用数组[]是为了方便循环
            Color[] blendColors = new Color[6];
            blendColors[0] = neighbors.NE;
            blendColors[1] = neighbors.E;
            blendColors[2] = neighbors.SE;
            blendColors[3] = neighbors.SW;
            blendColors[4] = neighbors.W;
            blendColors[5] = neighbors.NW;
            //前3个方向相邻单元的索引
            int[] directionIndex = new int[6];
            directionIndex[0] = neighborsIndex.NEIndex;
            directionIndex[1] = neighborsIndex.EIndex;
            directionIndex[2] = neighborsIndex.SEIndex;
            directionIndex[3] = neighborsIndex.SWIndex;
            directionIndex[4] = neighborsIndex.WIndex;
            directionIndex[5] = neighborsIndex.NWIndex;
            //前三个方向相邻单元的海拔
            int[] elevations = new int[6];
            elevations[0] = neighbors.NEElevation;
            elevations[1] = neighbors.EElevation;
            elevations[2] = neighbors.SEElevation;
            elevations[3] = neighbors.SWElevation;
            elevations[4] = neighbors.WElevation;
            elevations[5] = neighbors.NWElevation;
            //添加六边形单元六个方向的顶点、三角和颜色
            for (int j = 0; j < 6; j++)
            {
                //1.添加中心区域的3个顶点
                int          next = (j + 1) > 5 ? 0 : (j + 1);
                EdgeVertices e    = new EdgeVertices((currCellCenter + HexMetrics.SolidCorners[j]), (currCellCenter + HexMetrics.SolidCorners[next]));

                int prev  = (j - 1) < 0 ? 5 : (j - 1);
                int next2 = (j + 2) <= 5 ? (j + 2) : (j - 4);
                int prev2 = (j - 2) >= 0 ? (j - 2) : (j + 4);
                //是否有河流通过
                bool  hasRiverThroughEdge = HasRiverThroughEdge(river, directionIndex[j]);
                float RiverSurfaceY       = (elevation + HexMetrics.riverSurfaceElevationOffset) * HexMetrics.elevationStep;

                //如果有河流通过,则降低海拔来创造河道
                if (cellData.HasRiver)
                {
                    if (hasRiverThroughEdge)
                    {
                        e.v3.y = (elevation + HexMetrics.streamBedElevationOffset) * HexMetrics.elevationStep;
                        if (river.HasOutgoingRiver != river.HasIncomingRiver)
                        {
                            //TriangulateWithRiverBeginOrEnd(directions[j], directions[prev], directions[next], currCellColor, currCellCenter, e, ref colorBuffer, ref vertexBuffer);
                            EdgeVertices m = new EdgeVertices(Vector3.Lerp(currCellCenter, e.v1, 0.5f), Vector3.Lerp(currCellCenter, e.v5, 0.5f));
                            m.v3.y = e.v3.y;
                            TriangulateEdgeStrip(m, currCellColor, e, currCellColor, ref colorBuffer, ref vertexBuffer);
                            TriangulateEdgeFan(currCellCenter, m, currCellColor, ref colorBuffer, ref vertexBuffer);
                            TriangulateRiverQuad(m.v2, m.v4, e.v2, e.v4, RiverSurfaceY, RiverSurfaceY, 0.6f, ref uvBuffer, ref riverBuffers, river.HasIncomingRiver);
                            Vector3 center = currCellCenter;
                            center.y = m.v2.y = m.v4.y = RiverSurfaceY;
                            AddTriangle(center, m.v2, m.v4, ref riverBuffers);
                            if (river.HasIncomingRiver)
                            {
                                AddTriangleUV(new Vector2(0.5f, 0.4f), new Vector2(1f, 0.2f), new Vector2(0f, 0.2f), ref uvBuffer);
                            }
                            else
                            {
                                AddTriangleUV(new Vector2(0.5f, 0.4f), new Vector2(0f, 0.6f), new Vector2(1f, 0.6f), ref uvBuffer);
                            }
                        }
                        else
                        {
                            //TriangulateWithRiver(direction, directions[prev], directions[next], currCellColor, currCellCenter, e, ref colorBuffer, ref vertexBuffer, oppositeHasRiverThroughEdge);
                            Vector3 centerL, centerR;
                            //获取当前方向的相反方向,并判断是否有河流经过
                            if (HasRiverThroughEdge(river, directionIndex[OppositeDirection(j)]))
                            {
                                centerL = currCellCenter + HexMetrics.GetFirstSolidCorner(prev) * 0.25f;
                                centerR = currCellCenter + HexMetrics.GetSecondSolidCorner(next) * 0.25f;
                            }
                            else if (HasRiverThroughEdge(river, directionIndex[next]))
                            {
                                centerL = currCellCenter;
                                centerR = Vector3.Lerp(currCellCenter, e.v5, 2f / 3f);
                            }
                            else if (HasRiverThroughEdge(river, directionIndex[prev]))
                            {
                                centerL = Vector3.Lerp(currCellCenter, e.v1, 2f / 3f);
                                centerR = currCellCenter;
                            }
                            else if (HasRiverThroughEdge(river, directionIndex[next2]))
                            {
                                centerL = currCellCenter;
                                centerR = currCellCenter + HexMetrics.GetSolidEdgeMiddle(next) * (0.5f * HexMetrics.innerToOuter);
                            }
                            else
                            {
                                centerL = currCellCenter + HexMetrics.GetSolidEdgeMiddle(prev) * (0.5f * HexMetrics.innerToOuter);
                                centerR = currCellCenter;
                            }

                            Vector3      center = Vector3.Lerp(centerL, centerR, 0.5f);
                            EdgeVertices m      = new EdgeVertices(Vector3.Lerp(centerL, e.v1, 0.5f), Vector3.Lerp(centerR, e.v5, 0.5f), 1f / 6f);
                            m.v3.y = center.y = e.v3.y;
                            TriangulateEdgeStrip(m, currCellColor, e, currCellColor, ref colorBuffer, ref vertexBuffer);
                            AddTriangle(centerL, currCellColor, m.v1, currCellColor, m.v2, currCellColor, ref colorBuffer, ref vertexBuffer);
                            AddQuad(centerL, currCellColor, center, currCellColor, m.v2, currCellColor, m.v3, currCellColor, ref colorBuffer, ref vertexBuffer);
                            AddQuad(center, currCellColor, centerR, currCellColor, m.v3, currCellColor, m.v4, currCellColor, ref colorBuffer, ref vertexBuffer);
                            AddTriangle(centerR, currCellColor, m.v4, currCellColor, m.v5, currCellColor, ref colorBuffer, ref vertexBuffer);
                            bool reversed = river.IncomingRiver == directionIndex[j];
                            TriangulateRiverQuad(centerL, centerR, m.v2, m.v4, RiverSurfaceY, RiverSurfaceY, 0.4f, ref uvBuffer, ref riverBuffers, reversed);
                            TriangulateRiverQuad(m.v2, m.v4, e.v2, e.v4, RiverSurfaceY, RiverSurfaceY, 0.6f, ref uvBuffer, ref riverBuffers, reversed);
                        }
                    }
                    else
                    {
                        Vector3 center = currCellCenter;
                        if (HasRiverThroughEdge(river, directionIndex[next]))
                        {
                            if (HasRiverThroughEdge(river, directionIndex[prev]))
                            {
                                center += HexMetrics.GetSolidEdgeMiddle(j) * (HexMetrics.innerToOuter * 0.5f);
                            }
                            else if (HasRiverThroughEdge(river, directionIndex[prev2]))
                            {
                                center += HexMetrics.GetFirstSolidCorner(j) * 0.25f;
                            }
                        }
                        else if (HasRiverThroughEdge(river, directionIndex[prev]) && HasRiverThroughEdge(river, directionIndex[next2]))
                        {
                            center += HexMetrics.GetSecondSolidCorner(j) * 0.25f;
                        }
                        EdgeVertices m = new EdgeVertices(
                            Vector3.Lerp(center, e.v1, 0.5f),
                            Vector3.Lerp(center, e.v5, 0.5f)
                            );

                        TriangulateEdgeStrip(m, currCellColor, e, currCellColor, ref colorBuffer, ref vertexBuffer);
                        TriangulateEdgeFan(center, m, currCellColor, ref colorBuffer, ref vertexBuffer);
                    }
                }
                else
                {
                    TriangulateEdgeFan(currCellCenter, e, currCellColor, ref colorBuffer, ref vertexBuffer);
                }
                //Connection Between 2 cells
                #region  Bridge=桥
                //桥只连接前三个方向相邻的单元,从而避免重复连接
                if (j <= 2)
                {
                    if (directionIndex[j] == int.MinValue)
                    {//如果没有相邻的单元,则跳过循环
                        continue;
                    }

                    //添加外围桥接区域的顶点
                    Vector3 bridge = (HexMetrics.GetBridge(j));

                    bridge.y = (elevations[j] - elevation) * HexMetrics.elevationStep;
                    EdgeVertices e2 = new EdgeVertices(e.v1 + bridge, e.v5 + bridge);
                    if (hasRiverThroughEdge)
                    {
                        float neighborRiverSurfaceY = (elevations[j] + HexMetrics.riverSurfaceElevationOffset) * HexMetrics.elevationStep;
                        e2.v3.y = (elevations[j] + HexMetrics.streamBedElevationOffset) * HexMetrics.elevationStep;
                        TriangulateRiverQuad(e.v2, e.v4, e2.v2, e2.v4, RiverSurfaceY, neighborRiverSurfaceY, 0.8f, ref uvBuffer, ref riverBuffers, river.HasIncomingRiver && river.IncomingRiver == directionIndex[j]);
                    }
                    #region 桥面
                    //判断当前单元与相邻单元的海拔高低差,如果是斜坡,则添加阶梯,平面和峭壁则无需阶梯
                    if (HexMetrics.GetEdgeType(elevation, elevations[j]) == HexMetrics.HexEdgeType.Slope)
                    {
                        TriangulateEdgeTerraces(e, e2, currCellColor, blendColors[j], ref colorBuffer, ref vertexBuffer);
                    }
                    else
                    {
                        Color bridgeColor = (currCellColor + blendColors[j]) * 0.5f;
                        TriangulateEdgeStrip(e, currCellColor, e2, blendColors[j], ref colorBuffer, ref vertexBuffer);
                    }

                    #endregion

                    #region 桥洞

                    //添加外圈区域三向颜色混合

                    if (j <= 1 && directionIndex[next] != int.MinValue)
                    {
                        //下一个相邻单元的海拔
                        int     nextElevation = elevations[next];
                        Vector3 vertex5       = e.v5 + HexMetrics.GetBridge(next);
                        vertex5.y = nextElevation * HexMetrics.elevationStep;
                        //判断相邻的三个六边形单元的高低关系,按照最低(Bottom),左(Left),右(Right)的顺序进行三角化处理
                        if (elevation <= elevations[j])
                        {
                            if (elevation <= nextElevation)
                            {
                                //当前单元海拔最低
                                TriangulateCorner(e.v5, currCellColor, e2.v5, blendColors[j], vertex5, blendColors[next], ref colorBuffer, ref vertexBuffer, elevation, elevations[j], nextElevation);
                            }
                            else
                            {
                                TriangulateCorner(vertex5, blendColors[next], e.v5, currCellColor, e2.v5, blendColors[j], ref colorBuffer, ref vertexBuffer, nextElevation, elevation, elevations[j]);
                            }
                        }
                        else if (elevations[j] <= nextElevation)
                        {
                            TriangulateCorner(e2.v5, blendColors[j], vertex5, blendColors[next], e.v5, currCellColor, ref colorBuffer, ref vertexBuffer, elevations[j], nextElevation, elevation);
                        }
                        else
                        {
                            TriangulateCorner(vertex5, blendColors[next], e.v5, currCellColor, e2.v5, blendColors[j], ref colorBuffer, ref vertexBuffer, nextElevation, elevation, elevations[j]);
                        }
                    }

                    #endregion
                }

                #endregion
            }
            //4.turn off cell system by remove NewDataTag
            CommandBuffer.RemoveComponent <NewDataTag>(index, entity);
        }
Ejemplo n.º 9
0
 public HexEdgeType GetEdgeType(HexObject other)
 {
     return(HexMetrics.GetEdgeType(Elevation, other.Elevation));
 }
Ejemplo n.º 10
0
    public static Corner Build(HexCell begin, HexCell left, HexCell right, HexDirection leftDirection)
    {
        Vector3 beginCorner = begin.Position + HexMetrics.GetSecondSolidCorner(leftDirection);
        Vector3 leftCorner  = left.Position + HexMetrics.GetFirstSolidCorner(leftDirection.Opposite());
        Vector3 rightCorner = right.Position + HexMetrics.GetSecondSolidCorner(leftDirection.Previous2());

        HexEdgeType leftEdgeType  = HexMetrics.GetEdgeType(begin.Elevation, left.Elevation);
        HexEdgeType rightEdgeType = HexMetrics.GetEdgeType(begin.Elevation, right.Elevation);
        HexEdgeType endEdgeType   = HexMetrics.GetEdgeType(left.Elevation, right.Elevation);

        Corner corner;

        if (leftEdgeType == HexEdgeType.Slope)
        {
            if (rightEdgeType == HexEdgeType.Slope)
            {
                corner = new TerracesCorner(
                    beginCorner, leftCorner, rightCorner,
                    begin, left, right
                    );
            }
            else if (rightEdgeType == HexEdgeType.Flat)
            {
                corner = new TerracesCorner(
                    leftCorner, rightCorner, beginCorner,
                    left, right, begin
                    );
            }
            else
            {
                corner = new TerraceCliffCorner(
                    beginCorner, leftCorner, rightCorner,
                    begin, left, right
                    );
            }
        }
        else if (rightEdgeType == HexEdgeType.Slope)
        {
            if (leftEdgeType == HexEdgeType.Flat)
            {
                corner = new TerracesCorner(
                    rightCorner, beginCorner, leftCorner,
                    right, begin, left
                    );
            }
            else
            {
                corner = new CliffTerraceCorner(
                    beginCorner, leftCorner, rightCorner,
                    begin, left, right
                    );
            }
        }
        else if (endEdgeType == HexEdgeType.Slope)
        {
            if (left.Elevation < right.Elevation)
            {
                corner = new CliffTerraceCorner(
                    rightCorner, beginCorner, leftCorner,
                    right, begin, left
                    );
            }
            else
            {
                corner = new TerraceCliffCorner(
                    leftCorner, rightCorner, beginCorner,
                    left, right, begin
                    );
            }
        }
        else
        {
            corner = new FlatCorner(
                beginCorner, leftCorner, rightCorner,
                begin, left, right
                );
        }

        return(corner);
    }
Ejemplo n.º 11
0
 public HexEdgeType GetEdgeType(HexDirection direction)//узнать тип угла в направлении
 {
     return(HexMetrics.GetEdgeType(elevation, neighbors[(int)direction].elevation));
 }
 public void GetEdgeTypeSlopeTest2()
 {
     Assert.AreEqual(HexEdgeType.Slope, HexMetrics.GetEdgeType(5, 4));
 }
 public void GetEdgeTypeCliffTest2()
 {
     Assert.AreEqual(HexEdgeType.Cliff, HexMetrics.GetEdgeType(5, 2));
 }
 public void GetEdgeTypeFlatTest()
 {
     Assert.AreEqual(HexEdgeType.Flat, HexMetrics.GetEdgeType(3, 3));
 }
Ejemplo n.º 15
0
 public HexEdgeType GetEdgeType(HexDirection dirction)
 {
     return(HexMetrics.GetEdgeType(elevation, GetNeighbor(dirction).elevation));
 }
Ejemplo n.º 16
0
 public HexEdgeType GetEdgeType(HexCell thatCell)
 {
     return(HexMetrics.GetEdgeType(elevation, thatCell.elevation));
 }
Ejemplo n.º 17
0
 public HexEdgeType GetEdgeType(HexDirection dir)
 {
     return(HexMetrics.GetEdgeType(Elevation, m_neighbours[(int)dir].Elevation));
 }
Ejemplo n.º 18
0
 public HexEdgeType GetEdgeType(HexCell otherCell)//узнать тип угла относительно двух ячеек
 {
     return(HexMetrics.GetEdgeType(elevation, otherCell.elevation));
 }
Ejemplo n.º 19
0
 public HexEdgeType GetEdgeType(HexCell otherCell)
 {
     return(HexMetrics.GetEdgeType(Elevation, otherCell.Elevation));
 }
 /// <summary>
 /// Returns the edge connection type with the neighboring cell at the given direction.
 /// </summary>
 public HexEdgeType GetEdgeType(HexDirection direction)
 {
     // ! If on the edge of the map this can throw NullReferenceException
     return(HexMetrics.GetEdgeType(elevation, Neighbors[(int)direction].Elevation));
 }