OpenStreetMapで天気予報地図

 天気予報RSSOpenStreetMapを利用して、天気予報地図を作ってみた。

 処理の流れとしては、
  1)WaypointPainterクラスのレンダラーにURLImageIconWaypointRenderクラスを設定する。
  2)天気予報RSSを取得し、各地点の予報アイコンのURLを取得する。
  3)URLImageIconWaypointクラスを生成し、WaypointPainterのSetへ追加する。

 天気予報地点の緯度経度は、2009-05-23のGeocodingで取得したものをcitydata.xmlとしてまとめて使用した。

 また、以下のライブラリが必要となる。
 ・SwingXSwingX-WSInforma

ソースコード
 ソースコードは、以下のとおり。なお、OpenStreetTileInfo.javaは、2009-06-02のものを使用している。

・OsmTest.java

package test;

import java.awt.BorderLayout;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.WindowConstants;

import org.jdesktop.swingx.JXMapKit;
import org.jdesktop.swingx.mapviewer.DefaultTileFactory;
import org.jdesktop.swingx.mapviewer.GeoPosition;

public class OsmTest {
	private JFrame frame;
	private JXMapKit kit;
	
	public OsmTest(){
		frame=new JFrame();
		initFrame();
		initMap();
		Runnable r=new Runnable(){
			public void run(){
				WeatherChecker wc=new WeatherChecker(
						kit,getClass().getResource("citydata.xml"));
				wc.updateWeatherForcastRssList();
			}
		};
		new Thread(r).start();
	}
	
	private void initFrame(){
		frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
		frame.addWindowListener(new WindowAdapter(){
			@Override
			public void windowClosing(WindowEvent e) {
				int id=JOptionPane.showConfirmDialog(
					frame, "終了しますか?", "Info", 
					JOptionPane.YES_NO_OPTION,
					JOptionPane.INFORMATION_MESSAGE);
				if(id==JOptionPane.YES_OPTION){
					frame.setVisible(false);
					System.exit(0);
				}
			}
		});
		frame.getContentPane().setLayout(new BorderLayout());
		frame.setTitle("OSM");
		frame.setSize(640,480);
	}
	
	private void initMap(){
		OpenStreetTileInfo info=new OpenStreetTileInfo(1,17,17,256,true,true,
					"http://tile.openstreetmap.org", "x", "y", "zoom");
		DefaultTileFactory tile=new DefaultTileFactory(info);
		kit=new JXMapKit();
		kit.setDefaultProvider(JXMapKit.DefaultProviders.OpenStreetMaps);
		kit.setDataProviderCreditShown(false);
		kit.setTileFactory(tile);
	    kit.setAddressLocationShown(false);
		kit.setZoom(9);
	    kit.setAddressLocation(new GeoPosition(34.6833,135.5));
	    kit.getMainMap().setRestrictOutsidePanning(true);
	    kit.getMainMap().setHorizontalWrapped(false);
	    kit.getMainMap().setDrawTileBorders(false);
	    frame.getContentPane().add(kit.getMainMap(),BorderLayout.CENTER);
	}
	
	public static void main(String[] args){
		OsmTest app=new OsmTest();
		app.frame.setVisible(true);
	}
}

・URLImageIconWaypoint.java

package test;

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;

import javax.imageio.ImageIO;

import org.jdesktop.swingx.mapviewer.GeoPosition;
import org.jdesktop.swingx.mapviewer.Waypoint;

public class URLImageIconWaypoint extends Waypoint {
	private BufferedImage img;

	public URLImageIconWaypoint(double latitude, double longitude,URL url) 
		throws IOException{
		super(latitude, longitude);
		img=ImageIO.read(url);
	}
	
	public URLImageIconWaypoint(GeoPosition coord,URL url)
	throws IOException{
		super(coord);
		img=ImageIO.read(url);
	}

	public BufferedImage getImage(){
		return img;
	}
}

・URLImageIconWaypointRender.java

package test;

import java.awt.AlphaComposite;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;

import org.jdesktop.swingx.JXMapViewer;
import org.jdesktop.swingx.mapviewer.Waypoint;
import org.jdesktop.swingx.mapviewer.WaypointRenderer;

public class URLImageIconWaypointRender implements WaypointRenderer {
	private static final AlphaComposite alpha=
		AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f);
	
	@Override
	public boolean paintWaypoint(Graphics2D arg0, JXMapViewer arg1,Waypoint arg2) {
		if(arg2 instanceof URLImageIconWaypoint){
			arg0.setComposite(alpha);
			URLImageIconWaypoint wp=(URLImageIconWaypoint)arg2;
			BufferedImage img=wp.getImage();
			if(img==null)return false;
			int width=img.getWidth();
			int height=img.getHeight();
			arg0.drawImage(img, -width/2,-height/2,width, height, arg1);
			return true;
		}else{
			return false;
		}
	}
}

・WeatherChecker.java

package test;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.jdesktop.swingx.JXMapKit;
import org.jdesktop.swingx.JXMapViewer;
import org.jdesktop.swingx.mapviewer.Waypoint;
import org.jdesktop.swingx.mapviewer.WaypointPainter;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import de.nava.informa.core.ChannelIF;
import de.nava.informa.core.ItemIF;
import de.nava.informa.impl.basic.ChannelBuilder;
import de.nava.informa.parsers.FeedParser;

public class WeatherChecker{
	private Set<Waypoint> waypoints;
	private Map<String,double[]> latlng;
	private JXMapKit kit;
	
	public WeatherChecker(JXMapKit kit,URL url){
		this.kit=kit;
		latlng=new HashMap<String,double[]>();
		waypoints=new HashSet<Waypoint>();
		WaypointPainter<JXMapViewer>
 			wp=new WaypointPainter<JXMapViewer>();
		wp.setWaypoints(waypoints);
		wp.setRenderer(new URLImageIconWaypointRender());
		kit.getMainMap().setOverlayPainter(wp);
		buildMap(url);
	}
	
	private void buildMap(URL url){
		try{
			URLConnection conn=
				(URLConnection)url.openConnection();
			conn.setRequestProperty("Accept-Language", "ja;q=0.7,en;q=0.3");
			conn.connect();
			DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance();
			DocumentBuilder db=dbf.newDocumentBuilder();
			Document doc=db.parse(conn.getInputStream());
			NodeList list=doc.getChildNodes();
			for(int i=0;i<list.getLength();i++){
				Node node=list.item(i);
				parseNode(node);
			}
		}catch(MalformedURLException e){
			e.printStackTrace();
		}catch(IOException e){
			e.printStackTrace();
		}catch(ParserConfigurationException e){
			e.printStackTrace();
		}catch(SAXException e){
			e.printStackTrace();
		}
	}
	
	private void parseNode(Node n){
		if(n.getNodeName().equals("city")){
			String[] val=n.getTextContent().split(",");
			latlng.put(val[0],new double[]{
					Double.parseDouble(val[2]),
					Double.parseDouble(val[1])});
		}else{
			NodeList list=n.getChildNodes();
			for(int i=0;i<list.getLength();i++){
				Node node=list.item(i);
				parseNode(node);
			}
		}
	}
	
	public void updateWeatherForcastRssList(){
		try{
			DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance();
			DocumentBuilder db=dbf.newDocumentBuilder();
			URL url =
			 new URL("http://weather.livedoor.com/forecast/rss/forecastmap.xml");
			Document doc=db.parse(url.openStream());
			NodeList list=doc.getChildNodes();
			Node n=list.item(0);
			parse(n);
		}catch(Exception e){
			e.printStackTrace();
		}
	}
	
	private void parse(Node n){
		NodeList list=n.getChildNodes();
		for(int i=0;i<list.getLength();i++){
			Node tmp=list.item(i);
			if(tmp.getNodeType()==3)continue;
			if(tmp.getNodeName().equals("city")){
				NamedNodeMap map=tmp.getAttributes();
				double[] pos=latlng.get(
						map.getNamedItem("title").getNodeValue());
				String img=null;
				try{
					URL url=
					new URL(map.getNamedItem("source").getNodeValue());
					ChannelIF channel = FeedParser.parse(new ChannelBuilder(), url);
					Set<ItemIF> tv=channel.getItems();
					for(ItemIF item : tv){
						if(item.getTitle().contains("PR"))continue;
						img=
						item.getElementValues("image", new String[]{"url"})[0];
					}
					if(img!=null){
						final URLImageIconWaypoint wp
							=new URLImageIconWaypoint(
								pos[0],pos[1],new URL(img));
						Runnable r=new Runnable(){
							public void run(){
								waypoints.add(wp);
							}
						};
						javax.swing.SwingUtilities.invokeLater(r);
					}
					kit.getMainMap().repaint();
				}catch(Exception e){
					e.printStackTrace();
				}
			}
			if(tmp.hasChildNodes()){
				parse(tmp);
			}
		}
	}
}

■実行結果
 実行結果は、以下のとおり。