This article contains information about how to work with 3D vector tiles and Cesium.
Terrain modeling
3D terrain data can be represented in several ways. In the field of GIS, raster file images are usually used, and each cell value represents elevation (Digital Elevation Model).
For the purpose of visualisation of elevation model, another format can be used, so called Quantized 3D Mesh - the elevation is represented by either regular, but more commonly irregular triangle web.
Sources of 3D data
For the purpose of visualisation of terrain in the web browser, is Cesium one of the popular JavaScript libraries and data services to be used. You can setup your web application for 3D data visualisation in several ways:
-
Have your own terrain data and convert them to 3D quantized mesh format - then you need a server to a) process the data and b) to serve them
-
We at MapTiler do provide 3D tiles hosting service. If you login to your MaptTiler Cloud account, you can find 3D Terrain - Quantized Mesh tiles dataset there - and use it in your applications.
-
Use data provided by the Cesium service
Having 3D tiles data source is only one part of the problem. The 3D tiles will help you just to draw the elevation, but one also needs to “drape” another data source over the elevation, such as the streets map, outdoor map or the satellite map. That way, you can see nice 3D shaped landscape.
Configuring Cesium map application
When building a web applications, you have several options and you probably know already, which libraries and build-stack you are going to use. You can find a lot of useful examples at the Sandcastle of the Cesium project. We will demonstrate, how to create 3D web mapping application based on the cesium-webpack-example
Step 1: Install and run minimal Cesium application using webpack
Webpack is the static module builder for JavaScript applications. It helps you with the development of new application as well as with creation of the distribution package.
Download and unzip the cesium-webpack-example package (either using the direct download link or use Git commands)
git clone https://github.com/maptiler/cesium-webpack-example.git cd cesium-webpack-example
Then run the command, which should install all necessary dependencies
npm install
And after all necessary packages are successfully downloaded, you can start the development server, which will make it easy to develop custom 3D mapping application
npm start
And open the link http://localhost:8080/ in your browser
Basic example with Cesium data sources will popup. Now let’s start hacking around this example. The sources are located in the src/
folder, the file src/index.js
is of our main interest:
import { Cesium3DTileset, createWorldTerrain, IonResource, Viewer } from 'cesium'; import "cesium/Build/Cesium/Widgets/widgets.css"; import "./css/main.css"; var viewer = new Viewer('cesiumContainer', { terrainProvider: createWorldTerrain() }); var tileset = new Cesium3DTileset({ url: IonResource.fromAssetId(40866) }); viewer.scene.primitives.add(tileset); viewer.zoomTo(tileset);
We will restructure the code, so it uses sources directing to MapTiler cloud services. Let’s start from scratch, delete all the code, maybe except for the imports
import { Cesium3DTileset, createWorldTerrain, IonResource, Viewer } from 'cesium'; import "cesium/Build/Cesium/Widgets/widgets.css"; import "./css/main.css";
First we need to define the TerrainProvider instance
var terrain = new CesiumTerrainProvider({ url: `https://api.maptiler.com/tiles/terrain-quantized-mesh/?key=${MAPTILER_API_KEY}` });
As second step, we need to define the ImageProvider - and we will use the URL reference to one of the Maptiler services, in this case, it will be the Outdoor map:
var outdoor = new UrlTemplateImageryProvider({ url: `https://api.maptiler.com/maps/outdoor/{z}/{x}/{y}.png?key=${MAPTILER_API_KEY}`, minimumLevel: 0, maximumLevel: 20 });
We now have to important data sources: the terrain and the imagery overlay. This can be now pluged-in to the application. This can be done, using very complex Cesium.Viewer class or much simplier Cesium.Widget class.
var cesiumWidget = new CesiumWidget('cesiumContainer', { imageryProvider: outdoor, terrainProvider: terrain } );
Don’t forget to add used classes, which is CesiumTerrainProvider, UrlTemplateImageryProvider
and the CesiumWidget
to the import statement. The node server will reload automatically every time you change the code.
Now we just have to zoom to desired location (e.g. Alps region), this is done with the help of the Camera object
viewer.camera.flyTo({ destination: Cartesian3.fromDegrees(8.67, 46.72, 4300), orientation: { pitch: Math.toRadians(-20) } });
The full example now looks like this:
import { Cesium3DTileset, createWorldTerrain, IonResource, CesiumTerrainProvider, UrlTemplateImageryProvider, Viewer, CesiumWidget, Cartesian3, Math } from 'cesium'; import "cesium/Build/Cesium/Widgets/widgets.css"; import "./css/main.css"; var MAPTILER_API_KEY="XFXXXXXXXXXXXXXeeg"; var terrain = new CesiumTerrainProvider({ url: `https://api.maptiler.com/tiles/terrain-quantized-mesh/?key=${MAPTILER_API_KEY}` }); var outdoor = new UrlTemplateImageryProvider({ url: `https://api.maptiler.com/maps/outdoor/{z}/{x}/{y}.png?key=${MAPTILER_API_KEY}`, minimumLevel: 0, maximumLevel: 20 }); var widget = new CesiumWidget('cesiumContainer', { imageryProvider: outdoor, terrainProvider: terrain } ); widget.camera.flyTo({ destination: Cartesian3.fromDegrees(8.67, 46.72, 4300), orientation: { pitch: Math.toRadians(-20) } });
Comments
0 comments
Please sign in to leave a comment.