@equinor/esv-intersection 4.0.0 → 4.1.0
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.map +1 -1
- package/dist/index.mjs +1240 -282
- package/dist/index.mjs.map +1 -1
- 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 +2 -4
- 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
|
@@ -59,13 +59,26 @@ export const getEndLines = (
|
|
|
59
59
|
} => {
|
|
60
60
|
return {
|
|
61
61
|
top: [rightPath[0], leftPath[0]],
|
|
62
|
-
bottom: [
|
|
62
|
+
bottom: [
|
|
63
|
+
rightPath[rightPath.length - 1] as Point,
|
|
64
|
+
leftPath[leftPath.length - 1] as Point,
|
|
65
|
+
],
|
|
63
66
|
};
|
|
64
67
|
};
|
|
65
68
|
|
|
66
|
-
export const overlaps = (
|
|
69
|
+
export const overlaps = (
|
|
70
|
+
top1: number,
|
|
71
|
+
bottom1: number,
|
|
72
|
+
top2: number,
|
|
73
|
+
bottom2: number,
|
|
74
|
+
): boolean => top1 <= bottom2 && top2 <= bottom1;
|
|
67
75
|
|
|
68
|
-
export const strictlyOverlaps = (
|
|
76
|
+
export const strictlyOverlaps = (
|
|
77
|
+
top1: number,
|
|
78
|
+
bottom1: number,
|
|
79
|
+
top2: number,
|
|
80
|
+
bottom2: number,
|
|
81
|
+
): boolean => top1 < bottom2 && top2 < bottom1;
|
|
69
82
|
|
|
70
83
|
export const uniq = <T>(arr: T[]): T[] => Array.from<T>(new Set(arr));
|
|
71
84
|
|
|
@@ -74,10 +87,18 @@ const findIntersectingItems = (
|
|
|
74
87
|
end: number,
|
|
75
88
|
otherStrings: (Casing | Completion)[],
|
|
76
89
|
holes: HoleSize[],
|
|
77
|
-
): {
|
|
78
|
-
|
|
90
|
+
): {
|
|
91
|
+
overlappingHoles: HoleSize[];
|
|
92
|
+
overlappingOuterStrings: (Casing | Completion)[];
|
|
93
|
+
} => {
|
|
94
|
+
const overlappingHoles = holes.filter((hole: HoleSize) =>
|
|
95
|
+
overlaps(start, end, hole.start, hole.end),
|
|
96
|
+
);
|
|
79
97
|
|
|
80
|
-
const overlappingOuterStrings = otherStrings.filter(
|
|
98
|
+
const overlappingOuterStrings = otherStrings.filter(
|
|
99
|
+
(casing: Casing | Completion) =>
|
|
100
|
+
overlaps(start, end, casing.start, casing.end),
|
|
101
|
+
);
|
|
81
102
|
|
|
82
103
|
return {
|
|
83
104
|
overlappingHoles,
|
|
@@ -95,7 +116,9 @@ export const getUniqueDiameterChangeDepths = (
|
|
|
95
116
|
d, // to find diameter right before/after object
|
|
96
117
|
) => [d.start - epsilon, d.start, d.end, d.end + epsilon],
|
|
97
118
|
);
|
|
98
|
-
const trimmedChangedDepths = diameterChangeDepths.filter(
|
|
119
|
+
const trimmedChangedDepths = diameterChangeDepths.filter(
|
|
120
|
+
d => d >= intervalStart && d <= intervalEnd,
|
|
121
|
+
); // trim
|
|
99
122
|
|
|
100
123
|
trimmedChangedDepths.push(intervalStart);
|
|
101
124
|
trimmedChangedDepths.push(intervalEnd);
|
|
@@ -116,16 +139,30 @@ export const findCementOuterDiameterAtDepth = (
|
|
|
116
139
|
const defaultCementWidth = 100; // Default to flow cement outside to show error in data
|
|
117
140
|
|
|
118
141
|
const attachedStringAtDepth = attachedStrings.find(
|
|
119
|
-
(casingOrCompletion: Casing | Completion) =>
|
|
142
|
+
(casingOrCompletion: Casing | Completion) =>
|
|
143
|
+
casingOrCompletion.start <= depth && casingOrCompletion.end >= depth,
|
|
120
144
|
);
|
|
121
|
-
const attachedOuterDiameter = attachedStringAtDepth
|
|
145
|
+
const attachedOuterDiameter = attachedStringAtDepth
|
|
146
|
+
? attachedStringAtDepth.diameter
|
|
147
|
+
: 0;
|
|
122
148
|
|
|
123
149
|
const outerCasingAtDepth = nonAttachedStrings
|
|
124
|
-
.filter(
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
150
|
+
.filter(
|
|
151
|
+
(casingOrCompletion: Casing | Completion) =>
|
|
152
|
+
getInnerStringDiameter(casingOrCompletion) > attachedOuterDiameter,
|
|
153
|
+
)
|
|
154
|
+
.sort(
|
|
155
|
+
(a: Casing | Completion, b: Casing | Completion) =>
|
|
156
|
+
getInnerStringDiameter(a) - getInnerStringDiameter(b),
|
|
157
|
+
) // ascending
|
|
158
|
+
.find(casing => casing.start <= depth && casing.end >= depth);
|
|
159
|
+
|
|
160
|
+
const holeAtDepth = holes.find(
|
|
161
|
+
(hole: HoleSize) =>
|
|
162
|
+
hole.start <= depth &&
|
|
163
|
+
hole.end >= depth &&
|
|
164
|
+
hole.diameter > attachedOuterDiameter,
|
|
165
|
+
);
|
|
129
166
|
|
|
130
167
|
if (outerCasingAtDepth) {
|
|
131
168
|
return getInnerStringDiameter(outerCasingAtDepth);
|
|
@@ -147,12 +184,21 @@ export const findPerforationOuterDiameterAtDepth = (
|
|
|
147
184
|
const defaultPerforationWidth = 100; // Default to flow perforation outside to show error in data
|
|
148
185
|
|
|
149
186
|
const outerCasingAtDepth = nonAttachedStrings
|
|
150
|
-
.sort(
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
187
|
+
.sort(
|
|
188
|
+
(a: Casing | Completion, b: Casing | Completion) =>
|
|
189
|
+
b.diameter - a.diameter,
|
|
190
|
+
) // descending
|
|
191
|
+
.find(casing => casing.start <= depth && casing.end >= depth);
|
|
192
|
+
|
|
193
|
+
const holeAtDepth = holes.find(
|
|
194
|
+
(hole: HoleSize) => hole.start <= depth && hole.end >= depth,
|
|
195
|
+
);
|
|
154
196
|
|
|
155
|
-
if (
|
|
197
|
+
if (
|
|
198
|
+
outerCasingAtDepth &&
|
|
199
|
+
perforationSubKind !== 'Open hole frac pack' &&
|
|
200
|
+
perforationSubKind !== 'Open hole gravel pack'
|
|
201
|
+
) {
|
|
156
202
|
return getInnerStringDiameter(outerCasingAtDepth);
|
|
157
203
|
}
|
|
158
204
|
|
|
@@ -172,27 +218,42 @@ export const findCementPlugInnerDiameterAtDepth = (
|
|
|
172
218
|
// Default to flow cement outside to show error in data
|
|
173
219
|
const defaultCementWidth = 100;
|
|
174
220
|
const attachedStringAtDepth = attachedStrings
|
|
175
|
-
.sort(
|
|
176
|
-
|
|
221
|
+
.sort(
|
|
222
|
+
(a: Casing | Completion, b: Casing | Completion) =>
|
|
223
|
+
getInnerStringDiameter(a) - getInnerStringDiameter(b),
|
|
224
|
+
) // ascending
|
|
225
|
+
.find(
|
|
226
|
+
casingOrCompletion =>
|
|
227
|
+
casingOrCompletion.start <= depth && casingOrCompletion.end >= depth,
|
|
228
|
+
);
|
|
177
229
|
|
|
178
230
|
if (attachedStringAtDepth) {
|
|
179
231
|
return getInnerStringDiameter(attachedStringAtDepth);
|
|
180
232
|
}
|
|
181
233
|
|
|
182
234
|
// Start from an attached diameter
|
|
183
|
-
const minimumDiameter = attachedStrings.length
|
|
235
|
+
const minimumDiameter = attachedStrings.length
|
|
236
|
+
? Math.min(...attachedStrings.map(c => getInnerStringDiameter(c)))
|
|
237
|
+
: 0;
|
|
184
238
|
const nonAttachedStringAtDepth = nonAttachedStrings
|
|
185
|
-
.sort(
|
|
239
|
+
.sort(
|
|
240
|
+
(a: Casing | Completion, b: Casing | Completion) =>
|
|
241
|
+
getInnerStringDiameter(a) - getInnerStringDiameter(b),
|
|
242
|
+
) // ascending
|
|
186
243
|
.find(
|
|
187
244
|
(casingOrCompletion: Casing | Completion) =>
|
|
188
|
-
casingOrCompletion.start <= depth &&
|
|
245
|
+
casingOrCompletion.start <= depth &&
|
|
246
|
+
casingOrCompletion.end >= depth &&
|
|
247
|
+
minimumDiameter <= getInnerStringDiameter(casingOrCompletion),
|
|
189
248
|
);
|
|
190
249
|
|
|
191
250
|
if (nonAttachedStringAtDepth) {
|
|
192
251
|
return getInnerStringDiameter(nonAttachedStringAtDepth);
|
|
193
252
|
}
|
|
194
253
|
|
|
195
|
-
const holeAtDepth = holes.find(
|
|
254
|
+
const holeAtDepth = holes.find(
|
|
255
|
+
hole => hole.start <= depth && hole.end >= depth && hole.diameter,
|
|
256
|
+
);
|
|
196
257
|
|
|
197
258
|
if (holeAtDepth) {
|
|
198
259
|
return holeAtDepth.diameter;
|
|
@@ -209,36 +270,66 @@ export const createComplexRopeSegmentsForCement = (
|
|
|
209
270
|
exaggerationFactor: number,
|
|
210
271
|
getPoints: (start: number, end: number) => Point[],
|
|
211
272
|
): ComplexRopeSegment[] => {
|
|
212
|
-
const { attachedStrings, nonAttachedStrings } = splitByReferencedStrings(
|
|
273
|
+
const { attachedStrings, nonAttachedStrings } = splitByReferencedStrings(
|
|
274
|
+
cement.referenceIds,
|
|
275
|
+
casings,
|
|
276
|
+
completion,
|
|
277
|
+
);
|
|
213
278
|
|
|
214
279
|
if (attachedStrings.length === 0) {
|
|
215
|
-
throw new Error(
|
|
280
|
+
throw new Error(
|
|
281
|
+
`Invalid cement data, can't find referenced casing/completion string for cement with id '${cement.id}'`,
|
|
282
|
+
);
|
|
216
283
|
}
|
|
217
284
|
|
|
218
285
|
attachedStrings.sort((a, b) => a.end - b.end); // ascending
|
|
219
286
|
const bottomOfCement = attachedStrings[attachedStrings.length - 1]!.end;
|
|
220
287
|
|
|
221
|
-
const { overlappingOuterStrings, overlappingHoles } = findIntersectingItems(
|
|
288
|
+
const { overlappingOuterStrings, overlappingHoles } = findIntersectingItems(
|
|
289
|
+
cement.toc,
|
|
290
|
+
bottomOfCement,
|
|
291
|
+
nonAttachedStrings,
|
|
292
|
+
holes,
|
|
293
|
+
);
|
|
222
294
|
|
|
223
|
-
const outerDiameterIntervals = [
|
|
295
|
+
const outerDiameterIntervals = [
|
|
296
|
+
...overlappingOuterStrings,
|
|
297
|
+
...overlappingHoles,
|
|
298
|
+
].map(d => ({
|
|
224
299
|
start: d.start,
|
|
225
300
|
end: d.end,
|
|
226
301
|
}));
|
|
227
302
|
|
|
228
|
-
const changeDepths = getUniqueDiameterChangeDepths(
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
return [];
|
|
233
|
-
}
|
|
303
|
+
const changeDepths = getUniqueDiameterChangeDepths(
|
|
304
|
+
[cement.toc, bottomOfCement],
|
|
305
|
+
outerDiameterIntervals,
|
|
306
|
+
);
|
|
234
307
|
|
|
235
|
-
|
|
236
|
-
|
|
308
|
+
const diameterIntervals = changeDepths.flatMap(
|
|
309
|
+
(depth: number, index: number, list: number[]) => {
|
|
310
|
+
if (index === list.length - 1) {
|
|
311
|
+
return [];
|
|
312
|
+
}
|
|
237
313
|
|
|
238
|
-
|
|
239
|
-
|
|
314
|
+
const nextDepth = list[index + 1]!;
|
|
315
|
+
const diameterAtChangeDepth = findCementOuterDiameterAtDepth(
|
|
316
|
+
attachedStrings,
|
|
317
|
+
overlappingOuterStrings,
|
|
318
|
+
overlappingHoles,
|
|
319
|
+
depth,
|
|
320
|
+
);
|
|
321
|
+
|
|
322
|
+
return [
|
|
323
|
+
{
|
|
324
|
+
top: depth,
|
|
325
|
+
bottom: nextDepth,
|
|
326
|
+
diameter: diameterAtChangeDepth * exaggerationFactor,
|
|
327
|
+
},
|
|
328
|
+
];
|
|
329
|
+
},
|
|
330
|
+
);
|
|
240
331
|
|
|
241
|
-
const ropeSegments = diameterIntervals.map(
|
|
332
|
+
const ropeSegments = diameterIntervals.map(interval => ({
|
|
242
333
|
diameter: interval.diameter,
|
|
243
334
|
points: getPoints(interval.top, interval.bottom),
|
|
244
335
|
}));
|
|
@@ -250,15 +341,24 @@ const splitByReferencedStrings = (
|
|
|
250
341
|
referenceIds: string[],
|
|
251
342
|
casings: Casing[],
|
|
252
343
|
completion: Completion[],
|
|
253
|
-
): {
|
|
344
|
+
): {
|
|
345
|
+
attachedStrings: (Casing | Completion)[];
|
|
346
|
+
nonAttachedStrings: (Casing | Completion)[];
|
|
347
|
+
} =>
|
|
254
348
|
[...casings, ...completion].reduce(
|
|
255
349
|
(acc, current) => {
|
|
256
350
|
if (referenceIds.includes(current.id)) {
|
|
257
351
|
return { ...acc, attachedStrings: [...acc.attachedStrings, current] };
|
|
258
352
|
}
|
|
259
|
-
return {
|
|
353
|
+
return {
|
|
354
|
+
...acc,
|
|
355
|
+
nonAttachedStrings: [...acc.nonAttachedStrings, current],
|
|
356
|
+
};
|
|
357
|
+
},
|
|
358
|
+
{
|
|
359
|
+
attachedStrings: [] as (Casing | Completion)[],
|
|
360
|
+
nonAttachedStrings: [] as (Casing | Completion)[],
|
|
260
361
|
},
|
|
261
|
-
{ attachedStrings: [] as (Casing | Completion)[], nonAttachedStrings: [] as (Casing | Completion)[] },
|
|
262
362
|
);
|
|
263
363
|
|
|
264
364
|
export const createComplexRopeSegmentsForCementSqueeze = (
|
|
@@ -269,20 +369,37 @@ export const createComplexRopeSegmentsForCementSqueeze = (
|
|
|
269
369
|
exaggerationFactor: number,
|
|
270
370
|
getPoints: (start: number, end: number) => Point[],
|
|
271
371
|
): ComplexRopeSegment[] => {
|
|
272
|
-
const { attachedStrings, nonAttachedStrings } = splitByReferencedStrings(
|
|
372
|
+
const { attachedStrings, nonAttachedStrings } = splitByReferencedStrings(
|
|
373
|
+
squeeze.referenceIds,
|
|
374
|
+
casings,
|
|
375
|
+
completion,
|
|
376
|
+
);
|
|
273
377
|
|
|
274
378
|
if (attachedStrings.length === 0) {
|
|
275
|
-
throw new Error(
|
|
379
|
+
throw new Error(
|
|
380
|
+
`Invalid cement squeeze data, can't find referenced casing/completion for squeeze with id '${squeeze.id}'`,
|
|
381
|
+
);
|
|
276
382
|
}
|
|
277
383
|
|
|
278
|
-
const { overlappingOuterStrings, overlappingHoles } = findIntersectingItems(
|
|
384
|
+
const { overlappingOuterStrings, overlappingHoles } = findIntersectingItems(
|
|
385
|
+
squeeze.start,
|
|
386
|
+
squeeze.end,
|
|
387
|
+
nonAttachedStrings,
|
|
388
|
+
holes,
|
|
389
|
+
);
|
|
279
390
|
|
|
280
|
-
const outerDiameterIntervals = [
|
|
391
|
+
const outerDiameterIntervals = [
|
|
392
|
+
...overlappingOuterStrings,
|
|
393
|
+
...overlappingHoles,
|
|
394
|
+
].map(d => ({
|
|
281
395
|
start: d.start,
|
|
282
396
|
end: d.end,
|
|
283
397
|
}));
|
|
284
398
|
|
|
285
|
-
const changeDepths = getUniqueDiameterChangeDepths(
|
|
399
|
+
const changeDepths = getUniqueDiameterChangeDepths(
|
|
400
|
+
[squeeze.start, squeeze.end],
|
|
401
|
+
outerDiameterIntervals,
|
|
402
|
+
);
|
|
286
403
|
|
|
287
404
|
const diameterIntervals = changeDepths.flatMap((depth, index, list) => {
|
|
288
405
|
if (index === list.length - 1) {
|
|
@@ -291,12 +408,23 @@ export const createComplexRopeSegmentsForCementSqueeze = (
|
|
|
291
408
|
|
|
292
409
|
const nextDepth = list[index + 1]!;
|
|
293
410
|
|
|
294
|
-
const diameterAtDepth = findCementOuterDiameterAtDepth(
|
|
411
|
+
const diameterAtDepth = findCementOuterDiameterAtDepth(
|
|
412
|
+
attachedStrings,
|
|
413
|
+
overlappingOuterStrings,
|
|
414
|
+
overlappingHoles,
|
|
415
|
+
depth,
|
|
416
|
+
);
|
|
295
417
|
|
|
296
|
-
return [
|
|
418
|
+
return [
|
|
419
|
+
{
|
|
420
|
+
top: depth,
|
|
421
|
+
bottom: nextDepth,
|
|
422
|
+
diameter: diameterAtDepth * exaggerationFactor,
|
|
423
|
+
},
|
|
424
|
+
];
|
|
297
425
|
});
|
|
298
426
|
|
|
299
|
-
const ropeSegments = diameterIntervals.map(
|
|
427
|
+
const ropeSegments = diameterIntervals.map(interval => ({
|
|
300
428
|
diameter: interval.diameter,
|
|
301
429
|
points: getPoints(interval.top, interval.bottom),
|
|
302
430
|
}));
|
|
@@ -312,15 +440,31 @@ export const createComplexRopeSegmentsForCementPlug = (
|
|
|
312
440
|
exaggerationFactor: number,
|
|
313
441
|
getPoints: (start: number, end: number) => Point[],
|
|
314
442
|
): ComplexRopeSegment[] => {
|
|
315
|
-
const { attachedStrings, nonAttachedStrings } = splitByReferencedStrings(
|
|
443
|
+
const { attachedStrings, nonAttachedStrings } = splitByReferencedStrings(
|
|
444
|
+
plug.referenceIds,
|
|
445
|
+
casings,
|
|
446
|
+
completion,
|
|
447
|
+
);
|
|
316
448
|
|
|
317
|
-
const { overlappingHoles, overlappingOuterStrings } = findIntersectingItems(
|
|
318
|
-
|
|
449
|
+
const { overlappingHoles, overlappingOuterStrings } = findIntersectingItems(
|
|
450
|
+
plug.start,
|
|
451
|
+
plug.end,
|
|
452
|
+
nonAttachedStrings,
|
|
453
|
+
holes,
|
|
454
|
+
);
|
|
455
|
+
const innerDiameterIntervals = [
|
|
456
|
+
...attachedStrings,
|
|
457
|
+
...overlappingHoles,
|
|
458
|
+
...overlappingOuterStrings,
|
|
459
|
+
].map(d => ({
|
|
319
460
|
start: d.start,
|
|
320
461
|
end: d.end,
|
|
321
462
|
}));
|
|
322
463
|
|
|
323
|
-
const changeDepths = getUniqueDiameterChangeDepths(
|
|
464
|
+
const changeDepths = getUniqueDiameterChangeDepths(
|
|
465
|
+
[plug.start, plug.end],
|
|
466
|
+
innerDiameterIntervals,
|
|
467
|
+
);
|
|
324
468
|
|
|
325
469
|
const diameterIntervals = changeDepths.flatMap((depth, index, list) => {
|
|
326
470
|
if (index === list.length - 1) {
|
|
@@ -328,12 +472,23 @@ export const createComplexRopeSegmentsForCementPlug = (
|
|
|
328
472
|
}
|
|
329
473
|
|
|
330
474
|
const nextDepth = list[index + 1]!;
|
|
331
|
-
const diameterAtDepth = findCementPlugInnerDiameterAtDepth(
|
|
475
|
+
const diameterAtDepth = findCementPlugInnerDiameterAtDepth(
|
|
476
|
+
attachedStrings,
|
|
477
|
+
overlappingOuterStrings,
|
|
478
|
+
overlappingHoles,
|
|
479
|
+
depth,
|
|
480
|
+
);
|
|
332
481
|
|
|
333
|
-
return [
|
|
482
|
+
return [
|
|
483
|
+
{
|
|
484
|
+
top: depth,
|
|
485
|
+
bottom: nextDepth,
|
|
486
|
+
diameter: diameterAtDepth * exaggerationFactor,
|
|
487
|
+
},
|
|
488
|
+
];
|
|
334
489
|
});
|
|
335
490
|
|
|
336
|
-
const ropeSegments = diameterIntervals.map(
|
|
491
|
+
const ropeSegments = diameterIntervals.map(interval => ({
|
|
337
492
|
diameter: interval.diameter,
|
|
338
493
|
points: getPoints(interval.top, interval.bottom),
|
|
339
494
|
}));
|
|
@@ -358,7 +513,11 @@ const createGradientFill = (
|
|
|
358
513
|
return gradient;
|
|
359
514
|
};
|
|
360
515
|
|
|
361
|
-
export const createHoleBaseTexture = (
|
|
516
|
+
export const createHoleBaseTexture = (
|
|
517
|
+
{ firstColor, secondColor }: HoleOptions,
|
|
518
|
+
width: number,
|
|
519
|
+
height: number,
|
|
520
|
+
): Texture => {
|
|
362
521
|
const canvas = document.createElement('canvas');
|
|
363
522
|
canvas.width = width;
|
|
364
523
|
canvas.height = height;
|
|
@@ -368,13 +527,21 @@ export const createHoleBaseTexture = ({ firstColor, secondColor }: HoleOptions,
|
|
|
368
527
|
throw Error('Could not get canvas context!');
|
|
369
528
|
}
|
|
370
529
|
|
|
371
|
-
canvasCtx.fillStyle = createGradientFill(
|
|
530
|
+
canvasCtx.fillStyle = createGradientFill(
|
|
531
|
+
canvas,
|
|
532
|
+
canvasCtx,
|
|
533
|
+
firstColor,
|
|
534
|
+
secondColor,
|
|
535
|
+
0,
|
|
536
|
+
);
|
|
372
537
|
canvasCtx.fillRect(0, 0, canvas.width, canvas.height);
|
|
373
538
|
|
|
374
539
|
return Texture.from(canvas);
|
|
375
540
|
};
|
|
376
541
|
|
|
377
|
-
export const createScreenTexture = ({
|
|
542
|
+
export const createScreenTexture = ({
|
|
543
|
+
scalingFactor,
|
|
544
|
+
}: ScreenOptions): Texture => {
|
|
378
545
|
const canvas = document.createElement('canvas');
|
|
379
546
|
const size = DEFAULT_TEXTURE_SIZE * scalingFactor;
|
|
380
547
|
canvas.width = size;
|
|
@@ -395,13 +562,20 @@ export const createScreenTexture = ({ scalingFactor }: ScreenOptions): Texture =
|
|
|
395
562
|
const distanceBetweenLines = size / 3;
|
|
396
563
|
for (let i = -canvas.width; i < canvas.width; i++) {
|
|
397
564
|
canvasCtx.moveTo(-canvas.width + distanceBetweenLines * i, -canvas.height);
|
|
398
|
-
canvasCtx.lineTo(
|
|
565
|
+
canvasCtx.lineTo(
|
|
566
|
+
canvas.width + distanceBetweenLines * i,
|
|
567
|
+
canvas.height * 2,
|
|
568
|
+
);
|
|
399
569
|
}
|
|
400
570
|
canvasCtx.stroke();
|
|
401
571
|
return Texture.from(canvas);
|
|
402
572
|
};
|
|
403
573
|
|
|
404
|
-
export const createTubingTexture = ({
|
|
574
|
+
export const createTubingTexture = ({
|
|
575
|
+
innerColor,
|
|
576
|
+
outerColor,
|
|
577
|
+
scalingFactor,
|
|
578
|
+
}: TubingOptions): Texture => {
|
|
405
579
|
const size = DEFAULT_TEXTURE_SIZE * scalingFactor;
|
|
406
580
|
|
|
407
581
|
const canvas = document.createElement('canvas');
|
|
@@ -427,7 +601,11 @@ export const createTubingTexture = ({ innerColor, outerColor, scalingFactor }: T
|
|
|
427
601
|
return Texture.from(canvas);
|
|
428
602
|
};
|
|
429
603
|
|
|
430
|
-
export const createCementTexture = ({
|
|
604
|
+
export const createCementTexture = ({
|
|
605
|
+
firstColor,
|
|
606
|
+
secondColor,
|
|
607
|
+
scalingFactor,
|
|
608
|
+
}: CementOptions): Texture => {
|
|
431
609
|
const canvas = document.createElement('canvas');
|
|
432
610
|
|
|
433
611
|
const size = DEFAULT_TEXTURE_SIZE * scalingFactor;
|
|
@@ -456,7 +634,11 @@ export const createCementTexture = ({ firstColor, secondColor, scalingFactor }:
|
|
|
456
634
|
return Texture.from(canvas);
|
|
457
635
|
};
|
|
458
636
|
|
|
459
|
-
export const createCementPlugTexture = ({
|
|
637
|
+
export const createCementPlugTexture = ({
|
|
638
|
+
firstColor,
|
|
639
|
+
secondColor,
|
|
640
|
+
scalingFactor,
|
|
641
|
+
}: CementPlugOptions): Texture => {
|
|
460
642
|
const canvas = document.createElement('canvas');
|
|
461
643
|
|
|
462
644
|
const size = DEFAULT_TEXTURE_SIZE * scalingFactor;
|
|
@@ -478,14 +660,21 @@ export const createCementPlugTexture = ({ firstColor, secondColor, scalingFactor
|
|
|
478
660
|
const distanceBetweenLines = size / 12;
|
|
479
661
|
for (let i = -canvas.width; i < canvas.width; i++) {
|
|
480
662
|
canvasCtx.moveTo(-canvas.width + distanceBetweenLines * i, -canvas.height);
|
|
481
|
-
canvasCtx.lineTo(
|
|
663
|
+
canvasCtx.lineTo(
|
|
664
|
+
canvas.width + distanceBetweenLines * i,
|
|
665
|
+
canvas.height * 2,
|
|
666
|
+
);
|
|
482
667
|
}
|
|
483
668
|
canvasCtx.stroke();
|
|
484
669
|
|
|
485
670
|
return Texture.from(canvas);
|
|
486
671
|
};
|
|
487
672
|
|
|
488
|
-
export const createCementSqueezeTexture = ({
|
|
673
|
+
export const createCementSqueezeTexture = ({
|
|
674
|
+
firstColor,
|
|
675
|
+
secondColor,
|
|
676
|
+
scalingFactor,
|
|
677
|
+
}: CementSqueezeOptions): Texture => {
|
|
489
678
|
const canvas = document.createElement('canvas');
|
|
490
679
|
|
|
491
680
|
const size = DEFAULT_TEXTURE_SIZE * scalingFactor;
|
|
@@ -509,14 +698,20 @@ export const createCementSqueezeTexture = ({ firstColor, secondColor, scalingFac
|
|
|
509
698
|
const distanceBetweenLines = size / 12;
|
|
510
699
|
for (let i = -canvas.width; i < canvas.width; i++) {
|
|
511
700
|
canvasCtx.moveTo(-canvas.width + distanceBetweenLines * i, -canvas.height);
|
|
512
|
-
canvasCtx.lineTo(
|
|
701
|
+
canvasCtx.lineTo(
|
|
702
|
+
canvas.width + distanceBetweenLines * i,
|
|
703
|
+
canvas.height * 2,
|
|
704
|
+
);
|
|
513
705
|
}
|
|
514
706
|
canvasCtx.stroke();
|
|
515
707
|
|
|
516
708
|
return Texture.from(canvas);
|
|
517
709
|
};
|
|
518
710
|
|
|
519
|
-
export const createTubularRenderingObject = (
|
|
711
|
+
export const createTubularRenderingObject = (
|
|
712
|
+
radius: number,
|
|
713
|
+
pathPoints: Point[],
|
|
714
|
+
): TubularRenderingObject => {
|
|
520
715
|
const normals = createNormals(pathPoints);
|
|
521
716
|
const rightPath = offsetPoints(pathPoints, normals, radius);
|
|
522
717
|
const leftPath = offsetPoints(pathPoints, normals, -radius);
|
|
@@ -530,23 +725,46 @@ export type CasingInterval = {
|
|
|
530
725
|
end: number;
|
|
531
726
|
};
|
|
532
727
|
|
|
533
|
-
const createCasingInterval = (start: number, end: number): CasingInterval => ({
|
|
534
|
-
|
|
728
|
+
const createCasingInterval = (start: number, end: number): CasingInterval => ({
|
|
729
|
+
kind: 'casing',
|
|
730
|
+
start,
|
|
731
|
+
end,
|
|
732
|
+
});
|
|
733
|
+
const createCasingWindowInterval = (
|
|
734
|
+
start: number,
|
|
735
|
+
end: number,
|
|
736
|
+
): CasingInterval => ({ kind: 'casing-window', start, end });
|
|
535
737
|
|
|
536
|
-
export const getCasingIntervalsWithWindows = (
|
|
738
|
+
export const getCasingIntervalsWithWindows = (
|
|
739
|
+
casing: Casing,
|
|
740
|
+
): CasingInterval[] => {
|
|
537
741
|
const result = (casing.windows || [])
|
|
538
|
-
.filter((cw: CasingWindow) =>
|
|
742
|
+
.filter((cw: CasingWindow) =>
|
|
743
|
+
strictlyOverlaps(casing.start, casing.end, cw.start, cw.end),
|
|
744
|
+
)
|
|
539
745
|
.reduce<{ intervals: CasingInterval[]; lastBottom: number }>(
|
|
540
|
-
(
|
|
746
|
+
(
|
|
747
|
+
{ intervals, lastBottom },
|
|
748
|
+
currentWindow: CasingWindow,
|
|
749
|
+
index: number,
|
|
750
|
+
list: CasingWindow[],
|
|
751
|
+
) => {
|
|
541
752
|
const startCasingInterval: CasingInterval | null =
|
|
542
753
|
// last bottom before current start?
|
|
543
|
-
lastBottom < currentWindow.start
|
|
754
|
+
lastBottom < currentWindow.start
|
|
755
|
+
? createCasingInterval(lastBottom, currentWindow.start)
|
|
756
|
+
: null;
|
|
544
757
|
|
|
545
|
-
const updatedLastBottom = startCasingInterval
|
|
758
|
+
const updatedLastBottom = startCasingInterval
|
|
759
|
+
? startCasingInterval.end
|
|
760
|
+
: lastBottom;
|
|
546
761
|
|
|
547
762
|
const windowStart = Math.max(updatedLastBottom, currentWindow.start);
|
|
548
763
|
const windowEnd = Math.min(casing.end, currentWindow.end);
|
|
549
|
-
const windowInterval: CasingInterval = createCasingWindowInterval(
|
|
764
|
+
const windowInterval: CasingInterval = createCasingWindowInterval(
|
|
765
|
+
windowStart,
|
|
766
|
+
windowEnd,
|
|
767
|
+
);
|
|
550
768
|
|
|
551
769
|
const nextLastBottom = windowEnd;
|
|
552
770
|
|
|
@@ -558,9 +776,16 @@ export const getCasingIntervalsWithWindows = (casing: Casing): CasingInterval[]
|
|
|
558
776
|
? createCasingInterval(nextLastBottom, casing.end)
|
|
559
777
|
: null;
|
|
560
778
|
|
|
561
|
-
const newIntervals: CasingInterval[] = [
|
|
779
|
+
const newIntervals: CasingInterval[] = [
|
|
780
|
+
startCasingInterval,
|
|
781
|
+
windowInterval,
|
|
782
|
+
endCasingInterval,
|
|
783
|
+
].filter((i): i is CasingInterval => i != null);
|
|
562
784
|
|
|
563
|
-
return {
|
|
785
|
+
return {
|
|
786
|
+
intervals: [...intervals, ...newIntervals],
|
|
787
|
+
lastBottom: nextLastBottom,
|
|
788
|
+
};
|
|
564
789
|
},
|
|
565
790
|
{ intervals: [], lastBottom: casing.start },
|
|
566
791
|
);
|
|
@@ -583,11 +808,19 @@ export const prepareCasingRenderObject = (
|
|
|
583
808
|
const exaggeratedInnerRadius = exaggeratedInnerDiameter / 2;
|
|
584
809
|
const casingWallWidth = exaggeratedRadius - exaggeratedInnerRadius;
|
|
585
810
|
|
|
586
|
-
const sections = getCasingIntervalsWithWindows(casing).map(
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
811
|
+
const sections = getCasingIntervalsWithWindows(casing).map(
|
|
812
|
+
(casingInterval: CasingInterval) => {
|
|
813
|
+
const pathPoints = getPathPoints(
|
|
814
|
+
casingInterval.start,
|
|
815
|
+
casingInterval.end,
|
|
816
|
+
);
|
|
817
|
+
const { leftPath, rightPath } = createTubularRenderingObject(
|
|
818
|
+
exaggeratedRadius,
|
|
819
|
+
pathPoints,
|
|
820
|
+
);
|
|
821
|
+
return { kind: casingInterval.kind, leftPath, rightPath, pathPoints };
|
|
822
|
+
},
|
|
823
|
+
);
|
|
591
824
|
|
|
592
825
|
return {
|
|
593
826
|
kind: 'casing',
|
|
@@ -608,14 +841,25 @@ export const createComplexRopeSegmentsForPerforation = (
|
|
|
608
841
|
exaggerationFactor: number,
|
|
609
842
|
getPoints: (start: number, end: number) => Point[],
|
|
610
843
|
): ComplexRopeSegment[] => {
|
|
611
|
-
const { overlappingOuterStrings, overlappingHoles } = findIntersectingItems(
|
|
844
|
+
const { overlappingOuterStrings, overlappingHoles } = findIntersectingItems(
|
|
845
|
+
perforation.start,
|
|
846
|
+
perforation.end,
|
|
847
|
+
casings,
|
|
848
|
+
holes,
|
|
849
|
+
);
|
|
612
850
|
|
|
613
|
-
const outerDiameterIntervals = [
|
|
851
|
+
const outerDiameterIntervals = [
|
|
852
|
+
...overlappingOuterStrings,
|
|
853
|
+
...overlappingHoles,
|
|
854
|
+
].map(d => ({
|
|
614
855
|
start: d.start,
|
|
615
856
|
end: d.end,
|
|
616
857
|
}));
|
|
617
858
|
|
|
618
|
-
const changeDepths = getUniqueDiameterChangeDepths(
|
|
859
|
+
const changeDepths = getUniqueDiameterChangeDepths(
|
|
860
|
+
[perforation.start, perforation.end],
|
|
861
|
+
outerDiameterIntervals,
|
|
862
|
+
);
|
|
619
863
|
|
|
620
864
|
const diameterIntervals = changeDepths.flatMap((depth, index, list) => {
|
|
621
865
|
if (index === list.length - 1) {
|
|
@@ -624,12 +868,23 @@ export const createComplexRopeSegmentsForPerforation = (
|
|
|
624
868
|
|
|
625
869
|
const nextDepth = list[index + 1]!;
|
|
626
870
|
|
|
627
|
-
const diameterAtDepth = findPerforationOuterDiameterAtDepth(
|
|
871
|
+
const diameterAtDepth = findPerforationOuterDiameterAtDepth(
|
|
872
|
+
overlappingOuterStrings,
|
|
873
|
+
overlappingHoles,
|
|
874
|
+
depth,
|
|
875
|
+
perforation.subKind,
|
|
876
|
+
);
|
|
628
877
|
|
|
629
|
-
return [
|
|
878
|
+
return [
|
|
879
|
+
{
|
|
880
|
+
top: depth,
|
|
881
|
+
bottom: nextDepth,
|
|
882
|
+
diameter: diameterAtDepth * exaggerationFactor,
|
|
883
|
+
},
|
|
884
|
+
];
|
|
630
885
|
});
|
|
631
886
|
|
|
632
|
-
const ropeSegments = diameterIntervals.map(
|
|
887
|
+
const ropeSegments = diameterIntervals.map(interval => {
|
|
633
888
|
const points = getPoints(interval.top, interval.bottom);
|
|
634
889
|
|
|
635
890
|
const diameter = interval.diameter;
|
|
@@ -643,7 +898,11 @@ export const createComplexRopeSegmentsForPerforation = (
|
|
|
643
898
|
return ropeSegments;
|
|
644
899
|
};
|
|
645
900
|
|
|
646
|
-
const drawPacking = (
|
|
901
|
+
const drawPacking = (
|
|
902
|
+
canvas: HTMLCanvasElement,
|
|
903
|
+
ctx: CanvasRenderingContext2D,
|
|
904
|
+
perforationOptions: PerforationOptions,
|
|
905
|
+
) => {
|
|
647
906
|
const { packingOpacity, yellow } = perforationOptions;
|
|
648
907
|
|
|
649
908
|
ctx.fillStyle = yellow;
|
|
@@ -669,7 +928,8 @@ const drawFracLines = (
|
|
|
669
928
|
const amountOfSpikes = 10;
|
|
670
929
|
const spikeWidth = canvas.width / amountOfSpikes;
|
|
671
930
|
|
|
672
|
-
const diameter =
|
|
931
|
+
const diameter =
|
|
932
|
+
(extendedPerfShapeDiameter / 3) * perforationOptions.scalingFactor;
|
|
673
933
|
|
|
674
934
|
const fracLineLength = diameter / 4;
|
|
675
935
|
const spikeLength = diameter / 2;
|
|
@@ -680,15 +940,27 @@ const drawFracLines = (
|
|
|
680
940
|
|
|
681
941
|
const fracLines = () => {
|
|
682
942
|
for (let i = -1; i < amountOfSpikes; i++) {
|
|
683
|
-
const bottom: [number, number] = [
|
|
943
|
+
const bottom: [number, number] = [
|
|
944
|
+
i * spikeWidth + offsetX + spikeWidth / 2,
|
|
945
|
+
canvas.height / 2 - fracLineLength - offsetY - fracLineLength,
|
|
946
|
+
];
|
|
684
947
|
|
|
685
948
|
ctx.beginPath();
|
|
686
949
|
|
|
687
950
|
const start: [number, number] = [...bottom];
|
|
688
|
-
const controlPoint1: [number, number] = [
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
951
|
+
const controlPoint1: [number, number] = [
|
|
952
|
+
bottom[0] - fracLineCurve * 2,
|
|
953
|
+
bottom[1] - fracLineLength / 4,
|
|
954
|
+
];
|
|
955
|
+
const middle: [number, number] = [
|
|
956
|
+
bottom[0],
|
|
957
|
+
bottom[1] - fracLineLength / 2,
|
|
958
|
+
];
|
|
959
|
+
|
|
960
|
+
const controlPoint2: [number, number] = [
|
|
961
|
+
bottom[0] + fracLineCurve * 2,
|
|
962
|
+
bottom[1] - fracLineLength / 2 - fracLineLength / 4,
|
|
963
|
+
];
|
|
692
964
|
const end: [number, number] = [bottom[0], bottom[1] - fracLineLength];
|
|
693
965
|
|
|
694
966
|
ctx.bezierCurveTo(...start, ...controlPoint1, ...middle);
|
|
@@ -698,15 +970,27 @@ const drawFracLines = (
|
|
|
698
970
|
}
|
|
699
971
|
|
|
700
972
|
for (let i = -1; i < amountOfSpikes; i++) {
|
|
701
|
-
const bottom: [number, number] = [
|
|
973
|
+
const bottom: [number, number] = [
|
|
974
|
+
i * spikeWidth + spikeWidth + offsetX + spikeWidth / 2,
|
|
975
|
+
canvas.height / 2 + diameter / 2 + offsetY,
|
|
976
|
+
];
|
|
702
977
|
|
|
703
978
|
ctx.beginPath();
|
|
704
979
|
|
|
705
980
|
const start: [number, number] = [...bottom];
|
|
706
|
-
const controlPoint1: [number, number] = [
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
981
|
+
const controlPoint1: [number, number] = [
|
|
982
|
+
bottom[0] - fracLineCurve * 2,
|
|
983
|
+
bottom[1] + fracLineLength / 4,
|
|
984
|
+
];
|
|
985
|
+
const middle: [number, number] = [
|
|
986
|
+
bottom[0],
|
|
987
|
+
bottom[1] + fracLineLength / 2,
|
|
988
|
+
];
|
|
989
|
+
|
|
990
|
+
const controlPoint2: [number, number] = [
|
|
991
|
+
bottom[0] + fracLineCurve * 2,
|
|
992
|
+
bottom[1] + fracLineLength / 2 + fracLineLength / 4,
|
|
993
|
+
];
|
|
710
994
|
const end: [number, number] = [bottom[0], bottom[1] + fracLineLength];
|
|
711
995
|
|
|
712
996
|
ctx.bezierCurveTo(...start, ...controlPoint1, ...middle);
|
|
@@ -738,15 +1022,22 @@ const drawSpikes = (
|
|
|
738
1022
|
const spikeWidth = canvas.width / amountOfSpikes;
|
|
739
1023
|
ctx.strokeStyle = perforationOptions.outline;
|
|
740
1024
|
|
|
741
|
-
const diameter =
|
|
1025
|
+
const diameter =
|
|
1026
|
+
(extendedPerfShapeDiameter / 3) * perforationOptions.scalingFactor;
|
|
742
1027
|
|
|
743
1028
|
ctx.lineWidth = 1;
|
|
744
1029
|
const spikeLength = diameter / 2;
|
|
745
1030
|
|
|
746
1031
|
// left spikes
|
|
747
1032
|
for (let i = 0; i <= amountOfSpikes; i++) {
|
|
748
|
-
const left: [number, number] = [
|
|
749
|
-
|
|
1033
|
+
const left: [number, number] = [
|
|
1034
|
+
i * spikeWidth,
|
|
1035
|
+
canvas.height / 2 - diameter / 2,
|
|
1036
|
+
];
|
|
1037
|
+
const bottom: [number, number] = [
|
|
1038
|
+
left[0] - spikeWidth / 2,
|
|
1039
|
+
left[1] - spikeLength,
|
|
1040
|
+
];
|
|
750
1041
|
const right: [number, number] = [left[0] - spikeWidth, left[1]];
|
|
751
1042
|
|
|
752
1043
|
ctx.beginPath();
|
|
@@ -761,8 +1052,14 @@ const drawSpikes = (
|
|
|
761
1052
|
|
|
762
1053
|
// right spikes
|
|
763
1054
|
for (let i = 0; i <= amountOfSpikes; i++) {
|
|
764
|
-
const left: [number, number] = [
|
|
765
|
-
|
|
1055
|
+
const left: [number, number] = [
|
|
1056
|
+
i * spikeWidth,
|
|
1057
|
+
canvas.height / 2 + diameter / 2,
|
|
1058
|
+
];
|
|
1059
|
+
const bottom: [number, number] = [
|
|
1060
|
+
left[0] - spikeWidth / 2,
|
|
1061
|
+
left[1] + spikeLength,
|
|
1062
|
+
];
|
|
766
1063
|
const right: [number, number] = [left[0] - spikeWidth, left[1]];
|
|
767
1064
|
|
|
768
1065
|
ctx.beginPath();
|
|
@@ -780,7 +1077,13 @@ const drawSpikes = (
|
|
|
780
1077
|
|
|
781
1078
|
// for visual debugging
|
|
782
1079
|
// if this shoes up, something is wrong
|
|
783
|
-
const errorTexture = (
|
|
1080
|
+
const errorTexture = (
|
|
1081
|
+
errorMessage = 'Error!',
|
|
1082
|
+
existingContext?: {
|
|
1083
|
+
canvas: HTMLCanvasElement;
|
|
1084
|
+
canvasCtx: CanvasRenderingContext2D;
|
|
1085
|
+
},
|
|
1086
|
+
) => {
|
|
784
1087
|
console.error(`${errorMessage}`);
|
|
785
1088
|
const canvas = existingContext?.canvas || document.createElement('canvas');
|
|
786
1089
|
|
|
@@ -840,8 +1143,11 @@ const createPerforationTexture = (canvas: HTMLCanvasElement) => {
|
|
|
840
1143
|
};
|
|
841
1144
|
|
|
842
1145
|
const compareIntersectingPerforationsBy =
|
|
843
|
-
(targetPerf: Perforation, comparedPerforations: Perforation[]) =>
|
|
844
|
-
|
|
1146
|
+
(targetPerf: Perforation, comparedPerforations: Perforation[]) =>
|
|
1147
|
+
(compareFunc: (comparedPerf: Perforation) => boolean) =>
|
|
1148
|
+
comparedPerforations.some(
|
|
1149
|
+
perf => compareFunc(perf) && intersect(targetPerf, perf),
|
|
1150
|
+
);
|
|
845
1151
|
|
|
846
1152
|
/**
|
|
847
1153
|
* @Perforation
|
|
@@ -871,19 +1177,36 @@ const createSubkindPerforationTexture = {
|
|
|
871
1177
|
otherPerforations: Perforation[],
|
|
872
1178
|
perforationOptions: PerforationOptions,
|
|
873
1179
|
): Texture => {
|
|
874
|
-
const { canvas, ctx } = createPerforationCanvas(
|
|
1180
|
+
const { canvas, ctx } = createPerforationCanvas(
|
|
1181
|
+
perfShape,
|
|
1182
|
+
perforationOptions,
|
|
1183
|
+
);
|
|
875
1184
|
|
|
876
|
-
const compareBy = compareIntersectingPerforationsBy(
|
|
1185
|
+
const compareBy = compareIntersectingPerforationsBy(
|
|
1186
|
+
perforation,
|
|
1187
|
+
otherPerforations,
|
|
1188
|
+
);
|
|
877
1189
|
|
|
878
|
-
const intersectionsWithCasedHoleGravel: boolean = compareBy(
|
|
1190
|
+
const intersectionsWithCasedHoleGravel: boolean = compareBy(
|
|
1191
|
+
isSubkindCasedHoleGravelPack,
|
|
1192
|
+
);
|
|
879
1193
|
|
|
880
|
-
const intersectsWithCasedHoleFracturation: boolean = compareBy(
|
|
1194
|
+
const intersectsWithCasedHoleFracturation: boolean = compareBy(
|
|
1195
|
+
isSubKindCasedHoleFracturation,
|
|
1196
|
+
);
|
|
881
1197
|
|
|
882
|
-
const intersectionsWithCasedHoleFracPack: boolean = compareBy(
|
|
1198
|
+
const intersectionsWithCasedHoleFracPack: boolean = compareBy(
|
|
1199
|
+
isSubKindCasedHoleFracPack,
|
|
1200
|
+
);
|
|
883
1201
|
|
|
884
|
-
const intersectsWithPerforation =
|
|
1202
|
+
const intersectsWithPerforation =
|
|
1203
|
+
intersectionsWithCasedHoleGravel ||
|
|
1204
|
+
intersectsWithCasedHoleFracturation ||
|
|
1205
|
+
intersectionsWithCasedHoleFracPack;
|
|
885
1206
|
|
|
886
|
-
const openPerforationSpikeColor = intersectsWithPerforation
|
|
1207
|
+
const openPerforationSpikeColor = intersectsWithPerforation
|
|
1208
|
+
? perforationOptions.yellow
|
|
1209
|
+
: perforationOptions.red;
|
|
887
1210
|
|
|
888
1211
|
ctx.globalAlpha = perforationOptions.packingOpacity;
|
|
889
1212
|
if (perforation.isOpen) {
|
|
@@ -897,7 +1220,13 @@ const createSubkindPerforationTexture = {
|
|
|
897
1220
|
drawSpikes(canvas, ctx, perfShape.diameter, perforationOptions);
|
|
898
1221
|
|
|
899
1222
|
if (intersectionsWithCasedHoleFracPack) {
|
|
900
|
-
drawFracLines(
|
|
1223
|
+
drawFracLines(
|
|
1224
|
+
canvas,
|
|
1225
|
+
ctx,
|
|
1226
|
+
perfShape.diameter,
|
|
1227
|
+
perforationOptions,
|
|
1228
|
+
'spike',
|
|
1229
|
+
);
|
|
901
1230
|
}
|
|
902
1231
|
|
|
903
1232
|
return createPerforationTexture(canvas);
|
|
@@ -910,9 +1239,21 @@ const createSubkindPerforationTexture = {
|
|
|
910
1239
|
*/
|
|
911
1240
|
const createSubkindCasedHoleFracturationTexture = {
|
|
912
1241
|
packing: () => errorTexture(),
|
|
913
|
-
fracLines: (
|
|
914
|
-
|
|
915
|
-
|
|
1242
|
+
fracLines: (
|
|
1243
|
+
perfShape: ComplexRopeSegment,
|
|
1244
|
+
perforationOptions: PerforationOptions,
|
|
1245
|
+
): Texture => {
|
|
1246
|
+
const { canvas, ctx } = createPerforationCanvas(
|
|
1247
|
+
perfShape,
|
|
1248
|
+
perforationOptions,
|
|
1249
|
+
);
|
|
1250
|
+
drawFracLines(
|
|
1251
|
+
canvas,
|
|
1252
|
+
ctx,
|
|
1253
|
+
perfShape.diameter,
|
|
1254
|
+
perforationOptions,
|
|
1255
|
+
'diameter',
|
|
1256
|
+
);
|
|
916
1257
|
return createPerforationTexture(canvas);
|
|
917
1258
|
},
|
|
918
1259
|
spikes: () => errorTexture(),
|
|
@@ -926,12 +1267,21 @@ const createSubkindCasedHoleFracturationTexture = {
|
|
|
926
1267
|
* If a perforation of type "perforation" is overlapping, the fracturation lines extends from the tip of the perforation spikes into formation.
|
|
927
1268
|
*/
|
|
928
1269
|
const createSubkindCasedHoleFracPackTexture = {
|
|
929
|
-
packing: (
|
|
930
|
-
|
|
1270
|
+
packing: (
|
|
1271
|
+
perfShape: ComplexRopeSegment,
|
|
1272
|
+
perforationOptions: PerforationOptions,
|
|
1273
|
+
): Texture => {
|
|
1274
|
+
const { canvas, ctx } = createPerforationCanvas(
|
|
1275
|
+
perfShape,
|
|
1276
|
+
perforationOptions,
|
|
1277
|
+
);
|
|
931
1278
|
drawPacking(canvas, ctx, perforationOptions);
|
|
932
1279
|
return createPerforationTexture(canvas);
|
|
933
1280
|
},
|
|
934
|
-
fracLines: (
|
|
1281
|
+
fracLines: (
|
|
1282
|
+
perfShape: ComplexRopeSegment,
|
|
1283
|
+
perforationOptions: PerforationOptions,
|
|
1284
|
+
) => {
|
|
935
1285
|
const { canvas } = createPerforationCanvas(perfShape, perforationOptions);
|
|
936
1286
|
return createPerforationTexture(canvas);
|
|
937
1287
|
},
|
|
@@ -943,8 +1293,14 @@ const createSubkindCasedHoleFracPackTexture = {
|
|
|
943
1293
|
* Yellow gravel. Makes perforations of type "Perforation" yellow if overlapping and perforation are open.
|
|
944
1294
|
*/
|
|
945
1295
|
const createSubkindCasedHoleGravelPackTexture = {
|
|
946
|
-
packing: (
|
|
947
|
-
|
|
1296
|
+
packing: (
|
|
1297
|
+
perfShape: ComplexRopeSegment,
|
|
1298
|
+
perforationOptions: PerforationOptions,
|
|
1299
|
+
): Texture => {
|
|
1300
|
+
const { canvas, ctx } = createPerforationCanvas(
|
|
1301
|
+
perfShape,
|
|
1302
|
+
perforationOptions,
|
|
1303
|
+
);
|
|
948
1304
|
drawPacking(canvas, ctx, perforationOptions);
|
|
949
1305
|
return createPerforationTexture(canvas);
|
|
950
1306
|
},
|
|
@@ -957,8 +1313,14 @@ const createSubkindCasedHoleGravelPackTexture = {
|
|
|
957
1313
|
* Yellow gravel
|
|
958
1314
|
*/
|
|
959
1315
|
const createSubkindOpenHoleGravelPackTexture = {
|
|
960
|
-
packing: (
|
|
961
|
-
|
|
1316
|
+
packing: (
|
|
1317
|
+
perfShape: ComplexRopeSegment,
|
|
1318
|
+
perforationOptions: PerforationOptions,
|
|
1319
|
+
) => {
|
|
1320
|
+
const { canvas, ctx } = createPerforationCanvas(
|
|
1321
|
+
perfShape,
|
|
1322
|
+
perforationOptions,
|
|
1323
|
+
);
|
|
962
1324
|
drawPacking(canvas, ctx, perforationOptions);
|
|
963
1325
|
return createPerforationTexture(canvas);
|
|
964
1326
|
},
|
|
@@ -971,14 +1333,33 @@ const createSubkindOpenHoleGravelPackTexture = {
|
|
|
971
1333
|
* Yellow gravel. Yellow frac lines from hole OD into formation
|
|
972
1334
|
*/
|
|
973
1335
|
const createSubkindOpenHoleFracPackTexture = {
|
|
974
|
-
packing: (
|
|
975
|
-
|
|
1336
|
+
packing: (
|
|
1337
|
+
_perforation: Perforation,
|
|
1338
|
+
perfShape: ComplexRopeSegment,
|
|
1339
|
+
perforationOptions: PerforationOptions,
|
|
1340
|
+
) => {
|
|
1341
|
+
const { canvas, ctx } = createPerforationCanvas(
|
|
1342
|
+
perfShape,
|
|
1343
|
+
perforationOptions,
|
|
1344
|
+
);
|
|
976
1345
|
drawPacking(canvas, ctx, perforationOptions);
|
|
977
1346
|
return createPerforationTexture(canvas);
|
|
978
1347
|
},
|
|
979
|
-
fracLines: (
|
|
980
|
-
|
|
981
|
-
|
|
1348
|
+
fracLines: (
|
|
1349
|
+
perfShape: ComplexRopeSegment,
|
|
1350
|
+
perforationOptions: PerforationOptions,
|
|
1351
|
+
): Texture => {
|
|
1352
|
+
const { canvas, ctx } = createPerforationCanvas(
|
|
1353
|
+
perfShape,
|
|
1354
|
+
perforationOptions,
|
|
1355
|
+
);
|
|
1356
|
+
drawFracLines(
|
|
1357
|
+
canvas,
|
|
1358
|
+
ctx,
|
|
1359
|
+
perfShape.diameter,
|
|
1360
|
+
perforationOptions,
|
|
1361
|
+
'diameter',
|
|
1362
|
+
);
|
|
982
1363
|
return createPerforationTexture(canvas);
|
|
983
1364
|
},
|
|
984
1365
|
spikes: () => errorTexture(),
|
|
@@ -992,11 +1373,32 @@ export const createPerforationPackingTexture = (
|
|
|
992
1373
|
return foldPerforationSubKind(
|
|
993
1374
|
{
|
|
994
1375
|
Perforation: () => createSubkindPerforationTexture.packing(),
|
|
995
|
-
CasedHoleFracturation: () =>
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1376
|
+
CasedHoleFracturation: () =>
|
|
1377
|
+
createSubkindCasedHoleFracPackTexture.packing(
|
|
1378
|
+
perfShape,
|
|
1379
|
+
perforationOptions,
|
|
1380
|
+
),
|
|
1381
|
+
CasedHoleFracPack: () =>
|
|
1382
|
+
createSubkindCasedHoleFracPackTexture.packing(
|
|
1383
|
+
perfShape,
|
|
1384
|
+
perforationOptions,
|
|
1385
|
+
),
|
|
1386
|
+
OpenHoleGravelPack: () =>
|
|
1387
|
+
createSubkindOpenHoleGravelPackTexture.packing(
|
|
1388
|
+
perfShape,
|
|
1389
|
+
perforationOptions,
|
|
1390
|
+
),
|
|
1391
|
+
OpenHoleFracPack: () =>
|
|
1392
|
+
createSubkindOpenHoleFracPackTexture.packing(
|
|
1393
|
+
perforation,
|
|
1394
|
+
perfShape,
|
|
1395
|
+
perforationOptions,
|
|
1396
|
+
),
|
|
1397
|
+
CasedHoleGravelPack: () =>
|
|
1398
|
+
createSubkindCasedHoleGravelPackTexture.packing(
|
|
1399
|
+
perfShape,
|
|
1400
|
+
perforationOptions,
|
|
1401
|
+
),
|
|
1000
1402
|
},
|
|
1001
1403
|
perforation.subKind,
|
|
1002
1404
|
);
|
|
@@ -1010,11 +1412,25 @@ export const createPerforationFracLineTexture = (
|
|
|
1010
1412
|
return foldPerforationSubKind(
|
|
1011
1413
|
{
|
|
1012
1414
|
Perforation: () => createSubkindPerforationTexture.fracLines(),
|
|
1013
|
-
OpenHoleGravelPack: () =>
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1415
|
+
OpenHoleGravelPack: () =>
|
|
1416
|
+
createSubkindOpenHoleGravelPackTexture.fracLines(),
|
|
1417
|
+
OpenHoleFracPack: () =>
|
|
1418
|
+
createSubkindOpenHoleFracPackTexture.fracLines(
|
|
1419
|
+
perfShape,
|
|
1420
|
+
perforationOptions,
|
|
1421
|
+
),
|
|
1422
|
+
CasedHoleFracturation: () =>
|
|
1423
|
+
createSubkindCasedHoleFracturationTexture.fracLines(
|
|
1424
|
+
perfShape,
|
|
1425
|
+
perforationOptions,
|
|
1426
|
+
),
|
|
1427
|
+
CasedHoleGravelPack: () =>
|
|
1428
|
+
createSubkindCasedHoleGravelPackTexture.fracLines(),
|
|
1429
|
+
CasedHoleFracPack: () =>
|
|
1430
|
+
createSubkindCasedHoleFracPackTexture.fracLines(
|
|
1431
|
+
perfShape,
|
|
1432
|
+
perforationOptions,
|
|
1433
|
+
),
|
|
1018
1434
|
},
|
|
1019
1435
|
perforation.subKind,
|
|
1020
1436
|
);
|
|
@@ -1028,11 +1444,19 @@ export const createPerforationSpikeTexture = (
|
|
|
1028
1444
|
): Texture => {
|
|
1029
1445
|
return foldPerforationSubKind(
|
|
1030
1446
|
{
|
|
1031
|
-
Perforation: () =>
|
|
1447
|
+
Perforation: () =>
|
|
1448
|
+
createSubkindPerforationTexture.spikes(
|
|
1449
|
+
perforation,
|
|
1450
|
+
perfShape,
|
|
1451
|
+
otherPerforations,
|
|
1452
|
+
perforationOptions,
|
|
1453
|
+
),
|
|
1032
1454
|
OpenHoleGravelPack: () => createSubkindOpenHoleGravelPackTexture.spikes(),
|
|
1033
1455
|
OpenHoleFracPack: () => createSubkindOpenHoleFracPackTexture.spikes(),
|
|
1034
|
-
CasedHoleFracturation: () =>
|
|
1035
|
-
|
|
1456
|
+
CasedHoleFracturation: () =>
|
|
1457
|
+
createSubkindCasedHoleFracturationTexture.spikes(),
|
|
1458
|
+
CasedHoleGravelPack: () =>
|
|
1459
|
+
createSubkindCasedHoleGravelPackTexture.spikes(),
|
|
1036
1460
|
CasedHoleFracPack: () => createSubkindCasedHoleFracPackTexture.spikes(),
|
|
1037
1461
|
},
|
|
1038
1462
|
perforation.subKind,
|