iT邦幫忙

2023 iThome 鐵人賽

DAY 20
0
Mobile Development

Google Maps SDK for Android 與 GIS App 開發筆記系列 第 20

Day 20: Maps SDK for Android Utility–GeoJSON 套疊

  • 分享至 

  • xImage
  •  

資料格式

GeoJSON 是基於 JSON 格式的地理空間資料格式。可用來表示點 (Point)、線(LineString)、多邊形(Polygon)、多個點(MultiPoint)、多個線段(MultiLineString)、多個多邊形(MultiPolygon)。

基本型態大概會長得像下面這個範例一樣:

{
    "type": "FeatureCollection",
    "features": [
        {
            "type": "Feature",
            "geometry": {
                "type": "Point",
                "coordinates": [102.0,0.5]
            },
            "properties": {
                "prop0": "value0"
            }
        },
        {
            "type": "Feature",
            "geometry": {
                "type": "LineString",
                "coordinates": [
                    [102.0, 0.0],
                    [103.0, 1.0],
                    [104.0, 0.0],
                    [105.0, 1.0]
                ]
            },
            "properties": {
                "prop0": "value0",
                "prop1": 0.0
            }
        },
        {
            "type": "Feature",
            "geometry": {
                "type": "Polygon",
                "coordinates": [
                    [
                        [100.0, 0.0],
                        [101.0, 0.0],
                        [101.0, 1.0],
                        [100.0, 1.0],
                        [100.0, 0.0]
                    ]
                ]
            },
            "properties": {
                "prop0": "value0",
                "prop1": {
                    "this": "that"
                }
            }
        }
    ]
}

最外層會是 FeatureCollection,其中的 features 則包裹著不同型態的 Feature

Feature 中除了有基本的 geometry 負責帶有幾何形狀的空間資訊外,還包含可自定義的 properties

一個 geometry 一定會有以下這兩個屬性參數:

  • type: 說明經緯度所代表的幾何圖形 (點、線、面)。
    • PointLineStringPolygon
    • MultiPointMultiLineStringMultiPolygon
  • coordinates: 經緯度座標。

實際套疊

範例參考自 OXXO Studio: Google Maps API - 顯示台灣縣市 ( GeoJSON )

練習用資料:台灣縣市行政區域邊界圖

接下來我們將使用 g0v/twgeojson 的 twCounty2010.geo.json這份檔案,實際操作一次 GeoJSON 的套疊。

https://ithelp.ithome.com.tw/upload/images/20231004/20160271MrRMX7a5S8.png

從檔案裡可以看到,每個 feature 都帶有縣市名稱的 propertygeometry 中也有寫出它所提供的空間資料屬於 MultiPolygon

Dependency 引用

可以參考 Day 19: Maps SDK for Android Utility Library 介紹與環境建置

讀入 GeoJSON 資料,建立 GeoJsonLayer

讀入 GeoJSON 資料以建立 GeoJsonLayer 的方式可分為兩種:

1. 不限來源,只要能將資料轉為 JSONObject 物件。

val geoJsonData: JSONObject? = // 看你的來源是什麼,只要可以轉 JSONObject 就可以了
    
// 傳入 GoogleMap 物件 與 GeoJSON 資料 建立
val layer = GeoJsonLayer(map, geoJsonData)

2. 本地 raw 資料夾中的檔案,可以直接透過建構式加入。

// 傳入 GoogleMap 物件 與 GeoJSON 檔案的 resId 與 Context 建立
val layer = GeoJsonLayer(map, R.raw.geojson_file, context)

如果是在 assets 資料夾怎麼做?

概念上可以使用方法一。

將放置在 assets 資料夾的檔案讀取成 String 再轉成 JSONObject 傳遞給 GeoJsonLayer

val jsonString = resources.assets.open("twCounty2010.geo.json").bufferedReader().use { it.readText() }

val geoJson = JSONObject(jsonString)
val geoJsonLayer = GeoJsonLayer(map, geoJson)

GeoJsonLayer 加到地圖上

這裡的方法跟之前的幾何圖形繪製不太一樣,是呼叫 GeoJsonLayeraddLayerToMap() 來實現加入到地圖。

geoJsonLayer.addLayerToMap()

https://ithelp.ithome.com.tw/upload/images/20231004/20160271u3K2Oc8KvL.png

移除地圖上的 GeoJsonLayer

很簡單,呼叫 GeoJsonLayerremoveLayerFromMap() 就可以了。

geoJsonLayer.removeLayerFromMap()

新增或移除 GeoJsonFeature

GeoJSON 中的 feature 也可以透過程式另外加入或移除,方法如下:

建立

  1. 建立要加入的點、線或面 (GeoJsonPoint, GeoJsonLineString, GeoJsonPolygon 等)
  2. 建立要加入的 properties (HashMap)。
  3. 將前述兩個物件加入至 GeoJsonFeature 的建構式。id 可以視需求命名。
  4. 將建立好的 GeoJsonFeature 加入到已建立的 GeoJsonLayer
private fun addGeoJsonPointToLayer() {
    // 台中中央公園
    val centralPark = LatLng(24.1858, 120.6533)
    // 建立 GeoJsonPoint
    val point = GeoJsonPoint(centralPark)
    // 建立 GeoJson 的 Property
    val properties = hashMapOf("title" to "Taichung Central Park")
    // 建立 Feature
    val pointFeature = GeoJsonFeature(point, "test", properties, null)
    // 加入到 GeoJson 圖層
    geoJsonLayer?.addFeature(pointFeature)
}

https://ithelp.ithome.com.tw/upload/images/20231004/20160271usxwU19HjA.png

移除

如果要移除該 GeoJsonFeature,可以呼叫以下程式碼:

geoJsonLayer.removeFeature(pointFeature)

存取 GeoJsonLayer 上的 GeoFeature

要存取已建立的 GeoJsonLayer 中的 GeoFeature 們,可以使用以下方法:

for (feature in layer.features) {
    // TODO
}

存取 GeoFeature 下的 Property

// 檢查是否有該 Property
if (feature.hasProperty("title")) {
    // 存取其 Property
    val titleProperty = feature.getProperty("title")
}

點擊事件

GeoJsonLayer 的點擊事件可透過 GeoJsonLayer.OnFeatureClickListener() 來取得,每個 Feature 被點擊時的事件回呼

private fun addFeatureClickListener() {
    geoJsonLayer?.setOnFeatureClickListener {feature ->
        if (feature.hasProperty("title")) {
            val title = feature.getProperty("title")
            Toast.makeText(this, title, Toast.LENGTH_SHORT).show()
        }
    }
}

外觀樣式調整

外觀樣式的調整,可以針對整個 GeoJsonLayer 或是個別的 GeoJsonFeature

針對整個 GeoJsonLayer

針對整個 GeoJsonLayer,我們可以設定點、線、面的預設外觀樣式。

// 點預設樣式
geoJsonLayer?.defaultPointStyle
// 線預設樣式
geoJsonLayer?.defaultLineStringStyle
// 面預設樣式
geoJsonLayer?.defaultPolygonStyle

透過上述的三種方法,就可以個別取得三種類型的預設樣式。

假設我們要設定該 GeoJsonLayer 的點預設樣式,可以這樣寫。

val pointStyle = layer.defaultPointStyle
// 設定為可拖曳
pointStyle.isDraggable = true
// 預設標題
pointStyle.title = "Hello, World!"
// 預設說明文字
pointStyle.snippet = "I am a draggable marker"

針對單一 GeoJsonFeature

概念上跟針對圖層的調整一樣,只是將 ****Syle 物件設定到指定的物件上。

以前面加入的台中中央公園 Point 來說,我們可以將它的外觀設定為綠色,並顯示標題。

private fun addGeoJsonPointToLayer() {
    val centralPark = LatLng(24.1858, 120.6533)
    val point = GeoJsonPoint(centralPark)
    val properties = hashMapOf("title" to "Taichung Central Park")
    val pointFeature = GeoJsonFeature(point, "test", properties, null)
    
    // 自定義的樣式
    val pointStyle = GeoJsonPointStyle()
    // 改 Icon
    pointStyle.icon = BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN)
    // 標題設為台中中央公園
    pointStyle.title = "台中中央公園"
    // 將修改完的樣式傳入
    pointFeature.pointStyle = pointStyle
    
    geoJsonLayer?.addFeature(pointFeature)
}

https://ithelp.ithome.com.tw/upload/images/20231004/20160271ghBX5Zwrrb.png

參考資料

小結

以上就是 Google Maps SDK for Android 套疊 GeoJSON 資料的基本介紹,對於文章中的內容有任何問題,歡迎留言討論指教,謝謝大家~

明天見!!/images/emoticon/emoticon12.gif


上一篇
Day 19: Maps SDK for Android Utility Library 介紹與環境建置
下一篇
Day 21: Maps SDK for Android Utility–KML 套疊
系列文
Google Maps SDK for Android 與 GIS App 開發筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言