1. 程式人生 > >GMap.net開發升級日誌20150822-20170511

GMap.net開發升級日誌20150822-20170511

2015.8.22 1.更新了谷歌地球衛星地圖的路徑,可以訪問高清衛星地圖了。更新後,必須重新生成下GMap.NET.Core才能有效果 2.關於如何獲取谷歌地圖和其它地圖的地圖路徑: 點選Chrome瀏覽器的選單(位址列右側,圖示是三個橫線的)按鈕,選擇:工具 -> 開發者工具,如下所示: 在開發者工具中,切換到Network(網路請求)頁,此時工具會列出所有發生了的網路請求,請隨便放縮一下地圖,您會看到產生了很多新請求,標準的地圖圖片請求都是256x256大小的標準圖片,選擇其中的任意一個地圖圖片請求,右側Preview就會列出該圖片的網址和預覽圖。(注意:如果請求太多不好找,建議用底部的“Images”過濾功能來只顯示圖片,或者先用清空按鈕清除現有請求,再縮放下地圖刷新出新的圖片)。 監測到的Google地圖的圖片請求如下所示:

2015.10.30 1.谷歌衛星地圖連結:http://www.google.cn/maps/[email protected]&gl=cn&x={5}&y={7}&z={8} 2016.1.24 1.償試了對快取路徑的更改,把SQlitePureImageCache的快取的internal更改為public,從而可以單獨建立快取,測試成功 2.在MainForm中建立了SQlite的快取檔案,更改了快取的資料庫,然後把primate主快取改為現有路徑,測試成功。 3.編寫了一個搜尋指定檔案路徑下的全部png的檔案的模組,然後根據搜尋到的路徑來解析到縮放層級和X\Y編號,注意,因為陝西客戶提供的切圖的原點與GMAP.NET中的原點不一樣,因些要找到所有當前層級的Y方向的瓦片數量,然後再減去從路徑中解析到的Y編號再減1,這樣得到正常的X\Y值。然後再把批量匯入SQlite資料庫中,這樣便可以進行動態載入和瀏覽了!

2016.1.26 1.進展非常的順利,成功添加了百度、高德和谷歌混合地圖等,GIS資料方面非常的豐富。 2.關於地圖瓦片圖層方面,找到一篇非常強大的文章:http://www.360doc.com/content/14/0916/18/7931690_409974860.shtml 文章描述了地圖體系結構和各種地圖的瓦片連結計算公式,還提供了相應的瓦片路徑。但在新增百度地圖時發現,百度地圖能顯示,但瓦片是混亂的,估計是瓦片的索引方式不一樣的原因。於是在網上搜索百度瓦片,又搜尋到一篇非常好的文件,提供瞭如何在GMAP.NET中新增的程式碼類。我試著匯入GMAP.NET,非常成功。 3.以下為百度地圖的類程式碼,其中MakeTileImageUrl的程式碼和谷歌地圖的不太一樣,路徑格式也有些不一樣。using System; using

GMap.NET; using GMap.NET.MapProviders; using GMap.NET.Projections;

namespace GMap.NET.MapProviders { public abstract class BaiduMapProviderBase : GMapProvider { public BaiduMapProviderBase() { MaxZoom = null; RefererUrl = “http://map.baidu.com”; Copyright = string.Format("?{0} Baidu Corporation, ?{0} NAVTEQ, ?{0} Image courtesy of NASA", DateTime.Today.Year); }

    public override PureProjection Projection
    {
        get { return MercatorProjection.Instance; }
    }

    GMapProvider[] overlays;
    public override GMapProvider[] Overlays
    {
        get
        {
            if (overlays == null)
            {
                overlays = new GMapProvider[] { this };
            }
            return overlays;
        }
    }
}
public class BaiduMapProvider : BaiduMapProviderBase
{
    public static readonly BaiduMapProvider Instance;

    readonly Guid id = new Guid("EF3DD303-3F74-4938-BF40-232D0595EE86");
    public override Guid Id
    {
        get { return id; }
    }

    readonly string name = "百度交通地圖";
    public override string Name
    {
        get
        {
            return name;
        }
    }

    static BaiduMapProvider()
    {
        Instance = new BaiduMapProvider();
    }

    public override PureImage GetTileImage(GPoint pos, int zoom)
    {
        string url = MakeTileImageUrl(pos, zoom, LanguageStr);

        return GetTileImageUsingHttp(url);
    }

    string MakeTileImageUrl(GPoint pos, int zoom, string language)
    {
        zoom = zoom - 1;
        var offsetX = Math.Pow(2, zoom);
        var offsetY = offsetX - 1;

        var numX = pos.X - offsetX;
        var numY = -pos.Y + offsetY;

        zoom = zoom + 1;
        var num = (pos.X + pos.Y)%8 + 1;
        var x = numX.ToString().Replace("-", "M");
        var y = numY.ToString().Replace("-", "M");

        //http://q3.baidu.com/it/u=x=721;y=209;z=12;v=014;type=web&fm=44
        string url = string.Format(UrlFormat, num, x, y, zoom, "014", "web", "44");
        Console.WriteLine("url:" + url);
        return url;
    }
    //static readonly string UrlFormat = "http://shangetu1.map.bdimg.com/it/u=x={1};y={2};z={3};v=009;type=sate&fm=46&udt=20130506";
    //以下為百度的衛星地圖連結
    //http://shangetu1.map.bdimg.com/it/u=x=101237;y=37702;z=19;v=009;type=sate&fm=46&udt=20130506
    //百度交通地圖
   // http://online1.map.bdimg.com/onlinelabel/?qt=tile&x=1562&y=359&z=13&styles=pl&udt=20160204&scaler=1&p=1
    static readonly string UrlFormat = "http://online1.map.bdimg.com/onlinelabel/?qt=tile&x={1}&y={2}&z={3}&styles=pl&udt=20160204&scaler=1&p=1";
    //執行後需要往左側縮放才能看到地圖
    //static readonly string UrlFormat = "http://q{0}.baidu.com/it/u=x={1};y={2};z={3};v={4};type={5}&fm={6}";
    
}
public class BaiduSitellteMapProvider : BaiduMapProviderBase
{
    public static readonly BaiduSitellteMapProvider Instance;

    readonly Guid id = new Guid("EF3DD303-3F74-4938-BF40-232D0595EE85");
    public override Guid Id
    {
        get { return id; }
    }

    readonly string name = "百度衛星地圖";
    public override string Name
    {
        get
        {
            return name;
        }
    }

    static BaiduSitellteMapProvider()
    {
        Instance = new BaiduSitellteMapProvider();
    }

    public override PureImage GetTileImage(GPoint pos, int zoom)
    {
        string url = MakeTileImageUrl(pos, zoom, LanguageStr);

        return GetTileImageUsingHttp(url);
    }

    string MakeTileImageUrl(GPoint pos, int zoom, string language)
    {
        zoom = zoom - 1;
        var offsetX = Math.Pow(2, zoom);
        var offsetY = offsetX - 1;

        var numX = pos.X - offsetX;
        var numY = -pos.Y + offsetY;

        zoom = zoom + 1;
        var num = (pos.X + pos.Y) % 8 + 1;
        var x = numX.ToString().Replace("-", "M");
        var y = numY.ToString().Replace("-", "M");

        //http://q3.baidu.com/it/u=x=721;y=209;z=12;v=014;type=web&fm=44
        string url = string.Format(UrlFormat, num, x, y, zoom, "014", "web", "44");
        Console.WriteLine("url:" + url);
        return url;
    }
    static readonly string UrlFormat = "http://shangetu1.map.bdimg.com/it/u=x={1};y={2};z={3};v=009;type=sate&fm=46&udt=20130506";
    //以下為百度的衛星地圖連結
    //http://shangetu1.map.bdimg.com/it/u=x=101237;y=37702;z=19;v=009;type=sate&fm=46&udt=20130506
    //百度交通地圖
    // http://online1.map.bdimg.com/onlinelabel/?qt=tile&x=1562&y=359&z=13&styles=pl&udt=20160204&scaler=1&p=1
    //static readonly string UrlFormat = "http://online1.map.bdimg.com/onlinelabel/?qt=tile&x={1}&y={2}&z={3}&styles=pl&udt=20160204&scaler=1&p=1";
    //執行後需要往左側縮放才能看到地圖
    //static readonly string UrlFormat = "http://q{0}.baidu.com/it/u=x={1};y={2};z={3};v={4};type={5}&fm={6}";

}

}

2016.3.14 1.添加了搜狗和搜搜地圖

2016.3.20 1.因為蘋果電腦只有C盤,因此這個核心控制元件中加入了把瓦片地圖匯入E盤的功能,導致在蘋果電腦中無法執行,然後把這個核心控制元件的這行程式碼遮蔽了。

2016.3.24 1.調整了地圖的顯示次序,因為百度地圖偏移比較大,因此調整到後面去,把幾種常見的地圖調整到前面。

2016.3.28 1.經過測試,發現疊加瓦片地圖時,谷歌地圖可以看到20層以後的資料,而bing map確只有到19層,現在正在解決這個問題。已經解決了這個問題,原來只要在畫圖函式中的另一個分支判斷中加入畫切片圖的功能就可以了。

2.GMap.NET.Core.dll和GMap.NET.WindowsForms.dll每次重新生成後都要手動D:\VS2010原始碼\51CTO下載-greatmaps2016.3.28修改\greatmaps\GMap.NET.WindowsForms\bin\Debug拷過去,這點有些不方便。 3.添加了直接讀取資料夾匯入瓦片的功能,這樣就不用資料庫了。 4.其實不用把png的白色底色剔除,只要把底圖畫出,現在上面畫自己的切片圖層就可以了,這樣白邊的問題也解決了!

2016.4.15 1.發現一款非常強大的切圖工具,在網上下載了好幾個切圖的,如map tile\dstile等,都不好使用,發現http://www.cnblogs.com/xwgli/archive/2013/04/27/3046166.html這篇文章裡有個關鍵資訊,下載到 http://research.microsoft.com/en-us/um/redmond/projects/mapcruncher/ 這裡下載MapCruncher,然後用了下,非常好,可以實現切圖,不過有些卡。切出來的切片有點不一樣,經過研究發現,原來它是用QuadTileKey來表示的。參考:http://beniao.blog.51cto.com/389148/291726 2.然後修改了核心類,實現了這種瓦片格式的讀取,把x\y\z轉換為quadkey就可以了。

2016.4.27 1.經過測試又發現了一個問題,當完全沒有網路時,軟體沒有快取到任何瓦片地圖的情況下,自定義的高清切片地圖竟然也沒法使用,這是一個比較嚴重的bug,出現的原因已經查明瞭,應該是在判斷底圖是為為空上出了點問題。 2.drawmap下的t是從Matrix中獲取的,t又是從tilepoint中獲取的,當沒有聯網又沒任何快取時為t為空,這樣就導致了無法載入自定義的瓦片。最後換成原始的tilepoint就搞定了,但測試只能顯示到18級地圖,接下來要解決這個bug. 3.經過幾小時的努力,終於解決了這個問題。其實程式碼中有很多空值的判斷,需要搞清這些值的判斷,在什麼地方執行何種程式碼,這樣就清楚了程式碼的執行過程。另外要加強瓦片地圖動態載入演算法的研究,開發出效率更強更高的演算法。

2016.5.25 1.終於通過IIS伺服器釋出區域網的切片地圖,然後在軟體中加入了一個LocalBingMapProvider的類,成功實現了從區域網中讀取切片地圖的功能。 2.研究了geoserver和mapserver,非常強大,但mapserver佔用了80埠,使得IIS伺服器報錯不能啟動,最後把IIS伺服器的埠改為8055,然後本機可以訪問,但手機等區域網其它電腦無法訪問,原來是防火牆的問題,把防火牆設定為對8055埠開放就可以了。【開始】開啟【控制面板】,選擇【WINDOWS 防火牆】,進入在防火牆介面,選擇左側邊欄的【高階設定】在彈出的高階安全Windows防火牆介面中,選擇左側邊欄的【入站規則】,然後在右側邊欄選擇【新建規則】在彈出的視窗中完成如下操作: 選擇【埠】,下一步; 選擇【TCP】以及【特定本地埠】,填入要開放的埠號(或開放所有埠,可以以逗號分隔多個埠),下一步; 【允許連線】,下一步; 網路型別全部勾選,下一步; 【名稱】中填入自定義名稱,如:IIS 【完成】。 http://jingyan.baidu.com/article/335530da89540a19cb41c3cb.html 3.BingMapProvider的 MaxZoom = 21,否則只能訪問到19級圖片。

2016.10.7 1.匯入切片地圖時之前只能匯入單一的切片,再次匯入其它切片時,原有的切片會消失,因此設定了一個可以匯入多個切片的功能,採用陣列的方式匯入,然後在多個切片資料夾下尋找切片圖。因為測試需要多個切片圖,而電腦中一時找不到多個切片集,因此還沒辦法測試。經過後來測試沒有問題。 2.為GMapPolygon類添加了DataRow屬性,這樣匯入到地圖時把對應的access行傳遞到DataRow屬性中。畫點時,當點在多邊形內,就把這個DataRow傳遞給GMapMarkerBS自定義類的DataRow屬性,然後在匯出時就可以匯出小班屬性了,非常強大。面向物件的程式設計就是這麼任性。

2016.10.31 1.又認識一款叫geoWebCache的軟體,可以直接把切片變成WMS服務供Openlayer等呼叫。開始我以為是geoserver裡的一個功能,原來是不同的軟體呢。geoserver也非常的強大,我已經上手了。 2.說好1000元給遼寧的客戶做的程式碼,客戶先給了500,但當錄製好視訊和程式碼發過去時,客戶說太簡單了。可是看看我上面寫的升級日誌,真的有這麼簡單麼。有原始碼,又有視訊解說,當然覺得簡單。看來今後得留一手,不然每次都吃這樣的大虧。 20161225

  1. 從gitub中下載了一個greatmap原始碼,發現裡面竟然有mapcruncher的原始碼。測試了下,可以實現切片的功能。而微軟的官下載已經無法正常下載這個軟體件,或者下載後提示版本過期無法使用。
  2. 但這個原始碼生成的是bingmap格式的jpg檔案,經過堅苦的測試和修改,所它改成了png格式的切片,但仍然無法正常匯入我開發的大奇地圖。原理是有個類沒寫好,使用forlderlist來讀取多個檔案引數過程中,忽略了mapcruncher生成的切片圖,於是又修改了greatemap中的GMapcontrol類的核心程式碼,經過測試可以讀取切片了。這樣我就掌握了從衛圖切片到讀取轉換一條龍的核心技術,非常強大!

2017501 1.實現了載入高德地圖衛星地圖和路網地名疊加的地圖。花費了大概8小時的不間斷時間,晚飯都是吃的泡麵。高德地圖並不像谷歌地圖那樣,提供衛星地圖和路網地名相互疊加的切片,通過網路開發者工具,捕獲到的是衛星地圖的URL和一個亂七八糟的地名小切圖地址,研究了半天,只能解析出衛星地圖和路網的地址,然後實現了衛星地圖和路網的疊加。但是地名確沒有了。然後只能想別的辦法。經過測試,發現 static readonly string UrlFormat = “http://webst04.is.autonavi.com/appmaptile?style=6&x={0}&y={1}&z={2}”;這個地址中的style=6是衛星地圖的地址,style=7和8都是路網的地址,但有些不一樣,7是不透明的背景有些顏色,8是透明的png圖。然後測試了一下,果然能夠疊加。 2.疊加的方法之前在疊加本地無人機拍攝的圖時,修改的是底層的GMapControl類,但這樣擴充套件起來太麻煩了。於是想到修改MapProvider類,然後發現,AMapProvider中有個override的方法,就是獲取 到的地圖資料傳遞給 public override PureImage GetTileImage(GPoint pos, int zoom),於是在這裡面載入了一個把瓦片混合在一起的方法, BlendImage(new Bitmap[] { bottomBitmap }, ref mixBitmap);混合後又有問題,出現無法訪問MemoryStream的緩衝區的錯誤,除錯了半天,幾個小時的堅苦除錯後,發現問題出在這裡:if (ms.Length > 0) { pi = TileImageProxy.FromStream(ms); } MemoryStream responseStream = Stuff.CopyStream(ms, false); MemoryStream 一定要用這個方法來獲取 ,否則就會出現:無法訪問MemoryStream的緩衝區的錯誤。這個方法也是參考了GetTileImageUsingHttp裡的方法,不然還真搞不定!

2017502 1.經過測試還發現一個問題:新的高德混合地圖離線快取不能用,這樣就沒辦法離線使用,因此這個技術難點今天也要突破一下。 2.在高德地圖的provider類中加了一行程式碼,經測試,可以實現地圖的快取顯示了。 Cache.Instance.ImageCache.PutImageToCache(BitmapToBytes(mixBitmap),this.DbId, pos, zoom);這行程式碼是從谷歌地圖GoogleMapProvider中找到的,因為之前測試發現谷歌地圖有快取可以離線,但soso地圖和高德地圖不可以,於是檢視谷歌地圖的程式碼發現了這行程式碼,然後改了下引數,果然有用。不過快取呼叫動態演算法之類的還有待於不斷的探索學習,這樣才能開發出更加靈活的應用。同時,要注意多用面向物件的方法,以便今後擴充套件方便。另外要大膽嘗試,這樣才有更多的經經驗。比如cache類,不太敢用,怕會出錯,之前一直是想著要什麼地方傳遞引數。後來才發現這個類是一個單件類,只要呼叫Cache.Instance就可以用起來。因此程式設計要不斷的總結經驗,理論與實踐相結合才會有更好的解決方法。要多思考為什麼這樣做。

2017511 1.實現了高德地圖的路網與谷歌地球的衛星地圖疊加的功能,非常強大,就是上次混合地圖的基礎上做的,並且是用面向物件的方法實現,避免了修改底層程式碼。 2.實現後在這個電腦上測試不了,因為沒有翻牆,結果兩個地圖都無法顯示。但我把軟體拷到翻牆過後的電腦時,地圖可以顯示了!