This tutorial demonstrates how to add a text/legend on a 3D Grid or Projection Widget .
Each plane of the legend can be customized separately if needed.
To use this feature, you simply need to create a GridLegend with the desired legend settings,
and add it to a Grid or a ProjectionWidget through the .addLegend() method.
# Add a legend on a 3D Grid
In this example you can see how to add the legend to a 3D Grid.
With the interface below, you can dynamically change some of the legend options.
For more options please refer to the GridLegend documentation.
import { DefaultColorProvider } from "@int/geotoolkit/util/DefaultColorProvider.ts";
import { Plot } from "@int/geotoolkit3d/Plot.ts";
import { Vector2, Vector3 } from "/node_modules/.vite/deps/three.js?v=2235af65";
import { Grid } from "@int/geotoolkit3d/scene/grid/Grid.ts";
import { CompassAxis } from "@int/geotoolkit3d/scene/compass/CompassAxis.ts";
import { GridLegend } from "@int/geotoolkit3d/scene/grid/legend/GridLegend.ts";
import { PointSet } from "@int/geotoolkit3d/scene/pointset/PointSet.ts";
import { MathUtil } from "@int/geotoolkit/util/MathUtil.ts";
import { AlignmentStyle, TextStyle } from "@int/geotoolkit/attributes/TextStyle.ts";
let __legendHandle;
const __legendDynamicOptions = {
"sizeindevice": true,
"nearside": false,
"hideiftoolarge": true,
"textscale": 1
};
function createScene(divElement) {
const plot = createPlot(divElement);
const pointSet = createPointSet();
const grid = new Grid({ start: new Vector3(0, 0, 0), end: new Vector3(20, 20, 20) });
plot.getRoot().add(grid);
plot.getRoot().add(pointSet);
const legend = createLegend();
grid.addLegend(legend);
__legendHandle = legend;
return plot;
}
function createLegend() {
const legendStyle = new TextStyle({
"font": "15px Arial",
"color": "white",
"alignment": AlignmentStyle.Left
});
const titleStyle = new TextStyle({
"font": "22px Arial",
"color": "white",
"alignment": AlignmentStyle.Center
}).setFontWeight("bold");
const blackOutline = {
"enable": true,
"innercolor": "white",
"outlinecolor": "black",
"thickness": 3
};
const gridTextOpts = {
"planes": {
"left": {
"text": "SAMPLE LEGEND\n\nItem 1 - Item description\nItem 2 - Item description\nItem 3 - Item description\nItem 4 - Item description\n",
"style": legendStyle,
"outline": blackOutline,
"textoffset": new Vector2(0.25, 0.66)
},
"back": {
"text": "SAMPLE TITLE",
"style": titleStyle,
"outline": blackOutline,
"textoffset": new Vector2(0.5, 0.875)
},
"front": { "text": "Sample text", "style": titleStyle },
"right": { "text": "Sample text", "style": titleStyle }
}
};
return new GridLegend(gridTextOpts);
}
function createPlot(divElement) {
const lookAt = new Vector3(10, 10, 10);
const position = new Vector3().copy(lookAt.clone()).sub(new Vector3(-20, 20, -5));
const perspectivePlot = new Plot({
"container": divElement,
"camera": {
"position": position,
"lookat": lookAt
}
});
perspectivePlot.getCompass().setCompassObject(new CompassAxis());
return perspectivePlot;
}
function createPointSet() {
const points = generatePoints();
return new PointSet({
"data": {
"x": points["x"],
"y": points["y"],
"z": points["z"],
"sizes": points["sizes"],
"values": points["values"]
},
"symbolminsize": 0.15,
"symbolmaxsize": 0.3,
"colorprovider": new DefaultColorProvider({
"values": [points["valmin"], 0.5 * points["valmin"] + points["valmax"], points["valmax"]],
"colors": ["white", "orange", "red"]
})
});
}
function generatePoints() {
const result = {
"x": [],
"y": [],
"z": [],
"sizes": [],
"values": [],
"valmin": Number.POSITIVE_INFINITY,
"valmax": Number.NEGATIVE_INFINITY
};
for (let y = 0; y < 20; y++) {
const yHeight = Math.cos(Math.PI * 2 * y / 20) + 5;
for (let x = 0; x < 20; x++) {
const xHeight = Math.sin(Math.PI * 2 * x / 20) - 4 + (x + y) / 3;
result["x"].push(x);
result["y"].push(y);
const z = xHeight + yHeight;
result["z"].push(z);
const size = z / 10;
result["sizes"].push(size);
const value = z * (MathUtil.getSeededRandom(0, 1, 1) + size / 10);
result["values"].push(value);
result["valmin"] = Math.min(value, result["valmin"]);
result["valmax"] = Math.max(value, result["valmax"]);
}
}
return result;
}
function setLegendOptions(legend, options) {
legend.setOptions({
"planes": {
"front": options,
"left": options,
"back": options,
"right": options
}
});
}
function toggleSizeInDeviceButtonUI(isEnabled) {
__legendDynamicOptions["sizeindevice"] = isEnabled;
setLegendOptions(__legendHandle, __legendDynamicOptions);
}
function updateTextScale(value) {
__legendDynamicOptions["textscale"] = value;
setLegendOptions(__legendHandle, __legendDynamicOptions);
}
function toggleNearSideButtonUI(isEnabled) {
__legendDynamicOptions["nearside"] = isEnabled;
setLegendOptions(__legendHandle, __legendDynamicOptions);
}
function toggleHideIfTooLargeButtonUI(isEnabled) {
__legendDynamicOptions["hideiftoolarge"] = isEnabled;
setLegendOptions(__legendHandle, __legendDynamicOptions);
}
export { createScene, toggleHideIfTooLargeButtonUI, toggleNearSideButtonUI, toggleSizeInDeviceButtonUI, updateTextScale };
createScene(document.querySelector('[ref="plot"]'));
# Add a legend on a Projection Widget
In this example you can see how to add the legend to a 3D Projection Widget.
With the interface below, you can dynamically change some of the legend options.
For more options, please refer to the GridLegend documentation.
import { DefaultColorProvider } from "@int/geotoolkit/util/DefaultColorProvider.ts";
import { Plot } from "@int/geotoolkit3d/Plot.ts";
import { Vector2, Vector3 } from "/node_modules/.vite/deps/three.js?v=2235af65";
import { GridLegend } from "@int/geotoolkit3d/scene/grid/legend/GridLegend.ts";
import { AlignmentStyle, TextStyle } from "@int/geotoolkit/attributes/TextStyle.ts";
import { ProjectionWidget } from "@int/geotoolkit3d/widgets/ProjectionWidget.ts";
import { Pipe } from "@int/geotoolkit3d/scene/well/Pipe.ts";
import { Wells } from "/src/code/Carnac3D/helpers/wells.ts";
const X_SCALE = 1;
const Y_SCALE = 1;
const Z_SCALE = 2;
const CAMERA_DISTANCE = -4500;
const DEFAULT_COLORPROVIDER = new DefaultColorProvider({
"values": [0, 1, 2],
"colors": ["green", "yellow", "red"]
});
const __legendDynamicOptions = {
"sizeindevice": true,
"nearside": false,
"hideiftoolarge": true,
"textscale": 1
};
let legend;
function createScene(divElement) {
const plot = createPlot(divElement);
const pipe = createPipe();
plot.getRoot().add(pipe);
const projectionWidget = new ProjectionWidget();
projectionWidget.addMesh(pipe);
plot.getRoot().add(projectionWidget);
legend = createLegend();
projectionWidget.addLegend(legend);
return plot;
}
function createLegend() {
const legendStyle = new TextStyle({
"font": "13px Arial",
"color": "white",
"alignment": AlignmentStyle.Left
});
const titleStyle = new TextStyle({
"font": "20px Arial",
"color": "white",
"alignment": AlignmentStyle.Center
}).setFontWeight("bold");
const blackOutline = {
"enable": true,
"innercolor": "white",
"outlinecolor": "black",
"thickness": 3
};
const gridTextOpts = {
"planes": {
"right": {
"text": "SAMPLE LEGEND\n\nItem 1 - Item description\nItem 2 - Item description\nItem 3 - Item description\nItem 4 - Item description\n",
"style": legendStyle,
"outline": blackOutline,
"textoffset": new Vector2(0.5, 0.66)
},
"back": {
"text": "SAMPLE TITLE",
"style": titleStyle,
"outline": blackOutline,
"textoffset": new Vector2(0.5, 0.875)
},
"front": { "text": "Sample text", "style": titleStyle, "outline": blackOutline },
"left": { "text": "Sample text", "style": titleStyle, "outline": blackOutline }
}
};
return new GridLegend(gridTextOpts);
}
function createPipe() {
const data = Wells.getWell_pipe();
const pipe = new Pipe({
data,
tubeprecision: 8,
colorprovider: DEFAULT_COLORPROVIDER
});
pipe.position.set(456396.784, 678286319e-2, 0);
return pipe;
}
function createPlot(divElement) {
const center = new Vector3(457101.805, 6782420821e-3, -1466.69);
return new Plot({
"container": divElement,
"camera": {
"position": center.clone().add(new Vector3(CAMERA_DISTANCE, CAMERA_DISTANCE, 1e3)),
"lookat": center.clone().add(new Vector3(0, 0, 180))
},
"scale": new Vector3(X_SCALE, Y_SCALE, Z_SCALE)
});
}
function setLegendOptions(legend2, options) {
legend2.setOptions({
"planes": {
"front": options,
"left": options,
"back": options,
"right": options
}
});
}
function toggleSizeInDeviceButtonUI(isEnabled) {
__legendDynamicOptions["sizeindevice"] = isEnabled;
setLegendOptions(legend, __legendDynamicOptions);
}
function updateTextScale(value) {
__legendDynamicOptions["textscale"] = value;
setLegendOptions(legend, __legendDynamicOptions);
}
function toggleNearSideButtonUI(isEnabled) {
__legendDynamicOptions["nearside"] = isEnabled;
setLegendOptions(legend, __legendDynamicOptions);
}
function toggleHideIfTooLargeButtonUI(isEnabled) {
__legendDynamicOptions["hideiftoolarge"] = isEnabled;
setLegendOptions(legend, __legendDynamicOptions);
}
export { createScene, toggleHideIfTooLargeButtonUI, toggleNearSideButtonUI, toggleSizeInDeviceButtonUI, updateTextScale };
createScene(document.querySelector('[ref="plot"]'));