MeasureLengthTool.js 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. /*
  2. * MeasureLengthTool.js
  3. *
  4. * @author realor
  5. */
  6. import { Tool } from './Tool.js'
  7. import { I18N } from '../i18n/I18N.js'
  8. import { Controls } from '../ui/Controls.js'
  9. import { ObjectUtils } from '../utils/ObjectUtils.js'
  10. import * as THREE from '../lib/three.module.js'
  11. class MeasureLengthTool extends Tool {
  12. constructor(application, options) {
  13. super(application)
  14. this.name = 'measure_length'
  15. this.label = 'tool.measure_length.label'
  16. this.help = 'tool.measure_length.help'
  17. this.className = 'measure_length'
  18. this.setOptions(options)
  19. this.vertices = [] // Vector3[]
  20. this.line = null // THREE.Line
  21. this.points = null // THREE.Points
  22. this.lineMaterial = new THREE.LineBasicMaterial({ linewidth: 2, color: new THREE.Color(0x0000ff), opacity: 1, depthTest: false, transparent: true })
  23. this.pointsMaterial = new THREE.PointsMaterial({ color: 0, size: 4, sizeAttenuation: false, depthTest: false, transparent: true })
  24. this._onPointerUp = this.onPointerUp.bind(this)
  25. this.createPanel()
  26. }
  27. createPanel() {
  28. this.panel = this.application.createPanel(this.label, 'left')
  29. this.panel.preferredHeight = 120
  30. const helpElem = document.createElement('div')
  31. this.panel.bodyElem.appendChild(helpElem)
  32. const resetButton = Controls.addButton(this.panel.bodyElem, 'clear_linestring', 'button.clear', () => this.clearLineString())
  33. const undoButton = Controls.addButton(this.panel.bodyElem, 'undo_last', 'button.undo', () => this.removeLastPoint())
  34. this.distElem = document.createElement('div')
  35. this.distElem.style.textAlign = 'left'
  36. this.distElem.style.padding = '10px'
  37. this.panel.bodyElem.appendChild(this.distElem)
  38. }
  39. activate() {
  40. const application = this.application
  41. const container = application.container
  42. this.panel.visible = true
  43. container.addEventListener('pointerup', this._onPointerUp, false)
  44. application.pointSelector.activate()
  45. if (this.line && !ObjectUtils.isObjectDescendantOf(this.line, application.scene)) {
  46. this.vertices = []
  47. this.updateLineString()
  48. }
  49. }
  50. deactivate() {
  51. const application = this.application
  52. const container = application.container
  53. this.panel.visible = false
  54. container.removeEventListener('pointerup', this._onPointerUp, false)
  55. application.pointSelector.deactivate()
  56. }
  57. onPointerUp(event) {
  58. const pointSelector = this.application.pointSelector
  59. if (!pointSelector.isPointSelectionEvent(event)) return
  60. let snap = pointSelector.snap
  61. if (snap) {
  62. let axisMatrixWorld = snap.object ? snap.object.matrixWorld.clone() : new THREE.Matrix4()
  63. axisMatrixWorld.setPosition(snap.positionWorld)
  64. let vertex = snap.positionWorld
  65. this.vertices.push(vertex)
  66. this.updateLineString()
  67. pointSelector.auxiliaryPoints = this.vertices
  68. let count = this.vertices.length
  69. if (count > 1) {
  70. pointSelector.auxiliaryLines.push(new THREE.Line3(this.vertices[count - 2], this.vertices[count - 1]))
  71. }
  72. pointSelector.setAxisGuides(axisMatrixWorld, true)
  73. } else {
  74. pointSelector.clearAxisGuides()
  75. }
  76. }
  77. clearLineString() {
  78. const pointSelector = this.application.pointSelector
  79. pointSelector.auxiliaryPoints = []
  80. pointSelector.auxiliaryLines = []
  81. pointSelector.clearAxisGuides()
  82. this.vertices = []
  83. this.updateLineString()
  84. }
  85. removeLastPoint() {
  86. const pointSelector = this.application.pointSelector
  87. if (this.vertices.length > 0) {
  88. this.vertices.pop()
  89. this.updateLineString()
  90. if (this.vertices.length > 0) {
  91. let lastVertex = this.vertices[this.vertices.length - 1]
  92. pointSelector.auxiliaryLines.pop()
  93. let axisMatrixWorld = new THREE.Matrix4()
  94. axisMatrixWorld.setPosition(lastVertex)
  95. pointSelector.setAxisGuides(axisMatrixWorld, true)
  96. } else {
  97. pointSelector.clearAxisGuides()
  98. }
  99. }
  100. }
  101. updateLineString() {
  102. const application = this.application
  103. const overlays = application.overlays
  104. if (this.line !== null) {
  105. application.removeObject(this.line)
  106. this.line = null
  107. }
  108. if (this.points !== null) {
  109. application.removeObject(this.points)
  110. this.points = null
  111. }
  112. if (this.vertices.length > 0) {
  113. let geometry = new THREE.BufferGeometry()
  114. geometry.setFromPoints(this.vertices)
  115. this.line = new THREE.Line(geometry, this.lineMaterial, THREE.LineStrip)
  116. this.line.raycast = function() {}
  117. overlays.add(this.line)
  118. this.points = new THREE.Points(geometry, this.pointsMaterial)
  119. this.points.raycast = function() {}
  120. overlays.add(this.points)
  121. }
  122. application.repaint()
  123. let length = this.getLineStringLength()
  124. I18N.set(this.distElem, 'innerHTML', 'message.measure_length', length.toFixed(application.decimals), application.units)
  125. application.i18n.update(this.distElem)
  126. }
  127. getLineStringLength() {
  128. let length = 0
  129. const v = new THREE.Vector3()
  130. for (let i = 0; i < this.vertices.length - 1; i++) {
  131. let p1 = this.vertices[i]
  132. let p2 = this.vertices[i + 1]
  133. v.set(p1.x - p2.x, p1.y - p2.y, p1.z - p2.z)
  134. length += v.length()
  135. }
  136. return length
  137. }
  138. }
  139. export { MeasureLengthTool }