let faceAry = []; let keys = ['2d_point1', '2d_point2']; let lineKey = 'panorama_line_2d'; let startPoint = []; let face = []; let negativeXVec = [-0.01, 0] // 以相同点为起点, 0.01为单位长度, 沿x轴负半轴求出单位向量 let num = 0; let startLine = null; var rx1 = _3dLine(r2x, r3x, ret); var line_2d = _3dTo2d( make_matrix_from_quat([ 0.008515, -0.014279, 0.016179, 0.999731, -5.438891, 2.167653, 0.165233 ]), rx1, 0.05 )['to3d'] console.log('===================================='); console.log('line_2d',line_2d); console.log('===================================='); /** * 寻找所有通过point相交的线段 * @param {array} pointAry */ function findIntersectLine() { let lineLen = line_2d.panorama_line_2d.length; console.time(); // 对数组中的每条线段进行循环, 从第一个点开始 for (let i = 0; i < lineLen; i++) { let curline = line_2d[lineKey][i]; if (startLine && curline['3d_id'] === startLine['3d_id']) { continue; } // console.log(i); startLine = curline; let curPoint = startPoint = curline['2d_point1']; let nextPoint = null; let faceLine = []; while (true) { let data = find2dSamePoint(curPoint); let samePointNum = data.samePointNum; // 记录相同点的个数; let samePointLineAry = data.samePointLineAry; // 具有相同点的线段集合 if (samePointNum === 1) { // faceLine.indexOf(curline['3d_id']) < 0 && faceLine.push(curline['3d_id']); // 记录最后一条线段的3d_id // !arrayOnly(faceAry, faceLine) && faceAry.push(faceLine); // console.log(faceLine) break; } if (samePointNum === 2) { // 仅有两条线段相交于该点 faceLine.indexOf(curline['3d_id']) < 0 && faceLine.push(curline['3d_id']); curline = findLineBesideTwoId(samePointLineAry, curline['2d_id']); // 寻找下一线段, 并设为当前线段 // curPoint = curline['2d_point2']; // 下一线段终点 curPoint = findNextPoint(curline, curPoint); // 查找线段中与当前点不同的另一端点 // console.log(curline); if (arrayEquals(startPoint, curPoint)) { // 如果下一线段的终点为起始点, 则已形成闭环, 本次查找结束 faceLine.indexOf(curline['3d_id']) < 0 && faceLine.push(curline['3d_id']); // 记录最后一条线段的3d_id !arrayOnly(faceAry, faceLine) && faceAry.push(faceLine); // console.log(faceLine) break; } } if (samePointNum >= 3) { // 有3条及3条以上的线段相交于该点 let standardLine = findLineContainKey(samePointLineAry, curline['3d_id']); // 获取反向线段并作为基准线段 let endPoint = findNextPoint(standardLine, curPoint); // 查找线段中与当前点不同的另一端点 // if (arrayEquals(startPoint, curPoint)) { // 如果下一线段的终点为起始点, 则已形成闭环, 本次查找结束 // faceLine.indexOf(curline['3d_id']) < 0 && faceLine.push(curline['3d_id']); // 记录最后一条线段的3d_id // console.log(faceLine) // break; // } let standardVec = getVector(standardLine, curPoint); let standardAngle = getAngle(negativeXVec, standardVec, standardLine); let positiveLines = findLineBesideKey(samePointLineAry, standardLine['3d_id']); // 获取正向线段的集合 let min_s_c_angle = 500; // 最小的标准线与比较线夹角 let rightLine = null; // 最右线段 for (let j = 0; j < positiveLines.length; j++) { // 分别求出正向线段的向量 let postiveVec = getVector(positiveLines[j], curPoint); let postiveAngle = getAngle(negativeXVec, postiveVec); if (standardAngle < postiveAngle) { // let s_c_angle = 360 - (postiveAngle - standardAngle); let s_c_angle = 360 - (postiveAngle - standardAngle); // 查找最大夹角并记录最右线段 s_c_angle < min_s_c_angle && (min_s_c_angle = s_c_angle, rightLine = positiveLines[j]); } if (standardAngle > postiveAngle) { // let s_c_angle = 360 - (standardAngle - postiveAngle); let s_c_angle = standardAngle - postiveAngle; s_c_angle < min_s_c_angle && (min_s_c_angle = s_c_angle, rightLine = positiveLines[j]); } } faceLine.indexOf(rightLine['3d_id']) < 0 && faceLine.push(rightLine['3d_id']); curline = rightLine; // 寻找下一线段, 并设为当前线段 // curPoint = curline['2d_point2']; // 下一线段终点 curPoint = findNextPoint(curline, curPoint); // 查找线段中与当前点不同的另一端点 // console.log(standardVec); // return; } } // num++; // console.log(num) // console.log(faceLine) // console.log(num) if (num === 500) { console.log(faceLine); return; } } console.log('faceAry',faceAry); console.timeEnd(); } /** * 求两向量之间的夹角 * @param {array} standardVec 标准向量 * @param {array} comparativeVec 被比较向量 * @param {object} comparativeLine 被比较线段, 用于判断线段属于第几象限 */ function getAngle(standardVec, comparativeVec, comparativeLine) { if (!standardVec || !comparativeVec) { console.log('standardVec或comparativeVec未定义, 请检查'); return; } if (standardVec.length < 2 || comparativeVec.length < 2) { console.log('standardVec或comparativeVec长度小于2, 请检查'); return; } let s_x = standardVec[0]; let s_y = standardVec[1]; let c_x = comparativeVec[0]; let c_y = comparativeVec[1]; // 求内积 let productValue = s_x * c_x + s_y * c_y; // 求向量的模 let vs_val = Math.sqrt(s_x * s_x + s_y * s_y); let vc_val = Math.sqrt(c_x * c_x + c_y * c_y); // 求两向量间的cos值 let cos_val = productValue / (vs_val * vc_val); let minAngle = Math.acos(cos_val) * 180 / Math.PI; // 求出的是与x轴负半轴之间的最小夹角 // console.log(angle); comparativeVec[1] < 0 && (minAngle = 360 - minAngle); return minAngle; } /** * 获取线段象限 * @param {object} line * @returns {Boolean} true-表示正半轴, false-表示负半轴 */ function getQuadrant(line) { if (!line) { console.log('line未定义, 请检查'); return; } (line.reversed = null || typeof line.reversed === 'undefined') && (line.reversed = false); if ((line.reversed && line[keys[0]][1] > line[keys[1]][1]) || (!line.reversed && line[keys[1]][1] > line[keys[0]][1])) { // 翻转, 为point1-point2 return true; // true-表示正半轴 } if ((line.reversed && line[keys[0]][1] < line[keys[1]][1]) || (!line.reversed && line[keys[1]][1] < line[keys[0]][1])) { return false; // false-表示负半轴 } } /** * 根据标准线段, 比较线段所处的象限来翻转角度(即360 - 最小angle) * @param {object} standardLine 标准线段 * @param {object} comparativeLine 比较线段 * @param {array} samePoint 相同点 */ function angleReverse(standardLine, comparativeLine, samePoint) { let origin_x = samePoint[0]; // 取相同点作为原点 let origin_y = samePoint[1]; let s_x = standardLine[keys[0]][0]; // 标准线段的终点是point1 let s_y = standardLine[keys[0]][1]; let c_x = comparativeLine[keys[1]][0]; // 比较线段的终点是point2 let c_y = comparativeLine[keys[1]][1]; // 标准线段位于第一象限, 或位于x轴负半轴 if ((s_x < origin_x && s_y < origin_y) || (s_x < origin_x && s_y === origin_y)) { // 比较线段位于第一象限标准线的上方, 或位于第二象限, 或位于第三象限-s_y的上面 if (c_y > s_y || (c_x > origin_x) || (c_x > origin_x && c_y > -s_y)) { return false; // 不用进行角度翻转 } return true; } } /** * 根据相同点samePoint在线段中的位置来求对应的向量 * @param {object} line * @param {array} samePoint */ function getVector(line, samePoint) { if (!line) { console.log('line未定义, 请检查'); return; } if (!samePoint || samePoint.length < 2) { console.log('samePoint未定义或长度小于2, 请检查'); return; } for (let i = 0; i < keys.length; i++) { let key = keys[i]; // 相同点是线段的第一个点, 则 point2 - point1 为该线段向量 if (key === keys[0] && arrayEquals(line[key], samePoint)) { let vec_x = line[keys[1]][0] - line[keys[0]][0]; let vec_y = line[keys[1]][1] - line[keys[0]][1]; let vec = [vec_x, vec_y]; line['vector2'] = vec; return vec; } // 相同点是线段的第二个点, 则 point1 - point2 为该线段向量 if (key === keys[1] && arrayEquals(line[key], samePoint)) { let vec_x = line[keys[0]][0] - line[keys[1]][0]; let vec_y = line[keys[0]][1] - line[keys[1]][1]; let vec = [vec_x, vec_y]; line['vector2'] = vec; return vec; } } } /** * 查找线段除point外的另一定点 * @param {object} line * @param {array} point */ function findNextPoint(line, point) { for (let i = 0; i < keys.length; i++) { if (!arrayEquals(line[keys[i]], point)) { return line[keys[i]]; } } } /** * 仅有两个相同点的情况下调用, 查找含指定twoId之外的线段 * @param {*} lineAry * @param {*} twoDId */ function findLineBesideTwoId(lineAry, twoDId) { if (!lineAry) { console.log('lineAry未定义, 请检查'); return null; } if (typeof twoDId !== 'number') { console.log('threeDId未定义, 请检查'); return null; } for (let i = 0; i < lineAry.length; i++) { if (lineAry[i]['2d_id'] !== twoDId) { return lineAry[i]; } } } /** * 在集合中寻找除了含threeDId之外的其他线段 * @param {array} lineAry 线段集合 * @param {number} threeDId 表示寻找正向还是反向线段 */ function findLineBesideKey(lineAry, threeDId) { if (!lineAry) { console.log('lineAry未定义, 请检查'); return null; } if (typeof threeDId !== 'number') { console.log('threeDId未定义, 请检查'); return null; } let positiveLines = []; for (let i = 0; i < lineAry.length; i++) { if (lineAry[i]['3d_id'] === threeDId) { continue; } else { positiveLines.push(lineAry[i]); } // if (reversed && lineAry[i].reversed === reversed) { // return lineAry[i]; // } // if (!reversed && lineAry[i].reversed === reversed) { // positiveLines.push(lineAry[i]); // } } return positiveLines; } /** * 在集合中查找含有threeDId的线段 * @param {array} lineAry 线段集合 * @param {number} threeDId */ function findLineContainKey(lineAry, threeDId) { if (!lineAry) { console.log('lineAry未定义, 请检查'); return null; } if (typeof threeDId !== 'number') { console.log('threeDId未定义, 请检查'); return null; } for (let i = 0; i < lineAry.length; i++) { if (lineAry[i]['3d_id'] === threeDId) { return lineAry[i]; } } } /** * 寻找2D线段中的相同点 * @param {array} curPoint 寻找与该点相交的其他点 */ function find2dSamePoint(curPoint) { let lineLen = line_2d.panorama_line_2d.length; let samePointNum = 0; // 记录相同点的个数; let samePointLineAry = []; // 具有相同点的线段集合 // 对于指定点, 在集合的所有线段中寻找相同点 for (let j = 0; j < lineLen; j++) { let comparativeLine = line_2d[lineKey][j]; // 在线段中的两个点中寻找是否有相同点 for (let k = 0; k < keys.length; k++) { let key = keys[k] if (arrayEquals(comparativeLine[key], curPoint)) { key === keys[0] ? comparativeLine.reversed = false : comparativeLine.reversed = true; samePointNum++; samePointLineAry.push(comparativeLine); // 记录具有相同点的线段 } } } return { samePointNum: samePointNum, samePointLineAry: samePointLineAry } }