The end goal of creating tiles is to display them in an interactive web map, where users can zoom in to see the highest resolution data, and zoom out to see an overview of the data. We are using a javascript library called cesium to create the map that renders the web-tiles and 3D tiles. We include a custom cesium map as an optional page in our data portals. Data portals are a feature of the software we build and maintain, called MetacatUI.
- MetacatUI is web software we build that includes features like a searchable data catalog, data submission form, and data portals
- The KNB, ADC, DataONE site, all use the MetacatUI software. "Test" versions of these MetacatUI deployments also exist: dev.nceas, demo ADC, test ADC, test DataONE, among others.
- We are continually adding features and fixing bugs, see the list of issues
- Data portals are one of the features of MetacatUI.
- A portal is essentially a small website that users can build for their project. It includes a custom collection of data and ways to display information about that data as well as their project.
- Learn more about portals on the DataONE site and on the ADC site
- Here are some example portals:
- The tiled data that is created in the pipeline can be displayed in an optional "map" page in portals. So far, the map feature is only being used for a few projects, such as the PDG and the Defense Resiliency Platform Against Extreme Cold Weather.
- Portals can be created & edited in the portal builder in MetacatUI.
- Under the hood, the portal builder is just editing a portal document, which is some XML that configures each portal.
- The XML that creates a portal is defined by the portal & collections schema. (Not all version 1.1.0 schema features are supported in MetacatUI yet. Here is what we have left to do.)
- Changes to portals can also be made by downloading the portal XML, editing it, then uploading the new version via the DataONE API.
- Here are instructions on how to do that in R. (Also feel free to ask Robyn for further help/explanation!)
- The
formatId
for portal xml documents ishttps://purl.dataone.org/portals-1.1.0
defined in DataONEorg/object-format - You can also search for a portal using the portal label (the part in the URL that is after
/portals/
), for example:
- The
- Here are instructions on how to do that in R. (Also feel free to ask Robyn for further help/explanation!)
df <- query(ucsb, list(q ="label:permafrost AND (*:* NOT obsoletedBy:*)",
fl = "identifier,formatId,seriesId"),
as = "data.frame")
(The above query
function is doing a solr query, you can read more about that here)
When we have tiles/layers to test or publish, we add them to either the demo or production version of the Permafrost Discovery Gateway portal.
-
production version of the PDG portal: permafrost.arcticdata.io
- This is the public version of the portal, where we publish tiles/layers that are ready to share with the world
- solr query for the current public version of the PDG portal doc: https://arcticdata.io/metacat/d1/mn/v2/query/solr/?q=label:permafrost%20AND%20(*:*%20AND%20NOT%20obsoletedBy:*)&fl=label,dateUploaded,id,seriesId,formatId
- The XML document that configures this portal: https://arcticdata.io/metacat/d1/mn/v2/object/urn%3Auuid%3A0973cea6-fedc-4a0b-a8a1-4eed8c9f4d3b
-
demo version of the PDG portal: demo.arcticdata.io/portals/permafrost
- This is where we test tiles that we are working on
- solr query for the current demo version of the PDG portal doc
- XML document that configures this portal
Using the PDG XML document as an example, notice that the map page is configured with a <section>
element. We've named the section Imagery Viewer
(this could be anything), we've told MetacatUI that the section should be a visualization type page, specifically a cesium map. The cesium map is then configured with JSON, which is wrapped in CDATA tags, and stored as the optionValue
for the mapConfig
.
...
<section>
<label>Imagery Viewer</label>
<title>Imagery Viewer</title>
<option>
<optionName>sectionType</optionName>
<optionValue>visualization</optionValue>
</option>
<option>
<optionName>visualizationType</optionName>
<optionValue>cesium</optionValue>
</option>
<option>
<optionName>mapConfig</optionName>
<optionValue><![CDATA[ { ... JSON HERE ... } ]]></optionValue>
</option>
</section>
...
All options for the mapConfig
are outlined in the MetacatUI docs. Explanations on how the map & configuration works, and examples of more configurations are detailed in this Guide.
The map tiles (PNG web tiles or B3DM/JSON 3D tiles) need to be uploaded to a web-accessible location to display them in a portal (more about that in storing-the-data
). The url
option in each layer's config is where you point to this web accessible location.
The ConfigManager
class in the pdgstaging
library includes a get_metacatui_configs
method that will help you create config JSON to add to the layers list in the mapConfig. Note: this method is not well tested, and may need to be adapted to different circumstances.
- Cesium JS is the software that we use to make the map page in portals. We build our own UI (layers list, buttons, etc.) around the Cesium map. For more about Cesium, see the list of useful links in the MetacatUI map guide
- Cesium Ion is a paid service from the same people who build the open source Cesium JS library. It can convert some file types to Cesium 3D tiles, but not shapefiles! FME is the only software out there, other than our
py3dtiles
library, that converts shapefiles to 3D tiles (and it's quite expensive!)
Other than updating a portal document and displaying data on the web, you can also test tiles you've created by either 1) running Cesium locally, or 2) testing with Cesium sandcastle.
- The
viz-3dtiles
repo has the files & instructions you need for an easy setup
-
On your local machine, clone the
viz-3dtiles
repo. -
Using Homebrew in the terminal, install
express.js
by running runningbrew install node
thennpm install express
-
In the terminal, navigate to the directory
viz-3dtiles/test/run-cesium
and runnode server.js
. This should return a print statement in your terminal likeNow running at http://localhost:3003
. Navigate to that URL in your browser. -
On the Cesium site, create an account to obtain a personal token.
-
Replace the entire contents of the
/viz-3dtiles/test/run-cesium/cesium.js
file with:
Cesium.Ion.defaultAccessToken = "YOUR TOKEN HERE"; // <- update this
const viewer = new Cesium.Viewer('cesiumContainer');
const imageryLayers = viewer.imageryLayers;
const myNewProvider = new Cesium.WebMapTileServiceImageryProvider({
"url": "https://demo.arcticdata.io/cesium-layers/raster-imagery/bartsch_infrastructure/WorldCRS84Quad/{TileMatrix}/{TileCol}/{TileRow}.png",
"tilingScheme": new Cesium.GeographicTilingScheme()
})
const myNewLayer = new Cesium.ImageryLayer(myNewProvider)
imageryLayers.add(myNewLayer)
and be sure to insert your token.
-
Refresh your browser to reflect these changes to
cesium.js
-
To show the layer you created, transfer all the new PNG web tiles from the server to your local directory
viz-3dtiles/test/run-cesium/web-tiles
. For example, in your local machine's terminal, runscp username@datateam:/home/username/viz-workflow/web_tiles ~/Documents/viz-3dtiles/test/run-cesium/web-tiles
-
Within
cesium.js
, change
"url": "https://demo.arcticdata.io/cesium-layers/raster-imagery/bartsch_infrastructure/WorldCRS84Quad/{TileMatrix}/{TileCol}/{TileRow}.png",
to the path to your local web tiles, such as:
"url": "web-tiles/iwp_coverage/WGS1984Quad/{TileMatrix}/{TileCol}/{TileRow}.png",
The above file path needs to be adjusted to reflect the web tiles you want to visualize.
-
Refresh your browser and admire the data!
-
To kill the local host, close the terminal window or use
ctrl
+c
If you are working with a small dataset or a subset of a large dataset for testing and you are having trouble finding the tiles you visualized because there just isn't very many of them, you can use the morecantile library and add a few more lines of code to cesium.js
to fix your problem:
- In Python, run the following code to generate the bounding box coordinates for one of the web tiles (it can be any one!):
import morecantile
tms = morecantile.tms.get("WGS1984Quad")
tms.bounds(morecantile.Tile(x = {value}, y = {value}, z = {value}))
- The output will look something like this:
BoundingBox(left=-177.47314453125, bottom=71.20788574218751, right=-177.4676513671875, top=71.21337890625001)
- Modify
cesium.js
by adding 2 lines of code that define the"rectangle"
and apply thezoomTo()
function:
Cesium.Ion.defaultAccessToken = "YOUR TOKEN HERE"; // <- update this
const viewer = new Cesium.Viewer('cesiumContainer');
const imageryLayers = viewer.imageryLayers;
const myNewProvider = new Cesium.WebMapTileServiceImageryProvider({
"url": "https://demo.arcticdata.io/cesium-layers/raster-imagery/bartsch_infrastructure/WorldCRS84Quad/{TileMatrix}/{TileCol}/{TileRow}.png",
"tilingScheme": new Cesium.GeographicTilingScheme(),
"rectangle": Cesium.Rectangle.fromDegrees(-177.47314453125, 71.20788574218751, -177.4676513671875, 71.21337890625001)
})
const myNewLayer = new Cesium.ImageryLayer(myNewProvider)
imageryLayers.add(myNewLayer)
viewer.zoomTo(myNewLayer);
Save the file and refresh the browser. The window should automatically zoom to the tile you specified! However, it is also only visualizing that one tile, so take note of where it zoomed to, then remove those "rectangle"
and apply the zoomTo()
lines from cesium.js
, then refresh and manually zoom to that point to see all the tiles. Done!
- Cesium sandcastle is a free online sandbox for testing things in Cesium.
- Here's an editable example that renders some 3D tiles we made