diff --git a/src/components/CameraTargetMarker/CameraTargetMarker.tsx b/src/components/CameraTargetMarker/CameraTargetMarker.tsx index 9ebb22f..612cfec 100644 --- a/src/components/CameraTargetMarker/CameraTargetMarker.tsx +++ b/src/components/CameraTargetMarker/CameraTargetMarker.tsx @@ -8,12 +8,19 @@ import { Color, Group, Vector3 } from 'three' * @expand */ export type CameraTargetMarkerProps = { + // radius in world units of the camera target marker radius?: number + // opacity of the rendered marker opacity?: number, + // color of the rendered marker color?: number | string | Color + // fix/lock the position of the camera target marker to a specific position along the x-axis. Can be useful if you add multiple camera targets fixedX?: number + // fix/lock the position of the camera target marker to a specific position along the y-axis. Can be useful if you add multiple camera targets fixedY?: number + // fix/lock the position of the camera target marker to a specific position along the z-axis. Can be useful if you add multiple camera targets fixedZ?: number + // render order renderOrder?: number } diff --git a/src/components/Distance/Distance.tsx b/src/components/Distance/Distance.tsx index 50734b9..75ab966 100644 --- a/src/components/Distance/Distance.tsx +++ b/src/components/Distance/Distance.tsx @@ -8,9 +8,13 @@ import { DistanceContext } from './DistanceContext' * @expand */ export type DistanceProps = { + // the minimal distance for which the child elements of this component is rendered min?: number, + // the maximum distance for which the child elements of this component is rendered max: number, + // if enabled, the child elements will only be loaded when within visible range, and will be unloaded/unmounted once it falls out of visible range onDemand?: boolean, + // the elements that should be rendered when in visible range (min, max) children: ReactNode } diff --git a/src/components/Grids/BoxGrid/BoxGrid.tsx b/src/components/Grids/BoxGrid/BoxGrid.tsx index 5298000..96abe64 100644 --- a/src/components/Grids/BoxGrid/BoxGrid.tsx +++ b/src/components/Grids/BoxGrid/BoxGrid.tsx @@ -12,28 +12,51 @@ const pos = new Vector3() * @expand */ export type BoxGridProps = CommonComponentProps & { + // size of the grid box in world units size?: Vec3, + // the size of a grid cell in world units cellSize?: number, + // number of sub divisions of a grid cell subDivisions?: number, + // scale determining axes values and direction along each axis gridScale?: Vec3, + // world coordinates of the grid origin (origo) gridOrigin?: Vec3, + // the axes values at the specified origin (default 0,0,0) originValue?: Vec3, + // line width as a factor of the cell size gridLineWidth?: number, + // background color of the grid planes background?: string | Color | number, + // opacity of the grid planes background color backgroundOpacity?: number, + // opacity of the grid planes (including grid lines) opacity?: number, + // the color of the major grid lines gridColorMajor?: string | number | Color, + // the color of the minor/sub division grid lines gridColorMinor?: string | number | Color, + // axes color axesColor?: string | number | Color, + // axes line width as a factor of cell size axesLineWidth?: number, + // the axes tick size as a factor of cell size axesTickSize?: number, + // if enabled, project a shade of the objects within the grid planes, using an orthographic camera enableProjection?: boolean, + // the color of the projected shade when projection is enabled projectionColor?: string | number | Color, + // the quality/size of the projection texture used when projection is enabled projectionResolution?: number, + // the update frequency of the projected texture when projection is enabled (ms) projectionRefreshRate?: number, + // show rulers on the grid planes at the intersection point of the pointer showRulers?: boolean, + // enable automatic sizing and positioning of the box grid according to its child elements autoSize?: boolean, + // padding when autosize is enabled autoSizePadding?: number | Vec3 | BoxPadding, + // update frequency in ms when autosize is enabled autoSizeUpdateRate?: number, } diff --git a/src/components/Grids/Grid/Grid.tsx b/src/components/Grids/Grid/Grid.tsx index ea5a8fe..c39f71d 100644 --- a/src/components/Grids/Grid/Grid.tsx +++ b/src/components/Grids/Grid/Grid.tsx @@ -31,43 +31,81 @@ import vertexShader from './shaders/vertex.glsl' * @expand */ export type GridProps = CommonComponentProps & { + // which 2D plane to use for the grid (xz, xy or zy) plane: 'xz' | 'xy' | 'zy', + // size of the grid plane in world units size: Vec2, + // the size of a grid cell in world units cellSize?: number, + // number of sub divisions of a grid cell subDivisions?: number, + // world coordinates of the grid origin (origo) gridOrigin?: Vec2, + // scale determining axes values and direction along each axis gridScale?: Vec2, + // background color of the grid plane background?: string | Color | number, + // opacity of the grid plane background color backgroundOpacity?: number, + // opacity of the grid plane (including grid lines) opacity?: number, + // the color of the major grid lines gridColorMajor?: string | number | Color, + // the color of the minor/sub division grid lines gridColorMinor?: string | number | Color, + // line width as a factor of the cell size gridLineWidth?: number, + // show/hide axes including labels showAxes?: boolean, + // show/hide axes labels if showAxes is true showAxesLabels?: boolean, + // omit the first and last axis label if enabled trimAxesLabels?: boolean, + // the relative offset of the axes in local coordinates axesOffset?: Vec2, + // axes color axesColor?: string | number | Color, + // axes line width as a factor of cell size axesLineWidth?: number, + // the axes tick size as a factor of cell size axesTickSize?: number, + // the axes values at the specified origin (default 0,0) originValue?: Vec2, + // shows a radial grid if set to true radial?: boolean, + // progressively adds new segments as distance from the center increases when using radial grid dynamicSegments?: boolean, + // show rulers on the grid plane at the intersection point of the pointer showRulers?: boolean, + // the color of the rulers rulerColor?: string | number | Color, + // the ruler line width as a factor of the cell size rulerLineWidth?: number, + // the ruler opacity rulerOpacity?: number, + // offset along the axis perpendicular to the plane planeOffset?: number, + // dynamically change cell size depending on camera distance (if set to true) dynamicCellSize?: boolean, + // control thresholds and extremes when dynamic cell size is enabled cellSizeDistanceFactors?: number[][], + // side to render side?: 'front' | 'back' | 'both', + // allow a texture to be added to the grid plane texture?: Texture, + // mixing factor for blending texture (if present) with the grid plane (0..1) textureMix?: number, + // if enabled, project a shade of the objects within range onto the grid plane, using an orthographic camera enableProjection?: boolean, + // determines the range used for projecting objects onto the plane when enableProjection is set to true projectionDistance?: number, + // the color of the projected shade when projection is enabled projectionColor?: string | number | Color, + // the quality/size of the projection texture used when projection is enabled projectionResolution?: number, + // the update frequency of the projected texture when projection is enabled (ms) projectionRefreshRate?: number, + // callback function for retrieving the grid coordinates when grid rulers are enabled onRulerUpdate?: ((coords: Vec2 | null) => void) | null, } diff --git a/src/components/Grids/Grid/UtmGrid.tsx b/src/components/Grids/Grid/UtmGrid.tsx index 6c81762..de2787e 100644 --- a/src/components/Grids/Grid/UtmGrid.tsx +++ b/src/components/Grids/Grid/UtmGrid.tsx @@ -1,7 +1,7 @@ import { useContext, useEffect, useState } from 'react' -import { Grid, GridProps } from './Grid' import { Vec2 } from '../../../sdk/types/common' import { UtmAreaContext } from '../../UtmArea/UtmAreaContext' +import { Grid, GridProps } from './Grid' type GridConfig = { origin: Vec2, @@ -14,6 +14,7 @@ type GridConfig = { * @expand */ export type UtmGridProps = GridProps & { + // use relative values for axes labels instead of absolute values if enabled relativeValues?: boolean } diff --git a/src/components/common.ts b/src/components/common.ts index ae84953..6dfc574 100644 --- a/src/components/common.ts +++ b/src/components/common.ts @@ -7,13 +7,21 @@ import { Vec3 } from '../sdk' * Common props for 3d components */ export type CommonComponentProps = { + // will be added to the name property of the THREE.js Object3D instance name?: string + // set the visible flag on the THREE.js Object3D instance visible?: boolean + // set the userData object on the THREE.js Object3D instance userData?: Record + // set the position in parent's local coordinates position?: Vec3 + // set the castShadow property on the THREE.js Object3D instance. castShadow?: boolean + // set the receiveShadow property on the THREE.js Object3D instance. receiveShadow?: boolean + // set the renderOrder property on the THREE.js Object3D instance. renderOrder?: number + // set the layers property on the THREE.js Object3D instance. layers?: Layers } @@ -21,8 +29,12 @@ export type CommonComponentProps = { * Common props for 3d components that allow overriding shader materials */ export type CustomMaterialProps = { + // custom material or array of materials for overriding default component material(s) customMaterial?: Material | Material[] + // set a custom depth material if required customDepthMaterial?: Material + // set a custom distance material if required customDistanceMaterial?: Material + // callback to invoke when component is updated. Use this for setting/uppdaing uniforms in your custom material(s) onMaterialPropertiesChange?: (props: Record, material: Material | Material[]) => void } diff --git a/src/layers/layers.ts b/src/layers/layers.ts index 1fed6e4..c46d60f 100644 --- a/src/layers/layers.ts +++ b/src/layers/layers.ts @@ -1,9 +1,9 @@ import { Layers } from 'three' export const LAYERS = { - NOT_EMITTER: 29, - EMITTER: 30, - OCCLUDER: 31, + NOT_EMITTER: 29, // can be used to exclude an object from being used as an event emitter + EMITTER: 30, // used internally to flag an object as an event emitter + OCCLUDER: 31, // object will be considered in occlusion checks in the annotations system } export function createLayers(...values: number[]) { diff --git a/src/sdk/geometries/curve/curve-3d.ts b/src/sdk/geometries/curve/curve-3d.ts index 05af978..7393e14 100644 --- a/src/sdk/geometries/curve/curve-3d.ts +++ b/src/sdk/geometries/curve/curve-3d.ts @@ -7,20 +7,28 @@ import { copyVec3, crossVec3, dotVec3, lengthVec3, normalizeVec3, rotateVec3 } f * Interface for interpolating points on a 3d curve */ export interface Curve3D { + // get a point at the normalized position (time) along the full curve (0 = start, 1 = end) getPointAt: (pos: number) => Vec3 + // get a number of samples along the curve, optionally specifying a start and end position getPoints: (nSamples: number, from?: number, to?: number) => Vec3[] + // get the tangent at the normalized position (time) along the full curve (0 = start, 1 = end) getTangentAt: (pos: number) => Vec3 + // get a normal at the normalized position (time) along the full curve (0 = start, 1 = end) getNormalAt: (pos: number) => Vec3 + // get the bounding box of the full curve or optinally the segment between a from and/or to position getBoundingBox: (from?: number, to?: number) => { min: Vec3, max: Vec3, } + // get the position, point and distance to this point from an abritary point nearest: (point: Vec3) => { position: number, point: Vec3, distance: number, } + // the calculated length of the curve length: number, + // when enabled, the curve will be closed having it's end point and start point joined closed: boolean, } diff --git a/src/sdk/geometries/curve/tube-geometry.ts b/src/sdk/geometries/curve/tube-geometry.ts index 3a0a803..d390869 100644 --- a/src/sdk/geometries/curve/tube-geometry.ts +++ b/src/sdk/geometries/curve/tube-geometry.ts @@ -441,6 +441,9 @@ function generateTube(segments: TubeSegment[], radialSegments: number, closed: b return { vertices, indices, normals, uvs, vertexCount, indexCount } } +/** + * Generates a fully customized tube geometry extruded from a curve. + */ export function createTubeGeometry(curve: Curve3D, options: TubeGeometryOptions = {}) { const from = clamp(options.from || 0, 0, 1) const to = clamp(options.to || 1) diff --git a/src/sdk/geometries/triangulate-grid-delaunay.ts b/src/sdk/geometries/triangulate-grid-delaunay.ts index 4699a9a..b04e5da 100644 --- a/src/sdk/geometries/triangulate-grid-delaunay.ts +++ b/src/sdk/geometries/triangulate-grid-delaunay.ts @@ -1,6 +1,8 @@ import { Delatin } from './delatin' - +/** + * Triangulate an elevation grid using Delaunay triangulation + */ export function triangulateGridDelaunay(grid: Float32Array, columns: number, scaleX = 1, scaleY = 1, nullValue: number = -1, maxError: number = 5) { const width = columns const height = grid.length / width diff --git a/src/sdk/projection/crs.ts b/src/sdk/projection/crs.ts index 6c74b7a..3c618bb 100644 --- a/src/sdk/projection/crs.ts +++ b/src/sdk/projection/crs.ts @@ -2,6 +2,10 @@ import proj4, { Converter } from "proj4" export const wgs84Def = '+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs' +/** + * Maps between real world UTM coordinates and 3d world coordinates by assigning a known real world + * position to the center of the 3d world and specifying an UTM zone. + */ export class CRS { utmDef: string originWgs84: [number, number] diff --git a/src/sdk/utils/depth-buffer.ts b/src/sdk/utils/depth-buffer.ts index 8be28ba..7d9150c 100644 --- a/src/sdk/utils/depth-buffer.ts +++ b/src/sdk/utils/depth-buffer.ts @@ -32,6 +32,10 @@ let renderTarget: WebGLRenderTarget | null = null let pixelBuffer: Uint8Array | null = null let ndcZs: Float32Array | null = null +/** + * Generate a depth buffer and read-back values as normalized device coordinates (ndc) + * for objects assigned to the occluder layer + */ export async function getDepthBuffer( renderer: WebGLRenderer, scene: Scene, diff --git a/src/sdk/utils/depth-reader.ts b/src/sdk/utils/depth-reader.ts index 55ac576..d42c451 100644 --- a/src/sdk/utils/depth-reader.ts +++ b/src/sdk/utils/depth-reader.ts @@ -42,6 +42,9 @@ let pixelBuffer: Uint8Array | null = null postScene.add(postQuad); +/** + * Read-back the normalized device coordinates from a depth texture + */ export async function readDepth(depthTexture: Texture, renderer: WebGLRenderer, camera: PerspectiveCamera, idx?: number) { if (!depthTexture) return null; diff --git a/src/sdk/utils/elevation-map.ts b/src/sdk/utils/elevation-map.ts index e33b9ff..4659530 100644 --- a/src/sdk/utils/elevation-map.ts +++ b/src/sdk/utils/elevation-map.ts @@ -14,6 +14,10 @@ export function triangleNormal(p0: Vec3, p1: Vec3, p2: Vec3) { return normalizeVec3(crossVec3(a, b)) } +/** + * Encode elevation data to RGBA image values so it can be used as a data texture. Depth + * values are required by the surface material to map to color ramps and also for contours. + */ export function elevationMapToRGBA( data: Float32Array, nullValue: number = -1, @@ -32,6 +36,9 @@ export function elevationMapToRGBA( return buffer } +/** + * Calcukate and encode surface normals from an elevation grid as RGBA image values. + */ export function elevationMapNormalsToRGBA( data: Float32Array, columns: number, @@ -100,6 +107,9 @@ export function elevationMapNormalsToRGBA( return buffer } +/** + * Create a data texture from RGBA encoded normals + */ export function createNormalTexture( buffer: Uint8Array, width: number, @@ -117,6 +127,9 @@ export function createNormalTexture( return normalTexture } +/** + * Create a data texture from RGBA encoded depth values + */ export function createElevationTexture( buffer: Uint8Array, width: number, diff --git a/src/sdk/utils/irapbin-parser.ts b/src/sdk/utils/irapbin-parser.ts index f841490..4e4c935 100644 --- a/src/sdk/utils/irapbin-parser.ts +++ b/src/sdk/utils/irapbin-parser.ts @@ -1,3 +1,6 @@ +/** + * Parses irabin surface/horizon binary files and return the header information and elevation data + */ export async function parseIrapbin(blob: Blob, nullValue = -1, refDepth: number | null = null) { const buffer = await blob.arrayBuffer() const view = new DataView(buffer) diff --git a/src/sdk/utils/trajectory.ts b/src/sdk/utils/trajectory.ts index 80593e2..5eca45f 100644 --- a/src/sdk/utils/trajectory.ts +++ b/src/sdk/utils/trajectory.ts @@ -1,18 +1,44 @@ -import { PositionLog } from "../data/types/PositionLog"; +import { PositionLog } from "../data/types/PositionLog" +import { Curve3D, getSplineCurve } from '../geometries/curve/curve-3d' import { Vec3 } from '../types/common' -import { getSplineCurve } from '../geometries/curve/curve-3d' import { clamp } from './numbers' -import { Curve3D } from '../geometries/curve/curve-3d' +/** + * Interface for defining a trajectory. This can be used to work with wellbore trajectories, + * where the measured top, termination point and length are known. The measured length should + * be used when calculating positions of data given in MD, so that the position on the curve is + * given by: + * + * @example + * const pos = (md - trajectory.measuredTop) / trajectory.measuredLength + * + * @remarks + * Avoid using the calculated length of the curve for this purpose, as this may potentially be less precise/consistant. + * The `getPointAtDepth` function in this interface is calculated as in the above example when created using the `getTrajectory` function. + * + * @see {@link getTrajectory} + * @see {@link Curve3D} + */ export interface Trajectory { + // a unique id, typically wellbore id id: string | number + // the known measured length of the trajectory measuredLength: number + // the known measured depth (msl) at the top of the trajectory measuredTop: number + // the known measured depth (msl) at the termination point of the trajectory measuredBottom: number + // curve defining the trajectory for interpolation purposes curve: Curve3D + // get the point along the trajectory according to a MD msl value. Returns null if out of range. getPointAtDepth: (md: number, clamped?: boolean) => Vec3 | null } +/** + * Creates an instance conforming to the `Trajectory` interface, given an id and a position log normalized to MSL depths. + * + * @see {@link Trajectory} + */ export function getTrajectory(id: string, poslogMsl: PositionLog | null) : Trajectory | null { if (!poslogMsl || poslogMsl.length < 2 * 4) return null; const [origEast, , origNorth] = poslogMsl; diff --git a/src/sdk/utils/trigonometry.ts b/src/sdk/utils/trigonometry.ts index 314ed5a..cbbfc33 100644 --- a/src/sdk/utils/trigonometry.ts +++ b/src/sdk/utils/trigonometry.ts @@ -6,6 +6,11 @@ export const PI2 = Math.PI / 2 // half PI export const PI4 = Math.PI / 4 // quarter PI export const PI8 = Math.PI / 8 // eight PI +/** + * Given a 2D rectangle and an angle off the center, find the point + * of the closest corner. Used for anchoring connector lines + * to annotation labels. + */ export function edgeOfRectangle(rect: Vec2, theta: number) : Vec2{ while (theta < -Math.PI) { theta += TAU;