From ad8a5a3c5e83d31e15afcd68e422001bcd474f80 Mon Sep 17 00:00:00 2001 From: "mipha.ly@alibaba-inc.com" Date: Wed, 27 Feb 2019 17:14:01 +0800 Subject: [PATCH] feat(l7): feat heatmap layer --- demos/heatmap.html | 9 -- src/geom/buffer/{ => heatmap}/heatmap.js | 6 +- src/layer/heatmap.js | 55 --------- src/layer/heatmapLayer.js | 146 +++++++---------------- src/layer/index.js | 2 - src/layer/render/heatmap/heatmap.js | 105 ++++++++++++++++ 6 files changed, 153 insertions(+), 170 deletions(-) rename src/geom/buffer/{ => heatmap}/heatmap.js (95%) delete mode 100644 src/layer/heatmap.js create mode 100644 src/layer/render/heatmap/heatmap.js diff --git a/demos/heatmap.html b/demos/heatmap.html index 44f99033ef..415af28ee5 100644 --- a/demos/heatmap.html +++ b/demos/heatmap.html @@ -42,15 +42,6 @@ scene.on('loaded', () => { } }) .render(); - - /* scene.PointLayer({ - zIndex: 3 - }) - .source(data) - .shape('2d:circle') - .size(2) - .color('#EE2C2C') - .render();*/ }); }); diff --git a/src/geom/buffer/heatmap.js b/src/geom/buffer/heatmap/heatmap.js similarity index 95% rename from src/geom/buffer/heatmap.js rename to src/geom/buffer/heatmap/heatmap.js index 6553f1ea59..6d394a8ea7 100644 --- a/src/geom/buffer/heatmap.js +++ b/src/geom/buffer/heatmap/heatmap.js @@ -1,6 +1,6 @@ -import BufferBase from './bufferBase'; -import { colorScales } from '../../attr/colorscales'; -import * as THREE from '../../core/three'; +import BufferBase from '../bufferBase'; +import { colorScales } from '../../../attr/colorscales'; +import * as THREE from '../../../core/three'; export default class HeatmapBuffer extends BufferBase { diff --git a/src/layer/heatmap.js b/src/layer/heatmap.js deleted file mode 100644 index 3b23ad98da..0000000000 --- a/src/layer/heatmap.js +++ /dev/null @@ -1,55 +0,0 @@ -import Layer from '../core/layer'; -import gridBuffer from '../geom/buffer/heatmap/grid'; -import DrawGrid from './render/heatmap/gird'; -import DrawHexagon from './render/heatmap/hexagon'; -import hexagonBuffer from '../geom/buffer/heatmap/hexagon'; - -export default class HeatMapLayer extends Layer { - shape(type) { - this.shapeType = type; - return this; - } - render() { - this._prepareRender(); - return this; - } - _prepareRender() { - this.init(); - switch (this.shapeType) { - case 'grid' : - this._drawGrid(); - break; - case 'hexagon' : - this._drawHexagon(); - break; - default: - this._drawGrid(); - } - } - _drawHexagon() { - const style = this.get('styleOptions'); - const { radius } = this.layerSource.data; - this._buffer = new hexagonBuffer(this.layerData); - const config = { - ...style, - radius - }; - const Mesh = new DrawHexagon(this._buffer, config); - this.add(Mesh); - - } - _drawGrid() { - 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/heatmapLayer.js b/src/layer/heatmapLayer.js index 455bbfd943..117bab6822 100644 --- a/src/layer/heatmapLayer.js +++ b/src/layer/heatmapLayer.js @@ -1,111 +1,55 @@ import Layer from '../core/layer'; -import HeatmapBuffer from '../geom/buffer/heatmap'; -import { createColorRamp } from '../geom/buffer/heatmap'; -import { HeatmapIntensityMaterial, HeatmapColorizeMaterial } from '../geom/material/heatmapMateial'; -import Renderpass from '../core/engine/renderpass'; -import * as THREE from '../core/three'; - -export default class HeatmapLayer extends Layer { +import gridBuffer from '../geom/buffer/heatmap/grid'; +import DrawGrid from './render/heatmap/gird'; +import DrawHexagon from './render/heatmap/hexagon'; +import drawHeatmap from './render/heatmap/heatmap'; +import hexagonBuffer from '../geom/buffer/heatmap/hexagon'; +export default class HeatMapLayer extends Layer { + shape(type) { + this.shapeType = type; + return this; + } render() { + this._prepareRender(); + return this; + } + _prepareRender() { this.init(); - const bbox = this._calBoundingBox(this.layerData); - const colors = this.get('styleOptions').rampColors; - this.colorRamp = createColorRamp(colors); - this._createIntensityPass(bbox); - this._createColorizePass(bbox); + this.type = 'heatmap'; + switch (this.shapeType) { + case 'grid' : + this._drawGrid(); + break; + case 'hexagon' : + this._drawHexagon(); + break; + default: + drawHeatmap(this); + } } - - _createIntensityPass(bbox) { + _drawHexagon() { const style = this.get('styleOptions'); - const data = this.layerData; - // get attributes data - const buffer = new HeatmapBuffer({ - data - }); - const attributes = buffer.attributes; - // create geometery - const geometry = new THREE.BufferGeometry(); - // geometry.setIndex(attributes.indices); - geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.vertices, 3)); - geometry.addAttribute('a_dir', new THREE.Float32BufferAttribute(attributes.dirs, 2)); - geometry.addAttribute('a_weight', new THREE.Float32BufferAttribute(attributes.weights, 1)); - // set material - const material = new HeatmapIntensityMaterial({ - intensity: style.intensity, - radius: style.radius, - zoom: this.scene.getZoom() - }); - const mesh = new THREE.Mesh(geometry, material); - // set camera - const passOrth = new THREE.OrthographicCamera(bbox.width / -2, bbox.width / 2, bbox.height / 2, bbox.height / -2, 1, 10000); - passOrth.position.set(bbox.minX + bbox.width / 2, bbox.minY + bbox.height / 2, 1000); - // renderpass - const renderpass = new Renderpass({ - renderer: this.scene._engine._renderer, - camera: passOrth, - size: { - width: 10000, - height: 10000 * (bbox.height / bbox.width) - }, - clear: { - clearColor: 0x000000, - clearAlpha: 1.0 - } - }); - renderpass.add(mesh); - renderpass.render(); - this.intensityPass = renderpass; - const scene = this.scene; - render(); - function render() { - requestAnimationFrame(render); - renderpass.render(); - mesh.material.uniforms.u_zoom.value = scene.getZoom(); - } - } - _createColorizePass(bbox) { - // create plane geometry - const geometery = new THREE.PlaneBufferGeometry(bbox.width, bbox.height); - const material = new HeatmapColorizeMaterial({ - texture: this.intensityPass.texture, - colorRamp: this.colorRamp - }); - const mesh = new THREE.Mesh(geometery, material); - mesh.position.set(bbox.minX + bbox.width / 2, bbox.minY + bbox.height / 2, 0.0); - this.add(mesh); - } - - _calBoundingBox(data) { - let minX = Infinity; - let minY = Infinity; - let maxX = -Infinity; - let maxY = -Infinity; - for (let i = 0; i < data.length; i++) { - const p = data[i].coordinates; - if (p[0] < minX) { - minX = p[0]; - } else if (p[0] > maxX) { - maxX = p[0]; - } - if (p[1] < minY) { - minY = p[1]; - } else if (p[1] > maxY) { - maxY = p[1]; - } - } - const width = maxX - minX; - const height = maxY - minY; - - return { - minX, - maxX, - minY, - maxY, - width, - height + const { radius } = this.layerSource.data; + this._buffer = new hexagonBuffer(this.layerData); + const config = { + ...style, + radius }; + const Mesh = new DrawHexagon(this._buffer, config); + this.add(Mesh); + } + _drawGrid() { + 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/index.js b/src/layer/index.js index a6a5314142..f7754776e2 100644 --- a/src/layer/index.js +++ b/src/layer/index.js @@ -5,14 +5,12 @@ import LineLayer from './lineLayer'; import ImageLayer from './imageLayer'; import RasterLayer from './rasterLayer'; import HeatmapLayer from './heatmapLayer'; -import HeatMapLayer from './heatmap'; registerLayer('PolygonLayer', PolygonLayer); registerLayer('PointLayer', PointLayer); registerLayer('LineLayer', LineLayer); registerLayer('ImageLayer', ImageLayer); registerLayer('RasterLayer', RasterLayer); -registerLayer('HeatMapLayer', HeatMapLayer); registerLayer('HeatmapLayer', HeatmapLayer); export { LAYER_MAP } from './factory'; diff --git a/src/layer/render/heatmap/heatmap.js b/src/layer/render/heatmap/heatmap.js new file mode 100644 index 0000000000..02ab1063c0 --- /dev/null +++ b/src/layer/render/heatmap/heatmap.js @@ -0,0 +1,105 @@ +import HeatmapBuffer from '../../../geom/buffer/heatmap/heatmap'; +import { createColorRamp } from '../../../geom/buffer/heatmap/heatmap'; +import { HeatmapIntensityMaterial, HeatmapColorizeMaterial } from '../../../geom/material/heatmapMateial'; +import Renderpass from '../../../core/engine/renderpass'; +import * as THREE from '../../../core/three'; + +export default function drawHeatmap(layer) { + const bbox = calBoundingBox(layer.layerData); + const colors = layer.get('styleOptions').rampColors; + layer.colorRamp = createColorRamp(colors); + createIntensityPass(layer, bbox); + createColorizePass(layer, bbox); +} + +function createIntensityPass(layer, bbox) { + const style = layer.get('styleOptions'); + const data = layer.layerData; + // get attributes data + const buffer = new HeatmapBuffer({ + data + }); + const attributes = buffer.attributes; + // create geometery + const geometry = new THREE.BufferGeometry(); + // geometry.setIndex(attributes.indices); + geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.vertices, 3)); + geometry.addAttribute('a_dir', new THREE.Float32BufferAttribute(attributes.dirs, 2)); + geometry.addAttribute('a_weight', new THREE.Float32BufferAttribute(attributes.weights, 1)); + // set material + const material = new HeatmapIntensityMaterial({ + intensity: style.intensity, + radius: style.radius, + zoom: layer.scene.getZoom() + }); + const mesh = new THREE.Mesh(geometry, material); + // set camera + const passOrth = new THREE.OrthographicCamera(bbox.width / -2, bbox.width / 2, bbox.height / 2, bbox.height / -2, 1, 10000); + passOrth.position.set(bbox.minX + bbox.width / 2, bbox.minY + bbox.height / 2, 1000); + // renderpass + const renderpass = new Renderpass({ + renderer: layer.scene._engine._renderer, + camera: passOrth, + size: { + width: 10000, + height: 10000 * (bbox.height / bbox.width) + }, + clear: { + clearColor: 0x000000, + clearAlpha: 1.0 + } + }); + renderpass.add(mesh); + renderpass.render(); + layer.intensityPass = renderpass; + const scene = layer.scene; + render(); + function render() { + requestAnimationFrame(render); + renderpass.render(); + mesh.material.uniforms.u_zoom.value = scene.getZoom(); + } +} +function createColorizePass(layer, bbox) { + // create plane geometry + const geometery = new THREE.PlaneBufferGeometry(bbox.width, bbox.height); + const material = new HeatmapColorizeMaterial({ + texture: layer.intensityPass.texture, + colorRamp: layer.colorRamp + }); + const mesh = new THREE.Mesh(geometery, material); + mesh.position.set(bbox.minX + bbox.width / 2, bbox.minY + bbox.height / 2, 0.0); + layer.add(mesh); +} + +function calBoundingBox(data) { + let minX = Infinity; + let minY = Infinity; + let maxX = -Infinity; + let maxY = -Infinity; + for (let i = 0; i < data.length; i++) { + const p = data[i].coordinates; + if (p[0] < minX) { + minX = p[0]; + } else if (p[0] > maxX) { + maxX = p[0]; + } + if (p[1] < minY) { + minY = p[1]; + } else if (p[1] > maxY) { + maxY = p[1]; + } + } + const width = maxX - minX; + const height = maxY - minY; + + return { + minX, + maxX, + minY, + maxY, + width, + height + }; +} +