supercluster 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/supercluster-build.js +1 -1
- data/lib/supercluster.rb +17 -13
- metadata +5 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: efd0ad8ac6132db48162bd4a88f7ac536484e04c1264da89cce2e4dda74f7cc3
|
4
|
+
data.tar.gz: c8a7cda44c1aed69e45a3e7a8829dd49156392c528bd75a8d171691fb1252e79
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f2905a3182f1eae153e4cb402f345b7e26ef282e430e9540c6d9699bdf5e00ef60e9f400510aa5f35aeb2c2f829911eef9830c1da4107cf66a359cb0681d6da8
|
7
|
+
data.tar.gz: ba39da1c7b074a5e23823a510d1a0e417ac3d9ff4e7f54a68e2a44d24d2236819dcaa4f0c94c5e75883b968b2d714abda333a7c872585e1e2922f87046ae1099
|
data/lib/supercluster-build.js
CHANGED
@@ -1 +1 @@
|
|
1
|
-
!function(t){var n={};function e(o){if(n[o])return n[o].exports;var i=n[o]={i:o,l:!1,exports:{}};return t[o].call(i.exports,i,i.exports,e),i.l=!0,i.exports}e.m=t,e.c=n,e.d=function(t,n,o){e.o(t,n)||Object.defineProperty(t,n,{enumerable:!0,get:o})},e.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},e.t=function(t,n){if(1&n&&(t=e(t)),8&n)return t;if(4&n&&"object"==typeof t&&t&&t.__esModule)return t;var o=Object.create(null);if(e.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:t}),2&n&&"string"!=typeof t)for(var i in t)e.d(o,i,function(n){return t[n]}.bind(null,i));return o},e.n=function(t){var n=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(n,"a",n),n},e.o=function(t,n){return Object.prototype.hasOwnProperty.call(t,n)},e.p="",e(e.s=0)}([function(t,n,e){(function(t){
|
1
|
+
!function(t){var n={};function e(o){if(n[o])return n[o].exports;var i=n[o]={i:o,l:!1,exports:{}};return t[o].call(i.exports,i,i.exports,e),i.l=!0,i.exports}e.m=t,e.c=n,e.d=function(t,n,o){e.o(t,n)||Object.defineProperty(t,n,{enumerable:!0,get:o})},e.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},e.t=function(t,n){if(1&n&&(t=e(t)),8&n)return t;if(4&n&&"object"==typeof t&&t&&t.__esModule)return t;var o=Object.create(null);if(e.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:t}),2&n&&"string"!=typeof t)for(var i in t)e.d(o,i,function(n){return t[n]}.bind(null,i));return o},e.n=function(t){var n=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(n,"a",n),n},e.o=function(t,n){return Object.prototype.hasOwnProperty.call(t,n)},e.p="",e(e.s=0)}([function(t,n,e){(function(t){t.Supercluster=e(2).default}).call(this,e(1))},function(t,n){var e;e=function(){return this}();try{e=e||new Function("return this")()}catch(t){"object"==typeof window&&(e=window)}t.exports=e},function(t,n,e){"use strict";function o(t,n,e,r,s,u){if(s-r<=e)return;const h=r+s>>1;!function t(n,e,o,r,s,u){for(;s>r;){if(s-r>600){const i=s-r+1,h=o-r+1,c=Math.log(i),p=.5*Math.exp(2*c/3),a=.5*Math.sqrt(c*p*(i-p)/i)*(h-i/2<0?-1:1),l=Math.max(r,Math.floor(o-h*p/i+a)),f=Math.min(s,Math.floor(o+(i-h)*p/i+a));t(n,e,o,l,f,u)}const h=e[2*o+u];let c=r,p=s;for(i(n,e,r,o),e[2*s+u]>h&&i(n,e,r,s);c<p;){for(i(n,e,c,p),c++,p--;e[2*c+u]<h;)c++;for(;e[2*p+u]>h;)p--}e[2*r+u]===h?i(n,e,r,p):(p++,i(n,e,p,s)),p<=o&&(r=p+1),o<=p&&(s=p-1)}}(t,n,h,r,s,u%2),o(t,n,e,r,h-1,u+1),o(t,n,e,h+1,s,u+1)}function i(t,n,e,o){r(t,e,o),r(n,2*e,2*o),r(n,2*e+1,2*o+1)}function r(t,n,e){const o=t[n];t[n]=t[e],t[e]=o}function s(t,n,e,o){const i=t-e,r=n-o;return i*i+r*r}e.r(n),e.d(n,"default",(function(){return a}));const u=t=>t[0],h=t=>t[1];class c{constructor(t,n=u,e=h,i=64,r=Float64Array){this.nodeSize=i,this.points=t;const s=t.length<65536?Uint16Array:Uint32Array,c=this.ids=new s(t.length),p=this.coords=new r(2*t.length);for(let o=0;o<t.length;o++)c[o]=o,p[2*o]=n(t[o]),p[2*o+1]=e(t[o]);o(c,p,i,0,c.length-1,0)}range(t,n,e,o){return function(t,n,e,o,i,r,s){const u=[0,t.length-1,0],h=[];let c,p;for(;u.length;){const a=u.pop(),l=u.pop(),f=u.pop();if(l-f<=s){for(let s=f;s<=l;s++)c=n[2*s],p=n[2*s+1],c>=e&&c<=i&&p>=o&&p<=r&&h.push(t[s]);continue}const d=Math.floor((f+l)/2);c=n[2*d],p=n[2*d+1],c>=e&&c<=i&&p>=o&&p<=r&&h.push(t[d]);const m=(a+1)%2;(0===a?e<=c:o<=p)&&(u.push(f),u.push(d-1),u.push(m)),(0===a?i>=c:r>=p)&&(u.push(d+1),u.push(l),u.push(m))}return h}(this.ids,this.coords,t,n,e,o,this.nodeSize)}within(t,n,e){return function(t,n,e,o,i,r){const u=[0,t.length-1,0],h=[],c=i*i;for(;u.length;){const p=u.pop(),a=u.pop(),l=u.pop();if(a-l<=r){for(let i=l;i<=a;i++)s(n[2*i],n[2*i+1],e,o)<=c&&h.push(t[i]);continue}const f=Math.floor((l+a)/2),d=n[2*f],m=n[2*f+1];s(d,m,e,o)<=c&&h.push(t[f]);const g=(p+1)%2;(0===p?e-i<=d:o-i<=m)&&(u.push(l),u.push(f-1),u.push(g)),(0===p?e+i>=d:o+i>=m)&&(u.push(f+1),u.push(a),u.push(g))}return h}(this.ids,this.coords,t,n,e,this.nodeSize)}}const p={minZoom:0,maxZoom:16,radius:40,extent:512,nodeSize:64,log:!1,generateId:!1,reduce:null,map:t=>t};class a{constructor(t){this.options=_(Object.create(p),t),this.trees=new Array(this.options.maxZoom+1)}load(t){const{log:n,minZoom:e,maxZoom:o,nodeSize:i}=this.options;n&&console.time("total time");const r=`prepare ${t.length} points`;n&&console.time(r),this.points=t;let s=[];for(let n=0;n<t.length;n++)t[n].geometry&&s.push(f(t[n],n));this.trees[o+1]=new c(s,M,w,i,Float32Array),n&&console.timeEnd(r);for(let t=o;t>=e;t--){const e=+Date.now();s=this._cluster(s,t),this.trees[t]=new c(s,M,w,i,Float32Array),n&&console.log("z%d: %d clusters in %dms",t,s.length,+Date.now()-e)}return n&&console.timeEnd("total time"),this}getClusters(t,n){let e=((t[0]+180)%360+360)%360-180;const o=Math.max(-90,Math.min(90,t[1]));let i=180===t[2]?180:((t[2]+180)%360+360)%360-180;const r=Math.max(-90,Math.min(90,t[3]));if(t[2]-t[0]>=360)e=-180,i=180;else if(e>i){const t=this.getClusters([e,o,180,r],n),s=this.getClusters([-180,o,i,r],n);return t.concat(s)}const s=this.trees[this._limitZoom(n)],u=s.range(g(e),x(r),g(i),x(o)),h=[];for(const t of u){const n=s.points[t];h.push(n.numPoints?d(n):this.points[n.index])}return h}getChildren(t){const n=this._getOriginId(t),e=this._getOriginZoom(t),o="No cluster with the specified id.",i=this.trees[e];if(!i)throw new Error(o);const r=i.points[n];if(!r)throw new Error(o);const s=this.options.radius/(this.options.extent*Math.pow(2,e-1)),u=i.within(r.x,r.y,s),h=[];for(const n of u){const e=i.points[n];e.parentId===t&&h.push(e.numPoints?d(e):this.points[e.index])}if(0===h.length)throw new Error(o);return h}getLeaves(t,n,e){n=n||10,e=e||0;const o=[];return this._appendLeaves(o,t,n,e,0),o}getTile(t,n,e){const o=this.trees[this._limitZoom(t)],i=Math.pow(2,t),{extent:r,radius:s}=this.options,u=s/r,h=(e-u)/i,c=(e+1+u)/i,p={features:[]};return this._addTileFeatures(o.range((n-u)/i,h,(n+1+u)/i,c),o.points,n,e,i,p),0===n&&this._addTileFeatures(o.range(1-u/i,h,1,c),o.points,i,e,i,p),n===i-1&&this._addTileFeatures(o.range(0,h,u/i,c),o.points,-1,e,i,p),p.features.length?p:null}getClusterExpansionZoom(t){let n=this._getOriginZoom(t)-1;for(;n<=this.options.maxZoom;){const e=this.getChildren(t);if(n++,1!==e.length)break;t=e[0].properties.cluster_id}return n}_appendLeaves(t,n,e,o,i){const r=this.getChildren(n);for(const n of r){const r=n.properties;if(r&&r.cluster?i+r.point_count<=o?i+=r.point_count:i=this._appendLeaves(t,r.cluster_id,e,o,i):i<o?i++:t.push(n),t.length===e)break}return i}_addTileFeatures(t,n,e,o,i,r){for(const s of t){const t=n[s],u=t.numPoints,h={type:1,geometry:[[Math.round(this.options.extent*(t.x*i-e)),Math.round(this.options.extent*(t.y*i-o))]],tags:u?m(t):this.points[t.index].properties};let c;u?c=t.id:this.options.generateId?c=t.index:this.points[t.index].id&&(c=this.points[t.index].id),void 0!==c&&(h.id=c),r.features.push(h)}}_limitZoom(t){return Math.max(this.options.minZoom,Math.min(t,this.options.maxZoom+1))}_cluster(t,n){const e=[],{radius:o,extent:i,reduce:r}=this.options,s=o/(i*Math.pow(2,n));for(let o=0;o<t.length;o++){const i=t[o];if(i.zoom<=n)continue;i.zoom=n;const u=this.trees[n+1],h=u.within(i.x,i.y,s);let c=i.numPoints||1,p=i.x*c,a=i.y*c,f=r&&c>1?this._map(i,!0):null;const d=(o<<5)+(n+1)+this.points.length;for(const t of h){const e=u.points[t];if(e.zoom<=n)continue;e.zoom=n;const o=e.numPoints||1;p+=e.x*o,a+=e.y*o,c+=o,e.parentId=d,r&&(f||(f=this._map(i,!0)),r(f,this._map(e)))}1===c?e.push(i):(i.parentId=d,e.push(l(p/c,a/c,d,c,f)))}return e}_getOriginId(t){return t-this.points.length>>5}_getOriginZoom(t){return(t-this.points.length)%32}_map(t,n){if(t.numPoints)return n?_({},t.properties):t.properties;const e=this.points[t.index].properties,o=this.options.map(e);return n&&o===e?_({},o):o}}function l(t,n,e,o,i){return{x:t,y:n,zoom:1/0,id:e,parentId:-1,numPoints:o,properties:i}}function f(t,n){const[e,o]=t.geometry.coordinates;return{x:g(e),y:x(o),zoom:1/0,index:n,parentId:-1}}function d(t){return{type:"Feature",id:t.id,properties:m(t),geometry:{type:"Point",coordinates:[(n=t.x,360*(n-.5)),y(t.y)]}};var n}function m(t){const n=t.numPoints,e=n>=1e4?`${Math.round(n/1e3)}k`:n>=1e3?`${Math.round(n/100)/10}k`:n;return _(_({},t.properties),{cluster:!0,cluster_id:t.id,point_count:n,point_count_abbreviated:e})}function g(t){return t/360+.5}function x(t){const n=Math.sin(t*Math.PI/180),e=.5-.25*Math.log((1+n)/(1-n))/Math.PI;return e<0?0:e>1?1:e}function y(t){const n=(180-360*t)*Math.PI/180;return 360*Math.atan(Math.exp(n))/Math.PI-90}function _(t,n){for(const e in n)t[e]=n[e];return t}function M(t){return t.x}function w(t){return t.y}}]);
|
data/lib/supercluster.rb
CHANGED
@@ -1,27 +1,31 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require '
|
3
|
+
require 'mini_racer'
|
4
4
|
|
5
5
|
class Supercluster
|
6
6
|
class Error < StandardError; end
|
7
7
|
|
8
|
-
def
|
9
|
-
@context
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
8
|
+
def initialize(*args)
|
9
|
+
@context = MiniRacer::Context.new
|
10
|
+
@context.load(
|
11
|
+
File.expand_path('supercluster-build.js', __dir__)
|
12
|
+
)
|
13
|
+
@context.attach('args', proc { args })
|
14
|
+
@context.eval('var supercluster = new Supercluster(...args())')
|
14
15
|
end
|
15
16
|
|
16
|
-
def
|
17
|
-
context.
|
17
|
+
def load(*args)
|
18
|
+
@context.attach('args', proc { args })
|
19
|
+
@context.eval('supercluster.load(...args())')
|
18
20
|
end
|
19
21
|
|
20
|
-
def
|
21
|
-
|
22
|
+
def get_clusters(*args)
|
23
|
+
@context.attach('args', proc { args })
|
24
|
+
@context.eval('supercluster.getClusters(...args())')
|
22
25
|
end
|
23
26
|
|
24
|
-
def
|
25
|
-
|
27
|
+
def get_tiles(*args)
|
28
|
+
@context.attach('args', args)
|
29
|
+
@context.eval('supercluster.getTiles(...args())')
|
26
30
|
end
|
27
31
|
end
|
metadata
CHANGED
@@ -1,35 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: supercluster
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Yin
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-04-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: mini_racer
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
20
|
-
- - ">="
|
21
|
-
- !ruby/object:Gem::Version
|
22
|
-
version: 2.2.1
|
19
|
+
version: 0.2.0
|
23
20
|
type: :runtime
|
24
21
|
prerelease: false
|
25
22
|
version_requirements: !ruby/object:Gem::Requirement
|
26
23
|
requirements:
|
27
24
|
- - "~>"
|
28
25
|
- !ruby/object:Gem::Version
|
29
|
-
version:
|
30
|
-
- - ">="
|
31
|
-
- !ruby/object:Gem::Version
|
32
|
-
version: 2.2.1
|
26
|
+
version: 0.2.0
|
33
27
|
description: A very fast geospatial point clustering library for browsers and Node.
|
34
28
|
email: layerssss@gmail.com
|
35
29
|
executables: []
|