diff --git a/src/components/Model3DView.vue b/src/components/Model3DView.vue index 110e9db..2f38a72 100644 --- a/src/components/Model3DView.vue +++ b/src/components/Model3DView.vue @@ -386,6 +386,7 @@ function createGroundStore() { side: THREE.DoubleSide // 双面渲染:ml-citation{ref="5,8" data="citationList"} }); const planeMesh = new THREE.Mesh(planeGeometry, material); + planeMesh.rotateX(Math.PI / 2) scene.add(planeMesh); } @@ -928,4 +929,4 @@ function cleanupThree() { } } - \ No newline at end of file + diff --git a/src/core/Constract.ts b/src/core/Constract.ts index 910ac50..a26486d 100644 --- a/src/core/Constract.ts +++ b/src/core/Constract.ts @@ -17,6 +17,7 @@ const Constract = Object.freeze({ CursorModeMeasure: 'measure', CursorModeWay: 'way', CursorModeGstore: 'gstore', + CursorModeRack: 'rack', // 选择模式 CursorModeSelectByRec: 'selectByRec', diff --git a/src/core/ModelUtils.ts b/src/core/ModelUtils.ts index cd4d521..23bfa18 100644 --- a/src/core/ModelUtils.ts +++ b/src/core/ModelUtils.ts @@ -6,6 +6,7 @@ import { computeBoundsTree, disposeBoundsTree } from 'three-mesh-bvh' import { Vector2 } from 'three/src/math/Vector2' import type Toolbox from '@/model/itemType/Toolbox.ts' import EventBus from '@/runtime/EventBus.ts' +import Decimal from 'decimal.js' /** * 确保所有实体之间的关系满足一致性: @@ -474,3 +475,21 @@ function loadObject3DFromJson(items: ItemJson[]): THREE.Object3D[] { return result } + +/** + * 十进制求和 + * @param collection + * @param iteratee + */ +export function decimalSumBy(collection: ArrayLike | null | undefined, iteratee?: ((value: T) => number)): number { + + let sum = new Decimal(0) + _.forEach(collection, (t)=>{ + if (typeof iteratee === 'function') { + sum = sum.add(new Decimal(iteratee(t))) + } else { + sum = sum.add(new Decimal(t)) + } + }) + return sum.toNumber() +} diff --git a/src/core/manager/WorldModel.ts b/src/core/manager/WorldModel.ts index 8b6f429..ce62347 100644 --- a/src/core/manager/WorldModel.ts +++ b/src/core/manager/WorldModel.ts @@ -4,6 +4,7 @@ import EventBus from '@/runtime/EventBus' import Measure from '@/modules/measure' import Way from '@/modules/way' import Gstore from '@/modules/gstore' +import Rack from '@/modules/rack' import StateManager from '@/core/manager/StateManager.ts' export interface WorldModelState { @@ -64,7 +65,8 @@ export default class WorldModel { return Promise.all([ Measure, Way, - Gstore + Gstore, + Rack ]).then(() => { console.log('世界模型初始化完成') @@ -155,4 +157,4 @@ export default class WorldModel { } return Promise.reject('楼层不存在, catalogCode=' + catalogCode) } -} \ No newline at end of file +} diff --git a/src/editor/Model2DEditor.vue b/src/editor/Model2DEditor.vue index 136f18f..e30834e 100644 --- a/src/editor/Model2DEditor.vue +++ b/src/editor/Model2DEditor.vue @@ -53,6 +53,14 @@ :type="state?.cursorMode===Constract.CursorModeGstore?'primary':''" @click="()=>state.cursorMode = Constract.CursorModeGstore"> + + + +
b.bayWidth), this.defaultScale.y, item.dt.rackDepth) point.rotation.set( THREE.MathUtils.degToRad(this.defaultRotation.x), THREE.MathUtils.degToRad(this.defaultRotation.y), @@ -50,57 +52,95 @@ export default class RackRenderer extends BaseRenderer { throw new Error('not allow store line.') } - createPointBasic(item: ItemJson, option?: RendererCudOption): THREE.Object3D[] { + + createPoint(item: ItemJson, option?: RendererCudOption): THREE.Object3D[] { // 创建平面几何体 const group = new THREE.Group() group.name = RackRenderer.POINT_NAME + const rackWidth = decimalSumBy(item.dt.bays, b=>b.bayWidth) + const heights = [] + for (let i = 0; i < item.dt.bays.length; i++) { + const bay = item.dt.bays[i] + const bayHeight = decimalSumBy(bay.levelHeight) + heights.push(bayHeight) + } + const rackHeight = _.max(heights) // 绘制背景矩形框 - const planeGeometry = new THREE.PlaneGeometry(item.dt.storeWidth, item.dt.storeDepth) - planeGeometry.rotateX(-Math.PI / 2) + const planeGeometry = new THREE.PlaneGeometry(rackWidth, item.dt.rackDepth); + + planeGeometry.rotateX(Math.PI / 2) + const planeMaterial = new THREE.MeshBasicMaterial({ - color: 'white', + color: '#9a9090', transparent: true, // 启用透明 - opacity: 0.2, // 50%透明度 + opacity: 0.5, // 50%透明度 depthWrite: false, // 防止深度冲突 side: THREE.DoubleSide // 双面渲染:ml-citation{ref="5,8" data="citationList"} }) const planeMesh = new THREE.Mesh(planeGeometry, planeMaterial) group.add(planeMesh) - if (!item.dt.storeWidth || !item.dt.storeDepth) { + if (!item.dt.bays || !item.dt.rackDepth) { return [group] } // 绘制边框 - const lineXLen = item.dt.storeWidth - this.defaultLineWidth - const lineYLen = item.dt.storeDepth - this.defaultLineWidth + const lineXLen = rackWidth - this.defaultLineWidth + const lineYLen = item.dt.rackDepth - this.defaultLineWidth const lineGeometry = new LineGeometry().setPositions([ - -(lineXLen / 2), -(lineYLen / 2), 0, - lineXLen / 2, -(lineYLen / 2), 0, - lineXLen / 2, lineYLen / 2, 0, - -(lineXLen / 2), lineYLen / 2, 0, - -(lineXLen / 2), -(lineYLen / 2), 0 + -(lineXLen/2),0,-(lineYLen/2), + lineXLen/2,0,-(lineYLen/2), + lineXLen/2,0,lineYLen/2, + -(lineXLen/2),0,lineYLen/2, + -(lineXLen/2),0,-(lineYLen/2) ]) - lineGeometry.rotateX(-Math.PI / 2) const lineMaterial = new LineMaterial({ - color: 0x00ff00, + color: '#0d89a5', linewidth: 0.05, worldUnits: true, resolution: new THREE.Vector2(window.innerWidth, window.innerHeight), side: THREE.DoubleSide - }) - // - const line = new Line2(lineGeometry, lineMaterial) + }); + const line = new Line2(lineGeometry, lineMaterial); group.add(line as THREE.Object3D) - return [group] + let lineDistanceX = 0 + + for (let i = 0; item.dt.bays.length > 1 && i < item.dt.bays.length - 1; i++) { + const bay = item.dt.bays[i] + lineDistanceX += bay.bayWidth + const lineGeometryT = new LineGeometry().setPositions([ + -(lineDistanceX) +(lineXLen/2),0,lineYLen/2, + -(lineDistanceX)+(lineXLen/2),0,-(lineYLen/2) + ]) + const lineT = new Line2(lineGeometryT, lineMaterial); + group.add(lineT as THREE.Object3D) + } + + // 设置位置 + group.position.set(item.tf[0][0], item.tf[0][1], item.tf[0][2]) + + + item.dt.rackWidth = rackWidth + item.dt.rackHeight = rackHeight + + const points = [group] + this.fillObjectUserDataFromItem(item, ...points) + this.afterCreateOrUpdatePoint(item, option, points) + this.tempViewport.entityManager.appendObject(item.id, points) + this.appendToScene(...points) + return points } dispose() { super.dispose() this.pointMaterial.dispose() } + + createPointBasic(item: ItemJson, option?: RendererCudOption): Object3D[] { + return []; + } }