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: