@equinor/esv-intersection 4.0.0 → 4.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/axis.d.ts.map +1 -1
- package/dist/control/ExtendedCurveInterpolator.d.ts.map +1 -1
- package/dist/control/IntersectionReferenceSystem.d.ts.map +1 -1
- package/dist/control/LayerManager.d.ts.map +1 -1
- package/dist/control/MainController.d.ts.map +1 -1
- package/dist/control/ZoomPanHandler.d.ts.map +1 -1
- package/dist/control/overlay.d.ts.map +1 -1
- package/dist/datautils/colortable.d.ts.map +1 -1
- package/dist/datautils/findsample.d.ts.map +1 -1
- package/dist/datautils/picks.d.ts.map +1 -1
- package/dist/datautils/schematicShapeGenerator.d.ts +5 -5
- package/dist/datautils/schematicShapeGenerator.d.ts.map +1 -1
- package/dist/datautils/seismicimage.d.ts.map +1 -1
- package/dist/datautils/surfacedata.d.ts.map +1 -1
- package/dist/datautils/trajectory.d.ts.map +1 -1
- package/dist/index.cjs +1 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +2168 -1290
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +1 -14
- package/dist/index.umd.js.map +1 -1
- package/dist/layers/CalloutCanvasLayer.d.ts.map +1 -1
- package/dist/layers/CustomDisplayObjects/ComplexRope.d.ts.map +1 -1
- package/dist/layers/CustomDisplayObjects/UniformTextureStretchRope.d.ts.map +1 -1
- package/dist/layers/GeomodelCanvasLayer.d.ts.map +1 -1
- package/dist/layers/GeomodelLabelsLayer.d.ts.map +1 -1
- package/dist/layers/GeomodelLayerV2.d.ts.map +1 -1
- package/dist/layers/GridLayer.d.ts.map +1 -1
- package/dist/layers/ImageCanvasLayer.d.ts.map +1 -1
- package/dist/layers/ReferenceLineLayer.d.ts.map +1 -1
- package/dist/layers/SchematicLayer.d.ts.map +1 -1
- package/dist/layers/WellborePathLayer.d.ts.map +1 -1
- package/dist/layers/base/CanvasLayer.d.ts.map +1 -1
- package/dist/layers/base/HTMLLayer.d.ts.map +1 -1
- package/dist/layers/base/Layer.d.ts.map +1 -1
- package/dist/layers/base/PixiLayer.d.ts.map +1 -1
- package/dist/layers/base/SVGLayer.d.ts.map +1 -1
- package/dist/layers/schematicInterfaces.d.ts.map +1 -1
- package/dist/utils/arc-length.d.ts.map +1 -1
- package/dist/utils/root-finder.d.ts.map +1 -1
- package/dist/utils/text.d.ts.map +1 -1
- package/dist/utils/vectorUtils.d.ts.map +1 -1
- package/dist/vendor/pixi-dashed-line/index.d.ts.map +1 -1
- package/package.json +15 -17
- package/src/components/axis.ts +40 -10
- package/src/control/ExtendedCurveInterpolator.ts +47 -9
- package/src/control/IntersectionReferenceSystem.ts +110 -30
- package/src/control/LayerManager.ts +76 -24
- package/src/control/MainController.ts +37 -8
- package/src/control/ZoomPanHandler.ts +76 -14
- package/src/control/overlay.ts +18 -6
- package/src/datautils/colortable.ts +7 -2
- package/src/datautils/findsample.ts +12 -2
- package/src/datautils/picks.ts +66 -18
- package/src/datautils/schematicShapeGenerator.ts +570 -146
- package/src/datautils/seismicimage.ts +36 -10
- package/src/datautils/surfacedata.ts +119 -40
- package/src/datautils/trajectory.ts +56 -17
- package/src/layers/CalloutCanvasLayer.ts +129 -26
- package/src/layers/CustomDisplayObjects/ComplexRope.ts +2 -1
- package/src/layers/CustomDisplayObjects/ComplexRopeGeometry.ts +5 -5
- package/src/layers/CustomDisplayObjects/UniformTextureStretchRope.ts +6 -2
- package/src/layers/GeomodelCanvasLayer.ts +10 -3
- package/src/layers/GeomodelLabelsLayer.ts +212 -87
- package/src/layers/GeomodelLayerV2.ts +8 -3
- package/src/layers/GridLayer.ts +14 -3
- package/src/layers/ImageCanvasLayer.ts +17 -3
- package/src/layers/ReferenceLineLayer.ts +31 -9
- package/src/layers/SchematicLayer.ts +499 -150
- package/src/layers/WellborePathLayer.ts +22 -7
- package/src/layers/base/CanvasLayer.ts +18 -4
- package/src/layers/base/HTMLLayer.ts +11 -3
- package/src/layers/base/Layer.ts +10 -2
- package/src/layers/base/PixiLayer.ts +27 -7
- package/src/layers/base/SVGLayer.ts +13 -3
- package/src/layers/schematicInterfaces.ts +16 -6
- package/src/utils/arc-length.ts +31 -5
- package/src/utils/root-finder.ts +32 -4
- package/src/utils/text.ts +34 -7
- package/src/utils/vectorUtils.ts +23 -6
- package/src/vendor/pixi-dashed-line/index.ts +66 -13
|
@@ -21,14 +21,18 @@ const CURVE_CATMULL_ROM_ALPHA = 0.7;
|
|
|
21
21
|
const CURVE_CARDINAL_TENSION = 0.9;
|
|
22
22
|
const CURVE_BUNDLE_BETA = 1.0;
|
|
23
23
|
|
|
24
|
-
export interface WellborepathLayerOptions<
|
|
24
|
+
export interface WellborepathLayerOptions<
|
|
25
|
+
T extends [number, number][],
|
|
26
|
+
> extends LayerOptions<T> {
|
|
25
27
|
stroke: string;
|
|
26
28
|
strokeWidth: string;
|
|
27
29
|
curveType?: string;
|
|
28
30
|
tension?: number;
|
|
29
31
|
}
|
|
30
32
|
|
|
31
|
-
export class WellborepathLayer<
|
|
33
|
+
export class WellborepathLayer<
|
|
34
|
+
T extends [number, number][],
|
|
35
|
+
> extends SVGLayer<T> {
|
|
32
36
|
rescaleEvent: OnRescaleEvent | undefined;
|
|
33
37
|
|
|
34
38
|
constructor(id?: string, options?: WellborepathLayerOptions<T>) {
|
|
@@ -62,7 +66,10 @@ export class WellborepathLayer<T extends [number, number][]> extends SVGLayer<T>
|
|
|
62
66
|
}
|
|
63
67
|
this.elm.select('g').remove();
|
|
64
68
|
|
|
65
|
-
const data =
|
|
69
|
+
const data =
|
|
70
|
+
this.data ||
|
|
71
|
+
(this.referenceSystem &&
|
|
72
|
+
(this.referenceSystem.projectedPath as [number, number][]));
|
|
66
73
|
if (!data || !this.rescaleEvent) {
|
|
67
74
|
return;
|
|
68
75
|
}
|
|
@@ -80,15 +87,21 @@ export class WellborepathLayer<T extends [number, number][]> extends SVGLayer<T>
|
|
|
80
87
|
private renderWellborePath(data: [number, number][]): string {
|
|
81
88
|
if (this.rescaleEvent != null) {
|
|
82
89
|
const { xScale, yScale } = this.rescaleEvent;
|
|
83
|
-
const transformedData: [number, number][] = data.map(
|
|
90
|
+
const transformedData: [number, number][] = data.map(d => [
|
|
91
|
+
xScale(d[0]),
|
|
92
|
+
yScale(d[1]),
|
|
93
|
+
]);
|
|
84
94
|
|
|
85
95
|
// TODO: Might be a good idea to move something like this to a shared function in a base class
|
|
86
96
|
let curveFactory;
|
|
87
|
-
const { curveType, tension } = this
|
|
97
|
+
const { curveType, tension } = this
|
|
98
|
+
.options as WellborepathLayerOptions<T>;
|
|
88
99
|
switch (curveType) {
|
|
89
100
|
default:
|
|
90
101
|
case 'curveCatmullRom':
|
|
91
|
-
curveFactory = curveCatmullRom.alpha(
|
|
102
|
+
curveFactory = curveCatmullRom.alpha(
|
|
103
|
+
tension || CURVE_CATMULL_ROM_ALPHA,
|
|
104
|
+
);
|
|
92
105
|
break;
|
|
93
106
|
case 'curveLinear':
|
|
94
107
|
curveFactory = curveLinear;
|
|
@@ -103,7 +116,9 @@ export class WellborepathLayer<T extends [number, number][]> extends SVGLayer<T>
|
|
|
103
116
|
curveFactory = curveBundle.beta(tension || CURVE_BUNDLE_BETA);
|
|
104
117
|
break;
|
|
105
118
|
case 'curveCardinal':
|
|
106
|
-
curveFactory = curveCardinal.tension(
|
|
119
|
+
curveFactory = curveCardinal.tension(
|
|
120
|
+
tension || CURVE_CARDINAL_TENSION,
|
|
121
|
+
);
|
|
107
122
|
break;
|
|
108
123
|
case 'curveMonotoneX':
|
|
109
124
|
curveFactory = curveMonotoneX;
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { Layer } from './Layer';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
OnMountEvent,
|
|
4
|
+
OnUpdateEvent,
|
|
5
|
+
OnResizeEvent,
|
|
6
|
+
OnRescaleEvent,
|
|
7
|
+
} from '../../interfaces';
|
|
3
8
|
import { DEFAULT_LAYER_HEIGHT, DEFAULT_LAYER_WIDTH } from '../../constants';
|
|
4
9
|
|
|
5
10
|
export abstract class CanvasLayer<T> extends Layer<T> {
|
|
@@ -45,8 +50,14 @@ export abstract class CanvasLayer<T> extends Layer<T> {
|
|
|
45
50
|
override onMount(event: OnMountEvent): void {
|
|
46
51
|
super.onMount(event);
|
|
47
52
|
const { elm } = event;
|
|
48
|
-
const width =
|
|
49
|
-
|
|
53
|
+
const width =
|
|
54
|
+
event.width ||
|
|
55
|
+
parseInt(elm?.getAttribute('width') ?? '', 10) ||
|
|
56
|
+
DEFAULT_LAYER_WIDTH;
|
|
57
|
+
const height =
|
|
58
|
+
event.height ||
|
|
59
|
+
parseInt(elm?.getAttribute('height') ?? '', 10) ||
|
|
60
|
+
DEFAULT_LAYER_HEIGHT;
|
|
50
61
|
this.elm = elm;
|
|
51
62
|
let canvas: HTMLCanvasElement;
|
|
52
63
|
if (!this.canvas) {
|
|
@@ -89,7 +100,10 @@ export abstract class CanvasLayer<T> extends Layer<T> {
|
|
|
89
100
|
const flippedX = event.xBounds[0] > event.xBounds[1];
|
|
90
101
|
const flippedY = event.yBounds[0] > event.yBounds[1];
|
|
91
102
|
this.ctx?.translate(event.xScale(0), event.yScale(0));
|
|
92
|
-
this.ctx?.scale(
|
|
103
|
+
this.ctx?.scale(
|
|
104
|
+
event.xRatio * (flippedX ? -1 : 1),
|
|
105
|
+
event.yRatio * (flippedY ? -1 : 1),
|
|
106
|
+
);
|
|
93
107
|
}
|
|
94
108
|
|
|
95
109
|
clearCanvas(): void {
|
|
@@ -9,8 +9,14 @@ export abstract class HTMLLayer<T> extends Layer<T> {
|
|
|
9
9
|
override onMount(event: OnMountEvent): void {
|
|
10
10
|
super.onMount(event);
|
|
11
11
|
const { elm } = event;
|
|
12
|
-
const width =
|
|
13
|
-
|
|
12
|
+
const width =
|
|
13
|
+
event.width ||
|
|
14
|
+
parseInt(elm?.getAttribute('width') ?? '', 10) ||
|
|
15
|
+
DEFAULT_LAYER_WIDTH;
|
|
16
|
+
const height =
|
|
17
|
+
event.height ||
|
|
18
|
+
parseInt(elm?.getAttribute('height') ?? '', 10) ||
|
|
19
|
+
DEFAULT_LAYER_HEIGHT;
|
|
14
20
|
|
|
15
21
|
if (!this.elm) {
|
|
16
22
|
this.elm = select(elm).append('div');
|
|
@@ -39,7 +45,9 @@ export abstract class HTMLLayer<T> extends Layer<T> {
|
|
|
39
45
|
return;
|
|
40
46
|
}
|
|
41
47
|
super.onResize(event);
|
|
42
|
-
this.elm
|
|
48
|
+
this.elm
|
|
49
|
+
.style('height', `${event.height}px`)
|
|
50
|
+
.style('width', `${event.width}px`);
|
|
43
51
|
}
|
|
44
52
|
|
|
45
53
|
override setVisibility(visible: boolean): void {
|
package/src/layers/base/Layer.ts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
OnMountEvent,
|
|
3
|
+
OnUnmountEvent,
|
|
4
|
+
OnUpdateEvent,
|
|
5
|
+
OnRescaleEvent,
|
|
6
|
+
OnResizeEvent,
|
|
7
|
+
} from '../../interfaces';
|
|
2
8
|
import { IntersectionReferenceSystem } from '../../control';
|
|
3
9
|
|
|
4
10
|
const defaultOptions = {
|
|
@@ -116,7 +122,9 @@ export abstract class Layer<T> {
|
|
|
116
122
|
return this._referenceSystem;
|
|
117
123
|
}
|
|
118
124
|
|
|
119
|
-
set referenceSystem(
|
|
125
|
+
set referenceSystem(
|
|
126
|
+
referenceSystem: IntersectionReferenceSystem | undefined,
|
|
127
|
+
) {
|
|
120
128
|
this._referenceSystem = referenceSystem;
|
|
121
129
|
}
|
|
122
130
|
|
|
@@ -1,6 +1,18 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
autoDetectRenderer,
|
|
3
|
+
AutoDetectOptions,
|
|
4
|
+
Container,
|
|
5
|
+
ContainerChild,
|
|
6
|
+
Renderer,
|
|
7
|
+
RendererType,
|
|
8
|
+
} from 'pixi.js';
|
|
2
9
|
import { Layer, LayerOptions } from './Layer';
|
|
3
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
OnMountEvent,
|
|
12
|
+
OnRescaleEvent,
|
|
13
|
+
OnResizeEvent,
|
|
14
|
+
OnUnmountEvent,
|
|
15
|
+
} from '../../interfaces';
|
|
4
16
|
import { DEFAULT_LAYER_HEIGHT, DEFAULT_LAYER_WIDTH } from '../../constants';
|
|
5
17
|
|
|
6
18
|
// PixiRenderApplication has many similarities with PIXI.Application,
|
|
@@ -44,7 +56,11 @@ export abstract class PixiLayer<T> extends Layer<T> {
|
|
|
44
56
|
private ctx: PixiRenderApplication;
|
|
45
57
|
private container: Container;
|
|
46
58
|
|
|
47
|
-
constructor(
|
|
59
|
+
constructor(
|
|
60
|
+
ctx: PixiRenderApplication,
|
|
61
|
+
id?: string,
|
|
62
|
+
options?: LayerOptions<T>,
|
|
63
|
+
) {
|
|
48
64
|
super(id, options);
|
|
49
65
|
|
|
50
66
|
this.ctx = ctx;
|
|
@@ -62,7 +78,7 @@ export abstract class PixiLayer<T> extends Layer<T> {
|
|
|
62
78
|
|
|
63
79
|
clearLayer() {
|
|
64
80
|
const children = this.container.removeChildren();
|
|
65
|
-
children.forEach(
|
|
81
|
+
children.forEach(child => {
|
|
66
82
|
child.destroy();
|
|
67
83
|
});
|
|
68
84
|
}
|
|
@@ -70,7 +86,8 @@ export abstract class PixiLayer<T> extends Layer<T> {
|
|
|
70
86
|
override onMount(event: OnMountEvent) {
|
|
71
87
|
super.onMount(event);
|
|
72
88
|
|
|
73
|
-
this.pixiViewContainer =
|
|
89
|
+
this.pixiViewContainer =
|
|
90
|
+
this.element?.querySelector('#webgl-layer') ?? undefined;
|
|
74
91
|
|
|
75
92
|
if (!this.pixiViewContainer) {
|
|
76
93
|
this.pixiViewContainer = document.createElement('div');
|
|
@@ -108,7 +125,10 @@ export abstract class PixiLayer<T> extends Layer<T> {
|
|
|
108
125
|
const flippedX = event.xBounds[0] > event.xBounds[1];
|
|
109
126
|
const flippedY = event.yBounds[0] > event.yBounds[1];
|
|
110
127
|
this.setContainerPosition(event.xScale(0), event.yScale(0));
|
|
111
|
-
this.setContainerScale(
|
|
128
|
+
this.setContainerScale(
|
|
129
|
+
event.xRatio * (flippedX ? -1 : 1),
|
|
130
|
+
event.yRatio * (flippedY ? -1 : 1),
|
|
131
|
+
);
|
|
112
132
|
}
|
|
113
133
|
|
|
114
134
|
protected setContainerPosition(x?: number, y?: number) {
|
|
@@ -130,7 +150,7 @@ export abstract class PixiLayer<T> extends Layer<T> {
|
|
|
130
150
|
['z-index', `${this.order}`],
|
|
131
151
|
['opacity', `${this.opacity}`],
|
|
132
152
|
]
|
|
133
|
-
.map(
|
|
153
|
+
.map(pair => pair.join(':'))
|
|
134
154
|
.join(';');
|
|
135
155
|
|
|
136
156
|
this.pixiViewContainer?.setAttribute('style', styles);
|
|
@@ -9,8 +9,14 @@ export abstract class SVGLayer<T> extends Layer<T> {
|
|
|
9
9
|
override onMount(event: OnMountEvent): void {
|
|
10
10
|
super.onMount(event);
|
|
11
11
|
const { elm } = event;
|
|
12
|
-
const width =
|
|
13
|
-
|
|
12
|
+
const width =
|
|
13
|
+
event.width ||
|
|
14
|
+
parseInt(elm.getAttribute('width') ?? '', 10) ||
|
|
15
|
+
DEFAULT_LAYER_WIDTH;
|
|
16
|
+
const height =
|
|
17
|
+
event.height ||
|
|
18
|
+
parseInt(elm.getAttribute('height') ?? '', 10) ||
|
|
19
|
+
DEFAULT_LAYER_HEIGHT;
|
|
14
20
|
if (!this.elm) {
|
|
15
21
|
this.elm = select(elm).append('svg');
|
|
16
22
|
this.elm.attr('id', `${this.id}`);
|
|
@@ -18,7 +24,11 @@ export abstract class SVGLayer<T> extends Layer<T> {
|
|
|
18
24
|
}
|
|
19
25
|
this.elm.attr('height', height).attr('width', width);
|
|
20
26
|
const interactive = this.interactive ? 'auto' : 'none';
|
|
21
|
-
this.elm
|
|
27
|
+
this.elm
|
|
28
|
+
.style('position', 'absolute')
|
|
29
|
+
.style('pointer-events', interactive)
|
|
30
|
+
.style('opacity', this.opacity)
|
|
31
|
+
.style('z-index', this.order);
|
|
22
32
|
}
|
|
23
33
|
|
|
24
34
|
override onUnmount(): void {
|
|
@@ -46,7 +46,8 @@ export interface PAndASymbol extends SymbolComponent {
|
|
|
46
46
|
kind: 'pAndASymbol';
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
export const isPAndASymbol = (item: PAndA): item is PAndASymbol =>
|
|
49
|
+
export const isPAndASymbol = (item: PAndA): item is PAndASymbol =>
|
|
50
|
+
item.kind === 'pAndASymbol';
|
|
50
51
|
|
|
51
52
|
export interface CementSqueeze {
|
|
52
53
|
kind: 'cementSqueeze';
|
|
@@ -59,7 +60,8 @@ export interface CementSqueeze {
|
|
|
59
60
|
referenceIds: string[];
|
|
60
61
|
}
|
|
61
62
|
|
|
62
|
-
export const isCementSqueeze = (item: PAndA): item is CementSqueeze =>
|
|
63
|
+
export const isCementSqueeze = (item: PAndA): item is CementSqueeze =>
|
|
64
|
+
item.kind === 'cementSqueeze';
|
|
63
65
|
|
|
64
66
|
export interface CementPlug {
|
|
65
67
|
kind: 'cementPlug';
|
|
@@ -72,7 +74,8 @@ export interface CementPlug {
|
|
|
72
74
|
referenceIds: string[];
|
|
73
75
|
}
|
|
74
76
|
|
|
75
|
-
export const isCementPlug = (item: PAndA): item is CementSqueeze =>
|
|
77
|
+
export const isCementPlug = (item: PAndA): item is CementSqueeze =>
|
|
78
|
+
item.kind === 'cementPlug';
|
|
76
79
|
|
|
77
80
|
export type PAndA = PAndASymbol | CementSqueeze | CementPlug;
|
|
78
81
|
|
|
@@ -98,7 +101,11 @@ export interface CompletionSymbol extends BaseCompletion {
|
|
|
98
101
|
export type Completion = Tubing | Screen | CompletionSymbol;
|
|
99
102
|
|
|
100
103
|
export const foldCompletion =
|
|
101
|
-
<T>(
|
|
104
|
+
<T>(
|
|
105
|
+
fScreen: (obj: Screen) => T,
|
|
106
|
+
fTubing: (obj: Tubing) => T,
|
|
107
|
+
fSymbol: (obj: CompletionSymbol) => T,
|
|
108
|
+
) =>
|
|
102
109
|
(completion: Completion): T => {
|
|
103
110
|
switch (completion.kind) {
|
|
104
111
|
case 'screen':
|
|
@@ -303,7 +310,8 @@ export function isOpenHoleFracPack(perf: Perforation) {
|
|
|
303
310
|
);
|
|
304
311
|
}
|
|
305
312
|
|
|
306
|
-
export const isSubKindCasedHoleFracturation = (perf: Perforation): boolean =>
|
|
313
|
+
export const isSubKindCasedHoleFracturation = (perf: Perforation): boolean =>
|
|
314
|
+
perf.subKind === 'Cased hole fracturation';
|
|
307
315
|
|
|
308
316
|
export const intersect = (a: Perforation, b: Perforation): boolean => {
|
|
309
317
|
return a.start < b.end && a.end > b.start;
|
|
@@ -330,7 +338,9 @@ export interface InternalLayerOptions {
|
|
|
330
338
|
perforationLayerId: string;
|
|
331
339
|
}
|
|
332
340
|
|
|
333
|
-
export const defaultInternalLayerOptions = (
|
|
341
|
+
export const defaultInternalLayerOptions = (
|
|
342
|
+
layerId: string,
|
|
343
|
+
): InternalLayerOptions => ({
|
|
334
344
|
holeLayerId: `${layerId}-hole`,
|
|
335
345
|
casingLayerId: `${layerId}-casing`,
|
|
336
346
|
completionLayerId: `${layerId}-completion`,
|
package/src/utils/arc-length.ts
CHANGED
|
@@ -16,19 +16,40 @@ export class ArcLength {
|
|
|
16
16
|
* @param {Number} minDepth Min recursive depth before accepting solution
|
|
17
17
|
* @param {Number} maxDepth Max recursive depth
|
|
18
18
|
*/
|
|
19
|
-
static bisect(
|
|
20
|
-
|
|
19
|
+
static bisect(
|
|
20
|
+
func: fx,
|
|
21
|
+
minLimit = 0,
|
|
22
|
+
maxLimit = 1,
|
|
23
|
+
tolerance = 0.005,
|
|
24
|
+
minDepth = 4,
|
|
25
|
+
maxDepth = 10,
|
|
26
|
+
): number {
|
|
27
|
+
const calcRec = (
|
|
28
|
+
a: number,
|
|
29
|
+
b: number,
|
|
30
|
+
aVal: number[],
|
|
31
|
+
bVal: number[],
|
|
32
|
+
span: number,
|
|
33
|
+
tolerance: number,
|
|
34
|
+
depth = 0,
|
|
35
|
+
): number => {
|
|
21
36
|
const mid = (a + b) / 2;
|
|
22
37
|
const midVal = func(mid) as number[];
|
|
23
38
|
const spanA = Vector2.distance(aVal, midVal);
|
|
24
39
|
const spanB = Vector2.distance(midVal, bVal);
|
|
25
40
|
const length = spanA + spanB;
|
|
26
|
-
if (
|
|
41
|
+
if (
|
|
42
|
+
(depth >= minDepth && Math.abs(length - span) < tolerance) ||
|
|
43
|
+
depth >= maxDepth
|
|
44
|
+
) {
|
|
27
45
|
return length;
|
|
28
46
|
}
|
|
29
47
|
const tol = tolerance / 2;
|
|
30
48
|
const d = depth + 1;
|
|
31
|
-
return
|
|
49
|
+
return (
|
|
50
|
+
calcRec(a, mid, aVal, midVal, spanA, tol, d) +
|
|
51
|
+
calcRec(mid, b, midVal, bVal, spanB, tol, d)
|
|
52
|
+
);
|
|
32
53
|
};
|
|
33
54
|
const aVal = func(minLimit) as number[];
|
|
34
55
|
const bVal = func(maxLimit) as number[];
|
|
@@ -44,7 +65,12 @@ export class ArcLength {
|
|
|
44
65
|
* @param {Number} maxLimit Max limit
|
|
45
66
|
* @param {Number} segments Number of segments
|
|
46
67
|
*/
|
|
47
|
-
static trapezoid(
|
|
68
|
+
static trapezoid(
|
|
69
|
+
func: fx,
|
|
70
|
+
minLimit = 0,
|
|
71
|
+
maxLimit = 1,
|
|
72
|
+
segments = 1000,
|
|
73
|
+
): number {
|
|
48
74
|
let length = 0;
|
|
49
75
|
let lastPos = func(minLimit) as number[];
|
|
50
76
|
const step = (maxLimit - minLimit) / (segments - 1);
|
package/src/utils/root-finder.ts
CHANGED
|
@@ -15,7 +15,14 @@ export class RootFinder {
|
|
|
15
15
|
* @param {Number} minLimit Min limit of result
|
|
16
16
|
* @param {Number} maxLimit Max limit of result
|
|
17
17
|
*/
|
|
18
|
-
static newton(
|
|
18
|
+
static newton(
|
|
19
|
+
func: fx,
|
|
20
|
+
precision = 0.01,
|
|
21
|
+
maxIterations = 1000,
|
|
22
|
+
start = 0.5,
|
|
23
|
+
minLimit = 0,
|
|
24
|
+
maxLimit = 1,
|
|
25
|
+
): number | undefined {
|
|
19
26
|
const h = 0.0001;
|
|
20
27
|
let t = start;
|
|
21
28
|
for (let i = 0; i < maxIterations; i++) {
|
|
@@ -38,7 +45,14 @@ export class RootFinder {
|
|
|
38
45
|
* @param {Number} minLimit Min limit of result
|
|
39
46
|
* @param {Number} maxLimit Max limit of result
|
|
40
47
|
*/
|
|
41
|
-
static bisect(
|
|
48
|
+
static bisect(
|
|
49
|
+
func: fx,
|
|
50
|
+
precision = 0.01,
|
|
51
|
+
maxIterations = 1000,
|
|
52
|
+
start = 0.5,
|
|
53
|
+
minLimit = 0,
|
|
54
|
+
maxLimit = 1,
|
|
55
|
+
): number {
|
|
42
56
|
let tl = minLimit;
|
|
43
57
|
let th = maxLimit;
|
|
44
58
|
let t = start;
|
|
@@ -68,10 +82,24 @@ export class RootFinder {
|
|
|
68
82
|
* @param {Number} minLimit Min limit of result
|
|
69
83
|
* @param {Number} maxLimit Max limit of result
|
|
70
84
|
*/
|
|
71
|
-
static findRoot(
|
|
85
|
+
static findRoot(
|
|
86
|
+
func: fx,
|
|
87
|
+
precision = 0.01,
|
|
88
|
+
maxIterations = 1000,
|
|
89
|
+
start = 0.5,
|
|
90
|
+
minLimit = 0,
|
|
91
|
+
maxLimit = 1,
|
|
92
|
+
): number {
|
|
72
93
|
let t = RootFinder.newton(func, precision, maxIterations, start);
|
|
73
94
|
if (t == null) {
|
|
74
|
-
t = RootFinder.bisect(
|
|
95
|
+
t = RootFinder.bisect(
|
|
96
|
+
func,
|
|
97
|
+
precision,
|
|
98
|
+
maxIterations,
|
|
99
|
+
start,
|
|
100
|
+
minLimit,
|
|
101
|
+
maxLimit,
|
|
102
|
+
);
|
|
75
103
|
}
|
|
76
104
|
return t;
|
|
77
105
|
}
|
package/src/utils/text.ts
CHANGED
|
@@ -11,11 +11,19 @@ export function pixelsPerUnit(x: ScaleLinear<number, number>): number {
|
|
|
11
11
|
return Math.abs(x(min + 1));
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
export function calcSize(
|
|
14
|
+
export function calcSize(
|
|
15
|
+
factor: number,
|
|
16
|
+
min: number,
|
|
17
|
+
max: number,
|
|
18
|
+
x: ScaleLinear<number, number>,
|
|
19
|
+
): number {
|
|
15
20
|
return clamp(pixelsPerUnit(x) * factor, min, max);
|
|
16
21
|
}
|
|
17
22
|
|
|
18
|
-
export function isOverlappingHorizontally(
|
|
23
|
+
export function isOverlappingHorizontally(
|
|
24
|
+
r1: BoundingBox,
|
|
25
|
+
r2: BoundingBox,
|
|
26
|
+
): boolean {
|
|
19
27
|
const r1x2 = r1.x + r1.width;
|
|
20
28
|
const r2x2 = r2.x + r2.width;
|
|
21
29
|
|
|
@@ -36,13 +44,21 @@ export function isOverlapping(
|
|
|
36
44
|
const r1y2 = r1.y + r1.height + verticalPadding;
|
|
37
45
|
const r2y2 = r2.y + r2.height + verticalPadding;
|
|
38
46
|
|
|
39
|
-
if (
|
|
47
|
+
if (
|
|
48
|
+
r2.x - horizontalPadding > r1x2 ||
|
|
49
|
+
r2.y - verticalPadding > r1y2 ||
|
|
50
|
+
r2x2 + horizontalPadding < r1.x ||
|
|
51
|
+
r2y2 + verticalPadding < r1.y
|
|
52
|
+
) {
|
|
40
53
|
return false;
|
|
41
54
|
}
|
|
42
55
|
return true;
|
|
43
56
|
}
|
|
44
57
|
|
|
45
|
-
export function getOverlap(
|
|
58
|
+
export function getOverlap(
|
|
59
|
+
r1: BoundingBox,
|
|
60
|
+
r2: BoundingBox,
|
|
61
|
+
): { dx: number; dy: number } | undefined {
|
|
46
62
|
const r1x2 = r1.x + r1.width;
|
|
47
63
|
const r2x2 = r2.x + r2.width;
|
|
48
64
|
const r1y2 = r1.y + r1.height;
|
|
@@ -52,8 +68,14 @@ export function getOverlap(r1: BoundingBox, r2: BoundingBox): { dx: number; dy:
|
|
|
52
68
|
return undefined;
|
|
53
69
|
}
|
|
54
70
|
|
|
55
|
-
const dx = Math.max(
|
|
56
|
-
|
|
71
|
+
const dx = Math.max(
|
|
72
|
+
0,
|
|
73
|
+
Math.min(r1.x + r1.width, r2.x + r2.width) - Math.max(r1.x, r2.x),
|
|
74
|
+
);
|
|
75
|
+
const dy = Math.max(
|
|
76
|
+
0,
|
|
77
|
+
Math.min(r1.y + r1.height, r2.y + r2.height) - Math.max(r1.y, r2.y),
|
|
78
|
+
);
|
|
57
79
|
|
|
58
80
|
const newPoints = {
|
|
59
81
|
dx,
|
|
@@ -73,7 +95,12 @@ export function getOverlapOffset(
|
|
|
73
95
|
const r1y2 = r1.y + r1.height;
|
|
74
96
|
const r2y2 = r2.y + r2.height;
|
|
75
97
|
|
|
76
|
-
if (
|
|
98
|
+
if (
|
|
99
|
+
r2.x - horizontalPadding > r1x2 ||
|
|
100
|
+
r2.y - verticalPadding > r1y2 ||
|
|
101
|
+
r2x2 + horizontalPadding < r1.x ||
|
|
102
|
+
r2y2 + verticalPadding < r1.y
|
|
103
|
+
) {
|
|
77
104
|
return undefined;
|
|
78
105
|
}
|
|
79
106
|
|
package/src/utils/vectorUtils.ts
CHANGED
|
@@ -4,11 +4,18 @@ import Vector2 from '@equinor/videx-vector2';
|
|
|
4
4
|
export const pointToVector = (p: Point): Vector2 => new Vector2(p.x, p.y);
|
|
5
5
|
export const pointToArray = (p: Point): [number, number] => [p.x, p.y];
|
|
6
6
|
export const vectorToPoint = (v: Vector2): Point => new Point(v[0], v[1]);
|
|
7
|
-
export const vectorToArray = (v: Vector2): [number, number] => [
|
|
7
|
+
export const vectorToArray = (v: Vector2): [number, number] => [
|
|
8
|
+
v[0] ?? 0,
|
|
9
|
+
v[1] ?? 0,
|
|
10
|
+
];
|
|
8
11
|
export const arrayToPoint = (a: number[]): Point => new Point(a[0], a[1]);
|
|
9
|
-
export const arrayToVector = (a: number[]): Vector2 =>
|
|
12
|
+
export const arrayToVector = (a: number[]): Vector2 =>
|
|
13
|
+
new Vector2(a[0] ?? 0, a[1] ?? 0);
|
|
10
14
|
|
|
11
|
-
export const calcDist = (
|
|
15
|
+
export const calcDist = (
|
|
16
|
+
prev: [number, number],
|
|
17
|
+
point: [number, number],
|
|
18
|
+
): number => {
|
|
12
19
|
return arrayToVector(point).sub(prev).magnitude;
|
|
13
20
|
};
|
|
14
21
|
|
|
@@ -53,12 +60,20 @@ export const createNormals = (points: Point[]): Vector2[] => {
|
|
|
53
60
|
};
|
|
54
61
|
|
|
55
62
|
// TODO check if this can be simplified and return Vector/number[]
|
|
56
|
-
export const offsetPoint = (
|
|
63
|
+
export const offsetPoint = (
|
|
64
|
+
point: Point,
|
|
65
|
+
vector: Vector2,
|
|
66
|
+
offset: number,
|
|
67
|
+
): Point => {
|
|
57
68
|
const p = pointToVector(point);
|
|
58
69
|
return vectorToPoint(p.add(vector.scale(offset)));
|
|
59
70
|
};
|
|
60
71
|
|
|
61
|
-
export const offsetPoints = (
|
|
72
|
+
export const offsetPoints = (
|
|
73
|
+
points: Point[],
|
|
74
|
+
vectors: Vector2[],
|
|
75
|
+
offset: number,
|
|
76
|
+
): Point[] => {
|
|
62
77
|
if (points.length !== vectors.length) {
|
|
63
78
|
throw new Error('Number of vectors does not match number of points');
|
|
64
79
|
}
|
|
@@ -69,6 +84,8 @@ export const offsetPoints = (points: Point[], vectors: Vector2[], offset: number
|
|
|
69
84
|
if (vector != null) {
|
|
70
85
|
return offsetPoint(point, vector, offset);
|
|
71
86
|
}
|
|
72
|
-
throw new Error(
|
|
87
|
+
throw new Error(
|
|
88
|
+
`Trying to read index ${index} of point ${point}, but no such vector was found!`,
|
|
89
|
+
);
|
|
73
90
|
});
|
|
74
91
|
};
|