@geode/opengeodeweb-front 10.37.0 → 10.38.0-rc.1
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 +0 -1
- package/app/components/Viewer/ContextMenu/ContextMenu.vue +2 -0
- package/app/components/Viewer/EdgedCurve/SpecificEdgesOptions.vue +21 -1
- package/app/components/Viewer/Generic/Mesh/CellsOptions.vue +21 -1
- package/app/components/Viewer/Generic/Mesh/EdgesOptions.vue +21 -1
- package/app/components/Viewer/Generic/Mesh/PointsOptions.vue +13 -1
- package/app/components/Viewer/Generic/Mesh/PolygonsOptions.vue +21 -1
- package/app/components/Viewer/Generic/Mesh/PolyhedraOptions.vue +21 -1
- package/app/components/Viewer/Generic/Model/ModelStyleCard.vue +29 -31
- package/app/components/Viewer/ObjectTree/Layout.vue +2 -1
- package/app/components/Viewer/ObjectTree/Views/GlobalObjects.vue +24 -10
- package/app/components/Viewer/ObjectTree/Views/ModelTree.vue +5 -15
- package/app/components/Viewer/Options/AttributeColorBar.vue +7 -0
- package/app/components/Viewer/Options/AttributeSelector.vue +71 -21
- package/app/components/Viewer/Options/ColoringTypeSelector.vue +16 -0
- package/app/components/Viewer/Options/TextureItem.vue +15 -11
- package/app/components/Viewer/PointSet/SpecificPointsOptions.vue +13 -1
- package/app/components/Viewer/Solid/SpecificPolyhedraOptions.vue +21 -1
- package/app/components/Viewer/Surface/PolygonsOptions.vue +21 -1
- package/app/components/Viewer/Ui.vue +7 -3
- package/app/composables/batch_style.ts +64 -1
- package/app/composables/tree_filter.ts +8 -8
- package/app/composables/use_overlapping_picker.ts +2 -0
- package/app/composables/viewer_context_menu.ts +123 -0
- package/app/stores/menu.ts +3 -0
- package/app/utils/attributes.ts +38 -1
- package/app/utils/request_for_targets.ts +24 -0
- package/app/utils/treeview.ts +30 -0
- package/package.json +7 -9
|
@@ -1,16 +1,24 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import {
|
|
3
|
+
type AttributeRange,
|
|
4
|
+
type RangesPerData,
|
|
5
|
+
useBatchGroup,
|
|
6
|
+
} from "@ogw_front/composables/batch_style";
|
|
7
|
+
import { getAttributeRange, intersectAttributes } from "@ogw_front/utils/attributes";
|
|
2
8
|
import { DEFAULT_NO_DATA_COLOR } from "@ogw_front/utils/default_styles/constants";
|
|
3
9
|
import type { JsonRpcSchema } from "@ogw_shared/utils/types.js";
|
|
4
10
|
import ViewerOptionsAttributeColorBar from "@ogw_front/components/Viewer/Options/AttributeColorBar.vue";
|
|
5
11
|
import ViewerOptionsColorPicker from "@ogw_front/components/Viewer/Options/ColorPicker.vue";
|
|
6
|
-
import {
|
|
12
|
+
import { requestForTargets } from "@ogw_front/utils/request_for_targets";
|
|
7
13
|
import { useBackStore } from "@ogw_front/stores/back";
|
|
8
14
|
|
|
9
15
|
const backStore = useBackStore();
|
|
10
16
|
|
|
11
17
|
const attributeName = defineModel<string>("attributeName");
|
|
12
18
|
const attributeItem = defineModel<number>("attributeItem");
|
|
13
|
-
const attributeRange = defineModel<(number | undefined)[]>("attributeRange"
|
|
19
|
+
const attributeRange = defineModel<(number | undefined)[]>("attributeRange", {
|
|
20
|
+
default: () => [],
|
|
21
|
+
});
|
|
14
22
|
const attributeColorMap = defineModel<string>("attributeColorMap");
|
|
15
23
|
const attributeNoDataColor = defineModel<typeof DEFAULT_NO_DATA_COLOR>("attributeNoDataColor");
|
|
16
24
|
|
|
@@ -22,6 +30,13 @@ interface Props {
|
|
|
22
30
|
|
|
23
31
|
const { id, componentIds = undefined, schema } = defineProps<Props>();
|
|
24
32
|
|
|
33
|
+
interface Emits {
|
|
34
|
+
"update:attributeColorMap": [colorMap: string];
|
|
35
|
+
ranges_per_data: [ranges: RangesPerData];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const emit = defineEmits<Emits>();
|
|
39
|
+
|
|
25
40
|
interface AttributeInfo {
|
|
26
41
|
attribute_name: string;
|
|
27
42
|
nb_items: number;
|
|
@@ -30,6 +45,9 @@ interface AttributeInfo {
|
|
|
30
45
|
}
|
|
31
46
|
|
|
32
47
|
const attributes = ref<AttributeInfo[]>([]);
|
|
48
|
+
let attributesPerTarget = new Map<string, AttributeInfo[]>();
|
|
49
|
+
|
|
50
|
+
const groupTargetIds = useBatchGroup(() => id);
|
|
33
51
|
|
|
34
52
|
const currentAttribute = computed<AttributeInfo | undefined>(() =>
|
|
35
53
|
attributes.value.find((attr) => attr.attribute_name === attributeName.value),
|
|
@@ -39,16 +57,12 @@ const cssNoDataColor = computed<string>(() => {
|
|
|
39
57
|
return `rgba(${red}, ${green}, ${blue}, ${alpha})`;
|
|
40
58
|
});
|
|
41
59
|
const rangeMin = computed<number | undefined>({
|
|
42
|
-
get: () =>
|
|
43
|
-
const range = attributeRange.value as number[] | undefined;
|
|
44
|
-
return range ? range[0] : undefined;
|
|
45
|
-
},
|
|
60
|
+
get: () => attributeRange.value[0],
|
|
46
61
|
set: (val: number | undefined) => {
|
|
47
62
|
if (val === undefined) {
|
|
48
63
|
return;
|
|
49
64
|
}
|
|
50
|
-
const
|
|
51
|
-
const currentMax = range ? range[1] : undefined;
|
|
65
|
+
const [, currentMax] = attributeRange.value;
|
|
52
66
|
let newMin = val;
|
|
53
67
|
if (typeof currentMax === "number" && val > currentMax) {
|
|
54
68
|
newMin = currentMax;
|
|
@@ -57,16 +71,12 @@ const rangeMin = computed<number | undefined>({
|
|
|
57
71
|
},
|
|
58
72
|
});
|
|
59
73
|
const rangeMax = computed<number | undefined>({
|
|
60
|
-
get: () =>
|
|
61
|
-
const range = attributeRange.value as number[] | undefined;
|
|
62
|
-
return range ? range[1] : undefined;
|
|
63
|
-
},
|
|
74
|
+
get: () => attributeRange.value[1],
|
|
64
75
|
set: (val: number | undefined) => {
|
|
65
76
|
if (val === undefined) {
|
|
66
77
|
return;
|
|
67
78
|
}
|
|
68
|
-
const
|
|
69
|
-
const currentMin = range ? range[0] : undefined;
|
|
79
|
+
const [currentMin] = attributeRange.value;
|
|
70
80
|
let newMax = val;
|
|
71
81
|
if (typeof currentMin === "number" && val < currentMin) {
|
|
72
82
|
newMax = currentMin;
|
|
@@ -103,7 +113,37 @@ function hasSelectedComponent(components: unknown): boolean {
|
|
|
103
113
|
return Array.isArray(components) && components.length > 0;
|
|
104
114
|
}
|
|
105
115
|
|
|
106
|
-
function
|
|
116
|
+
async function getGroupAttributes(targetIds: string[]): Promise<void> {
|
|
117
|
+
const responses = await requestForTargets<{ attributes: AttributeInfo[] }>(schema, targetIds, {
|
|
118
|
+
attributes: [],
|
|
119
|
+
});
|
|
120
|
+
attributesPerTarget = new Map(
|
|
121
|
+
responses.map(([targetId, response]) => [targetId, response.attributes]),
|
|
122
|
+
);
|
|
123
|
+
attributes.value = intersectAttributes([...attributesPerTarget.values()]);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function initGroupAttribute(name: string, item: number): void {
|
|
127
|
+
const ranges = new Map<string, AttributeRange>();
|
|
128
|
+
for (const [targetId, targetAttributes] of attributesPerTarget) {
|
|
129
|
+
const attribute = targetAttributes.find((candidate) => candidate.attribute_name === name);
|
|
130
|
+
if (attribute) {
|
|
131
|
+
const { min, max } = getAttributeRange(
|
|
132
|
+
attribute as unknown as Parameters<typeof getAttributeRange>[0],
|
|
133
|
+
item,
|
|
134
|
+
);
|
|
135
|
+
ranges.set(targetId, [min, max]);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
emit("update:attributeColorMap", attributeColorMap.value ?? "batlow");
|
|
139
|
+
emit("ranges_per_data", ranges);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
async function getAttributes(): Promise<void> {
|
|
143
|
+
if (groupTargetIds.value) {
|
|
144
|
+
await getGroupAttributes(groupTargetIds.value);
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
107
147
|
const schemaProperties = schema.properties as Record<string, unknown> | undefined;
|
|
108
148
|
const requiresComponent = schemaProperties?.component_ids !== undefined;
|
|
109
149
|
if (requiresComponent && !hasSelectedComponent(componentIds)) {
|
|
@@ -115,7 +155,7 @@ function getAttributes(): void {
|
|
|
115
155
|
params.component_ids = componentIds;
|
|
116
156
|
}
|
|
117
157
|
|
|
118
|
-
backStore.request(
|
|
158
|
+
await backStore.request(
|
|
119
159
|
{ schema, params },
|
|
120
160
|
{
|
|
121
161
|
response_function: (response: unknown) => {
|
|
@@ -125,25 +165,34 @@ function getAttributes(): void {
|
|
|
125
165
|
);
|
|
126
166
|
}
|
|
127
167
|
|
|
128
|
-
onMounted(() => {
|
|
129
|
-
getAttributes();
|
|
168
|
+
onMounted(async () => {
|
|
169
|
+
await getAttributes();
|
|
130
170
|
});
|
|
131
171
|
|
|
132
172
|
watch(
|
|
133
173
|
() => [id, componentIds, schema],
|
|
134
|
-
() => {
|
|
135
|
-
getAttributes();
|
|
174
|
+
async () => {
|
|
175
|
+
await getAttributes();
|
|
136
176
|
},
|
|
137
177
|
);
|
|
138
178
|
|
|
179
|
+
watch([attributeName, attributeItem], ([name, item]) => {
|
|
180
|
+
if (groupTargetIds.value && name !== undefined) {
|
|
181
|
+
initGroupAttribute(name, item ?? 0);
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
|
|
139
185
|
watch([attributeName, attributeItem, currentAttribute], () => {
|
|
186
|
+
if (groupTargetIds.value) {
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
140
189
|
if (attributeColorMap.value === undefined) {
|
|
141
190
|
attributeColorMap.value = "batlow";
|
|
142
191
|
}
|
|
143
192
|
if (attributeNoDataColor.value === undefined) {
|
|
144
193
|
attributeNoDataColor.value = DEFAULT_NO_DATA_COLOR;
|
|
145
194
|
}
|
|
146
|
-
if (
|
|
195
|
+
if (attributeRange.value[0] === undefined) {
|
|
147
196
|
resetRange();
|
|
148
197
|
}
|
|
149
198
|
});
|
|
@@ -200,6 +249,7 @@ watch([attributeName, attributeItem, currentAttribute], () => {
|
|
|
200
249
|
v-model:minimum="rangeMin"
|
|
201
250
|
v-model:maximum="rangeMax"
|
|
202
251
|
v-model:colorMap="attributeColorMap"
|
|
252
|
+
:hide-range="groupTargetIds !== undefined"
|
|
203
253
|
@reset="resetRange"
|
|
204
254
|
/>
|
|
205
255
|
</template>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import type { JsonRpcSchema } from "@ogw_shared/utils/types.js";
|
|
3
3
|
import type { RGBAColor } from "@ogw_front/utils/default_styles/constants";
|
|
4
|
+
import type { RangesPerData } from "@ogw_front/composables/batch_style";
|
|
4
5
|
import ViewerOptionsAttributeSelector from "@ogw_front/components/Viewer/Options/AttributeSelector.vue";
|
|
5
6
|
import ViewerOptionsColorPicker from "@ogw_front/components/Viewer/Options/ColorPicker.vue";
|
|
6
7
|
import ViewerOptionsTexturesSelector from "@ogw_front/components/Viewer/Options/TexturesSelector.vue";
|
|
@@ -26,6 +27,16 @@ interface Schemas {
|
|
|
26
27
|
|
|
27
28
|
const coloring_style_key = defineModel<string>("coloring_style_key");
|
|
28
29
|
|
|
30
|
+
interface Emits {
|
|
31
|
+
vertex_attribute_ranges_per_data: [ranges: RangesPerData];
|
|
32
|
+
edge_attribute_ranges_per_data: [ranges: RangesPerData];
|
|
33
|
+
cell_attribute_ranges_per_data: [ranges: RangesPerData];
|
|
34
|
+
polygon_attribute_ranges_per_data: [ranges: RangesPerData];
|
|
35
|
+
polyhedron_attribute_ranges_per_data: [ranges: RangesPerData];
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const emit = defineEmits<Emits>();
|
|
39
|
+
|
|
29
40
|
const color = defineModel<RGBAColor>("color");
|
|
30
41
|
const textures = defineModel<Texture[]>("textures");
|
|
31
42
|
|
|
@@ -246,6 +257,7 @@ watch(
|
|
|
246
257
|
v-model:attributeRange="vertex_attribute_range"
|
|
247
258
|
v-model:attributeColorMap="vertex_attribute_color_map"
|
|
248
259
|
v-model:attributeNoDataColor="vertex_attribute_no_data_color"
|
|
260
|
+
@ranges_per_data="emit('vertex_attribute_ranges_per_data', $event)"
|
|
249
261
|
:id="id"
|
|
250
262
|
:componentIds="componentIds"
|
|
251
263
|
:schema="vertexSchema"
|
|
@@ -258,6 +270,7 @@ watch(
|
|
|
258
270
|
v-model:attributeRange="edge_attribute_range"
|
|
259
271
|
v-model:attributeColorMap="edge_attribute_color_map"
|
|
260
272
|
v-model:attributeNoDataColor="edge_attribute_no_data_color"
|
|
273
|
+
@ranges_per_data="emit('edge_attribute_ranges_per_data', $event)"
|
|
261
274
|
:id="id"
|
|
262
275
|
:componentIds="componentIds"
|
|
263
276
|
:schema="edgeSchema"
|
|
@@ -270,6 +283,7 @@ watch(
|
|
|
270
283
|
v-model:attributeRange="cell_attribute_range"
|
|
271
284
|
v-model:attributeColorMap="cell_attribute_color_map"
|
|
272
285
|
v-model:attributeNoDataColor="cell_attribute_no_data_color"
|
|
286
|
+
@ranges_per_data="emit('cell_attribute_ranges_per_data', $event)"
|
|
273
287
|
:id="id"
|
|
274
288
|
:componentIds="componentIds"
|
|
275
289
|
:schema="cellSchema"
|
|
@@ -282,6 +296,7 @@ watch(
|
|
|
282
296
|
v-model:attributeRange="polygon_attribute_range"
|
|
283
297
|
v-model:attributeColorMap="polygon_attribute_color_map"
|
|
284
298
|
v-model:attributeNoDataColor="polygon_attribute_no_data_color"
|
|
299
|
+
@ranges_per_data="emit('polygon_attribute_ranges_per_data', $event)"
|
|
285
300
|
:id="id"
|
|
286
301
|
:componentIds="componentIds"
|
|
287
302
|
:schema="polygonSchema"
|
|
@@ -294,6 +309,7 @@ watch(
|
|
|
294
309
|
v-model:attributeRange="polyhedron_attribute_range"
|
|
295
310
|
v-model:attributeColorMap="polyhedron_attribute_color_map"
|
|
296
311
|
v-model:attributeNoDataColor="polyhedron_attribute_no_data_color"
|
|
312
|
+
@ranges_per_data="emit('polyhedron_attribute_ranges_per_data', $event)"
|
|
297
313
|
:id="id"
|
|
298
314
|
:componentIds="componentIds"
|
|
299
315
|
:schema="polyhedronSchema"
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import FileUploader from "@ogw_front/components/FileUploader.vue";
|
|
3
3
|
import back_schemas from "@geode/opengeodeweb-back/opengeodeweb_back_typed_schemas.js";
|
|
4
|
+
import { intersectBy } from "@ogw_front/utils/attributes";
|
|
5
|
+
import { requestForTargets } from "@ogw_front/utils/request_for_targets";
|
|
4
6
|
import { useBackStore } from "@ogw_front/stores/back";
|
|
7
|
+
import { useBatchGroup } from "@ogw_front/composables/batch_style";
|
|
5
8
|
|
|
6
9
|
// Mirrors FileUploader's own (unexported) UploadFile type.
|
|
7
10
|
type UploadFile = File & { isConfigured?: boolean; displayName?: string };
|
|
@@ -40,21 +43,22 @@ watch(
|
|
|
40
43
|
const textureCoordinates = ref<string[]>([]);
|
|
41
44
|
const backStore = useBackStore();
|
|
42
45
|
|
|
43
|
-
|
|
46
|
+
const groupTargetIds = useBatchGroup(() => id);
|
|
47
|
+
|
|
48
|
+
async function getTextureCoordinates(): Promise<void> {
|
|
44
49
|
const schema = back_schemas.opengeodeweb_back.texture_coordinates;
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
},
|
|
50
|
+
const targetIds = groupTargetIds.value ?? [id];
|
|
51
|
+
const responses = await requestForTargets<{ texture_coordinates: string[] }>(schema, targetIds, {
|
|
52
|
+
texture_coordinates: [],
|
|
53
|
+
});
|
|
54
|
+
textureCoordinates.value = intersectBy(
|
|
55
|
+
responses.map(([, response]) => response.texture_coordinates),
|
|
56
|
+
(coordinate) => coordinate,
|
|
53
57
|
);
|
|
54
58
|
}
|
|
55
59
|
|
|
56
|
-
onMounted(() => {
|
|
57
|
-
getTextureCoordinates();
|
|
60
|
+
onMounted(async () => {
|
|
61
|
+
await getTextureCoordinates();
|
|
58
62
|
});
|
|
59
63
|
|
|
60
64
|
async function files_uploaded_event(value: UploadFile[]): Promise<void> {
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import {
|
|
3
|
+
type RangesPerData,
|
|
4
|
+
applyRangesPerData,
|
|
5
|
+
useBatchStyle,
|
|
6
|
+
} from "@ogw_front/composables/batch_style";
|
|
2
7
|
import ViewerContextMenuItem, {
|
|
3
8
|
type ItemProps,
|
|
4
9
|
} from "@ogw_front/components/Viewer/ContextMenu/ContextMenuItem.vue";
|
|
@@ -7,7 +12,6 @@ import type { RGBAColor } from "@ogw_front/utils/default_styles/constants";
|
|
|
7
12
|
import ViewerOptionsColoringTypeSelector from "@ogw_front/components/Viewer/Options/ColoringTypeSelector.vue";
|
|
8
13
|
import ViewerOptionsSizeSlider from "@ogw_front/components/Viewer/Options/Sliders/Size.vue";
|
|
9
14
|
import ViewerOptionsVisibilitySwitch from "@ogw_front/components/Viewer/Options/VisibilitySwitch.vue";
|
|
10
|
-
import { useBatchStyle } from "@ogw_front/composables/batch_style";
|
|
11
15
|
import { useDataStyleStore } from "@ogw_front/stores/data_style";
|
|
12
16
|
import { useHybridViewerStore } from "@ogw_front/stores/hybrid_viewer";
|
|
13
17
|
|
|
@@ -120,6 +124,13 @@ const vertex_attribute_no_data_color = computed<RGBAColor>({
|
|
|
120
124
|
hybridViewerStore.remoteRender();
|
|
121
125
|
},
|
|
122
126
|
});
|
|
127
|
+
|
|
128
|
+
async function setVertexAttributeRangesPerData(ranges: RangesPerData): Promise<void> {
|
|
129
|
+
await applyRangesPerData(ranges, (targetId, minimum, maximum) =>
|
|
130
|
+
dataStyleStore.setMeshPointsVertexAttributeRange(targetId, minimum, maximum),
|
|
131
|
+
);
|
|
132
|
+
hybridViewerStore.remoteRender();
|
|
133
|
+
}
|
|
123
134
|
</script>
|
|
124
135
|
<template>
|
|
125
136
|
<ViewerContextMenuItem
|
|
@@ -144,6 +155,7 @@ const vertex_attribute_no_data_color = computed<RGBAColor>({
|
|
|
144
155
|
v-model:vertex_attribute_name="vertex_attribute_name"
|
|
145
156
|
v-model:vertex_attribute_item="vertex_attribute_item"
|
|
146
157
|
v-model:vertex_attribute_range="vertex_attribute_range"
|
|
158
|
+
@vertex_attribute_ranges_per_data="setVertexAttributeRangesPerData"
|
|
147
159
|
v-model:vertex_attribute_color_map="vertex_attribute_color_map"
|
|
148
160
|
v-model:vertex_attribute_no_data_color="vertex_attribute_no_data_color"
|
|
149
161
|
:vertex_has_colormap="true"
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import {
|
|
3
|
+
type RangesPerData,
|
|
4
|
+
applyRangesPerData,
|
|
5
|
+
useBatchStyle,
|
|
6
|
+
} from "@ogw_front/composables/batch_style";
|
|
2
7
|
import ViewerContextMenuItem, {
|
|
3
8
|
type ItemProps,
|
|
4
9
|
} from "@ogw_front/components/Viewer/ContextMenu/ContextMenuItem.vue";
|
|
@@ -6,7 +11,6 @@ import type { RGBAColor } from "@ogw_front/utils/default_styles/constants";
|
|
|
6
11
|
import SolidPolyhedra from "@ogw_front/assets/viewer_svgs/solid_polyhedra.svg";
|
|
7
12
|
import ViewerOptionsColoringTypeSelector from "@ogw_front/components/Viewer/Options/ColoringTypeSelector.vue";
|
|
8
13
|
import ViewerOptionsVisibilitySwitch from "@ogw_front/components/Viewer/Options/VisibilitySwitch.vue";
|
|
9
|
-
import { useBatchStyle } from "@ogw_front/composables/batch_style";
|
|
10
14
|
import { useDataStyleStore } from "@ogw_front/stores/data_style";
|
|
11
15
|
import { useHybridViewerStore } from "@ogw_front/stores/hybrid_viewer";
|
|
12
16
|
|
|
@@ -163,6 +167,20 @@ const polyhedron_attribute_no_data_color = computed<RGBAColor>({
|
|
|
163
167
|
hybridViewerStore.remoteRender();
|
|
164
168
|
},
|
|
165
169
|
});
|
|
170
|
+
|
|
171
|
+
async function setVertexAttributeRangesPerData(ranges: RangesPerData): Promise<void> {
|
|
172
|
+
await applyRangesPerData(ranges, (targetId, minimum, maximum) =>
|
|
173
|
+
dataStyleStore.setMeshPolyhedraVertexAttributeRange(targetId, minimum, maximum),
|
|
174
|
+
);
|
|
175
|
+
hybridViewerStore.remoteRender();
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
async function setPolyhedronAttributeRangesPerData(ranges: RangesPerData): Promise<void> {
|
|
179
|
+
await applyRangesPerData(ranges, (targetId, minimum, maximum) =>
|
|
180
|
+
dataStyleStore.setMeshPolyhedraPolyhedronAttributeRange(targetId, minimum, maximum),
|
|
181
|
+
);
|
|
182
|
+
hybridViewerStore.remoteRender();
|
|
183
|
+
}
|
|
166
184
|
</script>
|
|
167
185
|
<template>
|
|
168
186
|
<ViewerContextMenuItem
|
|
@@ -185,11 +203,13 @@ const polyhedron_attribute_no_data_color = computed<RGBAColor>({
|
|
|
185
203
|
v-model:vertex_attribute_name="vertex_attribute_name"
|
|
186
204
|
v-model:vertex_attribute_item="vertex_attribute_item"
|
|
187
205
|
v-model:vertex_attribute_range="vertex_attribute_range"
|
|
206
|
+
@vertex_attribute_ranges_per_data="setVertexAttributeRangesPerData"
|
|
188
207
|
v-model:vertex_attribute_color_map="vertex_attribute_color_map"
|
|
189
208
|
v-model:vertex_attribute_no_data_color="vertex_attribute_no_data_color"
|
|
190
209
|
v-model:polyhedron_attribute_name="polyhedron_attribute_name"
|
|
191
210
|
v-model:polyhedron_attribute_item="polyhedron_attribute_item"
|
|
192
211
|
v-model:polyhedron_attribute_range="polyhedron_attribute_range"
|
|
212
|
+
@polyhedron_attribute_ranges_per_data="setPolyhedronAttributeRangesPerData"
|
|
193
213
|
v-model:polyhedron_attribute_color_map="polyhedron_attribute_color_map"
|
|
194
214
|
v-model:polyhedron_attribute_no_data_color="polyhedron_attribute_no_data_color"
|
|
195
215
|
/>
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import {
|
|
3
|
+
type RangesPerData,
|
|
4
|
+
applyRangesPerData,
|
|
5
|
+
useBatchStyle,
|
|
6
|
+
} from "@ogw_front/composables/batch_style";
|
|
2
7
|
import ViewerContextMenuItem, {
|
|
3
8
|
type ItemProps,
|
|
4
9
|
} from "@ogw_front/components/Viewer/ContextMenu/ContextMenuItem.vue";
|
|
@@ -6,7 +11,6 @@ import PolygonalSurfacePolygons from "@ogw_front/assets/viewer_svgs/surface_tria
|
|
|
6
11
|
import type { RGBAColor } from "@ogw_front/utils/default_styles/constants";
|
|
7
12
|
import ViewerOptionsColoringTypeSelector from "@ogw_front/components/Viewer/Options/ColoringTypeSelector.vue";
|
|
8
13
|
import ViewerOptionsVisibilitySwitch from "@ogw_front/components/Viewer/Options/VisibilitySwitch.vue";
|
|
9
|
-
import { useBatchStyle } from "@ogw_front/composables/batch_style";
|
|
10
14
|
import { useDataStyleStore } from "@ogw_front/stores/data_style";
|
|
11
15
|
import { useHybridViewerStore } from "@ogw_front/stores/hybrid_viewer";
|
|
12
16
|
|
|
@@ -178,6 +182,20 @@ const polygon_attribute_no_data_color = computed<RGBAColor>({
|
|
|
178
182
|
hybridViewerStore.remoteRender();
|
|
179
183
|
},
|
|
180
184
|
});
|
|
185
|
+
|
|
186
|
+
async function setVertexAttributeRangesPerData(ranges: RangesPerData): Promise<void> {
|
|
187
|
+
await applyRangesPerData(ranges, (targetId, minimum, maximum) =>
|
|
188
|
+
dataStyleStore.setMeshPolygonsVertexAttributeRange(targetId, minimum, maximum),
|
|
189
|
+
);
|
|
190
|
+
hybridViewerStore.remoteRender();
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
async function setPolygonAttributeRangesPerData(ranges: RangesPerData): Promise<void> {
|
|
194
|
+
await applyRangesPerData(ranges, (targetId, minimum, maximum) =>
|
|
195
|
+
dataStyleStore.setMeshPolygonsPolygonAttributeRange(targetId, minimum, maximum),
|
|
196
|
+
);
|
|
197
|
+
hybridViewerStore.remoteRender();
|
|
198
|
+
}
|
|
181
199
|
</script>
|
|
182
200
|
|
|
183
201
|
<template>
|
|
@@ -202,11 +220,13 @@ const polygon_attribute_no_data_color = computed<RGBAColor>({
|
|
|
202
220
|
v-model:vertex_attribute_name="vertex_attribute_name"
|
|
203
221
|
v-model:vertex_attribute_item="vertex_attribute_item"
|
|
204
222
|
v-model:vertex_attribute_range="vertex_attribute_range"
|
|
223
|
+
@vertex_attribute_ranges_per_data="setVertexAttributeRangesPerData"
|
|
205
224
|
v-model:vertex_attribute_color_map="vertex_attribute_color_map"
|
|
206
225
|
v-model:vertex_attribute_no_data_color="vertex_attribute_no_data_color"
|
|
207
226
|
v-model:polygon_attribute_name="polygon_attribute_name"
|
|
208
227
|
v-model:polygon_attribute_item="polygon_attribute_item"
|
|
209
228
|
v-model:polygon_attribute_range="polygon_attribute_range"
|
|
229
|
+
@polygon_attribute_ranges_per_data="setPolygonAttributeRangesPerData"
|
|
210
230
|
v-model:polygon_attribute_color_map="polygon_attribute_color_map"
|
|
211
231
|
v-model:polygon_attribute_no_data_color="polygon_attribute_no_data_color"
|
|
212
232
|
/>
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import {
|
|
3
|
+
type ViewerIdResult,
|
|
4
|
+
useOverlappingPicker,
|
|
5
|
+
} from "@ogw_front/composables/use_overlapping_picker";
|
|
2
6
|
import OverlappingObjectsPicker from "@ogw_front/components/Viewer/OverlappingObjectsPicker.vue";
|
|
3
7
|
import ToolActiveChip from "@ogw_front/components/Viewer/ToolActiveChip.vue";
|
|
8
|
+
import type { TreeMenuPayload } from "@ogw_front/utils/treeview";
|
|
4
9
|
import ViewerContextMenu from "@ogw_front/components/Viewer/ContextMenu/ContextMenu.vue";
|
|
5
10
|
import ViewerObjectTreeLayout from "@ogw_front/components/Viewer/ObjectTree/Layout.vue";
|
|
6
11
|
import { getCurrentInstance } from "vue";
|
|
7
12
|
import { useHybridViewerStore } from "@ogw_front/stores/hybrid_viewer";
|
|
8
13
|
import { useMenuStore } from "@ogw_front/stores/menu";
|
|
9
|
-
import { useOverlappingPicker } from "@ogw_front/composables/use_overlapping_picker";
|
|
10
14
|
import { useViewerStore } from "@ogw_front/stores/viewer";
|
|
11
15
|
|
|
12
16
|
interface Props {
|
|
@@ -18,7 +22,7 @@ interface Props {
|
|
|
18
22
|
const { displayMenu, containerWidth, containerHeight } = defineProps<Props>();
|
|
19
23
|
|
|
20
24
|
const emit = defineEmits<{
|
|
21
|
-
"show-menu": [
|
|
25
|
+
"show-menu": [payload: TreeMenuPayload];
|
|
22
26
|
}>();
|
|
23
27
|
const menuStore = useMenuStore();
|
|
24
28
|
const viewerStore = useViewerStore();
|
|
@@ -66,7 +70,7 @@ const {
|
|
|
66
70
|
get_viewer_id: trigger_picker,
|
|
67
71
|
} = useOverlappingPicker();
|
|
68
72
|
|
|
69
|
-
function get_viewer_id(x: number, y: number):
|
|
73
|
+
function get_viewer_id(x: number, y: number): Promise<ViewerIdResult> {
|
|
70
74
|
const instance = getCurrentInstance();
|
|
71
75
|
const containerRect = instance?.proxy?.$el
|
|
72
76
|
?.closest?.('[data-testid="hybridViewer"]')
|
|
@@ -1,14 +1,74 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type ComputedRef,
|
|
3
|
+
type InjectionKey,
|
|
4
|
+
type MaybeRefOrGetter,
|
|
5
|
+
computed,
|
|
6
|
+
inject,
|
|
7
|
+
provide,
|
|
8
|
+
toValue,
|
|
9
|
+
} from "vue";
|
|
1
10
|
import { useDataStore } from "@ogw_front/stores/data";
|
|
2
11
|
import { useTreeviewStore } from "@ogw_front/stores/treeview";
|
|
3
12
|
|
|
4
|
-
|
|
13
|
+
type AttributeRange = [number, number];
|
|
14
|
+
type RangesPerData = ReadonlyMap<string, AttributeRange>;
|
|
15
|
+
|
|
16
|
+
const BATCH_GROUP_KEY: InjectionKey<ComputedRef<string[]>> = Symbol("batch_group");
|
|
17
|
+
|
|
18
|
+
function provideBatchGroup(targetIds: () => string[]): void {
|
|
19
|
+
provide(BATCH_GROUP_KEY, computed(targetIds));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function injectBatchGroup(): ComputedRef<string[]> {
|
|
23
|
+
return inject(BATCH_GROUP_KEY, () => computed(() => []), true);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function groupTargetsOf(targetIds: string[], id: string): string[] | undefined {
|
|
27
|
+
return targetIds.includes(id) ? targetIds : undefined;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function useBatchGroup(id: MaybeRefOrGetter<string>): ComputedRef<string[] | undefined> {
|
|
31
|
+
const group = injectBatchGroup();
|
|
32
|
+
return computed(() => groupTargetsOf(group.value, toValue(id)));
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async function applyRangesPerData(
|
|
36
|
+
ranges: RangesPerData,
|
|
37
|
+
setRange: (id: string, minimum: number, maximum: number) => unknown,
|
|
38
|
+
): Promise<void> {
|
|
39
|
+
await Promise.all(
|
|
40
|
+
[...ranges].map(async ([targetId, [minimum, maximum]]) => {
|
|
41
|
+
await setRange(targetId, minimum, maximum);
|
|
42
|
+
}),
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async function applyActionOn(
|
|
47
|
+
targets: readonly string[],
|
|
48
|
+
action: (id: string) => Promise<unknown>,
|
|
49
|
+
): Promise<void> {
|
|
50
|
+
await Promise.all(
|
|
51
|
+
targets.map(async (targetId) => {
|
|
52
|
+
await action(targetId);
|
|
53
|
+
}),
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function useBatchStyle(): { applyBatchStyle: typeof applyBatchStyle } {
|
|
5
58
|
const treeviewStore = useTreeviewStore();
|
|
6
59
|
const dataStore = useDataStore();
|
|
60
|
+
const group = injectBatchGroup();
|
|
7
61
|
|
|
8
62
|
async function applyBatchStyle(
|
|
9
63
|
id: string,
|
|
10
64
|
action: (id: string) => Promise<unknown>,
|
|
11
65
|
): Promise<void> {
|
|
66
|
+
const groupTargets = groupTargetsOf(group.value, id);
|
|
67
|
+
if (groupTargets) {
|
|
68
|
+
await applyActionOn(groupTargets, action);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
|
|
12
72
|
const isActive = treeviewStore.activeItems.includes(id);
|
|
13
73
|
if (!isActive || treeviewStore.activeItems.length <= 1) {
|
|
14
74
|
await action(id);
|
|
@@ -38,3 +98,6 @@ export function useBatchStyle(): { applyBatchStyle: typeof applyBatchStyle } {
|
|
|
38
98
|
|
|
39
99
|
return { applyBatchStyle };
|
|
40
100
|
}
|
|
101
|
+
|
|
102
|
+
export { BATCH_GROUP_KEY, applyRangesPerData, provideBatchGroup, useBatchGroup, useBatchStyle };
|
|
103
|
+
export type { AttributeRange, RangesPerData };
|
|
@@ -30,10 +30,10 @@ interface UseTreeFilterReturn {
|
|
|
30
30
|
availableFilterOptions: ComputedRef<string[]>;
|
|
31
31
|
toggleSort: () => void;
|
|
32
32
|
customFilter: typeof customFilter;
|
|
33
|
-
applySearchFilter: (
|
|
34
|
-
newSelection: readonly
|
|
35
|
-
previousSelection?: readonly
|
|
36
|
-
) =>
|
|
33
|
+
applySearchFilter: <TId>(
|
|
34
|
+
newSelection: readonly TId[],
|
|
35
|
+
previousSelection?: readonly TId[],
|
|
36
|
+
) => TId[];
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
function customFilter(
|
|
@@ -163,10 +163,10 @@ function useTreeFilter(
|
|
|
163
163
|
return map;
|
|
164
164
|
});
|
|
165
165
|
|
|
166
|
-
function applySearchFilter(
|
|
167
|
-
newSelection: readonly
|
|
168
|
-
previousSelection: readonly
|
|
169
|
-
):
|
|
166
|
+
function applySearchFilter<TId>(
|
|
167
|
+
newSelection: readonly TId[],
|
|
168
|
+
previousSelection: readonly TId[] = [],
|
|
169
|
+
): TId[] {
|
|
170
170
|
if (!search.value) {
|
|
171
171
|
return [...newSelection];
|
|
172
172
|
}
|