This tutorial demonstrates how to use geotoolkit/scene/shapes/TiledShape to display server-side rendered overlays. The server-side code is based on the Custom Remote Reader tutorial Code to read seismic data from a SEG-Y file on the server side.
# Creating Remote Overlay
We created two layers, which render the same SEG-Y in the browser and in the server-side code using node.js. For demonstration purposes only we use node.js on server size and some classes from GeoToolkit to read SEG-Y format. We don't recommend using the same server-side implementation in production because it was created to show server and client communication only. The server-side layers render seismic in density mode and the client-side receives binary data and renders traces in the 'wiggle' mode. The code below shows how to create and initialize overlay.
# Creating Remote Overlay with Dynamic Model
The second part of the example uses the same initialization as previous one to bring a tiled image from the server using a dynamic model. It depends on screen resolution.
# Source code
import { Events as NodeEvents } from "@int/geotoolkit/scene/Node.ts";
import { Rect } from "@int/geotoolkit/util/Rect.ts";
import { Events as RubberBandEvents } from "@int/geotoolkit/controls/tools/RubberBand.ts";
import { Plot } from "@int/geotoolkit/plot/Plot.ts";
import { SeismicWidget } from "@int/geotoolkit/seismic/widgets/SeismicWidget.ts";
import { NormalizationType } from "@int/geotoolkit/seismic/pipeline/NormalizationType.ts";
import { SeismicColors } from "@int/geotoolkit/seismic/util/SeismicColors.ts";
import { SeismicPipeline } from "@int/geotoolkit/seismic/pipeline/SeismicPipeline.ts";
import { RemoteSeismicDataSource } from "@int/geotoolkit/seismic/data/RemoteSeismicDataSource.ts";
import { ManipulatorType } from "@int/geotoolkit/seismic/widgets/SeismicViewWidget.ts";
import { createDynamicLayer, createRemoteLayerImage } from "/src/code/Seismic/ImagesAndLayers/RemoteOverlay/remoteSeismicLayer.ts";
import "/src/code/Seismic/ImagesAndLayers/RemoteOverlay/nodeserverdataprovider.ts";
const host = "http://localhost:3001/";
const activateRubberBandZoom = function(widget) {
widget.setManipulatorType(ManipulatorType.RubberBand);
};
const activateRubberBandZoomAll = function(plots) {
for (let i = 0; i < plots.length; i++) {
activateRubberBandZoom(plots[i].getRoot());
}
};
const resetRubberBandZoomAll = function(resetOnly, plots) {
for (let i = 0; i < plots.length; i++) {
resetRubberBandZoom(plots[i].getRoot(), resetOnly);
}
};
function resetRubberBandZoom(widget, resetOnly) {
if (widget.getManipulatorType() === ManipulatorType.RubberBand || resetOnly === true) {
widget.setManipulatorType(ManipulatorType.Panning);
return;
}
widget.resetZoom();
widget.fitToBounds();
widget.setManipulatorType(ManipulatorType.Panning);
}
const createReader = function(onready, onfailure) {
const data = new RemoteSeismicDataSource({
"host": host,
"file": "data/section.segy",
"version": "node"
});
data.open(
() => {
data.select({}, (reader) => {
onready(reader);
});
},
(err) => {
onfailure(err);
}
);
};
const createPipeline = function(reader) {
return new SeismicPipeline({
"name": "Seismic",
"reader": reader,
"statistics": reader.getStatistics()
}).setOptions({
"normalization": {
"type": NormalizationType.RMS,
"scale": 0.4
},
"plot": {
"type": {
"wiggle": true
},
"decimationspacing": 5
},
"colors": {
"colormap": SeismicColors.getDefault().createNamedColorMap("WhiteBlack", 32)
}
});
};
function createPlot(canvas) {
const widget = new SeismicWidget({
"colorbar": {
"axis": {
"tickgenerator": {
"edge": {
"tickvisible": false,
"labelvisible": false
}
}
}
},
"layouttype": "inside",
"statusbar": {
"visible": false
}
});
return new Plot({
"canvaselement": canvas,
"root": widget
});
}
const createRemoteSeismicOverlay = function(plots, pipeline, overlay, cb) {
const widget = plots[0].getRoot();
widget.setPipeline(pipeline);
createRemoteLayerImage(widget, overlay["destination"], overlay["src"]);
widget.getToolByName("rubberband").on(RubberBandEvents.onZoomEnd, () => {
resetRubberBandZoomAll(true, plots);
cb();
});
};
const createDynamicVelocityOverlay = function(plots, pipeline, overlay) {
const widget = plots[1].getRoot();
widget.setPipeline(pipeline);
createDynamicLayer(widget, overlay["destination"], overlay["src"]);
};
function createScene(canvas, canvasDynamic, onError, cb) {
const plots = [];
plots.push(createPlot(canvas));
plots.push(createPlot(canvasDynamic));
createReader((reader) => {
const pipeline = createPipeline(reader);
const pipelineModelLimits = pipeline.getModelLimits();
createRemoteSeismicOverlay(plots, pipeline, {
"destination": pipelineModelLimits.clone(),
"src": {
"host": host,
"file": "data/section.segy"
}
}, cb);
createDynamicVelocityOverlay(plots, pipeline, {
"destination": pipelineModelLimits.clone(),
"src": {
"host": host,
"limits": new Rect(0, 0, 4e4, 1400),
"dynamic": true
}
});
let lockSynchronization = false;
const synchronizeModelLimits = function(event, sender) {
if (lockSynchronization) {
return;
}
lockSynchronization = true;
const visibleModelLimits = sender.getVisibleSeismicModelLimits();
for (let i = 0; i < plots.length; i++) {
const widget = plots[i].getRoot();
if (widget !== sender) {
widget.setVisibleSeismicModelLimits(visibleModelLimits);
}
}
lockSynchronization = false;
};
for (let i = 0; i < plots.length; i++) {
const widget = plots[i].getRoot();
widget.on(NodeEvents.VisibleLimitsChanged, synchronizeModelLimits);
}
}, (error) => {
onError(true);
});
return plots;
}
export { activateRubberBandZoomAll, createScene, resetRubberBandZoomAll };
createScene(document.querySelector('[ref="CreatingRemoteOverlay"]'), document.querySelector('[ref="DynamicModel"]'), this.inputServerWarningDialog, () => {
this.setRubberBandSelectionEnabled(false);
});