ts/public/GV/resources/workers/cluster.worker.js

44 lines
8.9 KiB
JavaScript
Raw Normal View History

2024-12-09 06:44:52 +00:00
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._datasetLength;r++)if(1!==this._visited[r]){this._visited[r]=1;var n=this._regionQuery(r);if(n.length<this.minPts)this.noise.push(r);else{var o=this.clusters.length;this.clusters.push([]),this._addToCluster(r,o),this._expandCluster(o,n)}}return this.clusters},DBSCAN.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.noise=[],this._datasetLength=t.length,this._visited=new Array(this._datasetLength),this._assigned=new Array(this._datasetLength)}e&&(this.epsilon=e),i&&(this.minPts=i),s&&(this.distance=s)},DBSCAN.prototype._expandCluster=function(t,e){for(var i=0;i<e.length;i++){var s=e[i];if(1!==this._visited[s]){this._visited[s]=1;var r=this._regionQuery(s);r.length>=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;i<this._datasetLength;i++){var s=this.distance(this.dataset[t],this.dataset[i]);s<this.epsilon&&e.push(i)}return e},DBSCAN.prototype._mergeArrays=function(t,e){for(var i=e.length,s=0;i>s;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;s<this.k;s++)this.centroids[s]=this.randomCentroid();for(var r=!0;r;){r=this.assign();for(var n=0;n<this.k;n++){for(var o=new Array(d),h=0,a=0;d>a;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;i<this.assignments.length;i++)t=this.assignments[i],"undefined"==typeof e[t]&&(e[t]=[]),e[t].push(i);return e},KMEANS.prototype.argmin=function(t,e,i){for(var s,r=Number.MAX_VALUE,n=0,o=e.length,h=0;o>h;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.splic
/**
* 方格聚合算法
* 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});
})