PrintTool.js 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. /*
  2. * PrintTool.js
  3. *
  4. * @author realor
  5. */
  6. import { Tool } from './Tool.js'
  7. import { Solid } from '../core/Solid.js'
  8. import { GeometryUtils } from '../utils/GeometryUtils.js'
  9. import { WebUtils } from '../utils/WebUtils.js'
  10. import { Controls } from '../ui/Controls.js'
  11. import { MessageDialog } from '../ui/MessageDialog.js'
  12. import { I18N } from '../i18n/I18N.js'
  13. import * as THREE from '../lib/three.module.js'
  14. class PrintTool extends Tool {
  15. constructor(application, options) {
  16. super(application)
  17. this.name = 'print'
  18. this.label = 'tool.print.label'
  19. this.help = 'tool.print.help'
  20. this.className = 'print'
  21. this.setOptions(options)
  22. this.createPanel()
  23. }
  24. createPanel() {
  25. this.panel = this.application.createPanel(this.label, 'left')
  26. this.panel.preferredHeight = 120
  27. this.titleElem = Controls.addTextField(this.panel.bodyElem, 'print_title', 'label.print_title', '', 'row')
  28. this.scaleElem = Controls.addTextField(this.panel.bodyElem, 'print_scale', 'label.print_scale', '10', 'row')
  29. this.scaleElem.style.width = '60px'
  30. this.printButton = Controls.addButton(this.panel.bodyElem, 'print_button', 'button.print', () => this.print())
  31. this.openLink = document.createElement('a')
  32. I18N.set(this.openLink, 'innerHTML', 'button.open')
  33. this.openLink.target = '_blank'
  34. this.openLink.style.display = 'none'
  35. this.panel.bodyElem.appendChild(this.openLink)
  36. }
  37. activate() {
  38. this.panel.visible = true
  39. }
  40. deactivate() {
  41. this.panel.visible = false
  42. }
  43. print() {
  44. this.printButton.disabled = true
  45. this.application.progressBar.progress = undefined
  46. this.application.progressBar.visible = true
  47. this.application.progressBar.message = ''
  48. setTimeout(() => this.drawScene(), 100)
  49. }
  50. drawScene() {
  51. const application = this.application
  52. const request = new XMLHttpRequest()
  53. const serviceUrl = location.protocol + '//' + location.host + '/bimrocket-server/api/print'
  54. let scale = parseFloat(this.scaleElem.value)
  55. // assume units in meters
  56. let factor = 1 * 39.37007874 * 72 // dots per meter
  57. factor /= scale
  58. let matrix = new THREE.Matrix4()
  59. matrix.makeTranslation(297, 382, 0)
  60. matrix.multiply(new THREE.Matrix4().makeScale(factor, factor, factor))
  61. matrix.multiply(application.camera.matrixWorldInverse)
  62. let printSource = {
  63. title: this.titleElem.value || 'Bimrocket print',
  64. commands: []
  65. }
  66. this.drawObject(application.baseObject, matrix, printSource)
  67. request.open('POST', serviceUrl, true)
  68. request.setRequestHeader('Content-Type', 'application/json;charset=UTF-8')
  69. request.onload = () => {
  70. this.printButton.disabled = false
  71. this.application.progressBar.visible = false
  72. if (request.status === 200) {
  73. let printResult = JSON.parse(request.responseText)
  74. this.openLink.href = serviceUrl + '/' + printResult.id
  75. this.openLink.click()
  76. } else this.showError(request)
  77. }
  78. request.onerror = () => {
  79. this.printButton.disabled = false
  80. this.application.progressBar.visible = false
  81. this.showError(request)
  82. }
  83. request.send(JSON.stringify(printSource))
  84. }
  85. drawObject(object, matrix, printSource) {
  86. const commands = printSource.commands
  87. if (object instanceof Solid) {
  88. try {
  89. if (object.edgesVisible) {
  90. let edgesGeometry = object.edgesGeometry
  91. let vertices = GeometryUtils.getBufferGeometryVertices(edgesGeometry)
  92. let p1 = new THREE.Vector3()
  93. let p2 = new THREE.Vector3()
  94. for (let i = 0; i < vertices.length; i += 2) {
  95. p1.copy(vertices[i])
  96. p1.applyMatrix4(object.matrixWorld)
  97. p1.applyMatrix4(matrix)
  98. p2.copy(vertices[i + 1])
  99. p2.applyMatrix4(object.matrixWorld)
  100. p2.applyMatrix4(matrix)
  101. commands.push({ type: 'moveto', args: [p1.x, p1.y] })
  102. commands.push({ type: 'lineto', args: [p2.x, p2.y] })
  103. commands.push({ type: 'stroke' })
  104. }
  105. }
  106. } catch (ex) {
  107. console.error(ex)
  108. }
  109. } else if (object instanceof THREE.Mesh) {
  110. var geometry = object.geometry
  111. if (geometry instanceof THREE.BufferGeometry) {
  112. const vertices = GeometryUtils.getBufferGeometryVertices(geometry)
  113. const p1 = new THREE.Vector3()
  114. const p2 = new THREE.Vector3()
  115. const p3 = new THREE.Vector3()
  116. const printFace = function(va, vb, vc) {
  117. p1.copy(vertices[va])
  118. p2.copy(vertices[vb])
  119. p3.copy(vertices[vc])
  120. p1.applyMatrix4(object.matrixWorld)
  121. p2.applyMatrix4(object.matrixWorld)
  122. p3.applyMatrix4(object.matrixWorld)
  123. p1.applyMatrix4(matrix)
  124. p2.applyMatrix4(matrix)
  125. p3.applyMatrix4(matrix)
  126. commands.push({ type: 'moveto', args: [p1.x, p1.y] })
  127. commands.push({ type: 'lineto', args: [p2.x, p2.y] })
  128. commands.push({ type: 'lineto', args: [p3.x, p3.y] })
  129. commands.push({ type: 'lineto', args: [p1.x, p1.y] })
  130. commands.push({ type: 'stroke' })
  131. }
  132. GeometryUtils.getBufferGeometryFaces(geometry, printFace)
  133. }
  134. } else if (object instanceof THREE.Line) {
  135. } else {
  136. for (let child of object.children) {
  137. if (child.visible) {
  138. this.drawObject(child, matrix, printSource)
  139. }
  140. }
  141. }
  142. }
  143. showError(request) {
  144. let status = request.status
  145. let message
  146. let statusMessage = WebUtils.getHttpStatusMessage(status)
  147. if (statusMessage.length > 0) {
  148. message = statusMessage
  149. } else {
  150. message = 'Error'
  151. }
  152. message += ' (HTTP ' + status + ').'
  153. MessageDialog.create('ERROR', message)
  154. .setClassName('error')
  155. .setI18N(this.application.i18n)
  156. .show()
  157. }
  158. }
  159. export { PrintTool }