@equinor/esv-intersection 3.0.4 → 3.0.6
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/README.md +18 -3
- package/dist/components/axis.d.ts +48 -0
- package/dist/components/axis.d.ts.map +1 -0
- package/dist/components/index.d.ts +2 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/constants.d.ts +1 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/control/ExtendedCurveInterpolator.d.ts +59 -0
- package/dist/control/ExtendedCurveInterpolator.d.ts.map +1 -0
- package/dist/control/IntersectionReferenceSystem.d.ts +97 -0
- package/dist/control/IntersectionReferenceSystem.d.ts.map +1 -0
- package/dist/control/LayerManager.d.ts +77 -0
- package/dist/control/LayerManager.d.ts.map +1 -0
- package/dist/control/MainController.d.ts +155 -0
- package/dist/control/MainController.d.ts.map +1 -0
- package/dist/control/ZoomPanHandler.d.ts +159 -0
- package/dist/control/ZoomPanHandler.d.ts.map +1 -0
- package/dist/control/index.d.ts +6 -0
- package/dist/control/index.d.ts.map +1 -0
- package/dist/control/interfaces.d.ts +38 -0
- package/dist/control/interfaces.d.ts.map +1 -0
- package/dist/control/overlay.d.ts +21 -0
- package/dist/control/overlay.d.ts.map +1 -0
- package/dist/datautils/colortable.d.ts +2 -0
- package/dist/datautils/colortable.d.ts.map +1 -0
- package/dist/datautils/findsample.d.ts +3 -0
- package/dist/datautils/findsample.d.ts.map +1 -0
- package/dist/datautils/index.d.ts +7 -0
- package/dist/datautils/index.d.ts.map +1 -0
- package/dist/datautils/interfaces.d.ts +64 -0
- package/dist/datautils/interfaces.d.ts.map +1 -0
- package/dist/datautils/picks.d.ts +75 -0
- package/dist/datautils/picks.d.ts.map +1 -0
- package/dist/datautils/schematicShapeGenerator.d.ts +60 -0
- package/dist/datautils/schematicShapeGenerator.d.ts.map +1 -0
- package/dist/datautils/seismicimage.d.ts +46 -0
- package/dist/datautils/seismicimage.d.ts.map +1 -0
- package/dist/datautils/surfacedata.d.ts +11 -0
- package/dist/datautils/surfacedata.d.ts.map +1 -0
- package/dist/datautils/trajectory.d.ts +15 -0
- package/dist/datautils/trajectory.d.ts.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.mjs +141 -143
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/index.umd.js.map +1 -1
- package/dist/interfaces.d.ts +1 -0
- package/dist/interfaces.d.ts.map +1 -0
- package/dist/layers/CalloutCanvasLayer.d.ts +61 -0
- package/dist/layers/CalloutCanvasLayer.d.ts.map +1 -0
- package/dist/layers/CustomDisplayObjects/ComplexRope.d.ts +22 -0
- package/dist/layers/CustomDisplayObjects/ComplexRope.d.ts.map +1 -0
- package/dist/layers/CustomDisplayObjects/ComplexRopeGeometry.d.ts +24 -0
- package/dist/layers/CustomDisplayObjects/ComplexRopeGeometry.d.ts.map +1 -0
- package/dist/layers/CustomDisplayObjects/FixedWidthSimpleRope.d.ts +21 -0
- package/dist/layers/CustomDisplayObjects/FixedWidthSimpleRope.d.ts.map +1 -0
- package/dist/layers/CustomDisplayObjects/FixedWidthSimpleRopeGeometry.d.ts +27 -0
- package/dist/layers/CustomDisplayObjects/FixedWidthSimpleRopeGeometry.d.ts.map +1 -0
- package/dist/layers/CustomDisplayObjects/UniformTextureStretchRope.d.ts +18 -0
- package/dist/layers/CustomDisplayObjects/UniformTextureStretchRope.d.ts.map +1 -0
- package/dist/layers/CustomDisplayObjects/UniformTextureStretchRopeGeometry.d.ts +25 -0
- package/dist/layers/CustomDisplayObjects/UniformTextureStretchRopeGeometry.d.ts.map +1 -0
- package/dist/layers/GeomodelCanvasLayer.d.ts +29 -0
- package/dist/layers/GeomodelCanvasLayer.d.ts.map +1 -0
- package/dist/layers/GeomodelLabelsLayer.d.ts +50 -0
- package/dist/layers/GeomodelLabelsLayer.d.ts.map +1 -0
- package/dist/layers/GeomodelLayerV2.d.ts +13 -0
- package/dist/layers/GeomodelLayerV2.d.ts.map +1 -0
- package/dist/layers/GridLayer.d.ts +30 -0
- package/dist/layers/GridLayer.d.ts.map +1 -0
- package/dist/layers/ImageCanvasLayer.d.ts +21 -0
- package/dist/layers/ImageCanvasLayer.d.ts.map +1 -0
- package/dist/layers/ReferenceLineLayer.d.ts +30 -0
- package/dist/layers/ReferenceLineLayer.d.ts.map +1 -0
- package/dist/layers/SchematicLayer.d.ts +114 -0
- package/dist/layers/SchematicLayer.d.ts.map +1 -0
- package/dist/layers/SeismicCanvasLayer.d.ts +19 -0
- package/dist/layers/SeismicCanvasLayer.d.ts.map +1 -0
- package/dist/layers/WellborePathLayer.d.ts +18 -0
- package/dist/layers/WellborePathLayer.d.ts.map +1 -0
- package/dist/layers/base/CanvasLayer.d.ts +20 -0
- package/dist/layers/base/CanvasLayer.d.ts.map +1 -0
- package/dist/layers/base/HTMLLayer.d.ts +14 -0
- package/dist/layers/base/HTMLLayer.d.ts.map +1 -0
- package/dist/layers/base/Layer.d.ts +70 -0
- package/dist/layers/base/Layer.d.ts.map +1 -0
- package/dist/layers/base/PixiLayer.d.ts +33 -0
- package/dist/layers/base/PixiLayer.d.ts.map +1 -0
- package/dist/layers/base/SVGLayer.d.ts +14 -0
- package/dist/layers/base/SVGLayer.d.ts.map +1 -0
- package/dist/layers/base/index.d.ts +6 -0
- package/dist/layers/base/index.d.ts.map +1 -0
- package/dist/layers/index.d.ts +17 -0
- package/dist/layers/index.d.ts.map +1 -0
- package/dist/layers/schematicInterfaces.d.ts +210 -0
- package/dist/layers/schematicInterfaces.d.ts.map +1 -0
- package/dist/utils/arc-length.d.ts +24 -0
- package/dist/utils/arc-length.d.ts.map +1 -0
- package/dist/utils/binary-search.d.ts +9 -0
- package/dist/utils/binary-search.d.ts.map +1 -0
- package/dist/utils/color.d.ts +6 -0
- package/dist/utils/color.d.ts.map +1 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/root-finder.d.ts +35 -0
- package/dist/utils/root-finder.d.ts.map +1 -0
- package/dist/utils/text.d.ts +15 -0
- package/dist/utils/text.d.ts.map +1 -0
- package/dist/utils/vectorUtils.d.ts +16 -0
- package/dist/utils/vectorUtils.d.ts.map +1 -0
- package/dist/vendor/pixi-dashed-line/index.d.ts +57 -0
- package/dist/vendor/pixi-dashed-line/index.d.ts.map +1 -0
- package/package.json +28 -21
- package/src/.eslintrc.json +5 -0
- package/src/components/axis.ts +247 -0
- package/src/components/index.ts +1 -0
- package/src/control/ExtendedCurveInterpolator.ts +155 -0
- package/src/control/IntersectionReferenceSystem.ts +391 -0
- package/src/control/LayerManager.ts +294 -0
- package/src/control/MainController.ts +296 -0
- package/src/control/ZoomPanHandler.ts +436 -0
- package/src/control/index.ts +5 -0
- package/src/control/interfaces.ts +42 -0
- package/src/control/overlay.ts +118 -0
- package/src/datautils/colortable.ts +14 -0
- package/src/datautils/findsample.ts +64 -0
- package/src/datautils/index.ts +6 -0
- package/src/datautils/interfaces.ts +68 -0
- package/src/datautils/picks.ts +328 -0
- package/src/datautils/schematicShapeGenerator.ts +1008 -0
- package/src/datautils/seismicimage.ts +180 -0
- package/src/datautils/surfacedata.ts +317 -0
- package/src/datautils/trajectory.ts +206 -0
- package/src/layers/CalloutCanvasLayer.ts +338 -0
- package/src/layers/CustomDisplayObjects/ComplexRope.ts +44 -0
- package/src/layers/CustomDisplayObjects/ComplexRopeGeometry.ts +184 -0
- package/src/layers/CustomDisplayObjects/FixedWidthSimpleRope.ts +41 -0
- package/src/layers/CustomDisplayObjects/FixedWidthSimpleRopeGeometry.ts +149 -0
- package/src/layers/CustomDisplayObjects/UniformTextureStretchRope.ts +39 -0
- package/src/layers/CustomDisplayObjects/UniformTextureStretchRopeGeometry.ts +174 -0
- package/src/layers/GeomodelCanvasLayer.ts +176 -0
- package/src/layers/GeomodelLabelsLayer.ts +615 -0
- package/src/layers/GeomodelLayerV2.ts +111 -0
- package/src/layers/GridLayer.ts +145 -0
- package/src/layers/ImageCanvasLayer.ts +55 -0
- package/src/layers/ReferenceLineLayer.ts +185 -0
- package/src/layers/SchematicLayer.ts +870 -0
- package/src/layers/SeismicCanvasLayer.ts +46 -0
- package/src/layers/WellborePathLayer.ts +129 -0
- package/src/layers/base/CanvasLayer.ts +102 -0
- package/src/layers/base/HTMLLayer.ts +70 -0
- package/src/layers/base/Layer.ts +217 -0
- package/src/layers/base/PixiLayer.ts +190 -0
- package/src/layers/base/SVGLayer.ts +63 -0
- package/src/layers/base/index.ts +5 -0
- package/src/layers/index.ts +16 -0
- package/src/layers/schematicInterfaces.ts +472 -0
- package/src/tsconfig.json +9 -0
- package/src/utils/arc-length.ts +66 -0
- package/src/utils/binary-search.ts +26 -0
- package/src/utils/color.ts +22 -0
- package/src/utils/index.ts +1 -0
- package/src/utils/root-finder.ts +78 -0
- package/src/utils/text.ts +88 -0
- package/src/utils/vectorUtils.ts +67 -0
- package/src/vendor/pixi-dashed-line/index.ts +390 -0
|
@@ -0,0 +1,870 @@
|
|
|
1
|
+
import { max } from 'd3-array';
|
|
2
|
+
import { scaleLinear, ScaleLinear } from 'd3-scale';
|
|
3
|
+
import { Graphics, groupD8, IPoint, Point, Rectangle, SimpleRope, Texture } from 'pixi.js';
|
|
4
|
+
import { DashLine } from '../vendor/pixi-dashed-line';
|
|
5
|
+
import { LayerOptions, PixiLayer, PixiRenderApplication } from '.';
|
|
6
|
+
import { DEFAULT_TEXTURE_SIZE, EXAGGERATED_DIAMETER, HOLE_OUTLINE, SCREEN_OUTLINE } from '../constants';
|
|
7
|
+
import {
|
|
8
|
+
assertNever,
|
|
9
|
+
Casing,
|
|
10
|
+
CasingOptions,
|
|
11
|
+
Cement,
|
|
12
|
+
CementOptions,
|
|
13
|
+
CementPlugOptions,
|
|
14
|
+
CementSqueeze,
|
|
15
|
+
CementSqueezeOptions,
|
|
16
|
+
foldCompletion,
|
|
17
|
+
HoleOptions,
|
|
18
|
+
HoleSize,
|
|
19
|
+
isCementSqueeze,
|
|
20
|
+
PAndA,
|
|
21
|
+
SchematicData,
|
|
22
|
+
ScreenOptions,
|
|
23
|
+
TubingOptions,
|
|
24
|
+
Screen,
|
|
25
|
+
Tubing,
|
|
26
|
+
CompletionSymbol,
|
|
27
|
+
isPAndASymbol,
|
|
28
|
+
isCementPlug,
|
|
29
|
+
CementPlug,
|
|
30
|
+
PAndASymbol,
|
|
31
|
+
InternalLayerOptions,
|
|
32
|
+
defaultHoleOptions,
|
|
33
|
+
defaultCasingOptions,
|
|
34
|
+
defaultCementOptions,
|
|
35
|
+
defaultCementSqueezeOptions,
|
|
36
|
+
defaultCementPlugOptions,
|
|
37
|
+
defaultScreenOptions,
|
|
38
|
+
defaultTubingOptions,
|
|
39
|
+
defaultInternalLayerOptions,
|
|
40
|
+
Perforation,
|
|
41
|
+
PerforationOptions,
|
|
42
|
+
defaultPerforationOptions,
|
|
43
|
+
Completion,
|
|
44
|
+
OutlineClosure,
|
|
45
|
+
hasPacking,
|
|
46
|
+
hasFracLines,
|
|
47
|
+
hasSpikes,
|
|
48
|
+
} from './schematicInterfaces';
|
|
49
|
+
import {
|
|
50
|
+
CasingRenderObject,
|
|
51
|
+
createCementTexture,
|
|
52
|
+
createComplexRopeSegmentsForCement,
|
|
53
|
+
createComplexRopeSegmentsForCementSqueeze,
|
|
54
|
+
createComplexRopeSegmentsForCementPlug,
|
|
55
|
+
createHoleBaseTexture,
|
|
56
|
+
createScreenTexture,
|
|
57
|
+
createTubingTexture,
|
|
58
|
+
createTubularRenderingObject,
|
|
59
|
+
prepareCasingRenderObject,
|
|
60
|
+
createCementPlugTexture,
|
|
61
|
+
createComplexRopeSegmentsForPerforation,
|
|
62
|
+
createPerforationPackingTexture,
|
|
63
|
+
PerforationShape,
|
|
64
|
+
createCementSqueezeTexture,
|
|
65
|
+
createPerforationFracLineTexture,
|
|
66
|
+
createPerforationSpikeTexture,
|
|
67
|
+
} from '../datautils/schematicShapeGenerator';
|
|
68
|
+
import { OnUpdateEvent, OnRescaleEvent, OnUnmountEvent } from '../interfaces';
|
|
69
|
+
import { convertColor } from '../utils/color';
|
|
70
|
+
import { createNormals, offsetPoint, offsetPoints } from '../utils/vectorUtils';
|
|
71
|
+
import { ComplexRope, ComplexRopeSegment } from './CustomDisplayObjects/ComplexRope';
|
|
72
|
+
import { FixedWidthSimpleRope } from './CustomDisplayObjects/FixedWidthSimpleRope';
|
|
73
|
+
import { UniformTextureStretchRope } from './CustomDisplayObjects/UniformTextureStretchRope';
|
|
74
|
+
|
|
75
|
+
interface ScalingFactors {
|
|
76
|
+
height: number;
|
|
77
|
+
zFactor: number;
|
|
78
|
+
yScale: ScaleLinear<number, number, never>;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
interface SymbolRenderObject {
|
|
82
|
+
pathPoints: Point[];
|
|
83
|
+
referenceDiameter: number;
|
|
84
|
+
symbolKey: string;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
interface CementRenderObject {
|
|
88
|
+
kind: 'cement';
|
|
89
|
+
segments: ComplexRopeSegment[];
|
|
90
|
+
casingIds: string[];
|
|
91
|
+
zIndex?: number;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
interface CementSqueezeRenderObject {
|
|
95
|
+
kind: 'cementSqueeze';
|
|
96
|
+
segments: ComplexRopeSegment[];
|
|
97
|
+
casingIds: string[];
|
|
98
|
+
zIndex?: number;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
type InterlacedRenderObjects = CasingRenderObject | CementRenderObject | CementSqueezeRenderObject;
|
|
102
|
+
|
|
103
|
+
const foldInterlacedRenderObjects =
|
|
104
|
+
<T>(fCasing: (obj: CasingRenderObject) => T, fCement: (obj: CementRenderObject) => T, fCementSqueeze: (obj: CementSqueezeRenderObject) => T) =>
|
|
105
|
+
(renderObject: InterlacedRenderObjects): T => {
|
|
106
|
+
switch (renderObject.kind) {
|
|
107
|
+
case 'casing':
|
|
108
|
+
return fCasing(renderObject);
|
|
109
|
+
case 'cement':
|
|
110
|
+
return fCement(renderObject);
|
|
111
|
+
case 'cementSqueeze':
|
|
112
|
+
return fCementSqueeze(renderObject);
|
|
113
|
+
default:
|
|
114
|
+
return assertNever(renderObject);
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
export interface SchematicLayerOptions<T extends SchematicData> extends LayerOptions<T> {
|
|
119
|
+
exaggerationFactor?: number;
|
|
120
|
+
internalLayerOptions?: InternalLayerOptions;
|
|
121
|
+
holeOptions?: HoleOptions;
|
|
122
|
+
casingOptions?: CasingOptions;
|
|
123
|
+
cementOptions?: CementOptions;
|
|
124
|
+
cementSqueezeOptions?: CementSqueezeOptions;
|
|
125
|
+
screenOptions?: ScreenOptions;
|
|
126
|
+
tubingOptions?: TubingOptions;
|
|
127
|
+
cementPlugOptions?: CementPlugOptions;
|
|
128
|
+
perforationOptions?: PerforationOptions;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const defaultSchematicLayerOptions = (layerId: string): SchematicLayerOptions<SchematicData> => ({
|
|
132
|
+
exaggerationFactor: 2,
|
|
133
|
+
internalLayerOptions: defaultInternalLayerOptions(layerId),
|
|
134
|
+
holeOptions: defaultHoleOptions,
|
|
135
|
+
casingOptions: defaultCasingOptions,
|
|
136
|
+
cementOptions: defaultCementOptions,
|
|
137
|
+
cementSqueezeOptions: defaultCementSqueezeOptions,
|
|
138
|
+
screenOptions: defaultScreenOptions,
|
|
139
|
+
tubingOptions: defaultTubingOptions,
|
|
140
|
+
cementPlugOptions: defaultCementPlugOptions,
|
|
141
|
+
perforationOptions: defaultPerforationOptions,
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
type InternalLayerVisibility = { [K in keyof InternalLayerOptions]: boolean };
|
|
145
|
+
|
|
146
|
+
export class SchematicLayer<T extends SchematicData> extends PixiLayer<T> {
|
|
147
|
+
private internalLayerVisibility: InternalLayerVisibility = {
|
|
148
|
+
holeLayerId: true,
|
|
149
|
+
casingLayerId: true,
|
|
150
|
+
completionLayerId: true,
|
|
151
|
+
cementLayerId: true,
|
|
152
|
+
pAndALayerId: true,
|
|
153
|
+
perforationLayerId: true,
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
private cementTextureCache: Texture;
|
|
157
|
+
private cementSqueezeTextureCache: Texture;
|
|
158
|
+
private cementPlugTextureCache: Texture;
|
|
159
|
+
private holeTextureCache: Texture;
|
|
160
|
+
private screenTextureCache: Texture;
|
|
161
|
+
private tubingTextureCache: Texture;
|
|
162
|
+
private textureSymbolCacheArray: { [key: string]: Texture };
|
|
163
|
+
|
|
164
|
+
protected scalingFactors: ScalingFactors = {
|
|
165
|
+
height: 600,
|
|
166
|
+
zFactor: 1,
|
|
167
|
+
yScale: scaleLinear(),
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
constructor(ctx: PixiRenderApplication, id?: string, options?: SchematicLayerOptions<T>) {
|
|
171
|
+
super(ctx, id, options);
|
|
172
|
+
this.options = <SchematicLayerOptions<T>>{
|
|
173
|
+
...this.options,
|
|
174
|
+
...defaultSchematicLayerOptions(this.id),
|
|
175
|
+
...options,
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
public override onUnmount(event?: OnUnmountEvent): void {
|
|
180
|
+
super.onUnmount(event);
|
|
181
|
+
this.scalingFactors = null;
|
|
182
|
+
this.cementTextureCache = null;
|
|
183
|
+
this.cementSqueezeTextureCache = null;
|
|
184
|
+
this.holeTextureCache = null;
|
|
185
|
+
this.screenTextureCache = null;
|
|
186
|
+
this.tubingTextureCache = null;
|
|
187
|
+
this.textureSymbolCacheArray = null;
|
|
188
|
+
this.internalLayerVisibility = null;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
public override onUpdate(event: OnUpdateEvent<T>): void {
|
|
192
|
+
super.onUpdate(event);
|
|
193
|
+
this.clearLayer();
|
|
194
|
+
this.preRender();
|
|
195
|
+
this.render();
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
public override onRescale(event: OnRescaleEvent): void {
|
|
199
|
+
const shouldRecalculate = this.scalingFactors.zFactor !== event.zFactor;
|
|
200
|
+
|
|
201
|
+
this.scalingFactors = { height: event.height, zFactor: event.zFactor, yScale: event.yScale };
|
|
202
|
+
super.optionsRescale(event);
|
|
203
|
+
const yRatio = this.yRatio();
|
|
204
|
+
const flippedX = event.xBounds[0] > event.xBounds[1];
|
|
205
|
+
const flippedY = event.yBounds[0] > event.yBounds[1];
|
|
206
|
+
this.setContainerPosition(event.xScale(0), event.yScale(0));
|
|
207
|
+
this.setContainerScale(event.xRatio * (flippedX ? -1 : 1), yRatio * (flippedY ? -1 : 1));
|
|
208
|
+
if (shouldRecalculate) {
|
|
209
|
+
this.clearLayer();
|
|
210
|
+
this.preRender();
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
this.render();
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
public override setVisibility(isVisible: boolean, layerId: string) {
|
|
217
|
+
if (layerId === this.id) {
|
|
218
|
+
super.setVisibility(isVisible, layerId);
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const { internalLayerOptions } = this.options as SchematicLayerOptions<T>;
|
|
223
|
+
|
|
224
|
+
const [keyFound] = Object.entries(internalLayerOptions).find(([_key, id]: [string, string]) => id === layerId);
|
|
225
|
+
if (keyFound) {
|
|
226
|
+
this.internalLayerVisibility[keyFound as keyof InternalLayerVisibility] = isVisible;
|
|
227
|
+
this.clearLayer();
|
|
228
|
+
this.preRender();
|
|
229
|
+
this.render();
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
public override getInternalLayerIds(): string[] {
|
|
234
|
+
const { internalLayerOptions } = this.options as SchematicLayerOptions<T>;
|
|
235
|
+
return Object.values(internalLayerOptions);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Calculate yRatio without zFactor
|
|
240
|
+
* TODO consider to move this into ZoomPanHandler
|
|
241
|
+
*/
|
|
242
|
+
protected yRatio(): number {
|
|
243
|
+
const domain = this.scalingFactors.yScale.domain();
|
|
244
|
+
const ySpan = domain[1] - domain[0];
|
|
245
|
+
const baseYSpan = ySpan * this.scalingFactors.zFactor;
|
|
246
|
+
const baseDomain = [domain[0], domain[0] + baseYSpan];
|
|
247
|
+
return Math.abs(this.scalingFactors.height / (baseDomain[1] - baseDomain[0]));
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
protected getZFactorScaledPathForPoints = (start: number, end: number): Point[] => {
|
|
251
|
+
const y = (y: number): number => y * this.scalingFactors.zFactor;
|
|
252
|
+
|
|
253
|
+
const path = this.referenceSystem.getCurtainPath(start, end, true);
|
|
254
|
+
return path.map((p) => new Point(p.point[0], y(p.point[1])));
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
protected drawBigPolygon = (coords: IPoint[], color = 0x000000) => {
|
|
258
|
+
const polygon = new Graphics();
|
|
259
|
+
polygon.beginFill(color);
|
|
260
|
+
polygon.drawPolygon(coords);
|
|
261
|
+
polygon.endFill();
|
|
262
|
+
|
|
263
|
+
this.addChild(polygon);
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
protected drawRope(path: Point[], texture: Texture, tint?: number): void {
|
|
267
|
+
if (path.length === 0) {
|
|
268
|
+
return null;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
const rope: SimpleRope = new SimpleRope(texture, path, 1);
|
|
272
|
+
|
|
273
|
+
rope.tint = tint || rope.tint;
|
|
274
|
+
|
|
275
|
+
this.addChild(rope);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
*
|
|
280
|
+
* @param leftPath Points for line on left side
|
|
281
|
+
* @param rightPath Points for line on right side
|
|
282
|
+
* @param lineColor Color of line
|
|
283
|
+
* @param lineWidth Width of line
|
|
284
|
+
* @param outlineClosure If line should be drawn at top and/or bottom of the paths
|
|
285
|
+
* @param lineAlignment alignment of the line to draw, (0 = inner, 0.5 = middle, 1 = outer).
|
|
286
|
+
*/
|
|
287
|
+
protected drawOutline(
|
|
288
|
+
leftPath: Point[],
|
|
289
|
+
rightPath: Point[],
|
|
290
|
+
lineColor: number,
|
|
291
|
+
lineWidth = 1,
|
|
292
|
+
outlineClosure: OutlineClosure = 'None',
|
|
293
|
+
lineAlignment = 1,
|
|
294
|
+
): void {
|
|
295
|
+
const leftPathReverse = leftPath.map<Point>((d) => d.clone()).reverse();
|
|
296
|
+
|
|
297
|
+
const startPointRight = rightPath[0];
|
|
298
|
+
const startPointLeft = leftPathReverse[0];
|
|
299
|
+
|
|
300
|
+
const line = new Graphics();
|
|
301
|
+
line.lineStyle(lineWidth, lineColor, undefined, lineAlignment);
|
|
302
|
+
line.moveTo(startPointRight.x, startPointRight.y);
|
|
303
|
+
rightPath.forEach((p: Point) => line.lineTo(p.x, p.y));
|
|
304
|
+
|
|
305
|
+
if (outlineClosure === 'None' || outlineClosure === 'Top') {
|
|
306
|
+
line.moveTo(startPointLeft.x, startPointLeft.y);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
leftPathReverse.forEach((p: Point) => line.lineTo(p.x, p.y));
|
|
310
|
+
|
|
311
|
+
if (outlineClosure === 'TopAndBottom' || outlineClosure === 'Top') {
|
|
312
|
+
line.lineTo(startPointRight.x, startPointRight.y);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
this.addChild(line);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Uses a dashed outline on one side to represent casing window
|
|
320
|
+
* The casing window should be visualized at the upper side of the wellbore path
|
|
321
|
+
* @param leftPath Points for line on left side
|
|
322
|
+
* @param pointPath Points for line on right side
|
|
323
|
+
* @param lineColor Color of line
|
|
324
|
+
* @param lineWidth Width of line
|
|
325
|
+
* @param lineAlignment alignment of the line to draw, (0 = inner, 0.5 = middle, 1 = outer).
|
|
326
|
+
*/
|
|
327
|
+
protected drawCasingWindowOutline(leftPath: Point[], rightPath: Point[], { lineColor, windowOptions }: CasingOptions, lineWidth = 1): void {
|
|
328
|
+
// Correct the dashed path. Should always be displayed on the upper side of the wellbore path.
|
|
329
|
+
const flippedPaths = !!this.referenceSystem?.options?.calculateDisplacementFromBottom;
|
|
330
|
+
const [linePath, dashedPath] = flippedPaths ? [leftPath, rightPath] : [rightPath, leftPath];
|
|
331
|
+
const [dashedAlignment, solidAlignment] = flippedPaths ? [1, 0] : [0, 1];
|
|
332
|
+
|
|
333
|
+
const graphics = new Graphics();
|
|
334
|
+
graphics.lineStyle(lineWidth, convertColor(lineColor), undefined, solidAlignment);
|
|
335
|
+
|
|
336
|
+
const startPointLinePath = linePath[0];
|
|
337
|
+
graphics.moveTo(startPointLinePath.x, startPointLinePath.y);
|
|
338
|
+
linePath.forEach((p: Point) => graphics.lineTo(p.x, p.y));
|
|
339
|
+
|
|
340
|
+
const dashedLine = new DashLine(graphics, {
|
|
341
|
+
dash: [windowOptions.dashLength, windowOptions.spaceLength],
|
|
342
|
+
color: convertColor(windowOptions.dashColor),
|
|
343
|
+
width: lineWidth,
|
|
344
|
+
alignment: dashedAlignment,
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
const startPointDashedPath = dashedPath[0];
|
|
348
|
+
dashedLine.moveTo(startPointDashedPath.x, startPointDashedPath.y);
|
|
349
|
+
dashedPath.forEach((currentPoint: Point) => {
|
|
350
|
+
dashedLine.lineTo(currentPoint.x, currentPoint.y);
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
this.addChild(graphics);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
private perforationRopeAndTextureReferences: { rope: ComplexRope; texture: Texture }[] = [];
|
|
357
|
+
|
|
358
|
+
public preRender(): void {
|
|
359
|
+
if (!this.data || !this.referenceSystem) {
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
const { exaggerationFactor } = this.options as SchematicLayerOptions<T>;
|
|
364
|
+
const { holeSizes, casings, cements, completion, symbols, pAndA, perforations } = this.data;
|
|
365
|
+
|
|
366
|
+
this.updateSymbolCache(symbols);
|
|
367
|
+
|
|
368
|
+
holeSizes.sort((a: HoleSize, b: HoleSize) => b.diameter - a.diameter);
|
|
369
|
+
const maxHoleDiameter = holeSizes.length > 0 ? max(holeSizes, (d) => d.diameter) * exaggerationFactor : EXAGGERATED_DIAMETER * exaggerationFactor;
|
|
370
|
+
if (this.internalLayerVisibility.holeLayerId) {
|
|
371
|
+
holeSizes.forEach((hole: HoleSize) => this.drawHoleSize(maxHoleDiameter, hole));
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
casings.sort((a: Casing, b: Casing) => b.diameter - a.diameter);
|
|
375
|
+
const casingRenderObjects: CasingRenderObject[] = casings.map((casing: Casing) => this.createCasingRenderObject(casing));
|
|
376
|
+
|
|
377
|
+
const cementShapes: CementRenderObject[] = cements.map(
|
|
378
|
+
(cement: Cement): CementRenderObject => ({
|
|
379
|
+
kind: 'cement',
|
|
380
|
+
segments: createComplexRopeSegmentsForCement(cement, casings, completion, holeSizes, exaggerationFactor, this.getZFactorScaledPathForPoints),
|
|
381
|
+
casingIds: (cement.referenceIds || []).filter((id) => id),
|
|
382
|
+
}),
|
|
383
|
+
);
|
|
384
|
+
|
|
385
|
+
const [cementSqueezes, remainingPAndA] = pAndA.reduce<[CementSqueeze[], Exclude<PAndA, CementSqueeze>[]]>(
|
|
386
|
+
([squeezes, remaining], current: PAndA) =>
|
|
387
|
+
isCementSqueeze(current) ? [[current, ...squeezes], remaining] : [squeezes, [current, ...remaining]],
|
|
388
|
+
[[], []],
|
|
389
|
+
);
|
|
390
|
+
|
|
391
|
+
const cementSqueezesShape: CementSqueezeRenderObject[] = cementSqueezes.map((squeeze) => ({
|
|
392
|
+
kind: 'cementSqueeze',
|
|
393
|
+
segments: this.createCementSqueezeShape(squeeze, casings, completion, holeSizes),
|
|
394
|
+
casingIds: squeeze.referenceIds,
|
|
395
|
+
}));
|
|
396
|
+
|
|
397
|
+
this.sortCementAndCasingRenderObjects(casingRenderObjects, cementShapes, cementSqueezesShape).forEach(
|
|
398
|
+
foldInterlacedRenderObjects(
|
|
399
|
+
(casingRO: CasingRenderObject) => {
|
|
400
|
+
if (this.internalLayerVisibility.casingLayerId) {
|
|
401
|
+
this.drawCasing(casingRO);
|
|
402
|
+
|
|
403
|
+
if (casingRO.hasShoe) {
|
|
404
|
+
this.drawShoe(casingRO.bottom, casingRO.referenceRadius);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
},
|
|
408
|
+
(cementRO: CementRenderObject) => {
|
|
409
|
+
if (this.internalLayerVisibility.cementLayerId) {
|
|
410
|
+
this.drawComplexRope(cementRO.segments, this.getCementTexture());
|
|
411
|
+
}
|
|
412
|
+
},
|
|
413
|
+
(cementSqueezesRO: CementSqueezeRenderObject) => {
|
|
414
|
+
if (this.internalLayerVisibility.pAndALayerId) {
|
|
415
|
+
this.drawComplexRope(cementSqueezesRO.segments, this.getCementSqueezeTexture());
|
|
416
|
+
}
|
|
417
|
+
},
|
|
418
|
+
),
|
|
419
|
+
);
|
|
420
|
+
|
|
421
|
+
this.perforationRopeAndTextureReferences.forEach(({ rope, texture }) => {
|
|
422
|
+
rope.destroy({
|
|
423
|
+
children: true,
|
|
424
|
+
texture: true,
|
|
425
|
+
baseTexture: true,
|
|
426
|
+
});
|
|
427
|
+
texture.destroy(true);
|
|
428
|
+
});
|
|
429
|
+
this.perforationRopeAndTextureReferences = [];
|
|
430
|
+
|
|
431
|
+
if (this.internalLayerVisibility.perforationLayerId) {
|
|
432
|
+
const { perforationOptions } = this.options as SchematicLayerOptions<T>;
|
|
433
|
+
const packings = perforations.filter(hasPacking);
|
|
434
|
+
const fracLines = perforations.filter(hasFracLines);
|
|
435
|
+
const spikes = perforations.filter(hasSpikes);
|
|
436
|
+
packings.forEach((perforation) => {
|
|
437
|
+
const perfShapes = this.createPerforationShape(perforation, casings, holeSizes);
|
|
438
|
+
const perfShapesByDiameter: { [key: number]: ComplexRopeSegment[] } = perfShapes.reduce(
|
|
439
|
+
(dict: { [key: number]: ComplexRopeSegment[] }, ps) => {
|
|
440
|
+
if (!dict[ps.diameter]) {
|
|
441
|
+
dict[ps.diameter] = [];
|
|
442
|
+
}
|
|
443
|
+
dict[ps.diameter] = [...dict[ps.diameter], ps];
|
|
444
|
+
return dict;
|
|
445
|
+
},
|
|
446
|
+
{},
|
|
447
|
+
);
|
|
448
|
+
Object.values(perfShapesByDiameter).forEach((perfShapesWithSameDiameter) => {
|
|
449
|
+
const texture = createPerforationPackingTexture(perforation, perfShapesWithSameDiameter[0], perforationOptions);
|
|
450
|
+
const rope = this.drawComplexRope(perfShapesWithSameDiameter, texture);
|
|
451
|
+
this.perforationRopeAndTextureReferences.push({ rope, texture });
|
|
452
|
+
});
|
|
453
|
+
});
|
|
454
|
+
|
|
455
|
+
spikes.forEach((perforation) => {
|
|
456
|
+
const perfShapes = this.createPerforationShape(perforation, casings, holeSizes);
|
|
457
|
+
const thiccPerfShapes = perfShapes.map((ps) => ({ ...ps, diameter: ps.diameter * 3 }));
|
|
458
|
+
const perfShapesByDiameter: { [key: number]: ComplexRopeSegment[] } = thiccPerfShapes.reduce(
|
|
459
|
+
(dict: { [key: number]: ComplexRopeSegment[] }, ps) => {
|
|
460
|
+
if (!dict[ps.diameter]) {
|
|
461
|
+
dict[ps.diameter] = [];
|
|
462
|
+
}
|
|
463
|
+
dict[ps.diameter] = [...dict[ps.diameter], ps];
|
|
464
|
+
return dict;
|
|
465
|
+
},
|
|
466
|
+
{},
|
|
467
|
+
);
|
|
468
|
+
Object.values(perfShapesByDiameter).forEach((perfShapesWithSameDiameter) => {
|
|
469
|
+
perfShapesWithSameDiameter.forEach((perfShape) => {
|
|
470
|
+
const texture = createPerforationSpikeTexture(perforation, perforations, perfShape, perforationOptions);
|
|
471
|
+
const rope = this.drawComplexRope([perfShape], texture);
|
|
472
|
+
this.perforationRopeAndTextureReferences.push({ rope, texture });
|
|
473
|
+
});
|
|
474
|
+
});
|
|
475
|
+
});
|
|
476
|
+
|
|
477
|
+
fracLines.forEach((perforation) => {
|
|
478
|
+
const perfShapes = this.createPerforationShape(perforation, casings, holeSizes);
|
|
479
|
+
const thiccPerfShapes = perfShapes.map((ps) => ({ ...ps, diameter: ps.diameter * 3 }));
|
|
480
|
+
const perfShapesByDiameter: { [key: number]: ComplexRopeSegment[] } = thiccPerfShapes.reduce(
|
|
481
|
+
(dict: { [key: number]: ComplexRopeSegment[] }, ps) => {
|
|
482
|
+
if (!dict[ps.diameter]) {
|
|
483
|
+
dict[ps.diameter] = [];
|
|
484
|
+
}
|
|
485
|
+
dict[ps.diameter] = [...dict[ps.diameter], ps];
|
|
486
|
+
return dict;
|
|
487
|
+
},
|
|
488
|
+
{},
|
|
489
|
+
);
|
|
490
|
+
Object.values(perfShapesByDiameter).forEach((perfShapesWithSameDiameter) => {
|
|
491
|
+
perfShapesWithSameDiameter.forEach((perfShape) => {
|
|
492
|
+
const texture = createPerforationFracLineTexture(perforation, perfShape, perforationOptions);
|
|
493
|
+
const rope = this.drawComplexRope([perfShape], texture);
|
|
494
|
+
this.perforationRopeAndTextureReferences.push({ rope, texture });
|
|
495
|
+
});
|
|
496
|
+
});
|
|
497
|
+
});
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
if (this.internalLayerVisibility.completionLayerId) {
|
|
501
|
+
completion.forEach(
|
|
502
|
+
foldCompletion(
|
|
503
|
+
(obj: Screen) => this.drawScreen(obj),
|
|
504
|
+
(obj: Tubing) => this.drawTubing(obj),
|
|
505
|
+
(obj: CompletionSymbol) => {
|
|
506
|
+
const symbolRenderObject = this.prepareSymbolRenderObject(obj);
|
|
507
|
+
this.drawSymbolComponent(symbolRenderObject);
|
|
508
|
+
},
|
|
509
|
+
),
|
|
510
|
+
);
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
if (this.internalLayerVisibility.pAndALayerId) {
|
|
514
|
+
remainingPAndA.forEach((obj) => {
|
|
515
|
+
if (isPAndASymbol(obj)) {
|
|
516
|
+
const symbolRenderObject = this.prepareSymbolRenderObject(obj);
|
|
517
|
+
this.drawSymbolComponent(symbolRenderObject);
|
|
518
|
+
}
|
|
519
|
+
if (isCementPlug(obj)) {
|
|
520
|
+
this.drawCementPlug(obj, casings, completion, holeSizes);
|
|
521
|
+
}
|
|
522
|
+
});
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
private updateSymbolCache(symbols: { [key: string]: string }) {
|
|
527
|
+
if (!this.textureSymbolCacheArray) {
|
|
528
|
+
this.textureSymbolCacheArray = {};
|
|
529
|
+
}
|
|
530
|
+
if (!symbols) {
|
|
531
|
+
return;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
const existingKeys = Object.keys(this.textureSymbolCacheArray);
|
|
535
|
+
Object.entries(symbols).forEach(([key, symbol]: [string, string]) => {
|
|
536
|
+
if (!existingKeys.includes(key)) {
|
|
537
|
+
this.textureSymbolCacheArray[key] = Texture.from(symbol);
|
|
538
|
+
}
|
|
539
|
+
});
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
private drawCementPlug(cementPlug: CementPlug, casings: Casing[], completion: Completion[], holes: HoleSize[]) {
|
|
543
|
+
const { exaggerationFactor, cementPlugOptions } = this.options as SchematicLayerOptions<T>;
|
|
544
|
+
|
|
545
|
+
const cementPlugSegments = createComplexRopeSegmentsForCementPlug(
|
|
546
|
+
cementPlug,
|
|
547
|
+
casings,
|
|
548
|
+
completion,
|
|
549
|
+
holes,
|
|
550
|
+
exaggerationFactor,
|
|
551
|
+
this.getZFactorScaledPathForPoints,
|
|
552
|
+
);
|
|
553
|
+
this.drawComplexRope(cementPlugSegments, this.getCementPlugTexture(cementPlugOptions));
|
|
554
|
+
|
|
555
|
+
const { rightPath, leftPath } = cementPlugSegments.reduce<{ rightPath: Point[]; leftPath: Point[] }>(
|
|
556
|
+
(acc, current) => {
|
|
557
|
+
const { leftPath, rightPath } = createTubularRenderingObject(current.diameter / 2, current.points);
|
|
558
|
+
|
|
559
|
+
return {
|
|
560
|
+
rightPath: [...acc.rightPath, ...rightPath],
|
|
561
|
+
leftPath: [...acc.leftPath, ...leftPath],
|
|
562
|
+
};
|
|
563
|
+
},
|
|
564
|
+
{ rightPath: [], leftPath: [] },
|
|
565
|
+
);
|
|
566
|
+
// eslint-disable-next-line no-magic-numbers
|
|
567
|
+
this.drawOutline(leftPath, rightPath, convertColor('black'), 0.25, 'TopAndBottom');
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
private createCasingRenderObject(casing: Casing): CasingRenderObject {
|
|
571
|
+
const { exaggerationFactor } = this.options as SchematicLayerOptions<T>;
|
|
572
|
+
return prepareCasingRenderObject(exaggerationFactor, casing, this.getZFactorScaledPathForPoints);
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
private getCementPlugTexture(cementPlugOptions: CementPlugOptions): Texture {
|
|
576
|
+
if (!this.cementPlugTextureCache) {
|
|
577
|
+
this.cementPlugTextureCache = createCementPlugTexture(cementPlugOptions);
|
|
578
|
+
}
|
|
579
|
+
return this.cementPlugTextureCache;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
private prepareSymbolRenderObject = (component: CompletionSymbol | PAndASymbol): SymbolRenderObject => {
|
|
583
|
+
const { exaggerationFactor } = this.options as SchematicLayerOptions<T>;
|
|
584
|
+
|
|
585
|
+
const exaggeratedDiameter = component.diameter * exaggerationFactor;
|
|
586
|
+
|
|
587
|
+
const pathPoints = this.getZFactorScaledPathForPoints(component.start, component.end);
|
|
588
|
+
|
|
589
|
+
return {
|
|
590
|
+
pathPoints,
|
|
591
|
+
referenceDiameter: exaggeratedDiameter,
|
|
592
|
+
symbolKey: component.symbolKey,
|
|
593
|
+
};
|
|
594
|
+
};
|
|
595
|
+
|
|
596
|
+
private drawSymbolComponent = ({ pathPoints, referenceDiameter, symbolKey }: SymbolRenderObject): void => {
|
|
597
|
+
const texture = this.getSymbolTexture(symbolKey, referenceDiameter);
|
|
598
|
+
// The rope renders fine in CANVAS/fallback mode
|
|
599
|
+
this.drawSVGRope(pathPoints, texture);
|
|
600
|
+
};
|
|
601
|
+
|
|
602
|
+
private drawSVGRope(path: Point[], texture: Texture): void {
|
|
603
|
+
if (path.length === 0) {
|
|
604
|
+
return null;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
const rope: UniformTextureStretchRope = new UniformTextureStretchRope(texture, path);
|
|
608
|
+
|
|
609
|
+
this.addChild(rope);
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
private getSymbolTexture(symbolKey: string, diameter: number): Texture {
|
|
613
|
+
return new Texture(this.textureSymbolCacheArray[symbolKey].baseTexture, null, new Rectangle(0, 0, 0, diameter), null, groupD8.MAIN_DIAGONAL);
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
private drawHoleSize = (maxHoleDiameter: number, holeObject: HoleSize): void => {
|
|
617
|
+
if (holeObject == null) {
|
|
618
|
+
return;
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
const pathPoints = this.getZFactorScaledPathForPoints(holeObject.start, holeObject.end);
|
|
622
|
+
if (pathPoints.length === 0) {
|
|
623
|
+
return;
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
const { exaggerationFactor, holeOptions } = this.options as SchematicLayerOptions<T>;
|
|
627
|
+
const exaggeratedDiameter = holeObject.diameter * exaggerationFactor;
|
|
628
|
+
const { rightPath, leftPath } = createTubularRenderingObject(exaggeratedDiameter / 2, pathPoints);
|
|
629
|
+
const texture = this.getHoleTexture(holeOptions, exaggeratedDiameter, maxHoleDiameter);
|
|
630
|
+
|
|
631
|
+
this.drawHoleRope(pathPoints, texture, maxHoleDiameter);
|
|
632
|
+
|
|
633
|
+
this.drawOutline(leftPath, rightPath, convertColor(holeOptions.lineColor), HOLE_OUTLINE * exaggerationFactor, 'TopAndBottom', 0);
|
|
634
|
+
};
|
|
635
|
+
|
|
636
|
+
private drawHoleRope(path: Point[], texture: Texture, maxHoleDiameter: number): void {
|
|
637
|
+
if (path.length === 0) {
|
|
638
|
+
return null;
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
const rope: SimpleRope = new SimpleRope(texture, path, maxHoleDiameter / DEFAULT_TEXTURE_SIZE);
|
|
642
|
+
|
|
643
|
+
this.addChild(rope);
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
private getHoleTexture(holeOptions: HoleOptions, diameter: number, maxHoleDiameter: number): Texture {
|
|
647
|
+
const size = DEFAULT_TEXTURE_SIZE;
|
|
648
|
+
const height = size;
|
|
649
|
+
const width = size;
|
|
650
|
+
|
|
651
|
+
const textureDiameter = (diameter / maxHoleDiameter) * size;
|
|
652
|
+
|
|
653
|
+
if (!this.holeTextureCache) {
|
|
654
|
+
this.holeTextureCache = createHoleBaseTexture(holeOptions, width, height);
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
const baseTexture = this.holeTextureCache.baseTexture;
|
|
658
|
+
const sidePadding = (height - textureDiameter) / 2;
|
|
659
|
+
const frame = new Rectangle(0, sidePadding, width, textureDiameter);
|
|
660
|
+
const texture = new Texture(baseTexture, frame);
|
|
661
|
+
|
|
662
|
+
return texture;
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
/**
|
|
666
|
+
* The rendering order of these components needs to be aligned
|
|
667
|
+
* @param casingRenderObjects
|
|
668
|
+
* @param cementRenderObject
|
|
669
|
+
* @param cementSqueezes
|
|
670
|
+
* @returns ordered rendering list
|
|
671
|
+
*/
|
|
672
|
+
private sortCementAndCasingRenderObjects(
|
|
673
|
+
casingRenderObjects: CasingRenderObject[],
|
|
674
|
+
cementRenderObject: CementRenderObject[],
|
|
675
|
+
cementSqueezes: CementSqueezeRenderObject[],
|
|
676
|
+
): InterlacedRenderObjects[] {
|
|
677
|
+
type InterlaceReducerAcc = {
|
|
678
|
+
result: InterlacedRenderObjects[];
|
|
679
|
+
remainingCement: CementRenderObject[];
|
|
680
|
+
remainingCementSqueezes: CementSqueezeRenderObject[];
|
|
681
|
+
};
|
|
682
|
+
|
|
683
|
+
let zIndex = 0;
|
|
684
|
+
|
|
685
|
+
const { result } = casingRenderObjects.reduce(
|
|
686
|
+
(acc: InterlaceReducerAcc, casingRenderObject: CasingRenderObject): InterlaceReducerAcc => {
|
|
687
|
+
const foundCementShape = acc.remainingCement.find((cement) => cement.casingIds.includes(casingRenderObject.id));
|
|
688
|
+
const foundCementSqueezes = acc.remainingCementSqueezes.filter((squeeze) => squeeze.casingIds.includes(casingRenderObject.id));
|
|
689
|
+
|
|
690
|
+
if (foundCementShape) {
|
|
691
|
+
foundCementShape.zIndex = zIndex++;
|
|
692
|
+
}
|
|
693
|
+
foundCementSqueezes.forEach((item) => (item.zIndex = zIndex++));
|
|
694
|
+
casingRenderObject.zIndex = zIndex++;
|
|
695
|
+
|
|
696
|
+
return {
|
|
697
|
+
result: [...acc.result, foundCementShape, casingRenderObject, ...foundCementSqueezes],
|
|
698
|
+
remainingCement: acc.remainingCement.filter((c) => c !== foundCementShape),
|
|
699
|
+
remainingCementSqueezes: acc.remainingCementSqueezes.filter((squeeze) => !foundCementSqueezes.includes(squeeze)),
|
|
700
|
+
};
|
|
701
|
+
},
|
|
702
|
+
{ result: [], remainingCement: cementRenderObject, remainingCementSqueezes: cementSqueezes },
|
|
703
|
+
);
|
|
704
|
+
|
|
705
|
+
return result.filter((item) => item !== undefined).sort((a, b) => a.zIndex - b.zIndex);
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
/**
|
|
709
|
+
*
|
|
710
|
+
* @param intervals
|
|
711
|
+
* @param texture
|
|
712
|
+
* optionally fetch the exaggerationFactor from a different options prop
|
|
713
|
+
* options.perforationOptions for example
|
|
714
|
+
* @param getExaggerationFactor
|
|
715
|
+
* @returns
|
|
716
|
+
*/
|
|
717
|
+
private drawComplexRope(intervals: ComplexRopeSegment[], texture: Texture): ComplexRope {
|
|
718
|
+
if (intervals.length === 0) {
|
|
719
|
+
return null;
|
|
720
|
+
}
|
|
721
|
+
const rope = new ComplexRope(texture, intervals);
|
|
722
|
+
|
|
723
|
+
this.addChild(rope);
|
|
724
|
+
|
|
725
|
+
return rope;
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
private static getOutlineClosureType = (index: number, maxIndex: number): OutlineClosure => {
|
|
729
|
+
if (index === 0) {
|
|
730
|
+
if (index === maxIndex) {
|
|
731
|
+
return 'TopAndBottom';
|
|
732
|
+
}
|
|
733
|
+
return 'Top';
|
|
734
|
+
}
|
|
735
|
+
if (index === maxIndex) {
|
|
736
|
+
return 'Bottom';
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
return 'None';
|
|
740
|
+
};
|
|
741
|
+
|
|
742
|
+
private drawCasing = (casingRenderObject: CasingRenderObject): void => {
|
|
743
|
+
const { casingOptions } = this.options as SchematicLayerOptions<T>;
|
|
744
|
+
const casingSolidColorNumber = convertColor(casingOptions.solidColor);
|
|
745
|
+
const casingLineColorNumber = convertColor(casingOptions.lineColor);
|
|
746
|
+
|
|
747
|
+
casingRenderObject.sections.forEach((section, index, list) => {
|
|
748
|
+
const outlineClosureType = SchematicLayer.getOutlineClosureType(index, list.length - 1);
|
|
749
|
+
|
|
750
|
+
const texture = this.createCasingTexture(casingRenderObject.referenceDiameter);
|
|
751
|
+
this.drawRope(section.pathPoints, texture, casingSolidColorNumber);
|
|
752
|
+
|
|
753
|
+
if (section.kind === 'casing-window') {
|
|
754
|
+
this.drawCasingWindowOutline(section.leftPath, section.rightPath, casingOptions, casingRenderObject.casingWallWidth);
|
|
755
|
+
} else {
|
|
756
|
+
this.drawOutline(section.leftPath, section.rightPath, casingLineColorNumber, casingRenderObject.casingWallWidth, outlineClosureType);
|
|
757
|
+
}
|
|
758
|
+
});
|
|
759
|
+
};
|
|
760
|
+
|
|
761
|
+
private createCasingTexture(diameter: number): Texture {
|
|
762
|
+
const textureWidthPO2 = 16;
|
|
763
|
+
return new Texture(Texture.WHITE.baseTexture, null, new Rectangle(0, 0, textureWidthPO2, diameter));
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
private drawShoe(casingEnd: number, casingRadius: number): void {
|
|
767
|
+
const { exaggerationFactor, casingOptions } = this.options as SchematicLayerOptions<T>;
|
|
768
|
+
const shoeWidth = casingOptions.shoeSize.width * exaggerationFactor;
|
|
769
|
+
const shoeLength = casingOptions.shoeSize.length * exaggerationFactor;
|
|
770
|
+
|
|
771
|
+
const shoeCoords = this.generateShoe(casingEnd, casingRadius, shoeLength, shoeWidth);
|
|
772
|
+
const shoeCoords2 = this.generateShoe(casingEnd, casingRadius, shoeLength, -shoeWidth);
|
|
773
|
+
this.drawBigPolygon(shoeCoords2);
|
|
774
|
+
this.drawBigPolygon(shoeCoords);
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
private generateShoe = (casingEnd: number, casingRadius: number, length: number, width: number): Point[] => {
|
|
778
|
+
const start = casingEnd - length;
|
|
779
|
+
const end = casingEnd;
|
|
780
|
+
|
|
781
|
+
const points = this.getZFactorScaledPathForPoints(start, end);
|
|
782
|
+
|
|
783
|
+
const normal = createNormals(points);
|
|
784
|
+
const shoeEdge: Point[] = offsetPoints(points, normal, casingRadius * (width < 0 ? -1 : 1));
|
|
785
|
+
|
|
786
|
+
const shoeTipPoint = points[points.length - 1];
|
|
787
|
+
const shoeTipNormal = normal[normal.length - 1];
|
|
788
|
+
const shoeTip: Point = offsetPoint(shoeTipPoint, shoeTipNormal, width + casingRadius * (width < 0 ? -1 : 1));
|
|
789
|
+
|
|
790
|
+
return [...shoeEdge, shoeTip];
|
|
791
|
+
};
|
|
792
|
+
|
|
793
|
+
private createCementSqueezeShape = (
|
|
794
|
+
squeeze: CementSqueeze,
|
|
795
|
+
casings: Casing[],
|
|
796
|
+
completion: Completion[],
|
|
797
|
+
holes: HoleSize[],
|
|
798
|
+
): ComplexRopeSegment[] => {
|
|
799
|
+
const { exaggerationFactor } = this.options as SchematicLayerOptions<T>;
|
|
800
|
+
return createComplexRopeSegmentsForCementSqueeze(squeeze, casings, completion, holes, exaggerationFactor, this.getZFactorScaledPathForPoints);
|
|
801
|
+
};
|
|
802
|
+
|
|
803
|
+
private getCementTexture(): Texture {
|
|
804
|
+
if (!this.cementTextureCache) {
|
|
805
|
+
const { cementOptions } = this.options as SchematicLayerOptions<T>;
|
|
806
|
+
this.cementTextureCache = createCementTexture(cementOptions);
|
|
807
|
+
}
|
|
808
|
+
return this.cementTextureCache;
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
private createPerforationShape = (perforation: Perforation, casings: Casing[], holes: HoleSize[]): PerforationShape[] => {
|
|
812
|
+
const { exaggerationFactor } = this.options as SchematicLayerOptions<T>;
|
|
813
|
+
return createComplexRopeSegmentsForPerforation(perforation, casings, holes, exaggerationFactor, this.getZFactorScaledPathForPoints);
|
|
814
|
+
};
|
|
815
|
+
|
|
816
|
+
private getCementSqueezeTexture(): Texture {
|
|
817
|
+
if (!this.cementSqueezeTextureCache) {
|
|
818
|
+
const { cementSqueezeOptions } = this.options as SchematicLayerOptions<T>;
|
|
819
|
+
this.cementSqueezeTextureCache = createCementSqueezeTexture(cementSqueezeOptions);
|
|
820
|
+
}
|
|
821
|
+
return this.cementSqueezeTextureCache;
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
private drawScreen({ start, end, diameter }: Screen): void {
|
|
825
|
+
const { exaggerationFactor, screenOptions } = this.options as SchematicLayerOptions<T>;
|
|
826
|
+
const exaggeratedDiameter = exaggerationFactor * diameter;
|
|
827
|
+
|
|
828
|
+
const pathPoints = this.getZFactorScaledPathForPoints(start, end);
|
|
829
|
+
const { leftPath, rightPath } = createTubularRenderingObject(exaggeratedDiameter / 2, pathPoints);
|
|
830
|
+
|
|
831
|
+
const texture = this.getScreenTexture();
|
|
832
|
+
|
|
833
|
+
this.drawCompletionRope(pathPoints, texture, exaggeratedDiameter);
|
|
834
|
+
this.drawOutline(leftPath, rightPath, convertColor(screenOptions.lineColor), SCREEN_OUTLINE * exaggerationFactor, 'TopAndBottom');
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
private drawTubing({ diameter, start, end }: Tubing): void {
|
|
838
|
+
const { exaggerationFactor, tubingOptions } = this.options as SchematicLayerOptions<T>;
|
|
839
|
+
const exaggeratedDiameter = exaggerationFactor * diameter;
|
|
840
|
+
|
|
841
|
+
const pathPoints = this.getZFactorScaledPathForPoints(start, end);
|
|
842
|
+
const texture = this.getTubingTexture(tubingOptions);
|
|
843
|
+
|
|
844
|
+
this.drawCompletionRope(pathPoints, texture, exaggeratedDiameter);
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
private getTubingTexture(tubingOptions: TubingOptions): Texture {
|
|
848
|
+
if (!this.tubingTextureCache) {
|
|
849
|
+
this.tubingTextureCache = createTubingTexture(tubingOptions);
|
|
850
|
+
}
|
|
851
|
+
return this.tubingTextureCache;
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
private getScreenTexture(): Texture {
|
|
855
|
+
if (!this.screenTextureCache) {
|
|
856
|
+
const { screenOptions } = this.options as SchematicLayerOptions<T>;
|
|
857
|
+
this.screenTextureCache = createScreenTexture(screenOptions);
|
|
858
|
+
}
|
|
859
|
+
return this.screenTextureCache;
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
private drawCompletionRope(path: Point[], texture: Texture, diameter: number): void {
|
|
863
|
+
if (path.length === 0) {
|
|
864
|
+
return;
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
const rope: FixedWidthSimpleRope = new FixedWidthSimpleRope(texture, path, diameter);
|
|
868
|
+
this.addChild(rope);
|
|
869
|
+
}
|
|
870
|
+
}
|