init: 广西机电数字孪生看板项目首次入库
23
src/App.vue
Normal file
@@ -0,0 +1,23 @@
|
||||
<template>
|
||||
<div id="app">
|
||||
<keep-alive>
|
||||
<router-view v-if="this.$route.meta.keepAlive"/>
|
||||
</keep-alive>
|
||||
<router-view v-if="!this.$route.meta.keepAlive"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
#app {
|
||||
font-family: MiSans Bold, serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
color: #2c3e50;
|
||||
}
|
||||
.el-dialog__wrapper {
|
||||
pointer-events: none;
|
||||
}
|
||||
.el-dialog {
|
||||
pointer-events: auto;
|
||||
}
|
||||
</style>
|
||||
31
src/api/FactoryCalendar.js
Normal file
@@ -0,0 +1,31 @@
|
||||
import request from '@/utils/request'
|
||||
import state from '@/store'
|
||||
import router from '@/router'
|
||||
// 初始化日历
|
||||
export function initClendar(year, month) {
|
||||
return request({
|
||||
url: '',
|
||||
method: 'post',
|
||||
data: {
|
||||
UserID: state.state.user.id,
|
||||
ModularID: router.currentRoute.path,
|
||||
type: '1',
|
||||
name: '车间生产管理工艺_基础表_工作日历_获得状态',
|
||||
param: '工作年=' + year + '&工作月=' + month
|
||||
}
|
||||
})
|
||||
}
|
||||
// 修改工作状态
|
||||
export function changeState(time, code) {
|
||||
return request({
|
||||
url: '',
|
||||
method: 'post',
|
||||
data: {
|
||||
UserID: state.state.user.id,
|
||||
ModularID: router.currentRoute.path,
|
||||
type: '2',
|
||||
name: '车间生产管理工艺_基础表_工作日历_设置状态',
|
||||
param: '工作日期=' + time + '&工作日状态=' + code
|
||||
}
|
||||
})
|
||||
}
|
||||
70
src/assets/font/Misans.css
Normal file
@@ -0,0 +1,70 @@
|
||||
@font-face {
|
||||
font-family: MiSans Demibold;
|
||||
src: url("MiSans-Demibold.ttf");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-display: block;
|
||||
}
|
||||
@font-face {
|
||||
font-family: MiSans Bold;
|
||||
src: url("MiSans-Bold.ttf");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-display: block;
|
||||
}
|
||||
@font-face {
|
||||
font-family: MiSans ExtraLight;
|
||||
src: url("MiSans-ExtraLight.ttf");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-display: block;
|
||||
}
|
||||
@font-face {
|
||||
font-family: MiSans Heavy;
|
||||
src: url("MiSans-Heavy.ttf");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-display: block;
|
||||
}
|
||||
@font-face {
|
||||
font-family: MiSans Light;
|
||||
src: url("MiSans-Light.ttf");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-display: block;
|
||||
}
|
||||
@font-face {
|
||||
font-family: MiSans Medium;
|
||||
src: url("MiSans-Medium.ttf");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-display: block;
|
||||
}
|
||||
@font-face {
|
||||
font-family: MiSans Normal;
|
||||
src: url("MiSans-Normal.ttf");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-display: block;
|
||||
}
|
||||
@font-face {
|
||||
font-family: MiSans Regular;
|
||||
src: url("MiSans-Regular.ttf");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-display: block;
|
||||
}
|
||||
@font-face {
|
||||
font-family: MiSans Semibold;
|
||||
src: url("MiSans-Semibold.ttf");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-display: block;
|
||||
}
|
||||
@font-face {
|
||||
font-family: MiSans Thin;
|
||||
src: url("MiSans-Thin.ttf");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-display: block;
|
||||
}
|
||||
BIN
src/assets/gray.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
src/assets/green.gif
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
src/assets/green.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
src/assets/image/1.png
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
src/assets/image/2.png
Normal file
|
After Width: | Height: | Size: 481 KiB |
BIN
src/assets/image/3.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
src/assets/image/GQlogo.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
src/assets/image/MESlogo.png
Normal file
|
After Width: | Height: | Size: 7.6 KiB |
BIN
src/assets/image/MSlogo.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
src/assets/image/MT.png
Normal file
|
After Width: | Height: | Size: 66 KiB |
BIN
src/assets/image/OP1010.jpg
Normal file
|
After Width: | Height: | Size: 5.9 MiB |
BIN
src/assets/image/OP1010.png
Normal file
|
After Width: | Height: | Size: 2.2 MiB |
BIN
src/assets/image/OP1020.jpg
Normal file
|
After Width: | Height: | Size: 2.7 MiB |
BIN
src/assets/image/OP1030.jpg
Normal file
|
After Width: | Height: | Size: 4.2 MiB |
BIN
src/assets/image/OP6010.jpg
Normal file
|
After Width: | Height: | Size: 104 KiB |
BIN
src/assets/image/OP6010.png
Normal file
|
After Width: | Height: | Size: 104 KiB |
BIN
src/assets/image/OP6020.jpg
Normal file
|
After Width: | Height: | Size: 566 KiB |
BIN
src/assets/image/OP60202.png
Normal file
|
After Width: | Height: | Size: 765 KiB |
BIN
src/assets/image/OP6030.jpg
Normal file
|
After Width: | Height: | Size: 313 KiB |
BIN
src/assets/image/OP6040.jpg
Normal file
|
After Width: | Height: | Size: 413 KiB |
BIN
src/assets/image/OP6050.jpg
Normal file
|
After Width: | Height: | Size: 422 KiB |
BIN
src/assets/image/OP6060.jpg
Normal file
|
After Width: | Height: | Size: 427 KiB |
BIN
src/assets/image/OP6070.jpg
Normal file
|
After Width: | Height: | Size: 524 KiB |
BIN
src/assets/image/OP6080.jpg
Normal file
|
After Width: | Height: | Size: 483 KiB |
BIN
src/assets/image/OP6090.jpg
Normal file
|
After Width: | Height: | Size: 360 KiB |
BIN
src/assets/image/OP6100.jpg
Normal file
|
After Width: | Height: | Size: 490 KiB |
BIN
src/assets/image/OP6110.jpg
Normal file
|
After Width: | Height: | Size: 439 KiB |
BIN
src/assets/image/OP6120.jpg
Normal file
|
After Width: | Height: | Size: 383 KiB |
BIN
src/assets/image/OP6130.jpg
Normal file
|
After Width: | Height: | Size: 400 KiB |
BIN
src/assets/image/OP6140.jpg
Normal file
|
After Width: | Height: | Size: 511 KiB |
BIN
src/assets/image/OP6150.jpg
Normal file
|
After Width: | Height: | Size: 352 KiB |
BIN
src/assets/image/OP6160.jpg
Normal file
|
After Width: | Height: | Size: 460 KiB |
BIN
src/assets/image/OP6170.jpg
Normal file
|
After Width: | Height: | Size: 388 KiB |
BIN
src/assets/image/OP6180.jpg
Normal file
|
After Width: | Height: | Size: 651 KiB |
BIN
src/assets/image/OP6190.jpg
Normal file
|
After Width: | Height: | Size: 769 KiB |
BIN
src/assets/image/OP6200.jpg
Normal file
|
After Width: | Height: | Size: 431 KiB |
BIN
src/assets/image/OP6210.jpg
Normal file
|
After Width: | Height: | Size: 431 KiB |
BIN
src/assets/image/TZ.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
src/assets/image/TZlogo.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
src/assets/image/WCLOGO.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
src/assets/image/arrow_down.png
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
src/assets/image/arrow_right.png
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
src/assets/image/arrow_up.png
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
src/assets/image/bg.jpg
Normal file
|
After Width: | Height: | Size: 704 KiB |
BIN
src/assets/image/call.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
src/assets/image/fangxiang.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
src/assets/image/gaojingLogo2.png
Normal file
|
After Width: | Height: | Size: 6.7 KiB |
BIN
src/assets/image/index_modile_logo.png
Normal file
|
After Width: | Height: | Size: 55 KiB |
BIN
src/assets/image/left1.png
Normal file
|
After Width: | Height: | Size: 7.4 KiB |
BIN
src/assets/image/left2.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
src/assets/image/left3.png
Normal file
|
After Width: | Height: | Size: 8.7 KiB |
BIN
src/assets/image/left4.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
src/assets/image/left5.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
src/assets/image/logo.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
src/assets/image/logo1.png
Normal file
|
After Width: | Height: | Size: 39 KiB |
BIN
src/assets/image/logo2.png
Normal file
|
After Width: | Height: | Size: 44 KiB |
BIN
src/assets/image/reset.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
src/assets/image/response.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
src/assets/image/s1.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
src/assets/image/s2.png
Normal file
|
After Width: | Height: | Size: 5.1 KiB |
BIN
src/assets/jy.png
Normal file
|
After Width: | Height: | Size: 307 KiB |
BIN
src/assets/logo.png
Normal file
|
After Width: | Height: | Size: 6.7 KiB |
BIN
src/assets/purple.png
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
BIN
src/assets/red.gif
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
src/assets/red.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
src/assets/sad.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
src/assets/smile.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
BIN
src/assets/usual.png
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
BIN
src/assets/yellow.gif
Normal file
|
After Width: | Height: | Size: 4.0 KiB |
BIN
src/assets/yellow.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
src/assets/哭脸.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
155
src/components/DMT/VR/VRButton.js
Normal file
@@ -0,0 +1,155 @@
|
||||
class VRButton {
|
||||
static createButton(renderer, options) {
|
||||
if (options) {
|
||||
console.error('THREE.VRButton: The "options" parameter has been removed. Please set the reference space type via renderer.xr.setReferenceSpaceType() instead.')
|
||||
}
|
||||
|
||||
const button = document.createElement('button')
|
||||
|
||||
function showEnterVR(/* device*/) {
|
||||
let currentSession = null
|
||||
|
||||
async function onSessionStarted(session) {
|
||||
session.addEventListener('end', onSessionEnded)
|
||||
|
||||
await renderer.xr.setSession(session)
|
||||
button.textContent = 'EXIT VR'
|
||||
|
||||
currentSession = session
|
||||
}
|
||||
|
||||
function onSessionEnded(/* event*/) {
|
||||
currentSession.removeEventListener('end', onSessionEnded)
|
||||
|
||||
button.textContent = 'ENTER VR'
|
||||
|
||||
currentSession = null
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
button.style.display = ''
|
||||
|
||||
button.style.cursor = 'pointer'
|
||||
button.style.left = 'calc(50% - 50px)'
|
||||
button.style.width = '100px'
|
||||
|
||||
button.textContent = 'ENTER VR'
|
||||
|
||||
button.onmouseenter = function() {
|
||||
button.style.opacity = '1.0'
|
||||
}
|
||||
|
||||
button.onmouseleave = function() {
|
||||
button.style.opacity = '0.5'
|
||||
}
|
||||
|
||||
button.onclick = function() {
|
||||
if (currentSession === null) {
|
||||
// WebXR's requestReferenceSpace only works if the corresponding feature
|
||||
// was requested at session creation time. For simplicity, just ask for
|
||||
// the interesting ones as optional features, but be aware that the
|
||||
// requestReferenceSpace call will fail if it turns out to be unavailable.
|
||||
// ('local' is always available for immersive sessions and doesn't need to
|
||||
// be requested separately.)
|
||||
|
||||
const sessionInit = { optionalFeatures: ['local-floor', 'bounded-floor', 'hand-tracking', 'layers'] }
|
||||
navigator.xr.requestSession('immersive-vr', sessionInit).then(onSessionStarted)
|
||||
} else {
|
||||
currentSession.end()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function disableButton() {
|
||||
button.style.display = ''
|
||||
|
||||
button.style.cursor = 'auto'
|
||||
button.style.left = 'calc(50% - 75px)'
|
||||
button.style.width = '150px'
|
||||
|
||||
button.onmouseenter = null
|
||||
button.onmouseleave = null
|
||||
|
||||
button.onclick = null
|
||||
}
|
||||
|
||||
function showWebXRNotFound() {
|
||||
disableButton()
|
||||
|
||||
button.textContent = 'VR NOT SUPPORTED'
|
||||
}
|
||||
|
||||
function showVRNotAllowed(exception) {
|
||||
disableButton()
|
||||
|
||||
console.warn('Exception when trying to call xr.isSessionSupported', exception)
|
||||
|
||||
button.textContent = 'VR NOT ALLOWED'
|
||||
}
|
||||
|
||||
function stylizeElement(element) {
|
||||
element.style.position = 'absolute'
|
||||
element.style.bottom = '20px'
|
||||
element.style.padding = '12px 6px'
|
||||
element.style.border = '1px solid #fff'
|
||||
element.style.borderRadius = '4px'
|
||||
element.style.background = 'rgba(0,0,0,0.1)'
|
||||
element.style.color = '#fff'
|
||||
element.style.font = 'normal 13px sans-serif'
|
||||
element.style.textAlign = 'center'
|
||||
element.style.opacity = '0.5'
|
||||
element.style.outline = 'none'
|
||||
element.style.zIndex = '999'
|
||||
}
|
||||
|
||||
if ('xr' in navigator) {
|
||||
button.id = 'VRButton'
|
||||
button.style.display = 'none'
|
||||
|
||||
stylizeElement(button)
|
||||
|
||||
navigator.xr.isSessionSupported('immersive-vr').then(function(supported) {
|
||||
supported ? showEnterVR() : showWebXRNotFound()
|
||||
|
||||
if (supported && VRButton.xrSessionIsGranted) {
|
||||
button.click()
|
||||
}
|
||||
}).catch(showVRNotAllowed)
|
||||
|
||||
return button
|
||||
} else {
|
||||
const message = document.createElement('a')
|
||||
|
||||
if (window.isSecureContext === false) {
|
||||
message.href = document.location.href.replace(/^http:/, 'https:')
|
||||
message.innerHTML = 'WEBXR NEEDS HTTPS' // TODO Improve message
|
||||
} else {
|
||||
message.href = 'https://immersiveweb.dev/'
|
||||
message.innerHTML = 'WEBXR NOT AVAILABLE'
|
||||
}
|
||||
|
||||
message.style.left = 'calc(50% - 90px)'
|
||||
message.style.width = '180px'
|
||||
message.style.textDecoration = 'none'
|
||||
|
||||
stylizeElement(message)
|
||||
|
||||
return message
|
||||
}
|
||||
}
|
||||
|
||||
static xrSessionIsGranted = false;
|
||||
|
||||
static registerSessionGrantedListener() {
|
||||
if ('xr' in navigator) {
|
||||
navigator.xr.addEventListener('sessiongranted', () => {
|
||||
VRButton.xrSessionIsGranted = true
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VRButton.registerSessionGrantedListener()
|
||||
|
||||
export { VRButton }
|
||||
327
src/components/DMT/config.vue
Normal file
@@ -0,0 +1,327 @@
|
||||
<template>
|
||||
<div style="pointer-events: none">
|
||||
<el-dialog title="修改配置文件" :visible.sync="dialogFormVisible" width="1000px" class="myDia" :modal="false" :close-on-press-escape="false" v-el-drag-dialog>
|
||||
<el-collapse v-model="activeNames">
|
||||
<el-collapse-item title="通讯配置" name="1">
|
||||
<el-row class="row-Show">
|
||||
<span class="title-show">标题</span>
|
||||
<el-input size="mini" style="width: 300px" v-model="configInfo['title']"></el-input>
|
||||
<span class="title-show">工位和协议</span>
|
||||
<el-input size="mini" style="width: 120px" v-model="configInfo['webSocketOpName']"></el-input>
|
||||
<el-input size="mini" style="width: 180px" v-model="configInfo['webSocketBSport']"></el-input>
|
||||
</el-row>
|
||||
<el-row class="row-Show">
|
||||
<span class="title-show">通讯类型</span>
|
||||
<el-radio-group size="mini" v-model="configInfo['connectType']">
|
||||
<el-radio :label="1">WebSocket</el-radio>
|
||||
<el-radio :label="2">MQTT</el-radio>
|
||||
<el-radio :label="3">其他</el-radio>
|
||||
</el-radio-group>
|
||||
</el-row>
|
||||
<el-row class="row-Show">
|
||||
<span class="title-show">Socket_IP&Port</span>
|
||||
<el-input size="mini" style="width: 300px" v-model="configInfo['webSocketIp']"></el-input>
|
||||
<span class="title-show">MQTT_IP&Port</span>
|
||||
<el-input size="mini" style="width: 200px" v-model="configInfo['MQTTHost']"></el-input>
|
||||
<el-input size="mini" style="width: 100px" v-model="configInfo['MQTTPort']"></el-input>
|
||||
</el-row>
|
||||
<el-row class="row-Show">
|
||||
<span class="title-show">数据服务器</span>
|
||||
<el-input size="mini" style="width: 300px" v-model="configInfo['dataBaseURL']"></el-input>
|
||||
<span class="title-show">node服务</span>
|
||||
<el-input size="mini" style="width: 300px" v-model="configInfo['NodeRootIp']"></el-input>
|
||||
</el-row>
|
||||
</el-collapse-item>
|
||||
<el-collapse-item name="2">
|
||||
<template slot="title">
|
||||
机器人/设备配置
|
||||
<el-button size="mini" type="warning" style="margin-left: 10px" @click.stop.prevent="dialogFormVisible = false">重置配置文件</el-button>
|
||||
<el-button size="mini" type="primary" style="margin-left: 10px" @click.stop.prevent="exportConfig">导出配置文件</el-button>
|
||||
{{ currentUUid }}
|
||||
</template>
|
||||
<el-col :span="6">
|
||||
<el-table
|
||||
:data="tableDataRobot"
|
||||
:highlight-current-row="false"
|
||||
element-loading-text="数据加载中"
|
||||
element-loading-spinner="el-icon-loading"
|
||||
element-loading-background="rgba(0, 0, 0, 0.2)"
|
||||
style="width: 100%"
|
||||
max-height="300"
|
||||
border
|
||||
size="mini"
|
||||
class="my-table-show"
|
||||
@cell-dblclick="showEdit"
|
||||
@row-click="rowClick">
|
||||
<el-table-column type="index" label=" " align="center" width="40"/>
|
||||
<!-- <el-table-column align="center" label="name">-->
|
||||
<!-- <template slot-scope="scope">-->
|
||||
<!-- {{ scope.row.name }}-->
|
||||
<!-- </template>-->
|
||||
<!-- </el-table-column>-->
|
||||
<el-table-column align="center" label="机器人模型id">
|
||||
<template slot-scope="scope">
|
||||
<el-input v-if="scope.row.edit" size="mini" v-model="scope.row.uuid"></el-input>
|
||||
<span v-else>{{ scope.row.uuid }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" width="50px" label="操作">
|
||||
<template slot-scope="scope">
|
||||
<el-button size="mini" type="text" style="color: #00893d" @click="applyRobotConfig(scope.row)">应用</el-button>
|
||||
<br>
|
||||
<el-button size="mini" type="text" style="color: red">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-col>
|
||||
<el-col :span="18">
|
||||
<el-table
|
||||
:data="RobotChildrenData"
|
||||
:highlight-current-row="false"
|
||||
element-loading-text="数据加载中"
|
||||
element-loading-spinner="el-icon-loading"
|
||||
element-loading-background="rgba(0, 0, 0, 0.2)"
|
||||
style="width: 100%"
|
||||
max-height="300"
|
||||
border
|
||||
size="mini">
|
||||
<el-table-column type="index" label=" " align="center" width="50"/>
|
||||
<!-- <el-table-column align="center" label="关节名字">-->
|
||||
<!-- <template slot-scope="scope">-->
|
||||
<!-- {{ scope.row.name }}-->
|
||||
<!-- </template>-->
|
||||
<!-- </el-table-column>-->
|
||||
<el-table-column align="center" label="关节ID" width="150">
|
||||
<template slot-scope="scope">
|
||||
<el-input size="mini" v-model="scope.row.ModelId "></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="type" width="110">
|
||||
<template slot-scope="scope">
|
||||
<el-select v-model="scope.row.type" size="mini">
|
||||
<el-option
|
||||
v-for="item in robotJointType"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"/>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="axis" width="80">
|
||||
<template slot-scope="scope">
|
||||
<el-select v-model="scope.row.axis" size="mini">
|
||||
<el-option
|
||||
v-for="item in robotJointAxis"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"/>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="flip" width="80">
|
||||
<template slot-scope="scope">
|
||||
<el-select v-model="scope.row.flip" size="mini">
|
||||
<el-option
|
||||
v-for="item in robotJointFlip"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:value="item.value"/>
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="delta" width="80">
|
||||
<template slot-scope="scope">
|
||||
<el-input size="mini" v-model="scope.row.delta "></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="multiple" width="120">
|
||||
<template slot-scope="scope">
|
||||
<el-input size="mini" v-model="scope.row.multiple "></el-input>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" width="50px" label="操作">
|
||||
<template slot-scope="scope">
|
||||
<el-button size="mini" type="text" style="color: #00893d" @click="applyRobotConfig(scope.row, scope.$index)">应用</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-col>
|
||||
</el-collapse-item>
|
||||
</el-collapse>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Mousetrap from './js/mousetrap.js'
|
||||
import axios from 'axios'
|
||||
export default {
|
||||
name: 'ConfigVue',
|
||||
data() {
|
||||
return {
|
||||
currentUUid: '',
|
||||
activeNames: '2',
|
||||
configInfo: {},
|
||||
tableDataRobot: [],
|
||||
tableDataRobotChildren: {},
|
||||
RobotChildrenData: [],
|
||||
dialogFormVisible: false,
|
||||
robotJointType: [
|
||||
{
|
||||
label: 'position',
|
||||
value: 'position'
|
||||
},
|
||||
{
|
||||
label: 'rotation',
|
||||
value: 'rotation'
|
||||
}
|
||||
],
|
||||
robotJointFlip: [
|
||||
{
|
||||
label: 1,
|
||||
value: 1
|
||||
},
|
||||
{
|
||||
label: -1,
|
||||
value: -1
|
||||
}
|
||||
],
|
||||
robotJointAxis: [
|
||||
{
|
||||
label: 'x',
|
||||
value: 'x'
|
||||
},
|
||||
{
|
||||
label: 'y',
|
||||
value: 'y'
|
||||
},
|
||||
{
|
||||
label: 'z',
|
||||
value: 'z'
|
||||
}
|
||||
],
|
||||
form: {
|
||||
name: '',
|
||||
region: '',
|
||||
date1: '',
|
||||
date2: '',
|
||||
delivery: false,
|
||||
type: [],
|
||||
resource: '',
|
||||
desc: ''
|
||||
},
|
||||
formLabelWidth: '120px'
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getConfig().then(res => {
|
||||
this.configInfo = res
|
||||
console.log(res)
|
||||
this.solveRobotInfoFirst()
|
||||
})
|
||||
const scope = this
|
||||
Mousetrap.bind('ctrl+c', function() {
|
||||
scope.solveConfig()
|
||||
return false
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
solveConfig() {
|
||||
console.log('ctrl + c')
|
||||
this.dialogFormVisible = !this.dialogFormVisible
|
||||
},
|
||||
getConfig() {
|
||||
return new Promise((resolve, reject) => {
|
||||
axios.get('./DMT_WEB/config/config.json').then(res => {
|
||||
const configData = res.data
|
||||
resolve(configData)
|
||||
}).catch(err => {
|
||||
reject(err)
|
||||
})
|
||||
})
|
||||
},
|
||||
solveRobotInfoFirst() {
|
||||
this.tableDataRobot = []
|
||||
this.tableDataRobotChildren = {}
|
||||
for (const argumentsKey in this.configInfo.robotList) {
|
||||
this.tableDataRobot.push({
|
||||
name: '',
|
||||
uuid: argumentsKey,
|
||||
edit: false
|
||||
})
|
||||
this.tableDataRobotChildren[argumentsKey] = []
|
||||
for (let i = 0; i < this.configInfo.robotList[argumentsKey].length; i++) {
|
||||
this.tableDataRobotChildren[argumentsKey].push(this.configInfo.robotList[argumentsKey][i])
|
||||
}
|
||||
}
|
||||
},
|
||||
showEdit(row) {
|
||||
row.edit = !row.edit
|
||||
},
|
||||
rowClick(row) {
|
||||
this.currentUUid = row.uuid
|
||||
this.RobotChildrenData = this.tableDataRobotChildren[row.uuid]
|
||||
},
|
||||
exportConfig() {
|
||||
this.configInfo['robotList'] = this.tableDataRobotChildren
|
||||
const saveJsonStr = JSON.stringify(this.configInfo)
|
||||
const blob = new Blob([saveJsonStr], {
|
||||
type: 'application/json'
|
||||
})
|
||||
const objectUrl = URL.createObjectURL(blob)
|
||||
const aa = document.createElement('a')
|
||||
aa.href = objectUrl
|
||||
aa.download = 'config.json'
|
||||
aa.click()
|
||||
URL.revokeObjectURL(objectUrl)
|
||||
},
|
||||
applyRobotConfig(row, index) {
|
||||
const rootRobotJoint = window.editor.robotList[this.currentUUid][index]
|
||||
if (row.ModelId === rootRobotJoint.ModelId) {
|
||||
window.editor.robotList[this.currentUUid][index].axis = row.axis
|
||||
window.editor.robotList[this.currentUUid][index].delta = row.delta
|
||||
window.editor.robotList[this.currentUUid][index].flip = row.flip
|
||||
window.editor.robotList[this.currentUUid][index].type = row.type
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.row-Show {
|
||||
margin: 10px 0
|
||||
}
|
||||
.title-show {
|
||||
font-weight: bolder;
|
||||
font-size: 16px;
|
||||
margin: 0 10px;
|
||||
width: 130px;
|
||||
display: inline-block;
|
||||
text-align: right;
|
||||
}
|
||||
</style>
|
||||
<style>
|
||||
.myDia .el-dialog {
|
||||
pointer-events: auto;
|
||||
}
|
||||
.myDia .el-dialog__body {
|
||||
padding: 5px 15px;
|
||||
}
|
||||
.myDia .el-dialog--center .el-dialog__body {
|
||||
padding: 15px;
|
||||
}
|
||||
.myDia .el-dialog__title {
|
||||
font-size: 22px;
|
||||
color: #000000;
|
||||
}
|
||||
.myDia .el-dialog__header {
|
||||
padding: 15px;
|
||||
}
|
||||
.myDia .el-dialog__wrapper{
|
||||
pointer-events:none;
|
||||
}
|
||||
.myDia .el-dialog{
|
||||
pointer-events:auto;
|
||||
}
|
||||
</style>
|
||||
46
src/components/DMT/el-dragDialog/drag.js
Normal file
@@ -0,0 +1,46 @@
|
||||
export default{
|
||||
bind(el, binding) {
|
||||
const dialogHeaderEl = el.querySelector('.el-dialog__header')
|
||||
const dragDom = el.querySelector('.el-dialog')
|
||||
dialogHeaderEl.style = 'cursor:move;'
|
||||
|
||||
// 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
|
||||
const sty = dragDom.currentStyle || window.getComputedStyle(dragDom, null)
|
||||
|
||||
dialogHeaderEl.onmousedown = (e) => {
|
||||
// 鼠标按下,计算当前元素距离可视区的距离
|
||||
const disX = e.clientX - dialogHeaderEl.offsetLeft
|
||||
const disY = e.clientY - dialogHeaderEl.offsetTop
|
||||
|
||||
// 获取到的值带px 正则匹配替换
|
||||
let styL, styT
|
||||
|
||||
// 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px
|
||||
if (sty.left.includes('%')) {
|
||||
styL = +document.body.clientWidth * (+sty.left.replace(/\%/g, '') / 100)
|
||||
styT = +document.body.clientHeight * (+sty.top.replace(/\%/g, '') / 100)
|
||||
} else {
|
||||
styL = +sty.left.replace(/\px/g, '')
|
||||
styT = +sty.top.replace(/\px/g, '')
|
||||
}
|
||||
|
||||
document.onmousemove = function(e) {
|
||||
// 通过事件委托,计算移动的距离
|
||||
const l = e.clientX - disX
|
||||
const t = e.clientY - disY
|
||||
|
||||
// 移动当前元素
|
||||
dragDom.style.left = `${l + styL}px`
|
||||
dragDom.style.top = `${t + styT}px`
|
||||
|
||||
// 将此时的位置传出去
|
||||
// binding.value({x:e.pageX,y:e.pageY})
|
||||
}
|
||||
|
||||
document.onmouseup = function(e) {
|
||||
document.onmousemove = null
|
||||
document.onmouseup = null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
13
src/components/DMT/el-dragDialog/index.js
Normal file
@@ -0,0 +1,13 @@
|
||||
import drag from './drag'
|
||||
|
||||
const install = function(Vue) {
|
||||
Vue.directive('el-drag-dialog', drag)
|
||||
}
|
||||
|
||||
if (window.Vue) {
|
||||
window['el-drag-dialog'] = drag
|
||||
Vue.use(install); // eslint-disable-line
|
||||
}
|
||||
|
||||
drag.install = install
|
||||
export default drag
|
||||
1437
src/components/DMT/index.vue
Normal file
1437
src/components/DMT/index2.vue
Normal file
1508
src/components/DMT/indexLG.vue
Normal file
1250
src/components/DMT/indexVR.vue
Normal file
78
src/components/DMT/js/MqttConnect.js
Normal file
@@ -0,0 +1,78 @@
|
||||
import { WebsocketMessageReceive } from './WebSocketMessage.js'
|
||||
import mqtt from 'mqtt'
|
||||
|
||||
function connectMqtt(editor) {
|
||||
const connection = {
|
||||
host: editor.mqttHost,
|
||||
port: editor.mqttPort,
|
||||
endpoint: '/mqtt',
|
||||
clean: true, // 保留会话
|
||||
connectTimeout: 4000, // 超时时间
|
||||
reconnectPeriod: 4000, // 重连时间间隔
|
||||
// 认证信息
|
||||
clientId: 'mqttjs_3be2c321' + new Date().getTime(), // 同一个ID 无法二次连接
|
||||
username: 'DT',
|
||||
password: ''
|
||||
}
|
||||
const subscription = {
|
||||
topic: editor.opname,
|
||||
qos: 0
|
||||
}
|
||||
const websocketMessageReceive = new WebsocketMessageReceive(editor)
|
||||
|
||||
const { host, port, endpoint, ...options } = connection
|
||||
const wsHeaderString = location.protocol === 'https:' ? 'wss' : 'ws'
|
||||
// const connectUrl = `${wsHeaderString}://${location.host}${endpoint}`
|
||||
const connectUrl = `${wsHeaderString}://${host}:${port}${endpoint}`
|
||||
console.log(connectUrl)
|
||||
try {
|
||||
editor.mqttClient = mqtt.connect(connectUrl, options)
|
||||
} catch (error) {
|
||||
console.log('MQTT connect error', error)
|
||||
}
|
||||
editor.mqttClient.on('connect', () => {
|
||||
editor.showMessage('加载完成,连接MQTT服务器成功!', 'success', 2000)
|
||||
console.log('MQTT Connection succeeded!')
|
||||
editor.isOk = true
|
||||
const { topic, qos } = subscription
|
||||
editor.mqttClient.subscribe(topic, { qos }, (error, res) => {
|
||||
if (error) {
|
||||
console.log('Subscribe to topics error', error)
|
||||
return
|
||||
}
|
||||
websocketMessageReceive.getOriginTagValue()
|
||||
})
|
||||
})
|
||||
editor.mqttClient.on('error', error => {
|
||||
console.log('MQTT Connection failed', error)
|
||||
try {
|
||||
editor.showMessage('MQTT服务器连接失败', 'error', 2000)
|
||||
editor.socket.close()
|
||||
if (editor.IsAllowConnect) {
|
||||
// 显示一下
|
||||
editor.showMessage('重新连接MQTT服务器', 'warning', 2000)
|
||||
console.log('重新连接MQTT服务器')
|
||||
// 重新连接,打开计时器
|
||||
setTimeout(function() {
|
||||
connectMqtt(editor)
|
||||
}, 5000)
|
||||
}
|
||||
} catch (exception) {
|
||||
const error = exception.toString()
|
||||
editor.showMessage.error('MQTT服务器出现错误,关闭连接' + error, 'error', 2000)
|
||||
}
|
||||
})
|
||||
// 接收消息
|
||||
editor.mqttClient.on('message', (topic, message) => {
|
||||
try {
|
||||
websocketMessageReceive.websocketMessage({ data: message.toString() })
|
||||
} catch (exception) {
|
||||
console.log(exception.toString())
|
||||
}
|
||||
})
|
||||
editor.mqttClient.on('close', () => {
|
||||
editor.mqttClient.end()
|
||||
})
|
||||
}
|
||||
export { connectMqtt }
|
||||
|
||||
40
src/components/DMT/js/ObjectAlarmCommand.js
Normal file
@@ -0,0 +1,40 @@
|
||||
import * as THREE from 'three'
|
||||
|
||||
/**
|
||||
* @param editor Editor
|
||||
* @param object THREE.Object3D
|
||||
* @constructor
|
||||
*/
|
||||
class ObjectAlarmCommand {
|
||||
constructor(editor, ModelId) {
|
||||
this.type = 'ObjectAlarmCommand'
|
||||
this.ModelId = ModelId
|
||||
this.editor = editor
|
||||
this.object = editor.getObjectById(ModelId)
|
||||
}
|
||||
|
||||
exec(isAlarm = true) {
|
||||
if (!this.object) return
|
||||
if (isAlarm) {
|
||||
this.object.traverse(object => {
|
||||
if (object instanceof THREE.Mesh && !Object.hasOwnProperty.call(object.userData, 'isAxis')) {
|
||||
object.material.color = new THREE.Color('#ff0000')
|
||||
object.material.side = 2
|
||||
object.material.transparent = true
|
||||
object.material.opacity = 0.8
|
||||
}
|
||||
})
|
||||
// this.editor.playSoundCommand.exec('Alarm', true, this.ModelId)
|
||||
} else {
|
||||
this.object.traverse(object => {
|
||||
if (object instanceof THREE.Mesh) {
|
||||
const m = this.editor.objMaterial.get(object.id)
|
||||
if (m)object.material = m.clone()
|
||||
}
|
||||
})
|
||||
// this.editor.playSoundCommand.exec('Alarm', false, this.ModelId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export { ObjectAlarmCommand }
|
||||
58
src/components/DMT/js/PlaySoundCommand.js
Normal file
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* @param editor Editor
|
||||
* @param object THREE.Object3D
|
||||
* @constructor
|
||||
*/
|
||||
class PlaySoundCommand {
|
||||
constructor() {
|
||||
this.type = 'PlaySoundCommand'
|
||||
this.PlayType = {
|
||||
Alarm: 'Alarm',
|
||||
Clash: 'Clash'
|
||||
}
|
||||
this.AlarmList = []
|
||||
this.isAlarm = false
|
||||
}
|
||||
|
||||
/**
|
||||
* 系统声音
|
||||
* @param type 报警Alarm, 碰撞Clash 。。。。。。。
|
||||
* @param state 报警/解除报警
|
||||
* @param ModelId 模型ID
|
||||
*/
|
||||
exec(type, state = true, ModelId) {
|
||||
switch (type) {
|
||||
case this.PlayType.Alarm:
|
||||
if (state) {
|
||||
if (!this.isAlarm) this.playAlarmSound(true)
|
||||
if (this.AlarmList.indexOf(ModelId) === -1) this.AlarmList.push(ModelId)
|
||||
this.isAlarm = true
|
||||
} else {
|
||||
this.AlarmList = this.AlarmList.filter(res => { return res !== ModelId })
|
||||
if (this.AlarmList.length === 0) {
|
||||
this.playAlarmSound(false)
|
||||
this.isAlarm = false
|
||||
}
|
||||
}
|
||||
break
|
||||
case this.PlayType.Clash:
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
playAlarmSound(play = true) {
|
||||
// const audio = document.getElementById('alarm')
|
||||
// play ? audio.play() : audio.pause()
|
||||
}
|
||||
playClashSound(play) {
|
||||
const audio = document.getElementById('clash')
|
||||
play ? audio.play() : audio.pause()
|
||||
}
|
||||
}
|
||||
|
||||
export { PlaySoundCommand }
|
||||
629
src/components/DMT/js/WebSocketMessage.js
Normal file
@@ -0,0 +1,629 @@
|
||||
import * as THREE from 'three'
|
||||
import { ObjectAlarmCommand } from './ObjectAlarmCommand.js'
|
||||
import { TWEEN } from 'three/examples/jsm/libs/tween.module.min.js'
|
||||
|
||||
const WebsocketMessageReceive = function(editor) {
|
||||
const scope = this
|
||||
this.websocketMessage = (msg) => {
|
||||
new Promise((resolve, reject) => {
|
||||
let returnMes
|
||||
const arrays_signal = msg.data.split('|')
|
||||
const m_SourceType = arrays_signal[0] // 数据类型:DT:数字孪生数据
|
||||
const m_DeviceType = arrays_signal[1] // 设备类型,Robot:机器人类型的设备,Device:普通设备
|
||||
const m_DeviceName = arrays_signal[2] // 设备名称
|
||||
const m_DevicePartName = arrays_signal[3] // 设备运动部件
|
||||
const m_DevicePartDate = arrays_signal[4] // 设备运动部件数据
|
||||
switch (m_SourceType) {
|
||||
case 'DT':
|
||||
switch (m_DeviceType) {
|
||||
case editor.ProtocolIdentifiers.Robot_7: // 接受机器人运动数据进行播放 --------------------------现场用----------------
|
||||
returnMes = scope.deviceMoveEvent.RobotTranslation7(m_DeviceName, m_DevicePartName, m_DevicePartDate)
|
||||
break
|
||||
case editor.ProtocolIdentifiers.Device_3:
|
||||
console.log('设备运行')// --------------------------现场用----------------
|
||||
returnMes = scope.deviceMoveEvent.DeviceThreeAxis(m_DeviceName, m_DevicePartName, m_DevicePartDate)
|
||||
break
|
||||
case editor.ProtocolIdentifiers.Agv_3:// --------------------------现场用----------------
|
||||
console.log('AGV运行')
|
||||
returnMes = scope.deviceMoveEvent.AGVThreeAxis(m_DeviceName, m_DevicePartName, m_DevicePartDate)
|
||||
break
|
||||
case editor.ProtocolIdentifiers.Device_1: // 接受设备运动数据进行播放,已更新
|
||||
break
|
||||
case editor.ProtocolIdentifiers.FirstPosition: // 接受第一个点的数据,瞬间跳到该点,已更新
|
||||
break
|
||||
case editor.ProtocolIdentifiers.WareHousePart: //
|
||||
returnMes = scope.drawWareHousePartOne(m_DeviceName)
|
||||
break
|
||||
case editor.ProtocolIdentifiers.Robot_6: // 接受机器人运动数据进行播放
|
||||
returnMes = scope.deviceMoveEvent.RobotTranslation(m_DeviceName, m_DevicePartName, m_DevicePartDate)
|
||||
break
|
||||
case editor.ProtocolIdentifiers.ReLoadData: // 加载所有要播放的数据,避免资源浪费 ***********************UUID测试好用了******************************
|
||||
break
|
||||
case editor.ProtocolIdentifiers.PlayAct: // 根据ID 播放数据 状态为1 0暂停 ***********************UUID测试好用了******************************
|
||||
scope.playActData(m_DeviceName, parseInt(m_DevicePartName))
|
||||
break
|
||||
// case editor.ProtocolIdentifiers.ModelTransparent: // 根据传过来的模型名字和透明度 改变模型的透明度 ***********************UUID测试好用了******************************
|
||||
// returnMes = scope.robotPlan_ModelOperation.modelTrans(m_DeviceName, m_DevicePartName)
|
||||
// break
|
||||
case editor.ProtocolIdentifiers.Visible: // 接受CS指令显示、隐藏模型 ***********************UUID测试好用了******************************
|
||||
returnMes = scope.visibleObjectToBS(m_DeviceName, m_DevicePartName)
|
||||
break
|
||||
case 'JointMoveTo':
|
||||
if (!JSON.parse(m_DevicePartName)) console.log('JointMoveTo数据不对' + m_DevicePartName)
|
||||
this.JointMoveTo(m_DeviceName, JSON.parse(m_DevicePartName))
|
||||
break
|
||||
case editor.ProtocolIdentifiers.C_B_TagIDTrigger:
|
||||
{
|
||||
const tag = JSON.parse(m_DeviceName)
|
||||
scope.solveTagValue(tag.TagID, tag.TagValue)
|
||||
}
|
||||
break
|
||||
case editor.ProtocolIdentifiers.C_B_ObjectAlarm:
|
||||
{
|
||||
const Info = JSON.parse(m_DeviceName)
|
||||
console.log(Info)
|
||||
for (const infoElement of Info) {
|
||||
new ObjectAlarmCommand(editor, infoElement.ModelId).exec(!!parseInt(infoElement.value))
|
||||
}
|
||||
}
|
||||
break
|
||||
case editor.ProtocolIdentifiers.C_B_JointMoveTo:
|
||||
{
|
||||
const MoveValueList = JSON.parse(m_DeviceName)
|
||||
scope.ModelJointMoveTo(MoveValueList)
|
||||
}
|
||||
break
|
||||
case 'showWeld':
|
||||
this.showWeld(m_DeviceName, m_DevicePartName)
|
||||
break
|
||||
case 'showCheckOk':
|
||||
this.showCheckOk(m_DeviceName, m_DevicePartName)
|
||||
break
|
||||
default:
|
||||
returnMes = '不存在协议:' + msg
|
||||
break
|
||||
}
|
||||
break
|
||||
default:
|
||||
returnMes = '不存在协议:' + msg
|
||||
break
|
||||
}
|
||||
resolve(returnMes)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* HandlerType: 1:显隐,2:自转,3:行为,4:私服位置,5:附加拆离指令
|
||||
* HandlerCode: 模型或者工艺代码
|
||||
* HandlerValue: 显隐:0/1 ,自传:正负转速&axis,行为暂停播放:0/1
|
||||
* TagValueTagValue: 信号值
|
||||
* @param tagId
|
||||
* @param tagValue
|
||||
*/
|
||||
this.solveTagValue = (tagId, tagValue) => {
|
||||
const scope = this
|
||||
const actionInfo = editor.TagActList[tagId]
|
||||
if (!actionInfo) return
|
||||
for (const actionInfoElement of actionInfo) {
|
||||
switch (actionInfoElement.HandlerType) {
|
||||
case editor.signalSolveType.warning: // 报警
|
||||
if (tagValue === actionInfoElement.TagValue) {
|
||||
new ObjectAlarmCommand(editor, actionInfoElement.HandlerCode).exec(!!parseInt(actionInfoElement.HandlerValue))
|
||||
}
|
||||
break
|
||||
case editor.signalSolveType.visible: // 显隐
|
||||
if (tagValue === actionInfoElement.TagValue) {
|
||||
scope.visibleObjectToBS(actionInfoElement.HandlerCode, parseInt(actionInfoElement.HandlerValue))
|
||||
}
|
||||
break
|
||||
case editor.signalSolveType.rotation: // 自转
|
||||
if (tagValue === actionInfoElement.TagValue) {
|
||||
const ValueFactor = actionInfoElement.ValueFactor
|
||||
const Axis = actionInfoElement.Axis
|
||||
// const JointType = actionInfoElement.JointType
|
||||
const Flip = actionInfoElement.Flip
|
||||
const ModelCode = actionInfoElement.HandlerCode
|
||||
scope.modelRotation(ModelCode, Axis, Flip * parseFloat(ValueFactor))
|
||||
}
|
||||
break
|
||||
case editor.signalSolveType.craft: // 行为
|
||||
if (tagValue === actionInfoElement.TagValue) {
|
||||
scope.playActData(actionInfoElement.HandlerCode, parseInt(actionInfoElement.HandlerValue))
|
||||
}
|
||||
break
|
||||
case editor.signalSolveType.targetLocation: // 伺服位置
|
||||
scope.solveServoSignal(actionInfoElement, tagValue)
|
||||
break
|
||||
case editor.signalSolveType.attach: // 附加功能
|
||||
console.log('这个地方的附加功能没用写')
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 根据ACTid播放动作,开启线程
|
||||
* @param actID
|
||||
* @param state
|
||||
*/
|
||||
this.playActData = (actID, state) => {
|
||||
const scope = this
|
||||
if (!editor.isOk) return
|
||||
if (!editor.worker[actID]) editor.worker[actID] = new Worker('./DMT_WEB/webWorker/playFunction.js')
|
||||
if (editor.moveTrigger[actID].moveStatus !== state) {
|
||||
editor.worker[actID].postMessage({
|
||||
ActID: actID,
|
||||
State: state,
|
||||
isOk: editor.isOk,
|
||||
craftPlaySolveType: editor.craftPlaySolveType,
|
||||
moveTrigger: JSON.stringify(editor.moveTrigger[actID])
|
||||
})
|
||||
editor.moveTrigger[actID].moveStatus = state
|
||||
}
|
||||
editor.worker[actID].onmessage = function(event) {
|
||||
editor.moveTrigger[actID].myVarSetInterval = event.data.myVarSetInterval
|
||||
editor.moveTrigger[actID].currentFrame = event.data.pausedFrame
|
||||
const currentFrameData = event.data.currentFrameData
|
||||
const frameType = event.data.frameType
|
||||
editor.solveAttachModel('', true)
|
||||
switch (frameType) {
|
||||
case editor.craftPlaySolveType.attach:
|
||||
if (editor.FrameOperation.attach) {
|
||||
const position = currentFrameData['AttachToModelCode']
|
||||
const List_AttachModel = currentFrameData['List_AttachModel']
|
||||
const IsTwoWay = currentFrameData['IsTwoWay']
|
||||
const IsAttach = currentFrameData['IsAttach']
|
||||
if (IsAttach) {
|
||||
const attachData = []
|
||||
for (const editorElement of List_AttachModel) {
|
||||
attachData.push({
|
||||
ModelId: editorElement.ModelCode,
|
||||
ModelName: editorElement.ModelName,
|
||||
RootId: position,
|
||||
IsTwoWay: IsTwoWay
|
||||
})
|
||||
}
|
||||
editor.attachList.set(position, attachData)
|
||||
} else {
|
||||
for (const detachData of List_AttachModel) {
|
||||
const detachModelCode = detachData.ModelCode
|
||||
editor.scene.attach(editor.getObjectById(detachModelCode))
|
||||
editor.attachList.forEach((value, key) => {
|
||||
const attachList = value.filter(res => { return res.ModelId !== detachModelCode })
|
||||
editor.attachList.set(key, attachList)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
break
|
||||
case editor.craftPlaySolveType.visible:
|
||||
if (editor.FrameOperation.visibleObject) {
|
||||
const position = currentFrameData['ModelCode']
|
||||
const Visible = parseInt(currentFrameData['Visible'])
|
||||
scope.visibleObjectToBS(position, Visible)
|
||||
}
|
||||
break
|
||||
case editor.craftPlaySolveType.rotation:
|
||||
if (editor.FrameOperation.rotationObject) {
|
||||
const position = currentFrameData['ModelCode']
|
||||
const Axis = currentFrameData['Axis']
|
||||
const Rate = currentFrameData['Rate']
|
||||
scope.modelRotation(position, Axis, Rate)
|
||||
}
|
||||
break
|
||||
case editor.craftPlaySolveType.craft:
|
||||
if (editor.FrameOperation.playCraft) {
|
||||
const position = currentFrameData['CraftCode']
|
||||
const craftState = parseInt(currentFrameData['CraftValue'])
|
||||
scope.playActData(position, craftState)
|
||||
}
|
||||
break
|
||||
case editor.craftPlaySolveType.FrameData:
|
||||
{
|
||||
const position = currentFrameData['i']
|
||||
const objectToMove = editor.getObjectById(position)
|
||||
if (objectToMove) {
|
||||
if (currentFrameData.tx === 'NaN' || currentFrameData.ty === 'NaN' || currentFrameData.tz === 'NaN' || currentFrameData.qx === 'NaN' || currentFrameData.qy === 'NaN' || currentFrameData.qz === 'NaN' || currentFrameData.qw === 'NaN') {
|
||||
console.log('craftDataError')
|
||||
// editor.robotPlan_MessageList.execute(position, 'craftDataError')
|
||||
} else {
|
||||
const movePosition = new THREE.Vector3(parseFloat(currentFrameData.tx), parseFloat(currentFrameData.ty), parseFloat(currentFrameData.tz))
|
||||
const nq = new THREE.Quaternion(parseFloat(currentFrameData.qx), parseFloat(currentFrameData.qy), parseFloat(currentFrameData.qz), parseFloat(currentFrameData.qw))
|
||||
objectToMove.quaternion.copy(nq)
|
||||
objectToMove.position.copy(movePosition)
|
||||
}
|
||||
}
|
||||
}
|
||||
break
|
||||
case editor.craftPlaySolveType.warning: // 报警
|
||||
if (editor.FrameOperation.warning) {
|
||||
new ObjectAlarmCommand(scope.editor, currentFrameData['ModelCode']).exec(!!parseInt(currentFrameData['Visible']))
|
||||
}
|
||||
break
|
||||
default:
|
||||
delete editor.worker[event.data.ActID]
|
||||
editor.moveTrigger[actID].moveStatus = 0
|
||||
editor.moveTrigger[actID].myVarSetInterval = null
|
||||
editor.moveTrigger[actID].currentFrame = 0
|
||||
editor.moveTrigger[actID].pausedFrame = 0
|
||||
break
|
||||
}
|
||||
editor.solveAttachModel('', false)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 接受CS模型自转的指令
|
||||
* 接受CS模型自转的指令
|
||||
* @param objectNames
|
||||
* @param values
|
||||
* @param axis
|
||||
*/
|
||||
this.modelRotation = (objectNames, axis, values) => {
|
||||
const scope = this
|
||||
const EP = 0.000001
|
||||
let dir = 0
|
||||
if (!editor.getObjectById(objectNames)) return
|
||||
const currentModel = editor.getObjectById(objectNames)
|
||||
if ((parseFloat(values) >= -EP) && (parseFloat(values) <= EP)) {
|
||||
if (editor.RotationWorker[objectNames]) {
|
||||
editor.RotationWorker[objectNames].terminate()
|
||||
delete editor.RotationWorker[objectNames]
|
||||
delete editor.ModelRotateWorker[objectNames]
|
||||
}
|
||||
return
|
||||
} else {
|
||||
dir = 1
|
||||
if (editor.RotationWorker[objectNames]) {
|
||||
editor.RotationWorker[objectNames].terminate()
|
||||
delete editor.RotationWorker[objectNames]
|
||||
delete editor.ModelRotateWorker[objectNames]
|
||||
}
|
||||
}
|
||||
editor.RotationWorker[objectNames] = new Worker('webWorker/modelRotation.js')
|
||||
|
||||
if (!editor.ModelRotateWorker[objectNames]) {
|
||||
editor.ModelRotateWorker[objectNames] = {
|
||||
state: 0,
|
||||
myVarSetInterval: null,
|
||||
doAnimation: false,
|
||||
ModelCode: objectNames
|
||||
}
|
||||
}
|
||||
|
||||
editor.RotationWorker[objectNames].postMessage({
|
||||
ObjectNames: objectNames,
|
||||
Values: values,
|
||||
Dir: dir,
|
||||
ModelRotateWorker: editor.ModelRotateWorker[objectNames],
|
||||
RotateSpeed: editor.rotateSpeed,
|
||||
RotationValue: currentModel.rotation[axis]
|
||||
})
|
||||
|
||||
editor.RotationWorker[objectNames].onmessage = (event) => {
|
||||
scope.modelSelfRotation(currentModel, event.data.rotation, axis)
|
||||
}
|
||||
}
|
||||
this.modelSelfRotation = (currentModel, rotation, axis) => {
|
||||
currentModel.rotation[axis] = rotation
|
||||
}
|
||||
this.ModelJointMoveTo = (MoveValueList) => {
|
||||
// TOBS?WEB?SCADAMain?DT|C_B_JointMoveTo|[{"ModelCode":"5E6D91B8-B44D-4C44-AAEF-10492E548A1A","JointType":"rotation","Axis":"x","Flip":1,"Value":0,"ValueFactor":0.017453292519943295,"Delta":0}]
|
||||
// TOBS?WEB?SCADAMain?DT|C_B_JointMoveTo|[{"ModelCode":"644506B1-A05A-4E57-BBA2-C63635586C63","JointType":"position","Axis":"y","Flip":-1,"Value":-15.0,"ValueFactor":0.001,"Delta":-655.0}]
|
||||
new Promise(resolve => {
|
||||
for (const MoveValue of MoveValueList) {
|
||||
const ModelCode = MoveValue.ModelCode
|
||||
const ValueFactor = parseFloat(MoveValue.ValueFactor)
|
||||
const type = MoveValue.JointType
|
||||
const Value = parseFloat(MoveValue.Value)
|
||||
const Flip = parseFloat(MoveValue.Flip)
|
||||
const axis = MoveValue.Axis
|
||||
const Delta = parseFloat(MoveValue.Delta)
|
||||
const object = editor.getObjectById(ModelCode)
|
||||
const originInfo = editor.objectIdSet.get(ModelCode)
|
||||
if (!originInfo) return
|
||||
const matrix = originInfo['matrix']
|
||||
const originValue = type === 'rotation' ? originInfo[type]['_' + axis] : originInfo[type][axis]
|
||||
const lastValue = originInfo['lastValue'] === null ? originValue : originInfo['lastValue']
|
||||
const moveValue = Flip * (Value - Delta) * ValueFactor
|
||||
|
||||
if (object) {
|
||||
editor.solveAttachModel('', true)
|
||||
const JointValue = originValue + moveValue
|
||||
new TWEEN.Tween({
|
||||
moveValue: lastValue
|
||||
}).to({ moveValue: JointValue }, 50)
|
||||
.onStart(function() {
|
||||
originInfo['lastValue'] = JointValue
|
||||
}).onUpdate(function() {
|
||||
switch (type) {
|
||||
case 'position':
|
||||
object[type][axis] = this._object.moveValue
|
||||
break
|
||||
case 'rotation':
|
||||
{
|
||||
const moveAxis = {
|
||||
x: new THREE.Vector3(1, 1, 1),
|
||||
y: new THREE.Vector3(1, 1, 1),
|
||||
z: new THREE.Vector3(1, 1, 1)
|
||||
}
|
||||
matrix.extractBasis(moveAxis.x, moveAxis.y, moveAxis.z)
|
||||
const nM = new THREE.Matrix4()
|
||||
nM.makeRotationAxis(moveAxis[axis], this._object.moveValue)
|
||||
nM.multiply(matrix)
|
||||
object.rotation.setFromRotationMatrix(nM)
|
||||
object.updateWorldMatrix()
|
||||
}
|
||||
break
|
||||
}
|
||||
}).start()
|
||||
editor.solveAttachModel('', false)
|
||||
} else {
|
||||
console.log('模型不存在')
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
/**
|
||||
* 接伺服类的数据
|
||||
* @param ModelInfo
|
||||
* @param tagValue
|
||||
*/
|
||||
this.solveServoSignal = (ModelInfo, tagValue) => {
|
||||
try {
|
||||
const type = ModelInfo.JointType
|
||||
const axis = ModelInfo.Axis
|
||||
const flip = ModelInfo.Flip
|
||||
const Value = ModelInfo.Value
|
||||
const ValueFactor = ModelInfo.ValueFactor // 倍率
|
||||
const ModelId = ModelInfo.HandlerCode // 模型代码
|
||||
const object = editor.getObjectById(ModelId)
|
||||
const originInfo = editor.objectIdSet.get(ModelId)
|
||||
if (!originInfo) return
|
||||
const matrix = originInfo['matrix']
|
||||
const originValue = type === 'rotation' ? originInfo[type]['_' + axis] : originInfo[type][axis]
|
||||
const lastValue = originInfo['lastValue'] === null ? originValue : originInfo['lastValue']
|
||||
const moveValue = flip * (parseFloat(tagValue) - Value) * ValueFactor
|
||||
|
||||
if (object) {
|
||||
editor.solveAttachModel('', true)
|
||||
const JointValue = originValue + moveValue
|
||||
new TWEEN.Tween({
|
||||
moveValue: lastValue
|
||||
}).to({ moveValue: JointValue }, 100)
|
||||
.onStart(function() {
|
||||
originInfo['lastValue'] = JointValue
|
||||
})
|
||||
.onUpdate(function() {
|
||||
switch (type) {
|
||||
case 'position':
|
||||
object[type][axis] = this._object.moveValue
|
||||
break
|
||||
case 'rotation':
|
||||
{
|
||||
const moveAxis = {
|
||||
x: new THREE.Vector3(1, 1, 1),
|
||||
y: new THREE.Vector3(1, 1, 1),
|
||||
z: new THREE.Vector3(1, 1, 1)
|
||||
}
|
||||
matrix.extractBasis(moveAxis.x, moveAxis.y, moveAxis.z)
|
||||
const nM = new THREE.Matrix4()
|
||||
nM.makeRotationAxis(moveAxis[axis], this._object.moveValue)
|
||||
// nM.makeRotationAxis(moveAxis[axis], JointValue)
|
||||
nM.multiply(matrix)
|
||||
object.rotation.setFromRotationMatrix(nM)
|
||||
object.updateWorldMatrix()
|
||||
}
|
||||
break
|
||||
}
|
||||
}).start()
|
||||
editor.solveAttachModel('', false)
|
||||
}
|
||||
//
|
||||
// if (object) {
|
||||
// editor.solveAttachModel('', true)
|
||||
// object[type][axis] = originValue + (ValueFactor * flip * parseFloat(tagValue) + Value)
|
||||
// editor.solveAttachModel('', false)
|
||||
// }
|
||||
} catch (e) {
|
||||
console.log('solveServoSignal错误')
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 接受机器人类的数据
|
||||
* @param ModelId
|
||||
* @param JointData
|
||||
* @constructor
|
||||
*/
|
||||
this.JointMoveTo = (ModelId, JointData = {}) => {
|
||||
if (editor.robotList[ModelId]) {
|
||||
const ModelList = editor.robotList[ModelId]
|
||||
// if (window.updateRobotData) window.updateRobotData(ModelId, JointData)
|
||||
// window.updateLabelInfoJoint(ModelId, JointData)
|
||||
for (let i = 0; i < ModelList.length; i++) {
|
||||
if (ModelList[i].ModelId === '') return
|
||||
this.jointMoveToPromise(JointData, ModelList[i], i, ModelId)
|
||||
}
|
||||
}
|
||||
}
|
||||
this.jointMoveToPromise = (JointData, ModelListData, i, ModelId) => {
|
||||
new Promise(resolve => {
|
||||
const ModelIdJoint = ModelListData.ModelId
|
||||
const object = ModelListData.object
|
||||
const type = ModelListData.type
|
||||
const axis = ModelListData.axis
|
||||
const matrix = ModelListData.matrix
|
||||
const flip = ModelListData.flip
|
||||
const delta = parseFloat(ModelListData.delta)
|
||||
const multiple = ModelListData.multiple
|
||||
const originInfo = editor.objectIdSet.get(ModelIdJoint)
|
||||
if (!originInfo) return
|
||||
const originValue = type === 'rotation' ? originInfo[type]['_' + axis] : originInfo[type][axis]
|
||||
const lastValue = ModelListData.lastValue === null ? originValue : ModelListData.lastValue
|
||||
const moveValue = flip * (parseFloat(JointData['J' + (i + 1)]) - delta) * multiple
|
||||
if (object) {
|
||||
const JointValue = originValue + moveValue
|
||||
new TWEEN.Tween({
|
||||
moveValue: lastValue
|
||||
}).to({ moveValue: JointValue }, 200)
|
||||
.onStart(function() {
|
||||
editor.robotList[ModelId][i]['lastValue'] = JointValue
|
||||
})
|
||||
.onUpdate(function() {
|
||||
switch (type) {
|
||||
case 'position':
|
||||
object[type][axis] = this._object.moveValue
|
||||
break
|
||||
case 'rotation':
|
||||
{
|
||||
const moveAxis = {
|
||||
x: new THREE.Vector3(1, 1, 1),
|
||||
y: new THREE.Vector3(1, 1, 1),
|
||||
z: new THREE.Vector3(1, 1, 1)
|
||||
}
|
||||
matrix.extractBasis(moveAxis.x, moveAxis.y, moveAxis.z)
|
||||
const nM = new THREE.Matrix4()
|
||||
nM.makeRotationAxis(moveAxis[axis], this._object.moveValue)
|
||||
// nM.makeRotationAxis(moveAxis[axis], JointValue)
|
||||
nM.multiply(matrix)
|
||||
object.rotation.setFromRotationMatrix(nM)
|
||||
object.updateWorldMatrix()
|
||||
}
|
||||
break
|
||||
}
|
||||
}).start()
|
||||
}
|
||||
})
|
||||
}
|
||||
this.getAxisValue = (axis, value) => {
|
||||
return JSON.parse('{"' + axis + '":' + value + '}')
|
||||
}
|
||||
|
||||
this.getAxisValue = (axis, value) => {
|
||||
return JSON.parse('{"' + axis + '":' + value + '}')
|
||||
}
|
||||
|
||||
this.showWeld = (ModelId, Welding) => {
|
||||
// 徐工专用
|
||||
if (ModelId === '46DDBCD8-D775-49A4-BB14-30015FF87595') editor.WeldLightVisible1 = !!parseInt(Welding)
|
||||
if (ModelId === '1E96DED2-6EEF-469F-BFE6-8F52FB62C2B0') editor.WeldLightVisible2 = !!parseInt(Welding)
|
||||
}
|
||||
this.showCheckOk = (check) => {
|
||||
// 徐工专用
|
||||
if (parseInt(check)) {
|
||||
editor.showTagList[3].title = '工件:QY16KC, 检测OK'
|
||||
} else {
|
||||
editor.showTagList[3].title = '工件:QY16KC'
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 显示隐藏物体
|
||||
* @param m_DeviceName
|
||||
* @param isVisible
|
||||
*/
|
||||
this.visibleObjectToBS = (m_DeviceName, isVisible) => {
|
||||
const currentModel = editor.getObjectById(m_DeviceName)
|
||||
if (currentModel) {
|
||||
currentModel.visible = !!parseInt(isVisible)
|
||||
currentModel.traverse(res => {
|
||||
res.visible = !!parseInt(isVisible)
|
||||
})
|
||||
currentModel.userData['visible'] = !!parseInt(isVisible)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化获取TagValue
|
||||
*/
|
||||
this.getOriginTagValue = () => {
|
||||
let msg = ''
|
||||
let socketMsg = ''
|
||||
const keyWord = 'B_C_DT_WebLoaded'
|
||||
msg = 'DT|' + keyWord
|
||||
socketMsg = editor.BSport + msg
|
||||
const topic = editor.BSport.split('?')[2]
|
||||
switch (editor.connectType) {
|
||||
case 1:
|
||||
editor.socket.send(socketMsg)
|
||||
break
|
||||
case 2:
|
||||
editor.mqttClient.publish(topic, msg, 0, error => {
|
||||
if (error) {
|
||||
console.log('Publish error', error)
|
||||
}
|
||||
})
|
||||
break
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 更新库存状态
|
||||
* @param dataInfo
|
||||
*/
|
||||
this.drawWareHousePartOne = (dataInfo) => {
|
||||
const scope = this
|
||||
try {
|
||||
const whInfo = JSON.parse(dataInfo)
|
||||
for (const whStoreInfo of whInfo) {
|
||||
const whStoreNum = whStoreInfo.Key // 库位号 唯一值
|
||||
const whStoreState = whStoreInfo.Value // 立库状态
|
||||
const whNum = whStoreNum.toString().substring(0, 4) // 立库号 1000一期立库 1003刀具库 1002三坐标测量库 1001机床线旁库
|
||||
const currentStoreInfo = editor.WareHouse.get(whStoreNum)
|
||||
if (currentStoreInfo) {
|
||||
if (parseInt(whStoreState) === 0) {
|
||||
// 0的时候直接移除库存
|
||||
editor.removeObject(currentStoreInfo.object)
|
||||
editor.WareHouse.delete(whStoreNum)
|
||||
} else {
|
||||
// 不一样的状态 更新
|
||||
if (currentStoreInfo.whStoreState !== whStoreState) {
|
||||
// 移除零件,更新库存信息信息
|
||||
editor.removeObject(currentStoreInfo.object)
|
||||
scope.updateStoreModel(whNum, whStoreNum, whStoreState)
|
||||
currentStoreInfo.whStoreState = whStoreState
|
||||
currentStoreInfo.object = null
|
||||
}
|
||||
}
|
||||
} else {
|
||||
editor.WareHouse.set(whStoreNum, {
|
||||
whNum: whNum,
|
||||
whStoreNum: whStoreNum,
|
||||
whStoreState: whStoreState,
|
||||
object: null
|
||||
})
|
||||
scope.updateStoreModel(whNum, whStoreNum, whStoreState)
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.log('库存解析错误')
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新零件
|
||||
* @param whNum
|
||||
* @param whStoreNum
|
||||
* @param whStoreState
|
||||
*/
|
||||
this.updateStoreModel = (whNum, whStoreNum, whStoreState) => {
|
||||
try {
|
||||
const basicPartModel = editor.WareHouseBasicModel.get('warehousepart' + whStoreState)
|
||||
const basicWareHouseModelData = editor.WareHouseBasicModel.get('warehouse' + whNum)
|
||||
if (basicPartModel && basicWareHouseModelData) {
|
||||
const basicPartModelClone = basicPartModel.clone()
|
||||
const basicPartModelPosition = basicWareHouseModelData[whStoreNum]
|
||||
basicPartModelClone.position.copy(basicPartModelPosition.getWorldPosition(new THREE.Vector3()))
|
||||
editor.scene.add(basicPartModelClone)
|
||||
editor.WareHouse.get(whStoreNum).object = basicPartModelClone
|
||||
}
|
||||
} catch (e) {
|
||||
console.log('库存模型解析错误')
|
||||
}
|
||||
}
|
||||
}
|
||||
export {
|
||||
WebsocketMessageReceive
|
||||
}
|
||||
1049
src/components/DMT/js/mousetrap.js
Normal file
74
src/components/DMT/js/websocketConnect.js
Normal file
@@ -0,0 +1,74 @@
|
||||
import { WebsocketMessageReceive } from './WebSocketMessage.js'
|
||||
|
||||
function connect(editor) {
|
||||
const host = 'ws://' + editor.ip + '//WebModule//websocket'
|
||||
let timeout = null
|
||||
const websocketMessageReceive = new WebsocketMessageReceive(editor)
|
||||
// 尝试连接至服务器
|
||||
try {
|
||||
if ('WebSocket' in window) {
|
||||
editor.socket = new WebSocket(host)
|
||||
} else {
|
||||
editor.showMessage('浏览器不支持WebSocket', 'error', 2000)
|
||||
}
|
||||
} catch (exception) {
|
||||
editor.showMessage('与服务器断开连接', 'error', 2000)
|
||||
return
|
||||
}
|
||||
// 连接成功
|
||||
editor.socket.onopen = function() {
|
||||
// 关闭timer
|
||||
try {
|
||||
clearInterval(timeout)
|
||||
} catch (exception) {
|
||||
console.log(exception)
|
||||
}
|
||||
const name = editor.opname
|
||||
editor.socket.send('LIN,' + name)
|
||||
editor.showMessage('加载完成,连接服务器成功!', 'success', 2000)
|
||||
editor.isOk = true
|
||||
websocketMessageReceive.getOriginTagValue()
|
||||
// let a = 0
|
||||
// setInterval(() => {
|
||||
// a += 0.5
|
||||
// const message = `DT|JointMoveTo|0f26fc6e-1caf-4f57-beb3-d8a65872fbdd|{"J1":"${a}","J2":"0","J3":"0","J4":"0","J5":"0","J6":"0","J7":"0","J8":"0","J9":"0","J10":"0","J11":"0","J12":"0"}`
|
||||
// websocketMessageReceive.websocketMessage({ data: message })
|
||||
// }, 10)
|
||||
}
|
||||
// 收到消息
|
||||
editor.socket.onmessage = function(msg) {
|
||||
try {
|
||||
websocketMessageReceive.websocketMessage(msg)
|
||||
} catch (exception) {
|
||||
const error = exception.toString()
|
||||
console.log(error)
|
||||
}
|
||||
}
|
||||
// 连接断开
|
||||
editor.socket.onclose = function(event) {
|
||||
try {
|
||||
editor.showMessage('onclose' + '服务器连接失败', 'error', 2000)
|
||||
editor.socket.close()
|
||||
if (editor.IsAllowConnect) {
|
||||
// 显示一下
|
||||
editor.showMessage('重新连接服务器', 'warning', 2000)
|
||||
console.log('onclose' + '重新连接服务器')
|
||||
// 重新连接,打开计时器
|
||||
timeout = setTimeout(function() {
|
||||
connect(editor)
|
||||
}, 5000)
|
||||
}
|
||||
} catch (exception) {
|
||||
const error = exception.toString()
|
||||
editor.showMessage.error('服务器出现错误,关闭连接' + error, 'error', 2000)
|
||||
}
|
||||
}
|
||||
// 出现错误
|
||||
editor.socket.onerror = function(event) {
|
||||
console.log('onerror_' + '服务器连接失败')
|
||||
editor.showMessage.error('服务器连接失败', 'error', 2000)
|
||||
}
|
||||
}
|
||||
|
||||
export { connect }
|
||||
|
||||
58
src/components/DMT/libs/DmtControl.js
Normal file
@@ -0,0 +1,58 @@
|
||||
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
|
||||
const _changeEvent = { type: 'change' }
|
||||
class DmtControl extends OrbitControls {
|
||||
constructor(object, domElement) {
|
||||
super(object, domElement)
|
||||
const scope = this
|
||||
const STATE = {
|
||||
NONE: -1,
|
||||
ROTATE: 0,
|
||||
DOLLY: 1,
|
||||
PAN: 2,
|
||||
TOUCH_ROTATE: 3,
|
||||
TOUCH_PAN: 4,
|
||||
TOUCH_DOLLY_PAN: 5,
|
||||
TOUCH_DOLLY_ROTATE: 6
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
let state = STATE.NONE
|
||||
this.resetState = function(target0, position0, zoom0) {
|
||||
scope.target.copy(target0)
|
||||
scope.object.position.copy(position0)
|
||||
scope.object.zoom = zoom0
|
||||
|
||||
scope.object.updateProjectionMatrix()
|
||||
scope.dispatchEvent(_changeEvent)
|
||||
|
||||
scope.update()
|
||||
|
||||
state = STATE.NONE
|
||||
}
|
||||
this.setLookAt = function(position0, target0, zoom0) {
|
||||
scope.target.copy(target0)
|
||||
scope.object.position.copy(position0)
|
||||
scope.object.zoom = zoom0
|
||||
|
||||
scope.object.updateProjectionMatrix()
|
||||
scope.dispatchEvent(_changeEvent)
|
||||
|
||||
scope.update()
|
||||
|
||||
state = STATE.NONE
|
||||
}
|
||||
this.moveTo = function(x, y, z) {
|
||||
// scope.target.set(x, y, z)
|
||||
}
|
||||
this.getState = function() {
|
||||
return {
|
||||
target: scope.target.clone(),
|
||||
position: scope.object.position.clone(),
|
||||
zoom: parseFloat(scope.object.zoom.toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
export {
|
||||
DmtControl
|
||||
}
|
||||
536
src/components/DMT/libs/DmtViewCube.js
Normal file
@@ -0,0 +1,536 @@
|
||||
import * as THREE from 'three'
|
||||
|
||||
let viewCubeUpdate = null
|
||||
|
||||
const Viewer = function Viewer(editor) {
|
||||
const ViewerDiv = document.createElement('div')
|
||||
ViewerDiv.id = 'orientCubeWrapperDiv'
|
||||
ViewerDiv.style.position = 'absolute'
|
||||
ViewerDiv.style.left = '10px'
|
||||
ViewerDiv.style.bottom = '10px'
|
||||
ViewerDiv.style.display = 'flex'
|
||||
ViewerDiv.style.backgroundColor = 'transparent'
|
||||
ViewerDiv.style.width = '180px'
|
||||
ViewerDiv.style.height = '180px'
|
||||
ViewerDiv.style.zIndex = '999'
|
||||
|
||||
const ViewerUI = document.createElement('div')
|
||||
ViewerUI.id = 'orientCubeWrapper'
|
||||
ViewerUI.style.width = '180px'
|
||||
ViewerUI.style.height = ' 180px'
|
||||
ViewerUI.style.opacity = ' 0.7'
|
||||
ViewerUI.style.transition = ' opacity 0.3s'
|
||||
|
||||
ViewerDiv.appendChild(ViewerUI)
|
||||
document.body.appendChild(ViewerDiv)
|
||||
|
||||
const cubeCameraDistance = 5
|
||||
const controlsViewer = editor.cameraControls
|
||||
const cubeWrapper = ViewerUI
|
||||
|
||||
const cubeScene = new THREE.Scene()
|
||||
const cubeRenderer = new THREE.WebGLRenderer({
|
||||
alpha: true,
|
||||
antialias: true,
|
||||
preserveDrawingBuffer: true
|
||||
})
|
||||
const cubeCamera = new THREE.PerspectiveCamera(50, cubeWrapper.offsetWidth / cubeWrapper.offsetHeight, 0.1, 100)
|
||||
cubeRenderer.setSize(cubeWrapper.offsetWidth, cubeWrapper.offsetHeight)
|
||||
cubeWrapper.appendChild(cubeRenderer.domElement)
|
||||
cubeScene.add(cubeCamera)
|
||||
cubeCamera.position.set(2, 2, 2)
|
||||
createArrow(new THREE.Vector3(5, 0, 0), new THREE.Vector3(-5, -5, -5), 13, 0xFF0000, 'X')// x
|
||||
createArrow(new THREE.Vector3(0, 0, 5), new THREE.Vector3(-5, -5, -5), 13, 0x0000FF, 'Z')// z
|
||||
createArrow(new THREE.Vector3(0, 5, 0), new THREE.Vector3(-5, -5, -5), 13, 0x008000, 'Y')// y
|
||||
cubeScene.add(new THREE.AmbientLight(0xffffff))
|
||||
initModel()
|
||||
let activeObject
|
||||
cubeRenderer.domElement.onmousemove = (event) => {
|
||||
const intersects = getIntersects(event)
|
||||
if (intersects.length !== 0) {
|
||||
const res = intersects.filter(function(res) {
|
||||
return res && res.object.name !== '' && res.object instanceof THREE.Mesh
|
||||
})[0]
|
||||
if (res && res.object) {
|
||||
if (activeObject) {
|
||||
if (activeObject.name === res.object.name) {
|
||||
activeObject.material.color.set('#6ad0f8')
|
||||
return
|
||||
} else {
|
||||
activeObject.material.color.set('#00c0ff')
|
||||
activeObject = null
|
||||
}
|
||||
}
|
||||
activeObject = res.object
|
||||
activeObject.material.color.set('#6ad0f8')
|
||||
}
|
||||
} else {
|
||||
if (activeObject) {
|
||||
activeObject.material.color.set('#00c0ff')
|
||||
activeObject = null
|
||||
}
|
||||
}
|
||||
}
|
||||
cubeRenderer.domElement.onclick = () => {
|
||||
if (!activeObject) return
|
||||
const _position = editor.camera.position
|
||||
const _target = editor.cameraControls.target
|
||||
const _zoom = editor.camera.zoom
|
||||
const Params = {
|
||||
positionX: Math.abs(_position.x),
|
||||
positionY: Math.abs(_position.y),
|
||||
positionZ: Math.abs(_position.z),
|
||||
positionXY: getTwoMax(_position.x, _position.y),
|
||||
positionXZ: getTwoMax(_position.x, _position.z),
|
||||
positionYZ: getTwoMax(_position.y, _position.z),
|
||||
positionXYZ: getThreeMax(_position.x, _position.y, _position.z),
|
||||
|
||||
targetX: Math.abs(_target.x),
|
||||
targetY: Math.abs(_target.y),
|
||||
targetZ: Math.abs(_target.z),
|
||||
targetXY: getTwoMax(_target.x, _target.y),
|
||||
targetXZ: getTwoMax(_target.x, _target.z),
|
||||
targetYZ: getTwoMax(_target.y, _target.z),
|
||||
targetXYZ: getThreeMax(_target.x, _target.y, _target.z)
|
||||
}
|
||||
const dirAxis = {
|
||||
'TOP': [0, 0, Params.positionZ,
|
||||
0, 0, Params.targetZ,
|
||||
_zoom],
|
||||
'BOTTOM': [0, 0, -Params.positionZ,
|
||||
0, 0, -Params.targetZ,
|
||||
_zoom],
|
||||
'FRONT': [Params.positionX, 0, 0,
|
||||
Params.targetX, 0, 0,
|
||||
_zoom],
|
||||
'BACK': [-Params.positionX, 0, 0,
|
||||
-Params.targetX, 0, 0,
|
||||
_zoom],
|
||||
'LEFT': [0, -Params.positionY, 0,
|
||||
0, -Params.targetY, 0,
|
||||
_zoom],
|
||||
'RIGHT': [0, Params.positionY, 0,
|
||||
0, Params.targetY, 0,
|
||||
_zoom],
|
||||
|
||||
'BACK-LEFT': [-Params.positionXY, -Params.positionXY, 0,
|
||||
-Params.targetXY, -Params.targetXY, 0,
|
||||
_zoom],
|
||||
'FRONT-LEFT': [Params.positionXY, -Params.positionXY, 0,
|
||||
Params.targetXY, -Params.targetXY, 0,
|
||||
_zoom],
|
||||
'TOP-LEFT': [0, -Params.positionYZ, Params.positionYZ,
|
||||
0, -Params.targetYZ, Params.targetYZ,
|
||||
_zoom],
|
||||
'TOP-RIGHT': [0, Params.positionYZ, Params.positionYZ,
|
||||
0, Params.targetYZ, Params.targetYZ,
|
||||
_zoom],
|
||||
'RIGHT-BOTTOM': [0, Params.positionYZ, -Params.positionYZ,
|
||||
0, Params.targetYZ, -Params.targetYZ,
|
||||
_zoom],
|
||||
'LEFT-BOTTOM': [0, -Params.positionYZ, -Params.positionYZ,
|
||||
0, -Params.targetYZ, -Params.targetYZ,
|
||||
_zoom],
|
||||
'BACK-BOTTOM': [-Params.positionXZ, 0, -Params.positionXZ,
|
||||
-Params.targetXZ, 0, -Params.targetXZ,
|
||||
_zoom],
|
||||
'TOP-FRONT': [Params.positionXZ, 0, Params.positionXZ,
|
||||
Params.targetXZ, 0, Params.targetXZ,
|
||||
_zoom],
|
||||
'FRONT-BOTTOM': [Params.positionXZ, 0, -Params.positionXZ,
|
||||
Params.targetXZ, 0, -Params.targetXZ,
|
||||
_zoom],
|
||||
'TOP-BACK': [-Params.positionXZ, 0, Params.positionXZ,
|
||||
-Params.targetXZ, 0, Params.targetXZ,
|
||||
_zoom],
|
||||
'RIGHT-FRONT': [Params.positionXY, Params.positionXY, 0,
|
||||
Params.targetXY, Params.targetXY, 0,
|
||||
_zoom],
|
||||
'BACK-RIGHT': [-Params.positionXY, Params.positionXY, 0,
|
||||
-Params.targetXY, Params.targetXY, 0,
|
||||
_zoom],
|
||||
|
||||
'BACK-RIGHT-BOTTOM': [-Params.positionXYZ, Params.positionXYZ, -Params.positionXYZ,
|
||||
-Params.targetXYZ, Params.targetXYZ, -Params.targetXYZ,
|
||||
_zoom],
|
||||
'TOP-RIGHT-BACK': [-Params.positionXYZ, Params.positionXYZ, Params.positionXYZ,
|
||||
-Params.targetXYZ, Params.targetXYZ, Params.targetXYZ,
|
||||
_zoom],
|
||||
'TOP-LEFT-BACK': [-Params.positionXYZ, -Params.positionXYZ, Params.positionXYZ,
|
||||
-Params.targetXYZ, -Params.targetXYZ, Params.targetXYZ,
|
||||
_zoom],
|
||||
'TOP-LEFT-FRONT': [Params.positionXYZ, -Params.positionXYZ, Params.positionXYZ,
|
||||
Params.targetXYZ, -Params.targetXYZ, Params.targetXYZ,
|
||||
_zoom],
|
||||
'FRONT-BOTTOM-RIGHT': [Params.positionXYZ, Params.positionXYZ, -Params.positionXYZ,
|
||||
Params.targetXYZ, Params.targetXYZ, -Params.targetXYZ,
|
||||
_zoom],
|
||||
'TOP-RIGHT-FRONT': [Params.positionXYZ, Params.positionXYZ, Params.positionXYZ,
|
||||
Params.targetXYZ, Params.targetXYZ, Params.targetXYZ,
|
||||
_zoom],
|
||||
'BACK-BOTTOM-LEFT': [-Params.positionXYZ, -Params.positionXYZ, -Params.positionXYZ,
|
||||
-Params.targetXYZ, -Params.targetXYZ, -Params.targetXYZ,
|
||||
_zoom],
|
||||
'FRONT-BOTTOM-LEFT': [Params.positionXYZ, -Params.positionXYZ, -Params.positionXYZ,
|
||||
Params.targetXYZ, -Params.targetXYZ, -Params.targetXYZ,
|
||||
_zoom]
|
||||
}
|
||||
if (activeObject.name && dirAxis[activeObject.name]) {
|
||||
const position = new THREE.Vector3(dirAxis[activeObject.name][0], dirAxis[activeObject.name][1], dirAxis[activeObject.name][2])
|
||||
const target = new THREE.Vector3(dirAxis[activeObject.name][3], dirAxis[activeObject.name][4], dirAxis[activeObject.name][5])
|
||||
const zoom = dirAxis[activeObject.name][6]
|
||||
|
||||
editor.cameraControls.setLookAt(position, target, zoom)
|
||||
// editor.cameraControls.setLookAt(dirAxis[activeObject.name][0],
|
||||
// dirAxis[activeObject.name][1],
|
||||
// dirAxis[activeObject.name][2],
|
||||
// 0, 0, 0, true)
|
||||
// editor.cameraControls.moveTo(editor.cameraControls._target.x, editor.cameraControls._target.y, editor.cameraControls._target.z, true)
|
||||
editor.camera.updateProjectionMatrix()
|
||||
editor.camera.clearViewOffset()
|
||||
updateCubeCamera()
|
||||
}
|
||||
|
||||
function getTwoMax(a, b) {
|
||||
return Math.abs(a) > Math.abs(b) ? Math.abs(a) : Math.abs(b)
|
||||
}
|
||||
|
||||
function getThreeMax(a, b, c) {
|
||||
return Math.abs(a) > Math.abs(b) ? Math.abs(a) > Math.abs(c) ? Math.abs(a) : Math.abs(c) : Math.abs(b) > Math.abs(c) ? Math.abs(b) : Math.abs(c)
|
||||
}
|
||||
}
|
||||
function updateCubeCamera() {
|
||||
cubeRenderer.render(cubeScene, cubeCamera)
|
||||
cubeCamera.rotation.copy(editor.camera.rotation)
|
||||
const dir = editor.camera.position.clone().sub(controlsViewer.target).normalize()
|
||||
dir.multiplyScalar(cubeCameraDistance)
|
||||
cubeCamera.position.copy(dir.multiplyScalar(cubeCameraDistance))
|
||||
}
|
||||
viewCubeUpdate = updateCubeCamera
|
||||
function createArrow(dir, origin, length = 1, color = '0xffff00', text = '') {
|
||||
// normalize the direction vector (convert to vector of length 1)
|
||||
dir.normalize()
|
||||
const arrowHelper = new THREE.ArrowHelper(dir, origin, length, color)
|
||||
cubeScene.add(arrowHelper)
|
||||
}
|
||||
function initModel() {
|
||||
const cubeMaterialRIGHT = new THREE.MeshLambertMaterial({
|
||||
color: 0x00c0ff,
|
||||
opacity: 1,
|
||||
map: new THREE.CanvasTexture(getTextCanvas('RIGHT')),
|
||||
side: THREE.DoubleSide
|
||||
})
|
||||
const cubeMaterialLEFT = new THREE.MeshLambertMaterial({
|
||||
color: 0x00c0ff,
|
||||
opacity: 1,
|
||||
map: new THREE.CanvasTexture(getTextCanvas('LEFT')), // BOTTOM
|
||||
side: THREE.DoubleSide
|
||||
})
|
||||
const cubeMaterialFRONT = new THREE.MeshLambertMaterial({
|
||||
color: 0x00c0ff,
|
||||
opacity: 1,
|
||||
map: new THREE.CanvasTexture(getTextCanvas('FRONT')),
|
||||
side: THREE.DoubleSide
|
||||
})
|
||||
const cubeMaterialBACK = new THREE.MeshLambertMaterial({
|
||||
color: 0x00c0ff,
|
||||
opacity: 1,
|
||||
map: new THREE.CanvasTexture(getTextCanvas('BACK')),
|
||||
side: THREE.DoubleSide
|
||||
})
|
||||
const cubeMaterialBOTTOM = new THREE.MeshLambertMaterial({
|
||||
color: 0x00c0ff,
|
||||
opacity: 1,
|
||||
map: new THREE.CanvasTexture(getTextCanvas('BOTTOM')),
|
||||
side: THREE.DoubleSide
|
||||
})
|
||||
const cubeMaterialTOP = new THREE.MeshLambertMaterial({
|
||||
color: 0x00c0ff,
|
||||
opacity: 1,
|
||||
map: new THREE.CanvasTexture(getTextCanvas('TOP')), // LEFT
|
||||
side: THREE.DoubleSide
|
||||
})
|
||||
const cubeMaterial = new THREE.MeshLambertMaterial({
|
||||
color: 0x00c0ff,
|
||||
opacity: 1,
|
||||
map: new THREE.CanvasTexture(getTextCanvas('')),
|
||||
side: THREE.DoubleSide
|
||||
})
|
||||
|
||||
const SphereA = new THREE.SphereGeometry(1, 32, 32, 0, 0.5 * Math.PI, 0, 0.5 * Math.PI)
|
||||
const edgesSphereA = new THREE.EdgesGeometry(SphereA, 3)
|
||||
const CylinderB = new THREE.CylinderGeometry(1, 1, 8, 64, 1, false, 0, 0.5 * Math.PI)
|
||||
const edgesCylinderB = new THREE.EdgesGeometry(CylinderB, 3)
|
||||
const cubeC = new THREE.BoxGeometry(7.99, 4.99, 7.99)
|
||||
const CylinderD = new THREE.CylinderGeometry(1, 1, 8, 64, 1, false, 0, 0.5 * Math.PI)
|
||||
const edgesCylinderD = new THREE.EdgesGeometry(CylinderD, 3)
|
||||
const edgesMaterial = new THREE.LineBasicMaterial({
|
||||
color: '#363636'
|
||||
})
|
||||
|
||||
const cube1 = new THREE.Mesh(cubeC, cubeMaterialRIGHT)
|
||||
cube1.position.y = 2.5
|
||||
cube1.rotation.y = Math.PI
|
||||
cube1.name = 'RIGHT'
|
||||
cubeScene.add(cube1)
|
||||
|
||||
const cube2 = new THREE.Mesh(cubeC, cubeMaterialLEFT)// BOTTOM
|
||||
cube2.position.y = -2.5
|
||||
cube2.name = 'LEFT'
|
||||
cubeScene.add(cube2)
|
||||
|
||||
const cube3 = new THREE.Mesh(cubeC, cubeMaterialFRONT)// BACK
|
||||
cube3.position.x = 2.5
|
||||
cube3.rotation.z = 0.5 * Math.PI
|
||||
cube3.name = 'FRONT'
|
||||
cubeScene.add(cube3)
|
||||
|
||||
const cube4 = new THREE.Mesh(cubeC, cubeMaterialTOP)// LEFT
|
||||
cube4.position.z = 2.5
|
||||
cube4.rotation.x = 0.5 * Math.PI
|
||||
cube4.name = 'TOP'
|
||||
cubeScene.add(cube4)
|
||||
|
||||
const cube5 = new THREE.Mesh(cubeC, cubeMaterialBACK)// FRONT
|
||||
cube5.position.x = -2.5
|
||||
cube5.rotation.z = 0.5 * Math.PI
|
||||
cube5.rotation.x = -Math.PI
|
||||
cube5.name = 'BACK'
|
||||
cubeScene.add(cube5)
|
||||
|
||||
const cube6 = new THREE.Mesh(cubeC, cubeMaterialBOTTOM)
|
||||
cube6.position.z = -2.5
|
||||
cube6.rotation.x = -0.5 * Math.PI
|
||||
cube6.name = 'BOTTOM'
|
||||
cubeScene.add(cube6)
|
||||
|
||||
const cube7 = new THREE.Mesh(CylinderB, cubeMaterial.clone())
|
||||
cube7.position.x = 4
|
||||
cube7.position.z = 4
|
||||
cube7.name = 'TOP-FRONT'
|
||||
const line7 = new THREE.LineSegments(edgesCylinderB, edgesMaterial)
|
||||
cube7.add(line7)
|
||||
cubeScene.add(cube7)
|
||||
|
||||
const cube8 = new THREE.Mesh(CylinderB, cubeMaterial.clone())
|
||||
cube8.position.x = -4
|
||||
cube8.position.z = -4
|
||||
cube8.rotation.y = Math.PI
|
||||
cube8.name = 'BACK-BOTTOM'
|
||||
const line8 = new THREE.LineSegments(edgesCylinderB, edgesMaterial)
|
||||
cube8.add(line8)
|
||||
cubeScene.add(cube8)
|
||||
|
||||
const cube9 = new THREE.Mesh(CylinderB, cubeMaterial.clone())
|
||||
cube9.position.x = 4
|
||||
cube9.position.z = -4
|
||||
cube9.rotation.y = 0.5 * Math.PI
|
||||
cube9.name = 'FRONT-BOTTOM'
|
||||
const line9 = new THREE.LineSegments(edgesCylinderB, edgesMaterial)
|
||||
cube9.add(line9)
|
||||
cubeScene.add(cube9)
|
||||
|
||||
const cube10 = new THREE.Mesh(CylinderB, cubeMaterial.clone())
|
||||
cube10.position.x = -4
|
||||
cube10.position.z = 4
|
||||
cube10.rotation.y = -0.5 * Math.PI
|
||||
cube10.name = 'TOP-BACK'
|
||||
const line10 = new THREE.LineSegments(edgesCylinderB, edgesMaterial)
|
||||
cube10.add(line10)
|
||||
cubeScene.add(cube10)
|
||||
|
||||
const cube11 = new THREE.Mesh(CylinderD, cubeMaterial.clone())
|
||||
cube11.position.x = 4
|
||||
cube11.position.y = 4
|
||||
cube11.rotation.z = 0.5 * Math.PI
|
||||
cube11.rotation.y = 0.5 * Math.PI
|
||||
cube11.name = 'RIGHT-FRONT'
|
||||
const line11 = new THREE.LineSegments(edgesCylinderD, edgesMaterial)
|
||||
cube11.add(line11)
|
||||
cubeScene.add(cube11)
|
||||
|
||||
const cube12 = new THREE.Mesh(CylinderD, cubeMaterial.clone())
|
||||
cube12.position.x = -4
|
||||
cube12.position.y = 4
|
||||
cube12.rotation.z = 0.5 * Math.PI
|
||||
cube12.rotation.y = -0.5 * Math.PI
|
||||
cube12.name = 'BACK-RIGHT'
|
||||
const line12 = new THREE.LineSegments(edgesCylinderD, edgesMaterial)
|
||||
cube12.add(line12)
|
||||
cubeScene.add(cube12)
|
||||
|
||||
const cube13 = new THREE.Mesh(CylinderD, cubeMaterial.clone())
|
||||
cube13.position.x = -4
|
||||
cube13.position.y = -4
|
||||
cube13.rotation.z = -0.5 * Math.PI
|
||||
cube13.rotation.y = -0.5 * Math.PI
|
||||
cube13.name = 'BACK-LEFT'
|
||||
const line13 = new THREE.LineSegments(edgesCylinderD, edgesMaterial)
|
||||
cube13.add(line13)
|
||||
cubeScene.add(cube13)
|
||||
|
||||
const cube14 = new THREE.Mesh(CylinderD, cubeMaterial.clone())
|
||||
cube14.position.x = 4
|
||||
cube14.position.y = -4
|
||||
cube14.rotation.z = -0.5 * Math.PI
|
||||
cube14.rotation.y = 0.5 * Math.PI
|
||||
cube14.name = 'FRONT-LEFT'
|
||||
const line14 = new THREE.LineSegments(edgesCylinderD, edgesMaterial)
|
||||
cube14.add(line14)
|
||||
cubeScene.add(cube14)
|
||||
|
||||
const cube15 = new THREE.Mesh(CylinderD, cubeMaterial.clone())
|
||||
cube15.position.z = 4
|
||||
cube15.position.y = 4
|
||||
cube15.rotation.x = -0.5 * Math.PI
|
||||
cube15.rotation.z = -0.5 * Math.PI
|
||||
cube15.name = 'TOP-RIGHT'
|
||||
const line15 = new THREE.LineSegments(edgesCylinderD, edgesMaterial)
|
||||
cube15.add(line15)
|
||||
cubeScene.add(cube15)
|
||||
|
||||
const cube16 = new THREE.Mesh(CylinderD, cubeMaterial.clone())
|
||||
cube16.position.z = -4
|
||||
cube16.position.y = 4
|
||||
cube16.rotation.x = -0.5 * Math.PI
|
||||
cube16.rotation.z = 0.5 * Math.PI
|
||||
cube16.name = 'RIGHT-BOTTOM'
|
||||
const line16 = new THREE.LineSegments(edgesCylinderD, edgesMaterial)
|
||||
cube16.add(line16)
|
||||
cubeScene.add(cube16)
|
||||
|
||||
const cube17 = new THREE.Mesh(CylinderD, cubeMaterial.clone())
|
||||
cube17.position.z = -4
|
||||
cube17.position.y = -4
|
||||
cube17.rotation.z = -0.5 * Math.PI
|
||||
cube17.rotation.x = 0.5 * Math.PI
|
||||
cube17.name = 'LEFT-BOTTOM'
|
||||
const line17 = new THREE.LineSegments(edgesCylinderD, edgesMaterial)
|
||||
cube17.add(line17)
|
||||
cubeScene.add(cube17)
|
||||
|
||||
const cube18 = new THREE.Mesh(CylinderD, cubeMaterial.clone())
|
||||
cube18.position.z = 4
|
||||
cube18.position.y = -4
|
||||
cube18.rotation.z = -0.5 * Math.PI
|
||||
cube18.name = 'TOP-LEFT'
|
||||
const line18 = new THREE.LineSegments(edgesCylinderD, edgesMaterial)
|
||||
cube18.add(line18)
|
||||
cubeScene.add(cube18)
|
||||
|
||||
const cube19 = new THREE.Mesh(SphereA, cubeMaterial.clone())
|
||||
cube19.position.x = 4
|
||||
cube19.position.y = 4
|
||||
cube19.position.z = 4
|
||||
cube19.rotation.z = -0.5 * Math.PI
|
||||
cube19.name = 'TOP-RIGHT-FRONT'
|
||||
const line19 = new THREE.LineSegments(edgesSphereA, edgesMaterial)
|
||||
cube19.add(line19)
|
||||
cubeScene.add(cube19)
|
||||
|
||||
const cube20 = new THREE.Mesh(SphereA, cubeMaterial.clone())
|
||||
cube20.position.x = 4
|
||||
cube20.position.y = 4
|
||||
cube20.position.z = -4
|
||||
cube20.rotation.z = -0.5 * Math.PI
|
||||
cube20.rotation.y = 0.5 * Math.PI
|
||||
cube20.name = 'FRONT-BOTTOM-RIGHT'
|
||||
const line20 = new THREE.LineSegments(edgesSphereA, edgesMaterial)
|
||||
cube20.add(line20)
|
||||
cubeScene.add(cube20)
|
||||
|
||||
const cube21 = new THREE.Mesh(SphereA, cubeMaterial.clone())
|
||||
cube21.position.x = -4
|
||||
cube21.position.y = 4
|
||||
cube21.position.z = -4
|
||||
cube21.rotation.y = -0.5 * Math.PI
|
||||
cube21.name = 'BACK-RIGHT-BOTTOM'
|
||||
const line21 = new THREE.LineSegments(edgesSphereA, edgesMaterial)
|
||||
cube21.add(line21)
|
||||
cubeScene.add(cube21)
|
||||
|
||||
const cube22 = new THREE.Mesh(SphereA, cubeMaterial.clone())
|
||||
cube22.position.x = -4
|
||||
cube22.position.y = 4
|
||||
cube22.position.z = 4
|
||||
cube22.name = 'TOP-RIGHT-BACK'
|
||||
const line22 = new THREE.LineSegments(edgesSphereA, edgesMaterial)
|
||||
cube22.add(line22)
|
||||
cubeScene.add(cube22)
|
||||
|
||||
const cube23 = new THREE.Mesh(SphereA, cubeMaterial.clone())
|
||||
cube23.position.x = -4
|
||||
cube23.position.y = -4
|
||||
cube23.position.z = -4
|
||||
cube23.rotation.y = -0.5 * Math.PI
|
||||
cube23.rotation.x = -0.5 * Math.PI
|
||||
cube23.name = 'BACK-BOTTOM-LEFT'
|
||||
const line23 = new THREE.LineSegments(edgesSphereA, edgesMaterial)
|
||||
cube23.add(line23)
|
||||
cubeScene.add(cube23)
|
||||
|
||||
const cube24 = new THREE.Mesh(SphereA, cubeMaterial.clone())
|
||||
cube24.position.x = 4
|
||||
cube24.position.y = -4
|
||||
cube24.position.z = -4
|
||||
cube24.rotation.y = Math.PI
|
||||
cube24.rotation.x = -0.5 * Math.PI
|
||||
cube24.name = 'FRONT-BOTTOM-LEFT'
|
||||
const line24 = new THREE.LineSegments(edgesSphereA, edgesMaterial)
|
||||
cube24.add(line24)
|
||||
cubeScene.add(cube24)
|
||||
|
||||
const cube25 = new THREE.Mesh(SphereA, cubeMaterial.clone())
|
||||
cube25.position.x = 4
|
||||
cube25.position.y = -4
|
||||
cube25.position.z = 4
|
||||
cube25.rotation.y = 0.5 * Math.PI
|
||||
cube25.rotation.x = 0.5 * Math.PI
|
||||
cube25.name = 'TOP-LEFT-FRONT'
|
||||
const line25 = new THREE.LineSegments(edgesSphereA, edgesMaterial)
|
||||
cube25.add(line25)
|
||||
cubeScene.add(cube25)
|
||||
|
||||
const cube26 = new THREE.Mesh(SphereA, cubeMaterial.clone())
|
||||
cube26.position.x = -4
|
||||
cube26.position.y = -4
|
||||
cube26.position.z = 4
|
||||
cube26.rotation.x = 0.5 * Math.PI
|
||||
cube26.name = 'TOP-LEFT-BACK'
|
||||
const line26 = new THREE.LineSegments(edgesSphereA, edgesMaterial)
|
||||
cube26.add(line26)
|
||||
cubeScene.add(cube26)
|
||||
}
|
||||
function getTextCanvas(text) {
|
||||
const width = 64
|
||||
const height = 64
|
||||
const canvas = document.createElement('canvas')
|
||||
canvas.width = width
|
||||
canvas.height = height
|
||||
const ctx = canvas.getContext('2d')
|
||||
ctx.fillStyle = '#8d8d8d'
|
||||
ctx.fillRect(0, 0, width, height)
|
||||
ctx.font = 'bolder 14px "Open sans", Arial'
|
||||
ctx.fillStyle = '#000000'
|
||||
ctx.textAlign = 'center'
|
||||
ctx.textBaseline = 'middle'
|
||||
ctx.fillText(text, width / 2, height / 2)
|
||||
return canvas
|
||||
}
|
||||
function getIntersects(event) {
|
||||
event.preventDefault()
|
||||
// 声明 raycaster 和 mouse 变量
|
||||
const raycaster = new THREE.Raycaster()
|
||||
// 通过鼠标点击位置,计算出 raycaster 所需点的位置,以屏幕为中心点,范围 -1 到 1
|
||||
const x = event.offsetX
|
||||
const y = event.offsetY
|
||||
const size = cubeRenderer.getSize(new THREE.Vector2())
|
||||
const mouse = new THREE.Vector2(x / size.width * 2 - 1, -y / size.height * 2 + 1)
|
||||
|
||||
raycaster.setFromCamera(mouse, cubeCamera)
|
||||
// 获取与射线相交的对象数组,其中的元素按照距离排序,越近的越靠前
|
||||
return raycaster.intersectObjects(cubeScene.children)
|
||||
}
|
||||
}
|
||||
|
||||
export { viewCubeUpdate, Viewer }
|
||||
1383
src/components/DMT/libs/PlacementController.js
Normal file
1409
src/components/DMT/libs/PlacementControllerCraft.js
Normal file
1403
src/components/DMT/libs/PlacementControllerModelLabel.js
Normal file
452
src/components/DMT/libs/ViewCube.js
Normal file
@@ -0,0 +1,452 @@
|
||||
import * as THREE from 'three'
|
||||
|
||||
let viewCubeUpdate = null
|
||||
|
||||
const Viewer = function Viewer(editor) {
|
||||
const cameraPosition = editor.cameraPosition
|
||||
const ViewerDiv = document.createElement('div')
|
||||
ViewerDiv.id = 'orientCubeWrapperDiv'
|
||||
ViewerDiv.style.position = 'absolute'
|
||||
ViewerDiv.style.left = '10px'
|
||||
ViewerDiv.style.bottom = '10px'
|
||||
ViewerDiv.style.display = 'flex'
|
||||
ViewerDiv.style.backgroundColor = 'transparent'
|
||||
ViewerDiv.style.width = '180px'
|
||||
ViewerDiv.style.height = '180px'
|
||||
ViewerDiv.style.zIndex = '999'
|
||||
|
||||
const ViewerUI = document.createElement('div')
|
||||
ViewerUI.id = 'orientCubeWrapper'
|
||||
ViewerUI.style.width = '180px'
|
||||
ViewerUI.style.height = ' 180px'
|
||||
ViewerUI.style.opacity = ' 0.7'
|
||||
ViewerUI.style.transition = ' opacity 0.3s'
|
||||
|
||||
ViewerDiv.appendChild(ViewerUI)
|
||||
document.body.appendChild(ViewerDiv)
|
||||
|
||||
const dirAxis = {
|
||||
'TOP': [0, 0, editor.cameraPosition, 0, 0, 0],
|
||||
'BOTTOM': [0, 0, -editor.cameraPosition, 0, 0, 0],
|
||||
'FRONT': [editor.cameraPosition, 0, 0, 0, 0, 0],
|
||||
'BACK': [-editor.cameraPosition, 0, 0, 0, 0, 0],
|
||||
'LEFT': [0, -editor.cameraPosition, 0, 0, 0, 0],
|
||||
'RIGHT': [0, editor.cameraPosition, 0, 0, 0, 0],
|
||||
|
||||
'BACK-LEFT': [-editor.cameraPosition, -editor.cameraPosition, 0, 0, 0, 0],
|
||||
'FRONT-LEFT': [editor.cameraPosition, -editor.cameraPosition, 0, 0, 0, 0],
|
||||
'TOP-LEFT': [0, -editor.cameraPosition, editor.cameraPosition, 0, 0, 0],
|
||||
'TOP-RIGHT': [0, editor.cameraPosition, editor.cameraPosition, 0, 0, 0],
|
||||
'RIGHT-BOTTOM': [0, editor.cameraPosition, -editor.cameraPosition, 0, 0, 0],
|
||||
'LEFT-BOTTOM': [0, -editor.cameraPosition, -editor.cameraPosition, 0, 0, 0],
|
||||
'BACK-BOTTOM': [-editor.cameraPosition, 0, -editor.cameraPosition, 0, 0, 0],
|
||||
'TOP-FRONT': [editor.cameraPosition, 0, editor.cameraPosition, 0, 0, 0], //
|
||||
'FRONT-BOTTOM': [editor.cameraPosition, 0, -editor.cameraPosition, 0, 0, 0],
|
||||
'TOP-BACK': [-editor.cameraPosition, 0, editor.cameraPosition, 0, 0, 0],
|
||||
'RIGHT-FRONT': [editor.cameraPosition, editor.cameraPosition, 0, 0, 0, 0],
|
||||
'BACK-RIGHT': [-editor.cameraPosition, editor.cameraPosition, 0, 0, 0, 0],
|
||||
|
||||
'BACK-RIGHT-BOTTOM': [-editor.cameraPosition, editor.cameraPosition, -cameraPosition, 0, 0, 0],
|
||||
'TOP-RIGHT-BACK': [-editor.cameraPosition, editor.cameraPosition, editor.cameraPosition, 0, 0, 0],
|
||||
'TOP-LEFT-BACK': [-editor.cameraPosition, -editor.cameraPosition, editor.cameraPosition, 0, 0, 0],
|
||||
'TOP-LEFT-FRONT': [editor.cameraPosition, -editor.cameraPosition, editor.cameraPosition, 0, 0, 0],
|
||||
'FRONT-BOTTOM-RIGHT': [editor.cameraPosition, editor.cameraPosition, -editor.cameraPosition, 0, 0, 0],
|
||||
'TOP-RIGHT-FRONT': [editor.cameraPosition, editor.cameraPosition, editor.cameraPosition, 0, 0, 0],
|
||||
'BACK-BOTTOM-LEFT': [-editor.cameraPosition, -editor.cameraPosition, -editor.cameraPosition, 0, 0, 0],
|
||||
'FRONT-BOTTOM-LEFT': [editor.cameraPosition, -editor.cameraPosition, -editor.cameraPosition, 0, 0, 0]
|
||||
}
|
||||
const cubeCameraDistance = 5
|
||||
const controlsViewer = editor.cameraControls
|
||||
const cubeWrapper = ViewerUI
|
||||
|
||||
const cubeScene = new THREE.Scene()
|
||||
const cubeRenderer = new THREE.WebGLRenderer({
|
||||
alpha: true,
|
||||
antialias: true,
|
||||
preserveDrawingBuffer: true
|
||||
})
|
||||
const cubeCamera = new THREE.PerspectiveCamera(50, cubeWrapper.offsetWidth / cubeWrapper.offsetHeight, 0.1, 100)
|
||||
cubeRenderer.setSize(cubeWrapper.offsetWidth, cubeWrapper.offsetHeight)
|
||||
cubeWrapper.appendChild(cubeRenderer.domElement)
|
||||
cubeScene.add(cubeCamera)
|
||||
cubeCamera.position.set(2, 2, 2)
|
||||
createArrow(new THREE.Vector3(5, 0, 0), new THREE.Vector3(-5, -5, -5), 13, 0xFF0000, 'X')// x
|
||||
createArrow(new THREE.Vector3(0, 0, 5), new THREE.Vector3(-5, -5, -5), 13, 0x0000FF, 'Z')// z
|
||||
createArrow(new THREE.Vector3(0, 5, 0), new THREE.Vector3(-5, -5, -5), 13, 0x008000, 'Y')// y
|
||||
cubeScene.add(new THREE.AmbientLight(0xffffff))
|
||||
initModel()
|
||||
let activeObject
|
||||
cubeRenderer.domElement.onmousemove = (event) => {
|
||||
const intersects = getIntersects(event)
|
||||
if (intersects.length !== 0) {
|
||||
const res = intersects.filter(function(res) {
|
||||
return res && res.object.name !== '' && res.object instanceof THREE.Mesh
|
||||
})[0]
|
||||
if (res && res.object) {
|
||||
if (activeObject) {
|
||||
if (activeObject.name === res.object.name) {
|
||||
activeObject.material.color.set('#6ad0f8')
|
||||
return
|
||||
} else {
|
||||
activeObject.material.color.set('#00c0ff')
|
||||
activeObject = null
|
||||
}
|
||||
}
|
||||
activeObject = res.object
|
||||
activeObject.material.color.set('#6ad0f8')
|
||||
}
|
||||
} else {
|
||||
if (activeObject) {
|
||||
activeObject.material.color.set('#00c0ff')
|
||||
activeObject = null
|
||||
}
|
||||
}
|
||||
}
|
||||
cubeRenderer.domElement.onclick = () => {
|
||||
if (!activeObject) return
|
||||
if (activeObject.name && dirAxis[activeObject.name]) {
|
||||
editor.cameraControls.setLookAt(dirAxis[activeObject.name][0],
|
||||
dirAxis[activeObject.name][1],
|
||||
dirAxis[activeObject.name][2],
|
||||
0, 0, 0, true)
|
||||
editor.cameraControls.moveTo(editor.cameraControls._target.x, editor.cameraControls._target.y, editor.cameraControls._target.z, true)
|
||||
editor.camera.updateProjectionMatrix()
|
||||
editor.camera.clearViewOffset()
|
||||
updateCubeCamera()
|
||||
}
|
||||
}
|
||||
function updateCubeCamera() {
|
||||
cubeRenderer.render(cubeScene, cubeCamera)
|
||||
cubeCamera.rotation.copy(editor.camera.rotation)
|
||||
const dir = editor.camera.position.clone().sub(controlsViewer._target).normalize()
|
||||
dir.multiplyScalar(cubeCameraDistance)
|
||||
cubeCamera.position.copy(dir.multiplyScalar(cubeCameraDistance))
|
||||
}
|
||||
viewCubeUpdate = updateCubeCamera
|
||||
function createArrow(dir, origin, length = 1, color = '0xffff00', text = '') {
|
||||
// normalize the direction vector (convert to vector of length 1)
|
||||
dir.normalize()
|
||||
const arrowHelper = new THREE.ArrowHelper(dir, origin, length, color)
|
||||
cubeScene.add(arrowHelper)
|
||||
}
|
||||
function initModel() {
|
||||
const cubeMaterialRIGHT = new THREE.MeshLambertMaterial({
|
||||
color: 0x00c0ff,
|
||||
opacity: 1,
|
||||
map: new THREE.CanvasTexture(getTextCanvas('RIGHT')),
|
||||
side: THREE.DoubleSide
|
||||
})
|
||||
const cubeMaterialLEFT = new THREE.MeshLambertMaterial({
|
||||
color: 0x00c0ff,
|
||||
opacity: 1,
|
||||
map: new THREE.CanvasTexture(getTextCanvas('LEFT')), // BOTTOM
|
||||
side: THREE.DoubleSide
|
||||
})
|
||||
const cubeMaterialFRONT = new THREE.MeshLambertMaterial({
|
||||
color: 0x00c0ff,
|
||||
opacity: 1,
|
||||
map: new THREE.CanvasTexture(getTextCanvas('FRONT')),
|
||||
side: THREE.DoubleSide
|
||||
})
|
||||
const cubeMaterialBACK = new THREE.MeshLambertMaterial({
|
||||
color: 0x00c0ff,
|
||||
opacity: 1,
|
||||
map: new THREE.CanvasTexture(getTextCanvas('BACK')),
|
||||
side: THREE.DoubleSide
|
||||
})
|
||||
const cubeMaterialBOTTOM = new THREE.MeshLambertMaterial({
|
||||
color: 0x00c0ff,
|
||||
opacity: 1,
|
||||
map: new THREE.CanvasTexture(getTextCanvas('BOTTOM')),
|
||||
side: THREE.DoubleSide
|
||||
})
|
||||
const cubeMaterialTOP = new THREE.MeshLambertMaterial({
|
||||
color: 0x00c0ff,
|
||||
opacity: 1,
|
||||
map: new THREE.CanvasTexture(getTextCanvas('TOP')), // LEFT
|
||||
side: THREE.DoubleSide
|
||||
})
|
||||
const cubeMaterial = new THREE.MeshLambertMaterial({
|
||||
color: 0x00c0ff,
|
||||
opacity: 1,
|
||||
map: new THREE.CanvasTexture(getTextCanvas('')),
|
||||
side: THREE.DoubleSide
|
||||
})
|
||||
|
||||
const SphereA = new THREE.SphereGeometry(1, 32, 32, 0, 0.5 * Math.PI, 0, 0.5 * Math.PI)
|
||||
const edgesSphereA = new THREE.EdgesGeometry(SphereA, 3)
|
||||
const CylinderB = new THREE.CylinderGeometry(1, 1, 8, 64, 1, false, 0, 0.5 * Math.PI)
|
||||
const edgesCylinderB = new THREE.EdgesGeometry(CylinderB, 3)
|
||||
const cubeC = new THREE.BoxGeometry(7.99, 4.99, 7.99)
|
||||
const CylinderD = new THREE.CylinderGeometry(1, 1, 8, 64, 1, false, 0, 0.5 * Math.PI)
|
||||
const edgesCylinderD = new THREE.EdgesGeometry(CylinderD, 3)
|
||||
const edgesMaterial = new THREE.LineBasicMaterial({
|
||||
color: '#363636'
|
||||
})
|
||||
|
||||
const cube1 = new THREE.Mesh(cubeC, cubeMaterialRIGHT)
|
||||
cube1.position.y = 2.5
|
||||
cube1.rotation.y = Math.PI
|
||||
cube1.name = 'RIGHT'
|
||||
cubeScene.add(cube1)
|
||||
|
||||
const cube2 = new THREE.Mesh(cubeC, cubeMaterialLEFT)// BOTTOM
|
||||
cube2.position.y = -2.5
|
||||
cube2.name = 'LEFT'
|
||||
cubeScene.add(cube2)
|
||||
|
||||
const cube3 = new THREE.Mesh(cubeC, cubeMaterialFRONT)// BACK
|
||||
cube3.position.x = 2.5
|
||||
cube3.rotation.z = 0.5 * Math.PI
|
||||
cube3.name = 'FRONT'
|
||||
cubeScene.add(cube3)
|
||||
|
||||
const cube4 = new THREE.Mesh(cubeC, cubeMaterialTOP)// LEFT
|
||||
cube4.position.z = 2.5
|
||||
cube4.rotation.x = 0.5 * Math.PI
|
||||
cube4.name = 'TOP'
|
||||
cubeScene.add(cube4)
|
||||
|
||||
const cube5 = new THREE.Mesh(cubeC, cubeMaterialBACK)// FRONT
|
||||
cube5.position.x = -2.5
|
||||
cube5.rotation.z = 0.5 * Math.PI
|
||||
cube5.rotation.x = -Math.PI
|
||||
cube5.name = 'BACK'
|
||||
cubeScene.add(cube5)
|
||||
|
||||
const cube6 = new THREE.Mesh(cubeC, cubeMaterialBOTTOM)
|
||||
cube6.position.z = -2.5
|
||||
cube6.rotation.x = -0.5 * Math.PI
|
||||
cube6.name = 'BOTTOM'
|
||||
cubeScene.add(cube6)
|
||||
|
||||
const cube7 = new THREE.Mesh(CylinderB, cubeMaterial.clone())
|
||||
cube7.position.x = 4
|
||||
cube7.position.z = 4
|
||||
cube7.name = 'TOP-FRONT'
|
||||
const line7 = new THREE.LineSegments(edgesCylinderB, edgesMaterial)
|
||||
cube7.add(line7)
|
||||
cubeScene.add(cube7)
|
||||
|
||||
const cube8 = new THREE.Mesh(CylinderB, cubeMaterial.clone())
|
||||
cube8.position.x = -4
|
||||
cube8.position.z = -4
|
||||
cube8.rotation.y = Math.PI
|
||||
cube8.name = 'BACK-BOTTOM'
|
||||
const line8 = new THREE.LineSegments(edgesCylinderB, edgesMaterial)
|
||||
cube8.add(line8)
|
||||
cubeScene.add(cube8)
|
||||
|
||||
const cube9 = new THREE.Mesh(CylinderB, cubeMaterial.clone())
|
||||
cube9.position.x = 4
|
||||
cube9.position.z = -4
|
||||
cube9.rotation.y = 0.5 * Math.PI
|
||||
cube9.name = 'FRONT-BOTTOM'
|
||||
const line9 = new THREE.LineSegments(edgesCylinderB, edgesMaterial)
|
||||
cube9.add(line9)
|
||||
cubeScene.add(cube9)
|
||||
|
||||
const cube10 = new THREE.Mesh(CylinderB, cubeMaterial.clone())
|
||||
cube10.position.x = -4
|
||||
cube10.position.z = 4
|
||||
cube10.rotation.y = -0.5 * Math.PI
|
||||
cube10.name = 'TOP-BACK'
|
||||
const line10 = new THREE.LineSegments(edgesCylinderB, edgesMaterial)
|
||||
cube10.add(line10)
|
||||
cubeScene.add(cube10)
|
||||
|
||||
const cube11 = new THREE.Mesh(CylinderD, cubeMaterial.clone())
|
||||
cube11.position.x = 4
|
||||
cube11.position.y = 4
|
||||
cube11.rotation.z = 0.5 * Math.PI
|
||||
cube11.rotation.y = 0.5 * Math.PI
|
||||
cube11.name = 'RIGHT-FRONT'
|
||||
const line11 = new THREE.LineSegments(edgesCylinderD, edgesMaterial)
|
||||
cube11.add(line11)
|
||||
cubeScene.add(cube11)
|
||||
|
||||
const cube12 = new THREE.Mesh(CylinderD, cubeMaterial.clone())
|
||||
cube12.position.x = -4
|
||||
cube12.position.y = 4
|
||||
cube12.rotation.z = 0.5 * Math.PI
|
||||
cube12.rotation.y = -0.5 * Math.PI
|
||||
cube12.name = 'BACK-RIGHT'
|
||||
const line12 = new THREE.LineSegments(edgesCylinderD, edgesMaterial)
|
||||
cube12.add(line12)
|
||||
cubeScene.add(cube12)
|
||||
|
||||
const cube13 = new THREE.Mesh(CylinderD, cubeMaterial.clone())
|
||||
cube13.position.x = -4
|
||||
cube13.position.y = -4
|
||||
cube13.rotation.z = -0.5 * Math.PI
|
||||
cube13.rotation.y = -0.5 * Math.PI
|
||||
cube13.name = 'BACK-LEFT'
|
||||
const line13 = new THREE.LineSegments(edgesCylinderD, edgesMaterial)
|
||||
cube13.add(line13)
|
||||
cubeScene.add(cube13)
|
||||
|
||||
const cube14 = new THREE.Mesh(CylinderD, cubeMaterial.clone())
|
||||
cube14.position.x = 4
|
||||
cube14.position.y = -4
|
||||
cube14.rotation.z = -0.5 * Math.PI
|
||||
cube14.rotation.y = 0.5 * Math.PI
|
||||
cube14.name = 'FRONT-LEFT'
|
||||
const line14 = new THREE.LineSegments(edgesCylinderD, edgesMaterial)
|
||||
cube14.add(line14)
|
||||
cubeScene.add(cube14)
|
||||
|
||||
const cube15 = new THREE.Mesh(CylinderD, cubeMaterial.clone())
|
||||
cube15.position.z = 4
|
||||
cube15.position.y = 4
|
||||
cube15.rotation.x = -0.5 * Math.PI
|
||||
cube15.rotation.z = -0.5 * Math.PI
|
||||
cube15.name = 'TOP-RIGHT'
|
||||
const line15 = new THREE.LineSegments(edgesCylinderD, edgesMaterial)
|
||||
cube15.add(line15)
|
||||
cubeScene.add(cube15)
|
||||
|
||||
const cube16 = new THREE.Mesh(CylinderD, cubeMaterial.clone())
|
||||
cube16.position.z = -4
|
||||
cube16.position.y = 4
|
||||
cube16.rotation.x = -0.5 * Math.PI
|
||||
cube16.rotation.z = 0.5 * Math.PI
|
||||
cube16.name = 'RIGHT-BOTTOM'
|
||||
const line16 = new THREE.LineSegments(edgesCylinderD, edgesMaterial)
|
||||
cube16.add(line16)
|
||||
cubeScene.add(cube16)
|
||||
|
||||
const cube17 = new THREE.Mesh(CylinderD, cubeMaterial.clone())
|
||||
cube17.position.z = -4
|
||||
cube17.position.y = -4
|
||||
cube17.rotation.z = -0.5 * Math.PI
|
||||
cube17.rotation.x = 0.5 * Math.PI
|
||||
cube17.name = 'LEFT-BOTTOM'
|
||||
const line17 = new THREE.LineSegments(edgesCylinderD, edgesMaterial)
|
||||
cube17.add(line17)
|
||||
cubeScene.add(cube17)
|
||||
|
||||
const cube18 = new THREE.Mesh(CylinderD, cubeMaterial.clone())
|
||||
cube18.position.z = 4
|
||||
cube18.position.y = -4
|
||||
cube18.rotation.z = -0.5 * Math.PI
|
||||
cube18.name = 'TOP-LEFT'
|
||||
const line18 = new THREE.LineSegments(edgesCylinderD, edgesMaterial)
|
||||
cube18.add(line18)
|
||||
cubeScene.add(cube18)
|
||||
|
||||
const cube19 = new THREE.Mesh(SphereA, cubeMaterial.clone())
|
||||
cube19.position.x = 4
|
||||
cube19.position.y = 4
|
||||
cube19.position.z = 4
|
||||
cube19.rotation.z = -0.5 * Math.PI
|
||||
cube19.name = 'TOP-RIGHT-FRONT'
|
||||
const line19 = new THREE.LineSegments(edgesSphereA, edgesMaterial)
|
||||
cube19.add(line19)
|
||||
cubeScene.add(cube19)
|
||||
|
||||
const cube20 = new THREE.Mesh(SphereA, cubeMaterial.clone())
|
||||
cube20.position.x = 4
|
||||
cube20.position.y = 4
|
||||
cube20.position.z = -4
|
||||
cube20.rotation.z = -0.5 * Math.PI
|
||||
cube20.rotation.y = 0.5 * Math.PI
|
||||
cube20.name = 'FRONT-BOTTOM-RIGHT'
|
||||
const line20 = new THREE.LineSegments(edgesSphereA, edgesMaterial)
|
||||
cube20.add(line20)
|
||||
cubeScene.add(cube20)
|
||||
|
||||
const cube21 = new THREE.Mesh(SphereA, cubeMaterial.clone())
|
||||
cube21.position.x = -4
|
||||
cube21.position.y = 4
|
||||
cube21.position.z = -4
|
||||
cube21.rotation.y = -0.5 * Math.PI
|
||||
cube21.name = 'BACK-RIGHT-BOTTOM'
|
||||
const line21 = new THREE.LineSegments(edgesSphereA, edgesMaterial)
|
||||
cube21.add(line21)
|
||||
cubeScene.add(cube21)
|
||||
|
||||
const cube22 = new THREE.Mesh(SphereA, cubeMaterial.clone())
|
||||
cube22.position.x = -4
|
||||
cube22.position.y = 4
|
||||
cube22.position.z = 4
|
||||
cube22.name = 'TOP-RIGHT-BACK'
|
||||
const line22 = new THREE.LineSegments(edgesSphereA, edgesMaterial)
|
||||
cube22.add(line22)
|
||||
cubeScene.add(cube22)
|
||||
|
||||
const cube23 = new THREE.Mesh(SphereA, cubeMaterial.clone())
|
||||
cube23.position.x = -4
|
||||
cube23.position.y = -4
|
||||
cube23.position.z = -4
|
||||
cube23.rotation.y = -0.5 * Math.PI
|
||||
cube23.rotation.x = -0.5 * Math.PI
|
||||
cube23.name = 'BACK-BOTTOM-LEFT'
|
||||
const line23 = new THREE.LineSegments(edgesSphereA, edgesMaterial)
|
||||
cube23.add(line23)
|
||||
cubeScene.add(cube23)
|
||||
|
||||
const cube24 = new THREE.Mesh(SphereA, cubeMaterial.clone())
|
||||
cube24.position.x = 4
|
||||
cube24.position.y = -4
|
||||
cube24.position.z = -4
|
||||
cube24.rotation.y = Math.PI
|
||||
cube24.rotation.x = -0.5 * Math.PI
|
||||
cube24.name = 'FRONT-BOTTOM-LEFT'
|
||||
const line24 = new THREE.LineSegments(edgesSphereA, edgesMaterial)
|
||||
cube24.add(line24)
|
||||
cubeScene.add(cube24)
|
||||
|
||||
const cube25 = new THREE.Mesh(SphereA, cubeMaterial.clone())
|
||||
cube25.position.x = 4
|
||||
cube25.position.y = -4
|
||||
cube25.position.z = 4
|
||||
cube25.rotation.y = 0.5 * Math.PI
|
||||
cube25.rotation.x = 0.5 * Math.PI
|
||||
cube25.name = 'TOP-LEFT-FRONT'
|
||||
const line25 = new THREE.LineSegments(edgesSphereA, edgesMaterial)
|
||||
cube25.add(line25)
|
||||
cubeScene.add(cube25)
|
||||
|
||||
const cube26 = new THREE.Mesh(SphereA, cubeMaterial.clone())
|
||||
cube26.position.x = -4
|
||||
cube26.position.y = -4
|
||||
cube26.position.z = 4
|
||||
cube26.rotation.x = 0.5 * Math.PI
|
||||
cube26.name = 'TOP-LEFT-BACK'
|
||||
const line26 = new THREE.LineSegments(edgesSphereA, edgesMaterial)
|
||||
cube26.add(line26)
|
||||
cubeScene.add(cube26)
|
||||
}
|
||||
function getTextCanvas(text) {
|
||||
const width = 64
|
||||
const height = 64
|
||||
const canvas = document.createElement('canvas')
|
||||
canvas.width = width
|
||||
canvas.height = height
|
||||
const ctx = canvas.getContext('2d')
|
||||
ctx.fillStyle = '#8d8d8d'
|
||||
ctx.fillRect(0, 0, width, height)
|
||||
ctx.font = 'bolder 14px "Open sans", Arial'
|
||||
ctx.fillStyle = '#000000'
|
||||
ctx.textAlign = 'center'
|
||||
ctx.textBaseline = 'middle'
|
||||
ctx.fillText(text, width / 2, height / 2)
|
||||
return canvas
|
||||
}
|
||||
function getIntersects(event) {
|
||||
event.preventDefault()
|
||||
// 声明 raycaster 和 mouse 变量
|
||||
const raycaster = new THREE.Raycaster()
|
||||
// 通过鼠标点击位置,计算出 raycaster 所需点的位置,以屏幕为中心点,范围 -1 到 1
|
||||
const x = event.offsetX
|
||||
const y = event.offsetY
|
||||
const size = cubeRenderer.getSize(new THREE.Vector2())
|
||||
const mouse = new THREE.Vector2(x / size.width * 2 - 1, -y / size.height * 2 + 1)
|
||||
|
||||
raycaster.setFromCamera(mouse, cubeCamera)
|
||||
// 获取与射线相交的对象数组,其中的元素按照距离排序,越近的越靠前
|
||||
return raycaster.intersectObjects(cubeScene.children)
|
||||
}
|
||||
}
|
||||
|
||||
export { viewCubeUpdate, Viewer }
|
||||
1166
src/components/DMT/libs/ViewCubeControls.js
Normal file
BIN
src/components/DMT/libs/alarm.mp3
Normal file
BIN
src/components/DMT/libs/bgc.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
32
src/components/DMT/libs/draco/README.md
Normal file
@@ -0,0 +1,32 @@
|
||||
# Draco 3D Data Compression
|
||||
|
||||
Draco is an open-source library for compressing and decompressing 3D geometric meshes and point clouds. It is intended to improve the storage and transmission of 3D graphics.
|
||||
|
||||
[Website](https://google.github.io/draco/) | [GitHub](https://github.com/google/draco)
|
||||
|
||||
## Contents
|
||||
|
||||
This folder contains three utilities:
|
||||
|
||||
* `draco_decoder.js` — Emscripten-compiled decoder, compatible with any modern browser.
|
||||
* `draco_decoder.wasm` — WebAssembly decoder, compatible with newer browsers and devices.
|
||||
* `draco_wasm_wrapper.js` — JavaScript wrapper for the WASM decoder.
|
||||
|
||||
Each file is provided in two variations:
|
||||
|
||||
* **Default:** Latest stable builds, tracking the project's [master branch](https://github.com/google/draco).
|
||||
* **glTF:** Builds targeted by the [glTF mesh compression extension](https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_draco_mesh_compression), tracking the [corresponding Draco branch](https://github.com/google/draco/tree/gltf_2.0_draco_extension).
|
||||
|
||||
Either variation may be used with `THREE.DRACOLoader`:
|
||||
|
||||
```js
|
||||
var dracoLoader = new THREE.DRACOLoader();
|
||||
dracoLoader.setDecoderPath('path/to/decoders/');
|
||||
dracoLoader.setDecoderConfig({type: 'js'}); // (Optional) Override detection of WASM support.
|
||||
```
|
||||
|
||||
Further [documentation on GitHub](https://github.com/google/draco/tree/master/javascript/example#static-loading-javascript-decoder).
|
||||
|
||||
## License
|
||||
|
||||
[Apache License 2.0](https://github.com/google/draco/blob/master/LICENSE)
|
||||