mirror of https://gitee.com/antv-l7/antv-l7
feat(l7): feat heatmap layer
This commit is contained in:
parent
59342df852
commit
eec6a121ac
|
@ -42,15 +42,6 @@ scene.on('loaded', () => {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.render();
|
.render();
|
||||||
|
|
||||||
/* scene.PointLayer({
|
|
||||||
zIndex: 3
|
|
||||||
})
|
|
||||||
.source(data)
|
|
||||||
.shape('2d:circle')
|
|
||||||
.size(2)
|
|
||||||
.color('#EE2C2C')
|
|
||||||
.render();*/
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import BufferBase from './bufferBase';
|
import BufferBase from '../bufferBase';
|
||||||
import { colorScales } from '../../attr/colorscales';
|
import { colorScales } from '../../../attr/colorscales';
|
||||||
import * as THREE from '../../core/three';
|
import * as THREE from '../../../core/three';
|
||||||
|
|
||||||
|
|
||||||
export default class HeatmapBuffer extends BufferBase {
|
export default class HeatmapBuffer extends BufferBase {
|
|
@ -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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,111 +1,55 @@
|
||||||
import Layer from '../core/layer';
|
import Layer from '../core/layer';
|
||||||
import HeatmapBuffer from '../geom/buffer/heatmap';
|
import gridBuffer from '../geom/buffer/heatmap/grid';
|
||||||
import { createColorRamp } from '../geom/buffer/heatmap';
|
import DrawGrid from './render/heatmap/gird';
|
||||||
import { HeatmapIntensityMaterial, HeatmapColorizeMaterial } from '../geom/material/heatmapMateial';
|
import DrawHexagon from './render/heatmap/hexagon';
|
||||||
import Renderpass from '../core/engine/renderpass';
|
import drawHeatmap from './render/heatmap/heatmap';
|
||||||
import * as THREE from '../core/three';
|
import hexagonBuffer from '../geom/buffer/heatmap/hexagon';
|
||||||
|
|
||||||
export default class HeatmapLayer extends Layer {
|
|
||||||
|
|
||||||
|
export default class HeatMapLayer extends Layer {
|
||||||
|
shape(type) {
|
||||||
|
this.shapeType = type;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
render() {
|
render() {
|
||||||
|
this._prepareRender();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
_prepareRender() {
|
||||||
this.init();
|
this.init();
|
||||||
const bbox = this._calBoundingBox(this.layerData);
|
this.type = 'heatmap';
|
||||||
const colors = this.get('styleOptions').rampColors;
|
switch (this.shapeType) {
|
||||||
this.colorRamp = createColorRamp(colors);
|
case 'grid' :
|
||||||
this._createIntensityPass(bbox);
|
this._drawGrid();
|
||||||
this._createColorizePass(bbox);
|
break;
|
||||||
|
case 'hexagon' :
|
||||||
|
this._drawHexagon();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
drawHeatmap(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
_drawHexagon() {
|
||||||
_createIntensityPass(bbox) {
|
|
||||||
const style = this.get('styleOptions');
|
const style = this.get('styleOptions');
|
||||||
const data = this.layerData;
|
const { radius } = this.layerSource.data;
|
||||||
// get attributes data
|
this._buffer = new hexagonBuffer(this.layerData);
|
||||||
const buffer = new HeatmapBuffer({
|
const config = {
|
||||||
data
|
...style,
|
||||||
});
|
radius
|
||||||
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 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,14 +5,12 @@ import LineLayer from './lineLayer';
|
||||||
import ImageLayer from './imageLayer';
|
import ImageLayer from './imageLayer';
|
||||||
import RasterLayer from './rasterLayer';
|
import RasterLayer from './rasterLayer';
|
||||||
import HeatmapLayer from './heatmapLayer';
|
import HeatmapLayer from './heatmapLayer';
|
||||||
import HeatMapLayer from './heatmap';
|
|
||||||
|
|
||||||
registerLayer('PolygonLayer', PolygonLayer);
|
registerLayer('PolygonLayer', PolygonLayer);
|
||||||
registerLayer('PointLayer', PointLayer);
|
registerLayer('PointLayer', PointLayer);
|
||||||
registerLayer('LineLayer', LineLayer);
|
registerLayer('LineLayer', LineLayer);
|
||||||
registerLayer('ImageLayer', ImageLayer);
|
registerLayer('ImageLayer', ImageLayer);
|
||||||
registerLayer('RasterLayer', RasterLayer);
|
registerLayer('RasterLayer', RasterLayer);
|
||||||
registerLayer('HeatMapLayer', HeatMapLayer);
|
|
||||||
registerLayer('HeatmapLayer', HeatmapLayer);
|
registerLayer('HeatmapLayer', HeatmapLayer);
|
||||||
|
|
||||||
export { LAYER_MAP } from './factory';
|
export { LAYER_MAP } from './factory';
|
||||||
|
|
|
@ -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
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue