@equinor/esv-intersection 3.1.9 → 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 +10 -10
- 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 +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +2533 -1570
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +2 -2
- package/dist/index.umd.js.map +1 -1
- package/dist/layers/CalloutCanvasLayer.d.ts.map +1 -1
- package/dist/layers/CustomDisplayObjects/ComplexRope.d.ts +2 -3
- package/dist/layers/CustomDisplayObjects/ComplexRope.d.ts.map +1 -1
- package/dist/layers/CustomDisplayObjects/ComplexRopeGeometry.d.ts.map +1 -1
- package/dist/layers/CustomDisplayObjects/FixedWidthSimpleRope.d.ts +3 -4
- package/dist/layers/CustomDisplayObjects/FixedWidthSimpleRope.d.ts.map +1 -1
- package/dist/layers/CustomDisplayObjects/FixedWidthSimpleRopeGeometry.d.ts +4 -4
- package/dist/layers/CustomDisplayObjects/FixedWidthSimpleRopeGeometry.d.ts.map +1 -1
- package/dist/layers/CustomDisplayObjects/UniformTextureStretchRope.d.ts +3 -4
- package/dist/layers/CustomDisplayObjects/UniformTextureStretchRope.d.ts.map +1 -1
- package/dist/layers/CustomDisplayObjects/UniformTextureStretchRopeGeometry.d.ts +4 -4
- package/dist/layers/CustomDisplayObjects/UniformTextureStretchRopeGeometry.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 +6 -6
- 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 +7 -8
- 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 +6 -6
- package/dist/utils/vectorUtils.d.ts.map +1 -1
- package/dist/vendor/pixi-dashed-line/index.d.ts +13 -13
- package/dist/vendor/pixi-dashed-line/index.d.ts.map +1 -1
- package/package.json +4 -6
- 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 +591 -165
- 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 +11 -13
- package/src/layers/CustomDisplayObjects/ComplexRopeGeometry.ts +14 -13
- package/src/layers/CustomDisplayObjects/FixedWidthSimpleRope.ts +11 -14
- package/src/layers/CustomDisplayObjects/FixedWidthSimpleRopeGeometry.ts +13 -12
- package/src/layers/CustomDisplayObjects/UniformTextureStretchRope.ts +16 -17
- package/src/layers/CustomDisplayObjects/UniformTextureStretchRopeGeometry.ts +11 -11
- package/src/layers/GeomodelCanvasLayer.ts +10 -3
- package/src/layers/GeomodelLabelsLayer.ts +212 -87
- package/src/layers/GeomodelLayerV2.ts +11 -7
- 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 +533 -173
- 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 +36 -43
- 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 +27 -10
- package/src/vendor/pixi-dashed-line/index.ts +93 -39
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CanvasSource, groupD8, Point, Rectangle, Texture } from 'pixi.js';
|
|
2
2
|
import { DEFAULT_TEXTURE_SIZE } from '../constants';
|
|
3
3
|
import {
|
|
4
4
|
Casing,
|
|
@@ -51,21 +51,34 @@ export interface CasingRenderObject {
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
export const getEndLines = (
|
|
54
|
-
rightPath: [
|
|
55
|
-
leftPath: [
|
|
54
|
+
rightPath: [Point, Point, ...Point[]],
|
|
55
|
+
leftPath: [Point, Point, ...Point[]],
|
|
56
56
|
): {
|
|
57
|
-
top: [
|
|
58
|
-
bottom: [
|
|
57
|
+
top: [Point, Point];
|
|
58
|
+
bottom: [Point, Point];
|
|
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
|
|
|
@@ -798,13 +1101,15 @@ const errorTexture = (errorMessage = 'Error!', existingContext?: { canvas: HTMLC
|
|
|
798
1101
|
canvasCtx.fillStyle = '#ff00ff';
|
|
799
1102
|
canvasCtx.fillRect(...xy, ...wh);
|
|
800
1103
|
|
|
801
|
-
const texture = new Texture(
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
1104
|
+
const texture = new Texture({
|
|
1105
|
+
source: new CanvasSource({
|
|
1106
|
+
resource: canvas,
|
|
1107
|
+
wrapMode: 'clamp-to-edge',
|
|
1108
|
+
}),
|
|
1109
|
+
orig: new Rectangle(0, 0, canvas.width, canvas.height),
|
|
1110
|
+
rotate: groupD8.MIRROR_HORIZONTAL,
|
|
1111
|
+
});
|
|
1112
|
+
|
|
808
1113
|
return texture;
|
|
809
1114
|
};
|
|
810
1115
|
|
|
@@ -827,19 +1132,22 @@ const createPerforationCanvas = (
|
|
|
827
1132
|
};
|
|
828
1133
|
|
|
829
1134
|
const createPerforationTexture = (canvas: HTMLCanvasElement) => {
|
|
830
|
-
const texture = new Texture(
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
groupD8.MIRROR_HORIZONTAL,
|
|
836
|
-
);
|
|
1135
|
+
const texture = new Texture({
|
|
1136
|
+
source: new CanvasSource({
|
|
1137
|
+
resource: canvas,
|
|
1138
|
+
}),
|
|
1139
|
+
orig: new Rectangle(0, 0, canvas.width, canvas.height),
|
|
1140
|
+
rotate: groupD8.MIRROR_HORIZONTAL,
|
|
1141
|
+
});
|
|
837
1142
|
return texture;
|
|
838
1143
|
};
|
|
839
1144
|
|
|
840
1145
|
const compareIntersectingPerforationsBy =
|
|
841
|
-
(targetPerf: Perforation, comparedPerforations: Perforation[]) =>
|
|
842
|
-
|
|
1146
|
+
(targetPerf: Perforation, comparedPerforations: Perforation[]) =>
|
|
1147
|
+
(compareFunc: (comparedPerf: Perforation) => boolean) =>
|
|
1148
|
+
comparedPerforations.some(
|
|
1149
|
+
perf => compareFunc(perf) && intersect(targetPerf, perf),
|
|
1150
|
+
);
|
|
843
1151
|
|
|
844
1152
|
/**
|
|
845
1153
|
* @Perforation
|
|
@@ -869,19 +1177,36 @@ const createSubkindPerforationTexture = {
|
|
|
869
1177
|
otherPerforations: Perforation[],
|
|
870
1178
|
perforationOptions: PerforationOptions,
|
|
871
1179
|
): Texture => {
|
|
872
|
-
const { canvas, ctx } = createPerforationCanvas(
|
|
1180
|
+
const { canvas, ctx } = createPerforationCanvas(
|
|
1181
|
+
perfShape,
|
|
1182
|
+
perforationOptions,
|
|
1183
|
+
);
|
|
873
1184
|
|
|
874
|
-
const compareBy = compareIntersectingPerforationsBy(
|
|
1185
|
+
const compareBy = compareIntersectingPerforationsBy(
|
|
1186
|
+
perforation,
|
|
1187
|
+
otherPerforations,
|
|
1188
|
+
);
|
|
875
1189
|
|
|
876
|
-
const intersectionsWithCasedHoleGravel: boolean = compareBy(
|
|
1190
|
+
const intersectionsWithCasedHoleGravel: boolean = compareBy(
|
|
1191
|
+
isSubkindCasedHoleGravelPack,
|
|
1192
|
+
);
|
|
877
1193
|
|
|
878
|
-
const intersectsWithCasedHoleFracturation: boolean = compareBy(
|
|
1194
|
+
const intersectsWithCasedHoleFracturation: boolean = compareBy(
|
|
1195
|
+
isSubKindCasedHoleFracturation,
|
|
1196
|
+
);
|
|
879
1197
|
|
|
880
|
-
const intersectionsWithCasedHoleFracPack: boolean = compareBy(
|
|
1198
|
+
const intersectionsWithCasedHoleFracPack: boolean = compareBy(
|
|
1199
|
+
isSubKindCasedHoleFracPack,
|
|
1200
|
+
);
|
|
881
1201
|
|
|
882
|
-
const intersectsWithPerforation =
|
|
1202
|
+
const intersectsWithPerforation =
|
|
1203
|
+
intersectionsWithCasedHoleGravel ||
|
|
1204
|
+
intersectsWithCasedHoleFracturation ||
|
|
1205
|
+
intersectionsWithCasedHoleFracPack;
|
|
883
1206
|
|
|
884
|
-
const openPerforationSpikeColor = intersectsWithPerforation
|
|
1207
|
+
const openPerforationSpikeColor = intersectsWithPerforation
|
|
1208
|
+
? perforationOptions.yellow
|
|
1209
|
+
: perforationOptions.red;
|
|
885
1210
|
|
|
886
1211
|
ctx.globalAlpha = perforationOptions.packingOpacity;
|
|
887
1212
|
if (perforation.isOpen) {
|
|
@@ -895,7 +1220,13 @@ const createSubkindPerforationTexture = {
|
|
|
895
1220
|
drawSpikes(canvas, ctx, perfShape.diameter, perforationOptions);
|
|
896
1221
|
|
|
897
1222
|
if (intersectionsWithCasedHoleFracPack) {
|
|
898
|
-
drawFracLines(
|
|
1223
|
+
drawFracLines(
|
|
1224
|
+
canvas,
|
|
1225
|
+
ctx,
|
|
1226
|
+
perfShape.diameter,
|
|
1227
|
+
perforationOptions,
|
|
1228
|
+
'spike',
|
|
1229
|
+
);
|
|
899
1230
|
}
|
|
900
1231
|
|
|
901
1232
|
return createPerforationTexture(canvas);
|
|
@@ -908,9 +1239,21 @@ const createSubkindPerforationTexture = {
|
|
|
908
1239
|
*/
|
|
909
1240
|
const createSubkindCasedHoleFracturationTexture = {
|
|
910
1241
|
packing: () => errorTexture(),
|
|
911
|
-
fracLines: (
|
|
912
|
-
|
|
913
|
-
|
|
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
|
+
);
|
|
914
1257
|
return createPerforationTexture(canvas);
|
|
915
1258
|
},
|
|
916
1259
|
spikes: () => errorTexture(),
|
|
@@ -924,12 +1267,21 @@ const createSubkindCasedHoleFracturationTexture = {
|
|
|
924
1267
|
* If a perforation of type "perforation" is overlapping, the fracturation lines extends from the tip of the perforation spikes into formation.
|
|
925
1268
|
*/
|
|
926
1269
|
const createSubkindCasedHoleFracPackTexture = {
|
|
927
|
-
packing: (
|
|
928
|
-
|
|
1270
|
+
packing: (
|
|
1271
|
+
perfShape: ComplexRopeSegment,
|
|
1272
|
+
perforationOptions: PerforationOptions,
|
|
1273
|
+
): Texture => {
|
|
1274
|
+
const { canvas, ctx } = createPerforationCanvas(
|
|
1275
|
+
perfShape,
|
|
1276
|
+
perforationOptions,
|
|
1277
|
+
);
|
|
929
1278
|
drawPacking(canvas, ctx, perforationOptions);
|
|
930
1279
|
return createPerforationTexture(canvas);
|
|
931
1280
|
},
|
|
932
|
-
fracLines: (
|
|
1281
|
+
fracLines: (
|
|
1282
|
+
perfShape: ComplexRopeSegment,
|
|
1283
|
+
perforationOptions: PerforationOptions,
|
|
1284
|
+
) => {
|
|
933
1285
|
const { canvas } = createPerforationCanvas(perfShape, perforationOptions);
|
|
934
1286
|
return createPerforationTexture(canvas);
|
|
935
1287
|
},
|
|
@@ -941,8 +1293,14 @@ const createSubkindCasedHoleFracPackTexture = {
|
|
|
941
1293
|
* Yellow gravel. Makes perforations of type "Perforation" yellow if overlapping and perforation are open.
|
|
942
1294
|
*/
|
|
943
1295
|
const createSubkindCasedHoleGravelPackTexture = {
|
|
944
|
-
packing: (
|
|
945
|
-
|
|
1296
|
+
packing: (
|
|
1297
|
+
perfShape: ComplexRopeSegment,
|
|
1298
|
+
perforationOptions: PerforationOptions,
|
|
1299
|
+
): Texture => {
|
|
1300
|
+
const { canvas, ctx } = createPerforationCanvas(
|
|
1301
|
+
perfShape,
|
|
1302
|
+
perforationOptions,
|
|
1303
|
+
);
|
|
946
1304
|
drawPacking(canvas, ctx, perforationOptions);
|
|
947
1305
|
return createPerforationTexture(canvas);
|
|
948
1306
|
},
|
|
@@ -955,8 +1313,14 @@ const createSubkindCasedHoleGravelPackTexture = {
|
|
|
955
1313
|
* Yellow gravel
|
|
956
1314
|
*/
|
|
957
1315
|
const createSubkindOpenHoleGravelPackTexture = {
|
|
958
|
-
packing: (
|
|
959
|
-
|
|
1316
|
+
packing: (
|
|
1317
|
+
perfShape: ComplexRopeSegment,
|
|
1318
|
+
perforationOptions: PerforationOptions,
|
|
1319
|
+
) => {
|
|
1320
|
+
const { canvas, ctx } = createPerforationCanvas(
|
|
1321
|
+
perfShape,
|
|
1322
|
+
perforationOptions,
|
|
1323
|
+
);
|
|
960
1324
|
drawPacking(canvas, ctx, perforationOptions);
|
|
961
1325
|
return createPerforationTexture(canvas);
|
|
962
1326
|
},
|
|
@@ -969,14 +1333,33 @@ const createSubkindOpenHoleGravelPackTexture = {
|
|
|
969
1333
|
* Yellow gravel. Yellow frac lines from hole OD into formation
|
|
970
1334
|
*/
|
|
971
1335
|
const createSubkindOpenHoleFracPackTexture = {
|
|
972
|
-
packing: (
|
|
973
|
-
|
|
1336
|
+
packing: (
|
|
1337
|
+
_perforation: Perforation,
|
|
1338
|
+
perfShape: ComplexRopeSegment,
|
|
1339
|
+
perforationOptions: PerforationOptions,
|
|
1340
|
+
) => {
|
|
1341
|
+
const { canvas, ctx } = createPerforationCanvas(
|
|
1342
|
+
perfShape,
|
|
1343
|
+
perforationOptions,
|
|
1344
|
+
);
|
|
974
1345
|
drawPacking(canvas, ctx, perforationOptions);
|
|
975
1346
|
return createPerforationTexture(canvas);
|
|
976
1347
|
},
|
|
977
|
-
fracLines: (
|
|
978
|
-
|
|
979
|
-
|
|
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
|
+
);
|
|
980
1363
|
return createPerforationTexture(canvas);
|
|
981
1364
|
},
|
|
982
1365
|
spikes: () => errorTexture(),
|
|
@@ -990,11 +1373,32 @@ export const createPerforationPackingTexture = (
|
|
|
990
1373
|
return foldPerforationSubKind(
|
|
991
1374
|
{
|
|
992
1375
|
Perforation: () => createSubkindPerforationTexture.packing(),
|
|
993
|
-
CasedHoleFracturation: () =>
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
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
|
+
),
|
|
998
1402
|
},
|
|
999
1403
|
perforation.subKind,
|
|
1000
1404
|
);
|
|
@@ -1008,11 +1412,25 @@ export const createPerforationFracLineTexture = (
|
|
|
1008
1412
|
return foldPerforationSubKind(
|
|
1009
1413
|
{
|
|
1010
1414
|
Perforation: () => createSubkindPerforationTexture.fracLines(),
|
|
1011
|
-
OpenHoleGravelPack: () =>
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
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
|
+
),
|
|
1016
1434
|
},
|
|
1017
1435
|
perforation.subKind,
|
|
1018
1436
|
);
|
|
@@ -1026,11 +1444,19 @@ export const createPerforationSpikeTexture = (
|
|
|
1026
1444
|
): Texture => {
|
|
1027
1445
|
return foldPerforationSubKind(
|
|
1028
1446
|
{
|
|
1029
|
-
Perforation: () =>
|
|
1447
|
+
Perforation: () =>
|
|
1448
|
+
createSubkindPerforationTexture.spikes(
|
|
1449
|
+
perforation,
|
|
1450
|
+
perfShape,
|
|
1451
|
+
otherPerforations,
|
|
1452
|
+
perforationOptions,
|
|
1453
|
+
),
|
|
1030
1454
|
OpenHoleGravelPack: () => createSubkindOpenHoleGravelPackTexture.spikes(),
|
|
1031
1455
|
OpenHoleFracPack: () => createSubkindOpenHoleFracPackTexture.spikes(),
|
|
1032
|
-
CasedHoleFracturation: () =>
|
|
1033
|
-
|
|
1456
|
+
CasedHoleFracturation: () =>
|
|
1457
|
+
createSubkindCasedHoleFracturationTexture.spikes(),
|
|
1458
|
+
CasedHoleGravelPack: () =>
|
|
1459
|
+
createSubkindCasedHoleGravelPackTexture.spikes(),
|
|
1034
1460
|
CasedHoleFracPack: () => createSubkindCasedHoleFracPackTexture.spikes(),
|
|
1035
1461
|
},
|
|
1036
1462
|
perforation.subKind,
|