Browse Source

InstancePointManager / LineSegmentManager 重构

master
修宁 6 months ago
parent
commit
744387d77c
  1. 4
      package.json
  2. 843
      pnpm-lock.yaml
  3. 33
      src/core/ModelUtils.ts
  4. 108
      src/core/base/BaseRenderer.ts
  5. 21
      src/core/engine/SceneHelp.ts
  6. 23
      src/core/manager/EntityManager.ts
  7. 122
      src/core/manager/InstancePointManager.ts
  8. 17
      src/core/manager/LabelManager.ts
  9. 235
      src/core/manager/LineSegmentManager.ts
  10. 183
      src/example/example1.js
  11. 5
      src/modules/charger/ChargerRenderer.ts
  12. 5
      src/modules/clx/ClxRenderer.ts
  13. 5
      src/modules/gstore/GstoreRenderer.ts
  14. 77
      src/modules/measure/MeasureRenderer.ts
  15. 5
      src/modules/pallet/PalletRenderer.ts
  16. 5
      src/modules/ptr/PtrRenderer.ts
  17. 6
      src/modules/rack/RackRenderer.ts
  18. 56
      src/types/ModelTypes.ts
  19. 49
      src/types/model.d.ts

4
package.json

@ -13,9 +13,7 @@
"format": "prettier --write src/" "format": "prettier --write src/"
}, },
"dependencies": { "dependencies": {
"@types/fabric": "^5.3.10", "@vueuse/core": "^13.2.0"
"@vueuse/core": "^13.2.0",
"fabric": "^6.7.0"
}, },
"devDependencies": { "devDependencies": {
"@ease-forge/runtime": "^1.0.12", "@ease-forge/runtime": "^1.0.12",

843
pnpm-lock.yaml

File diff suppressed because it is too large

33
src/core/ModelUtils.ts

@ -5,6 +5,39 @@ import type Viewport from '@/core/engine/Viewport'
import { Vector2 } from 'three/src/math/Vector2' import { Vector2 } from 'three/src/math/Vector2'
import EventBus from '@/runtime/EventBus.ts' import EventBus from '@/runtime/EventBus.ts'
import Decimal from 'decimal.js' import Decimal from 'decimal.js'
import type { Object3DLike } from '@/types/ModelTypes.ts'
export function setUserDataForItem(item: ItemJson, object: Object3DLike) {
if (!object.name && item.name) {
object.name = item.name
}
object.userData = {
...object.userData,
t: item.t,
createType: 'point',
entityId: item.id,
draggable: item.dt.protected !== true,
selectable: item.dt.selectable !== false
}
}
export function setUserDataForLine(start: ItemJson, end: ItemJson, type: LinkType, object: Object3DLike) {
const id = getLineId(start.id, end.id, type)
if (!object.name) {
object.name = id
}
object.userData = {
...object.userData,
createType: 'line',
entityId: id,
startId: start.id,
endId: end.id,
draggable: false,
selectable: false,
t: start.t
}
}
/** /**
* *

108
src/core/base/BaseRenderer.ts

@ -1,10 +1,11 @@
import type Viewport from '@/core/engine/Viewport' import type Viewport from '@/core/engine/Viewport'
import * as THREE from 'three' import * as THREE from 'three'
import { getLineId } from '@/core/ModelUtils.ts' import { getLineId, setUserDataForItem, setUserDataForLine } from '@/core/ModelUtils.ts'
import { Line2 } from 'three/examples/jsm/lines/Line2' import { Line2 } from 'three/examples/jsm/lines/Line2'
import InstancePointManager from '@/core/manager/InstancePointManager.ts' import InstancePointManager, { PointManageWrap } from '@/core/manager/InstancePointManager.ts'
import Constract from '@/core/Constract.ts' import Constract from '@/core/Constract.ts'
import type LineSegmentManager from '@/core/manager/LineSegmentManager.ts' import type LineSegmentManager from '@/core/manager/LineSegmentManager.ts'
import type { Object3DLike } from '@/types/ModelTypes.ts'
/** /**
* *
@ -92,12 +93,16 @@ export default abstract class BaseRenderer {
/** /**
* , item name / id / / / userData, * , item name / id / / / userData,
*/ */
abstract createPointBasic(item: ItemJson, option?: RendererCudOption): THREE.Object3D createPointBasic(item: ItemJson, option?: RendererCudOption): Object3DLike {
throw new Error('createPointBasic method must be implemented in derived class.')
}
/** /**
* 线 * 线
*/ */
abstract createLineBasic(start: ItemJson, end: ItemJson, type: LinkType): THREE.Object3D createLineBasic(start: ItemJson, end: ItemJson, type: LinkType): Object3DLike {
throw new Error('createLineBasic method must be implemented in derived class.')
}
abstract get defaultScale(): THREE.Vector3 abstract get defaultScale(): THREE.Vector3
@ -108,63 +113,32 @@ export default abstract class BaseRenderer {
/** /**
* 线 * 线
*/ */
afterCreateOrUpdateLine(start: ItemJson, end: ItemJson, type: LinkType, option: RendererCudOption, object: THREE.Object3D) { afterCreateOrUpdateLine(start: ItemJson, end: ItemJson, type: LinkType, option: RendererCudOption, object: Object3DLike) {
} }
/** /**
* *
*/ */
afterCreateOrUpdatePoint(item: ItemJson, option: RendererCudOption, object: THREE.Object3D) { afterCreateOrUpdatePoint(item: ItemJson, option: RendererCudOption, object: Object3DLike) {
} }
/** /**
* 线 * 线
*/ */
afterDeleteLine(start: ItemJson, end: ItemJson, type: LinkType, option: RendererCudOption, object: THREE.Object3D) { afterDeleteLine(start: ItemJson, end: ItemJson, type: LinkType, option: RendererCudOption, object: Object3DLike) {
}
fillObjectUserDataFromItem(item: ItemJson, object: THREE.Object3D) {
if (!object.name && item.name) {
object.name = item.name
}
object.userData = {
...object.userData,
createType: 'point',
entityId: item.id,
draggable: item.dt.protected !== true,
selectable: item.dt.selectable !== false,
t: item.t
}
}
fillObjectUserDataFromLine(start: ItemJson, end: ItemJson, type: LinkType, object: THREE.Object3D) {
const id = getLineId(start.id, end.id, type)
if (!object.name) {
object.name = id
}
object.userData = {
...object.userData,
createType: 'line',
entityId: getLineId(start.id, end.id, type),
startId: start.id,
endId: end.id,
draggable: false,
selectable: false,
t: start.t
}
} }
/** /**
* *
*/ */
appendToScene(...objects: THREE.Object3D[]) { appendToScene(...objects: Object3DLike[]) {
if (!this.tempViewport || !this.tempViewport.scene) { if (!this.tempViewport || !this.tempViewport.scene) {
console.warn('No active viewport to append objects to.') console.warn('No active viewport to append objects to.')
return return
} }
this.tempViewport.scene.add(...objects) this.tempViewport.scene.add(...objects)
const dragObjects = objects.filter(obj => !!obj.userData.draggable) // const dragObjects = objects.filter(obj => !!obj.userData.draggable)
//this.tempViewport.dragControl.setDragObjects(dragObjects, 'push') //this.tempViewport.dragControl.setDragObjects(dragObjects, 'push')
} }
@ -177,20 +151,26 @@ export default abstract class BaseRenderer {
//this.tempViewport.dragControl.setDragObjects(objects, 'remove') //this.tempViewport.dragControl.setDragObjects(objects, 'remove')
} }
createPointForEntity(item: ItemJson, option?: RendererCudOption): Object3DLike {
const point = this.createPoint(item, option)
point.visible = ((typeof item.v !== 'undefined') ? item.v : true)
setUserDataForItem(item, point)
this.afterCreateOrUpdatePoint(item, option, point)
this.tempViewport.entityManager.appendObject(item.id, point)
this.appendToScene(point)
return point
}
/** /**
* *
* @param item * @param item
* @param option * @param option
*/ */
createPoint(item: ItemJson, option?: RendererCudOption): THREE.Object3D { createPoint(item: ItemJson, option?: RendererCudOption): Object3DLike {
// 由基础类创造一个属于自己的点演示 // 由基础类创造一个属于自己的点演示
const point = this.createPointBasic(item, option) const point = this.createPointBasic(item, option)
if (!point || !point.position) {
debugger
}
if (item.name) {
point.name = item.name
}
point.position.set(item.tf[0][0], item.tf[0][1], item.tf[0][2]) point.position.set(item.tf[0][0], item.tf[0][1], item.tf[0][2])
@ -202,11 +182,6 @@ export default abstract class BaseRenderer {
point.scale.set(item.tf[2][0], item.tf[2][1], item.tf[2][2]) point.scale.set(item.tf[2][0], item.tf[2][1], item.tf[2][2])
point.visible = ((typeof item.v !== 'undefined') ? item.v : true) point.visible = ((typeof item.v !== 'undefined') ? item.v : true)
this.fillObjectUserDataFromItem(item, point)
this.afterCreateOrUpdatePoint(item, option, point)
this.tempViewport.entityManager.appendObject(item.id, point)
this.appendToScene(point)
return point return point
} }
@ -218,7 +193,7 @@ export default abstract class BaseRenderer {
*/ */
deletePoint(id: string, option?: RendererCudOption) { deletePoint(id: string, option?: RendererCudOption) {
const object = this.tempViewport.entityManager.findObjectById(id) const object = this.tempViewport.entityManager.findObjectById(id)
if (object) { if (object instanceof THREE.Object3D) {
this.removeFromScene(object) this.removeFromScene(object)
} }
@ -226,12 +201,21 @@ export default abstract class BaseRenderer {
this.tempViewport.entityManager.deleteObjectsOnly(id) this.tempViewport.entityManager.deleteObjectsOnly(id)
} }
updatePointForEntity(item: ItemJson, option?: RendererCudOption): Object3DLike {
const point = this.updatePoint(item, option)
point.visible = ((typeof item.v !== 'undefined') ? item.v : true)
setUserDataForItem(item, point)
this.afterCreateOrUpdatePoint(item, option, point)
return point
}
/** /**
* *
* @param item * @param item
* @param option * @param option
*/ */
updatePoint(item: ItemJson, option?: RendererCudOption) { updatePoint(item: ItemJson, option?: RendererCudOption): Object3DLike {
const object = this.tempViewport.entityManager.findObjectById(item.id) const object = this.tempViewport.entityManager.findObjectById(item.id)
if (!object) { if (!object) {
console.warn(`Point with ID "${item.id}" does not exist.`) console.warn(`Point with ID "${item.id}" does not exist.`)
@ -250,10 +234,7 @@ export default abstract class BaseRenderer {
) )
point.scale.set(item.tf[2][0], item.tf[2][1], item.tf[2][2]) point.scale.set(item.tf[2][0], item.tf[2][1], item.tf[2][2])
point.visible = ((typeof item.v !== 'undefined') ? item.v : true) return point
this.fillObjectUserDataFromItem(item, point)
this.afterCreateOrUpdatePoint(item, option, point)
} }
/** /**
@ -275,10 +256,11 @@ export default abstract class BaseRenderer {
const geom = line.geometry const geom = line.geometry
geom.setFromPoints([startPoint.position, endPoint.position]) geom.setFromPoints([startPoint.position, endPoint.position])
} }
this.fillObjectUserDataFromLine(start, end, type, line) setUserDataForLine(start, end, type, line)
this.tempViewport.entityManager.appendLineObject(id, line) this.tempViewport.entityManager.appendLineObject(id, line)
this.appendToScene(line) if (line instanceof THREE.Object3D) {
this.appendToScene(line)
}
this.afterCreateOrUpdateLine(start, end, type, option, line) this.afterCreateOrUpdateLine(start, end, type, option, line)
} }
@ -313,10 +295,10 @@ export default abstract class BaseRenderer {
*/ */
deleteLine(start: ItemJson, end: ItemJson, type: LinkType, option?: RendererCudOption) { deleteLine(start: ItemJson, end: ItemJson, type: LinkType, option?: RendererCudOption) {
const lineId = getLineId(start.id, end.id, type) const lineId = getLineId(start.id, end.id, type)
const lines = this.tempViewport.entityManager.findLineObjectById(lineId) const line = this.tempViewport.entityManager.findLineObjectById(lineId)
this.tempViewport.entityManager.deleteLineObjectOnly(lineId) this.tempViewport.entityManager.deleteLineObjectOnly(lineId)
this.afterDeleteLine(start, end, type, option, lines) this.afterDeleteLine(start, end, type, option, line)
} }
dispose() { dispose() {

21
src/core/engine/SceneHelp.ts

@ -3,6 +3,9 @@ import type WorldModel from '@/core/manager/WorldModel'
import { LineGeometry } from 'three/examples/jsm/lines/LineGeometry' import { LineGeometry } from 'three/examples/jsm/lines/LineGeometry'
import { LineMaterial } from 'three/examples/jsm/lines/LineMaterial' import { LineMaterial } from 'three/examples/jsm/lines/LineMaterial'
import { Line2 } from 'three/examples/jsm/lines/Line2' import { Line2 } from 'three/examples/jsm/lines/Line2'
import type { Object3DLike } from '@/types/ModelTypes.ts'
import { LineManageWrap } from '@/core/manager/LineSegmentManager.ts'
import { PointManageWrap } from '@/core/manager/InstancePointManager.ts'
/** /**
* *
@ -94,8 +97,20 @@ export default class SceneHelp {
}) })
} }
add(...object: THREE.Object3D[]) { add(...object: Object3DLike[]) {
this.scene.add(...object) for (const obj of object) {
if (obj instanceof THREE.Object3D) {
this.scene.add(obj)
} else if (obj instanceof LineManageWrap) {
// 默认会合并到 LineSegmentManager 中
} else if (obj instanceof PointManageWrap) {
if (!obj.parent) {
obj.manager.syncMeshObject3D(obj)
}
}
}
} }
/** /**
@ -173,4 +188,4 @@ function createAxes(axesSize = 5, axesColor = 0x000000, axesWidth = 2) {
group.add(line) group.add(line)
}) })
return group return group
} }

23
src/core/manager/EntityManager.ts

@ -5,6 +5,7 @@ import { getRenderer } from './ModuleManager'
import { getClosestObject, getLineId, parseLineId } from '@/core/ModelUtils' import { getClosestObject, getLineId, parseLineId } from '@/core/ModelUtils'
import { Vector2 } from 'three' import { Vector2 } from 'three'
import { getFreezeDeep } from '@/utils/webutils.ts' import { getFreezeDeep } from '@/utils/webutils.ts'
import type { Object3DLike } from '@/types/ModelTypes.ts'
/** /**
* *
@ -24,7 +25,7 @@ export default class EntityManager {
private readonly __relationIndex = new Map<string, Relation>() private readonly __relationIndex = new Map<string, Relation>()
// 所有 THREEJS "点"对象, 检索值是"点实体"的 id, 值是 THREE.Object3D 数组 // 所有 THREEJS "点"对象, 检索值是"点实体"的 id, 值是 THREE.Object3D 数组
private readonly __objectMap = new Map<string, THREE.Object3D>() private readonly __objectMap = new Map<string, Object3DLike>()
// 所有 THREEJS "可选中"对象, 检索值是"点实体"的 id, 值是 THREE.Object3D 数组 // 所有 THREEJS "可选中"对象, 检索值是"点实体"的 id, 值是 THREE.Object3D 数组
readonly _selectableObjects: THREE.Object3D[] = [] readonly _selectableObjects: THREE.Object3D[] = []
@ -32,7 +33,7 @@ export default class EntityManager {
readonly _draggableObjects: THREE.Object3D[] = [] readonly _draggableObjects: THREE.Object3D[] = []
// 所有 THREEJS "线"对象, 检索值是"线实体"的 id, 取值方式是 {type}${startId}${endId}, 值是 THREE.Object3D 数组 // 所有 THREEJS "线"对象, 检索值是"线实体"的 id, 取值方式是 {type}${startId}${endId}, 值是 THREE.Object3D 数组
private readonly __lineMap = new Map<string, THREE.Object3D>() private readonly __lineMap = new Map<string, Object3DLike>()
// 差量渲染器 // 差量渲染器
private readonly diffRenderer = new Map<string, BaseRenderer>() private readonly diffRenderer = new Map<string, BaseRenderer>()
@ -139,11 +140,11 @@ export default class EntityManager {
} }
if (typeof originEntity === 'undefined') { if (typeof originEntity === 'undefined') {
renderer.createPoint(entity, option as RendererCudOption) renderer.createPointForEntity(entity, option as RendererCudOption)
} else { } else {
option.originEntity = _.cloneDeep(originEntity) option.originEntity = _.cloneDeep(originEntity)
renderer.updatePoint(entity, option as RendererCudOption) renderer.updatePointForEntity(entity, option as RendererCudOption)
} }
} }
@ -413,26 +414,26 @@ export default class EntityManager {
return this.___entityMap.delete(id) return this.___entityMap.delete(id)
} }
findObjectById(id: string): THREE.Object3D | undefined { findObjectById(id: string): Object3DLike | undefined {
return this.__objectMap.get(id) return this.__objectMap.get(id)
} }
appendObject(id: string, object: THREE.Object3D) { appendObject(id: string, object: Object3DLike) {
this.__objectMap.set(id, object) this.__objectMap.set(id, object)
// 如果是可选中对象,添加到 _selectableObjects 中 // 如果是可选中对象,添加到 _selectableObjects 中
if (object.userData.selectable !== false) { if (object instanceof THREE.Object3D && object.userData.selectable !== false) {
this._selectableObjects.push(object) this._selectableObjects.push(object)
} }
if (object.userData.draggable) { if (object instanceof THREE.Object3D && object.userData.draggable) {
this._draggableObjects.push(object) this._draggableObjects.push(object)
} }
} }
appendLineObject(id: string, lines: THREE.Object3D) { appendLineObject(id: string, lines: Object3DLike) {
this.__lineMap.set(id, lines) this.__lineMap.set(id, lines)
} }
findLineObjectById(lineId: string): THREE.Object3D | undefined { findLineObjectById(lineId: string): Object3DLike | undefined {
return this.__lineMap.get(lineId) return this.__lineMap.get(lineId)
} }
@ -487,7 +488,7 @@ export default class EntityManager {
new THREE.Vector2(startX, startZ), new THREE.Vector2(startX, startZ),
new THREE.Vector2(endX, endZ) new THREE.Vector2(endX, endZ)
) )
const objectsInBox: THREE.Object3D[] = [] const objectsInBox: Object3DLike[] = []
for (const [id, obj] of this.__objectMap.entries()) { for (const [id, obj] of this.__objectMap.entries()) {
if (box.containsPoint(new Vector2(obj.position.x, obj.position.z))) { if (box.containsPoint(new Vector2(obj.position.x, obj.position.z))) {

122
src/core/manager/InstancePointManager.ts

@ -1,8 +1,6 @@
import * as THREE from 'three' import * as THREE from 'three'
import type IControls from '@/core/controls/IControls.ts'
import type Viewport from '@/core/engine/Viewport.ts' import type Viewport from '@/core/engine/Viewport.ts'
import { Vector3 } from 'three/src/math/Vector3' import { Vector3 } from 'three/src/math/Vector3'
import { Euler } from 'three/src/math/Euler'
export default class InstancePointManager { export default class InstancePointManager {
private readonly viewport: Viewport private readonly viewport: Viewport
@ -13,38 +11,47 @@ export default class InstancePointManager {
private readonly material: THREE.Material private readonly material: THREE.Material
private readonly dummy: THREE.Object3D = new THREE.Object3D() private readonly dummy: THREE.Object3D = new THREE.Object3D()
// itemId -> instanceId // itemId -> instanceId
private instanceData: Map<string, number> = new Map() private instanceData = new Map<string, PointManageWrap>()
/** /**
* *
* @param item * @param item
* @returns ID (-1) * @returns ID (-1)
*/ */
createPoint(item: ItemJson): number { createPoint(item: ItemJson): PointManageWrap {
if (this.freeIndices.length === 0) { if (this.freeIndices.length === 0) {
system.showErrorDialog('InstancePointManager is full') system.showErrorDialog('InstancePointManager is full')
return -1 return null
} }
const instanceId = this.freeIndices.pop()! const meshIndex = this.freeIndices.pop()!
this.instanceData.set(item.id, instanceId) return new PointManageWrap(this, {
uuid: item.id,
this.updatePoint(item) name: item.name,
return instanceId meshIndex: meshIndex,
visible: item.v !== false,
//@ts-ignore
userData: {
t: item.t,
createType: 'point',
entityId: item.id
}
})
} }
/** /**
* *
* @param item * @param item
* @param option * @param option
*/ */
updatePoint(item: ItemJson, option: { updatePoint(item: ItemJson, option: { position?: Vector3, rotation?: Vector3, scale?: Vector3 } = {}): void {
position?: Vector3 const wrap = this.instanceData.get(item.id)
rotation?: Vector3 if (wrap === undefined) return
scale?: Vector3
} = {}): void { wrap.visible = item.v !== false
const instanceId = this.instanceData.get(item.id) wrap.userData.t = item.t
if (instanceId === undefined) return wrap.userData.entityId = item.id
let [position, rotation, scale] = item.tf let [position, rotation, scale] = item.tf
if (option.position) { if (option.position) {
@ -57,20 +64,40 @@ export default class InstancePointManager {
scale = option.scale.toArray() scale = option.scale.toArray()
} }
this.dummy.position.set(position[0], position[1], position[2]) wrap.position.set(position[0], position[1], position[2])
this.dummy.rotation.set( wrap.rotation.set(
THREE.MathUtils.degToRad(rotation[0]), THREE.MathUtils.degToRad(rotation[0]),
THREE.MathUtils.degToRad(rotation[1]), THREE.MathUtils.degToRad(rotation[1]),
THREE.MathUtils.degToRad(rotation[2]) THREE.MathUtils.degToRad(rotation[2])
) )
this.dummy.scale.set(scale[0], scale[1], scale[2]) wrap.scale.set(scale[0], scale[1], scale[2])
this.syncMeshObject3D(wrap)
}
/**
*
*/
getObject3DLike(id: string): PointManageWrap {
return this.instanceData.get(id)
}
syncMeshObject3D(wrap: PointManageWrap) {
if (wrap.meshIndex < 0) {
console.error('InstancePointManager: Invalid meshIndex for wrap', wrap)
return
}
if (item.v === false) { if (!wrap.visible) {
this.dummy.scale.set(0, 0, 0) this.dummy.scale.set(0, 0, 0)
} else {
this.dummy.position.copy(wrap.position)
this.dummy.rotation.copy(wrap.rotation)
this.dummy.scale.copy(wrap.scale)
} }
this.dummy.updateMatrix() this.dummy.updateMatrix()
this.instancedMesh.setMatrixAt(instanceId, this.dummy.matrix) wrap.parent = this.instancedMesh
this.instancedMesh.setMatrixAt(wrap.meshIndex, this.dummy.matrix)
this.instancedMesh.instanceMatrix.needsUpdate = true this.instancedMesh.instanceMatrix.needsUpdate = true
} }
@ -79,18 +106,20 @@ export default class InstancePointManager {
* @param id ID * @param id ID
*/ */
deletePoint(id: string): void { deletePoint(id: string): void {
const instanceId = this.instanceData.get(id) const wrap = this.instanceData.get(id)
if (instanceId === undefined) return if (wrap === undefined) return
// 隐藏实例 // 隐藏实例
this.dummy.scale.set(0, 0, 0) this.dummy.scale.set(0, 0, 0)
this.dummy.updateMatrix() this.dummy.updateMatrix()
this.instancedMesh.setMatrixAt(instanceId, this.dummy.matrix) this.instancedMesh.setMatrixAt(wrap.meshIndex, this.dummy.matrix)
this.instancedMesh.instanceMatrix.needsUpdate = true this.instancedMesh.instanceMatrix.needsUpdate = true
// 回收索引 // 回收索引
this.freeIndices.push(instanceId) this.freeIndices.push(wrap.meshIndex)
this.instanceData.delete(id) this.instanceData.delete(id)
wrap.dispose()
} }
/** /**
@ -99,11 +128,11 @@ export default class InstancePointManager {
* @param target * @param target
*/ */
getWorldPosition(id: string, target: THREE.Vector3): void { getWorldPosition(id: string, target: THREE.Vector3): void {
const instanceId = this.instanceData.get(id) const instanceData = this.instanceData.get(id)
if (instanceId === undefined) return if (instanceData === undefined) return
const matrix = new THREE.Matrix4() const matrix = new THREE.Matrix4()
this.instancedMesh.getMatrixAt(instanceId, matrix) this.instancedMesh.getMatrixAt(instanceData.meshIndex, matrix)
target.setFromMatrixPosition(matrix) target.setFromMatrixPosition(matrix)
} }
@ -175,3 +204,38 @@ export default class InstancePointManager {
this.freeIndices.length = 0 this.freeIndices.length = 0
} }
} }
export class PointManageWrap {
readonly manager: InstancePointManager
meshIndex: number = -1
parent: THREE.Object3D | null = null
uuid: string
name: string
visible: boolean
readonly position = new THREE.Vector3()
readonly rotation = new THREE.Euler()
readonly scale = new THREE.Vector3(1, 1, 1)
//@ts-ignore
userData: UserData = {}
get type() {
return 'PointManageWrap'
}
get isObject3D() {
return false
}
constructor(pointManager: InstancePointManager, data: any, meshIndex: number = -1) {
this.manager = pointManager
this.meshIndex = meshIndex
_.extend(this, data)
}
dispose() {
this.manager.deletePoint(this.uuid)
this.parent = null
this.meshIndex = -1
}
}

17
src/core/manager/LabelManager.ts

@ -4,6 +4,7 @@ import type Viewport from '@/core/engine/Viewport.ts'
import { CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer' import { CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer'
import { Text } from 'troika-three-text' import { Text } from 'troika-three-text'
import SimSunTTF from '@/assets/fonts/simsunb.ttf' import SimSunTTF from '@/assets/fonts/simsunb.ttf'
import type { Object3DLike } from '@/types/ModelTypes.ts'
export interface LabelOption { export interface LabelOption {
/** /**
@ -40,10 +41,12 @@ export default class LabelManager implements IControls {
this.viewport = viewport this.viewport = viewport
} }
createOrUpdateLabelByDistance(parentObj: THREE.Object3D, startPos: THREE.Vector3, endPos: THREE.Vector3, option: LabelOption): Text | CSS2DObject { createOrUpdateLabelByDistance(lineRef: Object3DLike, startPos: THREE.Vector3, endPos: THREE.Vector3, option: LabelOption): Text | CSS2DObject {
let labelObj = this.labelMap.get(parentObj.userData.labelObjectId) let labelObj = this.labelMap.get(lineRef.userData.labelObjectId)
// 线段不存在
if (!labelObj) { if (!labelObj) {
labelObj = this.createLabel(parentObj, option) labelObj = this.createLabel(lineRef, option)
} }
const position = new THREE.Vector3().addVectors(startPos, endPos).multiplyScalar(0.5) const position = new THREE.Vector3().addVectors(startPos, endPos).multiplyScalar(0.5)
@ -52,12 +55,12 @@ export default class LabelManager implements IControls {
// 计算距离 // 计算距离
const distance = startPos.distanceTo(endPos) const distance = startPos.distanceTo(endPos)
const text = distance.toFixed(2) + ' m' const text = distance.toFixed(2) + ' m'
this.updateLabel(parentObj, text) this.updateLabel(lineRef, text)
return labelObj return labelObj
} }
createLabel(parentObj: THREE.Object3D, option: LabelOption): Text | CSS2DObject { createLabel(parentObj: Object3DLike, option: LabelOption): Text | CSS2DObject {
const labelObj = this.createLabelObject(option) const labelObj = this.createLabelObject(option)
parentObj.userData.labelObjectId = labelObj.uuid parentObj.userData.labelObjectId = labelObj.uuid
@ -77,7 +80,7 @@ export default class LabelManager implements IControls {
} }
updateLabel(parentObj: THREE.Object3D, text: string) { updateLabel(parentObj: Object3DLike, text: string) {
const labelObj = this.labelMap.get(parentObj.userData.labelObjectId) const labelObj = this.labelMap.get(parentObj.userData.labelObjectId)
if (labelObj) { if (labelObj) {
if (labelObj instanceof CSS2DObject) { if (labelObj instanceof CSS2DObject) {
@ -92,7 +95,7 @@ export default class LabelManager implements IControls {
} }
} }
removeLabel(parentObj: THREE.Object3D) { removeLabel(parentObj: Object3DLike) {
if (parentObj?.userData?.labelObjectId) { if (parentObj?.userData?.labelObjectId) {
const labelObj = this.labelMap.get(parentObj.userData.labelObjectId) const labelObj = this.labelMap.get(parentObj.userData.labelObjectId)
this.labelMap.delete(labelObj.uuid) this.labelMap.delete(labelObj.uuid)

235
src/core/manager/LineSegmentManager.ts

@ -3,6 +3,7 @@ import type Viewport from '@/core/engine/Viewport.ts'
import { LineSegmentsGeometry } from 'three/examples/jsm/lines/LineSegmentsGeometry' import { LineSegmentsGeometry } from 'three/examples/jsm/lines/LineSegmentsGeometry'
import { LineSegments2 } from 'three/examples/jsm/lines/LineSegments2' import { LineSegments2 } from 'three/examples/jsm/lines/LineSegments2'
import { LineMaterial } from 'three/examples/jsm/lines/LineMaterial' import { LineMaterial } from 'three/examples/jsm/lines/LineMaterial'
import type { Object3DLike, Vector3Like } from '@/types/ModelTypes.ts'
/** /**
* 线 * 线
@ -12,20 +13,26 @@ export default class LineSegmentManager {
private readonly lineGeometry: LineSegmentsGeometry private readonly lineGeometry: LineSegmentsGeometry
private readonly lineMaterial: LineMaterial private readonly lineMaterial: LineMaterial
private readonly lineSegments: LineSegments2 private readonly lineSegments: LineSegments2
private readonly segments: Map<string, LineSegmentData> = new Map() private readonly segments: Map<string, LineManageWrap> = new Map()
public needsUpdate: boolean = false public needsUpdate: boolean = false
private colorArray: Float32Array | null = null private colorArray: Float32Array | null = null
private positionArray: Float32Array | null = null private positionArray: Float32Array | null = null
/** /**
* 线 * 线
* @param key 线 * @param lineId 线
* @param start * @param start
* @param end * @param end
* @param color 线 () * @param color 线 ()
* @param userData () * @param userData ()
*/ */
createLine(key: string, start: THREE.Vector3Like, end: THREE.Vector3Like, color?: THREE.Color | number | string, userData?: any): void { createLine(lineId: string, start: THREE.Vector3 | [number, number, number], end: Vector3Like, color?: THREE.Color | number | string, userData: Partial<UserData> = {}): LineManageWrap {
const segment = this.segments.get(lineId)
if (segment) {
console.error(`LineSegmentManager: Line with id ${lineId} already exists.`)
return
}
const startVec = start instanceof THREE.Vector3 const startVec = start instanceof THREE.Vector3
? start.clone() ? start.clone()
: new THREE.Vector3(start[0], start[1], start[2]) : new THREE.Vector3(start[0], start[1], start[2])
@ -43,104 +50,126 @@ export default class LineSegmentManager {
colorObj = new THREE.Color(color) colorObj = new THREE.Color(color)
} }
if (this.segments.has(key)) { const result = new LineManageWrap(this, {
// 更新现有线段 uuid: lineId,
const segment = this.segments.get(key)! visible: true,
segment.start.copy(startVec) userData: {
segment.end.copy(endVec) entityId: lineId,
if (colorObj) segment.color = colorObj createType: 'line',
if (userData) segment.userData = userData ...userData
} else { }
// 创建新线段 }, startVec, endVec, colorObj)
this.segments.set(key, {
key,
start: startVec,
end: endVec,
color: colorObj,
visible: true,
userData
})
}
this.segments.set(lineId, result)
result.parent = this.lineSegments
this.needsUpdate = true this.needsUpdate = true
return result
} }
/** updateLine(lineId: string, start?: Vector3Like, end?: Vector3Like, color?: THREE.Color | number | string): LineManageWrap {
* 线 const wrap = this.segments.get(lineId)
* @param key 线 if (!wrap) return
* @param start
* @param end
*/
updateLinePosition(key: string, start: THREE.Vector3Like, end: THREE.Vector3Like): void {
const segment = this.segments.get(key)
if (!segment) return
if (start instanceof THREE.Vector3) {
segment.start.copy(start)
} else {
segment.start.set(start[0], start[1], start[2])
}
if (end instanceof THREE.Vector3) { // 更新起点和终点
segment.end.copy(end) if (start) {
} else { wrap.start.copy(start instanceof THREE.Vector3 ? start : new THREE.Vector3(start[0], start[1], start[2]))
segment.end.set(end[0], end[1], end[2]) }
if (end) {
wrap.end.copy(end instanceof THREE.Vector3 ? end : new THREE.Vector3(end[0], end[1], end[2]))
} }
this.needsUpdate = true // 更新颜色
}
/**
* 线
* @param key 线
* @param color
*/
updateLineColor(key: string, color: THREE.Color | number | string): void {
const segment = this.segments.get(key)
if (!segment) return
if (color instanceof THREE.Color) { if (color instanceof THREE.Color) {
segment.color = color wrap.color = color
} else if (typeof color === 'number') { } else if (typeof color === 'number') {
segment.color = new THREE.Color(color) wrap.color = new THREE.Color(color)
} else if (typeof color === 'string') { } else if (typeof color === 'string') {
segment.color = new THREE.Color(color) wrap.color = new THREE.Color(color)
} else {
segment.color = undefined
} }
this.needsUpdate = true this.needsUpdate = true
wrap.parent = this.lineSegments
return wrap
} }
/** // /**
* 线 // * 更新线段位置
* @param key 线 // * @param lineId 线段唯一标识
* @param visible // * @param start 新起点
*/ // * @param end 新终点
setLineVisible(key: string, visible: boolean): void { // */
const segment = this.segments.get(key) // updateLinePosition(lineId: string, start: THREE.Vector3Like, end: THREE.Vector3Like): void {
if (segment && segment.visible !== visible) { // const segment = this.segments.get(lineId)
segment.visible = visible // if (!segment) return
this.needsUpdate = true //
} // if (start instanceof THREE.Vector3) {
} // segment.start.copy(start)
// } else {
// segment.start.set(start[0], start[1], start[2])
// }
//
// if (end instanceof THREE.Vector3) {
// segment.end.copy(end)
// } else {
// segment.end.set(end[0], end[1], end[2])
// }
//
// this.needsUpdate = true
// }
//
// /**
// * 更新线段颜色
// * @param lineId 线段唯一标识
// * @param color 新颜色
// */
// updateLineColor(lineId: string, color: THREE.Color | number | string): void {
// const segment = this.segments.get(lineId)
// if (!segment) return
//
// if (color instanceof THREE.Color) {
// segment.color = color
// } else if (typeof color === 'number') {
// segment.color = new THREE.Color(color)
// } else if (typeof color === 'string') {
// segment.color = new THREE.Color(color)
// } else {
// segment.color = undefined
// }
//
// this.needsUpdate = true
// }
//
// /**
// * 设置线段可见性
// * @param lineId 线段唯一标识
// * @param visible 是否可见
// */
// setLineVisible(lineId: string, visible: boolean): void {
// const segment = this.segments.get(lineId)
// if (segment && segment.visible !== visible) {
// segment.visible = visible
// this.needsUpdate = true
// }
// }
/** /**
* 线 * 线
* @param key 线 * @param lineId 线
*/ */
deleteLine(key: string): void { deleteLine(lineId: string): void {
if (this.segments.delete(key)) { const wrap = this.segments.get(lineId)
this.needsUpdate = true if (wrap === undefined) return
}
wrap.dispose()
this.needsUpdate = true
} }
/** /**
* 线 * 线
* @param key 线 * @param lineId 线
*/ */
getLineData(key: string): LineSegmentData | undefined { getObject3DLike(lineId: string): Object3DLike {
return this.segments.get(key) return this.segments.get(lineId)
} }
/** /**
@ -212,9 +241,7 @@ export default class LineSegmentManager {
this.lineGeometry.setColors(this.colorArray) this.lineGeometry.setColors(this.colorArray)
// 设置实例计数为可见线段数量 // 设置实例计数为可见线段数量
const visibleCount = Array.from(this.segments.values()).filter(s => s.visible).length this.lineGeometry.instanceCount = Array.from(this.segments.values()).filter(s => s.visible).length
this.lineGeometry.instanceCount = visibleCount
this.needsUpdate = false this.needsUpdate = false
} }
@ -256,14 +283,42 @@ export default class LineSegmentManager {
} }
} }
/**
* 线 export class LineManageWrap {
*/ readonly manager: LineSegmentManager
interface LineSegmentData { parent: THREE.Object3D | null = null
key: string;
start: THREE.Vector3; start: THREE.Vector3
end: THREE.Vector3; end: THREE.Vector3
color?: THREE.Color; color: THREE.Color
visible?: boolean;
userData?: any; uuid: string
name: string
visible: boolean
readonly position = new THREE.Vector3()
readonly rotation = new THREE.Euler()
readonly scale = new THREE.Vector3(1, 1, 1)
//@ts-ignore
userData: UserData = {}
get type() {
return 'LineManageWrap'
}
get isObject3D() {
return false
}
constructor(lineManager: LineSegmentManager, data: any, start: THREE.Vector3, end: THREE.Vector3, color: THREE.Color) {
this.manager = lineManager
_.extend(this, data)
this.start = start
this.end = end
this.color = color
}
dispose() {
this.manager.deleteLine(this.uuid)
this.parent = null
}
} }

183
src/example/example1.js

@ -35,31 +35,31 @@ export default {
{ {
catalogCode: 'f1', t: 'floor', // 楼层 catalogCode: 'f1', t: 'floor', // 楼层
items: [ items: [
{ // {
id: 'rack1', // id: 'rack1',
t: 'rack', // t: 'rack',
v: true, // v: true,
tf: [[2.9, 0.1, 3.5], [0, 0, 0], [1.5, 0.25, 0.1]], // tf: [[2.9, 0.1, 3.5], [0, 0, 0], [1.5, 0.25, 0.1]],
dt: { // dt: {
rackDepth: 1, // 货架深度 // rackDepth: 1, // 货架深度
rackWidth: 5.6, // rackWidth: 5.6,
rackHeight: 4.2, // rackHeight: 4.2,
levelCount: 3, // 总层数 // levelCount: 3, // 总层数
bayCount: 4, // 总列数 // bayCount: 4, // 总列数
hideFloor: false, // 隐藏底板 // hideFloor: false, // 隐藏底板
extendColumns: true, // 扩展挡板 // extendColumns: true, // 扩展挡板
columnSpacing: 1, // 支脚跨越 // columnSpacing: 1, // 支脚跨越
bays: [ // 每列的配置 // bays: [ // 每列的配置
{ // {
bayWidth: 1.4, // 列的宽度 // bayWidth: 1.4, // 列的宽度
levelHeight: [1.4, 1.4, 1.4] // 每层的高度 // levelHeight: [1.4, 1.4, 1.4] // 每层的高度
}, // },
{ bayWidth: 1.4, levelHeight: [1.4, 1.4, 1.4] }, // { bayWidth: 1.4, levelHeight: [1.4, 1.4, 1.4] },
{ bayWidth: 1.4, levelHeight: [1.4, 1.4, 1.4] }, // { bayWidth: 1.4, levelHeight: [1.4, 1.4, 1.4] },
{ bayWidth: 1.4, levelHeight: [1.4, 1.4, 1.4] } // { bayWidth: 1.4, levelHeight: [1.4, 1.4, 1.4] }
] // ]
} // }
}, // },
{ {
id: 'P1', id: 'P1',
t: 'measure', t: 'measure',
@ -78,73 +78,74 @@ export default {
v: true, v: true,
tf: [[5, 0.1, 6.25], [90, 0, 0], [0.25, 0.25, 0.1]], tf: [[5, 0.1, 6.25], [90, 0, 0], [0.25, 0.25, 0.1]],
dt: { in: [], out: [], center: ['P2'] } dt: { in: [], out: [], center: ['P2'] }
}, {
id: '39zML1rnSOOQGQYQ2YUMGy',
t: 'way',
v: true,
tf: [[-4, 0.1, 2], [90, 0, 0], [0.25, 0.25, 0.1]],
dt: { in: [], out: [], center: ['6wrGKiVJniwgKkoggOoEy6'] }
}, {
id: '6wrGKiVJniwgKkoggOoEy6',
t: 'way',
v: true,
tf: [[5, 0.1, 2], [90, 0, 0], [0.25, 0.25, 0.1]],
dt: { in: [], out: [], center: ['39zML1rnSOOQGQYQ2YUMGy'] }
}, {
id: '6UhIIw9QPYh6acwyW8OSGs',
t: 'gstore',
v: true,
tf: [[-1, 0.1, 0.55], [0, 0, 0], [1.5, 1.2, 0.1]],
dt: { in: [], out: [], center: [], storeWidth: 1.4, storeDepth: 1.4 }
}, {
id: '1D0WSRPj8JJJwIcmA0UMqG',
t: 'gstore',
v: true,
tf: [[0.75, 0.1, 0.55], [0, 0, 0], [1.5, 1.2, 0.1]],
dt: { in: [], out: [], center: [], storeWidth: 1.4, storeDepth: 1.4 }
}, {
id: 'gstore3',
t: 'gstore',
v: true,
tf: [[3, 0.1, 0.55], [0, 0, 0], [1.5, 1.2, 0.1]],
dt: { in: [], out: [], center: [], storeWidth: 1.4, storeDepth: 1.4 }
}, {
id: 'pallet1',
t: 'pallet',
v: true,
tf: [[0.75, 0.075, 0.55], [0, 0, 0], [1.5, 1.2, 0.1]],
dt: { in: [], out: [], center: [], palletWidth: 1, palletDepth: 1.2 }
}, {
id: 'pallet2',
t: 'pallet',
v: true,
tf: [[3, 0.075, 0.55], [0, 0, 0], [1.5, 1.2, 0.1]],
dt: { in: [], out: [], center: [], palletWidth: 1, palletDepth: 1.2 }
}, {
id: 'ptr1',
t: 'ptr',
v: true,
tf: [[0.75, 0.075, 2], [0, 0, 0], [1.5, 1.2, 0.1]],
dt: { in: [], out: [], center: [], ptrWidth: 1.5, ptrDepth: 1.5, ptrHeight: 1.98 }
}, {
id: 'ptr2',
t: 'ptr',
v: true,
tf: [[3, 0.075, 2], [0, 0, 0], [1.5, 1.2, 0.1]],
dt: { in: [], out: [], center: [], ptrWidth: 1.5, ptrDepth: 1.5, ptrHeight: 1.98 }
}, {
id: 'pallet3',
t: 'pallet',
v: true,
tf: [[3, 0.175, 1.88], [0, 0, 0], [1.5, 1.2, 0.1]],
dt: { in: [], out: [], center: [], palletWidth: 1, palletDepth: 1.2 }
}, {
id: 'pallet4',
t: 'pallet',
v: true,
tf: [[0.75, 0.175, 3.5], [0, 0, 0], [1.5, 1.2, 0.1]],
dt: { in: [], out: [], center: [], palletWidth: 1, palletDepth: 1.2 }
} }
// {
// id: '39zML1rnSOOQGQYQ2YUMGy',
// t: 'way',
// v: true,
// tf: [[-4, 0.1, 2], [90, 0, 0], [0.25, 0.25, 0.1]],
// dt: { in: [], out: [], center: ['6wrGKiVJniwgKkoggOoEy6'] }
// }, {
// id: '6wrGKiVJniwgKkoggOoEy6',
// t: 'way',
// v: true,
// tf: [[5, 0.1, 2], [90, 0, 0], [0.25, 0.25, 0.1]],
// dt: { in: [], out: [], center: ['39zML1rnSOOQGQYQ2YUMGy'] }
// }, {
// id: '6UhIIw9QPYh6acwyW8OSGs',
// t: 'gstore',
// v: true,
// tf: [[-1, 0.1, 0.55], [0, 0, 0], [1.5, 1.2, 0.1]],
// dt: { in: [], out: [], center: [], storeWidth: 1.4, storeDepth: 1.4 }
// }, {
// id: '1D0WSRPj8JJJwIcmA0UMqG',
// t: 'gstore',
// v: true,
// tf: [[0.75, 0.1, 0.55], [0, 0, 0], [1.5, 1.2, 0.1]],
// dt: { in: [], out: [], center: [], storeWidth: 1.4, storeDepth: 1.4 }
// }, {
// id: 'gstore3',
// t: 'gstore',
// v: true,
// tf: [[3, 0.1, 0.55], [0, 0, 0], [1.5, 1.2, 0.1]],
// dt: { in: [], out: [], center: [], storeWidth: 1.4, storeDepth: 1.4 }
// }, {
// id: 'pallet1',
// t: 'pallet',
// v: true,
// tf: [[0.75, 0.075, 0.55], [0, 0, 0], [1.5, 1.2, 0.1]],
// dt: { in: [], out: [], center: [], palletWidth: 1, palletDepth: 1.2 }
// }, {
// id: 'pallet2',
// t: 'pallet',
// v: true,
// tf: [[3, 0.075, 0.55], [0, 0, 0], [1.5, 1.2, 0.1]],
// dt: { in: [], out: [], center: [], palletWidth: 1, palletDepth: 1.2 }
// }, {
// id: 'ptr1',
// t: 'ptr',
// v: true,
// tf: [[0.75, 0.075, 2], [0, 0, 0], [1.5, 1.2, 0.1]],
// dt: { in: [], out: [], center: [], ptrWidth: 1.5, ptrDepth: 1.5, ptrHeight: 1.98 }
// }, {
// id: 'ptr2',
// t: 'ptr',
// v: true,
// tf: [[3, 0.075, 2], [0, 0, 0], [1.5, 1.2, 0.1]],
// dt: { in: [], out: [], center: [], ptrWidth: 1.5, ptrDepth: 1.5, ptrHeight: 1.98 }
// }, {
// id: 'pallet3',
// t: 'pallet',
// v: true,
// tf: [[3, 0.175, 1.88], [0, 0, 0], [1.5, 1.2, 0.1]],
// dt: { in: [], out: [], center: [], palletWidth: 1, palletDepth: 1.2 }
// }, {
// id: 'pallet4',
// t: 'pallet',
// v: true,
// tf: [[0.75, 0.175, 3.5], [0, 0, 0], [1.5, 1.2, 0.1]],
// dt: { in: [], out: [], center: [], palletWidth: 1, palletDepth: 1.2 }
// }
] ]
}, },
{ {

5
src/modules/charger/ChargerRenderer.ts

@ -77,11 +77,6 @@ export default class ChargerRenderer extends BaseRenderer {
// 设置位置 // 设置位置
group.position.set(item.tf[0][0], item.tf[0][1], item.tf[0][2]) group.position.set(item.tf[0][0], item.tf[0][1], item.tf[0][2])
this.fillObjectUserDataFromItem(item, group)
this.afterCreateOrUpdatePoint(item, option, group)
this.tempViewport.entityManager.appendObject(item.id, group)
this.appendToScene(group)
return group return group
} }

5
src/modules/clx/ClxRenderer.ts

@ -78,11 +78,6 @@ export default class ClxRenderer extends BaseRenderer {
// 设置位置 // 设置位置
group.position.set(item.tf[0][0], item.tf[0][1], item.tf[0][2]) group.position.set(item.tf[0][0], item.tf[0][1], item.tf[0][2])
this.fillObjectUserDataFromItem(item, group)
this.afterCreateOrUpdatePoint(item, option, group)
this.tempViewport.entityManager.appendObject(item.id, group)
this.appendToScene(group)
return group return group
} }

5
src/modules/gstore/GstoreRenderer.ts

@ -106,11 +106,6 @@ export default class GstoreRenderer extends BaseRenderer {
// 设置位置 // 设置位置
group.position.set(item.tf[0][0], item.tf[0][1], item.tf[0][2]) group.position.set(item.tf[0][0], item.tf[0][1], item.tf[0][2])
this.fillObjectUserDataFromItem(item, group)
this.afterCreateOrUpdatePoint(item, option, group)
this.tempViewport.entityManager.appendObject(item.id, group)
this.appendToScene(group)
return group return group
} }

77
src/modules/measure/MeasureRenderer.ts

@ -2,11 +2,10 @@ import * as THREE from 'three'
import BaseRenderer from '@/core/base/BaseRenderer.ts' import BaseRenderer from '@/core/base/BaseRenderer.ts'
import { getLineId } from '@/core/ModelUtils.ts' import { getLineId } from '@/core/ModelUtils.ts'
import { LineMaterial } from 'three/examples/jsm/lines/LineMaterial.js' import { LineMaterial } from 'three/examples/jsm/lines/LineMaterial.js'
import { LineGeometry } from 'three/examples/jsm/lines/LineGeometry.js'
import { Line2 } from 'three/examples/jsm/lines/Line2.js'
import Constract from '@/core/Constract.ts' import Constract from '@/core/Constract.ts'
import InstancePointManager from '@/core/manager/InstancePointManager.ts' import InstancePointManager from '@/core/manager/InstancePointManager.ts'
import LineSegmentManager from '@/core/manager/LineSegmentManager.ts' import LineSegmentManager from '@/core/manager/LineSegmentManager.ts'
import type { Object3DLike } from '@/types/ModelTypes.ts'
/** /**
* *
@ -30,7 +29,7 @@ export default class MeasureRenderer extends BaseRenderer {
depthWrite: false, depthWrite: false,
side: THREE.DoubleSide side: THREE.DoubleSide
}) })
pointGeometry = new THREE.PlaneGeometry(0.25, 0.25) pointGeometry = new THREE.PlaneGeometry(1, 1)
lineMaterial: LineMaterial = new LineMaterial({ lineMaterial: LineMaterial = new LineMaterial({
color: 0xFF8C00, color: 0xFF8C00,
linewidth: 1, linewidth: 1,
@ -38,7 +37,7 @@ export default class MeasureRenderer extends BaseRenderer {
dashed: false dashed: false
}) })
readonly defulePositionY = Constract.HEIGHT_MEASURE readonly defulePositionY = Constract.HEIGHT_MEASURE
readonly defaultScale: THREE.Vector3 = new THREE.Vector3(0.1, 0.1, 0.1) readonly defaultScale: THREE.Vector3 = new THREE.Vector3(0.25, 0.1, 0.25)
readonly defaultRotation: THREE.Vector3 = new THREE.Vector3(0, 0, 0) readonly defaultRotation: THREE.Vector3 = new THREE.Vector3(0, 0, 0)
createPointManager(): InstancePointManager { createPointManager(): InstancePointManager {
@ -52,7 +51,7 @@ export default class MeasureRenderer extends BaseRenderer {
/** /**
* 使, * 使,
*/ */
override afterCreateOrUpdatePoint(item: ItemJson, option: RendererCudOption, object: THREE.Object3D) { override afterCreateOrUpdatePoint(item: ItemJson, option: RendererCudOption, object: Object3DLike) {
super.afterCreateOrUpdatePoint(item, option, object) super.afterCreateOrUpdatePoint(item, option, object)
const point = object const point = object
@ -66,31 +65,55 @@ export default class MeasureRenderer extends BaseRenderer {
} }
createLineBasic(start: ItemJson, end: ItemJson, type: LinkType): THREE.Object3D { // createLineBasic(start: ItemJson, end: ItemJson, type: LinkType): THREE.Object3D {
const geom = new LineGeometry() // const geom = new LineGeometry()
const obj = new Line2(geom, this.lineMaterial) // const obj = new Line2(geom, this.lineMaterial)
obj.frustumCulled = false // obj.frustumCulled = false
obj.name = MeasureRenderer.LINE_NAME // obj.name = MeasureRenderer.LINE_NAME
obj.uuid = getLineId(start.id, end.id, type) // obj.uuid = getLineId(start.id, end.id, type)
//
// return obj
// }
//
// createPointBasic(item: ItemJson, option?: RendererCudOption): THREE.Object3D {
// // const tt = new THREE.BoxGeometry(1, 1, 1)
// // const obj = new THREE.Mesh(tt, this.movelinePoint)
// // obj.name = MeasureRenderer.POINT_NAME
// // obj.uuid = item.id
// //
// // return [obj]
//
// // 创建平面几何体
// // const obj = new THREE.Mesh(this.pointGeometry,this.pointMaterial)
// // obj.name = MeasureRenderer.POINT_NAME
// // return obj
// }
return obj createPointBasic(item: ItemJson, option?: RendererCudOption): Object3DLike {
// 不允许改变高度/角度/大小
item.tf = [
[item.tf[0][0], this.defulePositionY, item.tf[0][2]],
[this.defaultRotation.x, this.defaultRotation.y, this.defaultRotation.z],
[this.defaultScale.x, this.defaultScale.y, this.defaultScale.z]
]
return this.pointManager.createPoint(item)
} }
createPointBasic(item: ItemJson, option?: RendererCudOption): THREE.Object3D { createLineBasic(start: ItemJson, end: ItemJson, type: LinkType): Object3DLike {
// const tt = new THREE.BoxGeometry(1, 1, 1) const lineId = getLineId(start.id, end.id, type)
// const obj = new THREE.Mesh(tt, this.movelinePoint) return this.lineSegmentManager.createLine(lineId, start.tf[0], end.tf[0], this.lineMaterial.color)
// obj.name = MeasureRenderer.POINT_NAME
// obj.uuid = item.id
//
// return [obj]
// 创建平面几何体
const obj = new THREE.Sprite(this.pointMaterial as THREE.SpriteMaterial)
obj.name = MeasureRenderer.POINT_NAME
return obj
} }
// appendToScene(...objects: THREE.Object3D[]) { // createLine(start: ItemJson, end: ItemJson, type: LinkType): Object3DLike {
// const lineId = getLineId(start.id, end.id, type)
// return this.lineSegmentManager.createLine(lineId, start.tf[0], end.tf[0], this.lineMaterial.color, {
// lineId: lineId,
// startId: start.id,
// endId: end.id
// })
// }
// appendToScene(...objects: THREE.Object3D[]) {
// if (!this.group || this.group.parent !== this.tempViewport.scene.scene) { // if (!this.group || this.group.parent !== this.tempViewport.scene.scene) {
// if (this.group && this.group.parent !== this.tempViewport.scene.scene) { // if (this.group && this.group.parent !== this.tempViewport.scene.scene) {
// // 幻影加载问题 // // 幻影加载问题
@ -108,7 +131,7 @@ export default class MeasureRenderer extends BaseRenderer {
// this.group.add(...objects) // this.group.add(...objects)
// } // }
afterCreateOrUpdateLine(start: ItemJson, end: ItemJson, type: LinkType, option: RendererCudOption, object: THREE.Object3D) { afterCreateOrUpdateLine(start: ItemJson, end: ItemJson, type: LinkType, option: RendererCudOption, object: Object3DLike) {
super.afterCreateOrUpdateLine(start, end, type, option, object) super.afterCreateOrUpdateLine(start, end, type, option, object)
const startPoint = this.tempViewport?.entityManager.findObjectById(start.id) const startPoint = this.tempViewport?.entityManager.findObjectById(start.id)
@ -147,7 +170,7 @@ export default class MeasureRenderer extends BaseRenderer {
// } // }
} }
afterDeleteLine(start: ItemJson, end: ItemJson, type: LinkType, option: RendererCudOption, object: THREE.Object3D) { afterDeleteLine(start: ItemJson, end: ItemJson, type: LinkType, option: RendererCudOption, object: Object3DLike) {
super.afterDeleteLine(start, end, type, option, object) super.afterDeleteLine(start, end, type, option, object)
this.tempViewport.labelManager.removeLabel(object) this.tempViewport.labelManager.removeLabel(object)

5
src/modules/pallet/PalletRenderer.ts

@ -96,11 +96,6 @@ export default class PalletRenderer extends BaseRenderer {
group.add(line as THREE.Object3D) group.add(line as THREE.Object3D)
// 设置位置 // 设置位置
group.position.set(item.tf[0][0], item.tf[0][1], item.tf[0][2]) group.position.set(item.tf[0][0], item.tf[0][1], item.tf[0][2])
this.fillObjectUserDataFromItem(item, group)
this.afterCreateOrUpdatePoint(item, option, group)
this.tempViewport.entityManager.appendObject(item.id, group)
this.appendToScene(group)
return group return group
} }

5
src/modules/ptr/PtrRenderer.ts

@ -78,11 +78,6 @@ export default class PtrRenderer extends BaseRenderer {
// 设置位置 // 设置位置
group.position.set(item.tf[0][0], item.tf[0][1], item.tf[0][2]) group.position.set(item.tf[0][0], item.tf[0][1], item.tf[0][2])
this.fillObjectUserDataFromItem(item, group)
this.afterCreateOrUpdatePoint(item, option, group)
this.tempViewport.entityManager.appendObject(item.id, group)
this.appendToScene(group)
return group return group
} }

6
src/modules/rack/RackRenderer.ts

@ -124,14 +124,8 @@ export default class RackRenderer extends BaseRenderer {
// 设置位置 // 设置位置
group.position.set(item.tf[0][0], item.tf[0][1], item.tf[0][2]) group.position.set(item.tf[0][0], item.tf[0][1], item.tf[0][2])
item.dt.rackWidth = rackWidth item.dt.rackWidth = rackWidth
item.dt.rackHeight = rackHeight item.dt.rackHeight = rackHeight
this.fillObjectUserDataFromItem(item, group)
this.afterCreateOrUpdatePoint(item, option, group)
this.tempViewport.entityManager.appendObject(item.id, group)
this.appendToScene(group)
return group return group
} }

56
src/types/ModelTypes.ts

@ -0,0 +1,56 @@
import { Object3D } from 'three'
import LineSegmentManager, { LineManageWrap } from '@/core/manager/LineSegmentManager.ts'
import InstancePointManager, { PointManageWrap } from '@/core/manager/InstancePointManager.ts'
import * as THREE from 'three'
//
// /**
// * 点数据接口, 用于平衡 Object3D 一致的取数方式
// */
// export interface PointData {
// uuid: string
// name: string
// color?: THREE.Color;
// visible: boolean
//
// userData: UserData
// position: THREE.Vector3
// rotation: THREE.Euler
// scale: THREE.Vector3
//
// meshIndex: number
// }
//
// /**
// * 线段数据接口, 用于平衡 Object3D 一致的取数方式
// */
// export interface LineSegmentData {
// uuid: string;
// name: string;
// color?: THREE.Color;
// visible?: boolean;
// userData: UserData;
//
// position: THREE.Vector3
// rotation: THREE.Euler
// scale: THREE.Vector3
//
// start: THREE.Vector3;
// end: THREE.Vector3;
// }
export interface LineManageReference {
manager: LineSegmentManager
id: string
}
export interface PointManagerReference {
manager: InstancePointManager
id: string
}
export type Object3DLike = Object3D | LineManageWrap | PointManageWrap
/**
* , THREE.Vector3
*/
export type Vector3Like = THREE.Vector3 | [number, number, number]

49
src/types/model.d.ts

@ -212,3 +212,52 @@ interface ItemJson {
[key: string]: any [key: string]: any
}, },
} }
/**
* Object3D Mesh / Geometry
*/
interface UserData {
/**
* ,
*/
t: string
/**
* ID, ItemJson id
*/
entityId: string
/**
* createType='line' , ID
*/
startId?: string
/**
* createType='line' , ID
*/
endId?: string
/**
* ID
*/
labelObjectId?: string
/**
* , 线
*/
createType: 'point' | 'line'
/**
* ,
*/
draggable: boolean
/**
* ,
*/
selectable: boolean
[key: string]: any
}

Loading…
Cancel
Save