This tutorial demonstrates how to create a Navigation view for WellLog widget. The navigation tool (geotoolkit/welllog/widgets/tools/Navigation) is added to the WellLog Widget to create a Navigation widget. Both widgets are created separately and added to one canvas. If these widgets are located in different plots, the scale can be synchronized in a manner similar to plot synchronization.

# WellLog Widget Initialization

The following code shows how to initialize WellLog widget tools. See the WellLog Widget tutorial.

The following code shows how to initialize the Navigation Tools

# WellLog Navigation

In the example below, the Navigation widget is displayed on the left. Adding a listener to the WellLog widget will allow the widget to change display on curve selection. Similarly, attaching listenings will allow for WellLog widget visible limits to be updated in real-time in accord with changing visible model limits in the Navigation widget.

import { ColorUtil, KnownColors } from "@int/geotoolkit/util/ColorUtil.ts";
import { MathUtil } from "@int/geotoolkit/util/MathUtil.ts";
import { LogData } from "@int/geotoolkit/welllog/data/LogData.ts";
import { LogCurve } from "@int/geotoolkit/welllog/LogCurve.ts";
import { AdaptiveLogCurveVisualHeader, Elements } from "@int/geotoolkit/welllog/header/AdaptiveLogCurveVisualHeader.ts";
import { TrackType as WellLogTrackType } from "@int/geotoolkit/welllog/TrackType.ts";
import { Events as WellLogEvents } from "@int/geotoolkit/welllog/widgets/Events.ts";
import { Plot } from "@int/geotoolkit/plot/Plot.ts";
import { Group } from "@int/geotoolkit/scene/Group.ts";
import { from } from "@int/geotoolkit/selection/from.ts";
import { Events as SelectionEvents } from "@int/geotoolkit/controls/tools/Selection.ts";
import { Axis } from "@int/geotoolkit/axis/Axis.ts";
import { Events as NavigationEvents, Navigation } from "@int/geotoolkit/welllog/widgets/tools/Navigation.ts";
import { Sections } from "@int/geotoolkit/welllog/header/AdaptiveLogVisualHeader.ts";
import { curveData } from "/src/code/WellLog/utils/curveData.ts";
import { createWellLogWidget } from "/src/code/WellLog/utils/common.ts";
import { HorizontalBoxLayout } from "@int/geotoolkit/layout/HorizontalBoxLayout.ts";
function createTestData(from2, step, curveMnemonic) {
  const depths = [];
  const values = [];
  const curveDat = curveData[curveMnemonic];
  const amountOfPoints = curveDat.length;
  for (let i = 0; i < amountOfPoints; i++) {
    depths.push(i * step + from2);
    values.push(curveDat[i]);
  }
  return new LogData({
    "name": curveMnemonic,
    "depths": depths,
    "values": values
  });
}
function createCurve(dataSource, color) {
  const limits = MathUtil.calculateNeatLimits(dataSource.getMinValue(), dataSource.getMaxValue(), false, false);
  return new LogCurve(dataSource).setLineStyle(ColorUtil.parseColor(color)).setNormalizationLimits(limits.getLow(), limits.getHigh());
}
class NavigationView {
  constructor() {
    this._wellLogWidget = null;
    this._navigationWidget = null;
    this._dataSources = {
      "GR": createTestData(4500, 10, "GR"),
      "CALI": createTestData(4500, 10, "CALI"),
      "SP": createTestData(4500, 10, "SP")
    };
  }
  initializeWellLog() {
    const widget = createWellLogWidget({
      "indent": 2
    }).setDepthLimits(this._dataSources["GR"].getMinDepth(), this._dataSources["GR"].getMaxDepth());
    widget.getHeaderContainer().getHeaderProvider().registerHeaderProvider(
      LogCurve.getClassName(),
      new AdaptiveLogCurveVisualHeader().setElement([Elements.ScaleFrom, Elements.ScaleTo], { "section": Sections.Top }).setElement(Elements.Tracking, { "section": Sections.Top })
    );
    widget.addTrack(WellLogTrackType.LinearTrack).addChild([createCurve(this._dataSources["GR"], KnownColors.Green)]);
    widget.addTrack(WellLogTrackType.LinearTrack).addChild([createCurve(this._dataSources["CALI"], KnownColors.Orange)]);
    widget.addTrack(WellLogTrackType.LinearTrack).addChild([createCurve(this._dataSources["SP"], KnownColors.Blue)]);
    widget.addTrack(WellLogTrackType.IndexTrack).setWidth(35);
    widget.setHeaderHeight("auto");
    widget.getToolByName("splitter").setEnabled(false);
    widget.getToolByName("pick").on(SelectionEvents.onSelectionChanged, (evt, sender, eventArgs) => {
      eventArgs.getSelection().forEach((selection) => {
        if (selection instanceof LogCurve) {
          from(this._navigationWidget).where((node) => node instanceof LogCurve).select((curve) => {
            curve.setLineStyle(selection.getLineStyle()).setData(selection.getDataSource(), true, true);
          });
        }
      });
    });
    return widget;
  }
  initializeNavigation() {
    const widget = createWellLogWidget({
      "horizontalscrollable": false,
      "verticalscrollable": false,
      "header": {
        "visible": false
      },
      "border": { "visible": true }
    }).setDepthLimits(this._dataSources["GR"].getMinDepth(), this._dataSources["GR"].getMaxDepth());
    widget.addTrack(WellLogTrackType.IndexTrack).setWidth(40);
    from(widget).where((node) => node instanceof Axis).selectFirst().setLabelPadding(4);
    widget.addTrack(WellLogTrackType.LinearTrack).addChild([createCurve(this._dataSources["GR"], KnownColors.Green)]).setWidth(100);
    widget.getToolByName("pick").setEnabled(false);
    widget.getToolByName("splitter").setEnabled(false);
    widget.getToolByName("cross-hair").setEnabled(false);
    widget.getToolByName("TrackPanning").setEnabled(false);
    return widget;
  }
  initializeNavigationTools() {
    const manipulatorLayer = this._navigationWidget.getToolByName("cross-hair").getManipulatorLayer();
    const navigationTool = new Navigation(manipulatorLayer).on(NavigationEvents.DepthRangeChanged, (evt, sender, eventArgs) => {
      this._wellLogWidget.setVisibleDepthLimits(eventArgs.getLimits());
    });
    navigationTool.setVisibleDepthLimits(this._wellLogWidget.getVisibleDepthLimits());
    const setVisibleDepthLimits = function() {
      navigationTool.setVisibleDepthLimits(this._wellLogWidget.getVisibleDepthLimits());
    }.bind(this);
    this._wellLogWidget.on(WellLogEvents.DepthRangeChanged, setVisibleDepthLimits);
    this._wellLogWidget.on(WellLogEvents.VisibleDepthLimitsChanged, setVisibleDepthLimits);
    return navigationTool;
  }
  disableRubberBand() {
    this._wellLogWidget.getToolByName("rubberband").setEnabled(false);
  }
  zoomIn() {
    this._wellLogWidget.scale(5 / 4);
    this.disableRubberBand();
  }
  zoomOut() {
    this._wellLogWidget.scale(4 / 5);
    this.disableRubberBand();
  }
  fitToHeight() {
    this._wellLogWidget.fitToHeight();
    this.disableRubberBand();
  }
  rubberBandZoom() {
    this._wellLogWidget.getToolByName("rubberband").setEnabled(true);
  }
  init(canvas) {
    this._plot = new Plot({
      "canvaselement": canvas,
      "root": new Group().setAutoModelLimitsMode(true).setLayout(new HorizontalBoxLayout()).addChild([
        this._navigationWidget = this.initializeNavigation().setLayoutStyle({
          "width": 140
        }).setMarginsStyle({ right: "2px" }),
        this._wellLogWidget = this.initializeWellLog().setLineStyle("lightgray").setMarginsStyle({ left: "2px" })
      ])
    });
    const gr = this._dataSources["GR"];
    const minDepth = gr.getMinDepth();
    const maxDepth = gr.getMaxDepth();
    this._wellLogWidget.setVisibleDepthLimits(minDepth, minDepth + (maxDepth - minDepth) / 4).fitToWidth();
    this._navigationWidget.fitToHeight().getTool().add([
      this.initializeNavigationTools()
    ]);
  }
  getPlot() {
    return this._plot;
  }
  getWidget() {
    return this._wellLogWidget;
  }
}
function createScene(canvas) {
  const app = new NavigationView();
  app.init(canvas);
  return app;
}
export { createScene };

createScene(document.querySelector('[ref="plot"]'));