diff --git a/.gitignore b/.gitignore
index 73a92f7460..5fb73328f2 100755
--- a/.gitignore
+++ b/.gitignore
@@ -69,7 +69,6 @@ lib
*.sw*
*.un~
-demos/mapbox.html
demos/gd.html
demos/data
demos/image
diff --git a/demos/01_point_circle.html b/demos/01_point_circle.html
index bb80671de8..7121179c29 100644
--- a/demos/01_point_circle.html
+++ b/demos/01_point_circle.html
@@ -10,6 +10,9 @@
point_circle
@@ -55,15 +58,15 @@ scene.on('loaded', () => {
.shape('2d:circle')
.size('value', [ 2, 80]) // default 1
//.size('value', [ 10, 300]) // default 1
- .active(false)
+ .active(true)
.filter('value', field_8 => {
return field_8 * 1 > 500;
})
- .color('type', colorObj.red)
+ .color('type', colorObj.blue)
.style({
stroke: 'rgb(255,255,255)',
strokeWidth: 1,
- opacity: 0.9
+ opacity: 1.
})
.render();
diff --git a/demos/01_point_column.html b/demos/01_point_column.html
index 8e1abda83c..fd7d33ae02 100644
--- a/demos/01_point_column.html
+++ b/demos/01_point_column.html
@@ -34,9 +34,11 @@ scene.on('loaded', () => {
zIndex: 2
})
.source(data.list, {
- type: 'array',
- x: 'j',
- y: 'w',
+ parser:{
+ type: 'json',
+ x: 'j',
+ y: 'w',
+ }
})
.shape('cylinder')
.size('t',(level)=> {
diff --git a/demos/01_point_distribute.html b/demos/01_point_distribute.html
index 18a714ab75..a3d1bd8f73 100644
--- a/demos/01_point_distribute.html
+++ b/demos/01_point_distribute.html
@@ -34,9 +34,11 @@ scene.on('loaded', () => {
zIndex: 2
})
.source(data, {
- type: 'csv',
- y: 'lat',
- x: 'lng'
+ parser:{
+ type: 'csv',
+ y: 'lat',
+ x: 'lng'
+ }
})
.size(1.0)
.color('#0D408C')
diff --git a/demos/02_point_circle.html b/demos/02_point_circle.html
new file mode 100644
index 0000000000..cc95ad57d6
--- /dev/null
+++ b/demos/02_point_circle.html
@@ -0,0 +1,77 @@
+
+
+
+
+
+
+
+
+
+ point_circle
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/04_image.html b/demos/04_image.html
index 3f0773c96e..5acb717137 100644
--- a/demos/04_image.html
+++ b/demos/04_image.html
@@ -33,8 +33,11 @@ const scene = new L7.Scene({
scene.on('loaded', () => {
const imageLayer = scene.ImageLayer().
source('https://gw.alipayobjects.com/zos/rmsportal/FnHFeFklTzKDdUESRNDv.jpg',{
-
- extent: [ 121.1680, 30.2828, 121.3840, 30.4219 ]
+ parser:{
+ type:'image',
+ extent: [ 121.1680, 30.2828, 121.3840, 30.4219 ]
+ }
+
})
.style({
opacity:1.0,
diff --git a/demos/05_raster_dem.html b/demos/05_raster_dem.html
index 0589eed6b4..fb560be45b 100644
--- a/demos/05_raster_dem.html
+++ b/demos/05_raster_dem.html
@@ -48,13 +48,14 @@ scene.on('loaded', () => {
const layer = scene.RasterLayer({ zIndex: 2 }).
source(values, {
- type: 'raster',
- width: n,
- height: m,
- min: 0,
- max: 8000,
- extent: [ 73.482190241, 3.82501784112, 135.106618732, 57.6300459963 ]
-
+ parser: {
+ type: 'raster',
+ width: n,
+ height: m,
+ min: 0,
+ max: 8000,
+ extent: [ 73.482190241, 3.82501784112, 135.106618732, 57.6300459963 ]
+ }
})
.style({
rampColors: {
diff --git a/demos/grid.html b/demos/grid.html
new file mode 100644
index 0000000000..94c2000bb9
--- /dev/null
+++ b/demos/grid.html
@@ -0,0 +1,74 @@
+
+
+
+
+
+
+
+
+ point_circle
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/mapbox.html b/demos/mapbox.html
new file mode 100644
index 0000000000..661b3c33c3
--- /dev/null
+++ b/demos/mapbox.html
@@ -0,0 +1,93 @@
+
+
+
+
+
+
+
+
+
+ point_circle
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/package.json b/package.json
index 8ab26df3c2..01f457cb7e 100755
--- a/package.json
+++ b/package.json
@@ -101,12 +101,14 @@
"@turf/invariant": "^6.1.2",
"@turf/meta": "^6.0.2",
"d3-dsv": "^1.0.10",
+ "d3-hexbin": "^0.2.2",
"earcut": "^2.1.3",
"fecha": "^2.3.3",
"gl-matrix": "^2.4.1",
"lodash": "^4.17.5",
"polyline-normals": "^2.0.2",
"rbush": "^2.0.2",
+ "simple-statistics": "^7.0.1",
"three": "^0.96.0",
"venn.js": "^0.2.20",
"viewport-mercator-project": "^5.2.0",
diff --git a/src/core/controller/geom.js b/src/core/controller/geom.js
deleted file mode 100644
index b0d474ac01..0000000000
--- a/src/core/controller/geom.js
+++ /dev/null
@@ -1,36 +0,0 @@
-import geom from '../../geom/geom';
-import { GeoBuffer, bufferGeometry, Material } from '../../geom/index';
-
-
-// geom shape buffer geometry material
-// shape name type()
-// buffer 1:n geometry
-// geometry
-//
-export default function polygonGeom(shape, coordinates, properties, layerid) {
- const polygongeom = geom.polygon;
- const { buffer, geometry, material } = polygongeom[shape];// polygon 映射表
- const bufferData = new GeoBuffer[buffer]({
- coordinates,
- properties,
- shape
- });
- bufferData.bufferStruct.name = layerid;
- const bg = new bufferGeometry[geometry](bufferData.bufferStruct);
- const mtl = Material[material]();
- return {
- geometry: bg,
- mtl
- };
-}
-
-export function pointGeom(shape, bufferData) {
- const pointgeom = geom.point;
- const { geometry, material } = pointgeom[shape];
- const bg = new bufferGeometry[geometry](bufferData.bufferStruct);
- const mtl = Material[material]();
- return {
- geometry: bg,
- mtl
- };
-}
diff --git a/src/core/controller/map.js b/src/core/controller/map.js
new file mode 100644
index 0000000000..3068e61cfe
--- /dev/null
+++ b/src/core/controller/map.js
@@ -0,0 +1,24 @@
+
+import { getMap } from '../../map';
+import Base from '../base';
+export default class MapContorller extends Base {
+ constructor(cfg, engine, scene) {
+ super(cfg);
+ this._engine = engine;
+ this.scene = scene;
+ }
+ _init() {
+ const mapType = this.get('mapType');
+ const mapCfg = this.get('mapCfg');
+ this.map = new getMap(mapType)(mapCfg);
+ this.map('mapLoad', this._mapload.bind(this));
+ }
+ _mapload() {
+ this.map.asyncCamera(this._engine);
+ this.emit('loaded');
+ }
+ _bindMapMethod() {
+
+ }
+
+}
diff --git a/src/core/engine/index.js b/src/core/engine/index.js
index d3a8eee42b..a12f2e06f6 100644
--- a/src/core/engine/index.js
+++ b/src/core/engine/index.js
@@ -11,6 +11,9 @@ export default class Engine extends EventEmitter {
this._camera = new Camera(container).camera;
this._renderer = new Renderer(container).renderer;
this._world = world;
+ // for MapBox
+ this.world = new THREE.Group();
+ this._scene.add(this.world);
this._picking = Picking(this._world, this._renderer, this._camera, this._scene);
this.clock = new THREE.Clock();
}
diff --git a/src/core/engine/picking/picking.js b/src/core/engine/picking/picking.js
index 0dfd718fbe..c467af20ce 100755
--- a/src/core/engine/picking/picking.js
+++ b/src/core/engine/picking/picking.js
@@ -11,6 +11,8 @@ class Picking {
this.scene = scene;
this._raycaster.linePrecision = 10;
this._pickingScene = PickingScene;
+ this.world = new THREE.Group();
+ this._pickingScene.add(this.world);
const size = this._renderer.getSize();
this._width = size.width;
this._height = size.height;
@@ -34,8 +36,7 @@ class Picking {
window.addEventListener('resize', this._resizeHandler, false);
}
pickdata(event) {
- const point = { x: event.pixel.x, y: event.pixel.y, type: event.type };
-
+ const point = { x: event.offsetX, y: event.offsetY, type: event.type };
const normalisedPoint = { x: 0, y: 0 };
normalisedPoint.x = (point.x / this._width) * 2 - 1;
normalisedPoint.y = -(point.y / this._height) * 2 + 1;
@@ -61,12 +62,12 @@ class Picking {
}
_filterObject(id) {
- this._pickingScene.children.forEach((object, index) => {
+ this.world.children.forEach((object, index) => {
index === id ? object.visible = true : object.visible = false;
});
}
_pickAllObject(point, normalisedPoint) {
- this._pickingScene.children.forEach((object, index) => {
+ this.world.children.forEach((object, index) => {
this._filterObject(index);
const item = this._pick(point, normalisedPoint, object.name);
item.type = point.type;
@@ -86,7 +87,6 @@ class Picking {
id = -999;
// return;
}
-
this._raycaster.setFromCamera(normalisedPoint, this._camera);
const intersects = this._raycaster.intersectObjects(this._pickingScene.children, true);
@@ -111,13 +111,14 @@ class Picking {
//
// Picking ID should already be added as an attribute
add(mesh) {
- this._pickingScene.add(mesh);
+ this.world.add(mesh);
+
this._needUpdate = true;
}
// Remove mesh from picking scene
remove(mesh) {
- this._pickingScene.remove(mesh);
+ this.world.remove(mesh);
this._needUpdate = true;
}
diff --git a/src/core/layer.js b/src/core/layer.js
index 50f2858587..dc0afbd99e 100644
--- a/src/core/layer.js
+++ b/src/core/layer.js
@@ -5,7 +5,7 @@
import Base from './base';
import * as THREE from './three';
import ColorUtil from '../attr/color-util';
-import * as source from '../source/index';
+import source from './source';
import PickingMaterial from '../core/engine/picking/pickingMaterial';
import Attr from '../attr/index';
import Util from '../util';
@@ -63,7 +63,8 @@ export default class Layer extends Base {
const layerId = this._getUniqueId();
this.layerId = layerId;
this._activeIds = null;
- scene._engine._scene.add(this._object3D);
+ const world = scene._engine.world;
+ world.add(this._object3D);
this.layerMesh = null;
this.layerLineMesh = null;
this._initEvents();
@@ -106,12 +107,9 @@ export default class Layer extends Base {
this._object3D.visible = this.get('visible');
}
source(data, cfg = {}) {
- const dataType = this._getDataType(data);
- const { type = dataType } = cfg;
cfg.data = data;
- cfg.mapType = this.get('mapType');
-
- this.layerSource = new source[type](cfg);
+ cfg.mapType = this.scene.mapType;
+ this.layerSource = new source(cfg);
// this.scene.workerPool.runTask({
// command: 'geojson',
// data: cfg
@@ -279,10 +277,10 @@ export default class Layer extends Base {
const { featureId } = e;
if (featureId < 0) return;
const activeStyle = this.get('activedOptions');
- const selectFeatureIds = this.layerSource.getSelectFeatureId(featureId);
+ // const selectFeatureIds = this.layerSource.getSelectFeatureId(featureId);
// 如果数据不显示状态则不进行高亮
- if (this.StyleData[selectFeatureIds[0]].hasOwnProperty('filter') && this.StyleData[selectFeatureIds[0]].filter === false) { return; }
- const style = Util.assign({}, this.StyleData[featureId]);
+ if (this.layerData[featureId].hasOwnProperty('filter') && this.layerData[featureId].filter === false) { return; }
+ const style = Util.assign({}, this.layerData[featureId]);
style.color = ColorUtil.toRGB(activeStyle.fill).map(e => e / 255);
this.updateStyle([ featureId ], style);
}
@@ -321,7 +319,7 @@ export default class Layer extends Base {
_updateSize(zoom) {
const sizeOption = this.get('attrOptions').size;
const fields = parseFields(sizeOption.field);
- const data = this.layerSource.propertiesData;
+ const data = this.layerSource.data.dataArray;
if (!this.zoomSizeCache) this.zoomSizeCache = {};
if (!this.zoomSizeCache[zoom]) {
this.zoomSizeCache[zoom] = [];
@@ -339,7 +337,8 @@ export default class Layer extends Base {
const self = this;
const attrs = self.get('attrs');
const mappedData = [];
- const data = this.layerSource.propertiesData;
+ // const data = this.layerSource.propertiesData;
+ const data = this.layerSource.data.dataArray;
for (let i = 0; i < data.length; i++) {
const record = data[i];
const newRecord = {};
@@ -362,18 +361,17 @@ export default class Layer extends Base {
}
}
}
+ newRecord.coordinates = record.coordinates;
mappedData.push(newRecord);
}
-
- this.StyleData = mappedData;
- return mappedData;
+ this.layerData = mappedData;
}
// 更新地图映射
_updateMaping() {
const self = this;
const attrs = self.get('attrs');
- const data = this.layerSource.propertiesData;
+ const data = this.layerSource.data.dataArray;
for (let i = 0; i < data.length; i++) {
const record = data[i];
for (const attrName in attrs) {
@@ -385,10 +383,10 @@ export default class Layer extends Base {
for (let j = 0; j < values.length; j++) {
const val = values[j];
const name = names[j];
- this.StyleData[i][name] = (Util.isArray(val) && val.length === 1) ? val[0] : val; // 只有一个值时返回第一个属性值
+ this.layerData[i][name] = (Util.isArray(val) && val.length === 1) ? val[0] : val; // 只有一个值时返回第一个属性值
}
} else {
- this.StyleData[i][names[0]] = values.length === 1 ? values[0] : values;
+ this.layerData[i][names[0]] = values.length === 1 ? values[0] : values;
}
attr.neadUpdate = true;
@@ -468,6 +466,7 @@ export default class Layer extends Base {
pickingMesh.material.setUniformsValue('u_zoom', zoom);
};
this._pickingMesh.add(pickingMesh);
+
}
_setPickingId() {
this._pickingId = this.getPickingId();
@@ -532,13 +531,13 @@ export default class Layer extends Base {
*/
_updateFilter(object) {
this._updateMaping();
- const filterData = this.StyleData;
+ const filterData = this.layerData;
this._activeIds = null; // 清空选中元素
const colorAttr = object.geometry.attributes.a_color;
const pickAttr = object.geometry.attributes.pickingId;
pickAttr.array.forEach((id, index) => {
id = Math.abs(id);
- const color = [ ...this.StyleData[id - 1].color ];
+ const color = [ ...this.layerData[id - 1].color ];
id = Math.abs(id);
const item = filterData[id - 1];
if (item.hasOwnProperty('filter') && item.filter === false) {
@@ -584,7 +583,7 @@ export default class Layer extends Base {
const pickingId = this.layerMesh.geometry.attributes.pickingId.array;
const colorAttr = this.layerMesh.geometry.attributes.a_color;
this._activeIds.forEach(index => {
- const color = this.StyleData[index].color;
+ const color = this.layerData[index].color;
const firstId = pickingId.indexOf(index + 1);
for (let i = firstId; i < pickingId.length; i++) {
if (pickingId[i] === index + 1) {
diff --git a/src/core/scene.js b/src/core/scene.js
index b85ba35a5a..38e3879c48 100644
--- a/src/core/scene.js
+++ b/src/core/scene.js
@@ -3,8 +3,8 @@ import { LAYER_MAP } from '../layer';
import Base from './base';
import LoadImage from './image';
import WorkerPool from './worker';
-import { MapProvider } from '../map/provider';
-import GaodeMap from '../map/gaodeMap';
+// import { MapProvider } from '../map/AMap';
+import { getMap } from '../map/index';
import Global from '../global';
import { compileBuiltinModules } from '../geom/shader';
export default class Scene extends Base {
@@ -31,16 +31,14 @@ export default class Scene extends Base {
}
_initMap() {
this.mapContainer = this.get('id');
- this._container = document.getElementById(this.mapContainer);
- const Map = new MapProvider(this.mapContainer, this._attrs);
+ this.mapType = this.get('mapType') || 'amap';
+ const MapProvider = getMap(this.mapType);
+ const Map = new MapProvider(this._attrs);
+ Map.mixMap(this);
+ this._container = document.getElementById(Map.container);
+ // const Map = new MapProvider(this.mapContainer, this._attrs);
Map.on('mapLoad', () => {
this._initEngine(Map.renderDom);
- const sceneMap = new GaodeMap(Map.map);
- // eslint-disable-next-line
- Object.getOwnPropertyNames(sceneMap.__proto__).forEach((key)=>{
- // eslint-disable-next-line
- if ('key' !== 'constructor') { this.__proto__[key] = sceneMap.__proto__[key]; }
- });
this.map = Map.map;
Map.asyncCamera(this._engine);
this.initLayer();
@@ -101,8 +99,10 @@ export default class Scene extends Base {
'dblclick'
];
events.forEach(event => {
- this.map.on(event, e => {
+
+ this._container.addEventListener(event, e => {
// 要素拾取
+ e.pixel || (e.pixel = e.point);
this._engine._picking.pickdata(e);
}, false);
});
diff --git a/src/core/source.js b/src/core/source.js
index 3a61aead88..259ab32179 100644
--- a/src/core/source.js
+++ b/src/core/source.js
@@ -1,17 +1,15 @@
-/*
- * @Author: ThinkGIS
- * @Date: 2018-06-08 11:19:06
- * @Last Modified by: mikey.zhaopeng
- * @Last Modified time: 2018-11-01 11:50:43
- */
+
import Base from './base';
const Controller = require('./controller/index');
-import { aProjectFlat } from '../geo/project';
+import { getTransform, getParser } from '../source';
+import { getMap } from '../map/index';
export default class Source extends Base {
getDefaultCfg() {
return {
data: null,
defs: {},
+ parser: {},
+ transforms: [],
scales: {
},
options: {}
@@ -19,26 +17,40 @@ export default class Source extends Base {
}
constructor(cfg) {
super(cfg);
-
+ const transform = this.get('transforms');
+ this._transforms = transform || [];
this._initControllers();
- this.prepareData();
+ // 数据解析
+ this._excuteParser();
+ // 数据转换 统计,聚合,分类
+ this._executeTrans();
+ // 坐标转换
+ this._projectCoords();
}
-
- // 标准化数据
- prepareData() {
+ _excuteParser() {
+ const parser = this.get('parser');
+ const { type = 'geojson' } = parser;
const data = this.get('data');
- this.propertiesData = [];// 临时使用
- this.geoData = [];
-
- data.coordinates.forEach(geo => {
- const coord = this._coordProject(geo);
- this.geoData.push(coord);
- this.propertiesData.push([]);
+ this.data = getParser(type)(data, parser);
+ }
+ /**
+ * 数据统计
+ */
+ _executeTrans() {
+ const trans = this._transforms;
+ trans.forEach(tran => {
+ const { type } = tran;
+ this.data = getTransform(type)(this.data, tran);
+ });
+ this._transforms = trans;
+ }
+ _projectCoords() {
+ this.data.dataArray.forEach(data => {
+ data.coordinates = this._coordProject(data.coordinates);
});
}
-
createScale(field) {
- const data = this.propertiesData;
+ const data = this.data.dataArray;
const scales = this.get('scales');
let scale = scales[field];
const scaleController = this.get('scaleController');
@@ -50,6 +62,8 @@ export default class Source extends Base {
}
_initControllers() {
const defs = this.get('defs');
+ const mapType = this.get('mapType');
+ this.projectFlat = getMap(mapType).project;
const scaleController = new Controller.Scale({
defs
});
@@ -83,9 +97,14 @@ export default class Source extends Base {
}
_coorConvert(geo) {
- const ll = aProjectFlat(geo);
- return [ ll.x, -ll.y, geo[2] || 0 ];
+ const ll = this.projectFlat(geo);
+ return [ ll.x, ll.y, geo[2] || 0 ];
}
+ getSelectFeature(featureId) {
+ const data = this.get('data');
+ // 如果是GeoJSON 数据返回原数
+ return data.features ? data.features[featureId] : this.data.dataArray[featureId];
+ }
}
diff --git a/src/core/three.js b/src/core/three.js
index 75cbe58b5d..03359e840d 100644
--- a/src/core/three.js
+++ b/src/core/three.js
@@ -4,6 +4,7 @@ export { Scene } from 'three/src/scenes/Scene.js';
export { WebGLRenderer } from 'three/src/renderers/WebGLRenderer.js';
export { CanvasTexture } from 'three/src/textures/CanvasTexture.js';
export { Object3D } from 'three/src/core/Object3D.js';
+export { Group } from 'three/src/objects/Group';
export { Clock } from 'three/src/core/Clock';
export { Points } from 'three/src/objects/Points.js';
export { LineSegments } from 'three/src/objects/LineSegments.js';
diff --git a/src/geo/lngLat.js b/src/geo/lngLat.js
index edc7b59576..b635918f0c 100644
--- a/src/geo/lngLat.js
+++ b/src/geo/lngLat.js
@@ -1,20 +1,75 @@
-export class LatLng {
- constructor(lat, lng, alt) {
- if (isNaN(lat) || isNaN(lng)) {
- throw new Error('Invalid LatLng object: (' + lat + ', ' + lng + ')');
- }
- this.lat = +lat;
- this.lng = +lng;
- if (alt !== undefined) {
- this.alt = +alt;
- }
+self._wkHandlers={};;
- }
- equal() {
+ function _prep_h17(){function a(b,c,d,e,g,k){var l=[0,0,0,0,0],n=d.slice(0,4).concat(l),p=[],s=Math.PI/180*6,A=void 0,I=void 0,A=d.slice(0,2),D=m(e),F=m(g),I=q.normalize(h(D).fg(h(A))),C=q.normalize(h(F).fg(h(A)));q.OK(I,k)?(A=q.oD(I),I=q.oD(C)):(A=q.oD(C),I=q.oD(I),k=[F,D],D=k[0],F=k[1],g=[g,e],e=g[0],g=g[1]);D=Math.ceil(Math.abs(I-A)/s);30<=D&&(D=60-D);for(k=0;kMath.sqrt(3)/2&&(d=Math.sqrt(3)/2);c=c.oJ(d)}return c}function g(a,c,e){if(void 0===e||!0===e)b.push(a[0],a[1]),b.push(-c.y,c.x,0,0),b.push(m,0,0),d.push(a[2]);if(void 0===e||!1===e)b.push(a[0],a[1]),b.push(c.y,-c.x,0,0),b.push(m,0,0),d.push(a[2])}for(var k=a[0],l=a[a.length-1],m=0,n=void 0;k[0]===l[0]&&k[1]===l[1]&&k!==l;)a.pop(),l=a[a.length-1];a.push(k);a.push(a[1]);a.unshift(l);var p=a.length;a.forEach(function(a,d, k){var l=k[d-1];k=k[d+1];var r=void 0;l&&(m+=q.Fd(a,l));if(0===d||d===p-1)0===d?(r=q.normalize(h(k[0]-a[0],k[1]-a[1])),c.push(0,1,2)):(r=q.normalize(h(a[0]-l[0],a[1]-l[1])),d=b.length/9+2,c.push(d-3,d-1,d-2)),g(a,r);else{d=q.normalize(h(a[0]-l[0],a[1]-l[1]));k=q.normalize(h(k[0]-a[0],k[1]-a[1]));l=q.normalize(d.multiply(-1).mi(k));n=q.OK(l,d);g(a,e(d,k),!0);g(a,e(d,k),!1);g(a,e(d,k),!0);g(a,e(d,k),!1);a=b.length/9-4;k=a+2;var r=9*a,s=r+9,x=s+9,B=x+9;d=Math.abs(q.cos(d,l)/q.sin(d,l));n?(b[r+7]=d,b[s+ 7]=-d,b[x+7]=-d,b[B+7]=d):(b[r+7]=-d,b[s+7]=d,b[x+7]=d,b[B+7]=-d);c.push(a,a-1,a+1);c.push(k,k+1,k+2)}})}function e(c,d,e){function g(a,b){if(p)for(;0=a&&(a+=2*Math.PI);return a}},s={mi:function(a){return h(this.x+a.x,this.y+a.y)},fg:function(a){return h(this.x-a.x,this.y-a.y)},multiply:function(a){return"number"===typeof a?h(this.x*a,this.y*a):this.x*a.x+this.y*a.y},oJ:function(a){return h(this.x/a,this.y/a)},NC:function(a){var b=a.y;return this.x===a.x&&this.y===b}};return{parse:function(a,b){var h=a.lineJoin,h=void 0===h?"bevel":h,k= a.lineCap,k=void 0===k?"butt":k,l=a.Zda,l=void 0===l?!1:l,m=a.tn,n=void 0===m?!1:m,p=a.LX,m=a.Iia,q=void 0===m?!0:m,m=a.Sda,s=[],A=[],I=g(a.Nr,void 0===p?!0:p),p=[];l?(d(I,s,A,p),h=s.length,[0,1,2,h/9-1,h/9-2].forEach(function(a){s[9*a+8]=-1})):(c(I,s,A,h,n,p),e(I,s,A,k,p));q&&(s=new Float32Array(s),A=65535=h||b.jn;if(d||b){d=1 {
+ const { color, id } = element;
+ const [ x, y, z ] = element.coordinates;
+ attribute.vertices.push(x, y, z);
+ attribute.miter.push(-1, -1);
+ attribute.vertices.push(x, y, z);
+ attribute.miter.push(1, 1);
+ attribute.vertices.push(x, y, z);
+ attribute.miter.push(-1, 1);
+ attribute.vertices.push(x, y, z);
+ attribute.miter.push(-1, -1);
+ attribute.vertices.push(x, y, z);
+ attribute.miter.push(1, -1);
+ attribute.vertices.push(x, y, z);
+ attribute.miter.push(1, 1);
+ attribute.colors.push(...color);
+ attribute.colors.push(...color);
+ attribute.colors.push(...color);
+ attribute.colors.push(...color);
+ attribute.colors.push(...color);
+ attribute.colors.push(...color);
+ attribute.pickingIds.push(id, id, id, id, id, id);
+ });
+ return attribute;
+}
diff --git a/src/geom/buffer/image.js b/src/geom/buffer/image.js
index 70b52aed51..262151b149 100644
--- a/src/geom/buffer/image.js
+++ b/src/geom/buffer/image.js
@@ -4,8 +4,9 @@ import * as THREE from '../../core/three';
export default class ImageBuffer extends BufferBase {
geometryBuffer() {
- const coordinates = this.get('coordinates');
- const images = this.get('image');
+ const layerData = this.get('layerData');
+ const coordinates = layerData[0].coordinates;
+ const images = layerData[0].images;
const positions = [ ...coordinates[0],
coordinates[1][0], coordinates[0][1], 0,
...coordinates[1],
diff --git a/src/geom/buffer/line.js b/src/geom/buffer/line.js
index a73006f07c..880ac2dc95 100644
--- a/src/geom/buffer/line.js
+++ b/src/geom/buffer/line.js
@@ -3,8 +3,7 @@ import { lineShape } from '../shape';
export default class LineBuffer extends BufferBase {
geometryBuffer() {
- const coordinates = this.get('coordinates');
- const properties = this.get('properties');
+ const layerData = this.get('layerData');
const shapeType = this.shapeType = this.get('shapeType');
const positions = [];
const positionsIndex = [];
@@ -16,16 +15,16 @@ export default class LineBuffer extends BufferBase {
this.attributes = this._getArcLineAttributes();
return;
}
- coordinates.forEach((geo, index) => {
- const props = properties[index];
- const attrData = this._getShape(geo, props, index);
+ layerData.forEach((item, index) => {
+ const props = item;
+ const attrData = this._getShape(item.coordinates, props, index);
positions.push(...attrData.positions);
positionsIndex.push(...attrData.indexes);
if (attrData.hasOwnProperty('instances')) {
instances.push(...attrData.instances);
}
});
- this.bufferStruct.style = properties;
+ this.bufferStruct.style = layerData;
this.bufferStruct.verts = positions;
this.bufferStruct.indexs = positionsIndex;
if (instances.length > 0) {
@@ -50,17 +49,16 @@ export default class LineBuffer extends BufferBase {
}
_getArcLineAttributes() {
- const coordinates = this.get('coordinates');
- const properties = this.get('properties');
+ const layerData = this.get('layerData');
const positions = [];
const colors = [];
const indexArray = [];
const sizes = [];
const instances = [];
- coordinates.forEach((geo, index) => {
- const props = properties[index];
+ layerData.forEach(item => {
+ const props = item;
const positionCount = positions.length / 3;
- const attrData = this._getShape(geo, props, positionCount);
+ const attrData = this._getShape(item.coordinates, props, positionCount);
positions.push(...attrData.positions);
colors.push(...attrData.colors);
indexArray.push(...attrData.indexArray);
@@ -76,8 +74,7 @@ export default class LineBuffer extends BufferBase {
};
}
_getMeshLineAttributes() {
- const coordinates = this.get('coordinates');
- const properties = this.get('properties');
+ const layerData = this.get('layerData');
const { lineType } = this.get('style');
const positions = [];
const pickingIds = [];
@@ -87,10 +84,10 @@ export default class LineBuffer extends BufferBase {
const indexArray = [];
const sizes = [];
const attrDistance = [];
- coordinates.forEach((geo, index) => {
- const props = properties[index];
+ layerData.forEach(item => {
+ const props = item;
const positionCount = positions.length / 3;
- const attr = lineShape.Line(geo, props, positionCount, (lineType !== 'soild'));
+ const attr = lineShape.Line(item.coordinates, props, positionCount, (lineType !== 'soild'));
positions.push(...attr.positions);
normal.push(...attr.normal);
miter.push(...attr.miter);
diff --git a/src/geom/buffer/point/fillBuffer.js b/src/geom/buffer/point/fillBuffer.js
index 84d257c3ee..7179959827 100644
--- a/src/geom/buffer/point/fillBuffer.js
+++ b/src/geom/buffer/point/fillBuffer.js
@@ -3,7 +3,7 @@ import * as THREE from '../../../core/three';
import * as polygonShape from '../../shape/polygon';
import * as polygonPath from '../../shape/path';
import Util from '../../../util';
-export default function fillBuffer(coordinates, properties) {
+export default function fillBuffer(layerData) {
const attribute = {
vertices: [],
normals: [],
@@ -14,8 +14,8 @@ export default function fillBuffer(coordinates, properties) {
faceUv: []
};
- coordinates.forEach((geo, index) => {
- let { size, shape, color, id } = properties[index];
+ layerData.forEach(item => {
+ let { size, shape, color, id, coordinates } = item;
let polygon = null;
const path = polygonPath[shape]();
if (pointShape['2d'].indexOf(shape) !== -1) {
@@ -27,7 +27,7 @@ export default function fillBuffer(coordinates, properties) {
} else {
throw new Error('Invalid shape type: ' + shape);
}
- toPointShapeAttributes(polygon, geo, { size, shape, color, id }, attribute);
+ toPointShapeAttributes(polygon, coordinates, { size, shape, color, id }, attribute);
});
return attribute;
diff --git a/src/geom/buffer/point/imageBuffer.js b/src/geom/buffer/point/imageBuffer.js
index 6bc37b052a..383134b6d9 100644
--- a/src/geom/buffer/point/imageBuffer.js
+++ b/src/geom/buffer/point/imageBuffer.js
@@ -1,4 +1,4 @@
-export default function ImageBuffer(coordinates, properties, opt) {
+export default function ImageBuffer(layerData, opt) {
const attributes = {
vertices: [],
colors: [],
@@ -7,10 +7,10 @@ export default function ImageBuffer(coordinates, properties, opt) {
pickingIds: [],
uv: []
};
- coordinates.forEach((pos, index) => {
- const { color, size, id, shape } = properties[index];
+ layerData.forEach(item => {
+ const { color, size, id, shape, coordinates } = item;
const { x, y } = opt.imagePos[shape];
- attributes.vertices.push(...pos);
+ attributes.vertices.push(...coordinates);
attributes.colors.push(...color);
attributes.pickingIds.push(id);
attributes.sizes.push(size * window.devicePixelRatio); //
diff --git a/src/geom/buffer/point/normalBuffer.js b/src/geom/buffer/point/normalBuffer.js
index d35fd4217b..aaa50ee424 100644
--- a/src/geom/buffer/point/normalBuffer.js
+++ b/src/geom/buffer/point/normalBuffer.js
@@ -1,13 +1,13 @@
-export default function NormalBuffer(coordinates, properties) {
+export default function NormalBuffer(layerData) {
const attributes = {
vertices: [],
colors: [],
sizes: [],
pickingIds: []
};
- coordinates.forEach((pos, index) => {
- const { color, size, id } = properties[index];
- attributes.vertices.push(...pos);
+ layerData.forEach(item => {
+ const { color, size, id, coordinates} = item;
+ attributes.vertices.push(...coordinates);
attributes.colors.push(...color);
attributes.pickingIds.push(id);
attributes.sizes.push(size);
diff --git a/src/geom/buffer/point/strokeBuffer.js b/src/geom/buffer/point/strokeBuffer.js
index c71726cbd6..eff757e3c6 100644
--- a/src/geom/buffer/point/strokeBuffer.js
+++ b/src/geom/buffer/point/strokeBuffer.js
@@ -3,7 +3,7 @@ import * as polygonShape from '../../shape/polygon';
import * as lineShape from '../../shape/line';
import { pointShape } from '../../../global';
import Util from '../../../util';
-export default function StrokeBuffer(coordinates, properties, style) {
+export default function StrokeBuffer(layerData, style) {
const attribute = {
shapes: [],
normal: [],
@@ -15,8 +15,8 @@ export default function StrokeBuffer(coordinates, properties, style) {
colors: []
};
const { stroke, strokeWidth } = style;
- coordinates.forEach((geo, index) => {
- let { size, shape, id } = properties[index];
+ layerData.forEach(item => {
+ let { size, shape, id, coordinates } = item;
const path = polygonPath[shape]();
const positionsIndex = attribute.miter.length;
let polygon = null;
@@ -33,7 +33,7 @@ export default function StrokeBuffer(coordinates, properties, style) {
} else {
throw new Error('Invalid shape type: ' + shape);
}
- polygonLineBuffer(polygon, geo, size, attribute);
+ polygonLineBuffer(polygon, coordinates, size, attribute);
});
return attribute;
diff --git a/src/geom/buffer/point/textBuffer.js b/src/geom/buffer/point/textBuffer.js
index 0bbab7d759..1d68acb3b1 100644
--- a/src/geom/buffer/point/textBuffer.js
+++ b/src/geom/buffer/point/textBuffer.js
@@ -9,7 +9,7 @@ const metrics = {
family: 'ios9',
size: 24
};
-export default function TextBuffer(coordinates, properties, style) {
+export default function TextBuffer(layerData, style) {
EventEmitter.call(this);
const attributes = {
originPoints: [],
@@ -21,7 +21,7 @@ export default function TextBuffer(coordinates, properties, style) {
const { textOffset = [ 0, 0 ] } = style;
const chars = [];
const textChars = {};
- properties.forEach(element => {
+ layerData.forEach(element => {
let text = element.shape || '';
text = text.toString();
for (let j = 0; j < text.length; j++) {
@@ -33,9 +33,9 @@ export default function TextBuffer(coordinates, properties, style) {
}
});
loadTextInfo(chars, (chars, texture) => {
- properties.forEach((element, index) => {
+ layerData.forEach(element => {
const size = element.size;
- const pos = coordinates[index];
+ const pos = layerData.coordinates;
const pen = { x: textOffset[0], y: textOffset[1] };
let text = element.shape || '';
text = text.toString();
diff --git a/src/geom/buffer/polygon.js b/src/geom/buffer/polygon.js
index c90172802a..60c585d872 100644
--- a/src/geom/buffer/polygon.js
+++ b/src/geom/buffer/polygon.js
@@ -3,22 +3,21 @@ import BufferBase from './bufferBase';
export default class PolygonBuffer extends BufferBase {
geometryBuffer() {
- const coordinates = this.get('coordinates');
- const properties = this.get('properties');
+ const layerData = this.get('layerData');
const shape = this.get('shape');
const positions = [];
const faceUv = [];
const sizes = [];
const positionsIndex = [];
let indexCount = 0;
- this.bufferStruct.style = properties;
- const isExtrude = properties[0].hasOwnProperty('size');
+ this.bufferStruct.style = layerData;
+ const isExtrude = layerData[0].hasOwnProperty('size');
// indices, normals, colors, UVs
- coordinates.forEach((geo, index) => {
- const heightValue = properties[index].size;
- let extrudeData = polygonShape[shape](geo);
+ layerData.forEach(item => {
+ const heightValue = item.size;
+ let extrudeData = polygonShape[shape](item.coordinates);
if (isExtrude && shape === 'extrude') {
- extrudeData = polygonShape.extrude(geo);
+ extrudeData = polygonShape.extrude(item.coordinates);
extrudeData.positions = extrudeData.positions.map(pos => {
pos[2] *= heightValue;
return pos;
@@ -48,7 +47,7 @@ export default class PolygonBuffer extends BufferBase {
this.bufferStruct.indices = positionsIndex;
this.bufferStruct.position = positions;
this.bufferStruct.indexCount = indexCount;
- this.bufferStruct.style = properties;
+ this.bufferStruct.style = layerData;
this.bufferStruct.faceUv = faceUv;
this.bufferStruct.sizes = sizes;
if (shape !== 'line') {
diff --git a/src/geom/buffer/raster.js b/src/geom/buffer/raster.js
index 32fa14a3ba..9f62192699 100644
--- a/src/geom/buffer/raster.js
+++ b/src/geom/buffer/raster.js
@@ -3,8 +3,8 @@ import { colorScales } from '../../attr/colorscales';
import * as THREE from '../../core/three';
export class RasterBuffer extends BufferBase {
geometryBuffer() {
- const coordinates = this.get('coordinates');
-
+ const layerData = this.get('layerData');
+ const { coordinates, width, data, height } = layerData.dataArray[0];
const positions = [
...coordinates[0],
coordinates[1][0], coordinates[0][1], 0,
@@ -14,9 +14,8 @@ export class RasterBuffer extends BufferBase {
coordinates[0][0], coordinates[1][1], 0
];
const imgPosUv = [ 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0 ];
- const raster = this.get('raster');
const size = this.get('size');
- const texture = new THREE.DataTexture(new Float32Array(raster.data), raster.width, raster.height, THREE.LuminanceFormat, THREE.FloatType);
+ const texture = new THREE.DataTexture(new Float32Array(data), width, height, THREE.LuminanceFormat, THREE.FloatType);
texture.generateMipmaps = true;
texture.needsUpdate = true;
const colors = this.get('rampColors');
@@ -28,7 +27,7 @@ export class RasterBuffer extends BufferBase {
this.bufferStruct.u_extent = [ coordinates[0][0], coordinates[0][1], coordinates[1][0], coordinates[1][1] ];
this.bufferStruct.u_colorTexture = colorTexture; // 颜色表‘=
- const triangles = this._buildTriangles(raster, size, this.bufferStruct.u_extent);
+ const triangles = this._buildTriangles(width, height, size, this.bufferStruct.u_extent);
const attributes = {
vertices: new Float32Array(triangles.vertices),
uvs: new Float32Array(triangles.uvs),
@@ -78,9 +77,8 @@ export class RasterBuffer extends BufferBase {
texture1.needsUpdate = true;
return texture1;
}
- _buildTriangles(raster, size = 1, extent) {
+ _buildTriangles(width, height, size = 1, extent) {
// const extent = [ 73.482190241, 3.82501784112, 135.106618732, 57.6300459963 ]
- const { width, height } = raster;
const indices = [];
const vertices = [];
const uvs = [];
diff --git a/src/geom/buffer/text.js b/src/geom/buffer/text.js
index 099f6d217f..5f906352b4 100644
--- a/src/geom/buffer/text.js
+++ b/src/geom/buffer/text.js
@@ -13,12 +13,11 @@ export default class TextBuffer extends BufferBase {
family: 'ios9',
size: 24
};
- const coordinates = this.get('coordinates');
- const properties = this.get('properties');
+ const layerData = this.get('layerData');
const { textOffset = [ 0, 0 ] } = this.get('style');
const chars = [];
const textChars = {};
- properties.forEach(element => {
+ layerData.forEach(element => {
let text = element.shape || '';
text = text.toString();
for (let j = 0; j < text.length; j++) {
@@ -39,9 +38,9 @@ export default class TextBuffer extends BufferBase {
const originPoints = [];
const textSizes = [];
const textOffsets = [];
- properties.forEach((element, index) => {
+ layerData.forEach(element => {
const size = element.size;
- const pos = coordinates[index];
+ const pos = element.coordinates;
// const pen = { x: pos[0] - dimensions.advance / 2, y: pos[1] };
const pen = { x: textOffset[0], y: textOffset[1] };
let text = element.shape || '';
@@ -53,7 +52,7 @@ export default class TextBuffer extends BufferBase {
this._drawGlyph(pos, text[i], pen, size, colors, textureElements, originPoints, textSizes, textOffsets, color);
}
});
- this.bufferStruct.style = properties;
+ this.bufferStruct.style = layerData;
this.attributes = {
originPoints,
textSizes,
diff --git a/src/geom/material/grid.js b/src/geom/material/grid.js
new file mode 100644
index 0000000000..65db262fcf
--- /dev/null
+++ b/src/geom/material/grid.js
@@ -0,0 +1,31 @@
+import grid_frag from '../shader/grid_frag.glsl';
+import grid_vert from '../shader/grid_vert.glsl';
+import Material from './material';
+
+
+export default class GridMaterial extends Material {
+ getDefaultParameters() {
+ return {
+ uniforms: {
+ u_opacity: { value: 1.0 },
+ u_time: { value: 0 },
+ u_xOffset: { value: 0.01 },
+ u_yOffset: { value: 0.01 },
+ u_coverage: { value: 0.8 }
+ },
+ defines: {
+
+ }
+ };
+ }
+ constructor(_uniforms, _defines, parameters) {
+ super(parameters);
+ const { uniforms, defines } = this.getDefaultParameters();
+ this.uniforms = Object.assign(uniforms, this.setUniform(_uniforms));
+ this.type = 'GridMaterial';
+ this.defines = Object.assign(defines, _defines);
+ this.vertexShader = grid_vert;
+ this.fragmentShader = grid_frag;
+ this.transparent = true;
+ }
+}
diff --git a/src/geom/material/polygonMaterial.js b/src/geom/material/polygonMaterial.js
index da8a598122..cd606fb8f1 100644
--- a/src/geom/material/polygonMaterial.js
+++ b/src/geom/material/polygonMaterial.js
@@ -1,28 +1,5 @@
import Material from './material';
import { getModule } from '../../util/shaderModule';
-// export default function PolygonMaterial(options) {
-// const material = new Material({
-// uniforms: {
-// u_opacity: { value: options.u_opacity || 1.0 },
-// u_texture: { value: options.u_texture },
-// u_time: { value: options.u_time || 0 },
-// u_zoom: { value: options.u_zoom || 0 },
-// u_baseColor: { value: options.u_baseColor || [ 1.0, 0, 0, 1.0 ] },
-// u_brightColor: { value: options.u_brightColor || [ 1.0, 0, 0, 1.0 ] },
-// u_windowColor: { value: options.u_windowColor || [ 1.0, 0, 0, 1.0 ] },
-// u_near: { value: options.u_near || 0.0 },
-// u_far: { value: options.u_far || 1.0 }
-// },
-// vertexShader: polygon_vert,
-// fragmentShader: polygon_frag,
-// transparent: true,
-// defines: {
-// TEXCOORD_0: !!options.u_texture
-// }
-// });
-// return material;
-// }
-
export default class PolygonMaterial extends Material {
getDefaultParameters() {
return {
diff --git a/src/geom/shader/grid_frag.glsl b/src/geom/shader/grid_frag.glsl
new file mode 100644
index 0000000000..042dde511e
--- /dev/null
+++ b/src/geom/shader/grid_frag.glsl
@@ -0,0 +1,8 @@
+ precision highp float;
+ uniform float u_opacity;
+ varying vec4 v_color;
+ void main() {
+ vec4 color = v_color;
+ gl_FragColor = color;
+ gl_FragColor.a =color.a*u_opacity;
+}
\ No newline at end of file
diff --git a/src/geom/shader/grid_vert.glsl b/src/geom/shader/grid_vert.glsl
new file mode 100644
index 0000000000..90c68a3b70
--- /dev/null
+++ b/src/geom/shader/grid_vert.glsl
@@ -0,0 +1,15 @@
+precision highp float;
+attribute vec2 miter;
+attribute vec4 a_color;
+uniform float u_xOffset;
+uniform float u_yOffset;
+uniform float u_coverage;
+varying vec4 v_color;
+
+void main() {
+ mat4 matModelViewProjection = projectionMatrix * modelViewMatrix;
+ v_color = a_color;
+ float x = position.x + miter.x * u_xOffset * u_coverage;
+ float y = position.y + miter.y * u_yOffset * u_coverage;
+ gl_Position = matModelViewProjection * vec4(x, y, position.z, 1.0);
+}
\ No newline at end of file
diff --git a/src/geom/shader/point_frag.glsl b/src/geom/shader/point_frag.glsl
index eecea0605c..10e11d0f09 100644
--- a/src/geom/shader/point_frag.glsl
+++ b/src/geom/shader/point_frag.glsl
@@ -1,7 +1,8 @@
precision highp float;
-#pragma import "common"
+#define PI 3.14159265359
+#define TWO_PI 6.28318530718
uniform float u_strokeWidth;
uniform vec4 u_stroke;
diff --git a/src/geom/shader/polygon_vert.glsl b/src/geom/shader/polygon_vert.glsl
index 7d35a1d249..eba0b62d02 100644
--- a/src/geom/shader/polygon_vert.glsl
+++ b/src/geom/shader/polygon_vert.glsl
@@ -15,7 +15,7 @@ varying float v_size;
void main() {
float scale = pow(2.0,(20.0 - u_zoom));
- mat4 matModelViewProjection = projectionMatrix * modelViewMatrix;
+ mat4 matModelViewProjection = projectionMatrix * modelViewMatrix * 100.;
vec3 newposition = position;
// newposition.x -= 128.0;
#ifdef SHAPE
diff --git a/src/layer/heatmap.js b/src/layer/heatmap.js
new file mode 100644
index 0000000000..f9971a55da
--- /dev/null
+++ b/src/layer/heatmap.js
@@ -0,0 +1,28 @@
+import Layer from '../core/layer';
+import gridBuffer from '../geom/buffer/heatmap/grid';
+import DrawGrid from './render/heatmap/gird';
+
+export default class HeatMapLayer extends Layer {
+ shape(type) {
+ this.shapeType = type;
+ return this;
+ }
+ render() {
+ this._prepareRender();
+ return this;
+ }
+ _prepareRender() {
+ this.init();
+ this.type = 'heatmap';
+ const style = this.get('styleOptions');
+ const { xOffset, yOffset } = this.layerSource.data;
+ this._buffer = new gridBuffer(this.layerData);
+ const config = {
+ ...style,
+ xOffset,
+ yOffset
+ };
+ const girdMesh = new DrawGrid(this._buffer, config);
+ this.add(girdMesh);
+ }
+}
diff --git a/src/layer/imageLayer.js b/src/layer/imageLayer.js
index f3092da117..92e9a60b59 100644
--- a/src/layer/imageLayer.js
+++ b/src/layer/imageLayer.js
@@ -1,26 +1,19 @@
import Layer from '../core/layer';
import * as THREE from '../core/three';
-import imageSource from '../source/imageSource';
import ImageBuffer from '../geom/buffer/image';
// import ImageGeometry from '../geom/bufferGeometry/image';
import ImageMaterial from '../geom/material/imageMaterial';
export default class imageLayer extends Layer {
- source(data, cfg = {}) {
- cfg.mapType = this.get('mapType');
- cfg.data = data;
- this.layerSource = new imageSource(cfg);
- return this;
- }
render() {
this.init();
this.type = 'image';
const source = this.layerSource;
const { opacity } = this.get('styleOptions');
// 加载 完成事件
- source.on('imageLoaded', () => {
+ source.data.images.then(images => {
+ this.layerData[0].images = images;
const buffer = new ImageBuffer({
- coordinates: source.geoData,
- image: source.image
+ layerData: this.layerData
});
this.initGeometry(buffer.attributes);
const material = new ImageMaterial({
diff --git a/src/layer/index.js b/src/layer/index.js
index 5e8fef27c6..1c2cad2fdf 100644
--- a/src/layer/index.js
+++ b/src/layer/index.js
@@ -4,17 +4,14 @@ import PointLayer from './pointLayer';
import LineLayer from './lineLayer';
import ImageLayer from './imageLayer';
import RasterLayer from './rasterLayer';
+import HeatMapLayer from './heatmap';
registerLayer('PolygonLayer', PolygonLayer);
registerLayer('PointLayer', PointLayer);
registerLayer('LineLayer', LineLayer);
registerLayer('ImageLayer', ImageLayer);
registerLayer('RasterLayer', RasterLayer);
+registerLayer('HeatMapLayer', HeatMapLayer);
export { LAYER_MAP } from './factory';
-export { default as PolygonLayer } from './polygonLayer';
-export { default as PointLayer } from './pointLayer';
-export { default as LineLayer } from './lineLayer';
-export { default as ImageLayer } from './imageLayer';
-export { default as RasterLayer } from './rasterLayer';
diff --git a/src/layer/lineLayer.js b/src/layer/lineLayer.js
index 4d40755100..c83c3f0a88 100644
--- a/src/layer/lineLayer.js
+++ b/src/layer/lineLayer.js
@@ -12,11 +12,10 @@ export default class LineLayer extends Layer {
this.type = 'polyline';
this.init();
const source = this.layerSource;
- const StyleData = this.StyleData;
+ const layerData = this.layerData;
const style = this.get('styleOptions');
const buffer = this._buffer = new LineBuffer({
- coordinates: source.geoData,
- properties: StyleData,
+ layerData,
shapeType: this.shapeType,
style
});
diff --git a/src/layer/pointLayer.js b/src/layer/pointLayer.js
index 74163f82b4..7acbdfbf53 100644
--- a/src/layer/pointLayer.js
+++ b/src/layer/pointLayer.js
@@ -45,12 +45,12 @@ export default class PointLayer extends Layer {
case 'fill' :// 填充图形
{
if (fill !== 'none') { // 是否填充
- const attributes = PointBuffer.FillBuffer(source.geoData, this.StyleData, style);
+ const attributes = PointBuffer.FillBuffer(this.layerData, style);
const meshfill = drawPoint.DrawFill(attributes, this.get('styleOptions'));
this.add(meshfill);
}
if (stroke !== 'none') { // 是否绘制边界
- const lineAttribute = PointBuffer.StrokeBuffer(source.geoData, this.StyleData, style);
+ const lineAttribute = PointBuffer.StrokeBuffer(this.layerData, style);
const meshStroke = drawPoint.DrawStroke(lineAttribute, this.get('styleOptions'));
this.add(meshStroke, 'line');
}
@@ -58,14 +58,14 @@ export default class PointLayer extends Layer {
}
case 'image':// 绘制图片标注
{
- const imageAttribute = PointBuffer.ImageBuffer(source.geoData, this.StyleData, { imagePos: this.scene.image.imagePos });
+ const imageAttribute = PointBuffer.ImageBuffer(this.layerData, { imagePos: this.scene.image.imagePos });
const imageMesh = drawPoint.DrawImage(imageAttribute, { ...style, texture: this.scene.image.texture });
this.add(imageMesh);
break;
}
case 'normal' : // 原生点
{
- const normalAttribute = PointBuffer.NormalBuffer(source.geoData, this.StyleData, style);
+ const normalAttribute = PointBuffer.NormalBuffer(this.layerData, style);
const normalPointMesh = drawPoint.DrawNormal(normalAttribute, style);
this.add(normalPointMesh);
break;
@@ -77,11 +77,11 @@ export default class PointLayer extends Layer {
_getShape() {
let shape = null;
- if (!this.StyleData[0].hasOwnProperty('shape')) {
+ if (!this.layerData[0].hasOwnProperty('shape')) {
return 'normal';
}
- for (let i = 0; i < this.StyleData.length; i++) {
- shape = this.StyleData[i].shape;
+ for (let i = 0; i < this.layerData.length; i++) {
+ shape = this.layerData[i].shape;
if (shape !== undefined) {
break;
}
@@ -102,8 +102,7 @@ export default class PointLayer extends Layer {
const styleOptions = this.get('styleOptions');
const buffer = new TextBuffer({
type: this.shapeType,
- coordinates: source.geoData,
- properties: this.StyleData,
+ layerData: this.layerData,
style: this.get('styleOptions')
});
diff --git a/src/layer/polygonLayer.js b/src/layer/polygonLayer.js
index 53e7c9903e..ba37ed3b87 100644
--- a/src/layer/polygonLayer.js
+++ b/src/layer/polygonLayer.js
@@ -21,11 +21,9 @@ export default class PolygonLayer extends Layer {
_prepareRender() {
this.init();
this.type = 'polygon';
- const source = this.layerSource;
this._buffer = new PolygonBuffer({
shape: this.shape,
- coordinates: source.geoData,
- properties: this.StyleData
+ layerData: this.layerData
});
this.add(this._getLayerRender());
}
diff --git a/src/layer/rasterLayer.js b/src/layer/rasterLayer.js
index 7a68dc8530..cb5d9f41a9 100644
--- a/src/layer/rasterLayer.js
+++ b/src/layer/rasterLayer.js
@@ -1,16 +1,10 @@
import Layer from '../core/layer';
import * as THREE from '../core/three';
-import RasterSource from '../source/rasterSource';
import RasterMaterial from '../geom/material/rasterMaterial';
import { RasterBuffer } from '../geom/buffer/raster';
export default class RasterLayer extends Layer {
- source(data, cfg = {}) {
- cfg.mapType = this.get('mapType');
- cfg.data = data;
- this.layerSource = new RasterSource(cfg);
- return this;
- }
+
render() {
this.type = 'raster';
this.init();
@@ -18,18 +12,18 @@ export default class RasterLayer extends Layer {
// 加载 完成事件
const styleOptions = this.get('styleOptions');
const buffer = new RasterBuffer({
- coordinates: source.geoData,
- raster: source.rasterData,
+ layerData: source.data,
rampColors: styleOptions.rampColors
});
this.initGeometry(buffer.attributes);
+ const rasterConfig = source.data.dataArray[0];
const material = new RasterMaterial({
u_texture: buffer.bufferStruct.u_raster,
u_colorTexture: buffer.bufferStruct.u_colorTexture,
u_opacity: 1.0,
u_extent: buffer.bufferStruct.u_extent,
- u_min: source.rasterData.min,
- u_max: source.rasterData.max,
+ u_min: rasterConfig.min,
+ u_max: rasterConfig.max,
u_dimension: buffer.attributes.dimension
});
diff --git a/src/layer/render/heatmap/gird.js b/src/layer/render/heatmap/gird.js
new file mode 100644
index 0000000000..5aa4b07796
--- /dev/null
+++ b/src/layer/render/heatmap/gird.js
@@ -0,0 +1,21 @@
+import * as THREE from '../../../core/three';
+import GridMaterial from '../../../geom/material/grid';
+export default function DrawGrid(attributes, style) {
+ const { opacity, xOffset, yOffset, coverage } = style;
+ const geometry = new THREE.BufferGeometry();
+ geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.vertices, 3));
+ geometry.addAttribute('miter', new THREE.Float32BufferAttribute(attributes.miter, 2));
+ geometry.addAttribute('a_color', new THREE.Float32BufferAttribute(attributes.colors, 4));
+ geometry.addAttribute('pickingId', new THREE.Float32BufferAttribute(attributes.pickingIds, 1));
+ const material = new GridMaterial({
+ u_opacity: opacity,
+ u_xOffset: xOffset,
+ u_yOffset: yOffset,
+ u_coverage: coverage
+ }, {
+ SHAPE: false
+ });
+ const gridMesh = new THREE.Mesh(geometry, material);
+ return gridMesh;
+}
+
diff --git a/src/map/provider.js b/src/map/AMap.js
similarity index 57%
rename from src/map/provider.js
rename to src/map/AMap.js
index 19763e8f45..e54615b94a 100644
--- a/src/map/provider.js
+++ b/src/map/AMap.js
@@ -1,18 +1,34 @@
import Base from '../core/base';
+import { scene } from '../global';
import * as Theme from '../theme/index';
import Util from '../util';
-import { scene } from '../global';
const DEG2RAD = Math.PI / 180;
-export class MapProvider extends Base {
+export default class GaodeMap extends Base {
getDefaultCfg() {
return Util.assign(scene, {
resizeEnable: true,
viewMode: '3D'
});
}
- constructor(container, cfg) {
+ static project(lnglat) {
+ const maxs = 85.0511287798;
+ const lat = Math.max(Math.min(maxs, lnglat[1]), -maxs);
+ const scale = 256 << 20;
+ let d = Math.PI / 180;
+ let x = lnglat[0] * d;
+ let y = lat * d;
+ y = Math.log(Math.tan((Math.PI / 4) + (y / 2)));
+ const a = 0.5 / Math.PI,
+ b = 0.5,
+ c = -0.5 / Math.PI;
+ d = 0.5;
+ x = scale * (a * x + b) - 215440491;
+ y = -(scale * (c * y + d) - 106744817);
+ return { x, y };
+ }
+ constructor(cfg) {
super(cfg);
- this.container = container;
+ this.container = this.get('id');
this.initMap();
this.addOverLayer();
setTimeout(() => {
@@ -85,4 +101,31 @@ export class MapProvider extends Base {
this.renderDom.id = 'l7_canvaslayer';
canvasContainer.appendChild(this.renderDom);
}
+ mixMap(scene) {
+ const map = this.map;
+ scene.getZoom = () => { return map.getZoom(); };
+ scene.getCenter = () => { return map.getCenter(); };
+ scene.getSize = () => { return map.getSize(); };
+ scene.getPitch = () => { return map.getPitch(); };
+ scene.getRotation = () => { return map.getRotation(); };
+ scene.getStatus = () => { return map.getStatus(); };
+ scene.getScale = () => { return map.getScale(); };
+ scene.getZoom = () => { return map.getZoom(); };
+ scene.setZoom = () => { return map.setZoom(); };
+ scene.setBounds = () => { return map.setBounds(); };
+ scene.setRotation = () => { return map.setRotation(); };
+ scene.zoomIn = () => { return map.zoomIn(); };
+ scene.setRotation = () => { return map.setRotation(); };
+ scene.zoomOut = () => { return map.zoomOut(); };
+ scene.panTo = () => { return map.panTo(); };
+ scene.panBy = () => { return map.panBy(); };
+ scene.setPitch = () => { return map.setPitch(); };
+ scene.pixelToLngLat = () => { return map.pixelToLngLat(); };
+ scene.lngLatToPixel = () => { return map.lngLatToPixel(); };
+ scene.setMapStyle = () => { return map.setMapStyle(); };
+ scene.containerToLngLat = pixel => {
+ const ll = new AMap.Pixel(pixel.x, pixel.y);
+ return map.containerToLngLat(ll);
+ };
+ }
}
diff --git a/src/map/baseMap.js b/src/map/baseMap.js
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/src/map/gaodeMap.js b/src/map/gaodeMap.js
index bdd98f54f5..4b4ff3eb5c 100644
--- a/src/map/gaodeMap.js
+++ b/src/map/gaodeMap.js
@@ -21,7 +21,7 @@ export default class GaodeMap {
return this.map.getStatus();
}
getScale() {
- return this.getScale();
+ return this.map.getScale();
}
setZoom(zoom) {
return this.map.setZoom(zoom);
diff --git a/src/map/index.js b/src/map/index.js
new file mode 100644
index 0000000000..ae5b7dbb7d
--- /dev/null
+++ b/src/map/index.js
@@ -0,0 +1,22 @@
+import MapBox from './mapbox';
+import { default as AMap } from './AMap';
+export {
+ AMap,
+ MapBox
+};
+const MapType = {
+ amap: AMap,
+ mapbox: MapBox
+};
+export const getMap = type => {
+ return MapType[type.toLowerCase()];
+};
+
+export const registerMap = (type, map) => {
+ if (getMap(type)) {
+ throw new Error(`Map type '${type}' existed.`);
+ }
+ map.type = type;
+ // 存储到 map 中
+ MapType[type.toLowerCase()] = map;
+};
diff --git a/src/map/mapbox.js b/src/map/mapbox.js
new file mode 100644
index 0000000000..8eebadc8ef
--- /dev/null
+++ b/src/map/mapbox.js
@@ -0,0 +1,154 @@
+import Base from '../core/base';
+import Util from '../util';
+import { scene } from '../global';
+import * as THREE from '../core/three';
+const WORLD_SIZE = 512;
+const MERCATOR_A = 6378137.0;
+const WORLD_SCALE = 1 / 100;
+const PROJECTION_WORLD_SIZE = WORLD_SIZE / (MERCATOR_A * Math.PI) / 2;
+export default class MapBox extends Base {
+ getDefaultCfg() {
+ return Util.assign(scene, {
+ resizeEnable: true,
+ viewMode: '3D'
+ });
+ }
+ static project(lnglat) {
+ const d = Math.PI / 180;
+ const x = -MERCATOR_A * lnglat[0] * d * PROJECTION_WORLD_SIZE;
+ const y = -MERCATOR_A * Math.log(Math.tan((Math.PI * 0.25) + (0.5 * lnglat[1] * d))) * PROJECTION_WORLD_SIZE;
+ return { x, y };
+ }
+ constructor(cfg) {
+ super(cfg);
+ this.container = this.get('container');
+ this.initMap();
+ this.addOverLayer();
+ setTimeout(() => {
+ this.emit('mapLoad');
+ }, 100);
+
+ }
+
+ initMap() {
+ mapboxgl.accessToken = 'pk.eyJ1IjoibHp4dWUiLCJhIjoiYnhfTURyRSJ9.Ugm314vAKPHBzcPmY1p4KQ';
+ this.map = new mapboxgl.Map(this._attrs);
+ }
+ asyncCamera(engine) {
+ this.engine = engine;
+ const camera = engine._camera;
+ const scene = engine.world;
+ const pickScene = engine._picking.world;
+ camera.matrixAutoUpdate = false;
+ scene.position.x = scene.position.y = WORLD_SIZE / 2;
+ scene.matrixAutoUpdate = false;
+ pickScene.position.x = pickScene.position.y = WORLD_SIZE / 2;
+ pickScene.matrixAutoUpdate = false;
+ this.updateCamera();
+ this.map.on('move', () => {
+ this.updateCamera();
+ });
+ }
+ updateCamera() {
+ const engine = this.engine;
+ const scene = engine.world;
+ const pickScene = engine._picking.world;
+ const camera = engine._camera;
+ // Build a projection matrix, paralleling the code found in Mapbox GL JS
+ const fov = 0.6435011087932844;
+ const cameraToCenterDistance = 0.5 / Math.tan(fov / 2) * this.map.transform.height * WORLD_SCALE;
+ const halfFov = fov / 2;
+ const groundAngle = Math.PI / 2 + this.map.transform._pitch;
+ const topHalfSurfaceDistance = Math.sin(halfFov) * cameraToCenterDistance / Math.sin(Math.PI - groundAngle - halfFov);
+
+ // Calculate z distance of the farthest fragment that should be rendered.
+ const furthestDistance = Math.cos(Math.PI / 2 - this.map.transform._pitch) * topHalfSurfaceDistance + cameraToCenterDistance;
+
+ // Add a bit extra to avoid precision problems when a fragment's distance is exactly `furthestDistance`
+ let farZ = furthestDistance * 1.1;
+ if (this.pitch > 50) {
+ farZ = 1000;
+ }
+ const { x, y } = this.map.transform.point;
+ camera.projectionMatrix = this.makePerspectiveMatrix(fov, this.map.transform.width / this.map.transform.height, 1, farZ);
+ const cameraWorldMatrix = new THREE.Matrix4();
+ const cameraTranslateZ = new THREE.Matrix4().makeTranslation(0, 0, cameraToCenterDistance);
+ const cameraRotateX = new THREE.Matrix4().makeRotationX(this.map.transform._pitch);
+ const cameraRotateZ = new THREE.Matrix4().makeRotationZ(this.map.transform.angle);
+ const cameraTranslateXY = new THREE.Matrix4().makeTranslation(x * WORLD_SCALE, -y * WORLD_SCALE, 0);
+ // const cameraTranslateCenter = new THREE.Matrix4().makeTranslation(0, 0, cameraToCenterDistance);
+ // Unlike the Mapbox GL JS camera, separate camera translation and rotation out into its world matrix
+ // If this is applied directly to the projection matrix, it will work OK but break raycasting
+ cameraWorldMatrix
+ .premultiply(cameraTranslateZ)
+ .premultiply(cameraRotateX)
+ .premultiply(cameraRotateZ)
+ .premultiply(cameraTranslateXY);
+
+ camera.matrixWorld.copy(cameraWorldMatrix);
+
+ const zoomPow = this.map.transform.scale * WORLD_SCALE;
+ // Handle scaling and translation of objects in the map in the world's matrix transform, not the camera
+ const scale = new THREE.Matrix4();
+ const translateCenter = new THREE.Matrix4();
+ const translateMap = new THREE.Matrix4();
+ const rotateMap = new THREE.Matrix4();
+ scale
+ .makeScale(zoomPow, zoomPow, 1.0);
+ translateCenter
+ .makeTranslation(WORLD_SIZE / 2, -WORLD_SIZE / 2, 0);
+ translateMap
+ .makeTranslation(-this.map.transform.x, this.map.transform.y, 0);
+ rotateMap
+ .makeRotationZ(Math.PI);
+ scene.matrix = new THREE.Matrix4();
+ scene.matrix
+ .premultiply(rotateMap)
+ .premultiply(translateCenter)
+ .premultiply(scale);
+ pickScene.matrix = new THREE.Matrix4();
+ pickScene.matrix
+ .premultiply(rotateMap)
+ .premultiply(translateCenter)
+ .premultiply(scale);
+ }
+ makePerspectiveMatrix(fovy, aspect, near, far) {
+ const out = new THREE.Matrix4();
+ const f = 1.0 / Math.tan(fovy / 2),
+ nf = 1 / (near - far);
+ const newMatrix = [
+ f / aspect, 0, 0, 0,
+ 0, f, 0, 0,
+ 0, 0, (far + near) * nf, -1,
+ 0, 0, (2 * far * near) * nf, 0
+ ];
+ out.elements = newMatrix;
+ return out;
+ }
+
+ projectFlat(lnglat) {
+ return this.map.lngLatToGeodeticCoord(lnglat);
+ }
+ getCenter() {
+ return this.map.getCenter();
+ }
+ getCenterFlat() {
+ return this.projectFlat(this.getCenter());
+ }
+ addOverLayer() {
+ const canvasContainer = document.getElementById(this.container);
+ this.canvasContainer = canvasContainer;
+ this.renderDom = document.createElement('div');
+ this.renderDom.style.cssText += 'position: absolute;top: 0; z-index:10;height: 100%;width: 100%;pointer-events: none;';
+ this.renderDom.id = 'l7_canvaslayer';
+ canvasContainer.appendChild(this.renderDom);
+ }
+ mixMap(scene) {
+ const map = this.map;
+ scene.getZoom = () => { return map.getZoom(); };
+ scene.getCenter = () => { return map.getCenter(); };
+ scene.getPitch = () => { return map.getPitch(); };
+ scene.containerToLngLat = point => { return map.unproject(point); };
+
+ }
+}
diff --git a/src/source/csvSource.js b/src/source/csvSource.js
deleted file mode 100644
index e5ce0b9834..0000000000
--- a/src/source/csvSource.js
+++ /dev/null
@@ -1,69 +0,0 @@
-import Source from '../core/source';
-import FeatureIndex from '../geo/featureIndex';
-import { csvParse } from 'd3-dsv';
-export default class CSVSource extends Source {
- prepareData() {
- this.type = 'csv';
- const data = this.get('data');
- const x = this.get('x');
- const y = this.get('y');
- const x1 = this.get('x1');
- const y1 = this.get('y1');
- const coords = this.get('coordinates');
- this.propertiesData = [];// 临时使用
- this.geoData = [];
- let csvdata = data;
- Array.isArray(csvdata) || (csvdata = csvParse(data));
- this.propertiesData = csvdata;
- csvdata.forEach((col, featureIndex) => {
- let coordinates = [];
- if (col.coordinates) {
- coordinates = col.coordinates;
- }
- if (x && y) { coordinates = [ col[x], col[y] ]; } // 点数据
- if (x1 && y1) { // 弧线 或者线段
- coordinates = [[ col[x], col[y] ], [ col[x1], col[y1] ]];
- }
- if (coords && col.coords) { coordinates = col.coords; }
- col._id = featureIndex + 1;
- this._coordProject(coordinates);
- this.geoData.push(this._coordProject(coordinates));
- });
- }
-
- featureIndex() {
- const data = this.get('data');
- this.featureIndex = new FeatureIndex(data);
- }
- getSelectFeatureId(featureId) {
- return [ featureId ];
- }
- getSelectFeature(featureId) {
- return this.propertiesData[featureId];
-
- }
- _getCoord(geo) {
- if (geo.geometry) {
- // GeoJSON feature
- geo = geo.geometry.coordinates;
- } else if (geo.coordinates) {
- // GeoJSON geometry
- geo = geo.coordinates;
- }
- return geo;
- }
- _coordProject(geo) {
- if (Array.isArray(geo[0][0])) {
- return geo.map(coor => {
- return this._coordProject(coor);
- });
- }
- if (!Array.isArray(geo[0])) {
- return this._coorConvert(geo);
- }
- return geo.map(coor => {
- return this._coorConvert(coor);
- });
- }
-
-}
diff --git a/src/source/factory.js b/src/source/factory.js
new file mode 100644
index 0000000000..37629b9e99
--- /dev/null
+++ b/src/source/factory.js
@@ -0,0 +1,11 @@
+
+const TRANSFORMS = {};
+const PARSERS = {};
+export const getParser = type => PARSERS[type];
+export const registerParser = (type, parserFunction) => {
+ PARSERS[type] = parserFunction;
+};
+export const getTransform = type => TRANSFORMS[type];
+export const registerTransform = (type, transFunction) => {
+ TRANSFORMS[type] = transFunction;
+};
diff --git a/src/source/geojsonSource.js b/src/source/geojsonSource.js
deleted file mode 100644
index 1b1c012568..0000000000
--- a/src/source/geojsonSource.js
+++ /dev/null
@@ -1,45 +0,0 @@
-import Source from '../core/source';
-import * as turfMeta from '@turf/meta';
-import { default as cleanCoords } from '@turf/clean-coords';
-import { getCoords } from '@turf/invariant';
-import FeatureIndex from '../geo/featureIndex';
-
-export default class GeojsonSource extends Source {
- prepareData() {
- this.type = 'geojson';
- const data = this.get('data');
- this.propertiesData = [];
- this.geoData = [];
- turfMeta.flattenEach(data, (currentFeature, featureIndex) => {
- const coord = getCoords(cleanCoords(currentFeature));
- this.geoData.push(this._coordProject(coord));
- currentFeature.properties._id = featureIndex + 1;
- this.propertiesData.push(currentFeature.properties);
- });
- }
- featureIndex() {
- const data = this.get('data');
- this.featureIndex = new FeatureIndex(data);
- }
- getSelectFeatureId(featureId) {
- const data = this.get('data');
- const selectFeatureIds = [];
- let featureStyleId = 0;
- turfMeta.flattenEach(data, (currentFeature, featureIndex/* , multiFeatureIndex*/) => {
- if (featureIndex === (featureId)) {
- selectFeatureIds.push(featureStyleId);
- }
- featureStyleId++;
- if (featureIndex > featureId) {
- return;
- }
- });
- return selectFeatureIds;
-
- }
- getSelectFeature(featureId) {
- const data = this.get('data');
- return data.features[featureId];
- }
-
-}
diff --git a/src/source/imageSource.js b/src/source/imageSource.js
deleted file mode 100644
index 137f5a0772..0000000000
--- a/src/source/imageSource.js
+++ /dev/null
@@ -1,37 +0,0 @@
-import Source from '../core/source';
-import { getImage } from '../util/ajax';
-export default class ImageSource extends Source {
- prepareData() {
- this.type = 'image';
- const extent = this.get('extent');
- const lb = this._coorConvert(extent.slice(0, 2));
- const tr = this._coorConvert(extent.slice(2, 4));
- this.geoData = [ lb, tr ];
- this.propertiesData = [];
- this._loadData();
- }
- _loadData() {
- const url = this.get('data');
- this.image = [];
- if (typeof (url) === 'string') {
- getImage({ url }, (err, img) => {
- this.image = img;
- this.emit('imageLoaded');
- });
- } else {
- const imageCount = url.length;
- let imageindex = 0;
- url.forEach(item => {
- getImage({ url: item }, (err, img) => {
- imageindex++;
- this.image.push(img);
- if (imageindex === imageCount) {
- this.emit('imageLoaded');
- }
-
- });
- });
-
- }
- }
-}
diff --git a/src/source/index.js b/src/source/index.js
index ea6b260c09..ff88ba484e 100644
--- a/src/source/index.js
+++ b/src/source/index.js
@@ -1,5 +1,23 @@
-export { default as geojson } from './geojsonSource';
-export { default as csv } from './csvSource';
-export { default as array } from './csvSource';
-export { default as basic } from '../core/source';
-export { default as imageSource } from './imageSource';
+// source parser
+
+import geojson from './parser/geojson';
+import image from './parser/image';
+import csv from './parser/csv';
+import json from './parser/json';
+import raster from './parser/raster';
+
+import { registerTransform, registerParser } from './factory';
+import { aggregatorToGrid } from './transform/grid';
+import { map } from './transform/map';
+
+registerParser('geojson', geojson);
+registerParser('image', image);
+registerParser('csv', csv);
+registerParser('json', json);
+registerParser('raster', raster);
+// 注册transform
+
+registerTransform('grid', aggregatorToGrid);
+registerTransform('map', map);
+
+export { getTransform, registerTransform, getParser, registerParser } from './factory';
diff --git a/src/source/parser/csv.js b/src/source/parser/csv.js
new file mode 100644
index 0000000000..f727d18209
--- /dev/null
+++ b/src/source/parser/csv.js
@@ -0,0 +1,23 @@
+import { csvParse } from 'd3-dsv';
+export default function csv(data, cfg) {
+ const { x, y, x1, y1 } = cfg;
+ const csvdata = csvParse(data);
+ const resultdata = [];
+ csvdata.forEach((col, featureIndex) => {
+ let coordinates = [];
+ if (x && y) { coordinates = [ col[x], col[y] ]; } // 点数据
+ if (x1 && y1) { // 弧线 或者线段
+ coordinates = [[ col[x], col[y] ], [ col[x1], col[y1] ]];
+ }
+ col._id = featureIndex + 1;
+ const dataItem = {
+ ...col,
+ coordinates
+
+ };
+ resultdata.push(dataItem);
+ });
+ return {
+ dataArray: resultdata
+ };
+}
diff --git a/src/source/parser/geojson.js b/src/source/parser/geojson.js
new file mode 100644
index 0000000000..6385fa0d42
--- /dev/null
+++ b/src/source/parser/geojson.js
@@ -0,0 +1,19 @@
+import * as turfMeta from '@turf/meta';
+import { default as cleanCoords } from '@turf/clean-coords';
+import { getCoords } from '@turf/invariant';
+
+export default function geoJSON(data) {
+ const resultData = [];
+ turfMeta.flattenEach(data, (currentFeature, featureIndex) => { // 多个polygon 拆成一个
+ const coord = getCoords(cleanCoords(currentFeature));
+ const dataItem = {
+ ...currentFeature.properties,
+ coordinates: coord,
+ _id: featureIndex + 1
+ };
+ resultData.push(dataItem);
+ });
+ return {
+ dataArray: resultData
+ };
+}
diff --git a/src/source/parser/image.js b/src/source/parser/image.js
new file mode 100644
index 0000000000..e4a6f99ddf
--- /dev/null
+++ b/src/source/parser/image.js
@@ -0,0 +1,41 @@
+import { getImage } from '../../util/ajax';
+export default function image(data, cfg) {
+ const { extent } = cfg;
+
+ const images = new Promise(resolve => {
+ loadData(data, res => {
+ resolve(res);
+ });
+ });
+ const resultData = {
+ images,
+ _id: 1,
+ dataArray: [{ coordinates: [[ extent[0], extent[1] ], [ extent[2], extent[3] ]] }]
+ };
+ return resultData;
+}
+function loadData(data, done) {
+ const url = data;
+ let image = [];
+ if (typeof (url) === 'string') {
+ getImage({ url }, (err, img) => {
+ image = img;
+ done(image);
+ });
+ } else {
+ const imageCount = url.length;
+ let imageindex = 0;
+ url.forEach(item => {
+ getImage({ url: item }, (err, img) => {
+ imageindex++;
+ image.push(img);
+ if (imageindex === imageCount) {
+ done(image);
+ }
+
+ });
+ });
+
+ }
+ return image;
+}
diff --git a/src/source/parser/json.js b/src/source/parser/json.js
new file mode 100644
index 0000000000..37128bebce
--- /dev/null
+++ b/src/source/parser/json.js
@@ -0,0 +1,21 @@
+export default function json(data, cfg) {
+ const { x, y, x1, y1 } = cfg;
+ const resultdata = [];
+ data.forEach((col, featureIndex) => {
+ let coordinates = [];
+ if (x && y) { coordinates = [ col[x], col[y] ]; } // 点数据
+ if (x1 && y1) { // 弧线 或者线段
+ coordinates = [[ col[x], col[y] ], [ col[x1], col[y1] ]];
+ }
+ col._id = featureIndex + 1;
+ const dataItem = {
+ ...col,
+ coordinates
+
+ };
+ resultdata.push(dataItem);
+ });
+ return {
+ dataArray: resultdata
+ };
+}
diff --git a/src/source/parser/raster.js b/src/source/parser/raster.js
new file mode 100644
index 0000000000..7d33903a23
--- /dev/null
+++ b/src/source/parser/raster.js
@@ -0,0 +1,15 @@
+export default function raster(data, cfg) {
+ const { extent, width, height, min, max } = cfg;
+ const resultData = {
+ _id: 1,
+ dataArray: [
+ {
+ data,
+ width,
+ height,
+ min,
+ max,
+ coordinates: [[ extent[0], extent[1] ], [ extent[2], extent[3] ]] }]
+ };
+ return resultData;
+}
diff --git a/src/source/rainSource.js b/src/source/rainSource.js
deleted file mode 100644
index 6808878742..0000000000
--- a/src/source/rainSource.js
+++ /dev/null
@@ -1,31 +0,0 @@
-import imageSource from './imageSource';
-export class RainSource extends imageSource {
- prepareData() {
- const extent = this.get('extent');
- const lb = this._coorConvert(extent.slice(0, 2));
- const tr = this._coorConvert(extent.slice(2, 4));
- this.extent = [ lb, tr ];
- this.propertiesData = [];
- this._genaratePoints();
- this._loadData();
- }
- _genaratePoints() {
- const numParticles = 512 * 512;
-
- const particleRes = this.particleRes = Math.ceil(Math.sqrt(numParticles));
- const numPoints = particleRes * particleRes;
- const particleState = [];
- const particleState0 = new Uint8ClampedArray(numPoints * 4);
- const particleState1 = new Uint8ClampedArray(numPoints * 4);
- const emptyPixels = new Uint8ClampedArray(numPoints * 4);
- for (let i = 0; i < particleState0.length; i++) {
- particleState0[i] = Math.floor(Math.random() * 256); // randomize the initial particle positions
- }
- this.particleIndices = new Float32Array(numPoints);
- for (let i = 0; i < numPoints; i++) this.particleIndices[i] = i;
- this.particleImage0 = new ImageData(particleState0, particleRes, particleRes);
- this.particleImage1 = new ImageData(particleState1, particleRes, particleRes);
- this.backgroundImage = new ImageData(emptyPixels, particleRes, particleRes);
- this.geoData = particleState;
- }
-}
diff --git a/src/source/rasterSource.js b/src/source/rasterSource.js
deleted file mode 100644
index 2439422dce..0000000000
--- a/src/source/rasterSource.js
+++ /dev/null
@@ -1,20 +0,0 @@
-import Source from '../core/source';
-export default class RasterSource extends Source {
- prepareData() {
- this.type = 'raster';
- const extent = this.get('extent');
- const lb = this._coorConvert(extent.slice(0, 2));
- const tr = this._coorConvert(extent.slice(2, 4));
- this.geoData = [ lb, tr ];
- this.propertiesData = [];
- this.rasterData = {
- data: this.get('data'),
- width: this.get('width'),
- height: this.get('height'),
- min: this.get('min'),
- max: this.get('max')
- };
-
- }
-
-}
diff --git a/src/source/transform/grid.js b/src/source/transform/grid.js
new file mode 100644
index 0000000000..d2ace3476c
--- /dev/null
+++ b/src/source/transform/grid.js
@@ -0,0 +1,101 @@
+/**
+ * 生成四边形热力图
+ */
+import * as statistics from './statistics';
+
+const R_EARTH = 6378000;
+
+/**
+ * 计算方格密度图
+ * @param {*} data 经纬度数据 和属性数据
+ * @param {*} size 半径大小 单位 km
+ * @return
+ */
+export function aggregatorToGrid(data, option) {
+ const dataArray = data.dataArray;
+ const { size = 10 } = option;
+ const { gridHash, gridOffset } = _pointsGridHash(dataArray, size);
+ const layerData = _getGridLayerDataFromGridHash(gridHash, gridOffset, option);
+ return {
+ xOffset: gridOffset.xOffset / 360 * (256 << 20) / 2,
+ yOffset: gridOffset.xOffset / 360 * (256 << 20) / 2,
+ dataArray: layerData
+ };
+}
+
+function _pointsGridHash(dataArray, size) {
+ let latMin = Infinity;
+ let latMax = -Infinity;
+ let pLat;
+ for (let index = 0; index < dataArray.length; index++) {
+ const point = dataArray[index];
+ pLat = point.coordinates[1];
+ if (Number.isFinite(pLat)) {
+ latMin = pLat < latMin ? pLat : latMin;
+ latMax = pLat > latMax ? pLat : latMax;
+ }
+
+ }
+ // const centerLat = (latMin + latMax) / 2;
+ const centerLat = 34.54083;
+ const gridOffset = _calculateGridLatLonOffset(size, centerLat);
+ if (gridOffset.xOffset <= 0 || gridOffset.yOffset <= 0) {
+ return { gridHash: {}, gridOffset };
+ }
+ const gridHash = {};
+ for (let index = 0; index < dataArray.length; index++) {
+ const point = dataArray[index];
+ const lat = point.coordinates[1];
+ const lng = point.coordinates[0];
+
+ if (Number.isFinite(lat) && Number.isFinite(lng)) {
+ const latIdx = Math.floor((lat + 90) / gridOffset.yOffset);
+ const lonIdx = Math.floor((lng + 180) / gridOffset.xOffset);
+ const key = `${latIdx}-${lonIdx}`;
+
+ gridHash[key] = gridHash[key] || { count: 0, points: [] };
+ gridHash[key].count += 1;
+ gridHash[key].points.push(point);
+ }
+ }
+
+ return { gridHash, gridOffset };
+}
+// 计算网格偏移量
+function _calculateGridLatLonOffset(cellSize, latitude) {
+ const yOffset = _calculateLatOffset(cellSize);
+ const xOffset = _calculateLonOffset(latitude, cellSize);
+ return { yOffset, xOffset };
+}
+
+function _calculateLatOffset(dy) {
+ return (dy / R_EARTH) * (180 / Math.PI);
+}
+
+function _calculateLonOffset(lat, dx) {
+ return ((dx / R_EARTH) * (180 / Math.PI)) / Math.cos((lat * Math.PI) / 180);
+}
+function _getGridLayerDataFromGridHash(gridHash, gridOffset, option) {
+ return Object.keys(gridHash).reduce((accu, key, i) => {
+ const idxs = key.split('-');
+ const latIdx = parseInt(idxs[0], 10);
+ const lonIdx = parseInt(idxs[1], 10);
+ const item = {};
+ if (option.field && option.method) {
+ const columns = getColumn(gridHash[key].points, option.field);
+ item[option.method] = statistics[option.method](columns);
+ }
+ Object.assign(item, {
+ _id: i + 1,
+ coordinates: [ -180 + gridOffset.xOffset * lonIdx, -90 + gridOffset.yOffset * latIdx ],
+ count: gridHash[key].count
+ });
+ accu.push(item);
+ return accu;
+ }, []);
+}
+function getColumn(data, columnName) {
+ return data.map(item => {
+ return item[columnName];
+ });
+}
diff --git a/src/source/transform/hexagon.js b/src/source/transform/hexagon.js
new file mode 100644
index 0000000000..df796c7450
--- /dev/null
+++ b/src/source/transform/hexagon.js
@@ -0,0 +1,41 @@
+import { hexbin } from 'd3-hexbin';
+import { aProjectFlat, unProjectFlat } from '../../geo/project';
+import * as statistics from './statistics';
+const R_EARTH = 6378000;
+export function pointToHexbin(data, option) {
+ const dataArray = data.dataArray;
+ const { size = 10 } = option;
+ const pixlSize = size / (2 * Math.PI * R_EARTH) * (256 << 20) / 2;
+ const screenPoints = dataArray.map(point => {
+ const { x, y } = aProjectFlat(point.coordinates);
+ return {
+ ...point,
+ coordinates: [ x, y ]
+ };
+ });
+
+ const newHexbin = hexbin()
+ .radius(pixlSize)
+ .x(d => d.coordinates[0])
+ .y(d => d.coordinates[1]);
+ const hexbinBins = newHexbin(screenPoints);
+ const result = {
+ size: pixlSize
+ };
+ result.dataArray = hexbinBins.map((hex, index) => {
+ if (option.field && option.method) {
+ const columns = getColumn(hex, option.field);
+ hex[option.method] = statistics[option.method](columns);
+ }
+ return {
+ coordinates: unProjectFlat([ hex.x, hex.y ]),
+ id: index + 1
+ };
+ });
+ return result;
+}
+function getColumn(data, columnName) {
+ return data.map(item => {
+ return item[columnName];
+ });
+}
diff --git a/src/source/transform/map.js b/src/source/transform/map.js
new file mode 100644
index 0000000000..47c66e1005
--- /dev/null
+++ b/src/source/transform/map.js
@@ -0,0 +1,7 @@
+export function map(data, options) {
+ const { callback } = options;
+ if (callback) {
+ data.dataArray = data.dataArray.map(callback);
+ }
+ return data;
+}
diff --git a/src/source/transform/statistics.js b/src/source/transform/statistics.js
new file mode 100644
index 0000000000..2a7a317846
--- /dev/null
+++ b/src/source/transform/statistics.js
@@ -0,0 +1,10 @@
+/* 支持 'max', 'mean', 'median', 'min', 'mode', 'product', 'standardDeviation',
+ * 'sum', 'sumSimple', 'variance', 'count', 'distinct'
+ */
+export { default as min } from 'simple-statistics/src/min';
+export { default as max } from 'simple-statistics/src/max';
+export { default as mean } from 'simple-statistics/src/mean';
+export { default as sum } from 'simple-statistics/src/sum';
+export { default as median } from 'simple-statistics/src/median';
+export { default as standardDeviation } from 'simple-statistics/src/standard_deviation';
+
diff --git a/test/asset/data/point.js b/test/asset/data/point.js
new file mode 100644
index 0000000000..6fc7183712
--- /dev/null
+++ b/test/asset/data/point.js
@@ -0,0 +1,1490 @@
+export const pointData = [
+ { grid_y: 121055, count: 7600, grid_x: 480481 },
+ { grid_y: 121055, count: 3800, grid_x: 480487 },
+ { grid_y: 121055, count: 3800, grid_x: 480493 },
+ { grid_y: 121055, count: 7600, grid_x: 480501 },
+ { grid_y: 121055, count: 3800, grid_x: 480502 },
+ { grid_y: 121055, count: 15200, grid_x: 480503 },
+ { grid_y: 121055, count: 3800, grid_x: 480504 },
+ { grid_y: 121055, count: 7600, grid_x: 480505 },
+ { grid_y: 121055, count: 3800, grid_x: 480506 },
+ { grid_y: 121055, count: 3800, grid_x: 480507 },
+ { grid_y: 121055, count: 3800, grid_x: 480512 },
+ { grid_y: 121055, count: 3800, grid_x: 480530 },
+ { grid_y: 121056, count: 3800, grid_x: 480494 },
+ { grid_y: 121056, count: 3800, grid_x: 480496 },
+ { grid_y: 121056, count: 7600, grid_x: 480501 },
+ { grid_y: 121056, count: 11400, grid_x: 480502 },
+ { grid_y: 121056, count: 7600, grid_x: 480503 },
+ { grid_y: 121056, count: 7600, grid_x: 480504 },
+ { grid_y: 121056, count: 3800, grid_x: 480506 },
+ { grid_y: 121056, count: 3800, grid_x: 480508 },
+ { grid_y: 121056, count: 3800, grid_x: 480509 },
+ { grid_y: 121056, count: 3800, grid_x: 480520 },
+ { grid_y: 121056, count: 3800, grid_x: 480524 },
+ { grid_y: 121057, count: 11400, grid_x: 480484 },
+ { grid_y: 121057, count: 3800, grid_x: 480489 },
+ { grid_y: 121057, count: 3800, grid_x: 480500 },
+ { grid_y: 121057, count: 3800, grid_x: 480502 },
+ { grid_y: 121057, count: 3800, grid_x: 480509 },
+ { grid_y: 121057, count: 3800, grid_x: 480515 },
+ { grid_y: 121057, count: 3800, grid_x: 480522 },
+ { grid_y: 121057, count: 3800, grid_x: 480523 },
+ { grid_y: 121057, count: 15200, grid_x: 480524 },
+ { grid_y: 121057, count: 3800, grid_x: 480525 },
+ { grid_y: 121057, count: 3800, grid_x: 480527 },
+ { grid_y: 121058, count: 3800, grid_x: 480478 },
+ { grid_y: 121058, count: 3800, grid_x: 480482 },
+ { grid_y: 121058, count: 3800, grid_x: 480485 },
+ { grid_y: 121058, count: 3800, grid_x: 480486 },
+ { grid_y: 121058, count: 3800, grid_x: 480487 },
+ { grid_y: 121058, count: 3800, grid_x: 480490 },
+ { grid_y: 121058, count: 3800, grid_x: 480497 },
+ { grid_y: 121058, count: 3800, grid_x: 480499 },
+ { grid_y: 121058, count: 7600, grid_x: 480501 },
+ { grid_y: 121058, count: 3800, grid_x: 480502 },
+ { grid_y: 121058, count: 7600, grid_x: 480503 },
+ { grid_y: 121058, count: 3800, grid_x: 480521 },
+ { grid_y: 121058, count: 3800, grid_x: 480522 },
+ { grid_y: 121058, count: 3800, grid_x: 480523 },
+ { grid_y: 121058, count: 3800, grid_x: 480524 },
+ { grid_y: 121058, count: 3800, grid_x: 480528 },
+ { grid_y: 121059, count: 3800, grid_x: 480495 },
+ { grid_y: 121059, count: 3800, grid_x: 480499 },
+ { grid_y: 121059, count: 3800, grid_x: 480500 },
+ { grid_y: 121059, count: 7600, grid_x: 480502 },
+ { grid_y: 121059, count: 7600, grid_x: 480503 },
+ { grid_y: 121059, count: 3800, grid_x: 480504 },
+ { grid_y: 121059, count: 34200, grid_x: 480507 },
+ { grid_y: 121059, count: 3800, grid_x: 480511 },
+ { grid_y: 121059, count: 3800, grid_x: 480516 },
+ { grid_y: 121060, count: 7600, grid_x: 480491 },
+ { grid_y: 121060, count: 7600, grid_x: 480496 },
+ { grid_y: 121060, count: 3800, grid_x: 480497 },
+ { grid_y: 121060, count: 3800, grid_x: 480498 },
+ { grid_y: 121060, count: 7600, grid_x: 480499 },
+ { grid_y: 121060, count: 7600, grid_x: 480500 },
+ { grid_y: 121060, count: 7600, grid_x: 480502 },
+ { grid_y: 121060, count: 3800, grid_x: 480505 },
+ { grid_y: 121060, count: 3800, grid_x: 480506 },
+ { grid_y: 121060, count: 3800, grid_x: 480511 },
+ { grid_y: 121060, count: 3800, grid_x: 480513 },
+ { grid_y: 121060, count: 3800, grid_x: 480514 },
+ { grid_y: 121061, count: 3800, grid_x: 480491 },
+ { grid_y: 121061, count: 7600, grid_x: 480497 },
+ { grid_y: 121061, count: 7600, grid_x: 480499 },
+ { grid_y: 121061, count: 11400, grid_x: 480500 },
+ { grid_y: 121061, count: 3800, grid_x: 480501 },
+ { grid_y: 121061, count: 7600, grid_x: 480502 },
+ { grid_y: 121061, count: 15200, grid_x: 480503 },
+ { grid_y: 121061, count: 11400, grid_x: 480504 },
+ { grid_y: 121061, count: 7600, grid_x: 480505 },
+ { grid_y: 121061, count: 3800, grid_x: 480506 },
+ { grid_y: 121061, count: 3800, grid_x: 480507 },
+ { grid_y: 121061, count: 3800, grid_x: 480511 },
+ { grid_y: 121061, count: 3800, grid_x: 480526 },
+ { grid_y: 121062, count: 15200, grid_x: 480489 },
+ { grid_y: 121062, count: 7600, grid_x: 480491 },
+ { grid_y: 121062, count: 7600, grid_x: 480492 },
+ { grid_y: 121062, count: 7600, grid_x: 480499 },
+ { grid_y: 121062, count: 11400, grid_x: 480500 },
+ { grid_y: 121062, count: 3800, grid_x: 480502 },
+ { grid_y: 121062, count: 3800, grid_x: 480503 },
+ { grid_y: 121062, count: 7600, grid_x: 480504 },
+ { grid_y: 121062, count: 3800, grid_x: 480505 },
+ { grid_y: 121062, count: 3800, grid_x: 480517 },
+ { grid_y: 121062, count: 7600, grid_x: 480522 },
+ { grid_y: 121062, count: 3800, grid_x: 480527 },
+ { grid_y: 121062, count: 3800, grid_x: 480530 },
+ { grid_y: 121063, count: 3800, grid_x: 480488 },
+ { grid_y: 121063, count: 7600, grid_x: 480489 },
+ { grid_y: 121063, count: 15200, grid_x: 480492 },
+ { grid_y: 121063, count: 3800, grid_x: 480493 },
+ { grid_y: 121063, count: 3800, grid_x: 480497 },
+ { grid_y: 121063, count: 7600, grid_x: 480499 },
+ { grid_y: 121063, count: 7600, grid_x: 480500 },
+ { grid_y: 121063, count: 15200, grid_x: 480501 },
+ { grid_y: 121063, count: 11400, grid_x: 480502 },
+ { grid_y: 121063, count: 3800, grid_x: 480516 },
+ { grid_y: 121063, count: 3800, grid_x: 480518 },
+ { grid_y: 121063, count: 3800, grid_x: 480522 },
+ { grid_y: 121063, count: 11400, grid_x: 480524 },
+ { grid_y: 121063, count: 3800, grid_x: 480525 },
+ { grid_y: 121064, count: 7600, grid_x: 480488 },
+ { grid_y: 121064, count: 3800, grid_x: 480489 },
+ { grid_y: 121064, count: 7600, grid_x: 480490 },
+ { grid_y: 121064, count: 3800, grid_x: 480491 },
+ { grid_y: 121064, count: 3800, grid_x: 480493 },
+ { grid_y: 121064, count: 3800, grid_x: 480495 },
+ { grid_y: 121064, count: 3800, grid_x: 480496 },
+ { grid_y: 121064, count: 15200, grid_x: 480499 },
+ { grid_y: 121064, count: 3800, grid_x: 480500 },
+ { grid_y: 121064, count: 15200, grid_x: 480501 },
+ { grid_y: 121064, count: 7600, grid_x: 480502 },
+ { grid_y: 121064, count: 3800, grid_x: 480523 },
+ { grid_y: 121065, count: 3800, grid_x: 480487 },
+ { grid_y: 121065, count: 3800, grid_x: 480488 },
+ { grid_y: 121065, count: 3800, grid_x: 480489 },
+ { grid_y: 121065, count: 11400, grid_x: 480490 },
+ { grid_y: 121065, count: 7600, grid_x: 480491 },
+ { grid_y: 121065, count: 3800, grid_x: 480492 },
+ { grid_y: 121065, count: 7600, grid_x: 480499 },
+ { grid_y: 121065, count: 3800, grid_x: 480500 },
+ { grid_y: 121065, count: 7600, grid_x: 480501 },
+ { grid_y: 121065, count: 3800, grid_x: 480509 },
+ { grid_y: 121065, count: 3800, grid_x: 480512 },
+ { grid_y: 121065, count: 3800, grid_x: 480516 },
+ { grid_y: 121065, count: 3800, grid_x: 480527 },
+ { grid_y: 121066, count: 3800, grid_x: 480488 },
+ { grid_y: 121066, count: 7600, grid_x: 480489 },
+ { grid_y: 121066, count: 3800, grid_x: 480490 },
+ { grid_y: 121066, count: 11400, grid_x: 480491 },
+ { grid_y: 121066, count: 7600, grid_x: 480492 },
+ { grid_y: 121066, count: 3800, grid_x: 480496 },
+ { grid_y: 121066, count: 7600, grid_x: 480498 },
+ { grid_y: 121066, count: 3800, grid_x: 480500 },
+ { grid_y: 121066, count: 7600, grid_x: 480501 },
+ { grid_y: 121066, count: 3800, grid_x: 480505 },
+ { grid_y: 121066, count: 3800, grid_x: 480509 },
+ { grid_y: 121066, count: 3800, grid_x: 480511 },
+ { grid_y: 121066, count: 3800, grid_x: 480512 },
+ { grid_y: 121066, count: 3800, grid_x: 480514 },
+ { grid_y: 121067, count: 15200, grid_x: 480491 },
+ { grid_y: 121067, count: 3800, grid_x: 480493 },
+ { grid_y: 121067, count: 3800, grid_x: 480494 },
+ { grid_y: 121067, count: 7600, grid_x: 480495 },
+ { grid_y: 121067, count: 7600, grid_x: 480496 },
+ { grid_y: 121067, count: 7600, grid_x: 480497 },
+ { grid_y: 121067, count: 7600, grid_x: 480498 },
+ { grid_y: 121067, count: 3800, grid_x: 480499 },
+ { grid_y: 121067, count: 11400, grid_x: 480500 },
+ { grid_y: 121067, count: 3800, grid_x: 480501 },
+ { grid_y: 121067, count: 3800, grid_x: 480503 },
+ { grid_y: 121067, count: 3800, grid_x: 480509 },
+ { grid_y: 121067, count: 3800, grid_x: 480513 },
+ { grid_y: 121067, count: 3800, grid_x: 480515 },
+ { grid_y: 121068, count: 7600, grid_x: 480488 },
+ { grid_y: 121068, count: 7600, grid_x: 480489 },
+ { grid_y: 121068, count: 11400, grid_x: 480490 },
+ { grid_y: 121068, count: 3800, grid_x: 480491 },
+ { grid_y: 121068, count: 7600, grid_x: 480493 },
+ { grid_y: 121068, count: 3800, grid_x: 480494 },
+ { grid_y: 121068, count: 3800, grid_x: 480495 },
+ { grid_y: 121068, count: 41800, grid_x: 480499 },
+ { grid_y: 121068, count: 19000, grid_x: 480500 },
+ { grid_y: 121068, count: 3800, grid_x: 480501 },
+ { grid_y: 121068, count: 3800, grid_x: 480502 },
+ { grid_y: 121068, count: 3800, grid_x: 480504 },
+ { grid_y: 121068, count: 3800, grid_x: 480509 },
+ { grid_y: 121068, count: 3800, grid_x: 480515 },
+ { grid_y: 121069, count: 3800, grid_x: 480489 },
+ { grid_y: 121069, count: 3800, grid_x: 480491 },
+ { grid_y: 121069, count: 7600, grid_x: 480492 },
+ { grid_y: 121069, count: 7600, grid_x: 480493 },
+ { grid_y: 121069, count: 3800, grid_x: 480494 },
+ { grid_y: 121069, count: 3800, grid_x: 480495 },
+ { grid_y: 121069, count: 7600, grid_x: 480499 },
+ { grid_y: 121069, count: 3800, grid_x: 480502 },
+ { grid_y: 121069, count: 3800, grid_x: 480509 },
+ { grid_y: 121069, count: 3800, grid_x: 480513 },
+ { grid_y: 121069, count: 3800, grid_x: 480515 },
+ { grid_y: 121069, count: 3800, grid_x: 480517 },
+ { grid_y: 121069, count: 7600, grid_x: 480524 },
+ { grid_y: 121070, count: 3800, grid_x: 480490 },
+ { grid_y: 121070, count: 11400, grid_x: 480491 },
+ { grid_y: 121070, count: 3800, grid_x: 480492 },
+ { grid_y: 121070, count: 3800, grid_x: 480497 },
+ { grid_y: 121070, count: 3800, grid_x: 480501 },
+ { grid_y: 121070, count: 7600, grid_x: 480510 },
+ { grid_y: 121070, count: 19000, grid_x: 480513 },
+ { grid_y: 121070, count: 3800, grid_x: 480514 },
+ { grid_y: 121070, count: 3800, grid_x: 480515 },
+ { grid_y: 121070, count: 11400, grid_x: 480516 },
+ { grid_y: 121070, count: 7600, grid_x: 480517 },
+ { grid_y: 121070, count: 3800, grid_x: 480518 },
+ { grid_y: 121070, count: 3800, grid_x: 480519 },
+ { grid_y: 121070, count: 7600, grid_x: 480533 },
+ { grid_y: 121071, count: 11400, grid_x: 480491 },
+ { grid_y: 121071, count: 7600, grid_x: 480492 },
+ { grid_y: 121071, count: 15200, grid_x: 480493 },
+ { grid_y: 121071, count: 7600, grid_x: 480494 },
+ { grid_y: 121071, count: 3800, grid_x: 480495 },
+ { grid_y: 121071, count: 3800, grid_x: 480497 },
+ { grid_y: 121071, count: 3800, grid_x: 480502 },
+ { grid_y: 121071, count: 3800, grid_x: 480503 },
+ { grid_y: 121071, count: 3800, grid_x: 480510 },
+ { grid_y: 121071, count: 11400, grid_x: 480513 },
+ { grid_y: 121071, count: 7600, grid_x: 480515 },
+ { grid_y: 121071, count: 7600, grid_x: 480516 },
+ { grid_y: 121071, count: 7600, grid_x: 480517 },
+ { grid_y: 121071, count: 3800, grid_x: 480519 },
+ { grid_y: 121071, count: 3800, grid_x: 480520 },
+ { grid_y: 121071, count: 3800, grid_x: 480523 },
+ { grid_y: 121072, count: 15200, grid_x: 480492 },
+ { grid_y: 121072, count: 11400, grid_x: 480493 },
+ { grid_y: 121072, count: 3800, grid_x: 480494 },
+ { grid_y: 121072, count: 3800, grid_x: 480496 },
+ { grid_y: 121072, count: 3800, grid_x: 480500 },
+ { grid_y: 121072, count: 7600, grid_x: 480501 },
+ { grid_y: 121072, count: 3800, grid_x: 480508 },
+ { grid_y: 121072, count: 7600, grid_x: 480514 },
+ { grid_y: 121072, count: 3800, grid_x: 480515 },
+ { grid_y: 121072, count: 3800, grid_x: 480517 },
+ { grid_y: 121072, count: 3800, grid_x: 480518 },
+ { grid_y: 121073, count: 7600, grid_x: 480491 },
+ { grid_y: 121073, count: 7600, grid_x: 480492 },
+ { grid_y: 121073, count: 3800, grid_x: 480494 },
+ { grid_y: 121073, count: 3800, grid_x: 480497 },
+ { grid_y: 121073, count: 11400, grid_x: 480501 },
+ { grid_y: 121073, count: 7600, grid_x: 480502 },
+ { grid_y: 121073, count: 3800, grid_x: 480503 },
+ { grid_y: 121073, count: 3800, grid_x: 480504 },
+ { grid_y: 121073, count: 3800, grid_x: 480511 },
+ { grid_y: 121073, count: 3800, grid_x: 480512 },
+ { grid_y: 121073, count: 3800, grid_x: 480516 },
+ { grid_y: 121073, count: 3800, grid_x: 480517 },
+ { grid_y: 121074, count: 3800, grid_x: 480459 },
+ { grid_y: 121074, count: 3800, grid_x: 480491 },
+ { grid_y: 121074, count: 3800, grid_x: 480492 },
+ { grid_y: 121074, count: 3800, grid_x: 480493 },
+ { grid_y: 121074, count: 3800, grid_x: 480494 },
+ { grid_y: 121074, count: 7600, grid_x: 480497 },
+ { grid_y: 121074, count: 3800, grid_x: 480498 },
+ { grid_y: 121074, count: 3800, grid_x: 480499 },
+ { grid_y: 121074, count: 7600, grid_x: 480501 },
+ { grid_y: 121074, count: 15200, grid_x: 480502 },
+ { grid_y: 121074, count: 3800, grid_x: 480503 },
+ { grid_y: 121074, count: 3800, grid_x: 480507 },
+ { grid_y: 121074, count: 7600, grid_x: 480517 },
+ { grid_y: 121074, count: 3800, grid_x: 480520 },
+ { grid_y: 121075, count: 3800, grid_x: 480493 },
+ { grid_y: 121075, count: 3800, grid_x: 480495 },
+ { grid_y: 121075, count: 3800, grid_x: 480496 },
+ { grid_y: 121075, count: 3800, grid_x: 480497 },
+ { grid_y: 121075, count: 7600, grid_x: 480498 },
+ { grid_y: 121075, count: 7600, grid_x: 480499 },
+ { grid_y: 121075, count: 7600, grid_x: 480500 },
+ { grid_y: 121075, count: 7600, grid_x: 480501 },
+ { grid_y: 121075, count: 7600, grid_x: 480502 },
+ { grid_y: 121075, count: 7600, grid_x: 480503 },
+ { grid_y: 121075, count: 3800, grid_x: 480504 },
+ { grid_y: 121075, count: 7600, grid_x: 480506 },
+ { grid_y: 121075, count: 3800, grid_x: 480511 },
+ { grid_y: 121075, count: 3800, grid_x: 480517 },
+ { grid_y: 121075, count: 3800, grid_x: 480518 },
+ { grid_y: 121075, count: 3800, grid_x: 480519 },
+ { grid_y: 121075, count: 7600, grid_x: 480520 },
+ { grid_y: 121076, count: 3800, grid_x: 480491 },
+ { grid_y: 121076, count: 7600, grid_x: 480498 },
+ { grid_y: 121076, count: 7600, grid_x: 480499 },
+ { grid_y: 121076, count: 3800, grid_x: 480501 },
+ { grid_y: 121076, count: 3800, grid_x: 480502 },
+ { grid_y: 121076, count: 15200, grid_x: 480503 },
+ { grid_y: 121076, count: 3800, grid_x: 480509 },
+ { grid_y: 121076, count: 3800, grid_x: 480515 },
+ { grid_y: 121076, count: 3800, grid_x: 480516 },
+ { grid_y: 121076, count: 3800, grid_x: 480521 },
+ { grid_y: 121076, count: 3800, grid_x: 480523 },
+ { grid_y: 121077, count: 3800, grid_x: 480475 },
+ { grid_y: 121077, count: 3800, grid_x: 480496 },
+ { grid_y: 121077, count: 7600, grid_x: 480498 },
+ { grid_y: 121077, count: 7600, grid_x: 480499 },
+ { grid_y: 121077, count: 7600, grid_x: 480500 },
+ { grid_y: 121077, count: 3800, grid_x: 480501 },
+ { grid_y: 121077, count: 3800, grid_x: 480503 },
+ { grid_y: 121077, count: 7600, grid_x: 480506 },
+ { grid_y: 121077, count: 3800, grid_x: 480509 },
+ { grid_y: 121077, count: 3800, grid_x: 480511 },
+ { grid_y: 121077, count: 3800, grid_x: 480517 },
+ { grid_y: 121077, count: 3800, grid_x: 480518 },
+ { grid_y: 121077, count: 3800, grid_x: 480531 },
+ { grid_y: 121078, count: 3800, grid_x: 480462 },
+ { grid_y: 121078, count: 3800, grid_x: 480474 },
+ { grid_y: 121078, count: 3800, grid_x: 480479 },
+ { grid_y: 121078, count: 3800, grid_x: 480485 },
+ { grid_y: 121078, count: 3800, grid_x: 480496 },
+ { grid_y: 121078, count: 7600, grid_x: 480497 },
+ { grid_y: 121078, count: 3800, grid_x: 480499 },
+ { grid_y: 121078, count: 7600, grid_x: 480501 },
+ { grid_y: 121078, count: 3800, grid_x: 480502 },
+ { grid_y: 121078, count: 3800, grid_x: 480507 },
+ { grid_y: 121078, count: 7600, grid_x: 480509 },
+ { grid_y: 121078, count: 15200, grid_x: 480510 },
+ { grid_y: 121078, count: 3800, grid_x: 480512 },
+ { grid_y: 121078, count: 3800, grid_x: 480529 },
+ { grid_y: 121078, count: 3800, grid_x: 480530 },
+ { grid_y: 121079, count: 3800, grid_x: 480462 },
+ { grid_y: 121079, count: 3800, grid_x: 480478 },
+ { grid_y: 121079, count: 3800, grid_x: 480497 },
+ { grid_y: 121079, count: 3800, grid_x: 480499 },
+ { grid_y: 121079, count: 3800, grid_x: 480504 },
+ { grid_y: 121079, count: 3800, grid_x: 480511 },
+ { grid_y: 121079, count: 3800, grid_x: 480532 },
+ { grid_y: 121080, count: 3800, grid_x: 480479 },
+ { grid_y: 121080, count: 3800, grid_x: 480491 },
+ { grid_y: 121080, count: 3800, grid_x: 480492 },
+ { grid_y: 121080, count: 3800, grid_x: 480493 },
+ { grid_y: 121080, count: 7600, grid_x: 480494 },
+ { grid_y: 121080, count: 3800, grid_x: 480495 },
+ { grid_y: 121080, count: 3800, grid_x: 480499 },
+ { grid_y: 121080, count: 3800, grid_x: 480500 },
+ { grid_y: 121080, count: 3800, grid_x: 480510 },
+ { grid_y: 121080, count: 3800, grid_x: 480520 },
+ { grid_y: 121081, count: 11400, grid_x: 480462 },
+ { grid_y: 121081, count: 3800, grid_x: 480492 },
+ { grid_y: 121081, count: 3800, grid_x: 480493 },
+ { grid_y: 121081, count: 3800, grid_x: 480494 },
+ { grid_y: 121081, count: 11400, grid_x: 480495 },
+ { grid_y: 121081, count: 3800, grid_x: 480518 },
+ { grid_y: 121081, count: 3800, grid_x: 480522 },
+ { grid_y: 121081, count: 3800, grid_x: 480523 },
+ { grid_y: 121082, count: 3800, grid_x: 480490 },
+ { grid_y: 121082, count: 3800, grid_x: 480494 },
+ { grid_y: 121082, count: 3800, grid_x: 480507 },
+ { grid_y: 121082, count: 3800, grid_x: 480510 },
+ { grid_y: 121082, count: 3800, grid_x: 480519 },
+ { grid_y: 121082, count: 3800, grid_x: 480520 },
+ { grid_y: 121082, count: 3800, grid_x: 480521 },
+ { grid_y: 121083, count: 3800, grid_x: 480511 },
+ { grid_y: 121083, count: 7600, grid_x: 480513 },
+ { grid_y: 121083, count: 3800, grid_x: 480514 },
+ { grid_y: 121083, count: 3800, grid_x: 480515 },
+ { grid_y: 121083, count: 3800, grid_x: 480516 },
+ { grid_y: 121083, count: 3800, grid_x: 480520 },
+ { grid_y: 121083, count: 3800, grid_x: 480522 },
+ { grid_y: 121083, count: 3800, grid_x: 480523 },
+ { grid_y: 121083, count: 7600, grid_x: 480524 },
+ { grid_y: 121083, count: 3800, grid_x: 480525 },
+ { grid_y: 121084, count: 3800, grid_x: 480485 },
+ { grid_y: 121084, count: 3800, grid_x: 480486 },
+ { grid_y: 121084, count: 3800, grid_x: 480487 },
+ { grid_y: 121084, count: 3800, grid_x: 480494 },
+ { grid_y: 121084, count: 3800, grid_x: 480495 },
+ { grid_y: 121084, count: 3800, grid_x: 480497 },
+ { grid_y: 121084, count: 3800, grid_x: 480500 },
+ { grid_y: 121084, count: 3800, grid_x: 480512 },
+ { grid_y: 121084, count: 22800, grid_x: 480513 },
+ { grid_y: 121084, count: 7600, grid_x: 480514 },
+ { grid_y: 121084, count: 3800, grid_x: 480515 },
+ { grid_y: 121084, count: 3800, grid_x: 480520 },
+ { grid_y: 121084, count: 3800, grid_x: 480521 },
+ { grid_y: 121084, count: 3800, grid_x: 480522 },
+ { grid_y: 121084, count: 3800, grid_x: 480523 },
+ { grid_y: 121084, count: 3800, grid_x: 480531 },
+ { grid_y: 121085, count: 3800, grid_x: 480499 },
+ { grid_y: 121085, count: 7600, grid_x: 480500 },
+ { grid_y: 121085, count: 3800, grid_x: 480501 },
+ { grid_y: 121085, count: 3800, grid_x: 480504 },
+ { grid_y: 121085, count: 3800, grid_x: 480506 },
+ { grid_y: 121085, count: 7600, grid_x: 480513 },
+ { grid_y: 121085, count: 11400, grid_x: 480514 },
+ { grid_y: 121085, count: 3800, grid_x: 480515 },
+ { grid_y: 121085, count: 3800, grid_x: 480517 },
+ { grid_y: 121085, count: 3800, grid_x: 480518 },
+ { grid_y: 121085, count: 3800, grid_x: 480520 },
+ { grid_y: 121085, count: 3800, grid_x: 480527 },
+ { grid_y: 121085, count: 3800, grid_x: 480532 },
+ { grid_y: 121086, count: 3800, grid_x: 480483 },
+ { grid_y: 121086, count: 3800, grid_x: 480490 },
+ { grid_y: 121086, count: 7600, grid_x: 480494 },
+ { grid_y: 121086, count: 3800, grid_x: 480497 },
+ { grid_y: 121086, count: 7600, grid_x: 480498 },
+ { grid_y: 121086, count: 3800, grid_x: 480499 },
+ { grid_y: 121086, count: 7600, grid_x: 480500 },
+ { grid_y: 121086, count: 3800, grid_x: 480507 },
+ { grid_y: 121086, count: 3800, grid_x: 480511 },
+ { grid_y: 121086, count: 7600, grid_x: 480512 },
+ { grid_y: 121086, count: 7600, grid_x: 480516 },
+ { grid_y: 121086, count: 3800, grid_x: 480517 },
+ { grid_y: 121086, count: 7600, grid_x: 480518 },
+ { grid_y: 121086, count: 3800, grid_x: 480520 },
+ { grid_y: 121086, count: 11400, grid_x: 480521 },
+ { grid_y: 121086, count: 3800, grid_x: 480523 },
+ { grid_y: 121086, count: 3800, grid_x: 480524 },
+ { grid_y: 121086, count: 3800, grid_x: 480527 },
+ { grid_y: 121086, count: 7600, grid_x: 480528 },
+ { grid_y: 121086, count: 3800, grid_x: 480529 },
+ { grid_y: 121086, count: 3800, grid_x: 480531 },
+ { grid_y: 121087, count: 7600, grid_x: 480460 },
+ { grid_y: 121087, count: 3800, grid_x: 480463 },
+ { grid_y: 121087, count: 3800, grid_x: 480472 },
+ { grid_y: 121087, count: 3800, grid_x: 480489 },
+ { grid_y: 121087, count: 3800, grid_x: 480494 },
+ { grid_y: 121087, count: 3800, grid_x: 480495 },
+ { grid_y: 121087, count: 7600, grid_x: 480501 },
+ { grid_y: 121087, count: 15200, grid_x: 480502 },
+ { grid_y: 121087, count: 11400, grid_x: 480503 },
+ { grid_y: 121087, count: 7600, grid_x: 480504 },
+ { grid_y: 121087, count: 7600, grid_x: 480508 },
+ { grid_y: 121087, count: 3800, grid_x: 480518 },
+ { grid_y: 121087, count: 3800, grid_x: 480519 },
+ { grid_y: 121087, count: 3800, grid_x: 480527 },
+ { grid_y: 121087, count: 3800, grid_x: 480528 },
+ { grid_y: 121087, count: 3800, grid_x: 480529 },
+ { grid_y: 121087, count: 7600, grid_x: 480533 },
+ { grid_y: 121088, count: 3800, grid_x: 480460 },
+ { grid_y: 121088, count: 3800, grid_x: 480478 },
+ { grid_y: 121088, count: 7600, grid_x: 480479 },
+ { grid_y: 121088, count: 3800, grid_x: 480483 },
+ { grid_y: 121088, count: 3800, grid_x: 480487 },
+ { grid_y: 121088, count: 7600, grid_x: 480491 },
+ { grid_y: 121088, count: 3800, grid_x: 480493 },
+ { grid_y: 121088, count: 3800, grid_x: 480494 },
+ { grid_y: 121088, count: 7600, grid_x: 480496 },
+ { grid_y: 121088, count: 3800, grid_x: 480497 },
+ { grid_y: 121088, count: 3800, grid_x: 480498 },
+ { grid_y: 121088, count: 3800, grid_x: 480502 },
+ { grid_y: 121088, count: 7600, grid_x: 480503 },
+ { grid_y: 121088, count: 3800, grid_x: 480504 },
+ { grid_y: 121088, count: 3800, grid_x: 480505 },
+ { grid_y: 121088, count: 7600, grid_x: 480506 },
+ { grid_y: 121088, count: 3800, grid_x: 480507 },
+ { grid_y: 121088, count: 7600, grid_x: 480508 },
+ { grid_y: 121088, count: 7600, grid_x: 480510 },
+ { grid_y: 121088, count: 3800, grid_x: 480511 },
+ { grid_y: 121088, count: 7600, grid_x: 480512 },
+ { grid_y: 121088, count: 7600, grid_x: 480520 },
+ { grid_y: 121088, count: 3800, grid_x: 480529 },
+ { grid_y: 121089, count: 3800, grid_x: 480462 },
+ { grid_y: 121089, count: 3800, grid_x: 480470 },
+ { grid_y: 121089, count: 3800, grid_x: 480472 },
+ { grid_y: 121089, count: 3800, grid_x: 480474 },
+ { grid_y: 121089, count: 3800, grid_x: 480475 },
+ { grid_y: 121089, count: 3800, grid_x: 480476 },
+ { grid_y: 121089, count: 7600, grid_x: 480477 },
+ { grid_y: 121089, count: 3800, grid_x: 480480 },
+ { grid_y: 121089, count: 3800, grid_x: 480481 },
+ { grid_y: 121089, count: 7600, grid_x: 480482 },
+ { grid_y: 121089, count: 3800, grid_x: 480486 },
+ { grid_y: 121089, count: 3800, grid_x: 480489 },
+ { grid_y: 121089, count: 3800, grid_x: 480491 },
+ { grid_y: 121089, count: 7600, grid_x: 480493 },
+ { grid_y: 121089, count: 11400, grid_x: 480498 },
+ { grid_y: 121089, count: 3800, grid_x: 480501 },
+ { grid_y: 121089, count: 7600, grid_x: 480502 },
+ { grid_y: 121089, count: 3800, grid_x: 480503 },
+ { grid_y: 121089, count: 3800, grid_x: 480504 },
+ { grid_y: 121089, count: 3800, grid_x: 480505 },
+ { grid_y: 121089, count: 7600, grid_x: 480506 },
+ { grid_y: 121089, count: 3800, grid_x: 480508 },
+ { grid_y: 121089, count: 7600, grid_x: 480512 },
+ { grid_y: 121089, count: 3800, grid_x: 480514 },
+ { grid_y: 121089, count: 3800, grid_x: 480521 },
+ { grid_y: 121089, count: 3800, grid_x: 480530 },
+ { grid_y: 121090, count: 3800, grid_x: 480461 },
+ { grid_y: 121090, count: 3800, grid_x: 480467 },
+ { grid_y: 121090, count: 3800, grid_x: 480470 },
+ { grid_y: 121090, count: 3800, grid_x: 480474 },
+ { grid_y: 121090, count: 3800, grid_x: 480475 },
+ { grid_y: 121090, count: 7600, grid_x: 480480 },
+ { grid_y: 121090, count: 3800, grid_x: 480484 },
+ { grid_y: 121090, count: 3800, grid_x: 480487 },
+ { grid_y: 121090, count: 3800, grid_x: 480495 },
+ { grid_y: 121090, count: 3800, grid_x: 480498 },
+ { grid_y: 121090, count: 7600, grid_x: 480499 },
+ { grid_y: 121090, count: 3800, grid_x: 480500 },
+ { grid_y: 121090, count: 45600, grid_x: 480501 },
+ { grid_y: 121090, count: 34200, grid_x: 480502 },
+ { grid_y: 121090, count: 15200, grid_x: 480503 },
+ { grid_y: 121090, count: 7600, grid_x: 480504 },
+ { grid_y: 121090, count: 7600, grid_x: 480505 },
+ { grid_y: 121090, count: 3800, grid_x: 480506 },
+ { grid_y: 121090, count: 3800, grid_x: 480508 },
+ { grid_y: 121090, count: 3800, grid_x: 480509 },
+ { grid_y: 121090, count: 3800, grid_x: 480510 },
+ { grid_y: 121090, count: 3800, grid_x: 480511 },
+ { grid_y: 121090, count: 3800, grid_x: 480512 },
+ { grid_y: 121090, count: 3800, grid_x: 480521 },
+ { grid_y: 121090, count: 3800, grid_x: 480522 },
+ { grid_y: 121090, count: 3800, grid_x: 480523 },
+ { grid_y: 121090, count: 3800, grid_x: 480524 },
+ { grid_y: 121090, count: 7600, grid_x: 480525 },
+ { grid_y: 121090, count: 3800, grid_x: 480527 },
+ { grid_y: 121091, count: 3800, grid_x: 480461 },
+ { grid_y: 121091, count: 3800, grid_x: 480467 },
+ { grid_y: 121091, count: 7600, grid_x: 480472 },
+ { grid_y: 121091, count: 3800, grid_x: 480481 },
+ { grid_y: 121091, count: 3800, grid_x: 480486 },
+ { grid_y: 121091, count: 7600, grid_x: 480491 },
+ { grid_y: 121091, count: 7600, grid_x: 480493 },
+ { grid_y: 121091, count: 3800, grid_x: 480494 },
+ { grid_y: 121091, count: 15200, grid_x: 480495 },
+ { grid_y: 121091, count: 7600, grid_x: 480496 },
+ { grid_y: 121091, count: 11400, grid_x: 480498 },
+ { grid_y: 121091, count: 11400, grid_x: 480500 },
+ { grid_y: 121091, count: 3800, grid_x: 480501 },
+ { grid_y: 121091, count: 11400, grid_x: 480502 },
+ { grid_y: 121091, count: 7600, grid_x: 480503 },
+ { grid_y: 121091, count: 7600, grid_x: 480504 },
+ { grid_y: 121091, count: 3800, grid_x: 480508 },
+ { grid_y: 121091, count: 3800, grid_x: 480509 },
+ { grid_y: 121091, count: 3800, grid_x: 480520 },
+ { grid_y: 121091, count: 7600, grid_x: 480521 },
+ { grid_y: 121091, count: 7600, grid_x: 480522 },
+ { grid_y: 121091, count: 26600, grid_x: 480523 },
+ { grid_y: 121091, count: 7600, grid_x: 480524 },
+ { grid_y: 121091, count: 7600, grid_x: 480525 },
+ { grid_y: 121091, count: 15200, grid_x: 480526 },
+ { grid_y: 121091, count: 3800, grid_x: 480527 },
+ { grid_y: 121091, count: 3800, grid_x: 480528 },
+ { grid_y: 121091, count: 3800, grid_x: 480532 },
+ { grid_y: 121091, count: 3800, grid_x: 480533 },
+ { grid_y: 121092, count: 7600, grid_x: 480460 },
+ { grid_y: 121092, count: 3800, grid_x: 480465 },
+ { grid_y: 121092, count: 7600, grid_x: 480466 },
+ { grid_y: 121092, count: 3800, grid_x: 480467 },
+ { grid_y: 121092, count: 3800, grid_x: 480468 },
+ { grid_y: 121092, count: 3800, grid_x: 480469 },
+ { grid_y: 121092, count: 3800, grid_x: 480474 },
+ { grid_y: 121092, count: 7600, grid_x: 480482 },
+ { grid_y: 121092, count: 3800, grid_x: 480491 },
+ { grid_y: 121092, count: 3800, grid_x: 480492 },
+ { grid_y: 121092, count: 3800, grid_x: 480493 },
+ { grid_y: 121092, count: 7600, grid_x: 480494 },
+ { grid_y: 121092, count: 11400, grid_x: 480495 },
+ { grid_y: 121092, count: 3800, grid_x: 480496 },
+ { grid_y: 121092, count: 15200, grid_x: 480498 },
+ { grid_y: 121092, count: 7600, grid_x: 480499 },
+ { grid_y: 121092, count: 3800, grid_x: 480501 },
+ { grid_y: 121092, count: 7600, grid_x: 480502 },
+ { grid_y: 121092, count: 3800, grid_x: 480503 },
+ { grid_y: 121092, count: 3800, grid_x: 480504 },
+ { grid_y: 121092, count: 7600, grid_x: 480507 },
+ { grid_y: 121092, count: 3800, grid_x: 480508 },
+ { grid_y: 121092, count: 3800, grid_x: 480511 },
+ { grid_y: 121092, count: 3800, grid_x: 480512 },
+ { grid_y: 121092, count: 3800, grid_x: 480516 },
+ { grid_y: 121092, count: 7600, grid_x: 480523 },
+ { grid_y: 121092, count: 7600, grid_x: 480524 },
+ { grid_y: 121092, count: 7600, grid_x: 480525 },
+ { grid_y: 121092, count: 7600, grid_x: 480526 },
+ { grid_y: 121092, count: 3800, grid_x: 480532 },
+ { grid_y: 121092, count: 3800, grid_x: 480533 },
+ { grid_y: 121093, count: 3800, grid_x: 480463 },
+ { grid_y: 121093, count: 7600, grid_x: 480466 },
+ { grid_y: 121093, count: 3800, grid_x: 480468 },
+ { grid_y: 121093, count: 3800, grid_x: 480493 },
+ { grid_y: 121093, count: 3800, grid_x: 480494 },
+ { grid_y: 121093, count: 3800, grid_x: 480496 },
+ { grid_y: 121093, count: 3800, grid_x: 480498 },
+ { grid_y: 121093, count: 3800, grid_x: 480499 },
+ { grid_y: 121093, count: 3800, grid_x: 480502 },
+ { grid_y: 121093, count: 3800, grid_x: 480503 },
+ { grid_y: 121093, count: 3800, grid_x: 480504 },
+ { grid_y: 121093, count: 3800, grid_x: 480507 },
+ { grid_y: 121093, count: 3800, grid_x: 480508 },
+ { grid_y: 121093, count: 3800, grid_x: 480509 },
+ { grid_y: 121093, count: 3800, grid_x: 480512 },
+ { grid_y: 121093, count: 3800, grid_x: 480514 },
+ { grid_y: 121093, count: 3800, grid_x: 480520 },
+ { grid_y: 121093, count: 3800, grid_x: 480521 },
+ { grid_y: 121093, count: 3800, grid_x: 480523 },
+ { grid_y: 121093, count: 3800, grid_x: 480524 },
+ { grid_y: 121093, count: 3800, grid_x: 480526 },
+ { grid_y: 121093, count: 3800, grid_x: 480532 },
+ { grid_y: 121093, count: 3800, grid_x: 480533 },
+ { grid_y: 121094, count: 3800, grid_x: 480467 },
+ { grid_y: 121094, count: 3800, grid_x: 480491 },
+ { grid_y: 121094, count: 3800, grid_x: 480496 },
+ { grid_y: 121094, count: 3800, grid_x: 480497 },
+ { grid_y: 121094, count: 7600, grid_x: 480499 },
+ { grid_y: 121094, count: 3800, grid_x: 480503 },
+ { grid_y: 121094, count: 7600, grid_x: 480509 },
+ { grid_y: 121094, count: 3800, grid_x: 480514 },
+ { grid_y: 121094, count: 3800, grid_x: 480519 },
+ { grid_y: 121094, count: 3800, grid_x: 480521 },
+ { grid_y: 121094, count: 7600, grid_x: 480532 },
+ { grid_y: 121095, count: 3800, grid_x: 480462 },
+ { grid_y: 121095, count: 3800, grid_x: 480467 },
+ { grid_y: 121095, count: 3800, grid_x: 480472 },
+ { grid_y: 121095, count: 3800, grid_x: 480473 },
+ { grid_y: 121095, count: 3800, grid_x: 480476 },
+ { grid_y: 121095, count: 3800, grid_x: 480480 },
+ { grid_y: 121095, count: 3800, grid_x: 480497 },
+ { grid_y: 121095, count: 3800, grid_x: 480498 },
+ { grid_y: 121095, count: 3800, grid_x: 480501 },
+ { grid_y: 121095, count: 3800, grid_x: 480515 },
+ { grid_y: 121095, count: 3800, grid_x: 480520 },
+ { grid_y: 121095, count: 3800, grid_x: 480522 },
+ { grid_y: 121095, count: 3800, grid_x: 480530 },
+ { grid_y: 121095, count: 3800, grid_x: 480531 },
+ { grid_y: 121096, count: 3800, grid_x: 480465 },
+ { grid_y: 121096, count: 3800, grid_x: 480483 },
+ { grid_y: 121096, count: 7600, grid_x: 480485 },
+ { grid_y: 121096, count: 3800, grid_x: 480489 },
+ { grid_y: 121096, count: 3800, grid_x: 480491 },
+ { grid_y: 121096, count: 3800, grid_x: 480494 },
+ { grid_y: 121096, count: 7600, grid_x: 480497 },
+ { grid_y: 121096, count: 3800, grid_x: 480498 },
+ { grid_y: 121096, count: 3800, grid_x: 480499 },
+ { grid_y: 121096, count: 3800, grid_x: 480500 },
+ { grid_y: 121096, count: 7600, grid_x: 480502 },
+ { grid_y: 121096, count: 7600, grid_x: 480503 },
+ { grid_y: 121096, count: 3800, grid_x: 480504 },
+ { grid_y: 121096, count: 3800, grid_x: 480505 },
+ { grid_y: 121096, count: 3800, grid_x: 480507 },
+ { grid_y: 121096, count: 3800, grid_x: 480510 },
+ { grid_y: 121096, count: 3800, grid_x: 480511 },
+ { grid_y: 121096, count: 3800, grid_x: 480512 },
+ { grid_y: 121096, count: 7600, grid_x: 480515 },
+ { grid_y: 121096, count: 3800, grid_x: 480517 },
+ { grid_y: 121096, count: 7600, grid_x: 480520 },
+ { grid_y: 121096, count: 3800, grid_x: 480525 },
+ { grid_y: 121096, count: 3800, grid_x: 480527 },
+ { grid_y: 121096, count: 3800, grid_x: 480529 },
+ { grid_y: 121096, count: 3800, grid_x: 480531 },
+ { grid_y: 121097, count: 3800, grid_x: 480465 },
+ { grid_y: 121097, count: 3800, grid_x: 480472 },
+ { grid_y: 121097, count: 3800, grid_x: 480482 },
+ { grid_y: 121097, count: 11400, grid_x: 480483 },
+ { grid_y: 121097, count: 3800, grid_x: 480484 },
+ { grid_y: 121097, count: 3800, grid_x: 480485 },
+ { grid_y: 121097, count: 3800, grid_x: 480486 },
+ { grid_y: 121097, count: 11400, grid_x: 480487 },
+ { grid_y: 121097, count: 7600, grid_x: 480488 },
+ { grid_y: 121097, count: 7600, grid_x: 480489 },
+ { grid_y: 121097, count: 7600, grid_x: 480491 },
+ { grid_y: 121097, count: 11400, grid_x: 480492 },
+ { grid_y: 121097, count: 3800, grid_x: 480493 },
+ { grid_y: 121097, count: 3800, grid_x: 480494 },
+ { grid_y: 121097, count: 7600, grid_x: 480495 },
+ { grid_y: 121097, count: 3800, grid_x: 480497 },
+ { grid_y: 121097, count: 7600, grid_x: 480499 },
+ { grid_y: 121097, count: 3800, grid_x: 480501 },
+ { grid_y: 121097, count: 3800, grid_x: 480506 },
+ { grid_y: 121097, count: 3800, grid_x: 480509 },
+ { grid_y: 121097, count: 7600, grid_x: 480513 },
+ { grid_y: 121097, count: 3800, grid_x: 480515 },
+ { grid_y: 121097, count: 7600, grid_x: 480520 },
+ { grid_y: 121097, count: 3800, grid_x: 480522 },
+ { grid_y: 121097, count: 3800, grid_x: 480531 },
+ { grid_y: 121097, count: 7600, grid_x: 480532 },
+ { grid_y: 121097, count: 7600, grid_x: 480533 },
+ { grid_y: 121098, count: 7600, grid_x: 480464 },
+ { grid_y: 121098, count: 3800, grid_x: 480475 },
+ { grid_y: 121098, count: 7600, grid_x: 480484 },
+ { grid_y: 121098, count: 11400, grid_x: 480487 },
+ { grid_y: 121098, count: 11400, grid_x: 480489 },
+ { grid_y: 121098, count: 3800, grid_x: 480497 },
+ { grid_y: 121098, count: 7600, grid_x: 480499 },
+ { grid_y: 121098, count: 15200, grid_x: 480501 },
+ { grid_y: 121098, count: 3800, grid_x: 480502 },
+ { grid_y: 121098, count: 3800, grid_x: 480504 },
+ { grid_y: 121098, count: 3800, grid_x: 480509 },
+ { grid_y: 121098, count: 3800, grid_x: 480519 },
+ { grid_y: 121098, count: 3800, grid_x: 480521 },
+ { grid_y: 121098, count: 7600, grid_x: 480523 },
+ { grid_y: 121098, count: 3800, grid_x: 480524 },
+ { grid_y: 121098, count: 3800, grid_x: 480526 },
+ { grid_y: 121098, count: 3800, grid_x: 480529 },
+ { grid_y: 121098, count: 3800, grid_x: 480532 },
+ { grid_y: 121098, count: 7600, grid_x: 480533 },
+ { grid_y: 121099, count: 7600, grid_x: 480461 },
+ { grid_y: 121099, count: 3800, grid_x: 480464 },
+ { grid_y: 121099, count: 3800, grid_x: 480469 },
+ { grid_y: 121099, count: 7600, grid_x: 480470 },
+ { grid_y: 121099, count: 3800, grid_x: 480477 },
+ { grid_y: 121099, count: 3800, grid_x: 480481 },
+ { grid_y: 121099, count: 3800, grid_x: 480482 },
+ { grid_y: 121099, count: 7600, grid_x: 480485 },
+ { grid_y: 121099, count: 7600, grid_x: 480486 },
+ { grid_y: 121099, count: 19000, grid_x: 480487 },
+ { grid_y: 121099, count: 7600, grid_x: 480488 },
+ { grid_y: 121099, count: 3800, grid_x: 480497 },
+ { grid_y: 121099, count: 3800, grid_x: 480499 },
+ { grid_y: 121099, count: 7600, grid_x: 480500 },
+ { grid_y: 121099, count: 19000, grid_x: 480501 },
+ { grid_y: 121099, count: 7600, grid_x: 480502 },
+ { grid_y: 121099, count: 3800, grid_x: 480504 },
+ { grid_y: 121099, count: 7600, grid_x: 480505 },
+ { grid_y: 121099, count: 3800, grid_x: 480519 },
+ { grid_y: 121099, count: 3800, grid_x: 480520 },
+ { grid_y: 121099, count: 3800, grid_x: 480528 },
+ { grid_y: 121099, count: 7600, grid_x: 480532 },
+ { grid_y: 121100, count: 3800, grid_x: 480461 },
+ { grid_y: 121100, count: 3800, grid_x: 480462 },
+ { grid_y: 121100, count: 3800, grid_x: 480465 },
+ { grid_y: 121100, count: 3800, grid_x: 480480 },
+ { grid_y: 121100, count: 15200, grid_x: 480481 },
+ { grid_y: 121100, count: 3800, grid_x: 480484 },
+ { grid_y: 121100, count: 7600, grid_x: 480487 },
+ { grid_y: 121100, count: 11400, grid_x: 480488 },
+ { grid_y: 121100, count: 7600, grid_x: 480489 },
+ { grid_y: 121100, count: 3800, grid_x: 480490 },
+ { grid_y: 121100, count: 3800, grid_x: 480497 },
+ { grid_y: 121100, count: 7600, grid_x: 480502 },
+ { grid_y: 121100, count: 7600, grid_x: 480504 },
+ { grid_y: 121100, count: 7600, grid_x: 480505 },
+ { grid_y: 121100, count: 3800, grid_x: 480508 },
+ { grid_y: 121100, count: 3800, grid_x: 480523 },
+ { grid_y: 121100, count: 3800, grid_x: 480528 },
+ { grid_y: 121100, count: 3800, grid_x: 480529 },
+ { grid_y: 121100, count: 7600, grid_x: 480530 },
+ { grid_y: 121100, count: 3800, grid_x: 480531 },
+ { grid_y: 121100, count: 7600, grid_x: 480532 },
+ { grid_y: 121100, count: 7600, grid_x: 480533 },
+ { grid_y: 121101, count: 3800, grid_x: 480459 },
+ { grid_y: 121101, count: 3800, grid_x: 480462 },
+ { grid_y: 121101, count: 3800, grid_x: 480475 },
+ { grid_y: 121101, count: 7600, grid_x: 480482 },
+ { grid_y: 121101, count: 7600, grid_x: 480488 },
+ { grid_y: 121101, count: 7600, grid_x: 480489 },
+ { grid_y: 121101, count: 3800, grid_x: 480492 },
+ { grid_y: 121101, count: 3800, grid_x: 480497 },
+ { grid_y: 121101, count: 3800, grid_x: 480498 },
+ { grid_y: 121101, count: 3800, grid_x: 480501 },
+ { grid_y: 121101, count: 7600, grid_x: 480504 },
+ { grid_y: 121101, count: 11400, grid_x: 480505 },
+ { grid_y: 121101, count: 3800, grid_x: 480510 },
+ { grid_y: 121101, count: 3800, grid_x: 480517 },
+ { grid_y: 121101, count: 3800, grid_x: 480519 },
+ { grid_y: 121101, count: 7600, grid_x: 480520 },
+ { grid_y: 121101, count: 3800, grid_x: 480522 },
+ { grid_y: 121101, count: 3800, grid_x: 480527 },
+ { grid_y: 121101, count: 7600, grid_x: 480528 },
+ { grid_y: 121101, count: 7600, grid_x: 480529 },
+ { grid_y: 121101, count: 7600, grid_x: 480530 },
+ { grid_y: 121101, count: 7600, grid_x: 480531 },
+ { grid_y: 121101, count: 11400, grid_x: 480532 },
+ { grid_y: 121101, count: 11400, grid_x: 480533 },
+ { grid_y: 121102, count: 3800, grid_x: 480466 },
+ { grid_y: 121102, count: 3800, grid_x: 480468 },
+ { grid_y: 121102, count: 3800, grid_x: 480479 },
+ { grid_y: 121102, count: 3800, grid_x: 480480 },
+ { grid_y: 121102, count: 3800, grid_x: 480481 },
+ { grid_y: 121102, count: 3800, grid_x: 480486 },
+ { grid_y: 121102, count: 3800, grid_x: 480487 },
+ { grid_y: 121102, count: 3800, grid_x: 480488 },
+ { grid_y: 121102, count: 3800, grid_x: 480489 },
+ { grid_y: 121102, count: 3800, grid_x: 480490 },
+ { grid_y: 121102, count: 3800, grid_x: 480492 },
+ { grid_y: 121102, count: 7600, grid_x: 480493 },
+ { grid_y: 121102, count: 3800, grid_x: 480497 },
+ { grid_y: 121102, count: 3800, grid_x: 480499 },
+ { grid_y: 121102, count: 3800, grid_x: 480501 },
+ { grid_y: 121102, count: 3800, grid_x: 480503 },
+ { grid_y: 121102, count: 7600, grid_x: 480504 },
+ { grid_y: 121102, count: 11400, grid_x: 480505 },
+ { grid_y: 121102, count: 7600, grid_x: 480506 },
+ { grid_y: 121102, count: 3800, grid_x: 480514 },
+ { grid_y: 121102, count: 3800, grid_x: 480518 },
+ { grid_y: 121102, count: 7600, grid_x: 480519 },
+ { grid_y: 121102, count: 3800, grid_x: 480525 },
+ { grid_y: 121102, count: 7600, grid_x: 480527 },
+ { grid_y: 121102, count: 7600, grid_x: 480528 },
+ { grid_y: 121102, count: 7600, grid_x: 480529 },
+ { grid_y: 121102, count: 15200, grid_x: 480530 },
+ { grid_y: 121102, count: 3800, grid_x: 480531 },
+ { grid_y: 121102, count: 3800, grid_x: 480532 },
+ { grid_y: 121102, count: 7600, grid_x: 480533 },
+ { grid_y: 121103, count: 3800, grid_x: 480459 },
+ { grid_y: 121103, count: 3800, grid_x: 480460 },
+ { grid_y: 121103, count: 7600, grid_x: 480471 },
+ { grid_y: 121103, count: 3800, grid_x: 480472 },
+ { grid_y: 121103, count: 3800, grid_x: 480481 },
+ { grid_y: 121103, count: 3800, grid_x: 480482 },
+ { grid_y: 121103, count: 3800, grid_x: 480484 },
+ { grid_y: 121103, count: 3800, grid_x: 480485 },
+ { grid_y: 121103, count: 11400, grid_x: 480488 },
+ { grid_y: 121103, count: 15200, grid_x: 480489 },
+ { grid_y: 121103, count: 7600, grid_x: 480495 },
+ { grid_y: 121103, count: 7600, grid_x: 480496 },
+ { grid_y: 121103, count: 3800, grid_x: 480497 },
+ { grid_y: 121103, count: 3800, grid_x: 480501 },
+ { grid_y: 121103, count: 3800, grid_x: 480503 },
+ { grid_y: 121103, count: 7600, grid_x: 480505 },
+ { grid_y: 121103, count: 3800, grid_x: 480506 },
+ { grid_y: 121103, count: 3800, grid_x: 480507 },
+ { grid_y: 121103, count: 3800, grid_x: 480509 },
+ { grid_y: 121103, count: 3800, grid_x: 480510 },
+ { grid_y: 121103, count: 3800, grid_x: 480514 },
+ { grid_y: 121103, count: 3800, grid_x: 480517 },
+ { grid_y: 121103, count: 3800, grid_x: 480519 },
+ { grid_y: 121103, count: 3800, grid_x: 480522 },
+ { grid_y: 121103, count: 3800, grid_x: 480525 },
+ { grid_y: 121103, count: 3800, grid_x: 480528 },
+ { grid_y: 121103, count: 3800, grid_x: 480529 },
+ { grid_y: 121103, count: 3800, grid_x: 480530 },
+ { grid_y: 121103, count: 3800, grid_x: 480533 },
+ { grid_y: 121104, count: 3800, grid_x: 480460 },
+ { grid_y: 121104, count: 3800, grid_x: 480461 },
+ { grid_y: 121104, count: 3800, grid_x: 480463 },
+ { grid_y: 121104, count: 3800, grid_x: 480466 },
+ { grid_y: 121104, count: 3800, grid_x: 480477 },
+ { grid_y: 121104, count: 7600, grid_x: 480478 },
+ { grid_y: 121104, count: 7600, grid_x: 480479 },
+ { grid_y: 121104, count: 3800, grid_x: 480480 },
+ { grid_y: 121104, count: 7600, grid_x: 480481 },
+ { grid_y: 121104, count: 7600, grid_x: 480482 },
+ { grid_y: 121104, count: 3800, grid_x: 480483 },
+ { grid_y: 121104, count: 3800, grid_x: 480487 },
+ { grid_y: 121104, count: 11400, grid_x: 480488 },
+ { grid_y: 121104, count: 7600, grid_x: 480489 },
+ { grid_y: 121104, count: 15200, grid_x: 480490 },
+ { grid_y: 121104, count: 3800, grid_x: 480491 },
+ { grid_y: 121104, count: 3800, grid_x: 480494 },
+ { grid_y: 121104, count: 7600, grid_x: 480495 },
+ { grid_y: 121104, count: 7600, grid_x: 480496 },
+ { grid_y: 121104, count: 7600, grid_x: 480497 },
+ { grid_y: 121104, count: 3800, grid_x: 480499 },
+ { grid_y: 121104, count: 3800, grid_x: 480500 },
+ { grid_y: 121104, count: 3800, grid_x: 480506 },
+ { grid_y: 121104, count: 3800, grid_x: 480513 },
+ { grid_y: 121104, count: 3800, grid_x: 480515 },
+ { grid_y: 121104, count: 7600, grid_x: 480516 },
+ { grid_y: 121104, count: 7600, grid_x: 480517 },
+ { grid_y: 121104, count: 3800, grid_x: 480519 },
+ { grid_y: 121104, count: 7600, grid_x: 480520 },
+ { grid_y: 121104, count: 3800, grid_x: 480524 },
+ { grid_y: 121104, count: 7600, grid_x: 480525 },
+ { grid_y: 121104, count: 7600, grid_x: 480526 },
+ { grid_y: 121104, count: 3800, grid_x: 480527 },
+ { grid_y: 121104, count: 3800, grid_x: 480528 },
+ { grid_y: 121104, count: 7600, grid_x: 480530 },
+ { grid_y: 121104, count: 7600, grid_x: 480531 },
+ { grid_y: 121105, count: 3800, grid_x: 480460 },
+ { grid_y: 121105, count: 7600, grid_x: 480462 },
+ { grid_y: 121105, count: 3800, grid_x: 480463 },
+ { grid_y: 121105, count: 3800, grid_x: 480464 },
+ { grid_y: 121105, count: 3800, grid_x: 480467 },
+ { grid_y: 121105, count: 3800, grid_x: 480468 },
+ { grid_y: 121105, count: 3800, grid_x: 480469 },
+ { grid_y: 121105, count: 7600, grid_x: 480470 },
+ { grid_y: 121105, count: 7600, grid_x: 480472 },
+ { grid_y: 121105, count: 3800, grid_x: 480473 },
+ { grid_y: 121105, count: 3800, grid_x: 480476 },
+ { grid_y: 121105, count: 7600, grid_x: 480477 },
+ { grid_y: 121105, count: 7600, grid_x: 480480 },
+ { grid_y: 121105, count: 3800, grid_x: 480481 },
+ { grid_y: 121105, count: 7600, grid_x: 480482 },
+ { grid_y: 121105, count: 7600, grid_x: 480483 },
+ { grid_y: 121105, count: 3800, grid_x: 480485 },
+ { grid_y: 121105, count: 7600, grid_x: 480487 },
+ { grid_y: 121105, count: 3800, grid_x: 480488 },
+ { grid_y: 121105, count: 22800, grid_x: 480489 },
+ { grid_y: 121105, count: 15200, grid_x: 480490 },
+ { grid_y: 121105, count: 11400, grid_x: 480492 },
+ { grid_y: 121105, count: 3800, grid_x: 480493 },
+ { grid_y: 121105, count: 3800, grid_x: 480494 },
+ { grid_y: 121105, count: 3800, grid_x: 480495 },
+ { grid_y: 121105, count: 3800, grid_x: 480496 },
+ { grid_y: 121105, count: 7600, grid_x: 480497 },
+ { grid_y: 121105, count: 3800, grid_x: 480500 },
+ { grid_y: 121105, count: 3800, grid_x: 480501 },
+ { grid_y: 121105, count: 3800, grid_x: 480509 },
+ { grid_y: 121105, count: 3800, grid_x: 480515 },
+ { grid_y: 121105, count: 3800, grid_x: 480517 },
+ { grid_y: 121105, count: 3800, grid_x: 480518 },
+ { grid_y: 121105, count: 3800, grid_x: 480519 },
+ { grid_y: 121105, count: 3800, grid_x: 480520 },
+ { grid_y: 121105, count: 3800, grid_x: 480521 },
+ { grid_y: 121105, count: 3800, grid_x: 480522 },
+ { grid_y: 121105, count: 11400, grid_x: 480526 },
+ { grid_y: 121105, count: 11400, grid_x: 480527 },
+ { grid_y: 121105, count: 3800, grid_x: 480528 },
+ { grid_y: 121105, count: 3800, grid_x: 480529 },
+ { grid_y: 121105, count: 3800, grid_x: 480531 },
+ { grid_y: 121105, count: 7600, grid_x: 480532 },
+ { grid_y: 121105, count: 7600, grid_x: 480533 },
+ { grid_y: 121106, count: 3800, grid_x: 480464 },
+ { grid_y: 121106, count: 7600, grid_x: 480465 },
+ { grid_y: 121106, count: 3800, grid_x: 480466 },
+ { grid_y: 121106, count: 3800, grid_x: 480469 },
+ { grid_y: 121106, count: 3800, grid_x: 480471 },
+ { grid_y: 121106, count: 3800, grid_x: 480472 },
+ { grid_y: 121106, count: 3800, grid_x: 480473 },
+ { grid_y: 121106, count: 3800, grid_x: 480476 },
+ { grid_y: 121106, count: 11400, grid_x: 480479 },
+ { grid_y: 121106, count: 15200, grid_x: 480480 },
+ { grid_y: 121106, count: 3800, grid_x: 480484 },
+ { grid_y: 121106, count: 3800, grid_x: 480487 },
+ { grid_y: 121106, count: 3800, grid_x: 480488 },
+ { grid_y: 121106, count: 7600, grid_x: 480490 },
+ { grid_y: 121106, count: 7600, grid_x: 480494 },
+ { grid_y: 121106, count: 3800, grid_x: 480495 },
+ { grid_y: 121106, count: 3800, grid_x: 480497 },
+ { grid_y: 121106, count: 15200, grid_x: 480498 },
+ { grid_y: 121106, count: 15200, grid_x: 480499 },
+ { grid_y: 121106, count: 3800, grid_x: 480500 },
+ { grid_y: 121106, count: 3800, grid_x: 480501 },
+ { grid_y: 121106, count: 11400, grid_x: 480503 },
+ { grid_y: 121106, count: 3800, grid_x: 480504 },
+ { grid_y: 121106, count: 7600, grid_x: 480505 },
+ { grid_y: 121106, count: 3800, grid_x: 480506 },
+ { grid_y: 121106, count: 11400, grid_x: 480507 },
+ { grid_y: 121106, count: 3800, grid_x: 480508 },
+ { grid_y: 121106, count: 3800, grid_x: 480509 },
+ { grid_y: 121106, count: 3800, grid_x: 480511 },
+ { grid_y: 121106, count: 3800, grid_x: 480513 },
+ { grid_y: 121106, count: 3800, grid_x: 480514 },
+ { grid_y: 121106, count: 3800, grid_x: 480515 },
+ { grid_y: 121106, count: 3800, grid_x: 480519 },
+ { grid_y: 121106, count: 7600, grid_x: 480520 },
+ { grid_y: 121106, count: 3800, grid_x: 480523 },
+ { grid_y: 121106, count: 11400, grid_x: 480527 },
+ { grid_y: 121106, count: 7600, grid_x: 480528 },
+ { grid_y: 121106, count: 3800, grid_x: 480529 },
+ { grid_y: 121106, count: 3800, grid_x: 480530 },
+ { grid_y: 121106, count: 3800, grid_x: 480532 },
+ { grid_y: 121106, count: 7600, grid_x: 480533 },
+ { grid_y: 121107, count: 7600, grid_x: 480459 },
+ { grid_y: 121107, count: 7600, grid_x: 480461 },
+ { grid_y: 121107, count: 3800, grid_x: 480462 },
+ { grid_y: 121107, count: 3800, grid_x: 480464 },
+ { grid_y: 121107, count: 3800, grid_x: 480466 },
+ { grid_y: 121107, count: 3800, grid_x: 480467 },
+ { grid_y: 121107, count: 3800, grid_x: 480471 },
+ { grid_y: 121107, count: 3800, grid_x: 480472 },
+ { grid_y: 121107, count: 3800, grid_x: 480478 },
+ { grid_y: 121107, count: 3800, grid_x: 480479 },
+ { grid_y: 121107, count: 7600, grid_x: 480480 },
+ { grid_y: 121107, count: 3800, grid_x: 480483 },
+ { grid_y: 121107, count: 3800, grid_x: 480485 },
+ { grid_y: 121107, count: 7600, grid_x: 480497 },
+ { grid_y: 121107, count: 11400, grid_x: 480498 },
+ { grid_y: 121107, count: 19000, grid_x: 480499 },
+ { grid_y: 121107, count: 11400, grid_x: 480500 },
+ { grid_y: 121107, count: 3800, grid_x: 480501 },
+ { grid_y: 121107, count: 3800, grid_x: 480503 },
+ { grid_y: 121107, count: 7600, grid_x: 480507 },
+ { grid_y: 121107, count: 15200, grid_x: 480508 },
+ { grid_y: 121107, count: 3800, grid_x: 480510 },
+ { grid_y: 121107, count: 3800, grid_x: 480512 },
+ { grid_y: 121107, count: 7600, grid_x: 480513 },
+ { grid_y: 121107, count: 7600, grid_x: 480514 },
+ { grid_y: 121107, count: 3800, grid_x: 480516 },
+ { grid_y: 121107, count: 7600, grid_x: 480517 },
+ { grid_y: 121107, count: 3800, grid_x: 480520 },
+ { grid_y: 121107, count: 11400, grid_x: 480522 },
+ { grid_y: 121107, count: 7600, grid_x: 480523 },
+ { grid_y: 121107, count: 3800, grid_x: 480524 },
+ { grid_y: 121107, count: 7600, grid_x: 480525 },
+ { grid_y: 121107, count: 3800, grid_x: 480526 },
+ { grid_y: 121107, count: 3800, grid_x: 480527 },
+ { grid_y: 121107, count: 3800, grid_x: 480528 },
+ { grid_y: 121107, count: 7600, grid_x: 480529 },
+ { grid_y: 121107, count: 7600, grid_x: 480532 },
+ { grid_y: 121107, count: 7600, grid_x: 480533 },
+ { grid_y: 121108, count: 7600, grid_x: 480459 },
+ { grid_y: 121108, count: 7600, grid_x: 480460 },
+ { grid_y: 121108, count: 3800, grid_x: 480461 },
+ { grid_y: 121108, count: 3800, grid_x: 480464 },
+ { grid_y: 121108, count: 3800, grid_x: 480495 },
+ { grid_y: 121108, count: 3800, grid_x: 480497 },
+ { grid_y: 121108, count: 15200, grid_x: 480498 },
+ { grid_y: 121108, count: 19000, grid_x: 480499 },
+ { grid_y: 121108, count: 11400, grid_x: 480500 },
+ { grid_y: 121108, count: 11400, grid_x: 480501 },
+ { grid_y: 121108, count: 11400, grid_x: 480502 },
+ { grid_y: 121108, count: 11400, grid_x: 480503 },
+ { grid_y: 121108, count: 7600, grid_x: 480507 },
+ { grid_y: 121108, count: 3800, grid_x: 480513 },
+ { grid_y: 121108, count: 3800, grid_x: 480514 },
+ { grid_y: 121108, count: 3800, grid_x: 480515 },
+ { grid_y: 121108, count: 11400, grid_x: 480516 },
+ { grid_y: 121108, count: 7600, grid_x: 480517 },
+ { grid_y: 121108, count: 3800, grid_x: 480518 },
+ { grid_y: 121108, count: 3800, grid_x: 480519 },
+ { grid_y: 121108, count: 3800, grid_x: 480520 },
+ { grid_y: 121108, count: 3800, grid_x: 480524 },
+ { grid_y: 121108, count: 3800, grid_x: 480526 },
+ { grid_y: 121108, count: 7600, grid_x: 480527 },
+ { grid_y: 121108, count: 3800, grid_x: 480528 },
+ { grid_y: 121108, count: 3800, grid_x: 480529 },
+ { grid_y: 121108, count: 3800, grid_x: 480530 },
+ { grid_y: 121108, count: 7600, grid_x: 480533 },
+ { grid_y: 121109, count: 7600, grid_x: 480459 },
+ { grid_y: 121109, count: 7600, grid_x: 480460 },
+ { grid_y: 121109, count: 7600, grid_x: 480496 },
+ { grid_y: 121109, count: 7600, grid_x: 480497 },
+ { grid_y: 121109, count: 7600, grid_x: 480498 },
+ { grid_y: 121109, count: 11400, grid_x: 480499 },
+ { grid_y: 121109, count: 7600, grid_x: 480500 },
+ { grid_y: 121109, count: 3800, grid_x: 480501 },
+ { grid_y: 121109, count: 11400, grid_x: 480502 },
+ { grid_y: 121109, count: 3800, grid_x: 480503 },
+ { grid_y: 121109, count: 3800, grid_x: 480506 },
+ { grid_y: 121109, count: 7600, grid_x: 480507 },
+ { grid_y: 121109, count: 3800, grid_x: 480508 },
+ { grid_y: 121109, count: 3800, grid_x: 480510 },
+ { grid_y: 121109, count: 3800, grid_x: 480513 },
+ { grid_y: 121109, count: 7600, grid_x: 480514 },
+ { grid_y: 121109, count: 7600, grid_x: 480516 },
+ { grid_y: 121109, count: 11400, grid_x: 480517 },
+ { grid_y: 121109, count: 3800, grid_x: 480518 },
+ { grid_y: 121109, count: 3800, grid_x: 480523 },
+ { grid_y: 121109, count: 3800, grid_x: 480531 },
+ { grid_y: 121109, count: 3800, grid_x: 480533 },
+ { grid_y: 121110, count: 7600, grid_x: 480459 },
+ { grid_y: 121110, count: 3800, grid_x: 480460 },
+ { grid_y: 121110, count: 3800, grid_x: 480461 },
+ { grid_y: 121110, count: 3800, grid_x: 480465 },
+ { grid_y: 121110, count: 3800, grid_x: 480467 },
+ { grid_y: 121110, count: 3800, grid_x: 480471 },
+ { grid_y: 121110, count: 3800, grid_x: 480478 },
+ { grid_y: 121110, count: 3800, grid_x: 480479 },
+ { grid_y: 121110, count: 3800, grid_x: 480489 },
+ { grid_y: 121110, count: 7600, grid_x: 480497 },
+ { grid_y: 121110, count: 7600, grid_x: 480498 },
+ { grid_y: 121110, count: 7600, grid_x: 480499 },
+ { grid_y: 121110, count: 7600, grid_x: 480502 },
+ { grid_y: 121110, count: 3800, grid_x: 480504 },
+ { grid_y: 121110, count: 3800, grid_x: 480510 },
+ { grid_y: 121110, count: 7600, grid_x: 480511 },
+ { grid_y: 121110, count: 3800, grid_x: 480512 },
+ { grid_y: 121110, count: 11400, grid_x: 480516 },
+ { grid_y: 121110, count: 7600, grid_x: 480517 },
+ { grid_y: 121110, count: 3800, grid_x: 480518 },
+ { grid_y: 121110, count: 7600, grid_x: 480519 },
+ { grid_y: 121110, count: 3800, grid_x: 480521 },
+ { grid_y: 121110, count: 3800, grid_x: 480523 },
+ { grid_y: 121110, count: 3800, grid_x: 480526 },
+ { grid_y: 121111, count: 3800, grid_x: 480460 },
+ { grid_y: 121111, count: 3800, grid_x: 480493 },
+ { grid_y: 121111, count: 3800, grid_x: 480496 },
+ { grid_y: 121111, count: 11400, grid_x: 480500 },
+ { grid_y: 121111, count: 3800, grid_x: 480501 },
+ { grid_y: 121111, count: 7600, grid_x: 480502 },
+ { grid_y: 121111, count: 3800, grid_x: 480503 },
+ { grid_y: 121111, count: 3800, grid_x: 480504 },
+ { grid_y: 121111, count: 3800, grid_x: 480505 },
+ { grid_y: 121111, count: 3800, grid_x: 480506 },
+ { grid_y: 121111, count: 3800, grid_x: 480511 },
+ { grid_y: 121111, count: 3800, grid_x: 480515 },
+ { grid_y: 121111, count: 3800, grid_x: 480516 },
+ { grid_y: 121111, count: 7600, grid_x: 480517 },
+ { grid_y: 121111, count: 3800, grid_x: 480528 },
+ { grid_y: 121112, count: 3800, grid_x: 480459 },
+ { grid_y: 121112, count: 3800, grid_x: 480460 },
+ { grid_y: 121112, count: 3800, grid_x: 480465 },
+ { grid_y: 121112, count: 3800, grid_x: 480467 },
+ { grid_y: 121112, count: 3800, grid_x: 480478 },
+ { grid_y: 121112, count: 3800, grid_x: 480479 },
+ { grid_y: 121112, count: 7600, grid_x: 480496 },
+ { grid_y: 121112, count: 7600, grid_x: 480500 },
+ { grid_y: 121112, count: 7600, grid_x: 480501 },
+ { grid_y: 121112, count: 7600, grid_x: 480505 },
+ { grid_y: 121112, count: 3800, grid_x: 480506 },
+ { grid_y: 121112, count: 3800, grid_x: 480512 },
+ { grid_y: 121112, count: 3800, grid_x: 480519 },
+ { grid_y: 121112, count: 3800, grid_x: 480525 },
+ { grid_y: 121112, count: 3800, grid_x: 480530 },
+ { grid_y: 121112, count: 3800, grid_x: 480532 },
+ { grid_y: 121112, count: 3800, grid_x: 480533 },
+ { grid_y: 121113, count: 3800, grid_x: 480459 },
+ { grid_y: 121113, count: 3800, grid_x: 480460 },
+ { grid_y: 121113, count: 3800, grid_x: 480462 },
+ { grid_y: 121113, count: 3800, grid_x: 480463 },
+ { grid_y: 121113, count: 3800, grid_x: 480466 },
+ { grid_y: 121113, count: 7600, grid_x: 480479 },
+ { grid_y: 121113, count: 3800, grid_x: 480482 },
+ { grid_y: 121113, count: 7600, grid_x: 480483 },
+ { grid_y: 121113, count: 3800, grid_x: 480485 },
+ { grid_y: 121113, count: 3800, grid_x: 480496 },
+ { grid_y: 121113, count: 3800, grid_x: 480497 },
+ { grid_y: 121113, count: 3800, grid_x: 480498 },
+ { grid_y: 121113, count: 7600, grid_x: 480499 },
+ { grid_y: 121113, count: 7600, grid_x: 480500 },
+ { grid_y: 121113, count: 3800, grid_x: 480501 },
+ { grid_y: 121113, count: 3800, grid_x: 480502 },
+ { grid_y: 121113, count: 3800, grid_x: 480505 },
+ { grid_y: 121113, count: 3800, grid_x: 480506 },
+ { grid_y: 121113, count: 3800, grid_x: 480507 },
+ { grid_y: 121113, count: 3800, grid_x: 480514 },
+ { grid_y: 121113, count: 3800, grid_x: 480517 },
+ { grid_y: 121113, count: 7600, grid_x: 480518 },
+ { grid_y: 121113, count: 7600, grid_x: 480522 },
+ { grid_y: 121113, count: 3800, grid_x: 480527 },
+ { grid_y: 121113, count: 3800, grid_x: 480530 },
+ { grid_y: 121114, count: 3800, grid_x: 480459 },
+ { grid_y: 121114, count: 3800, grid_x: 480460 },
+ { grid_y: 121114, count: 3800, grid_x: 480462 },
+ { grid_y: 121114, count: 3800, grid_x: 480463 },
+ { grid_y: 121114, count: 3800, grid_x: 480466 },
+ { grid_y: 121114, count: 3800, grid_x: 480467 },
+ { grid_y: 121114, count: 3800, grid_x: 480468 },
+ { grid_y: 121114, count: 3800, grid_x: 480471 },
+ { grid_y: 121114, count: 7600, grid_x: 480474 },
+ { grid_y: 121114, count: 3800, grid_x: 480475 },
+ { grid_y: 121114, count: 7600, grid_x: 480478 },
+ { grid_y: 121114, count: 7600, grid_x: 480479 },
+ { grid_y: 121114, count: 3800, grid_x: 480480 },
+ { grid_y: 121114, count: 7600, grid_x: 480481 },
+ { grid_y: 121114, count: 15200, grid_x: 480482 },
+ { grid_y: 121114, count: 3800, grid_x: 480483 },
+ { grid_y: 121114, count: 7600, grid_x: 480484 },
+ { grid_y: 121114, count: 3800, grid_x: 480485 },
+ { grid_y: 121114, count: 7600, grid_x: 480486 },
+ { grid_y: 121114, count: 7600, grid_x: 480491 },
+ { grid_y: 121114, count: 3800, grid_x: 480496 },
+ { grid_y: 121114, count: 7600, grid_x: 480497 },
+ { grid_y: 121114, count: 7600, grid_x: 480498 },
+ { grid_y: 121114, count: 7600, grid_x: 480500 },
+ { grid_y: 121114, count: 11400, grid_x: 480501 },
+ { grid_y: 121114, count: 3800, grid_x: 480502 },
+ { grid_y: 121114, count: 3800, grid_x: 480507 },
+ { grid_y: 121114, count: 7600, grid_x: 480508 },
+ { grid_y: 121114, count: 7600, grid_x: 480510 },
+ { grid_y: 121114, count: 3800, grid_x: 480511 },
+ { grid_y: 121114, count: 7600, grid_x: 480515 },
+ { grid_y: 121114, count: 3800, grid_x: 480524 },
+ { grid_y: 121114, count: 3800, grid_x: 480533 },
+ { grid_y: 121115, count: 3800, grid_x: 480460 },
+ { grid_y: 121115, count: 3800, grid_x: 480468 },
+ { grid_y: 121115, count: 3800, grid_x: 480470 },
+ { grid_y: 121115, count: 3800, grid_x: 480471 },
+ { grid_y: 121115, count: 7600, grid_x: 480483 },
+ { grid_y: 121115, count: 7600, grid_x: 480484 },
+ { grid_y: 121115, count: 11400, grid_x: 480485 },
+ { grid_y: 121115, count: 3800, grid_x: 480486 },
+ { grid_y: 121115, count: 3800, grid_x: 480491 },
+ { grid_y: 121115, count: 3800, grid_x: 480494 },
+ { grid_y: 121115, count: 7600, grid_x: 480496 },
+ { grid_y: 121115, count: 3800, grid_x: 480499 },
+ { grid_y: 121115, count: 7600, grid_x: 480501 },
+ { grid_y: 121115, count: 3800, grid_x: 480507 },
+ { grid_y: 121115, count: 3800, grid_x: 480511 },
+ { grid_y: 121115, count: 7600, grid_x: 480515 },
+ { grid_y: 121115, count: 11400, grid_x: 480516 },
+ { grid_y: 121115, count: 3800, grid_x: 480517 },
+ { grid_y: 121115, count: 3800, grid_x: 480527 },
+ { grid_y: 121115, count: 3800, grid_x: 480528 },
+ { grid_y: 121116, count: 3800, grid_x: 480465 },
+ { grid_y: 121116, count: 7600, grid_x: 480468 },
+ { grid_y: 121116, count: 3800, grid_x: 480471 },
+ { grid_y: 121116, count: 3800, grid_x: 480476 },
+ { grid_y: 121116, count: 7600, grid_x: 480478 },
+ { grid_y: 121116, count: 7600, grid_x: 480479 },
+ { grid_y: 121116, count: 3800, grid_x: 480480 },
+ { grid_y: 121116, count: 3800, grid_x: 480482 },
+ { grid_y: 121116, count: 7600, grid_x: 480483 },
+ { grid_y: 121116, count: 11400, grid_x: 480484 },
+ { grid_y: 121116, count: 11400, grid_x: 480485 },
+ { grid_y: 121116, count: 7600, grid_x: 480487 },
+ { grid_y: 121116, count: 3800, grid_x: 480489 },
+ { grid_y: 121116, count: 3800, grid_x: 480491 },
+ { grid_y: 121116, count: 3800, grid_x: 480492 },
+ { grid_y: 121116, count: 3800, grid_x: 480493 },
+ { grid_y: 121116, count: 3800, grid_x: 480494 },
+ { grid_y: 121116, count: 3800, grid_x: 480501 },
+ { grid_y: 121116, count: 3800, grid_x: 480502 },
+ { grid_y: 121116, count: 3800, grid_x: 480503 },
+ { grid_y: 121116, count: 3800, grid_x: 480507 },
+ { grid_y: 121116, count: 3800, grid_x: 480509 },
+ { grid_y: 121116, count: 3800, grid_x: 480510 },
+ { grid_y: 121116, count: 3800, grid_x: 480512 },
+ { grid_y: 121116, count: 7600, grid_x: 480515 },
+ { grid_y: 121116, count: 15200, grid_x: 480516 },
+ { grid_y: 121116, count: 3800, grid_x: 480533 },
+ { grid_y: 121117, count: 3800, grid_x: 480459 },
+ { grid_y: 121117, count: 3800, grid_x: 480468 },
+ { grid_y: 121117, count: 3800, grid_x: 480470 },
+ { grid_y: 121117, count: 3800, grid_x: 480477 },
+ { grid_y: 121117, count: 3800, grid_x: 480478 },
+ { grid_y: 121117, count: 3800, grid_x: 480480 },
+ { grid_y: 121117, count: 3800, grid_x: 480482 },
+ { grid_y: 121117, count: 7600, grid_x: 480483 },
+ { grid_y: 121117, count: 7600, grid_x: 480484 },
+ { grid_y: 121117, count: 11400, grid_x: 480485 },
+ { grid_y: 121117, count: 7600, grid_x: 480486 },
+ { grid_y: 121117, count: 7600, grid_x: 480487 },
+ { grid_y: 121117, count: 11400, grid_x: 480488 },
+ { grid_y: 121117, count: 7600, grid_x: 480495 },
+ { grid_y: 121117, count: 3800, grid_x: 480496 },
+ { grid_y: 121117, count: 3800, grid_x: 480497 },
+ { grid_y: 121117, count: 3800, grid_x: 480509 },
+ { grid_y: 121117, count: 3800, grid_x: 480510 },
+ { grid_y: 121117, count: 3800, grid_x: 480516 },
+ { grid_y: 121117, count: 3800, grid_x: 480520 },
+ { grid_y: 121117, count: 7600, grid_x: 480526 },
+ { grid_y: 121117, count: 3800, grid_x: 480528 },
+ { grid_y: 121117, count: 3800, grid_x: 480533 },
+ { grid_y: 121118, count: 3800, grid_x: 480459 },
+ { grid_y: 121118, count: 3800, grid_x: 480460 },
+ { grid_y: 121118, count: 3800, grid_x: 480478 },
+ { grid_y: 121118, count: 3800, grid_x: 480481 },
+ { grid_y: 121118, count: 3800, grid_x: 480482 },
+ { grid_y: 121118, count: 7600, grid_x: 480483 },
+ { grid_y: 121118, count: 7600, grid_x: 480484 },
+ { grid_y: 121118, count: 3800, grid_x: 480486 },
+ { grid_y: 121118, count: 7600, grid_x: 480487 },
+ { grid_y: 121118, count: 7600, grid_x: 480488 },
+ { grid_y: 121118, count: 7600, grid_x: 480514 },
+ { grid_y: 121118, count: 3800, grid_x: 480516 },
+ { grid_y: 121118, count: 3800, grid_x: 480517 },
+ { grid_y: 121118, count: 3800, grid_x: 480518 },
+ { grid_y: 121118, count: 3800, grid_x: 480521 },
+ { grid_y: 121118, count: 3800, grid_x: 480528 },
+ { grid_y: 121118, count: 3800, grid_x: 480533 },
+ { grid_y: 121119, count: 3800, grid_x: 480467 },
+ { grid_y: 121119, count: 3800, grid_x: 480469 },
+ { grid_y: 121119, count: 3800, grid_x: 480478 },
+ { grid_y: 121119, count: 3800, grid_x: 480479 },
+ { grid_y: 121119, count: 3800, grid_x: 480483 },
+ { grid_y: 121119, count: 3800, grid_x: 480485 },
+ { grid_y: 121119, count: 7600, grid_x: 480486 },
+ { grid_y: 121119, count: 7600, grid_x: 480487 },
+ { grid_y: 121119, count: 3800, grid_x: 480514 },
+ { grid_y: 121119, count: 3800, grid_x: 480518 },
+ { grid_y: 121119, count: 3800, grid_x: 480526 },
+ { grid_y: 121120, count: 3800, grid_x: 480466 },
+ { grid_y: 121120, count: 3800, grid_x: 480468 },
+ { grid_y: 121120, count: 3800, grid_x: 480479 },
+ { grid_y: 121120, count: 3800, grid_x: 480480 },
+ { grid_y: 121120, count: 3800, grid_x: 480483 },
+ { grid_y: 121120, count: 3800, grid_x: 480484 },
+ { grid_y: 121120, count: 3800, grid_x: 480485 },
+ { grid_y: 121120, count: 7600, grid_x: 480486 },
+ { grid_y: 121120, count: 3800, grid_x: 480491 },
+ { grid_y: 121120, count: 3800, grid_x: 480497 },
+ { grid_y: 121120, count: 3800, grid_x: 480509 },
+ { grid_y: 121120, count: 3800, grid_x: 480515 },
+ { grid_y: 121120, count: 3800, grid_x: 480518 },
+ { grid_y: 121120, count: 3800, grid_x: 480526 },
+ { grid_y: 121121, count: 3800, grid_x: 480472 },
+ { grid_y: 121121, count: 3800, grid_x: 480473 },
+ { grid_y: 121121, count: 7600, grid_x: 480480 },
+ { grid_y: 121121, count: 3800, grid_x: 480481 },
+ { grid_y: 121121, count: 7600, grid_x: 480483 },
+ { grid_y: 121121, count: 7600, grid_x: 480484 },
+ { grid_y: 121121, count: 7600, grid_x: 480485 },
+ { grid_y: 121121, count: 7600, grid_x: 480486 },
+ { grid_y: 121121, count: 3800, grid_x: 480495 },
+ { grid_y: 121122, count: 3800, grid_x: 480474 },
+ { grid_y: 121122, count: 3800, grid_x: 480479 },
+ { grid_y: 121122, count: 3800, grid_x: 480481 },
+ { grid_y: 121122, count: 3800, grid_x: 480483 },
+ { grid_y: 121122, count: 7600, grid_x: 480484 },
+ { grid_y: 121122, count: 3800, grid_x: 480485 },
+ { grid_y: 121122, count: 7600, grid_x: 480491 },
+ { grid_y: 121122, count: 7600, grid_x: 480492 },
+ { grid_y: 121122, count: 7600, grid_x: 480493 },
+ { grid_y: 121122, count: 3800, grid_x: 480494 },
+ { grid_y: 121122, count: 7600, grid_x: 480495 },
+ { grid_y: 121122, count: 3800, grid_x: 480510 },
+ { grid_y: 121122, count: 3800, grid_x: 480517 },
+ { grid_y: 121123, count: 7600, grid_x: 480469 },
+ { grid_y: 121123, count: 7600, grid_x: 480477 },
+ { grid_y: 121123, count: 3800, grid_x: 480478 },
+ { grid_y: 121123, count: 3800, grid_x: 480479 },
+ { grid_y: 121123, count: 11400, grid_x: 480481 },
+ { grid_y: 121123, count: 7600, grid_x: 480482 },
+ { grid_y: 121123, count: 7600, grid_x: 480484 },
+ { grid_y: 121123, count: 7600, grid_x: 480485 },
+ { grid_y: 121123, count: 3800, grid_x: 480486 },
+ { grid_y: 121123, count: 3800, grid_x: 480491 },
+ { grid_y: 121123, count: 3800, grid_x: 480492 },
+ { grid_y: 121123, count: 3800, grid_x: 480493 },
+ { grid_y: 121123, count: 7600, grid_x: 480495 },
+ { grid_y: 121123, count: 3800, grid_x: 480509 },
+ { grid_y: 121123, count: 3800, grid_x: 480517 },
+ { grid_y: 121123, count: 7600, grid_x: 480518 },
+ { grid_y: 121124, count: 3800, grid_x: 480469 },
+ { grid_y: 121124, count: 3800, grid_x: 480474 },
+ { grid_y: 121124, count: 3800, grid_x: 480476 },
+ { grid_y: 121124, count: 3800, grid_x: 480478 },
+ { grid_y: 121124, count: 3800, grid_x: 480480 },
+ { grid_y: 121124, count: 3800, grid_x: 480481 },
+ { grid_y: 121124, count: 3800, grid_x: 480483 },
+ { grid_y: 121124, count: 3800, grid_x: 480485 },
+ { grid_y: 121124, count: 3800, grid_x: 480487 },
+ { grid_y: 121124, count: 3800, grid_x: 480493 },
+ { grid_y: 121124, count: 3800, grid_x: 480505 },
+ { grid_y: 121124, count: 3800, grid_x: 480530 },
+ { grid_y: 121125, count: 3800, grid_x: 480466 },
+ { grid_y: 121125, count: 3800, grid_x: 480472 },
+ { grid_y: 121125, count: 3800, grid_x: 480477 },
+ { grid_y: 121125, count: 3800, grid_x: 480478 },
+ { grid_y: 121125, count: 7600, grid_x: 480479 },
+ { grid_y: 121125, count: 3800, grid_x: 480480 },
+ { grid_y: 121125, count: 3800, grid_x: 480483 },
+ { grid_y: 121125, count: 3800, grid_x: 480484 },
+ { grid_y: 121125, count: 7600, grid_x: 480488 },
+ { grid_y: 121125, count: 3800, grid_x: 480496 },
+ { grid_y: 121125, count: 3800, grid_x: 480497 },
+ { grid_y: 121125, count: 3800, grid_x: 480509 },
+ { grid_y: 121126, count: 3800, grid_x: 480459 },
+ { grid_y: 121126, count: 3800, grid_x: 480469 },
+ { grid_y: 121126, count: 7600, grid_x: 480470 },
+ { grid_y: 121126, count: 7600, grid_x: 480472 },
+ { grid_y: 121126, count: 3800, grid_x: 480474 },
+ { grid_y: 121126, count: 7600, grid_x: 480478 },
+ { grid_y: 121126, count: 3800, grid_x: 480479 },
+ { grid_y: 121126, count: 15200, grid_x: 480480 },
+ { grid_y: 121126, count: 15200, grid_x: 480483 },
+ { grid_y: 121126, count: 7600, grid_x: 480485 },
+ { grid_y: 121126, count: 3800, grid_x: 480486 },
+ { grid_y: 121126, count: 3800, grid_x: 480489 },
+ { grid_y: 121126, count: 3800, grid_x: 480517 },
+ { grid_y: 121126, count: 3800, grid_x: 480529 },
+ { grid_y: 121127, count: 3800, grid_x: 480460 },
+ { grid_y: 121127, count: 7600, grid_x: 480465 },
+ { grid_y: 121127, count: 3800, grid_x: 480468 },
+ { grid_y: 121127, count: 3800, grid_x: 480470 },
+ { grid_y: 121127, count: 11400, grid_x: 480472 },
+ { grid_y: 121127, count: 7600, grid_x: 480473 },
+ { grid_y: 121127, count: 3800, grid_x: 480477 },
+ { grid_y: 121127, count: 3800, grid_x: 480478 },
+ { grid_y: 121127, count: 15200, grid_x: 480479 },
+ { grid_y: 121127, count: 11400, grid_x: 480480 },
+ { grid_y: 121127, count: 3800, grid_x: 480482 },
+ { grid_y: 121127, count: 38000, grid_x: 480483 },
+ { grid_y: 121127, count: 3800, grid_x: 480484 },
+ { grid_y: 121127, count: 3800, grid_x: 480486 },
+ { grid_y: 121127, count: 3800, grid_x: 480487 },
+ { grid_y: 121127, count: 3800, grid_x: 480488 },
+ { grid_y: 121127, count: 3800, grid_x: 480493 },
+ { grid_y: 121127, count: 3800, grid_x: 480496 },
+ { grid_y: 121127, count: 3800, grid_x: 480515 },
+ { grid_y: 121127, count: 3800, grid_x: 480517 },
+ { grid_y: 121127, count: 3800, grid_x: 480519 },
+ { grid_y: 121127, count: 3800, grid_x: 480522 },
+ { grid_y: 121128, count: 3800, grid_x: 480459 },
+ { grid_y: 121128, count: 3800, grid_x: 480463 },
+ { grid_y: 121128, count: 3800, grid_x: 480465 },
+ { grid_y: 121128, count: 3800, grid_x: 480467 },
+ { grid_y: 121128, count: 3800, grid_x: 480469 },
+ { grid_y: 121128, count: 11400, grid_x: 480470 },
+ { grid_y: 121128, count: 3800, grid_x: 480471 },
+ { grid_y: 121128, count: 3800, grid_x: 480472 },
+ { grid_y: 121128, count: 3800, grid_x: 480473 },
+ { grid_y: 121128, count: 3800, grid_x: 480474 },
+ { grid_y: 121128, count: 7600, grid_x: 480475 },
+ { grid_y: 121128, count: 3800, grid_x: 480476 },
+ { grid_y: 121128, count: 3800, grid_x: 480483 },
+ { grid_y: 121128, count: 7600, grid_x: 480484 },
+ { grid_y: 121128, count: 11400, grid_x: 480486 },
+ { grid_y: 121128, count: 11400, grid_x: 480487 },
+ { grid_y: 121128, count: 3800, grid_x: 480488 },
+ { grid_y: 121128, count: 3800, grid_x: 480490 },
+ { grid_y: 121128, count: 3800, grid_x: 480495 },
+ { grid_y: 121128, count: 11400, grid_x: 480496 },
+ { grid_y: 121128, count: 7600, grid_x: 480498 },
+ { grid_y: 121128, count: 7600, grid_x: 480499 },
+ { grid_y: 121128, count: 3800, grid_x: 480507 },
+ { grid_y: 121128, count: 3800, grid_x: 480509 },
+ { grid_y: 121128, count: 3800, grid_x: 480515 },
+ { grid_y: 121128, count: 3800, grid_x: 480517 },
+ { grid_y: 121128, count: 3800, grid_x: 480523 },
+ { grid_y: 121128, count: 3800, grid_x: 480531 },
+ { grid_y: 121129, count: 3800, grid_x: 480467 },
+ { grid_y: 121129, count: 3800, grid_x: 480468 },
+ { grid_y: 121129, count: 7600, grid_x: 480469 },
+ { grid_y: 121129, count: 3800, grid_x: 480470 },
+ { grid_y: 121129, count: 7600, grid_x: 480471 },
+ { grid_y: 121129, count: 30400, grid_x: 480472 },
+ { grid_y: 121129, count: 7600, grid_x: 480473 },
+ { grid_y: 121129, count: 3800, grid_x: 480479 },
+ { grid_y: 121129, count: 7600, grid_x: 480480 },
+ { grid_y: 121129, count: 7600, grid_x: 480481 },
+ { grid_y: 121129, count: 3800, grid_x: 480482 },
+ { grid_y: 121129, count: 3800, grid_x: 480483 },
+ { grid_y: 121129, count: 3800, grid_x: 480486 },
+ { grid_y: 121129, count: 3800, grid_x: 480487 },
+ { grid_y: 121129, count: 3800, grid_x: 480490 },
+ { grid_y: 121129, count: 3800, grid_x: 480492 },
+ { grid_y: 121129, count: 3800, grid_x: 480493 },
+ { grid_y: 121129, count: 3800, grid_x: 480494 },
+ { grid_y: 121129, count: 3800, grid_x: 480498 },
+ { grid_y: 121129, count: 7600, grid_x: 480500 },
+ { grid_y: 121129, count: 3800, grid_x: 480502 },
+ { grid_y: 121129, count: 7600, grid_x: 480511 },
+ { grid_y: 121129, count: 7600, grid_x: 480514 },
+ { grid_y: 121129, count: 7600, grid_x: 480518 },
+ { grid_y: 121130, count: 3800, grid_x: 480468 },
+ { grid_y: 121130, count: 7600, grid_x: 480470 },
+ { grid_y: 121130, count: 7600, grid_x: 480471 },
+ { grid_y: 121130, count: 7600, grid_x: 480472 },
+ { grid_y: 121130, count: 3800, grid_x: 480476 },
+ { grid_y: 121130, count: 3800, grid_x: 480477 },
+ { grid_y: 121130, count: 7600, grid_x: 480481 },
+ { grid_y: 121130, count: 3800, grid_x: 480482 },
+ { grid_y: 121130, count: 3800, grid_x: 480485 },
+ { grid_y: 121130, count: 3800, grid_x: 480492 },
+ { grid_y: 121130, count: 7600, grid_x: 480494 },
+ { grid_y: 121130, count: 3800, grid_x: 480497 },
+ { grid_y: 121130, count: 3800, grid_x: 480498 },
+ { grid_y: 121130, count: 3800, grid_x: 480500 },
+ { grid_y: 121130, count: 3800, grid_x: 480503 },
+ { grid_y: 121130, count: 3800, grid_x: 480506 },
+ { grid_y: 121130, count: 7600, grid_x: 480507 },
+ { grid_y: 121130, count: 3800, grid_x: 480509 },
+ { grid_y: 121130, count: 7600, grid_x: 480510 },
+ { grid_y: 121130, count: 3800, grid_x: 480511 },
+ { grid_y: 121130, count: 7600, grid_x: 480514 },
+ { grid_y: 121130, count: 3800, grid_x: 480527 },
+ { grid_y: 121130, count: 3800, grid_x: 480530 },
+ { grid_y: 121131, count: 3800, grid_x: 480459 },
+ { grid_y: 121131, count: 3800, grid_x: 480468 },
+ { grid_y: 121131, count: 3800, grid_x: 480471 },
+ { grid_y: 121131, count: 3800, grid_x: 480478 },
+ { grid_y: 121131, count: 3800, grid_x: 480485 },
+ { grid_y: 121131, count: 3800, grid_x: 480486 },
+ { grid_y: 121131, count: 3800, grid_x: 480489 },
+ { grid_y: 121131, count: 3800, grid_x: 480490 },
+ { grid_y: 121131, count: 7600, grid_x: 480499 },
+ { grid_y: 121131, count: 3800, grid_x: 480507 },
+ { grid_y: 121131, count: 3800, grid_x: 480508 },
+ { grid_y: 121131, count: 3800, grid_x: 480509 },
+ { grid_y: 121131, count: 19000, grid_x: 480515 },
+ { grid_y: 121131, count: 7600, grid_x: 480516 },
+ { grid_y: 121131, count: 7600, grid_x: 480517 },
+ { grid_y: 121131, count: 3800, grid_x: 480526 },
+ { grid_y: 121131, count: 3800, grid_x: 480529 },
+ { grid_y: 121131, count: 3800, grid_x: 480533 },
+ { grid_y: 121132, count: 7600, grid_x: 480469 },
+ { grid_y: 121132, count: 3800, grid_x: 480470 },
+ { grid_y: 121132, count: 3800, grid_x: 480472 },
+ { grid_y: 121132, count: 3800, grid_x: 480474 },
+ { grid_y: 121132, count: 3800, grid_x: 480479 },
+ { grid_y: 121132, count: 3800, grid_x: 480480 },
+ { grid_y: 121132, count: 3800, grid_x: 480489 },
+ { grid_y: 121132, count: 3800, grid_x: 480495 },
+ { grid_y: 121132, count: 3800, grid_x: 480497 },
+ { grid_y: 121132, count: 3800, grid_x: 480499 },
+ { grid_y: 121132, count: 3800, grid_x: 480503 },
+ { grid_y: 121132, count: 3800, grid_x: 480508 },
+ { grid_y: 121132, count: 3800, grid_x: 480519 },
+ { grid_y: 121133, count: 3800, grid_x: 480464 },
+ { grid_y: 121133, count: 3800, grid_x: 480466 },
+ { grid_y: 121133, count: 3800, grid_x: 480477 },
+ { grid_y: 121133, count: 3800, grid_x: 480478 },
+ { grid_y: 121133, count: 3800, grid_x: 480482 },
+ { grid_y: 121133, count: 3800, grid_x: 480490 },
+ { grid_y: 121133, count: 3800, grid_x: 480491 },
+ { grid_y: 121133, count: 7600, grid_x: 480497 },
+ { grid_y: 121133, count: 3800, grid_x: 480498 },
+ { grid_y: 121133, count: 3800, grid_x: 480499 },
+ { grid_y: 121133, count: 3800, grid_x: 480502 },
+ { grid_y: 121133, count: 3800, grid_x: 480516 },
+ { grid_y: 121133, count: 3800, grid_x: 480519 },
+ { grid_y: 121133, count: 3800, grid_x: 480520 },
+ { grid_y: 121134, count: 3800, grid_x: 480468 },
+ { grid_y: 121134, count: 7600, grid_x: 480477 },
+ { grid_y: 121134, count: 3800, grid_x: 480481 },
+ { grid_y: 121134, count: 7600, grid_x: 480482 },
+ { grid_y: 121134, count: 3800, grid_x: 480484 },
+ { grid_y: 121134, count: 3800, grid_x: 480485 },
+ { grid_y: 121134, count: 3800, grid_x: 480493 },
+ { grid_y: 121134, count: 3800, grid_x: 480501 },
+ { grid_y: 121134, count: 3800, grid_x: 480508 },
+ { grid_y: 121134, count: 3800, grid_x: 480514 },
+ { grid_y: 121134, count: 3800, grid_x: 480516 },
+ { grid_y: 121134, count: 3800, grid_x: 480519 },
+ { grid_y: 121134, count: 3800, grid_x: 480520 },
+ { grid_y: 121134, count: 3800, grid_x: 480526 },
+ { grid_y: 121134, count: 3800, grid_x: 480527 },
+ { grid_y: 121135, count: 3800, grid_x: 480460 },
+ { grid_y: 121135, count: 3800, grid_x: 480477 },
+ { grid_y: 121135, count: 3800, grid_x: 480481 },
+ { grid_y: 121135, count: 7600, grid_x: 480482 },
+ { grid_y: 121135, count: 11400, grid_x: 480483 },
+ { grid_y: 121135, count: 7600, grid_x: 480484 },
+ { grid_y: 121135, count: 3800, grid_x: 480486 },
+ { grid_y: 121135, count: 3800, grid_x: 480489 },
+ { grid_y: 121135, count: 3800, grid_x: 480493 },
+ { grid_y: 121135, count: 3800, grid_x: 480503 },
+ { grid_y: 121135, count: 3800, grid_x: 480510 },
+ { grid_y: 121135, count: 3800, grid_x: 480529 },
+ { grid_y: 121135, count: 3800, grid_x: 480533 }
+];
diff --git a/test/unit/source/transfrom/hexagon.js b/test/unit/source/transfrom/hexagon.js
new file mode 100644
index 0000000000..b0877e7b80
--- /dev/null
+++ b/test/unit/source/transfrom/hexagon.js
@@ -0,0 +1,21 @@
+import { expect } from 'chai';
+import { pointData } from '../../../asset/data/point';
+import { pointToHexbin } from '../../../../src/source/transform/hexagon';
+describe('hexagon Test', function() {
+
+ it('pointToHexbin', function() {
+ const dataArray = pointData.map(item => {
+ const lng = 1e-6 * (250 * item.grid_x + 125),
+ lat = 1e-6 * (250 * item.grid_y + 125);
+ return {
+ v: item.count * 1,
+ coordinates: [ lng, lat ]
+ };
+ });
+
+ const data = {
+ dataArray
+ };
+ const hexgonGrid = pointToHexbin(data, { size: 100, field: 'count', method: 'sum' });
+ });
+});