Ajaxを利用してPostGISの情報をGoogle Mapsに表示する。

まずはHTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="ja">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta http-equiv="Content-Script-Type" content="text/javascript">
    <meta http-equiv="Content-Style-Type" content="text/css">
    <title>地図サンプル</title>
    <script type="text/javascript" src="js/prototype.js"></script>
    <script type="text/javascript" charset="utf-8" src="http://maps.google.com/maps?file=api&v=2&key=AB・・・&hl=ja"></script>
    <script>
    <!--
    var map;
    var objArray = new Array();
    function initOnLoad() {
        map = new GMap2($("MAP"));
        map.addControl(new GLargeMapControl());
        map.addControl(new GMapTypeControl());
        map.enableContinuousZoom();
        map.enableScrollWheelZoom();
        map.disableDoubleClickZoom();
        map.addMapType(G_PHYSICAL_MAP);
        map.addMapType(G_SATELLITE_3D_MAP);
        map.setCenter(new GLatLng(35.689487380721324, 139.6917736530304), 17);

        GEvent.addListener(map, "moveend", ajaxRequest);
    }
    function ajaxRequest() {
        var request = GXmlHttp.create();
        var url = "http://localhost:8080/Sample/map";
        var bounds = map.getBounds();
        var ne = bounds.getNorthEast();
        var sw = bounds.getSouthWest();
        var params = "n=" + ne.lat() + "&s=" + sw.lat() + "&e=" + ne.lng() + "&w=" + sw.lng();
        request.open("POST", url, true);
        request.onreadystatechange = function() {
            if( request.readyState == 4 ) {
                for( var i = 0; i < objArray.length; i++ ) {
                    map.removeOverlay(objArray[i]);
                }
                objArray = new Array();
                var xml = request.responseXML;
                var features = xml.documentElement.getElementsByTagName("point");
                for( var i = 0; features && i < features.length; i++ ) {
                    var feature = features[i];
                    var latlng = feature.getElementsByTagName("latlng")[0].firstChild.nodeValue;
                    var obj = new GMarker(stringToGLatLngArray(latlng)[0]);
                    map.addOverlay(obj);
                    objArray.push(obj);
                }
                features = xml.documentElement.getElementsByTagName("linestring");
                for( var i = 0; features && i < features.length; i++ ) {
                    var feature = features[i];
                    var latlng = feature.getElementsByTagName("latlng")[0].firstChild.nodeValue;
                    var obj = new GPolyline(stringToGLatLngArray(latlng), "#FF0000", 5);
                    map.addOverlay(obj);
                    objArray.push(obj);
                }
                features = xml.documentElement.getElementsByTagName("polygon");
                for( var i = 0; features && i < features.length; i++ ) {
                    var feature = features[i];
                    var latlng = feature.getElementsByTagName("latlng")[0].firstChild.nodeValue;
                    var obj = new GPolygon(stringToGLatLngArray(latlng), "#00FF00", 5, 1, "#00FF00", 0.2);
                    map.addOverlay(obj);
                    objArray.push(obj);
                }
            }
        }
        request.setRequestHeader("Content-type", "application/x-www-form-urlencoded;charset=UTF-8");
        request.send(params);
    }
    function stringToGLatLngArray(str) {
        var geometries = str.split(",");
        var geomArray = new Array();
        for( var i = 0; i < geometries.length; i++ ) {
            var geometry = geometries[i].split(" ");
            geomArray.push(new GLatLng(geometry[1], geometry[0]));
        }
        return geomArray;
    }
    // -->
    </script>
</head>
<body onload="initOnLoad();">
    <div id="MAP" style="width: 100%; height: 500px;">&nbsp;</div>
</body>
</html>


DBはPostGISを利用可能な状態にして

sample=# CREATE TABLE GeometryTable ( id INTEGER NOT NULL );
sample=# SELECT AddGeometryColumn('geometrytable', 'geometry', 4326, 'GEOMETRY', 2);
sample=#
sample=# \d GeometryTable
 カラム    |  型       |  修飾語
----------------------------------
 id        | integer   | not null
 geometry  | geometry  |
CHECK 制約:
    "enforce_dims_geometry" CHECK (ndims(geometry) = 2)
    "enforce_srid_geometry" CHECK (srid(geometry) = 4326)
sample=#
sample=# INSERT INTO GeometryTable VALUES ( 1, GeomFromText('POINT(139.6917736530304 35.689487380721324)', 4326));
sample=# INSERT INTO GeometryTable VALUES ( 2, GeomFromText('LINESTRING(139.6921142935753 35.69046768390191,139.69293236732483 35.68719995978114)', 4326));
sample=# INSERT INTO GeometryTable VALUES ( 3, GeomFromText('POLYGON((139.690692722797 35.6902389475707,139.691510796547 35.6869494287404,139.694270789623 35.687415633699,139.69346344471 35.690718203893,139.69069272279735.6902389475707))', 4326));


生成されるXMLはこんな感じ

<?xml version="1.0" encoding="UTF-8" ?>
<features>
    <point>
    <latlng>139.6917736530304 35.689487380721324</latlng>
    </point>
    <linestring>
        <latlng>139.6921142935753 35.69046768390191,139.69293236732483 35.68719995978114</latlng>
    </linestring>
    <polygon>
        <latlng>139.6906954050064 35.69023894757071,139.69150006771088 35.68694942874041,139.69426542520523 35.68741345517749,139.69345808029175 35.690720382324216,139.6906954050064 35.69023894757071</latlng>
    </polygon>
</features>


XMLを生成するServlet

@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    // 北
    String north = request.getParameter("n");
    // 西
    String west = request.getParameter("w");
    // 東
    String east = request.getParameter("e");
    // 南
    String south = request.getParameter("s");

    StringBuffer geometry = new StringBuffer("POLYGON((");
    geometry.append(west).append(" ").append(north).append(",");
    geometry.append(west).append(" ").append(south).append(",");
    geometry.append(east).append(" ").append(south).append(",");
    geometry.append(east).append(" ").append(north).append(",");
    geometry.append(west).append(" ").append(north);
    geometry.append("))");

    String sql = "SELECT AsText(geometry) AS geometry FROM GeometryTable WHERE ST_Intersects(geometry, GeomFromText(?, 4326)) = True";

    Connection con = null;
    Statement st = null;
    ResultSet rs = null;
    try {
        Class.forName("org.postgresql.Driver");
        con = DriverManager.getConnection("jdbc:postgresql:sample", "postgres", "postgres");
        st = con.createStatement(sql);
        st.setString(1, geometry.toString());
        rs = st.executeQuery();

        StringBuffer result = new StringBuffer("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>");
        result.append("<features>");
        while( rs.next() ) {
            String geometry = rs.getString("geometry");
            if( geometry.startsWith("POINT") ) {
                result.append("<point><latlng>").append(geometry.substring(6, geometry.length() - 1)).append("</latlng></point>");
            } else if( geometry.startsWith("LINESTRING") ) {
                result.append("<linestring><latlng>").append(geometry.substring(11, geometry.length() - 1)).append("</latlng></linestring>");
            } else if( geometry.startsWith("POLYGON") ) {
                result.append("<polygon><latlng>").append(geometry.substring(9, geometry.length() - 2)).append("</latlng></polygon>");
            }
        }
        result.append("</features>");
    } catch( Exception e ) {
        return;
    } finally {
        if( rs != null ) {
            try {
                rs.close();
            } catch( SQLException e ) {
            }
        }
        if( st != null ) {
            try {
                st.close();
            } catch( SQLException e ) {
            }
        }
        if( con != null ) {
            try {
                con.close();
            } catch( SQLException e ) {
            }
        }
    }
    response.setContentType("text/xml; charset=utf-8");
    response.getWriter().println(result);
}


この状態で東京都庁周辺を表示する、しないによってサーバから取得するデータ(XML)が動的に変わります。