LineDraw.js 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. import math from './math'
  2. import Colors from '@sdk/modules/core/enum/Colors'
  3. import config from '@sdk/internal/configs'
  4. //画线等函数--by 许钟文
  5. import { Fatline, LineGeometry, LineMaterial } from '@sdk/modules/core/objects/Line.js'
  6. var defaultColor = Colors.lightGreen
  7. let player = null
  8. var LineDraw = {
  9. /*
  10. 多段普通线 (第二个点和第三个点之间是没有线段的, 所以不用在意线段顺序)
  11. */
  12. createLine: function (posArr, o) {
  13. var mat
  14. if (o.mat) {
  15. mat = o.mat
  16. } else {
  17. let prop = {
  18. color: o.color || defaultColor,
  19. transparent: o.dontAlwaysSeen ? false : true,
  20. depthTest: o.dontAlwaysSeen ? true : false,
  21. }
  22. if (o.deshed) {
  23. prop.lineWidth = o.lineWidth || 1 //windows无效。 似乎mac/ios上粗细有效 ?
  24. prop.dashSize = o.dashSize || 0.1
  25. prop.gapSize = o.gapSize || 0.1
  26. }
  27. mat = new THREE[o.deshed ? 'LineDashedMaterial' : 'LineBasicMaterial'](prop)
  28. }
  29. var line = new THREE.LineSegments(new THREE.BufferGeometry(), mat)
  30. line.renderOrder = o.renderOrder || 4
  31. this.moveLine(line, posArr)
  32. return line
  33. },
  34. moveLine: function (line, posArr) {
  35. if (posArr.length == 0) {
  36. return console.log(1)
  37. }
  38. let position = []
  39. posArr.forEach(e => position.push(e.x, e.y, e.z))
  40. line.geometry.setAttribute('position', new THREE.BufferAttribute(new Float32Array(position), 3))
  41. line.geometry.attributes.position.needsUpdate = true
  42. line.geometry.computeBoundingSphere()
  43. if (line.material instanceof THREE.LineDashedMaterial) {
  44. line.computeLineDistances()
  45. }
  46. },
  47. createFatLineMat: function (o) {
  48. let matParam = Object.assign(
  49. {},
  50. {
  51. //默认
  52. lineWidth: 5,
  53. color: 0xffffff,
  54. transparent: true,
  55. depthWrite: false,
  56. depthTest: false,
  57. dashSize: 0.1,
  58. gapSize: 0.1,
  59. },
  60. o,
  61. {
  62. //修正覆盖:
  63. // dashed
  64. /* polygonOffset: true, //是否开启多边形偏移 for not cover the lineMesh
  65. polygonOffsetFactor: -o.width * 2.5 || -5, //多边形偏移因子
  66. polygonOffsetUnits: -4.0, //多边形偏移单位 */
  67. }
  68. )
  69. var mat = new LineMaterial(matParam)
  70. return mat
  71. },
  72. /*
  73. 创建可以改变粗细的线。
  74. */
  75. createFatLine: function (posArr, o) {
  76. let geometry = new LineGeometry()
  77. geometry.setColors(o.color || [1, 1, 1])
  78. var matLine = o.material || this.createFatLineMat(o)
  79. let line = new Fatline(geometry, matLine)
  80. //line.computeLineDistances();
  81. line.scale.set(1, 1, 1)
  82. line.renderOrder = 2
  83. this.moveFatLine(line, posArr)
  84. return line
  85. },
  86. /* createFatLine: function (posArr, o) {
  87. var geometry = new THREE.BufferGeometry()
  88. geometry.setAttribute('position', new THREE.BufferAttribute(new Float32Array(posArr), 3))
  89. geometry.setAttribute('color', new THREE.BufferAttribute(new Float32Array(o.color || [1, 1, 1]), 3))
  90. var matLine = o.material || this.createFatLineMat(o)
  91. var line = new THREE.Line(geometry, matLine)
  92. line.computeLineDistances()
  93. line.scale.set(1, 1, 1)
  94. line.renderOrder = 2
  95. return line
  96. }, */
  97. moveFatLine: function (line, posArr) {
  98. var geometry = line.geometry
  99. var positions = []
  100. posArr.forEach(e => positions.push(e.x, e.y, e.z))
  101. if (positions.length > 0) {
  102. if (!geometry) {
  103. geometry = line.geometry = new LineGeometry()
  104. }
  105. if (geometry.attributes.instanceEnd && geometry.attributes.instanceEnd.data.array.length != positions.length) {
  106. //positions个数改变会有部分显示不出来,所以重建
  107. geometry.dispose()
  108. geometry = new LineGeometry()
  109. line.geometry = geometry
  110. }
  111. geometry.setPositions(positions)
  112. if (line.material.dashed) {
  113. //line.geometry.computeBoundingSphere();
  114. line.computeLineDistances()
  115. }
  116. } else {
  117. geometry.dispose()
  118. line.geometry = new LineGeometry()
  119. }
  120. },
  121. /* moveFatLine: function (line, posArr) {
  122. var geometry = line.geometry
  123. geometry.setPositions(posArr)
  124. }, */
  125. /*
  126. 为line创建用于检测鼠标的透明mesh,实际是个1-2段圆台。
  127. 由于近大远小的原因,假设没有透视畸变、创建的是等粗的圆柱的话, 所看到的线上每个位置的粗细应该和距离成反比。所以将圆柱改为根据距离线性渐变其截面半径的圆台,在最近点(相机到线的垂足)最细。如果最近点在线段上,则分成两段圆台,否则一段。
  128. */
  129. createBoldLine: function (points, o, p) {
  130. player = p
  131. o = o || {}
  132. var cylinder = o && o.cylinder
  133. var CD = points[1].clone().sub(points[0])
  134. var rotate = function () {
  135. //根据端点旋转好模型
  136. cylinder.lastVector = CD //记录本次的端点向量
  137. var AB = new THREE.Vector3(0, -1, 0)
  138. var axisVec = AB.clone().cross(CD).normalize() //得到垂直于它们的向量,也就是旋转轴
  139. var rotationAngle = AB.angleTo(CD)
  140. cylinder.quaternion.setFromAxisAngle(axisVec, rotationAngle)
  141. }
  142. if (o && o.type == 'init') {
  143. cylinder = new THREE.Mesh()
  144. cylinder.material = o.mat
  145. if (CD.length() == 0) return cylinder
  146. rotate()
  147. }
  148. if (CD.length() == 0) return cylinder
  149. if (o.type != 'update') {
  150. var CDcenter = points[0].clone().add(points[1]).multiplyScalar(0.5)
  151. cylinder.position.copy(CDcenter)
  152. if (!cylinder.lastVector || o.type == 'moveAndRotate') rotate()
  153. else if (cylinder.lastVector && CD.angleTo(cylinder.lastVector) > 0) rotate() //线方向改了or线反向了 重新旋转一下模型
  154. // if (config.isEdit && !objects.mainDesign.editing) return cylinder //节省初始加载时间?
  155. }
  156. //为了保证线段任何地方的可检测点击范围看起来一样大,更新圆台的结构(但是在镜头边缘会比中心看起来大)
  157. var height = points[0].distanceTo(points[1])
  158. var standPos = (o && o.standPos) || player.position
  159. var k = config.isMobile ? 20 : 40
  160. var dis1 = points[0].distanceTo(standPos)
  161. var dis2 = points[1].distanceTo(standPos)
  162. var foot = math.getFootPoint(standPos, points[0], points[1]) //垂足
  163. if (o.constantBold || player.mode != 'panorama') {
  164. var width = 0.1 //0.08;
  165. var pts = [new THREE.Vector2(width, height / 2), new THREE.Vector2(width, -height / 2)]
  166. } else if (foot.clone().sub(points[0]).dot(foot.clone().sub(points[1])) > 0) {
  167. //foot不在线段上
  168. var pts = [new THREE.Vector2(dis1 / k, height / 2), new THREE.Vector2(dis2 / k, -height / 2)]
  169. } else {
  170. //在线段上的话,要在垂足这加一个节点,因它距离站位最近,而两端较远
  171. var dis3 = foot.distanceTo(standPos)
  172. var len = foot.distanceTo(points[0])
  173. var pts = [new THREE.Vector2(dis1 / k, height / 2), new THREE.Vector2(dis3 / k, height / 2 - len), new THREE.Vector2(dis2 / k, -height / 2)]
  174. }
  175. cylinder.geometry && cylinder.geometry.dispose() //若不删除会占用内存
  176. cylinder.geometry = new THREE.LatheBufferGeometry(pts, 4 /* Math.min(dis1,dis2)<10?4:3 */)
  177. cylinder.renderOrder = 2
  178. return cylinder
  179. },
  180. updateBoldLine: function (cylinder, points, type, standPos, constantBold) {
  181. this.createBoldLine(points, { type: type, cylinder: cylinder, standPos: standPos, constantBold }, player) //type:move:平移 会改长短 , type:update根据距离和角度更新 不改长短
  182. },
  183. Fatline, fatLineGeometry:LineGeometry,
  184. }
  185. export default LineDraw