From 6dd6c5dd018551c67a42c1e1e28373c55ede58e9 Mon Sep 17 00:00:00 2001 From: thinkinggis Date: Wed, 17 Apr 2019 15:41:26 +0800 Subject: [PATCH] feat(tile): add tile --- demos/01_point_circle.html | 4 +- package.json | 1 + src/core/engine/picking/picking.js | 12 +- src/core/source.js | 2 +- src/geo/{buffer.js => lnglat.js} | 0 src/geo/point.js | 0 src/geom/buffer/image.js | 2 +- src/geom/extrude.js | 10 +- src/geom/shader/index.js | 5 + src/geom/shader/polygon_frag.glsl | 13 +- src/geom/shader/polygon_vert.glsl | 3 +- src/geom/shape/path.js | 6 +- src/layer/render/image/drawImage.js | 13 ++ src/layer/render/polygon/drawFill.js | 12 +- src/layer/tile/imageTile.js | 190 +++++++----------- src/layer/tile/tile.js | 99 ++++----- .../tile/{tile-cache.js => tileCache.js} | 0 src/layer/tile/tileLayer.js | 8 + 18 files changed, 183 insertions(+), 197 deletions(-) rename src/geo/{buffer.js => lnglat.js} (100%) create mode 100644 src/geo/point.js create mode 100644 src/layer/render/image/drawImage.js rename src/layer/tile/{tile-cache.js => tileCache.js} (100%) create mode 100644 src/layer/tile/tileLayer.js diff --git a/demos/01_point_circle.html b/demos/01_point_circle.html index 57c8ef8dc7..f63a295ae3 100644 --- a/demos/01_point_circle.html +++ b/demos/01_point_circle.html @@ -59,11 +59,11 @@ scene.on('loaded', () => { .source(data,{ isCluster:true }) - .shape('hexagon') + .shape('circle') .size('point_count', [ 5, 40]) // default 1 //.size('value', [ 10, 300]) // default 1 .active(true) - .color('point_count',colorObj.blue) + .color('point_count',["#002466","#105CB3","#2894E0","#CFF6FF","#FFF5B8","#FFAB5C","#F27049","#730D1C"]) .style({ stroke: 'rgb(255,255,255)', strokeWidth: 1, diff --git a/package.json b/package.json index 529672e824..125dcb8168 100755 --- a/package.json +++ b/package.json @@ -96,6 +96,7 @@ }, "dependencies": { "@antv/g": "^3.1.3", + "@antv/geo-coord": "^1.0.8", "@antv/util": "~2.0.1", "@mapbox/tiny-sdf": "^1.1.0", "@turf/bbox": "^6.0.1", diff --git a/src/core/engine/picking/picking.js b/src/core/engine/picking/picking.js index 6d6ba60de1..3d61d86427 100755 --- a/src/core/engine/picking/picking.js +++ b/src/core/engine/picking/picking.js @@ -87,21 +87,11 @@ class Picking { id = -999; // return; } - this._raycaster.setFromCamera(normalisedPoint, this._camera); - - const intersects = this._raycaster.intersectObjects(this._pickingScene.children, true); const _point2d = { x: point.x, y: point.y }; - - let _point3d; - if (intersects.length > 0) { - _point3d = intersects[0].point; - } const item = { layerId, featureId: id, - point2d: _point2d, - point3d: _point3d, - intersects + point2d: _point2d }; return item; diff --git a/src/core/source.js b/src/core/source.js index 765636ea5d..60f667c755 100644 --- a/src/core/source.js +++ b/src/core/source.js @@ -33,7 +33,7 @@ export default class Source extends Base { // 数据转换 统计,聚合,分类 this._executeTrans(); // 坐标转换 - this._projectCoords(); + // this._projectCoords(); } setData(data, cfg = {}) { Object.assign(this._attrs, cfg); diff --git a/src/geo/buffer.js b/src/geo/lnglat.js similarity index 100% rename from src/geo/buffer.js rename to src/geo/lnglat.js diff --git a/src/geo/point.js b/src/geo/point.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/geom/buffer/image.js b/src/geom/buffer/image.js index 262151b149..5c69a4abf5 100644 --- a/src/geom/buffer/image.js +++ b/src/geom/buffer/image.js @@ -23,7 +23,7 @@ export default class ImageBuffer extends BufferBase { const uv = [ 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0 ]; const texture = new THREE.Texture(image); texture.magFilter = THREE.LinearFilter; - texture.minFilter = THREE.LinearFilter; + texture.minFilter = THREE.LinearMipMapLinearFilter; texture.needsUpdate = true; const attributes = { vertices: new Float32Array(positions), diff --git a/src/geom/extrude.js b/src/geom/extrude.js index 3b3375b798..8ae4aef5c1 100644 --- a/src/geom/extrude.js +++ b/src/geom/extrude.js @@ -19,18 +19,18 @@ export default function extrudePolygon(points, extrude) { const flattengeo = earcut.flatten(points); const positions = []; let cells = []; - + const { dimensions } = flattengeo; const triangles = earcut(flattengeo.vertices, flattengeo.holes, flattengeo.dimensions); cells = triangles; - const pointCount = flattengeo.vertices.length / 3; + const pointCount = flattengeo.vertices.length / dimensions; const { vertices } = flattengeo; extrude ? full() : flat(); function flat() { for (let i = 0; i < pointCount; i++) { - positions.push([ vertices[ i * 3 ], vertices[i * 3 + 1 ], 0 ]); + positions.push([ vertices[ i * dimensions ], vertices[i * dimensions + 1 ], 0 ]); } } function full() { @@ -41,10 +41,10 @@ export default function extrudePolygon(points, extrude) { // 顶部坐标 for (let i = 0; i < pointCount; i++) { - positions.push([ vertices[ i * 3 ], vertices[i * 3 + 1 ], 1 ]); + positions.push([ vertices[ i * dimensions ], vertices[i * dimensions + 1 ], 1 ]); } for (let i = 0; i < pointCount; i++) { - positions.push([ vertices[ i * 3 ], vertices[i * 3 + 1 ], 0 ]); + positions.push([ vertices[ i * dimensions ], vertices[i * dimensions + 1 ], 0 ]); } for (let i = 0; i < n; i++) { if (i === (n - 1)) { diff --git a/src/geom/shader/index.js b/src/geom/shader/index.js index c884b87690..0962214754 100644 --- a/src/geom/shader/index.js +++ b/src/geom/shader/index.js @@ -41,6 +41,10 @@ import image_frag from '../shader/image_frag.glsl'; import raster_vert from '../shader/raster_vert.glsl'; import raster_frag from '../shader/raster_frag.glsl'; +// tile +import tile_polygon_vert from '../shader/tile/polygon_vert.glsl'; +import tile_polygon_frag from '../shader/tile/polygon_frag.glsl'; + import common from './common.glsl'; import { registerModule } from '../../util/shaderModule'; import pick_color from './shaderChunks/pick_color.glsl'; @@ -60,5 +64,6 @@ export function compileBuiltinModules() { registerModule('text', { vs: text_vert, fs: text_frag }); registerModule('image', { vs: image_vert, fs: image_frag }); registerModule('raster', { vs: raster_vert, fs: raster_frag }); + registerModule('tilepolygon', { vs: tile_polygon_vert, fs: tile_polygon_frag }); } diff --git a/src/geom/shader/polygon_frag.glsl b/src/geom/shader/polygon_frag.glsl index bad3913f6b..545721cd04 100644 --- a/src/geom/shader/polygon_frag.glsl +++ b/src/geom/shader/polygon_frag.glsl @@ -41,7 +41,12 @@ float sdRect(vec2 p, vec2 sz) { float inside = min(max(d.x, d.y), 0.); return outside + inside; } - +float circle(in vec2 _st, in float _radius){ + vec2 dist = _st-vec2(0.5); + return 1.-smoothstep(_radius-(_radius*0.01), + _radius+(_radius*0.01), + dot(dist,dist)*4.0); +} void main() { if(v_color.w == 0.0) { @@ -106,6 +111,12 @@ void main() { gl_FragColor = vec4(foggedColor,1.0); } #else + // #ifdef SHAPE + // vec2 st = gl_FragCoord.xy / v_size ; + // vec3 color = vec3(circle(st,0.5)); + // gl_FragColor = vec4(color, 1.0 ); + // return; + // #endif gl_FragColor = vec4(v_color.xyz , v_color.w); #endif diff --git a/src/geom/shader/polygon_vert.glsl b/src/geom/shader/polygon_vert.glsl index 2015bee5f5..815244fb97 100644 --- a/src/geom/shader/polygon_vert.glsl +++ b/src/geom/shader/polygon_vert.glsl @@ -30,6 +30,7 @@ void main() { if(pickingId == u_activeId) { v_color = u_activeColor; } + v_size = a_size.x * scale; gl_Position = matModelViewProjection * vec4(newposition, 1.0); return; } @@ -49,7 +50,7 @@ void main() { float lightWeight = ambientRatio + diffuseRatio * lambert + specularRatio * specular; v_texCoord = faceUv; v_lightWeight = lightWeight; - // v_size = a_size; + v_color =vec4(a_color.rgb*lightWeight, a_color.w); if(pickingId == u_activeId) { v_color = u_activeColor; diff --git a/src/geom/shape/path.js b/src/geom/shape/path.js index a693484d9c..82bd51d68e 100644 --- a/src/geom/shape/path.js +++ b/src/geom/shape/path.js @@ -16,7 +16,7 @@ function triangle() { return polygonPath(3); } function hexagon() { - return polygonPath(6); + return polygonPath(6, 1); } export { circle, @@ -29,11 +29,11 @@ export { square as squareColumn }; -export function polygonPath(pointCount) { +export function polygonPath(pointCount, start = 0) { const step = Math.PI * 2 / pointCount; const line = []; for (let i = 0; i < pointCount; i++) { - line.push(step * i - Math.PI / 12); + line.push(step * i - start * Math.PI / 12); } const path = line.map(t => { const x = Math.sin(t + Math.PI / 4), diff --git a/src/layer/render/image/drawImage.js b/src/layer/render/image/drawImage.js new file mode 100644 index 0000000000..54a49d75a3 --- /dev/null +++ b/src/layer/render/image/drawImage.js @@ -0,0 +1,13 @@ +import * as THREE from '../../../core/three'; +import ImageMaterial from '../../../geom/material/imageMaterial'; +export default function DrawImage(attributes, style) { + this.geometry = new THREE.BufferGeometry(); + this.geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.vertices, 3)); + this.geometry.addAttribute('uv', new THREE.Float32BufferAttribute(attributes.uvs, 2)); + const { opacity } = style; + const material = new ImageMaterial({ + u_texture: attributes.texture, + u_opacity: opacity + }); + return new THREE.Mesh(this.geometry, material); +} diff --git a/src/layer/render/polygon/drawFill.js b/src/layer/render/polygon/drawFill.js index 8c5e5beb65..b273686929 100644 --- a/src/layer/render/polygon/drawFill.js +++ b/src/layer/render/polygon/drawFill.js @@ -1,5 +1,7 @@ import * as THREE from '../../../core/three'; -import PolygonMaterial from '../../../geom/material/polygonMaterial'; +// import PolygonMaterial from '../../../geom/material/polygonMaterial'; +import TileMaterial from '../../../geom/material/tile/polygon'; + export default function DrawPolygonFill(attributes, style) { const { opacity, activeColor } = style; const geometry = new THREE.BufferGeometry(); @@ -7,7 +9,13 @@ export default function DrawPolygonFill(attributes, style) { geometry.addAttribute('a_color', new THREE.Float32BufferAttribute(attributes.colors, 4)); geometry.addAttribute('pickingId', new THREE.Float32BufferAttribute(attributes.pickingIds, 1)); geometry.addAttribute('normal', new THREE.Float32BufferAttribute(attributes.normals, 3)); - const material = new PolygonMaterial({ + // const material = new PolygonMaterial({ + // u_opacity: opacity, + // u_activeColor: activeColor + // }, { + // SHAPE: false + // }); + const material = new TileMaterial({ u_opacity: opacity, u_activeColor: activeColor }, { diff --git a/src/layer/tile/imageTile.js b/src/layer/tile/imageTile.js index c14a052e01..3a3a8f6b46 100644 --- a/src/layer/tile/imageTile.js +++ b/src/layer/tile/imageTile.js @@ -1,137 +1,83 @@ -// import * as THREE from '../../core/three'; -// import Tile from './tile'; -// export default class ImageTile extends Tile { -// constructor(layer, z, x, y) { -// } -// requestTileAsync() { -// // Making this asynchronous really speeds up the LOD framerate -// setTimeout(() => { -// if (!this._mesh) { -// this._mesh = this._createMesh(); -// this._requestTile(); -// } -// }, 0); -// } -// _requestTile() { -// const urlParams = { -// x: this._tile[0], -// y: this._tile[1], -// z: this._tile[2] -// }; +import Tile from './tile'; +import ImageBuffer from '../../geom/buffer/image'; +import DrawImage from '../render/image/drawImage'; +export default class ImageTile extends Tile { + requestTileAsync() { + // Making this asynchronous really speeds up the LOD framerate + setTimeout(() => { + if (!this._mesh) { + this._mesh = this._createMesh(); + this._requestTile(); + } + }, 0); + } + _requestTile() { + const urlParams = { + x: this._tile[0], + y: this._tile[1], + z: this._tile[2] + }; -// const url = this._getTileURL(urlParams); + const url = this._getTileURL(urlParams); -// const image = document.createElement('img'); + const image = document.createElement('img'); -// image.addEventListener('load', event => { -// const texture = new THREE.Texture(); + image.addEventListener('load', () => { -// texture.image = image; -// texture.needsUpdate = true; + this._createMesh(image); + this._ready = true; + }, false); -// // Silky smooth images when tilted -// texture.magFilter = THREE.LinearFilter; -// texture.minFilter = THREE.LinearMipMapLinearFilter; + // image.addEventListener('progress', event => {}, false); + // image.addEventListener('error', event => {}, false); -// // TODO: Set this to renderer.getMaxAnisotropy() / 4 -// texture.anisotropy = 4; + image.crossOrigin = ''; -// texture.needsUpdate = true; + // Load image + image.src = url; -// // Something went wrong and the tile or its material is missing -// // -// // Possibly removed by the cache before the image loaded -// if (!this._mesh || !this._mesh.children[0] || !this._mesh.children[0].material) { -// return; -// } + this._image = image; + } + _getBufferData(images) { + const NW = this._tileBounds.getTopLeft().to; + const SE = this._tileBounds.getBottomRight(); + const coordinate = [[ NW.x, NW.y ], [ SE.x, SE.y ]]; + return [{ + coordinate, + images + }]; + } + _createMesh(image) { + if (!this._center) { + return; + } + this._layerData = this._getBufferData(image); + const buffer = new ImageBuffer({ + layerData: this._layerData + }); -// this._mesh.children[0].material.map = texture; -// this._mesh.children[0].material.needsUpdate = true; + const style = this.get('styleOptions'); + const mesh = DrawImage(buffer.attributes, style); + this.Object3D.push(mesh); + return this.Object3D; + } + _abortRequest() { + if (!this._image) { + return; + } -// this._texture = texture; -// this._ready = true; -// }, false); + this._image.src = ''; + } -// // image.addEventListener('progress', event => {}, false); -// // image.addEventListener('error', event => {}, false); + destroy() { + // Cancel any pending requests + this._abortRequest(); -// image.crossOrigin = ''; + // Clear image reference + this._image = null; -// // Load image -// image.src = url; + super.destroy(); + } -// this._image = image; -// } - -// _createMesh() { -// // Something went wrong and the tile -// // -// // Possibly removed by the cache before loaded -// if (!this._center) { -// return; -// } - -// const mesh = new THREE.Object3D(); -// const geom = new THREE.PlaneBufferGeometry(this._side, this._side, 1); - -// let material; -// if (!this._world._environment._skybox) { -// material = new THREE.MeshBasicMaterial({ -// depthWrite: false -// }); - -// // const material = new THREE.MeshPhongMaterial({ -// // depthWrite: false -// // }); -// } else { -// // Other MeshStandardMaterial settings -// // -// // material.envMapIntensity will change the amount of colour reflected(?) -// // from the environment map–can be greater than 1 for more intensity - -// material = new THREE.MeshStandardMaterial({ -// depthWrite: false -// }); -// material.roughness = 1; -// material.metalness = 0.1; -// material.envMap = this._world._environment._skybox.getRenderTarget(); -// } - -// const localMesh = new THREE.Mesh(geom, material); -// localMesh.rotation.x = -90 * Math.PI / 180; - -// localMesh.receiveShadow = true; - -// mesh.add(localMesh); -// mesh.renderOrder = 0.1; - -// mesh.position.x = this._center[0]; -// mesh.position.z = this._center[1]; - -// // const box = new BoxHelper(localMesh); -// // mesh.add(box); -// // -// // mesh.add(this._createDebugMesh()); - -// return mesh; -// } -// _abortRequest() { -// if (!this._image) { -// return; -// } - -// this._image.src = ''; -// } - -// destroy() { -// // Cancel any pending requests -// this._abortRequest(); - -// // Clear image reference -// this._image = null; - -// super.destroy(); -// } - -// } +} diff --git a/src/layer/tile/tile.js b/src/layer/tile/tile.js index 8ca5d10b48..4502a5bb70 100644 --- a/src/layer/tile/tile.js +++ b/src/layer/tile/tile.js @@ -1,59 +1,62 @@ -// const r2d = 180 / Math.PI; -// const tileURLRegex = /\{([zxy])\}/g; -// export class Tile { -// constructor(layer, z, x, y) { -// this.layer = layer; -// this._tile = [ z, x, y ]; +import * as THREE from '../../core/three'; +import { toLngLatBounds, toBounds } from '@antv/geo-coord'; +import { sphericalMercator } from '@antv/geo-coord/lib/geo/projection/spherical-mercator'; +const r2d = 180 / Math.PI; +const tileURLRegex = /\{([zxy])\}/g; -// } -// _createMesh() {} -// _createDebugMesh() {} +export class Tile { + constructor(layer, z, x, y) { + this.layer = layer; + this._tile = [ x, y, z ]; + this._tileLnglatBounds = this._tileLnglatBounds(this._tile); -// _getTileURL(urlParams) { -// if (!urlParams.s) { -// // Default to a random choice of a, b or c -// urlParams.s = String.fromCharCode(97 + Math.floor(Math.random() * 3)); -// } + this._tileBounds = this._tileBounds(this._tileLnglatBounds); -// tileURLRegex.lastIndex = 0; -// return this._path.replace(tileURLRegex, function(value, key) { -// // Replace with paramter, otherwise keep existing value -// return urlParams[key]; -// }); -// } + this._center = this._tileBounds.getCenter(); -// _tileBoundsFromWGS84(boundsWGS84) { -// const sw = this._layer._world.latLonToPoint(LatLon(boundsWGS84[1], boundsWGS84[0])); -// const ne = this._layer._world.latLonToPoint(LatLon(boundsWGS84[3], boundsWGS84[2])); + this._centerLnglat = this._tileLnglatBounds.getCenter(); + this.Object3D = new THREE.Object3D(); -// return [sw.x, sw.y, ne.x, ne.y]; -// } -// // Get tile bounds in WGS84 coordinates -// _tileBoundsWGS84(tile) { -// const e = this._tile2lon(tile[0] + 1, tile[2]); -// const w = this._tile2lon(tile[0], tile[2]); -// const s = this._tile2lat(tile[1] + 1, tile[2]); -// const n = this._tile2lat(tile[1], tile[2]); -// return [ w, s, e, n ]; -// } + } + _createMesh() {} + _getTileURL(urlParams) { + if (!urlParams.s) { + // Default to a random choice of a, b or c + urlParams.s = String.fromCharCode(97 + Math.floor(Math.random() * 3)); + } -// _tile2lon(x, z) { -// return x / Math.pow(2, z) * 360 - 180; -// } + tileURLRegex.lastIndex = 0; + return this._path.replace(tileURLRegex, function(value, key) { + return urlParams[key]; + }); + } + // 经纬度范围转瓦片范围 + _tileBounds(lnglatBound) { + const nw = sphericalMercator.project(lnglatBound.getTopLeft()); + const se = sphericalMercator.project(lnglatBound.getBottomRight()); -// _tile2lat(y, z) { -// const n = Math.PI - 2 * Math.PI * y / Math.pow(2, z); -// return r2d * Math.atan(0.5 * (Math.exp(n) - Math.exp(-n))); -// } + return toBounds(nw, se); + } -// _boundsToCenter(bounds) { -// const x = bounds[0] + (bounds[2] - bounds[0]) / 2; -// const y = bounds[1] + (bounds[3] - bounds[1]) / 2; + // Get tile bounds in WGS84 coordinates + _tileLnglatBounds(tile) { + const e = this._tile2lon(tile[0] + 1, tile[2]); + const w = this._tile2lon(tile[0], tile[2]); + const s = this._tile2lat(tile[1] + 1, tile[2]); + const n = this._tile2lat(tile[1], tile[2]); + return toLngLatBounds([ w, n ], [ e, s ]); + } -// return [ x, y ]; -// } -// destory() { + _tile2lng(x, z) { + return x / Math.pow(2, z) * 360 - 180; + } -// } -// } + _tile2lat(y, z) { + const n = Math.PI - 2 * Math.PI * y / Math.pow(2, z); + return r2d * Math.atan(0.5 * (Math.exp(n) - Math.exp(-n))); + } + destory() { + + } +} diff --git a/src/layer/tile/tile-cache.js b/src/layer/tile/tileCache.js similarity index 100% rename from src/layer/tile/tile-cache.js rename to src/layer/tile/tileCache.js diff --git a/src/layer/tile/tileLayer.js b/src/layer/tile/tileLayer.js new file mode 100644 index 0000000000..c3a6732ce1 --- /dev/null +++ b/src/layer/tile/tileLayer.js @@ -0,0 +1,8 @@ +import Layer from '../core/layer'; +export class TileLayer extends Layer { + draw() { + } + drawTile() { + + } +}