@equinor/esv-intersection 3.0.3 → 3.0.4
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/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +1 -2
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/index.umd.js.map +1 -1
- package/package.json +11 -11
- package/dist/components/axis.d.ts +0 -47
- package/dist/components/index.d.ts +0 -1
- package/dist/control/ExtendedCurveInterpolator.d.ts +0 -58
- package/dist/control/IntersectionReferenceSystem.d.ts +0 -96
- package/dist/control/LayerManager.d.ts +0 -76
- package/dist/control/MainController.d.ts +0 -154
- package/dist/control/ZoomPanHandler.d.ts +0 -158
- package/dist/control/index.d.ts +0 -5
- package/dist/control/interfaces.d.ts +0 -37
- package/dist/control/overlay.d.ts +0 -20
- package/dist/datautils/colortable.d.ts +0 -1
- package/dist/datautils/findsample.d.ts +0 -2
- package/dist/datautils/index.d.ts +0 -6
- package/dist/datautils/interfaces.d.ts +0 -63
- package/dist/datautils/picks.d.ts +0 -74
- package/dist/datautils/schematicShapeGenerator.d.ts +0 -59
- package/dist/datautils/seismicimage.d.ts +0 -45
- package/dist/datautils/surfacedata.d.ts +0 -10
- package/dist/datautils/trajectory.d.ts +0 -14
- package/dist/layers/CalloutCanvasLayer.d.ts +0 -60
- package/dist/layers/CustomDisplayObjects/ComplexRope.d.ts +0 -22
- package/dist/layers/CustomDisplayObjects/ComplexRopeGeometry.d.ts +0 -27
- package/dist/layers/CustomDisplayObjects/FixedWidthSimpleRope.d.ts +0 -20
- package/dist/layers/CustomDisplayObjects/FixedWidthSimpleRopeGeometry.d.ts +0 -26
- package/dist/layers/CustomDisplayObjects/UniformTextureStretchRope.d.ts +0 -17
- package/dist/layers/CustomDisplayObjects/UniformTextureStretchRopeGeometry.d.ts +0 -24
- package/dist/layers/GeomodelCanvasLayer.d.ts +0 -28
- package/dist/layers/GeomodelLabelsLayer.d.ts +0 -49
- package/dist/layers/GeomodelLayerV2.d.ts +0 -12
- package/dist/layers/GridLayer.d.ts +0 -29
- package/dist/layers/ImageCanvasLayer.d.ts +0 -20
- package/dist/layers/ReferenceLineLayer.d.ts +0 -29
- package/dist/layers/SchematicLayer.d.ts +0 -113
- package/dist/layers/SeismicCanvasLayer.d.ts +0 -18
- package/dist/layers/WellborePathLayer.d.ts +0 -17
- package/dist/layers/base/CanvasLayer.d.ts +0 -19
- package/dist/layers/base/HTMLLayer.d.ts +0 -13
- package/dist/layers/base/Layer.d.ts +0 -69
- package/dist/layers/base/PixiLayer.d.ts +0 -32
- package/dist/layers/base/SVGLayer.d.ts +0 -13
- package/dist/layers/base/index.d.ts +0 -5
- package/dist/layers/index.d.ts +0 -16
- package/dist/layers/schematicInterfaces.d.ts +0 -209
- package/dist/utils/arc-length.d.ts +0 -23
- package/dist/utils/binary-search.d.ts +0 -8
- package/dist/utils/color.d.ts +0 -5
- package/dist/utils/index.d.ts +0 -1
- package/dist/utils/root-finder.d.ts +0 -34
- package/dist/utils/text.d.ts +0 -14
- package/dist/utils/vectorUtils.d.ts +0 -15
- package/dist/vendor/pixi-dashed-line/index.d.ts +0 -57
- package/src/components/axis.ts +0 -247
- package/src/components/index.ts +0 -1
- package/src/control/ExtendedCurveInterpolator.ts +0 -155
- package/src/control/IntersectionReferenceSystem.ts +0 -391
- package/src/control/LayerManager.ts +0 -294
- package/src/control/MainController.ts +0 -296
- package/src/control/ZoomPanHandler.ts +0 -436
- package/src/control/index.ts +0 -5
- package/src/control/interfaces.ts +0 -42
- package/src/control/overlay.ts +0 -118
- package/src/datautils/colortable.ts +0 -14
- package/src/datautils/findsample.ts +0 -64
- package/src/datautils/index.ts +0 -6
- package/src/datautils/interfaces.ts +0 -68
- package/src/datautils/picks.ts +0 -328
- package/src/datautils/schematicShapeGenerator.ts +0 -1008
- package/src/datautils/seismicimage.ts +0 -180
- package/src/datautils/surfacedata.ts +0 -318
- package/src/datautils/trajectory.ts +0 -206
- package/src/layers/CalloutCanvasLayer.ts +0 -338
- package/src/layers/CustomDisplayObjects/ComplexRope.ts +0 -45
- package/src/layers/CustomDisplayObjects/ComplexRopeGeometry.ts +0 -190
- package/src/layers/CustomDisplayObjects/FixedWidthSimpleRope.ts +0 -41
- package/src/layers/CustomDisplayObjects/FixedWidthSimpleRopeGeometry.ts +0 -149
- package/src/layers/CustomDisplayObjects/UniformTextureStretchRope.ts +0 -39
- package/src/layers/CustomDisplayObjects/UniformTextureStretchRopeGeometry.ts +0 -174
- package/src/layers/GeomodelCanvasLayer.ts +0 -176
- package/src/layers/GeomodelLabelsLayer.ts +0 -619
- package/src/layers/GeomodelLayerV2.ts +0 -110
- package/src/layers/GridLayer.ts +0 -145
- package/src/layers/ImageCanvasLayer.ts +0 -55
- package/src/layers/ReferenceLineLayer.ts +0 -185
- package/src/layers/SchematicLayer.ts +0 -872
- package/src/layers/SeismicCanvasLayer.ts +0 -46
- package/src/layers/WellborePathLayer.ts +0 -129
- package/src/layers/base/CanvasLayer.ts +0 -102
- package/src/layers/base/HTMLLayer.ts +0 -70
- package/src/layers/base/Layer.ts +0 -217
- package/src/layers/base/PixiLayer.ts +0 -190
- package/src/layers/base/SVGLayer.ts +0 -63
- package/src/layers/base/index.ts +0 -5
- package/src/layers/index.ts +0 -16
- package/src/layers/schematicInterfaces.ts +0 -472
- package/src/utils/arc-length.ts +0 -66
- package/src/utils/binary-search.ts +0 -26
- package/src/utils/color.ts +0 -22
- package/src/utils/index.ts +0 -1
- package/src/utils/root-finder.ts +0 -78
- package/src/utils/text.ts +0 -88
- package/src/utils/vectorUtils.ts +0 -67
- package/src/vendor/pixi-dashed-line/index.ts +0 -394
|
@@ -1,391 +0,0 @@
|
|
|
1
|
-
import Vector2 from '@equinor/videx-vector2';
|
|
2
|
-
import { clamp, radians } from '@equinor/videx-math';
|
|
3
|
-
import { CurveInterpolator, normalize } from 'curve-interpolator';
|
|
4
|
-
|
|
5
|
-
import { Interpolators, Trajectory, MDPoint } from '../interfaces';
|
|
6
|
-
import { ExtendedCurveInterpolator } from './ExtendedCurveInterpolator';
|
|
7
|
-
|
|
8
|
-
// determines how curvy the curve is
|
|
9
|
-
const TENSION = 0.75;
|
|
10
|
-
// determines how many segments to split the curve into
|
|
11
|
-
const ARC_DIVISIONS = 5000;
|
|
12
|
-
// specifies amount of steps (in the range [0,1]) to work back from the end of the curve
|
|
13
|
-
const THRESHOLD_DIRECTION_DISTANCE = 0.001;
|
|
14
|
-
|
|
15
|
-
const DEFAULT_START_EXTEND_LENGTH = 1000.0;
|
|
16
|
-
const DEFAULT_END_EXTEND_LENGTH = 1000.0;
|
|
17
|
-
|
|
18
|
-
const CURTAIN_SAMPLING_ANGLE_THRESHOLD = 0.0005;
|
|
19
|
-
const CURTAIN_SAMPLING_INTERVAL = 0.1;
|
|
20
|
-
|
|
21
|
-
const defaultOptions = {
|
|
22
|
-
approxT: true,
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
export interface ReferenceSystemOptions {
|
|
26
|
-
normalizedLength?: number;
|
|
27
|
-
arcDivisions?: number;
|
|
28
|
-
tension?: number;
|
|
29
|
-
trajectoryAngle?: number;
|
|
30
|
-
calculateDisplacementFromBottom?: boolean;
|
|
31
|
-
curveInterpolator?: ExtendedCurveInterpolator;
|
|
32
|
-
trajectoryInterpolator?: ExtendedCurveInterpolator;
|
|
33
|
-
curtainInterpolator?: ExtendedCurveInterpolator;
|
|
34
|
-
approxT?: boolean;
|
|
35
|
-
quickT?: boolean;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export class IntersectionReferenceSystem {
|
|
39
|
-
options: ReferenceSystemOptions;
|
|
40
|
-
|
|
41
|
-
path: number[][] = [];
|
|
42
|
-
|
|
43
|
-
projectedPath: number[][] = [];
|
|
44
|
-
|
|
45
|
-
projectedTrajectory: number[][];
|
|
46
|
-
|
|
47
|
-
private _offset: number = 0;
|
|
48
|
-
|
|
49
|
-
displacement: number;
|
|
50
|
-
|
|
51
|
-
depthReference: number;
|
|
52
|
-
|
|
53
|
-
wellboreId: number;
|
|
54
|
-
|
|
55
|
-
trajectoryOffset: number;
|
|
56
|
-
|
|
57
|
-
interpolators: Interpolators;
|
|
58
|
-
|
|
59
|
-
startVector: number[];
|
|
60
|
-
|
|
61
|
-
endVector: number[];
|
|
62
|
-
|
|
63
|
-
_curtainPathCache: MDPoint[];
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Creates a common reference system that layers and other components can use
|
|
67
|
-
* @param path (required) array of 3d coordinates: [x, y, z]
|
|
68
|
-
* @param options (optional)
|
|
69
|
-
* @param options.trajectoryAngle (optional) - trajectory angle in degrees, overrides the calculated value
|
|
70
|
-
* @param options.calculateDisplacementFromBottom - (optional) specify if the path is passed from bottom up
|
|
71
|
-
*/
|
|
72
|
-
constructor(path: number[][], options?: ReferenceSystemOptions) {
|
|
73
|
-
if (path.length < 1) {
|
|
74
|
-
throw new Error('Missing coordinates');
|
|
75
|
-
}
|
|
76
|
-
if (path[0] && path[0].length !== 3) {
|
|
77
|
-
throw new Error('Coordinates should be in 3d');
|
|
78
|
-
}
|
|
79
|
-
this.setPath(path, options);
|
|
80
|
-
|
|
81
|
-
this.project = this.project.bind(this);
|
|
82
|
-
this.unproject = this.unproject.bind(this);
|
|
83
|
-
this.getPosition = this.getPosition.bind(this);
|
|
84
|
-
this.getProjectedLength = this.getProjectedLength.bind(this);
|
|
85
|
-
this.getTrajectory = this.getTrajectory.bind(this);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
private setPath(path: number[][], options: ReferenceSystemOptions = {}): void {
|
|
89
|
-
this.options = { ...defaultOptions, ...options };
|
|
90
|
-
const { arcDivisions, tension, calculateDisplacementFromBottom } = this.options;
|
|
91
|
-
|
|
92
|
-
this.path = path;
|
|
93
|
-
|
|
94
|
-
this.projectedPath = IntersectionReferenceSystem.toDisplacement(path);
|
|
95
|
-
|
|
96
|
-
const [displacement] = this.projectedPath[this.projectedPath.length - 1];
|
|
97
|
-
this.displacement = displacement;
|
|
98
|
-
|
|
99
|
-
this.interpolators = {
|
|
100
|
-
curve: options.curveInterpolator || new ExtendedCurveInterpolator(path),
|
|
101
|
-
trajectory:
|
|
102
|
-
options.trajectoryInterpolator ||
|
|
103
|
-
new ExtendedCurveInterpolator(
|
|
104
|
-
path.map((d: number[]) => [d[0], d[1]]),
|
|
105
|
-
{ tension: tension || TENSION, arcDivisions: arcDivisions || ARC_DIVISIONS },
|
|
106
|
-
),
|
|
107
|
-
curtain:
|
|
108
|
-
options.curtainInterpolator ||
|
|
109
|
-
new ExtendedCurveInterpolator(this.projectedPath, { tension: tension || TENSION, arcDivisions: arcDivisions || ARC_DIVISIONS }),
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
const trajVector = this.getTrajectoryVector();
|
|
113
|
-
const negativeTrajVector = trajVector.map((d: number) => d * -1);
|
|
114
|
-
|
|
115
|
-
if (calculateDisplacementFromBottom) {
|
|
116
|
-
this.endVector = negativeTrajVector;
|
|
117
|
-
this.startVector = trajVector;
|
|
118
|
-
} else {
|
|
119
|
-
this.endVector = trajVector;
|
|
120
|
-
this.startVector = negativeTrajVector;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
this._curtainPathCache = undefined;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* Map a length along the curve to intersection coordinates
|
|
128
|
-
* @param length length along the curve
|
|
129
|
-
*/
|
|
130
|
-
project(length: number): number[] {
|
|
131
|
-
const { curtain } = this.interpolators;
|
|
132
|
-
const { calculateDisplacementFromBottom } = this.options;
|
|
133
|
-
const cl = clamp(calculateDisplacementFromBottom ? this.length - (length - this._offset) : length - this._offset, 0, this.length);
|
|
134
|
-
const p = curtain.getPointAtArcLength(cl, this.options);
|
|
135
|
-
return p as number[];
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
curtainTangent(length: number): number[] {
|
|
139
|
-
const { curtain } = this.interpolators;
|
|
140
|
-
const l = length - this._offset;
|
|
141
|
-
const t = curtain.findTForArcLength(l, this.options);
|
|
142
|
-
const tangent = t && curtain.getTangentAt(t);
|
|
143
|
-
return tangent as number[];
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
/**
|
|
147
|
-
* Returns as resampled version of the projected path between start and end
|
|
148
|
-
* Samples are picked from the beginning of the path at every CURTAIN_SAMPLING_INTERVAL meters
|
|
149
|
-
* If the angle between two consecutive segments is close to 180 degrees depending on CURTAIN_SAMPLING_ANGLE_THRESHOLD,
|
|
150
|
-
* a sample in between is discarded.
|
|
151
|
-
*
|
|
152
|
-
* The start and the end are not guaranteed to be part of the returned set of points
|
|
153
|
-
* @param startMd in MD
|
|
154
|
-
* @param endMd in MD
|
|
155
|
-
* @param includeStartEnd guarantee to include the starting and end points
|
|
156
|
-
*/
|
|
157
|
-
getCurtainPath(startMd: number, endMd: number, includeStartEnd = false): MDPoint[] {
|
|
158
|
-
if (!this._curtainPathCache) {
|
|
159
|
-
const points: MDPoint[] = [];
|
|
160
|
-
let prevAngle = Math.PI * 2; // Always add first point
|
|
161
|
-
for (let i = this._offset; i <= this.length + this._offset; i += CURTAIN_SAMPLING_INTERVAL) {
|
|
162
|
-
const point = this.project(i);
|
|
163
|
-
const angle = Math.atan2(point[1], point[0]);
|
|
164
|
-
|
|
165
|
-
// Reduce number of points on a straight line by angle since last point
|
|
166
|
-
if (Math.abs(angle - prevAngle) > CURTAIN_SAMPLING_ANGLE_THRESHOLD) {
|
|
167
|
-
points.push({ point, md: i });
|
|
168
|
-
prevAngle = angle;
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
this._curtainPathCache = points;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
if (includeStartEnd) {
|
|
175
|
-
const startPoint = { point: this.project(startMd), md: startMd };
|
|
176
|
-
const pointsBetween = this._curtainPathCache.filter((p) => p.md > startMd && p.md < endMd);
|
|
177
|
-
const endPoint = { point: this.project(endMd), md: endMd };
|
|
178
|
-
return [startPoint, ...pointsBetween, endPoint];
|
|
179
|
-
}
|
|
180
|
-
return this._curtainPathCache.filter((p) => p.md >= startMd && p.md <= endMd);
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
/**
|
|
184
|
-
* Map a displacement back to length along the curve
|
|
185
|
-
*/
|
|
186
|
-
unproject(displacement: number): number {
|
|
187
|
-
const { normalizedLength, calculateDisplacementFromBottom } = this.options;
|
|
188
|
-
const displacementFromStart = calculateDisplacementFromBottom ? this.displacement - displacement : displacement;
|
|
189
|
-
const length = normalizedLength || this.length;
|
|
190
|
-
|
|
191
|
-
if (displacementFromStart < 0) {
|
|
192
|
-
return displacementFromStart;
|
|
193
|
-
}
|
|
194
|
-
if (displacementFromStart > this.displacement) {
|
|
195
|
-
return length + (displacementFromStart - this.displacement);
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
const ls = this.interpolators.curtain.getIntersectsAsPositions(displacementFromStart, 0, 1);
|
|
199
|
-
if (ls && ls.length) {
|
|
200
|
-
return ls[0] * length + this._offset;
|
|
201
|
-
}
|
|
202
|
-
return null;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
/**
|
|
206
|
-
* Get the normalized displacement [0 - 1] of a specific length along the curve
|
|
207
|
-
*/
|
|
208
|
-
getProjectedLength(length: number): number {
|
|
209
|
-
const { curtain } = this.interpolators;
|
|
210
|
-
const pl = this.project(length);
|
|
211
|
-
const l = pl[0] / curtain.maxX;
|
|
212
|
-
return Number.isFinite(l) ? clamp(l, 0, 1) : 0;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
/**
|
|
216
|
-
* Get the trajectory position at a length along the curve
|
|
217
|
-
*/
|
|
218
|
-
getPosition(length: number): number[] {
|
|
219
|
-
const { trajectory } = this.interpolators;
|
|
220
|
-
const t = this.getProjectedLength(length);
|
|
221
|
-
const p = trajectory.getPointAt(t) as number[];
|
|
222
|
-
return p;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
/**
|
|
226
|
-
* Generate a set of coordinates along the trajectory of the curve
|
|
227
|
-
*/
|
|
228
|
-
getTrajectory(steps: number, from = 0, to = 1): Trajectory {
|
|
229
|
-
const extensionStart = from < 0 ? -from : 0;
|
|
230
|
-
const extensionEnd = to > 1 ? to - 1 : 0;
|
|
231
|
-
|
|
232
|
-
const refStart = this.interpolators.trajectory.getPointAt(0) as number[];
|
|
233
|
-
const refEnd = this.interpolators.trajectory.getPointAt(1) as number[];
|
|
234
|
-
|
|
235
|
-
let p0;
|
|
236
|
-
let p3;
|
|
237
|
-
let offset = 0;
|
|
238
|
-
const t0 = Math.max(0, from);
|
|
239
|
-
const t1 = Math.min(1, to);
|
|
240
|
-
const p1 = this.interpolators.trajectory.getPointAt(t0) as number[];
|
|
241
|
-
const p2 = this.interpolators.trajectory.getPointAt(t1) as number[];
|
|
242
|
-
|
|
243
|
-
if (extensionStart) {
|
|
244
|
-
p0 = [
|
|
245
|
-
refStart[0] + this.startVector[0] * extensionStart * this.displacement,
|
|
246
|
-
refStart[1] + this.startVector[1] * extensionStart * this.displacement,
|
|
247
|
-
];
|
|
248
|
-
offset = -Vector2.distance(p0, refStart);
|
|
249
|
-
} else if (from > 0) {
|
|
250
|
-
offset = Vector2.distance(p1, refStart);
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
if (extensionEnd) {
|
|
254
|
-
p3 = [refEnd[0] + this.endVector[0] * extensionEnd * this.displacement, refEnd[1] + this.endVector[1] * extensionEnd * this.displacement];
|
|
255
|
-
}
|
|
256
|
-
const points = [];
|
|
257
|
-
const tl = to - from;
|
|
258
|
-
const preSteps = Math.floor((extensionStart / tl) * steps);
|
|
259
|
-
const curveSteps = Math.ceil(((t1 - t0) / tl) * steps);
|
|
260
|
-
const postSteps = steps - curveSteps - preSteps;
|
|
261
|
-
|
|
262
|
-
if (p0) {
|
|
263
|
-
points.push(p0);
|
|
264
|
-
for (let i = 1; i < preSteps; i++) {
|
|
265
|
-
const f = (i / preSteps) * extensionStart * this.displacement;
|
|
266
|
-
points.push([p0[0] - this.startVector[0] * f, p0[1] - this.startVector[1] * f]);
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
const curvePoints = this.interpolators.trajectory.getPoints(curveSteps - 1, null, t0, t1) as number[][]; // returns steps + 1 points
|
|
270
|
-
points.push(...curvePoints);
|
|
271
|
-
if (p3) {
|
|
272
|
-
for (let i = 1; i < postSteps - 1; i++) {
|
|
273
|
-
const f = (i / postSteps) * extensionEnd * this.displacement;
|
|
274
|
-
points.push([p2[0] + this.endVector[0] * f, p2[1] + this.endVector[1] * f]);
|
|
275
|
-
}
|
|
276
|
-
points.push(p3);
|
|
277
|
-
}
|
|
278
|
-
return { points, offset };
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
/**
|
|
282
|
-
* Generate a set of coordinates along the trajectory of the curve
|
|
283
|
-
*/
|
|
284
|
-
getExtendedTrajectory(
|
|
285
|
-
numPoints: number,
|
|
286
|
-
startExtensionLength = DEFAULT_START_EXTEND_LENGTH,
|
|
287
|
-
endExtensionLength = DEFAULT_END_EXTEND_LENGTH,
|
|
288
|
-
): Trajectory {
|
|
289
|
-
if (!isFinite(startExtensionLength) || startExtensionLength < 0.0) {
|
|
290
|
-
throw new Error('Invalid parameter, getExtendedTrajectory() must be called with a valid and positive startExtensionLength parameter');
|
|
291
|
-
}
|
|
292
|
-
if (!isFinite(endExtensionLength) || endExtensionLength < 0.0) {
|
|
293
|
-
throw new Error('Invalid parameter, getExtendedTrajectory() must be called with a valid and positive endExtensionLength parameter');
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
const totalLength = this.displacement + startExtensionLength + endExtensionLength;
|
|
297
|
-
const startExtensionNumPoints = Math.floor((startExtensionLength / totalLength) * numPoints);
|
|
298
|
-
const curveSteps = Math.max(Math.ceil((this.displacement / totalLength) * numPoints), 1);
|
|
299
|
-
const endExtensionNumPoints = numPoints - curveSteps - startExtensionNumPoints;
|
|
300
|
-
|
|
301
|
-
const points = [];
|
|
302
|
-
|
|
303
|
-
const refStart = new Vector2(this.interpolators.trajectory.getPointAt(0.0) as number[]);
|
|
304
|
-
const startVec = new Vector2(this.startVector);
|
|
305
|
-
const startExtensionStepLength = startExtensionLength / startExtensionNumPoints;
|
|
306
|
-
for (let i = startExtensionNumPoints; i > 0; i--) {
|
|
307
|
-
const f = i * startExtensionStepLength;
|
|
308
|
-
const point = refStart.add(startVec.scale(f));
|
|
309
|
-
points.push(point.toArray());
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
const curveStepPoints = this.interpolators.trajectory.getPoints(curveSteps, null, 0.0, 1.0) as number[][];
|
|
313
|
-
points.push(...curveStepPoints);
|
|
314
|
-
|
|
315
|
-
const refEnd = new Vector2(this.interpolators.trajectory.getPointAt(1.0) as number[]);
|
|
316
|
-
const endVec = new Vector2(this.endVector);
|
|
317
|
-
const endExtensionStepLength = endExtensionLength / (endExtensionNumPoints - 1); // -1 so last point is at end of extension
|
|
318
|
-
for (let i = 1; i < endExtensionNumPoints; i++) {
|
|
319
|
-
const f = i * endExtensionStepLength;
|
|
320
|
-
const point = refEnd.add(endVec.scale(f));
|
|
321
|
-
points.push(point.toArray());
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
const offset = -startExtensionLength;
|
|
325
|
-
|
|
326
|
-
const trajectory = { points, offset };
|
|
327
|
-
return trajectory;
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
getTrajectoryVector(): number[] {
|
|
331
|
-
const { trajectoryAngle, calculateDisplacementFromBottom } = this.options;
|
|
332
|
-
|
|
333
|
-
if (isFinite(trajectoryAngle)) {
|
|
334
|
-
const angleInRad = radians(trajectoryAngle);
|
|
335
|
-
return new Vector2(Math.cos(angleInRad), Math.sin(angleInRad)).toArray();
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
const trajectoryVec = IntersectionReferenceSystem.getDirectionVector(
|
|
339
|
-
this.interpolators.trajectory,
|
|
340
|
-
calculateDisplacementFromBottom ? THRESHOLD_DIRECTION_DISTANCE : 1 - THRESHOLD_DIRECTION_DISTANCE,
|
|
341
|
-
calculateDisplacementFromBottom ? 0 : 1,
|
|
342
|
-
);
|
|
343
|
-
return trajectoryVec;
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
/**
|
|
347
|
-
* Perform a curtain projection on a set of points in 3D
|
|
348
|
-
* @param points
|
|
349
|
-
* @param origin
|
|
350
|
-
* @param offset
|
|
351
|
-
* @returns {array}
|
|
352
|
-
*/
|
|
353
|
-
static toDisplacement(points: number[][], offset = 0): number[][] {
|
|
354
|
-
let p0: number[] = points[0];
|
|
355
|
-
let l = 0;
|
|
356
|
-
const projected = points.map((p1: number[]) => {
|
|
357
|
-
const dx = p1[0] - p0[0];
|
|
358
|
-
const dy = p1[1] - p0[1];
|
|
359
|
-
l += Math.sqrt(dx ** 2 + dy ** 2);
|
|
360
|
-
p0 = p1;
|
|
361
|
-
return [offset > 0 ? offset - l : l, p1[2] || 0];
|
|
362
|
-
});
|
|
363
|
-
return projected;
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
/**
|
|
367
|
-
* returns a normalized vector
|
|
368
|
-
* @param interpolator interpolated curve
|
|
369
|
-
* @param from number between 0 and 1
|
|
370
|
-
* @param to number between 0 and 1
|
|
371
|
-
*/
|
|
372
|
-
static getDirectionVector(interpolator: CurveInterpolator, from: number, to: number): number[] {
|
|
373
|
-
const p1 = interpolator.getPointAt(to);
|
|
374
|
-
const p2 = interpolator.getPointAt(from);
|
|
375
|
-
|
|
376
|
-
return normalize([p1[0] - p2[0], p1[1] - p2[1]]) as number[];
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
get length(): number {
|
|
380
|
-
return this.interpolators.curve.length;
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
get offset(): number {
|
|
384
|
-
return this._offset;
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
set offset(offset: number) {
|
|
388
|
-
this._curtainPathCache = undefined;
|
|
389
|
-
this._offset = offset;
|
|
390
|
-
}
|
|
391
|
-
}
|
|
@@ -1,294 +0,0 @@
|
|
|
1
|
-
import { select, Selection } from 'd3-selection';
|
|
2
|
-
import { ZoomPanHandler } from './ZoomPanHandler';
|
|
3
|
-
import { Layer, GridLayer, LayerOptions } from '../layers';
|
|
4
|
-
import { ScaleOptions, OnMountEvent, OnRescaleEvent } from '../interfaces';
|
|
5
|
-
import { Axis } from '../components';
|
|
6
|
-
import { IntersectionReferenceSystem } from './IntersectionReferenceSystem';
|
|
7
|
-
import { HORIZONTAL_AXIS_MARGIN, VERTICAL_AXIS_MARGIN } from '../constants';
|
|
8
|
-
import { AxisOptions } from './interfaces';
|
|
9
|
-
|
|
10
|
-
export class LayerManager {
|
|
11
|
-
private container: HTMLElement;
|
|
12
|
-
|
|
13
|
-
private layerContainer: HTMLElement;
|
|
14
|
-
|
|
15
|
-
private _zoomPanHandler: ZoomPanHandler;
|
|
16
|
-
|
|
17
|
-
private layers: Layer<unknown>[] = [];
|
|
18
|
-
|
|
19
|
-
private _axis: Axis;
|
|
20
|
-
private _svgContainer: Selection<HTMLElement, unknown, null, undefined>;
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Handles layers and axis also holds a zoom and pan handler object
|
|
24
|
-
* @param container root container
|
|
25
|
-
* @param scaleOptions
|
|
26
|
-
* @param axisOptions
|
|
27
|
-
*/
|
|
28
|
-
constructor(container: HTMLElement, scaleOptions?: ScaleOptions, axisOptions?: AxisOptions) {
|
|
29
|
-
this.container = container;
|
|
30
|
-
this.layerContainer = document.createElement('div');
|
|
31
|
-
this.layerContainer.className = 'layer-container';
|
|
32
|
-
this.container.appendChild(this.layerContainer);
|
|
33
|
-
this.adjustToSize(+this.container.getAttribute('width'), +this.container.getAttribute('height'));
|
|
34
|
-
this._zoomPanHandler = new ZoomPanHandler(container, (event) => this.rescale(event));
|
|
35
|
-
if (scaleOptions) {
|
|
36
|
-
const { xMin, xMax, yMin, yMax, xBounds, yBounds } = scaleOptions;
|
|
37
|
-
if (xMin !== undefined && xMax !== undefined && yMin !== undefined && yMax !== undefined) {
|
|
38
|
-
this._zoomPanHandler.setBounds([xMin, xMax], [yMin, yMax]);
|
|
39
|
-
}
|
|
40
|
-
if (xBounds && yBounds) {
|
|
41
|
-
this._zoomPanHandler.setBounds(xBounds, yBounds);
|
|
42
|
-
}
|
|
43
|
-
} else {
|
|
44
|
-
this._zoomPanHandler.setBounds([0, 1], [0, 1]);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
if (axisOptions) {
|
|
48
|
-
this._axis = this.createAxis(axisOptions);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
this.rescale = this.rescale.bind(this);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Adds and mounts an array of layers
|
|
56
|
-
* @param layers array of layers
|
|
57
|
-
*/
|
|
58
|
-
addLayers(layers: Layer<unknown>[]): LayerManager {
|
|
59
|
-
layers.forEach((layer) => this.addLayer(layer));
|
|
60
|
-
return this;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Gets all layers currently mounted
|
|
65
|
-
*/
|
|
66
|
-
getLayers(): Layer<unknown>[] {
|
|
67
|
-
return this.layers;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Clears data from all mounted layers
|
|
72
|
-
* @param includeReferenceSystem - (optional) if true also removes reference system, default is true
|
|
73
|
-
*/
|
|
74
|
-
clearAllData(includeReferenceSystem: boolean = true): LayerManager {
|
|
75
|
-
this.layers.forEach((l) => l.clearData(includeReferenceSystem));
|
|
76
|
-
return this;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Adds the layer to the manager, and mounts it
|
|
81
|
-
* @param layer Layer
|
|
82
|
-
* @param params extra params to pass to the onUpdate method
|
|
83
|
-
*/
|
|
84
|
-
addLayer(layer: Layer<unknown>, params?: LayerOptions<unknown>): LayerManager {
|
|
85
|
-
this.layers.push(layer);
|
|
86
|
-
this.initLayer(layer, params);
|
|
87
|
-
|
|
88
|
-
return this;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Remove and unmount layer from manager
|
|
93
|
-
* @param layerId name of layer
|
|
94
|
-
*/
|
|
95
|
-
removeLayer(layerId: string): LayerManager {
|
|
96
|
-
const layer = this.layers.find((l) => l.id === layerId);
|
|
97
|
-
if (layer) {
|
|
98
|
-
layer.onUnmount();
|
|
99
|
-
this.layers = this.layers.filter((l) => l.id !== layerId);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
return this;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Remove and unmount all layers from manager
|
|
107
|
-
*/
|
|
108
|
-
removeAllLayers(): LayerManager {
|
|
109
|
-
const { layers } = this;
|
|
110
|
-
layers.forEach((layer) => {
|
|
111
|
-
this.removeLayer(layer.id);
|
|
112
|
-
});
|
|
113
|
-
return this;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
getLayer(layerId: string): Layer<unknown> {
|
|
117
|
-
return this.layers.find((l) => l.id === layerId || l.getInternalLayerIds().includes(layerId));
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
initLayer(layer: Layer<unknown>, params?: LayerOptions<unknown>): LayerManager {
|
|
121
|
-
const event: OnMountEvent = {
|
|
122
|
-
elm: this.layerContainer,
|
|
123
|
-
};
|
|
124
|
-
layer.onMount(event);
|
|
125
|
-
const rescaleEvent = this.zoomPanHandler.currentStateAsEvent();
|
|
126
|
-
layer.onUpdate({ ...rescaleEvent, ...params });
|
|
127
|
-
layer.onRescale(rescaleEvent);
|
|
128
|
-
|
|
129
|
-
if (this._svgContainer) {
|
|
130
|
-
const highestZIndex = this.layers.length > 0 ? this.layers.reduce((max, layers) => (max.order > layers.order ? max : layers)).order : 1;
|
|
131
|
-
this._svgContainer.style('z-index', `${highestZIndex + 1}`);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
return this;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
showLayer(layerId: string): LayerManager {
|
|
138
|
-
const layer = this.getLayer(layerId);
|
|
139
|
-
if (!layer) {
|
|
140
|
-
return this;
|
|
141
|
-
}
|
|
142
|
-
layer.setVisibility(true, layerId);
|
|
143
|
-
layer.onRescale(this.zoomPanHandler.currentStateAsEvent());
|
|
144
|
-
return this;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
hideLayer(layerId: string): LayerManager {
|
|
148
|
-
const layer = this.getLayer(layerId);
|
|
149
|
-
if (!layer) {
|
|
150
|
-
return this;
|
|
151
|
-
}
|
|
152
|
-
layer.setVisibility(false, layerId);
|
|
153
|
-
layer.onRescale(this.zoomPanHandler.currentStateAsEvent());
|
|
154
|
-
return this;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
/**
|
|
158
|
-
* Adjust layers, axis, and zoom according to inputted dimensions
|
|
159
|
-
* @param width (required)
|
|
160
|
-
* @param height (required)
|
|
161
|
-
*/
|
|
162
|
-
adjustToSize(width: number, height: number): void {
|
|
163
|
-
const layersWidth = Math.max(this._axis ? width - HORIZONTAL_AXIS_MARGIN : width, 0);
|
|
164
|
-
const layersHeight = Math.max(this._axis ? height - VERTICAL_AXIS_MARGIN : height, 0);
|
|
165
|
-
|
|
166
|
-
if (this._axis) {
|
|
167
|
-
const resizeEvent = { width, height };
|
|
168
|
-
this._axis.onResize(resizeEvent);
|
|
169
|
-
}
|
|
170
|
-
if (this.layers) {
|
|
171
|
-
const resizeEvent = { width: layersWidth, height: layersHeight };
|
|
172
|
-
this.layers.forEach((layer) => layer.onResize(resizeEvent));
|
|
173
|
-
}
|
|
174
|
-
if (this._zoomPanHandler) {
|
|
175
|
-
this._zoomPanHandler.adjustToSize(layersWidth, layersHeight, true);
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
setReferenceSystem(irs: IntersectionReferenceSystem): void {
|
|
180
|
-
this.layers.forEach((layer) => (layer.referenceSystem = irs));
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
showAxis(): LayerManager {
|
|
184
|
-
this._axis.show();
|
|
185
|
-
return this;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
hideAxis(): LayerManager {
|
|
189
|
-
this._axis.hide();
|
|
190
|
-
return this;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
showAxisLabels(): LayerManager {
|
|
194
|
-
this._axis.showLabels();
|
|
195
|
-
return this;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
hideAxisLabels(): LayerManager {
|
|
199
|
-
this._axis.hideLabels();
|
|
200
|
-
return this;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
setAxisOffset(x: number, y: number): LayerManager {
|
|
204
|
-
this._axis.offsetX = x;
|
|
205
|
-
this._axis.offsetY = y;
|
|
206
|
-
const gridLayers = this.layers.filter((l: Layer<unknown>) => l instanceof GridLayer<unknown>);
|
|
207
|
-
gridLayers.forEach((l: GridLayer<unknown>) => {
|
|
208
|
-
l.offsetX = x;
|
|
209
|
-
l.offsetY = y;
|
|
210
|
-
});
|
|
211
|
-
return this;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
setXAxisOffset(x: number): LayerManager {
|
|
215
|
-
this._axis.offsetX = x;
|
|
216
|
-
const gridLayers = this.layers.filter((l: Layer<unknown>) => l instanceof GridLayer<unknown>);
|
|
217
|
-
gridLayers.forEach((l: GridLayer<unknown>) => {
|
|
218
|
-
l.offsetX = x;
|
|
219
|
-
});
|
|
220
|
-
return this;
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
setYAxisOffset(y: number): LayerManager {
|
|
224
|
-
this._axis.offsetY = y;
|
|
225
|
-
const gridLayers = this.layers.filter((l: Layer<unknown>) => l instanceof GridLayer<unknown>);
|
|
226
|
-
gridLayers.forEach((l: GridLayer<unknown>) => {
|
|
227
|
-
l.offsetY = y;
|
|
228
|
-
});
|
|
229
|
-
return this;
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
setZoomLevelBoundary(zoomlevels: [number, number]): LayerManager {
|
|
233
|
-
this._zoomPanHandler.setZoomLevelBoundary(zoomlevels);
|
|
234
|
-
return this;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
setMaxZoomLevel(zoomlevel: number): LayerManager {
|
|
238
|
-
this._zoomPanHandler.setMaxZoomLevel(zoomlevel);
|
|
239
|
-
return this;
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
setMinZoomLevel(zoomlevel: number): LayerManager {
|
|
243
|
-
this._zoomPanHandler.setMinZoomLevel(zoomlevel);
|
|
244
|
-
return this;
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
destroy(): LayerManager {
|
|
248
|
-
this.removeAllLayers();
|
|
249
|
-
this.layerContainer.remove();
|
|
250
|
-
this.layerContainer = undefined;
|
|
251
|
-
this.container = undefined;
|
|
252
|
-
this.layers = undefined;
|
|
253
|
-
this._zoomPanHandler = undefined;
|
|
254
|
-
this._axis = undefined;
|
|
255
|
-
this._svgContainer = undefined;
|
|
256
|
-
|
|
257
|
-
return this;
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
get zoomPanHandler(): ZoomPanHandler {
|
|
261
|
-
return this._zoomPanHandler;
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
get axis(): Axis {
|
|
265
|
-
return this._axis;
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
private rescale(event: OnRescaleEvent): void {
|
|
269
|
-
if (this._axis) {
|
|
270
|
-
this._axis.onRescale(event);
|
|
271
|
-
}
|
|
272
|
-
if (this.layers) {
|
|
273
|
-
this.layers.forEach((layer) => (layer.isVisible === true ? layer.onRescale(event) : {}));
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
private createAxis = (options: AxisOptions): Axis => {
|
|
278
|
-
const { container } = this;
|
|
279
|
-
this._svgContainer = select(container)
|
|
280
|
-
.append('div')
|
|
281
|
-
.attr('class', 'axis')
|
|
282
|
-
.style('position', 'absolute')
|
|
283
|
-
.style('z-index', '10')
|
|
284
|
-
.style('pointer-events', 'none');
|
|
285
|
-
|
|
286
|
-
const svg = this._svgContainer.append('svg').attr('height', `${container.offsetHeight}px`).attr('width', `${container.offsetWidth}px`);
|
|
287
|
-
|
|
288
|
-
const showLabels = true;
|
|
289
|
-
|
|
290
|
-
const axis = new Axis(svg, showLabels, options.xLabel, options.yLabel, options.unitOfMeasure);
|
|
291
|
-
|
|
292
|
-
return axis;
|
|
293
|
-
};
|
|
294
|
-
}
|