U L T R A G L O B E : http://www.jdultra.com/
Displays the earth with level of detail, imagery, elevation and connection to OGC web services.
The earth model is wgs 84.
Support for WMS and OGC 3DTiles.
Partial I3S support.
Here's a simple getting started project: ULTRAGLOBE getting started
unzip and run:
npm install
npm run dev
Google Map Tile API limited availability from google API. if the quotas are used up, try again tomorrow.
Shadow analysis limited availability from google API. if the quotas are used up, try again tomorrow.
I3S Points (new york trees) and blue marble
More controls for selecting and moving 3DTiles tilesets
In your HTML, have a div with a specific id.
<body>
<div id="screen" oncontextmenu="return false;" style="position: absolute; height:100%; width:100%; left: 0px; top:0px;"></div>
</body>
in your main javascript file, insert the following:
import { Map } from '@jdultra/ultra-globe/dist/ultraglobe.min.js';
let map = new Map({ divID: 'screen' });
At this point, you'll only see a black planet with atmosphere as no data has yet been loaded.
You can enable shadows and set a time:
let map = new Map({ divID: 'screen', shadows:true });
map.setDate(new Date(2023,5, 21, 8, 0,0,0));
The time will be relative to the local time-zone. OGC3DTiles tilesets, including google map tiles, will automatically cast shadows.
Loading data is done through a layering system. Each data type has it's own layer type
Use the WMSLayer to add imagery from a WMS layer.
import { Map, WMSLayer } from '@jdultra/ultra-globe/dist/ultraglobe.min.js';
let map = new Map({ divID: 'screen' });
var wmsLayer = new C({
id: 0,
name: "WMS",
bounds: [-180, -90, 180, 90],
url: "https://www.gebco.net/data_and_products/gebco_web_services/web_map_service/mapserv",
layer: "gebco_latest_2",
epsg: "EPSG:4326",
version: "1.1.1",
visible:true
})
//add a layer at index 0
map.setLayer(wmsLayer, 0);
You can also load imagery from a single image:
import { Map, SingleImageImageryLayer } from '@jdultra/ultra-globe/dist/ultraglobe.min.js';
import bluemarble from './images/bluemarble.jpg'
let map = new Map({ divID: 'screen' });
var imagery = new SingleImageImageryLayer({
id: 0,
name: "imagery",
bounds: [-180, -90, 180, 90],
url: bluemarble,
visible: true
})
//add a layer at index 0
map.setLayer(imagery, 0);
the imagery is expected in "equidistant cylindrical" projection (EPSG:4326).
You can also add elevation from a single image
import { Map, SingleImageElevationLayer } from '@jdultra/ultra-globe/dist/ultraglobe.min.js';
import earthElevationImage from './images/earthElevationImage.jpg'
let map = new Map({ divID: 'screen' });
var earthElevation = new SingleImageElevationLayer({
id: 0,
name: "singleImageEarthElevation",
bounds: [-180, -90, 180, 90],
url: earthElevationImage,
visible: true,
min: 0,
max: 8000
});
//add a layer at index 0
map.setLayer(earthElevation, 0);
Loading data for the entire earth from a single image is definitely not ideal as you'll be limitted in terms of quality.
chack out the classes "SimpleElevationLayer" and "UltraImageryLayer" to get an idea of how to implement your own layers to connect to your imagery/elevation service or generate on the fly data.
An OGC3DTilesLayer allows placing a tileset anywhere on earth
import { Map, OGC3DTilesLayer } from '@jdultra/ultra-globe/dist/ultraglobe.min.js';
let map = new Map({ divID: 'screen' });
var ogc3dTiles = new OGC3DTilesLayer({
id: 0,
name: "OGC 3DTiles",
visible: true,
url: "https://storage.googleapis.com/ogc-3d-tiles/ayutthaya/tileset.json",
zUp: false,
longitude: 100.5877,
latitude: 14.3692,
height: 16,
rotationY: 0.5,
scale: 1,
geometricErrorMultiplier: 1.5,
loadOutsideView:true
});
map.setLayer(ogc3dTiles, 0);
In the case of a tileset that is already georeferenced (region bounding volume) you should omit the properties related to tileset positioning and scaling :
var ogc3dTiles = new OGC3DTilesLayer({
id: 6,
name: "OGC 3DTiles",
visible: true,
url: "path/to/georeferenced/tileset.json",
geometricErrorMultiplier: 1.5,
loadOutsideView:true
});
map.setLayer(ogc3dTiles, 2);
The 3DTiles support is done through this library: https://github.com/ebeaufay/3DTilesViewer
Although google maps 3D Tiles can be loaded via the OGC3DTilesLayer, a specific GoogleMap3DTileLayer manages the default settings to get the data in the right location
import { Map, GoogleMap3DTileLayer } from '@jdultra/ultra-globe/dist/ultraglobe.min.js';
let map = new Map({ divID: 'screen' });
var googleMaps3DTiles = new GoogleMap3DTileLayer({
id: 0,
name: "Google Maps 3D Tiles",
visible: true,
apiKey: "your google maps api key",
loadOutsideView: true,
displayCopyright: true,
});
map.setLayer(googleMaps3DTiles, 0);
In the same spirit, an I3SLayer is also provided although only points are supported currently
Layers can also be removed:
map.removeLayer(imageryLayer);
The controls are on by default and handle moving around with the mouse or touch:
Pan: left mouse button / single touch
rotate: right mouse button | ctrl+left mouse button / 2 touch move right or left
zoom: mouse wheel / 2 touch move apart or closer together
The Map.controller property gives you access to the root controller object to add or replace controllers. Controllers are chained together via the append method:
import { Map, PanController, RotateController, ZoomController } from '@jdultra/ultra-globe/dist/ultraglobe.min.js';
let map = new Map({ divID: 'screen' });
map.controller.clear(); // clear existing controller chain
map.controller.append(new PanController(map.camera, map.domContainer, map));
map.controller.append(new RotateController(map.camera, map.domContainer, map));
map.controller.append(new ZoomController(map.camera, map.domContainer, map));
A utility method in the Map object allows specifying a camera location and target in geodetic coordinates (lon, lat, height).
import { Map } from '@jdultra/ultra-globe/dist/ultraglobe.min.js';
map.moveAndLookAt({x:13.42, y:52.5, z:300},{x:13.42, y:52.4895, z:170})
A utility to transform between geodetic coordinates and cartesian coordinates is made available through the map.planet.llhToCartesin object. You can use it to convert easily and accurately between geodetic WGS84 coordinates to cartesian coordinates.
const geodeticCameraPosition = map.planet.llhToCartesian.inverse(map.camera.position);
const cartesianCameraPosition = map.planet.llhToCartesian.forward(geodeticCameraPosition);
the maps LayerManager allows accessing layers
let map = new Map({ divID: 'screen' });
// retrieve a layer by id
let imageryLayer = map.layerManager.getLayerByID(0);
imageryLayer.setVisible(false);
// retrieve all layers
let layers = map.getLayers();
for (let layer of layers) {
console.log(layer.getID()+" "+layer.getName());
}
convert a location on screen to cartesians coordinates through raycasting on the depth buffer.
self.domContainer.addEventListener('mouseup', (e) => {
let sideEffect = new THREE.Vector3();
map.screenPixelRayCast(e.x, e.y, sideEffect)
console.log(sideEffect);
}, false);
Rather than a full fledged geospatial framework. This library is intended as a lightweight library on top of threeJS. Nevertheless, the render pipeline is mildly complex hence the need to manage it in the Map object itself. You can access threejs context objects from the map:
Map#renderer
Map#labelRenderer
Map#camera
Map#scene