Last updated

Remote Overlay

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);
        });