操作系统数据中心 - 来自网格参考的邮政编码

问题描述

我负责维护英格兰西南部步行俱乐部的网站,该网站显示了即将进行的步行活动列表。每个步行条目都有一个用于步行开始的操作系统网格参考,以及一个步行者可以输入到其卫星导航设备的英国邮政编码,以帮助他们开车到步行的起点。我目前使用 Nearby UK 的 API 获取每次步行的起点网格参考的最近邮政编码,这也为我提供了从我的网格参考到邮政编码中心的罗盘方位和距离,在一个国家地区可以是从步行开始一英里或更远。根据这些,我计算出邮政编码中心的网格参考,然后我可以将这两个点显示为操作系统地图上的标记 - 到目前为止,一切都很好。

最近完成了从 OS Open Space 到 OS Data Hub 的迁移,我想知道我是否还可以使用 OS Data Hub 为我提供距网格参考最近的邮政编码,以及从一个到另一个的方位角和距离,或者邮政编码中心的网格参考,而不需要为此使用 Nearby API。

大约一个月前,我向 Ordnance Survey 的客户成功团队询问了这个问题,但他们还没有提供任何帮助。我还尝试了各种使用英国邮政编码数据库方法,该数据库列出了每个英国邮政编码及其东坐标和北坐标,但在整个列表中搜索最近的坐标,使用毕达哥拉斯计算到步行起点,需要几分钟。这可能是因为我必须使用我们的 walks 数据库进行搜索,该数据库是用 Visual Basic 编写的,但那是另一回事了。

任何关于如何从 OS Data Hub 获取最近的邮政编码及其位置的指针,对于给定的网格参考,都非常受欢迎。

解决方法

例如,您可以找到最近的邮政编码,只要它的中心距离不超过 1 公里

https://api.os.uk/search/names/v1/nearest?point=440200,458300&radius=1000&fq=LOCAL_TYPE:Postcode&key=yourkey

超过 1 公里,您需要在原点周围的外圈中进一步搜索

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width,initial-scale=1.0" />
    <title>Basic Map</title>
    <link rel="stylesheet" href="https://labs.os.uk/public/os-api-branding/v0.2.0/os-api-branding.css" />
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.5.0/css/ol.css" />
    <style>
        body { margin:0; padding:0; }
        #map { position:absolute; top:0; bottom:0; width:100%; }
    </style>
</head>
<body>

<div id="map"></div>

<script src="https://labs.os.uk/public/os-api-branding/v0.2.0/os-api-branding.js"></script>
<script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.5.0/build/ol.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.5.0/proj4.js"></script>
<script>

    var apiKey = 'ufArYa1UUPHJcOYbiJDaKkA7Fb4oCkEs';

    var serviceUrl = 'https://api.os.uk/maps/raster/v1/zxy';

    // Setup the EPSG:27700 (British National Grid) projection.
    proj4.defs("EPSG:27700","+proj=tmerc +lat_0=49 +lon_0=-2 +k=0.9996012717 +x_0=400000 +y_0=-100000 +ellps=airy +towgs84=446.448,-125.157,542.06,0.15,0.247,0.842,-20.489 +units=m +no_defs");
    ol.proj.proj4.register(proj4);

    var tilegrid = new ol.tilegrid.TileGrid({
        resolutions: [ 896.0,448.0,224.0,112.0,56.0,28.0,14.0,7.0,3.5,1.75 ],origin: [ -238375.0,1376256.0 ]
    });

    var gridReference = new ol.Feature();
    gridReference.setStyle(
        new ol.style.Style({
            image: new ol.style.Circle({
                radius: 6,fill: new ol.style.Fill({
                    color: 'red'
                })
            }),text: new ol.style.Text({
                font: 'bold 14px sans-serif',offsetY: -6,textBaseline: 'bottom'
            })
        })
    );

    var postcode = new ol.Feature();
    postcode.setStyle(
        new ol.style.Style({
            image: new ol.style.Circle({
                radius: 6,fill: new ol.style.Fill({
                    color: 'blue'
                })
            }),textBaseline: 'bottom'
            })
        })
    );

    // Initialize the map object.
    var map = new ol.Map({
        layers: [
            new ol.layer.Tile({
                source: new ol.source.XYZ({
                    url: serviceUrl + '/Road_27700/{z}/{x}/{y}.png?key=' + apiKey,projection: 'EPSG:27700',tileGrid: tilegrid
                })
            }),new ol.layer.Vector({
                source: new ol.source.Vector({
                    features: [gridReference,postcode]
                })
            })
        ],target: 'map',view: new ol.View({
            projection: 'EPSG:27700',extent: [ -238375.0,0.0,900000.0,1376256.0 ],resolutions: tilegrid.getResolutions(),minZoom: 0,maxZoom: 9,center: [ 337297,503695 ],zoom: 7
        })
    });

    map.on('singleclick',function(evt) {
        gridReference.setGeometry(new ol.geom.Point(evt.coordinate));
        postcode.setGeometry(undefined);

        var x = (Math.round(evt.coordinate[0]/10)/10) + 10000;
        var y = (Math.round(evt.coordinate[1]/10)/10) + 5000;

        var a1y = (4 - (Math.floor(y/5000)%5))*5;
        var a2y = (4 - (Math.floor(y/1000)%5))*5;
        var y1 = Math.floor(y/100)%10;
        var y2 = Math.floor(y/10)%10;
        var y3 = Math.floor(y)%10;
        a1y += (Math.floor(x/5000)%5);
        a2y += (Math.floor(x/1000)%5);
        var x1 = Math.floor(x/100)%10;
        var x2 = Math.floor(x/10)%10;
        var x3 = Math.floor(x)%10;

        var grid500km = String.fromCharCode(a1y + Math.floor((a1y+17)/25) + "A".charCodeAt(0));
        var grid100km = grid500km + String.fromCharCode(a2y + Math.floor((a2y+17)/25) + "A".charCodeAt(0));
        var gridText = grid100km + x1 + x2 + x3 + y1 + y2 + y3;

        gridReference.getStyle().getText().setText(gridText);

        var minDistSq = Infinity;
        var postcodeCoord,postcodeText;
        var radius = 0;
        tryPoints([evt.coordinate]);

        function tryPoints(coordinates) {

            var promises = [];

            coordinates.forEach(function(coordinate) {
                promises.push(
                    fetch(
                        'https://api.os.uk/search/names/v1/nearest?point=' +
                        coordinate[0].toFixed(2) + ',' + coordinate[1].toFixed(2) +
                        '&radius=1000&fq=LOCAL_TYPE:Postcode&key=' + apiKey
                    ).then(function(response) {
                        return response.json();
                    })
                );
            });

            Promise.all(promises).then(function(results) {
                results.forEach(function(result) {
                    if (result.results && result.results.length > 0) {
                        var entry = result.results[0]['GAZETTEER_ENTRY'];
                        var dx = entry['GEOMETRY_X'] - evt.coordinate[0];
                        var dy = entry['GEOMETRY_Y'] - evt.coordinate[1];
                        var distSq = dx * dx + dy * dy;
                        if (distSq < minDistSq) {
                            minDistSq = distSq;
                            postcodeCoord = [entry['GEOMETRY_X'],entry['GEOMETRY_Y']];
                            postcodeText = entry['NAME1'];
                        }
                    }
                });
                if (postcodeCoord) {
                    postcode.setGeometry(new ol.geom.Point(postcodeCoord));
                    postcode.getStyle().getText().setText(postcodeText);
                } else if (radius < 4) {
                    radius++;
                    var outerCircle = ol.geom.Polygon.fromCircle(new ol.geom.Circle(evt.coordinate,radius * 1000),16 * radius);
                    tryPoints(outerCircle.getCoordinates()[0].slice(0,-1));
                }
            });

        }

    });

</script>

</body>
</html>

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...