determineFace.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. let faceAry = [];
  2. let keys = ['2d_point1', '2d_point2'];
  3. let lineKey = 'panorama_line_2d';
  4. let startPoint = [];
  5. let face = [];
  6. let negativeXVec = [-0.01, 0] // 以相同点为起点, 0.01为单位长度, 沿x轴负半轴求出单位向量
  7. let num = 0;
  8. let startLine = null;
  9. // rx1 = _3dLine(r2x, r3x, ret);
  10. var line_2d = _3dTo2d(
  11. make_matrix_from_quat([
  12. 0.008515,
  13. -0.014279,
  14. 0.016179,
  15. 0.999731,
  16. -5.438891,
  17. 2.167653,
  18. 0.165233
  19. ]),
  20. rx1,
  21. 0.05
  22. )['to3d']
  23. // console.log('====================================');
  24. // console.log('line_2d',line_2d);
  25. // console.log('====================================');
  26. /**
  27. * 寻找所有通过point相交的线段
  28. * @param {array} pointAry
  29. */
  30. function findIntersectLine() {
  31. let lineLen = line_2d.panorama_line_2d.length;
  32. console.time();
  33. // 对数组中的每条线段进行循环, 从第一个点开始
  34. for (let i = 0; i < lineLen; i++) {
  35. let curline = line_2d[lineKey][i];
  36. if (startLine && curline['3d_id'] === startLine['3d_id']) {
  37. continue;
  38. }
  39. // console.log(i);
  40. startLine = curline;
  41. let curPoint = startPoint = curline['2d_point1'];
  42. let nextPoint = null;
  43. let faceLine = [];
  44. while (true) {
  45. let data = find2dSamePoint(curPoint);
  46. let samePointNum = data.samePointNum; // 记录相同点的个数;
  47. let samePointLineAry = data.samePointLineAry; // 具有相同点的线段集合
  48. if (samePointNum === 1|| faceLine.length > 4) {
  49. // faceLine.indexOf(curline['3d_id']) < 0 && faceLine.push(curline['3d_id']); // 记录最后一条线段的3d_id
  50. // !arrayOnly(faceAry, faceLine) && faceAry.push(faceLine);
  51. // console.log(faceLine)
  52. break;
  53. }
  54. if (samePointNum === 2) { // 仅有两条线段相交于该点
  55. faceLine.indexOf(curline['3d_id']) < 0 && faceLine.push(curline['3d_id']);
  56. curline = findLineBesideTwoId(samePointLineAry, curline['2d_id']); // 寻找下一线段, 并设为当前线段
  57. // curPoint = curline['2d_point2']; // 下一线段终点
  58. curPoint = findNextPoint(curline, curPoint); // 查找线段中与当前点不同的另一端点
  59. // console.log(curline);
  60. if (arrayEquals(startPoint, curPoint)) { // 如果下一线段的终点为起始点, 则已形成闭环, 本次查找结束
  61. faceLine.indexOf(curline['3d_id']) < 0 && faceLine.push(curline['3d_id']); // 记录最后一条线段的3d_id
  62. !arrayOnly(faceAry, faceLine) && faceAry.push(faceLine);
  63. // console.log(faceLine)
  64. break;
  65. }
  66. }
  67. if (samePointNum >= 3) { // 有3条及3条以上的线段相交于该点
  68. let standardLine = findLineContainKey(samePointLineAry, curline['3d_id']); // 获取反向线段并作为基准线段
  69. let endPoint = findNextPoint(standardLine, curPoint); // 查找线段中与当前点不同的另一端点
  70. // if (arrayEquals(startPoint, curPoint)) { // 如果下一线段的终点为起始点, 则已形成闭环, 本次查找结束
  71. // faceLine.indexOf(curline['3d_id']) < 0 && faceLine.push(curline['3d_id']); // 记录最后一条线段的3d_id
  72. // console.log(faceLine)
  73. // break;
  74. // }
  75. let standardVec = getVector(standardLine, curPoint);
  76. let standardAngle = getAngle(negativeXVec, standardVec, standardLine);
  77. let positiveLines = findLineBesideKey(samePointLineAry, standardLine['3d_id']); // 获取正向线段的集合
  78. let min_s_c_angle = 500; // 最小的标准线与比较线夹角
  79. let rightLine = null; // 最右线段
  80. for (let j = 0; j < positiveLines.length; j++) { // 分别求出正向线段的向量
  81. let postiveVec = getVector(positiveLines[j], curPoint);
  82. let postiveAngle = getAngle(negativeXVec, postiveVec);
  83. if (standardAngle < postiveAngle) {
  84. // let s_c_angle = 360 - (postiveAngle - standardAngle);
  85. let s_c_angle = 360 - (postiveAngle - standardAngle);
  86. // 查找最大夹角并记录最右线段
  87. s_c_angle < min_s_c_angle && (min_s_c_angle = s_c_angle, rightLine = positiveLines[j]);
  88. }
  89. if (standardAngle > postiveAngle) {
  90. // let s_c_angle = 360 - (standardAngle - postiveAngle);
  91. let s_c_angle = standardAngle - postiveAngle;
  92. s_c_angle < min_s_c_angle && (min_s_c_angle = s_c_angle, rightLine = positiveLines[j]);
  93. }
  94. }
  95. faceLine.indexOf(rightLine['3d_id']) < 0 && faceLine.push(rightLine['3d_id']);
  96. curline = rightLine; // 寻找下一线段, 并设为当前线段
  97. // curPoint = curline['2d_point2']; // 下一线段终点
  98. curPoint = findNextPoint(curline, curPoint); // 查找线段中与当前点不同的另一端点
  99. // console.log(standardVec);
  100. // return;
  101. }
  102. }
  103. // num++;
  104. // console.log(num)
  105. // console.log(faceLine)
  106. // console.log(num)
  107. if (num === 500) {
  108. console.log(faceLine);
  109. return;
  110. }
  111. }
  112. console.log('faceAry',faceAry);
  113. console.timeEnd();
  114. }
  115. /**
  116. * 求两向量之间的夹角
  117. * @param {array} standardVec 标准向量
  118. * @param {array} comparativeVec 被比较向量
  119. * @param {object} comparativeLine 被比较线段, 用于判断线段属于第几象限
  120. */
  121. function getAngle(standardVec, comparativeVec, comparativeLine) {
  122. if (!standardVec || !comparativeVec) {
  123. console.log('standardVec或comparativeVec未定义, 请检查');
  124. return;
  125. }
  126. if (standardVec.length < 2 || comparativeVec.length < 2) {
  127. console.log('standardVec或comparativeVec长度小于2, 请检查');
  128. return;
  129. }
  130. let s_x = standardVec[0];
  131. let s_y = standardVec[1];
  132. let c_x = comparativeVec[0];
  133. let c_y = comparativeVec[1];
  134. // 求内积
  135. let productValue = s_x * c_x + s_y * c_y;
  136. // 求向量的模
  137. let vs_val = Math.sqrt(s_x * s_x + s_y * s_y);
  138. let vc_val = Math.sqrt(c_x * c_x + c_y * c_y);
  139. // 求两向量间的cos值
  140. let cos_val = productValue / (vs_val * vc_val);
  141. let minAngle = Math.acos(cos_val) * 180 / Math.PI; // 求出的是与x轴负半轴之间的最小夹角
  142. // console.log(angle);
  143. comparativeVec[1] < 0 && (minAngle = 360 - minAngle);
  144. return minAngle;
  145. }
  146. /**
  147. * 获取线段象限
  148. * @param {object} line
  149. * @returns {Boolean} true-表示正半轴, false-表示负半轴
  150. */
  151. function getQuadrant(line) {
  152. if (!line) {
  153. console.log('line未定义, 请检查');
  154. return;
  155. }
  156. (line.reversed = null || typeof line.reversed === 'undefined') && (line.reversed = false);
  157. if ((line.reversed && line[keys[0]][1] > line[keys[1]][1]) || (!line.reversed && line[keys[1]][1] > line[keys[0]][1])) { // 翻转, 为point1-point2
  158. return true; // true-表示正半轴
  159. }
  160. if ((line.reversed && line[keys[0]][1] < line[keys[1]][1]) || (!line.reversed && line[keys[1]][1] < line[keys[0]][1])) {
  161. return false; // false-表示负半轴
  162. }
  163. }
  164. /**
  165. * 根据标准线段, 比较线段所处的象限来翻转角度(即360 - 最小angle)
  166. * @param {object} standardLine 标准线段
  167. * @param {object} comparativeLine 比较线段
  168. * @param {array} samePoint 相同点
  169. */
  170. function angleReverse(standardLine, comparativeLine, samePoint) {
  171. let origin_x = samePoint[0]; // 取相同点作为原点
  172. let origin_y = samePoint[1];
  173. let s_x = standardLine[keys[0]][0]; // 标准线段的终点是point1
  174. let s_y = standardLine[keys[0]][1];
  175. let c_x = comparativeLine[keys[1]][0]; // 比较线段的终点是point2
  176. let c_y = comparativeLine[keys[1]][1];
  177. // 标准线段位于第一象限, 或位于x轴负半轴
  178. if ((s_x < origin_x && s_y < origin_y) || (s_x < origin_x && s_y === origin_y)) {
  179. // 比较线段位于第一象限标准线的上方, 或位于第二象限, 或位于第三象限-s_y的上面
  180. if (c_y > s_y || (c_x > origin_x) || (c_x > origin_x && c_y > -s_y)) {
  181. return false; // 不用进行角度翻转
  182. }
  183. return true;
  184. }
  185. }
  186. /**
  187. * 根据相同点samePoint在线段中的位置来求对应的向量
  188. * @param {object} line
  189. * @param {array} samePoint
  190. */
  191. function getVector(line, samePoint) {
  192. if (!line) {
  193. console.log('line未定义, 请检查');
  194. return;
  195. }
  196. if (!samePoint || samePoint.length < 2) {
  197. console.log('samePoint未定义或长度小于2, 请检查');
  198. return;
  199. }
  200. for (let i = 0; i < keys.length; i++) {
  201. let key = keys[i];
  202. // 相同点是线段的第一个点, 则 point2 - point1 为该线段向量
  203. if (key === keys[0] && arrayEquals(line[key], samePoint)) {
  204. let vec_x = line[keys[1]][0] - line[keys[0]][0];
  205. let vec_y = line[keys[1]][1] - line[keys[0]][1];
  206. let vec = [vec_x, vec_y];
  207. line['vector2'] = vec;
  208. return vec;
  209. }
  210. // 相同点是线段的第二个点, 则 point1 - point2 为该线段向量
  211. if (key === keys[1] && arrayEquals(line[key], samePoint)) {
  212. let vec_x = line[keys[0]][0] - line[keys[1]][0];
  213. let vec_y = line[keys[0]][1] - line[keys[1]][1];
  214. let vec = [vec_x, vec_y];
  215. line['vector2'] = vec;
  216. return vec;
  217. }
  218. }
  219. }
  220. /**
  221. * 查找线段除point外的另一定点
  222. * @param {object} line
  223. * @param {array} point
  224. */
  225. function findNextPoint(line, point) {
  226. for (let i = 0; i < keys.length; i++) {
  227. if (!arrayEquals(line[keys[i]], point)) {
  228. return line[keys[i]];
  229. }
  230. }
  231. }
  232. /**
  233. * 仅有两个相同点的情况下调用, 查找含指定twoId之外的线段
  234. * @param {*} lineAry
  235. * @param {*} twoDId
  236. */
  237. function findLineBesideTwoId(lineAry, twoDId) {
  238. if (!lineAry) {
  239. console.log('lineAry未定义, 请检查');
  240. return null;
  241. }
  242. if (typeof twoDId !== 'number') {
  243. console.log('threeDId未定义, 请检查');
  244. return null;
  245. }
  246. for (let i = 0; i < lineAry.length; i++) {
  247. if (lineAry[i]['2d_id'] !== twoDId) {
  248. return lineAry[i];
  249. }
  250. }
  251. }
  252. /**
  253. * 在集合中寻找除了含threeDId之外的其他线段
  254. * @param {array} lineAry 线段集合
  255. * @param {number} threeDId 表示寻找正向还是反向线段
  256. */
  257. function findLineBesideKey(lineAry, threeDId) {
  258. if (!lineAry) {
  259. console.log('lineAry未定义, 请检查');
  260. return null;
  261. }
  262. if (typeof threeDId !== 'number') {
  263. console.log('threeDId未定义, 请检查');
  264. return null;
  265. }
  266. let positiveLines = [];
  267. for (let i = 0; i < lineAry.length; i++) {
  268. if (lineAry[i]['3d_id'] === threeDId) {
  269. continue;
  270. } else {
  271. positiveLines.push(lineAry[i]);
  272. }
  273. // if (reversed && lineAry[i].reversed === reversed) {
  274. // return lineAry[i];
  275. // }
  276. // if (!reversed && lineAry[i].reversed === reversed) {
  277. // positiveLines.push(lineAry[i]);
  278. // }
  279. }
  280. return positiveLines;
  281. }
  282. /**
  283. * 在集合中查找含有threeDId的线段
  284. * @param {array} lineAry 线段集合
  285. * @param {number} threeDId
  286. */
  287. function findLineContainKey(lineAry, threeDId) {
  288. if (!lineAry) {
  289. console.log('lineAry未定义, 请检查');
  290. return null;
  291. }
  292. if (typeof threeDId !== 'number') {
  293. console.log('threeDId未定义, 请检查');
  294. return null;
  295. }
  296. for (let i = 0; i < lineAry.length; i++) {
  297. if (lineAry[i]['3d_id'] === threeDId) {
  298. return lineAry[i];
  299. }
  300. }
  301. }
  302. /**
  303. * 寻找2D线段中的相同点
  304. * @param {array} curPoint 寻找与该点相交的其他点
  305. */
  306. function find2dSamePoint(curPoint) {
  307. let lineLen = line_2d.panorama_line_2d.length;
  308. let samePointNum = 0; // 记录相同点的个数;
  309. let samePointLineAry = []; // 具有相同点的线段集合
  310. // 对于指定点, 在集合的所有线段中寻找相同点
  311. for (let j = 0; j < lineLen; j++) {
  312. let comparativeLine = line_2d[lineKey][j];
  313. // 在线段中的两个点中寻找是否有相同点
  314. for (let k = 0; k < keys.length; k++) {
  315. let key = keys[k]
  316. if (arrayEquals(comparativeLine[key], curPoint)) {
  317. key === keys[0] ? comparativeLine.reversed = false : comparativeLine.reversed = true;
  318. samePointNum++;
  319. samePointLineAry.push(comparativeLine); // 记录具有相同点的线段
  320. }
  321. }
  322. }
  323. return {
  324. samePointNum: samePointNum,
  325. samePointLineAry: samePointLineAry
  326. }
  327. }