You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
cy_web/src/api/util/mapDrawing.js

1743 lines
56 KiB

import * as THREE from '@/lib/three/build/three.module.js'
import { WEBGL } from '@/lib/three/examples/jsm/WebGL.js'
import { OrbitControls } from '@/lib/three/examples/jsm/controls/OrbitControls.js'
import { Line2 } from '@/lib/three/examples/jsm/lines/Line2.js'
import { LineGeometry } from '@/lib/three/examples/jsm/lines/LineGeometry.js'
import { LineMaterial } from '@/lib/three/examples/jsm/lines/LineMaterial.js'
import { FBXLoader } from '@/lib/three/examples/jsm/loaders/FBXLoader.js'
const EventEmitter = require('events')
// var latticeForPiler1 = JSON.parse(JSON.stringify(localStorage.getItem('latticeForPiler1')))
// console.log(this.property.latticeForPiler1);
class MapDrawing extends EventEmitter {
constructor (container, property) {
super()
this.initDefaultOptions()
this.container = container
this.property = this.mergeObject(this.property, property)
// this.property.latticeForPiler1=JSON.parse(JSON.stringify(localStorage.getItem('latticeForPiler1')))
}
/**
* 初始化默认配置
*/
initDefaultOptions () {
this.property = {
width: 500,
height: 500,
event: {
onClick: (data) => {
}
},
scene: null,
camera: null,
renderer: null,
videoGround: null,
light: null,
mesh: null,
material: {
baseLine: null,
line: null
},
layer: {
storageRack: [],
storageRackLabel: [],
freightSpace: [],
fourwayCarRoad: [],
roadChild: [],
otherPoint: [],
pointChild: [],
levels: {
// nowLevel: localStorage.getItem('level').slice(6, 7)
nowLevel:localStorage.getItem('level')?localStorage.getItem('level').slice(6, 7) : 'level-1'
}
},
textures: [],
cars: [],
trajectorys: [],
errorNodes: {},
raycaster: new THREE.Raycaster(),
pointer: new THREE.Vector2(),
config: {},
latticeForPiler1 : JSON.parse((localStorage.getItem('latticeForPiler1')))
}
let fps = 60 // 多少毫秒执行一次
this.animateControlInfo = {
fps: fps,
fpsInterval: 1000 / fps,
last: new Date().getTime() // 上次执行的时刻
}
}
/**
* 合并json对象
* @param obj1
* @param obj2
* @returns {{}}
*/
mergeObject (obj1, obj2) {
let obj3 = {}
for (let attrname in obj1) {
if (obj1.hasOwnProperty(attrname)) {
obj3[attrname] = obj1[attrname]
}
}
for (let attrname1 in obj2) {
if (obj2.hasOwnProperty(attrname1)) {
obj3[attrname1] = obj2[attrname1]
}
}
return obj3
}
/**
* 初始化场景
*/
initScene () {
this.property.scene = new THREE.Scene()
this.property.scene.background = null
}
/**
* 初始化摄像头
*/
initCamera () {
// 设置透视投影的相机,默认情况下相机的上方向为Y轴,右方向为X轴,沿着Z轴朝里(视野角:fov 纵横比:aspect 相机离视体积最近的距离:near 相机离视体积最远的距离:far)
this.property.camera = new THREE.PerspectiveCamera(45, this.property.width / this.property.height, 1, 15000)
let eyePoint = this.property.config.eyePoint || [0, 1000, 0]
this.property.camera.position.set(eyePoint[0], eyePoint[1], eyePoint[2])
// camera.position.x = 0;//设置相机的位置坐标
// camera.position.y = 0;//设置相机的位置坐标
// camera.position.z = 100;//设置相机的位置坐标
// camera.up.x = 1;//设置相机的上为「x」轴方向
// camera.up.y = 1;//设置相机的上为「y」轴方向
// camera.up.z = 0;//设置相机的上为「z」轴方向
// 设置视野的中心坐标
this.property.camera.lookAt(0, 0, 0)
}
/**
* 初始化渲染器
*/
initRender () {
this.property.renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true })
// console.log(this.property.width,this.property.height);
this.property.renderer.setSize(this.property.width, this.property.height - 180)
document.getElementById('mapContainer').appendChild(this.property.renderer.domElement)
// 设置背景色
this.property.renderer.setClearColor(0x000000, 1.0)
}
/**
* 初始化事件
*/
initEvent () {
let self = this
document.getElementById('mapContainer').addEventListener('click', (event) => {
self.mouseClick(event)
})
}
/**
* 初始化通用材质
*/
initMaterials () {
// Color:线条的颜色,用16进制来表示,默认的颜色是白色。
// Linewidth:线条的宽度,默认时候1个单位宽度。
// Linecap:线条两端的外观,默认是圆角端点,当线条较粗的时候才看得出效果,如果线条很细,那么你几乎看不出效果了。
// Linejoin:两个线条的连接点处的外观,默认是“round”,表示圆角。
// VertexColors:定义线条材质是否使用顶点颜色,这是一个boolean值。意思是,线条各部分的颜色会根据顶点的颜色来进行插值。
this.property.material.baseLine = new THREE.LineBasicMaterial({ color: 0x0000ff })
this.property.material.line = new LineMaterial({ color: 0x0000ff, linewidth: 5 })
this.property.material.line.resolution.set(this.property.width, this.property.height)
this.property.material.colorByPointLine = new THREE.LineBasicMaterial({
vertexColors: THREE.VertexColors
})
}
/**
* 初始化视角交互控制器
*/
initControls () {
this.property.controls = new OrbitControls(this.property.camera, this.property.renderer.domElement)
// controls.addEventListener('change', this.render) // 持续渲染的场景不需要,静态场景才需要监听
// controls.target.set(64, 64, 128)
this.property.controls.minZoom = 0.5
this.property.controls.maxZoom = 4
// 限制最大仰视角和俯视角
this.property.controls.minPolarAngle = 0
this.property.controls.maxPolarAngle = 1.5
// 禁止缩放
// controls.enableZoom=false
// 缩放限制
// controls.minDistance = 50
// controls.maxDistance = 450
// 是否使用键盘
this.property.controls.enableKeys = true
// 修改鼠标按键
this.property.controls.mouseButtons = {
LEFT: THREE.MOUSE.PAN,
MIDDLE: THREE.MOUSE.DOLLY,
RIGHT: THREE.MOUSE.ROTATE
}
this.property.controls.touches = {
ONE: THREE.TOUCH.PAN, // 单个手指 拖动(默认旋转:ROTATE)
TWO: THREE.TOUCH.DOLLY_PAN // 两个手指 缩放
}
// controls.update()
}
/**
* 初始化光源
*/
initLight () {
// this.property.light = new THREE.DirectionalLight(0xFF0000, 11.0, 0)
// this.property.light.position.set(200, 2000, 200)
// this.property.scene.add(this.property.light)
this.property.light = new THREE.AmbientLight(0xffffff)
this.property.light.position.set(100, 100, 200)
this.property.scene.add(this.property.light)
// this.property.light = new THREE.PointLight(0xffffff, 1, 0)
// this.property.light.position.set(300, 2000, 300)
// this.property.scene.add(this.property.light)
}
layerControl (layerId, showFlg,sliceIndex) {
let layer
if (layerId.indexOf('level') > -1) {
let index = layerId.split('-')[1]
layer = this.property.layer.levels[index]
if (showFlg) {
this.property.layer.levels.nowLevel = sliceIndex
} else {
this.property.layer.levels.nowLevel = null
}
} else {
layer = this.property.layer[layerId]
}
if (layerId === 'freightSpace' && Object.keys(this.property.layer.levels).length > 1 && showFlg) {
layer = null
Object.keys(this.property.layer.levels).map(levelKey => {
if (this.property.layer.levels.nowLevel) {
layer = this.property.layer.levels[this.property.layer.levels.nowLevel]
}
})
}
if (layer) {
layer.map(obj => {
if (obj.type === 'GridHelper') {
} else if (obj.type === 'Mesh') {
obj.visible = showFlg
} else if (obj.type === 'Group') {
obj.visible = showFlg
obj.children.forEach((child, i) => {
child.visible = showFlg
})
}
})
}
if (layerId === 'freightSpace') {
layer = this.property.layer['storageRackLabel']
layer.map(obj => {
if (obj.type === 'GridHelper') {
} else if (obj.type === 'Mesh') {
obj.visible = !showFlg
} else if (obj.type === 'Group') {
obj.visible = !showFlg
obj.children.forEach((child, i) => {
child.visible = !showFlg
})
}
})
}
}
/**
* 执行渲染
*/
render () {
this.property.renderer.render(this.property.scene, this.property.camera)
}
/**
* 绘制基础线条
* @param points
* @param info
* @returns {Line}
*/
drawBaseLine (points, info, nodeId = '') {
let lineMaterial = info ? new THREE.LineBasicMaterial(info) : this.property.material.baseLine
var geometry = new THREE.Geometry()
points.map((point) => {
// 长宽高分别对应桌面的xy以及竖直与屏幕,正值基于000点向右上及屏幕前方延伸
geometry.vertices.push(new THREE.Vector3(point[0], point[1], point[2]))
})
var line = new THREE.Line(geometry, lineMaterial)
this.property.scene.add(line)
line.nodeId = nodeId
line.customNodeType = 'baseLine'
line.customDataType = info.type || ''
line.nodeInfo = info
return line
}
/**
* 绘制有宽度的线条
* @param points
* @returns {Line2|Line2}
*/
drawLine (points, info = { id: '' }) {
if (!info.id) {
info.id = ''
}
var geometry = new LineGeometry()
let pointsBuffer = []
points.map((point) => {
// 长宽高分别对应桌面的xy以及竖直与屏幕,正值基于000点向右上及屏幕前方延伸
pointsBuffer.push(point[0])
pointsBuffer.push(point[1])
pointsBuffer.push(point[2])
})
geometry.setPositions(pointsBuffer)
var line = new Line2(geometry, this.property.material.line)
line.computeLineDistances()
this.property.scene.add(line)
line.nodeId = info.id
line.customNodeType = 'line'
line.customDataType = info.type || ''
line.nodeInfo = info
return line
}
/**
* 画网格
* @param width
* @param heigth
*/
initGrid (width = 1000, heigth = 1000, singleWidth, singleHeight) {
singleWidth = singleWidth || 100
singleHeight = singleHeight || 100
let xNum = parseInt(width / singleWidth)
let zNum = parseInt(heigth / singleHeight)
for (let i = 0; i <= xNum; i++) {
let xLine = this.drawBaseLine([[0, 0, -heigth / 2], [0, 0, heigth / 2]], { color: 0xffffff, opacity: 0.1 })
xLine.position.x = (i * width / xNum) - width / 2
}
for (let j = 0; j <= zNum; j++) {
let zLine = this.drawBaseLine([[-width / 2, 0, 0], [width / 2, 0, 0]], { color: 0xffffff, opacity: 0.1 })
zLine.position.z = (j * heigth / zNum) - heigth / 2
}
}
/**
* 画视频地板
* @param videoDomId
* @param height
*/
initVideoGround () {
if (this.property.videoGround) {
this.property.videoGround.video = document.createElement(this.property.videoGround.videoDomId)
this.property.videoGround.video.src = this.property.videoGround.src
this.property.videoGround.video.autoplay = true
// this.property.videoGround.video.muted = true
this.property.videoGround.video.volume = 0.001
this.property.videoGround.video.loop = true
this.property.videoGround.video.load()
this.property.videoGround.video.crossOrigin = 'anonymous'
// 通过video对象实例化纹理
let texture = new THREE.VideoTexture(this.property.videoGround.video)
texture.wrapS = texture.wrapT = THREE.ClampToEdgeWrapping
texture.minFilter = THREE.LinearFilter
// 创建几何体
let geometry = new THREE.PlaneGeometry(this.property.videoGround.width, this.property.videoGround.height)
// 几何体材质对象
const materials = new THREE.MeshBasicMaterial({ map: texture })
// 创建网格模型对象
this.property.videoGround.node = new THREE.Mesh(geometry, materials)
// 设置几何体位置
this.property.videoGround.node.position.x = 0
this.property.videoGround.node.position.y = this.property.videoGround.elevation
this.property.videoGround.node.position.z = 0
// 设置平躺
this.property.videoGround.node.rotation.x = -Math.PI / 2
this.property.scene.add(this.property.videoGround.node)
}
}
/**
* 计算轨迹路线
* @param points
* @returns {CurvePath}
*/
computeCurve (points) {
let line, p1, p2, p3
// 作为拐弯的弧度
let R = 20
// 添加一些点作为开头和拐点
let arr = []
points.map(point => {
arr.push(new THREE.Vector3(point[0], point[1], point[2]))
})
let curvePath = new THREE.CurvePath()
for (let i = 0; i < arr.length - 1; i++) {
if (i === 0) {
let dir = arr[0].clone().sub(arr[1])
dir.normalize()
p2 = arr[1].clone()
if (arr.length === 2) {
p2.add(dir.clone())
} else {
p2.add(dir.clone().multiplyScalar(R))
}
line = new THREE.LineCurve3(arr[0], p2)
curvePath.curves.push(line)
} else {
// 计算三个点构成的两条线的方向
let dir1 = arr[i - 1].clone().sub(arr[i])
dir1.normalize()
let dir2 = arr[i + 1].clone().sub(arr[i])
dir2.normalize()
let p12_ = arr[i].clone()
p12_.add(dir1.clone().multiplyScalar(R))
p1 = arr[i].clone().add(dir1.clone().multiplyScalar(R))
p2 = arr[i].clone()
p3 = arr[i].clone().add(dir2.clone().multiplyScalar(R))
let beziercurve = new THREE.QuadraticBezierCurve3(p1, p2, p3)
let line1 = arr[i].clone()
line1.add(dir2.clone().multiplyScalar(R))
let line2 = arr[i + 1].clone()
if (i < arr.length - 2) {
// 最后一段不用减掉半径尺寸
line2.add(dir2.clone().multiplyScalar(-R))
}
line = new THREE.LineCurve3(line1, line2)
// 把转换曲线和直线插入曲线中
curvePath.curves.push(beziercurve, line)
}
}
return curvePath
}
/**
* 绘制流动管线
* @param curve
* @param imageName
* @returns {{tube: Mesh, curve: *}}
*/
createTube (curve, imageName = 'arrow', info) {
if (!info.id) {
info.id = ''
}
let width = info.width || 5
let tubeGeometry = new THREE.TubeGeometry(curve, 200, width, 6, false)
let textureLoader = new THREE.TextureLoader()
let texture = textureLoader.load(require('../../assets/image/' + imageName + '.png'))
this.property.textures[info.id] = {
texture: texture
}
texture.wrapS = THREE.RepeatWrapping
texture.wrapT = THREE.RepeatWrapping
texture.repeat.x = 10
texture.repeat.y = 4
texture.offset.y = 0.5
let tubeMaterial = new THREE.MeshMatcapMaterial({
map: texture,
transparent: true
})
let tube = new THREE.Mesh(tubeGeometry, tubeMaterial)
this.property.scene.add(tube)
tube.nodeId = info.id
tube.customNodeType = 'pipeline'
tube.customDataType = (info.type || '') + 'Trajectory'
tube.nodeInfo = info
return {
curve: curve,
tube: tube
}
}
/**
* 绘制管线
*/
drawPipeline (pathPoints, imageName = 'arrow', info) {
return this.createTube(this.computeCurve(pathPoints), imageName, info)
}
/**
* 绘制矩形
* @param info
* @returns {Mesh}
*/
//3.14
drawRectangle (info) {
let self = this
if (!info.id) {
info.id = ''
}
let defaultInfo = {
s3: [20, 20, 20],
segments: [1, 1, 1],
color: 0x666666
}
if (!info) {
info = defaultInfo
} else {
if (!info.s3) {
info.s3 = defaultInfo.s3
}
if (!info.segments) {
info.segments = defaultInfo.segments
}
if (!info.color) {
info.color = defaultInfo.color
}
if (isNaN(parseFloat(info.rotationX))) {
info.rotationX = -Math.PI / 2
}
}
//构建几何体
let gube = new THREE.CubeGeometry(info.s3[0], info.s3[1], info.s3[2], info.segments[0], info.segments[1], info.segments[2])
// console.log(info.s3[0], info.s3[1], info.s3[2], info.segments[0], info.segments[1], info.segments[2]);
var gubeMaterial = new THREE.MeshMatcapMaterial({
color: self.loadColor(info.color)
})
var gubeMesh = new THREE.Mesh(gube, gubeMaterial)
// gubeMesh.position.set(info.p3[0], info.p3[1], info.p3[2])
gubeMesh.nodeId = info.id
gubeMesh.customNodeType = 'rectangle'
gubeMesh.customDataType = info.type || ''
gubeMesh.nodeInfo = info
const group = new THREE.Group()
group.position.set(info.p3[0], info.p3[1], info.p3[2])
group.add(gubeMesh)
if (info.label) {
let label = this.addTextGeometry({
id: info.id,
type: info.type + 'Label',
label: info.label
})
group.add(label)
if (info.isStorageRack) {
label.visible = false
self.property.layer.storageRackLabel.push(label)
}
if (info.isRoad) {
label.visible = false
}
if (info.isOtherPoint) {
label.visible = false
}
}
this.property.scene.add(group)
return group
}
/**
* 创建矩形
* @param info
* @returns {Mesh}
*/
createRectangle (info) {
// console.log('我执行了');
let self = this
if (!info.id) {
info.id = ''
}
let defaultInfo = {
s3: [20, 20, 20],
segments: [1, 1, 1],
color: 0x666666
}
if (!info) {
info = defaultInfo
} else {
if (!info.s3) {
info.s3 = defaultInfo.s3
}
if (!info.segments) {
info.segments = defaultInfo.segments
}
if (!info.color) {
info.color = defaultInfo.color
}
}
let gube = new THREE.CubeGeometry(info.s3[0], info.s3[1], info.s3[2], info.segments[0], info.segments[1], info.segments[2])
var gubeMaterial = new THREE.MeshMatcapMaterial({
color: self.loadColor(info.color)
})
var gubeMesh = new THREE.Mesh(gube, gubeMaterial)
gubeMesh.position.set(info.p3[0], info.p3[1], info.p3[2])
gubeMesh.nodeId = info.id
gubeMesh.customNodeType = 'rectangle'
gubeMesh.customDataType = info.type || ''
gubeMesh.nodeInfo = info
return gubeMesh
}
/**
* 创建矩形
* @param info
* @returns {Mesh}
*/
addTextGeometry (info) {
// console.log(1111);
// debugger
if (typeof info === 'string') {
info = {
id: '',
label: info
}
}
let text = info.label
if (typeof text !== 'string') {
text = text.toString()
}
let rows = text.split('\r\n')
if (!info.lineHeight) {
info.lineHeight = 140
}
if (!info.scale) {
info.scale = 0.6
}
if (!info.width) {
info.width = 160
}
if (!info.height) {
info.height = 20 * rows.length + 70
}
if (isNaN(parseFloat(info.rotationX))) {
info.rotationX = -Math.PI / 2
}
// 用canvas生成图片
let canvas = document.createElement('canvas')
let ctx = canvas.getContext('2d')
canvas.width = info.width
canvas.height = info.height
// 设置文字
ctx.fillStyle = 'transparent'
ctx.fillRect(0, 0, info.width, info.height)
rows.map((row, index) => {
// if(latticeForPiler1)
// 制作矩形
ctx.fillStyle = 'black'
ctx.font = '600 40px "宋体"'
// ctx.font = '600 40px "宋体"'
// ctx.color = 'red'
ctx.fillStyle = 'black'
ctx.fillText(row, 5, info.lineHeight * index + 60)
})
// console.log(ctx);
// 生成图片
let url = canvas.toDataURL('image/png')
// 将图片构建到纹理中
let geometry1 = new THREE.PlaneGeometry(info.width, info.height)
let material1 = new THREE.MeshBasicMaterial({
map: new THREE.TextureLoader().load(url),
side: THREE.DoubleSide,
opacity: 1,
transparent: true
})
let rect = new THREE.Mesh(geometry1, material1)
rect.position.set(0, 10, 0)
rect.rotation.x = info.rotationX
if (this.property.config.textRotation) {
rect.rotation.z = this.property.config.textRotation
}
rect.scale.set(info.scale, info.scale, info.scale)
rect.nodeId = info.id
rect.customNodeType = 'label'
rect.customDataType = info.type || ''
rect.nodeInfo = info
return rect
}
/**
* 绘制内部矩形
* @param paren
* @returns {[]}
*/
drawRactangleInParent (paren, children, dictionary) {
let position = paren.node.position
let fullHeight = paren.s3[2] * 0.1 > 4 ? paren.s3[2] - 4 : paren.s3[2] * 0.9
let offset = (paren.s3[2] - fullHeight) / 4
let height = (paren.s3[2]) / paren.capacity
let y = position.z - paren.s3[2] / 2 + height / 2 + offset
let childNodes = []
for (let i = 0; i < children.length; i++) {
let child = children[i]
let width = paren.s3[0] * 0.1 > 4 ? paren.s3[0] - 4 : paren.s3[0] * 0.9
let stateDictionary = dictionary[dictionary.hasOwnProperty(child.state) ? child.state : '0']
let freightSpace = this.drawRectangle({
id: child.id,
parentId: child.parentId,
label: child.id,
spaceId: child.spaceId,
type: paren.childType || 'child',
p3: [paren.p3[0], paren.p3[1] + 1, y + height * i],
s3: [width, 5, height - 3],
segments: [1, 1, 1],
state: child.state || 0,
color: stateDictionary.color
})
childNodes.push(freightSpace)
this.property.layer.freightSpace.push(freightSpace)
if (this.property.config.mutiLayer) {
if (!this.property.layer.levels.hasOwnProperty(child.level)) {
this.property.layer.levels[child.level] = []
}
this.property.layer.levels[child.level].push(freightSpace)
if (child.level > 1) {
freightSpace.visible = false
}
}
}
return childNodes
}
/**
* 绘制内部矩形(带高度)
* @param paren
* @returns {[]}
*/
//四向车当前使用函数 3.15改
drawRactangleInParentWithLevel (paren, children, dictionary) {
let childNodes = []
// console.log('我被调用了一次');
for (let i = 0; i < children.length; i++) {
let child = children[i]
let stateDictionary = dictionary[dictionary.hasOwnProperty(child.state) ? child.state : '0']
// console.log('我被调用了');
let freightSpace = this.drawRectangle({
id: child.id,
parentId: child.parentId,
label: child.id,
spaceId: child.spaceId,
type: 'child',
p3: [paren.p3[0], paren.p3[1] + 5, paren.p3[2]],
s3: [paren.s3[0], 5, paren.s3[2]],
segments: [1, 1, 1],
state: child.state || 0,
color: stateDictionary.color
})
childNodes.push(freightSpace)
this.property.layer.freightSpace.push(freightSpace)
if (this.property.config.mutiLayer) {
if (!this.property.layer.levels.hasOwnProperty(child.level)) {
this.property.layer.levels[child.level] = []
}
this.property.layer.levels[child.level].push(freightSpace)
if (child.level > 1) {
freightSpace.visible = false
}
}
}
return childNodes
}
/**
* 绘制仓库
*/
drawWarehouses () {
// console.log('我不知道我调用了几次');
//调用一次
let self = this
Object.keys(this.property.warehouseInfo.storageRack).map(storageRackId => {
let storageRack = this.property.warehouseInfo.storageRack[storageRackId]
let stateDictionary = this.property.config.tileStateDictionary[this.property.config.tileStateDictionary.hasOwnProperty(storageRack.state) ? storageRack.state : '0']
//疑似仓库地图 点位`1
console.log(this.property.layer.levels.nowLevel);
let storageRackInfo = {
id: storageRack.id,
type: 'storageRack',
label: storageRack.id,
p3: [storageRack.x, 0, storageRack.y],
// p3: [120, 0, 120],
s3: [storageRack.xLength, 2, storageRack.yLength],
segments: [1, 1, 1],
capacity: storageRack.capacity,
color: stateDictionary.color,
freightSpace: storageRack.freightSpace,
childType: 'freightSpace',
state: storageRack.state,
isStorageRack: true
}
storageRackInfo.node = storageRack.node = this.drawRectangle(storageRackInfo)
self.property.layer.storageRack.push(storageRackInfo.node)
let freightSpaces = Object.values(storageRackInfo.freightSpace)
let dictionary = this.property.config.freightSpaceStateDictionary
if (self.property.config.mutiLayer) {
// console.log('你好,Mr.sun',storageRackInfo);
storageRack.childNodes = self.drawRactangleInParentWithLevel(storageRackInfo, freightSpaces, dictionary)
} else {
console.log(2222);
storageRack.childNodes = self.drawRactangleInParent(storageRackInfo, freightSpaces, dictionary)
}
})
}
filterFreightSpace (rowIndex, columnIndex, levelIndex) {
this.property.layer.freightSpace.map(freightSpace => {
let suc = false
freightSpace.children.forEach((child, i) => {
if (child.nodeInfo.spaceId) {
let nums = child.nodeInfo.spaceId.split('-')
if ((isNaN(parseInt(rowIndex)) || rowIndex === nums[0]) &&
(isNaN(parseInt(columnIndex)) || columnIndex === nums[1]) &&
(isNaN(parseInt(levelIndex)) || levelIndex === nums[2])) {
suc = true
}
}
})
freightSpace.visible = suc
})
}
/**
* 绘制四向车通路
*/
drawRoad () {
let self = this
Object.keys(this.property.warehouseInfo.fourwayCarRoad).map(fourwayCarRoadId => {
let fourwayCarRoad = this.property.warehouseInfo.fourwayCarRoad[fourwayCarRoadId]
let stateDictionary = this.property.config.roadStateDictionary[this.property.config.roadStateDictionary.hasOwnProperty(fourwayCarRoad.state) ? fourwayCarRoad.state : '0']
//p3
let fourwayCarRoadInfo = {
id: fourwayCarRoad.id,
type: 'fourwayCarRoad',
label: fourwayCarRoad.id,
p3: [fourwayCarRoad.x, 0, fourwayCarRoad.y],
// p3: [1, 0, 2],
s3: [fourwayCarRoad.xLength, 2, fourwayCarRoad.yLength],
segments: [1, 1, 1],
color: stateDictionary.color,
level: fourwayCarRoad.level,
childType: 'roadTile',
isRoad: true
}
fourwayCarRoadInfo.node = fourwayCarRoad.node = this.drawRectangle(fourwayCarRoadInfo)
self.property.layer.fourwayCarRoad.push(fourwayCarRoadInfo.node)
let children = Object.values(fourwayCarRoadInfo.level)
let dictionary = this.property.config.roadStateDictionary
if (self.property.config.mutiLayer) {
fourwayCarRoad.childNodes = self.drawRactangleInParentWithLevel(fourwayCarRoadInfo, children, dictionary)
} else {
fourwayCarRoad.childNodes = self.drawRactangleInParent(fourwayCarRoadInfo, children, dictionary)
}
})
}
/**
* 绘制特殊点位
*/
drawOtherPoint () {
let self = this
Object.keys(this.property.warehouseInfo.otherPoint).map(otherPointId => {
let otherPoint = this.property.warehouseInfo.otherPoint[otherPointId]
let stateDictionary = this.property.config.otherPointStateDictionary[this.property.config.otherPointStateDictionary.hasOwnProperty(otherPoint.state) ? otherPoint.state : '0']
let otherPointInfo = {
id: otherPoint.id,
type: 'otherPoint',
label: otherPoint.id,
p3: [otherPoint.x, 0, otherPoint.y],
s3: [otherPoint.xLength, 2, otherPoint.yLength],
segments: [1, 1, 1],
color: stateDictionary.color,
childType: 'otherPointTile',
isOtherPoint: true
}
otherPointInfo.node = otherPoint.node = this.drawRectangle(otherPointInfo)
self.property.layer.otherPoint.push(otherPointInfo.node)
let children = Object.values(otherPointInfo.level)
let dictionary = this.property.config.otherPointStateDictionary
if (self.property.config.mutiLayer) {
otherPoint.childNodes = self.drawRactangleInParentWithLevel(otherPointInfo, children, dictionary)
} else {
otherPoint.childNodes = self.drawRactangleInParent(otherPointInfo, children, dictionary)
}
})
}
/**
* 绘制堆垛机
*/
drawPilers () {
if (this.property.warehouseInfo.piler) {
Object.keys(this.property.warehouseInfo.piler).map(pilerId => {
let piler = this.property.warehouseInfo.piler[pilerId]
piler.type = 'piler'
piler.p3 = piler.pathPoints[0]
piler.segments = [1, 1, 1]
let stateDictionary = this.property.config.pilerStateDictionary[this.property.config.pilerStateDictionary.hasOwnProperty(piler.state) ? piler.state : '0']
piler.color = stateDictionary.color
piler.node = this.drawRectangle(piler)
piler.pathModel = this.drawPipeline(piler.pathPoints, 'arrow', piler)
})
}
}
/**
* 绘制小车
*/
drawCars () {
if (this.property.warehouseInfo.carModel.cars) {
Object.keys(this.property.warehouseInfo.carModel.cars).map(carId => {
let car = this.property.warehouseInfo.carModel.cars[carId]
if (car.pathPoints) {
car.type = 'car'
car.label = car.id
car.p3 = car.pathPoints[0]
car.segments = [1, 1, 1]
let stateDictionary = this.property.config.carStateDictionary[this.property.config.carStateDictionary.hasOwnProperty(car.state) ? car.state : '0']
car.color = stateDictionary.color
car.node = this.drawRectangle(car)
}
})
}
}
/**
* 绘制小车
*/
drawCar (carInfo) {
if (!this.property.warehouseInfo.carModel) {
this.property.warehouseInfo.carModel = {
cars: {}
}
}
if (!this.property.warehouseInfo.carModel.cars.hasOwnProperty(carInfo.carId)) {
let car = this.property.warehouseInfo.carModel.cars[carInfo.carId] = JSON.parse(JSON.stringify(carInfo))
car.id = car.carId
car.type = 'car'
car.label = car.carId
car.p3 = car.pathPoints[0]
car.segments = [1, 1, 1]
let stateDictionary = this.property.config.carStateDictionary[this.property.config.carStateDictionary.hasOwnProperty(car.state) ? car.state : '0']
car.color = stateDictionary.color
car.node = this.drawRectangle(car)
}
}
/**
* 绘制传送带
*/
drawBelt () {
if (this.property.warehouseInfo.beltModel) {
let beltModel = this.property.warehouseInfo.beltModel
if (beltModel.pathPoints) {
beltModel.pathModel = this.drawPipeline(beltModel.pathPoints, 'arrow-g', beltModel)
Object.keys(this.property.warehouseInfo.beltModel.trays).map(trayId => {
let tray = this.property.warehouseInfo.beltModel.trays[trayId]
tray.type = 'tray'
tray.label = tray.id
tray.p3 = beltModel.pathPoints[0]
tray.segments = [1, 1, 1]
let stateDictionary = this.property.config.trayStateDictionary[this.property.config.trayStateDictionary.hasOwnProperty(tray.state) ? tray.state : '0']
tray.color = stateDictionary.color
tray.node = this.drawRectangle(tray)
})
}
}
}
getS3 (mesh) {
let box = new THREE.Box3().setFromObject(mesh)
let size = box.size()
return size
}
/**
* 物体是否在场景中显示
* @param {THREE.Object3D} obj 3D物体
* @return {Boolean} 是否在场景中显示
* */
activeInHierarchy (obj) {
if (!obj.visible) {
return false
}
// 遍历父对象
let parent = obj.parent
while (parent) {
if (!parent.visible) {
return 0
}
parent = parent.parent
}
return 1
}
/**
* 获取点击到的所有物体
* @param {THREE.Event} event 点击事件
* @param {THREE.Group} group group
* @param {Boolean} visibleType 物体隐藏还是显示 0只看隐藏的1只看显示的2看全部的
* @return {Array} 射线下的所有物体
* */
getIntersects (event, visibleType = 1) {
let canvas = event.path ? event.path[0] : event.currentTarget.children[0]
event.preventDefault()
/**
* THREE.Raycaster 对象从屏幕上的点击位置向场景发射的一束光线
* THREE.Raycaster,THREE.Vector2():声明raycaster 和mouse变量
* */
var raycaster = new THREE.Raycaster()
// 处理画布与电脑屏幕存在偏移量问题
var divObj = canvas.getBoundingClientRect()
// 获取鼠标点击位置
var Sx = event.clientX - divObj.left
var Sy = event.clientY - divObj.top
// 将鼠标位置归一化为设备坐标。x 和 y 方向的取值范围是 (-1 to +1)
var x = (Sx / canvas.width) * 2 - 1
var y = -(Sy / canvas.height) * 2 + 1
// 通过鼠标点击的位置(二维坐标)和当前相机的矩阵计算出射线的位置
raycaster.setFromCamera(new THREE.Vector2(x, y), this.property.camera)
// 获取与raycaster射线相交的数组集合,其中的元素按照距离排序,越靠近的越靠前
var intersects = raycaster.intersectObjects(this.property.scene.children, true)
let objs = []
intersects.forEach(object => {
if (visibleType === 2 || this.activeInHierarchy(object.object) === visibleType) {
objs.push(object)
}
})
// 返回选中的对象数组query
return objs
}
/**
* 点击事件
**/
mouseClick (event) {
const intersects = this.getIntersects(event)
let data = { all: [] }
if (intersects.length > 0) {
intersects.map(intersect => {
let selectObj = intersect.object
if (selectObj.hasOwnProperty('customNodeType')) {
if (!data[selectObj.customNodeType]) {
data[selectObj.customNodeType] = []
}
data[selectObj.customNodeType].push(selectObj)
data['all'].push(selectObj)
}
})
}
// this.property.event.onClick(data)
this.property.event.ondblclick(data)
}
/**
* 动画处理
*/
animate (from) {
// console.log(1122222);
let self = from || this
requestAnimationFrame(() => {
// console.log(111);
self.animate(self)
})
// if (!this.interValKey) {
// this.interValKey = setInterval(() => {
// self.animate(self)
// }, 100)
// }
// 执行时的时间
var now = new Date().getTime()
var elapsed = now - this.animateControlInfo.last
// console.log(elapsed,this.animateControlInfo.fpsInterval);
// 经过了足够的时间
if (elapsed > this.animateControlInfo.fpsInterval) {
this.animateControlInfo.last = now - (elapsed % this.animateControlInfo.fpsInterval) // 校正当前时间
if (self.property.warehouseInfo) {
self.computePipeLineFlow()
if (self.property.warehouseInfo.piler) {
self.computePilerState()
}
if (self.property.warehouseInfo.carModel) {
self.computeCarState()
}
if (self.property.warehouseInfo.beltModel) {
self.computeTrayState()
}
}
self.render()
}
// if (this.property.videoGround && this.property.videoGround.video.played) {
// }
}
moveTo (nodeId, fuzzyQuery = false) {
let position = this.getPositionByText(nodeId, fuzzyQuery)
if (position) {
let nowEyePoint = this.property.camera.position
let newEyePoint = [
nowEyePoint.x + position.x - this.property.controls.target.x,
nowEyePoint.y + position.y - this.property.controls.target.y,
nowEyePoint.z + position.z - this.property.controls.target.z
]
let distance = this.getDistanceByPoints(newEyePoint, position)
let rate = 500 / distance
newEyePoint = this.getNewPointByRate(position, newEyePoint, rate)
this.property.camera.position.set(newEyePoint[0], newEyePoint[1], newEyePoint[2])
this.property.controls.target.set(position.x, position.y, position.z)
}
}
getNewPointByRate (p1, p2, rate = 1) {
if (p1.x) {
if (p1.e) {
p1.y = p1.e
}
p1 = [p1.x, p1.y, p1.z]
}
if (p2.x) {
if (p2.e) {
p2.y = p2.e
}
p2 = [p2.x, p2.y, p2.z]
}
let newPoint = [
p1[0] + (p2[0] - p1[0]) * rate,
p1[1] + (p2[1] - p1[1]) * rate,
p1[2] + (p2[2] - p1[2]) * rate
]
return newPoint
}
getDistanceByPoints (p1, p2) {
if (p1.x) {
if (p1.e) {
p1.y = p1.e
}
p1 = [p1.x, p1.y, p1.z]
}
if (p2.x) {
if (p2.e) {
p2.y = p2.e
}
p2 = [p2.x, p2.y, p2.z]
}
let distance = Math.sqrt(Math.pow(p2[0] - p1[0], 2) + Math.pow(p2[1] - p1[1], 2) + Math.pow(p2[2] - p1[2], 2))
return distance
}
getPositionByText (text, fuzzyQuery = false) {
let position = null
this.property.scene.traverse(obj => {
if (obj.type === 'GridHelper') {
} else if (obj.type === 'Mesh') {
if (obj.nodeId !== undefined && obj.customDataType === 'freightSpace') {
if ((!fuzzyQuery && obj.nodeId.toString() === text) || (fuzzyQuery && obj.nodeId.toString().indexOf(text) > -1)) {
if (!position || obj.position.x || obj.position.y || obj.position.z) { position = obj.position }
}
}
} else if (obj.type === 'Group') {
let exist = false
obj.children.forEach((child, i) => {
if (child.nodeId !== undefined) {
if ((!fuzzyQuery && child.nodeId.toString() === text) || (fuzzyQuery && child.nodeId.toString().indexOf(text) > -1)) {
exist = true
}
}
})
if (exist) {
position = obj.position
}
}
})
return position
}
/**
* 管线流动
*/
computePipeLineFlow () {
let self = this
Object.keys(self.property.textures).map(textureID => {
if (self.property.textures[textureID].direction === -1) {
self.property.textures[textureID].texture.offset.x += 0.005
} else {
self.property.textures[textureID].texture.offset.x -= 0.005
}
})
}
/**
* 计算堆垛机当前状态
*/
computePilerState () {
let self = this
Object.keys(this.property.warehouseInfo.piler).map((pilerId, index) => {
let piler = this.property.warehouseInfo.piler[pilerId]
let trajectory = piler.pathModel
if (piler.noAnim) {
let position = trajectory.curve.getPoint(piler.targetRate / 100)
piler.node.position.set(position.x, position.y, position.z)
piler.noAnim = false
} else {
let step = piler.step || 0.1
if (trajectory && piler.targetRate !== null && piler.targetRate !== undefined && piler.rate !== null && piler.rate !== undefined) {
if (Math.abs(piler.rate - piler.targetRate) < 0.001) {
if (!piler.stopFlg) {
piler.stopFlg = true
self.stopPiler(piler.id)
}
} else {
if (piler.rate < piler.targetRate) {
piler.rate += piler.targetRate - piler.rate > step ? step : piler.targetRate - piler.rate
} else if (piler.rate > piler.targetRate) {
piler.rate -= piler.rate - piler.targetRate > step ? step : piler.rate - piler.targetRate
}
let position = trajectory.curve.getPoint(piler.rate / 100)
if (position) {
piler.node.position.set(position.x, position.y, position.z)
position = trajectory.curve.getPoint(piler.rate / 100 + 0.001)
if (position) {
piler.node.up = new THREE.Vector3(0, 1, 0)
piler.node.lookAt(position.x, position.y, position.z)
piler.node.rotation.y = piler.node.rotation.y + Math.PI / 2
}
}
}
}
}
if (piler.state === '3') {
if (!piler.scale || piler.scale > 1.5) {
piler.scale = 1
}
piler.scale = piler.scale + 0.01
piler.node.scale.set(piler.scale, 1, piler.scale)
}
let stateDictionary = self.property.config.pilerStateDictionary[piler.state]
if (stateDictionary) {
piler.node.children[0].material.color.set(self.loadColor(stateDictionary.color))
}
})
}
/**
* 计算小车当前状态
*/
computeCarState () {
let self = this
Object.keys(this.property.warehouseInfo.carModel.cars).map((carId, index) => {
let car = this.property.warehouseInfo.carModel.cars[carId]
let trajectory = car.pathModel
if (car.noAnim) {
let position = trajectory.curve.getPoint(car.targetRate / 100)
car.node.position.set(position.x, position.y, position.z)
car.noAnim = false
} else {
let step = car.step || 0.2
if (trajectory && car.targetRate !== null && car.targetRate !== undefined && car.rate !== null && car.rate !== undefined) {
if (Math.abs(car.rate - car.targetRate) < 0.001) {
if (!car.stopFlg) {
car.stopFlg = true
self.stopCar(car.id)
}
} else {
if (car.rate < car.targetRate) {
car.rate += car.targetRate - car.rate > step ? step : car.targetRate - car.rate
} else if (car.rate > car.targetRate) {
car.rate -= car.rate - car.targetRate > step ? step : car.rate - car.targetRate
}
let position = trajectory.curve.getPoint(car.rate / 100)
if (position) {
car.node.position.set(position.x, position.y, position.z)
position = trajectory.curve.getPoint(car.rate / 100 + 0.001)
if (position) {
car.node.up = new THREE.Vector3(0, 1, 0)
car.node.lookAt(position.x, position.y, position.z)
car.node.rotation.y = car.node.rotation.y - Math.PI / 2
}
}
}
}
}
let stateDictionary = self.property.config.carStateDictionary[car.state]
if (stateDictionary) {
car.node.children[0].material.color.set(self.loadColor(stateDictionary.color))
}
})
}
/**
* 计算托盘当前状态
*/
computeTrayState () {
let self = this
let trajectory = this.property.warehouseInfo.beltModel.pathModel
Object.keys(this.property.warehouseInfo.beltModel.trays).map((trayId, index) => {
let tray = this.property.warehouseInfo.beltModel.trays[trayId]
if (tray.noAnim) {
let position = trajectory.curve.getPoint(tray.targetRate / 100)
tray.node.position.set(position.x, position.y, position.z)
tray.noAnim = false
} else {
let step = tray.step || 0.2
if (trajectory && tray.targetRate !== null && tray.targetRate !== undefined && tray.rate !== null && tray.rate !== undefined) {
if (Math.abs(tray.rate - tray.targetRate) < 0.001) {
if (!tray.stopFlg) {
tray.stopFlg = true
self.stopTray(tray.id)
}
} else {
if (tray.rate < tray.targetRate) {
tray.rate += tray.targetRate - tray.rate > step ? step : tray.targetRate - tray.rate
} else if (tray.rate > tray.targetRate) {
tray.rate -= tray.rate - tray.targetRate > step ? step : tray.rate - tray.targetRate
}
let position = trajectory.curve.getPoint(tray.rate / 100)
if (position) {
tray.node.position.set(position.x, position.y, position.z)
position = trajectory.curve.getPoint(tray.rate / 100 + 0.001)
if (position) {
tray.node.up = new THREE.Vector3(0, 1, 0)
tray.node.lookAt(position.x, position.y, position.z)
tray.node.rotation.y = tray.node.rotation.y + Math.PI / 2
}
}
}
}
}
let stateDictionary = self.property.config.trayStateDictionary[tray.state]
if (stateDictionary) {
tray.node.children[0].material.color.set(self.loadColor(stateDictionary.color))
}
})
}
/**
* 更新堆垛机状态
* @param pilerInfo
*/
updatePiler (pilerInfo) {
let self = this
setTimeout(() => {
// 因为是事件回调中更新,所以需要setTimeout,不然持续更新错误状态
self.doUpdatePiler(pilerInfo)
}, 100)
}
doUpdatePiler (pilerInfo) {
let piler = this.property.warehouseInfo.piler[pilerInfo.pilerId]
if (piler) {
switch (pilerInfo.carryCargo) {
default:
case false:
if (piler.node.children.length > 2) {
piler.node.remove(piler.node.children[2])
}
break
case true:
if (piler.node.children.length <= 2) {
let parentS3 = piler.s3
let reckInfo = {
id: pilerInfo.cargoId,
type: 'cargo',
p3: [0, parentS3[1] / 2 + 1, 0],
s3: [parentS3[0] / 2 - 2, 1, parentS3[2] - 4],
segments: [1, 1, 1],
color: 0x333300
}
let rect = this.createRectangle(reckInfo)
piler.node.add(rect)
}
break
}
if (!piler.rate) {
piler.rate = 0
}
if (pilerInfo.state === '3') {
this.property.errorNodes[pilerInfo.pilerId] = pilerInfo.pilerId
piler.state = '3'
} else {
if (this.property.errorNodes.hasOwnProperty(pilerInfo.pilerId)) {
delete this.property.errorNodes[pilerInfo.pilerId]
}
if (pilerInfo.noAnim) {
piler.noAnim = pilerInfo.noAnim
piler.rate = pilerInfo.rate
} else {
piler.stopFlg = false
}
if (pilerInfo.hasOwnProperty('state')) {
piler.state = pilerInfo.state
} else {
if (piler.rate < pilerInfo.rate) {
piler.state = '1'
} else if (piler.rate > pilerInfo.rate) {
piler.state = '2'
} else if (piler.rate === pilerInfo.rate) {
piler.state = '0'
}
}
}
piler.targetRate = pilerInfo.rate
let textureLoader = new THREE.TextureLoader()
let texture
switch (piler.state) {
default:
case '0':
texture = textureLoader.load(require('../../assets/image/arrow.png'))
this.property.textures[pilerInfo.pilerId].direction = 1
break
case '1':
texture = textureLoader.load(require('../../assets/image/arrow-g.png'))
this.property.textures[pilerInfo.pilerId].direction = 1
break
case '2':
texture = textureLoader.load(require('../../assets/image/arrow-r.png'))
this.property.textures[pilerInfo.pilerId].direction = -1
break
case '3':
texture = textureLoader.load(require('../../assets/image/arrow.png'))
this.property.textures[pilerInfo.pilerId].direction = 1
break
}
texture.wrapS = THREE.RepeatWrapping
texture.wrapT = THREE.RepeatWrapping
texture.repeat.x = 10
texture.repeat.y = 4
texture.offset.y = 0.5
piler.pathModel.tube.material.map = texture
this.property.textures[pilerInfo.pilerId].texture = texture
}
}
/**
* 停止堆垛机动画触发
* @param pilerId
*/
stopPiler (pilerId) {
let piler = this.property.warehouseInfo.piler[pilerId]
if (piler) {
if (piler.state !== '3') {
piler.state = '0'
}
let textureLoader = new THREE.TextureLoader()
let texture = textureLoader.load(require('../../assets/image/arrow.png'))
texture.wrapS = THREE.RepeatWrapping
texture.wrapT = THREE.RepeatWrapping
texture.repeat.x = 10
texture.repeat.y = 4
texture.offset.y = 0.5
piler.pathModel.tube.material.map = texture
this.property.textures[pilerId].texture = texture
try {
this.property.event.onAnimateStop('piler', piler)
} catch (e) {
// console.log(e.toString())
}
}
}
/**
* 更新小车位置
* @param carInfo
*/
updateCar (carInfo) {
let self = this
setTimeout(() => {
// 因为是事件回调中更新,所以需要setTimeout,不然持续更新错误状态
self.doUpdateCar(carInfo)
}, 100)
}
doUpdateCar (carInfo) {
let car = this.property.warehouseInfo.carModel.cars[carInfo.carId]
if (car) {
if (carInfo.pathPoints) {
car.rate = 0
car.pathModel = this.drawPipeline(carInfo.pathPoints, 'arrow-g', car)
}
switch (carInfo.carryCargo) {
default:
case false:
if (car.node.children.length > 2) {
car.node.remove(car.node.children[2])
}
break
case true:
if (car.node.children.length <= 2) {
let parentS3 = car.s3
let reckInfo = {
id: carInfo.cargoId,
type: 'cargo',
p3: [0, 2, 0],
s3: [parentS3[0] - 4, 20, parentS3[2] - 4],
segments: [1, 1, 1],
color: 0x333300
}
let rect = this.createRectangle(reckInfo)
car.node.add(rect)
}
break
}
if (!car.rate) {
car.rate = 0
}
car.targetRate = carInfo.rate
if (carInfo.noAnim) {
car.noAnim = carInfo.noAnim
car.rate = car.targetRate
} else {
car.stopFlg = false
}
if (carInfo.hasOwnProperty('state')) {
car.state = carInfo.state
} else {
car.state = car.rate !== carInfo.rate ? '1' : '0'
}
}
}
/**
* 停止小车动画触发
* @param carId
*/
stopCar (carId) {
let car = this.property.warehouseInfo.carModel.cars[carId]
if (car) {
if (car.pathModel && car.pathModel.tube) {
this.property.scene.remove(car.pathModel.tube)
}
car.state = '0'
try {
this.property.event.onAnimateStop('car', car)
} catch (e) {
// console.log(e.toString())
}
}
}
/**
* 修改托盘位置
* @param trayInfo
*/
updateTray (trayInfo) {
let self = this
setTimeout(() => {
// 因为是事件回调中更新,所以需要setTimeout,不然持续更新错误状态
self.doUpdateTray(trayInfo)
}, 100)
}
doUpdateTray (trayInfo) {
let tray = this.property.warehouseInfo.beltModel.trays[trayInfo.trayId]
if (tray) {
switch (trayInfo.carryCargo) {
default:
case false:
if (tray.node.children.length > 2) {
tray.node.remove(tray.node.children[2])
}
break
case true:
if (tray.node.children.length <= 2) {
let parentS3 = tray.s3
let reckInfo = {
id: trayInfo.cargoId,
type: 'cargo',
p3: [0, 2, 0],
s3: [parentS3[0] - 4, 20, parentS3[2] - 4],
segments: [1, 1, 1],
color: 0x333300
}
let rect = this.createRectangle(reckInfo)
tray.node.add(rect)
}
break
}
if (!tray.rate) {
tray.rate = 0
}
tray.targetRate = trayInfo.rate
if (trayInfo.noAnim) {
tray.noAnim = trayInfo.noAnim
tray.rate = tray.targetRate
} else {
tray.stopFlg = false
}
if (trayInfo.hasOwnProperty('state')) {
tray.state = trayInfo.state
} else {
tray.state = tray.rate !== trayInfo.rate ? '1' : '0'
}
}
}
/**
* 停止托盘动画触发
* @param trayId
*/
stopTray (trayId) {
let tray = this.property.warehouseInfo.beltModel.trays[trayId]
if (tray) {
tray.state = '0'
try {
this.property.event.onAnimateStop('tray', tray)
} catch (e) {
// console.log(e.toString())
}
}
}
/**
* 更新仓库库存状态
*/
updateStorage (warehouseInfo) {
let self = this
let warehouseData = JSON.parse(JSON.stringify(warehouseInfo))
let freightSpaceStateDictionary = JSON.parse(JSON.stringify(this.property.config.freightSpaceStateDictionary))
Object.keys(warehouseData.storageRack).map(storageRackId => {
Object.keys(warehouseData.storageRack[storageRackId].freightSpace).map(freightSpaceId => {
let freightSpace = warehouseData.storageRack[storageRackId].freightSpace[freightSpaceId]
Object.keys(freightSpaceStateDictionary).map(tileStateKey => {
if (freightSpace.state&&freightSpace.state.toString() === tileStateKey) {
if (!freightSpaceStateDictionary[tileStateKey].nodeIds) {
freightSpaceStateDictionary[tileStateKey].nodeIds = []
}
freightSpaceStateDictionary[tileStateKey].nodeIds.push(freightSpace.id)
}
})
})
})
this.property.scene.traverse(obj => {
if (obj.type === 'GridHelper') {
} else if (obj.type === 'Mesh') {
if (obj.customDataType === 'freightSpace') {
Object.keys(freightSpaceStateDictionary).map(tileStateKey => {
if (freightSpaceStateDictionary[tileStateKey].nodeIds && freightSpaceStateDictionary[tileStateKey].nodeIds.indexOf(obj.nodeId) > -1) {
obj.material.color.set(self.loadColor(freightSpaceStateDictionary[tileStateKey].color))
}
})
}
} else if (obj.type === 'Group') {
obj.children.forEach((child, i) => {
Object.keys(freightSpaceStateDictionary).map(tileStateKey => {
if (freightSpaceStateDictionary[tileStateKey].nodeIds && freightSpaceStateDictionary[tileStateKey].nodeIds.indexOf(child.nodeId) > -1) {
// debugger
child.material.color.set(self.loadColor(freightSpaceStateDictionary[tileStateKey].color))
}
})
})
}
})
}
/**
* 更新仓库库存状态
*/
updateStorageByKey (freightSpaceId, state) {
let self = this
let tileState = JSON.parse(JSON.stringify(this.property.config.freightSpaceStateDictionary[state]))
this.property.scene.traverse(obj => {
if (obj.type === 'GridHelper') {
} else if (obj.type === 'Mesh') {
if (obj.nodeId !== undefined && obj.nodeId.toString() === freightSpaceId) {
obj.material.color.set(self.loadColor(tileState.color))
}
} else if (obj.type === 'Group') {
obj.children.forEach((child, i) => {
if (child.nodeId !== undefined && child.nodeId.toString() === freightSpaceId) {
child.material.color.set(self.loadColor(tileState.color))
}
})
}
})
}
loadColor (colorText) {
if (typeof colorText === 'string') {
let color = parseInt(colorText.replace(/#/g, '0x'))
// let color = parseInt(colorText.replace(/#/g, '0x'))
// console.log(colorText);
return color
} else {
return colorText
}
}
loadFbxModel (url) {
let self = this
// 实例化一个FBXLoader对象
const loader = new FBXLoader()
// 加载fbx文件
loader.load(url, (model) => {
model.traverse(childModel => {
self.loadColorForModel(childModel)
})
// 将模型添加到场景中
self.property.scene.add(model)
}, (event) => {
// 控制台打印加载进度
// console.log((event.loaded / event.total * 100) + '% loaded')
}, (error) => {
// 控制台打印加载失败
console.error(error)
})
}
loadColorForModel (model) {
let self = this
if (model.material) {
model.castShadow = true
model.material.emissive = model.material.color
model.material.emissiveMap = model.material.map
} else if (model.children.length > 0) {
model.children.map(childModel => {
self.loadColorForModel(childModel)
})
}
}
/**
* 初始化地图
*/
initMap () {
if (WEBGL.isWebGLAvailable() === false) {
document.body.appendChild(WEBGL.getWebGLErrorMessage())
} else {
this.initScene()
this.initCamera()
this.initRender()
this.initMaterials()
this.initControls()
// this.initVideoGround()
}
}
initWarehouse () {
if (this.property.warehouseInfo) {
this.drawWarehouses()
if (this.property.config.vehicleType === 1) {
// this.drawPilers()
// this.drawBelt()
} else {
this.drawRoad()
}
// this.drawCars()
} else {
this.initLight()
}
this.animate()
this.initEvent()
// if (this.property.grid) {
// this.initGrid(this.property.grid.width, this.property.grid.height, this.property.grid.singleWidth, this.property.grid.singleHeight)
// }
}
}
export default MapDrawing