国土数値地理情報から白地図を作る。3

前回までで各県の輪郭は作れる様になりました。前の記事では北海道だけやりましたが、これを47都道府県全てを対象に行います。そして描画のたび毎にこの処理を毎回やるのは時間がかかりすぎます。そこで計算結果をXMLに書き出す事にします。日本地図を描画するには新しく作るXMLから読み出してSVGに描画という流れにします。

1. ディレクトリの準備

SVGを保存するSVGフォルダ、XMLを保存するXMLフォルダを用意します。ディレクトリは次の様になります。

国土数値情報行政区域フォルダにはダンロードしたデータが入っています。SVGとXMLは空のフォルダでplotPrefData3.phpを走らせると各県のSVGとXMLが保存されます。

2. XMLを作成するPHP

plotPrefData3.php

<?php
//ダウンロードした数値地図から都道府県の輪郭のXMLを作成するためのPHP

$startTime = microtime(true);

ini_set('memory_limit', '640M');

mb_language("Japanese");//文字コードの設定
mb_internal_encoding("UTF-8");

$loadXML[1] = "./国土数値情報行政区域/N03-170101_01_GML/N03-17_01_170101.xml"; $saveFile[1] ="hokkaido";
$loadXML[2] = "./国土数値情報行政区域/N03-170101_02_GML/N03-17_02_170101.xml"; $saveFile[2] ="aomori";
$loadXML[3] = "./国土数値情報行政区域/N03-170101_03_GML/N03-17_03_170101.xml"; $saveFile[3] ="iwate";
$loadXML[4] = "./国土数値情報行政区域/N03-170101_04_GML/N03-17_04_170101.xml"; $saveFile[4] ="miyagi";
$loadXML[5] = "./国土数値情報行政区域/N03-170101_05_GML/N03-17_05_170101.xml"; $saveFile[5] ="akita";
$loadXML[6] = "./国土数値情報行政区域/N03-170101_06_GML/N03-17_06_170101.xml"; $saveFile[6] ="yamagata";
$loadXML[7] = "./国土数値情報行政区域/N03-170101_07_GML/N03-17_07_170101.xml"; $saveFile[7] ="fukushima";
$loadXML[8] = "./国土数値情報行政区域/N03-170101_08_GML/N03-17_08_170101.xml"; $saveFile[8] ="ibaraki";
$loadXML[9] = "./国土数値情報行政区域/N03-170101_09_GML/N03-17_09_170101.xml"; $saveFile[9] ="tochigi";
$loadXML[10] = "./国土数値情報行政区域/N03-170101_10_GML/N03-17_10_170101.xml"; $saveFile[10] ="gunnma";
$loadXML[11] = "./国土数値情報行政区域/N03-170101_11_GML/N03-17_11_170101.xml"; $saveFile[11] ="saitama";
$loadXML[12] = "./国土数値情報行政区域/N03-170101_12_GML/N03-17_12_170101.xml"; $saveFile[12] ="chiba";
$loadXML[13] = "./国土数値情報行政区域/N03-170101_13_GML/N03-17_13_170101.xml"; $saveFile[13] ="tokyo";
$loadXML[14] = "./国土数値情報行政区域/N03-170101_14_GML/N03-17_14_170101.xml"; $saveFile[14] ="kanagawa";
$loadXML[15] = "./国土数値情報行政区域/N03-170101_15_GML/N03-17_15_170101.xml"; $saveFile[15] ="niigata";
$loadXML[16] = "./国土数値情報行政区域/N03-170101_16_GML/N03-17_16_170101.xml"; $saveFile[16] ="toyama";
$loadXML[17] = "./国土数値情報行政区域/N03-170101_17_GML/N03-17_17_170101.xml"; $saveFile[17] ="isihikawa";
$loadXML[18] = "./国土数値情報行政区域/N03-170101_18_GML/N03-17_18_170101.xml"; $saveFile[18] ="fukui";
$loadXML[19] = "./国土数値情報行政区域/N03-170101_19_GML/N03-17_19_170101.xml"; $saveFile[19] ="yamanashi";
$loadXML[20] = "./国土数値情報行政区域/N03-170101_20_GML/N03-17_20_170101.xml"; $saveFile[20] ="nagano";
$loadXML[21] = "./国土数値情報行政区域/N03-170101_21_GML/N03-17_21_170101.xml"; $saveFile[21] ="gifu";
$loadXML[22] = "./国土数値情報行政区域/N03-170101_22_GML/N03-17_22_170101.xml"; $saveFile[22] ="sizuoka";
$loadXML[23] = "./国土数値情報行政区域/N03-170101_23_GML/N03-17_23_170101.xml"; $saveFile[23] ="aiti";
$loadXML[24] = "./国土数値情報行政区域/N03-170101_24_GML/N03-17_24_170101.xml"; $saveFile[24] ="mie";
$loadXML[25] = "./国土数値情報行政区域/N03-170101_25_GML/N03-17_25_170101.xml"; $saveFile[25] ="shiga";
$loadXML[26] = "./国土数値情報行政区域/N03-170101_26_GML/N03-17_26_170101.xml"; $saveFile[26] ="kyoto";
$loadXML[27] = "./国土数値情報行政区域/N03-170101_27_GML/N03-17_27_170101.xml"; $saveFile[27] ="osaka";
$loadXML[28] = "./国土数値情報行政区域/N03-170101_28_GML/N03-17_28_170101.xml"; $saveFile[28] ="hyougo";
$loadXML[29] = "./国土数値情報行政区域/N03-170101_29_GML/N03-17_29_170101.xml"; $saveFile[29] ="nara";
$loadXML[30] = "./国土数値情報行政区域/N03-170101_30_GML/N03-17_30_170101.xml"; $saveFile[30] ="wakayama";
$loadXML[31] = "./国土数値情報行政区域/N03-170101_31_GML/N03-17_31_170101.xml"; $saveFile[31] ="tottori";
$loadXML[32] = "./国土数値情報行政区域/N03-170101_32_GML/N03-17_32_170101.xml"; $saveFile[32] ="shimane";
$loadXML[33] = "./国土数値情報行政区域/N03-170101_33_GML/N03-17_33_170101.xml"; $saveFile[33] ="okayama";
$loadXML[34] = "./国土数値情報行政区域/N03-170101_34_GML/N03-17_34_170101.xml"; $saveFile[34] ="hiroshima";
$loadXML[35] = "./国土数値情報行政区域/N03-170101_35_GML/N03-17_35_170101.xml"; $saveFile[35] ="yamaguchi";
$loadXML[36] = "./国土数値情報行政区域/N03-170101_36_GML/N03-17_36_170101.xml"; $saveFile[36] ="tokushima";
$loadXML[37] = "./国土数値情報行政区域/N03-170101_37_GML/N03-17_37_170101.xml"; $saveFile[37] ="kagawa";
$loadXML[38] = "./国土数値情報行政区域/N03-170101_38_GML/N03-17_38_170101.xml"; $saveFile[38] ="ehime";
$loadXML[39] = "./国土数値情報行政区域/N03-170101_39_GML/N03-17_39_170101.xml"; $saveFile[39] ="kouchi";
$loadXML[40] = "./国土数値情報行政区域/N03-170101_40_GML/N03-17_40_170101.xml"; $saveFile[40] ="fukuoka";
$loadXML[41] = "./国土数値情報行政区域/N03-170101_41_GML/N03-17_41_170101.xml"; $saveFile[41] ="saga";
$loadXML[42] = "./国土数値情報行政区域/N03-170101_42_GML/N03-17_42_170101.xml"; $saveFile[42] ="nagasaki";
$loadXML[43] = "./国土数値情報行政区域/N03-170101_43_GML/N03-17_43_170101.xml"; $saveFile[43] ="kumamoto";
$loadXML[44] = "./国土数値情報行政区域/N03-170101_44_GML/N03-17_44_170101.xml"; $saveFile[44] ="ooita";
$loadXML[45] = "./国土数値情報行政区域/N03-170101_45_GML/N03-17_45_170101.xml"; $saveFile[45] ="miyazaki";
$loadXML[46] = "./国土数値情報行政区域/N03-170101_46_GML/N03-17_46_170101.xml"; $saveFile[46] ="kagoshima";
$loadXML[47] = "./国土数値情報行政区域/N03-170101_47_GML/N03-17_47_170101.xml"; $saveFile[47] ="okinawa";

for ($i = 1  ; $i<47+1 ; $i++){
  $saveSVG= "./SVG/" . $saveFile[$i] . ".svg";//SVGファイルのファイル名
  $saveXML= "./XML/" . $saveFile[$i] . ".xml";//xmlファイル
  print("file=".$saveFile[$i] ."\n");
  loadXMLsaveSVGXML($loadXML[$i],$saveXML,$saveSVG);
}

$endTime = microtime(true);
$exeTime = $endTime - $startTime;
print("exe Time=".$exeTime . "\n");


function loadXMLsaveSVGXML($loadXML,$saveXML,$saveSVG){
  $startTime = microtime(true);
  //重複したデータを配列から取り除き県境と海岸線だけのデータにする。
  //数が10個(?)以下のデータは削除。小さい小島とかは省略する。

  print("XML file loading...");
  $dom = new DOMDocument('1.0', 'UTF-8');
  $dom->preserveWhiteSpace = false;
  $dom->formatOutput = true;
  $dom->load($loadXML);

  $root = $dom->getElementsByTagName("*")->item(0);//最初の要素の中身を取り出す

  $i = 0;
  foreach( $root->getElementsByTagNameNS("*","Curve") as $itemGML ){//これでgml:Curveのところが取れるらしい。
    $dataArray = explode("\n",$itemGML->nodeValue);//改行コードで配列にわける

    $j=0;
    foreach ($dataArray as $item) {//各要素ごとに繰り返す
      $item = trim($item);
      if($item != ""){//空白文字列の時には処理をしない。
        $coordinate[$i][$j]=$item;
        $j++;
      }
    }
    $i++;
  }


  $i = 0;
  foreach( $root->getElementsByTagNameNS("*","Curve") as $itemGML ){//これでgml:Curveのところが取れるらしい。
    $dataArray = explode("\n",$itemGML->nodeValue);//改行コードで配列にわける

    $j=0;
    foreach ($dataArray as $item) {//各要素ごとに繰り返す
      $item = trim($item);
      if($item != ""){//空白文字列の時には処理をしない。
        $coordinate[$i][$j]=$item;
        $j++;
      }
    }
    $i++;
  }

  print("\n");
  //行政区域の重なりを調べ、重なっている場合にはかさなっている座標を削除する。
  $figMax = count($coordinate);
  for ($fig1=0 ;$fig1<$figMax ; $fig1++){
    print("  ($fig1/$figMax)\r");
    for ($fig2=$fig1+1 ;$fig2<$figMax ; $fig2++){
      $checkArray = array();
      $checkArray = array_intersect($coordinate[$fig1],$coordinate[$fig2]);//2つの配列で重なった部分をしらべる
      if (count($checkArray) !== 0){//重なりがある場合
        $doublePoint = array();//重なっている座標を入れる配列。
        $doublePoint = array_intersect($coordinate[$fig1],$coordinate[$fig2]);//重なった値を返す
        $doublePoint = array_values($doublePoint);//キーをつめる

        //$coordinate[$fig1]と$doublePointで共通する値を削除する。
        $coordinate[$fig1] = array_diff($coordinate[$fig1],$doublePoint);//配列の差を求める。$coordinate[$fig1]から共通の項目を引く
        //$fig2について
        $coordinate[$fig2] = array_diff($coordinate[$fig2],$doublePoint);

        $coordinate[$fig1] = array_values($coordinate[$fig1]);//キーをつめる
        $coordinate[$fig2] = array_values($coordinate[$fig2]);//キーをつめる
      }
    }
  }


  //削除してなくなった行政区域を調べる
  for ($fig1=0 ;$fig1<$figMax ; $fig1++){
    $dataCount = count($coordinate[$fig1]);//その行政区域の座標データ数を調べる
    if ($dataCount < 10){
      unset($coordinate[$fig1]);//座標データが0だったらその配列を削除
    }
  }
  $coordinate = array_values($coordinate);//キーをつめる
  $deleteCount = count($coordinate);
  print("deleted($deleteCount/$figMax)\n");


  //======================距離を調べて点と点が離れている時には別の配列データにする。
  $m = 0;
  $figMax = count($coordinate);
  for ($i=0 ;$i<$figMax ; $i++){
    $jmax = count($coordinate[$i]);
    $n = 0;//新しい配列に入れるためにnを0にする。
    for ($j=0 ;$j<$jmax-1 ; $j++){
      $latilongArray = explode(" ",$coordinate[$i][$j]);//空白区切りでデータを取り出す
      $latitude1String = $latilongArray[0];//各要素を取り出す
      $longitude1String = $latilongArray[1];

      $latilongArray = explode(" ",$coordinate[$i][$j+1]);//空白区切りでデータを取り出す
      $latitude2String = $latilongArray[0];//各要素を取り出す
      $longitude2String = $latilongArray[1];

      $x1 = floatval($latitude1String);//文字列のデータをfloatに変換する。
      $y1 = floatval($longitude1String);
      $x2 = floatval($latitude2String);
      $y2 = floatval($longitude2String);
      $dx = $x2 - $x1;
      $dy = $y2 - $y1;
      $s = $dx * $dx  + $dy * $dy;//$jと$j+1の距離の二乗 この値で判定する。

      $temp[$m][$n] = $coordinate[$i][$j];//$jのデータを配列に入れる。tempは作業用の仮の配列
      $n++;//次のためにnをひとつ進める。

      if (($s > 1.0E-4) || ($n > 30000)){//$j+1が遠くにあるときの処理 もしくは一つの図形が大きくなりすぎた時に分割する。
        $m++;//新規の図形 新しい配列に入れる。
        $n = 0;//新しい配列の先頭から
        //$temp[$m][$n] = $coordinate[$i][$j+1];
      }
    }// for $j
    $m++;//元の配列が一つ終わったら次の配列にする。
  }// for $i
  $temp = array_values($temp);//キーをつめる
  $coordinate = $temp;//元の配列に戻す。

  //
  $figMax = count($coordinate);
  for ($fig1=0 ;$fig1<$figMax ; $fig1++){
    $dataCount = count($coordinate[$fig1]);//その行政区域の座標データ数を調べる
    if ($dataCount < 10){
      unset($coordinate[$fig1]);//座標データが0だったらその配列を削除
    }
  }
  $coordinate = array_values($coordinate);//キーをつめる
  $deleteCount = count($coordinate);
  print("deleted($deleteCount/$figMax)\n");


  //=========================XMLで図形を書き出す
  $contents='<?xml version="1.0" encoding="UTF-8"?>';
  $contents .="\n";
  $contents .='<ksj>' . "\n";
  //境界線データの書き出し polylineでデータで書き出す。
  $imax = count($coordinate);
  for ($i=0 ;$i<$imax ; $i++){
    $contents .='<gml>'. "\n";//図形の書き出し

    $jmax = count($coordinate[$i]);
    for ($j=0 ;$j<$jmax ; $j++){
        $contents .= $coordinate[$i][$j] . "\n";
    }
    $contents .= '</gml>' . "\n";
  }
  $contents .='</ksj>' . "\n";
  file_put_contents($saveXML, $contents);

  //=========================SVGで書き出す
  //スクリーンサイズ
  $screenWidth = 4000;
  $screenHeight = 4000;

  /*日本地図を描くための範囲を決める。
  最北端:北緯45度33分28秒 東経148度45分14秒  46.0
  最南端:北緯20度25分30.6585秒 東経136度4分11.1766秒  20.0
  最東端:北緯24度17分12秒 東経153度58分50秒 154.0
  最西端:北緯24度26分58秒 東経122度56分01秒 122.0
  */
  $north_max = 46.0;
  $south_max = 20.0;
  $east_max = 154.0;
  $west_max = 122.0;

  $y_max = log(tan(pi()/4.0 + deg2rad($north_max)/2.0));
  $y_min = log(tan(pi()/4.0 + deg2rad($south_max)/2.0));
  $x_max = deg2rad($east_max);//横方向
  $x_min= deg2rad($west_max);

  print("x min=" . $x_min . " x max=" . $x_max . " :  y min=" . $y_min . " y max=".$y_max ."\n");

  $cLo = ($x_max - $x_min)/2 + $x_min;
  $dx = $x_max - $x_min;
  $dy = $y_max - $y_min;
  $mX = $screenWidth/$dx;
  $mY = $screenHeight/$dy;

  if ($mX < $mY){
    $multiple = $mX;
  } else {
    $multiple = $mY;
  }

  //y軸の描画用の定数
  $yOffset = $y_max;
  print("multiple=" . $multiple ."\n");

  //==========================SVGファイルを書き出す
  $contents='<?xml version="1.0" standalone="no"?>';
  $contents .="\n";
  $contents .='<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">';
  $contents .="\n";
  $contents .='<svg width="40cm" height="40cm" viewBox="0 0 4000 4000" xmlns="http://www.w3.org/2000/svg" version="1.1">';
  $contents .="\n";
  $contents .='<desc>都道府県の境界線データ</desc>';
  $contents .="\n";
  $contents .='<polyline fill="none" stroke="black" stroke-width="1" points="0,0 4000,0 4000,4000,0,4000" />';//図形の書き出し
  //境界線データの書き出し polylineでデータで書き出す。

  $imax = count($coordinate);
  print("imax=$imax\n");
  for ($i=0 ;$i<$imax ; $i++){
    $jmax = count($coordinate[$i]);
    //print("jmax=$jmax\n");
    $svgData = "";
    for ($j= 0;$j<$jmax ; $j++){
        //メルカトル図法による計算。

        $latilongArray = explode(" ",$coordinate[$i][$j]);//空白で区切る
        //print("strring=" . $coordinate[$i][$j] . "\n");
        $latitude1String = $latilongArray[0];//各要素を取り出す
        $longitude1String = $latilongArray[1];

        $radian = deg2rad(floatval($latitude1String));
        $x = deg2rad(floatval($longitude1String)) - $cLo;//横方向
        $y = log(tan(pi()/4.0 + $radian/2.0));//縦方向

        $x = $multiple * $x + $screenWidth/2;
        $y = $multiple * (1.0 - $y) - ($multiple * (1.0-$yOffset));
        $svgData .= $x . "," . $y . " ";

    }
    $contents .='<polyline fill="none" stroke="blue" stroke-width="1" points="';//図形の書き出し
    $contents .= $svgData . '" />' . "\n";
  }

  $contents .="</svg>";

  file_put_contents($saveSVG, $contents);



  $endTime = microtime(true);
  $exeTime = $endTime - $startTime;
  print("exe Time=".$exeTime . "\n");
}

ちょっと長いコードになってきました。実行時間もかなりかかります。私のMacBook Pro(macOS Sierra 2.9 GHz Intel Core i5)では12096秒(201分)かかりました。

3. PHPのバージョンについて

余談ですがPHPのバージョンは7.0を使っています。

標準で入っているPHPは5.0系だと思いますが7.0系にすると処理速度が格段に上がります。だいたい2倍ぐらいに速度あがります。

PHPのバージョンアップは「MacをPHP7へバージョンアップする」あたりを参考にどうぞ。

4. XMLからSVGを作成するPHP

次に書き出したXMLから47都道府県を1枚のSVGに描画するPHPが必要になります。

plotXML2JapanPrefBound.php

<?php
//XMLフォルダに保存した各県のデータを読み取りSVGを描画

ini_set('memory_limit', '2540M');

mb_language("Japanese");//文字コードの設定
mb_internal_encoding("UTF-8");

//ファイルリスト
$xmlFile[1] ="./XML/hokkaido.xml";
$xmlFile[2] ="./XML/aomori.xml";
$xmlFile[3] ="./XML/iwate.xml";
$xmlFile[4] ="./XML/miyagi.xml";
$xmlFile[5] ="./XML/akita.xml";
$xmlFile[6] ="./XML/yamagata.xml";
$xmlFile[7] ="./XML/fukushima.xml";
$xmlFile[8] ="./XML/ibaraki.xml";
$xmlFile[9] ="./XML/tochigi.xml";
$xmlFile[10] ="./XML/gunnma.xml";
$xmlFile[11] ="./XML/saitama.xml";
$xmlFile[12] ="./XML/chiba.xml";
$xmlFile[13] ="./XML/tokyo.xml";
$xmlFile[14] ="./XML/kanagawa.xml";
$xmlFile[15] ="./XML/niigata.xml";
$xmlFile[16] ="./XML/toyama.xml";
$xmlFile[17] ="./XML/isihikawa.xml";
$xmlFile[18] ="./XML/fukui.xml";
$xmlFile[19] ="./XML/yamanashi.xml";
$xmlFile[20] ="./XML/nagano.xml";
$xmlFile[21] ="./XML/gifu.xml";
$xmlFile[22] ="./XML/sizuoka.xml";
$xmlFile[23] ="./XML/aiti.xml";
$xmlFile[24] ="./XML/mie.xml";
$xmlFile[25] ="./XML/shiga.xml";
$xmlFile[26] ="./XML/kyoto.xml";
$xmlFile[27] ="./XML/osaka.xml";
$xmlFile[28] ="./XML/hyougo.xml";
$xmlFile[29] ="./XML/nara.xml";
$xmlFile[30] ="./XML/wakayama.xml";
$xmlFile[31] ="./XML/tottori.xml";
$xmlFile[32] ="./XML/shimane.xml";
$xmlFile[33] ="./XML/okayama.xml";
$xmlFile[34] ="./XML/hiroshima.xml";
$xmlFile[35] ="./XML/yamaguchi.xml";
$xmlFile[36] ="./XML/tokushima.xml";
$xmlFile[37] ="./XML/kagawa.xml";
$xmlFile[38] ="./XML/ehime.xml";
$xmlFile[39] ="./XML/kouchi.xml";
$xmlFile[40] ="./XML/fukuoka.xml";
$xmlFile[41] ="./XML/saga.xml";
$xmlFile[42] ="./XML/nagasaki.xml";
$xmlFile[43] ="./XML/kumamoto.xml";
$xmlFile[44] ="./XML/ooita.xml";
$xmlFile[45] ="./XML/miyazaki.xml";
$xmlFile[46] ="./XML/kagoshima.xml";
$xmlFile[47] ="./XML/okinawa.xml";

$saveSVG = "./japanPrefBound.svg";


readXMLmakeOutline($xmlFile,$saveSVG);

function readXMLmakeOutline($xmlFile,$saveSVG){
  $startKenNo = 1;
  $endKenNo = 47;

  for ($ken=$startKenNo; $ken<$endKenNo+1; $ken++){
    //XMLの読み込み
    $dom = new DOMDocument('1.0', 'UTF-8');
    $dom->preserveWhiteSpace = false;
    $dom->formatOutput = true;
    $dom->load($xmlFile[$ken]);

    $root = $dom->getElementsByTagName("*")->item(0);//最初の要素の中身を取り出す

    //読み込んだxmlの中身を$coordinateStringに展開する。
    $j = 0;
    foreach( $root->getElementsByTagName("gml") as $itemGML ){//これでgmlの中身を$itemに取れる。
      $dataArray = explode("\n",$itemGML->nodeValue);//改行コードで配列にわける

      $i=0;
      foreach ($dataArray as $item) {//各要素ごとに繰り返す
        $item = trim($item);
        if($item != ""){//空白文字列の時には処理をしない。
          $coordinate[$ken][$j][$i]=$item;
          $i++;
        }//if
      }//foreach
      $j++;
    }//foreach( $root->
  }//for ($ken=$startKenNo; $ken<$endKenNo+1; $ken++) XMLの読み込み完了

  //=========================SVGで書き出す
  //スクリーンサイズ
  $screenWidth = 4000;
  $screenHeight = 4000;

  //日本地図を描くための範囲を決める。
  $north_max = 46.0;//最北端:北緯45度33分28秒 東経148度45分14秒  46.0
  $south_max = 20.0;//最南端:北緯20度25分30.6585秒 東経136度4分11.1766秒  20.0
  $east_max = 154.0;//最東端:北緯24度17分12秒 東経153度58分50秒 154.0
  $west_max = 122.0;//最西端:北緯24度26分58秒 東経122度56分01秒 122.0

  $y_max = log(tan(pi()/4.0 + deg2rad($north_max)/2.0));
  $y_min = log(tan(pi()/4.0 + deg2rad($south_max)/2.0));
  $x_max = deg2rad($east_max);//横方向
  $x_min= deg2rad($west_max);

  $cLo = ($x_max - $x_min)/2 + $x_min;
  $dx = $x_max - $x_min;
  $dy = $y_max - $y_min;
  $mX = $screenWidth/$dx;
  $mY = $screenHeight/$dy;

  if ($mX < $mY){
    $multiple = $mX;
  } else {
    $multiple = $mY;
  }

  //y軸の描画用の定数
  $yOffset = $y_max;
  print("multiple=" . $multiple ."\n");

  //==========================SVGファイルを書き出す
  $contents='<?xml version="1.0" standalone="no"?>';
  $contents .="\n";
  $contents .='<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">';
  $contents .="\n";
  $contents .='<svg width="40cm" height="40cm" viewBox="0 0 4000 4000" xmlns="http://www.w3.org/2000/svg" version="1.1">';
  $contents .="\n";
  $contents .='<desc>都道府県の境界線データ</desc>';
  $contents .="\n";
  $contents .='<polyline fill="none" stroke="black" stroke-width="1" points="0,0 4000,0 4000,4000,0,4000" />';//図形の書き出し
  //境界線データの書き出し polylineでデータで書き出す。

  for ($ken=$startKenNo; $ken<$endKenNo+1; $ken++){
    $imax = count($coordinate[$ken]);
    print("imax=$imax\n");
    for ($i=0 ;$i<$imax ; $i++){
      $jmax = count($coordinate[$ken][$i]);
      //print("jmax=$jmax\n");
      $svgData = "";
      for ($j= 0;$j<$jmax ; $j++){
          //メルカトル図法による計算。

          $latilongArray = explode(" ",$coordinate[$ken][$i][$j]);//空白で区切る
          $latitude1String = $latilongArray[0];//各要素を取り出す
          $longitude1String = $latilongArray[1];

          $radian = deg2rad(floatval($latitude1String));
          $x = deg2rad(floatval($longitude1String)) - $cLo;//横方向
          $y = log(tan(pi()/4.0 + $radian/2.0));//縦方向

          $x = $multiple * $x + $screenWidth/2;
          $y = $multiple * (1.0 - $y) - ($multiple * (1.0-$yOffset));
          $svgData .= $x . "," . $y . " ";

      }
      $contents .='<polyline fill="none" stroke="blue" stroke-width="1" points="';//図形の書き出し
      $contents .= $svgData . '" />' . "\n";
    }
  }

  $contents .="</svg>";
  file_put_contents($saveSVG, $contents);


}// end of function

このスクリプトでjapanPrefBound.svgというファイルが出来上がります。このファイルをSVGを表示できるアプリで開けば県別の白地図になっています。が、、、このファイル266.6MBもあって簡単には開けません。Illustratorでは無理。Safariも開けませんでした。Chromeで開けますが全体を描画し終わるまでに時間がかかります。ゆっくりと描画していく様子を見ながら待ちましょう。

とりあえず出来ましたが、このままでは使い勝手が悪すぎるのでファイルサイズを軽くするために以下の事を考えます。
・小さい島は描画しない。
・点と点の間隔を調整する。広げる。

これは次の記事で。