diff --git a/.torch.compile.opts.js b/.torch.compile.opts.js index c2e828ddc9..cea3ac8770 100755 --- a/.torch.compile.opts.js +++ b/.torch.compile.opts.js @@ -1,5 +1,4 @@ const path = require('path'); - module.exports = { babelrc: { presets: [ @@ -10,7 +9,7 @@ module.exports = { include: [ 'src/**/*.js', 'test/**/*.js', - 'node_modules/three/**/*.js', + 'node_modules/_three@0.96.0@three/**/*.js', 'node_modules/simple-statistics/src/*.js' ], exclude: [ diff --git a/demos/hexgon.html b/demos/hexgon.html new file mode 100644 index 0000000000..ce5ed92af9 --- /dev/null +++ b/demos/hexgon.html @@ -0,0 +1,76 @@ + + + + + + + + + point_circle + + + + +
+ + + + + + + + diff --git a/package.json b/package.json index 01f457cb7e..e992b41020 100755 --- a/package.json +++ b/package.json @@ -78,11 +78,11 @@ "prepublishOnly": "npm run build-lib && npm run dist", "screenshot": "node ./bin/screenshot.js", "start": "npm run dev", - "test": "torch --compile --renderer --recursive test/unit", + "test": "torch --compile-opts ./.torch.compile.opts.js --compile --renderer --recursive test/unit", "test-all": "npm run test && npm run test-bugs", "test-bugs": "torch --compile --renderer --recursive test/bugs", "test-bugs-live": "torch --compile --interactive --watch --recursive test/bugs", - "test-live": "torch --compile --interactive --watch --recursive test/unit", + "test-live": "torch --compile --interactive --watch --recursive test/unit", "watch": "webpack --config webpack-dev.config.js", "win-dev": "node ./bin/win-dev.js" }, diff --git a/src/core/three.js b/src/core/three.js index 03359e840d..1658e39038 100644 --- a/src/core/three.js +++ b/src/core/three.js @@ -35,4 +35,4 @@ export { BufferAttribute } from 'three/src/core/BufferAttribute.js'; -// export * from '../../build/Three.js'; +// export * from '../../build/three.js'; diff --git a/src/geom/buffer/heatmap/hexagon.js b/src/geom/buffer/heatmap/hexagon.js new file mode 100644 index 0000000000..1d30f66807 --- /dev/null +++ b/src/geom/buffer/heatmap/hexagon.js @@ -0,0 +1,32 @@ +import { polygonPath } from '../../shape/path'; +import { fill } from '../../shape/polygon'; +export default function hexagonBuffer(layerData) { + const attribute = { + vertices: [], + miter: [], + colors: [], + pickingIds: [] + }; + const a = Math.cos(Math.PI / 6); + const points = [ + [ 0, -1, 0 ], + [ -a, -0.5, 0 ], + [ -a, 0.5, 0 ], + [ 0, 1, 0 ], + [ a, 0.5, 0 ], + [ a, -0.5, 0 ], + [ 0, -1, 0 ] + ]; + // const hexgonPoints = polygonPath(6); + const hexgonFill = fill([ points ]); + const { positionsIndex, positions } = hexgonFill; + layerData.forEach(element => { + positionsIndex.forEach(pointIndex => { + attribute.vertices.push(...element.coordinates); + attribute.miter.push(positions[pointIndex][0], positions[pointIndex][1]); + attribute.pickingIds.push(element.id); + attribute.colors.push(...element.color); + }); + }); + return attribute; +} diff --git a/src/geom/material/hexagon.js b/src/geom/material/hexagon.js new file mode 100644 index 0000000000..4b2e0896c8 --- /dev/null +++ b/src/geom/material/hexagon.js @@ -0,0 +1,31 @@ +import grid_frag from '../shader/hexagon_frag.glsl'; +import grid_vert from '../shader/hexagon_vert.glsl'; +import Material from './material'; + + +export default class hexagonMaterial extends Material { + getDefaultParameters() { + return { + uniforms: { + u_opacity: { value: 1.0 }, + u_time: { value: 0 }, + u_radius: { value: 0.01 }, + u_angle: { 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 = 'hexagonMaterial'; + this.defines = Object.assign(defines, _defines); + this.vertexShader = grid_vert; + this.fragmentShader = grid_frag; + this.transparent = true; + } +} diff --git a/src/geom/shader/hexagon_frag.glsl b/src/geom/shader/hexagon_frag.glsl new file mode 100644 index 0000000000..042dde511e --- /dev/null +++ b/src/geom/shader/hexagon_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/hexagon_vert.glsl b/src/geom/shader/hexagon_vert.glsl new file mode 100644 index 0000000000..30268d4861 --- /dev/null +++ b/src/geom/shader/hexagon_vert.glsl @@ -0,0 +1,17 @@ +precision highp float; +attribute vec2 miter; +attribute vec4 a_color; +uniform float u_radius; +uniform float u_coverage; +uniform float u_angle; +varying vec4 v_color; + +void main() { + mat4 matModelViewProjection = projectionMatrix * modelViewMatrix; + mat2 rotationMatrix = mat2(cos(u_angle), sin(u_angle), -sin(u_angle), cos(u_angle)); + v_color = a_color; + vec2 offset =vec2(rotationMatrix * miter * u_radius * u_coverage ); + float x = position.x + offset.x; + float y = position.y + offset.y; + gl_Position = matModelViewProjection * vec4(x, y, position.z, 1.0); +} \ No newline at end of file diff --git a/src/geom/shader/point_vert.glsl b/src/geom/shader/point_vert.glsl index 55b7d76a76..a39283badf 100644 --- a/src/geom/shader/point_vert.glsl +++ b/src/geom/shader/point_vert.glsl @@ -2,7 +2,6 @@ precision highp float; attribute vec4 a_color; attribute float a_size; attribute float a_shape; -attribute vec4 a_idColor; uniform vec4 u_stroke; uniform float u_strokeWidth; uniform float u_opacity; diff --git a/src/geom/shader/polygon_vert.glsl b/src/geom/shader/polygon_vert.glsl index eba0b62d02..5ae3a3c2a1 100644 --- a/src/geom/shader/polygon_vert.glsl +++ b/src/geom/shader/polygon_vert.glsl @@ -3,7 +3,6 @@ precision highp float; #define diffuseRatio 0.4 #define specularRatio 0.1 attribute vec4 a_color; -attribute vec4 a_idColor; attribute vec2 faceUv; attribute vec3 a_shape; attribute vec3 a_size; diff --git a/src/layer/heatmap.js b/src/layer/heatmap.js index f9971a55da..3b23ad98da 100644 --- a/src/layer/heatmap.js +++ b/src/layer/heatmap.js @@ -1,6 +1,8 @@ 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) { @@ -13,6 +15,30 @@ export default class HeatMapLayer extends Layer { } _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; @@ -25,4 +51,5 @@ export default class HeatMapLayer extends Layer { const girdMesh = new DrawGrid(this._buffer, config); this.add(girdMesh); } + } diff --git a/src/layer/render/heatmap/hexagon.js b/src/layer/render/heatmap/hexagon.js new file mode 100644 index 0000000000..04b7580cbd --- /dev/null +++ b/src/layer/render/heatmap/hexagon.js @@ -0,0 +1,21 @@ +import * as THREE from '../../../core/three'; +import GridMaterial from '../../../geom/material/hexagon'; +export default function DrawHexagon(attributes, style) { + const { opacity, radius, angle, 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_radius: radius, + u_angle: angle / 180 * Math.PI, + u_coverage: coverage + }, { + SHAPE: false + }); + const hexgonMesh = new THREE.Mesh(geometry, material); + return hexgonMesh; +} + diff --git a/src/source/index.js b/src/source/index.js index ff88ba484e..1d7fe62ba4 100644 --- a/src/source/index.js +++ b/src/source/index.js @@ -8,6 +8,7 @@ import raster from './parser/raster'; import { registerTransform, registerParser } from './factory'; import { aggregatorToGrid } from './transform/grid'; +import { pointToHexbin } from './transform/hexagon'; import { map } from './transform/map'; registerParser('geojson', geojson); @@ -18,6 +19,7 @@ registerParser('raster', raster); // 注册transform registerTransform('grid', aggregatorToGrid); +registerTransform('hexagon', pointToHexbin); registerTransform('map', map); export { getTransform, registerTransform, getParser, registerParser } from './factory'; diff --git a/src/source/transform/grid.js b/src/source/transform/grid.js index d2ace3476c..21440bae89 100644 --- a/src/source/transform/grid.js +++ b/src/source/transform/grid.js @@ -17,8 +17,8 @@ export function aggregatorToGrid(data, 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, + xOffset: gridOffset.xOffset / 360 * (256 << 20) / 2, dataArray: layerData }; } diff --git a/src/source/transform/hexagon.js b/src/source/transform/hexagon.js index f0aa9692f1..c550dc32ac 100644 --- a/src/source/transform/hexagon.js +++ b/src/source/transform/hexagon.js @@ -20,7 +20,7 @@ export function pointToHexbin(data, option) { .y(d => d.coordinates[1]); const hexbinBins = newHexbin(screenPoints); const result = { - size: pixlSize + radius: pixlSize }; result.dataArray = hexbinBins.map((hex, index) => { if (option.field && option.method) { @@ -31,8 +31,9 @@ export function pointToHexbin(data, option) { item[option.method] = hex[option.method]; return { ...item, + count: hex.length, coordinates: unProjectFlat([ hex.x, hex.y ]), - id: index + 1 + _id: index + 1 }; }); return result; diff --git a/test/unit/geom/buffer/heatmap/hexagon.js b/test/unit/geom/buffer/heatmap/hexagon.js new file mode 100644 index 0000000000..c92074bca3 --- /dev/null +++ b/test/unit/geom/buffer/heatmap/hexagon.js @@ -0,0 +1,35 @@ +import { expect } from 'chai'; +import hexagonBuffer from '../../../../../src/geom/buffer/heatmap/hexagon'; +describe('hexagon heatMap buffer', () => { + const layerData = [ + { color: [ 1, 1, 0, 1 ], coordinates: [ 120.12063099925889, 30.263947783103486, 0 ], id: 1 }, + { color: [ 1, 0.5, 0, 1 ], coordinates: [ 120.12218696039365, 30.263947783103486, 0 ], id: 2 }, + { + color: [ 1, 0.1, 0, 1 ], + coordinates: [ 120.12374292152843, 30.263947783103486, 0 ], + id: 3 + }, + { color: [ 1, 0, 0.2, 1 ], coordinates: [ 120.1252988826632, 30.263947783103486, 0 ], id: 4 }, + { + color: [ 0, 1, 0, 1 ], + coordinates: [ 120.12607686323062, 30.263947783103486, 0 ], + id: 5 + }, + { + color: [ 1, 1, 0, 1 ], + coordinates: [ 120.12685484379799, 30.263947783103486, 0 ], + id: 6 + }, + { color: [ 1, 1, 1, 1 ], coordinates: [ 120.12841080493274, 30.263947783103486, 0 ], id: 7 }, + { color: [ 0, 1, 1, 1 ], coordinates: [ 120.13230070776972, 30.263947783103486, 0 ], id: 8 }, + { color: [ 0, 1, 0, 1 ], coordinates: [ 120.12763282436538, 30.263947783103486, 0 ], id: 9 }, + { color: [ 1, 1, 0, 1 ], coordinates: [ 120.12996676606754, 30.263947783103486, 0 ], id: 10 } + ]; + it('hexagon buffer', () => { + const attribute = hexagonBuffer(layerData); + expect(attribute.colors.length).eql(480); + expect(attribute.miter.length).eql(240); + expect(attribute.pickingIds.length).eql(120); + expect(attribute.vertices.length).eql(360); + }); +}); diff --git a/test/unit/shader-module/base-spec.js b/test/unit/shader-module/base-spec.js index 8f2b35c079..ebe8cd9b43 100644 --- a/test/unit/shader-module/base-spec.js +++ b/test/unit/shader-module/base-spec.js @@ -24,9 +24,8 @@ describe('test shader module', function() { it('should import a module correctly.', function() { const { vs, fs } = getModule('module1'); - expect(vs).eq('#define PI 3.14'); - expect(fs).eq(''); + expect(fs.replace(/(\s+)|(\n)+|(\r\n)+/g, '')).eqls('#ifdefGL_FRAGMENT_PRECISION_HIGHprecisionhighpfloat;#elseprecisionmediumpfloat;#endif'); }); }); diff --git a/test/unit/source/transfrom/hexagon.js b/test/unit/source/transfrom/hexagon.js index aad4edb018..8fd3ce4dc6 100644 --- a/test/unit/source/transfrom/hexagon.js +++ b/test/unit/source/transfrom/hexagon.js @@ -18,6 +18,5 @@ describe('hexagon Test', function() { }; const hexgonGrid = pointToHexbin(data, { size: 100, field: 'v', method: 'sum' }); expect(hexgonGrid.dataArray.length).eql(567); - console.log(hexgonGrid); }); }); diff --git a/webpack.config.js b/webpack.config.js index 9106df5d7f..823d9ef161 100755 --- a/webpack.config.js +++ b/webpack.config.js @@ -4,7 +4,8 @@ const pkg = require('./package.json'); module.exports = { devtool: 'cheap-source-map', entry: { - l7: './src/index.js' + l7: './src/index.js', + three: './src/core/three.js' }, output: { filename: '[name].js',