Last updated

Custom ComponentNode

This tutorial shows how to create custom component node implementations derived from the ComponentNode class.

The key idea is that data passed to custom elements is NOT restricted to any specific format. Instead, the developer is responsible for defining how his/her data is interpreted and converted to a CarnacJS node or shape.
In this tutorial, data (geometries) for SimpleComponentNode objects are structured as JSON objects.

Also, a trivial implementation of AbstractComponentNodeFactory is provided that returns the node's class instance in its createComponentNode() method call.

General information (how to register your custom component, how to add data of the component's to a wellbore, how to get it visualized) is represented in the General Information tutorial.

# 'Tubing' Schematic Element Implementation

This is an example of a "tubing" schematic element implementation:

import { Plot } from "@int/geotoolkit/plot/Plot.ts";
import { Rect } from "@int/geotoolkit/util/Rect.ts";
import { Events } from "@int/geotoolkit/scene/Node.ts";
import { SimpleComponentNodeFactory } from "/src/code/Schematics/CustomComponentNode/simpleComponentNodeFactory.ts";
import { ComponentNodeFactoryRegistry } from "@int/geotoolkit/schematics/factory/ComponentNodeFactoryRegistry.ts";
import { WellBoreData } from "@int/geotoolkit/schematics/data/WellBoreData.ts";
import { WellBoreNode } from "@int/geotoolkit/schematics/scene/WellBoreNode.ts";
const createScene = (canvas) => {
  const componentName = "MySimpleComponent";
  const nodeFactory = new SimpleComponentNodeFactory();
  const factoryRegistry = new ComponentNodeFactoryRegistry();
  factoryRegistry.setFactory(componentName, nodeFactory);
  const wellBoreData = new WellBoreData();
  const shapeOptions = {
    "geometry": {},
    "top": 50,
    "bottom": 100,
    "left": -25,
    "right": 25
  };
  wellBoreData.addComponent(componentName, shapeOptions);
  const wellBoreNode = new WellBoreNode({
    "data": wellBoreData,
    "registry": factoryRegistry
  });
  const plotMinY = 0, plotMaxY = 250, plotMinX = 0, plotMaxX = 250;
  const plotSizeX = plotMaxX - plotMinX;
  const plotSizeY = plotMaxY - plotMinY;
  wellBoreNode.setBounds(new Rect(
    plotMinX + plotSizeX / 4,
    plotMinY,
    plotMaxX - plotSizeX / 4,
    plotMaxY
  ));
  const plot = new Plot({
    "canvaselement": canvas,
    "root": wellBoreNode
  });
  wellBoreNode.on(Events.Invalidate, () => plot.update());
  plot.setSize(plotSizeX, plotSizeY);
  return plot;
};
export {
  createScene
};

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

# Node constructor

Most of its code is essentially component data to Carnac shapes geometry conversion (a rectangle and two polygons filled with gradient fill style). The data is passed as a parameter to the node's constructor:

# Node geometry

Then the node's geometry bounds gets by getGeometryBounds() method call: