今日は、
地図上のあるポイントが特定の領域内に含まれるが否かを調べる方法をネットで検索したところ、以下の資料を見つけました。
「領域内外判定方法」
http://www.j-tokkyo.com/1999/G06T/JP11144041.shtml
上のページでは、プログラムコードまで参照できませんが、使用したい理論は
「点p=(Xp,Yp)と、多角形の頂点qi=(Xi,Yi)が与えられた時、
多角形の各辺について、M1=(Xp- Xi)(Xp-Xi+1)を計算して
これが負である場合のみ、
M2=(Xp-Xi){(Xp-Xi)(Yi+1-Yi)-(Yp-Yi)(Xi+1-Xi)}を求めて
その符号( M2<0のとき1、M2>0のとき0)の和を求め、
これが偶数であるとき、与えられた点pは多角形で囲まれる領域の外部にあり、
奇数であるときには内部にあると判定する」
です。上は特許のようですが、商用利用はしないので、この理論を元に、javascriptでコーディングして、googleマップ上のある
Glatlng地点がGpolygon領域内にあるかを判定する関数を作ってみました。もっとも、この理論は2次元平面座標系の理論だから、地球面上の
地図に適用させると、領域の頂点間の距離が大きくなると誤差がでます。また、北半球かつ東半球の緯度経度でないと正常結果が得られません。南緯や西経に
対応させるのは全点に90と180を加えてから計算すればよいはずです。球面への対応は、球面三角法で座標の計算をしなおせばいいような気がします。
今の所、肝はjavascriptやphpやvbで簡単に出来るといったところです。
以下が作成した領域判定の関数です。
function Region_chk(gpoint,gpolygon){
var result = new Boolean();
var count = 0;
for (i=0;i<gpolygon.getVertexCount()-1;i++){
if(
(
((gpoint.lng()-gpolygon.getVertex(i).lng()) *
(gpoint.lng()-gpolygon.getVertex(i+1).lng()))
< 0)
&&(
( (gpoint.lng()-gpolygon.getVertex(i).lng()) *
(
((gpoint.lng()-gpolygon.getVertex(i).lng()) *
(gpolygon.getVertex(i+1).lat()-gpolygon.getVertex(i).lat()))
-
((gpoint.lat()-gpolygon.getVertex(i).lat()) *
(gpolygon.getVertex(i+1).lng()-gpolygon.getVertex(i).lng()))
)
)
< 0)
){count++;}
}
if(count % 2 == 0){
result = false;
}else{
result = true;
}
return result;
}
この関数を、簡単にテスト出来るページも作ってみました。
http://yoneyone.my-sv.net/regionchk.htm
です。
次に取り組んでいる事というか本来の目的は、件の、総理府提供の国勢調査「町丁・字等境界データ」のXMLから領域を取り出してジオコーディングした
住所がどの国勢調査の(町丁・字)地域に入るか調べたいのです。
出来る限り、javascriptのみで作成するのを目的に、無理そうならphpで作成しDBは使用せず、ダウンロードしたXMLファイルのまま処理
したいのです。Xpathを使えば検索の手間が省けそうです。DBを使うとしても検査対象とするXMLファイル名の絞込みに使うぐらいにとどめたいで
す。
何故DB使わないかというと、XMLのデータを全部DBに入れて処理するのは、完成すれば後が楽だけれども、XMLデータをロードするプログラムも作
らなければならないし、XML->EXCELロード->VBA->CSV->MySQLでやるにしても作業がたいへんそうに思えるからです。
※SQL Server 2008で、空間データ型やXMLネーティブ型なる物があるそうです
が、これって無償の「SQL Server 2008 Express Edition」でも使えるみたい
ですね。これもダウンロードして試してみようかな....