Skip to content

Commit

Permalink
Merge pull request #68 from equinor/wellbore_details
Browse files Browse the repository at this point in the history
Added logic for displaying details along wellbores
  • Loading branch information
olems authored May 12, 2023
2 parents ddf80c1 + 3401cd1 commit 28e7e20
Show file tree
Hide file tree
Showing 13 changed files with 303 additions and 74 deletions.
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ dist
node_modules
package-lock.json
tsconfig.json
test
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@equinor/videx-map",
"version": "1.13.0",
"version": "1.14.0",
"description": "Component for Pixi-overlay in Leaflet.",
"main": "dist/index.js",
"module": "dist/index.esm.js",
Expand Down
51 changes: 42 additions & 9 deletions src/WellboreModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,14 @@ import Vector2 from '@equinor/videx-vector2';
import { ModuleInterface } from './ModuleInterface';
import { Config, InputConfig, getDefaultConfig } from './utils/wellbores/Config';
import { RootShader, WellboreShader } from './utils/wellbores/Shader';
import { SourceData, Group, GroupOptions, WellboreData, RootData } from './utils/wellbores/data';
import {
SourceData,
Group,
GroupOptions,
DetailOptions,
WellboreData,
RootData,
} from './utils/wellbores/data';
import LineDictionary from './utils/LineDictionary';
import PointDictionary from './utils/PointDictionary';
import Projector from './utils/wellbores/Projector';
Expand Down Expand Up @@ -100,10 +107,20 @@ export default class WellboreModule extends ModuleInterface {
}

registerGroup(key: string, options?: GroupOptions) : void {
if (this.groups[key]) throw Error(`Group [${key}] already registered!`);
if (this.groups[key]) throw Error(`Group already registered: ${key}!`);
this.groups[key] = new Group(key, options);
}

/**
* Registers a new detail on given group.
* @param key Detail key.
* @param groupKeys Target group keys.
* @param options
*/
registerDetail(key: string, groupKeys: string[], options: DetailOptions) : void {
this.forEachGroup(groupKeys, group => group.registerDetail(key, options));
}

private addRoot(position: Vector2) : RootData {
const overlapping = this.pointDict.getOverlapping(position);

Expand All @@ -119,8 +136,8 @@ export default class WellboreModule extends ModuleInterface {

/**
* Add a single wellbore
* @param key data group to add wellbore into
* @param data wellbore data
* @param data Wellbore data
* @param group Group to add wellbore into
*/
addWellbore(data: SourceData, group: Group = this.groups.default) : void {
if (data.path.length === 0) throw Error('Empty wellbore path!');
Expand All @@ -140,8 +157,8 @@ export default class WellboreModule extends ModuleInterface {
wellboreWidth: wellboreResize.max.scale,
tick,
});
if (wellbore.mesh) {
this.containers.wellbores.addChild(wellbore.mesh);
if (wellbore.container) {
this.containers.wellbores.addChild(wellbore.container);
}
this.containers.labels.addChild(wellbore.label.container);
group.append(wellbore);
Expand Down Expand Up @@ -186,6 +203,11 @@ export default class WellboreModule extends ModuleInterface {
});
}

private forAllGroups(func: (group: Group, key: string) => void) {
Object.keys(this.groups).forEach(key => func(this.groups[key], key));
this.requestRedraw();
}

private forEachGroup(keys: string[], func: (group: Group, key: string) => void): void {
const registeredKeys = Object.keys(this.groups);
const filteredKeys = (keys.length === 0) ? registeredKeys : keys.filter(key => registeredKeys.includes(key));
Expand Down Expand Up @@ -267,6 +289,15 @@ export default class WellboreModule extends ModuleInterface {
this.forEachGroup(keys, group => group.setWellboreVisibility(visible));
}

/**
* Enable/disable details
* @param visible
* @param key Key of detail to set visibility for
*/
setDetailVisibility(visible: boolean, key: string) {
this.forAllGroups(group => group.setDetailVisibility(key, visible));
}


/** "Soft" filtering function. Will turn wellbores that does not pass filter gray-ish. */
softFilter(filterFunction : (v: SourceData) => boolean, ...keys: string[]): void {
Expand Down Expand Up @@ -362,6 +393,7 @@ export default class WellboreModule extends ModuleInterface {

Object.values(this.groups).forEach(g => {
g.wellbores = [];
g.resetDetails();
});
this.roots = [];

Expand All @@ -379,7 +411,8 @@ export default class WellboreModule extends ModuleInterface {
clear(...keys: string[]) : void {
// clear all?
if (keys.length === 0) {
return this.clearAll();
this.clearAll();
return;
}
this.highlight.clear();

Expand All @@ -396,10 +429,11 @@ export default class WellboreModule extends ModuleInterface {
}

// remove PIXI elements
w.mesh?.destroy();
w.container?.destroy();
w.label?.container?.destroy();
});
group.wellbores = [];
group.resetDetails();
});

// update roots
Expand Down Expand Up @@ -509,6 +543,5 @@ export default class WellboreModule extends ModuleInterface {
this.pixiOverlay.redraw();
this._redrawAnimFrame = null;
});

}
}
67 changes: 22 additions & 45 deletions src/utils/LineInterpolator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,70 +2,45 @@
import Vector2 from '@equinor/videx-vector2';
import { mix } from '@equinor/videx-linear-algebra';

/**
* Path used by the interpolator.
*/
/** Path used by the interpolator. */
interface PathPoint {
/**
* Point along the line.
*/
/** Point along the line. */
point: Vector2;
/**
* Normalized direction towards next point.
*/

/** Normalized direction towards next point. */
direction: Vector2;
/**
* Distance to point along line.
*/

/** Distance to point along line. */
distance: number;
/**
* Relative distance to point along line.
*/

/** Relative distance to point along line. */
relative: number;
}

/**
* Point in returned segment.
*/
/** Point in returned segment. */
export interface SegmentPoint {
/**
* Point along line.
*/
/** Point along line. */
position: Vector2;
/**
* Normalized direction towards next point.
*/

/** Normalized direction towards next point. */
direction: Vector2;
/**
* Distance to point along line.
*/

/** Distance to point along line. */
distance: number;
}

/**
* Interpolator for finding points and subsegments on a line defined by a collection
* of Vector2 or 2D vectors.
*/
/** Interpolator for finding points and subsegments on a line defined by a collection of Vector2 or 2D vectors. */
export class LineInterpolator {

/**
* Amount of provided points.
*/
/** Amount of provided points. */
amount : number;

/**
* Length of line.
*/
/** Length of line. */
length : number;

/**
* True if line is an approximation of a single point.
*/
/** True if line is an approximation of a single point. */
singlePoint : boolean = true;

/**
* Collection of points along line with distances.
*/
/** Collection of points along line with distances. */
path: PathPoint[];

/**
Expand Down Expand Up @@ -106,7 +81,9 @@ export class LineInterpolator {
};

// Not a single point if outside radius
if(Vector2.distance(point, root) > radius) this.singlePoint = false;
if(Vector2.distance(point, root) > radius) {
this.singlePoint = false;
}
}

// Re-iterate over path to calculate relative distances
Expand Down
8 changes: 4 additions & 4 deletions src/utils/wellbores/Shader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ function toShader(n: number): string {
}

// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// WELLBORE SHADER
// #region WELLBORE SHADER

/** Uniforms used by the shader. */
export interface WellboreUniforms {
Expand Down Expand Up @@ -137,8 +137,6 @@ export class WellboreShader {
alpha = 0.03;
}
else discard;
col *= alpha;
gl_FragColor = vec4(col, alpha);
}
Expand All @@ -148,8 +146,9 @@ export class WellboreShader {
}
}

// #endregion
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
// CIRCLE SHADER / ROOT SHADER
// #region CIRCLE SHADER

export interface RootUniforms {
active: boolean;
Expand Down Expand Up @@ -231,4 +230,5 @@ export class RootShader {
}
}

// #endregion
// >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
46 changes: 46 additions & 0 deletions src/utils/wellbores/data/Group.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Colors, getDefaultColors, InputColors } from '../Colors';
import { WellboreData, FilterStatus } from './WellboreData';
import { RootData } from './RootData';
import { SourceData } from './SourceData';
import { Detail, DetailOptions, getDetail } from './details';

export interface GroupOptions {
order?: number;
Expand All @@ -23,6 +24,7 @@ export class Group {
order: number = 0;
mirrorLabels: boolean = false;
wellbores: WellboreData[] = [];
details: { [key: string]: Detail } = {};
active: boolean = true;
activeFilter: Filter = null;
/** Is active filter soft or hard (Ghost) */
Expand All @@ -49,13 +51,57 @@ export class Group {
}
}

registerDetail(key: string, detail: DetailOptions) {
if (key in this.details) {
throw Error(`Detail already registered, ${key}, for group: ${this.key}!`);
}
this.details[key] = getDetail(detail);
}

setDetailVisibility(key: string, visible: boolean) {
if (key in this.details) {
const detail = this.details[key];

// Always initialize a visible detail, if not already done
if (visible && !detail.initialized) {
this.wellbores.forEach(wellbore => {
wellbore.tryDrawDetail(key, detail);
});

detail.initialized = true;
}

// If duplicate
if (visible === detail.visible) return;

this.wellbores.forEach(wellbore => {
wellbore.setDetailsVisibility(key, visible);
});

detail.visible = visible;
}
}

resetDetails() {
Object.values(this.details).forEach(detail => {
detail.initialized = false;
});
}

append(wellbore: WellboreData) {
wellbore.zIndex = this.order * 10000 + this.wellbores.length;
if (this.activeFilter) {
const targetFilter = this.isHardFilter ? FilterStatus.hard : FilterStatus.soft;
wellbore.setFilter(this.activeFilter(wellbore.data) ? FilterStatus.none : targetFilter);
wellbore.root.recalculate(true);
}

// If appended wellbore belongs to an initialized detail
Object.entries(this.details).forEach(([key, detail]) => {
if (!detail.initialized) return;
wellbore.tryDrawDetail(key, detail);
});

this.wellbores.push(wellbore);
}

Expand Down
Loading

0 comments on commit 28e7e20

Please sign in to comment.