--- title : 使用TGOS服務地址轉座標 tags: TGOS服務、地址轉座標 creat-date: 2022-02-16 update_date : 2022-02-16 --- --- # 使用TGOS服務地址轉座標 --- #### ==說明:透過TGOS服務,將輸入地址轉X、Y座標== #### ==條件:需先申請TGOS服務,取得ID、Key== #### ==注意:TGOS服務有筆數的限制,若處理筆數過多,此服務會被鎖住。== --- ## 一、步驟 地址範例:XX縣/市XX鄉/鎮/市/區XX村/里XX鄰XX路/街XX段XX巷XX弄XX之XX號XX樓 例  如:基隆市信義區東信里11鄰東信路282之45號 ### step1.清除門牌地址內的相關符號及字體半全形轉換 移除符號,例如: 空白符號、斷行符號、大於(>)、小於(<)、之(-)、雙引號(“) 及單引號(‘)等 ### step2.文數字轉換 (1)中文數字轉為阿拉伯數字(如:鄰、弄、號、樓) 、阿拉伯數字轉為中文數字(如:巷) (2) 「 F、f 」轉換為「樓」 (3) 「B、b」轉換為「地下」 ,且數字候補填「樓」 ### step3.自動補填鄰里 依鄉鎮市、路街、號至「TGOS的全國門牌清單查詢服務」,以自動補填鄰、里 ### step4. 保留「號」以後的文字內容 <br/> ## 二、程式內容 ```C#=1 public static void AddressCheck(ref DataSet_ColumnValue dscv, ref DataSet_ColumnValue dscvTown, ref DataSet_ColumnValue dscvX, ref DataSet_ColumnValue dscvY) { string[] sNum = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" }; string[] sSymbol = { "\n\r", "\n", ">", ">", "<", "<", "\"", "'" }; string sValue = dscv.Value.Trim().Replace(" ", ""); sValue = sValue.Replace("台中縣", "臺中市"); sValue = sValue.Replace("臺中縣", "臺中市"); // 字體全形轉換為半形、移除符 for (int k = 0; k <= 7; k++) { if (sValue.Contains(sNum[k])) sValue = sValue.Replace(sNum[k], k.ToString()); sValue = sValue.Replace(sSymbol[k], ""); } // 「B、b、F、f」樓層轉換 sValue = sValue.Replace("f", "樓").Replace("F", "樓"); if (sValue.Contains("b") || sValue.Contains("B")) { int nBIndex = (sValue.Contains("b")) ? sValue.IndexOf("b") : sValue.IndexOf("B"); if (sValue.Length != nBIndex + 1) { if (sValue.Length == nBIndex + 2) sValue += "樓"; else sValue = sValue.Substring(0, nBIndex + 2) + "樓" + sValue.Substring(nBIndex + 2, sValue.Length - (nBIndex + 2)); sValue = (sValue.Contains("b")) ? sValue.Replace("b", "地下") : sValue.Replace("B", "地下"); } } // 地址範例:○○縣/市 ○○鄉/鎮/市/區 ○○村/里 ○○鄰 ○○路/街 ○○段 ○○巷 ○○弄 ○○之 ○○號 ○○樓 string[] sBNumber = { "零", "一", "二", "三", "四", "五", "六", "七", "八", "九" }; string[] sAddrName = { "區", "村", "里", "鄰", "路", "街", "段", "巷", "弄", "號", "樓" }; string sZipCode = "", sFloor = "", sKeyName = "", sNewAddr = "", sTempValue = sValue, sOriTown = "", sOriVillage = ""; if (sTempValue.IndexOf("臺中市") > 0) { sZipCode = sTempValue.Split('臺')[0]; sTempValue = sTempValue.Replace(sZipCode, ""); sNewAddr = "臺中市"; sTempValue = sTempValue.Replace(sNewAddr, ""); } else if (sTempValue.IndexOf("臺中市") == 0) { sNewAddr = "臺中市"; sTempValue = sTempValue.Replace(sNewAddr, ""); } else { sNewAddr = (sTempValue.Length > 0 && sTempValue.IndexOf("市") < 0 && sTempValue.IndexOf("縣") < 0) ? "臺中市" : sNewAddr; } for (int k = 0; k <= 10; k++) { if (sTempValue.IndexOf(sAddrName[k]) > 0) { sKeyName = sTempValue.Split(Convert.ToChar(sAddrName[k]))[0] + sAddrName[k]; sTempValue = sTempValue.Replace(sKeyName, ""); // 判斷「巷」是全阿拉伯數字(bLane = false),還是有包含其他的中文字(bLane = true) bool bLane = false; if (sAddrName[k] == "巷") { int nTotNum = 0; for (int n = 0; n < sKeyName.Length - 1; n++) { string sName = sKeyName.Substring(n, 1); for (int m = 0; m <= 9; m++) { if (sName == sBNumber[m] || sName == m.ToString() || sName == "之") nTotNum++; } } if (nTotNum != sKeyName.Length - 1) bLane = true; } // 中文數字(如: 鄰、巷、弄、號、樓)轉為阿拉伯數字 if (sAddrName[k] == "鄰" || (sAddrName[k] == "巷" && bLane == false) || sAddrName[k] == "弄" || sAddrName[k] == "號" || sAddrName[k] == "樓") { for (int m = 0; m <= 9; m++) { if (sKeyName.Contains(sBNumber[m])) sKeyName = sKeyName.Replace(sBNumber[m], m.ToString()); } sKeyName = sKeyName.Replace("○", "0"); if (sAddrName[k] == "號") sKeyName = sKeyName.Replace("-", "之"); } // 文字中有阿拉伯數字轉國字 if (sAddrName[k] == "街" || sAddrName[k] == "路" || (sAddrName[k] == "巷" && bLane == true)) { bool bCheck = false; int nFirstIndex = 0, nEndIndex = 0; for (int m = 0; m <= 9; m++) { if (sKeyName.Contains(m.ToString())) { // 取得數字的第一個和最後一個位置 nFirstIndex = (bCheck == false) ? sKeyName.IndexOf(m.ToString()) : sKeyName.LastIndexOf(m.ToString()); bCheck = true; } } if (bCheck) { nEndIndex = (nEndIndex == 0) ? nFirstIndex : nEndIndex; if (nEndIndex < nFirstIndex) { int nIndex = nFirstIndex; nFirstIndex = nEndIndex; nEndIndex = nIndex; } string sNumAddr = sKeyName.Substring(nFirstIndex, nEndIndex - nFirstIndex + 1); string sReturnNum = returnResult(sNumAddr.toInt()); sKeyName = sKeyName.Replace(sNumAddr, sReturnNum); } } sOriTown = (sAddrName[k] == "區") ? sKeyName : sOriTown; sOriVillage = (sAddrName[k] == "里" || sAddrName[k] == "村") ? sKeyName : sOriVillage; if (sAddrName[k] == "樓") sFloor = sKeyName; else sNewAddr += sKeyName; // 樓不加入 } } try { // TGOS的全國門牌清單查詢服務 DataSet dsAddrList = TGOS_Search(sNewAddr); DataTable dtInfo = dsAddrList.Tables["Info"]; DataTable dtAddrList = dsAddrList.Tables["AddressList"]; if (dtAddrList.Rows.Count == 0) { // 地址有誤 // 拆解的地址有誤,直接用他原始的地址去查 dsAddrList = TGOS_Search(sValue); dtInfo = dsAddrList.Tables["Info"]; dtAddrList = dsAddrList.Tables["AddressList"]; if (dtAddrList.Rows.Count == 0) { dscv.CheckValue = 2; } else { if (dtInfo.Rows[0]["OutMatchType"].ToString() == "模糊比對" && dtAddrList.Rows[0]["FULL_ADDR"].ToString() != sNewAddr) { dscv.CheckValue = 2; } else { if (dscvTown != null) dscvTown.Value = dtAddrList.Rows[0]["TOWN"].ToString(); dscvX.Value = dtAddrList.Rows[0]["X"].ToString(); dscvY.Value = dtAddrList.Rows[0]["Y"].ToString(); sValue = sZipCode + dtAddrList.Rows[0]["FULL_ADDR"].ToString() + sFloor + sTempValue; dscv.CheckValue = (dscv.OriValue != sValue) ? 1 : dscv.CheckValue; // 地址有修正過 } } } else { if (dtInfo.Rows[0]["OutMatchType"].ToString() == "模糊比對" && dtAddrList.Rows[0]["FULL_ADDR"].ToString() != sNewAddr) { // 地址有誤 // 拆解的地址有誤,直接用他原始的地址去查 dsAddrList = TGOS_Search(sValue); dtInfo = dsAddrList.Tables["Info"]; dtAddrList = dsAddrList.Tables["AddressList"]; if (dtAddrList.Rows.Count == 0) { dscv.CheckValue = 2; } else { if (dtInfo.Rows[0]["OutMatchType"].ToString() == "模糊比對" && dtAddrList.Rows[0]["FULL_ADDR"].ToString() != sNewAddr) { dscv.CheckValue = 2; } else { if (dscvTown != null) dscvTown.Value = dtAddrList.Rows[0]["TOWN"].ToString(); dscvX.Value = dtAddrList.Rows[0]["X"].ToString(); dscvY.Value = dtAddrList.Rows[0]["Y"].ToString(); sValue = sZipCode + dtAddrList.Rows[0]["FULL_ADDR"].ToString() + sFloor + sTempValue; dscv.CheckValue = (dscv.OriValue != sValue) ? 1 : dscv.CheckValue; // 地址有修正過 } } } else { if (dscvTown != null) dscvTown.Value = dtAddrList.Rows[0]["TOWN"].ToString(); dscvX.Value = dtAddrList.Rows[0]["X"].ToString(); dscvY.Value = dtAddrList.Rows[0]["Y"].ToString(); sValue = sZipCode + dtAddrList.Rows[0]["FULL_ADDR"].ToString() + sFloor + sTempValue; dscv.CheckValue = (dscv.OriValue != sValue) ? 1 : dscv.CheckValue; // 地址有修正過 } } } catch (Exception ex) { dscv.CheckValue = 2; sValue = sZipCode + sNewAddr + sTempValue; } // 若行政區、X、Y坐標為空值,則設為有誤 if (dscvTown != null) { if (dscvTown.Value == "") dscvTown.CheckValue = 2; } if (dscvX.Value == "") dscvX.CheckValue = 2; if (dscvY.Value == "") dscvY.CheckValue = 2; dscv.Value = sValue; } /// <summary> /// TGOS的全國門牌清單查詢服務 /// </summary> /// <param name="sAddress">地址</param> /// <returns></returns> public static DataSet TGOS_Search(string sAddress) { WSQueryAddr wsq1 = new WSQueryAddr(); string rtval = wsq1.QueryAddr(ConfigurationManager.AppSettings["togs.queryAddr.APPID"], ConfigurationManager.AppSettings["togs.queryAddr.APIKey"], sAddress, "EPSG:3826", 2, "JSON", 0, false, false, false, false, false, false, false, false, true, true, true, 10); DataSet dsAddrList = JsonConvert.DeserializeObject<DataSet>(rtval); return dsAddrList; } ``` <br/> ## 三、TGOS查詢比對 ![](https://i.imgur.com/PP9VNE0.png) <br/> ## 四、產出結果 ![](https://i.imgur.com/fWcsLtM.png) <br/> ## 五、常用座標轉換 | 坐標系統 | 用途 | EPSG | X坐標 | Y坐標 | | -------- | -------- | -------- | -------- | -------- | | TWD97二度分帶-中央經線121度 | 台灣本島圖資 | EPSG:3826 | 179266 | 2502459 | | TWD67二度分帶-中央經線121度 | 台灣本島圖資(早期) | EPSG:3828 | 178436 | 2502665 | | WGS84經緯度(球體) | 全球圖資 如:Google Map, GPS| EPSG:4326 | 120.311914 | 22.620820 | | Spherical Mercator (投影) | 圖磚, WMTS | EPSG:3857 | 13393061.01 | 2586227.26 | #### 資料來源:https://gisdawh.kcg.gov.tw/md/mdread.cfm?qid=qa%5C%E5%B9%B3%E5%8F%B0%E5%9C%B0%E5%9C%96%E8%88%87%E5%9C%96%E8%B3%87%E5%9D%90%E6%A8%99%E7%B3%BB%E7%B5%B1%E8%AA%AA%E6%98%8E