The Geocap Javascript API allows web developers to create client-side software that connects to the Subsurface Portal for ArcGIS. This will typically be web pages that performs 2D and 3D rendering of seismic data. With the Geocap Javascript API anyone can create web pages that perform sophisticated seismic visualization using only a few lines of code.
Features of the Javascript API :
On order to use the Geocap Javascript API you will need a running Subsurface Portal for ArcGIS. Your web browser must also be capable of WebGL rendering with hardware supported graphics acceleration.
Some specifics:
In order to run the examples in this section you must have a Subsurface Portal for ArcGIS running with at least one 3D or 2D survey installed. Also you should have access to the Geocap Javascript API either as a separate download or a URL.
The following example shows the Javascript required to fetch a seismic 3D volume from a server and display in a 3D view. See Example 1 : Simple Cube for the complete example.
<body> <canvas id="sceneArea"></canvas> <script> require(["geocap/Scene", "geocap/FeatureLayerDataSource", "geocap/Seismic3DDataSource", "geocap/Seismic3DSectionControllers", "geocap/View3DThree", "dojo/parser", "dojo/domReady!"], function (Scene, FeatureLayerDataSource, Seismic3DDataSource, Seismic3DSectionControllers, View3DThree, parser) { // URL to map service var mapserver_url = "http://localhost:6080/arcgis/rest/services/Peon/MapServer"; // Survey outline feature. This just shows the survey outline, not the data var peon_outline = new FeatureLayerDataSource({ url: mapserver_url, layerid: 0 }); // Get all features in feature layer queryparams = { f: "json", returnZ: true, where: "objectid > 0", returnGeometry: true, } peon_outline.setQueryParameters(queryparams); // Seismic 3D data (amplitudes). The survey of interest corresponds to feature with OID = 1 var seismics3d = Seismic3DDataSource({ url: mapserver_url, layerid: 0, surveyid: 1 }); // Create scene to hold data var scene = new Scene(); // Add data to scene scene.addFeatureLayer(peon_outline); scene.addSeismic3D(seismics3d); // Create 3D view for scene and insert it in given DOM element var c = document.getElementById("sceneArea"); var view = new View3DThree({ scene: scene, canvas: c }); // Exaggerate Z to make the display more interesting view.setZScale(5); // Lets look at the area of the survey view.zoomToDatasource(peon_outline); // Call this before using Seismic3DSectionControllers parser.parse(); // The range controller call method in the view object telling it to show particular 3D volume sections // We there need to get hold of the view object and attach it to the controller var seismic_vo = view.getViewObject(seismics3d); var range_controller = dijit.registry.byId("rangecontroller"); range_controller.setViewObject(seismic_vo); }); </script> <!-- Sliders that move the 3D seismic volume sections --> <div id="rangecontroller" data-dojo-type="Seismic3DSectionControllers"> </div> </body> |
This will display a seismic 3D volume along with three simple sliders to move the sections.
Lets examine this example in more detail.
<canvas id="sceneArea"></canvas> |
In line 3 we create a HTML canvas element. This element serves as the element into which the WebGL rendering will take place. In line 46 you see this element being provided to the view object. You can position the canvas element anywhere in page like any other HTML element.
require(["geocap/Scene", "geocap/FeatureLayerDataSource", "geocap/Seismic3DDataSource", "geocap/Seismic3DSectionControllers", "geocap/View3DThree", "dojo/parser", "dojo/domReady!"], function (Scene, FeatureLayerDataSource, Seismic3DDataSource, Seismic3DSectionControllers, View3DThree, parser) { |
Here we see Dojo AMD loading mechanism used to load various modules contained in the API. The Geocap Javascript API is implemented as a set of classes using the Dojo class mechanism. The rest of this example will instantiate these classes in turn.
// URL to map service var mapserver_url = "http://localhost:6080/arcgis/rest/services/Peon/MapServer"; // Survey outline feature. This just shows the survey outline, not the data var peon_outline = new FeatureLayerDataSource({ url: mapserver_url, layerid: 0 }); // Get all features in feature layer queryparams = { f: "json", returnZ: true, where: "objectid > 0", returnGeometry: true, } peon_outline.setQueryParameters(queryparams); |
In lines 15-30 we connect to the feature layer that contains our survey outlines. The FeatureLayerDataSource uses the query capabilities of the underlying map service to fetch the necessary data, including extent and feature geometry. Therefore, the arguments provided to the queryparameters object correspond to the ones used by the ArcGIS query REST API. Note that the feature layer object used here is just used to provide the cube lattice surrounding the cube data. It makes for a more appealing display, but is not strictly required in order to display the seismics. The FeatureLayerDataSource object will show any feature layer and has no inherent knowledge of seismics.
// Seismic 3D data (amplitudes). The survey of interest corresponds to feature with OID = 1 var seismics3d = Seismic3DDataSource({ url: mapserver_url, layerid: 0, surveyid: 1 }); |
In line 33 we use the Seismic3DDataSource object to connect to a seismic 3D survey. In the seismic server this corresponds to a particular feature containing the survey outline. The surveyid : 1 argument tells us that the survey is the feature with OBJECTID = 1. The Seismic3DDataSource object will then be able to provide metadata and data (the amplitudes) for the survey.
// Create scene to hold data var scene = new Scene(); // Add data to scene scene.addFeatureLayer(peon_outline); scene.addSeismic3D(seismics3d); |
In line 36 we create the Scene object and add our data to the scene. The Scene object contains little functionality other than being a placeholder for various datasources, and is mostly used as input to the View object used to render the data.
// Create 3D view for scene and insert it in given DOM element var c = document.getElementById("sceneArea"); var view = new View3DThree({ scene: scene, canvas: c }); // Exaggerate Z to make the display more interesting view.setZScale(5); // Lets look at the area of the survey view.zoomToDatasource(peon_outline); |
Here we see the instantiation of the View3DThree object, which will render our data in 3D using the Three.js render engine. By providing the existing Scene object as argument the view will have access to the data that is to be rendered into the canvas. In this case no spatial reference is provided to the view, so it will assume the default web mercator. If a particular coordinate system is desired you should provide the well-known ID as argument to the constructor, such as 'sref = 4326'.
var seismic_vo = view.getViewObject(seismics3d); var range_controller = dijit.registry.byId("rangecontroller"); range_controller.setViewObject(seismic_vo); }); </script> <!-- Sliders that move the 3D seismic volume sections --> <div id="rangecontroller" data-dojo-type="Seismic3DSectionControllers"> </div> |
Finally we create three sliders that will be used to move the seismic inline, crossline, and timeslice sections. Line 58 retrieves the so-called view object that represents the seismic cube. This object has methods for the display of the seismic sections, such as timeslice number 423. The Seismic3DSectionControllers is a simple Dijit widget that calls these methods based on the slider movement. You are free to create your own sliders or move the sections using other means as long as you call the corremt methods in the seismic 3D view objects.
This section describes the underlying object oriented design used by the Geocap Javascript API.
The above diagram shows a high level view of the rendering pipeline. The different datasources are collected in a Scene object, which in turn produces the corresponding view objects. The view objects direct the rendering of the input data into the target view. The views take care of transforming the incoming drawing commands to the underlying WebGL rendering engine. The datasources and the Scene object know nothing about graphics and rendering. Their task is to provide data and meta data to the view objects. They also manage spatial projections. A view is created with respect to a specific spatial reference and the view objects will ask the data sources to provide data in the target coordinate system.
We will now describe the classes in more detail. The main groups of classes are datasources, views and view objects.
The above figure shows the hierarchical relationship between the subclasses of DataSource and View. The classes that implement specific 3D engines are filled with green. Note that the dotted Babylon classes are not yet implemented.
Each datasource type has a corresponding view object. The view object keeps a reference to the data source as well as the target view object into which the data will be rendered.
<!DOCTYPE html> <html lang="en" xmlns="http://www.w3.org/1999/xhtml"> <head> <meta charset="utf-8" /> <title>Peon</title> <!-- Avoid favicon error --> <link rel="icon" href="data:;base64,iVBORwOKGO=" /> <style> html, body { height: 100%; width: 100%; margin: 0; padding: 0; } #rangecontroller { position: fixed; top: 50px; left: 50px; width: 400px; height: 400px; } </style> <script> // Make dojo look here for geocap module. Include this BEFORE including dojo var dojoConfig = { parseOnLoad: true, async: true, packages: [ { name: "geocap", location: "/js/geocap" }, { name: "geocapshader", location: "/shader" } ] }; </script> <script src="js/dojo-release-1.10.4-src/dojo/dojo.js"></script> <script src="js/three.js"></script> </head> <body> <canvas id="sceneArea"></canvas> <script> require(["geocap/Scene", "geocap/FeatureLayerDataSource", "geocap/Seismic3DDataSource", "geocap/Seismic3DSectionControllers", "geocap/View3DThree", "dojo/parser", "dojo/domReady!"], function (Scene, FeatureLayerDataSource, Seismic3DDataSource, Seismic3DSectionControllers, View3DThree, parser) { // URL to map service var mapserver_url = "http://localhost:6080/arcgis/rest/services/Peon/MapServer"; // Survey outline feature. This just shows the survey outline, not the data var peon_outline = new FeatureLayerDataSource({ url: mapserver_url, layerid: 0 }); // Get all features in feature layer queryparams = { f: "json", returnZ: true, where: "objectid > 0", returnGeometry: true, } peon_outline.setQueryParameters(queryparams); // Seismic 3D data (amplitudes). The survey of interest corresponds to feature with OID = 1 var seismics3d = Seismic3DDataSource({ url: mapserver_url, layerid: 0, surveyid: 1 }); // Create scene to hold data var scene = new Scene(); // Add data to scene scene.addFeatureLayer(peon_outline); scene.addSeismic3D(seismics3d); // Create 3D view for scene and insert it in given DOM element var c = document.getElementById("sceneArea"); var view = new View3DThree({ scene: scene, canvas: c }); // Exaggerate Z to make the display more interesting view.setZScale(5); // Lets look at the area of the survey view.zoomToDatasource(peon_outline); // Call this before using Seismic3DSectionControllers parser.parse(); // The range controller call method in the view object telling it to show particular 3D volume sections // We there need to get hold of the view object and attach it to the controller var seismic_vo = view.getViewObject(seismics3d); var range_controller = dijit.registry.byId("rangecontroller"); range_controller.setViewObject(seismic_vo); }); </script> <!-- Sliders that move the 3D seismic volume sections --> <div id="rangecontroller" data-dojo-type="Seismic3DSectionControllers"> </div> </body> </html> |