シャーレーポピーを見に秩父高原牧場へ。
斜面一帯が全てポピー・・・・圧倒されました。

ポピー(1)

ポピー(1)

ポピー(2)

ポピー(2)

ポピー(3)

ポピー(3)

ポピー(4)

ポピー(4)

ポピー(5)

ポピー(5)

ポピー(6)

ポピー(6)

美の山公園からの眺望(1)

美の山公園からの眺望(1)
秩父高原牧場のポピー畑が見えました

美の山公園からの眺望(2)

美の山公園からの眺望(2)
武甲山、甲武信ヶ岳等

秩父神社

秩父神社

コメント   

 都道府県別の統計データをもとに色分けされた地図を、新聞・雑誌やWebサイト、地図帳などで見かける機会はよくあります。
 こういったものは地図ソフトを使用すれば作ることができますが、「自分の好きなようにいろいろと加工したい」となると自作するに限る・・・ということで、ゼロから作成することにチャレンジです!

 まずは、ベースとなる日本列島の輪郭、及び都道府県境の座標データの入手から。しかし、残念ながら都道府県境のデータを見つけることは出来ませんでした。地図ソフトの中には都道府県の輪郭情報が提供されているものもあるでしょうが、著作権の問題からそれらを使用出来ないので・・・。
 ただし、都道府県単位よりも細かい市区町村境のデータであれば、国土交通省のページにて公開されています。
 ・国土数値情報ダウンロードサービス URL:http://nlftp.mlit.go.jp/ksj/index.html
 当ページでは様々な国土情報データが登録されてますが、今回はこの中から「行政区域」を選択。データ形式はJPGIS2.1としました(http://nlftp.mlit.go.jp/ksj/gml/datalist/KsjTmplt-N03.html)。
 データファイルは各都道府県別、調査年度別に(大正8年~平成25年)分かれていて選択するのがやや面倒ですが、現時点(2014年5月)で最新の平成25年のデータを47都道府県分※ダウンロードしました。
 ※ファイル名がN03-130401_XX_GML.zipとなっているもの。
  XXの部分には都道府県コードが入ります。東京都であればN03-130401_13_GML.zip

 ダウンロードしたファイルを解凍すると、以下6ファイルが収納されています。
 ※N03-130401_13_GML.zip(東京都)の例
   KS-META-N03-13_13_130401.xml
   N03-13_13_130401.dbf
   N03-13_13_130401.sbn
   N03-13_13_130401.sbx
   N03-13_13_130401.shp
   N03-13_13_130401.shx
   N03-13_13_130401.xml
 上記のうち緑色フォントの5つはSHAPE形式の構成ファイルです。これらファイルを見るには専用のアプリケーションが必要で普通のテキストエディタでは読み取れないので除外。一番上のファイル(青色フォント)には概要が記載されているだけなので、今回は一番下の赤色フォントのXMLファイルを対象とします。
 ※ファイル名:N03-13_XX_130401.xml
  XXの部分には都道府県コードが入るのでN03-13_01_130401.xml~N03-13_47_130401.xmlの47個
 
 このファイルの中身を見ると、データは大きく分けて以下の3つで構成されています。

 (1)行政区域情報

	<ksj:AdministrativeArea gml:id="gy40"> <!-- ID -->
		<ksj:are xlink:href="#sf40"/>      <!-- 対応する「領域面データ」(2)のID -->
		<ksj:prn>東京都</ksj:prn>          <!-- 都道府県名 -->
		<ksj:sun></ksj:sun>                <!-- 支庁名(北海道のみ)-->
		<ksj:con></ksj:con>                <!-- 郡・政令市名 -->
		<ksj:cn2>府中市</ksj:cn2>          <!-- 市区町村名 -->
		<ksj:aac codeSpace="AdministrativeAreaCode.xml">13206</ksj:aac> <!-- 行政区域コード -->
	</ksj:AdministrativeArea>

 基本的には1市区町村につき1属性情報なのですが、島などで対応する「面データ」が複数存在する場合には、その数分だけ属性情報があります。例えば大田区の場合は、本土(ID:gy68)の他に昭和島(ID:gy72)、京浜島(ID:gy73)、さらに詳細不明の1箇所(ID:gy74)の計4つの属性データが存在します。同じ人工島でも大井ふ頭と城南島は、本土と陸続きとみなされているようで分かれていません。ちなみに、小笠原村はたくさんの島で構成されているため2,420もの属性データに分かれています。
 島の他に「領域面データ」が複数存在ケースとして飛び地があります。府中市にも小金井市内に飛び地が存在するため、上記(ID:gy40)の他に1つ属性データがあります(ID:gy45)。

 (2)領域面データ

	<gml:Surface gml:id="sf40">
 		<gml:patches>
			 <gml:PolygonPatch>
				 <gml:exterior>
					 <gml:Ring>
						<gml:curveMember xlink:href="#cv40_0"/> <!-- 対応する「境界線データ」(3)のID -->
 					</gml:Ring>
				 </gml:exterior>
			 </gml:PolygonPatch>
		 </gml:patches>
	 </gml:Surface>

 通常は上記のように1つの領域面データにつき、対応する1つの境界線データIDが記述されているだけのシンプルな構成となっています。ただし、区域内に他市区町村の飛び地がある場合(前述した小金井市の場合は府中市の飛び地)は、以下のような構成となります。

	<gml:Surface gml:id="sf35">
		<gml:patches>
			<gml:PolygonPatch>
				<gml:exterior> <!-- 通常の領域 -->
					<gml:Ring>
						<gml:curveMember xlink:href="#cv35_0"/> <!-- 対応する「境界線データ」(3)のID -->
					</gml:Ring>
				</gml:exterior>
				<gml:interior> <!-- 飛び地等で穴となる領域 -->
					<gml:Ring>
						<gml:curveMember xlink:href="#cv35_1"/> <!-- 対応する「境界線データ」(3)のID -->
					</gml:Ring>
				</gml:interior>
			</gml:PolygonPatch>
		</gml:patches>
	</gml:Surface>

 この例(小金井市)では対応する境界線データIDが2件登録されています。ここで4行目と9行目に注目して下さい。
 4行目ではgml:exteriorと記述されている部分が9行目ではgml:interiorとなっています。「exterior」は通常の領域を、「interior」は飛び地等で穴となる領域を表しているようです。ちなみに今回ダウンロードしたデータの中で穴領域(interior)が最も多いのは広島県廿日市市で、11箇所もあります。

 (3)境界線データ

	<gml:Curve gml:id="cv40_0"> <!-- 境界線データID -->
		<gml:segments>
			<gml:LineStringSegment>
				<gml:posList>
				35.69545100 139.48958400
				35.69537900 139.48936800
				        (中略)
				35.69535200 139.48964000
				35.69545100 139.48958400
				</gml:posList>
			</gml:LineStringSegment>
		</gml:segments>
	</gml:Curve>

 このように市区町村境界線の位置情報(緯度・経度)が収納されています。先頭のデータ(5行目)と最後のデータ(9行目)は同一座標となっていて通常は反時計回りに並んでいますが、前述した飛び地等で穴となる領域(interior)の場合は時計回りとなっています。後術しますが、GoogleMapsAPIでドーナツ状の中抜けポリゴンを描く場合は、内側領域を外側領域と逆回りに読み込む必要があるので、元データの段階でこのような仕様になっているのは好都合です。

 次にこれらのデータの加工方法ですが、市区町村境界の座標から都道府県境界をピックアップするに当たっては、いろいろな作業が生じそうなので、データベース化するのが便利かな?・・・と思い、MySQLのテーブルに収納することにしました。
 テーブル・フィールド構成は以下のようにしました。

・t_Prefecture 都道府県情報
[SQL]
CREATE TABLE IF NOT EXISTS `t_Prefecture` (
`PrefectureCode` smallint(2) unsigned zerofill NOT NULL, — 都道府県コード
`PrefectureName` varchar(10) NOT NULL, — 都道府県名
PRIMARY KEY (`PrefectureCode`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
[/SQL]
 ごく普遍的な情報なので、特にテーブル化しなくても良いのですが・・・。

・t_AdministrativeArea 行政区域(市区町村)情報
[SQL]
CREATE TABLE IF NOT EXISTS `t_AdministrativeArea` (
`PrefectureCode` smallint(2) unsigned zerofill NOT NULL, — 都道府県コード
`AdministrativeAreaCode` int(5) unsigned zerofill NOT NULL, — 行政区域コード(全国地方公共団体コード)
`CityName` varchar(100) DEFAULT NULL, — 市区町村名
`SubprefectureName` varchar(100) DEFAULT NULL, — 支庁名(北海道のみ)
PRIMARY KEY (`PrefectureCode`,`AdministrativeAreaCode`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
[/SQL]
 元データでは郡・政令市名と市区町村名とに分かれていますが、同一フィールド(CityName)にまとめることにしました。
 北海道の支庁名は、ほとんど使用することはないでしょうが一応収納。なお、データの中には「所属未定地」というものがあるのですが、これはAdministrativeAreaCode=都道府県コード+000として収納することにしました。

・t_Surface 領域面情報
[SQL]
CREATE TABLE IF NOT EXISTS `t_Surface` (
`PrefectureCode` smallint(2) unsigned zerofill NOT NULL, — 都道府県コード
`AdministrativeAreaCode` int(5) unsigned zerofill DEFAULT NULL, — 行政区域コード(全国地方公共団体コード)
`SurfaceCode` int(5) NOT NULL, — 領域面コード
PRIMARY KEY (`PrefectureCode`,`AdministrativeAreaCode`,`SurfaceCode`),
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
[/SQL]
 構成する「領域面」が1つのみの市区町村についてはレコード数=1ですが、前述したように島や飛び地の存在などで領域が複数にわたる市区町村ではレコード数>1となります。

・t_Curve 境界線情報
[SQL]
CREATE TABLE IF NOT EXISTS `t_Curve` (
`PrefectureCode` smallint(2) unsigned zerofill NOT NULL, — 都道府県コード
`AdministrativeAreaCode` int(5) unsigned zerofill DEFAULT NULL, — 行政区域コード(全国地方公共団体コード)
`SurfaceCode` int(5) NOT NULL, — 領域面コード
`CurveCode` int(5) NOT NULL, — 境界線コード
`InteriorFlag` tinyint(2) NOT NULL DEFAULT ‘0’, — 通常(外輪線)は=0 内輪腺の場合>0
PRIMARY KEY (`PrefectureCode`,`AdministrativeAreaCode`,`SurfaceCode`,`CurveCode`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
[/SQL]
 通常の領域面(t_Surface)については、対応する境界線(t_Curve)は外輪線のみなのでレコード数は1:1となりますが(図-1)、領域内に飛び地がある場合は外輪線に加えて内輪線も存在するので1領域に対して境界線のレコード数は「飛び地数+1」となります(図-2)

通常の領域

図-1 通常の領域

飛び地のある領域

図-2 飛び地のある領域

・t_Point 点情報
[SQL]
CREATE TABLE IF NOT EXISTS `t_Point` (
`PrefectureCode` smallint(2) unsigned zerofill NOT NULL, — 都道府県コード
`AdministrativeAreaCode` int(5) unsigned zerofill DEFAULT NULL, — 行政区域コード(全国地方公共団体コード)
`SurfaceCode` int(5) NOT NULL, — 領域面コード
`CurveCode` int(5) NOT NULL, — 境界線コード
`PointNo` int(5) NOT NULL DEFAULT ‘0’, — 点コード
`Lat` decimal(15,8) DEFAULT NULL, — 緯度
`Lng` decimal(15,8) DEFAULT NULL, — 経度
PRIMARY KEY (`PrefectureCode`,`AdministrativeAreaCode`,`SurfaceCode`,`CurveCode`,`PointNo`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
[/SQL]
 境界線を構成する座標点の緯度・経度を収納します。

 次は、XMLからデータを読み込み、作成したMySQLテーブルへ挿入する作業。手作業で行うにはボリュームがあり過ぎるので、PHPでコーディングすることにしました。
 PHP(Ver.5以降)でXMLファイルを読み込む場合、simplexml_load_file関数を使用するのが便利なので、まずは次のようなコードを試しました。

   $PrefCode = 13;                                                         //都道府県コード(東京都:13)
   $FileName = "xml/N03-13_" . sprintf("%02d",$PrefCode) . "_130401.xml";  //XMLファイル名
   $xmlObj = simplexml_load_file($FileName);                               //XMLファイルをパース
   print "<pre>";
   print_r($xmlObj);                                                       //パース内容を出力
   print "</pre>";

 しかし、上記コードを実行しても何も出力されません。調べてみるとXMLでは要素名のコロン(:)は名前空間を意味し、これがあるとsimplexml_load_fileが上手く働かないようです。今回の対象ファイルの要素名には「gml:Curve」「ksj:prn」などコロンだらけなので、まさにこのケースに該当します。
 対応策としては、「.☆★ ステレオタイプラボ ★☆.」に良い方法が掲載されていましたので、これを拝借。
 simplexml_load_fileでうまくパース出来ない、なんて事はない。& 正解とお手軽方法

   $PrefCode = 13;                                                         //都道府県コード(東京都:13)
   $FileName = "xml/N03-13_" . sprintf("%02d",$PrefCode) . "_130401.xml";  //XMLファイル名
   $xmlString = file_get_contents($FileName);                              //XMLの内容を文字列に読み込む
   $xmlString = preg_replace('/:/','_',$xmlString);                        //文字列置き換え「:」→「_」
   $xmlData = simplexml_load_string($xmlString);                           //文字列をパース
   print "<pre>";
   print_r($xmlData);
   print "</pre>";

 これで上手く読み込めるようになりました。

 後は読み込んだデータをSQLでMySQLへ投げるだけ・・・。
 読み込むデータは、MySQLテーブルと同じフォーマットのクラスに一旦収納すると分かりやすいので、次のようなクラスを定義しました(MySQLのフィールド構成とは若干異なりますが)。

//行政区域(市区町村)情報 
class AdministrativeArea {
  public $AreaCode;    //行政区域コード(全国地方公共団体コード)
  public $Prf;         //都道府県名
  public $Sun;         //支庁名(北海道のみ)
  public $Con;         //郡・政令市名
  public $Cty;         //市区町村名
}

//領域面情報
class Surface {
  public $AreaCode;        //行政区域コード(全国地方公共団体コード)
  public $SurfaceCode = 0; //領域面コード
}

//境界線情報
class Curve {
  public $AreaCode;        //行政区域コード(全国地方公共団体コード)
  public $SurfaceCode = 0; //領域面コード
  public $CurveCode = 0;   //境界線コード
}

//点情報
class Point {
  public $AreaCode;        //行政区域コード(全国地方公共団体コード)
  public $SurfaceCode = 0; //領域面コード
  public $CurveCode = 0;   //境界線コード
  public $PointCode = 0;   //点コード
  public $Lat = array() ;  //緯度
  public $Lng = array() ;  //経度
}

 前述したように、XMLファイルのデータ3つのパート(行政区域情報・面情報・線情報)で構成されていて、それぞれの親子関係は、
  (親)行政区域情報 - 領域面情報 - 境界線情報(子)
 といった形です。
 この場合、通常は子側に親側のコードを持たせることで関連付けを行うものですが、当XMLファイルでは逆に親側に子側のコードを記述しています。
 そのため、本来は
  ・行政区域情報データ数=行政区域数
  ・領域面情報データ数=領域面数
  ・境界線情報データ数=境界線数
 となるべき所が、
  ・行政区域情報データ数=領域面数
  ・領域面情報データ数=境界線数
  ・境界線情報データ数=座標点数
 といった形で収納されているのです。従って、子側のデータ取得時には親側データを参照してIDを取得する関数を噛ませることにしました(関数「get_AreaCode」「get_SurfaceCode」「get_cvNo」)。
 また、行政区域(市区町村)情報クラスのインスタンス生成時には、既に登録済みであるかをチェックして重複登録を避けています(関数「existAreaCode」)。
 最終的に以下のようなコードでXML→MySQLへのデータ転記を実現出来ました。

<?php
   ini_set( 'error_reporting', ~E_WARNING ); 
   ini_set( 'memory_limit', '1024M' );
   set_time_limit(0);
   $errMsg;
   $mysqli = connectDBi($errMsg);
   if ($mysqli) {
      echo "MySQL接続OK<br>";
   } else {
      echo "MySQL接続NG<br>".$errMsg;
      exit();
   }
   echo str_pad(" ",4096)."<br>";

   for ($PrefCode = 1; $PrefCode <= 47; $PrefCode++) {
      $FileName = "xml/N03-13_" . sprintf("%02d",$PrefCode) . "_130401.xml";
      $xmlString = file_get_contents($FileName);
      $xmlString = preg_replace('/:/','_',$xmlString);
      $xmlData = simplexml_load_string($xmlString);
   
      $areaInfo = array();
      $aNo = 0;
      $surfaceInfo = array();
      $sNo = 0;
      foreach ($xmlData->ksj_AdministrativeArea as $data) {
         if (isset($data->ksj_aac) && isset($data->ksj_aac['codeSpace'])) {
            if (strlen((string)$data->ksj_aac) == 0) {
               $areaCode = intval($PrefCode."000");
            } else {
               $areaCode = (int)$data->ksj_aac;
            }
            if (!existAreaCode($areaInfo,$areaCode)) {
               $areaInfo[$aNo] = new AdministrativeArea;
               $areaInfo[$aNo]->AreaCode = $areaCode;
               $areaInfo[$aNo]->Prf = (string)$data->ksj_prn;
               $areaInfo[$aNo]->Sun = (string)$data->ksj_sun;
               $areaInfo[$aNo]->Con = (string)$data->ksj_con;
               $areaInfo[$aNo]->Cty = (string)$data->ksj_cn2;
               $aNo ++;
            }
            $surfaceInfo[$sNo] = new Surface;
            $surfaceInfo[$sNo]->AreaCode = $areaCode;
            $surfaceInfo[$sNo]->SurfaceCode = (int)str_replace("#sf","",$data->ksj_are['xlink_href']);
            $sNo ++;
         }
      }
   
      $curveInfo = array();
      $cNo = 0;
      foreach ($xmlData->gml_Surface as $gmlsf) {
         if (isset($gmlsf['gml_id'])) {
            $intSurface = (int)str_replace("sf","",$gmlsf['gml_id']);
            $areaCode = get_AreaCode($surfaceInfo,$intSurface);
            foreach ($gmlsf->xpath('gml_patches//gml_Ring/gml_curveMember') as $gmlcv) {
               if (isset($gmlcv['xlink_href'])) {
                  $curveInfo[$cNo] = new Curve;
                  $curveInfo[$cNo]->AreaCode = $areaCode;
                  $curveInfo[$cNo]->SurfaceCode = $intSurface;
                  $curveInfo[$cNo]->CurveCode = (int)substr($gmlcv['xlink_href'],strpos($gmlcv['xlink_href'],"_")+1);
                  $curveInfo[$cNo]->CurveID = (string)str_replace("#cv","",$gmlcv['xlink_href']);
                  $cNo ++;
               }
            }
         }
      }
   
      $pointInfo = array();
      $pNo = 0;
      foreach ($xmlData->gml_Curve as $gmlcv) {
         if (isset($gmlcv['gml_id'])) {
            $strCurveID = (string)str_replace("cv","",$gmlcv['gml_id']);
            $intCurve = (int)substr($strCurveID,strpos($strCurveID,"_")+1);
            $intSurface = get_SurfaceCode($curveInfo,$strCurveID);
            $areaCode = get_AreaCode($surfaceInfo,$intSurface);
            foreach ($gmlcv->gml_segments->gml_LineStringSegment->gml_posList as $posList) {
               $strlatlng = explode("\n", trim($posList));
               for ($pp = 0; $pp < count($strlatlng); $pp++) {
                  $latlng = explode(" ", trim($strlatlng[$pp]));
                  if (count($latlng) == 2) {
                     if (is_numeric($latlng[0]) && is_numeric($latlng[1])) {
                        $pointInfo[$pNo] = new Point;
                        $pointInfo[$pNo]->AreaCode = $areaCode;
                        $pointInfo[$pNo]->SurfaceCode = $intSurface;
                        $pointInfo[$pNo]->CurveCode = $intCurve;
                        $pointInfo[$pNo]->PointCode = $pp;
                        $pointInfo[$pNo]->Lat = $latlng[0];
                        $pointInfo[$pNo]->Lng = $latlng[1];
                        $pNo++;
                     }
                  }
               }
            }
         }
      }

      echo "Pref=".$PrefCode."<br>";
      echo "area count = ".count($areaInfo)."<br>";
      echo "surface count = ".count($surfaceInfo)."<br>";
      echo "curve count = ".count($curveInfo)."<br>";
      echo "point count = ".count($pointInfo)."<br>";
      ob_flush();
      flush();

      $strSQL = "INSERT INTO t_Prefecture (`PrefectureCode`,`PrefectureName`)";
      $strSQL .= " VALUES (".$PrefCode.",'".$areaInfo[0]->Prf."')";
      if ($mysqli) {
         if(!$mysqli->query($strSQL)){
            echo "失敗!". $strSQL ."<br>";
            exit();
         }
      }

      for ($i = 0; $i < count($areaInfo); $i++) {
         $strSQL = "INSERT INTO t_AdministrativeArea (`PrefectureCode`,`AdministrativeAreaCode`,`CityName`,`SubprefectureName`)";
         $strSQL .= " VALUES (".$PrefCode.",".$areaInfo[$i]->AreaCode.",'".$areaInfo[$i]->Con.$areaInfo[$i]->Cty."','".$areaInfo[$i]->Sun."')";
         if ($mysqli) {
            if(!$mysqli->query($strSQL)){
               echo "失敗!". $strSQL ."<br>";
               exit();
            }
         }
      }
   
      for ($i = 0; $i < count($surfaceInfo); $i++) {
         $strSQL = "INSERT INTO t_Surface (`PrefectureCode`,`AdministrativeAreaCode`,`SurfaceCode`)";
         $strSQL .= " VALUES (".$PrefCode.",".$surfaceInfo[$i]->AreaCode.",".$surfaceInfo[$i]->SurfaceCode.")";
         if ($mysqli) {
            if(!$mysqli->query($strSQL)){
               echo "失敗!". $strSQL ."<br>";
               exit();
            }
         }
      }
      
      for ($i = 0; $i < count($curveInfo); $i++) {
         $strSQL = "INSERT INTO t_Curve (`PrefectureCode`,`AdministrativeAreaCode`,`SurfaceCode`,`CurveCode`)";
         $strSQL .= " VALUES (".$PrefCode.",".$curveInfo[$i]->AreaCode.",".$curveInfo[$i]->SurfaceCode.",".$curveInfo[$i]->CurveCode.")";
         if ($mysqli) {
            if(!$mysqli->query($strSQL)){
               echo "失敗!". $strSQL ."<br>";
               exit();
            }
         }
      }
      
      for ($i = 0; $i < count($pointInfo); $i++) {
         $strSQL = "INSERT INTO t_Point (`PrefectureCode`,`AdministrativeAreaCode`,`SurfaceCode`,`CurveCode`,`PointNo`,`Lat`,`Lng`)";
         $strSQL .= " VALUES (".$PrefCode.",".$pointInfo[$i]->AreaCode.",".$pointInfo[$i]->SurfaceCode.",".$pointInfo[$i]->CurveCode;
         $strSQL .= ",".$pointInfo[$i]->PointCode.",".$pointInfo[$i]->Lat.",".$pointInfo[$i]->Lng.")";
         if ($mysqli) {
            if(!$mysqli->query($strSQL)){
               echo "失敗!". $strSQL ."<br>";
               exit();
            }
         }
      }
   }

   if ($mysqli) {
      $mysqli->close();
   }

   echo "終了しました。<br>";

   ini_restore('error_reporting'); 
   ini_restore('memory_limit');

   function get_AreaCode($surfaceinfo,$sfCode) {
      for ($i = 0; $i < count($surfaceinfo); $i++) {
         if ($surfaceinfo[$i]->SurfaceCode == $sfCode) {
            return $surfaceinfo[$i]->AreaCode;
         }
      }
      return null;
   }

   function get_SurfaceCode($curveinfo,$cvID) {
      for ($i = 0; $i < count($curveinfo); $i++) {
         if ($curveinfo[$i]->CurveID == $cvID) {
            return $curveinfo[$i]->SurfaceCode;
         }
      }
      return null;
   }

   function get_cvNo($cvCode,$curveinfo) {
      $strCurve = (string)str_replace("cv","",$cvCode);
      $intCurve = (int)substr($strCurve,0,strpos($strCurve,"_"));
      $intCurveSub = (int)substr($strCurve,strpos($strCurve,"_")+1);
      for ($i = 0; $i < count($curveinfo); $i++) {
         if ($curveinfo[$i]->CurveCode == $intCurve && $curveinfo[$i]->CurveCodeSub == $intCurveSub) {
            return $i;
         }
      }
      return -1;
   }

   function existAreaCode($areaInfo,$areaCode) {
      for ($i = 0; $i < count($areaInfo); $i++) {
         if ($areaInfo[$i]->AreaCode == $areaCode) {
            return true;
         }
      }
      return false;
   }

   //行政区域(市区町村)情報 
   class AdministrativeArea {
     public $AreaCode;    //行政区域コード(全国地方公共団体コード)
     public $Prf;         //都道府県名
     public $Sun;         //支庁名(北海道のみ)
     public $Con;         //郡・政令市名
     public $Cty;         //市区町村名
   }

   //領域面情報
   class Surface {
     public $AreaCode;        //行政区域コード(全国地方公共団体コード)
     public $SurfaceCode = 0; //領域面コード
   }

   //境界線情報
   class Curve {
     public $AreaCode;        //行政区域コード(全国地方公共団体コード)
     public $SurfaceCode = 0; //領域面コード
     public $CurveCode = 0;   //境界線コード  外輪線=0 内輪腺>0
     public $CurveID;         //境界線ID(照合用文字列)
   }

   //点情報
   class Point {
     public $AreaCode;        //行政区域コード(全国地方公共団体コード)
     public $SurfaceCode = 0; //領域面コード
     public $CurveCode = 0;   //境界線コード
     public $PointCode = 0;   //点コード
     public $Lat;             //緯度
     public $Lng;             //経度
   }

   //MySQLへ接続
   function connectDBi(&$err) {

     //MySQL 接続情報
     $MySQL_SERVER = "サーバー名";
     $MySQL_USER = "ユーザー名";
     $MySQL_PASSWORD = "パスワード";
     $MySQL_DBNAME = "データベース名";

     $err = "";
     $mysqli = new mysqli($MySQL_SERVER, $MySQL_USER, $MySQL_PASSWORD, $MySQL_DBNAME);
     if ($mysqli->connect_errno) {
        $err = "データベース接続に失敗しました。";
     } else {
        //文字化け対策
        if (!$mysqli->set_charset("utf8")) {
           $err = "文字コードセットに失敗しました。";
        }
     }
     if (strlen($err) > 0) {
        return false;
     } else {
        return $mysqli;
     }
   }
?>

 
 かなり重い処理になるので、
  ini_set( ‘memory_limit’, ‘1024M’ ); (2行目) 
 とメモリを大量に確保しましたが、使用のサーバ環境によってはメモリ容量を十分に確保出来ず、処理を分ける必要があるかもしれません。
 点情報(テーブル:t_Point)のレコード数は、なんと9,594,268。これだけで600MBオーバーとなりました。ここまで巨大なテーブルですと、この後の都道府県境のピックアップ処理に支障をきたしそうなので分割した方が良さそうですが、それは次回に・・・。
 なお、今回取得したデータの検証を兼ねて、選択した市区町村の範囲をポリゴン表示させる地図をGoogleMapsAPIにて作成してみました(MAP表示)。データが1,000万近くあるので固まってしまうかと心配しましたが、思ったよりも速く表示出来ています。ただし、東京都小笠原村や長崎県対馬市など、データ点数の多い市区町村の描画には時間がかかります。
 広島県尾道市のような島がたくさんあるケースでもきちんと表示(図-3)。また、前述した東京都小金井市(区域内に他市区町村の飛び地があるケース)も、図-4のとおり府中市の飛び地が中抜け表示されました。

複数領域のケース(広島県尾道市)

図-3 選択した市区町村の範囲をポリゴン表示
複数領域のケース(広島県尾道市)

領域内に他市区町村の飛び地があるケース(東京都小金井市)

図-4 選択した市区町村の範囲をポリゴン表示
領域内に他市区町村の飛び地があるケース(東京都小金井市)

コメント   

 2014年5月25日(日)
 地元の府中市美術館で現在開催中の展覧会は「東京・ソウル・台北・長春—官展にみる近代美術」。本展は会期が1ヶ月弱と短いので「忘れないうちに・・・」と散歩がてら観覧してきました。

府中市美術館


 東京、ソウル、台北、長春(旧満州国)の4都市で開催された公募展の入選作や馴染みの深い画家の作品を紹介するというユニークな展覧会です。
 世界的には有名でなくても素晴らしい作品を残している近代日本画家は大勢いて、勉強不足の私にとっては「こんな素晴らしい画家がいたのか」という発見の連続なわけですが、「同じように韓国(朝鮮)や台湾、中国にも優れた画家は多数いるはず・・・」との予想通り、素晴らしい作品にたくさん出会えました。
 いずれの官展も日本統治下で開催されたもので主に日本の画家が審査員を務めていたようですが、だからといって日本の画壇の流儀を強制しているような雰囲気は全く感じられなかったので、政治的な背景は考えずに単純に秀逸な絵画として展示作品を楽しむことが出来ました。

承徳喇嘛廟
<安井曾太郎>


窓辺
<イ・インソン(李仁星)>


初秋
<チェン・チェンボー(陳澄波)>


 これら官展で名をあげた画家たちは、それぞれの本国ではどのような評価を受けているのか気になる所です。
 日曜日なのに会場はガラガラでした。結構良い展覧会だと思うんですけど・・・。6月8日(日)まで。

コメント