Skip to content

Commit 60411d2

Browse files
committed
Add seismic layers
1 parent 534990a commit 60411d2

File tree

7 files changed

+184
-64
lines changed

7 files changed

+184
-64
lines changed

ui/locales/toolbox/toolbox.de.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,4 @@
1818
"Complete": "Export Abgeschlossen"
1919
}
2020
}
21-
}
21+
}

ui/locales/toolbox/toolbox.en.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"actions": {
3+
"export": ""
4+
},
5+
"ogc": {
6+
"layer-selection": {
7+
"title": "",
8+
"confirm": ""
9+
},
10+
"queue": {
11+
"title": ""
12+
},
13+
"stage": {
14+
"Prepare": "",
15+
"Running": "",
16+
"Success": "",
17+
"Failure": "",
18+
"Complete": ""
19+
}
20+
}
21+
}

ui/locales/toolbox/toolbox.fr.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"actions": {
3+
"export": ""
4+
},
5+
"ogc": {
6+
"layer-selection": {
7+
"title": "",
8+
"confirm": ""
9+
},
10+
"queue": {
11+
"title": ""
12+
},
13+
"stage": {
14+
"Prepare": "",
15+
"Running": "",
16+
"Success": "",
17+
"Failure": "",
18+
"Complete": ""
19+
}
20+
}
21+
}

ui/locales/toolbox/toolbox.it.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"actions": {
3+
"export": ""
4+
},
5+
"ogc": {
6+
"layer-selection": {
7+
"title": "",
8+
"confirm": ""
9+
},
10+
"queue": {
11+
"title": ""
12+
},
13+
"stage": {
14+
"Prepare": "",
15+
"Running": "",
16+
"Success": "",
17+
"Failure": "",
18+
"Complete": ""
19+
}
20+
}
21+
}

ui/src/features/ogc/ogc.service.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,11 +210,11 @@ export class OgcService extends BaseService {
210210
},
211211
polygon: points,
212212
};
213-
if (layer.ogcId != null) {
213+
if (layer.ogc !== undefined) {
214214
// A layer from the gst service, most likely a 3dtile.
215215
return {
216216
type: 'gst',
217-
id: layer.ogcId,
217+
id: layer.ogc.id,
218218
requestedFormat: 'tiles3d',
219219

220220
// The coordinate system used in the output file.

ui/src/layers/helpers.ts

Lines changed: 81 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
Cesium3DTileStyle,
99
Cesium3DTilesVoxelProvider,
1010
CustomShader,
11+
CustomShaderTranslucencyMode,
1112
Ellipsoid,
1213
GeoJsonDataSource,
1314
ImageBasedLighting,
@@ -17,6 +18,9 @@ import {
1718
Matrix3,
1819
Matrix4,
1920
Rectangle,
21+
Resource,
22+
Scene,
23+
UniformType,
2024
Viewer,
2125
VoxelPrimitive,
2226
} from 'cesium';
@@ -131,7 +135,7 @@ export async function create3DTilesetFromConfig(
131135
config: LayerConfig,
132136
tileLoadCallback,
133137
) {
134-
let resource: string | IonResource | AmazonS3Resource;
138+
let resource: string | AmazonS3Resource | IonResource | Resource;
135139
if (config.aws_s3_bucket && config.aws_s3_key) {
136140
resource = new AmazonS3Resource({
137141
sessionService,
@@ -140,10 +144,27 @@ export async function create3DTilesetFromConfig(
140144
});
141145
} else if (config.url) {
142146
resource = config.url;
143-
} else {
147+
} else if (config.assetId) {
144148
resource = await IonResource.fromAssetId(config.assetId!, {
145149
accessToken: config.ionToken,
146150
});
151+
} else if (config.ogc) {
152+
const url =
153+
config.ogc.styleId === undefined
154+
? `https://ogc-api.gst-viewer.swissgeol.ch/collections/${config.ogc.id}/download_format/tiles3d`
155+
: `https://ogc-api.gst-viewer.swissgeol.ch/collections/${config.ogc.id}/styles/${config.ogc.styleId}/download_format/tiles3d`;
156+
resource = new Resource({
157+
url,
158+
headers: {
159+
// This is the Authorization required to access the Seismic layers.
160+
// This is a read-only auth level and safe to expose.
161+
// The reason these credentials exist is related to how GST categorizes and exposes its data.
162+
// They are not intended for security and can thus be public.
163+
Authorization: 'Basic T0dDLVNlaXNtaWNzOk9HQy1TZWlzbWljc18yMDI1Kg==',
164+
},
165+
});
166+
} else {
167+
throw new Error(`layer is missing a usable source: ${config.layer}`);
147168
}
148169

149170
const tileset: PickableCesium3DTileset = await Cesium3DTileset.fromUrl(
@@ -167,28 +188,53 @@ export async function create3DTilesetFromConfig(
167188
}
168189

169190
tileset.pickable = config.pickable ?? false;
170-
viewer.scene.primitives.add(tileset);
191+
192+
const updateShader = (opacity: number) => {
193+
const requiredTranslucency =
194+
opacity === 1
195+
? CustomShaderTranslucencyMode.OPAQUE
196+
: CustomShaderTranslucencyMode.TRANSLUCENT;
197+
198+
const needsNewShader =
199+
tileset.customShader === undefined ||
200+
tileset.customShader.translucencyMode !== requiredTranslucency;
201+
202+
if (needsNewShader) {
203+
tileset.customShader = new CustomShader({
204+
translucencyMode: requiredTranslucency,
205+
fragmentShaderText: `
206+
void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) {
207+
material.specular = vec3(0.0); // no view-dependent spec
208+
material.occlusion = 1.0; // full diffuse
209+
material.alpha = u_alpha;
210+
}
211+
`,
212+
uniforms: {
213+
u_alpha: {
214+
type: UniformType.FLOAT,
215+
value: opacity,
216+
},
217+
},
218+
});
219+
} else {
220+
tileset.customShader!.setUniform('u_alpha', opacity);
221+
}
222+
};
223+
updateShader(config.opacity ?? 1);
224+
225+
tileset.imageBasedLighting = new ImageBasedLighting();
226+
tileset.imageBasedLighting.imageBasedLightingFactor = new Cartesian2(1, 0);
171227

172228
config.setVisibility = (visible) => {
173229
tileset.show = !!visible;
174230
};
175231

176232
if (!config.opacityDisabled) {
177233
config.setOpacity = (opacity) => {
178-
const style = config.style;
179-
if (style && (style.color || style.labelColor)) {
180-
const { propertyName, colorType, colorValue } = styleColorParser(style);
181-
const color = `${colorType}(${colorValue}, ${opacity})`;
182-
tileset.style = new Cesium3DTileStyle({
183-
...style,
184-
[propertyName]: color,
185-
});
186-
} else {
187-
const color = `vec4(1, 1, 1, ${opacity})`;
188-
tileset.style = new Cesium3DTileStyle({ ...style, color });
189-
}
234+
updateShader(opacity);
235+
viewer.scene.requestRender();
190236
};
191-
config.setOpacity(config.opacity ? config.opacity : 1);
237+
config.setOpacity(config.opacity ?? 1);
192238
}
193239

194240
if (tileLoadCallback) {
@@ -197,7 +243,7 @@ export async function create3DTilesetFromConfig(
197243
);
198244
}
199245

200-
if (config.propsOrder) {
246+
if (config.propsOrder && tileset.properties) {
201247
tileset.properties.propsOrder = config.propsOrder;
202248
}
203249
if (config.heightOffset) {
@@ -221,21 +267,29 @@ export async function create3DTilesetFromConfig(
221267

222268
tileset.colorBlendMode = Cesium3DTileColorBlendMode.REPLACE;
223269

224-
tileset.customShader = new CustomShader({
225-
fragmentShaderText: `
226-
void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) {
227-
material.specular = vec3(0.0); // no view-dependent spec
228-
material.occlusion = 1.0; // full diffuse
229-
}
230-
`,
231-
});
270+
// Disable `pickPosition` until the tileset is loaded.
271+
// Without this, hovering over the viewer will cause a render error due to `layout-cursor-info` attempting to pick
272+
// the incomplete tileset.
273+
pickSuppressionCount += 1;
274+
viewer.scene.pickPosition = pickSuppression;
232275

233-
tileset.imageBasedLighting = new ImageBasedLighting();
234-
tileset.imageBasedLighting.imageBasedLightingFactor = new Cartesian2(1, 0);
276+
tileset.allTilesLoaded.addEventListener(() => {
277+
pickSuppressionCount -= 1;
278+
if (pickSuppressionCount === 0) {
279+
viewer.scene.pickPosition = originalPick;
280+
}
281+
});
235282

283+
viewer.scene.primitives.add(tileset);
236284
return tileset;
237285
}
238286

287+
const originalPick = Scene.prototype.pickPosition;
288+
let pickSuppressionCount = 0;
289+
const pickSuppression: typeof originalPick = () => {
290+
return null as unknown as Cartesian3;
291+
};
292+
239293
export async function createSwisstopoWMTSImageryLayer(
240294
viewer: Viewer,
241295
config: LayerConfig,
@@ -297,24 +351,6 @@ export function createCesiumObject(
297351
return factories[config.type!](viewer, config, tileLoadCallback);
298352
}
299353

300-
function styleColorParser(style: any) {
301-
const propertyName = style.color ? 'color' : 'labelColor';
302-
let colorType = style[propertyName].slice(
303-
0,
304-
style[propertyName].indexOf('('),
305-
);
306-
const lastIndex =
307-
colorType === 'rgba'
308-
? style[propertyName].lastIndexOf(',')
309-
: style[propertyName].indexOf(')');
310-
const colorValue = style[propertyName].slice(
311-
style[propertyName].indexOf('(') + 1,
312-
lastIndex,
313-
);
314-
colorType = colorType === 'rgb' ? 'rgba' : colorType;
315-
return { propertyName, colorType, colorValue };
316-
}
317-
318354
export function getBoxFromRectangle(
319355
rectangle: Rectangle,
320356
height: number,

0 commit comments

Comments
 (0)