@equinor/esv-intersection 3.0.1 → 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.
Files changed (109) hide show
  1. package/dist/index.cjs +2 -2
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.mjs +2241 -1938
  4. package/dist/index.mjs.map +1 -1
  5. package/dist/index.umd.js +2 -2
  6. package/dist/index.umd.js.map +1 -1
  7. package/package.json +21 -22
  8. package/dist/components/axis.d.ts +0 -47
  9. package/dist/components/index.d.ts +0 -1
  10. package/dist/control/ExtendedCurveInterpolator.d.ts +0 -58
  11. package/dist/control/IntersectionReferenceSystem.d.ts +0 -96
  12. package/dist/control/LayerManager.d.ts +0 -76
  13. package/dist/control/MainController.d.ts +0 -154
  14. package/dist/control/ZoomPanHandler.d.ts +0 -158
  15. package/dist/control/index.d.ts +0 -5
  16. package/dist/control/interfaces.d.ts +0 -37
  17. package/dist/control/overlay.d.ts +0 -20
  18. package/dist/datautils/colortable.d.ts +0 -1
  19. package/dist/datautils/findsample.d.ts +0 -2
  20. package/dist/datautils/index.d.ts +0 -6
  21. package/dist/datautils/interfaces.d.ts +0 -63
  22. package/dist/datautils/picks.d.ts +0 -74
  23. package/dist/datautils/schematicShapeGenerator.d.ts +0 -59
  24. package/dist/datautils/seismicimage.d.ts +0 -45
  25. package/dist/datautils/surfacedata.d.ts +0 -10
  26. package/dist/datautils/trajectory.d.ts +0 -14
  27. package/dist/layers/CalloutCanvasLayer.d.ts +0 -60
  28. package/dist/layers/CustomDisplayObjects/ComplexRope.d.ts +0 -22
  29. package/dist/layers/CustomDisplayObjects/ComplexRopeGeometry.d.ts +0 -27
  30. package/dist/layers/CustomDisplayObjects/FixedWidthSimpleRope.d.ts +0 -20
  31. package/dist/layers/CustomDisplayObjects/FixedWidthSimpleRopeGeometry.d.ts +0 -26
  32. package/dist/layers/CustomDisplayObjects/UniformTextureStretchRope.d.ts +0 -17
  33. package/dist/layers/CustomDisplayObjects/UniformTextureStretchRopeGeometry.d.ts +0 -24
  34. package/dist/layers/GeomodelCanvasLayer.d.ts +0 -28
  35. package/dist/layers/GeomodelLabelsLayer.d.ts +0 -49
  36. package/dist/layers/GeomodelLayerV2.d.ts +0 -12
  37. package/dist/layers/GridLayer.d.ts +0 -29
  38. package/dist/layers/ImageCanvasLayer.d.ts +0 -20
  39. package/dist/layers/ReferenceLineLayer.d.ts +0 -29
  40. package/dist/layers/SchematicLayer.d.ts +0 -113
  41. package/dist/layers/SeismicCanvasLayer.d.ts +0 -18
  42. package/dist/layers/WellborePathLayer.d.ts +0 -17
  43. package/dist/layers/base/CanvasLayer.d.ts +0 -19
  44. package/dist/layers/base/HTMLLayer.d.ts +0 -13
  45. package/dist/layers/base/Layer.d.ts +0 -69
  46. package/dist/layers/base/PixiLayer.d.ts +0 -32
  47. package/dist/layers/base/SVGLayer.d.ts +0 -13
  48. package/dist/layers/base/index.d.ts +0 -5
  49. package/dist/layers/index.d.ts +0 -16
  50. package/dist/layers/schematicInterfaces.d.ts +0 -208
  51. package/dist/utils/arc-length.d.ts +0 -23
  52. package/dist/utils/binary-search.d.ts +0 -8
  53. package/dist/utils/color.d.ts +0 -5
  54. package/dist/utils/index.d.ts +0 -1
  55. package/dist/utils/root-finder.d.ts +0 -34
  56. package/dist/utils/text.d.ts +0 -14
  57. package/dist/utils/vectorUtils.d.ts +0 -15
  58. package/dist/vendor/pixi-dashed-line/index.d.ts +0 -57
  59. package/src/components/axis.ts +0 -247
  60. package/src/components/index.ts +0 -1
  61. package/src/control/ExtendedCurveInterpolator.ts +0 -155
  62. package/src/control/IntersectionReferenceSystem.ts +0 -391
  63. package/src/control/LayerManager.ts +0 -294
  64. package/src/control/MainController.ts +0 -296
  65. package/src/control/ZoomPanHandler.ts +0 -436
  66. package/src/control/index.ts +0 -5
  67. package/src/control/interfaces.ts +0 -42
  68. package/src/control/overlay.ts +0 -118
  69. package/src/datautils/colortable.ts +0 -14
  70. package/src/datautils/findsample.ts +0 -64
  71. package/src/datautils/index.ts +0 -6
  72. package/src/datautils/interfaces.ts +0 -68
  73. package/src/datautils/picks.ts +0 -328
  74. package/src/datautils/schematicShapeGenerator.ts +0 -1007
  75. package/src/datautils/seismicimage.ts +0 -180
  76. package/src/datautils/surfacedata.ts +0 -318
  77. package/src/datautils/trajectory.ts +0 -206
  78. package/src/layers/CalloutCanvasLayer.ts +0 -338
  79. package/src/layers/CustomDisplayObjects/ComplexRope.ts +0 -45
  80. package/src/layers/CustomDisplayObjects/ComplexRopeGeometry.ts +0 -190
  81. package/src/layers/CustomDisplayObjects/FixedWidthSimpleRope.ts +0 -41
  82. package/src/layers/CustomDisplayObjects/FixedWidthSimpleRopeGeometry.ts +0 -149
  83. package/src/layers/CustomDisplayObjects/UniformTextureStretchRope.ts +0 -39
  84. package/src/layers/CustomDisplayObjects/UniformTextureStretchRopeGeometry.ts +0 -174
  85. package/src/layers/GeomodelCanvasLayer.ts +0 -176
  86. package/src/layers/GeomodelLabelsLayer.ts +0 -619
  87. package/src/layers/GeomodelLayerV2.ts +0 -110
  88. package/src/layers/GridLayer.ts +0 -145
  89. package/src/layers/ImageCanvasLayer.ts +0 -55
  90. package/src/layers/ReferenceLineLayer.ts +0 -185
  91. package/src/layers/SchematicLayer.ts +0 -871
  92. package/src/layers/SeismicCanvasLayer.ts +0 -46
  93. package/src/layers/WellborePathLayer.ts +0 -129
  94. package/src/layers/base/CanvasLayer.ts +0 -102
  95. package/src/layers/base/HTMLLayer.ts +0 -70
  96. package/src/layers/base/Layer.ts +0 -217
  97. package/src/layers/base/PixiLayer.ts +0 -190
  98. package/src/layers/base/SVGLayer.ts +0 -63
  99. package/src/layers/base/index.ts +0 -5
  100. package/src/layers/index.ts +0 -16
  101. package/src/layers/schematicInterfaces.ts +0 -470
  102. package/src/utils/arc-length.ts +0 -66
  103. package/src/utils/binary-search.ts +0 -26
  104. package/src/utils/color.ts +0 -22
  105. package/src/utils/index.ts +0 -1
  106. package/src/utils/root-finder.ts +0 -78
  107. package/src/utils/text.ts +0 -88
  108. package/src/utils/vectorUtils.ts +0 -67
  109. package/src/vendor/pixi-dashed-line/index.ts +0 -394
@@ -1,1007 +0,0 @@
1
- import { groupD8, IPoint, Point, Rectangle, Texture, WRAP_MODES } from 'pixi.js';
2
- import { DEFAULT_TEXTURE_SIZE } from '../constants';
3
- import {
4
- Casing,
5
- CasingWindow,
6
- Cement,
7
- CementOptions,
8
- CementPlug,
9
- CementPlugOptions,
10
- CementSqueeze,
11
- CementSqueezeOptions,
12
- Completion,
13
- HoleOptions,
14
- HoleSize,
15
- ScreenOptions,
16
- TubingOptions,
17
- Perforation,
18
- PerforationOptions,
19
- foldPerforationSubKind,
20
- intersect,
21
- isSubKindCasedHoleFracPack,
22
- isSubkindCasedHoleGravelPack,
23
- PerforationSubKind,
24
- } from '../layers/schematicInterfaces';
25
- import { ComplexRopeSegment } from '../layers/CustomDisplayObjects/ComplexRope';
26
- import { createNormals, offsetPoints } from '../utils/vectorUtils';
27
-
28
- export type PerforationShape = ComplexRopeSegment;
29
-
30
- export interface TubularRenderingObject {
31
- leftPath: Point[];
32
- rightPath: Point[];
33
- }
34
-
35
- export interface CasingRenderObject {
36
- id: string;
37
- kind: 'casing';
38
- referenceDiameter: number;
39
- referenceRadius: number;
40
- casingWallWidth: number;
41
- hasShoe: boolean;
42
- bottom: number;
43
- zIndex?: number;
44
- sections: {
45
- kind: 'casing' | 'casing-window';
46
- leftPath: Point[];
47
- rightPath: Point[];
48
- pathPoints: Point[];
49
- }[];
50
- }
51
-
52
- export const getEndLines = (
53
- rightPath: IPoint[],
54
- leftPath: IPoint[],
55
- ): {
56
- top: IPoint[];
57
- bottom: IPoint[];
58
- } => {
59
- return {
60
- top: [rightPath[0], leftPath[0]],
61
- bottom: [rightPath[rightPath.length - 1], leftPath[leftPath.length - 1]],
62
- };
63
- };
64
-
65
- export const overlaps = (top1: number, bottom1: number, top2: number, bottom2: number): boolean => top1 <= bottom2 && top2 <= bottom1;
66
-
67
- export const strictlyOverlaps = (top1: number, bottom1: number, top2: number, bottom2: number): boolean => top1 < bottom2 && top2 < bottom1;
68
-
69
- export const uniq = <T>(arr: T[]): T[] => Array.from<T>(new Set(arr));
70
-
71
- const findIntersectingItems = (
72
- start: number,
73
- end: number,
74
- otherStrings: (Casing | Completion)[],
75
- holes: HoleSize[],
76
- ): { overlappingHoles: HoleSize[]; overlappingOuterStrings: (Casing | Completion)[] } => {
77
- const overlappingHoles = holes.filter((hole: HoleSize) => overlaps(start, end, hole.start, hole.end));
78
-
79
- const overlappingOuterStrings = otherStrings.filter((casing: Casing | Completion) => overlaps(start, end, casing.start, casing.end));
80
-
81
- return {
82
- overlappingHoles,
83
- overlappingOuterStrings,
84
- };
85
- };
86
-
87
- export const getUniqueDiameterChangeDepths = (
88
- [intervalStart, intervalEnd]: [number, number],
89
- diameterIntervals: { start: number; end: number }[],
90
- ): number[] => {
91
- const epsilon = 0.0001;
92
- const diameterChangeDepths = diameterIntervals.flatMap(
93
- (
94
- d, // to find diameter right before/after object
95
- ) => [d.start - epsilon, d.start, d.end, d.end + epsilon],
96
- );
97
- const trimmedChangedDepths = diameterChangeDepths.filter((d) => d >= intervalStart && d <= intervalEnd); // trim
98
-
99
- trimmedChangedDepths.push(intervalStart);
100
- trimmedChangedDepths.push(intervalEnd);
101
-
102
- const uniqDepths = uniq(trimmedChangedDepths);
103
- return uniqDepths.sort((a: number, b: number) => a - b);
104
- };
105
-
106
- const getInnerStringDiameter = (stringType: Casing | Completion): number =>
107
- stringType.kind === 'casing' ? stringType.innerDiameter : stringType.diameter;
108
-
109
- export const findCementOuterDiameterAtDepth = (
110
- attachedStrings: (Casing | Completion)[],
111
- nonAttachedStrings: (Casing | Completion)[],
112
- holes: HoleSize[],
113
- depth: number,
114
- ): number => {
115
- const defaultCementWidth = 100; // Default to flow cement outside to show error in data
116
-
117
- const attachedStringAtDepth = attachedStrings.find(
118
- (casingOrCompletion: Casing | Completion) => casingOrCompletion.start <= depth && casingOrCompletion.end >= depth,
119
- );
120
- const attachedOuterDiameter = attachedStringAtDepth ? attachedStringAtDepth.diameter : 0;
121
-
122
- const outerCasingAtDepth = nonAttachedStrings
123
- .filter((casingOrCompletion: Casing | Completion) => getInnerStringDiameter(casingOrCompletion) > attachedOuterDiameter)
124
- .sort((a: Casing | Completion, b: Casing | Completion) => getInnerStringDiameter(a) - getInnerStringDiameter(b)) // ascending
125
- .find((casing) => casing.start <= depth && casing.end >= depth);
126
-
127
- const holeAtDepth = holes.find((hole: HoleSize) => hole.start <= depth && hole.end >= depth && hole.diameter > attachedOuterDiameter);
128
-
129
- if (outerCasingAtDepth) {
130
- return getInnerStringDiameter(outerCasingAtDepth);
131
- }
132
-
133
- if (holeAtDepth) {
134
- return holeAtDepth.diameter;
135
- }
136
-
137
- return defaultCementWidth;
138
- };
139
-
140
- export const findPerforationOuterDiameterAtDepth = (
141
- nonAttachedStrings: (Casing | Completion)[],
142
- holes: HoleSize[],
143
- depth: number,
144
- perforationSubKind: PerforationSubKind,
145
- ): number => {
146
- const defaultPerforationWidth = 100; // Default to flow perforation outside to show error in data
147
-
148
- const outerCasingAtDepth = nonAttachedStrings
149
- .sort((a: Casing | Completion, b: Casing | Completion) => b.diameter - a.diameter) // descending
150
- .find((casing) => casing.start <= depth && casing.end >= depth);
151
-
152
- const holeAtDepth = holes.find((hole: HoleSize) => hole.start <= depth && hole.end >= depth);
153
-
154
- if (outerCasingAtDepth && perforationSubKind !== 'Open hole frac pack' && perforationSubKind !== 'Open hole gravel pack') {
155
- return getInnerStringDiameter(outerCasingAtDepth);
156
- }
157
-
158
- if (holeAtDepth) {
159
- return holeAtDepth.diameter;
160
- }
161
-
162
- return defaultPerforationWidth;
163
- };
164
-
165
- export const findCementPlugInnerDiameterAtDepth = (
166
- attachedStrings: (Casing | Completion)[],
167
- nonAttachedStrings: (Casing | Completion)[],
168
- holes: HoleSize[],
169
- depth: number,
170
- ): number => {
171
- // Default to flow cement outside to show error in data
172
- const defaultCementWidth = 100;
173
- const attachedStringAtDepth = attachedStrings
174
- .sort((a: Casing | Completion, b: Casing | Completion) => getInnerStringDiameter(a) - getInnerStringDiameter(b)) // ascending
175
- .find((casingOrCompletion) => casingOrCompletion.start <= depth && casingOrCompletion.end >= depth);
176
-
177
- if (attachedStringAtDepth) {
178
- return getInnerStringDiameter(attachedStringAtDepth);
179
- }
180
-
181
- // Start from an attached diameter
182
- const minimumDiameter = attachedStrings.length ? Math.min(...attachedStrings.map((c) => getInnerStringDiameter(c))) : 0;
183
- const nonAttachedStringAtDepth = nonAttachedStrings
184
- .sort((a: Casing | Completion, b: Casing | Completion) => getInnerStringDiameter(a) - getInnerStringDiameter(b)) // ascending
185
- .find(
186
- (casingOrCompletion: Casing | Completion) =>
187
- casingOrCompletion.start <= depth && casingOrCompletion.end >= depth && minimumDiameter <= getInnerStringDiameter(casingOrCompletion),
188
- );
189
-
190
- if (nonAttachedStringAtDepth) {
191
- return getInnerStringDiameter(nonAttachedStringAtDepth);
192
- }
193
-
194
- const holeAtDepth = holes.find((hole) => hole.start <= depth && hole.end >= depth && hole.diameter);
195
-
196
- if (holeAtDepth) {
197
- return holeAtDepth.diameter;
198
- }
199
-
200
- return defaultCementWidth;
201
- };
202
-
203
- export const createComplexRopeSegmentsForCement = (
204
- cement: Cement,
205
- casings: Casing[],
206
- completion: Completion[],
207
- holes: HoleSize[],
208
- exaggerationFactor: number,
209
- getPoints: (start: number, end: number) => Point[],
210
- ): ComplexRopeSegment[] => {
211
- const { attachedStrings, nonAttachedStrings } = splitByReferencedStrings(cement.referenceIds, casings, completion);
212
-
213
- if (attachedStrings.length === 0) {
214
- throw new Error(`Invalid cement data, can't find referenced casing/completion string for cement with id '${cement.id}'`);
215
- }
216
-
217
- attachedStrings.sort((a: Casing, b: Casing) => a.end - b.end); // ascending
218
- const bottomOfCement = attachedStrings[attachedStrings.length - 1].end;
219
-
220
- const { overlappingOuterStrings, overlappingHoles } = findIntersectingItems(cement.toc, bottomOfCement, nonAttachedStrings, holes);
221
-
222
- const outerDiameterIntervals = [...overlappingOuterStrings, ...overlappingHoles].map((d) => ({
223
- start: d.start,
224
- end: d.end,
225
- }));
226
-
227
- const changeDepths = getUniqueDiameterChangeDepths([cement.toc, bottomOfCement], outerDiameterIntervals);
228
-
229
- const diameterIntervals = changeDepths.flatMap((depth: number, index: number, list: number[]) => {
230
- if (index === list.length - 1) {
231
- return [];
232
- }
233
-
234
- const nextDepth = list[index + 1];
235
- const diameterAtChangeDepth = findCementOuterDiameterAtDepth(attachedStrings, overlappingOuterStrings, overlappingHoles, depth);
236
-
237
- return [{ top: depth, bottom: nextDepth, diameter: diameterAtChangeDepth * exaggerationFactor }];
238
- });
239
-
240
- const ropeSegments = diameterIntervals.map((interval) => ({
241
- diameter: interval.diameter,
242
- points: getPoints(interval.top, interval.bottom),
243
- }));
244
-
245
- return ropeSegments;
246
- };
247
-
248
- const splitByReferencedStrings = (
249
- referenceIds: string[],
250
- casings: Casing[],
251
- completion: Completion[],
252
- ): { attachedStrings: (Casing | Completion)[]; nonAttachedStrings: (Casing | Completion)[] } =>
253
- [...casings, ...completion].reduce(
254
- (acc, current) => {
255
- if (referenceIds.includes(current.id)) {
256
- return { ...acc, attachedStrings: [...acc.attachedStrings, current] };
257
- }
258
- return { ...acc, nonAttachedStrings: [...acc.nonAttachedStrings, current] };
259
- },
260
- { attachedStrings: [], nonAttachedStrings: [] },
261
- );
262
-
263
- export const createComplexRopeSegmentsForCementSqueeze = (
264
- squeeze: CementSqueeze,
265
- casings: Casing[],
266
- completion: Completion[],
267
- holes: HoleSize[],
268
- exaggerationFactor: number,
269
- getPoints: (start: number, end: number) => Point[],
270
- ): ComplexRopeSegment[] => {
271
- const { attachedStrings, nonAttachedStrings } = splitByReferencedStrings(squeeze.referenceIds, casings, completion);
272
-
273
- if (attachedStrings.length === 0) {
274
- throw new Error(`Invalid cement squeeze data, can't find referenced casing/completion for squeeze with id '${squeeze.id}'`);
275
- }
276
-
277
- const { overlappingOuterStrings, overlappingHoles } = findIntersectingItems(squeeze.start, squeeze.end, nonAttachedStrings, holes);
278
-
279
- const outerDiameterIntervals = [...overlappingOuterStrings, ...overlappingHoles].map((d) => ({
280
- start: d.start,
281
- end: d.end,
282
- }));
283
-
284
- const changeDepths = getUniqueDiameterChangeDepths([squeeze.start, squeeze.end], outerDiameterIntervals);
285
-
286
- const diameterIntervals = changeDepths.flatMap((depth, index, list) => {
287
- if (index === list.length - 1) {
288
- return [];
289
- }
290
-
291
- const nextDepth = list[index + 1];
292
-
293
- const diameterAtDepth = findCementOuterDiameterAtDepth(attachedStrings, overlappingOuterStrings, overlappingHoles, depth);
294
-
295
- return [{ top: depth, bottom: nextDepth, diameter: diameterAtDepth * exaggerationFactor }];
296
- });
297
-
298
- const ropeSegments = diameterIntervals.map((interval) => ({
299
- diameter: interval.diameter,
300
- points: getPoints(interval.top, interval.bottom),
301
- }));
302
-
303
- return ropeSegments;
304
- };
305
-
306
- export const createComplexRopeSegmentsForCementPlug = (
307
- plug: CementPlug,
308
- casings: Casing[],
309
- completion: Completion[],
310
- holes: HoleSize[],
311
- exaggerationFactor: number,
312
- getPoints: (start: number, end: number) => Point[],
313
- ): ComplexRopeSegment[] => {
314
- const { attachedStrings, nonAttachedStrings } = splitByReferencedStrings(plug.referenceIds, casings, completion);
315
-
316
- const { overlappingHoles, overlappingOuterStrings } = findIntersectingItems(plug.start, plug.end, nonAttachedStrings, holes);
317
- const innerDiameterIntervals = [...attachedStrings, ...overlappingHoles, ...overlappingOuterStrings].map((d) => ({
318
- start: d.start,
319
- end: d.end,
320
- }));
321
-
322
- const changeDepths = getUniqueDiameterChangeDepths([plug.start, plug.end], innerDiameterIntervals);
323
-
324
- const diameterIntervals = changeDepths.flatMap((depth, index, list) => {
325
- if (index === list.length - 1) {
326
- return [];
327
- }
328
-
329
- const nextDepth = list[index + 1];
330
- const diameterAtDepth = findCementPlugInnerDiameterAtDepth(attachedStrings, overlappingOuterStrings, overlappingHoles, depth);
331
-
332
- return [{ top: depth, bottom: nextDepth, diameter: diameterAtDepth * exaggerationFactor }];
333
- });
334
-
335
- const ropeSegments = diameterIntervals.map((interval) => ({
336
- diameter: interval.diameter,
337
- points: getPoints(interval.top, interval.bottom),
338
- }));
339
-
340
- return ropeSegments;
341
- };
342
-
343
- const createGradientFill = (
344
- canvas: HTMLCanvasElement,
345
- canvasCtx: CanvasRenderingContext2D,
346
- firstColor: string,
347
- secondColor: string,
348
- startPctOffset: number,
349
- ): CanvasGradient => {
350
- const halfWayPct = 0.5;
351
- const gradient = canvasCtx.createLinearGradient(0, 0, 0, canvas.height);
352
- gradient.addColorStop(0, firstColor);
353
- gradient.addColorStop(halfWayPct - startPctOffset, secondColor);
354
- gradient.addColorStop(halfWayPct + startPctOffset, secondColor);
355
- gradient.addColorStop(1, firstColor);
356
-
357
- return gradient;
358
- };
359
-
360
- export const createHoleBaseTexture = ({ firstColor, secondColor }: HoleOptions, width: number, height: number): Texture => {
361
- const canvas = document.createElement('canvas');
362
- canvas.width = width;
363
- canvas.height = height;
364
- const canvasCtx = canvas.getContext('2d');
365
-
366
- canvasCtx.fillStyle = createGradientFill(canvas, canvasCtx, firstColor, secondColor, 0);
367
- canvasCtx.fillRect(0, 0, canvas.width, canvas.height);
368
-
369
- return Texture.from(canvas);
370
- };
371
-
372
- export const createScreenTexture = ({ scalingFactor }: ScreenOptions): Texture => {
373
- const canvas = document.createElement('canvas');
374
- const size = DEFAULT_TEXTURE_SIZE * scalingFactor;
375
- canvas.width = size;
376
- canvas.height = size;
377
- const canvasCtx = canvas.getContext('2d');
378
-
379
- canvasCtx.fillStyle = 'white';
380
- canvasCtx.fillRect(0, 0, canvas.width, canvas.height);
381
-
382
- const baseLineWidth = size / 10; // eslint-disable-line no-magic-numbers
383
- canvasCtx.strokeStyle = '#AAAAAA';
384
- canvasCtx.lineWidth = baseLineWidth;
385
- canvasCtx.beginPath();
386
-
387
- const distanceBetweenLines = size / 3;
388
- for (let i = -canvas.width; i < canvas.width; i++) {
389
- canvasCtx.moveTo(-canvas.width + distanceBetweenLines * i, -canvas.height);
390
- canvasCtx.lineTo(canvas.width + distanceBetweenLines * i, canvas.height * 2);
391
- }
392
- canvasCtx.stroke();
393
- return Texture.from(canvas);
394
- };
395
-
396
- export const createTubingTexture = ({ innerColor, outerColor, scalingFactor }: TubingOptions): Texture => {
397
- const size = DEFAULT_TEXTURE_SIZE * scalingFactor;
398
-
399
- const canvas = document.createElement('canvas');
400
- canvas.width = size;
401
- canvas.height = size;
402
- const canvasCtx = canvas.getContext('2d');
403
- const gradient = canvasCtx.createLinearGradient(0, 0, 0, size);
404
-
405
- const innerColorStart = 0.3;
406
- const innerColorEnd = 0.7;
407
- gradient.addColorStop(0, outerColor);
408
- gradient.addColorStop(innerColorStart, innerColor);
409
- gradient.addColorStop(innerColorEnd, innerColor);
410
- gradient.addColorStop(1, outerColor);
411
-
412
- canvasCtx.fillStyle = gradient;
413
- canvasCtx.fillRect(0, 0, canvas.width, canvas.height);
414
-
415
- return Texture.from(canvas);
416
- };
417
-
418
- export const createCementTexture = ({ firstColor, secondColor, scalingFactor }: CementOptions): Texture => {
419
- const canvas = document.createElement('canvas');
420
-
421
- const size = DEFAULT_TEXTURE_SIZE * scalingFactor;
422
- const lineWidth = scalingFactor;
423
- canvas.width = size;
424
- canvas.height = size;
425
- const canvasCtx = canvas.getContext('2d');
426
-
427
- canvasCtx.fillStyle = firstColor;
428
- canvasCtx.fillRect(0, 0, canvas.width, canvas.height);
429
- canvasCtx.lineWidth = lineWidth;
430
- canvasCtx.fillStyle = secondColor;
431
- canvasCtx.beginPath();
432
-
433
- const distanceBetweenLines = size / 12; // eslint-disable-line no-magic-numbers
434
- for (let i = -canvas.width; i < canvas.width; i++) {
435
- canvasCtx.moveTo(-canvas.width + distanceBetweenLines * i, -canvas.height);
436
- canvasCtx.lineTo(canvas.width + distanceBetweenLines * i, canvas.height);
437
- }
438
- canvasCtx.stroke();
439
-
440
- return Texture.from(canvas);
441
- };
442
-
443
- export const createCementPlugTexture = ({ firstColor, secondColor, scalingFactor }: CementPlugOptions): Texture => {
444
- const canvas = document.createElement('canvas');
445
-
446
- const size = DEFAULT_TEXTURE_SIZE * scalingFactor;
447
- canvas.width = size;
448
- canvas.height = size;
449
- const canvasCtx = canvas.getContext('2d');
450
-
451
- canvasCtx.fillStyle = firstColor;
452
- canvasCtx.fillRect(0, 0, canvas.width, canvas.height);
453
- canvasCtx.lineWidth = scalingFactor;
454
- canvasCtx.strokeStyle = secondColor;
455
- canvasCtx.beginPath();
456
-
457
- canvasCtx.setLineDash([20, 10]); // eslint-disable-line no-magic-numbers
458
- const distanceBetweenLines = size / 12; // eslint-disable-line no-magic-numbers
459
- for (let i = -canvas.width; i < canvas.width; i++) {
460
- canvasCtx.moveTo(-canvas.width + distanceBetweenLines * i, -canvas.height);
461
- canvasCtx.lineTo(canvas.width + distanceBetweenLines * i, canvas.height * 2);
462
- }
463
- canvasCtx.stroke();
464
-
465
- return Texture.from(canvas);
466
- };
467
-
468
- export const createCementSqueezeTexture = ({ firstColor, secondColor, scalingFactor }: CementSqueezeOptions): Texture => {
469
- const canvas = document.createElement('canvas');
470
-
471
- const size = DEFAULT_TEXTURE_SIZE * scalingFactor;
472
- const lineWidth = scalingFactor;
473
- canvas.width = size;
474
- canvas.height = size;
475
-
476
- const canvasCtx = canvas.getContext('2d');
477
- canvasCtx.lineWidth = lineWidth;
478
- canvasCtx.fillStyle = firstColor;
479
- canvasCtx.strokeStyle = secondColor;
480
-
481
- canvasCtx.fillRect(0, 0, canvas.width, canvas.height);
482
- canvasCtx.beginPath();
483
-
484
- canvasCtx.setLineDash([20, 10]); // eslint-disable-line no-magic-numbers
485
- const distanceBetweenLines = size / 12; // eslint-disable-line no-magic-numbers
486
- for (let i = -canvas.width; i < canvas.width; i++) {
487
- canvasCtx.moveTo(-canvas.width + distanceBetweenLines * i, -canvas.height);
488
- canvasCtx.lineTo(canvas.width + distanceBetweenLines * i, canvas.height * 2);
489
- }
490
- canvasCtx.stroke();
491
-
492
- return Texture.from(canvas);
493
- };
494
-
495
- export const createTubularRenderingObject = (radius: number, pathPoints: IPoint[]): TubularRenderingObject => {
496
- const normals = createNormals(pathPoints);
497
- const rightPath = offsetPoints(pathPoints, normals, radius);
498
- const leftPath = offsetPoints(pathPoints, normals, -radius);
499
-
500
- return { leftPath, rightPath };
501
- };
502
-
503
- export type CasingInterval = {
504
- kind: 'casing' | 'casing-window';
505
- start: number;
506
- end: number;
507
- };
508
-
509
- const createCasingInterval = (start: number, end: number): CasingInterval => ({ kind: 'casing', start, end });
510
- const createCasingWindowInterval = (start: number, end: number): CasingInterval => ({ kind: 'casing-window', start, end });
511
-
512
- export const getCasingIntervalsWithWindows = (casing: Casing): CasingInterval[] => {
513
- const result = (casing.windows || [])
514
- .filter((cw: CasingWindow) => strictlyOverlaps(casing.start, casing.end, cw.start, cw.end))
515
- .reduce<{ intervals: CasingInterval[]; lastBottom: number }>(
516
- ({ intervals, lastBottom }, currentWindow: CasingWindow, index: number, list: CasingWindow[]) => {
517
- const startCasingInterval: CasingInterval | null =
518
- // last bottom before current start?
519
- lastBottom < currentWindow.start ? createCasingInterval(lastBottom, currentWindow.start) : null;
520
-
521
- const updatedLastBottom = startCasingInterval ? startCasingInterval.end : lastBottom;
522
-
523
- const windowStart = Math.max(updatedLastBottom, currentWindow.start);
524
- const windowEnd = Math.min(casing.end, currentWindow.end);
525
- const windowInterval: CasingInterval = createCasingWindowInterval(windowStart, windowEnd);
526
-
527
- const nextLastBottom = windowEnd;
528
-
529
- const isLastWindow = index === list.length - 1;
530
- const endCasingInterval: CasingInterval | null =
531
- isLastWindow &&
532
- // still room for a casing interval?
533
- nextLastBottom < casing.end
534
- ? createCasingInterval(nextLastBottom, casing.end)
535
- : null;
536
-
537
- const newIntervals: CasingInterval[] = [startCasingInterval, windowInterval, endCasingInterval].filter((i) => i);
538
-
539
- return { intervals: [...intervals, ...newIntervals], lastBottom: nextLastBottom };
540
- },
541
- { intervals: [], lastBottom: casing.start },
542
- );
543
-
544
- if (!result.intervals.length) {
545
- return [createCasingInterval(casing.start, casing.end)];
546
- }
547
-
548
- return result.intervals;
549
- };
550
-
551
- export const prepareCasingRenderObject = (
552
- exaggerationFactor: number,
553
- casing: Casing,
554
- getPathPoints: (start: number, end: number) => Point[],
555
- ): CasingRenderObject => {
556
- const exaggeratedDiameter = casing.diameter * exaggerationFactor;
557
- const exaggeratedRadius = exaggeratedDiameter / 2;
558
- const exaggeratedInnerDiameter = casing.innerDiameter * exaggerationFactor;
559
- const exaggeratedInnerRadius = exaggeratedInnerDiameter / 2;
560
- const casingWallWidth = exaggeratedRadius - exaggeratedInnerRadius;
561
-
562
- const sections = getCasingIntervalsWithWindows(casing).map((casingInterval: CasingInterval) => {
563
- const pathPoints = getPathPoints(casingInterval.start, casingInterval.end);
564
- const { leftPath, rightPath } = createTubularRenderingObject(exaggeratedRadius, pathPoints);
565
- return { kind: casingInterval.kind, leftPath, rightPath, pathPoints };
566
- });
567
-
568
- return {
569
- kind: 'casing',
570
- id: casing.id,
571
- referenceDiameter: exaggeratedDiameter,
572
- referenceRadius: exaggeratedRadius,
573
- sections,
574
- casingWallWidth,
575
- hasShoe: casing.hasShoe,
576
- bottom: casing.end,
577
- };
578
- };
579
-
580
- export const createComplexRopeSegmentsForPerforation = (
581
- perforation: Perforation,
582
- casings: Casing[],
583
- holes: HoleSize[],
584
- exaggerationFactor: number,
585
- getPoints: (start: number, end: number) => Point[],
586
- ): ComplexRopeSegment[] => {
587
- const { overlappingOuterStrings, overlappingHoles } = findIntersectingItems(perforation.start, perforation.end, casings, holes);
588
-
589
- const outerDiameterIntervals = [...overlappingOuterStrings, ...overlappingHoles].map((d) => ({
590
- start: d.start,
591
- end: d.end,
592
- }));
593
-
594
- const changeDepths = getUniqueDiameterChangeDepths([perforation.start, perforation.end], outerDiameterIntervals);
595
-
596
- const diameterIntervals = changeDepths.flatMap((depth, index, list) => {
597
- if (index === list.length - 1) {
598
- return [];
599
- }
600
-
601
- const nextDepth = list[index + 1];
602
-
603
- const diameterAtDepth = findPerforationOuterDiameterAtDepth(overlappingOuterStrings, overlappingHoles, depth, perforation.subKind);
604
-
605
- return [{ top: depth, bottom: nextDepth, diameter: diameterAtDepth * exaggerationFactor }];
606
- });
607
-
608
- const ropeSegments = diameterIntervals.map((interval) => {
609
- const points = getPoints(interval.top, interval.bottom);
610
-
611
- const diameter = interval.diameter;
612
-
613
- return {
614
- diameter,
615
- points,
616
- };
617
- });
618
-
619
- return ropeSegments;
620
- };
621
-
622
- const drawPacking = (canvas: HTMLCanvasElement, ctx: CanvasRenderingContext2D, perforationOptions: PerforationOptions) => {
623
- const { packingOpacity, yellow } = perforationOptions;
624
-
625
- ctx.fillStyle = yellow;
626
- ctx.strokeStyle = yellow;
627
-
628
- const xy: [number, number] = [0, 0];
629
- const wh: [number, number] = [canvas.width, canvas.height];
630
- ctx.save();
631
- ctx.globalAlpha = packingOpacity;
632
- ctx.fillRect(...xy, ...wh);
633
- ctx.restore();
634
- };
635
-
636
- const drawFracLines = (
637
- canvas: HTMLCanvasElement,
638
- ctx: CanvasRenderingContext2D,
639
- extendedPerfShapeDiameter: number,
640
- perforationOptions: PerforationOptions,
641
- startAt: 'diameter' | 'spike',
642
- ) => {
643
- const { fracLineCurve } = perforationOptions;
644
-
645
- const amountOfSpikes = 10;
646
- const spikeWidth = canvas.width / amountOfSpikes;
647
-
648
- const diameter = (extendedPerfShapeDiameter / 3) * perforationOptions.scalingFactor;
649
-
650
- const fracLineLength = diameter / 4;
651
- const spikeLength = diameter / 2;
652
- const offsetX = 0;
653
- const offsetY = startAt === 'diameter' ? 0 : spikeLength;
654
-
655
- const fracLines = () => {
656
- for (let i = -1; i < amountOfSpikes; i++) {
657
- const bottom: [number, number] = [i * spikeWidth + offsetX + spikeWidth / 2, canvas.height / 2 - fracLineLength - offsetY - fracLineLength];
658
-
659
- ctx.beginPath();
660
-
661
- const start: [number, number] = [...bottom];
662
- const controlPoint1: [number, number] = [bottom[0] - fracLineCurve * 2, bottom[1] - fracLineLength / 4];
663
- const middle: [number, number] = [bottom[0], bottom[1] - fracLineLength / 2];
664
-
665
- const controlPoint2: [number, number] = [bottom[0] + fracLineCurve * 2, bottom[1] - fracLineLength / 2 - fracLineLength / 4];
666
- const end: [number, number] = [bottom[0], bottom[1] - fracLineLength];
667
-
668
- ctx.bezierCurveTo(...start, ...controlPoint1, ...middle);
669
- ctx.bezierCurveTo(...middle, ...controlPoint2, ...end);
670
-
671
- ctx.stroke();
672
- }
673
-
674
- for (let i = -1; i < amountOfSpikes; i++) {
675
- const bottom: [number, number] = [i * spikeWidth + spikeWidth + offsetX + spikeWidth / 2, canvas.height / 2 + diameter / 2 + offsetY];
676
-
677
- ctx.beginPath();
678
-
679
- const start: [number, number] = [...bottom];
680
- const controlPoint1: [number, number] = [bottom[0] - fracLineCurve * 2, bottom[1] + fracLineLength / 4];
681
- const middle: [number, number] = [bottom[0], bottom[1] + fracLineLength / 2];
682
-
683
- const controlPoint2: [number, number] = [bottom[0] + fracLineCurve * 2, bottom[1] + fracLineLength / 2 + fracLineLength / 4];
684
- const end: [number, number] = [bottom[0], bottom[1] + fracLineLength];
685
-
686
- ctx.bezierCurveTo(...start, ...controlPoint1, ...middle);
687
- ctx.bezierCurveTo(...middle, ...controlPoint2, ...end);
688
-
689
- ctx.stroke();
690
- }
691
- };
692
-
693
- ctx.strokeStyle = perforationOptions.yellow;
694
- ctx.lineWidth = 6;
695
- ctx.save();
696
- ctx.globalAlpha = perforationOptions.packingOpacity;
697
- fracLines();
698
- ctx.restore();
699
- ctx.lineWidth = 1;
700
- ctx.strokeStyle = perforationOptions.outline;
701
- fracLines();
702
-
703
- ctx.closePath();
704
- };
705
-
706
- const drawSpikes = (
707
- canvas: HTMLCanvasElement,
708
- ctx: CanvasRenderingContext2D,
709
- extendedPerfShapeDiameter: number,
710
- perforationOptions: PerforationOptions,
711
- ) => {
712
- const amountOfSpikes = 10;
713
- const spikeWidth = canvas.width / amountOfSpikes;
714
- ctx.strokeStyle = perforationOptions.outline;
715
-
716
- const diameter = (extendedPerfShapeDiameter / 3) * perforationOptions.scalingFactor;
717
-
718
- ctx.lineWidth = 1;
719
- const spikeLength = diameter / 2;
720
- const offsetX = 0;
721
-
722
- // left spikes
723
- for (let i = 0; i <= amountOfSpikes; i++) {
724
- const left: [number, number] = [i * spikeWidth + offsetX, canvas.height / 2 - diameter / 2];
725
- const bottom: [number, number] = [left[0] - spikeWidth / 2, left[1] - spikeLength];
726
- const right: [number, number] = [left[0] - spikeWidth, left[1]];
727
-
728
- ctx.beginPath();
729
- ctx.moveTo(...left);
730
- ctx.lineTo(...bottom);
731
- ctx.lineTo(...right);
732
- ctx.fill();
733
-
734
- ctx.lineWidth = 1;
735
- ctx.stroke();
736
- }
737
-
738
- // right spikes
739
- for (let i = 0; i <= amountOfSpikes; i++) {
740
- const left: [number, number] = [i * spikeWidth + offsetX, canvas.height / 2 + diameter / 2];
741
- const bottom: [number, number] = [left[0] - spikeWidth / 2, left[1] + spikeLength];
742
- const right: [number, number] = [left[0] - spikeWidth, left[1]];
743
-
744
- ctx.beginPath();
745
- ctx.moveTo(...left);
746
- ctx.lineTo(...bottom);
747
- ctx.lineTo(...right);
748
- ctx.fill();
749
-
750
- ctx.lineWidth = 1;
751
- ctx.stroke();
752
- }
753
-
754
- ctx.closePath();
755
- };
756
-
757
- // for visual debugging
758
- // if this shoes up, something is wrong
759
- const errorTexture = (errorMessage = 'Error!', existingContext?: { canvas: HTMLCanvasElement; canvasCtx: CanvasRenderingContext2D }) => {
760
- console.error(`${errorMessage}`);
761
- const canvas = existingContext?.canvas || document.createElement('canvas');
762
-
763
- const size = DEFAULT_TEXTURE_SIZE;
764
- canvas.width = size / 2;
765
- canvas.height = size;
766
- const canvasCtx = existingContext?.canvasCtx || canvas.getContext('2d');
767
-
768
- const xy: [number, number] = [0, 0];
769
- const wh: [number, number] = [canvas.width, canvas.height];
770
-
771
- canvasCtx.fillStyle = '#ff00ff';
772
- canvasCtx.fillRect(...xy, ...wh);
773
-
774
- const texture = new Texture(
775
- Texture.from(canvas, { wrapMode: WRAP_MODES.CLAMP }).baseTexture,
776
- null,
777
- new Rectangle(0, 0, canvas.width, canvas.height),
778
- null,
779
- groupD8.MIRROR_HORIZONTAL,
780
- );
781
- return texture;
782
- };
783
-
784
- const createPerforationCanvas = (
785
- perfShape: ComplexRopeSegment,
786
- options: PerforationOptions,
787
- ): { canvas: HTMLCanvasElement; ctx: CanvasRenderingContext2D } => {
788
- const canvas = document.createElement('canvas');
789
- const perfShapeDiameter = perfShape.diameter;
790
- const size = perfShapeDiameter * options.scalingFactor;
791
- canvas.width = size / 2;
792
- canvas.height = size;
793
- const ctx = canvas.getContext('2d');
794
-
795
- return { canvas, ctx };
796
- };
797
-
798
- const createPerforationTexture = (canvas: HTMLCanvasElement) => {
799
- const texture = new Texture(
800
- Texture.from(canvas, { wrapMode: WRAP_MODES.CLAMP }).baseTexture,
801
- null,
802
- new Rectangle(0, 0, canvas.width, canvas.height),
803
- null,
804
- groupD8.MIRROR_HORIZONTAL,
805
- );
806
- return texture;
807
- };
808
-
809
- /**
810
- * @Perforation
811
- * If a perforation does not overlap with another perforations of type with gravel,
812
- * the perforation spikes are either red when open or grey when closed.
813
- * Open and closed refers to two fields on a perforation item referencing runs.
814
- *
815
- * If a perforation overlaps with another perforation of type with gravel and the perforation is open,
816
- * the perforation spikes should be yellow. If closed the perforation remains grey.
817
- *
818
- * Cased Hole Frac Pack:
819
- * Makes perforations of type "Perforation" yellow if overlapping and perforation are open.
820
- * If a perforation of type "perforation" is overlapping, the fracturation lines extends from the tip of the perforation spikes into formation.
821
- *
822
- * Cased Hole Gravel Pack:
823
- * Yellow gravel. Makes perforations of type "Perforation" yellow if overlapping and perforation are open.
824
- */
825
- const createSubkindPerforationTexture = {
826
- packing: () => errorTexture(),
827
- fracLines: () => errorTexture(),
828
- spikes: (
829
- perforation: Perforation,
830
- perfShape: ComplexRopeSegment,
831
- otherPerforations: Perforation[],
832
- perforationOptions: PerforationOptions,
833
- ): Texture => {
834
- const { canvas, ctx } = createPerforationCanvas(perfShape, perforationOptions);
835
-
836
- const intersectionsWithCasedHoleGravel: boolean = otherPerforations.some(
837
- (perf) => isSubkindCasedHoleGravelPack(perf) && intersect(perforation, perf),
838
- );
839
-
840
- const intersectionsWithCasedHoleFracPack: boolean = otherPerforations.some(
841
- (perf) => isSubKindCasedHoleFracPack(perf) && intersect(perforation, perf),
842
- );
843
-
844
- const shouldDrawFracLines = intersectionsWithCasedHoleGravel || intersectionsWithCasedHoleFracPack;
845
-
846
- if (shouldDrawFracLines) {
847
- if (perforation.isOpen) {
848
- ctx.fillStyle = perforationOptions.yellow;
849
- ctx.strokeStyle = perforationOptions.yellow;
850
- } else {
851
- ctx.fillStyle = perforationOptions.grey;
852
- ctx.strokeStyle = perforationOptions.grey;
853
- }
854
- } else {
855
- if (perforation.isOpen) {
856
- ctx.fillStyle = perforationOptions.red;
857
- ctx.strokeStyle = perforationOptions.red;
858
- } else {
859
- ctx.fillStyle = perforationOptions.grey;
860
- ctx.strokeStyle = perforationOptions.grey;
861
- }
862
- }
863
-
864
- drawSpikes(canvas, ctx, perfShape.diameter, perforationOptions);
865
-
866
- if (intersectionsWithCasedHoleFracPack) {
867
- drawFracLines(canvas, ctx, perfShape.diameter, perforationOptions, 'spike');
868
- }
869
-
870
- return createPerforationTexture(canvas);
871
- },
872
- };
873
-
874
- /**
875
- * @Cased_hole_fracturation
876
- * Yellow fracturation lines from casing OD into formation
877
- */
878
- const createSubkindCasedHoleFracturationTexture = {
879
- packing: () => errorTexture(),
880
- fracLines: (perfShape: ComplexRopeSegment, perforationOptions: PerforationOptions): Texture => {
881
- const { canvas, ctx } = createPerforationCanvas(perfShape, perforationOptions);
882
- drawFracLines(canvas, ctx, perfShape.diameter, perforationOptions, 'diameter');
883
- return createPerforationTexture(canvas);
884
- },
885
- spikes: () => errorTexture(),
886
- };
887
-
888
- /**
889
- * @Cased_hole_frac_pack
890
- * Yellow gravel and fracturation lines.
891
- * Makes perforations of type "Perforation" yellow if overlapping and perforation are open.
892
- * If no perforation of type "perforation" are overlapping, there are no fracturation lines and no spikes.
893
- * If a perforation of type "perforation" is overlapping, the fracturation lines extends from the tip of the perforation spikes into formation.
894
- */
895
- const createSubkindCasedHoleFracPackTexture = {
896
- packing: (perfShape: ComplexRopeSegment, perforationOptions: PerforationOptions): Texture => {
897
- const { canvas, ctx } = createPerforationCanvas(perfShape, perforationOptions);
898
- drawPacking(canvas, ctx, perforationOptions);
899
- return createPerforationTexture(canvas);
900
- },
901
- fracLines: (perfShape: ComplexRopeSegment, perforationOptions: PerforationOptions) => {
902
- const { canvas } = createPerforationCanvas(perfShape, perforationOptions);
903
- return createPerforationTexture(canvas);
904
- },
905
- spikes: () => errorTexture(),
906
- };
907
-
908
- /**
909
- * @Cased_hole_gravel_pack
910
- * Yellow gravel. Makes perforations of type "Perforation" yellow if overlapping and perforation are open.
911
- */
912
- const createSubkindCasedHoleGravelPackTexture = {
913
- packing: (perfShape: ComplexRopeSegment, perforationOptions: PerforationOptions): Texture => {
914
- const { canvas, ctx } = createPerforationCanvas(perfShape, perforationOptions);
915
- drawPacking(canvas, ctx, perforationOptions);
916
- return createPerforationTexture(canvas);
917
- },
918
- fracLines: () => errorTexture(),
919
- spikes: () => errorTexture(),
920
- };
921
-
922
- /**
923
- * @Open_hole_gravel_pack
924
- * Yellow gravel
925
- */
926
- const createSubkindOpenHoleGravelPackTexture = {
927
- packing: (perfShape: ComplexRopeSegment, perforationOptions: PerforationOptions) => {
928
- const { canvas, ctx } = createPerforationCanvas(perfShape, perforationOptions);
929
- drawPacking(canvas, ctx, perforationOptions);
930
- return createPerforationTexture(canvas);
931
- },
932
- fracLines: () => errorTexture(),
933
- spikes: () => errorTexture(),
934
- };
935
-
936
- /**
937
- * @Open_hole_frac_pack
938
- * Yellow gravel. Yellow frac lines from hole OD into formation
939
- */
940
- const createSubkindOpenHoleFracPackTexture = {
941
- packing: (_perforation: Perforation, perfShape: ComplexRopeSegment, perforationOptions: PerforationOptions) => {
942
- const { canvas, ctx } = createPerforationCanvas(perfShape, perforationOptions);
943
- drawPacking(canvas, ctx, perforationOptions);
944
- return createPerforationTexture(canvas);
945
- },
946
- fracLines: (perfShape: ComplexRopeSegment, perforationOptions: PerforationOptions): Texture => {
947
- const { canvas, ctx } = createPerforationCanvas(perfShape, perforationOptions);
948
- drawFracLines(canvas, ctx, perfShape.diameter, perforationOptions, 'diameter');
949
- return createPerforationTexture(canvas);
950
- },
951
- spikes: () => errorTexture(),
952
- };
953
-
954
- export const createPerforationPackingTexture = (
955
- perforation: Perforation,
956
- perfShape: ComplexRopeSegment,
957
- perforationOptions: PerforationOptions,
958
- ): Texture => {
959
- return foldPerforationSubKind(
960
- {
961
- Perforation: () => createSubkindPerforationTexture.packing(),
962
- CasedHoleFracturation: () => createSubkindCasedHoleFracPackTexture.packing(perfShape, perforationOptions),
963
- CasedHoleFracPack: () => createSubkindCasedHoleFracPackTexture.packing(perfShape, perforationOptions),
964
- OpenHoleGravelPack: () => createSubkindOpenHoleGravelPackTexture.packing(perfShape, perforationOptions),
965
- OpenHoleFracPack: () => createSubkindOpenHoleFracPackTexture.packing(perforation, perfShape, perforationOptions),
966
- CasedHoleGravelPack: () => createSubkindCasedHoleGravelPackTexture.packing(perfShape, perforationOptions),
967
- },
968
- perforation.subKind,
969
- );
970
- };
971
-
972
- export const createPerforationFracLineTexture = (
973
- perforation: Perforation,
974
- perfShape: ComplexRopeSegment,
975
- perforationOptions: PerforationOptions,
976
- ): Texture => {
977
- return foldPerforationSubKind(
978
- {
979
- Perforation: () => createSubkindPerforationTexture.fracLines(),
980
- OpenHoleGravelPack: () => createSubkindOpenHoleGravelPackTexture.fracLines(),
981
- OpenHoleFracPack: () => createSubkindOpenHoleFracPackTexture.fracLines(perfShape, perforationOptions),
982
- CasedHoleFracturation: () => createSubkindCasedHoleFracturationTexture.fracLines(perfShape, perforationOptions),
983
- CasedHoleGravelPack: () => createSubkindCasedHoleGravelPackTexture.fracLines(),
984
- CasedHoleFracPack: () => createSubkindCasedHoleFracPackTexture.fracLines(perfShape, perforationOptions),
985
- },
986
- perforation.subKind,
987
- );
988
- };
989
-
990
- export const createPerforationSpikeTexture = (
991
- perforation: Perforation,
992
- otherPerforations: Perforation[],
993
- perfShape: ComplexRopeSegment,
994
- perforationOptions: PerforationOptions,
995
- ): Texture => {
996
- return foldPerforationSubKind(
997
- {
998
- Perforation: () => createSubkindPerforationTexture.spikes(perforation, perfShape, otherPerforations, perforationOptions),
999
- OpenHoleGravelPack: () => createSubkindOpenHoleGravelPackTexture.spikes(),
1000
- OpenHoleFracPack: () => createSubkindOpenHoleFracPackTexture.spikes(),
1001
- CasedHoleFracturation: () => createSubkindCasedHoleFracturationTexture.spikes(),
1002
- CasedHoleGravelPack: () => createSubkindCasedHoleGravelPackTexture.spikes(),
1003
- CasedHoleFracPack: () => createSubkindCasedHoleFracPackTexture.spikes(),
1004
- },
1005
- perforation.subKind,
1006
- );
1007
- };