Browse Source

更新超欠挖点图

caner 1 year ago
parent
commit
983a207fd1
3 changed files with 112 additions and 19 deletions
  1. 11 4
      src/pages/three/index.vue
  2. 71 7
      src/pages/three/pointFace.vue
  3. 30 8
      src/pages/three/three.service.ts

+ 11 - 4
src/pages/three/index.vue

@@ -20,6 +20,7 @@
         :show-leng="tabs[checkTab].showLeng"
         :show-leng="tabs[checkTab].showLeng"
         :hole-config="tabs[checkTab].holeConfig"
         :hole-config="tabs[checkTab].holeConfig"
         :tunnel-config="tabs[checkTab].tunnelConfig"
         :tunnel-config="tabs[checkTab].tunnelConfig"
+        :map-config="tabs[checkTab].mapConfig"
       />
       />
     </div>
     </div>
   </div>
   </div>
@@ -39,7 +40,7 @@ interface Tabs {
   showLeng: boolean,
   showLeng: boolean,
   tunnelConfig?: TunnelConfig,
   tunnelConfig?: TunnelConfig,
   holeConfig: HoleConfig | undefined,
   holeConfig: HoleConfig | undefined,
-  mapConfig?: { isRotate: boolean, cameraP: { X: number, Y: number, Z: number }, }
+  mapConfig?: { isRotate?: boolean, cameraP?: { X: number, Y: number, Z: number }, contrlLeft?:boolean }
 }
 }
 const dicColor = {
 const dicColor = {
   ZBK: 5.5,
   ZBK: 5.5,
@@ -53,7 +54,7 @@ const dicColor = {
 } as any // 孔类型颜色配置需要配合3D图列颜色值
 } as any // 孔类型颜色配置需要配合3D图列颜色值
 const tabs = ref<Tabs[]>([
 const tabs = ref<Tabs[]>([
   {
   {
-    label: '单面炮孔', value: 0, showLeng: true, tunnelConfig: { show: true, type: 0 }, holeConfig: { show: 1, data: [ ...pathData as any ], position: { x: -3, y: -4, z: 0 } }
+    label: '单面炮孔', value: 0, showLeng: true, tunnelConfig: { show: true, type: 0 }, holeConfig: { show: 1, data: [ ...pathData as any ], position: { x: -3, y: -4, z: 0 } }, mapConfig: { contrlLeft: false }
   },
   },
   {
   {
     label: '无角度多组多段炮孔路径', value: 1, showLeng: true, holeConfig: { show: 2, data: [ ...pathData as any ], position: { x: -3, y: -4, z: 0 } }
     label: '无角度多组多段炮孔路径', value: 1, showLeng: true, holeConfig: { show: 2, data: [ ...pathData as any ], position: { x: -3, y: -4, z: 0 } }
@@ -74,13 +75,19 @@ const tabs = ref<Tabs[]>([
     }
     }
   },
   },
   {
   {
-    label: '单个分块掌子面', value: 4, showLeng: false, holeConfig: { show: 5, data: new Array(18).fill('green'), position: { x: -100, y: -105, z: -8 } }
+    label: '单个分块掌子面', value: 4, showLeng: false, holeConfig: { show: 5, data: new Array(18).fill('green'), position: { x: -100, y: -105, z: -8 } }, mapConfig: { contrlLeft: false }
   },
   },
   {
   {
     label: '多个分块掌子面+外轮廓', value: 5, showLeng: false, holeConfig: { show: 6, data: [ [ new Array(18).fill('green'), new Array(48).fill('red') ] ], position: { x: -3, y: -4, z: 0 } }
     label: '多个分块掌子面+外轮廓', value: 5, showLeng: false, holeConfig: { show: 6, data: [ [ new Array(18).fill('green'), new Array(48).fill('red') ] ], position: { x: -3, y: -4, z: 0 } }
   },
   },
   {
   {
-    label: '超欠挖点图', value: 6, showLeng: false, holeConfig: { show: 7, data: [ [ ...SEJ ], [ ...SIJ ] ], position: { x: 0, y: -1, z: 0 } }
+    label: '超欠挖图',
+    value: 6,
+    showLeng: false,
+    holeConfig: {
+      show: 7, data: [ [ ...SEJ ], [ ...SIJ ] ], position: { x: 0, y: -1, z: 0 }
+    },
+    mapConfig: { contrlLeft: false }
   }
   }
 ])
 ])
 const checkTab = ref(0)
 const checkTab = ref(0)

+ 71 - 7
src/pages/three/pointFace.vue

@@ -78,7 +78,8 @@ const props = withDefaults(defineProps<{
   }),
   }),
   mapConfig: () => ({
   mapConfig: () => ({
     cameraP: { X: 0, Y: 0, Z: 18 },
     cameraP: { X: 0, Y: 0, Z: 18 },
-    isRotate: true
+    isRotate: true,
+    contrlLeft: true
   })
   })
 })
 })
 const leng = [
 const leng = [
@@ -237,6 +238,66 @@ function createExceedBreakPoint(designArr: [], breakArr: [], position = { x: -2.
   return group
   return group
 }
 }
 
 
+// 创建网格坐标
+function createGridding() {
+  const geometry = new threeService.THREE.BufferGeometry() // geometry为三维空间中的点集同点集闭合后的各个面的集合
+  // 在x轴上定义两个点p1(-500,0,0),p2(500,0,0)。
+  const vertices = new Float32Array([
+    -7, 0, 0,
+    7, 0, 0
+  ])
+  geometry.setAttribute('position', new threeService.THREE.BufferAttribute(vertices, 3))
+  const group = new threeService.THREE.Group()
+  for (let i = 0; i <= 10; i++) {
+    const linex = new threeService.THREE.Line(geometry, new threeService.THREE.LineBasicMaterial({ color: '#ccc', opacity: 0.5 }))
+    linex.position.z = (i * 1.4) - 7 //   7/(10/2)
+    const liney = new threeService.THREE.Line(geometry, new threeService.THREE.LineBasicMaterial({ color: '#ccc', opacity: 0.5 }))
+    liney.position.x = (i * 1.4) - 7 // 7/(10/2)
+    liney.rotation.y = Math.PI / 2 // 将线旋转90度
+    group.add(linex, liney)
+  }
+  group.rotation.x = Math.PI / 2
+  return group
+}
+
+// 创建超欠挖线
+function createExceedBreakLine(arr: { x: number, y: number, z: number }[], color: string, position = { x: 0, y: -1.5, z: 0 }) {
+  const group = new threeService.THREE.Group()
+  const material = new threeService.THREE.LineBasicMaterial({ color })
+  const points = arr.map((el) => (new threeService.THREE.Vector3(el.x, el.y, el.z)))
+  const geometry = new threeService.THREE.BufferGeometry().setFromPoints(points)
+  const line = new threeService.THREE.Line(geometry, material)
+  group.position.set(position.x, position.y, position.z)
+  group.add(line)
+  return group
+}
+
+// 创建3D文字+对应点
+function create3DLabel(point: { x: number; y: number; z: number; txt: string; r: number; c: string }[], position = { x: 0, y: -1.5, z: 0 }, size = 1.2, showPoint = true) {
+  const group = new threeService.THREE.Group()
+  for (let k = 0; k < point.length; k++) {
+    const item = point[k]
+    const canvas = document.createElement('canvas')
+    const context = canvas.getContext('2d')
+    context!.font = `${size * 50}px Arial`
+    context!.fillStyle = 'white'
+    context!.fillText(item.txt, 170, 100)
+    const texture = new threeService.THREE.CanvasTexture(canvas)
+    const material = new threeService.THREE.SpriteMaterial({ map: texture, rotation: item.r })
+    const sprite = new threeService.THREE.Sprite(material)
+    sprite.scale.set(size, size * 0.5, 1)
+    // sprite.center.set(0.1, 0.1)
+    sprite.position.set(item.x, item.y, item.z)
+    group.add(sprite)
+  }
+  if (showPoint) {
+    const points = createPoint(point, { x: 0, y: 0, z: 0 }, 0.05)
+    group.add(points)
+  }
+  group.position.set(position.x, position.y, position.z)
+  return group
+}
+
 // 添加obj
 // 添加obj
 function addOBJ() {
 function addOBJ() {
   if (!threeService.scene) return
   if (!threeService.scene) return
@@ -386,14 +447,17 @@ function addOBJ() {
   }
   }
   // 超欠挖点图
   // 超欠挖点图
   if (props.holeConfig.show === 7) {
   if (props.holeConfig.show === 7) {
-    const designArr = props.holeConfig.data[0].map((el: number[]) => ({
-      x: el[0], y: el[1], z: 0, c: '#33D7FF'
-    })) || []
+    const designArr = props.holeConfig.data[0].map((el: number[]) => ({ x: +el[0], y: +el[1], z: 0 })) || []
     const breakArr = props.holeConfig.data[1].map((el: number[]) => ({
     const breakArr = props.holeConfig.data[1].map((el: number[]) => ({
-      x: el[0], y: el[1], z: 0, c: el[3] > 0 ? '#2F3CFC' : '#BB343B'
+      x: +el[0] || 0, y: +el[1] || 0, z: 0, txt: Math.floor(+el[3] * 100) / 100 || 0, c: '#BB343B'
     })) || []
     })) || []
-    const group = createExceedBreakPoint(designArr, breakArr, props.holeConfig.position)
-    threeService.scene.add(group)
+    if (!designArr.length || !breakArr.length) return
+    const num = 36 // 抽取36个点/角度平均分布
+    const breakArrText = threeService.splitArray(breakArr, num).map((el:{x: number; y: number; z: number; txt: string; r: number; c: string;}[], index) => ({ ...el[0], r: index * (Math.PI / num) }))
+    const designLine = createExceedBreakLine(designArr, '#33D7FF')
+    const breakLine = createExceedBreakLine(breakArr.concat(breakArr[0]), '#BB343B')
+    const textGroup = create3DLabel(breakArrText)
+    threeService.scene.add(designLine, breakLine, textGroup)
   }
   }
 }
 }
 
 

+ 30 - 8
src/pages/three/three.service.ts

@@ -2,8 +2,9 @@ import * as Three from 'three'
 import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
 import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
 
 
 export interface MapOption {
 export interface MapOption {
-  cameraP: { X: number, Y: number, Z: number },
-  isRotate?: boolean
+  cameraP?: { X: number, Y: number, Z: number },
+  isRotate?: boolean,
+  contrlLeft?: boolean
 }
 }
 export default class ThreeService {
 export default class ThreeService {
   renderer = null as unknown as Three.WebGLRenderer // 渲染器
   renderer = null as unknown as Three.WebGLRenderer // 渲染器
@@ -46,9 +47,10 @@ export default class ThreeService {
    */
    */
   resetCamera(option?: MapOption) {
   resetCamera(option?: MapOption) {
     if (!this.dom) return
     if (!this.dom) return
-    const { cameraP, isRotate } = {
+    const { cameraP, isRotate, contrlLeft } = {
       cameraP: { X: 0, Y: 0, Z: 18 },
       cameraP: { X: 0, Y: 0, Z: 18 },
       isRotate: true,
       isRotate: true,
+      contrlLeft: true,
       ...option
       ...option
     }
     }
     // 相机
     // 相机
@@ -59,7 +61,7 @@ export default class ThreeService {
     this.OrbitControls = new OrbitControls(this.camera, this.renderer.domElement) // 控制器
     this.OrbitControls = new OrbitControls(this.camera, this.renderer.domElement) // 控制器
     this.OrbitControls.update()
     this.OrbitControls.update()
     this.OrbitControls.enabled = isRotate // 启用控制
     this.OrbitControls.enabled = isRotate // 启用控制
-    // this.OrbitControls.enableRotate = true // 启用左键控制
+    this.OrbitControls.enableRotate = contrlLeft // 启用左键控制
     // // this.OrbitControls.autoRotate = true //自动旋转
     // // this.OrbitControls.autoRotate = true //自动旋转
     // this.OrbitControls.enableZoom = true // 启用缩放
     // this.OrbitControls.enableZoom = true // 启用缩放
     // this.OrbitControls.maxDistance = 500 // 最大范围
     // this.OrbitControls.maxDistance = 500 // 最大范围
@@ -71,7 +73,7 @@ export default class ThreeService {
    * @returns data点中的元素
    * @returns data点中的元素
    */
    */
   onMouseDblclick() {
   onMouseDblclick() {
-    let data = null as any
+    let data = null
     this.dom.addEventListener(
     this.dom.addEventListener(
       'click',
       'click',
       (event) => {
       (event) => {
@@ -184,7 +186,7 @@ export default class ThreeService {
    */
    */
   SvgPathToPrint(DOMID: string) {
   SvgPathToPrint(DOMID: string) {
     const svg = document.getElementById(DOMID)
     const svg = document.getElementById(DOMID)
-    const arrList = [] as any
+    const arrList = []
     for (let j = 0; j < svg!.childNodes.length; j++) {
     for (let j = 0; j < svg!.childNodes.length; j++) {
       const item = svg!.childNodes[j] as any
       const item = svg!.childNodes[j] as any
       const obj = {
       const obj = {
@@ -202,9 +204,9 @@ export default class ThreeService {
     }
     }
 
 
     const newARR = [ arrList[0], arrList[1], arrList[2], arrList[3] ]
     const newARR = [ arrList[0], arrList[1], arrList[2], arrList[3] ]
-    const overarr = [] as any
+    const overarr = []
     for (let z = 0; z < newARR.length; z++) {
     for (let z = 0; z < newARR.length; z++) {
-      const item = newARR[z] as any
+      const item = newARR[z]
       if (!item) continue
       if (!item) continue
       // 汇总
       // 汇总
       for (let d = 0; d < item.list.length; d++) {
       for (let d = 0; d < item.list.length; d++) {
@@ -255,6 +257,26 @@ export default class ThreeService {
     return group
     return group
   }
   }
 
 
+  /**
+   * 将数组平均分割成指定数量的子数组
+   * @param {Array} array - 需要分割的数组
+   * @param {number} parts - 分割的子数组数量
+   * @returns {Array} - 分割后的子数组组成的数组
+   */
+  splitArray(array: string | any[], parts: number) {
+    const result = []
+    const len = array.length
+    const partSize = Math.ceil(len / parts)
+
+    for (let i = 0; i < parts; i++) {
+      const start = i * partSize
+      const end = start + partSize
+      result.push(array.slice(start, end))
+    }
+
+    return result
+  }
+
   /**
   /**
    * 清楚缓存
    * 清楚缓存
    */
    */