在 Azure Maps 中显示矢量切片 (PBF)

Display Vector Tile (PBF) in Azure Maps

我正在使用 Azure Maps,并希望显示我使用 tippecanoe 生成的矢量切片。

我最初在前端的 Azure Maps 中遇到错误 javascript,这基本上是在抱怨生成的 pbf 是不可接受的,因为它被压缩了。我修好了。

现在,前端 javascript 不会抛出任何错误,除非找不到 z/x/y pbf 文件。

当它没有在 javascript console.log 中抛出任何错误时,它不会显示来自矢量切片 pbf 的任何矢量。

我认为我不正确的是 javascript.

中的 sourceLayer
<script type="text/javascript">
        function InitMap() {
        console.log("Hi from InitMap")
            var map = new atlas.Map('myMap', {
                center: [-122.33, 47.6],
                zoom: 12,
                language: 'en-US',
                authOptions: {
                    authType: 'subscriptionKey',
                    subscriptionKey: '<My Azure Maps Key>'
                }
            });

            //Wait until the map resources are ready.
            map.events.add('ready', function () {
                //Create a vector tile source and add it to the map.
                datasource = new atlas.source.VectorTileSource(null, {
                    tiles: ['http://127.0.0.1:8080/api/file/{z}/{x}/{y}.pbf'],
                    maxZoom: 12
                });
                map.sources.add(datasource);

                var buildingLayer = new atlas.layer.PolygonLayer(datasource, null, {
                    sourceLayer: 'Feature',
                    fillColor: 'red',
                    fillOpacity: 0.7
                });
                map.layers.add(buildingLayer, 'labels');
            });
        }
    </script>

这是我的 Spring 引导程序,它服务于通过 tippecanoe 生成的 Vector Tiles (PBF):

@ResponseBody
@CrossOrigin
@GetMapping("api/file/{z}/{x}/{y}.pbf")
public ResponseEntity<Resource>getPbf(
            @PathVariable("z") int z,
            @PathVariable("x") int x,
            @PathVariable("y") int y,
            HttpServletResponse httpServletResponse
        ) throws FileNotFoundException {
    
    File file = new File(String.format("/home/markus/Documents/AssessorTilesNotZipped/%d/%d/%d.pbf", z, x, y));
    System.out.println("Z: " + String.valueOf(z) + ", X: " + String.valueOf(x) + ", Y: " + String.valueOf(y));
    HttpHeaders headers = new HttpHeaders();
    String filename = file.getName();
    headers.add("Content-disposition", "attachment; filename=" + filename);
    Resource resource = new InputStreamResource(new FileInputStream(file));
    return ResponseEntity.ok()
            .headers(headers)
            .contentLength(file.length())
            .contentType(MediaType.parseMediaType("application/x-protobuf"))
            .body(resource);
}

正如我所说,我认为我无法正确处理 Javascript 中的 sourceLayer。因此,下面是我使用 tippecanoe 生成 PBF 的 JSON 示例。

> {
"type": "FeatureCollection",
"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } },
"features": [
{ "type": "Feature", "properties": { "FIPS_CODE": 8009, "PARCEL_APN": null, "TAXAPN": null, "SITE_HOUSE_NUMBER": null, "SITE_DIRECTION": null, "SITE_STREET_NAME": null, "SITE_MODE": null, "SITE_QUADRANT": null, "SITE_UNIT_PREFIX": null, "SITE_UNIT_NUMBER": null, "SITE_CITY": null, "SITE_STATE": null, "SITE_ZIP": null, "SITE_PLUS_4": null, "_X_COORD": -102.554234, "_Y_COORD": 37.057221, "ADDR_SCORE": null, "OWNER_NAME_1": null, "OWNER_NAME_2": null, "MAIL_HOUSE_NUMBER": null, "MAIL_DIRECTION": null, "MAIL_STREET_NAME": null, "MAIL_MODE": null, "MAIL_QUADRANT": null, "MAIL_CITY": null, "MAIL_STATE": null, "MAIL_ZIP": null, "MAIL_PLUS_4": null, "MAIL_UNIT_PREFIX": null, "MAIL_UNIT_NUMBER": null, "USE_CODE_MUNI_DESC": null, "USE_CODE_MUNI": null, "USE_CODE_STD_LPS": null, "USE_CODE_STD_DESC_LPS": null, "USE_CODE_STD_CTGR_DESC_LPS": null, "USE_CODE_STD_CTGR_LPS": null, "AGGR_ACREAGE": null, "AGGR_LOT_COUNT": null, "ZONING": null, "BLDG_NUMBER": null, "BUILDING_SQFT": null, "STORIES_NUMBER": null, "STORIES_NUMBER_DESC": null, "TOTAL_ROOMS": null, "UNITS_NUMBER": null, "PARKING_SPACES": null, "BLDG_CLASS": null, "BLDG_CLASS_DESC": null, "CONSTRUCTION_CODE": null, "CONSTRUCTION_CODE_DESC": null, "EXTERIOR_WALL_TYPE": null, "EXTERIOR_WALL_DESC": null, "ROOF_COVER_TYPE": null, "ROOF_COVER_DESC": null, "LOCATION_ID": "US_08_009_XXX5168237061", "PROPERTY_DMP_ID": null, "PARCEL_DMP_ID": "516823706_1", "GEOM": "POLYGON ((-102.56102308 37.05449825, -102.56102664000002 37.061756619999983, -102.54291585 37.061754539999974, -102.54291557 37.058128049999986, -102.55197089 37.05812792, -102.55197016 37.050873270000011, -102.56102013 37.05087081, -102.56102308 37.05449825))" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -102.56102308, 37.05449825 ], [ -102.561026640000023, 37.061756619999983 ], [ -102.54291585, 37.061754539999974 ], [ -102.54291557, 37.058128049999986 ], [ -102.55197089, 37.05812792 ], [ -102.55197016, 37.050873270000011 ], [ -102.56102013, 37.05087081 ], [ -102.56102308, 37.05449825 ] ] ] } },
{ "type": "Feature", "properties": { "FIPS_CODE": 8009, "PARCEL_APN": null, "TAXAPN": null, "SITE_HOUSE_NUMBER": null, "SITE_DIRECTION": null, "SITE_STREET_NAME": null, "SITE_MODE": null, "SITE_QUADRANT": null, "SITE_UNIT_PREFIX": null, "SITE_UNIT_NUMBER": null, "SITE_CITY": null, "SITE_STATE": null, "SITE_ZIP": null, "SITE_PLUS_4": null, "_X_COORD": -102.737556, "_Y_COORD": 37.156019, "ADDR_SCORE": null, "OWNER_NAME_1": null, "OWNER_NAME_2": null, "MAIL_HOUSE_NUMBER": null, "MAIL_DIRECTION": null, "MAIL_STREET_NAME": null, "MAIL_MODE": null, "MAIL_QUADRANT": null, "MAIL_CITY": null, "MAIL_STATE": null, "MAIL_ZIP": null, "MAIL_PLUS_4": null, "MAIL_UNIT_PREFIX": null, "MAIL_UNIT_NUMBER": null, "USE_CODE_MUNI_DESC": null, "USE_CODE_MUNI": null, "USE_CODE_STD_LPS": null, "USE_CODE_STD_DESC_LPS": null, "USE_CODE_STD_CTGR_DESC_LPS": null, "USE_CODE_STD_CTGR_LPS": null, "AGGR_ACREAGE": null, "AGGR_LOT_COUNT": null, "ZONING": null, "BLDG_NUMBER": null, "BUILDING_SQFT": null, "STORIES_NUMBER": null, "STORIES_NUMBER_DESC": null, "TOTAL_ROOMS": null, "UNITS_NUMBER": null, "PARKING_SPACES": null, "BLDG_CLASS": null, "BLDG_CLASS_DESC": null, "CONSTRUCTION_CODE": null, "CONSTRUCTION_CODE_DESC": null, "EXTERIOR_WALL_TYPE": null, "EXTERIOR_WALL_DESC": null, "ROOF_COVER_TYPE": null, "ROOF_COVER_DESC": null, "LOCATION_ID": "US_08_009_XXX5168237062", "PROPERTY_DMP_ID": null, "PARCEL_DMP_ID": "516823706_2", "GEOM": "POLYGON ((-102.7330126 37.148770959999979, -102.74207003 37.148767860000021, -102.74210194 37.16326582, -102.73304057000001 37.16326841, -102.7330126 37.148770959999979))" }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -102.7330126, 37.148770959999979 ], [ -102.74207003, 37.148767860000021 ], [ -102.74210194, 37.16326582 ], [ -102.733040570000014, 37.16326841 ], [ -102.7330126, 37.148770959999979 ] ] ] } },
{ "type": "Feature", "properties": { "FIPS_CODE": 8009, "PARCEL_APN": null, "TAXAPN": null, "SITE_HOUSE_NUMBER": null, "SITE_DIRECTION": null, "SITE_STREET_NAME": null, "SITE_MODE": null, "SITE_QUADRANT": null, "SITE_UNIT_PREFIX": null, "SITE_UNIT_NUMBER": null, "SITE_CITY": null, "SITE_STATE": null, "SITE_ZIP": null, "SITE_PLUS_4": null, "_X_COORD": -102.81506, "_Y_COORD": 37.004085, "ADDR_SCORE": null, "OWNER_NAME_1": null, "OWNER_NAME_2": null, "MAIL_HOUSE_NUMBER": null, "MAIL_DIRECTION": null, "MAIL_STREET_NAME": null, "MAIL_MODE": null, "MAIL_QUADRANT": null, "MAIL_CITY": null, "MAIL_STATE": null, "MAIL_ZIP": null, "MAIL_PLUS_4": null, "MAIL_UNIT_PREFIX": null, "MAIL_UNIT_NUMBER": null, "USE_CODE_MUNI_DESC": null, "USE_CODE_MUNI": null, "USE_CODE_STD_LPS": null, "USE_CODE_STD_DESC_LPS": null, "USE_CODE_STD_CTGR_DESC_LPS": null, "USE_CODE_STD_CTGR_LPS": null, "AGGR_ACREAGE": null, "AGGR_LOT_COUNT": null, "ZONING": null, "BLDG_NUMBER": null, "BUILDING_SQFT": null, "STORIES_NUMBER": null, "STORIES_NUMBER_DESC": null, "TOTAL_ROOMS": null, "UNITS_NUMBER": null, "PARKING_SPACES": null, "BLDG_CLASS": null, "BLDG_CLASS_DESC": null, "CONSTRUCTION_CODE": null, "CONSTRUCTION_CODE_DESC": null, "EXTERIOR_WALL_TYPE": null, "EXTERIOR_WALL_DESC": null, "ROOF_COVER_TYPE": null, "ROOF_COVER_DESC": null, "LOCATION_ID": "US_08_009_XXX5168237063", "PROPERTY_DMP_ID": null, "PARCEL_DMP_ID": "516823706_3", "GEOM": "MULTIPOLYGON (((-102.8144019 37.000220300000024, -102.81440001 37.003712959999973, -102.80987063 37.0037188, -102.80987594 37.000216500000022, -102.80534993 37.000142429999983, -102.79628788000002 37.000114470000028, -102.79628782 36.999781059999975, -102.80082103000001 36.99990944000001, -102.80401110000003 37.000001709999985, -102.809876 37.000180469999968, -102.81285284 37.000269880000019, -102.8144019 37.000220300000024)), ((-102.81440001 37.003712959999973, -102.8152316 37.00371293, -102.81522985 37.00734288000001, -102.81439467000001 37.007342709999989, -102.81440001 37.003712959999973)), ((-102.82868814 37.01459485, -102.8324637 37.014591250000024, -102.83246369 37.014663750000011, -102.82794237000002 37.014704750000021, -102.82794456 37.010969900000021, -102.82861387000003 37.01096972, -102.82868814 37.01459485)), ((-102.83246474 37.00738149, -102.83298162 37.007378249999988, -102.8330751 37.010969139999986, -102.83246423000001 37.010968670000011, -102.83246474 37.00738149)), ((-102.84676076 37.01446194, -102.84676385 37.014609619999987, -102.84604829 37.01460972000001, -102.8460482 37.01447282, -102.84676076 37.01446194)), ((-102.83734745 37.01097245, -102.83699172000001 37.010976860000028, -102.83699172000001 37.010972190000018, -102.83734745 37.01097245)), ((-102.83760191 37.010972639999977, -102.83734745 37.01097245, -102.83760182 37.0109693, -102.83760191 37.010972639999977)))" }, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [ -102.8144019, 37.000220300000024 ], [ -102.81440001, 37.003712959999973 ], [ -102.80987063, 37.0037188 ], [ -102.80987594, 37.000216500000022 ], [ -102.80534993, 37.000142429999983 ], [ -102.796287880000023, 37.000114470000028 ], [ -102.79628782, 36.999781059999975 ], [ -102.80082103, 36.99990944000001 ], [ -102.804011100000025, 37.000001709999985 ], [ -102.809876, 37.000180469999968 ], [ -102.81285284, 37.000269880000019 ], [ -102.8144019, 37.000220300000024 ] ] ], [ [ [ -102.81440001, 37.003712959999973 ], [ -102.8152316, 37.00371293 ], [ -102.81522985, 37.00734288000001 ], [ -102.814394670000013, 37.007342709999989 ], [ -102.81440001, 37.003712959999973 ] ] ], [ [ [ -102.82868814, 37.01459485 ], [ -102.8324637, 37.014591250000024 ], [ -102.83246369, 37.014663750000011 ], [ -102.827942370000017, 37.014704750000021 ], [ -102.82794456, 37.010969900000021 ], [ -102.828613870000027, 37.01096972 ], [ -102.82868814, 37.01459485 ] ] ], [ [ [ -102.83246474, 37.00738149 ], [ -102.83298162, 37.007378249999988 ], [ -102.8330751, 37.010969139999986 ], [ -102.832464230000014, 37.010968670000011 ], [ -102.83246474, 37.00738149 ] ] ], [ [ [ -102.84676076, 37.01446194 ], [ -102.84676385, 37.014609619999987 ], [ -102.84604829, 37.01460972000001 ], [ -102.8460482, 37.01447282 ], [ -102.84676076, 37.01446194 ] ] ], [ [ [ -102.83734745, 37.01097245 ], [ -102.836991720000015, 37.010976860000028 ], [ -102.836991720000015, 37.010972190000018 ], [ -102.83734745, 37.01097245 ] ] ], [ [ [ -102.83760191, 37.010972639999977 ], [ -102.83734745, 37.01097245 ], [ -102.83760182, 37.0109693 ], [ -102.83760191, 37.010972639999977 ] ] ] ] } },

我还尝试过一件事,在浏览器控制台中,我尝试导入一个 pbf:

datasource = new atlas.source.VectorTileSource(null, { tiles: [http://127.0.0.1:8080/api/file/5/1/13.pbf'], maxZoom:12});

我找回了一个对象,当我尝试使用以下方法构建图层时:

var buildingLayer = new atlas.layer.PolygonLayer(datasource, null { sourceLayer: 'Feature', fillColor: 'red', fillOpacity: 0.7});

我不确定。

一些尝试:

  • 一种可能是矢量切片中数据的缩放范围和源上的最大缩放设置。源上的最大缩放指定源数据可用的最接近缩放级别。查看您的多边形,它们会很小,但在缩放级别 12 时可见,但当缩小两个或更多级别时,它们最终会非常小。

  • 仔细检查您用于创建矢量切片的设置,并确保它们在缩放级别 12 或更大缩小(即 11、10...)时可用

  • 检查网络调用以验证是否正在请求您的矢量切片。

  • 仔细检查矢量图块中的源图层 ID,确保它在多边形图层中相同。

  • 缩放您期望数据所在的地图(科罗拉多州南部、东部)并确保不要放大太多,然后在浏览器控制台中尝试这行代码。它应该检索正在呈现的数据源中的所有功能。 map.map.querySourceFeatures(datasource.getId(), { sourceLayer: 'Feature'})

好的,我发现了我犯的几个错误。感谢@rbrundritt 的建议,以及我不得不调查的要点。

我使用不同的 geojson 多边形集(MS Building Footprint)来测试生成的 tippecanoe 文件。

在我 运行 之前是这样的:

tippecanoe --no-feature-limit --no-tile-size-limit --exclude-all --minimum-zoom=5 --maximum-zoom=g --output-to-directory "/home/markus/Documents/AssessorTiles" /home/markus/Documents/Assessor_Json/*.json

--exclude-all 正在删除所有具有多边形(几何)数据分类的列。

所以,我 运行 以下是 MS 建筑足迹:

tippecanoe --no-feature-limit --no-tile-size-limit --minimum-zoom=2 --no-tile-compression --maximum-zoom=g --output-to-directory "/home/markus/Documents/GA_MicrosoftBuilding" /home/markus/Documents/MS_Building_Footprints_GA_Only/*.json

现在,MS Building Footprint 是经过修改的,我在其中为每个多边形添加了一个增量计数器并添加了状态。

这是修改后的 MS 建筑占地面积示例 json:

    {
"type": "FeatureCollection",
"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } },
"features": [
{ "type": "Feature", "properties": { "STATE": "GA", "BLDID": 1 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -82.561175, 30.686596 ], [ -82.561175, 30.686414 ], [ -82.560928, 30.686414 ], [ -82.560928, 30.686596 ], [ -82.561175, 30.686596 ] ] ] } },
{ "type": "Feature", "properties": { "STATE": "GA", "BLDID": 2 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -82.570518, 30.683769 ], [ -82.570513, 30.683796 ], [ -82.570401, 30.68378 ], [ -82.570386, 30.683854 ], [ -82.570595, 30.683884 ], [ -82.570615, 30.683783 ], [ -82.570518, 30.683769 ] ] ] } },
{ "type": "Feature", "properties": { "STATE": "GA", "BLDID": 3 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -82.125603, 30.740081 ], [ -82.125472, 30.740081 ], [ -82.125472, 30.740141 ], [ -82.125603, 30.740141 ], [ -82.125603, 30.740081 ] ] ] } },
{ "type": "Feature", "properties": { "STATE": "GA", "BLDID": 4 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ -82.075463, 30.737503 ], [ -82.075425, 30.737516 ], [ -82.075433, 30.737534 ], [ -82.075434, 30.737534 ], [ -82.075449, 30.737568 ], [ -82.075487, 30.737555 ], [ -82.075463, 30.737503 ] ] ] } },

密钥在将 PBF 读回 Azure 地图中起着重要作用 javascript。

这是我对 azure maps 所做的更改 javascript:

                var buildingLayer = new atlas.layer.PolygonLayer(datasource, null, {
                sourceLayer: 'GA',
                fillColor: 'red',
                fillOpacity: 0.7
            });
            map.layers.add(buildingLayer, 'labels');

所以,我使用了状态键,在本例中 'GA' 作为天蓝色地图中的 sourceLayer javascript。

然后 woola,矢量切片 (PBF) 显示在地图浏览器上。

如果 Microsoft 可以根据更通用的密钥生成多边形,那就太好了。目前,我看到的唯一解决方案是添加一个通用密钥,即:'POLYGON' 到 json 中并重建 PBF。