基于Uinty3D的真实二维导航地图开发

最近做了一个真实二维导航地图开发,写点心得和总结,希望对刚开始做这方面的童鞋有所启发。

先来看看最终效果,包括在线和离线两种显示:

1)在线模式,必须连接互联网

电子地图

 

卫星地图

 2)离线模式 ,主要是使用本地离线瓦片

电子地图

 卫星地图

3)实现功能和步骤:

a、地图瓦片主要来源于GMap,这个工具挺好用的,能够下载到的瓦片基本都能用,前期准备工作就是使用该工具下载好你想要显示的瓦片层级,并拷将瓦片拷贝到指定的路径下;

b、在GMap目录下找到地图相关的所有动态库.dll,拷贝到你已经创建好的Unity项目中;

c、使用刚刚拷贝的动态库进行编程,绘制瓦片使用底层Graphics.DrawTexture函数;

d、基本脚本写两个就行,一个写界面响应鼠标和按钮,一个用于绘制瓦片和地图刷新;

其中瓦片绘制部分的核心代码分享出来:

    /// <summary>
    /// 绘制地图瓦片
    /// </summary>
    protected virtual void DrawMap()
    {
        // 判断是否更新边界
        if (Core.updatingBounds || MapProvider == EmptyProvider.Instance || MapProvider == null)
        {
            return;
        }
        // 瓦片调用锁
        Core.tileDrawingListLock.AcquireReaderLock();
        Core.Matrix.EnterReadLock();

        try
        {
            //int index = 0;
            // 遍历瓦片绘制的列表 
            foreach (var tilePoint in Core.tileDrawingList)
            {
                Core.tileRect.Location = tilePoint.PosPixel;
                // 设置瓦片偏移(在坐标系中的像素偏移)
                Core.tileRect.OffsetNegative(Core.compensationOffset);
                // 瓦片找到标志
                bool found = false;
                // 根据信息从瓦片缓存区取出瓦片
                Tile t = Core.Matrix.GetTileWithNoLock(Core.Zoom, tilePoint.PosXY);
                // 瓦片不为空
                if (t.NotEmpty)
                {
                    foreach (GMapImage img in t.Overlays)
                    {
                        if (img == null || img.Img == null)
                        {
                            continue;
                        }
                        if (!found)
                            found = true;

                        // 获取纹理
                        Texture2D tileTexture2D = new Texture2D((int)Core.tileRect.Width, (int)Core.tileRect.Height);
                        tileTexture2D.LoadImage(img.Data.ToArray());
                        if (!img.IsParent)
                        {
                            if (!MapRenderTransform.HasValue)
                            {
                                long y = Core.tileRect.Y + Core.renderOffset.Y;
                                // 当瓦片上边缘在initTopMenuHeight以内,下边缘在initTopMenuHeight以外
                                if (y < initTopMenuHeight && (y + Core.tileRect.Height) > initTopMenuHeight)
                                {
                                    // 将要显示区域
                                    Rect showRect = new Rect(0, 0, 1f, Mathf.Abs((y + 256 - initTopMenuHeight) / (float)256));
                                    // 将要显示高度
                                    long showHeight = y + 256 - initTopMenuHeight;
                                    Graphics.DrawTexture(
                                        new Rect(Core.tileRect.X + Core.renderOffset.X, initTopMenuHeight, Core.tileRect.Width, showHeight), // 左上角坐标和宽高
                                        tileTexture2D,
                                        showRect,
                                        0, 0, 0, 0, null);
                                }
                                else if (y >= initTopMenuHeight || (y + Core.tileRect.Height) <= 0)
                                {
                                    Graphics.DrawTexture(new Rect(Core.tileRect.X + Core.renderOffset.X, Core.tileRect.Y + Core.renderOffset.Y, Core.tileRect.Width, Core.tileRect.Height),
                                    tileTexture2D);
                                }
                                else
                                {

                                }
                            }
                        }
                        else
                        {
                            // 将计算移动到加载线程
                            System.Drawing.RectangleF srcRect = new System.Drawing.RectangleF((float)(img.Xoff * (img.Img.Width / img.Ix)), (float)(img.Yoff * (img.Img.Height / img.Ix)), (img.Img.Width / img.Ix), (img.Img.Height / img.Ix));
                            System.Drawing.Rectangle dst = new System.Drawing.Rectangle((int)Core.tileRect.X, (int)Core.tileRect.Y, (int)Core.tileRect.Width, (int)Core.tileRect.Height);
                            Graphics.DrawTexture(new Rect(dst.X, dst.Y, srcRect.Width, srcRect.Height), tileTexture2D);
                        }
                        Destroy(tileTexture2D);
                    }
                }
                // 如果获取的瓦片为空,则使用低版本的替换
                else if (enableLowPixelTiles && MapProvider.Projection is MercatorProjection)
                {
                    int zoomOffset = 1;
                    Tile parentTile = Tile.Empty;
                    long Ix = 0;

                    while (!parentTile.NotEmpty && zoomOffset < Core.Zoom && zoomOffset <= LevelsKeepInMemmory)
                    {
                        Ix = (long)Math.Pow(2, zoomOffset);
                        parentTile = Core.Matrix.GetTileWithNoLock(Core.Zoom - zoomOffset++, new GPoint((int)(tilePoint.PosXY.X / Ix), (int)(tilePoint.PosXY.Y / Ix)));
                    }

                    if (parentTile.NotEmpty)
                    {
                        long Xoff = Math.Abs(tilePoint.PosXY.X - (parentTile.Pos.X * Ix));
                        long Yoff = Math.Abs(tilePoint.PosXY.Y - (parentTile.Pos.Y * Ix));

                        // render tile 
                        {
                            //foreach (GMapImage img in parentTile.Overlays)
                            //{
                            //    if (img != null && img.Img != null && !img.IsParent)
                            //    {
                            //        if (!found)
                            //            found = true;

                            //        System.Drawing.RectangleF srcRect = new System.Drawing.RectangleF((float)(Xoff * (img.Img.Width / Ix)), (float)(Yoff * (img.Img.Height / Ix)), (img.Img.Width / Ix), (img.Img.Height / Ix));
                            //        System.Drawing.Rectangle dst = new System.Drawing.Rectangle((int)Core.tileRect.X, (int)Core.tileRect.Y, (int)Core.tileRect.Width, (int)Core.tileRect.Height);

                            //        g.DrawImage(img.Img, dst, srcRect.X, srcRect.Y, srcRect.Width, srcRect.Height, GraphicsUnit.Pixel, TileFlipXYAttributes);
                            //        g.FillRectangle(SelectedAreaFill, dst);
                            //    }
                            //}
                        }
                    }
                }
                 绘制网格线
                //if (ShowTileGridLines)
                //{
                //    g.DrawRectangle(EmptyTileBorders, (int)Core.tileRect.X, (int)Core.tileRect.Y, (int)Core.tileRect.Width, (int)Core.tileRect.Height);
                //    {
                //        g.DrawString((tilePoint.PosXY == Core.centerTileXYLocation ? "CENTER: " : "TILE: ") + tilePoint, MissingDataFont, Brushes.Red, new RectangleF(Core.tileRect.X, Core.tileRect.Y, Core.tileRect.Width, Core.tileRect.Height), CenterFormat);
                //    }
                //}
            }
        }
        finally
        {
            Core.Matrix.LeaveReadLock();
            Core.tileDrawingListLock.ReleaseReaderLock();
        }
    }

 如果有需要的童鞋可以关注本号,后续我会继续更新三维地形和二维地形的分享^o^!!!!!!!!!。

 

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值