提高 Mapbox GL 地理编码器的准确性

Increase Accuracy of Mapbox GL Geocoder

是否可以提高 Geocoder JSON 响应的精确度/精度?

我可以使用地图完成它,但是,使用地理编码器这是不可能的。

问题描述

为 JS 使用 Mapbox Geocoder:

<script src="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v4.7.2/mapbox-gl-geocoder.min.js"></script>

使用教程 在没有地图的情况下使用地理编码器:

https://docs.mapbox.com/mapbox-gl-js/example/mapbox-gl-geocoder-no-map/

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Use the geocoder without a map</title>
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
<link href="https://api.mapbox.com/mapbox-gl-js/v2.6.1/mapbox-gl.css" rel="stylesheet">
<script src="https://api.mapbox.com/mapbox-gl-js/v2.6.1/mapbox-gl.js"></script>
<style>
body { margin: 0; padding: 0; }
#map { position: absolute; top: 0; bottom: 0; width: 100%; }
</style>
</head>
<body>
<script src="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v4.7.2/mapbox-gl-geocoder.min.js"></script>
<link rel="stylesheet" href="https://api.mapbox.com/mapbox-gl-js/plugins/mapbox-gl-geocoder/v4.7.2/mapbox-gl-geocoder.css" type="text/css">
 
<style>
#geocoder {
z-index: 1;
margin: 20px;
}
.mapboxgl-ctrl-geocoder {
min-width: 100%;
}
</style>
 
<div id="geocoder"></div>
<pre id="result"></pre>
 
<script>
    mapboxgl.accessToken = 'pk.eyJ1IjoiaGVldm8iLCJhIjoiY2t2bWZkZXVqNXkzcjJvcXB0MHZyeTV1ZiJ9.d-C9xDxy9sNFiiN4klZl_w';
const geocoder = new MapboxGeocoder({
accessToken: mapboxgl.accessToken,
types: 'country,region,place,postcode,locality,neighborhood'
});
 
geocoder.addTo('#geocoder');
 
// Get the geocoder results container.
const results = document.getElementById('result');
 
// Add geocoder result to container.
geocoder.on('result', (e) => {
results.innerText = JSON.stringify(e.result, null, 2);
});
 
// Clear results container when search is cleared.
geocoder.on('clear', () => {
results.innerText = '';
});
</script>
 
</body>
</html>

我收到一个包含大量数据的 JSON response,我可以在发送请求之前配置一些选项。但是,我无法在以下文档中找到提高此响应准确度/精确度的选项:

https://github.com/mapbox/mapbox-gl-geocoder/blob/main/API.md

JSON 响应只有 6 位十进制数字,如下面的 Mapbox 网站示例所示,计算近距离时不可靠。

{
    "type": "FeatureCollection",
    "query": [
        "825",
        "s",
        "milwaukee",
        "ave",
        "deerfield",
        "il",
        "60015"
    ],
    "features": [{
            "id": "address.4356035406756260",
            "type": "Feature",
            "place_type": [
                "address"
            ],
            "relevance": 1,
            "properties": {},
            "text": "Milwaukee Ave",
            "place_name": "825 Milwaukee Ave, Deerfield, Illinois 60015, United States",
            "matching_text": "South Milwaukee Avenue",
            "matching_place_name": "825 South Milwaukee Avenue, Deerfield, Illinois 60015, United States",
            "center": [
                -87.921434,
                42.166602
            ],
            "geometry": {
                "type": "Point",
                "coordinates": [
                    -87.921434,
                    42.166602
                ],
                "interpolated": true,
                "omitted": true
            },
            "address": "825",
            "context": [{
                    "id": "neighborhood.287187",
                    "text": "Lake Cook Road"
                },
                {
                    "id": "postcode.13903677306297990",
                    "text": "60015"
                },
                {
                    "id": "place.5958304312090910",
                    "wikidata": "Q287895",
                    "text": "Deerfield"
                },
                {
                    "id": "region.3290978600358810",
                    "short_code": "US-IL",
                    "wikidata": "Q1204",
                    "text": "Illinois"
                },
                {
                    "id": "country.9053006287256050",
                    "short_code": "us",
                    "wikidata": "Q30",
                    "text": "United States"
                }
            ]
        },
        {
            "id": "address.7464624790403620",
            "type": "Feature",
            "place_type": [
                "address"
            ],
            "relevance": 0.5,
            "properties": {},
            "text": "Milwaukee Ave",
            "place_name": "825 Milwaukee Ave, Wheeling, Illinois 60090, United States",
            "matching_text": "South Milwaukee Avenue",
            "matching_place_name": "825 South Milwaukee Avenue, Wheeling, Illinois 60090, United States",
            "center": [
                -87.910299,
                42.144504
            ],
            "geometry": {
                "type": "Point",
                "coordinates": [
                    -87.910299,
                    42.144504
                ],
                "interpolated": true
            },
            "address": "825",
            "context": [{
                    "id": "neighborhood.287187",
                    "text": "Lake Cook Road"
                },
                {
                    "id": "postcode.9418633295906190",
                    "text": "60090"
                },
                {
                    "id": "place.9902190947082220",
                    "wikidata": "Q935043",
                    "text": "Wheeling"
                },
                {
                    "id": "region.3290978600358810",
                    "short_code": "US-IL",
                    "wikidata": "Q1204",
                    "text": "Illinois"
                },
                {
                    "id": "country.9053006287256050",
                    "short_code": "us",
                    "wikidata": "Q30",
                    "text": "United States"
                }
            ]
        },
        {
            "id": "address.6472754353404224",
            "type": "Feature",
            "place_type": [
                "address"
            ],
            "relevance": 0.5,
            "properties": {},
            "text": "Milwaukee Avenue",
            "place_name": "825 Milwaukee Avenue, Glenview, Illinois 60025, United States",
            "matching_text": "South Milwaukee Avenue",
            "matching_place_name": "825 South Milwaukee Avenue, Glenview, Illinois 60025, United States",
            "center": [
                -87.852677,
                42.071152
            ],
            "geometry": {
                "type": "Point",
                "coordinates": [
                    -87.852677,
                    42.071152
                ]
            },
            "address": "825",
            "context": [{
                    "id": "neighborhood.275266",
                    "text": "Northfield Woods"
                },
                {
                    "id": "postcode.3787740186211610",
                    "text": "60025"
                },
                {
                    "id": "place.10211845459386970",
                    "wikidata": null,
                    "text": "Glenview"
                },
                {
                    "id": "region.3290978600358810",
                    "short_code": "US-IL",
                    "wikidata": "Q1204",
                    "text": "Illinois"
                },
                {
                    "id": "country.9053006287256050",
                    "short_code": "us",
                    "wikidata": "Q30",
                    "text": "United States"
                }
            ]
        },
        {
            "id": "address.1225436500189372",
            "type": "Feature",
            "place_type": [
                "address"
            ],
            "relevance": 0.5,
            "properties": {},
            "text": "Milwaukee Ave",
            "place_name": "825 Milwaukee Ave, Buffalo Grove, Illinois 60089, United States",
            "matching_text": "South Milwaukee Avenue",
            "matching_place_name": "825 South Milwaukee Avenue, Buffalo Grove, Illinois 60089, United States",
            "center": [
                -87.917484,
                42.158084
            ],
            "geometry": {
                "type": "Point",
                "coordinates": [
                    -87.917484,
                    42.158084
                ],
                "interpolated": true
            },
            "address": "825",
            "context": [{
                    "id": "neighborhood.287187",
                    "text": "Lake Cook Road"
                },
                {
                    "id": "postcode.11727721238210580",
                    "text": "60089"
                },
                {
                    "id": "place.8589721255665070",
                    "wikidata": "Q967086",
                    "text": "Buffalo Grove"
                },
                {
                    "id": "region.3290978600358810",
                    "short_code": "US-IL",
                    "wikidata": "Q1204",
                    "text": "Illinois"
                },
                {
                    "id": "country.9053006287256050",
                    "short_code": "us",
                    "wikidata": "Q30",
                    "text": "United States"
                }
            ]
        },
        {
            "id": "address.240107872738130",
            "type": "Feature",
            "place_type": [
                "address"
            ],
            "relevance": 0.5,
            "properties": {},
            "text": "Milwaukee Avenue",
            "place_name": "825 Milwaukee Avenue, Wheeling, Illinois 60090, United States",
            "matching_text": "South Milwaukee Avenue",
            "matching_place_name": "825 South Milwaukee Avenue, Wheeling, Illinois 60090, United States",
            "center": [
                -87.898319,
                42.126289
            ],
            "geometry": {
                "type": "Point",
                "coordinates": [
                    -87.898319,
                    42.126289
                ],
                "interpolated": true,
                "omitted": true
            },
            "address": "825",
            "context": [{
                    "id": "neighborhood.287189",
                    "text": "Milwaukee Avenue"
                },
                {
                    "id": "postcode.9418633295906190",
                    "text": "60090"
                },
                {
                    "id": "place.9902190947082220",
                    "wikidata": "Q935043",
                    "text": "Wheeling"
                },
                {
                    "id": "region.3290978600358810",
                    "short_code": "US-IL",
                    "wikidata": "Q1204",
                    "text": "Illinois"
                },
                {
                    "id": "country.9053006287256050",
                    "short_code": "us",
                    "wikidata": "Q30",
                    "text": "United States"
                }
            ]
        }
    ],
    "attribution": "NOTICE: © 2018 Mapbox and its suppliers. All rights reserved. Use of this data is subject to the Mapbox Terms of Service (https://www.mapbox.com/about/maps/). This response and the information it contains may not be retained. POI(s) provided by Foursquare."
}

小数点后 6 位的精度为您提供约 10 厘米的精度。 Mapbox 正在使用 GeoJSON 规范,该规范对精度有以下建议:

The size of a GeoJSON text in bytes is a major interoperability consideration, and precision of coordinate values has a large impact on the size of texts. A GeoJSON text containing many detailed Polygons can be inflated almost by a factor of two by increasing coordinate precision from 6 to 15 decimal places. For geographic coordinates with units of degrees, 6 decimal places (a default common in, e.g., sprintf) amounts to about 10 centimeters, a precision well within that of current GPS systems. Implementations should consider the cost of using a greater precision than necessary.

支持 GPS 的智能手机在开阔天空下通常可以精确到 4.9 米(16 英尺)半径范围内。但是,它们的准确性在建筑物、桥梁和树木附近会变差。ref

下面是使用小数点后6位精度时的距离精度演示:

var lat1, lat2, lon1, lon2;

//https://www.geeksforgeeks.org/program-distance-two-points-earth/
// JavaScript program to calculate Distance Between Two Points on Earth
function distance(lat1, lat2, lon1, lon2) {

  // The math module contains a function
  // named toRadians which converts from
  // degrees to radians.
  lon1 = lon1 * Math.PI / 180;
  lon2 = lon2 * Math.PI / 180;
  lat1 = lat1 * Math.PI / 180;
  lat2 = lat2 * Math.PI / 180;

  // Haversine formula
  let dlon = lon2 - lon1;
  let dlat = lat2 - lat1;
  let a = Math.pow(Math.sin(dlat / 2), 2) +
    Math.cos(lat1) * Math.cos(lat2) *
    Math.pow(Math.sin(dlon / 2), 2);

  let c = 2 * Math.asin(Math.sqrt(a));

  // Radius of earth is 6371 kilometers
  let km = c * 6371; //kilometers
  let mi = c * 3956; //miles

  // calculate the result
  return [(km), (mi), (km * 1000), (km * 100000)];
}

function update() {
  lat1 = document.getElementById('lat1').value;
  lat2 = document.getElementById('lat2').value;
  lon1 = document.getElementById('lon1').value;
  lon2 = document.getElementById('lon2').value;
  let result = distance(lat1, lat2, lon1, lon2);
  format('result1', ...result);
}
update();

function format(id, km, mi, m, cm) {
  document.getElementById(id).innerHTML =
    `Centimeters:\t${cm}\n` +
    `Meters:\t\t${m}\n` +
    `Kilometers:\t${km}\n` +
    `Miles:\t\t${mi}\n`;
}
format('result2', ...distance(42.167803, 42.144516, -87.921589, -87.910345));
body {
  margin: 0;
  padding: 1rem;
}

input {
  width: 110px;
  font-size: 16px;
  color: red;
}

.result {
  width: 400px;
  height: 5rem;
  background-color: wheat;
  font-size: 16px;
  white-space: pre;
}
<p>Change values to update result.</p>
<label for="lat1">Latitude A:</label>
<input type="number" id="lat1" name="lat1" value="0.000000" step="0.000001" onchange="update()">
<label for="lon1">Longitude A:</label>
<input type="number" id="lon1" name="lon1" value="0.000000" step="0.000001" onchange="update()">
<br>
<label for="lat2">Latitude B:</label>
<input type="number" id="lat2" name="lat2" value="0.000001" step="0.000001" onchange="update()">
<label for="lon2">Longitude B:</label>
<input type="number" id="lon2" name="lon2" value="0.000000" step="0.000001" onchange="update()">

<div id="result1" class="result"></div>
<hr>
<p>(42.167803, -87.921589) to (42.144516, -87.910345) distance:</p>
<div id="result2" class="result"></div>

您可以在Google Maps上验证上述距离。


如果您搜索“美国伊利诺伊州”,您会得到 coordinates -89.2749461071049 40.1492928594。可能与他们收集数据的方式有关。他们从开放数据源(如 OpenStreetMap 和 NASA)和购买的专有数据源(如 DigitalGlobe)收集数据。ref. To verify, you can add new marker/location 具有更准确的坐标,并查看 API returns 是否仅提供 6 位数字或全部坐标.