2点の住所から直線距離を求めます。緯度と経度がわかればそこから距離を計算することができます。住所から緯度と経度を求めるためにYahoo!ジオコーダAPIを使用します。アプリケーションIDは各自で取得してください。
東京都庁の位置を求めます。住所は「東京都新宿区西新宿2丁目8-1」です。「東京都新宿区西新宿2丁目8-1」をエンコードするとE6%9D%B1%E4%BA%AC%E9%83%BD%E6%96%B0%E5%AE%BF%E5%8C%BA%E8%A5%BF%E6%96%B0%E5%AE%BF2%E4%B8%81%E7%9B%AE8-1なので、https://map.yahooapis.jp/geocode/V1/geoCoder?appid=【アプリケーションIDは各自で取得してください】&query=%E6%9D%B1%E4%BA%AC%E9%83%BD%E6%96%B0%E5%AE%BF%E5%8C%BA%E8%A5%BF%E6%96%B0%E5%AE%BF2%E4%B8%81%E7%9B%AE8-1とリクエストとすると以下のようなレスポンスが得られます。Coordinatesの部分を取り出せば緯度と経度を知ることができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
<?xml version="1.0" encoding="utf-8"?> <YDF xmlns="http://olp.yahooapis.jp/ydf/1.0" totalResultsReturned="1" totalResultsAvailable="1" firstResultPosition="1"> <ResultInfo> <Count>1</Count> <Total>1</Total> <Start>1</Start> <Status>200</Status> <Description></Description> <Copyright></Copyright> <Latency>0.069</Latency> </ResultInfo> <Feature> <Id>13104.70.2.8.1</Id> <Gid></Gid> <Name>東京都新宿区西新宿2丁目8-1</Name> <Geometry> <Type>point</Type> <Coordinates>139.69164748,35.68918461</Coordinates> <BoundingBox>139.68723300,35.68610000 139.69565300,35.69250300</BoundingBox> </Geometry> <Category/> <Description></Description> <Style/> <Property> <Uid>3bd6dbe32ddaa85375f76ba0b4e80e0400427758</Uid> <CassetteId>b22fee69b0dcaf2c2fe2d6a27906dafc</CassetteId> <Yomi>トウキョウトシンジュククニシシンジュク2チョウメ</Yomi> <Country><Code>JP</Code><Name>日本</Name></Country> <Address>東京都新宿区西新宿2丁目8-1</Address> <GovernmentCode>13104</GovernmentCode> <AddressMatchingLevel>6</AddressMatchingLevel> <AddressType>地番・戸番</AddressType> </Property> </Feature> </YDF> |
これは取得した緯度経度を格納するためのクラスです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public class LatitudeLongitude { public LatitudeLongitude(double latitude, double longitude) { Latitude = latitude; Longitude = longitude; } public double Latitude { get; } public double Longitude { get; } } |
これは住所から緯度と経度を取得するためのメソッドです。住所としておかしな文字列を渡してしまった場合はnullが返されます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
public partial class Form1 : Form { string myYahooID = "【アプリケーションIDは各自で取得してください】"; LatitudeLongitude GetLatitudeLongitude(string str) { string urlEnc = System.Web.HttpUtility.UrlEncode(str); string url = "https://map.yahooapis.jp/geocode/V1/geoCoder?appid="; url += myYahooID; url += "&query="; url += urlEnc; var xmlDoc = new XmlDocument(); xmlDoc.Load(url); XmlNamespaceManager xmlNsManager = new XmlNamespaceManager(xmlDoc.NameTable); xmlNsManager.AddNamespace("ns", "http://olp.yahooapis.jp/ydf/1.0"); var nodes = xmlDoc.SelectNodes("//ns:Coordinates", xmlNsManager); if (nodes.Count == 0) return null; try { string ret = ""; foreach (XmlNode emp in nodes) ret += emp.InnerText; string[] strs = ret.Split(new string[] { ",", }, StringSplitOptions.RemoveEmptyEntries); double d0 = double.Parse(strs[0]); // 経度 double d1 = double.Parse(strs[1]); // 緯度 return new LatitudeLongitude(d1, d0); } catch { return null; } } } |
次に緯度と経度から2点間の距離を調べる方法ですが、公式のようなものがあります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
// 緯度経度をラジアンに変換 double radLat1 = latitudeLongitude1.Latitude * Math.PI / 180; double radLon1 = latitudeLongitude1.Longitude * Math.PI / 180; double radLat2 = latitudeLongitude2.Latitude * Math.PI / 180; double radLon2 = latitudeLongitude2.Longitude * Math.PI / 180; double r = 6378137.0; // 赤道半径 double averageLat = (radLat1 - radLat2) / 2; double averageLon = (radLon1 - radLon2) / 2; // 単位はメートル return r * 2 * Asin(Sqrt(Pow(Sin(averageLat), 2) + Cos(radLat1) * Cos(radLat2) * Pow(Sin(averageLon), 2))); double Pow(double d, int i){ return Math.Pow(d, i); } double Asin(double d){ return Math.Asin(d); } double Sin(double d){ return Math.Sin(d); } double Cos(double d){ return Math.Cos(d); } double Sqrt(double d){ return Math.Sqrt(d); } |
あとはこれを使って距離を求めます。東京都庁と大阪府庁の距離を求めてみましょう。
東京都庁は「東京都新宿区西新宿2丁目8-1」、大阪府庁は「大阪府大阪市中央区大手前2丁目1-22」です。実行してみると東京と大阪の距離は約395.59キロメートルと表示されます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { string str1 = "東京都新宿区西新宿2丁目8-1"; string str2 = "大阪府大阪市中央区大手前2丁目1-22"; double distance = GetDistance(str1, str2); double kilometers = Math.Round(distance / 1000, 2); MessageBox.Show("東京と大阪の距離は約" + kilometers + "キロメートルです。"); } double GetDistance(string str1, string str2) { LatitudeLongitude latitudeLongitude1 = GetLatitudeLongitude(str1); LatitudeLongitude latitudeLongitude2 = GetLatitudeLongitude(str2); // 緯度経度をラジアンに変換 double radLat1 = latitudeLongitude1.Latitude * Math.PI / 180; double radLon1 = latitudeLongitude1.Longitude * Math.PI / 180; double radLat2 = latitudeLongitude2.Latitude * Math.PI / 180; double radLon2 = latitudeLongitude2.Longitude * Math.PI / 180; double r = 6378137.0; // 赤道半径 double averageLat = (radLat1 - radLat2) / 2; double averageLon = (radLon1 - radLon2) / 2; return r * 2 * Asin(Sqrt(Pow(Sin(averageLat), 2) + Cos(radLat1) * Cos(radLat2) * Pow(Sin(averageLon), 2))); } } |