|
| 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 | + |
| 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 | + |
| 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 | + |
| 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 | + |
| 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