ひつじかいさんの「ひつじかいの雑記帳」というブログを拝見し、その中に、地図の描写において色々と興味深い記事を拝読しました。これは自分でもやってみたい、そう思い、その記録を記載してみたいと思います。
Web上で操作可能な日本の白地図(都道府県別)を作る(6) ― データをGeoJSON形式にする ―
今回はMySQLのデータをGeoJSONコードに落として、DBを使わず、スタンドアロンでも使用できるようにします。なお現在、国土数値情報でもGeoJSON形式でデータが公開されているようです。
データはMultiPolygonとして、次の様式です。
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {
"prefcode": "1",
"prefname": "北海道"
},
"geometry": {
"type": "MultiPolygon",
"coordinates": [
[
[
[141.883998, 45.496344],
[141.878319, 45.488176],
…,
[141.883998, 45.496344],
[141.883998, 45.496344]
]
],
[
[
[141.188495,45.2545],
[141.178855,45.24859],
…,
[141.197514,45.258546],
[141.188495,45.2545]
]
],
…
]
}
},{
"type": "Feature",
"properties": {
"prefcode": "2",
"prefname": "青森県"
},
"geometry": {
"coordinates": [
…
]
}
}
…
]
}その上で、次のプログラムを実行させました。GeoJSONファイルは生成されるのですが、白地図が表示できません。症状としては、北海道から秋田県(05)までは表示されるのですが、山形県(06)を加えると表示されなくなります。ひつじかいさんのブログにある[blankmap.zip]では正しく表示されるのに、自分の環境で生成したGeoJSONファイルでは表示されません。
<?php
$errMsg;
$mysqli = connectDBi($errMsg);
if ($mysqli) {
echo "MySQL接続OK<br>";
} else {
echo "MySQL接続NG<br>" . $errMsg;
exit();
}
$fc = new FeatureCollection;
$d2 = 0; // 配列coordinatesの第2層の要素。ポリゴンに穴がある場合は$d2>0となるが、今回扱うデータには存在しないため0で固定
// for ($PrefCode = 1; $PrefCode <= 47; $PrefCode++) {
for ($PrefCode = 1; $PrefCode <= 5; $PrefCode++) {
$formerPoint = null;
$feature = new Feature;
$strSQL = "SELECT t_JapanPrefectureBorder.*, t_Prefecture.PrefectureName";
$strSQL .= " FROM t_JapanPrefectureBorder";
$strSQL .= " INNER JOIN t_Prefecture";
$strSQL .= " ON t_JapanPrefectureBorder.PrefectureCode = t_Prefecture.PrefectureCode";
$strSQL .= " WHERE t_JapanPrefectureBorder.PrefectureCode = " . $PrefCode; $strSQL .= " ORDER BY BorderCode, PointNo DESC";
$rst = $mysqli->query($strSQL);
while($col = $rst->fetch_array(MYSQLI_ASSOC)) {
if (!isset($formerPoint)) {
$cNo = 0;
$feature->properties = new PrefInfo($col);
$feature->geometry = new Geometry("MultiPolygon");
} else if ($formerPoint["BorderCode"]<>$col["BorderCode"]) {
$cNo ++;
}
if (!isset($feature->geometry->coordinates[$cNo])) {
$feature->geometry->coordinates[$cNo][$d2] = array();
}
array_push($feature->geometry->coordinates[$cNo][$d2],array(floatval($col["Lng"]),floatval($col["Lat"])));
$formerPoint = $col;
}
$rst->close();
array_push($fc->features,$feature);
}
if ($mysqli) {
$mysqli->close();
}
$geojson = json_encode($fc);
$geojson = str_replace("}},","}},\n",$geojson);
echo $geojson . "<br>";
$path = "json/PrefectureBorder.json";
$fp = fopen($path,'w');
fwrite($fp, $geojson);
fclose($fp);
echo "終了しました。";
class FeatureCollection {
public $type = "FeatureCollection";
public $features = array();
}
class Feature {
public $type = "Feature";
public $properties;
public $geometry;
}
class Geometry {
public $type;
public $coordinates = array();
function __construct($type=""){
$this->type = $type;
}
}
class PrefInfo {
public $prefcode;
public $prefname;
function __construct($p){
$this->prefcode = $p["PrefectureCode"];
$this->prefname = $p["PrefectureName"];
}
}
//MySQLへ接続
function connectDBi(&$err)
{
//MySQL 接続情報
$MySQL_SERVER = "localhost";
$MySQL_USER = "[user_name]";
$MySQL_PASSWORD = "[password]";
$MySQL_DBNAME = "map";
$err = "";
$mysqli = new mysqli($MySQL_SERVER, $MySQL_USER, $MySQL_PASSWORD, $MySQL_DBNAME);
if ($mysqli->connect_errno) {
$err = "データベース接続に失敗しました。";
}
if (strlen($err) > 0) {
return false;
} else {
return $mysqli;
}
}
※06の山形県を加えるとすべて表示されなくなる。
データを確認すると、”coordinates”の最初と最後のデータが一致している必要があるのですが、どうもそれが一致していないようです。そこで”coordinates”の最初と最後のデータを比較し、異なるようであれば最後のデータに最初のデータを付け加えるようプログラムを少し変更してみました。
<?php
$errMsg;
$mysqli = connectDBi($errMsg);
if ($mysqli) {
echo "MySQL接続OK<br>";
} else {
echo "MySQL接続NG<br>" . $errMsg;
exit();
}
$fc = new FeatureCollection;
$d2 = 0; // 配列coordinatesの第2層の要素。ポリゴンに穴がある場合は$d2>0となるが、今回扱うデータには存在しないため0で固定
for ($PrefCode = 1; $PrefCode <= 47; $PrefCode++) {
$formerPoint = null;
$feature = new Feature;
$strSQL = "SELECT t_JapanPrefectureBorder.*, t_Prefecture.PrefectureName";
$strSQL .= " FROM t_JapanPrefectureBorder";
$strSQL .= " INNER JOIN t_Prefecture";
$strSQL .= " ON t_JapanPrefectureBorder.PrefectureCode = t_Prefecture.PrefectureCode";
$strSQL .= " WHERE t_JapanPrefectureBorder.PrefectureCode = " . $PrefCode;
$strSQL .= " ORDER BY BorderCode, PointNo DESC";
$rst = $mysqli->query($strSQL);
while ($col = $rst->fetch_array(MYSQLI_ASSOC)) {
if (!isset($formerPoint)) {
$cNo = 0;
$feature->properties = new PrefInfo($col);
$feature->geometry = new Geometry("MultiPolygon");
} else if ($formerPoint["BorderCode"] <> $col["BorderCode"]) {
//! 最初と最後のデータを確認する...
if ($tmp1 <> $tmp2){
array_push($feature->geometry->coordinates[$cNo][$d2], $tmp1);
}
$cNo++;
}
if (!isset($feature->geometry->coordinates[$cNo])) {
$feature->geometry->coordinates[$cNo][$d2] = array();
$tmp1 = array(floatval($col["Lng"]), floatval($col["Lat"]));
}
$tmp2 = array(floatval($col["Lng"]), floatval($col["Lat"]));
array_push($feature->geometry->coordinates[$cNo][$d2], $tmp2);
$formerPoint = $col;
}
//! 最初と最後のデータを確認する...
if ($tmp1 <> $tmp2){
array_push($feature->geometry->coordinates[$cNo][$d2], $tmp1);
}
$rst->close();
array_push($fc->features, $feature);
}
if ($mysqli) {
$mysqli->close();
}
$geojson = json_encode($fc);
$geojson = str_replace("}},", "}},\n", $geojson);
echo $geojson . "<br>";
$path = "json/PrefectureBorder.json";
$fp = fopen($path, 'w');
fwrite($fp, $geojson);
fclose($fp);
echo "終了しました。";
class FeatureCollection
{
public $type = "FeatureCollection";
public $features = array();
}
class Feature
{
public $type = "Feature";
public $properties;
public $geometry;
}
class Geometry
{
public $type;
public $coordinates = array();
function __construct($type = "")
{
$this->type = $type;
}
}
class PrefInfo
{
public $prefcode;
public $prefname;
function __construct($p)
{
$this->prefcode = $p["PrefectureCode"];
$this->prefname = $p["PrefectureName"];
}
}
//MySQLへ接続
function connectDBi(&$err)
{
//MySQL 接続情報
$MySQL_SERVER = "localhost";
$MySQL_USER = "[user_name]"";
$MySQL_PASSWORD = "[password]";
$MySQL_DBNAME = "map";
$err = "";
$mysqli = new mysqli($MySQL_SERVER, $MySQL_USER, $MySQL_PASSWORD, $MySQL_DBNAME);
if ($mysqli->connect_errno) {
$err = "データベース接続に失敗しました。";
}
if (strlen($err) > 0) {
return false;
} else {
return $mysqli;
}
}
これで正常に表示されるようになりました。


