Skip to content

Commit 5916ac9

Browse files
mgermeriegchoqueux
authored andcommitted
tutorial: add tutorials on how to use iTowns
1 parent ce8029c commit 5916ac9

28 files changed

+795
-123
lines changed

docs/tutorials/Fundamentals.md

+118
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
ITowns is a javascript framework for 3D geographic data visualisation.
2+
It can display a wide range of data such as ortho-images, Digital Elevation Models (DEM) or 3D models.
3+
4+
ITowns is based on [Three.js](https://threejs.org/), which is a javascript library that implements WebGL to render sophisticated 3D Geometry on a webpage.
5+
6+
In this tutorial, we shall be introduced to the fundamentals of iTowns : how it displays geographic data.
7+
8+
***
9+
10+
## Data visualization with iTowns
11+
12+
The support to display anything within iTowns is called a `View`.
13+
14+
To provide geographic data visualization, a `View` contains a combination of `Layers` which, in a digital map environment, are visual representations of any geographic data.
15+
In other words, all data that are displayed using iTowns are supported by some `Layer`.
16+
17+
Each `View` in iTowns displays 3D data in a unique Coordinates Reference System (CRS).
18+
Yet, the data displayed within a `View` do not necessarily have to be in the `View`'s CRS.
19+
ITowns comes with two pre-made `View` types : `GlobeView` and `PlanarView`.
20+
Each of these allows visualizing data from different types (raster or vector) and from different CRS.
21+
On this matter, iTowns distinguishes two cases :
22+
23+
- The first one regards data that are to be displayed as raster.
24+
These data can either be original raster data or vector data whose representation is projected on the ground.
25+
Data from this type are displayed in a `GlobeView` if their source CRS is [WGS 84](https://epsg.io/4326) or [Pseudo-Mercator](https://epsg.io/3857).
26+
However, if their source CRS defines a local projection (such as [RGF93 / Lambert 93](https://epsg.io/2154) for instance), they are displayed in a `PlanarView`.
27+
- On another hand, vector data that are to be displayed as 3D objects can be displayed in any type of `View`, regardless of their source CRS.
28+
29+
It is important to aknowledge the following facts regarding original raster data and `Views` :
30+
- a `GlobeView` allows displaying multiple raster data from two different source CRS : [WGS 84](https://epsg.io/4326) and [Pseudo-Mercator](https://epsg.io/3857),
31+
- a `PlanarView` allows displaying multiple raster data, but all those data sources must have the same CRS.
32+
33+
Tutorials of how to create and use the two `View` types can be found [here]{@tutorial Raster-data-WGS84} for the `GlobeView` and [here]{@tutorial Raster-data-Lambert93} for the `PlanarView`.
34+
35+
***
36+
37+
## The data supported by iTowns
38+
39+
40+
ITowns comes with a wide range of compatible data sources.
41+
It can be used to display data from web servers that use protocols such as Web Map (Tile) Service ([WMS](https://www.ogc.org/standards/wms) and [WMTS](https://www.ogc.org/standards/wmts)), Web Feature Service ([WFS](https://www.ogc.org/standards/wfs)) and Tile Map Service ([TMS](https://wiki.osgeo.org/wiki/Tile_Map_Service_Specification)).
42+
Data from user given files can also be displayed.
43+
44+
Regarding data formats, iTowns offers several possibilities : [vector tile](https://docs.mapbox.com/help/glossary/vector-tiles/) resources from [MapBox](https://www.mapbox.com/), [Potree](https://github.com/potree/potree) 3D point clouds, oriented images, [GeoJSON](https://geojson.org/), [KML](https://www.ogc.org/standards/kml) or [GPX](https://www.topografix.com/gpx.asp).
45+
46+
***
47+
48+
## The support for visualized data
49+
50+
It was earlier mentioned that data are displayed as `Layers` within iTowns.
51+
Several specific types of `Layers` exist, the use of which depends on the data to display :
52+
53+
- `ColorLayer` can be used to display raster graphics or vector data projected on the ground (left picture in the table bellow),
54+
- `ElevationLayer` can be used to display 3D elevation models (center picture in the table bellow),
55+
- `GeometryLayer` can be used to display 3D objects, such as geometric shapes or buildings modelling (right picture in the table bellow).
56+
- `FeatureGeometryLayer` is a pre-configured `GeometryLayer` which simplifies its implementation in given cases.
57+
- `PointCloudLayer` can be used to display 3D point clouds.
58+
- `OrientedImageLayer` can be used to display some oriented images.
59+
60+
61+
| ![color layer](images/Fundamentals-1.png) | ![elevation layer](images/Fundamentals-2.png) | ![geometry layer](images/Fundamentals-3.png) |
62+
| :---: | :---: | :---: |
63+
| A simple `ColorLayer` is displayed | An `ElevationLayer` is added to represent terrain elevation | A `GeometryLayer` is added to model the buildings |
64+
65+
***
66+
67+
## Vector data appearance
68+
69+
ITowns can display vector data in two ways : the data can be displayed in a `View` as 3D objects, or as entities that are projected on the ground.
70+
You can see bellow pictures illustrating the two cases.
71+
72+
| ![flattened vector data](images/Fundamentals-4.png) | ![3d vector data](images/Fundamentals-5.png) |
73+
| :---: | :---: |
74+
| Vector data projected on the ground | Vector data display as 3D objects |
75+
76+
In both ways, the appearance and positioning of the vector data can be adjusted by modifying the `Style` parameter of the `Layer` the data are displayed in.
77+
The `Style` in iTowns comes with several properties :
78+
- `fill` allows defining style rules for polygons interior,
79+
- `stroke` allows defining style rules for lines and polygons edges,
80+
- `point` allows defining style rules for points.
81+
82+
Each of these three properties comes with a bunch of parameters to set vector data appearance and positioning, such as `color`, `opacity`, `width`, `base_altitude`...
83+
You can find a list of all the possible parameters in `Style` [documentation]{@link Style}.
84+
85+
These parameters can be set as static values or as functions of the vector data properties.
86+
For example, let's suppose some vector data contains polygons.
87+
Setting `fill.color` to `red` will color all the polygons in red.
88+
If on another hand, all polygons come with a `color` property within the vector data, you can access it within `Style` in two ways :
89+
- either by using brackets, which in our example results in setting `fill.color` to `'{color}'` ;
90+
- or by passing a method to the `fill.color` value.
91+
The first parameter of this method will automatically be an object containing all the properties of the vector data.
92+
In our example, the method could simply return the `color` property.
93+
94+
ITowns offers the possibility to display labels attached to points.
95+
The content and appearance of the labels can be set the same way as for the polygons, lines and points : using a `Style` property which is called `text`.
96+
For instance, setting `text.field` to `'{name}'` will display a label on each point that has a `name` property within the vector data.
97+
The content of the label will be the content stored in the data under the `name` property.
98+
99+
### Vector data projected on the ground
100+
101+
When vector data are flattened on the ground, they are displayed in a `ColorLayer`.
102+
In that case, the data basically consist in polygons, lines or points.
103+
Their appearance can be adjusted by modifying the `Style` of the `ColorLayer`.
104+
Yet, their positioning can't be modified since it is computed so that tey appear projected on the ground.
105+
106+
Tutorial on how to modify the appearance of some vector data displayed on the ground can be found [here]{@tutorial Vector-data-on-ground}.
107+
108+
### Vector data displayed as 3D objects
109+
110+
In the case of vector data represented as 3D objects, the data are displayed in a `GeometryLayer`.
111+
The appearance and positioning of the vector data can be adjusted by modifying the `Style` of the `GeometryLayer`.
112+
Two parameters allow modifying the data position :
113+
- `base_altitude` which defines the altitude at the base of the 3D objects ;
114+
- `extrusion_height` which defines the height of the 3D objects, giving them volume.
115+
116+
For example, given a set of polygons, setting `fill.base_altitude` to `500` and `fill.extrusion_height` to `20` will render extruded polygon expanding between 500 and 520 meters of altitude.
117+
118+
You can find tutorial on how to use the `base_altitude` and `extrusion_height` parameters [here]{@tutorial Vector-data-3d}.
+238
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
The goal of this tutorial is to give an example on how to use iTowns to visualize data that are in [RGF93 / Lambert-93](https://epsg.io/2154) Coordinate Reference System (CRS).
2+
These data are ortho-images provided by the [Geoportail](https://www.geoportail.gouv.fr) API.
3+
This tutorial also aims at teaching how to visualize some elevation data, by superposing ortho-images with a Digital Elevation Model (DEM).
4+
5+
## Preparing the webpage
6+
7+
The webpage we want to display data on should be structured as follows :
8+
```html
9+
<!DOCTYPE html>
10+
<html>
11+
<head>
12+
<meta charset="UTF-8">
13+
<title>Display a planar view with iTowns</title>
14+
<style>
15+
html { height: 100%; }
16+
body { margin: 0; overflow: hidden; height: 100%; }
17+
#viewerDiv { margin: auto; height: 100%; width: 100%; padding: 0; }
18+
canvas { display: block }
19+
</style>
20+
</head>
21+
<body>
22+
<div id="viewerDiv"></div>
23+
<script src="js/itowns.js"></script>
24+
<script type="text/javascript">
25+
// Our code goes here
26+
</script>
27+
</body>
28+
</html>
29+
```
30+
31+
What we are doing here is fairly simple :
32+
- we create a container `<div id="viewerDiv"></div>` that shall serve as a support for the data we wish to display ;
33+
- we define the layout of this container within our webpage ;
34+
- we import iTowns framework (which in our case is imported within a `js/` repository).
35+
36+
We shall then add javascript to use iTowns to display data within a `<script>` markup following iTowns import.
37+
38+
## Create a view
39+
40+
As mentioned in [fundamentals tutorial]{@tutorial Fundamentals}, we need a `{@link View}` to support any geographic data we wish to display.
41+
What we want here is to display data in a RGF93 / Lambert-93 projection, which is a conic local projection.
42+
Therefore, we should use a `{@link PlanarView}`, which is a specific type of `View` adapted to local projections.
43+
We can create it as such :
44+
45+
```js
46+
const viewerDiv = document.getElementById('viewerDiv');
47+
48+
itowns.proj4.defs(
49+
'EPSG:2154',
50+
'+proj=lcc +lat_1=49 +lat_2=44 +lat_0=46.5 +lon_0=3 +x_0=700000 +y_0=6600000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs'
51+
);
52+
const viewExtent = new itowns.Extent(
53+
'EPSG:2154',
54+
644500.0, 659499.99,
55+
6857500.0, 6867499.99,
56+
);
57+
58+
const view = new itowns.PlanarView(viewerDiv, viewExtent);
59+
```
60+
61+
Several things are done here :
62+
- First, we retrieve the `DomElement` relative to the container we created to serve as a support for iTowns.
63+
- Then we define the geographic extent of our view by instantiating iTowns `{@link Extent}` class.
64+
To do so, we need to pass five argument to `Extent` constructor, which are :
65+
- The Coordinates Reference System (CRS) of the extent, given as its EPSG code.
66+
Here, we use [RGF93 / Lambert-93](https://epsg.io/2154) CRS.
67+
Not all CRS are defined by default within iTowns, which is why we need to define our CRS using [proj4](https://proj.org/) prior to instantiating the `Extent` ;
68+
- The westernmost, easternmost, southernmost and northernmost coordinates of the extent.
69+
- Finally, we create a `PlanarView` giving it the required `DomElement` and `Extent` parameters.
70+
71+
At this stage, our webpage should look like this :
72+
73+
![Simple PlanarView](images/Raster-data-Lambert93-1.png)
74+
75+
The blue rectangle you can see is the view we just created.
76+
By default, iTowns position the camera on top of the view center.
77+
We can change the initial camera position by passing a `CameraTransformOption` object as an optional parameter of `PlanarView` constructor.
78+
79+
To do so, we first need to create our `CameraTransformOption` object :
80+
81+
```js
82+
const placement = {
83+
coord: viewExtent.center(),
84+
tilt: 12,
85+
heading: 40,
86+
range: 16000,
87+
}
88+
```
89+
90+
We are specifying here that the camera should target the center of the extent, with an azimuth of 40 degrees and a pitch of 12 degrees under the horizontal plane.
91+
The camera should also be at a distance of 16000 meters from its target (i.e. from the view extent center).
92+
93+
We can then just pass this object into `PlanarView` constructor parameters :
94+
95+
```js
96+
const view = new itowns.PlanarView(viewerDiv, viewExtent, {
97+
placement: placement,
98+
});
99+
```
100+
101+
Our webpage should now look like this :
102+
103+
![PlanarView with placement](images/Raster-data-Lambert93-2.png)
104+
105+
Now that we have a functional `View`, we shall use it to display geographic data.
106+
107+
## Add a color layer
108+
109+
The first data we want to display on our planar surface is ortho-images.
110+
To do so, we must define the source at which ortho-images data can be fetched thanks to the `Source` class.
111+
We can start displaying ortho-images provided by the [Geoportail](https://www.geoportail.gouv.fr) as such :
112+
113+
```js
114+
const sourceOrtho = new itowns.WMSSource({
115+
url: "https://wxs.ign.fr/3ht7xcw6f7nciopo16etuqp2/geoportail/r/wms",
116+
name: "HR.ORTHOIMAGERY.ORTHOPHOTOS",
117+
format: 'image/png',
118+
crs: 'EPSG:2154',
119+
extent: viewExtent,
120+
});
121+
const layerOrtho = new itowns.ColorLayer('Ortho', { source: sourceOrtho });
122+
view.addLayer(layerOrtho);
123+
```
124+
125+
In this code, we first define the source specifications of the data we wish to fetch.
126+
`{@link WMSSource}` needs several mandatory parameters :
127+
- the server `url`, the `name` of the data and their `format`, which are used to generate the final `url` at which data shall be fetched ;
128+
- the CRS of the fetched data ;
129+
- the geographic extent of the resources (set here as the extent of the view).
130+
131+
Then we create a `{@link ColorLayer}` from two parameters : a unique `id` for the layer (`Ortho`) as well as the `Source` instance for the layer data.
132+
133+
Finally, we add the created layer to the view with `view.addLayer(layerOrtho);`.
134+
135+
The result we get at this stage is the following, where we can see the newly added ortho-imagery layer :
136+
137+
![Ortho layer](images/Raster-data-Lambert93-3.png)
138+
139+
## Add an elevation layer
140+
141+
The process of adding an `{@link ElevationLayer}` is similar to what we just did with the `ColorLayer`.
142+
At first, we need to define the source of the elevation raster data.
143+
Then we can simply create the `ElevationLayer`, giving it a unique `id` and the source configuration, and finally adding it to the view.
144+
145+
```js
146+
const sourceDEM = new itowns.WMSSource({
147+
url: "https://wxs.ign.fr/3ht7xcw6f7nciopo16etuqp2/geoportail/r/wms",
148+
name: "ELEVATION.ELEVATIONGRIDCOVERAGE.HIGHRES",
149+
format: "image/x-bil;bits=32",
150+
crs: 'EPSG:2154',
151+
extent: viewExtent,
152+
});
153+
const layerDEM = new itowns.ElevationLayer('DEM', { source: sourceDEM });
154+
view.addLayer(layerDEM);
155+
```
156+
157+
The result is shown bellow.
158+
The camera has been zoomed in to get a more precise rendering of the elevation variations, which are not very important on the extent we chose to display.
159+
160+
![dem layer](images/Raster-data-Lambert93-4.png)
161+
162+
## Result
163+
164+
With this tutorial, we learnt how to use iTowns `ColorLayer` and an `ElevationLayer` to display data in a local conic projection.
165+
The code that is shown bellow sums up all the steps it took to do so.
166+
167+
```html
168+
<!DOCTYPE html>
169+
<html>
170+
<head>
171+
<meta charset="UTF-8">
172+
<title>Display a planar view with iTowns</title>
173+
<style>
174+
html { height: 100%; }
175+
body { margin: 0; overflow: hidden; height: 100%; }
176+
#viewerDiv { margin: auto; height: 100%; width: 100%; padding: 0; }
177+
canvas { display: block }
178+
</style>
179+
</head>
180+
<body>
181+
<div id="viewerDiv"></div>
182+
<script src="js/itowns.js"></script>
183+
<script type="text/javascript">
184+
185+
// Retrieve the view container
186+
const viewerDiv = document.getElementById('viewerDiv');
187+
188+
// Define the view geographic extent
189+
itowns.proj4.defs(
190+
'EPSG:2154',
191+
'+proj=lcc +lat_1=49 +lat_2=44 +lat_0=46.5 +lon_0=3 +x_0=700000 +y_0=6600000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs'
192+
);
193+
const viewExtent = new itowns.Extent(
194+
'EPSG:2154',
195+
644500.0, 659499.99,
196+
6857500.0, 6867499.99,
197+
);
198+
199+
// Define the camera initial placement
200+
const placement = {
201+
coord: viewExtent.center(),
202+
tilt: 12,
203+
heading: 40,
204+
range: 16000,
205+
};
206+
207+
// Create the planar view
208+
const view = new itowns.PlanarView(viewerDiv, viewExtent, {
209+
placement: placement,
210+
});
211+
212+
// Define the source of the ortho-images
213+
const sourceOrtho = new itowns.WMSSource({
214+
url: "https://wxs.ign.fr/3ht7xcw6f7nciopo16etuqp2/geoportail/r/wms",
215+
name: "HR.ORTHOIMAGERY.ORTHOPHOTOS",
216+
format: "image/png",
217+
crs: 'EPSG:2154',
218+
extent: viewExtent,
219+
});
220+
// Create the ortho-images ColorLayer and add it to the view
221+
const layerOrtho = new itowns.ColorLayer('Ortho', { source: sourceOrtho });
222+
view.addLayer(layerOrtho);
223+
224+
// Define the source of the dem data
225+
const sourceDEM = new itowns.WMSSource({
226+
url: "https://wxs.ign.fr/3ht7xcw6f7nciopo16etuqp2/geoportail/r/wms",
227+
name: "ELEVATION.ELEVATIONGRIDCOVERAGE.HIGHRES",
228+
format: "image/x-bil;bits=32",
229+
crs: 'EPSG:2154',
230+
extent: viewExtent,
231+
});
232+
// Create the dem ElevationLayer and add it to the view
233+
const layerDEM = new itowns.ElevationLayer('DEM', { source: sourceDEM });
234+
view.addLayer(layerDEM);
235+
</script>
236+
</body>
237+
</html>
238+
```

0 commit comments

Comments
 (0)