gltf-parser-plugin 1.1.6 → 1.1.8
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/build/gltf-parser-plugin.module.js +1676 -458
- package/build/gltf-parser-plugin.module.js.map +1 -1
- package/build/index.d.ts +249 -50
- package/package.json +9 -8
|
@@ -1,23 +1,68 @@
|
|
|
1
|
-
import { Box2, Box3, BufferAttribute, BufferGeometry, Color, CustomBlending, DataTexture, DoubleSide, EdgesGeometry, EventDispatcher, Float32BufferAttribute, FrontSide, Group, InstancedMesh, LineSegments, Loader, Matrix2, Matrix3, Matrix4, Mesh, MeshBasicMaterial, MeshStandardMaterial, OneFactor, OrthographicCamera, Quaternion, RGBAFormat, SRGBColorSpace, Scene, ShaderMaterial, Texture, Triangle, UnsignedByteType, Vector2, Vector3, Vector4, WebGLRenderTarget, WebGLRenderer, ZeroFactor } from "three";
|
|
2
|
-
//#region src/mesh-helper/
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
1
|
+
import { Box2, Box3, BufferAttribute, BufferGeometry, Color, CustomBlending, DataTexture, DoubleSide, EdgesGeometry, Euler, EventDispatcher, Float32BufferAttribute, FrontSide, Group, InstancedMesh, LineSegments, Loader, Material, Matrix2, Matrix3, Matrix4, Mesh, MeshBasicMaterial, MeshStandardMaterial, OneFactor, OrthographicCamera, Quaternion, RGBAFormat, SRGBColorSpace, Scene, ShaderMaterial, Texture, Triangle, UnsignedByteType, Vector2, Vector3, Vector4, WebGLRenderTarget, WebGLRenderer, ZeroFactor } from "three";
|
|
2
|
+
//#region src/mesh-helper/index-visibility.ts
|
|
3
|
+
/** 从 mesh 的 idMap 和 hiddenOids 构建需要隐藏的 feature ID 集合 */
|
|
4
|
+
function getHiddenFeatureIds(mesh, hiddenOids) {
|
|
5
|
+
const idMap = mesh.userData?.idMap;
|
|
6
|
+
if (!idMap) return /* @__PURE__ */ new Set();
|
|
7
|
+
const hidden = /* @__PURE__ */ new Set();
|
|
8
|
+
for (const oid of hiddenOids) {
|
|
9
|
+
const fid = idMap[oid];
|
|
10
|
+
if (fid !== void 0) hidden.add(fid);
|
|
11
|
+
}
|
|
12
|
+
return hidden;
|
|
13
|
+
}
|
|
14
|
+
/** 对单个 mesh 应用可见性过滤(通过修改 index 排除隐藏的三角形) */
|
|
15
|
+
function applyVisibilityToMesh(mesh, hiddenOids) {
|
|
16
|
+
const { meshFeatures } = mesh.userData;
|
|
17
|
+
if (!meshFeatures) return;
|
|
18
|
+
const geometry = mesh.geometry;
|
|
19
|
+
const index = geometry.index;
|
|
20
|
+
const featureIdAttr = geometry.getAttribute("_feature_id_0");
|
|
21
|
+
if (!index || !featureIdAttr) return;
|
|
22
|
+
const hiddenFeatureIds = getHiddenFeatureIds(mesh, hiddenOids);
|
|
23
|
+
if (hiddenFeatureIds.size === 0) {
|
|
24
|
+
restoreMeshIndex(mesh);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
if (!mesh.userData._originalIndex) mesh.userData._originalIndex = index.array.slice(0);
|
|
28
|
+
const originalArray = mesh.userData._originalIndex;
|
|
29
|
+
const filtered = originalArray instanceof Uint32Array ? new Uint32Array(originalArray.length) : new Uint16Array(originalArray.length);
|
|
30
|
+
let writeOffset = 0;
|
|
31
|
+
for (let i = 0; i < originalArray.length; i += 3) {
|
|
32
|
+
const fid = featureIdAttr.getX(originalArray[i]);
|
|
33
|
+
if (hiddenFeatureIds.has(fid)) continue;
|
|
34
|
+
filtered[writeOffset++] = originalArray[i];
|
|
35
|
+
filtered[writeOffset++] = originalArray[i + 1];
|
|
36
|
+
filtered[writeOffset++] = originalArray[i + 2];
|
|
37
|
+
}
|
|
38
|
+
const filteredArray = filtered.subarray(0, writeOffset);
|
|
39
|
+
geometry.setIndex(new BufferAttribute(filteredArray, 1));
|
|
40
|
+
geometry.index.needsUpdate = true;
|
|
41
|
+
}
|
|
42
|
+
/** 恢复 mesh 的原始 index */
|
|
43
|
+
function restoreMeshIndex(mesh) {
|
|
44
|
+
const original = mesh.userData?._originalIndex;
|
|
45
|
+
if (!original) return;
|
|
46
|
+
const geometry = mesh.geometry;
|
|
47
|
+
if (!geometry?.index) return;
|
|
48
|
+
geometry.setIndex(new BufferAttribute(original, 1));
|
|
49
|
+
geometry.index.needsUpdate = true;
|
|
50
|
+
}
|
|
51
|
+
/** 遍历 scene 中所有 tile mesh,应用可见性过滤 */
|
|
52
|
+
function applyVisibilityToScene(scene, hiddenOids) {
|
|
53
|
+
const oidSet = hiddenOids;
|
|
54
|
+
if (oidSet.size === 0) {
|
|
55
|
+
scene.traverse((obj) => {
|
|
56
|
+
const mesh = obj;
|
|
57
|
+
if (mesh.userData?.meshFeatures && !mesh.userData?.isSplit) restoreMeshIndex(mesh);
|
|
58
|
+
});
|
|
59
|
+
return;
|
|
19
60
|
}
|
|
20
|
-
|
|
61
|
+
scene.traverse((obj) => {
|
|
62
|
+
const mesh = obj;
|
|
63
|
+
if (mesh.userData?.meshFeatures && mesh.userData?.structuralMetadata && !mesh.userData?.isSplit) applyVisibilityToMesh(mesh, oidSet);
|
|
64
|
+
});
|
|
65
|
+
}
|
|
21
66
|
//#endregion
|
|
22
67
|
//#region src/mesh-helper/idmap.ts
|
|
23
68
|
var FEATURE_INDEX = 0;
|
|
@@ -108,87 +153,143 @@ function queryFeatureFromIntersection(hit) {
|
|
|
108
153
|
//#endregion
|
|
109
154
|
//#region src/mesh-helper/mesh.ts
|
|
110
155
|
/**
|
|
111
|
-
*
|
|
156
|
+
* 合并多个 feature 的三角形为单一 BufferGeometry(共享顶点属性,index 为并集)
|
|
112
157
|
*/
|
|
113
|
-
function
|
|
114
|
-
|
|
115
|
-
for (let i = 0; i < featureIdAttr.count; i++) {
|
|
116
|
-
const featureId = featureIdAttr.getX(i);
|
|
117
|
-
if (!featureIdMap.has(featureId)) featureIdMap.set(featureId, /* @__PURE__ */ new Set());
|
|
118
|
-
featureIdMap.get(featureId).add(i);
|
|
119
|
-
}
|
|
120
|
-
return featureIdMap;
|
|
121
|
-
}
|
|
122
|
-
/**
|
|
123
|
-
* Create a geometry for a specified feature ID
|
|
124
|
-
*/
|
|
125
|
-
function createGeometryForFeatureId(originalGeometry, featureIdMap, targetFeatureId) {
|
|
158
|
+
function createGeometryForFeatureIdSet(originalGeometry, featureIdAttr, targetFids) {
|
|
159
|
+
if (targetFids.size === 0 || !originalGeometry.index) return null;
|
|
126
160
|
const newGeometry = new BufferGeometry();
|
|
127
|
-
const targetVertexIndices = featureIdMap.get(targetFeatureId);
|
|
128
|
-
if (!targetVertexIndices || targetVertexIndices.size === 0) return null;
|
|
129
161
|
const attributes = originalGeometry.attributes;
|
|
130
162
|
for (const attributeName in attributes) newGeometry.setAttribute(attributeName, attributes[attributeName]);
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
163
|
+
const originalIndex = originalGeometry.index.array;
|
|
164
|
+
const newIndices = [];
|
|
165
|
+
for (let i = 0; i < originalIndex.length; i += 3) {
|
|
166
|
+
const a = originalIndex[i];
|
|
167
|
+
const b = originalIndex[i + 1];
|
|
168
|
+
const c = originalIndex[i + 2];
|
|
169
|
+
const fa = featureIdAttr.getX(a);
|
|
170
|
+
if (fa === featureIdAttr.getX(b) && fa === featureIdAttr.getX(c) && targetFids.has(fa)) newIndices.push(a, b, c);
|
|
171
|
+
}
|
|
172
|
+
if (newIndices.length === 0) return null;
|
|
173
|
+
newGeometry.setIndex(newIndices);
|
|
142
174
|
return newGeometry;
|
|
143
175
|
}
|
|
144
176
|
/**
|
|
145
|
-
*
|
|
177
|
+
* 将同一瓦片 mesh 内、属于给定 OID 集合的所有 feature 合并为 **单个** Mesh(每瓦片最多一个)
|
|
146
178
|
*/
|
|
147
|
-
function
|
|
179
|
+
function splitMeshByOidsMerged(originalMesh, oidSet) {
|
|
180
|
+
if (oidSet.size === 0) return null;
|
|
181
|
+
const idMap = originalMesh.userData?.idMap;
|
|
182
|
+
if (!idMap) return null;
|
|
148
183
|
const { meshFeatures, structuralMetadata } = originalMesh.userData;
|
|
149
184
|
const { geometry, featureIds } = meshFeatures;
|
|
150
185
|
const featureId = featureIds[0];
|
|
151
186
|
const featureIdAttr = geometry.getAttribute(`_feature_id_${featureId.attribute}`);
|
|
152
187
|
if (!featureIdAttr) {
|
|
153
188
|
console.warn("No feature ID attribute found");
|
|
154
|
-
return
|
|
155
|
-
}
|
|
156
|
-
const
|
|
157
|
-
const
|
|
158
|
-
for (const
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
_oid = propertyData?._oid;
|
|
164
|
-
if (_oid === oid) {
|
|
165
|
-
const newGeometry = createGeometryForFeatureId(geometry, featureIdMap, fid);
|
|
166
|
-
if (newGeometry && newGeometry.attributes.position.count > 0) {
|
|
167
|
-
const newMesh = new Mesh(newGeometry, originalMesh.material.clone());
|
|
168
|
-
newMesh.parent = originalMesh.parent;
|
|
169
|
-
newMesh.position.copy(originalMesh.position);
|
|
170
|
-
newMesh.rotation.copy(originalMesh.rotation);
|
|
171
|
-
newMesh.scale.copy(originalMesh.scale);
|
|
172
|
-
newMesh.matrixWorld.copy(originalMesh.matrixWorld);
|
|
173
|
-
newMesh.userData = {
|
|
174
|
-
...originalMesh.userData,
|
|
175
|
-
featureId: fid,
|
|
176
|
-
oid,
|
|
177
|
-
originalMesh,
|
|
178
|
-
propertyData,
|
|
179
|
-
isSplit: true
|
|
180
|
-
};
|
|
181
|
-
newMesh.name = `feature_${fid}_${oid || ""}`;
|
|
182
|
-
currentBatchMeshes.push(newMesh);
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
} catch (e) {
|
|
186
|
-
console.warn(`Failed to get property data for feature ${fid}:`, e);
|
|
189
|
+
return null;
|
|
190
|
+
}
|
|
191
|
+
const targetFids = /* @__PURE__ */ new Set();
|
|
192
|
+
const oidsOnMesh = [];
|
|
193
|
+
for (const oid of oidSet) {
|
|
194
|
+
const fid = idMap[oid];
|
|
195
|
+
if (fid !== void 0) {
|
|
196
|
+
targetFids.add(fid);
|
|
197
|
+
oidsOnMesh.push(oid);
|
|
187
198
|
}
|
|
188
|
-
} catch (error) {
|
|
189
|
-
console.warn(`Error creating mesh for feature ${fid}:`, error);
|
|
190
199
|
}
|
|
191
|
-
return
|
|
200
|
+
if (targetFids.size === 0) return null;
|
|
201
|
+
const newGeometry = createGeometryForFeatureIdSet(geometry, featureIdAttr, targetFids);
|
|
202
|
+
if (!newGeometry || newGeometry.attributes.position.count === 0) return null;
|
|
203
|
+
const newMesh = new Mesh(newGeometry, originalMesh.material.clone());
|
|
204
|
+
newMesh.parent = originalMesh.parent;
|
|
205
|
+
newMesh.position.copy(originalMesh.position);
|
|
206
|
+
newMesh.rotation.copy(originalMesh.rotation);
|
|
207
|
+
newMesh.scale.copy(originalMesh.scale);
|
|
208
|
+
newMesh.matrixWorld.copy(originalMesh.matrixWorld);
|
|
209
|
+
oidsOnMesh.sort((a, b) => a - b);
|
|
210
|
+
const primaryOid = oidsOnMesh[0];
|
|
211
|
+
let propertyData = null;
|
|
212
|
+
if (structuralMetadata && idMap[primaryOid] !== void 0) try {
|
|
213
|
+
propertyData = structuralMetadata.getPropertyTableData(featureId.propertyTable, idMap[primaryOid]);
|
|
214
|
+
} catch {}
|
|
215
|
+
newMesh.userData = {
|
|
216
|
+
...originalMesh.userData,
|
|
217
|
+
featureId: idMap[primaryOid],
|
|
218
|
+
oid: primaryOid,
|
|
219
|
+
collectorOids: oidsOnMesh,
|
|
220
|
+
originalMesh,
|
|
221
|
+
propertyData,
|
|
222
|
+
isSplit: true,
|
|
223
|
+
isMergedSplit: true
|
|
224
|
+
};
|
|
225
|
+
newMesh.name = `merged_features_${oidsOnMesh.length}_${primaryOid}`;
|
|
226
|
+
return newMesh;
|
|
227
|
+
}
|
|
228
|
+
/** 瓦片内原始 feature mesh(非 split 子网格) */
|
|
229
|
+
function isFeatureSourceMesh(mesh) {
|
|
230
|
+
const u = mesh.userData;
|
|
231
|
+
return Boolean(u?.meshFeatures && u?.structuralMetadata && !u?.isSplit);
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* 从瓦片中获取所有 OID
|
|
235
|
+
*/
|
|
236
|
+
function getAllOidsFromTiles(tiles) {
|
|
237
|
+
const oidSet = /* @__PURE__ */ new Set();
|
|
238
|
+
tiles.group.traverse((child) => {
|
|
239
|
+
const mesh = child;
|
|
240
|
+
if (!isFeatureSourceMesh(mesh)) return;
|
|
241
|
+
const idMap = mesh.userData.idMap;
|
|
242
|
+
if (!idMap) return;
|
|
243
|
+
for (const oid of Object.keys(idMap).map(Number)) oidSet.add(oid);
|
|
244
|
+
});
|
|
245
|
+
return Array.from(oidSet);
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* 根据 OID 获取属性数据(从瓦片 structuralMetadata)
|
|
249
|
+
*/
|
|
250
|
+
function getPropertyDataByOid(tiles, oid) {
|
|
251
|
+
let result = null;
|
|
252
|
+
tiles.group.traverse((child) => {
|
|
253
|
+
if (result) return;
|
|
254
|
+
const mesh = child;
|
|
255
|
+
if (!isFeatureSourceMesh(mesh)) return;
|
|
256
|
+
const idMap = mesh.userData.idMap;
|
|
257
|
+
if (!idMap || idMap[oid] === void 0) return;
|
|
258
|
+
const { meshFeatures, structuralMetadata } = mesh.userData;
|
|
259
|
+
const featureId = meshFeatures.featureIds[0];
|
|
260
|
+
const fid = idMap[oid];
|
|
261
|
+
try {
|
|
262
|
+
result = structuralMetadata.getPropertyTableData(featureId.propertyTable, fid);
|
|
263
|
+
} catch {}
|
|
264
|
+
});
|
|
265
|
+
return result;
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* 单次遍历场景构建 OID → 属性表数据。
|
|
269
|
+
* 批量样式/筛选时使用,避免对每个 OID 重复 traverse(O(n×场景节点))。
|
|
270
|
+
*/
|
|
271
|
+
function getPropertyDataMapFromTiles(tiles) {
|
|
272
|
+
const map = /* @__PURE__ */ new Map();
|
|
273
|
+
tiles.group.traverse((child) => {
|
|
274
|
+
const mesh = child;
|
|
275
|
+
if (!isFeatureSourceMesh(mesh)) return;
|
|
276
|
+
const idMap = mesh.userData.idMap;
|
|
277
|
+
if (!idMap) return;
|
|
278
|
+
const { meshFeatures, structuralMetadata } = mesh.userData;
|
|
279
|
+
const propertyTable = meshFeatures.featureIds[0].propertyTable;
|
|
280
|
+
for (const oid of Object.keys(idMap).map(Number)) {
|
|
281
|
+
if (map.has(oid)) continue;
|
|
282
|
+
const fid = idMap[oid];
|
|
283
|
+
if (fid === void 0) continue;
|
|
284
|
+
try {
|
|
285
|
+
const data = structuralMetadata.getPropertyTableData(propertyTable, fid);
|
|
286
|
+
map.set(oid, data);
|
|
287
|
+
} catch {
|
|
288
|
+
map.set(oid, null);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
});
|
|
292
|
+
return map;
|
|
192
293
|
}
|
|
193
294
|
/**
|
|
194
295
|
* 根据OID获取包含该OID的瓦片mesh
|
|
@@ -197,9 +298,7 @@ function getTileMeshesByOid(tiles, oid) {
|
|
|
197
298
|
const tileMeshes = [];
|
|
198
299
|
tiles.group.traverse((child) => {
|
|
199
300
|
const mesh = child;
|
|
200
|
-
if (mesh
|
|
201
|
-
if (checkMeshContainsOid(mesh, oid)) tileMeshes.push(mesh);
|
|
202
|
-
}
|
|
301
|
+
if (isFeatureSourceMesh(mesh) && checkMeshContainsOid(mesh, oid)) tileMeshes.push(mesh);
|
|
203
302
|
});
|
|
204
303
|
return tileMeshes;
|
|
205
304
|
}
|
|
@@ -208,43 +307,74 @@ function checkMeshContainsOid(mesh, oid) {
|
|
|
208
307
|
if (!idMap) return false;
|
|
209
308
|
return idMap[oid] !== void 0;
|
|
210
309
|
}
|
|
310
|
+
//#endregion
|
|
311
|
+
//#region src/MeshCollector.ts
|
|
312
|
+
/** 去重并排序 OID */
|
|
313
|
+
function normalizeMeshCollectorOids(oids) {
|
|
314
|
+
return [...new Set(oids)].sort((a, b) => a - b);
|
|
315
|
+
}
|
|
211
316
|
/**
|
|
212
|
-
*
|
|
317
|
+
* 与 MeshCollector.getCacheKey()、插件 collectorCache 键一致
|
|
213
318
|
*/
|
|
214
|
-
function
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
return
|
|
319
|
+
function meshCollectorQueryCacheKey(query) {
|
|
320
|
+
const oidsNorm = normalizeMeshCollectorOids(query.oids ?? []);
|
|
321
|
+
const oidPart = oidsNorm.length > 0 ? oidsNorm.join(",") : "*";
|
|
322
|
+
const condRaw = query.condition?.trim() ?? "";
|
|
323
|
+
return `${oidPart}@@${condRaw === "" ? "_" : encodeURIComponent(condRaw)}`;
|
|
324
|
+
}
|
|
325
|
+
/** @deprecated 请使用 meshCollectorQueryCacheKey({ oids }) */
|
|
326
|
+
function meshCollectorGroupKey(oids) {
|
|
327
|
+
return meshCollectorQueryCacheKey({ oids });
|
|
223
328
|
}
|
|
224
|
-
//#endregion
|
|
225
|
-
//#region src/MeshCollector.ts
|
|
226
329
|
/**
|
|
227
|
-
* MeshCollector -
|
|
228
|
-
* 随着瓦片变化,会自动更新 meshes 并触发 mesh-change 事件
|
|
330
|
+
* MeshCollector - 按查询条件监听并收集 split mesh
|
|
229
331
|
*/
|
|
230
332
|
var MeshCollector = class extends EventDispatcher {
|
|
231
|
-
|
|
333
|
+
queryOids;
|
|
334
|
+
condition;
|
|
335
|
+
cacheKey;
|
|
232
336
|
plugin;
|
|
233
337
|
_meshes = [];
|
|
234
338
|
_disposed = false;
|
|
235
|
-
constructor(
|
|
339
|
+
constructor(query, plugin) {
|
|
236
340
|
super();
|
|
237
|
-
|
|
341
|
+
const oids = normalizeMeshCollectorOids(query.oids ?? []);
|
|
342
|
+
const condition = query.condition?.trim() || void 0;
|
|
343
|
+
if (oids.length === 0 && !condition) throw new Error("MeshCollector requires at least one OID in oids and/or a non-empty condition");
|
|
344
|
+
this.queryOids = oids;
|
|
345
|
+
this.condition = condition;
|
|
346
|
+
this.cacheKey = meshCollectorQueryCacheKey({
|
|
347
|
+
oids,
|
|
348
|
+
condition
|
|
349
|
+
});
|
|
238
350
|
this.plugin = plugin;
|
|
239
351
|
plugin._registerCollector(this);
|
|
240
352
|
this._updateMeshes();
|
|
241
353
|
}
|
|
354
|
+
getCacheKey() {
|
|
355
|
+
return this.cacheKey;
|
|
356
|
+
}
|
|
357
|
+
/** 查询里显式传入的 OID(规范化后);仅用 condition 筛选时可能为空数组 */
|
|
358
|
+
getOids() {
|
|
359
|
+
return this.queryOids;
|
|
360
|
+
}
|
|
361
|
+
/** 有显式 OID 时返回第一个;否则无意义(可能为 undefined) */
|
|
362
|
+
getOid() {
|
|
363
|
+
return this.queryOids[0];
|
|
364
|
+
}
|
|
242
365
|
get meshes() {
|
|
243
366
|
return this._meshes;
|
|
244
367
|
}
|
|
368
|
+
/** 与 setStyle 一致的条件表达式(若有) */
|
|
369
|
+
getCondition() {
|
|
370
|
+
return this.condition;
|
|
371
|
+
}
|
|
245
372
|
_updateMeshes() {
|
|
246
373
|
if (this._disposed) return;
|
|
247
|
-
const newMeshes = this.plugin.
|
|
374
|
+
const newMeshes = this.plugin._getMeshesForCollectorQueryInternal({
|
|
375
|
+
oids: this.queryOids,
|
|
376
|
+
condition: this.condition
|
|
377
|
+
});
|
|
248
378
|
if (newMeshes.length !== this._meshes.length || newMeshes.some((mesh, i) => mesh !== this._meshes[i])) {
|
|
249
379
|
this._meshes = newMeshes;
|
|
250
380
|
this.dispatchEvent({
|
|
@@ -253,9 +383,6 @@ var MeshCollector = class extends EventDispatcher {
|
|
|
253
383
|
});
|
|
254
384
|
}
|
|
255
385
|
}
|
|
256
|
-
getOid() {
|
|
257
|
-
return this.oid;
|
|
258
|
-
}
|
|
259
386
|
dispose() {
|
|
260
387
|
if (this._disposed) return;
|
|
261
388
|
this._disposed = true;
|
|
@@ -264,6 +391,51 @@ var MeshCollector = class extends EventDispatcher {
|
|
|
264
391
|
}
|
|
265
392
|
};
|
|
266
393
|
//#endregion
|
|
394
|
+
//#region src/plugin/style-condition-eval.ts
|
|
395
|
+
/**
|
|
396
|
+
* 与 StyleHelper 中 `show`、`conditions` 条件项的表达式求值一致
|
|
397
|
+
* 在 propertyData 的键作为变量名的上下文中执行 `Boolean(expr)`
|
|
398
|
+
*
|
|
399
|
+
* 实现:对每个表达式字符串只编译一次 `new Function('data', 'with(d){...}')`,
|
|
400
|
+
* 避免按「表达式 × 属性键集合」重复编译,也避免每次求值排序/拼接 cacheKey。
|
|
401
|
+
*/
|
|
402
|
+
var compiledCache = /* @__PURE__ */ new Map();
|
|
403
|
+
var MAX_CACHE_ENTRIES = 512;
|
|
404
|
+
function getCompiled(expr) {
|
|
405
|
+
let fn = compiledCache.get(expr);
|
|
406
|
+
if (fn) return fn;
|
|
407
|
+
try {
|
|
408
|
+
fn = new Function("data", `var d = data != null && typeof data === "object" ? data : {};
|
|
409
|
+
with (d) { return Boolean(${expr}); }`);
|
|
410
|
+
} catch {
|
|
411
|
+
return null;
|
|
412
|
+
}
|
|
413
|
+
if (compiledCache.size >= MAX_CACHE_ENTRIES) {
|
|
414
|
+
const first = compiledCache.keys().next().value;
|
|
415
|
+
if (first !== void 0) compiledCache.delete(first);
|
|
416
|
+
}
|
|
417
|
+
compiledCache.set(expr, fn);
|
|
418
|
+
return fn;
|
|
419
|
+
}
|
|
420
|
+
/**
|
|
421
|
+
* 清空表达式编译缓存(热更新或单测可调用)
|
|
422
|
+
*/
|
|
423
|
+
function clearStyleConditionCache() {
|
|
424
|
+
compiledCache.clear();
|
|
425
|
+
}
|
|
426
|
+
function evaluateStyleCondition(expr, propertyData) {
|
|
427
|
+
if (expr === true) return true;
|
|
428
|
+
if (expr === false) return false;
|
|
429
|
+
if (typeof expr !== "string" || !expr.trim()) return true;
|
|
430
|
+
const fn = getCompiled(expr.trim());
|
|
431
|
+
if (!fn) return false;
|
|
432
|
+
try {
|
|
433
|
+
return fn(propertyData ?? {});
|
|
434
|
+
} catch {
|
|
435
|
+
return false;
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
//#endregion
|
|
267
439
|
//#region src/utils/build-textures.ts
|
|
268
440
|
/**
|
|
269
441
|
* Build textures from GLTF data
|
|
@@ -566,15 +738,24 @@ function polygonIntersectsRect(polygon, minX, minY, maxX, maxY) {
|
|
|
566
738
|
return false;
|
|
567
739
|
}
|
|
568
740
|
/**
|
|
741
|
+
* 将 structure 中的 bbox 数组转为 Box3。
|
|
742
|
+
* 约定与 `selectByBox` 一致:`[minX, minY, minZ, maxX, maxY, maxZ]`,至少 6 个数。
|
|
743
|
+
*/
|
|
744
|
+
function bboxArrayToBox3(bbox) {
|
|
745
|
+
if (!bbox || bbox.length < 6) return null;
|
|
746
|
+
const box = new Box3();
|
|
747
|
+
box.min.set(bbox[0], bbox[1], bbox[2]);
|
|
748
|
+
box.max.set(bbox[3], bbox[4], bbox[5]);
|
|
749
|
+
return box;
|
|
750
|
+
}
|
|
751
|
+
/**
|
|
569
752
|
* 从 OID 节点映射中按 Box3 范围筛选构件
|
|
570
753
|
*/
|
|
571
754
|
function selectByBoxFromOidMap(oidNodeMap, box) {
|
|
572
755
|
const result = [];
|
|
573
|
-
const nodeBox = new Box3();
|
|
574
756
|
for (const [oid, node] of oidNodeMap) {
|
|
575
|
-
|
|
576
|
-
nodeBox
|
|
577
|
-
nodeBox.max.set(node.bbox[3], node.bbox[4], node.bbox[5]);
|
|
757
|
+
const nodeBox = bboxArrayToBox3(node.bbox);
|
|
758
|
+
if (!nodeBox) continue;
|
|
578
759
|
if (box.intersectsBox(nodeBox)) result.push(oid);
|
|
579
760
|
}
|
|
580
761
|
return result;
|
|
@@ -619,7 +800,394 @@ function selectByPolygonFromOidMap(oidNodeMap, polygon, axis = "xz") {
|
|
|
619
800
|
return result;
|
|
620
801
|
}
|
|
621
802
|
//#endregion
|
|
622
|
-
//#region
|
|
803
|
+
//#region src/utils/color-input.ts
|
|
804
|
+
function toColor(value) {
|
|
805
|
+
return value instanceof Color ? value : new Color(value);
|
|
806
|
+
}
|
|
807
|
+
//#endregion
|
|
808
|
+
//#region node_modules/.pnpm/fflate@0.8.2/node_modules/fflate/esm/browser.js
|
|
809
|
+
var u8 = Uint8Array, u16 = Uint16Array, i32 = Int32Array;
|
|
810
|
+
var fleb = new u8([
|
|
811
|
+
0,
|
|
812
|
+
0,
|
|
813
|
+
0,
|
|
814
|
+
0,
|
|
815
|
+
0,
|
|
816
|
+
0,
|
|
817
|
+
0,
|
|
818
|
+
0,
|
|
819
|
+
1,
|
|
820
|
+
1,
|
|
821
|
+
1,
|
|
822
|
+
1,
|
|
823
|
+
2,
|
|
824
|
+
2,
|
|
825
|
+
2,
|
|
826
|
+
2,
|
|
827
|
+
3,
|
|
828
|
+
3,
|
|
829
|
+
3,
|
|
830
|
+
3,
|
|
831
|
+
4,
|
|
832
|
+
4,
|
|
833
|
+
4,
|
|
834
|
+
4,
|
|
835
|
+
5,
|
|
836
|
+
5,
|
|
837
|
+
5,
|
|
838
|
+
5,
|
|
839
|
+
0,
|
|
840
|
+
0,
|
|
841
|
+
0,
|
|
842
|
+
0
|
|
843
|
+
]);
|
|
844
|
+
var fdeb = new u8([
|
|
845
|
+
0,
|
|
846
|
+
0,
|
|
847
|
+
0,
|
|
848
|
+
0,
|
|
849
|
+
1,
|
|
850
|
+
1,
|
|
851
|
+
2,
|
|
852
|
+
2,
|
|
853
|
+
3,
|
|
854
|
+
3,
|
|
855
|
+
4,
|
|
856
|
+
4,
|
|
857
|
+
5,
|
|
858
|
+
5,
|
|
859
|
+
6,
|
|
860
|
+
6,
|
|
861
|
+
7,
|
|
862
|
+
7,
|
|
863
|
+
8,
|
|
864
|
+
8,
|
|
865
|
+
9,
|
|
866
|
+
9,
|
|
867
|
+
10,
|
|
868
|
+
10,
|
|
869
|
+
11,
|
|
870
|
+
11,
|
|
871
|
+
12,
|
|
872
|
+
12,
|
|
873
|
+
13,
|
|
874
|
+
13,
|
|
875
|
+
0,
|
|
876
|
+
0
|
|
877
|
+
]);
|
|
878
|
+
var clim = new u8([
|
|
879
|
+
16,
|
|
880
|
+
17,
|
|
881
|
+
18,
|
|
882
|
+
0,
|
|
883
|
+
8,
|
|
884
|
+
7,
|
|
885
|
+
9,
|
|
886
|
+
6,
|
|
887
|
+
10,
|
|
888
|
+
5,
|
|
889
|
+
11,
|
|
890
|
+
4,
|
|
891
|
+
12,
|
|
892
|
+
3,
|
|
893
|
+
13,
|
|
894
|
+
2,
|
|
895
|
+
14,
|
|
896
|
+
1,
|
|
897
|
+
15
|
|
898
|
+
]);
|
|
899
|
+
var freb = function(eb, start) {
|
|
900
|
+
var b = new u16(31);
|
|
901
|
+
for (var i = 0; i < 31; ++i) b[i] = start += 1 << eb[i - 1];
|
|
902
|
+
var r = new i32(b[30]);
|
|
903
|
+
for (var i = 1; i < 30; ++i) for (var j = b[i]; j < b[i + 1]; ++j) r[j] = j - b[i] << 5 | i;
|
|
904
|
+
return {
|
|
905
|
+
b,
|
|
906
|
+
r
|
|
907
|
+
};
|
|
908
|
+
};
|
|
909
|
+
var _a = freb(fleb, 2), fl = _a.b, revfl = _a.r;
|
|
910
|
+
fl[28] = 258, revfl[258] = 28;
|
|
911
|
+
var fd = freb(fdeb, 0).b;
|
|
912
|
+
var rev = new u16(32768);
|
|
913
|
+
for (var i = 0; i < 32768; ++i) {
|
|
914
|
+
var x = (i & 43690) >> 1 | (i & 21845) << 1;
|
|
915
|
+
x = (x & 52428) >> 2 | (x & 13107) << 2;
|
|
916
|
+
x = (x & 61680) >> 4 | (x & 3855) << 4;
|
|
917
|
+
rev[i] = ((x & 65280) >> 8 | (x & 255) << 8) >> 1;
|
|
918
|
+
}
|
|
919
|
+
var hMap = (function(cd, mb, r) {
|
|
920
|
+
var s = cd.length;
|
|
921
|
+
var i = 0;
|
|
922
|
+
var l = new u16(mb);
|
|
923
|
+
for (; i < s; ++i) if (cd[i]) ++l[cd[i] - 1];
|
|
924
|
+
var le = new u16(mb);
|
|
925
|
+
for (i = 1; i < mb; ++i) le[i] = le[i - 1] + l[i - 1] << 1;
|
|
926
|
+
var co;
|
|
927
|
+
if (r) {
|
|
928
|
+
co = new u16(1 << mb);
|
|
929
|
+
var rvb = 15 - mb;
|
|
930
|
+
for (i = 0; i < s; ++i) if (cd[i]) {
|
|
931
|
+
var sv = i << 4 | cd[i];
|
|
932
|
+
var r_1 = mb - cd[i];
|
|
933
|
+
var v = le[cd[i] - 1]++ << r_1;
|
|
934
|
+
for (var m = v | (1 << r_1) - 1; v <= m; ++v) co[rev[v] >> rvb] = sv;
|
|
935
|
+
}
|
|
936
|
+
} else {
|
|
937
|
+
co = new u16(s);
|
|
938
|
+
for (i = 0; i < s; ++i) if (cd[i]) co[i] = rev[le[cd[i] - 1]++] >> 15 - cd[i];
|
|
939
|
+
}
|
|
940
|
+
return co;
|
|
941
|
+
});
|
|
942
|
+
var flt = new u8(288);
|
|
943
|
+
for (var i = 0; i < 144; ++i) flt[i] = 8;
|
|
944
|
+
for (var i = 144; i < 256; ++i) flt[i] = 9;
|
|
945
|
+
for (var i = 256; i < 280; ++i) flt[i] = 7;
|
|
946
|
+
for (var i = 280; i < 288; ++i) flt[i] = 8;
|
|
947
|
+
var fdt = new u8(32);
|
|
948
|
+
for (var i = 0; i < 32; ++i) fdt[i] = 5;
|
|
949
|
+
var flrm = /* @__PURE__ */ hMap(flt, 9, 1), fdrm = /* @__PURE__ */ hMap(fdt, 5, 1);
|
|
950
|
+
var max = function(a) {
|
|
951
|
+
var m = a[0];
|
|
952
|
+
for (var i = 1; i < a.length; ++i) if (a[i] > m) m = a[i];
|
|
953
|
+
return m;
|
|
954
|
+
};
|
|
955
|
+
var bits = function(d, p, m) {
|
|
956
|
+
var o = p / 8 | 0;
|
|
957
|
+
return (d[o] | d[o + 1] << 8) >> (p & 7) & m;
|
|
958
|
+
};
|
|
959
|
+
var bits16 = function(d, p) {
|
|
960
|
+
var o = p / 8 | 0;
|
|
961
|
+
return (d[o] | d[o + 1] << 8 | d[o + 2] << 16) >> (p & 7);
|
|
962
|
+
};
|
|
963
|
+
var shft = function(p) {
|
|
964
|
+
return (p + 7) / 8 | 0;
|
|
965
|
+
};
|
|
966
|
+
var slc = function(v, s, e) {
|
|
967
|
+
if (s == null || s < 0) s = 0;
|
|
968
|
+
if (e == null || e > v.length) e = v.length;
|
|
969
|
+
return new u8(v.subarray(s, e));
|
|
970
|
+
};
|
|
971
|
+
var ec = [
|
|
972
|
+
"unexpected EOF",
|
|
973
|
+
"invalid block type",
|
|
974
|
+
"invalid length/literal",
|
|
975
|
+
"invalid distance",
|
|
976
|
+
"stream finished",
|
|
977
|
+
"no stream handler",
|
|
978
|
+
,
|
|
979
|
+
"no callback",
|
|
980
|
+
"invalid UTF-8 data",
|
|
981
|
+
"extra field too long",
|
|
982
|
+
"date not in range 1980-2099",
|
|
983
|
+
"filename too long",
|
|
984
|
+
"stream finishing",
|
|
985
|
+
"invalid zip data"
|
|
986
|
+
];
|
|
987
|
+
var err = function(ind, msg, nt) {
|
|
988
|
+
var e = new Error(msg || ec[ind]);
|
|
989
|
+
e.code = ind;
|
|
990
|
+
if (Error.captureStackTrace) Error.captureStackTrace(e, err);
|
|
991
|
+
if (!nt) throw e;
|
|
992
|
+
return e;
|
|
993
|
+
};
|
|
994
|
+
var inflt = function(dat, st, buf, dict) {
|
|
995
|
+
var sl = dat.length, dl = dict ? dict.length : 0;
|
|
996
|
+
if (!sl || st.f && !st.l) return buf || new u8(0);
|
|
997
|
+
var noBuf = !buf;
|
|
998
|
+
var resize = noBuf || st.i != 2;
|
|
999
|
+
var noSt = st.i;
|
|
1000
|
+
if (noBuf) buf = new u8(sl * 3);
|
|
1001
|
+
var cbuf = function(l) {
|
|
1002
|
+
var bl = buf.length;
|
|
1003
|
+
if (l > bl) {
|
|
1004
|
+
var nbuf = new u8(Math.max(bl * 2, l));
|
|
1005
|
+
nbuf.set(buf);
|
|
1006
|
+
buf = nbuf;
|
|
1007
|
+
}
|
|
1008
|
+
};
|
|
1009
|
+
var final = st.f || 0, pos = st.p || 0, bt = st.b || 0, lm = st.l, dm = st.d, lbt = st.m, dbt = st.n;
|
|
1010
|
+
var tbts = sl * 8;
|
|
1011
|
+
do {
|
|
1012
|
+
if (!lm) {
|
|
1013
|
+
final = bits(dat, pos, 1);
|
|
1014
|
+
var type = bits(dat, pos + 1, 3);
|
|
1015
|
+
pos += 3;
|
|
1016
|
+
if (!type) {
|
|
1017
|
+
var s = shft(pos) + 4, l = dat[s - 4] | dat[s - 3] << 8, t = s + l;
|
|
1018
|
+
if (t > sl) {
|
|
1019
|
+
if (noSt) err(0);
|
|
1020
|
+
break;
|
|
1021
|
+
}
|
|
1022
|
+
if (resize) cbuf(bt + l);
|
|
1023
|
+
buf.set(dat.subarray(s, t), bt);
|
|
1024
|
+
st.b = bt += l, st.p = pos = t * 8, st.f = final;
|
|
1025
|
+
continue;
|
|
1026
|
+
} else if (type == 1) lm = flrm, dm = fdrm, lbt = 9, dbt = 5;
|
|
1027
|
+
else if (type == 2) {
|
|
1028
|
+
var hLit = bits(dat, pos, 31) + 257, hcLen = bits(dat, pos + 10, 15) + 4;
|
|
1029
|
+
var tl = hLit + bits(dat, pos + 5, 31) + 1;
|
|
1030
|
+
pos += 14;
|
|
1031
|
+
var ldt = new u8(tl);
|
|
1032
|
+
var clt = new u8(19);
|
|
1033
|
+
for (var i = 0; i < hcLen; ++i) clt[clim[i]] = bits(dat, pos + i * 3, 7);
|
|
1034
|
+
pos += hcLen * 3;
|
|
1035
|
+
var clb = max(clt), clbmsk = (1 << clb) - 1;
|
|
1036
|
+
var clm = hMap(clt, clb, 1);
|
|
1037
|
+
for (var i = 0; i < tl;) {
|
|
1038
|
+
var r = clm[bits(dat, pos, clbmsk)];
|
|
1039
|
+
pos += r & 15;
|
|
1040
|
+
var s = r >> 4;
|
|
1041
|
+
if (s < 16) ldt[i++] = s;
|
|
1042
|
+
else {
|
|
1043
|
+
var c = 0, n = 0;
|
|
1044
|
+
if (s == 16) n = 3 + bits(dat, pos, 3), pos += 2, c = ldt[i - 1];
|
|
1045
|
+
else if (s == 17) n = 3 + bits(dat, pos, 7), pos += 3;
|
|
1046
|
+
else if (s == 18) n = 11 + bits(dat, pos, 127), pos += 7;
|
|
1047
|
+
while (n--) ldt[i++] = c;
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
var lt = ldt.subarray(0, hLit), dt = ldt.subarray(hLit);
|
|
1051
|
+
lbt = max(lt);
|
|
1052
|
+
dbt = max(dt);
|
|
1053
|
+
lm = hMap(lt, lbt, 1);
|
|
1054
|
+
dm = hMap(dt, dbt, 1);
|
|
1055
|
+
} else err(1);
|
|
1056
|
+
if (pos > tbts) {
|
|
1057
|
+
if (noSt) err(0);
|
|
1058
|
+
break;
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
1061
|
+
if (resize) cbuf(bt + 131072);
|
|
1062
|
+
var lms = (1 << lbt) - 1, dms = (1 << dbt) - 1;
|
|
1063
|
+
var lpos = pos;
|
|
1064
|
+
for (;; lpos = pos) {
|
|
1065
|
+
var c = lm[bits16(dat, pos) & lms], sym = c >> 4;
|
|
1066
|
+
pos += c & 15;
|
|
1067
|
+
if (pos > tbts) {
|
|
1068
|
+
if (noSt) err(0);
|
|
1069
|
+
break;
|
|
1070
|
+
}
|
|
1071
|
+
if (!c) err(2);
|
|
1072
|
+
if (sym < 256) buf[bt++] = sym;
|
|
1073
|
+
else if (sym == 256) {
|
|
1074
|
+
lpos = pos, lm = null;
|
|
1075
|
+
break;
|
|
1076
|
+
} else {
|
|
1077
|
+
var add = sym - 254;
|
|
1078
|
+
if (sym > 264) {
|
|
1079
|
+
var i = sym - 257, b = fleb[i];
|
|
1080
|
+
add = bits(dat, pos, (1 << b) - 1) + fl[i];
|
|
1081
|
+
pos += b;
|
|
1082
|
+
}
|
|
1083
|
+
var d = dm[bits16(dat, pos) & dms], dsym = d >> 4;
|
|
1084
|
+
if (!d) err(3);
|
|
1085
|
+
pos += d & 15;
|
|
1086
|
+
var dt = fd[dsym];
|
|
1087
|
+
if (dsym > 3) {
|
|
1088
|
+
var b = fdeb[dsym];
|
|
1089
|
+
dt += bits16(dat, pos) & (1 << b) - 1, pos += b;
|
|
1090
|
+
}
|
|
1091
|
+
if (pos > tbts) {
|
|
1092
|
+
if (noSt) err(0);
|
|
1093
|
+
break;
|
|
1094
|
+
}
|
|
1095
|
+
if (resize) cbuf(bt + 131072);
|
|
1096
|
+
var end = bt + add;
|
|
1097
|
+
if (bt < dt) {
|
|
1098
|
+
var shift = dl - dt, dend = Math.min(dt, end);
|
|
1099
|
+
if (shift + bt < 0) err(3);
|
|
1100
|
+
for (; bt < dend; ++bt) buf[bt] = dict[shift + bt];
|
|
1101
|
+
}
|
|
1102
|
+
for (; bt < end; ++bt) buf[bt] = buf[bt - dt];
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
st.l = lm, st.p = lpos, st.b = bt, st.f = final;
|
|
1106
|
+
if (lm) final = 1, st.m = lbt, st.d = dm, st.n = dbt;
|
|
1107
|
+
} while (!final);
|
|
1108
|
+
return bt != buf.length && noBuf ? slc(buf, 0, bt) : buf.subarray(0, bt);
|
|
1109
|
+
};
|
|
1110
|
+
var et = /* @__PURE__ */ new u8(0);
|
|
1111
|
+
var gzs = function(d) {
|
|
1112
|
+
if (d[0] != 31 || d[1] != 139 || d[2] != 8) err(6, "invalid gzip data");
|
|
1113
|
+
var flg = d[3];
|
|
1114
|
+
var st = 10;
|
|
1115
|
+
if (flg & 4) st += (d[10] | d[11] << 8) + 2;
|
|
1116
|
+
for (var zs = (flg >> 3 & 1) + (flg >> 4 & 1); zs > 0; zs -= !d[st++]);
|
|
1117
|
+
return st + (flg & 2);
|
|
1118
|
+
};
|
|
1119
|
+
var gzl = function(d) {
|
|
1120
|
+
var l = d.length;
|
|
1121
|
+
return (d[l - 4] | d[l - 3] << 8 | d[l - 2] << 16 | d[l - 1] << 24) >>> 0;
|
|
1122
|
+
};
|
|
1123
|
+
/**
|
|
1124
|
+
* Expands GZIP data
|
|
1125
|
+
* @param data The data to decompress
|
|
1126
|
+
* @param opts The decompression options
|
|
1127
|
+
* @returns The decompressed version of the data
|
|
1128
|
+
*/
|
|
1129
|
+
function gunzipSync(data, opts) {
|
|
1130
|
+
var st = gzs(data);
|
|
1131
|
+
if (st + 8 > data.length) err(6, "invalid gzip data");
|
|
1132
|
+
return inflt(data.subarray(st, -8), { i: 2 }, opts && opts.out || new u8(gzl(data)), opts && opts.dictionary);
|
|
1133
|
+
}
|
|
1134
|
+
var td = typeof TextDecoder != "undefined" && /* @__PURE__ */ new TextDecoder();
|
|
1135
|
+
try {
|
|
1136
|
+
td.decode(et, { stream: true });
|
|
1137
|
+
} catch (e) {}
|
|
1138
|
+
//#endregion
|
|
1139
|
+
//#region src/utils/tileset-structure-uri.ts
|
|
1140
|
+
/** 从 tileset 取内嵌 structure 的 data URI(优先 MapTalks:`asset.extras.maptalks.structureUri`) */
|
|
1141
|
+
function getStructureDataUriFromTileset(root) {
|
|
1142
|
+
if (!root) return null;
|
|
1143
|
+
const maptalks = (root.asset?.extras)?.maptalks;
|
|
1144
|
+
if (maptalks && typeof maptalks === "object") {
|
|
1145
|
+
const uri = maptalks.structureUri;
|
|
1146
|
+
if (typeof uri === "string" && uri.trim()) return uri.trim();
|
|
1147
|
+
}
|
|
1148
|
+
const legacy = root.structureUri;
|
|
1149
|
+
if (typeof legacy === "string" && legacy.trim()) return legacy.trim();
|
|
1150
|
+
return null;
|
|
1151
|
+
}
|
|
1152
|
+
function base64ToUint8Array(b64) {
|
|
1153
|
+
const clean = b64.replace(/\s/g, "");
|
|
1154
|
+
if (typeof globalThis.atob === "function") {
|
|
1155
|
+
const bin = globalThis.atob(clean);
|
|
1156
|
+
const out = new Uint8Array(bin.length);
|
|
1157
|
+
for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);
|
|
1158
|
+
return out;
|
|
1159
|
+
}
|
|
1160
|
+
if (typeof Buffer !== "undefined") return new Uint8Array(Buffer.from(clean, "base64"));
|
|
1161
|
+
throw new Error("[tileset-structure-uri] No base64 decoder available");
|
|
1162
|
+
}
|
|
1163
|
+
/**
|
|
1164
|
+
* 同步解析 `data:application/x-gzip;base64,...`:base64 → 二进制 → gunzip → UTF-8 文本。
|
|
1165
|
+
*/
|
|
1166
|
+
function decodeGzipBase64DataUriSync(dataUri) {
|
|
1167
|
+
const comma = dataUri.indexOf(",");
|
|
1168
|
+
if (comma < 0) throw new Error("[tileset-structure-uri] Invalid data URI: missing comma");
|
|
1169
|
+
if (!dataUri.slice(0, comma).toLowerCase().includes("base64")) throw new Error("[tileset-structure-uri] Expected base64 data URI (e.g. data:application/x-gzip;base64,...)");
|
|
1170
|
+
const raw = gunzipSync(base64ToUint8Array(dataUri.slice(comma + 1)));
|
|
1171
|
+
return new TextDecoder("utf-8").decode(raw);
|
|
1172
|
+
}
|
|
1173
|
+
/**
|
|
1174
|
+
* 从已加载的根 tileset 读取内嵌 structure(`asset.extras.maptalks.structureUri`,
|
|
1175
|
+
* 若无则回退根级 `structureUri`),同步解码并解析。
|
|
1176
|
+
* - 无有效 URI 或解析失败时返回 `null`(不抛错)。
|
|
1177
|
+
*/
|
|
1178
|
+
function parseEmbeddedStructureDataFromTilesSync(tiles) {
|
|
1179
|
+
const uri = getStructureDataUriFromTileset(tiles.rootTileset);
|
|
1180
|
+
if (!uri) return null;
|
|
1181
|
+
try {
|
|
1182
|
+
const text = decodeGzipBase64DataUriSync(uri);
|
|
1183
|
+
return JSON.parse(text);
|
|
1184
|
+
} catch (e) {
|
|
1185
|
+
console.warn("[GLTFParserPlugin] Failed to decode tileset structureUri:", e);
|
|
1186
|
+
return null;
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1189
|
+
//#endregion
|
|
1190
|
+
//#region node_modules/.pnpm/3d-tiles-renderer@0.4.23_three@0.183.2/node_modules/3d-tiles-renderer/build/constants-D7SEibTb.js
|
|
623
1191
|
var N = 6378137;
|
|
624
1192
|
//#endregion
|
|
625
1193
|
//#region node_modules/.pnpm/three@0.183.2/node_modules/three/examples/jsm/postprocessing/Pass.js
|
|
@@ -700,22 +1268,22 @@ var FullScreenQuad = class {
|
|
|
700
1268
|
function q(a, e, t) {
|
|
701
1269
|
return a && e in a ? a[e] : t;
|
|
702
1270
|
}
|
|
703
|
-
function
|
|
1271
|
+
function An(a) {
|
|
704
1272
|
return a !== "BOOLEAN" && a !== "STRING" && a !== "ENUM";
|
|
705
1273
|
}
|
|
706
|
-
function
|
|
1274
|
+
function qi(a) {
|
|
707
1275
|
return /^FLOAT/.test(a);
|
|
708
1276
|
}
|
|
709
|
-
function
|
|
1277
|
+
function He(a) {
|
|
710
1278
|
return /^VEC/.test(a);
|
|
711
1279
|
}
|
|
712
|
-
function
|
|
1280
|
+
function qe(a) {
|
|
713
1281
|
return /^MAT/.test(a);
|
|
714
1282
|
}
|
|
715
|
-
function
|
|
716
|
-
return
|
|
1283
|
+
function In(a, e, t, s = null) {
|
|
1284
|
+
return qe(t) || He(t) ? s.fromArray(a, e) : a[e];
|
|
717
1285
|
}
|
|
718
|
-
function
|
|
1286
|
+
function Gt(a) {
|
|
719
1287
|
const { type: e, componentType: t } = a;
|
|
720
1288
|
switch (e) {
|
|
721
1289
|
case "SCALAR": return t === "INT64" ? 0n : 0;
|
|
@@ -730,7 +1298,7 @@ function Vt(a) {
|
|
|
730
1298
|
case "ENUM": return 0;
|
|
731
1299
|
}
|
|
732
1300
|
}
|
|
733
|
-
function
|
|
1301
|
+
function Ts(a, e) {
|
|
734
1302
|
if (e == null) return !1;
|
|
735
1303
|
switch (a) {
|
|
736
1304
|
case "SCALAR": return typeof e == "number" || typeof e == "bigint";
|
|
@@ -746,7 +1314,7 @@ function ys(a, e) {
|
|
|
746
1314
|
}
|
|
747
1315
|
throw new Error("ClassProperty: invalid type.");
|
|
748
1316
|
}
|
|
749
|
-
function
|
|
1317
|
+
function Fe(a, e = null) {
|
|
750
1318
|
switch (a) {
|
|
751
1319
|
case "INT8": return Int8Array;
|
|
752
1320
|
case "INT16": return Int16Array;
|
|
@@ -765,16 +1333,16 @@ function De(a, e = null) {
|
|
|
765
1333
|
}
|
|
766
1334
|
throw new Error("ClassProperty: invalid type.");
|
|
767
1335
|
}
|
|
768
|
-
function
|
|
1336
|
+
function Wi(a, e = null) {
|
|
769
1337
|
if (a.array) {
|
|
770
1338
|
e = e && Array.isArray(e) ? e : [], e.length = a.count;
|
|
771
|
-
for (let s = 0, n = e.length; s < n; s++) e[s] =
|
|
772
|
-
} else e =
|
|
1339
|
+
for (let s = 0, n = e.length; s < n; s++) e[s] = at(a, e[s]);
|
|
1340
|
+
} else e = at(a, e);
|
|
773
1341
|
return e;
|
|
774
1342
|
}
|
|
775
|
-
function
|
|
1343
|
+
function at(a, e = null) {
|
|
776
1344
|
const t = a.default, s = a.type;
|
|
777
|
-
if (e = e ||
|
|
1345
|
+
if (e = e || Gt(a), t === null) {
|
|
778
1346
|
switch (s) {
|
|
779
1347
|
case "SCALAR": return 0;
|
|
780
1348
|
case "VEC2": return e.set(0, 0);
|
|
@@ -788,31 +1356,31 @@ function nt(a, e = null) {
|
|
|
788
1356
|
case "ENUM": return "";
|
|
789
1357
|
}
|
|
790
1358
|
throw new Error("ClassProperty: invalid type.");
|
|
791
|
-
} else if (
|
|
792
|
-
else if (
|
|
1359
|
+
} else if (qe(s)) e.fromArray(t);
|
|
1360
|
+
else if (He(s)) e.fromArray(t);
|
|
793
1361
|
else return t;
|
|
794
1362
|
}
|
|
795
|
-
function
|
|
1363
|
+
function ji(a, e) {
|
|
796
1364
|
if (a.noData === null) return e;
|
|
797
1365
|
const t = a.noData, s = a.type;
|
|
798
1366
|
if (Array.isArray(e)) for (let r = 0, o = e.length; r < o; r++) e[r] = n(e[r]);
|
|
799
1367
|
else e = n(e);
|
|
800
1368
|
return e;
|
|
801
1369
|
function n(r) {
|
|
802
|
-
return i(r) && (r =
|
|
1370
|
+
return i(r) && (r = at(a, r)), r;
|
|
803
1371
|
}
|
|
804
1372
|
function i(r) {
|
|
805
|
-
if (
|
|
1373
|
+
if (qe(s)) {
|
|
806
1374
|
const o = r.elements;
|
|
807
1375
|
for (let l = 0, c = t.length; l < c; l++) if (t[l] !== o[l]) return !1;
|
|
808
1376
|
return !0;
|
|
809
|
-
} else if (
|
|
1377
|
+
} else if (He(s)) {
|
|
810
1378
|
for (let o = 0, l = t.length; o < l; o++) if (t[o] !== r.getComponent(o)) return !1;
|
|
811
1379
|
return !0;
|
|
812
1380
|
} else return t === r;
|
|
813
1381
|
}
|
|
814
1382
|
}
|
|
815
|
-
function
|
|
1383
|
+
function Xi(a, e) {
|
|
816
1384
|
switch (a) {
|
|
817
1385
|
case "INT8": return Math.max(e / 127, -1);
|
|
818
1386
|
case "INT16": return Math.max(e, 32767, -1);
|
|
@@ -824,13 +1392,13 @@ function Gi(a, e) {
|
|
|
824
1392
|
case "UINT64": return Number(e) / 0x10000000000000000;
|
|
825
1393
|
}
|
|
826
1394
|
}
|
|
827
|
-
function
|
|
1395
|
+
function Yi(a, e) {
|
|
828
1396
|
const { type: t, componentType: s, scale: n, offset: i, normalized: r } = a;
|
|
829
1397
|
if (Array.isArray(e)) for (let h = 0, d = e.length; h < d; h++) e[h] = o(e[h]);
|
|
830
1398
|
else e = o(e);
|
|
831
1399
|
return e;
|
|
832
1400
|
function o(h) {
|
|
833
|
-
return
|
|
1401
|
+
return qe(t) ? h = c(h) : He(t) ? h = l(h) : h = u(h), h;
|
|
834
1402
|
}
|
|
835
1403
|
function l(h) {
|
|
836
1404
|
return h.x = u(h.x), h.y = u(h.y), "z" in h && (h.z = u(h.z)), "w" in h && (h.w = u(h.w)), h;
|
|
@@ -841,24 +1409,24 @@ function zi(a, e) {
|
|
|
841
1409
|
return h;
|
|
842
1410
|
}
|
|
843
1411
|
function u(h) {
|
|
844
|
-
return r && (h =
|
|
1412
|
+
return r && (h = Xi(s, h)), (r || qi(s)) && (h = h * n + i), h;
|
|
845
1413
|
}
|
|
846
1414
|
}
|
|
847
|
-
function
|
|
1415
|
+
function Zt(a, e, t = null) {
|
|
848
1416
|
if (a.array) {
|
|
849
1417
|
Array.isArray(e) || (e = new Array(a.count || 0)), e.length = t !== null ? t : a.count;
|
|
850
|
-
for (let s = 0, n = e.length; s < n; s++)
|
|
851
|
-
} else
|
|
1418
|
+
for (let s = 0, n = e.length; s < n; s++) Ts(a.type, e[s]) || (e[s] = Gt(a));
|
|
1419
|
+
} else Ts(a.type, e) || (e = Gt(a));
|
|
852
1420
|
return e;
|
|
853
1421
|
}
|
|
854
|
-
function
|
|
1422
|
+
function lt(a, e) {
|
|
855
1423
|
for (const t in e) t in a || delete e[t];
|
|
856
1424
|
for (const t in a) {
|
|
857
1425
|
const s = a[t];
|
|
858
|
-
e[t] =
|
|
1426
|
+
e[t] = Zt(s, e[t]);
|
|
859
1427
|
}
|
|
860
1428
|
}
|
|
861
|
-
function
|
|
1429
|
+
function $i(a) {
|
|
862
1430
|
switch (a) {
|
|
863
1431
|
case "ENUM": return 1;
|
|
864
1432
|
case "SCALAR": return 1;
|
|
@@ -873,21 +1441,21 @@ function Hi(a) {
|
|
|
873
1441
|
default: return -1;
|
|
874
1442
|
}
|
|
875
1443
|
}
|
|
876
|
-
var
|
|
1444
|
+
var mt = class {
|
|
877
1445
|
constructor(e, t, s = null) {
|
|
878
1446
|
this.name = t.name || null, this.description = t.description || null, this.type = t.type, this.componentType = t.componentType || null, this.enumType = t.enumType || null, this.array = t.array || !1, this.count = t.count || 0, this.normalized = t.normalized || !1, this.offset = t.offset || 0, this.scale = q(t, "scale", 1), this.max = q(t, "max", Infinity), this.min = q(t, "min", -Infinity), this.required = t.required || !1, this.noData = q(t, "noData", null), this.default = q(t, "default", null), this.semantic = q(t, "semantic", null), this.enumSet = null, this.accessorProperty = s, s && (this.offset = q(s, "offset", this.offset), this.scale = q(s, "scale", this.scale), this.max = q(s, "max", this.max), this.min = q(s, "min", this.min)), t.type === "ENUM" && (this.enumSet = e[this.enumType], this.componentType === null && (this.componentType = q(this.enumSet, "valueType", "UINT16")));
|
|
879
1447
|
}
|
|
880
1448
|
shapeToProperty(e, t = null) {
|
|
881
|
-
return
|
|
1449
|
+
return Zt(this, e, t);
|
|
882
1450
|
}
|
|
883
1451
|
resolveDefaultElement(e) {
|
|
884
|
-
return
|
|
1452
|
+
return at(this, e);
|
|
885
1453
|
}
|
|
886
1454
|
resolveDefault(e) {
|
|
887
|
-
return
|
|
1455
|
+
return Wi(this, e);
|
|
888
1456
|
}
|
|
889
1457
|
resolveNoData(e) {
|
|
890
|
-
return
|
|
1458
|
+
return ji(this, e);
|
|
891
1459
|
}
|
|
892
1460
|
resolveEnumsToStrings(e) {
|
|
893
1461
|
const t = this.enumSet;
|
|
@@ -900,10 +1468,10 @@ var ht = class {
|
|
|
900
1468
|
}
|
|
901
1469
|
}
|
|
902
1470
|
adjustValueScaleOffset(e) {
|
|
903
|
-
return
|
|
1471
|
+
return An(this.type) ? Yi(this, e) : e;
|
|
904
1472
|
}
|
|
905
1473
|
};
|
|
906
|
-
var
|
|
1474
|
+
var Jt = class {
|
|
907
1475
|
constructor(e, t = {}, s = {}, n = null) {
|
|
908
1476
|
this.definition = e, this.class = t[e.class], this.className = e.class, this.enums = s, this.data = n, this.name = "name" in e ? e.name : null, this.properties = null;
|
|
909
1477
|
}
|
|
@@ -914,24 +1482,24 @@ var Qt = class {
|
|
|
914
1482
|
return !!this.definition.properties[e];
|
|
915
1483
|
}
|
|
916
1484
|
dispose() {}
|
|
917
|
-
_initProperties(e =
|
|
1485
|
+
_initProperties(e = mt) {
|
|
918
1486
|
const t = {};
|
|
919
1487
|
for (const s in this.class.properties) t[s] = new e(this.enums, this.class.properties[s], this.definition.properties[s]);
|
|
920
1488
|
this.properties = t;
|
|
921
1489
|
}
|
|
922
1490
|
};
|
|
923
|
-
var
|
|
1491
|
+
var Qi = class extends mt {
|
|
924
1492
|
constructor(e, t, s = null) {
|
|
925
1493
|
super(e, t, s), this.attribute = (s == null ? void 0 : s.attribute) ?? null;
|
|
926
1494
|
}
|
|
927
1495
|
};
|
|
928
|
-
var
|
|
1496
|
+
var Zi = class extends Jt {
|
|
929
1497
|
constructor(...e) {
|
|
930
|
-
super(...e), this.isPropertyAttributeAccessor = !0, this._initProperties(
|
|
1498
|
+
super(...e), this.isPropertyAttributeAccessor = !0, this._initProperties(Qi);
|
|
931
1499
|
}
|
|
932
1500
|
getData(e, t, s = {}) {
|
|
933
1501
|
const n = this.properties;
|
|
934
|
-
|
|
1502
|
+
lt(n, s);
|
|
935
1503
|
for (const i in n) s[i] = this.getPropertyValue(i, e, t, s[i]);
|
|
936
1504
|
return s;
|
|
937
1505
|
}
|
|
@@ -943,23 +1511,23 @@ var Wi = class extends Qt {
|
|
|
943
1511
|
} else throw new Error("PropertyAttributeAccessor: Requested class property does not exist.");
|
|
944
1512
|
n = i.shapeToProperty(n);
|
|
945
1513
|
const o = s.getAttribute(i.attribute.toLowerCase());
|
|
946
|
-
if (
|
|
1514
|
+
if (qe(r)) {
|
|
947
1515
|
const l = n.elements;
|
|
948
1516
|
for (let c = 0, u = l.length; c < u;) l[c] = o.getComponent(t, c);
|
|
949
|
-
} else if (
|
|
1517
|
+
} else if (He(r)) n.fromBufferAttribute(o, t);
|
|
950
1518
|
else if (r === "SCALAR" || r === "ENUM") n = o.getX(t);
|
|
951
1519
|
else throw new Error("StructuredMetadata.PropertyAttributeAccessor: BOOLEAN and STRING types are not supported by property attributes.");
|
|
952
1520
|
return n = i.adjustValueScaleOffset(n), n = i.resolveEnumsToStrings(n), n = i.resolveNoData(n), n;
|
|
953
1521
|
}
|
|
954
1522
|
};
|
|
955
|
-
var
|
|
1523
|
+
var Ji = class extends mt {
|
|
956
1524
|
constructor(e, t, s = null) {
|
|
957
|
-
super(e, t, s), this.values = (s == null ? void 0 : s.values) ?? null, this.valueLength =
|
|
1525
|
+
super(e, t, s), this.values = (s == null ? void 0 : s.values) ?? null, this.valueLength = $i(this.type), this.arrayOffsets = q(s, "arrayOffsets", null), this.stringOffsets = q(s, "stringOffsets", null), this.arrayOffsetType = q(s, "arrayOffsetType", "UINT32"), this.stringOffsetType = q(s, "stringOffsetType", "UINT32");
|
|
958
1526
|
}
|
|
959
1527
|
getArrayLengthFromId(e, t) {
|
|
960
1528
|
let s = this.count;
|
|
961
1529
|
if (this.arrayOffsets !== null) {
|
|
962
|
-
const { arrayOffsets: n, arrayOffsetType: i } = this, o = new (
|
|
1530
|
+
const { arrayOffsets: n, arrayOffsetType: i } = this, o = new (Fe(i))(e[n]);
|
|
963
1531
|
s = o[t + 1] - o[t];
|
|
964
1532
|
}
|
|
965
1533
|
return s;
|
|
@@ -968,29 +1536,29 @@ var ji = class extends ht {
|
|
|
968
1536
|
let s = t;
|
|
969
1537
|
if (this.arrayOffsets) {
|
|
970
1538
|
const { arrayOffsets: n, arrayOffsetType: i } = this;
|
|
971
|
-
s = new (
|
|
1539
|
+
s = new (Fe(i))(e[n])[s];
|
|
972
1540
|
} else this.array && (s *= this.count);
|
|
973
1541
|
return s;
|
|
974
1542
|
}
|
|
975
1543
|
};
|
|
976
|
-
var
|
|
1544
|
+
var Ki = class extends Jt {
|
|
977
1545
|
constructor(...e) {
|
|
978
|
-
super(...e), this.isPropertyTableAccessor = !0, this.count = this.definition.count, this._initProperties(
|
|
1546
|
+
super(...e), this.isPropertyTableAccessor = !0, this.count = this.definition.count, this._initProperties(Ji);
|
|
979
1547
|
}
|
|
980
1548
|
getData(e, t = {}) {
|
|
981
1549
|
const s = this.properties;
|
|
982
|
-
|
|
1550
|
+
lt(s, t);
|
|
983
1551
|
for (const n in s) t[n] = this.getPropertyValue(n, e, t[n]);
|
|
984
1552
|
return t;
|
|
985
1553
|
}
|
|
986
1554
|
_readValueAtIndex(e, t, s, n = null) {
|
|
987
|
-
const i = this.properties[e], { componentType: r, type: o } = i, l = this.data, c = l[i.values], h = new (
|
|
988
|
-
if (
|
|
1555
|
+
const i = this.properties[e], { componentType: r, type: o } = i, l = this.data, c = l[i.values], h = new (Fe(r, o))(c), d = i.getIndexOffsetFromId(l, t);
|
|
1556
|
+
if (An(o) || o === "ENUM") return In(h, (d + s) * i.valueLength, o, n);
|
|
989
1557
|
if (o === "STRING") {
|
|
990
1558
|
let m = d + s, f = 0;
|
|
991
1559
|
if (i.stringOffsets !== null) {
|
|
992
|
-
const { stringOffsets: g, stringOffsetType: y } = i,
|
|
993
|
-
f =
|
|
1560
|
+
const { stringOffsets: g, stringOffsetType: y } = i, b = new (Fe(y))(l[g]);
|
|
1561
|
+
f = b[m + 1] - b[m], m = b[m];
|
|
994
1562
|
}
|
|
995
1563
|
const p = new Uint8Array(h.buffer, m, f);
|
|
996
1564
|
n = new TextDecoder().decode(p);
|
|
@@ -1012,8 +1580,8 @@ var Yi = class extends Qt {
|
|
|
1012
1580
|
return s = n.adjustValueScaleOffset(s), s = n.resolveEnumsToStrings(s), s = n.resolveNoData(s), s;
|
|
1013
1581
|
}
|
|
1014
1582
|
};
|
|
1015
|
-
var
|
|
1016
|
-
var
|
|
1583
|
+
var Pe = /* @__PURE__ */ new Box2();
|
|
1584
|
+
var bs = class {
|
|
1017
1585
|
constructor() {
|
|
1018
1586
|
this._renderer = new WebGLRenderer(), this._target = new WebGLRenderTarget(1, 1), this._texTarget = new WebGLRenderTarget(), this._quad = new FullScreenQuad(new ShaderMaterial({
|
|
1019
1587
|
blending: CustomBlending,
|
|
@@ -1055,56 +1623,56 @@ var xs = class {
|
|
|
1055
1623
|
}
|
|
1056
1624
|
renderPixelToTarget(e, t, s) {
|
|
1057
1625
|
const { _renderer: n, _target: i } = this;
|
|
1058
|
-
|
|
1626
|
+
Pe.min.copy(t), Pe.max.copy(t), Pe.max.x += 1, Pe.max.y += 1, n.initRenderTarget(i), n.copyTextureToTexture(e, i.texture, Pe, s, 0);
|
|
1059
1627
|
}
|
|
1060
1628
|
};
|
|
1061
|
-
var
|
|
1629
|
+
var de = /* @__PURE__ */ new class {
|
|
1062
1630
|
constructor() {
|
|
1063
1631
|
let a = null;
|
|
1064
|
-
Object.getOwnPropertyNames(
|
|
1065
|
-
e !== "constructor" && (this[e] = (...t) => (a = a || new
|
|
1632
|
+
Object.getOwnPropertyNames(bs.prototype).forEach((e) => {
|
|
1633
|
+
e !== "constructor" && (this[e] = (...t) => (a = a || new bs(), a[e](...t)));
|
|
1066
1634
|
});
|
|
1067
1635
|
}
|
|
1068
|
-
}(),
|
|
1069
|
-
function
|
|
1636
|
+
}(), _s = /* @__PURE__ */ new Vector2(), Ss = /* @__PURE__ */ new Vector2(), Ms = /* @__PURE__ */ new Vector2();
|
|
1637
|
+
function er(a, e) {
|
|
1070
1638
|
return e === 0 ? a.getAttribute("uv") : a.getAttribute(`uv${e}`);
|
|
1071
1639
|
}
|
|
1072
|
-
function
|
|
1640
|
+
function vn(a, e, t = new Array(3)) {
|
|
1073
1641
|
let s = 3 * e, n = 3 * e + 1, i = 3 * e + 2;
|
|
1074
1642
|
return a.index && (s = a.index.getX(s), n = a.index.getX(n), i = a.index.getX(i)), t[0] = s, t[1] = n, t[2] = i, t;
|
|
1075
1643
|
}
|
|
1076
|
-
function
|
|
1077
|
-
const [i, r, o] = s, l =
|
|
1078
|
-
|
|
1644
|
+
function Ln(a, e, t, s, n) {
|
|
1645
|
+
const [i, r, o] = s, l = er(a, e);
|
|
1646
|
+
_s.fromBufferAttribute(l, i), Ss.fromBufferAttribute(l, r), Ms.fromBufferAttribute(l, o), n.set(0, 0, 0).addScaledVector(_s, t.x).addScaledVector(Ss, t.y).addScaledVector(Ms, t.z);
|
|
1079
1647
|
}
|
|
1080
|
-
function
|
|
1648
|
+
function En(a, e, t, s) {
|
|
1081
1649
|
const n = a.x - Math.floor(a.x), i = a.y - Math.floor(a.y), r = Math.floor(n * e % e), o = Math.floor(i * t % t);
|
|
1082
1650
|
return s.set(r, o), s;
|
|
1083
1651
|
}
|
|
1084
|
-
var
|
|
1085
|
-
var
|
|
1652
|
+
var Cs = /* @__PURE__ */ new Vector2(), As = /* @__PURE__ */ new Vector2(), Is = /* @__PURE__ */ new Vector2();
|
|
1653
|
+
var tr = class extends mt {
|
|
1086
1654
|
constructor(e, t, s = null) {
|
|
1087
1655
|
super(e, t, s), this.channels = q(s, "channels", [0]), this.index = q(s, "index", null), this.texCoord = q(s, "texCoord", null), this.valueLength = parseInt(this.type.replace(/[^0-9]/g, "")) || 1;
|
|
1088
1656
|
}
|
|
1089
1657
|
readDataFromBuffer(e, t, s = null) {
|
|
1090
1658
|
const n = this.type;
|
|
1091
1659
|
if (n === "BOOLEAN" || n === "STRING") throw new Error("PropertyTextureAccessor: BOOLEAN and STRING types not supported.");
|
|
1092
|
-
return
|
|
1660
|
+
return In(e, t * this.valueLength, n, s);
|
|
1093
1661
|
}
|
|
1094
1662
|
};
|
|
1095
|
-
var
|
|
1663
|
+
var sr = class extends Jt {
|
|
1096
1664
|
constructor(...e) {
|
|
1097
|
-
super(...e), this.isPropertyTextureAccessor = !0, this._asyncRead = !1, this._initProperties(
|
|
1665
|
+
super(...e), this.isPropertyTextureAccessor = !0, this._asyncRead = !1, this._initProperties(tr);
|
|
1098
1666
|
}
|
|
1099
1667
|
getData(e, t, s, n = {}) {
|
|
1100
1668
|
const i = this.properties;
|
|
1101
|
-
|
|
1669
|
+
lt(i, n);
|
|
1102
1670
|
const r = Object.keys(i), o = r.map((l) => n[l]);
|
|
1103
1671
|
return this.getPropertyValuesAtTexel(r, e, t, s, o), r.forEach((l, c) => n[l] = o[c]), n;
|
|
1104
1672
|
}
|
|
1105
1673
|
async getDataAsync(e, t, s, n = {}) {
|
|
1106
1674
|
const i = this.properties;
|
|
1107
|
-
|
|
1675
|
+
lt(i, n);
|
|
1108
1676
|
const r = Object.keys(i), o = r.map((l) => n[l]);
|
|
1109
1677
|
return await this.getPropertyValuesAtTexelAsync(r, e, t, s, o), r.forEach((l, c) => n[l] = o[c]), n;
|
|
1110
1678
|
}
|
|
@@ -1115,30 +1683,30 @@ var Qi = class extends Qt {
|
|
|
1115
1683
|
}
|
|
1116
1684
|
getPropertyValuesAtTexel(e, t, s, n, i = []) {
|
|
1117
1685
|
for (; i.length < e.length;) i.push(null);
|
|
1118
|
-
i.length = e.length,
|
|
1119
|
-
const r = this.data, o = this.definition.properties, l = this.properties, c =
|
|
1686
|
+
i.length = e.length, de.increaseSizeTo(i.length);
|
|
1687
|
+
const r = this.data, o = this.definition.properties, l = this.properties, c = vn(n, t);
|
|
1120
1688
|
for (let d = 0, m = e.length; d < m; d++) {
|
|
1121
1689
|
const f = e[d];
|
|
1122
1690
|
if (!o[f]) continue;
|
|
1123
1691
|
const p = l[f], g = r[p.index];
|
|
1124
|
-
|
|
1692
|
+
Ln(n, p.texCoord, s, c, Cs), En(Cs, g.image.width, g.image.height, As), Is.set(d, 0), de.renderPixelToTarget(g, As, Is);
|
|
1125
1693
|
}
|
|
1126
1694
|
const u = new Uint8Array(e.length * 4);
|
|
1127
|
-
if (this._asyncRead) return
|
|
1128
|
-
return
|
|
1695
|
+
if (this._asyncRead) return de.readDataAsync(u).then(() => (h.call(this), i));
|
|
1696
|
+
return de.readData(u), h.call(this), i;
|
|
1129
1697
|
function h() {
|
|
1130
1698
|
for (let d = 0, m = e.length; d < m; d++) {
|
|
1131
1699
|
const f = e[d], p = l[f], g = p.type;
|
|
1132
|
-
if (i[d] =
|
|
1700
|
+
if (i[d] = Zt(p, i[d]), p) {
|
|
1133
1701
|
if (!o[f]) {
|
|
1134
1702
|
i[d] = p.resolveDefault(i);
|
|
1135
1703
|
continue;
|
|
1136
1704
|
}
|
|
1137
1705
|
} else throw new Error("PropertyTextureAccessor: Requested property does not exist.");
|
|
1138
|
-
const y = p.valueLength * (p.count || 1), x = p.channels.map((
|
|
1706
|
+
const y = p.valueLength * (p.count || 1), x = p.channels.map((S) => u[4 * d + S]), b = p.componentType, M = new (Fe(b, g))(y);
|
|
1139
1707
|
if (new Uint8Array(M.buffer).set(x), p.array) {
|
|
1140
|
-
const
|
|
1141
|
-
for (let C = 0, v =
|
|
1708
|
+
const S = i[d];
|
|
1709
|
+
for (let C = 0, v = S.length; C < v; C++) S[C] = p.readDataFromBuffer(M, C, S[C]);
|
|
1142
1710
|
} else i[d] = p.readDataFromBuffer(M, 0, i[d]);
|
|
1143
1711
|
i[d] = p.adjustValueScaleOffset(i[d]), i[d] = p.resolveEnumsToStrings(i[d]), i[d] = p.resolveNoData(i[d]);
|
|
1144
1712
|
}
|
|
@@ -1150,25 +1718,37 @@ var Qi = class extends Qt {
|
|
|
1150
1718
|
});
|
|
1151
1719
|
}
|
|
1152
1720
|
};
|
|
1153
|
-
var
|
|
1721
|
+
var vs = class {
|
|
1154
1722
|
constructor(e, t, s, n = null, i = null) {
|
|
1155
|
-
const { schema: r, propertyTables: o = [], propertyTextures: l = [], propertyAttributes: c = [] } = e, { enums: u, classes: h } = r, d = o.map((p) => new
|
|
1723
|
+
const { schema: r, propertyTables: o = [], propertyTextures: l = [], propertyAttributes: c = [] } = e, { enums: u, classes: h } = r, d = o.map((p) => new Ki(p, h, u, s));
|
|
1156
1724
|
let m = [], f = [];
|
|
1157
|
-
n && (n.propertyTextures && (m = n.propertyTextures.map((p) => new
|
|
1725
|
+
n && (n.propertyTextures && (m = n.propertyTextures.map((p) => new sr(l[p], h, u, t))), n.propertyAttributes && (f = n.propertyAttributes.map((p) => new Zi(c[p], h, u)))), this.schema = r, this.tableAccessors = d, this.textureAccessors = m, this.attributeAccessors = f, this.object = i, this.textures = t, this.nodeMetadata = n;
|
|
1158
1726
|
}
|
|
1727
|
+
/**
|
|
1728
|
+
* Returns data from one or more property tables. Pass a single table index and row ID to
|
|
1729
|
+
* get one object, or parallel arrays of table indices and row IDs to get an array of
|
|
1730
|
+
* results. Each returned object conforms to the structure class referenced in the schema.
|
|
1731
|
+
* @param {number|Array<number>} tableIndices Table index or array of table indices.
|
|
1732
|
+
* @param {number|Array<number>} ids Row ID or array of row IDs.
|
|
1733
|
+
* @param {Object|Array|null} [target=null] Optional target object or array to write into.
|
|
1734
|
+
* @returns {Object|Array}
|
|
1735
|
+
*/
|
|
1159
1736
|
getPropertyTableData(e, t, s = null) {
|
|
1160
1737
|
if (!Array.isArray(e) || !Array.isArray(t)) s = s || {}, s = this.tableAccessors[e].getData(t, s);
|
|
1161
1738
|
else {
|
|
1162
1739
|
s = s || [];
|
|
1163
1740
|
const n = Math.min(e.length, t.length);
|
|
1164
1741
|
s.length = n;
|
|
1165
|
-
for (let i = 0; i < n; i++)
|
|
1166
|
-
const r = this.tableAccessors[e[i]];
|
|
1167
|
-
s[i] = r.getData(t[i], s[i]);
|
|
1168
|
-
}
|
|
1742
|
+
for (let i = 0; i < n; i++) s[i] = this.tableAccessors[e[i]].getData(t[i], s[i]);
|
|
1169
1743
|
}
|
|
1170
1744
|
return s;
|
|
1171
1745
|
}
|
|
1746
|
+
/**
|
|
1747
|
+
* Returns name and class information for one or more property tables. Defaults to all
|
|
1748
|
+
* tables when `tableIndices` is `null`.
|
|
1749
|
+
* @param {Array<number>|null} [tableIndices=null]
|
|
1750
|
+
* @returns {Array<{name: string, className: string}>|{name: string, className: string}}
|
|
1751
|
+
*/
|
|
1172
1752
|
getPropertyTableInfo(e = null) {
|
|
1173
1753
|
if (e === null && (e = this.tableAccessors.map((t, s) => s)), Array.isArray(e)) return e.map((t) => {
|
|
1174
1754
|
const s = this.tableAccessors[t];
|
|
@@ -1185,12 +1765,29 @@ var As = class {
|
|
|
1185
1765
|
};
|
|
1186
1766
|
}
|
|
1187
1767
|
}
|
|
1768
|
+
/**
|
|
1769
|
+
* Returns data from property textures at the given point on the mesh. Takes the triangle
|
|
1770
|
+
* index and barycentric coordinate from a raycast result. See `MeshFeatures.getFeatures`
|
|
1771
|
+
* for how to obtain these values.
|
|
1772
|
+
* @param {number} triangle Triangle index from a raycast hit.
|
|
1773
|
+
* @param {Vector3} barycoord Barycentric coordinate of the hit point.
|
|
1774
|
+
* @param {Array} [target=[]] Optional target array to write into.
|
|
1775
|
+
* @returns {Array}
|
|
1776
|
+
*/
|
|
1188
1777
|
getPropertyTextureData(e, t, s = []) {
|
|
1189
1778
|
const n = this.textureAccessors;
|
|
1190
1779
|
s.length = n.length;
|
|
1191
1780
|
for (let i = 0; i < n.length; i++) s[i] = n[i].getData(e, t, this.object.geometry, s[i]);
|
|
1192
1781
|
return s;
|
|
1193
1782
|
}
|
|
1783
|
+
/**
|
|
1784
|
+
* Returns the same data as `getPropertyTextureData` but performs texture reads
|
|
1785
|
+
* asynchronously.
|
|
1786
|
+
* @param {number} triangle Triangle index from a raycast hit.
|
|
1787
|
+
* @param {Vector3} barycoord Barycentric coordinate of the hit point.
|
|
1788
|
+
* @param {Array} [target=[]] Optional target array to write into.
|
|
1789
|
+
* @returns {Promise<Array>}
|
|
1790
|
+
*/
|
|
1194
1791
|
async getPropertyTextureDataAsync(e, t, s = []) {
|
|
1195
1792
|
const n = this.textureAccessors;
|
|
1196
1793
|
s.length = n.length;
|
|
@@ -1203,30 +1800,48 @@ var As = class {
|
|
|
1203
1800
|
}
|
|
1204
1801
|
return await Promise.all(i), s;
|
|
1205
1802
|
}
|
|
1803
|
+
/**
|
|
1804
|
+
* Returns information about the property texture accessors, including their class names
|
|
1805
|
+
* and per-property channel/texcoord mappings.
|
|
1806
|
+
* @returns {Array<{name: string, className: string, properties: Object}>}
|
|
1807
|
+
*/
|
|
1206
1808
|
getPropertyTextureInfo() {
|
|
1207
1809
|
return this.textureAccessors;
|
|
1208
1810
|
}
|
|
1811
|
+
/**
|
|
1812
|
+
* Returns data stored as property attributes for the given vertex index.
|
|
1813
|
+
* @param {number} attributeIndex Vertex index.
|
|
1814
|
+
* @param {Array} [target=[]] Optional target array to write into.
|
|
1815
|
+
* @returns {Array}
|
|
1816
|
+
*/
|
|
1209
1817
|
getPropertyAttributeData(e, t = []) {
|
|
1210
1818
|
const s = this.attributeAccessors;
|
|
1211
1819
|
t.length = s.length;
|
|
1212
1820
|
for (let n = 0; n < s.length; n++) t[n] = s[n].getData(e, this.object.geometry, t[n]);
|
|
1213
1821
|
return t;
|
|
1214
1822
|
}
|
|
1823
|
+
/**
|
|
1824
|
+
* Returns name and class information for all property attribute accessors.
|
|
1825
|
+
* @returns {Array<{name: string, className: string}>}
|
|
1826
|
+
*/
|
|
1215
1827
|
getPropertyAttributeInfo() {
|
|
1216
1828
|
return this.attributeAccessors.map((e) => ({
|
|
1217
1829
|
name: e.name,
|
|
1218
1830
|
className: e.definition.class
|
|
1219
1831
|
}));
|
|
1220
1832
|
}
|
|
1833
|
+
/**
|
|
1834
|
+
* Disposes all texture, table, and attribute accessors.
|
|
1835
|
+
*/
|
|
1221
1836
|
dispose() {
|
|
1222
1837
|
this.textureAccessors.forEach((e) => e.dispose()), this.tableAccessors.forEach((e) => e.dispose()), this.attributeAccessors.forEach((e) => e.dispose());
|
|
1223
1838
|
}
|
|
1224
1839
|
};
|
|
1225
|
-
var
|
|
1226
|
-
function
|
|
1840
|
+
var Ls = /* @__PURE__ */ new Vector2(), Es = /* @__PURE__ */ new Vector2(), ws = /* @__PURE__ */ new Vector2();
|
|
1841
|
+
function or(a) {
|
|
1227
1842
|
return a.x > a.y && a.x > a.z ? 0 : a.y > a.z ? 1 : 2;
|
|
1228
1843
|
}
|
|
1229
|
-
var
|
|
1844
|
+
var ar = class {
|
|
1230
1845
|
constructor(e, t, s) {
|
|
1231
1846
|
this.geometry = e, this.textures = t, this.data = s, this._asyncRead = !1, this.featureIds = s.featureIds.map((n) => {
|
|
1232
1847
|
const { texture: i, ...r } = n, o = {
|
|
@@ -1242,26 +1857,48 @@ var tr = class {
|
|
|
1242
1857
|
}), o;
|
|
1243
1858
|
});
|
|
1244
1859
|
}
|
|
1860
|
+
/**
|
|
1861
|
+
* Returns an indexed list of all textures used by features in the extension.
|
|
1862
|
+
* @returns {Array<Texture>}
|
|
1863
|
+
*/
|
|
1245
1864
|
getTextures() {
|
|
1246
1865
|
return this.textures;
|
|
1247
1866
|
}
|
|
1867
|
+
/**
|
|
1868
|
+
* Returns the feature ID info for each feature set defined on this primitive.
|
|
1869
|
+
* @returns {Array<FeatureInfo>}
|
|
1870
|
+
*/
|
|
1248
1871
|
getFeatureInfo() {
|
|
1249
1872
|
return this.featureIds;
|
|
1250
1873
|
}
|
|
1874
|
+
/**
|
|
1875
|
+
* Performs the same function as `getFeatures` but reads texture data asynchronously.
|
|
1876
|
+
* @param {number} triangle Triangle index from a raycast hit.
|
|
1877
|
+
* @param {Vector3} barycoord Barycentric coordinate of the hit point.
|
|
1878
|
+
* @returns {Promise<Array<number|null>>}
|
|
1879
|
+
*/
|
|
1251
1880
|
getFeaturesAsync(...e) {
|
|
1252
1881
|
this._asyncRead = !0;
|
|
1253
1882
|
const t = this.getFeatures(...e);
|
|
1254
1883
|
return this._asyncRead = !1, t;
|
|
1255
1884
|
}
|
|
1885
|
+
/**
|
|
1886
|
+
* Returns the list of feature IDs at the given point on the mesh. Takes the triangle
|
|
1887
|
+
* index from a raycast result and a barycentric coordinate. Results are indexed in the
|
|
1888
|
+
* same order as the feature info returned by `getFeatureInfo()`.
|
|
1889
|
+
* @param {number} triangle Triangle index from a raycast hit.
|
|
1890
|
+
* @param {Vector3} barycoord Barycentric coordinate of the hit point.
|
|
1891
|
+
* @returns {Array<number|null>}
|
|
1892
|
+
*/
|
|
1256
1893
|
getFeatures(e, t) {
|
|
1257
1894
|
const { geometry: s, textures: n, featureIds: i } = this, r = new Array(i.length).fill(null), o = i.length;
|
|
1258
|
-
|
|
1259
|
-
const l =
|
|
1895
|
+
de.increaseSizeTo(o);
|
|
1896
|
+
const l = vn(s, e), c = l[or(t)];
|
|
1260
1897
|
for (let d = 0, m = i.length; d < m; d++) {
|
|
1261
1898
|
const f = i[d], p = "nullFeatureId" in f ? f.nullFeatureId : null;
|
|
1262
1899
|
if ("texture" in f) {
|
|
1263
1900
|
const g = n[f.texture.index];
|
|
1264
|
-
|
|
1901
|
+
Ln(s, f.texture.texCoord, t, l, Ls), En(Ls, g.image.width, g.image.height, Es), ws.set(d, 0), de.renderPixelToTarget(n[f.texture.index], Es, ws);
|
|
1265
1902
|
} else if ("attribute" in f) {
|
|
1266
1903
|
const y = s.getAttribute(`_feature_id_${f.attribute}`).getX(c);
|
|
1267
1904
|
y !== p && (r[d] = y);
|
|
@@ -1271,8 +1908,8 @@ var tr = class {
|
|
|
1271
1908
|
}
|
|
1272
1909
|
}
|
|
1273
1910
|
const u = new Uint8Array(o * 4);
|
|
1274
|
-
if (this._asyncRead) return
|
|
1275
|
-
return
|
|
1911
|
+
if (this._asyncRead) return de.readDataAsync(u).then(() => (h(), r));
|
|
1912
|
+
return de.readData(u), h(), r;
|
|
1276
1913
|
function h() {
|
|
1277
1914
|
const d = new Uint32Array(1);
|
|
1278
1915
|
for (let m = 0, f = i.length; m < f; m++) {
|
|
@@ -1280,12 +1917,15 @@ var tr = class {
|
|
|
1280
1917
|
if ("texture" in p) {
|
|
1281
1918
|
const { channels: y } = p.texture, x = y.map((T) => u[4 * m + T]);
|
|
1282
1919
|
new Uint8Array(d.buffer).set(x);
|
|
1283
|
-
const
|
|
1284
|
-
|
|
1920
|
+
const b = d[0];
|
|
1921
|
+
b !== g && (r[m] = b);
|
|
1285
1922
|
}
|
|
1286
1923
|
}
|
|
1287
1924
|
}
|
|
1288
1925
|
}
|
|
1926
|
+
/**
|
|
1927
|
+
* Disposes all textures used by this instance.
|
|
1928
|
+
*/
|
|
1289
1929
|
dispose() {
|
|
1290
1930
|
this.textures.forEach((e) => {
|
|
1291
1931
|
e && (e.dispose(), e.image instanceof ImageBitmap && e.image.close());
|
|
@@ -1293,13 +1933,13 @@ var tr = class {
|
|
|
1293
1933
|
}
|
|
1294
1934
|
};
|
|
1295
1935
|
new FullScreenQuad(new MeshBasicMaterial());
|
|
1296
|
-
var
|
|
1936
|
+
var zt = new DataTexture(new Uint8Array([
|
|
1297
1937
|
255,
|
|
1298
1938
|
255,
|
|
1299
1939
|
255,
|
|
1300
1940
|
255
|
|
1301
1941
|
]), 1, 1);
|
|
1302
|
-
|
|
1942
|
+
zt.needsUpdate = !0;
|
|
1303
1943
|
Object.freeze({
|
|
1304
1944
|
NONE: 0,
|
|
1305
1945
|
SCREEN_ERROR: 1,
|
|
@@ -1472,7 +2112,7 @@ var GLTFWorkerLoader = class extends Loader {
|
|
|
1472
2112
|
if (hasStructuralMetadata && data.structuralMetadata) {
|
|
1473
2113
|
const rootExtension = data.json?.extensions?.[EXT_STRUCTURAL_METADATA];
|
|
1474
2114
|
if (rootExtension) {
|
|
1475
|
-
rootMetadata = new
|
|
2115
|
+
rootMetadata = new vs({
|
|
1476
2116
|
schema: data.structuralMetadata.schema,
|
|
1477
2117
|
propertyTables: data.structuralMetadata.propertyTables || [],
|
|
1478
2118
|
propertyTextures: rootExtension.propertyTextures || [],
|
|
@@ -1495,7 +2135,7 @@ var GLTFWorkerLoader = class extends Loader {
|
|
|
1495
2135
|
const primMetadataExt = extensions?.[EXT_STRUCTURAL_METADATA];
|
|
1496
2136
|
if (primMetadataExt) {
|
|
1497
2137
|
const rootExtension = data.json?.extensions?.[EXT_STRUCTURAL_METADATA];
|
|
1498
|
-
if (rootExtension) child.userData.structuralMetadata = new
|
|
2138
|
+
if (rootExtension) child.userData.structuralMetadata = new vs({
|
|
1499
2139
|
schema: data.structuralMetadata.schema,
|
|
1500
2140
|
propertyTables: data.structuralMetadata.propertyTables || [],
|
|
1501
2141
|
propertyTextures: rootExtension.propertyTextures || [],
|
|
@@ -1505,17 +2145,13 @@ var GLTFWorkerLoader = class extends Loader {
|
|
|
1505
2145
|
}
|
|
1506
2146
|
if (hasMeshFeatures) {
|
|
1507
2147
|
const meshFeaturesExt = extensions?.[EXT_MESH_FEATURES];
|
|
1508
|
-
if (meshFeaturesExt) child.userData.meshFeatures = new
|
|
2148
|
+
if (meshFeaturesExt) child.userData.meshFeatures = new ar(child.geometry, textures, meshFeaturesExt);
|
|
1509
2149
|
}
|
|
1510
2150
|
});
|
|
1511
2151
|
}
|
|
1512
2152
|
};
|
|
1513
2153
|
//#endregion
|
|
1514
2154
|
//#region src/plugin/PartColorHelper.ts
|
|
1515
|
-
function ensureColor$1(color) {
|
|
1516
|
-
if (color instanceof Color) return color;
|
|
1517
|
-
return new Color(color);
|
|
1518
|
-
}
|
|
1519
2155
|
function getMaterials(mesh) {
|
|
1520
2156
|
const mat = mesh.material;
|
|
1521
2157
|
if (!mat) return [];
|
|
@@ -1533,7 +2169,7 @@ function getMaterialForColor(color) {
|
|
|
1533
2169
|
}
|
|
1534
2170
|
var materialCache = /* @__PURE__ */ new Map();
|
|
1535
2171
|
/**
|
|
1536
|
-
* 构件着色/透明度辅助器,参考 example 逻辑:
|
|
2172
|
+
* 构件着色/透明度辅助器,参考 example 逻辑:hidePartsByOids -> 修改材质 -> scene.add -> mesh-change 监听
|
|
1537
2173
|
* 由 GLTFParserPlugin 内部使用,scene 通过 tiles.group 获取
|
|
1538
2174
|
*/
|
|
1539
2175
|
var PartColorHelper = class {
|
|
@@ -1573,7 +2209,7 @@ var PartColorHelper = class {
|
|
|
1573
2209
|
setPartColorByOids(oids, color) {
|
|
1574
2210
|
const scene = this.context.getScene();
|
|
1575
2211
|
if (!scene) return;
|
|
1576
|
-
const material = getMaterialForColor(
|
|
2212
|
+
const material = getMaterialForColor(toColor(color));
|
|
1577
2213
|
for (const oid of oids) {
|
|
1578
2214
|
this.coloredOids.add(oid);
|
|
1579
2215
|
this.materialByOid.set(oid, material);
|
|
@@ -1589,7 +2225,7 @@ var PartColorHelper = class {
|
|
|
1589
2225
|
collector.addEventListener("mesh-change", handler);
|
|
1590
2226
|
}
|
|
1591
2227
|
}
|
|
1592
|
-
this.context.
|
|
2228
|
+
this.context.hidePartsByOids(this.getAllModifiedOids());
|
|
1593
2229
|
}
|
|
1594
2230
|
/**
|
|
1595
2231
|
* 恢复指定构件的颜色
|
|
@@ -1624,7 +2260,7 @@ var PartColorHelper = class {
|
|
|
1624
2260
|
}
|
|
1625
2261
|
}
|
|
1626
2262
|
}
|
|
1627
|
-
this.context.
|
|
2263
|
+
this.context.showPartsByOids(oids);
|
|
1628
2264
|
}
|
|
1629
2265
|
/**
|
|
1630
2266
|
* 根据 oid 数组设置构件透明度
|
|
@@ -1662,7 +2298,7 @@ var PartColorHelper = class {
|
|
|
1662
2298
|
collector.addEventListener("mesh-change", handler);
|
|
1663
2299
|
}
|
|
1664
2300
|
}
|
|
1665
|
-
this.context.
|
|
2301
|
+
this.context.hidePartsByOids(this.getAllModifiedOids());
|
|
1666
2302
|
}
|
|
1667
2303
|
/**
|
|
1668
2304
|
* 恢复指定构件的透明度
|
|
@@ -1694,18 +2330,14 @@ var PartColorHelper = class {
|
|
|
1694
2330
|
}
|
|
1695
2331
|
}
|
|
1696
2332
|
}
|
|
1697
|
-
this.context.
|
|
2333
|
+
this.context.showPartsByOids(oids);
|
|
1698
2334
|
}
|
|
1699
2335
|
};
|
|
1700
2336
|
//#endregion
|
|
1701
2337
|
//#region src/plugin/PartBlinkHelper.ts
|
|
1702
|
-
function ensureColor(color) {
|
|
1703
|
-
if (color instanceof Color) return color;
|
|
1704
|
-
return new Color(color);
|
|
1705
|
-
}
|
|
1706
2338
|
/**
|
|
1707
2339
|
* 构件闪烁强调辅助器
|
|
1708
|
-
* 通过
|
|
2340
|
+
* 通过 hidePartsByOids + split mesh + emissive 动画实现闪烁效果
|
|
1709
2341
|
*/
|
|
1710
2342
|
var PartBlinkHelper = class {
|
|
1711
2343
|
blinkOids = /* @__PURE__ */ new Set();
|
|
@@ -1778,7 +2410,7 @@ var PartBlinkHelper = class {
|
|
|
1778
2410
|
this.meshChangeHandlers.set(oid, handler);
|
|
1779
2411
|
collector.addEventListener("mesh-change", handler);
|
|
1780
2412
|
}
|
|
1781
|
-
this.context.
|
|
2413
|
+
this.context.hidePartsByOids(Array.from(this.blinkOids));
|
|
1782
2414
|
if (this.blinkOids.size > 0) this.startAnimation();
|
|
1783
2415
|
}
|
|
1784
2416
|
/**
|
|
@@ -1786,7 +2418,7 @@ var PartBlinkHelper = class {
|
|
|
1786
2418
|
* @param color 颜色值,支持 hex 数字、颜色字符串(如 "#ff0000")、THREE.Color 对象
|
|
1787
2419
|
*/
|
|
1788
2420
|
setBlinkColor(color) {
|
|
1789
|
-
const c =
|
|
2421
|
+
const c = toColor(color);
|
|
1790
2422
|
this.blinkColor.copy(c);
|
|
1791
2423
|
this.blinkMaterial.color.copy(c);
|
|
1792
2424
|
this.blinkMaterial.emissive.copy(c);
|
|
@@ -1823,7 +2455,7 @@ var PartBlinkHelper = class {
|
|
|
1823
2455
|
}
|
|
1824
2456
|
}
|
|
1825
2457
|
this.blinkOids.clear();
|
|
1826
|
-
this.context.
|
|
2458
|
+
this.context.showPartsByOids(oidsToUnhide);
|
|
1827
2459
|
}
|
|
1828
2460
|
dispose() {
|
|
1829
2461
|
this.clearAllBlinkParts();
|
|
@@ -1833,41 +2465,54 @@ var PartBlinkHelper = class {
|
|
|
1833
2465
|
//#region src/plugin/PartFrameHelper.ts
|
|
1834
2466
|
/**
|
|
1835
2467
|
* 构件线框显示辅助器
|
|
1836
|
-
* 通过
|
|
2468
|
+
* 通过 hidePartsByOids + split mesh + 填充材质 + EdgesGeometry 实现线框效果
|
|
1837
2469
|
*/
|
|
2470
|
+
var DEFAULT_FRAME_COLOR = 54442;
|
|
1838
2471
|
var PartFrameHelper = class {
|
|
1839
2472
|
frameOids = /* @__PURE__ */ new Set();
|
|
1840
2473
|
originalMaterialByMesh = /* @__PURE__ */ new Map();
|
|
1841
2474
|
frameDataByOid = /* @__PURE__ */ new Map();
|
|
1842
2475
|
meshChangeHandlers = /* @__PURE__ */ new Map();
|
|
1843
|
-
|
|
1844
|
-
|
|
2476
|
+
fillColorByOid = /* @__PURE__ */ new Map();
|
|
2477
|
+
edgeColorByOid = /* @__PURE__ */ new Map();
|
|
2478
|
+
fillMaterialCache = /* @__PURE__ */ new Map();
|
|
2479
|
+
edgeMaterialCache = /* @__PURE__ */ new Map();
|
|
1845
2480
|
edgeThreshold;
|
|
1846
2481
|
constructor(context) {
|
|
1847
2482
|
this.context = context;
|
|
1848
|
-
this.
|
|
1849
|
-
|
|
2483
|
+
this.edgeThreshold = 15;
|
|
2484
|
+
}
|
|
2485
|
+
getFillMaterial(hex) {
|
|
2486
|
+
if (!this.fillMaterialCache.has(hex)) this.fillMaterialCache.set(hex, new MeshBasicMaterial({
|
|
2487
|
+
color: hex,
|
|
1850
2488
|
transparent: true,
|
|
1851
2489
|
opacity: .3,
|
|
1852
2490
|
side: DoubleSide,
|
|
1853
2491
|
depthWrite: false
|
|
1854
|
-
});
|
|
1855
|
-
this.
|
|
1856
|
-
|
|
2492
|
+
}));
|
|
2493
|
+
return this.fillMaterialCache.get(hex);
|
|
2494
|
+
}
|
|
2495
|
+
getEdgeMaterial(hex) {
|
|
2496
|
+
if (!this.edgeMaterialCache.has(hex)) this.edgeMaterialCache.set(hex, new MeshBasicMaterial({
|
|
2497
|
+
color: hex,
|
|
1857
2498
|
transparent: true,
|
|
1858
2499
|
opacity: .8
|
|
1859
|
-
});
|
|
1860
|
-
this.
|
|
2500
|
+
}));
|
|
2501
|
+
return this.edgeMaterialCache.get(hex);
|
|
1861
2502
|
}
|
|
1862
|
-
createWireframeForMeshes(meshes, scene) {
|
|
2503
|
+
createWireframeForMeshes(meshes, scene, oid) {
|
|
2504
|
+
const fillHex = this.fillColorByOid.get(oid) ?? DEFAULT_FRAME_COLOR;
|
|
2505
|
+
const edgeHex = this.edgeColorByOid.get(oid) ?? DEFAULT_FRAME_COLOR;
|
|
2506
|
+
const fillMaterial = this.getFillMaterial(fillHex);
|
|
2507
|
+
const edgeMaterial = this.getEdgeMaterial(edgeHex);
|
|
1863
2508
|
const frameMeshes = [];
|
|
1864
2509
|
const lines = [];
|
|
1865
2510
|
for (const mesh of meshes) {
|
|
1866
2511
|
if (!this.originalMaterialByMesh.has(mesh.uuid)) this.originalMaterialByMesh.set(mesh.uuid, mesh.material);
|
|
1867
|
-
mesh.material =
|
|
2512
|
+
mesh.material = fillMaterial;
|
|
1868
2513
|
scene.add(mesh);
|
|
1869
2514
|
frameMeshes.push(mesh);
|
|
1870
|
-
const line = new LineSegments(new EdgesGeometry(mesh.geometry, this.edgeThreshold),
|
|
2515
|
+
const line = new LineSegments(new EdgesGeometry(mesh.geometry, this.edgeThreshold), edgeMaterial);
|
|
1871
2516
|
line.matrix.copy(mesh.matrixWorld);
|
|
1872
2517
|
line.matrixAutoUpdate = false;
|
|
1873
2518
|
scene.add(line);
|
|
@@ -1898,7 +2543,7 @@ var PartFrameHelper = class {
|
|
|
1898
2543
|
const collector = this.context.getMeshCollectorByOid(oid);
|
|
1899
2544
|
const oldData = this.frameDataByOid.get(oid);
|
|
1900
2545
|
if (oldData) this.removeFrameData(oldData, scene);
|
|
1901
|
-
const newData = this.createWireframeForMeshes(collector.meshes, scene);
|
|
2546
|
+
const newData = this.createWireframeForMeshes(collector.meshes, scene, oid);
|
|
1902
2547
|
this.frameDataByOid.set(oid, newData);
|
|
1903
2548
|
}
|
|
1904
2549
|
/**
|
|
@@ -1912,13 +2557,13 @@ var PartFrameHelper = class {
|
|
|
1912
2557
|
for (const oid of oids) {
|
|
1913
2558
|
this.frameOids.add(oid);
|
|
1914
2559
|
const collector = this.context.getMeshCollectorByOid(oid);
|
|
1915
|
-
const data = this.createWireframeForMeshes(collector.meshes, scene);
|
|
2560
|
+
const data = this.createWireframeForMeshes(collector.meshes, scene, oid);
|
|
1916
2561
|
this.frameDataByOid.set(oid, data);
|
|
1917
2562
|
const handler = () => this.applyFrameToOid(oid);
|
|
1918
2563
|
this.meshChangeHandlers.set(oid, handler);
|
|
1919
2564
|
collector.addEventListener("mesh-change", handler);
|
|
1920
2565
|
}
|
|
1921
|
-
this.context.
|
|
2566
|
+
this.context.hidePartsByOids(Array.from(this.frameOids));
|
|
1922
2567
|
}
|
|
1923
2568
|
/**
|
|
1924
2569
|
* 清除所有线框显示构件
|
|
@@ -1940,20 +2585,484 @@ var PartFrameHelper = class {
|
|
|
1940
2585
|
}
|
|
1941
2586
|
}
|
|
1942
2587
|
this.frameOids.clear();
|
|
1943
|
-
this.
|
|
2588
|
+
this.fillColorByOid.clear();
|
|
2589
|
+
this.edgeColorByOid.clear();
|
|
2590
|
+
this.context.showPartsByOids(oidsToUnhide);
|
|
2591
|
+
}
|
|
2592
|
+
/**
|
|
2593
|
+
* 设置指定构件的线框填充颜色
|
|
2594
|
+
* @param oids 构件 OID 数组
|
|
2595
|
+
* @param color 颜色值,支持 hex 数字、颜色字符串(如 "#ff0000")、THREE.Color 对象
|
|
2596
|
+
*/
|
|
2597
|
+
setFrameFillColor(oids, color) {
|
|
2598
|
+
const hex = toColor(color).getHex();
|
|
2599
|
+
for (const oid of oids) {
|
|
2600
|
+
if (!this.frameOids.has(oid)) continue;
|
|
2601
|
+
this.fillColorByOid.set(oid, hex);
|
|
2602
|
+
this.applyFrameToOid(oid);
|
|
2603
|
+
}
|
|
2604
|
+
}
|
|
2605
|
+
/**
|
|
2606
|
+
* 设置指定构件的线框边框颜色
|
|
2607
|
+
* @param oids 构件 OID 数组
|
|
2608
|
+
* @param color 颜色值,支持 hex 数字、颜色字符串(如 "#ff0000")、THREE.Color 对象
|
|
2609
|
+
*/
|
|
2610
|
+
setFrameEdgeColor(oids, color) {
|
|
2611
|
+
const hex = toColor(color).getHex();
|
|
2612
|
+
for (const oid of oids) {
|
|
2613
|
+
if (!this.frameOids.has(oid)) continue;
|
|
2614
|
+
this.edgeColorByOid.set(oid, hex);
|
|
2615
|
+
this.applyFrameToOid(oid);
|
|
2616
|
+
}
|
|
1944
2617
|
}
|
|
1945
2618
|
dispose() {
|
|
1946
2619
|
this.clearAllFrameParts();
|
|
2620
|
+
this.fillMaterialCache.forEach((m) => m.dispose());
|
|
2621
|
+
this.fillMaterialCache.clear();
|
|
2622
|
+
this.edgeMaterialCache.forEach((m) => m.dispose());
|
|
2623
|
+
this.edgeMaterialCache.clear();
|
|
2624
|
+
}
|
|
2625
|
+
};
|
|
2626
|
+
//#endregion
|
|
2627
|
+
//#region src/plugin/style-appearance-shared.ts
|
|
2628
|
+
function vec3Key(v) {
|
|
2629
|
+
if (v === void 0) return "";
|
|
2630
|
+
if (Array.isArray(v)) return `${v[0] ?? 0},${v[1] ?? 0},${v[2] ?? 0}`;
|
|
2631
|
+
const p = v;
|
|
2632
|
+
return `${p.x},${p.y},${p.z}`;
|
|
2633
|
+
}
|
|
2634
|
+
function eulerKey(r) {
|
|
2635
|
+
if (r === void 0) return "";
|
|
2636
|
+
if (Array.isArray(r)) return `${r[0] ?? 0},${r[1] ?? 0},${r[2] ?? 0},${r.length >= 4 && typeof r[3] === "string" ? r[3] : "XYZ"}`;
|
|
2637
|
+
const e = r;
|
|
2638
|
+
return `${e.x},${e.y},${e.z},${e.order}`;
|
|
2639
|
+
}
|
|
2640
|
+
function applyVec3(target, input) {
|
|
2641
|
+
if (Array.isArray(input)) target.set(input[0] ?? 0, input[1] ?? 0, input[2] ?? 0);
|
|
2642
|
+
else target.copy(input);
|
|
2643
|
+
}
|
|
2644
|
+
function applyEuler(target, input) {
|
|
2645
|
+
if (Array.isArray(input)) if (input.length >= 4 && typeof input[3] === "string") target.set(input[0] ?? 0, input[1] ?? 0, input[2] ?? 0, input[3]);
|
|
2646
|
+
else target.set(input[0] ?? 0, input[1] ?? 0, input[2] ?? 0, "XYZ");
|
|
2647
|
+
else target.copy(input);
|
|
2648
|
+
}
|
|
2649
|
+
function appearanceGroupKey(a) {
|
|
2650
|
+
return `${a.material.uuid}|${vec3Key(a.translation)}|${vec3Key(a.scale)}|${eulerKey(a.rotation)}|${vec3Key(a.origin)}`;
|
|
2651
|
+
}
|
|
2652
|
+
function buildPivotStyleMatrix(pivot, sx, sy, sz, euler) {
|
|
2653
|
+
const m = new Matrix4().makeTranslation(-pivot.x, -pivot.y, -pivot.z);
|
|
2654
|
+
m.premultiply(new Matrix4().makeScale(sx, sy, sz));
|
|
2655
|
+
m.premultiply(new Matrix4().makeRotationFromEuler(euler));
|
|
2656
|
+
m.premultiply(new Matrix4().makeTranslation(pivot.x, pivot.y, pivot.z));
|
|
2657
|
+
return m;
|
|
2658
|
+
}
|
|
2659
|
+
function resolveConditionsAppearance(conditions, propertyData) {
|
|
2660
|
+
if (!conditions?.length) return null;
|
|
2661
|
+
for (const [cond, value] of conditions) if (evaluateStyleCondition(cond, propertyData)) return value;
|
|
2662
|
+
return null;
|
|
2663
|
+
}
|
|
2664
|
+
function resolveStyleAppearance(conditions, propertyData) {
|
|
2665
|
+
return resolveConditionsAppearance(conditions, propertyData);
|
|
2666
|
+
}
|
|
2667
|
+
/** 与 setStyle 相同的 OID 分组逻辑(show + conditions → 外观分组 + 被 show 隐藏的 OID) */
|
|
2668
|
+
function buildAppearanceGroupsFromPropertyMap(propertyByOid, config) {
|
|
2669
|
+
const hiddenOidsList = [];
|
|
2670
|
+
const groups = /* @__PURE__ */ new Map();
|
|
2671
|
+
const conditions = config.conditions ?? [];
|
|
2672
|
+
for (const [oid, propertyData] of propertyByOid) {
|
|
2673
|
+
if (propertyData == null) continue;
|
|
2674
|
+
if (config.show) {
|
|
2675
|
+
if (!evaluateStyleCondition(config.show, propertyData)) {
|
|
2676
|
+
hiddenOidsList.push(oid);
|
|
2677
|
+
continue;
|
|
2678
|
+
}
|
|
2679
|
+
}
|
|
2680
|
+
const appearance = resolveStyleAppearance(conditions, propertyData);
|
|
2681
|
+
if (!appearance) continue;
|
|
2682
|
+
const gkey = appearanceGroupKey(appearance);
|
|
2683
|
+
let g = groups.get(gkey);
|
|
2684
|
+
if (!g) {
|
|
2685
|
+
g = {
|
|
2686
|
+
appearance,
|
|
2687
|
+
oids: []
|
|
2688
|
+
};
|
|
2689
|
+
groups.set(gkey, g);
|
|
2690
|
+
}
|
|
2691
|
+
g.oids.push(oid);
|
|
2692
|
+
}
|
|
2693
|
+
return {
|
|
2694
|
+
hiddenOidsList,
|
|
2695
|
+
groups
|
|
2696
|
+
};
|
|
2697
|
+
}
|
|
2698
|
+
function restoreMeshAppearanceMaps(mesh, maps) {
|
|
2699
|
+
const original = maps.originalMaterialByMesh.get(mesh.uuid);
|
|
2700
|
+
if (original) {
|
|
2701
|
+
mesh.material = original;
|
|
2702
|
+
maps.originalMaterialByMesh.delete(mesh.uuid);
|
|
2703
|
+
}
|
|
2704
|
+
const origT = maps.originalTransformByMesh.get(mesh.uuid);
|
|
2705
|
+
if (origT) {
|
|
2706
|
+
mesh.position.copy(origT.position);
|
|
2707
|
+
mesh.scale.copy(origT.scale);
|
|
2708
|
+
mesh.rotation.copy(origT.rotation);
|
|
2709
|
+
maps.originalTransformByMesh.delete(mesh.uuid);
|
|
2710
|
+
}
|
|
2711
|
+
}
|
|
2712
|
+
/**
|
|
2713
|
+
* 将 StyleAppearance 应用到 mesh(与 StyleHelper.applyAppearanceToCollector 一致)
|
|
2714
|
+
*/
|
|
2715
|
+
function applyStyleAppearanceToMesh(mesh, appearance, scene, maps) {
|
|
2716
|
+
if (!maps.originalMaterialByMesh.has(mesh.uuid)) maps.originalMaterialByMesh.set(mesh.uuid, mesh.material);
|
|
2717
|
+
mesh.material = appearance.material;
|
|
2718
|
+
if (appearance.translation !== void 0 || appearance.scale !== void 0 || appearance.rotation !== void 0) {
|
|
2719
|
+
if (!maps.originalTransformByMesh.has(mesh.uuid)) maps.originalTransformByMesh.set(mesh.uuid, {
|
|
2720
|
+
position: mesh.position.clone(),
|
|
2721
|
+
scale: mesh.scale.clone(),
|
|
2722
|
+
rotation: mesh.rotation.clone()
|
|
2723
|
+
});
|
|
2724
|
+
const bt = maps.originalTransformByMesh.get(mesh.uuid);
|
|
2725
|
+
mesh.position.copy(bt.position);
|
|
2726
|
+
mesh.scale.copy(bt.scale);
|
|
2727
|
+
mesh.rotation.copy(bt.rotation);
|
|
2728
|
+
if (appearance.scale !== void 0 || appearance.rotation !== void 0) {
|
|
2729
|
+
const pivot = new Vector3();
|
|
2730
|
+
if (appearance.origin !== void 0) applyVec3(pivot, appearance.origin);
|
|
2731
|
+
else pivot.set(0, 0, 0);
|
|
2732
|
+
let sx = 1;
|
|
2733
|
+
let sy = 1;
|
|
2734
|
+
let sz = 1;
|
|
2735
|
+
if (appearance.scale !== void 0) if (Array.isArray(appearance.scale)) {
|
|
2736
|
+
sx = appearance.scale[0] ?? 1;
|
|
2737
|
+
sy = appearance.scale[1] ?? 1;
|
|
2738
|
+
sz = appearance.scale[2] ?? 1;
|
|
2739
|
+
} else {
|
|
2740
|
+
const sc = appearance.scale;
|
|
2741
|
+
sx = sc.x;
|
|
2742
|
+
sy = sc.y;
|
|
2743
|
+
sz = sc.z;
|
|
2744
|
+
}
|
|
2745
|
+
const euler = new Euler();
|
|
2746
|
+
if (appearance.rotation !== void 0) applyEuler(euler, appearance.rotation);
|
|
2747
|
+
else euler.set(0, 0, 0);
|
|
2748
|
+
const styleM = buildPivotStyleMatrix(pivot, sx, sy, sz, euler);
|
|
2749
|
+
mesh.updateMatrix();
|
|
2750
|
+
mesh.matrix.multiply(styleM);
|
|
2751
|
+
mesh.matrix.decompose(mesh.position, mesh.quaternion, mesh.scale);
|
|
2752
|
+
}
|
|
2753
|
+
if (appearance.translation !== void 0) applyVec3(mesh.position, appearance.translation);
|
|
2754
|
+
}
|
|
2755
|
+
mesh.updateMatrixWorld();
|
|
2756
|
+
scene.add(mesh);
|
|
2757
|
+
}
|
|
2758
|
+
//#endregion
|
|
2759
|
+
//#region src/plugin/StyleHelper.ts
|
|
2760
|
+
/**
|
|
2761
|
+
* 构件样式辅助器
|
|
2762
|
+
* 通过 show 表达式控制可见性,通过 conditions 应用条件材质与可选位姿
|
|
2763
|
+
*/
|
|
2764
|
+
var StyleHelper = class {
|
|
2765
|
+
/** 当前样式配置,可通过 plugin.style 获取 */
|
|
2766
|
+
style = null;
|
|
2767
|
+
styledOids = /* @__PURE__ */ new Set();
|
|
2768
|
+
hiddenOids = /* @__PURE__ */ new Set();
|
|
2769
|
+
originalMaterialByMesh = /* @__PURE__ */ new Map();
|
|
2770
|
+
originalTransformByMesh = /* @__PURE__ */ new Map();
|
|
2771
|
+
/** 按材质分组后的收集器,key 与 collector.getCacheKey() 一致 */
|
|
2772
|
+
meshChangeHandlers = /* @__PURE__ */ new Map();
|
|
2773
|
+
/** 当前样式占用的收集器(用于 clearStyle / 下次 applyStyle 前卸载监听) */
|
|
2774
|
+
styleCollectors = [];
|
|
2775
|
+
constructor(context) {
|
|
2776
|
+
this.context = context;
|
|
2777
|
+
}
|
|
2778
|
+
/**
|
|
2779
|
+
* 设置样式
|
|
2780
|
+
* @param style 样式配置,传 null 或空对象清除样式
|
|
2781
|
+
*/
|
|
2782
|
+
setStyle(style) {
|
|
2783
|
+
this.clearStyle();
|
|
2784
|
+
this.style = style;
|
|
2785
|
+
if (!style || !style.show && (!style.conditions || style.conditions.length === 0)) return;
|
|
2786
|
+
this.applyStyle();
|
|
2787
|
+
}
|
|
2788
|
+
/**
|
|
2789
|
+
* 清除样式,恢复默认显示
|
|
2790
|
+
*/
|
|
2791
|
+
clearStyle() {
|
|
2792
|
+
const styledOidsList = Array.from(this.styledOids);
|
|
2793
|
+
const hiddenOidsList = Array.from(this.hiddenOids);
|
|
2794
|
+
for (const collector of this.styleCollectors) {
|
|
2795
|
+
collector.meshes.forEach((mesh) => {
|
|
2796
|
+
const original = this.originalMaterialByMesh.get(mesh.uuid);
|
|
2797
|
+
if (original) {
|
|
2798
|
+
mesh.material = original;
|
|
2799
|
+
this.originalMaterialByMesh.delete(mesh.uuid);
|
|
2800
|
+
}
|
|
2801
|
+
const origT = this.originalTransformByMesh.get(mesh.uuid);
|
|
2802
|
+
if (origT) {
|
|
2803
|
+
mesh.position.copy(origT.position);
|
|
2804
|
+
mesh.scale.copy(origT.scale);
|
|
2805
|
+
mesh.rotation.copy(origT.rotation);
|
|
2806
|
+
this.originalTransformByMesh.delete(mesh.uuid);
|
|
2807
|
+
}
|
|
2808
|
+
mesh.removeFromParent();
|
|
2809
|
+
});
|
|
2810
|
+
const handler = this.meshChangeHandlers.get(collector.getCacheKey());
|
|
2811
|
+
if (handler) collector.removeEventListener("mesh-change", handler);
|
|
2812
|
+
}
|
|
2813
|
+
this.meshChangeHandlers.clear();
|
|
2814
|
+
this.styleCollectors = [];
|
|
2815
|
+
this.style = null;
|
|
2816
|
+
this.styledOids.clear();
|
|
2817
|
+
this.hiddenOids.clear();
|
|
2818
|
+
this.context.showPartsByOids([...styledOidsList, ...hiddenOidsList]);
|
|
2819
|
+
}
|
|
2820
|
+
applyStyle() {
|
|
2821
|
+
const style = this.style;
|
|
2822
|
+
if (!style) return;
|
|
2823
|
+
if (!this.context.getScene()) return;
|
|
2824
|
+
const tiles = this.context.getTiles();
|
|
2825
|
+
if (!tiles) return;
|
|
2826
|
+
const propertyByOid = getPropertyDataMapFromTiles(tiles);
|
|
2827
|
+
for (const collector of this.styleCollectors) {
|
|
2828
|
+
const h = this.meshChangeHandlers.get(collector.getCacheKey());
|
|
2829
|
+
if (h) collector.removeEventListener("mesh-change", h);
|
|
2830
|
+
}
|
|
2831
|
+
this.styleCollectors = [];
|
|
2832
|
+
this.meshChangeHandlers.clear();
|
|
2833
|
+
const { hiddenOidsList, groups } = buildAppearanceGroupsFromPropertyMap(propertyByOid, {
|
|
2834
|
+
show: style.show,
|
|
2835
|
+
conditions: style.conditions ?? []
|
|
2836
|
+
});
|
|
2837
|
+
for (const { oids } of groups.values()) for (const oid of oids) this.styledOids.add(oid);
|
|
2838
|
+
this.hiddenOids = new Set(hiddenOidsList);
|
|
2839
|
+
const oidsToHide = [...hiddenOidsList];
|
|
2840
|
+
for (const { oids } of groups.values()) oidsToHide.push(...oids);
|
|
2841
|
+
const maps = {
|
|
2842
|
+
originalMaterialByMesh: this.originalMaterialByMesh,
|
|
2843
|
+
originalTransformByMesh: this.originalTransformByMesh
|
|
2844
|
+
};
|
|
2845
|
+
for (const { appearance, oids } of groups.values()) {
|
|
2846
|
+
const sortedOids = normalizeMeshCollectorOids(oids);
|
|
2847
|
+
const collector = this.context.getMeshCollectorByCondition({ oids: sortedOids });
|
|
2848
|
+
this.styleCollectors.push(collector);
|
|
2849
|
+
const cacheKey = collector.getCacheKey();
|
|
2850
|
+
const handler = () => {
|
|
2851
|
+
const s = this.context.getScene();
|
|
2852
|
+
if (!s) return;
|
|
2853
|
+
collector.meshes.forEach((mesh) => {
|
|
2854
|
+
applyStyleAppearanceToMesh(mesh, appearance, s, maps);
|
|
2855
|
+
});
|
|
2856
|
+
};
|
|
2857
|
+
this.meshChangeHandlers.set(cacheKey, handler);
|
|
2858
|
+
collector.addEventListener("mesh-change", handler);
|
|
2859
|
+
handler();
|
|
2860
|
+
}
|
|
2861
|
+
this.context.hidePartsByOids(oidsToHide);
|
|
2862
|
+
}
|
|
2863
|
+
/**
|
|
2864
|
+
* 瓦片加载完成后重新应用样式(由插件调用)
|
|
2865
|
+
*/
|
|
2866
|
+
onTilesLoadEnd() {
|
|
2867
|
+
if (this.style) this.applyStyle();
|
|
2868
|
+
}
|
|
2869
|
+
dispose() {
|
|
2870
|
+
this.clearStyle();
|
|
2871
|
+
}
|
|
2872
|
+
};
|
|
2873
|
+
//#endregion
|
|
2874
|
+
//#region src/plugin/PartHighlightHelper.ts
|
|
2875
|
+
var highlightMaterialCache = /* @__PURE__ */ new Map();
|
|
2876
|
+
function getMaterialForHighlight(style) {
|
|
2877
|
+
const color = style.color != null ? toColor(style.color) : new Color(16776960);
|
|
2878
|
+
const opacity = style.opacity != null ? Math.max(0, Math.min(1, style.opacity)) : 1;
|
|
2879
|
+
const key = `${color.getHex()}_${opacity}`;
|
|
2880
|
+
if (!highlightMaterialCache.has(key)) {
|
|
2881
|
+
const mat = new MeshStandardMaterial({
|
|
2882
|
+
color: color.clone(),
|
|
2883
|
+
roughness: .5,
|
|
2884
|
+
metalness: .1,
|
|
2885
|
+
opacity,
|
|
2886
|
+
transparent: opacity < 1
|
|
2887
|
+
});
|
|
2888
|
+
highlightMaterialCache.set(key, mat);
|
|
2889
|
+
}
|
|
2890
|
+
return highlightMaterialCache.get(key);
|
|
2891
|
+
}
|
|
2892
|
+
function toMaterial(value) {
|
|
2893
|
+
if (value instanceof Material) return value;
|
|
2894
|
+
return getMaterialForHighlight(value);
|
|
2895
|
+
}
|
|
2896
|
+
function toStyleAppearance(ha) {
|
|
2897
|
+
return {
|
|
2898
|
+
material: toMaterial(ha.material),
|
|
2899
|
+
translation: ha.translation,
|
|
2900
|
+
scale: ha.scale,
|
|
2901
|
+
rotation: ha.rotation,
|
|
2902
|
+
origin: ha.origin
|
|
2903
|
+
};
|
|
2904
|
+
}
|
|
2905
|
+
/**
|
|
2906
|
+
* 构件高亮辅助器
|
|
2907
|
+
* 与 setStyle 相同的 show / conditions / 位姿语义,多组命名高亮;底层通过 hidePartsByOids + split mesh 实现
|
|
2908
|
+
*/
|
|
2909
|
+
var PartHighlightHelper = class {
|
|
2910
|
+
highlightGroups = /* @__PURE__ */ new Map();
|
|
2911
|
+
originalMaterialByMesh = /* @__PURE__ */ new Map();
|
|
2912
|
+
originalTransformByMesh = /* @__PURE__ */ new Map();
|
|
2913
|
+
meshChangeHandlers = /* @__PURE__ */ new Map();
|
|
2914
|
+
highlightCollectors = [];
|
|
2915
|
+
/** 上次 hidePartsByOids 传入的 OID 列表,用于重新应用前 showParts */
|
|
2916
|
+
lastHiddenOids = [];
|
|
2917
|
+
constructor(context) {
|
|
2918
|
+
this.context = context;
|
|
2919
|
+
}
|
|
2920
|
+
getMaps() {
|
|
2921
|
+
return {
|
|
2922
|
+
originalMaterialByMesh: this.originalMaterialByMesh,
|
|
2923
|
+
originalTransformByMesh: this.originalTransformByMesh
|
|
2924
|
+
};
|
|
2925
|
+
}
|
|
2926
|
+
/**
|
|
2927
|
+
* 合并多组命名高亮:按 Map 插入顺序,后写入的组覆盖同一 OID 的外观
|
|
2928
|
+
*/
|
|
2929
|
+
mergeAppearanceByOid(propertyByOid) {
|
|
2930
|
+
const appearanceByOid = /* @__PURE__ */ new Map();
|
|
2931
|
+
for (const [, hl] of this.highlightGroups) {
|
|
2932
|
+
const conditions = (hl.conditions ?? []).map(([c, h]) => [c, toStyleAppearance(h)]);
|
|
2933
|
+
for (const [oid, propertyData] of propertyByOid) {
|
|
2934
|
+
if (propertyData == null) continue;
|
|
2935
|
+
if (hl.oids && !hl.oids.includes(oid)) continue;
|
|
2936
|
+
if (hl.show && !evaluateStyleCondition(hl.show, propertyData)) continue;
|
|
2937
|
+
const app = resolveConditionsAppearance(conditions, propertyData);
|
|
2938
|
+
if (!app) continue;
|
|
2939
|
+
appearanceByOid.set(oid, app);
|
|
2940
|
+
}
|
|
2941
|
+
}
|
|
2942
|
+
return appearanceByOid;
|
|
2943
|
+
}
|
|
2944
|
+
/** 各组 show 失败需隐藏的 OID(与 setStyle 一致:show 不满足则隐藏原片) */
|
|
2945
|
+
collectUnionShowHide(propertyByOid) {
|
|
2946
|
+
const unionHide = /* @__PURE__ */ new Set();
|
|
2947
|
+
for (const [, hl] of this.highlightGroups) for (const [oid, propertyData] of propertyByOid) {
|
|
2948
|
+
if (propertyData == null) continue;
|
|
2949
|
+
if (hl.oids && !hl.oids.includes(oid)) continue;
|
|
2950
|
+
if (hl.show && !evaluateStyleCondition(hl.show, propertyData)) unionHide.add(oid);
|
|
2951
|
+
}
|
|
2952
|
+
return unionHide;
|
|
2953
|
+
}
|
|
2954
|
+
clearCollectorsAndRestoreMeshes() {
|
|
2955
|
+
const maps = this.getMaps();
|
|
2956
|
+
for (const collector of this.highlightCollectors) {
|
|
2957
|
+
collector.meshes.forEach((mesh) => {
|
|
2958
|
+
restoreMeshAppearanceMaps(mesh, maps);
|
|
2959
|
+
mesh.removeFromParent();
|
|
2960
|
+
});
|
|
2961
|
+
const handler = this.meshChangeHandlers.get(collector.getCacheKey());
|
|
2962
|
+
if (handler) collector.removeEventListener("mesh-change", handler);
|
|
2963
|
+
}
|
|
2964
|
+
this.meshChangeHandlers.clear();
|
|
2965
|
+
this.highlightCollectors = [];
|
|
2966
|
+
}
|
|
2967
|
+
reapplyAll() {
|
|
2968
|
+
this.clearCollectorsAndRestoreMeshes();
|
|
2969
|
+
if (this.lastHiddenOids.length > 0) this.context.showPartsByOids(this.lastHiddenOids);
|
|
2970
|
+
if (this.highlightGroups.size === 0) {
|
|
2971
|
+
this.lastHiddenOids = [];
|
|
2972
|
+
return;
|
|
2973
|
+
}
|
|
2974
|
+
const tiles = this.context.getTiles();
|
|
2975
|
+
const scene = this.context.getScene();
|
|
2976
|
+
if (!tiles || !scene) return;
|
|
2977
|
+
const propertyByOid = getPropertyDataMapFromTiles(tiles);
|
|
2978
|
+
const appearanceByOid = this.mergeAppearanceByOid(propertyByOid);
|
|
2979
|
+
const unionHide = this.collectUnionShowHide(propertyByOid);
|
|
2980
|
+
const oidsToHide = [...new Set([...appearanceByOid.keys(), ...unionHide])];
|
|
2981
|
+
this.lastHiddenOids = oidsToHide;
|
|
2982
|
+
const groups = /* @__PURE__ */ new Map();
|
|
2983
|
+
for (const [oid, app] of appearanceByOid) {
|
|
2984
|
+
const gkey = appearanceGroupKey(app);
|
|
2985
|
+
let g = groups.get(gkey);
|
|
2986
|
+
if (!g) {
|
|
2987
|
+
g = {
|
|
2988
|
+
appearance: app,
|
|
2989
|
+
oids: []
|
|
2990
|
+
};
|
|
2991
|
+
groups.set(gkey, g);
|
|
2992
|
+
}
|
|
2993
|
+
g.oids.push(oid);
|
|
2994
|
+
}
|
|
2995
|
+
const maps = this.getMaps();
|
|
2996
|
+
for (const { appearance, oids } of groups.values()) {
|
|
2997
|
+
const sortedOids = normalizeMeshCollectorOids(oids);
|
|
2998
|
+
const collector = this.context.getMeshCollectorByCondition({ oids: sortedOids });
|
|
2999
|
+
this.highlightCollectors.push(collector);
|
|
3000
|
+
const cacheKey = collector.getCacheKey();
|
|
3001
|
+
const handler = () => {
|
|
3002
|
+
const s = this.context.getScene();
|
|
3003
|
+
if (!s) return;
|
|
3004
|
+
collector.meshes.forEach((mesh) => {
|
|
3005
|
+
applyStyleAppearanceToMesh(mesh, appearance, s, maps);
|
|
3006
|
+
});
|
|
3007
|
+
};
|
|
3008
|
+
this.meshChangeHandlers.set(cacheKey, handler);
|
|
3009
|
+
collector.addEventListener("mesh-change", handler);
|
|
3010
|
+
handler();
|
|
3011
|
+
}
|
|
3012
|
+
this.context.hidePartsByOids(oidsToHide);
|
|
3013
|
+
}
|
|
3014
|
+
/**
|
|
3015
|
+
* 高亮指定构件(语义与 setStyle 一致,多 name 参数)
|
|
3016
|
+
*/
|
|
3017
|
+
highlight(options) {
|
|
3018
|
+
const { name, show, conditions, oids } = options;
|
|
3019
|
+
if (!show && (!conditions || conditions.length === 0)) {
|
|
3020
|
+
this.cancelHighlight(name);
|
|
3021
|
+
return;
|
|
3022
|
+
}
|
|
3023
|
+
this.highlightGroups.set(name, {
|
|
3024
|
+
show,
|
|
3025
|
+
conditions,
|
|
3026
|
+
oids
|
|
3027
|
+
});
|
|
3028
|
+
this.reapplyAll();
|
|
3029
|
+
}
|
|
3030
|
+
/**
|
|
3031
|
+
* 取消指定名称的高亮
|
|
3032
|
+
*/
|
|
3033
|
+
cancelHighlight(name) {
|
|
3034
|
+
if (!this.highlightGroups.has(name)) return;
|
|
3035
|
+
this.highlightGroups.delete(name);
|
|
3036
|
+
this.reapplyAll();
|
|
3037
|
+
}
|
|
3038
|
+
/**
|
|
3039
|
+
* 取消所有高亮
|
|
3040
|
+
*/
|
|
3041
|
+
cancelAllHighlight() {
|
|
3042
|
+
this.highlightGroups.clear();
|
|
3043
|
+
this.reapplyAll();
|
|
3044
|
+
}
|
|
3045
|
+
/**
|
|
3046
|
+
* 瓦片加载完成后重新应用高亮(由插件调用)
|
|
3047
|
+
*/
|
|
3048
|
+
onTilesLoadEnd() {
|
|
3049
|
+
if (this.highlightGroups.size === 0) return;
|
|
3050
|
+
this.reapplyAll();
|
|
3051
|
+
}
|
|
3052
|
+
dispose() {
|
|
3053
|
+
this.cancelAllHighlight();
|
|
1947
3054
|
}
|
|
1948
3055
|
};
|
|
1949
3056
|
//#endregion
|
|
1950
3057
|
//#region src/plugin/InteractionFilter.ts
|
|
1951
3058
|
/**
|
|
1952
|
-
* 冻结与隔离逻辑:管理构件的交互过滤及
|
|
3059
|
+
* 冻结与隔离逻辑:管理构件的交互过滤及 MeshCollector 获取的 mesh 在场景中的显隐
|
|
3060
|
+
* split mesh 使用 userData.oid(单 feature)或 userData.collectorOids(合并 mesh):任一相关 OID 被冻结/隔离规则命中则整 mesh 脱离场景
|
|
1953
3061
|
*/
|
|
1954
3062
|
var InteractionFilter = class {
|
|
1955
3063
|
frozenOids = /* @__PURE__ */ new Set();
|
|
1956
3064
|
isolatedOids = /* @__PURE__ */ new Set();
|
|
3065
|
+
/** 按 collector 分组键追踪 mesh */
|
|
1957
3066
|
trackedMeshes = /* @__PURE__ */ new Map();
|
|
1958
3067
|
meshListeners = /* @__PURE__ */ new Map();
|
|
1959
3068
|
isPluginRemoving = false;
|
|
@@ -1965,12 +3074,19 @@ var InteractionFilter = class {
|
|
|
1965
3074
|
if (this.isolatedOids.size > 0 && !this.isolatedOids.has(oid)) return true;
|
|
1966
3075
|
return false;
|
|
1967
3076
|
}
|
|
1968
|
-
|
|
3077
|
+
/** 合并 split:任一 collector OID 被 block 则整 mesh 视为应隐藏 */
|
|
3078
|
+
isMeshInteractionBlocked(mesh) {
|
|
3079
|
+
const coids = mesh.userData?.collectorOids;
|
|
3080
|
+
if (coids && coids.length > 0) return coids.some((oid) => this.isOidBlocked(oid));
|
|
3081
|
+
const oid = mesh.userData?.oid;
|
|
3082
|
+
return oid !== void 0 && this.isOidBlocked(oid);
|
|
3083
|
+
}
|
|
3084
|
+
trackMesh(mesh) {
|
|
1969
3085
|
if (this.meshListeners.has(mesh)) return;
|
|
1970
3086
|
const onAdded = () => {
|
|
1971
3087
|
if (this.isPluginRemoving) return;
|
|
1972
3088
|
mesh.userData._detachedParent = null;
|
|
1973
|
-
if (this.
|
|
3089
|
+
if (this.isMeshInteractionBlocked(mesh) && mesh.parent) {
|
|
1974
3090
|
const parent = mesh.parent;
|
|
1975
3091
|
this.isPluginRemoving = true;
|
|
1976
3092
|
mesh.userData._detachedParent = parent;
|
|
@@ -1998,8 +3114,8 @@ var InteractionFilter = class {
|
|
|
1998
3114
|
}
|
|
1999
3115
|
mesh.userData._detachedParent = null;
|
|
2000
3116
|
}
|
|
2001
|
-
onCollectorMeshChange(
|
|
2002
|
-
const tracked = this.trackedMeshes.get(
|
|
3117
|
+
onCollectorMeshChange(groupKey, newMeshes) {
|
|
3118
|
+
const tracked = this.trackedMeshes.get(groupKey);
|
|
2003
3119
|
const newSet = new Set(newMeshes);
|
|
2004
3120
|
if (tracked) {
|
|
2005
3121
|
for (const mesh of tracked) if (!newSet.has(mesh)) {
|
|
@@ -2009,39 +3125,36 @@ var InteractionFilter = class {
|
|
|
2009
3125
|
}
|
|
2010
3126
|
const trackSet = tracked || /* @__PURE__ */ new Set();
|
|
2011
3127
|
for (const mesh of newMeshes) if (!trackSet.has(mesh)) {
|
|
2012
|
-
this.trackMesh(mesh
|
|
3128
|
+
this.trackMesh(mesh);
|
|
2013
3129
|
trackSet.add(mesh);
|
|
2014
3130
|
}
|
|
2015
|
-
this.trackedMeshes.set(
|
|
3131
|
+
this.trackedMeshes.set(groupKey, trackSet);
|
|
2016
3132
|
}
|
|
2017
3133
|
syncCollectorMeshes() {
|
|
2018
3134
|
this.isPluginRemoving = true;
|
|
2019
|
-
for (const [
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
if (!
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
storedParent.add(mesh);
|
|
2033
|
-
mesh.userData._detachedParent = null;
|
|
2034
|
-
}
|
|
3135
|
+
for (const [, collector] of this.context.getCollectorCache()) for (const mesh of collector.meshes) {
|
|
3136
|
+
if (!this.meshListeners.has(mesh)) continue;
|
|
3137
|
+
if (this.isMeshInteractionBlocked(mesh)) {
|
|
3138
|
+
if (mesh.parent && !mesh.userData._detachedParent) {
|
|
3139
|
+
const parent = mesh.parent;
|
|
3140
|
+
mesh.userData._detachedParent = parent;
|
|
3141
|
+
parent.remove(mesh);
|
|
3142
|
+
}
|
|
3143
|
+
} else {
|
|
3144
|
+
const storedParent = mesh.userData._detachedParent;
|
|
3145
|
+
if (storedParent && !mesh.parent) {
|
|
3146
|
+
storedParent.add(mesh);
|
|
3147
|
+
mesh.userData._detachedParent = null;
|
|
2035
3148
|
}
|
|
2036
3149
|
}
|
|
2037
3150
|
}
|
|
2038
3151
|
this.isPluginRemoving = false;
|
|
2039
3152
|
}
|
|
2040
|
-
onUnregisterCollector(
|
|
2041
|
-
const tracked = this.trackedMeshes.get(
|
|
3153
|
+
onUnregisterCollector(groupKey) {
|
|
3154
|
+
const tracked = this.trackedMeshes.get(groupKey);
|
|
2042
3155
|
if (tracked) {
|
|
2043
3156
|
for (const mesh of tracked) this.untrackMesh(mesh);
|
|
2044
|
-
this.trackedMeshes.delete(
|
|
3157
|
+
this.trackedMeshes.delete(groupKey);
|
|
2045
3158
|
}
|
|
2046
3159
|
}
|
|
2047
3160
|
freezeByOids(oids) {
|
|
@@ -2049,16 +3162,14 @@ var InteractionFilter = class {
|
|
|
2049
3162
|
this.syncCollectorMeshes();
|
|
2050
3163
|
}
|
|
2051
3164
|
freezeByOid(oid) {
|
|
2052
|
-
this.
|
|
2053
|
-
this.syncCollectorMeshes();
|
|
3165
|
+
this.freezeByOids([oid]);
|
|
2054
3166
|
}
|
|
2055
3167
|
unfreezeByOids(oids) {
|
|
2056
3168
|
for (const oid of oids) this.frozenOids.delete(oid);
|
|
2057
3169
|
this.syncCollectorMeshes();
|
|
2058
3170
|
}
|
|
2059
3171
|
unfreezeByOid(oid) {
|
|
2060
|
-
this.
|
|
2061
|
-
this.syncCollectorMeshes();
|
|
3172
|
+
this.unfreezeByOids([oid]);
|
|
2062
3173
|
}
|
|
2063
3174
|
unfreeze() {
|
|
2064
3175
|
this.frozenOids.clear();
|
|
@@ -2080,8 +3191,7 @@ var InteractionFilter = class {
|
|
|
2080
3191
|
this.syncCollectorMeshes();
|
|
2081
3192
|
}
|
|
2082
3193
|
unisolateByOid(oid) {
|
|
2083
|
-
this.
|
|
2084
|
-
this.syncCollectorMeshes();
|
|
3194
|
+
this.unisolateByOids([oid]);
|
|
2085
3195
|
}
|
|
2086
3196
|
unisolate() {
|
|
2087
3197
|
this.isolatedOids.clear();
|
|
@@ -2193,18 +3303,23 @@ var GLTFParserPlugin = class {
|
|
|
2193
3303
|
_options;
|
|
2194
3304
|
_structureData = null;
|
|
2195
3305
|
_oidNodeMap = /* @__PURE__ */ new Map();
|
|
2196
|
-
|
|
3306
|
+
/** rootTileset 已存在且已尝试过内嵌解析后仍为 null,则不再重复 gunzip */
|
|
3307
|
+
_structureEmbedResolved = false;
|
|
2197
3308
|
_modelInfo = null;
|
|
2198
3309
|
_modelInfoPromise = null;
|
|
2199
3310
|
_interactionFilter;
|
|
2200
3311
|
_partColorHelper = null;
|
|
2201
3312
|
_partBlinkHelper = null;
|
|
2202
3313
|
_partFrameHelper = null;
|
|
3314
|
+
_styleHelper = null;
|
|
3315
|
+
_partHighlightHelper = null;
|
|
2203
3316
|
oids = [];
|
|
2204
|
-
|
|
3317
|
+
/** WebGLRenderer 实例,用于 mesh helper 等扩展 */
|
|
3318
|
+
get renderer() {
|
|
3319
|
+
return this._renderer;
|
|
3320
|
+
}
|
|
3321
|
+
_renderer = null;
|
|
2205
3322
|
splitMeshCache = /* @__PURE__ */ new Map();
|
|
2206
|
-
maxUniformVectors = 1024;
|
|
2207
|
-
featureIdCount = 32;
|
|
2208
3323
|
collectors = /* @__PURE__ */ new Set();
|
|
2209
3324
|
collectorCache = /* @__PURE__ */ new Map();
|
|
2210
3325
|
/**
|
|
@@ -2218,7 +3333,7 @@ var GLTFParserPlugin = class {
|
|
|
2218
3333
|
useIndexedDB: false,
|
|
2219
3334
|
...options
|
|
2220
3335
|
};
|
|
2221
|
-
if (options?.renderer) this.
|
|
3336
|
+
if (options?.renderer) this._renderer = options.renderer;
|
|
2222
3337
|
this._interactionFilter = new InteractionFilter({ getCollectorCache: () => this.collectorCache });
|
|
2223
3338
|
setMaxWorkers(this._options.maxWorkers);
|
|
2224
3339
|
}
|
|
@@ -2227,38 +3342,43 @@ var GLTFParserPlugin = class {
|
|
|
2227
3342
|
*/
|
|
2228
3343
|
init(tiles) {
|
|
2229
3344
|
this.tiles = tiles;
|
|
2230
|
-
|
|
2231
|
-
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
getScene: () => this.tiles?.group ?? null
|
|
2241
|
-
});
|
|
2242
|
-
this._partFrameHelper = new PartFrameHelper({
|
|
2243
|
-
hideByOids: (oids) => this.hideByOids(oids),
|
|
2244
|
-
unhideByOids: (oids) => this.unhideByOids(oids),
|
|
2245
|
-
getMeshCollectorByOid: (oid) => this.getMeshCollectorByOid(oid),
|
|
2246
|
-
getScene: () => this.tiles?.group ?? null
|
|
3345
|
+
const partFx = this._createPartEffectHost();
|
|
3346
|
+
this._partColorHelper = new PartColorHelper(partFx);
|
|
3347
|
+
this._partBlinkHelper = new PartBlinkHelper(partFx);
|
|
3348
|
+
this._partFrameHelper = new PartFrameHelper(partFx);
|
|
3349
|
+
this._styleHelper = new StyleHelper({
|
|
3350
|
+
getTiles: () => this.tiles,
|
|
3351
|
+
hidePartsByOids: partFx.hidePartsByOids,
|
|
3352
|
+
showPartsByOids: partFx.showPartsByOids,
|
|
3353
|
+
getMeshCollectorByCondition: partFx.getMeshCollectorByCondition,
|
|
3354
|
+
getScene: partFx.getScene
|
|
2247
3355
|
});
|
|
3356
|
+
this._partHighlightHelper = new PartHighlightHelper(partFx);
|
|
2248
3357
|
this._loader = new GLTFWorkerLoader(tiles.manager, {
|
|
2249
3358
|
metadata: this._options.metadata,
|
|
2250
3359
|
materialBuilder: this._options.materialBuilder
|
|
2251
3360
|
});
|
|
2252
3361
|
tiles.manager.addHandler(this._gltfRegex, this._loader);
|
|
2253
|
-
if (this.renderer) this._updateWebGLLimits();
|
|
2254
3362
|
tiles.addEventListener("load-model", this._onLoadModelCB);
|
|
2255
3363
|
tiles.addEventListener("tiles-load-end", this._onTilesLoadEndCB);
|
|
3364
|
+
tiles.addEventListener("load-root-tileset", this._onLoadRootTilesetCB);
|
|
3365
|
+
this._syncStructureFromTileset();
|
|
2256
3366
|
tiles.traverse((tile) => {
|
|
2257
3367
|
const tileWithCache = tile;
|
|
2258
|
-
if (tileWithCache.
|
|
3368
|
+
if (tileWithCache.engineData?.scene) this._onLoadModel(tileWithCache.engineData.scene);
|
|
2259
3369
|
return true;
|
|
2260
3370
|
}, null);
|
|
2261
3371
|
}
|
|
3372
|
+
_createPartEffectHost() {
|
|
3373
|
+
return {
|
|
3374
|
+
getTiles: () => this.tiles ?? null,
|
|
3375
|
+
hidePartsByOids: (oids) => this.hidePartsByOids(oids),
|
|
3376
|
+
showPartsByOids: (oids) => this.showPartsByOids(oids),
|
|
3377
|
+
getMeshCollectorByOid: (oid) => this.getMeshCollectorByOid(oid),
|
|
3378
|
+
getMeshCollectorByCondition: (q) => this.getMeshCollectorByCondition(q),
|
|
3379
|
+
getScene: () => this.tiles?.group ?? null
|
|
3380
|
+
};
|
|
3381
|
+
}
|
|
2262
3382
|
/**
|
|
2263
3383
|
* Fetch tile data with IndexedDB caching support
|
|
2264
3384
|
*/
|
|
@@ -2290,56 +3410,51 @@ var GLTFParserPlugin = class {
|
|
|
2290
3410
|
if (this._options.beforeParseTile) buffer = await this._options.beforeParseTile(buffer, tile, extension, uri, abortSignal);
|
|
2291
3411
|
return this.tiles.parseTile(buffer, tile, extension, uri, abortSignal);
|
|
2292
3412
|
}
|
|
2293
|
-
|
|
3413
|
+
/** 与 tileset 同目录的侧车 JSON,如 structure.json / modelInfo.json */
|
|
3414
|
+
_sidecarJsonUrl(fileName) {
|
|
2294
3415
|
const rootURL = this.tiles?.rootURL;
|
|
2295
3416
|
if (!rootURL) return null;
|
|
2296
|
-
return rootURL.replace(/[^/]+$/,
|
|
3417
|
+
return rootURL.replace(/[^/]+$/, fileName);
|
|
2297
3418
|
}
|
|
2298
3419
|
_buildOidNodeMap(node, map) {
|
|
2299
3420
|
if (node.id !== void 0) map.set(node.id, node);
|
|
2300
3421
|
if (node.children) for (const child of node.children) this._buildOidNodeMap(child, map);
|
|
2301
3422
|
}
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
const data = await response.json();
|
|
2315
|
-
this._structureData = data;
|
|
2316
|
-
this._oidNodeMap.clear();
|
|
2317
|
-
if (data.trees) for (const tree of data.trees) this._buildOidNodeMap(tree, this._oidNodeMap);
|
|
2318
|
-
return data;
|
|
2319
|
-
} catch (error) {
|
|
2320
|
-
console.error("[GLTFParserPlugin] Error loading structure.json:", error);
|
|
2321
|
-
return null;
|
|
2322
|
-
}
|
|
2323
|
-
}
|
|
2324
|
-
async _ensureStructureLoaded() {
|
|
3423
|
+
/** 仅根 tileset 变化时重解析 structureUri(子 tileset 的 load-tileset 不会触发) */
|
|
3424
|
+
_onLoadRootTilesetCB = () => {
|
|
3425
|
+
this._structureData = null;
|
|
3426
|
+
this._oidNodeMap.clear();
|
|
3427
|
+
this._structureEmbedResolved = false;
|
|
3428
|
+
this._syncStructureFromTileset();
|
|
3429
|
+
};
|
|
3430
|
+
/**
|
|
3431
|
+
* 从已加载根 tileset 的内嵌 structure(优先 asset.extras.maptalks.structureUri)同步解压并建索引。
|
|
3432
|
+
* rootTileset 尚未就绪时返回 null,可稍后再次调用;已成功或已判定无内嵌数据后见 _structureEmbedResolved。
|
|
3433
|
+
*/
|
|
3434
|
+
_syncStructureFromTileset() {
|
|
2325
3435
|
if (this._structureData) return this._structureData;
|
|
2326
|
-
if (
|
|
2327
|
-
|
|
3436
|
+
if (this._structureEmbedResolved) return null;
|
|
3437
|
+
if (!this.tiles?.rootTileset) return null;
|
|
3438
|
+
const embedded = parseEmbeddedStructureDataFromTilesSync(this.tiles);
|
|
3439
|
+
this._structureEmbedResolved = true;
|
|
3440
|
+
if (!embedded) return null;
|
|
3441
|
+
this._structureData = embedded;
|
|
3442
|
+
this._oidNodeMap.clear();
|
|
3443
|
+
if (embedded.trees) for (const tree of embedded.trees) this._buildOidNodeMap(tree, this._oidNodeMap);
|
|
3444
|
+
return embedded;
|
|
2328
3445
|
}
|
|
2329
3446
|
/**
|
|
2330
|
-
* 根据 oid
|
|
2331
|
-
* 包含 bbox、children、name 等完整结构信息
|
|
2332
|
-
* 首次调用时会自动从 tileset URL 推导并请求 structure.json
|
|
3447
|
+
* 根据 oid 获取结构树节点(数据来自 tileset 内嵌 structureUri 同步解压)
|
|
2333
3448
|
*/
|
|
2334
|
-
|
|
2335
|
-
|
|
3449
|
+
getNodeTreeByOid(oid) {
|
|
3450
|
+
this._syncStructureFromTileset();
|
|
2336
3451
|
return this._oidNodeMap.get(oid) ?? null;
|
|
2337
3452
|
}
|
|
2338
3453
|
/**
|
|
2339
|
-
* 根据 oid
|
|
3454
|
+
* 根据 oid 数组批量获取结构树节点
|
|
2340
3455
|
*/
|
|
2341
|
-
|
|
2342
|
-
|
|
3456
|
+
getNodeTreeByOids(oids) {
|
|
3457
|
+
this._syncStructureFromTileset();
|
|
2343
3458
|
const result = /* @__PURE__ */ new Map();
|
|
2344
3459
|
for (const oid of oids) {
|
|
2345
3460
|
const node = this._oidNodeMap.get(oid);
|
|
@@ -2348,41 +3463,58 @@ var GLTFParserPlugin = class {
|
|
|
2348
3463
|
return result;
|
|
2349
3464
|
}
|
|
2350
3465
|
/**
|
|
2351
|
-
*
|
|
2352
|
-
*
|
|
3466
|
+
* 根据 oid 从结构数据取轴对齐包围盒(`bbox` 为 `[minX,minY,minZ,maxX,maxY,maxZ]`,与 `selectByBox` 一致)
|
|
3467
|
+
* @returns 无对应节点或缺少有效 bbox 时返回 `null`
|
|
3468
|
+
*/
|
|
3469
|
+
getBoundingBoxByOid(oid) {
|
|
3470
|
+
this._syncStructureFromTileset();
|
|
3471
|
+
return bboxArrayToBox3(this._oidNodeMap.get(oid)?.bbox);
|
|
3472
|
+
}
|
|
3473
|
+
/**
|
|
3474
|
+
* 计算给定 OID 集合的几何中心(世界坐标系与结构 bbox / 瓦片 mesh 一致)。
|
|
3475
|
+
* 优先合并结构树中的轴对齐 bbox;若无有效 bbox 则合并对应 split mesh 的世界包围盒。
|
|
3476
|
+
*/
|
|
3477
|
+
getCenterByOids(oids) {
|
|
3478
|
+
if (!this.tiles || oids.length === 0) return null;
|
|
3479
|
+
const unique = [...new Set(oids)];
|
|
3480
|
+
if (unique.length === 0) return null;
|
|
3481
|
+
return this._getCenterFromOidList(unique);
|
|
3482
|
+
}
|
|
3483
|
+
/**
|
|
3484
|
+
* 按属性条件筛选构件(语义同 `setStyle` 的 `show` / conditions 中的表达式字符串),
|
|
3485
|
+
* 返回筛选结果的整体中心点;合并方式同 {@link getCenterByOids}。
|
|
3486
|
+
*/
|
|
3487
|
+
getCenterByCondition(condition) {
|
|
3488
|
+
if (!this.tiles) return null;
|
|
3489
|
+
const cond = condition.trim();
|
|
3490
|
+
if (!cond) return null;
|
|
3491
|
+
const targetOids = [];
|
|
3492
|
+
for (const oid of getAllOidsFromTiles(this.tiles)) if (evaluateStyleCondition(cond, getPropertyDataByOid(this.tiles, oid))) targetOids.push(oid);
|
|
3493
|
+
if (targetOids.length === 0) return null;
|
|
3494
|
+
return this._getCenterFromOidList(targetOids);
|
|
3495
|
+
}
|
|
3496
|
+
/**
|
|
3497
|
+
* 完整结构数据(与内嵌 structure JSON 一致)
|
|
2353
3498
|
*/
|
|
2354
|
-
|
|
2355
|
-
return this.
|
|
3499
|
+
getStructureData() {
|
|
3500
|
+
return this._syncStructureFromTileset();
|
|
2356
3501
|
}
|
|
2357
3502
|
/**
|
|
2358
|
-
*
|
|
2359
|
-
* @param box 查询用的 Box3 范围,坐标系与 structure.json 中 bbox 一致
|
|
2360
|
-
* @returns 范围内所有构件的 oid 数组
|
|
3503
|
+
* 选择包围盒范围内的构件(坐标系与结构 bbox 一致)
|
|
2361
3504
|
*/
|
|
2362
|
-
|
|
2363
|
-
|
|
3505
|
+
selectByBox(box) {
|
|
3506
|
+
this._syncStructureFromTileset();
|
|
2364
3507
|
return selectByBoxFromOidMap(this._oidNodeMap, box);
|
|
2365
3508
|
}
|
|
2366
3509
|
/**
|
|
2367
|
-
*
|
|
2368
|
-
* @param polygon 多边形顶点数组(Vector3),按顺序连接构成闭合多边形
|
|
2369
|
-
* @param axis 投影平面,决定使用 bbox 的哪两个轴做 2D 判定
|
|
2370
|
-
* - 'xz'(默认):俯视图,取 bbox 的 x/z 坐标
|
|
2371
|
-
* - 'xy':正视图,取 bbox 的 x/y 坐标
|
|
2372
|
-
* - 'yz':侧视图,取 bbox 的 y/z 坐标
|
|
2373
|
-
* @returns 范围内所有构件的 oid 数组
|
|
3510
|
+
* 选择多边形(平面投影)范围内的构件
|
|
2374
3511
|
*/
|
|
2375
|
-
|
|
2376
|
-
|
|
3512
|
+
selectByPolygon(polygon, axis = "xz") {
|
|
3513
|
+
this._syncStructureFromTileset();
|
|
2377
3514
|
return selectByPolygonFromOidMap(this._oidNodeMap, polygon, axis);
|
|
2378
3515
|
}
|
|
2379
|
-
_getModelInfoUrl() {
|
|
2380
|
-
const rootURL = this.tiles?.rootURL;
|
|
2381
|
-
if (!rootURL) return null;
|
|
2382
|
-
return rootURL.replace(/[^/]+$/, "modelInfo.json");
|
|
2383
|
-
}
|
|
2384
3516
|
async _fetchModelInfo() {
|
|
2385
|
-
const url = this.
|
|
3517
|
+
const url = this._sidecarJsonUrl("modelInfo.json");
|
|
2386
3518
|
if (!url) {
|
|
2387
3519
|
console.warn("[GLTFParserPlugin] Cannot derive modelInfo.json URL: tiles not initialized");
|
|
2388
3520
|
return null;
|
|
@@ -2432,83 +3564,41 @@ var GLTFParserPlugin = class {
|
|
|
2432
3564
|
scene.traverse((c) => {
|
|
2433
3565
|
if (c.material) this._setupMaterial(c);
|
|
2434
3566
|
});
|
|
3567
|
+
applyVisibilityToScene(scene, new Set(this.oids));
|
|
2435
3568
|
}
|
|
2436
3569
|
_notifyCollectors() {
|
|
2437
3570
|
for (const collector of this.collectors) collector._updateMeshes();
|
|
3571
|
+
this._styleHelper?.onTilesLoadEnd();
|
|
2438
3572
|
}
|
|
2439
3573
|
_registerCollector(collector) {
|
|
2440
3574
|
this.collectors.add(collector);
|
|
2441
3575
|
}
|
|
2442
3576
|
_unregisterCollector(collector) {
|
|
2443
|
-
const
|
|
3577
|
+
const key = collector.getCacheKey();
|
|
2444
3578
|
this.collectors.delete(collector);
|
|
2445
|
-
this.collectorCache.delete(
|
|
2446
|
-
this._interactionFilter.onUnregisterCollector(
|
|
2447
|
-
}
|
|
2448
|
-
_updateWebGLLimits() {
|
|
2449
|
-
const gl = this.renderer.getContext();
|
|
2450
|
-
this.maxUniformVectors = gl.getParameter(gl.MAX_FRAGMENT_UNIFORM_VECTORS);
|
|
3579
|
+
this.collectorCache.delete(key);
|
|
3580
|
+
this._interactionFilter.onUnregisterCollector(key);
|
|
2451
3581
|
}
|
|
2452
3582
|
/**
|
|
2453
|
-
*
|
|
3583
|
+
* 遍历所有已加载瓦片,应用可见性过滤
|
|
2454
3584
|
*/
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
const
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
3585
|
+
_applyVisibilityToAllTiles() {
|
|
3586
|
+
if (!this.tiles) return;
|
|
3587
|
+
const hiddenSet = new Set(this.oids);
|
|
3588
|
+
this.tiles.traverse((tile) => {
|
|
3589
|
+
const tileWithCache = tile;
|
|
3590
|
+
if (tileWithCache.engineData?.scene) applyVisibilityToScene(tileWithCache.engineData.scene, hiddenSet);
|
|
3591
|
+
return true;
|
|
3592
|
+
}, null);
|
|
2463
3593
|
}
|
|
2464
3594
|
/**
|
|
2465
|
-
*
|
|
3595
|
+
* 设置材质(DoubleSide 等基础配置)
|
|
2466
3596
|
*/
|
|
2467
3597
|
_setupMaterial(mesh) {
|
|
2468
3598
|
const material = mesh.material;
|
|
2469
3599
|
if (material.userData._meshHelperSetup) return;
|
|
2470
3600
|
material.userData._meshHelperSetup = true;
|
|
2471
3601
|
material.side = DoubleSide;
|
|
2472
|
-
const previousOnBeforeCompile = material.onBeforeCompile;
|
|
2473
|
-
if (!material.defines) material.defines = {};
|
|
2474
|
-
material.userData._materialFeatureIdCount = this.featureIdCount;
|
|
2475
|
-
Object.defineProperty(material.defines, "FEATURE_ID_COUNT", {
|
|
2476
|
-
get: () => {
|
|
2477
|
-
if (material.userData._materialFeatureIdCount !== this.featureIdCount) {
|
|
2478
|
-
material.userData._materialFeatureIdCount = this.featureIdCount;
|
|
2479
|
-
material.needsUpdate = true;
|
|
2480
|
-
}
|
|
2481
|
-
return material.userData._materialFeatureIdCount;
|
|
2482
|
-
},
|
|
2483
|
-
enumerable: true,
|
|
2484
|
-
configurable: true
|
|
2485
|
-
});
|
|
2486
|
-
material.onBeforeCompile = (shader, renderer) => {
|
|
2487
|
-
previousOnBeforeCompile?.call(material, shader, renderer);
|
|
2488
|
-
if (shader.vertexShader.includes("varying float vFeatureId;")) return;
|
|
2489
|
-
shader.uniforms.hiddenFeatureIds = new FeatureIdUniforms(mesh, this);
|
|
2490
|
-
shader.vertexShader = shader.vertexShader.replace("#include <common>", `#include <common>
|
|
2491
|
-
attribute float _feature_id_0;
|
|
2492
|
-
varying float vFeatureId;`);
|
|
2493
|
-
shader.vertexShader = shader.vertexShader.replace("#include <begin_vertex>", `#include <begin_vertex>
|
|
2494
|
-
vFeatureId = _feature_id_0;`);
|
|
2495
|
-
shader.fragmentShader = shader.fragmentShader.replace("#include <common>", `#include <common>
|
|
2496
|
-
uniform float hiddenFeatureIds[FEATURE_ID_COUNT];
|
|
2497
|
-
varying float vFeatureId;
|
|
2498
|
-
|
|
2499
|
-
bool shouldHideFeature(float featureId) {
|
|
2500
|
-
for(int i = 0; i < FEATURE_ID_COUNT; i++) {
|
|
2501
|
-
if(abs(hiddenFeatureIds[i] - featureId) < 0.001) {
|
|
2502
|
-
return true;
|
|
2503
|
-
}
|
|
2504
|
-
}
|
|
2505
|
-
return false;
|
|
2506
|
-
}`);
|
|
2507
|
-
shader.fragmentShader = shader.fragmentShader.replace("void main() {", `void main() {
|
|
2508
|
-
if(shouldHideFeature(vFeatureId)) {
|
|
2509
|
-
discard;
|
|
2510
|
-
}`);
|
|
2511
|
-
};
|
|
2512
3602
|
}
|
|
2513
3603
|
/**
|
|
2514
3604
|
* Query feature information from intersection
|
|
@@ -2561,52 +3651,120 @@ var GLTFParserPlugin = class {
|
|
|
2561
3651
|
return this._interactionFilter.getIsolatedOids();
|
|
2562
3652
|
}
|
|
2563
3653
|
/**
|
|
2564
|
-
*
|
|
3654
|
+
* 合并 OID 列表对应的结构 bbox;若无可用 bbox 则使用 split mesh 世界包围盒并求中心。
|
|
2565
3655
|
*/
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
const
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
if (!
|
|
2573
|
-
|
|
2574
|
-
|
|
3656
|
+
_getCenterFromOidList(oids) {
|
|
3657
|
+
this._syncStructureFromTileset();
|
|
3658
|
+
const union = new Box3();
|
|
3659
|
+
let hasStructureBox = false;
|
|
3660
|
+
for (const oid of oids) {
|
|
3661
|
+
const b = this.getBoundingBoxByOid(oid);
|
|
3662
|
+
if (b && !b.isEmpty()) if (!hasStructureBox) {
|
|
3663
|
+
union.copy(b);
|
|
3664
|
+
hasStructureBox = true;
|
|
3665
|
+
} else union.union(b);
|
|
3666
|
+
}
|
|
3667
|
+
if (hasStructureBox && !union.isEmpty()) return union.getCenter(new Vector3());
|
|
3668
|
+
const meshes = this._getMeshesByOidsInternal(oids);
|
|
3669
|
+
if (meshes.length === 0) return null;
|
|
3670
|
+
const meshBox = new Box3();
|
|
3671
|
+
for (const mesh of meshes) {
|
|
3672
|
+
mesh.updateMatrixWorld(true);
|
|
3673
|
+
meshBox.expandByObject(mesh);
|
|
3674
|
+
}
|
|
3675
|
+
if (meshBox.isEmpty()) return null;
|
|
3676
|
+
return meshBox.getCenter(new Vector3());
|
|
3677
|
+
}
|
|
3678
|
+
/**
|
|
3679
|
+
* 按 OID 集合:每个瓦片 mesh 只生成 **一个** 合并后的 split mesh(同一组 oid / condition 一条几何)
|
|
3680
|
+
*/
|
|
3681
|
+
_getMergedSplitMeshesForOidSet(oidSet) {
|
|
3682
|
+
if (!this.tiles || oidSet.size === 0) return [];
|
|
3683
|
+
const sortedKey = [...oidSet].sort((a, b) => a - b).join(",");
|
|
3684
|
+
const result = [];
|
|
3685
|
+
const candidateTiles = /* @__PURE__ */ new Set();
|
|
3686
|
+
for (const oid of oidSet) for (const tm of getTileMeshesByOid(this.tiles, oid)) candidateTiles.add(tm);
|
|
3687
|
+
for (const tileMesh of candidateTiles) {
|
|
3688
|
+
const cacheKey = `merged|${tileMesh.uuid}|${sortedKey}`;
|
|
3689
|
+
let cached = this.splitMeshCache.get(cacheKey);
|
|
3690
|
+
if (!cached) {
|
|
3691
|
+
const m = splitMeshByOidsMerged(tileMesh, oidSet);
|
|
3692
|
+
cached = m ? [m] : [];
|
|
3693
|
+
this.splitMeshCache.set(cacheKey, cached);
|
|
2575
3694
|
}
|
|
2576
|
-
|
|
3695
|
+
result.push(...cached);
|
|
2577
3696
|
}
|
|
2578
|
-
return
|
|
3697
|
+
return result;
|
|
2579
3698
|
}
|
|
2580
3699
|
/**
|
|
2581
|
-
*
|
|
2582
|
-
* MeshCollector 会监听瓦片变化,自动更新 meshes 并触发 mesh-change 事件
|
|
2583
|
-
* 内部缓存:相同 oid 多次调用会返回同一个 collector 实例
|
|
3700
|
+
* 内部方法:根据单个 oid 获取 split mesh(每瓦片合并为一条)
|
|
2584
3701
|
*/
|
|
2585
|
-
|
|
2586
|
-
|
|
3702
|
+
_getMeshesByOidInternal(oid) {
|
|
3703
|
+
return this._getMergedSplitMeshesForOidSet(new Set([oid]));
|
|
3704
|
+
}
|
|
3705
|
+
/**
|
|
3706
|
+
* 内部方法:根据多个 oid 获取合并 split mesh(每瓦片一条,而非每 oid 一条)
|
|
3707
|
+
*/
|
|
3708
|
+
_getMeshesByOidsInternal(oids) {
|
|
3709
|
+
return this._getMergedSplitMeshesForOidSet(new Set(oids));
|
|
3710
|
+
}
|
|
3711
|
+
/**
|
|
3712
|
+
* 按查询收集 mesh:可只传 oids、只传 condition(全场景 OID 上筛选)、或两者组合
|
|
3713
|
+
* condition 与 setStyle 的 show / conditions 中字符串表达式语义一致
|
|
3714
|
+
*/
|
|
3715
|
+
_getMeshesForCollectorQueryInternal(params) {
|
|
3716
|
+
if (!this.tiles) return [];
|
|
3717
|
+
const cond = params.condition?.trim();
|
|
3718
|
+
let targetOids;
|
|
3719
|
+
if (!cond) {
|
|
3720
|
+
if (params.oids.length === 0) return [];
|
|
3721
|
+
targetOids = [...new Set(params.oids)].sort((a, b) => a - b);
|
|
3722
|
+
} else {
|
|
3723
|
+
const candidate = params.oids.length === 0 ? getAllOidsFromTiles(this.tiles) : [...new Set(params.oids)];
|
|
3724
|
+
targetOids = [];
|
|
3725
|
+
for (const oid of candidate) if (evaluateStyleCondition(cond, getPropertyDataByOid(this.tiles, oid))) targetOids.push(oid);
|
|
3726
|
+
targetOids.sort((a, b) => a - b);
|
|
3727
|
+
}
|
|
3728
|
+
return this._getMeshesByOidsInternal(targetOids);
|
|
3729
|
+
}
|
|
3730
|
+
/**
|
|
3731
|
+
* 根据查询获取 MeshCollector(oids + 可选 condition,缓存键相同则复用实例)
|
|
3732
|
+
*/
|
|
3733
|
+
getMeshCollectorByCondition(query) {
|
|
3734
|
+
const hasOids = normalizeMeshCollectorOids(query.oids ?? []).length > 0;
|
|
3735
|
+
const hasCond = Boolean(query.condition?.trim());
|
|
3736
|
+
if (!hasOids && !hasCond) throw new Error("getMeshCollectorByCondition requires non-empty oids and/or a condition string");
|
|
3737
|
+
const key = meshCollectorQueryCacheKey(query);
|
|
3738
|
+
const existing = this.collectorCache.get(key);
|
|
2587
3739
|
if (existing) return existing;
|
|
2588
|
-
const collector = new MeshCollector(
|
|
2589
|
-
this.collectorCache.set(
|
|
2590
|
-
this._interactionFilter.onCollectorMeshChange(
|
|
3740
|
+
const collector = new MeshCollector(query, this);
|
|
3741
|
+
this.collectorCache.set(key, collector);
|
|
3742
|
+
this._interactionFilter.onCollectorMeshChange(key, collector.meshes);
|
|
2591
3743
|
collector.addEventListener("mesh-change", (event) => {
|
|
2592
|
-
this._interactionFilter.onCollectorMeshChange(
|
|
3744
|
+
this._interactionFilter.onCollectorMeshChange(key, event.meshes);
|
|
2593
3745
|
});
|
|
2594
3746
|
return collector;
|
|
2595
3747
|
}
|
|
2596
3748
|
/**
|
|
3749
|
+
* 根据单个 oid 获取 MeshCollector(等价于 getMeshCollectorByCondition({ oids: [oid] }))
|
|
3750
|
+
*/
|
|
3751
|
+
getMeshCollectorByOid(oid) {
|
|
3752
|
+
return this.getMeshCollectorByCondition({ oids: [oid] });
|
|
3753
|
+
}
|
|
3754
|
+
/**
|
|
2597
3755
|
* Hide the corresponding part of the original mesh according to the OID array
|
|
2598
3756
|
*/
|
|
2599
|
-
|
|
3757
|
+
hidePartsByOids(oids) {
|
|
2600
3758
|
this.oids = oids;
|
|
2601
|
-
this.
|
|
3759
|
+
this._applyVisibilityToAllTiles();
|
|
2602
3760
|
}
|
|
2603
3761
|
/**
|
|
2604
3762
|
* Restore the display of the corresponding mesh according to the OID array
|
|
2605
3763
|
*/
|
|
2606
|
-
|
|
3764
|
+
showPartsByOids(oids) {
|
|
2607
3765
|
const oidSet = new Set(oids);
|
|
2608
3766
|
this.oids = this.oids.filter((existingOid) => !oidSet.has(existingOid));
|
|
2609
|
-
this.
|
|
3767
|
+
this._applyVisibilityToAllTiles();
|
|
2610
3768
|
}
|
|
2611
3769
|
/**
|
|
2612
3770
|
* 根据 oid 数组设置构件颜色
|
|
@@ -2619,7 +3777,7 @@ var GLTFParserPlugin = class {
|
|
|
2619
3777
|
}
|
|
2620
3778
|
/**
|
|
2621
3779
|
* 恢复指定构件的颜色
|
|
2622
|
-
* 从场景移除 split mesh
|
|
3780
|
+
* 从场景移除 split mesh,恢复原 mesh 显示
|
|
2623
3781
|
* @param oids 构件 OID 数组
|
|
2624
3782
|
*/
|
|
2625
3783
|
restorePartColorByOids(oids) {
|
|
@@ -2681,17 +3839,72 @@ var GLTFParserPlugin = class {
|
|
|
2681
3839
|
this._partFrameHelper?.clearAllFrameParts();
|
|
2682
3840
|
}
|
|
2683
3841
|
/**
|
|
3842
|
+
* 设置指定构件的线框填充颜色
|
|
3843
|
+
* @param oids 构件 OID 数组
|
|
3844
|
+
* @param color 颜色值,支持 hex 数字、颜色字符串(如 "#ff0000")、THREE.Color 对象
|
|
3845
|
+
*/
|
|
3846
|
+
setFrameFillColor(oids, color) {
|
|
3847
|
+
this._partFrameHelper?.setFrameFillColor(oids, color);
|
|
3848
|
+
}
|
|
3849
|
+
/**
|
|
3850
|
+
* 设置指定构件的线框边框颜色
|
|
3851
|
+
* @param oids 构件 OID 数组
|
|
3852
|
+
* @param color 颜色值,支持 hex 数字、颜色字符串(如 "#ff0000")、THREE.Color 对象
|
|
3853
|
+
*/
|
|
3854
|
+
setFrameEdgeColor(oids, color) {
|
|
3855
|
+
this._partFrameHelper?.setFrameEdgeColor(oids, color);
|
|
3856
|
+
}
|
|
3857
|
+
/**
|
|
3858
|
+
* 设置构件样式(条件可见性 + 条件材质)
|
|
3859
|
+
* @param style 样式配置,传 null 清除样式
|
|
3860
|
+
*/
|
|
3861
|
+
setStyle(style) {
|
|
3862
|
+
this._styleHelper?.setStyle(style);
|
|
3863
|
+
}
|
|
3864
|
+
/**
|
|
3865
|
+
* 当前样式配置,只读
|
|
3866
|
+
*/
|
|
3867
|
+
get style() {
|
|
3868
|
+
return this._styleHelper?.style ?? null;
|
|
3869
|
+
}
|
|
3870
|
+
/**
|
|
3871
|
+
* 清除构件样式
|
|
3872
|
+
*/
|
|
3873
|
+
clearStyle() {
|
|
3874
|
+
this._styleHelper?.clearStyle();
|
|
3875
|
+
}
|
|
3876
|
+
/**
|
|
3877
|
+
* 高亮指定构件(语义与 setStyle 一致:show、conditions、可选 oids,另需 name 标识分组)
|
|
3878
|
+
* @param options 高亮配置
|
|
3879
|
+
*/
|
|
3880
|
+
highlight(options) {
|
|
3881
|
+
this._partHighlightHelper?.highlight(options);
|
|
3882
|
+
}
|
|
3883
|
+
/**
|
|
3884
|
+
* 取消指定名称的高亮
|
|
3885
|
+
* @param name 高亮组名称
|
|
3886
|
+
*/
|
|
3887
|
+
cancelHighlight(name) {
|
|
3888
|
+
this._partHighlightHelper?.cancelHighlight(name);
|
|
3889
|
+
}
|
|
3890
|
+
/**
|
|
3891
|
+
* 取消所有高亮
|
|
3892
|
+
*/
|
|
3893
|
+
cancelAllHighlight() {
|
|
3894
|
+
this._partHighlightHelper?.cancelAllHighlight();
|
|
3895
|
+
}
|
|
3896
|
+
/**
|
|
2684
3897
|
* Restore the original materials of the mesh
|
|
2685
3898
|
*/
|
|
2686
|
-
|
|
3899
|
+
showAllParts() {
|
|
2687
3900
|
this.oids = [];
|
|
2688
|
-
this.
|
|
3901
|
+
this._applyVisibilityToAllTiles();
|
|
2689
3902
|
}
|
|
2690
3903
|
/**
|
|
2691
|
-
*
|
|
3904
|
+
* 获取当前隐藏的 OID 数量(兼容旧 API)
|
|
2692
3905
|
*/
|
|
2693
3906
|
getFeatureIdCount() {
|
|
2694
|
-
return this.
|
|
3907
|
+
return this.oids.length;
|
|
2695
3908
|
}
|
|
2696
3909
|
/**
|
|
2697
3910
|
* Plugin disposal
|
|
@@ -2701,6 +3914,7 @@ var GLTFParserPlugin = class {
|
|
|
2701
3914
|
this.tiles.manager.removeHandler(this._gltfRegex);
|
|
2702
3915
|
this.tiles.removeEventListener("load-model", this._onLoadModelCB);
|
|
2703
3916
|
this.tiles.removeEventListener("tiles-load-end", this._onTilesLoadEndCB);
|
|
3917
|
+
this.tiles.removeEventListener("load-root-tileset", this._onLoadRootTilesetCB);
|
|
2704
3918
|
}
|
|
2705
3919
|
if (this._loader) this._loader.removeListeners();
|
|
2706
3920
|
for (const collector of this.collectors) collector.dispose();
|
|
@@ -2709,7 +3923,7 @@ var GLTFParserPlugin = class {
|
|
|
2709
3923
|
this.splitMeshCache.clear();
|
|
2710
3924
|
this._structureData = null;
|
|
2711
3925
|
this._oidNodeMap.clear();
|
|
2712
|
-
this.
|
|
3926
|
+
this._structureEmbedResolved = false;
|
|
2713
3927
|
this._modelInfo = null;
|
|
2714
3928
|
this._modelInfoPromise = null;
|
|
2715
3929
|
this._interactionFilter.dispose();
|
|
@@ -2718,11 +3932,15 @@ var GLTFParserPlugin = class {
|
|
|
2718
3932
|
this._partBlinkHelper = null;
|
|
2719
3933
|
this._partFrameHelper?.dispose();
|
|
2720
3934
|
this._partFrameHelper = null;
|
|
3935
|
+
this._styleHelper?.dispose();
|
|
3936
|
+
this._styleHelper = null;
|
|
3937
|
+
this._partHighlightHelper?.dispose();
|
|
3938
|
+
this._partHighlightHelper = null;
|
|
2721
3939
|
this._loader = null;
|
|
2722
3940
|
this.tiles = null;
|
|
2723
3941
|
}
|
|
2724
3942
|
};
|
|
2725
3943
|
//#endregion
|
|
2726
|
-
export { GLTFParserPlugin, MeshCollector };
|
|
3944
|
+
export { GLTFParserPlugin, MeshCollector, clearStyleConditionCache, decodeGzipBase64DataUriSync, evaluateStyleCondition, getStructureDataUriFromTileset, meshCollectorGroupKey, meshCollectorQueryCacheKey, normalizeMeshCollectorOids, parseEmbeddedStructureDataFromTilesSync };
|
|
2727
3945
|
|
|
2728
3946
|
//# sourceMappingURL=gltf-parser-plugin.module.js.map
|