驗證字串是否是有效的地理座標
一、簡介
在本教程中,我們將探索在 Java 中驗證地理座標及其準確性的各種方法。
2.了解地理座標
地理座標通常表示為緯度和經度值,精確定位球形地球上的位置。緯度測量赤道以北或以南的距離,範圍從 -90°(南極)到 90°(北極)。另一方面,經度測量本初子午線以東或以西的距離,跨度為 -180°(國際日期變更線)到 180°。
3. 了解精度和準確度
在檢查座標的有效性時,要考慮的關鍵因素是小數位數的精確度。由座標表示並與位置相關聯的詳細程度由精確度表示,精確度由小數位數表示。
此外,舍入座標可能會導致不準確,尤其是在對鄰近度敏感的應用中。例如,繪製建築物地圖可能需要精確到小數點後五位(大約一公尺)的座標,而城市級地圖可能只需要兩位小數(大約一公里)。
4. 經緯度格式
了解各種格式對於座標輸入和驗證都是基礎。
4.1.十進制 (DD)
地理座標通常以十進位表示,其中緯度和經度都以十進位值表示。在 DD 格式中,有效緯度值的範圍通常為 -90 到 90,而有效經度值的範圍為 -180 到 180。例如,巴黎艾菲爾鐵塔的座標約為 48.8588445(緯度)和 2.2943506(經度)。
4.2.度、分、秒 (DMS)
DMS格式涉及度、分、秒,緯度和經度以度表示。每個度數又分為60分鐘,每分鐘可選擇性地分為60秒。 °(度)、'(分)和 」(秒)等符號用來分隔這些部分。例如,自由女神像的座標為 40°41'21.7"N(緯度)和 74°02'40.7"W(經度)。
4.3.軍用網格參考系統 (MGRS)
MGRS 是另一種用於指定地球表面位置的座標格式。它將世界劃分為網格區域並提供它們的簡明表示。每個部分是一個 6° 寬的區域,編號為 1 到 60,並進一步分為由兩個字母代碼標識的 100,000 公尺正方形。在每個方格內,精確的位置由“東向”和“北向”給出,均以米為單位。例如,中國長城的八達嶺部分可以定位為 50TMK6356175784。
5. 使用正規表示式進行基本驗證
正規表示式是模式匹配的強大工具。我們可以使用 Java 的Pattern
和Matcher
類別製作正規表示式模式來識別有效的座標格式。
第一個正規表示式是為 DD 格式設計的,其中兩個十進制數字用逗號分隔,並帶有可選空格:
public static final String DD_COORDINATE_REGEX = "^(-?\\d+\\.\\d+)(\\s*,\\s*)?(-?\\d+\\.\\d+)$";
第二個正規表示式是為了處理 DMS 格式而建構的。它檢查兩組座標,包括度、分、秒和基本方向(N、S、W 或 E),從而允許靈活地使用符號:
public static final String DMS_COORDINATE_REGEX =
"^(\\d{1,3})°(\\d{1,2})\'(\\d{1,2}(\\.\\d+)?)?\"?([NSns])(\\s*,\\s*)?
(\\d{1,3})°(\\d{1,2})\'(\\d{1,2}(\\.\\d+)?)?\"?([WEwe])$";
最終的正規表示式迎合 MGRS 座標。此代碼驗證由兩個數字表示的 UTM 區域、使用字母字元(不包括 I 和 O)的緯度帶以及後跟偶數對排列的 2 到 10 個數字組成的模式:
public static final String MGRS_COORDINATE_REGEX =
"^\\d{1,2}[^IO]{3}(\\d{10}|\\d{8}|\\d{6}|\\d{4}|\\d{2})$";
讓我們定義實用方法來驗證每種格式:
boolean validateCoordinates(String coordinateString) {
return isValidDDFormat(coordinateString) || isValidDMSFormat(coordinateString) || isValidMGRSFormat(coordinateString);
}
boolean isValidDDFormat(String coordinateString) {
return Pattern.compile(DD_COORDINATE_REGEX).matcher(coordinateString).matches();
}
boolean isValidDMSFormat(String coordinateString) {
return Pattern.compile(DMS_COORDINATE_REGEX).matcher(coordinateString).matches();
}
boolean isValidMGRSFormat(String coordinateString) {
return Pattern.compile(MGRS_COORDINATE_REGEX).matcher(coordinateString).matches();
}
正規表示式對於基本驗證很有用,但不能保證座標的正確性。例如,DD 正規表示式不會驗證座標是否落在地球的緯度和經度範圍內。
6.複雜場景的自訂驗證邏輯
為了處理複雜的場景,讓我們將驗證過程分解為更小、更明確的步驟。
6.1.十進制度
讓我們改進isValidDDFormat()
方法來處理邊緣情況,例如非數字輸入和無效座標:
boolean isValidDDFormat(String coordinateString) {
try {
String[] parts = coordinateString.split(",");
if (parts.length != 2) {
return false;
}
double latitude = Double.parseDouble(parts[0].trim());
double longitude = Double.parseDouble(parts[1].trim());
if (latitude < -90 || latitude > 90 || longitude < -180 || longitude > 180) {
return false;
}
return true;
} catch (NumberFormatException e) {
return false;
}
}
String.split()
方法使用逗號和空格作為分隔符號來分割座標,以適應不同的輸入格式。這確保了恰好有兩個部分(緯度和經度)。然後我們驗證數值是否在指定範圍內。
捕獲NumberFormatException
是為了處理解析雙精度數失敗的情況。
6.2.度、分和秒
接下來,我們改進isValidDMSFormat()
方法,將座標字串拆分為度、分、秒和半球部分,並相應地驗證每個部分:
boolean isInvalidLatitude(int degrees, int minutes, double seconds, String hemisphere) {
return degrees < 0 || degrees > 90 || minutes < 0 || minutes >= 60 || seconds < 0 || seconds >= 60 ||
(!hemisphere.equalsIgnoreCase("N") && !hemisphere.equalsIgnoreCase("S"));
}
isInvalidLatitude()
方法檢查所提供的緯度分量是否超出有效範圍。如果滿足以下任何無效條件,則傳回true
(無效):
- 緯度小於 0 或大於 90
- 緯度分鐘小於 0 或大於或等於 60
- 緯度秒小於 0 或大於或等於 60
- 半球不是“N”(北)或“S”(南)
同樣,我們將為經度創建等效的驗證方法:
boolean isInvalidLongitude(int degrees, int minutes, double seconds, String hemisphere) {
return degrees < 0 || degrees > 180 || minutes < 0 || minutes >= 60 || seconds < 0 || seconds >= 60 ||
(!hemisphere.equalsIgnoreCase("E") && !hemisphere.equalsIgnoreCase("W"));
}
isInvalidLongitude()
方法檢查提供的經度分量,如果滿足以下任何無效條件,則傳回true
(無效):
- 經度小於 0 或大於 180
- 經度分鐘小於 0 或大於或等於 60
- 經度秒小於 0 或大於或等於 60
- 半球不是“E”(東)或“W”(西)
最後,讓我們利用這兩種驗證方法來驗證 DMS 座標:
boolean isValidDMSFormatWithCustomValidation(String coordinateString) {
try {
String[] dmsParts = coordinateString.split("[°',]");
if (dmsParts.length > 6) {
return false;
}
int degreesLatitude = Integer.parseInt(dmsParts[0].trim());
int minutesLatitude = Integer.parseInt(dmsParts[1].trim());
String[] secondPartsLatitude = dmsParts[2].split("\"");
double secondsLatitude = secondPartsLatitude.length > 1 ? Double.parseDouble(secondPartsLatitude[0].trim()) : 0.0;
String hemisphereLatitude = secondPartsLatitude.length > 1 ? secondPartsLatitude[1] : dmsParts[2];
int degreesLongitude = Integer.parseInt(dmsParts[3].trim());
int minutesLongitude = Integer.parseInt(dmsParts[4].trim());
String[] secondPartsLongitude = dmsParts[5].split("\"");
double secondsLongitude = secondPartsLongitude.length > 1 ? Double.parseDouble(secondPartsLongitude[0].trim()) : 0.0;
String hemisphereLongitude = secondPartsLongitude.length > 1 ? secondPartsLongitude[1] : dmsParts[5];
if (isInvalidLatitude(degreesLatitude, minutesLatitude, secondsLatitude, hemisphereLatitude) ||
isInvalidLongitude(degreesLongitude, minutesLongitude, secondsLongitude, hemisphereLongitude)) {
return false;
}
return true;
} catch (NumberFormatException e) {
return false;
}
}
isValidDMSFormatWithCustomValidation()
方法將輸入拆分為緯度和縱向分量,並使用輔助方法分別驗證它們。如果所有檢查都通過,則 DMS 格式被視為有效,並且該方法傳回true
(有效)。
七、結論
在本文中,我們探索了兩種不同的驗證地理座標的方法。正規表示式為基本驗證提供了快速的解決方案,而自訂驗證邏輯提供了靈活性和錯誤回饋,使其適合複雜的場景。
與往常一樣,範例的原始程式碼可 在 GitHub 上取得。