Azure Maps 勾勒出多边形拉伸的轮廓,或添加线拉伸层以突出显示形状的轮廓

azure maps outlining a polygon extrusion or adding a line extrusion layer to highlight the outline of shapes

提问人:Erik Bussing 提问时间:11/14/2023 更新时间:11/16/2023 访问量:28

问:

我目前正在尝试在 azure maps 中为建筑物创建一个映射工具,为了给它提供一些 3d 样式,我想添加一个多边形拉伸层,并根据您正在查看的楼层增加多边形的高度。但是,这使得更难看到不同房间的轮廓。我想要一个类似“线拉伸层”的东西,或者一个选项来突出显示拉伸多边形的边缘,甚至能够删除拉伸的顶部也会受到欢迎。 你们有什么想法我怎么能做到这一点吗?是否可以在挤压件的顶部放置线层?而不是在地图上?

我花了很多时间研究不同的选择,但没有找到任何接近我想要的东西。 我只想在挤压件的边缘有一条黑线

javascript c# html azure-maps

评论


答:

0赞 rbrundritt 11/15/2023 #1

不幸的是,没有线拉伸层。但是,有几种方法可以改善您的方案。

选项 1:每层楼的多边形拉伸

使用面拉伸图层的 base 和 height 属性创建每个楼层的切片。这应该在每个楼层之间创建一个接缝/线,并且还允许您使用事件来选择和突出显示各个楼层。为此,您可以为每个楼层创建一个面,并根据楼层编号为其分配一个底面/高度,也可以为每个楼层创建一个图层,并在数据源中重复使用相同的面。使用层方法将更具可扩展性,因为您的应用程序将使用更少的数据。如果您的楼层高度保持不变,事情可能会容易一些。如果我们假设您有一个指示建筑物所具有楼层数的值,则可以在每个图层上使用过滤器来确定是否应为该面创建楼层。这可能看起来像这样:

enter image description here

下面是一些示例源代码。您也可以在这里尝试直播:https://rbrundritt.azurewebsites.net/Demos/AzureMaps/BuildingFloors/index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <title></title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />

    <!-- Add references to the Azure Maps Map control JavaScript and CSS files. -->
    <link href="https://atlas.microsoft.com/sdk/javascript/mapcontrol/3/atlas.min.css" rel="stylesheet" />
    <script src="https://atlas.microsoft.com/sdk/javascript/mapcontrol/3/atlas.min.js"></script>

    <script>
        var map, datasource;

        //The colors to use for each floor.
        var colorScale = {
            1: '#09e076',
            2: '#0bbf67',
            3: '#f7e305',
            4: '#f7c707',
            5: '#f78205',
            6: '#f75e05',
            7: '#f72505'
        };

        //The height of a single floor in meters.
        var floorHeight = 4; 

        function GetMap() {
            //Initialize a map instance.
            map = new atlas.Map('myMap', {
                center: [-122.134183, 47.643853],
                zoom: 14,
                maxPitch: 85,
                style: 'satellite',

                //Pitch the map so that the extrusion of the polygons is visible.
                pitch: 45,

                view: 'Auto',

                //Add authentication details for connecting to Azure Maps.
                authOptions: {
                    authType: 'subscriptionKey',
                    subscriptionKey: '[YOUR_AZURE_MAPS_KEY]'
                }
            });

            //Create a legend.
            createLegend();

            //Wait until the map resources are ready.
            map.events.add('ready', function () {
                //Create a data source to add your data to.
                datasource = new atlas.source.DataSource();
                map.sources.add(datasource);

                //Load a dataset of polygons that have metadata we can style against.
                datasource.importDataFromUrl('MSFT_Campus_Buildings.geojson');                

                //Create a polygon extrusion layer per floor.
                for(var i = 1; i <= 7; i++) {
                    map.layers.add(new atlas.layer.PolygonExtrusionLayer(datasource, null, {
                        base: floorHeight * (i - 1),
                        height: floorHeight * i,
                        fillColor: colorScale[i],
                        filter: ['>=', ['get', 'floors'], i]
                    }), 'labels');                
                }
            });
        }

        function createLegend() {
            var html = [];

            Object.keys(colorScale).forEach(function (key) {
                html.push('<i style="background:', colorScale[key], '"></i> ', key, '<br/>');
            });

            document.getElementById('legend').innerHTML += html.join('');
        }
    </script>
    <style>
        html, body, #myMap {
            margin: 0;
            padding:0;
            height: 100%;
            width:100%;
        }

        #myMap {
            background: linear-gradient(to bottom, #1e528e 0%,#728a7c 15%,#e9ce5d 100%); /** Give the sky/background some color for when the maps is pitched a lot **/
        }

        #legend {
            position: absolute;
            top: 1px;
            left: 5px;
            font-family: Arial;
            font-size: 12px;
            background-color: rgba(255, 255, 255, 0.8);
            border-radius: 5px;
            padding: 5px;
            line-height: 20px;
        }

            #legend i {
                width: 18px;
                height: 18px;
                float: left;
                margin-right: 8px;
                opacity: 0.7;
            }
    </style>
</head>
<body onload="GetMap()">
    <div id="myMap"></div>

    <div id="legend">Floor<br /></div>
</body>
</html>

我尝试将所有地板的颜色设置为相同的颜色,但接缝不是很明显。如果希望所有楼层的颜色相同,可以在每个楼层之间添加一个具有单独颜色的薄层,如下所示:

enter image description here

这是上述代码的修改版本,用于执行此操作。您也可以在这里现场尝试: https://rbrundritt.azurewebsites.net/Demos/AzureMaps/BuildingFloors/FloorSeperator.html

<!DOCTYPE html>
<html lang="en">
<head>
    <title></title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />

    <!-- Add references to the Azure Maps Map control JavaScript and CSS files. -->
    <link href="https://atlas.microsoft.com/sdk/javascript/mapcontrol/3/atlas.min.css" rel="stylesheet" />
    <script src="https://atlas.microsoft.com/sdk/javascript/mapcontrol/3/atlas.min.js"></script>

    <script>
        var map, datasource;

        //The height of a single floor in meters.
        var floorHeight = 3.9;
        var floorSeperatorHeight = 0.1;

        function GetMap() {
            //Initialize a map instance.
            map = new atlas.Map('myMap', {
                center: [-122.134183, 47.643853],
                zoom: 14,
                maxPitch: 85,
                style: 'satellite',

                //Pitch the map so that the extrusion of the polygons is visible.
                pitch: 45,

                view: 'Auto',

                //Add authentication details for connecting to Azure Maps.
                authOptions: {
                    authType: 'subscriptionKey',
                    subscriptionKey: '[YOUR_AZURE_MAPS_KEY]'
                }
            });

            //Wait until the map resources are ready.
            map.events.add('ready', function () {
                //Create a data source to add your data to.
                datasource = new atlas.source.DataSource();
                map.sources.add(datasource);

                //Load a dataset of polygons that have metadata we can style against.
                datasource.importDataFromUrl('MSFT_Campus_Buildings.geojson');

                //Create a polygon extrusion layer per floor. And a thin layer above the top floor to act as a seperator.
                var floorBase = 0;

                for (var i = 1; i <= 7; i++) {
                    floorBase = (floorHeight + floorSeperatorHeight) * (i - 1);

                    map.layers.add(new atlas.layer.PolygonExtrusionLayer(datasource, null, {
                        base: floorBase,
                        height: floorBase + floorHeight,
                        filter: ['>=', ['get', 'floors'], i]
                    }), 'labels');

                    //Add a layer to render a thin line seperator between each floor. Can skip the top floor by making filter ">" rather than ">="
                    map.layers.add(new atlas.layer.PolygonExtrusionLayer(datasource, null, {
                        base: floorBase + floorHeight,
                        height: floorBase + floorHeight + floorSeperatorHeight,
                        fillColor: 'black',
                        filter: ['>', ['get', 'floors'], i]
                    }), 'labels');
                }
            });
        }
    </script>
    <style>
        html, body, #myMap {
            margin: 0;
            padding:0;
            height: 100%;
            width:100%;
        }

        #myMap {
            background: linear-gradient(to bottom, #1e528e 0%,#728a7c 15%,#e9ce5d 100%); /** Give the sky/background some color for when the maps is pitched a lot **/
        }
    </style>
</head>
<body onload="GetMap()">
    <div id="myMap"></div>
</body>
</html>

选项 2:集成 Deck.gl

Deck.gl 是另一个 WebGL 渲染层,它支持渲染多边形拉伸和线条,如下所示:https://deck.gl/examples/geojson-layer-polygons。Deck.gl 可以通过以下示例与 Azure Maps 一起使用: 可以通过以下示例所示: https://samples.azuremaps.com/?search=deck&sample=deck-gl-custom-webgl-layer 这将为你提供你要查找的线条,但会在 Azure Maps API 之外引入许多新内容,这将使保持一致变得更加困难。例如,事件的处理方式不同,因此您的地图可能会使用两种不同类型的事件,这可能会使将来更难维护。我也有一种感觉,这种方法的实现会复杂得多。WebGlLayer