Merge branch 'main' of github.com:specklesystems/speckle-server into alessandro/web-1172-change-the-users-repository-to-abstract-the-email-field-in

This commit is contained in:
Alessandro Magionami
2024-07-24 11:16:28 +02:00
7 changed files with 156 additions and 5 deletions
+5 -1
View File
@@ -105,7 +105,7 @@ const getStream = () => {
// prettier-ignore
// 'https://speckle.xyz/streams/da9e320dad/commits/5388ef24b8?c=%5B-7.66134,10.82932,6.41935,-0.07739,-13.88552,1.8697,0,1%5D'
// Revit sample house (good for bim-like stuff with many display meshes)
'https://speckle.xyz/streams/da9e320dad/commits/5388ef24b8'
// 'https://speckle.xyz/streams/da9e320dad/commits/5388ef24b8'
// 'https://latest.speckle.dev/streams/c1faab5c62/commits/ab1a1ab2b6'
// 'https://speckle.xyz/streams/da9e320dad/commits/5388ef24b8'
// 'https://latest.speckle.dev/streams/58b5648c4d/commits/60371ecb2d'
@@ -393,6 +393,10 @@ const getStream = () => {
// 'https://app.speckle.systems/projects/47bbaf594f/models/de52414725f8937b1f0e2f550ef9ca52'
// qGIS sRGB vertex colors
// 'https://latest.speckle.systems/projects/5a6609a4b9/models/10f4931e8c'
// DUI3 blocks
// 'https://latest.speckle.systems/projects/126cd4b7bb/models/c6f3f309a2'
'https://latest.speckle.systems/projects/126cd4b7bb/models/6b62c61a22'
// 'https://latest.speckle.systems/projects/126cd4b7bb/models/4dc5265453'
)
}
+1
View File
@@ -25,6 +25,7 @@ export type SpeckleObject = {
name?: string
referencedId?: string
units?: string
applicationId?: string
}
export interface ViewerParams {
@@ -19,6 +19,7 @@ export enum SpeckleType {
RevitInstance = 'RevitInstance',
Text = 'Text',
Transform = 'Transform',
InstanceProxy = 'InstanceProxy',
Unknown = 'Unknown'
}
@@ -1,8 +1,8 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import { MathUtils } from 'three'
import { MathUtils, Matrix4 } from 'three'
import { type TreeNode, WorldTree } from '../../tree/WorldTree.js'
import { NodeMap } from '../../tree/NodeMap.js'
import type { SpeckleObject } from '../../../index.js'
import { type SpeckleObject } from '../../../index.js'
import type ObjectLoader from '@speckle/objectloader'
import Logger from '../../utils/Logger.js'
@@ -22,6 +22,9 @@ export default class SpeckleConverter {
private spoofIDs = false
private tree: WorldTree
private typeLookupTable: { [type: string]: string } = {}
private instanceDefinitionLookupTable: { [id: string]: TreeNode } = {}
private instancedObjectsLookupTable: { [id: string]: SpeckleObject } = {}
private instanceProxies: { [id: string]: TreeNode } = {}
private instanceCounter = 0
private readonly NodeConverterMapping: {
@@ -44,6 +47,8 @@ export default class SpeckleConverter {
RevitInstance: this.RevitInstanceToNode.bind(this),
Text: this.TextToNode.bind(this),
Dimension: this.DimensionToNode.bind(this),
InstanceDefinitionProxy: this.InstanceDefinitionProxyToNode.bind(this),
InstanceProxy: this.InstanceProxyToNode.bind(this),
Parameter: null
}
@@ -521,6 +526,130 @@ export default class SpeckleConverter {
}
}
private async InstanceDefinitionProxyToNode(obj: SpeckleObject, node: TreeNode) {
if (!obj.applicationId) {
Logger.warn(`Instance Definition Proxy ${obj.id} has no applicationId`)
return
}
this.instanceDefinitionLookupTable[obj.applicationId] = node
}
private async InstanceProxyToNode(obj: SpeckleObject, node: TreeNode) {
if (!obj.applicationId) {
Logger.warn(`Instance proxy ${obj.id} has no application id`)
return
}
this.instanceProxies[obj.applicationId] = node
return
}
private getInstanceProxyDefinitionId(obj: SpeckleObject): string {
return (obj.DefinitionId || obj.definitionId) as string
}
private getInstanceProxyTransform(obj: SpeckleObject): Array<number> {
if (!(obj.transform || obj.Transform)) {
return new Matrix4().toArray()
}
return (obj.transform || obj.Transform) as Array<number>
}
private getInstanceProxyDefinitionObjects(obj: SpeckleObject): Array<string> {
return (obj.Objects || obj.objects) as Array<string>
}
private createTransformNode(obj: SpeckleObject) {
const transformNodeId = MathUtils.generateUUID()
const transformData = this.getEmptyTransformData(transformNodeId)
transformData.units = obj.units as string
transformData.matrix = this.getInstanceProxyTransform(obj)
return this.tree.parse({
id: transformNodeId,
raw: transformData,
atomic: false,
children: []
})
}
private async ConvertInstanceProxyToNode(obj: SpeckleObject, node: TreeNode) {
const definitionId = this.getInstanceProxyDefinitionId(obj)
if (!definitionId) {
Logger.warn(`Instance Proxy ${obj.id} has no definitionId`)
return
}
const definition = this.instanceDefinitionLookupTable[definitionId]
const transformNode = this.createTransformNode(obj)
this.tree.addNode(transformNode, node)
const objectApplicationIds = this.getInstanceProxyDefinitionObjects(
definition.model.raw
)
for (const objectApplicationId of objectApplicationIds) {
const speckleData = this.instancedObjectsLookupTable[objectApplicationId]
const instancedNode = this.tree.parse({
id: this.getCompoundId(speckleData.id, this.instanceCounter++),
raw: speckleData,
atomic: false,
children: [],
instanced: true
})
this.tree.addNode(instancedNode, transformNode)
await this.convertToNode(speckleData, instancedNode)
}
}
public async convertInstances() {
/** uh, oh */
this.NodeConverterMapping.InstanceProxy = this.ConvertInstanceProxyToNode.bind(this)
/** Find the nodes that need to be 'consumed' */
const consumeApplicationIds: { [id: string]: TreeNode | null } = {}
let consumeApplicationIdsCount = 0
for (const k in this.instanceDefinitionLookupTable) {
const definition = this.instanceDefinitionLookupTable[k]
const objects = this.getInstanceProxyDefinitionObjects(definition.model.raw)
for (let i = 0; i < objects.length; i++) {
consumeApplicationIds[objects[i].toString()] = null
consumeApplicationIdsCount++
}
}
/** Do a short async walk */
await this.tree.walkAsync((node: TreeNode) => {
if (!node.model.raw.applicationId) return true
const applicationId = node.model.raw.applicationId.toString()
if (consumeApplicationIds[applicationId] !== undefined) {
consumeApplicationIds[applicationId] = node
consumeApplicationIdsCount--
}
/** Break out when all applicationIds are accounted for*/
if (consumeApplicationIdsCount === 0) return false
return true
})
/** Consume them */
for (const k in consumeApplicationIds) {
const objectNode = consumeApplicationIds[k]
if (!objectNode) {
Logger.error(`Consumable applicationId ${k} could not be found`)
continue
}
/** Store the speckle object data */
this.instancedObjectsLookupTable[k] = objectNode.model.raw
/** Remove the instance from the list (if needed) */
delete this.instanceProxies[k]
/** Remove the node from the world tree */
this.tree.removeNode(objectNode, true)
}
/** Remaining instance proxies should all be valid */
for (const k in this.instanceProxies) {
const node = this.instanceProxies[k]
/** Create the final instances */
await this.convertToNode(node.model.raw, node)
}
}
private async PointcloudToNode(obj: SpeckleObject, node: TreeNode) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
//@ts-ignore
@@ -70,6 +70,8 @@ export class SpeckleGeometryConverter extends GeometryConverter {
return this.TextToGeometryData(node)
case SpeckleType.Transform:
return this.TransformToGeometryData(node)
case SpeckleType.InstanceProxy:
return this.InstanceProxyToGeometyData(node)
case SpeckleType.Unknown:
// console.warn(`Skipping geometry conversion for ${type}`)
return null
@@ -176,6 +178,11 @@ export class SpeckleGeometryConverter extends GeometryConverter {
return null
}
private InstanceProxyToGeometyData(node: NodeData): GeometryData | null {
node
return null
}
/**
* POINT CLOUD
*/
@@ -128,6 +128,8 @@ export class SpeckleLoader extends Loader {
return Promise.resolve(false)
}
await this.converter.convertInstances()
const t0 = performance.now()
const geometryConverter = new SpeckleGeometryConverter()
@@ -108,8 +108,14 @@ export class WorldTree {
if (this.nodeMaps[parent.model.subtreeId]?.addNode(node)) parent.addChild(node)
}
public removeNode(node: TreeNode): void {
public removeNode(node: TreeNode, removeChildren: boolean): void {
const children = node.children
this.nodeMaps[node.model.subtreeId]?.removeNode(node)
node.drop()
if (!removeChildren || !children) return
for (let k = 0; k < children.length; k++) {
this.removeNode(children[k], removeChildren)
}
}
public findAll(predicate: SearchPredicate, node?: TreeNode): Array<TreeNode> {
@@ -197,7 +203,8 @@ export class WorldTree {
if (subtreeNode) {
this.nodeMaps[subtreeNode[0].model.subtreeId].purge()
delete this.nodeMaps[subtreeNode[0].model.subtreeId]
this.removeNode(subtreeNode[0])
// Potentially true?
this.removeNode(subtreeNode[0], false)
}
return
}