13
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

循環する緯度経度の値を正規化する。

Last updated at Posted at 2015-09-18

地球って丸いけど、平面で表現したい。

位置情報を扱うときに丸い地球を平面に見立てて緯度をY軸、経度をX軸として扱いますよね。

普通に考えると…

  • 緯度は赤道が0度で、北極が90度、南極がー90度
  • 経度はグリニッジ天文台が0度で日本の方がプラス方向で最大180度、北大西洋を超えてアメリカの方がマイナス方向で最大-180度

…なんですが、地球って丸いので(というか緯度経度はその名の通り角度なので)値はぐるぐる循環します。
経度180度経度-180度も同じです。

一瞬 x' = x % 180 で良いのかな?って思いますが、うまくいかないです。

緯度と経度を正規化する関数

緯度を-90度から90度まで経度を-180度から180度までに正規化します。

function coordinate(lat,lon) {
	var side = ( Math.cos(lat * Math.PI / 180) > 0 ) ? 0 : 180;//裏側(?)なら経度を180度移動

	var latitude  = Math.asin(Math.sin(lat * Math.PI / 180)) * 180 / Math.PI;
	var longitude = Math.atan(Math.tan((lon + side) * Math.PI / 360)) * 360 / Math.PI;

	return [latitude,longitude];
}

緯度を正規化する関数

ということで作りました。入力が何度[°]になってても-90度から90度を返します。

// 緯度(Y軸方向)の出力は-90度~90度
function latitude(deg) {
	return Math.asin(Math.sin(deg * Math.PI / 180)) * 180 / Math.PI;
}

経度を-180度から180度までに正規化する関数(制限付き)

経度はちょっと複雑で-180度=180度なんですよね。
※コメントに頂いた通り、緯度をぐるっとまわして地球の裏側(?)に行く場合には正しくありません。緯度の範囲に制限があります。

// 経度(X軸方向)の出力は-180度~180度 ※ただし緯度が裏側にいないこと。
function longitude(deg) {
	return Math.atan(Math.tan(deg * Math.PI / 360)) * 360 / Math.PI;
}

グラフで表示

緯度経度の入力値を-540度から540度まで指定してますが、出力は-90~90、-180~180になってるのがわかると思います。
参考で剰余modの場合も表示します。

cap.png

ソースコード

緯度経度の正規化関数も含めてHTMLで確認するソースコードです。
グラフの生成はGoogle Chartを参考にしました。

index.html
<!DOCTYPE html>
<html>

<head>
	<meta charset="UTF-8">
	<title>循環する緯度経度の正規化</title>
	<script type="text/javascript" src="https://www.google.com/jsapi"></script>
	<script type="text/javascript" src="geo.js"></script>
	<script type="text/javascript">
		google.load("visualization", "1", {packages: ["corechart"]});
		google.setOnLoadCallback(drawChart);
	</script>
</head>

<body>
	<div id="latitude" style="width: 640px; height: 320px;"></div>
	<div id="longitude"style="width: 640px; height: 320px;"></div>
	<div id="modulus"style="width: 640px; height: 320px;"></div>
</body>

</html>
geo.js

// 緯度が90度より大きい時などにも対応
function coordinate(lat,lon) {
	var side = ( Math.cos(lat * Math.PI / 180) > 0 ) ? 0 : 180;//裏側(?)なら経度を180度移動

	var latitude  = Math.asin(Math.sin(lat * Math.PI / 180)) * 180 / Math.PI;
	var longitude = Math.atan(Math.tan((lon + side) * Math.PI / 360)) * 360 / Math.PI;

	return [latitude,longitude];
}


// 緯度(Y軸方向)の出力は-90度~90度 
function latitude(deg) {
	return Math.asin(Math.sin(deg * Math.PI / 180)) * 180 / Math.PI;
}

// 経度(X軸方向)の出力は-180度~180度 ※ただし緯度が裏側にいないこと。
function longitude(deg) {
	return Math.atan(Math.tan(deg * Math.PI / 360)) * 360 / Math.PI;
}

// 参考 Modulus
function modulus(deg) {
	return deg % 180;
}

function drawChart() {

	var lat_array = [];
	var lon_array = [];
	var mod_array = [];

	lat_array.push(['latitude-in', 'latitude-out']);
	lon_array.push(['longitude-in', 'longitude-out']);
	mod_array.push(['mod-in', 'mod-out']);

	for (var deg = -540; deg < 540; deg++) {
		var clat = coordinate(deg,0);//経度が0度(イギリス)
		var clon = coordinate(0,deg);//緯度が0度(赤道)
		lat_array.push([deg, clat[0]]);
		lon_array.push([deg, clon[1]]);
		mod_array.push([deg, modulus(deg)]);
	}

	chart('latitude', lat_array, 'latitude(緯度)');
	chart('longitude', lon_array, 'longitude(経度)');
	chart('modulus', mod_array, 'mod(剰余)');

}

function chart(id, data_array, title) {
	var data = google.visualization.arrayToDataTable(data_array);
	var options = {
		title: title,
		hAxis: {
			title: 'In',
			minValue: -540,
			maxValue: 540
		},
		vAxis: {
			title: 'Out',
			minValue: -180,
			maxValue: 180
		},
		legend: 'none'
	};
	var c = new google.visualization.ScatterChart(document.getElementById(id));
	c.draw(data, options);
}

ツッコミ・コメント上等!

もっといい手があるよ!とか、ココちがくない?ということがあればコメントよろしくお願いします。

13
14
8

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?