feat(l7): feat heatmap layer

This commit is contained in:
mipha.ly@alibaba-inc.com 2019-02-27 17:14:01 +08:00 committed by mipha.ly
parent e5e4688d0d
commit 852c21b312
6 changed files with 153 additions and 170 deletions

View File

@ -42,15 +42,6 @@ scene.on('loaded', () => {
}
})
.render();
/* scene.PointLayer({
zIndex: 3
})
.source(data)
.shape('2d:circle')
.size(2)
.color('#EE2C2C')
.render();*/
});
});
</script>

View File

@ -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 {

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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';

View File

@ -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
};
}