// 归一化 function normalize(xyz) { var _mo_ = Math.sqrt(xyz[0] * xyz[0] + xyz[1] * xyz[1] + xyz[2] * xyz[2]); var x = xyz[0] / _mo_; var y = xyz[1] / _mo_; var z = xyz[2] / _mo_; return [x, y, z]; } // 向量归一化 function normalizeV(xy) { var _mo_ = Math.sqrt(xy[0] * xy[0] + xy[1] * xy[1]); var x = xy[0] / _mo_; var y = xy[1] / _mo_; // var z = xyz[2] / _mo_; return [x, y]; } /** * 画线 * @param {*} arr * @param {*} context * @param {*} color * @param {*} w * @param {*} h * @param {*} isClear */ function circularLine(arr, context, color,cam_pos, w, h, isClear) { if (isClear) { context.clearRect(0, 0, w, h); // context.translate(w/2, h/2); } if (cam_pos.length>0) { for (let i = 0; i < cam_pos.length; i++) { const element = cam_pos[i]; draw_point(context,element,w,h) } } context.strokeStyle = color; context.lineWidth = 4; context.beginPath(); context.moveTo(arr[0][0] * w/2, arr[0][1] * h/2); for (let i = 0; i < arr.length; i++) { context.lineTo(arr[i][0] * w/2, arr[i][1] * h/2); } context.closePath(); context.stroke(); } /** * 选择线 * @param {*} current * @param {*} cubeLine * @param {*} w * @param {*} h */ function selectLine(current, cubeLine, w, h) { for (let i = 0; i < cubeLine.length; i++) { for (let j = 0; j < cubeLine[i].line.length; j++) { if (isInLine(current, cubeLine[i].line[j], w, h)) { // return current,arr[i] return [cubeLine[i].line[j],cubeLine[i]['room']]; } } } return []; } function _getWhichPoint(line, current, verticalLine, cubeLine, cube,w,h) { current = [current[0]/w*2,current[1]/h*2] var direction=0; if (verticalLine[0]) { direction = 0 } if (verticalLine[1]) { direction = 1 } for (let i = 0; i < cube.length; i++) { for (let j = 0; j < cube[i].points.length; j++) { if ( cube[i].points[j]["id"] === line["_3d_point1"]["point_id"] || cube[i].points[j]["id"] === line["_3d_point2"]["point_id"] ) { // cube[i].points[j]['data'][0] = current[0] cube[i].points[j]["data"][direction] = current[direction]; } } } // for (let i = 0; i < cubeLine.length; i++) { // for (let j = 0; j < cubeLine[i].line.length; j++) { // if ( // cubeLine[i].line[j]["_3d_point1"]["point_id"] === // line["_3d_point1"]["point_id"] || // cubeLine[i].line[j]["_3d_point1"]["point_id"] === // line["_3d_point2"]["point_id"] // ) { // cubeLine[i].line[j]["_3d_point1"]["data"][direction] = current[direction]; // } // if ( // cubeLine[i].line[j]["_3d_point2"]["point_id"] === // line["_3d_point1"]["point_id"] || // cubeLine[i].line[j]["_3d_point2"]["point_id"] === // line["_3d_point2"]["point_id"] // ) { // cubeLine[i].line[j]["_3d_point2"]["data"][direction] = current[direction]; // } // } // } return [cubeLine, cube]; } /** * 判断是否在线上 * @param {*} current * @param {*} arr * @param {*} w * @param {*} h */ function isInLine(current, arr, w, h) { var accuay = 2; var minX = arr["_3d_point1"]["data"][0], minY = arr["_3d_point1"]["data"][1], maxX = arr["_3d_point1"]["data"][0], maxY = arr["_3d_point1"]["data"][1]; minX = Math.min(minX, arr["_3d_point1"]["data"][0]); maxX = Math.max(maxX, arr["_3d_point1"]["data"][0]); minY = Math.min(minY, arr["_3d_point1"]["data"][1]); maxY = Math.max(maxY, arr["_3d_point1"]["data"][1]); minX = Math.min(minX, arr["_3d_point2"]["data"][0]); maxX = Math.max(maxX, arr["_3d_point2"]["data"][0]); minY = Math.min(minY, arr["_3d_point2"]["data"][1]); maxY = Math.max(maxY, arr["_3d_point2"]["data"][1]); return ( current[0] >= minX * w/2 - accuay && current[0] <= maxX * w/2 + accuay && current[1] >= minY * h/2 - accuay && current[1] <= maxY * h/2 + accuay ); } /** * 计算向量的垂直向量 * @param {向量} arr */ function verticalLine(arr) { if (arr.length !== 0) { var x, y; y = Math.sqrt(1 / ((arr[1] * arr[1]) / (arr[0] * arr[0]) + 1)); x = Math.sqrt(1 - y * y); return [x, y]; } return []; } function getPointFromLine(line) { var ret = [] var temp for (let i = 0; i < line.length; i++) { temp = [] for (let j = 0; j < line[i].line.length; j++) { temp.push(line[i].line[j]['_3d_point2']['data']) } ret.push(temp) } } /** * 根据顶点数据获取向量数据 * @param {顶点数据} cube */ function changeData(cube) { let ret = [] let item = [] ; for (let i = 0; i < cube.length; i++) { item = [] for (let j = 0; j < cube[i].points.length; j++) { if (j+1 minX * scaleTime && current[0] < maxX * scaleTime && current[1] > minY * scaleTimeH && current[1] < maxY * scaleTimeH ); } /** * 计算两线段的交点 * @param {线段一端点} a * @param {线段一端点} b * @param {线段二端点} c * @param {线段二端点} d */ function segmentsIntr(a, b, c, d){ // 三角形abc 面积的2倍 var area_abc = (a.x - c.x) * (b.y - c.y) - (a.y - c.y) * (b.x - c.x); // 三角形abd 面积的2倍 var area_abd = (a.x - d.x) * (b.y - d.y) - (a.y - d.y) * (b.x - d.x); // 面积符号相同则两点在线段同侧,不相交 (对点在线段上的情况,本例当作不相交处理); if ( area_abc*area_abd>=0 ) { return false; } // 三角形cda 面积的2倍 var area_cda = (c.x - a.x) * (d.y - a.y) - (c.y - a.y) * (d.x - a.x); // 三角形cdb 面积的2倍 // 注意: 这里有一个小优化.不需要再用公式计算面积,而是通过已知的三个面积加减得出. var area_cdb = area_cda + area_abc - area_abd ; if ( area_cda * area_cdb >= 0 ) { return false; } //计算交点坐标 var t = area_cda / ( area_abd- area_abc ); var dx= t*(b.x - a.x), dy= t*(b.y - a.y); return toDecimal({ x: a.x + dx , y: a.y + dy }); } /** * 判断一个点是否在面上 * @param {点} point * @param {面} vs */ function pointInside(point, vs) { // ray-casting algorithm based on // http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html let temp = [] for (let i = 0; i < vs.points.length; i++) { temp.push(vs.points[i]['data']) } var x = point[0], y = point[1]; var inside = false; for (var i = 0, j = temp.length - 1; i < temp.length; j = i++) { var xi = temp[i][0], yi = temp[i][1]; var xj = temp[j][0], yj = temp[j][1]; var intersect = ((yi > y) != (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi); if (intersect) inside = !inside; } return inside; }; function cubePointInFace(selectRoomId,cube,cubeLine) { let selectCube let ret = [] for (let i = 0; i < cube.length; i++) { if (cube[i]['roomId']==selectRoomId) { selectCube = cube[i] for (let j = 0; j < cube[i].points.length; j++) { pointInside(cube[i].points[j]['data'],f_cube[0]) } } } for (let i = 0; i < cube.length; i++) { if (cube[i]['roomId']!==selectRoomId) { for (let j = 0; j < selectCube.points.length; j++) { if (pointInside(selectCube.points[j]['data'],cube[i])) { ret.push(selectCube.points[j]['data']) } } } } return ret } /** * 找出相交线的交点 * @param {线段数组} cubeLine */ function intersect(selectRoomId,cubeLine) { //获取选中面的每条线段 let selectCubeVector = []; let ret = [] for (let i = 0; i < cubeLine.length; i++) { if (cubeLine[i]['room']===selectRoomId) { for (let j = 0; j < cubeLine[i].line.length; j++) { // segmentsIntr(cubeLine[i].line) // cubeLine[i].line[j]['_vector'] selectCubeVector.push([{ x:cubeLine[i].line[j]['_3d_point1']['data'][0], y:cubeLine[i].line[j]['_3d_point1']['data'][1], },{ x:cubeLine[i].line[j]['_3d_point2']['data'][0], y:cubeLine[i].line[j]['_3d_point2']['data'][1], }]) } } } for (let i = 0; i < cubeLine.length; i++) { //未选中的房间 if (cubeLine[i]['room']!==selectRoomId) { for (let k = 0; k < selectCubeVector.length; k++) { for (let l = 0; l < cubeLine[i].line.length; l++) { let item = [{ x:cubeLine[i].line[l]['_3d_point1']['data'][0], y:cubeLine[i].line[l]['_3d_point1']['data'][1], },{ x:cubeLine[i].line[l]['_3d_point2']['data'][0], y:cubeLine[i].line[l]['_3d_point2']['data'][1], }] if ((segmentsIntr(selectCubeVector[k][0],selectCubeVector[k][1],item[0],item[1]))) { let tempItem = segmentsIntr(selectCubeVector[k][0],selectCubeVector[k][1],item[0],item[1]) //判断该交点不是面的顶点 if ((selectCubeVector[k][0]['x']==tempItem['x'] && selectCubeVector[k][0]['y']==tempItem['y']) || (selectCubeVector[k][1]['x']==tempItem['x'] && selectCubeVector[k][1]['y']==tempItem['y']) || (item[0]['x']==tempItem['x']&&item[0]['y']==tempItem['y']) || (item[1]['x']==tempItem['x']&&item[1]['y']==tempItem['y'])) { } else{ ret.push(segmentsIntr(selectCubeVector[k][0],selectCubeVector[k][1],item[0],item[1])) } } } } } } return ret } function pushInNewCube(inFaceArr,intersectArr,cube) { let count = 0; let temp = [] let item for (let i = 0; i < cube.length; i++) { item = [] for (let j = 0; j < cube[i].points.length; j++) { let ele = cube[i].points[j]; item.push(ele['data']) } for (let l = 0; l < intersectArr.length; l++) { let el = intersectArr[l]; item.push([el.x,el.y]) } for (let k = 0; k < inFaceArr.length; k++) { let element = inFaceArr[k]; item.push(element) } temp.push(item) } return changeCube(temp) } function changeCube(arr) { let item; let ret = []; let count = 0 for (let i = 0; i < arr.length; i++) { const element = arr[i]; item = [] for (let j = 0; j < arr[i].length; j++) { count++ item.push({ id:count, data:arr[i][j], }) } ret.push({ roomId:i, points:item }) } return ret } function draw_point(ctx, point,w,h) { ctx.fillStyle="#00cc00"; ctx.fillRect(point.x*w-4,point.y*h-4,4,4); } /** * 判断选择的cube相机位置是否在面内 * @param {选择的面id} selectFaceId * @param {*} cube */ function pointInSelectFace(selectFaceId,cube) { for (let i = 0; i < cube.length; i++) { const element = cube[i]; if (element['roomId'] ===selectFaceId) { for (let j = 0; j < element['campos'].length; j++) { if (!pointInside([element['campos'][j].x,element['campos'][j].y],element)) { return false } } } } return true } /** * 判断交点是否为顶点 * @param {交点坐标} intersectArr * @param {顶点数组} cube */ function interectNotInPoint(intersectArr,cube) { if (intersectArr.length>0) { for (let k = 0; k < intersectArr.length; k++) { for (let i = 0; i < cube.length; i++) { let element = cube[i]; for (let j = 0; j < element['points'].length; j++) { let ele = element['points'][j]['data']; if (intersectArr[k].x==ele[0]&&intersectArr[k].y==ele[1]) { return true } } } } return false } return false } /** * * @param {原生数据} raw_cube */ function rawToCube(raw_cube,w,h) { let item; let count = 0 let ret = []; for (let i = 0; i < raw_cube.length; i++) { item = { roomId:i, campos:[ { x:-0.1, y:0.25 } ], points:[] } for (let j = 0; j < raw_cube[i].point.length; j++) { count++ let element = raw_cube[i].point[j]; let norV = fixRawData([element['x'],element['y']],w,h) item.points.push({ id:count, data:norV }) } ret.push(item) } return ret } /** * 将鼠标点击起始点移到中心 * @param {鼠标点} xy */ function calculateXY(xy,w,h) { return [xy[0]-w/2,xy[1]-h/2] } function fixRawData(xy,w,h) { return [xy[0]*50 / w,xy[1]*50 / h] } /** * 四舍五入保留7位小数 * @param {数组} arr */ function toDecimal(arr) { var xf = parseFloat(arr.x); var yf = parseFloat(arr.y); if (isNaN(xf) || isNaN(yf)) { return; } tx = Math.round(xf * 10e6) / 10e6; ty = Math.round(yf * 10e6) / 10e6; return {x:tx,y:ty}; } function calculateRawData(data) { let {vertex,room} = data let item let ret = [] for (let i = 0; i < room.length; i++) { let element = room[i]; item = { point:[] } for (let j = 0; j < element.length; j++) { let ele = element[j]; for (let a = 0; a < vertex.length; a++) { if (a === ele) { item.point.push(vertex[a]) } } } ret.push(item) } return ret }