import * as THREE from "../../../libs/three.js/build/three.module.js"; var Common = { /* sortByScore: function(list, request, rank){ var i = request ? Common.filterAll(list, request) : list return 0 === i.length ? null : i = i.map(function(e) { return { item: e, score: rank.reduce(function(t, i) { return t + i(e) }, 0) } }).sort(function(e, t) { return t.score - e.score; }) } */ sortByScore: function(list, request, rank){ var i = request ? Common.filterAll(list, request) : list return 0 === i.length ? null : i = i.map(function(e) { let scores = rank.map(function(f){return f(e)}) //add return { item: e, scores, score: scores.reduce(function(t, i) { return t + i }, 0) } }).sort(function(e, t) { return t.score - e.score; }) } , filterAll: function(e, t) { return e.filter(function (e) { return t.every(function (t) { return t(e) }) }) }, //--------------- find : function(list, request, rank, sortByScore ) { if(sortByScore){ var r = this.sortByScore(list, request, rank) return r && r[0] && r[0].item }else{ var i = request ? Common.filterAll(list, request) : list return 0 === i.length ? null : (rank && rank.forEach(function(e) { i = Common.stableSort(i, e) }), i[0]) } } , stableSort: function(e, f) {//用到排序函数,涉及到两个item相减 return e.map(function(e, i) { return { value: e, index: i } }).sort(function(e, u) { var n = f(e.value, u.value); return 0 !== n ? n : e.index - u.index //似乎就是加多了这一步:若差距为0,按照原顺序 }).map(function(e) { return e.value }) }, average: function (e, t) { if (0 === e.length) return null; for (var i = 0, n = 0, r = 0; r < e.length; r++) { var o = t ? e[r][t] : e[r]; i += o, n++ } return i / n }, //--------------------------- getMixedSet : function(arr1, arr2){//交集 return arr1.filter(item=>arr2.includes(item)); }, getUnionSet : function(arr1, arr2){//并集 return arr1.concat(arr2.filter(item=>!arr1.includes(item))) }, getDifferenceSet : function(arr1, arr2){//差集 不能识别重复的,如getDifferenceSet([1,2,2],[1,1,2]) 为空 var arr11 = arr1.filter(item=>!arr2.includes(item)); var arr22 = arr2.filter(item=>!arr1.includes(item)); return arr11.concat(arr22) }, getDifferenceSetMuti : function(arr){//收集绝对没有重复的元素,也就是判断出现次数=1的 var set = []; arr.forEach(arr1=>{ arr1.forEach(item=>{ var index = set.indexOf(item) if(index>-1){ set.splice(index, 1) }else{ set.push(item) } }) }) return set; } , CloneJson : function(data){ var str = JSON.stringify(data) return JSON.parse(str) } , CloneObject : function(copyObj, result, isSimpleCopy, simpleCopyList=[]) { //isSimpleCopy 只复制最外层 //复制json result的可能:普通数字或字符串、普通数组、复杂对象 simpleCopyList.push(THREE.Object3D) //遇到simpleCopyList中的类直接使用不拷贝 if(!copyObj || typeof copyObj == 'number' || typeof copyObj == 'string' || copyObj instanceof Function || simpleCopyList.some(className => copyObj instanceof className)){ return copyObj } result = result || {}; if (copyObj instanceof Array) { return copyObj.map(e=>{ return this.CloneObject(e) }) }else{ if(copyObj.clone instanceof Function ){ //解决一部分 return copyObj.clone() } } for (var key in copyObj) { if (copyObj[key] instanceof Object && !isSimpleCopy) result[key] = this.CloneObject(copyObj[key]); else result[key] = copyObj[key]; //如果是函数类同基本数据,即复制引用 } return result; } , CloneClassObject :function(copyObj ){//复杂类对象 var newobj = new copyObj.constructor(); this.CopyClassObject(newobj, copyObj) return newobj } , CopyClassObject :function(targetObj, copyObj){//复杂类对象 for(let i in copyObj){ if(i in copyObj.__proto__)break; //到函数了跳出 targetObj[i] = this.CloneObject(copyObj[i], null ) /* else if(copyObj[i].clone instanceof Function ){ targetObj[i] = copyObj[i].clone() }else{ targetObj[i] = copyObj[i]; } */ } } , ifSame : function(object1, object2, simpleEqualClass=[]){ //对于复杂的类对象,若能简单判断就直接写进simpleEqualClass if(object1 == object2 )return true // 0 != undefined , 0 == '' else if(!object1 || !object2) return false else if(object1.constructor != object2.constructor){ return false }else if(simpleEqualClass.some(className => object1 instanceof className)){ return object1 == object2 }else if(object1 instanceof Array ) { if(object1.length != object2.length)return false; var _object2 = object2.slice(0); for(let i=0;iCommon.ifSame(object1[i], e, simpleEqualClass)); if(u == void 0 && !_object2.includes(u) && !object1.includes(u))return false; else{ let index = _object2.indexOf(u); _object2.splice(index,1); } } return true }else if(object1.equals instanceof Function ){//复杂数据仅支持这种,其他的可能卡住? return object1.equals(object2) }else if(typeof object1 == 'number' || typeof object1 == 'string'){ if(isNaN(object1) && isNaN(object2))return true else return object1 == object2 }else if(typeof object1 == "object"){ var keys1 = Object.keys(object1) var keys2 = Object.keys(object2) if(!Common.ifSame(keys1,keys2,simpleEqualClass))return false; for(let i in object1){ var same = Common.ifSame(object1[i], object2[i],simpleEqualClass); if(!same)return false } return true }else{ console.log('isSame出现例外') } } , replaceAll : function (str, f, e) { //f全部替换成e var reg = new RegExp(f, "g"); //创建正则RegExp对象 return str.replace(reg, e); } , downloadFile : function(data, filename, cb) { var save_link = document.createElementNS('http://www.w3.org/1999/xhtml', 'a'); save_link.href = data; save_link.download = filename; var event = document.createEvent('MouseEvents'); event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null); save_link.dispatchEvent(event); cb && cb(); }, intervalTool:{ //延时update,防止卡顿 list:[], isWaiting:function(name, func, delayTime){ if(!this.list.includes(name)){ //如果没有该项, 则开始判断 var needWait = func(); //触发了改变,则等待一段时间后再自动判断 if(needWait){ this.list.push(name); setTimeout(()=>{ var a = this.list.indexOf(name); this.list.splice(a,1); this.isWaiting(name, func, delayTime) //循环 },delayTime) } } }, /* wait:function(name, delayTime){ this.list.push(name); setTimeout(()=>{ },delayTime) }, */ } , pushToGroupAuto : function(items, groups, recognizeFunction){//自动分组。 items是将分到一起的组合。items.length = 1 or 2. recognizeFunction = recognizeFunction || function(){} var atGroups = groups.filter(group=>group.find( item => items[0] == item || recognizeFunction(item, items[0]) || items[1] == item || items[1] && recognizeFunction(item, items[1]) )) if(atGroups.length){//在不同组 //因为items是一组的,所以先都放入组1 items.forEach(item=> {if(!atGroups[0].includes(item)) atGroups[0].push(item);}) if(atGroups.length>1){//如果在不同组,说明这两个组需要合并 var combineGroup = [] atGroups.forEach(group=>{ combineGroup = Common.getUnionSet(combineGroup, group) groups.splice(groups.indexOf(group),1) }) groups.push(combineGroup) } }else{//直接加入为一组 groups.push(items) } }, getBestCount : function(name, minCount=1,maxCount=6, durBound1 = 1.2, durBound2 = 8, ifLog){ let timeStamp = performance.getEntriesByName("loop-start"); let count if(timeStamp.length){ let dur = performance.now() - timeStamp[timeStamp.length-1].startTime; let k = -(maxCount-minCount)/(durBound2 - durBound1) let m = maxCount - durBound1 * k count = THREE.MathUtils.clamp(Math.round(k * dur + m), minCount, maxCount ) //dur在iphoneX中静止有7,pc是2 if(ifLog){//注意,console.log本身用时挺高, 降4倍时可能占用0.5毫秒 name && console.log(name, count , ' ,dur:', dur) } }else{ count = maxCount // ? } //主要在手机端有效果。 return count }, batchHandling : {//分批处理 lists:[], getSlice : function(name, items , {stopWhenAllUsed, min=5,max=100, durBound1 , durBound2 }){ if(!this.lists[name]) this.lists[name] = {list:[] } //更新列表项目,但不变原来的顺序 let list = this.lists[name].list.filter(a=>items.some(item=>a.item == item))//去掉已经不在items里的项目 this.lists[name].list = list items.forEach(item=>{//增加新的项目。 if(!list.some(a=>a.item == item)){ list.push({item, count:0}) } }) //至此,在后排的都是未使用的 const maxUseCount = Common.getBestCount(name, min,max , durBound1, durBound2 /* , true */ ) ; //本次最多可以使用的个数 let unUsed = list.filter(e=>e.count == 0)//未使用的项目(count为0)优先 let result = [] unUsed.slice(0,maxUseCount).forEach(e=>{ result.push(e.item); e.count ++; }) if(unUsed.length > maxUseCount){ //还是剩有未使用的项目,等待下一次 }else{ //所有项目都能使用一次 if(!stopWhenAllUsed){ //若不是全部使用就停止 let wholeCount = Math.min(items.length, maxUseCount); let restCount = wholeCount - result.length; //补齐 list.slice(0,restCount).forEach(e=>{ result.push(e.item); e.count ++; }) } list.forEach(e=>e.count--) //复原,等待新的循环 } return {list:result } } }, } Potree.Common = Common export default Common