function DBSCAN(t,e,i,s){this.dataset=[],this.epsilon=1,this.minPts=2,this.distance=this._euclideanDistance,this.clusters=[],this.noise=[],this._visited=[],this._assigned=[],this._datasetLength=0,this._init(t,e,i,s)}function KMEANS(t,e,i){this.k=3,this.dataset=[],this.assignments=[],this.centroids=[],this.init(t,e,i)}function PriorityQueue(t,e,i){this._queue=[],this._priorities=[],this._sorting="desc",this._init(t,e,i)}function OPTICS(t,e,i,s){this.epsilon=1,this.minPts=1,this.distance=this._euclideanDistance,this._reachability=[],this._processed=[],this._coreDistance=0,this._orderedList=[],this._init(t,e,i,s)}function Utils(){}if(DBSCAN.prototype.run=function(t,e,i,s){this._init(t,e,i,s);for(var r=0;r=this.minPts&&(e=this._mergeArrays(e,r))}1!==this._assigned[s]&&this._addToCluster(s,t)}},DBSCAN.prototype._addToCluster=function(t,e){this.clusters[e].push(t),this._assigned[t]=1},DBSCAN.prototype._regionQuery=function(t){for(var e=[],i=0;is;s++){var r=e[s];t.indexOf(r)<0&&t.push(r)}return t},DBSCAN.prototype._euclideanDistance=function(t,e){for(var i=0,s=Math.min(t.length,e.length);s--;)i+=(t[s]-e[s])*(t[s]-e[s]);return Math.sqrt(i)},"undefined"!=typeof module&&module.exports&&(module.exports=DBSCAN),KMEANS.prototype.init=function(t,e,i){this.assignments=[],this.centroids=[],"undefined"!=typeof t&&(this.dataset=t),"undefined"!=typeof e&&(this.k=e),"undefined"!=typeof i&&(this.distance=i)},KMEANS.prototype.run=function(t,e){this.init(t,e);for(var i=this.dataset.length,s=0;sa;a++)o[a]=0;for(var u=0;i>u;u++){var d=this.dataset[u].length;if(n===this.assignments[u]){for(var a=0;d>a;a++)o[a]+=this.dataset[u][a];h++}}if(h>0){for(var a=0;d>a;a++)o[a]/=h;this.centroids[n]=o}else this.centroids[n]=this.randomCentroid(),r=!0}}return this.getClusters()},KMEANS.prototype.randomCentroid=function(){var t,e,i=this.dataset.length-1;do e=Math.round(Math.random()*i),t=this.dataset[e];while(this.centroids.indexOf(t)>=0);return t},KMEANS.prototype.assign=function(){for(var t,e=!1,i=this.dataset.length,s=0;i>s;s++)t=this.argmin(this.dataset[s],this.centroids,this.distance),t!=this.assignments[s]&&(this.assignments[s]=t,e=!0);return e},KMEANS.prototype.getClusters=function(){for(var t,e=new Array(this.k),i=0;ih;h++)s=i(t,e[h]),r>s&&(r=s,n=h);return n},KMEANS.prototype.distance=function(t,e){for(var i=0,s=Math.min(t.length,e.length);s--;){var r=t[s]-e[s];i+=r*r}return Math.sqrt(i)},"undefined"!=typeof module&&module.exports&&(module.exports=KMEANS),PriorityQueue.prototype.insert=function(t,e){for(var i=this._queue.length,s=i;s--;){var r=this._priorities[s];"desc"===this._sorting?e>r&&(i=s):r>e&&(i=s)}this._insertAt(t,e,i)},PriorityQueue.prototype.remove=function(t){for(var e=this._queue.length;e--;){var i=this._queue[e];if(t===i){this._queue.splice(e,1),this._priorities.splice(e,1);break}}},PriorityQueue.prototype.forEach=function(t){this._queue.forEach(t)},PriorityQueue.prototype.getElements=function(){return this._queue},PriorityQueue.prototype.getElementPriority=function(t){return this._priorities[t]},PriorityQueue.prototype.getPriorities=function(){return this._priorities},PriorityQueue.prototype.getElementsWithPriorities=function(){for(var t=[],e=0,i=this._queue.length;i>e;e++)t.push([this._queue[e],this._priorities[e]]);return t},PriorityQueue.prototype._init=function(t,e,i){if(t&&e){if(this._queue=[],this._priorities=[],t.length!==e.length)throw new Error("Arrays must have the same length");for(var s=0;sr;r++)if(1!==this._processed[r]){this._processed[r]=1,this.clusters.push([r]);var o=this.clusters.length-1;this._orderedList.push(r);var h=new PriorityQueue(null,null,"asc"),a=this._regionQuery(r);void 0!==this._distanceToCore(r)&&(this._updateQueue(r,a,h),this._expandCluster(o,h))}return this.clusters},OPTICS.prototype.getReachabilityPlot=function(){for(var t=[],e=0,i=this._orderedList.length;i>e;e++){var s=this._orderedList[e],r=this._reachability[s];t.push([s,r])}return t},OPTICS.prototype._init=function(t,e,i,s){if(t){if(!(t instanceof Array))throw Error("Dataset must be of type array, "+typeof t+" given");this.dataset=t,this.clusters=[],this._reachability=new Array(this.dataset.length),this._processed=new Array(this.dataset.length),this._coreDistance=0,this._orderedList=[]}e&&(this.epsilon=e),i&&(this.minPts=i),s&&(this.distance=s)},OPTICS.prototype._updateQueue=function(t,e,i){var s=this;this._coreDistance=this._distanceToCore(t),e.forEach(function(e){if(void 0===s._processed[e]){var r=s.distance(s.dataset[t],s.dataset[e]),n=Math.max(s._coreDistance,r);void 0===s._reachability[e]?(s._reachability[e]=n,i.insert(e,n)):ns;s++){var n=i[s];if(void 0===this._processed[n]){var o=this._regionQuery(n);this._processed[n]=1,this.clusters[t].push(n),this._orderedList.push(n),void 0!==this._distanceToCore(n)&&(this._updateQueue(n,o,e),this._expandCluster(t,e))}}},OPTICS.prototype._distanceToCore=function(t){for(var e=this.epsilon,i=0;e>i;i++){var s=this._regionQuery(t,i);if(s.length>=this.minPts)return i}},OPTICS.prototype._regionQuery=function(t,e){e=e||this.epsilon;for(var i=[],s=0,r=this.dataset.length;r>s;s++)this.distance(this.dataset[t],this.dataset[s])n;n++){var o=t[n],h=Math.max(o.center-o.min,o.center-o.max);h>r&&(r=h)}for(var n=0;e>n;n++){var a=2*Math.random()-1;i.push(a),s+=a*a}s=Math.sqrt(s);for(var n=0;e>n;n++)i[n]/=s,i[n]*=r,i[n]+=t[n].center;return i},"undefined"!=typeof module&&module.exports&&(module.exports={DBSCAN:require("./DBSCAN.js"),KMEANS:require("./KMEANS.js"),OPTICS:require("./OPTICS.js"),PriorityQueue:require("./PriorityQueue.js")}); /** * 方格聚合算法 * 1、根据 range 将当前屏幕分割成由 n 个正方形组成的矩形 * 2、遍历传过来的 posArr * 3、计算每个 pos 对应所在的格子 */ function getGridGroup(arrPos,range){ let width = 1870; let heigh = 917; let row = parseInt(heigh/range)+1; let col = parseInt(width/range)+1; let res = []; let resGroup = []; arrPos.forEach((screenPos,index)=>{ // screenPos[0] -> x // screenPos[1] -> y let x = parseInt(screenPos[0]/range); let y = parseInt(screenPos[1]/range); let nowGridIndex = parseInt((x*col + y)/range); if(!res[nowGridIndex]){ res[nowGridIndex] = [] } res[nowGridIndex].push(index) }) res.forEach(i=>{ if(i.length>1){ resGroup.push(i) } }) return resGroup } let dbscan = new DBSCAN(); let kmeans = new KMEANS(); this.addEventListener('message',(msg)=>{ let posArr = JSON.parse(msg.data.posArr); // this.postMessage({res:dbscan.run(posArr,msg.data.range),key:msg.data.key}); // this.postMessage({res:kmeans.run(posArr),key:msg.data.key}); this.postMessage({res:getGridGroup(posArr,msg.data.range),key:msg.data.key}); })