> ## Content Index
> Fetch the complete content index at: https://blog.anthea.day/llms.txt
> Use this file to discover other available public pages before exploring further.

# 歡迎來到 GIS 的世界－ Day 26：旅遊規劃小專案用縣市找景點
- URL: https://blog.anthea.day/series-2022-ithome-26/
- Published: 2022-10-09T16:13:06.000Z
- Updated: 2026-11-06T19:47:27.000Z
- Author: Anthea / 芫荽
- Tags: #Migrated-1792241843742, #Import 2026-10-17 12:57, Coding, 2022 iThome 鐵人賽：歡迎來到 GIS 的世界

有關縣市找景點的完整功能描述如下：

> \- 身為一個使用者，我可以點擊地圖上的查詢按鈕，選擇縣市之後找到該縣市的景點。  
> \- 身為一個使用者，查詢縣市景點之後，地圖上只會呈現該縣市的景點。

從後端的角度來看，第一點是我們要做到的事情，所以首先，我們來檢視一下資料庫裡有沒有儲存到相關的縣市資訊：

![](https://cdn-images-1.medium.com/max/800/0*lX9PSS5dyJXwr_tS.png)

這是我們在前幾天寫出來的 API，直接撈取資料庫的所有資料然後回傳 — — 看起來除了 XY 座標和 `address` 之外，我們沒有任何和縣市有關的資訊。假設今天我們不只要做縣市，還需要細分到鄉鎮市區的時候，純文字、沒有固定格式的 `address`，要如何特別找到綠島鄉呢?

因此，我們要從資料庫裏面的 Geometry 著手，利用縣市的範圍找到交集，決定哪些景點在使用者選取的縣市內。

#### 縣市界線

這個時候，政府資料開放平台就派上用場了。裡面由國土測繪中心所提供的[直轄市、縣市界線](https://data.gov.tw/dataset/7442?ref=blog.anthea.day)是一個很好用的素材，可以讓我們藉由讀取檔案，找到縣市的 Geometry，接著再利用 NetTopologySuite 去針對我們資料庫裡的資料作處理。

在使用之前要注意：我們的資料所儲存的座標系統是 4326，國土測繪中心所提供的是 以 TWD97 為基準的 Shapefile，所以要先使用 QGIS Export Feature As 的功能，匯出成 4326 再繼續使用喔。

### API

步驟很簡單，讀取縣市界線的 Shapefile，找到的話就和景點的清單做比較，如果景點在這個縣市裡（Within），就撈出來：

```C#
/// <summary> 縣市裡的景點清單 </summary>
/// <param name="county">縣市代碼</param>
[HttpGet("{county}")]
public IActionResult ScenicSpotInCounty(string county)
{
    // 建立一個空的 Geometry
    Geometry? countyGeometry = null;
    
    // 讀取 Shapefile
    foreach (var feature in Shapefile.ReadAllFeatures(@"C:\Users\user\Downloads\mapdata202209220943\COUNTY_MOI_1090820_4326.shp"))
    {
        // 如果 COUNTYID 的欄位等於傳入的縣市代碼則記錄下這筆 Geometry
        if (feature.Attributes["COUNTYID"].ToString() == county)
        {
            countyGeometry = feature.Geometry;
            break;
        }
    }
    
    // 處理找不到縣市代碼的情況
    if (countyGeometry == null) throw new KeyNotFoundException($"找不到代碼為 {county} 的縣市");
    
    var data = _db.ScenicSpots
        .Where(s => s.Geom.Within(countyGeometry))
        .Select(s => new ScenicSpotInfo()
        {
            Id = s.Id,
            Name = s.Name,
            Telephone = s.Telephone ?? "",
            Address = s.Address ?? "",
            X = s.Geom.Centroid.X,
            Y = s.Geom.Centroid.Y,
            Type = s.Type ?? "未分類",
            Park = s.Park ?? "",
            Info = s.Info ?? "暫無詳細資訊",
            UpdateTime = s.UpdateTime
        }).ToList();
    
    return Ok(data);
}
```

如果比較喜歡使用 Contains 的話，請記得把第 24 行修改一下喔：

```
.Where(s => countyGeometry.Contains(s.Geom))
```

#### Reference

- [政府資料開放平台 — 直轄市、縣市界線(TWD97經緯度)](https://data.gov.tw/dataset/7442?ref=blog.anthea.day)