SuperMap iClient3D for WebGL/WebGPU

主要介绍 SuperMap iClient3D for WebGL/WebGPU的入门用法,详细的接口参数请参考 API页面。

准备

获取 SuperMap iClient3D for WebGL/WebGPU

开发时需要引入SuperMap iClient3D for WebGL/WebGPU。其中包括必备的CSS 文件和 JS 文件。你可以通过以下几种方式获取:

SuperMap iClient3D for WebGL/WebGPU

引入

文件方式引入

将获取版本解压缩后,在examples/Webgl文件夹下新建HTML文件, 在文件中通过<script> 标签将SuperMap3D.js文件引入:

                                        <!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <script type="text/javascript" src="../../Build/SuperMap3D/SuperMap3D.js"></script>
</head>
</html>
                                    

同时应该根据需要在 <head> 标签中引入的其他css文件和js文件,如下:

                                        <!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
    <link href="../../Build/SuperMap3D/Widgets/widgets.css" rel="stylesheet">
    <link href="./css/pretty.css" rel="stylesheet">
    <script src="./js/jquery.min.js"></script>
    <script src="./js/config.js"></script>
    <script type="text/javascript" src="../../Build/SuperMap3D/SuperMap3D.js"></script>
    
</head>
</html>
                                    

创建三维场景

初始化三维球

在准备章节,已经新建了一个 HTML 页面,在页面中继续添加代码以初始化三维球,如下:

                                    <!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
    <link href="../../Build/SuperMap3D/Widgets/widgets.css" rel="stylesheet">
    <link href="./css/pretty.css" rel="stylesheet">
    <script src="./js/jquery.min.js"></script>
    <script src="./js/config.js"></script>
    <script type="text/javascript" src="../../Build/SuperMap3D/SuperMap3D.js"></script>
</head>
<body>
<div id="Container"></div>
<script>
    function onload(SuperMap3D) {
        var viewer = new SuperMap3D.Viewer('Container');
    }
</html>
                            

设置地图风格

在初始化时,三维球上可以叠加本地图片作为影像:

                                <script>
    function onload(SuperMap3D) {
        var viewer = new SuperMap3D.Viewer('Container');
          //使用本地的一张图片初始化地球,建议图片长宽比2:1
            viewer.imageryLayers.addImageryProvider(new SuperMap3D.SingleTileImageryProvider({
            url :  './images/worldimage.jpg'
        }));
    }
                            

运行效果

引用在线地图:SuperMap iClient3D for WebGL 对多种互联网地图信息进行了封装, 例如BingMap、天地图等,并分别为其提供了影像添加接口 BingMapsImageryProviderTiandituImageryProvider

添加BingMap影像作为底图:

                                <script>
    function onload(SuperMap3D) {
        var viewer = new SuperMap3D.Viewer('Container');
            viewer.imageryLayers.addImageryProvider(new SuperMap3D.BingMapsImageryProvider({
            url : 'https://dev.virtualearth.net',
            mapStyle : SuperMap3D.BingMapsStyle.AERIAL,
            key : BING_MAP_KEY //由BingMap官网申请的密钥
        }));
    }
                            

运行效果

添加天地图作为底图:

                                <script>
    function onload(SuperMap3D) {
        var viewer = new SuperMap3D.Viewer('Container');
        var labelImagery = new SuperMap3D.TiandituImageryProvider({
            mapStyle: SuperMap3D.TiandituMapsStyle.CIA_C,//天地图全球中文注记服务
            token: TOKEN_TIANDITU //由天地图官网申请的密钥
        });
        viewer.imageryLayers.addImageryProvider(labelImagery);
    }
                            

运行效果

添加图层

SuperMap iClient3D for WebGL/WebGPU 提供多种接口,支持在创建好的三维场景中添加种类丰富的数据图层。在此以添加地形图层为例介绍使用WebGPU方式加载的方法

添加地形图层:

(1)选择使用WebGL方式加载(默认WebGL2):

                             var viewer = new SuperMap3D.Viewer('Container',{
        //创建地形服务提供者的实例,url为SuperMap iServer发布的TIN地形服务
        terrainProvider : new SuperMap3D.SuperMapTerrainProvider({
            url : URL_CONFIG.SiChuan_TERRAIN,
            isSct : true,//地形服务源自SuperMap iServer发布时需设置isSct为true
            invisibility:true
        }),
    });
    viewer.resolutionScale = window.devicePixelRatio;
	viewer.scene.camera.setView({
        destination : new SuperMap3D.Cartesian3(-1206939.1925299785, 5337998.241228442, 3286279.2424502545),
        orientation : {
            heading : 1.4059101895600987,
            pitch : -0.20917672793046682,
            roll : 2.708944180085382e-13
        }
    });
                            

(2)选择使用WebGPU方式加载:

                            var viewer = new SuperMap3D.Viewer('Container',{
        //创建地形服务提供者的实例,url为SuperMap iServer发布的TIN地形服务
        terrainProvider : new SuperMap3D.SuperMapTerrainProvider({
            url : URL_CONFIG.SiChuan_TERRAIN,
            isSct : true,//地形服务源自SuperMap iServer发布时需设置isSct为true
            invisibility:true
        }),
        //使用WebGPU方式加载(若不开启此属性,则默认以WebGL2.0方式加载)
        contextOptions: {
            contextType : SuperMap3D.ContextType.WebGPU,
        }
    });
    viewer.resolutionScale = window.devicePixelRatio;
    viewer.scenePromise.then(function(scene){
    	//初始化场景(由于WebGPU采用异步加载,初始化场景需要放在回调中打开)
        init(SuperMap3D, scene, viewer);
    });
    function init(SuperMap3D, scene, viewer){
	    viewer.scene.camera.setView({
	        destination : new SuperMap3D.Cartesian3(-1206939.1925299785, 5337998.241228442, 3286279.2424502545),
	        orientation : {
	            heading : 1.4059101895600987,
	            pitch : -0.20917672793046682,
	            roll : 2.708944180085382e-13
	        }
	    });
}
                            
                            

添加影像图层:

                             var layer = new SuperMap3D.SuperMapImageryProvider({
    url : TEST_IMG  //影像服务的地址
});
var imgLayer = viewer.imageryLayers.addImageryProvider(layer)
                            

添加S3M图层:对于在SuperMap iServer上发布的S3M服务,可以通过以下两种方式打开。

(1).通过open接口将整个场景打开,这种方法简单易操作且不易出现遗漏图层的情况

                            var scene = viewer.scene;
var promise = scene.open("http://localhost:8090/iserver/services/3D-test/rest/realspace");  //url为在SuperMap iServer上发布的服务地址
                            

(2).通过addS3MTilesLayerByScp接口进行添加,该方式的优势是,可以根据自己的需要选择部分图层添加到场景中,提高加载性能,但需要加载多图层的整个场景时,不如scene.open方便。

                                var promise = scene.addS3MTilesLayerByScp('http://localhost:8090/iserver/services/3D-test/rest/realspace/datas/zj/config',
    {
        name : "base",
        cacheKey: "123456"  //三维缓存密钥,由SuperMap iServer设置和获取
    });
promise.then(function(layer){
    layer.visible = true;
});
                            

添加MVT图层:在SuperMap桌面产品中将地图生成好的矢量瓦片地图通过SuperMap iServer发布成矢量瓦片或三维服务后, 在WebGL中利用接口addVectorTilesMap将MVT图层服务添加到场景中。

                                var mvtMap = scene.addVectorTilesMap({
    url: url,  //MVT的服务地址
    canvasWidth: 512,
    name: 'testMVT',
    viewer: viewer
});
                            

场景设置

SuperMap iClient3D for WebGL提供了多种接口,方便用户对场景进行个性化设置。

颜色设置

SuperMap iClient3D for WebGL支持对场景的颜色进行设置:

                                viewer.scene.colorCorrection.show = true;
viewer.scene.colorCorrection.saturation = $("#saturation").val();
viewer.scene.colorCorrection.brightness = $("#brightness").val();
viewer.scene.colorCorrection.contrast = $("#contrast").val();
viewer.scene.colorCorrection.hue = $("#hue").val();
    //颜色校正开关
$("#colorCorrectionShow").on("input change", function() {
viewer.scene.colorCorrection.show = this.checked;
});
    //调节饱和度
$("#saturation").on("input change", function() {
	viewer.scene.colorCorrection.saturation = this.value;
});
    //调节亮度
$("#brightness").on("input change", function() {
viewer.scene.colorCorrection.brightness = this.value;
});
    //调节对比度
$("#contrast").on("input change", function() {
viewer.scene.colorCorrection.contrast = this.value;
});
    //调节色调
$("#hue").on("input change", function() {
viewer.scene.colorCorrection.hue = this.value;
});
                            

泛光效果设置

SuperMap iClient3D for WebGL支持在场景中开启泛光,并支持对泛光效果进行设置

                                //泛光效果开关
viewer.scene.bloomEffect.show = this.checked;
//调节亮度阈值
$("#bloom-threshold").on("input change", function() {
    viewer.scene.bloomEffect.threshold = parseFloat(this.value);
});
//调节泛光强度
$("#bloom-intensity").on("input change", function() {
viewer.scene.bloomEffect.bloomIntensity = parseFloat(this.value);
});
                            

分屏显示

支持对场景进行分屏显示,在不同的视口中对场景中的数据进行不同的操作,目前SuperMap iClient3D for WebGL支持 设置“NONE”、“HORIZONTAL”、“TRIPLE”、“VERTICAL”、“VerticalTrisection”和“QUAD”等11种模式。

                                scene.multiViewportMode = SuperMap3D.MultiViewportMode[value];
                            

场景出图

SuperMap iClient3D for WebGL支持在浏览器中将指定场景的某一角度作为图片保存至本地。具体方法为:

                                //根据图片生成画布
    function convertImageToCanvas(image) {
        var canvas = document.createElement("canvas");
        canvas.width = image.width;
        canvas.height = image.height;
        canvas.getContext("2d").drawImage(image, 0, 0);
        return canvas;
    };
//将图片保存至本地
    function download(base64data) {
        var image = new Image();
        image.src = base64data;
        image.onload = function() {
            var canvas = convertImageToCanvas(image);
            url = canvas.toDataURL("image/jpeg");
            var a = document.createElement('a');
            var event = new MouseEvent('click');
            a.download = (new Date()).getTime() + ".jpg"; // 指定下载图片的名称
            a.href = url;
            a.dispatchEvent(event); // 触发超链接的点击事件
        }
    } 
                            

查询

空间查询

SuperMap iClient3D for WebGL提供了丰富的接口,支持场景模型的空间位置信息查询和GPU空间查询等功能。

空间位置信息查询:实时获取鼠标点击位置的空间信息。

                                var handler = new SuperMap3D.ScreenSpaceEventHandler(scene.canvas);

    //设置鼠标左键单击回调事件
    handler.setInputAction(function(e) {
        //首先移除之前添加的点
        viewer.entities.removeAll();
        //获取点击位置笛卡尔坐标
        var position = scene.pickPosition(e.position);

        //将笛卡尔坐标转化为经纬度坐标
        var cartographic = SuperMap3D.Cartographic.fromCartesian(position);
        var longitude = SuperMap3D.Math.toDegrees(cartographic.longitude);
        var latitude = SuperMap3D.Math.toDegrees(cartographic.latitude);
        var height = cartographic.height;
        if(height < 0) {
            height = 0;
        }

        //创建弹出框信息,即时查看获取的位置信息
        var entity = new SuperMap3D.Entity({
            name : "位置信息",
            description : createDescription(SuperMap3D, [longitude, latitude, height])
        });
        viewer.selectedEntity = entity;

        //为更直观地展示查询的位置,在点击处添加对应点
        viewer.entities.add(new SuperMap3D.Entity({
            point : new SuperMap3D.PointGraphics({
                color : new SuperMap3D.Color(1, 1, 0),
                pixelSize : 10,
                outlineColor : new SuperMap3D.Color(0, 1, 1)
            }),
            position : SuperMap3D.Cartesian3.fromDegrees(longitude, latitude , height + 0.5)
        }));
    }, SuperMap3D.ScreenSpaceEventType.LEFT_CLICK);
                                

GPU空间查询:在场景中创建查询对象,通过GPU空间分析,获取查询对象与模型或模型子对象的空间关系。目前查询对象支持GeoCone、 GeoBox、GeoCylinder、GeoEllipsoid和GeoSphere等几类。示例代码如下:

                                    var geometry = undefined;
var pos = undefined;
var mode = SuperMap3D.PositionMode.Intersects
var spatialQuery = new SuperMap3D.SpatialQuery3D(scene);
var handler = new SuperMap3D.ScreenSpaceEventHandler(scene.canvas);

handler.setInputAction(function (evt) {
    var length = 100;
    var width = 100;
    var height = 100;
    // 获取鼠标点击的笛卡尔坐标
    var cartesian = scene.pickPosition(evt.position);
    var cartographic = SuperMap3D.Cartographic.fromCartesian(cartesian);
    pos = new SuperMap3D.Point3D(SuperMap3D.Math.toDegrees(cartographic.longitude), SuperMap3D.Math.toDegrees(cartographic.latitude), cartographic.height);
    geometry = new SuperMap3D.GeoBox(length, width, height);
    geometry.geoPosition = pos;
    spatialQuery.geometry = geometry;
    spatialQuery.positionMode = mode;
    spatialQuery.layers = layerSelect;
    spatialQuery.outlineColor = SuperMap3D.Color.CORNFLOWERBLUE;
    spatialQuery.fillStyle = SuperMap3D.FillStyle.Fill_And_WireFrame

    spatialQuery.build();
    tooltip.setVisible(false);
    handler.removeInputAction(SuperMap3D.ScreenSpaceEventType.MOUSE_MOVE)  //移除鼠标移动事件监听
}, SuperMap3D.ScreenSpaceEventType.LEFT_CLICK);
                            

运行效果

属性查询

属性查询是指在场景中对S3M模型的图层或对象属性进行查询

                                    function doSqlQuery(SQL) {
    var getFeatureParam;
    getFeatureParam = new SuperMap.REST.FilterParameter({
        attributeFilter: SQL //SQL为查询条件
});
                            

量算

SuperMap iClient3D for WebGL提供了量算功能,支持在前端对地形或S3M模型进行距离、面积和高差等指标的实时量算, 并支持贴地距离和贴地面积的量算。

下列代码展示距离量算的方法:

                                var handlerDis;
//初始化测量距离
    handlerDis = new SuperMap3D.MeasureHandler(viewer, SuperMap3D.MeasureMode.Distance, clampMode);
//注册测距功能事件
    handlerDis.measureEvt.addEventListener(function (result) {
    var dis = Number(result.distance);
    var selOptV = $("#selOpt").val();
    var positions = result.positions;
    if (selOptV == 3 || selOptV == 4) {
        dis = Number(calcClampDistance(positions));
    }
    var distance = dis > 1000 ? (dis / 1000).toFixed(2) + 'km' : dis.toFixed(2) + 'm';
    handlerDis.disLabel.text = '距离:' + distance;
});
                            

运行效果

绘制

SuperMap iClient3D for WebGL支持在前端实时进行点、线、面的绘制。

下列代码展示在前端绘制线的方法:

                                var handlerLine = new SuperMap3D.DrawHandler(viewer,SuperMap3D.DrawMode.Line);
handlerLine.activeEvt.addEventListener(function(isActive){
    if(isActive == true){
        viewer.enableCursorStyle = false;
        viewer._element.style.cursor = '';
        $('body').removeClass('drawCur').addClass('drawCur');
    }
    else{
        viewer.enableCursorStyle = true;
        $('body').removeClass('drawCur');
    }
});
handlerLine.movingEvt.addEventListener(function(windowPosition){
    if(handlerLine.isDrawing){
        tooltip.showAt(windowPosition,'<p>左键点击确定折线中间点</p><p>右键单击结束绘制</p>');
    }
    else{
        tooltip.showAt(windowPosition,'<p>点击绘制第一个点</p>');
    }
});
handlerLine.drawEvt.addEventListener(function(result){
    tooltip.setVisible(false);
});
                            

三维空间分析

SuperMap iClient3D for WebGL支持对三维场景进行一系列的空间分析。

通视分析

通视分析是指对场景中的指定两个点之间的通视性进行分析,具体步骤如下:

(1).打开三维场景或添加三维图层,此步骤可参考 “添加图层”中的"叠加S3M图层。

(2).将获取的点位坐标转为经纬度坐标,进行通视分析。

                                var cartographic = SuperMap3D.Cartographic.fromCartesian(position);
var longitude = SuperMap3D.Math.toDegrees(cartographic.longitude);
var latitude = SuperMap3D.Math.toDegrees(cartographic.latitude);
var height = cartographic.height;
                            

(3).添加观察点和目标点,进行通视分析。

                                //设置观察点
sightline.viewPosition = [longitude, latitude, height];
                                
                                //添加目标点
sightline.addTargetPoint({
    position : [longitude, latitude, height],
    name : "point" + new Date()
});
                            

可视域分析

可视域分析是指在三维场景中,基于指定观察点,对一定视域内对象的可见性进行分析。主要步骤有:

(1).打开三维场景。

(2).创建可视域分析对象,并指定可视区域和不可视区域的显示样式:

                                var viewshed3D = new SuperMap3D.ViewShed3D(scene);
var colorStr1 = viewshed3D.visibleAreaColor.toCssColorString();
var colorStr2 = viewshed3D.hiddenAreaColor.toCssColorString();
$("#colorPicker1").spectrum({
    color: colorStr1,
    showPalette: true,
    showAlpha: true,
    localStorageKey: "spectrum.demo",
    palette: palette
});
$('#colorPicker2').spectrum({
    color: colorStr2,
    showPalette: true,
    showAlpha: true,
    localStorageKey: "spectrum.demo",
    palette: palette
});
                            

(3).设置视口位置:

                                var viewPosition;
viewshed3D.viewPosition = [longitude, latitude, height];
                            

(4).以观察者位置(视口位置点)为球心,在场景中拾取一个点,将以观察者位置与该点的连线为半径绘制三维的可视域:

                                //计算该点与视口位置点坐标的距离
var distance = SuperMap3D.Cartesian3.distance(viewPosition, last);
if (distance > 0) {
    // 将鼠标当前点坐标转化成经纬度
    var cartographic = SuperMap3D.Cartographic.fromCartesian(last);
    var longitude = SuperMap3D.Math.toDegrees(cartographic.longitude);
    var latitude = SuperMap3D.Math.toDegrees(cartographic.latitude);
    var height = cartographic.height;
    // 通过该点设置可视域分析对象的距离及方向
    viewshed3D.setDistDirByPoint([longitude, latitude, height]);
}
                            

(5).进行可视域分析:

                                viewshed3D.build();
                            

阴影分析

阴影分析是指对场景中指定区域在指定时间段内的阴影率进行分析。主要步骤有:

(1).打开三维场景。值得注意的是在创建Viewer时,应将阴影开启,确保阴影可用:

                                var viewer = new SuperMap3D.Viewer('Container', {
    shadows : true
});
                                

(2).创建阴影查询对象,并设置图层的阴影模式:

                                //创建阴影查询对象
var shadowQuery = new SuperMap3D.ShadowQueryPoints(scene);
//设置图层的阴影模式
layers[0].shadowType = 2; //2表示图层上的所有模型都产生阴影
layers[1].shadowType = 2;
                                

(3).绘制阴影分析区域:

                                var handlerPolygon = new SuperMap3D.DrawHandler(viewer,SuperMap3D.DrawMode.Polygon,0);
handlerPolygon.activeEvt.addEventListener(function(isActive){
    if(isActive == true){
    viewer.enableCursorStyle = false;
    viewer._element.style.cursor = '';
    $('body').removeClass('drawCur').addClass('drawCur');
    }
    else{
    viewer.enableCursorStyle = true;
    $('body').removeClass('drawCur');
    }
});
                                

(4).阴影分析完成后,还可以获取分析区域内空间位置上的阴影率:

                                var shadowRadio=shadowQuery.getShadowRadio(cartographic);
                                

(5).执行阴影分析:

                                shadowQuery.build();
                                

天际线分析

天际线分析是指对三维场景的天际线进行绘制和分析。主要步骤有:

(1).打开三维场景。

(2).创建天际线分析对象:

                                var skyline = new SuperMap3D.Skyline(scene);
                                

(3).为使结果直观,将当前相机位置设置为天际线分析的视口:

                                 //天际线分析的视口位置设置成当前相机位置
skyline.viewPosition = [longitude, latitude, height];
//设置俯仰和方向
skyline.pitch = SuperMap3D.Math.toDegrees(scene.camera.pitch);
skyline.direction = SuperMap3D.Math.toDegrees(scene.camera.heading);
skyline.radius = 10000; // 设置天际线分析半径,单位:米

                                

(4).执行天际线分析:

                                skyline.build();
                                

(5).提取二维天际线:

                                var object = skyline.getSkyline2D();
                                

(6).此外,SuperMap iClient3D for WebGL还支持绘制限高体以辅助规划和建设部门的决策。 限高体的含义是在当前视口下,为保持当前的天际线不变,在指定区域内修建的建筑高度不能超过该限高体的高度,其绘制方法如下:

                                skyline.addLimitbody({
        position: arr,
        name: "limitBody"
    });