SuperMap iClient3D for WebGL 之反向遮罩

本文介绍如何使用 Cesium 的 entity 绘制技术,通过创建两个实体面覆盖整个地球,并利用 holes 属性挖空特定区域,最终实现对目标区域的高亮显示。

作者:Taco

前言

        全球范围内如果要凸显某一个区域,往往都是通过使这个区域高亮显示。但是有时候由于地球的影像花花绿绿的,导致不能一眼就看到我们需要看到的部分。那么我们该如何在加载全球场景的时候一下子就能看到我们想要看的呢?不如我们把其他部分都给盖上!只显示我们需要的!

        那么通过什么能够实现这个功能呢?首先想到的就是entity,直接用实体把地球给盖上呗,然而在实现的过程中却发现,单个的实体并不能将全球盖上。单个实体的范围当设置跨过半球的时候,会出现变形,或者陷入地球中。既然单个的不行那就整两个!绘制两个实体面来将地球包裹上。

一,绘制实体面包裹地球

实现代码

viewer.entities.add({
						polygon: {
							// 获取指定属性(positions,holes(图形内需要挖空的区域))
							hierarchy: {
								//左下左上右上右下
								// 0,60,0,-60,180,-60,180,60,0,-60
								positions: [{
									x: 3197104.586923899,
									y: -0.5580000157243585,
									z: 5500477.1339386385
								}, {
									x: 3197104.586923899,
									y: -0.5580000157243585,
									z: -5500477.1339386385
								}, {
									x: -3197104.5869239476,
									y: -3.915323898915733,
									z: -5500477.1339386385
								}, {
									x: -3197104.5869239476,
									y: -3.915323898915733,
									z: 5500477.1339386385
								}, {
									x: 3197104.586923899,
									y: -0.5580000157243585,
									z: 5500477.1339386385
								}],
							},
							// 边框
							outline: false,
							// 边框颜色
							outlineColor: Cesium.Color.WHITE,
							// 边框尺寸
							outlineWidth: 2,
							// 填充的颜色,withAlpha透明度
							material: Cesium.Color.BLUE.withAlpha(0.5),
							// 是否被提供的材质填充
							fill: true,
							// 是否显示
							show: true,
							// 顺序,仅当`clampToGround`为true并且支持地形上的折线时才有效。
							zIndex: 10
						}
					});
			viewer.entities.add({
						polygon: {
							// 获取指定属性(positions,holes(图形内需要挖空的区域))
							hierarchy: {
								//左下左上右上右下
								// 0,60,0,-60,180,-60,180,60,0,-60
								positions: [{
									x: 3197104.586923899,
									y: 0.5580000157243585,
									z: 5500477.1339386385
								}, {
									x: 3197104.586923899,
									y: 0.5580000157243585,
									z: -5500477.1339386385
								}, {
									x: -3197104.5869239476,
									y: 3.915323898915733,
									z: -5500477.1339386385
								}, {
									x: -3197104.5869239476,
									y: 3.915323898915733,
									z: 5500477.1339386385
								}, {
									x: 3197104.586923899,
									y: 0.5580000157243585,
									z: 5500477.1339386385
								}],
							},
							// 边框
							outline: false,
							// 边框颜色
							outlineColor: Cesium.Color.RED,
							// 边框尺寸
							outlineWidth: 200,
							// 填充的颜色,withAlpha透明度
							material: Cesium.Color.BLUE.withAlpha(0.5),
							// 是否被提供的材质填充
							fill: true,
							// 是否显示
							show: true,
							// 顺序,仅当`clampToGround`为true并且支持地形上的折线时才有效。
							zIndex: 10
						}
					});

                        

 

这样我们就得到了一个蓝色的球体将地球包裹住。有人会说为什么你使用两个面来包裹,明明一个实体球也能把地球包上的。这是因为我们还要挖洞啊。要突出展示出我们需要的部分。

二,掏出需要的部分

        将面中间掏空需要使用的是实体的holes,需要将坐标传入进来就可以实现将面的内部掏空。但是由于我们没有直接可以使用的面数据,需要在iserver中请求已经发布好的数据服务,再到前端调用绘制。我们这里提前发布了一个青岛的矢量面作为矢量面数据。

	var queryObj = {
					"getFeatureMode": "SQL",
					"datasetNames": ["demo:青岛市"],
					"maxFeatures": 1000,
					"queryParameter": {
						attributeFilter: "SMID >0"
					}
				};
				var queryObjJSON = JSON.stringify(queryObj);
				console.log(queryObjJSON);
				$.ajax({
					type: 'GET',
					url: "http://localhost:8090/iserver/services/data-demo/rest/data/featureResults/355a3692952d45809f95e46252a89322_241f63d221864e1caca0b775fbce56fc.rjson",
					data: queryObjJSON,
					success: function(data) {
						var resultObj = JSON.parse(data);
						console.log(resultObj);
						for (var i = 0; i < resultObj.featureUriList.length; i++) {
							$.ajax({
								type: 'GET',
								url: resultObj.featureUriList[i] + ".rjson?hasGeometry=true",
								data: queryObjJSON,
								success: function(data) {
									var resultObj = JSON.parse(data);
									//console.log("resultObj", resultObj)
									addClapFeature(resultObj);
								}
							});
						}

					}
				});

最后使用holes去挖空之前的实体面

var hole = Cesium.Cartesian3.fromDegreesArray(lonLatArr); 

viewer.entities.add({
						polygon: {
							// 获取指定属性(positions,holes(图形内需要挖空的区域))
							hierarchy: {
								//左下左上右上右下
								// 0,60,0,-60,180,-60,180,60,0,-60
								positions: [],
								holes: [{
//传入的值
									positions: hole
								}]
							},
						}
					});

   三,效果演示

      

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值