0%

geoserver 發佈 cesium terrain

terrain

今天心血來潮玩看看 geoserver 發 cesium terrain , 主要 參考這篇文章
以前雖然也搞過發 cesium terrain , 可以參考這篇 , 不過那個難度對一個新手來說真是噁爛 , 這個搞起來友善多啦

Cesium HelloWorld

HelloWorld 參考這裡
如果要用舊版的話 載點在此

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<!-- Include the CesiumJS JavaScript and CSS files -->
<script src="https://cesium.com/downloads/cesiumjs/releases/1.100/Build/Cesium/Cesium.js"></script>
<link href="https://cesium.com/downloads/cesiumjs/releases/1.100/Build/Cesium/Widgets/widgets.css" rel="stylesheet">
</head>
<body>
<div id="cesiumContainer"></div>
<script>
// Your access token can be found at: https://cesium.com/ion/tokens.
// Replace `your_access_token` with your Cesium ion access token.

Cesium.Ion.defaultAccessToken = 'your_access_token';

// Initialize the Cesium Viewer in the HTML element with the `cesiumContainer` ID.
const viewer = new Cesium.Viewer('cesiumContainer', {
terrainProvider: Cesium.createWorldTerrain()
});
// Add Cesium OSM Buildings, a global 3D buildings layer.
const buildingTileset = viewer.scene.primitives.add(Cesium.createOsmBuildings());
// Fly the camera to San Francisco at the given longitude, latitude, and height.
viewer.camera.flyTo({
destination : Cesium.Cartesian3.fromDegrees(-122.4175, 37.655, 400),
orientation : {
heading : Cesium.Math.toRadians(0.0),
pitch : Cesium.Math.toRadians(-15.0),
}
});
</script>
</div>
</body>
</html>

下載資料

想要底圖的話可以下載 naturalearth
或是 BlueMarble
等等給 imageryProvider 使用

這裡 可以下載台灣的 DTM
這裡有個關鍵要注意到 , 他的投影好像沒定義好 , 所以 geoserver 吃不到 , 所以設定下 twd97 給他

最後如果要全世界的話就要用 srtmdata 不過選起來很自虐就對啦

geoserver 安裝 DDS/BIL extension

注意一定要裝這個 extension , 沒裝的話也是可以看到 terrain 效果 , 不過會穿模
下載這個 DDS/BIL extension 檔名大概是這樣 geoserver-2.21-SNAPSHOT-dds-plugin.zip 看你用啥版本
老樣子把解開的 jar 丟到 geoserver-2.21.x-latest-bin\webapps\geoserver\WEB-INF\lib
都裝好以後發圖層的時候會多一個 BIL Format Settings , 然後選 16bit 即可 , 這個步驟至關重要 , 設定成 8bit 的話就陣亡

設定 CORS

通常會噴類似以下的訊息
Access to XMLHttpRequest at 'http://localhost:8080/geoserver/ows?SERVICE=WMS&REQUEST=GetCapabilities&tiled=true' from origin 'http://127.0.0.1:5500' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

首先找到這個檔案 webapps\geoserver\WEB-INF\web.xml
看是用 Jetty or Tomcat 把它標示的註解打開就好 Uncomment following filter to enable CORS in Jetty. Do not forget the second config block further down
接著要找到這串 Uncomment following filter to enable CORS 一樣把註解打開

解決 cesium 401 問題

這個不同版本好像不太一樣 , 有的會噴有的不會

1
{code: "InvalidCredentials", message: "Invalid access token"}

解法看是要乖乖放 token 上去

1
Cesium.Ion.defaultAccessToken='token';

或是設定這兩個參數 false 應該就可以過 , 反正 imageryProvider 要用自己的就對啦 , 參考自此

1
2
3
4
var viewer = new Cesium.Viewer('cesiumContainer', {
imageryProvider: false,
geocoder: false
})

新增樣式

看他的文章寫說這樣效果比較好就乖乖跟著弄吧 , 設定好以後記得回到圖層設定 style 指向這個 style

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?xml version='1.0' encoding='ISO-8859-1'?>
<StyledLayerDescriptor version='1.0.0' xsi:schemaLocation='http://www.opengis.net/sld StyledLayerDescriptor.xsd' xmlns='http://www.opengis.net/sld' xmlns:ogc='http://www.opengis.net/ogc' xmlns:xlink='http://www.w3.org/1999/xlink' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>
<!-- a Named Layer is the basic building block of an SLD document -->
<NamedLayer>
<Name>SRTM2Color</Name>
<UserStyle>
<FeatureTypeStyle>
<Rule>
<RasterSymbolizer>
<Opacity>1.0</Opacity>
<ChannelSelection>
<GrayChannel>
<SourceChannelName>1</SourceChannelName>
</GrayChannel>
</ChannelSelection>
<ColorMap extended='true' type='ramp'>
<ColorMapEntry color='#000000' quantity='-32768'/>
<ColorMapEntry color='#BA9800' quantity='15000'/>
</ColorMap>
</RasterSymbolizer>
</Rule>
</FeatureTypeStyle>
</UserStyle>
</NamedLayer>
</StyledLayerDescriptor>

最終結果

最後要說這個做法有啥優點的話 , 大概就是不用搞一堆 .terrain 檔案在機器上面吧

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<html lang="zh-Hant">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<title>Document</title>


<!-- <script src="Cesium/Cesium.js"></script> -->
<!-- <link href="Cesium/Widgets/widgets.css" rel="stylesheet"> -->

<script src="https://cesium.com/downloads/cesiumjs/releases/1.100/Build/Cesium/Cesium.js"></script>
<link href="https://cesium.com/downloads/cesiumjs/releases/1.100/Build/Cesium/Widgets/widgets.css"
rel="stylesheet">
<script src="./GeoserverTerrainProvider.js"
type="text/javascript"></script>
</head>
<body>
<div id="cesiumContainer"></div>
<script>
async function init() {
const container = document.getElementById('cesiumContainer');
const terrainProvider = await Cesium.GeoserverTerrainProvider({
"url": "http://localhost:8080/geoserver",
// "layerName": "elevation:SRTM90",
// "layerName": "cite:srtm_61_08"
"layerName": "cite:dem_20m"
});

const imageryProvider = new Cesium.WebMapServiceImageryProvider({
"url": "http://localhost:8080/geoserver/ows",
"parameters": {
"format": "image/png",
"transparent": true
},
"layers": "cite:NE2_LR_LC_SR_W_DR",
"maximumLevel": 15
});

const options = {
// imageryProvider: imageryProvider,
baseLayerPicker: false,
showRenderLoopErrors: true,
animation: true,
fullscreenButton: false,
geocoder: false,
homeButton: false,
infoBox: false,
sceneModePicker: true,
selectionIndicator: false,
timeline: false,
navigationHelpButton: false,
navigationInstructionsInitiallyVisible: false,
targetFrameRate: 30,
terrainExaggeration: 1.0,
};
// Cesium.Ion.defaultAccessToken='申请的token';
viewer = new Cesium.Viewer(container, options);
viewer.terrainProvider = terrainProvider;
}
init();

</script>
</body>


</html>
關閉