8 posts categorized "SVGMapServices"

2010年8 月 4日 (水)

Shapefile to TILED SVG Map converter

We publish an open source software which generates the TILED SVG Map data conforming to the Tiling specification of SVG Map Profile (or newer SVG Tiling and Layering Module by setting option) specifications based on the past Shapefile to SVG Map with metadata converter.
The function to divide one shapefile into the tile group is implemented on this software. In general, because big size shapefiles are distributed, this software may be useful. This software is coded with JAVA, and uses geoTools.

SVG Map Profileタイリング仕様に対応した、タイル分割されたSVG MapデータをShapefileから生成するソフトウェアを以前のShapefile to SVG Map with metadata converterを基に作成しましたので、オープンソースとして公開します。このソフトウエアには、1つのShapefileを指定された分割数でタイル分割する機能が実装されています。Shapefileは一般に大きなサイズのものが配布されていますので有用と思います。
オプションを指定することで、SVG 1.2をベースとした、より新たな仕様(Tiling and Layering Module)にも対応します。このソフトウエアはJAVAでコーディングされ、geoToolsとそれに同梱されているJTSライブラリを用いています。

Download Shape2SvgMap.java # update 2010/08/18 support geotools2.6.5

2008年8 月 2日 (土)

The system which performs hyper-layering of a landslide map and a 1:25000 topographical map

This page is English Version of the Japanese article of this blog.

We release the SVG Map based web map mashupping system which performs a composite view (Hyper-Layering) of landslide map data base which National Research Institute for Earth Science and Disaster Prevention releases and 1:25000"DENSHI-KOKUDO" topographical SVG map which released Geographical Survey Institute.

Please access the following URL with PC in which SVG Map Toolkit was installed.
http://www.svg-map.org/svg/wmsGw/CJ_BOSAI.svg

Supplement :
In this system, the SVG-ize server which enables it to treat the map services provided by the WMS specifications of OGC as SVG Map is used.
# The server of an original landslide map has a WMS interface.

The SVG-ize server is only a server which generates the container SVG data which refers to a WMS server instead of a gateway which performs the reworking of the data of a WMS server. Therefore, the processing is light and constructing as a static data is also easy.  (See Also: Relationship between WMS and SVG Map )

Although some characteristic mechanisms are further included in this server, I would like to explain in full detail separately about those mechanisms.

2008年1 月25日 (金)

Shapefile to SVG Map with metadata converter

 メタデータの埋め込み仕様に従ってメタデータが埋め込まれたSVG Mapデータを生成するソフトウェアを、Shape to SVG Map Converterをもとにして作成しました。
 メタデータのネームスペース宣言が適切ではないなどいくつかの問題点がありますが、このソフトウェアで変換したデータを、テキストエディタの正規表現による置換機能やXSLT等を用いて所望の描画スタイルを設定できると思います。

We publish the software which generates a SVG Map data where metadata was embedded according to the embedding specifications for the metadata based on Shape to SVG Map Converter.
It has some problems, such as a namespace declaration sentence of the metadata which cannot be said to be suitable. However, the data which this software generated is useful in order to carry out a rendition style set using XSLT, replacement functions of a text editor, etc.

// =============================================================================
// Meta-embedded SVG Map exporter program
//
// Copyright (C) 2008 by Satoru Takagi All rights reserved.
// 
http://www.svg-map.com/
//
// Usage: java Shape2SvgMapMeta shapefile.shp
//
// This program uses geoTools2.3.0
// =============================================================================
//
// This software is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License as published by  the  Free
// Software Foundation; either version 2.1 of the License, or (at  your  option)
// any later version.
//
// This library is distributed in the hope that it will be  useful,  but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for  more
// details.
//
// You should have received a copy of the  GNU  Lesser  General  Public  License
// along with this library; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// =============================================================================

import java.io.*;
import java.io.IOException;
import java.net.URL;

import org.geotools.data.*;
import org.geotools.data.shapefile.ShapefileDataStore;
import org.geotools.feature.*;

import com.vividsolutions.jts.geom.*;

public class Shape2SvgMapMeta {
double  boundHeight = 400.0; // SVG Height
double  projCenter;
String fillColor = "green";
String strokeColor = "black";
double strokeWidth = 0.01;
// CRS:84 (WGS84 Long-Lat) This URI(URN) is ambiguous...
String CRS = "
http://purl.org/crs/84";
double[] affineParam = new double[6];
FeatureType readFT;
String metaString;

public static void main(String[] args) {
  Shape2SvgMapMeta s2sm = new Shape2SvgMapMeta();
  try {
   // Prepare an output SVG Map file
   FileOutputStream osFile = new FileOutputStream( args[0] + ".svg" );
   Writer fos = new BufferedWriter(new OutputStreamWriter( osFile , "UTF-8" ));
   
   // Shape file
   URL shapeURL = (new File(args[0])).toURL();
   
   s2sm.parse(  shapeURL , fos );
   fos.close();
   
  }catch(Exception e){
   e.printStackTrace();
  }
}


public void parse( URL shapeURL , Writer out ) throws Exception {
  double maxX, minX, maxY, minY;
 
  // Initialize shape file reader
  ShapefileDataStore readStore = new ShapefileDataStore(shapeURL);
  FeatureSource source = readStore.getFeatureSource();
  readFT = source.getSchema();

 
  // get envelope
  Envelope env = source.getBounds();
  maxX = env.getMaxX();
  minX = env.getMinX();
  maxY = env.getMaxY();
  minY = env.getMinY();
 
  // Make affine parameters for CRS metadata of SVG Map
  // Equirectangular Projection (Standard parallel = Center of map)
  //
  // SVG_X = a * GEO_X + c * GEO_Y + e
  // SVG_Y = b * GEO_X + d * GEO_Y + f
  affineParam[1] = 0.0; // b
  affineParam[2] = 0.0; // c
 
  affineParam[3] = - boundHeight / ( maxY - minY ); // d
 
  projCenter = ( maxY + minY ) / 2.0;
  affineParam[0] = - affineParam[3] * Math.cos( projCenter * Math.PI / 180.0 ); // a
 
  affineParam[4] = -affineParam[0] * minX; // e
  affineParam[5] = -affineParam[3] * maxY; // f
 
  // Make a SVG ViewBox
  double origX , origY , cWidth , cHeight;
  cWidth  = Math.abs( ( maxX - minX ) * affineParam[0] );
  cHeight = Math.abs( ( maxY - minY ) * affineParam[3] );
  origX = affineParam[0] * minX + affineParam[4];
  origY = affineParam[3] * maxY + affineParam[5];
 
  // get FeatureCollection
  FeatureCollection fsShape = source.getFeatures();
 
 
  // Start SVG Map output
  // SVG header etc.
  out.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
  out.write("<svg  xmlns=\"
http://www.w3.org/2000/svg\" ");
  out.write("xmlns:xlink=\"
http://www.w3.org/1999/xlink\" ");
  out.write("xmlns:lm=\"
http://www.svg-map.org/svgmap/localmetadata/\" ");
  out.write("viewBox=\"" + origX + " " + origY + " " + cWidth + " " + cHeight + "\" >\n");
 
  // metadata for SVG Map
  out.write("<metadata>\n");
 
  // CRS metadata
  out.write(" <rdf:RDF xmlns:rdf=\"
http://www.w3.org/1999/02/22-rdf-syntax-ns#\" ");
  out.write("xmlns:crs=\"
http://opengis.org/xmldtds/transformations.dtd\" xmlns:svg=\"http://www.w3.org/2000/svg\">\n");
  out.write("  <rdf:Description>\n");
  out.write("   <crs:CoordinateReferenceSystem rdf:resource=\"" + CRS + "\"  ");
  out.write("svg:transform=\"matrix(" + affineParam[0] + "," + affineParam[1] + "," + affineParam[2]
   + "," + affineParam[3] + "," + affineParam[4] + "," + affineParam[5] +")\" />\n");
  out.write("  </rdf:Description>\n");
  out.write(" </rdf:RDF>\n");
  out.write("</metadata>\n");
 
  // Icon for Point
  out.write("<defs>\n");
  out.write(" <g id=\"p0\" >\n");
  out.write("<circle cx=\"0.0\" cy=\"0.0\" r=\"" + (cWidth / 300) + "\" stroke=\"none\" />\n");
  out.write(" </g>\n");
  out.write("</defs>\n");
 
  // Main data body
  FeatureIterator reader = fsShape.features();
  Feature oneFeature;
  Geometry oneGeom;
  Coordinate[] coord;
  while (reader.hasNext()) {
   oneFeature = reader.next();
   metaString = getMetaString( oneFeature );
   isChild = false;
   oneGeom = oneFeature.getDefaultGeometry();
   parseGeometry(oneGeom , out );
  }
  reader.close();
  out.write("</svg>\n");
}

boolean isChild;
private void parseGeometry(Geometry geom , Writer out ) throws Exception {
  Coordinate[] coord;
  Coordinate oneCrd = new Coordinate();
  if (geom instanceof Polygon ){
   out.write("<path ");
   if ( ! isChild ){ out.write(metaString);}
   out.write("fill=\"" + fillColor + "\" fill-rule=\"evenodd\" d=\"M");
   coord = (((Polygon)geom).getExteriorRing()).getCoordinates();
   for ( int i = 0 ; i < coord.length ; i++ ){
    if ( i!= 0 ){
     out.write( "L" );
    }
    oneCrd = transform2D(coord[i] );
    out.write( oneCrd.x + "," + oneCrd.y + " " );
   }
   out.write ("Z ");
   
   for ( int j = 0 ; j < ((Polygon)geom).getNumInteriorRing() ; j++ ){
    coord = (((Polygon)geom).getInteriorRingN(j)).getCoordinates();
    for ( int i = 0 ; i < coord.length ; i++ ){
     if ( i!= 0 ){
      out.write( "L" );
     } else {
      out.write( "M" );
     }
     oneCrd = transform2D(coord[i] );
     out.write( oneCrd.x + "," + oneCrd.y + " " );
    }
    out.write ("Z ");
   }
   
   out.write ("\"/>\n");
  } else if (geom instanceof LineString ){
   out.write("<polyline ");
   if ( ! isChild ){ out.write(metaString);}
   out.write("fill=\"none\" stroke-width=\"" + strokeWidth + "\" stroke=\"" + strokeColor + "\" points=\"");
   coord = ((LineString)geom).getCoordinates();
   for ( int i = 0 ; i < coord.length ; i++ ){
    oneCrd = transform2D(coord[i] );
    out.write( oneCrd.x + "," + oneCrd.y + " " );
   }
   out.write ("\"/>\n");
  } else if (geom instanceof Point ){
   oneCrd = transform2D(((Point)geom).getCoordinate() );
   out.write("<use ");
   if ( ! isChild ){ out.write(metaString);}
   out.write("xlink:href=\"#p0\" fill=\"" + fillColor + "\"");
   out.write(" x=\"" + oneCrd.x + "\"" + " y=\"" + oneCrd.y + "\"/>\n");
  } else if (geom instanceof GeometryCollection ){
//   out.write("<g ");
//   if ( ! isChild ){ out.write(metaString);}
//   out.write(">\n");
//   isChild = true;
   for ( int j = 0 ; j < ((GeometryCollection)geom).getNumGeometries() ; j++){
    Geometry childGeom = ((GeometryCollection)geom).getGeometryN(j);
    parseGeometry(childGeom , out);
   }
//   out.write("</g>\n");
  } else if (geom instanceof Geometry ){
   out.write("<!-- Type: Other Geometry...." + geom + "-->\n");
  } else if (geom instanceof Object){
   out.write("<!-- Type: Other Object...." + geom + "-->\n");
  }
}

private  Coordinate transform2D( Coordinate inCrd ){
  Coordinate outCrd = new Coordinate(
   affineParam[0] * inCrd.x + affineParam[2] * inCrd.y + affineParam[4] ,
   affineParam[1] * inCrd.x + affineParam[3] * inCrd.y + affineParam[5] );
  return (outCrd);
}

private String getMetaString( Feature oneFeature ){
  StringBuffer metaString = new StringBuffer();
  for ( int i = 0 ; i < readFT.getAttributeCount() ; i++){
   if (oneFeature.getAttribute(i) instanceof Geometry == false ){
    metaString.append("lm:");
    metaString.append( readFT.getAttributeType(i).getName());
    metaString.append("=\"");
    metaString.append( oneFeature.getAttribute(i));
    metaString.append( "\" ");
   }
  }
  return ( metaString.toString() );
}

}

2007年12 月13日 (木)

地すべり地形分布図データベースと電子国土SVGの重ね合わせシステム

防災科学技術研究所が公開している、地すべり地形分布図データベースを電子国土SVGデータと重ね合わせて表示するシステムを公開します。

SVG Map ToolkitがインストールされたPCで以下のURLにアクセスしてください。
http://www.svg-map.org/svg/wmsGw/CJ_BOSAI.svg

補足:
 このシステムは、OGCのWMS仕様で提供されている地図サービスをSVG Mapとして扱えるようにするサーバを設置することで、SVG Mapのハイパーレイヤリング機能を用いて、先に公開された電子国土SVGデータなどとの重ねあわせを実現しています。
#地すべり地形分布図データベースはWMSのインターフェースを持っています。(
参照

 SVG Mapは、<image>要素を用いることで、外部の地図データ(ベクタでもラスタでも)を参照することができます。(参考1)(参考2
 そこで、WMSのサービスを参照するためのURLを<image>要素のxlink:hrefに設定し、正しく空間参照系メタデータを記述することによって、WMSのラスターデータを参照するSVG Mapのコンテナデータを生成することができます。なお、空間参照系メタデータは、WMSのサービスへのリクエストパラメータから逆算することができます。
 このようなコンテナデータを生成するサーバを設置することで、WMS仕様で提供されている地図サービスをSVG Mapとして扱えるようになる訳です。
#WMSのサーバからデータを取得して再加工するようなゲートウェイではなく、WMSのサーバを参照するコンテナデータを生成するだけのサーバです。(そのため処理は軽く、静的なシステムに仕立てることも容易)今回実装したサーバには、他にもいくつかの特徴的な機能が含まれているのですが、それについては別途詳説します。

2007年6 月20日 (水)

SVG MapをInkscapeで作る

オープンソースの有名なドローツール、Inkscapeを用いて、SVG Mapコンテンツ(地理座標付き)を作成する方法を紹介します。概要としては、まずSVG Mapの下絵を準備します。(この下絵に地理座標が付いていれば、その上に描いたコンテンツに地理座標が付く訳です。)次に、その下絵をInkscapeに読み込ませ、その上でコンテンツを作成していきます。そして、下絵を除去し、保存します。(Inkscapeは保存方法によって地理座標メタデータを保持します。)

下絵としては、狭いエリア限定でgoogleMapsをスクリーンキャプチャして使えます。
#狭いエリア限定の理由は、googleMapsが使用している図法がメルカトル図法のためです。SVG Mapで使用できる図法は、1次のアフィン変換で行えるもの(正距円筒図法など)のみですので、メルカトル図法が近似的に正距円筒図法とみなせないと使えません。

注意:googleMapsの画像は、コンテンツ作成時の下絵としてしか使えません。この下絵をインターネットで公開すると、googleMapsの利用規約に違反します。

それでは以下でその方法をご紹介します。



地図の中心: ---
  1. 画面中央にある横線[Hline]は、図法の違いによる誤差の"目安"です。この横線が2本見えるときは、誤差が無視できません。一本になるレベルまで拡大して使用すると良いでしょう。 (ただし、赤道上では目安になりません。)
  2. 使いたいエリアの地図を表示して、Alt+PrintScreen(Windowsの場合)を押し、画像編集ソフト(Photoshopなど。フリーならJTrimなど)にペーストし、地図の部分を正確に切り出して(地図のサイズは、横:---pix,縦:---pixです。)、jpeg形式でsavedGoogleMap.jpgとして保存しましょう。これが下絵の画像となります。
  3. 次に、適当な名前のSVGデータとして、以下のSVGソースをテキストエディタでコピー&ペースト&同じディレクトリに保存すると、CRS付きのSVG地図データが出来上がります。これが下絵のSVG Mapデータです。 (今表示している地図に基づいてアフィン変換パラメータが計算され書き込まれています。)
  4. 保存したSVG Mapの下絵をInkscapeで開き、それを下絵にして、自分の主題情報を描画しましょう。その後、下絵のjpeg画像データを削除し、保存(InkscapeSVG形式:このオプションだとメタデータが保持される)すると、自分のSVG地図が完成します。
    注:下絵の画像をインターネットで公開しないでください。(googleの利用規約に違反します)

SVG Source

<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100" height="100">
  <metadata>
    <rdf:RDF xmlns:rdf="http://www.w3.og/1999/02/22-rdf-syntax-ns#" xmlns:crs="http://www.ogc.org/crs" xmlns:svg="http://www.w3.org/svg">
      <rdf:Description>
        <crs:CoordinateReferenceSystem rdf:resource="http://purl.org/crs/84" svg:transform="matrix(0,0,0,0,0,0)" />
      </rdf:Description>
    </rdf:RDF>
  </metadata>
  <g fill-opacity="0.5">
    <image x="0" y="0" width="100" height="100" xlink:href="savedGoogleMap.jpg" />
  </g>
</svg>

このプログラムは、入門Ajax経度・緯度を調べる(地図作成作業補助サンプル)を参考にさせていただきました。 

2007年5 月18日 (金)

電子国土SVG Mapコンテナビルダー

電子国土ラボ が公開されました。電子国土SVGデータは、30秒区切りのタイルデータになっています。そのため、このデータはタイリングして使用すると便利です。

そこで、タイリングされた地図データの仕様に基づいた、コンテナSVGファイルを生成するプログラムを公開します。

ダウンロードした電子国土データのディレクトリを指定すると、そのディレクトリ内にある地図タイルデータをタイリングするコンテナSVGデータを生成します。

LGPLに基づいてご使用ください。

MakeCJContainer.java

// The basic Cyber Japan SVG Map mesh data container for tiling
//
// Copyright (C) 2007 by Satoru Takagi All rights reserved.
//  http://www.svg-map.com/
//
// Usage : java MakeCJContainer SearchDirectory
// Output: SearchDirectory.svg
//
// =============================================================================
//
// This software is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License as published by  the  Free
// Software Foundation; either version 2.1 of the License, or (at  your  option)
// any later version.
//
// This library is distributed in the hope that it will be  useful,  but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for  more
// details.
//
// You should have received a copy of the  GNU  Lesser  General  Public  License
// along with this library; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// =============================================================================
import java.io.*;
import java.util.*;

public class MakeCJContainer {
public final static double svgMeshHeight = 400.0; // set mesh Height for SVG

public static double svgMeshWidth;
    public static String target;
static boolean firstTile = false;
static double tA, tB , tC , tD , tE , tF; // transform matrix for CRS

// Main
    public static void main( String argv[] ){
        try {
   // Prepare an output SVG Map file
   FileOutputStream osFile = new FileOutputStream( argv[0] + ".svg" );
   Writer fos = new BufferedWriter(new OutputStreamWriter( osFile , "UTF-8" ));

            MakeCJContainer.target = ".svg";
            MakeCJContainer top
                = new MakeCJContainer( new File( "."+ File.separator + argv[0] + File.separator) , fos );
   fos.close();
        }
        catch( ArrayIndexOutOfBoundsException e ) {  // Parameter error
            System.err.println("Usage:java MakeCJContainer searchname");
            System.exit(-1);
        }
        catch( Exception e ) {   // Other Errors
            System.err.println("Error....");
         e.printStackTrace();
            System.exit(-1);
        }
    }

// Constructor
    public MakeCJContainer( File dir ,  Writer out ) throws Exception {
    
        try {
         searchSubDirs( dir , out );
        }
     catch( Exception e ) {
            throw e;
        }
     out.write("</svg>\n");
    }

// Generation of image element of SVG Map mesh
    public void writeImageElement( File aFile ,  Writer out ) {
     String name;
     int mStart , mEnd;
  if( aFile.getName().indexOf( target ) >= 0 ){
   name = aFile.getPath();
   mStart = name.lastIndexOf(File.separator) + 1;
   mEnd = name.indexOf( "-all" );
   try {
    CyberJpMesh mesh = new CyberJpMesh( name.substring(mStart , mEnd));
   
    if (firstTile==false){
     printSvgHeader( mesh.longitude , mesh.latitude , CyberJpMesh.span , CyberJpMesh.span , out);
     firstTile=true;
    }
    calcTransform( mesh.longitude , mesh.latitude + CyberJpMesh.span );
       out.write("<image xlink:href=\"" + name.replace('\\' , '/') +"\" "
    + "y=\"" + transY + "\" " + "x=\"" + transX + "\" "
    + "width=\"" + svgMeshWidth + "\" " + "height=\"" + svgMeshHeight + "\" />\n");
   } catch (Exception e ) {
   
   }
  }
    }

// Recurrent search for subdirectory
    public void searchSubDirs(File dir ,  Writer out ) throws Exception {
     File[] files;
     String[] names;
     names = dir.list();
     int fileLength = names.length;
     files = new File[ fileLength ];
        try {
         for( int i=0; i< fileLength; i++ ){
          files[i] = new File( dir.getPath() + File.separator + names[i] );
              if( files[i].isDirectory() ) {
              searchSubDirs( files[i] , out );
             } else {
              writeImageElement( files[i] , out);
             }
         }
        }
        catch( Exception e ) {
            throw e;
        }
    
    }


// Coordinate Trnasformer
private double transX , transY;

private void calcTransform( double x , double y){
  transX = tA * x + tC * y + tE;
  transY = tB * x + tD * y + tF;
}


// Prepare transform matrix for CRS using first mesh and write SVG header.
public void printSvgHeader(double x , double y , double w , double h ,  Writer out) throws Exception{
  tD = - svgMeshHeight / h;
  svgMeshWidth =  svgMeshHeight * Math.cos( y * Math.PI / 180.0 ) * w / h ;
  tA = - tD * Math.cos( y * Math.PI / 180.0 );
  tB = 0.0;
  tC = 0.0;
 
  tE = - tA * x;
  tF = - tD * ( y + h );
 
 
  out.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
  out.write("<svg  xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" viewBox=\"" + 0.0 + " " + 0.0 + " " + w * tA + " " + (- h * tD) + "\">\n");
  out.write("<metadata>\n");
  out.write("<rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\" xmlns:crs=\"http://www.ogc.org/crs\" xmlns:svg=\"http://www.w3.org/2000/svg\">\n");
  out.write("<rdf:Description>");
  out.write("<crs:CoordinateReferenceSystem rdf:resource=\"http://purl.org/crs/84\"  svg:transform=\"matrix(" + tA + "," + tB + "," + tC + "," + tD + "," + tE + "," + tF + ")\" />\n");
  out.write("</rdf:Description>\n");
  out.write("</rdf:RDF>\n");
  out.write("</metadata>\n");
}

}

CyberJpMesh.java

// 電子国土SVGのメッシュコードを入出力します
// 2007/04/06 Satoru Takagi

import java.util.*;
import java.io.*;

public class CyberJpMesh{

public String mesh , latMesh , longMesh;
public int latNo , longNo;
public double latitude , longitude;

public static double span = 30.0 / (60.0 * 60.0); // 30sec

public static void main( String argv[] ) {
  if (argv.length == 2 ){
   CyberJpMesh jm = new CyberJpMesh(Double.parseDouble(argv[0]) , Double.parseDouble(argv[1]));
   System.out.println( "mesh3:" + jm );
  } else {
   CyberJpMesh jm = new CyberJpMesh( argv[0]);
   System.out.println( "lat:" + jm.latitude + " long:" + jm.longitude );
  }
}

public CyberJpMesh(double lati , double longi){
  latitude = lati;
  longitude = longi;
 
  latNo = (int)(latitude * 60.0 * 60.0 * 100.0);
  longNo = (int)(longitude * 60.0 * 60.0 * 100.0);
 
  latMesh = Integer.toString(latNo);
  longMesh = Integer.toString(longNo);
  mesh = longMesh + "-" + latMesh;
 
}

public CyberJpMesh(String meshNo){
  mesh = meshNo;
  int delim = mesh.indexOf("-");
  if ( delim < 0 ) {
   throw new NumberFormatException();
  }
  longMesh=mesh.substring(0,delim);
  latMesh=mesh.substring(delim+1);
 
  latNo = Integer.parseInt(latMesh);
  longNo = Integer.parseInt(longMesh);
 
  latitude = (double)latNo / (60.0 * 60.0 * 100);
  longitude = (double)longNo / (60.0 * 60.0 * 100);
 
}

public String toString(){
  return (mesh);
}

}

電子国土ラボ

国土交通省国土地理院と共同研究実施各社が行っている、「SVGコンテンツを利用した電子国土の実用的な普及戦略に関する研究」 の成果を提供するためのラボサイトが公開されました。

電子国土ラボ

同サイトでは、現在試作検証中のSVG形式の電子国土(1/25000の電子地図)データに関する情報が提供されています。 5月18日時点で、2次メッシュ区画で50枚弱が提供されています。

電子国土データの内容に関しては、電子国土ポータルサイトもご覧ください。

また、SVG Mapコンソーシアムのメンバーの数社が、共同研究の実施会社に含まれており、SVG Mapコンソーシアムの活動へのフィードバックなどが期待できます。

2007年4 月 4日 (水)

Shape to SVG Map converter

SVG Map Profileの最も基本的な部分(空間参照系メタデータの埋め込み)のサンプルプログラムを公開します。ShapeファイルからSVG Mapコンテンツを生成します。
GeoTools を使用していますので、少しの修正で他の形式からの変換もできるでしょう。
またまた つたないコードですがご勘弁を・・
LGPLライセンスに基づいて、ご使用ください。

(2007.5.9 CRSのURIを改訂)

We post the sample code of Shape to SVG Map Converter which used GeoTools. This code includes the most basic part of SVG Map Profile (Coordinate Reference System metadata). Please use it based on the LGPL license.

// =============================================================================
// The basic SVG Map exporter program
//
// Copyright (C) 2007 by Satoru Takagi All rights reserved.
//  http://blog.svg-map.com/
//
// Usage: java Shape2SvgMapBasic shapefile.shp
//
// This program uses geoTools2.3.0
// =============================================================================
//
// This software is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License as published by  the  Free
// Software Foundation; either version 2.1 of the License, or (at  your  option)
// any later version.
//
// This library is distributed in the hope that it will be  useful,  but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for  more
// details.
//
// You should have received a copy of the  GNU  Lesser  General  Public  License
// along with this library; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// =============================================================================

import java.io.*;
import java.io.IOException;
import java.net.URL;

import org.geotools.data.*;
import org.geotools.data.shapefile.ShapefileDataStore;
import org.geotools.feature.*;

import com.vividsolutions.jts.geom.*;

public class Shape2SvgMapBasic {
double  boundHeight = 400.0; // SVG Height
double  projCenter;
String fillColor = "green";
String strokeColor = "black";
double strokeWidth = 0.01;
// CRS:84 (WGS84 Long-Lat) This URI(URN) is ambiguous...
String CRS = "http://purl.org/crs/84";
double[] affineParam = new double[6];

public static void main(String[] args) {
  Shape2SvgMapBasic s2sm = new Shape2SvgMapBasic();
  try {
   // Prepare an output SVG Map file
   FileOutputStream osFile = new FileOutputStream( args[0] + ".svg" );
   Writer fos = new BufferedWriter(new OutputStreamWriter( osFile , "UTF-8" ));
   
   // Shape file
   URL shapeURL = (new File(args[0])).toURL();
   
   s2sm.parse(  shapeURL , fos );
   fos.close();
   
  }catch(Exception e){
   e.printStackTrace();
  }
}


public void parse( URL shapeURL , Writer out ) throws Exception {
  double maxX, minX, maxY, minY;
 
  // Initialize shape file reader
  ShapefileDataStore readStore = new ShapefileDataStore(shapeURL);
  FeatureSource source = readStore.getFeatureSource();

 
  // get envelope
  Envelope env = source.getBounds();
  maxX = env.getMaxX();
  minX = env.getMinX();
  maxY = env.getMaxY();
  minY = env.getMinY();
 
  // Make affine parameters for CRS metadata of SVG Map
  // Equirectangular Projection (Standard parallel = Center of map)
  //
  // SVG_X = a * GEO_X + c * GEO_Y + e
  // SVG_Y = b * GEO_X + d * GEO_Y + f
  affineParam[1] = 0.0; // b
  affineParam[2] = 0.0; // c
 
  affineParam[3] = - boundHeight / ( maxY - minY ); // d
 
  projCenter = ( maxY + minY ) / 2.0;
  affineParam[0] = - affineParam[3] * Math.cos( projCenter * Math.PI / 180.0 ); // a
 
  affineParam[4] = -affineParam[0] * minX; // e
  affineParam[5] = -affineParam[3] * maxY; // f
 
  // Make a SVG ViewBox
  double origX , origY , cWidth , cHeight;
  cWidth  = Math.abs( ( maxX - minX ) * affineParam[0] );
  cHeight = Math.abs( ( maxY - minY ) * affineParam[3] );
  origX = affineParam[0] * minX + affineParam[4];
  origY = affineParam[3] * maxY + affineParam[5];
 
  // get FeatureCollection
  FeatureCollection fsShape = source.getFeatures();
 
 
  // Start SVG Map output
  // SVG header etc.
  out.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
  out.write("<svg  xmlns=\"http://www.w3.org/2000/svg\" ");
  out.write("xmlns:xlink=\"http://www.w3.org/1999/xlink\" ");
  out.write("viewBox=\"" + origX + " " + origY + " " + cWidth + " " + cHeight + "\" >\n");
 
  // metadata for SVG Map
  out.write("<metadata>\n");
 
  // CRS metadata
  out.write(" <rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\" ");
  out.write("xmlns:crs=\"http://opengis.org/xmldtds/transformations.dtd\" xmlns:svg=\"http://www.w3.org/2000/svg\">\n");
  out.write("  <rdf:Description>\n");
  out.write("   <crs:CoordinateReferenceSystem rdf:resource=\"" + CRS + "\"  ");
  out.write("svg:transform=\"matrix(" + affineParam[0] + "," + affineParam[1] + "," + affineParam[2]
   + "," + affineParam[3] + "," + affineParam[4] + "," + affineParam[5] +")\" />\n");
  out.write("  </rdf:Description>\n");
  out.write(" </rdf:RDF>\n");
  out.write("</metadata>\n");
 
  // Icon for Point
  out.write("<defs>\n");
  out.write(" <g id=\"p0\" >\n");
  out.write("<circle cx=\"0.0\" cy=\"0.0\" r=\"" + (cWidth / 300) + "\" stroke=\"none\" />\n");
  out.write(" </g>\n");
  out.write("</defs>\n");
 
  // Main data body
  FeatureIterator reader = fsShape.features();
  Feature oneFeature;
  Geometry oneGeom;
  Coordinate[] coord;
  while (reader.hasNext()) {
   oneFeature = reader.next();
   oneGeom = oneFeature.getDefaultGeometry();
   parseGeometry(oneGeom , out );
  }
  reader.close();
  out.write("</svg>\n");
}
 
private void parseGeometry(Geometry geom , Writer out ) throws Exception {
  Coordinate[] coord;
  Coordinate oneCrd = new Coordinate();
  if (geom instanceof Polygon ){
   out.write("<path ");
   out.write("fill=\"" + fillColor + "\" fill-rule=\"evenodd\" d=\"M");
   coord = (((Polygon)geom).getExteriorRing()).getCoordinates();
   for ( int i = 0 ; i < coord.length ; i++ ){
    if ( i!= 0 ){
     out.write( "L" );
    }
    oneCrd = transform2D(coord[i] );
    out.write( oneCrd.x + "," + oneCrd.y + " " );
   }
   out.write ("Z ");
   
   for ( int j = 0 ; j < ((Polygon)geom).getNumInteriorRing() ; j++ ){
    coord = (((Polygon)geom).getInteriorRingN(j)).getCoordinates();
    for ( int i = 0 ; i < coord.length ; i++ ){
     if ( i!= 0 ){
      out.write( "L" );
     } else {
      out.write( "M" );
     }
     oneCrd = transform2D(coord[i] );
     out.write( oneCrd.x + "," + oneCrd.y + " " );
    }
    out.write ("Z ");
   }
   
   out.write ("\"/>\n");
  } else if (geom instanceof LineString ){
   out.write("<polyline ");
   out.write("fill=\"none\" stroke-width=\"" + strokeWidth + "\" stroke=\"" + strokeColor + "\" points=\"");
   coord = ((LineString)geom).getCoordinates();
   for ( int i = 0 ; i < coord.length ; i++ ){
    oneCrd = transform2D(coord[i] );
    out.write( oneCrd.x + "," + oneCrd.y + " " );
   }
   out.write ("\"/>\n");
  } else if (geom instanceof Point ){
   oneCrd = transform2D(((Point)geom).getCoordinate() );
   out.write("<use ");
   out.write("xlink:href=\"#p0\" fill=\"" + fillColor + "\"");
   out.write(" x=\"" + oneCrd.x + "\"" + " y=\"" + oneCrd.y + "\"/>\n");
  } else if (geom instanceof GeometryCollection ){
   out.write("<g>\n");
   for ( int j = 0 ; j < ((GeometryCollection)geom).getNumGeometries() ; j++){
    Geometry childGeom = ((GeometryCollection)geom).getGeometryN(j);
    parseGeometry(childGeom , out);
   }
   out.write("</g>\n");
  } else if (geom instanceof Geometry ){
   out.write("<!-- Type: Other Geometry...." + geom + "-->\n");
  } else if (geom instanceof Object){
   out.write("<!-- Type: Other Object...." + geom + "-->\n");
  }
}

private  Coordinate transform2D( Coordinate inCrd ){
  Coordinate outCrd = new Coordinate(
   affineParam[0] * inCrd.x + affineParam[2] * inCrd.y + affineParam[4] ,
   affineParam[1] * inCrd.x + affineParam[3] * inCrd.y + affineParam[5] );
  return (outCrd);
}
}