都道府県別の統計データをもとに色分けされた地図を、新聞・雑誌や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日(日)まで。

 2014年4月26日(土)
 ちょうど1年ぶりに埼玉県立近代美術館へ。昨秋より改修工事のため休館していましたが、この4月にリニューアルオープンしました。

埼玉県立近代美術館

埼玉県立近代美術館


 外見は全く変わっていない模様・・・館内もほとんど変わりがないように見えましたが、広報誌によればトイレと常設展示室の改修を行ったとのことです。

 まずは、特別展「ピカソの陶芸」を観覧。先週は版画、今回は陶芸とピカソの連チャンです。

「ピカソの陶芸」ちらし

「ピカソの陶芸」ちらし

 陶芸にはあまり興味がなかったのですが、ピカソの作品は何とも味のある独特な作品ばかりで楽しめました。ピカソはキプロスの青銅器など古代の陶器の影響を受けたのこと。岡本太郎も縄文土器に強い影響を受けたようですし、先史美術は芸術家にインスピレーションを与える「何か」を持っているのでしょうね。
 なお、当特別展に出品されている陶芸作品は全てヨックモック所蔵だそうです。
 葉巻の形をした「シガール」で有名な洋菓子店・・・外国の会社かと思ってましたが、調べてみたら日本生まれのお菓子屋さんでした。
 
 ピカソの後は、一般展示室の「埼玉女流工芸展」へ。3年連続の観覧となりますが、今年も質の高い出展作品が多数。
 その中でも、一番素晴らしいと感じたのは押し花の「Journey」という作品(新井小百合さん作)。しばらくの間、見とれてしまいました。

Journey(押し花)<新井小百合さん作>

Journey(押し花)
<新井小百合さん作>


 後藤あんなさん作(昨年も素晴らしい作品を出展されていました)のガラス細工も美しい逸品。
花に抱かれて(ガラス)<後藤あんなさん作>

花に抱かれて(ガラス)
<後藤あんなさん作>


 
 
 ここの美術館を訪問した後は、いつも東口の喫茶店「エーデル2」でのオムライスが定番化しているのですが、今回初めてオムライス以外のもの(ハンバーグ)を注文してみました。
ハンバーグ

ハンバーグ


 厨房からは焼く音が聞こえてこなかったので煮込みハンバーグになるのでしょうか? 不味くはなかったですが、微妙・・・。やっぱりオムライスにしておけば良かった ^^;
 ガンバレ、昔ながらの喫茶店!

 2013年4月23日(水)
 上野の国立博物館で開催中の特別展「栄西と建仁寺」。休日だと大混雑でしょうし、行列に並ぶのは好きでないので予定に入れていなかったのですが、思いがけず平日に都内で時間が空いたので急遽観覧することに。

 目的はもちろん俵屋宗達の「風神雷神図屏風」。何といっても国宝、それも誰もが知っているような超有名作品ですから。印刷物等では何度も見ていますが、やはり本物を生で見られるのは嬉しい限り。
 相対する風神と雷神の、お互いに力を鼓舞するのを楽しんでいるかのような表情がたまりません。解説には「雷神は赤で描かれるのが通例だったが、白で描くことで両者の対比を明確にした」といったようなことが記載されていましたが、確かに金地には赤よりも白で描いた方が存在感が際立つように思います。

風神雷神図屏風
<俵屋宗達>


 この「国宝中の国宝」が見られただけでも十分満足なのですが、この展覧会はそれだけにはとどまりません。風神雷神の陰で脇役に追いやられてしまった作品の中にも、通常の展覧会ならば目玉となってもおかしくない大作・逸品がズラリ!
 中でも、海北友松の「雲龍図」は大迫力。雲龍図といえば、一昨年にやはり同じ国立博物館で観覧した曽我蕭白のものが思い出されますが、蕭白のものは胴体部分が欠損していることもあり、今回の友松作品の方により魅力を感じました。

雲龍図(右4幅)
<海北友松>


雲龍図(左4幅)
<海北友松>


 得意の鶏を描いた伊藤若冲の「雪梅雄鶏図」もお見事!

雪梅雄鶏図
<伊藤若冲>


 本特別展のタイトルにもなっている栄西(「ようさい」と読むようです)の関連の作品もいろいろ。どの作品にも詳しく解説があり、「書は何が書かれているのか良く分からず、僧の坐像はあまり興味なし、茶碗等の器に関する知識は全くない・・・」といった私にも優しい展示で勉強になりました。現物よりも解説を見る方が主になってしまいましたが・・・。

 また、本展(平成館)とは別に、本館には尾形光琳の「風神雷神図屏風」も展示されていました。こちらは国宝ではなく重要文化財ですが、よく考えたら模写なのに重要文化財って凄いことです。やはり素晴らしい作品で、私なんかには宗達作との優劣なんてつけられません。
 その他、上村松園の「焔」や菱田春草の「梨に双鳩」などの大作が何でもないかのように展示されていました。さすがは国立博物館です。

 本特別展「栄西と建仁寺」は5月18日(日)まで開催されますが、途中展示替えがあり海北友松の「雲龍図」の左幅・右幅を揃って観覧出来るのは5月6日(火)まで。
 なお、昨日から公開の「キトラ古墳壁画」は70分待ちとのことで断念。こちらは、いつの日か明日香村へ見に行ければ・・・。

 2014年4月19日(土)
 ピカソの版画を集めた展覧会「パブロ・ ピカソ ―版画の線とフォルム―」の観覧に町田市立国際版画美術館へ。この日は開館記念日とのことで、入場無料でした。

町田市立国際版画美術館

 展示作品はモノクロのものが多いですが、さすが多才なピカソだけあって代名詞ともいえるキュビズム作品を始め、いろいろな作風の版画を楽しめました。
 技法もエッチング、ドライポイント、リノカット、リトグラフ・・・とさまざま。

 中でもピカソが好んだモチーフの1つ「鳩」を描いた作品は、愛情がたっぷり注がれている感じで実に味わい深いものでした。

 当展覧会は6月15日(日)まで。作品の一部は展示替えがあるようです(前期は5月11日まで)。

 なお、版画ではありませんが、特別出品されていた陶芸作品(皿)にも惹かれました。現在、埼玉県立近代美術館で「ピカソの陶芸」展が開催されているので、そちらにも行きたくなりました。

 2014年4月13日(日)
 小さいながらも趣向を凝らした企画展を開催して頑張っている印象の三鷹市美術ギャラリーへ、「華麗なるインド」以来約1年ぶりに訪問。
 昨日から始まった「マリー・ローランサン展 ~女の一生~」を観覧してきました。
 
 ローランサンの絵はポスターなどで目にする機会は多いのですが、本物の作品をまとめて観覧するのは今回が初めて。油彩でありながら水彩画かと思うような淡く優しいタッチ。パステルカラーが特徴ですが、中でも黄色の使い方が印象的でした。
 もう少し作品解説が充実していると嬉しかったのですが、パリの印象そのままの簡潔ながら洗練された作品の数々を楽しめました。

 なお、マリー・ローランサン美術館というのが長野県の蓼科にあったことも、2年半前に閉館してしまったことも、今回初めて知りました。こういった、画家本人と特に縁があるわけでもない観光地の美術館の運営は、今後まずます苦しくなるでしょうねえ・・・。

 当展覧会は6月22日(日)まで。観覧料は600円ですが、当美術館サイトより割引券を印刷して持参すると480円になります。

「マリー・ローランサン展 ~女の一生~」ちらし

荒川沿いにある、さくら草公園(さいたま市桜区)へ。
サクラソウはどこにでも咲いてそうなイメージだったのですが、実は希少種でここ(田島ヶ原サクラソウ自生地)は日本唯一のまとまった群生地だとのこと。特別天然記念物に指定されています。

ちなみに「さいたま市桜区」の名称は、このサクラソウに由来するのだとか・・・。

サクラソウ(1)

サクラソウ(1)

サクラソウ(2)

サクラソウ(2) 花びらの形が特徴的

サクラソウ(2)

サクラソウ(3) お菓子のような手裏剣のような・・・

ノウルシ

ノウルシ

サクラソウ・ノウルシ

一面ノウルシの中、所々にサクラソウ

サクラソウとノウルシ

サクラソウとノウルシ

特別天然記念物の石碑

特別天然記念物の石碑

3月30日(日)
府中市美術館の特別展「江戸絵画の19世紀」を観覧してきました。

この時期の恒例となっている「春の江戸絵画まつり」企画ですが、今回はタイトルから分かる通り江戸時代の中でも後期~晩期に当たる19世紀に時期を絞ったもの。狩野探幽、尾形光琳、円山応挙、伊藤若冲、曽我蕭白といった画家は対象外です。有名処では鈴木其一と谷文晁くらいで、随分と地味な印象です。浮世絵画家は北斎・広重・国芳と揃っていますが、今年は「大浮世絵展」をはじめ各地で浮世絵展が開かれているので、いまいちありがたみに欠けてしまいます。

構成もどうも中途半端な印象で、これだったらいっそのこと一人か二人の画家に焦点を当てた企画にした方が統一感が出て良かったのではないかと思います。
昨秋の特別展(ウイリアムモリス展)もかなり例年より地味でしたし、予算が削られているのだろうか?と心配になってしまいます。今秋には府中市制60周年記念の「ミレー展」が開催されるので、それを盛大にするための節約ということであれば良いのですが・・・。

休日でも比較的空いている当美術館ですが、この日は春の嵐のせいかガラガラでした。
本特別展は前後期制で前期は4月13日(日)まで。後期展示は4月15日(火)~5月6日(火)

「江戸絵画の19世紀」ちらし

城山かたくりの里に行った後、同じ神奈川県だからと橋本から横浜へ移動。横浜線で1本ですが、結構時間がかかりました。横浜高島屋の「川瀬巴水展 -郷愁の日本風景-」へ。

大正から戦後くらいまでの日本の風景を描いた作品の数々。実際には見たことはない風景なのですが、懐かしさを感じずにはいられないのが巴水作品の魅力。特に東京を描いた作品などは「わずか100年程度前に本当にこんな所はあったのか?」と思ってしまいます。それだけ変遷が速いんでしょう・・・今の東京の姿も100年後には「昔はこんなだったのか!」と言われるくらいにいうくらいに変わってしまうのでしょうかね?

巴水作品は、昼や夕刻を描いたものも色鮮やかで素晴らしいのですが、夜や雪を描いたものの方が風情があってより魅力的だと個人的には思います。

場所柄、買い物ついでに立ち寄った観覧客も多いようで結構賑わっていました。そんな客層のせいなのか、作品の真ん前でスマホをいじってたり、ガラスで保護されているとはいえ作品に触れてしまったり・・・とマナーの悪い人が散見されたのが何とも残念でした。
会期は3月31日(月)まで。わずか2週間足らずというのは短すぎです。

雪に暮るゝ寺島村 東京十二題

雪に暮るゝ寺島村 東京十二題

出雲松江(三ヶ月) 旅みやげ第三集

出雲松江(三ヶ月) 旅みやげ第三集

芝増上寺 東京二十景

芝増上寺 東京二十景

亀戸の藤

亀戸の藤

京都清水寺 日本風景集Ⅱ 関西篇

京都清水寺 日本風景集Ⅱ 関西篇

佃住吉神社 新東京百景

佃住吉神社 新東京百景

木曾の須原 日本風景選集

木曾の須原 日本風景選集

清洲橋

清洲橋

富士川

富士川

箱根宮の下富士屋ホテル(冬)

箱根宮の下富士屋ホテル(冬)

北日本は大雪だったようで北風が強い一日でしたが、春分の日ということで、春を感じに相模原市の城山かたくりの里へ。
今年の冬は寒かったせいか、目当てにしていたカタクリ(ニホンカタクリ)はまだ咲き初め。見頃は来月になるかと思いますが、雪割草や福寿草など、きっと道端に咲いていても気づかないような小さくて可愛い花々にほっこり気分にさせられました。

カタクリ(1)

カタクリ(1)

カタクリ(2)

カタクリ(2)

福寿草

福寿草

バイカオウレン

バイカオウレン

雪割草(1)

雪割草(1)

雪割草(2)

雪割草(2)

菊咲イチゲ(1)

菊咲イチゲ(1)

菊咲イチゲ(2)

菊咲イチゲ(2)

豊後梅

豊後梅

玄海ツツジ

玄海ツツジ

ミツマタ

ミツマタ

東イチゲ

東イチゲ

アセビ(馬酔木)

アセビ(馬酔木)

桜玄海ツツジ

桜玄海ツツジ