This example shows how to connect the seismic widget and multi histogram widget to show histograms for selected areas on seismic data. The user can select polygonal or rectangular areas on 2d seismic received from remote server. These areas can be moved and extended. Multiple areas are supported and displayed with different colors in seismic overlay and histogram widget.
# Seismic Component
Seismic component encapsulates geotoolkit/seismic/widgets/SeismicViewWidget and adds an overlay to keep the geometry of the selected areas, which is called geometry layer and code to retrieve an array of samples from a polygonal area in seismic model coordinates. The code below shows how to initialize widget and create a geometry layer.
# Gets Samples for Selected Area
The most important part of Seismic Component code gets samples for selected area in 2d seismic. It requests samples in asynchronous mode from seismic pipeline. Pipeline requests samples from server via reader if they are not in the local cache. The code below shows this method.
# Add Selected Area to Seismic
Seismic Component has a method to add selected area to geometry overlay. The area is a rectangle to two arrays of x and y coordinates of polygon. Coordinates are provided in manipulator layer, which has different transformation from geometry layer. The code below transforms to device coordinate and device to geometry layer and add a new shape to geometry layer.
# Histogram Component
Histogram component is based on geotoolkit/widgets/MultiHistograms and a new histogram in the stacked order for selected area. If the user moves or changes geometry of the existing area the method createOrUpdateHistogram updates data and recalculates histogram.
# Area Tool
Area tool allows creating polygon or rectangle in geometry layer, modifying geometry or position of shapes. It uses RectangularShapeAdapter and PolyLineShapeAdapter to display handles to change geometry of shapes.
# Result
This example contains seismic component, histogram component, area selection and editing tool, and code to combine these components together. Use any of the selection tools from the toolbar to select an area in the 2dSeicmic. The histogram will be displayed automatically.
import { from } from "@int/geotoolkit/selection/from.ts";
import { Plot } from "@int/geotoolkit/plot/Plot.ts";
import { HorizontalBoxLayout } from "@int/geotoolkit/layout/HorizontalBoxLayout.ts";
import { Group } from "@int/geotoolkit/scene/Group.ts";
import { SeismicColors } from "@int/geotoolkit/seismic/util/SeismicColors.ts";
import { NormalizationType } from "@int/geotoolkit/seismic/pipeline/NormalizationType.ts";
import { Polygon } from "@int/geotoolkit/scene/shapes/Polygon.ts";
import { Events as RubberBandEvents, RubberBand } from "@int/geotoolkit/controls/tools/RubberBand.ts";
import { Events as PolygonSelectionEvents, PolygonSelection } from "@int/geotoolkit/controls/tools/PolygonSelection.ts";
import { RemoteSeismicDataSource } from "@int/geotoolkit/seismic/data/RemoteSeismicDataSource.ts";
import { Events as HistogramComponentEvents, HistogramComponent } from "/src/code/Seismic/ImagesAndLayers/Histogram/histogramcomponent.ts";
import { SeismicComponent } from "/src/code/Seismic/ImagesAndLayers/Histogram/seismiccomponent.ts";
import { AreaTool, Events as AreaToolEvents } from "/src/code/Seismic/ImagesAndLayers/Histogram/areatool.ts";
import { warn } from "@int/geotoolkit/base.js";
let seismicComponent = null;
let histogramComponent = null;
const POLYGON_SELECTION_TOOL_NAME = "SeismicPolygonSelectionTool";
const BOX_SELECTION_TOOL_NAME = "SeismicBoxSelectionTool";
const AREA_TOOL_NAME = "AreaTool";
const HISTOGRAM_WIDTH = "30%";
const SEISMIC_WIDTH = "70%";
let group;
let plot;
let setRubberBandSelection = null;
function createSectionQuery(position, key, oppositeKey) {
const selectKeys = [];
selectKeys[0] = {
"name": key["key"],
"min": position,
"max": position,
"step": key["increment"],
"order": "asc"
};
selectKeys[1] = {
"name": oppositeKey["key"],
"min": oppositeKey["min"],
"max": oppositeKey["max"],
"step": oppositeKey["increment"],
"order": "asc"
};
return {
"keys": selectKeys,
"emptyTracesKey": {
"name": oppositeKey["key"],
"min": oppositeKey["min"],
"max": oppositeKey["max"]
}
};
}
const createReader = function(onready) {
const host = "https://demo.int.com/INTGeoServer/json";
const data = new RemoteSeismicDataSource({
"host": host,
"file": "data/seismic/Gullfaks_Amplitude.xgy",
"version": 2
});
data.open(
() => {
const keys = data.getKeys();
const key = keys[0];
const oppositeKey = keys[1];
const query = createSectionQuery(key["min"], key, oppositeKey);
data.select(query, (reader) => {
onready(reader);
});
},
(err) => {
warn("Data can't be loaded from server!");
}
);
};
const disableTools = function(activeTool) {
let tool = seismicComponent.getWidget().getToolByName(BOX_SELECTION_TOOL_NAME);
if (activeTool !== tool) {
tool.setEnabled(false);
}
tool = seismicComponent.getWidget().getToolByName(POLYGON_SELECTION_TOOL_NAME);
if (activeTool !== tool) {
tool.setEnabled(false);
}
tool = seismicComponent.getWidget().getToolByName(AREA_TOOL_NAME);
if (activeTool !== tool) {
tool.setEnabled(activeTool === null);
}
};
const initializePolygonSelection = function(manipulatorLayer) {
return new PolygonSelection(manipulatorLayer).setName(POLYGON_SELECTION_TOOL_NAME).setEnabled(false).on(PolygonSelectionEvents.onSelectionEnd, (evt, object, eventArgs) => {
setRubberBandSelection(false);
const x = eventArgs.getCoordinates()["x"];
const y = eventArgs.getCoordinates()["y"];
const area = seismicComponent.addSelectedArea(x, y);
seismicComponent.getTraceData(area["x"], area["y"]).then((data) => {
histogramComponent.createOrUpdateHistogram(area["id"], area["id"].toString(), data, area["color"]);
histogramComponent.getWidget().setDesiredWidth(HISTOGRAM_WIDTH);
seismicComponent.getWidget().setDesiredWidth(SEISMIC_WIDTH);
group.updateLayout();
});
});
};
const initializeRubberBandSelection = function(manipulatorLayer) {
return new RubberBand(manipulatorLayer).setName(BOX_SELECTION_TOOL_NAME).setEnabled(false).on(RubberBandEvents.onZoomEnd, (eventType, sender, eventArgs) => {
const rect = eventArgs.getArea();
const area = seismicComponent.addSelectedArea(rect);
seismicComponent.getTraceData(area["x"], area["y"]).then((data) => {
histogramComponent.createOrUpdateHistogram(area["id"], area["id"].toString(), data, area["color"]);
histogramComponent.getWidget().setDesiredWidth(HISTOGRAM_WIDTH);
seismicComponent.getWidget().setDesiredWidth(SEISMIC_WIDTH);
group.updateLayout();
});
disableTools(null);
});
};
const initializeAreaTool = function(manipulatorLayer, geometryLayer) {
const areaTool = new AreaTool(manipulatorLayer, geometryLayer).setName(AREA_TOOL_NAME).setEnabled(true).on(AreaToolEvents.AreaChanged, (evt, object, eventArgs) => {
const shape = eventArgs["shape"];
if (!shape)
return;
let x, y;
const id = shape.getId();
if (shape instanceof Polygon) {
x = shape.getPointsX().slice();
y = shape.getPointsY().slice();
if (shape.getLocalTransform()) {
shape.getLocalTransform().transformPoints(x, y, x.length);
}
} else {
let rect = shape.getBounds();
if (shape.getLocalTransform()) {
rect = shape.getLocalTransform().transformRect(rect);
}
x = [rect.getLeft(), rect.getRight(), rect.getRight(), rect.getLeft(), rect.getLeft()];
y = [rect.getTop(), rect.getTop(), rect.getBottom(), rect.getBottom(), rect.getTop()];
}
seismicComponent.getTraceData(x, y).then((data) => {
histogramComponent.createOrUpdateHistogram(id, id, data);
});
});
return areaTool;
};
function initializeSeismic(seismicReader) {
const component = new SeismicComponent(seismicReader);
component.getPipeline().setOptions({
"normalization": {
"type": NormalizationType.RMS,
"scale": 1
},
"plot": {
"type": {
"wiggle": false,
"interpolateddensity": true
},
"decimationspacing": 5
},
"colors": {
"colormap": SeismicColors.getDefault().createNamedColorMap("WhiteBlack", 32)
}
});
const manipulatorLayer = component.getManipulatorLayer();
const geometryLayer = component.getGeometryLayer();
const polygonSelectionTool = initializePolygonSelection(manipulatorLayer);
component.getWidget().getTool().insert(0, polygonSelectionTool);
const rubberBancSelectionTool = initializeRubberBandSelection(manipulatorLayer);
component.getWidget().getTool().insert(0, rubberBancSelectionTool);
const areaTool = initializeAreaTool(manipulatorLayer, geometryLayer);
component.getWidget().getTool().insert(0, areaTool);
return component;
}
const activatePolygonSelectionTool = function() {
if (seismicComponent.getWidget() == null) {
return;
}
const tool = seismicComponent.getWidget().getToolByName(POLYGON_SELECTION_TOOL_NAME);
tool.setEnabled(!tool.isEnabled());
disableTools(tool);
};
const activateRubberBandSelectionTool = function() {
if (seismicComponent.getWidget() == null) {
return;
}
const tool = seismicComponent.getWidget().getToolByName(BOX_SELECTION_TOOL_NAME);
tool.setEnabled(!tool.isEnabled());
disableTools(tool);
};
const activatePointSelectionTool = function() {
if (seismicComponent.getWidget() == null) {
return;
}
const tool = seismicComponent.getWidget().getToolByName(AREA_TOOL_NAME);
tool.setEnabled(true);
disableTools(tool);
};
function resetSelection() {
if (seismicComponent.getWidget() == null) {
return;
}
let tool = seismicComponent.getWidget().getToolByName(POLYGON_SELECTION_TOOL_NAME);
tool.setEnabled(false);
tool = seismicComponent.getWidget().getToolByName(BOX_SELECTION_TOOL_NAME);
tool.setEnabled(false);
tool = seismicComponent.getWidget().getToolByName(AREA_TOOL_NAME);
tool.setEnabled(false);
const layer = seismicComponent.getGeometryLayer();
layer.clearChildren();
histogramComponent.removeHistograms();
histogramComponent.getWidget().setDesiredWidth("0%");
seismicComponent.getWidget().setDesiredWidth("100%");
group.updateLayout();
}
function resetZoom() {
if (seismicComponent.getWidget() == null) {
return;
}
seismicComponent.getWidget().resetZoom();
}
const zoomIn = function() {
if (seismicComponent == null) {
return;
}
seismicComponent.zoomIn();
};
const zoomOut = function() {
if (seismicComponent == null) {
return;
}
seismicComponent.zoomOut();
};
function initializeHistogram() {
const histogram = new HistogramComponent();
histogram.on(HistogramComponentEvents.HistogramSelected, (eventName, sender, eventArgs) => {
const id = +eventArgs["id"];
activatePointSelectionTool();
const tool = seismicComponent.getWidget().getToolByName(AREA_TOOL_NAME);
const geometryLayer = seismicComponent.getGeometryLayer();
const shape = from(geometryLayer).where((node) => node.getId() === id).selectFirst();
tool.selectShape(shape);
});
return histogram;
}
function initialize(canvas, setRubberBandSelectionEnabled) {
setRubberBandSelection = setRubberBandSelectionEnabled;
createReader((reader) => {
seismicComponent = initializeSeismic(reader);
histogramComponent = initializeHistogram();
group = new Group().setAutoModelLimitsMode(true).setLayout(new HorizontalBoxLayout()).addChild([
seismicComponent.getWidget().setDesiredWidth("100%"),
histogramComponent.getWidget().setDesiredWidth("0%")
]);
plot = new Plot({
"canvaselement": canvas,
"root": group
});
});
}
function dispose() {
if (plot) {
plot.dispose();
}
}
export {
activatePointSelectionTool,
activatePolygonSelectionTool,
activateRubberBandSelectionTool,
dispose,
initialize,
resetSelection,
resetZoom,
zoomIn,
zoomOut
};
createScene();