Display a map with elevation.

Giro3D version
THREE.js version
OpenLayers version
CRS
Memory usage (CPU)
Memory usage (GPU)
Frames
Clear color
Clear alpha
Status
Local clipping enabled
Capabilities
WebGL 2
Max texture units
Max texture size
Precision
Max fragment shader uniforms
Logarithmic depth buffer
Max shader attributes
Check shader errors
EXT_clip_control
EXT_color_buffer_float
EXT_color_buffer_half_float
EXT_conservative_depth
EXT_depth_clamp
EXT_float_blend
EXT_polygon_offset_clamp
EXT_texture_compression_bptc
EXT_texture_compression_rgtc
EXT_texture_filter_anisotropic
EXT_texture_mirror_clamp_to_edge
EXT_texture_norm16
NV_shader_noperspective_interpolation
OES_draw_buffers_indexed
OES_sample_variables
OES_shader_multisample_interpolation
OES_texture_float_linear
OVR_multiview2
WEBGL_clip_cull_distance
WEBGL_compressed_texture_astc
WEBGL_compressed_texture_etc
WEBGL_compressed_texture_etc1
WEBGL_compressed_texture_s3tc
WEBGL_compressed_texture_s3tc_srgb
WEBGL_debug_renderer_info
WEBGL_debug_shaders
WEBGL_lose_context
WEBGL_multi_draw
WEBGL_polygon_mode
WEBGL_stencil_texturing
MSAA
EDL
EDL Radius
EDL Strength
Inpainting
Inpainting steps
Inpainting depth contrib.
Point cloud occlusion
Type
FOV
Automatic plane computation
Far plane
Near plane
Max far plane
Min near plane
Width (pixels)
Height (pixels)
x
y
z
x
y
z
color
Enable cache
Default TTL (seconds)
Capacity (MB)
Capacity (entries)
Entries
Memory usage (approx)
Pending requests
Memory tracker
Identifier
Memory usage (CPU)
Memory usage (GPU)
Status
Render order
Enable
Plane normal X
Plane normal Y
Plane normal Z
Distance
Helper size
Negate plane
Visible
Freeze updates
Opacity
Show volumes
Volume color
Discard no-data values
Sidedness
Front
Depth test
Visible tiles
Reachable tiles
Loaded tiles
Cast shadow
Receive shadow
Tile width (pixels)
Tile height (pixels)
Show grid
Background
Background opacity
Show tiles outlines
Tile outline color
Show tile info
Show extent
Extent color
Subdivision threshold
Deformation
Wireframe
Tile subdivisions
Show collider meshes
CPU terrain
Stitching
Geometry pool
Enabled
Mode
Hillshade
Hillshade intensity
Z factor
Hillshade zenith
Hillshade azimuth
Elevation layers only
Enable
Color
Opacity
X step
Y step
X Offset
Y Offset
Thickness
Enable
Color
Thickness
Opacity
Primary interval (m)
Secondary interval (m)
Brightness
Contrast
Saturation
Layer count
Render state
Normal
Layers
Identifier
Memory usage (CPU)
Memory usage (GPU)
Name
Source CRS
Status
Resolution factor
Visible
Frozen
Interpretation
Loaded images
Minimum elevation
Maximum elevation
Show extent
Extent color
Enabled
Mode
Elevation
Lower bound
Upper bound
Type
Color space
Data type
Flip Y
Synchronous
CRS
Memory usage (CPU)
Memory usage (GPU)
Loaded/Requested
CRS
Main URL
Inner source
Identifier
Memory usage (CPU)
Memory usage (GPU)
Name
Source CRS
Status
Resolution factor
Visible
Frozen
Interpretation
Loaded images
Blending mode
Normal
Brightness
Contrast
Saturation
Opacity
Show extent
Extent color
Enabled
Mode
Elevation
Lower bound
Upper bound
Type
Color space
Data type
Flip Y
Synchronous
CRS
Memory usage (CPU)
Memory usage (GPU)
Loaded/Requested
CRS
Main URL
Inner source
Show helpers
Show hidden objects
Name filter
Hierarchy
Properties
isObject3D
uuid
name
type
matrixAutoUpdate
matrixWorldAutoUpdate
matrixWorldNeedsUpdate
visible
castShadow
receiveShadow
frustumCulled
renderOrder
x
y
z
x
y
z
0% © IGN
index.js
// # Giro3D - Getting started

// ### Welcome to Giro3D !

// In this tutorial, we will cover the base features of Giro3D : the creation of the
// [instance](../apidoc/classes/core.Instance.html), the creation of a
// [map](../apidoc/classes/entities.Map.html), and setting up the navigation controls.

// ##### Note
// This walkthrough is based on the [2.5D Map example](../examples/getting-started.html).
// Feel free to visit this example to see the final result of this tutorial.

import { Vector3 } from "three";
import { MapControls } from "three/examples/jsm/controls/MapControls.js";

import TileWMS from "ol/source/TileWMS.js";

import Instance from "@giro3d/giro3d/core/Instance.js";
import Extent from "@giro3d/giro3d/core/geographic/Extent.js";
import Map from "@giro3d/giro3d/entities/Map.js";
import ColorLayer from "@giro3d/giro3d/core/layer/ColorLayer.js";
import ElevationLayer from "@giro3d/giro3d/core/layer/ElevationLayer.js";
import BilFormat from "@giro3d/giro3d/formats/BilFormat.js";
import Inspector from "@giro3d/giro3d/gui/Inspector.js";
import TiledImageSource from "@giro3d/giro3d/sources/TiledImageSource.js";

// ### Initialization of the Giro3D instance

// Before creating our map, we must setup Giro3D in our page, by creating an instance.

// The instance is the entry point of a Giro3D context. It needs a DOM element to render its scene.

// #### Register the custom CRS

// Our map uses the [EPSG:3946](https://epsg.io/3946) French coordinate reference system (CRS) that
// is not built-in into Giro3D's CRS registry.

// ####
// Let's register a definition for this CRS. The definition is taken from https://epsg.io/3946.proj4.
Instance.registerCRS(
  "EPSG:3946",
  "+proj=lcc +lat_1=45.25 +lat_2=46.75 +lat_0=46 +lon_0=3 +x_0=1700000 +y_0=5200000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs",
);

// Now we are ready to create our instance. Note that the `crs` parameter is necessary to determine
// the interpretation of coordinates from the 3D scene.
// We will use the `view` element from our HTML page to initialize the instance.
const instance = new Instance({
  target: "view",
  crs: "EPSG:3946",
});

// ### Create the Map

// Let's create a map of the city of [Lyon](https://en.wikipedia.org/wiki/Lyon), with satellite
// imagery and a digital elevation model (DEM).

// #### Specify the map extent

// A map is a rectangular region of the world that will contain geographic data.

// Let's define a geographic extent (or bounding box) of our map.
// We initialize the [`Extent`](../apidoc/classes/core.geographic.Extent.html) class,
// specifying the CRS name (that we just defined above), with the minimum and maximum X (longitude,
// or easting) and Y (latitude, or northing) values.
const xmin = 1837816.94334;
const xmax = 1847692.32501;
const ymin = 5170036.4587;
const ymax = 5178412.82698;

const extent = new Extent("EPSG:3946", xmin, xmax, ymin, ymax);

// #### Create the Map object

// Now we can create the Map. The only mandatory parameter is the extent
// but you can experiment with the other options if you'd like.
const map = new Map({ extent });

// Let's add the map to the instance.
instance.add(map);

// #### Create the color layer

// If we looked at the page now, the map would be rendered as a colored rectangle.
// This is the aspect of the map without any data in it (only the background color).
// Nothing very exciting.

// Let's add a color layer.

// In Giro3D, layers are the basic components of the Map. They can be either a color layer,
// or an elevation layer. In both cases, the data comes from a source.

// ##### Specify the data source

// Let's create a source that will pull data from a WMS service.
// We are using the
// [`TiledImageSource`](../apidoc/classes/sources.TiledImageSource.html) for that.
// This source will wrap an OpenLayers source, in this case a `TileWMS`.
const satelliteSource = new TiledImageSource({
  source: new TileWMS({
    url: "https://data.geopf.fr/wms-r",
    projection: "EPSG:3946",
    params: {
      LAYERS: ["ORTHOIMAGERY.ORTHOPHOTOS"],
      FORMAT: "image/jpeg",
    },
  }),
});

// ##### Create the layer

// Now we can create the layer. Note that we specify an extent for the layer. This is not
// strictly required, but since our map is much smaller than the WMS source, we want to avoid
// processing data that is outside our layer.
const colorLayer = new ColorLayer({
  name: "satellite",
  source: satelliteSource,
  extent: map.extent,
});

// And add it to the map.
map.addLayer(colorLayer);

// Note: `addLayer()` is an asynchronous method, because the layer must be prepared before being
// ready for rendering. We could use the returned promise to wait for the end of the preprocessing
// step, but we don't need that in our example.

// #### Creation of the elevation layer

// Creating an elevation layer is a very similar process to the color layer : we initialize the
// source, then create the layer and add it to the map.

// The only difference is that we are going to use an
// [`ElevationLayer`](../apidoc/classes/core.layer.ElevationLayer.html).

// Contrary to the color layer, the elevation layer does not produce any color information on the
// map, but it rather deforms the map to display the terrain (hence the name 2.5D map).

// Let's create a WMS source for this layer.
const demSource = new TiledImageSource({
  source: new TileWMS({
    url: "https://data.geopf.fr/wms-r",
    projection: "EPSG:3946",
    crossOrigin: "anonymous",
    params: {
      LAYERS: ["ELEVATION.ELEVATIONGRIDCOVERAGE.HIGHRES"],
      FORMAT: "image/x-bil;bits=32",
    },
  }),
  format: new BilFormat(),
  noDataValue: -1000,
});

// Then create the elevation layer.
const elevationLayer = new ElevationLayer({
  name: "dem",
  extent: map.extent,
  source: demSource,
});

// ##### Add the layer

// Now we are ready to add our layer to the map.
map.addLayer(elevationLayer);

// ### Set the camera and navigation controls

// Giro3D uses the THREE.js controls to navigate in the scene. In our example, we are going to use
// the `MapControls`, which are perfectly adapted to our need.

// Let's get the THREE camera of our scene.
const camera = instance.view.camera;

// Let's specify the camera position. We will position it in the southwest corner of the map, at an
// altitude of 2000 meters.
const cameraAltitude = 2000;

const cameraPosition = new Vector3(extent.west, extent.south, cameraAltitude);

camera.position.copy(cameraPosition);

// Now we can create the `MapControls` with our camera and the DOM element of our scene.
const controls = new MapControls(camera, instance.domElement);

// Let's set the controls' target to our map center.
controls.target = extent.centerAsVector3();

// And specify some parameters for the navigation.
controls.enableDamping = true;
controls.dampingFactor = 0.2;
controls.maxPolarAngle = Math.PI / 2.3;

controls.saveState();

// Now let's register those controls with the instance. The instance will automatically register
// the event handlers relevant to the navigation in the scene.
instance.view.setControls(controls);

// ### Optional: Set up the inspector

// This is an optional step, but very useful for diagnostic and debugging issues with Giro3D.
// The `Inspector` is a panel containing lots of useful information about the Giro3D instance.

// This supposes that we have a `div` ready to host our inspector.

Inspector.attach("inspector", instance);

// ### The StatusBar

// This widget is no part of the Giro3D library, but is used in the examples
// to display various informations about the scene, such as the geographic
// coordinates of the mouse cursor.

// Let's initialize the coordinate bar widget on our instance.

// ### Moving around

// Use the mouse the navigate in the scene and observe the map updating with fresh data.

// [See the final result](../examples/getting-started.html).
index.html
<!doctype html>
<html lang="en">
  <head>
    <title>2.5D Map</title>
    <meta charset="UTF-8" />
    <meta name="name" content="getting-started" />
    <meta name="description" content="Display a map with elevation." />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />

    <link rel="icon" href="https://giro3d.org/images/favicon.svg" />
    <link
      href="https://giro3d.org/assets/bootstrap-custom.css"
      rel="stylesheet"
    />
    <script src="https://giro3d.org/assets/bootstrap.bundle.min.js"></script>
    <link
      rel="stylesheet"
      type="text/css"
      href="https://giro3d.org/next/examples/css/example.css"
    />
  </head>

  <body>
    <div id="view" class="m-0 p-0 w-100 h-100"></div>
    <div
      id="inspector"
      class="position-absolute top-0 start-0 mh-100 overflow-auto"
    ></div>

    <script type="module" src="index.js"></script>
    <script>
      /* activate popovers */
      const popoverTriggerList = [].slice.call(
        document.querySelectorAll('[data-bs-toggle="popover"]'),
      );
      popoverTriggerList.map(
        // bootstrap is used as script in the template, disable warning about undef
        // eslint-disable-next-line no-undef
        (popoverTriggerEl) =>
          new bootstrap.Popover(popoverTriggerEl, {
            trigger: "hover",
            placement: "left",
            content: document.getElementById(
              popoverTriggerEl.getAttribute("data-bs-content"),
            ).innerHTML,
            html: true,
          }),
      );
    </script>
  </body>
</html>
package.json
{
    "name": "getting-started",
    "dependencies": {
        "@giro3d/giro3d": "git+https://gitlab.com/giro3d/giro3d.git"
    },
    "devDependencies": {
        "vite": "^3.2.3"
    },
    "scripts": {
        "start": "vite",
        "build": "vite build"
    }
}