import * as THREE from 'three' import BaseRenderer from '@/core/base/BaseRenderer.ts' import { getLineId } from '@/core/ModelUtils.ts' 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' /** * 辅助测量工具渲染器 */ export default class MeasureRenderer extends BaseRenderer { /** * 当前测绘内容组, 所有测量点、线、标签都在这个组中. 但不包括临时点、线 */ group: THREE.Group static GROUP_NAME = 'measure_group' static LABEL_NAME = 'measure_label' static POINT_NAME = 'measure_point' static LINE_NAME = 'measure_line' public useHtmlLabel = false pointMaterial: THREE.Material lineMaterial: LineMaterial readonly defulePositionY = Constract.HEIGHT_MEASURE readonly defaultScale: THREE.Vector3 = new THREE.Vector3(0.1, 0.1, 0.1) readonly defaultRotation: THREE.Vector3 = new THREE.Vector3(0, 0, 0) constructor(itemTypeName: string) { super(itemTypeName) } async init() { this.pointMaterial = new THREE.SpriteMaterial({ color: 0xFFFF99, // 0x303133, transparent: true, side: THREE.DoubleSide, opacity: 1, sizeAttenuation: true }) this.lineMaterial = new LineMaterial({ color: 0xFF8C00, linewidth: 1, vertexColors: false, dashed: false }) return Promise.all([ super.init() ]) } /** * 所有的点,必须使用同一个尺寸, 改属性也无效 */ override afterCreateOrUpdatePoint(item: ItemJson, option: RendererCudOption, object: THREE.Object3D) { super.afterCreateOrUpdatePoint(item, option, object) const point = object point.scale.set(this.defaultScale.x, this.defaultScale.y, this.defaultScale.z) point.rotation.set( THREE.MathUtils.degToRad(this.defaultRotation.x), THREE.MathUtils.degToRad(this.defaultRotation.y), THREE.MathUtils.degToRad(this.defaultRotation.z) ) } createLineBasic(start: ItemJson, end: ItemJson, type: LinkType): THREE.Object3D { const geom = new LineGeometry() const obj = new Line2(geom, this.lineMaterial) obj.frustumCulled = false obj.name = MeasureRenderer.LINE_NAME 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.Sprite(this.pointMaterial as THREE.SpriteMaterial) obj.name = MeasureRenderer.POINT_NAME return obj } // appendToScene(...objects: THREE.Object3D[]) { // if (!this.group || this.group.parent !== this.tempViewport.scene.scene) { // if (this.group && this.group.parent !== this.tempViewport.scene.scene) { // // 幻影加载问题 // this.group.parent.removeFromParent() // } // // this.group = new THREE.Group() // this.group.name = MeasureRenderer.GROUP_NAME // this.tempViewport?.scene.add(this.group) // } // // const dragObjects = objects.filter(obj => !!obj.userData.draggable) // //this.tempViewport.dragControl.setDragObjects(dragObjects, 'push') // // this.group.add(...objects) // } afterCreateOrUpdateLine(start: ItemJson, end: ItemJson, type: LinkType, option: RendererCudOption, object: THREE.Object3D) { super.afterCreateOrUpdateLine(start, end, type, option, object) const startPoint = this.tempViewport?.entityManager.findObjectById(start.id) const endPoint = this.tempViewport?.entityManager.findObjectById(end.id) this.tempViewport.labelManager.createOrUpdateLabelByDistance(object, startPoint.position, endPoint.position, { useHtmlLabel: this.useHtmlLabel, fontSize: 0.4, color: '#333333' }) // const p0 = startPoint.position // const p1 = endPoint.position // // const dist = p0.distanceTo(p1) // const label = numberToString(dist) + ' m' // // const position = new THREE.Vector3().addVectors(p0, p1).multiplyScalar(0.5) // let labelObj: Text | CSS2DObject | undefined = object.userData.labelObj // if (!labelObj || !labelObj.parent) { // labelObj = this.createLabel(label) // this.appendToScene(labelObj) // object.userData.labelObj = labelObj // } // // labelObj.position.set(position.x, position.y + 0.3, position.z - 0.2) // // if (this.useHtmlLabel) { // labelObj.element.innerHTML = label // // } else { // // 让文本朝向摄像机 // labelObj.quaternion.copy(this.tempViewport.camera.quaternion) // labelObj.text = label // labelObj.sync() // } } afterDeleteLine(start: ItemJson, end: ItemJson, type: LinkType, option: RendererCudOption, object: THREE.Object3D) { super.afterDeleteLine(start, end, type, option, object) this.tempViewport.labelManager.removeLabel(object) // 删除标签 // const labelObj = object.userData?.labelObj // if (labelObj && labelObj.parent) { // labelObj.parent.remove(labelObj) // } } dispose() { super.dispose() if (this.group && this.group.parent) { this.group.parent.remove(this.group) } this.group = undefined this.pointMaterial?.dispose() this.lineMaterial?.dispose() } }