util.js 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862
  1. /**
  2. * 判断数组是否是两条线段组成
  3. * @param {线段数组} arr
  4. */
  5. function isTwoLine(arr) {
  6. var max = 0,
  7. min = 1;
  8. for (var i = 0; i < arr.length; i++) {
  9. if (arr[i][0] > max) {
  10. max = arr[i][0];
  11. }
  12. if (arr[i][0] < min) {
  13. min = arr[i][0];
  14. }
  15. }
  16. return [min === 0, max];
  17. }
  18. /*
  19. @function: 加载3D线段,需要根据平台自行实现
  20. @info: 这里生成一个3D单位CUBE的所有线段
  21. */
  22. function _3dLine(r2x, r3x, ret) {
  23. // 坐标点长度
  24. var r1x = 0.5;
  25. // 矩形的各个定点
  26. var r2x_t = [
  27. [-r1x, -r1x, +r1x],
  28. [-r1x, +r1x, +r1x],
  29. [+r1x, +r1x, +r1x],
  30. [+r1x, -r1x, +r1x],
  31. [-r1x, -r1x, -r1x],
  32. [-r1x, +r1x, -r1x],
  33. [+r1x, +r1x, -r1x],
  34. [+r1x, -r1x, -r1x]
  35. ];
  36. // 线段的坐标
  37. // z轴
  38. var r3x_t = [
  39. [0, 1],
  40. [1, 2],
  41. [2, 3],
  42. [3, 0],
  43. [4, 5],
  44. [5, 6],
  45. [6, 7],
  46. [7, 4],
  47. [0, 4],
  48. [1, 5],
  49. [2, 6],
  50. [3, 7]
  51. ];
  52. // 各个线段的坐标
  53. var ret_t = [
  54. ["", ""],
  55. ["", ""],
  56. ["", ""],
  57. ["", ""],
  58. ["", ""],
  59. ["", ""],
  60. ["", ""],
  61. ["", ""],
  62. ["", ""],
  63. ["", ""],
  64. ["", ""],
  65. ["", ""]
  66. ];
  67. // ret[0][0] = r2x[r3x[0][0]];
  68. for (var i = 0; i < r3x.length; i++) {
  69. ret[i] = {
  70. "3d_id": i,
  71. "3d_point1": r2x[r3x[i][0]],
  72. "3d_point2": r2x[r3x[i][1]]
  73. }
  74. // ret[i][0] = r2x[r3x[i][0]];
  75. // ret[i][1] = r2x[r3x[i][1]];
  76. }
  77. ret_t[0][0] = r2x_t[r3x_t[0][0]];
  78. for (var i = 0; i < r3x_t.length; i++) {
  79. ret_t[i][0] = r2x_t[r3x_t[i][0]];
  80. ret_t[i][1] = r2x_t[r3x_t[i][1]];
  81. }
  82. return ret;
  83. }
  84. /**
  85. * 生成3D格式数据
  86. * @param {三维线段数组} arr
  87. * @param {组成面得线段数组} faceArr
  88. */
  89. function fix3dLineArr(arr, faceArr) {
  90. var ret = []
  91. for (let i = 0; i < faceArr.length; i++) {
  92. var item = {
  93. faceLine: [],
  94. index: [],
  95. verticalLine: []
  96. }
  97. for (let j = 0; j < faceArr[i].length; j++) {
  98. for (let k = 0; k < arr.length; k++) {
  99. if (faceArr[i][j] == arr[k]['3d_id']) {
  100. item.faceLine.push({
  101. id: faceArr[i][j],
  102. points: [arr[k]["3d_point1"], arr[k]["3d_point2"]]
  103. })
  104. item.index.push(faceArr[i][j])
  105. }
  106. }
  107. }
  108. ret.push(item)
  109. }
  110. return ret
  111. }
  112. // 归一化
  113. function normalize(xyz, isFixed) {
  114. var _mo_ = Math.sqrt(xyz[0] * xyz[0] + xyz[1] * xyz[1] + xyz[2] * xyz[2]);
  115. var x = xyz[0] / _mo_;
  116. var y = xyz[1] / _mo_;
  117. var z = xyz[2] / _mo_;
  118. var r1x;
  119. if (isFixed) {
  120. r1x = [-y, -x, z];
  121. } else {
  122. r1x = [x, y, z];
  123. }
  124. return r1x;
  125. }
  126. /*
  127. @function: 相机在坐标原点上,返回空间点在球目图片上的投影点,和'_calculate3dPoint'互逆
  128. @param {xyz}: 空间中的3D点,不需要先进行归一化
  129. @return {ret}: 纹理空间的2D点,范围为[0 ,1]
  130. */
  131. function _calculate2dPoint(xyz) {
  132. var ret = ["", ""];
  133. //@info: 这一步是为了兼容我们所用的球目相机的正方向,并且进行归一化
  134. // const auto r1x = Vector<VAL64> {-xyz[1] ,-xyz[0] ,xyz[2] ,0}.normalize () ;
  135. var r1x = normalize(xyz, true);
  136. // var r1x = xyz
  137. ret[0] = Math.atan2(r1x[1], r1x[0]) / (Math.PI * 2) + 0.5;
  138. ret[1] = (Math.acos(r1x[2]) / (Math.PI * 2)) * 2;
  139. return ret;
  140. // ARRAY2<VAL64> ret ;
  141. // //@info: 这一步是为了兼容我们所用的球目相机的正方向,并且进行归一化
  142. // const auto r1x = Vector<VAL64> {-xyz[1] ,-xyz[0] ,xyz[2] ,0}.normalize () ;
  143. // //@info: 分别计算投影点坐标
  144. // //@info: 反三角函数,缩放,平移
  145. // ret[0] = _ATAN_ (r1x[1] , r1x[0]) / VAL64 (VALX_PI * 2) + VAL64 (0.5) ;
  146. // ret[1] = _ACOS_ (r1x[2]) / VAL64 (VALX_PI * 2) * 2 ;
  147. // return std::move (ret) ;
  148. }
  149. /*
  150. @function: 相机在坐标原点上,返回球目图片上的投影点所在单位球上的原点,和'_calculate2dPoint'互逆
  151. @param {txy}: 纹理空间的2D点,范围为[0 ,1]
  152. @return {ret}: 空间中的3D点,在单位球上
  153. */
  154. function _calculate3dPoint(txy) {
  155. var ret = ["", "", ""];
  156. var r1x = (txy[1] / 2) * (Math.PI * 2);
  157. var r2x = (txy[0] - 0.5) * (Math.PI * 2);
  158. ret[0] = -Math.sin(r1x) * Math.sin(r2x);
  159. ret[1] = -Math.sin(r1x) * Math.cos(r2x);
  160. ret[2] = Math.cos(r1x);
  161. return ret;
  162. }
  163. /*
  164. @function: 计算栅格化所有线段后最大生成点的数量
  165. @param {line}: 线段的数组,line[i][0]为第一个点,line[i][1]为第二个点
  166. @param {gap}: 栅格化所需的步长,既每多长生成一个点
  167. @return {ret}: 最大生成点的数量
  168. */
  169. function _calculateMaxPoint(line, gap) {
  170. var ret = 0;
  171. for (var i = 0; i < line.length; i++) {
  172. var r1x = line[i][0];
  173. var r2x = line[i][1];
  174. // Math.hypot(x1 - x0, y1 - y0);
  175. ret += Math.ceil(
  176. Math.hypot(r1x[0] - r2x[0], r1x[1] - r2x[1], r1x[2] - r2x[2]) / gap + 0.5
  177. );
  178. }
  179. return ret;
  180. }
  181. /*
  182. @function: 计算3D线段在球目图片上的栅格化投影
  183. @param {camera_pose_matrix}: 相机位置,外参矩阵
  184. @param {line}: 线段的数组,line[i][0]为第一个点,line[i][1]为第二个点
  185. @param {gap}: 栅格化所需的步长,既每多长生成一个点
  186. @return {ret}: 栅格化投影投影后的2D线段,点坐标属于纹理空间,范围为[0 ,1]
  187. */
  188. function _3dTo2d(camera_pose_matrix, line, gap) {
  189. var ret = [];
  190. var ret_t = [];
  191. var item;
  192. var r10x = numbers.matrix.inverse(camera_pose_matrix);
  193. for (var i = 0; i < line.length; i++) {
  194. ret_t.push({ line: [] });
  195. item = []
  196. var r1x_temp = [[line[i]["3d_point1"][0]], [line[i]['3d_point1'][1]], [line[i]['3d_point1'][2]], [1]];
  197. var r2x_temp = [[line[i]['3d_point2'][0]], [line[i]['3d_point2'][1]], [line[i]['3d_point2'][2]], [1]];
  198. var r1x = numbers.matrix.multiply(r10x, r1x_temp);
  199. var r2x = numbers.matrix.multiply(r10x, r2x_temp);
  200. var r3x = Math.hypot(r2x[0] - r1x[0], r2x[1] - r1x[1], r2x[2] - r1x[2]) / gap
  201. var r2r1 = [r2x[0] - r1x[0], r2x[1] - r1x[1], r2x[2] - r1x[2]];
  202. var hasNormalize = normalize(r2r1, false);
  203. var r5x = [
  204. hasNormalize[0] * gap,
  205. hasNormalize[1] * gap,
  206. hasNormalize[2] * gap
  207. ];
  208. for (var j = 0; j < r3x; j++) {
  209. var r6x = [
  210. parseFloat(r1x[0]) + parseFloat(r5x[0]) * j,
  211. parseFloat(r1x[1]) + parseFloat(r5x[1]) * j,
  212. parseFloat(r1x[2]) + parseFloat(r5x[2]) * j
  213. ];
  214. var r7x = _calculate2dPoint(r6x);
  215. if (r7x[0] > maxX) {
  216. maxX = r7x[0];
  217. }
  218. ret_t[i].line.push(toDecimal(r7x));
  219. item.push(toDecimal(r7x))
  220. }
  221. var r6x_t = [
  222. parseFloat(r1x[0]) + parseFloat(r5x[0]) * r3x,
  223. parseFloat(r1x[1]) + parseFloat(r5x[1]) * r3x,
  224. parseFloat(r1x[2]) + parseFloat(r5x[2]) * r3x
  225. ];
  226. var r7x_t = _calculate2dPoint(r6x_t);
  227. ret_t[i].line.push(toDecimal(r7x_t));
  228. item.push(toDecimal(r7x_t))
  229. ret.push({
  230. "3d_id": [line[i]["3d_id"]][0],
  231. '2d_arr': fixLine(item)
  232. })
  233. }
  234. // ret2dObj(ret)
  235. return {
  236. drawArr: ret_t,
  237. to3d: ret2dObj(ret)
  238. };
  239. // return ret_t;
  240. }
  241. /**
  242. * 生成对应的2d线段
  243. * @param {三维线段数组} arr
  244. */
  245. function ret2dObj(arr) {
  246. var ret = [];
  247. var count = 0
  248. for (var i = 0; i < arr.length; i++) {
  249. for (var j = 0; j < arr[i]["2d_arr"].length; j++) {
  250. ret.push({
  251. "2d_id": count,
  252. "3d_id": i,
  253. "2d_point1": arr[i]["2d_arr"][j]["2d_point1"],
  254. "2d_point2": arr[i]["2d_arr"][j]["2d_point2"]
  255. })
  256. count++
  257. }
  258. }
  259. return {
  260. panorama_line_2d: ret
  261. }
  262. }
  263. function fixLine(arr) {
  264. var obj,
  265. t_arr = [];
  266. for (var i = 0; i < arr.length; i++) {
  267. obj = {
  268. "2d_point1": arr[i],
  269. "2d_point2": arr[i + 1]
  270. };
  271. if (obj["2d_point2"] && obj["2d_point2"] != obj["2d_point1"]) {
  272. t_arr.push(obj);
  273. }
  274. }
  275. return t_arr;
  276. }
  277. /**
  278. * 四舍五入保留6位小数
  279. * @param {数组} arr
  280. */
  281. function toDecimal(arr) {
  282. var xf = parseFloat(arr[0]);
  283. var yf = parseFloat(arr[1]);
  284. if (isNaN(xf) || isNaN(yf)) {
  285. return;
  286. }
  287. tx = Math.round(xf * 10e5) / 10e5;
  288. ty = Math.round(yf * 10e5) / 10e5;
  289. return [tx, ty];
  290. }
  291. function make_matrix_from_quat(quat) {
  292. var ret = numbers.matrix.identity(4);
  293. var r1x =
  294. quat[0] * quat[0] +
  295. quat[1] * quat[1] +
  296. quat[2] * quat[2] +
  297. quat[3] * quat[3];
  298. if (r1x != 0) {
  299. var x2 = (2 / r1x) * quat[0];
  300. var y2 = (2 / r1x) * quat[1];
  301. var z2 = (2 / r1x) * quat[2];
  302. var xx = quat[0] * x2;
  303. var xy = quat[0] * y2;
  304. var xz = quat[0] * z2;
  305. var yy = quat[1] * y2;
  306. var yz = quat[1] * z2;
  307. var zz = quat[2] * z2;
  308. var wx = quat[3] * x2;
  309. var wy = quat[3] * y2;
  310. var wz = quat[3] * z2;
  311. ret[0][0] = 1 - (yy + zz);
  312. ret[1][0] = xy - wz;
  313. ret[2][0] = xz + wy;
  314. ret[0][1] = xy + wz;
  315. ret[1][1] = 1 - (xx + zz);
  316. ret[2][1] = yz - wx;
  317. ret[0][2] = xz - wy;
  318. ret[1][2] = yz + wx;
  319. ret[2][2] = 1 - (xx + yy);
  320. }
  321. // ret = numbers.matrix.multiply([[1, 0, 0], [0, 1, 0], [0, 0, 1]], transpose(ret))
  322. var tran = [
  323. [1, 0, 0, quat[4]],
  324. [0, 1, 0, quat[5]],
  325. [0, 0, 1, quat[6]],
  326. [0, 0, 0, 1]
  327. ];
  328. ret = numbers.matrix.multiply(tran, transpose(ret));
  329. return ret;
  330. // [
  331. // [1, 0, 0, quat[4]],
  332. // [0, 1, 0, quat[5]],
  333. // [0, 0, 1, quat[6]],
  334. // [0 ,0 ,0 ,1]
  335. // ]
  336. }
  337. /**
  338. * 矩阵转置
  339. * @param {矩阵} arr
  340. */
  341. function transpose(arr) {
  342. var arr2 = [];
  343. for (var i = 0; i < arr[0].length; i++) {
  344. arr2[i] = [];
  345. }
  346. for (var i = 0; i < arr.length; i++) {
  347. for (var j = 0; j < arr[i].length; j++) {
  348. arr2[j][i] = arr[i][j];
  349. }
  350. }
  351. return arr2;
  352. }
  353. /**
  354. * 画线
  355. * @param {*画布} context
  356. * @param {*画布宽度 } w
  357. * @param {*画布高度} h
  358. * @param {*水平缩放倍数} scaleTime
  359. * @param {*垂直缩放倍数} scaleTimeH
  360. * @param {*线条数组} lineArr
  361. * @param {*是否重画} isclear
  362. */
  363. function drawSingleLine(
  364. context,
  365. w,
  366. h,
  367. scaleTime,
  368. scaleTimeH,
  369. lineArr,
  370. isclear
  371. ) {
  372. context.beginPath();
  373. if (isclear) {
  374. context.clearRect(0, 0, w, h);
  375. context.drawImage(img, 0, 0, w, h);
  376. }
  377. context.moveTo(
  378. lineArr[0].line[0][0] * scaleTime,
  379. lineArr[0].line[0][1] * scaleTimeH
  380. );
  381. for (var i = 0; i < lineArr.length; i++) {
  382. if (isTwoLine(lineArr[i].line)[0]) {
  383. for (var k = 0; k < lineArr[i].line.length; k++) {
  384. if (lineArr[i].line[k][0] < 0.5) {
  385. var temp = lineArr[i].line[k][0] + isTwoLine(lineArr[i].line)[1];
  386. if (temp <= 1) {
  387. lineArr[i].line.push([temp, lineArr[i].line[k][1]]);
  388. }
  389. }
  390. }
  391. }
  392. context.moveTo(
  393. lineArr[i].line[0][0] * scaleTime,
  394. lineArr[i].line[0][1] * scaleTimeH
  395. );
  396. for (var j = 0; j < lineArr[i].line.length; j++) {
  397. if (j + 1 < lineArr[i].line.length) {
  398. // Math.hypot(
  399. // lineArr[i].line[j+1][0] - lineArr[i].line[j][0],
  400. // lineArr[i].line[j+1][1] - lineArr[i].line[j][1]
  401. // ) < 0.05
  402. if (Math.abs(lineArr[i].line[j + 1][0] - lineArr[i].line[j][0]) > 0.5) {
  403. context.moveTo(
  404. lineArr[i].line[j + 1][0] * scaleTime,
  405. lineArr[i].line[j + 1][1] * scaleTimeH
  406. );
  407. } else {
  408. context.lineTo(
  409. lineArr[i].line[j][0] * scaleTime,
  410. lineArr[i].line[j][1] * scaleTimeH
  411. );
  412. }
  413. }
  414. if (j + 1 === lineArr[i].line.length) {
  415. context.lineTo(
  416. lineArr[i].line[j][0] * scaleTime,
  417. lineArr[i].line[j][1] * scaleTimeH
  418. );
  419. }
  420. }
  421. }
  422. context.stroke();
  423. }
  424. /**
  425. * 选中伸缩的墙进行画线
  426. * @param {画布} context
  427. * @param {画布宽度} w
  428. * @param {画布高度} h
  429. * @param {水平缩放倍数} scaleTime
  430. * @param {垂直缩放倍数} scaleTimeH
  431. * @param {线条数组} lineArr
  432. */
  433. function selectDragLine(context, w, h, scaleTime, scaleTimeH, lineArr, test) {
  434. context.strokeStyle = "#ff0000";
  435. drawSingleLine(context, w, h, scaleTime, scaleTimeH, lineArr, true);
  436. context.strokeStyle = "#00ff00";
  437. drawSingleLine(context, w, h, scaleTime, scaleTimeH, test, false);
  438. }
  439. /**
  440. * 找到面得中心坐标
  441. * @param {线段数组} lineArr
  442. * @param {水平缩放倍数} scaleTime
  443. * @param {垂直缩放倍数} scaleTimeH
  444. */
  445. function _calculateMiddlePoint(test, scaleTime, scaleTimeH) {
  446. var minX = 1,
  447. minY = 1,
  448. maxX = 0,
  449. maxY = 0;
  450. for (var i = 0; i < test.length; i++) {
  451. for (var j = 0; j < test[i].line.length; j++) {
  452. minX = Math.min(minX, test[i].line[j][0]);
  453. minY = Math.min(minY, test[i].line[j][1]);
  454. maxX = Math.max(maxX, test[i].line[j][0]);
  455. maxY = Math.max(maxY, test[i].line[j][1]);
  456. }
  457. }
  458. return [
  459. ((maxX - minX) / 2 + minX) * scaleTime,
  460. ((maxY - minY) / 2 + minY) * scaleTimeH
  461. ];
  462. }
  463. /**
  464. * 计算墙体中心和鼠标坐标点的距离
  465. * @param {当前鼠标点击的坐标点} current
  466. * @param {墙体的中心点坐标} middle
  467. */
  468. function _calculateMiddlePointDistance(current, middle) {
  469. return _calculateDistance(current, middle);
  470. }
  471. /**
  472. * 计算两点之间的距离
  473. * @param {坐标点} p1
  474. * @param {坐标点} p2
  475. */
  476. function _calculateDistance(p1, p2) {
  477. return Math.sqrt(Math.pow(p2[1] - p1[1], 2) + Math.pow(p2[0] - p1[0], 2));
  478. }
  479. /**
  480. * 判断点是否在墙体上
  481. * @param {鼠标当前坐标点} current
  482. * @param {墙体线段} lineArr
  483. * @param {水平缩放倍数} scaleTime
  484. * @param {垂直缩放倍数} scaleTimeH
  485. */
  486. function isInFace(current, test, scaleTime, scaleTimeH) {
  487. var fixArr = [];
  488. var selectYArr = [];
  489. var minX = 1,
  490. minY = 1,
  491. maxX = 0,
  492. maxY = 0;
  493. for (var i = 0; i < test.length; i++) {
  494. for (var j = 0; j < test[i].line.length; j++) {
  495. minX = Math.min(minX, test[i].line[j][0]);
  496. // minY = Math.min(minY, test[i].line[j][1]);
  497. maxX = Math.max(maxX, test[i].line[j][0]);
  498. // maxY = Math.max(maxY, test[i].line[j][1]);
  499. fixArr.push({
  500. id: parseFloat(test[i].line[j][0]).toFixed(1),
  501. y: test[i].line[j][1]
  502. });
  503. }
  504. }
  505. for (var i = 0; i < fixArr.length; i++) {
  506. if (fixArr[i].id == parseFloat(current[0] / scaleTime).toFixed(1)) {
  507. selectYArr.push(fixArr[i].y);
  508. }
  509. }
  510. for (var i = 0; i < selectYArr.length; i++) {
  511. minY = Math.min(minY, selectYArr[i]);
  512. maxY = Math.max(maxY, selectYArr[i]);
  513. }
  514. return (
  515. current[0] > minX * scaleTime &&
  516. current[0] < maxX * scaleTime &&
  517. current[1] > minY * scaleTimeH &&
  518. current[1] < maxY * scaleTimeH
  519. );
  520. }
  521. // 最简单数组去重法
  522. /*
  523. * 新建一新数组,遍历传入数组,值不在新数组就push进该新数组中
  524. * IE8以下不支持数组的indexOf方法
  525. * */
  526. function uniq(array){
  527. var temp = []; //一个新的临时数组
  528. for(var i = 0; i < array.length; i++){
  529. if(temp.indexOf(array[i]) == -1){
  530. temp.push(array[i]);
  531. }
  532. }
  533. return temp;
  534. }
  535. function get3dLinePoint(arr,fullPoint) {
  536. let temp = []
  537. for (let i = 0; i < arr.length; i++) {
  538. temp.push(arr[i]['3d_point1'])
  539. temp.push(arr[i]['3d_point2'])
  540. }
  541. return uniq(temp)
  542. }
  543. /**
  544. * 更新墙体线段的位置
  545. * @param {缩放的大小} distance
  546. * @param {墙体线段} lineArr
  547. */
  548. function updateLineArr(distance, lineArr, _3dLineArr, _3dPoint,selectArr,verticalVec) {
  549. // deltaX:值为负的(-1),则表示滚轮向左滚动。值为正的(1),则表示滚轮向右滚动。
  550. // deltaY:值为负的(-1),则表示滚轮向下滚动。值为正的(1),则表示滚轮向上滚动。
  551. // deltaFactor:增量因子。通过 deltaFactor * deltaX 或者 deltaFactor * deltaY 可以得到浏览器实际的滚动距离。
  552. // distance = -10
  553. let selectLine = []
  554. for (let i = 0; i < selectArr.length; i++) {
  555. selectLine.push(_3dLineArr[selectArr[i]])
  556. }
  557. let _3dLinePoint = get3dLinePoint(selectLine)
  558. for (let i = 0; i < _3dLinePoint.length; i++) {
  559. for (let j = 0; j < _3dPoint.length; j++) {
  560. if (_3dLinePoint[i].toString() === _3dPoint[j].toString()) {
  561. _3dPoint[j][0] += distance * Math.abs(verticalVec[0])
  562. _3dPoint[j][1] += distance * Math.abs(verticalVec[1])
  563. }
  564. }
  565. }
  566. rx1 = _3dLine(_3dPoint, r3x, ret);
  567. lineArr = _3dTo2d(
  568. make_matrix_from_quat([
  569. 0.008515,
  570. -0.014279,
  571. 0.016179,
  572. 0.999731,
  573. -5.438891,
  574. 2.167653,
  575. 0.165233
  576. ]),
  577. rx1,
  578. 0.05
  579. )["drawArr"];
  580. drawGeometry(rx1)
  581. return lineArr;
  582. }
  583. function updateSelectArr(lineArr, idxArr) {
  584. var ret = [];
  585. for (var i = 0; i < idxArr.length; i++) {
  586. ret.push(lineArr[idxArr[i]])
  587. }
  588. return ret
  589. }
  590. function _culaculateFaceArr(lineArr, faceArr, _3dLine) {
  591. var ret = [];
  592. var ret1 = []
  593. for (var i = 0; i < faceArr.length; i++) {
  594. var item = [];
  595. var item1 = []
  596. for (var j = 0; j < faceArr[i].length; j++) {
  597. item1.push(_3dLine[faceArr[i][j]]['3d_id'])
  598. item.push(lineArr[faceArr[i][j]]);
  599. // item1.push(_3dLine)
  600. }
  601. ret.push({
  602. id: i,
  603. arr: item
  604. });
  605. ret1.push(item1)
  606. }
  607. return [ret,ret1];
  608. }
  609. function selectWhichFace(lineArr, faceArr, current, _3dLine, scaleTime, scaleTimeH) {
  610. var retArr = _culaculateFaceArr(lineArr, faceArr,_3dLine);
  611. var allFaceArr = retArr[0]
  612. var all3DArr = retArr[1]
  613. var ret = 0;
  614. var minDist =
  615. faceArr &&
  616. _calculateMiddlePointDistance(
  617. current,
  618. _calculateMiddlePoint(allFaceArr[0].arr, scaleTime, scaleTimeH)
  619. );
  620. for (var i = 0; i < allFaceArr.length; i++) {
  621. if (isInFace(current, allFaceArr[i].arr, scaleTime, scaleTimeH)) {
  622. // tempRet = i
  623. ret = i
  624. if (
  625. _calculateMiddlePointDistance(
  626. current,
  627. _calculateMiddlePoint(allFaceArr[i].arr, scaleTime, scaleTimeH)
  628. ) < minDist
  629. ) {
  630. minDist = _calculateMiddlePointDistance(
  631. current,
  632. _calculateMiddlePoint(allFaceArr[i].arr, scaleTime, scaleTimeH)
  633. );
  634. } else {
  635. ret = i
  636. }
  637. }
  638. }
  639. return [allFaceArr[ret],all3DArr[ret]];
  640. }
  641. /**
  642. * 求与该平面相交的线段的相关信息
  643. * @param {array} faceLine 面的索引数组
  644. * @return {object} verticalLineData
  645. */
  646. function findverticalLine(faceLine,n_panorama_line_3d) {
  647. let lineAry = [];
  648. let verticalLineData = {
  649. lineAry: [],
  650. vecAry: [],
  651. verticalVec: []
  652. }
  653. for (let k = 0; k < faceLine.length; k++) {
  654. n_panorama_line_3d.find(item => {
  655. if (item['3d_id'] === faceLine[k]) {
  656. for (let l = 0; l < geoKeys.length; l++) {
  657. let sta_point = item[geoKeys[l]];
  658. for (let i = 0; i < n_panorama_line_3d.length; i++) {
  659. for (let j = 0; j < geoKeys.length; j++) {
  660. let line = n_panorama_line_3d[i];
  661. let curpoint = line[geoKeys[j]];
  662. let id = n_panorama_line_3d[i]['3d_id'];
  663. // 如果相交线段在当前面中, 则求它对应的向量
  664. if (arrayEquals(sta_point, curpoint) && faceLine.indexOf(id) >= 0 && verticalLineData.vecAry.length < 2) {
  665. let croodData = getThreeDVec(line['3d_point1'], line['3d_point2']);
  666. let vec3 = new THREE.Vector3(croodData[0], croodData[1], croodData[2])
  667. verticalLineData.vecAry.push(vec3);
  668. }
  669. if (arrayEquals(sta_point, curpoint) && faceLine.indexOf(id) < 0 && verticalLineData.lineAry.indexOf(id) < 0) {
  670. verticalLineData.lineAry.push(id);
  671. }
  672. }
  673. }
  674. }
  675. }
  676. })
  677. }
  678. let crossVec = new THREE.Vector3();
  679. crossVec.crossVectors(verticalLineData.vecAry[0], verticalLineData.vecAry[1]);
  680. crossVec.normalize();
  681. verticalLineData.verticalVec.push(crossVec.x, crossVec.y, crossVec.z)
  682. // console.log(tmp);
  683. // console.log(lineAry);
  684. return verticalLineData;
  685. }
  686. /**
  687. * 计算三维空间中的向量
  688. * @param {array} point1
  689. * @param {array} point2
  690. */
  691. function getThreeDVec(point1, point2) {
  692. if (!point1 || !point2 || (point1.length !== point2.length)) {
  693. console.log('点数据有误, 请检查');
  694. return;
  695. }
  696. let vec = [];
  697. for (let i = 0; i < point1.length; i++) {
  698. let val = point1[i] - point2[i];
  699. vec.push(val);
  700. }
  701. if (vec.length < 3) {
  702. console.log('所求三维向量有误, 请检查');
  703. return;
  704. }
  705. return vec;
  706. }
  707. /**
  708. * 根据sta查找点
  709. * @param {array} line1 第一条线段的点坐标
  710. * @param {array} line2 第二条线段的点坐标
  711. * @param {Boolean} sta 决定查找相同的点或不相同的点
  712. */
  713. function findPoint(line1, line2, sta) {
  714. if (!line1 || !line2) {
  715. console.log('线段未定义' + line1 + ' ' + line2);
  716. return null;
  717. }
  718. if (line1.length < 2 || line2.length < 2) {
  719. console.log('线段点坐标个数小于3, 请检查')
  720. return
  721. }
  722. if (sta === null || typeof sta === 'undefined') {
  723. sta = true;
  724. }
  725. // 根据sta值寻找当前线段与下一线段中符合要求的点
  726. for (let i = 0; i < line1.length; i++) {
  727. // sta为false, 寻找与下一线段都不相同的点
  728. if (!sta && sta === arrayEquals(line1[i], line2[0]) && sta === arrayEquals(line1[i], line2[1])) {
  729. return line1[i];
  730. }
  731. // sta为true, 寻找与下一线段相交的点
  732. if (sta && (sta === arrayEquals(line1[i], line2[0]) || sta === arrayEquals(line1[i], line2[1]))) {
  733. return line1[i];
  734. }
  735. }
  736. return null;
  737. }
  738. /**
  739. * 判断两个数组是否相等
  740. * @param {array} array1
  741. * @param {array} array2
  742. */
  743. function arrayEquals(array1, array2) {
  744. if (!array1 || !array2) {
  745. return false;
  746. }
  747. if (array1.length !== array2.length) {
  748. return false;
  749. }
  750. for (let i = 0, len = array1.length; i < len; i++) {
  751. if (array1[i] instanceof Array && array2[i] instanceof Array) {
  752. if (!arrayEquals(array1[i], array2[2])) {
  753. return false;
  754. }
  755. } else if (array1[i] !== array2[i]) {
  756. return false;
  757. }
  758. }
  759. return true;
  760. }
  761. /**
  762. * 判断一个数组中的元素是否都包含在另一个数组中
  763. * @param {array} arrays
  764. * @param {array} array2
  765. * @returns {boolean} true-表示数组元素唯一, false表示数组元素不唯一
  766. */
  767. function arrayOnly(array1, array2) {
  768. if (!array1 || !array2) {
  769. console.log('数组未定义, 请检查');
  770. return;
  771. }
  772. if (!array1.length || !array2.length || array1.length === 0) {
  773. return false;
  774. }
  775. for (let i = 0; i < array1.length; i++) {
  776. let num = 0;
  777. for (let j = 0; j < array1[i].length; j++) {
  778. if (array2.indexOf(array1[i][j]) >= 0) {
  779. // return false;
  780. num++;
  781. }
  782. }
  783. if (num === array1[i].length) {
  784. return true;
  785. }
  786. }
  787. return false;
  788. }