Coordinate Transformation

Transforming internal depth coordinates into canvas ones is trivial task in the only case of geotoolkit/schematics/scene/WellBoreNode/ViewMode/Regular. In other view modes - Compressed and KeepAspectRatio - depth axis scale is piece-linear one. So PieceLinearValueTransformer class is developed that handles "internal" transforming from linear to piece-linear model space (and vice versa).
Familiarization with ViewMode enumeration type as well as Getting Started tutorial in SchematicsJS is beneficial.

# Transformation

The tutorial displays SchematicsWidget within HTML5 canvas limits.
On other hand set of textarea HTML elements (one per each schematics component) are displayed outside the canvas.
Method "modelDepthToCanvas" is used to synchronize the text areas vertically with their respective schematics components.

import { getPixelScale } from "@int/geotoolkit/base.js";
import { Plot } from "@int/geotoolkit/plot/Plot.ts";
import { CompositeSchematicsWidget } from "@int/geotoolkit/schematics/widgets/CompositeSchematicsWidget.ts";
import { WellBoreData } from "@int/geotoolkit/schematics/data/WellBoreData.ts";
import { Point } from "@int/geotoolkit/util/Point.ts";
import { Alignment } from "@int/geotoolkit/layout/BoxLayout.ts";
import { Mode } from "@int/geotoolkit/schematics/labeling/Mode.ts";
const depths = [
  341,
  1020,
  3e3,
  4500,
  14589
];
const descriptions = [
  "Drive Pipe",
  "Surface Casing",
  "Intermediate Casing-1",
  "Intermediate Casing-2",
  "Production Casing"
];
const diameters = [
  [26, 25],
  [20, 19],
  [13, 12],
  [9.5, 9],
  [7, 6.5]
];
function createData() {
  const wellBoreData = new WellBoreData();
  for (let i = 0; i < depths.length; ++i) {
    wellBoreData.addComponent("casing", {
      description: descriptions[i],
      geometry: {
        depth: { from: 0, to: depths[i] },
        diameter: { outer: diameters[i][0], inner: diameters[i][1] }
      }
    });
  }
  return wellBoreData;
}
const elementHeight = 75;
const elementWidth = 250;
const xGap = 5;
const pt = new Point();
let plot = null;
let widget = null;
let elements = [];
function modelDepthToCanvas(depthModel) {
  pt.setPoint(0, depthModel);
  widget.getDevicePoint(pt, pt);
  return pt.getY();
}
function updateTextAreas() {
  const canvas = plot.getContainingElement();
  const dxCanvas = (canvas.offsetLeft + canvas.width) / getPixelScale();
  for (let i = 0; i < depths.length; ++i) {
    let depthCanvas = modelDepthToCanvas(depths[i]);
    depthCanvas = Math.round(depthCanvas);
    const textElement = elements[i];
    textElement.style.left = dxCanvas + xGap + "px";
    textElement.style.top = depthCanvas - elementHeight + "px";
  }
}
function getExtendedComponentInfo(i) {
  return descriptions[i] + ":\ndepth: " + depths[i] + "\nod: " + diameters[i][0] + " id: " + diameters[i][1];
}
function createTextAreas(refParent) {
  for (let i = 0; i < depths.length; ++i) {
    const textElement = document.createElement("textarea");
    textElement.value = getExtendedComponentInfo(i);
    textElement.style.backgroundColor = "lightgray";
    textElement.style.borderRadius = "6px";
    textElement.style.borderWidth = "1px";
    textElement.style.position = "absolute";
    textElement.style.height = elementHeight + "px";
    textElement.style.width = elementWidth + "px";
    refParent.appendChild(textElement);
    elements.push(textElement);
  }
}
function createScene(refCanvas) {
  const data = createData();
  widget = new CompositeSchematicsWidget({
    "alignment": Alignment.Left,
    "labeling": { "mode": Mode.NoLabels },
    "wellborenode": {},
    "annotationssizes": {
      "north": 0,
      "south": 0
    },
    "tooltip": {
      "autoflip": true
    },
    "data": {
      "elements": data
    }
  });
  plot = new Plot({
    "canvaselement": refCanvas,
    "root": widget
  });
}
function disposeScene() {
  if (plot) {
    plot.dispose();
  }
}
function disposeTextAreas() {
  if (elements && elements.length > 0) {
    const parent = elements[0].parentNode;
    for (let i = elements.length - 1; i >= 0; --i) {
      const textElement = elements[i];
      parent.removeChild(textElement);
    }
    elements = [];
  }
}
export { createScene, createTextAreas, disposeScene, disposeTextAreas, updateTextAreas };

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