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/demos/tile.html b/demos/tile.html
index f0867c42a7..b3ac0aaae2 100644
--- a/demos/tile.html
+++ b/demos/tile.html
@@ -25,50 +25,36 @@
const scene = new L7.Scene({
id: 'map',
- mapStyle: 'dark', // 样式URL
+ mapStyle: 'light', // 样式URL
center: [104.838088,34.075889 ],
pitch: 0,
- zoom: 4.5,
+ hash:true,
+ zoom: 3,
});
window.scene = scene;
scene.on('loaded', () => {
- // https://gw.alipayobjects.com/os/basement_prod/24883cde-3352-4e53-af52-f6e59d4fe2c8.json
- //tile https://gw.alipayobjects.com/os/basement_prod/c400bd4e-5b46-4769-b969-c1f09feaf908.json
- $.getJSON('https://gw.alipayobjects.com/os/basement_prod/c400bd4e-5b46-4769-b969-c1f09feaf908.json', city => {
- city.type = "FeatureCollection";
- city.features = city.features.map((item)=>{
- return {
- type: "Feature",
- properties:item.tags,
- "geometry":{
- "type": "Polygon",
- "coordinates":item.geometry
- }
- }
- })
-
- console.log(city.features[0]);
- const citylayer = scene.PolygonLayer()
+ scene.ImageTileLayer({
+ zIndex:0
+ })
+ .source('http://webst01.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}')
+ .render();
+
+ $.getJSON('https://gw.alipayobjects.com/os/rmsportal/JToMOWvicvJOISZFCkEI.json', city => {
+ const citylayer = scene.PolygonLayer(
+ {
+ zIndex:4
+ }
+ )
.source(city)
- .color('Code',["#FFF5B8","#FFDC7D","#FFAB5C","#F27049","#D42F31","#730D1C"])
+ .color('pm2_5_24h',["#FFF5B8","#FFDC7D","#FFAB5C","#F27049","#D42F31","#730D1C"])
.shape('fill')
- .active(true)
.style({
- opacity: 1
+ opacity: 1.0
})
.render();
- console.log(citylayer);
- /**
- const citylayer2 = scene.PolygonLayer()
- .source(city)
- .shape('line')
- .color('#fff')
- .style({
- opacity: 1.0
- })
- .render();
- **/
+
+
});
});
diff --git a/package.json b/package.json
index dcca835f42..43486efeb6 100755
--- a/package.json
+++ b/package.json
@@ -79,7 +79,7 @@
"prepublishOnly": "npm run build-lib && npm run dist",
"screenshot": "node ./bin/screenshot.js",
"start": "npm run dev",
- "test": "torch --compile-opts ./.torch.compile.opts.js --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",
@@ -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/layer.js b/src/core/layer.js
index 507729b617..9523aa21eb 100644
--- a/src/core/layer.js
+++ b/src/core/layer.js
@@ -679,6 +679,8 @@ export default class Layer extends Base {
} else if (this.type === 'polyline') {
offset = 2;
+ } else if (this.type === 'polygon') {
+ offset = 1;
}
this._object3D.position && (this._object3D.position.z = offset * Math.pow(2, 20 - zoom));
if (zoom < minZoom || zoom > maxZoom) {
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/material/imageMaterial.js b/src/geom/material/imageMaterial.js
index d193576d7b..ecf950f498 100644
--- a/src/geom/material/imageMaterial.js
+++ b/src/geom/material/imageMaterial.js
@@ -9,7 +9,8 @@ export default function ImageMaterial(options) {
},
vertexShader: vs,
fragmentShader: fs,
- transparent: true
+ transparent: true,
+ depthTest: false
});
return material;
}
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/index.js b/src/layer/index.js
index 02e72edceb..8b33d8534e 100644
--- a/src/layer/index.js
+++ b/src/layer/index.js
@@ -5,6 +5,8 @@ import LineLayer from './lineLayer';
import ImageLayer from './imageLayer';
import RasterLayer from './rasterLayer';
import HeatmapLayer from './heatmapLayer';
+import TileLayer from './tile/tileLayer';
+import ImageTileLayer from './tile/imageTileLayer';
registerLayer('PolygonLayer', PolygonLayer);
registerLayer('PointLayer', PointLayer);
@@ -12,6 +14,8 @@ registerLayer('LineLayer', LineLayer);
registerLayer('ImageLayer', ImageLayer);
registerLayer('RasterLayer', RasterLayer);
registerLayer('HeatmapLayer', HeatmapLayer);
+registerLayer('TileLayer', TileLayer);
+registerLayer('ImageTileLayer', ImageTileLayer);
export { LAYER_MAP } from './factory';
export { registerLayer };
diff --git a/src/layer/render/image/drawImage.js b/src/layer/render/image/drawImage.js
new file mode 100644
index 0000000000..93330df82f
--- /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) {
+ const geometry = new THREE.BufferGeometry();
+ geometry.addAttribute('position', new THREE.Float32BufferAttribute(attributes.vertices, 3));
+ 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(geometry, material);
+}
diff --git a/src/layer/render/polygon/drawFill.js b/src/layer/render/polygon/drawFill.js
index 8c5e5beb65..d9981cbdbb 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 TileMaterial from '../../../geom/material/tile/polygon';
+
export default function DrawPolygonFill(attributes, style) {
const { opacity, activeColor } = style;
const geometry = new THREE.BufferGeometry();
@@ -7,6 +9,12 @@ 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({
+ // u_opacity: opacity,
+ // u_activeColor: activeColor
+ // }, {
+ // SHAPE: false
+ // });
const material = new PolygonMaterial({
u_opacity: opacity,
u_activeColor: activeColor
diff --git a/src/layer/tile/imageTile.js b/src/layer/tile/imageTile.js
index c14a052e01..d30e336385 100644
--- a/src/layer/tile/imageTile.js
+++ b/src/layer/tile/imageTile.js
@@ -1,137 +1,82 @@
-// 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', () => {
-// image.addEventListener('load', event => {
-// const texture = new THREE.Texture();
+ this._createMesh(image);
+ this._ready = true;
+ }, false);
-// texture.image = image;
-// texture.needsUpdate = true;
+ // image.addEventListener('progress', event => {}, false);
+ // image.addEventListener('error', event => {}, false);
-// // Silky smooth images when tilted
-// texture.magFilter = THREE.LinearFilter;
-// texture.minFilter = THREE.LinearMipMapLinearFilter;
+ image.crossOrigin = '';
-// // TODO: Set this to renderer.getMaxAnisotropy() / 4
-// texture.anisotropy = 4;
+ // Load image
+ image.src = url;
-// texture.needsUpdate = true;
+ this._image = image;
+ }
+ _getBufferData(images) {
+ const NW = this._tileBounds.getTopLeft();
+ const SE = this._tileBounds.getBottomRight();
+ const coordinates = [[ NW.x, NW.y, 0 ], [ SE.x, SE.y, 0 ]];
+ return [{
+ coordinates,
+ images
+ }];
+ }
+ _createMesh(image) {
+ if (!this._center) {
+ return;
+ }
+ this._layerData = this._getBufferData(image);
+ const buffer = new ImageBuffer({
+ layerData: this._layerData
+ });
+ buffer.attributes.texture = buffer.texture;
+ const style = this.layer.get('styleOptions');
+ const mesh = DrawImage(buffer.attributes, style);
+ this.Object3D.add(mesh);
+ return this.Object3D;
+ }
+ _abortRequest() {
+ if (!this._image) {
+ return;
+ }
-// // 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.src = '';
+ }
-// this._mesh.children[0].material.map = texture;
-// this._mesh.children[0].material.needsUpdate = true;
+ destroy() {
+ // Cancel any pending requests
+ this._abortRequest();
-// this._texture = texture;
-// this._ready = true;
-// }, false);
+ // Clear image reference
+ this._image = null;
-// // image.addEventListener('progress', event => {}, false);
-// // image.addEventListener('error', event => {}, false);
+ super.destroy();
+ }
-// image.crossOrigin = '';
-
-// // Load image
-// image.src = url;
-
-// 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/imageTileLayer.js b/src/layer/tile/imageTileLayer.js
new file mode 100644
index 0000000000..5417854b73
--- /dev/null
+++ b/src/layer/tile/imageTileLayer.js
@@ -0,0 +1,8 @@
+import TileLayer from './tileLayer';
+import ImageTile from './imageTile';
+
+export default class ImageTileLayer extends TileLayer {
+ _createTile(key, layer) {
+ return new ImageTile(key, this.url, layer);
+ }
+}
diff --git a/src/layer/tile/tile-cache.js b/src/layer/tile/tile-cache.js
deleted file mode 100644
index cd42e03cd1..0000000000
--- a/src/layer/tile/tile-cache.js
+++ /dev/null
@@ -1,22 +0,0 @@
-import LRUCache from '../../util/lru-cache';
-export default class TileCache {
- constructor(limit = 50) {
- this._cache = new LRUCache(limit);
- }
-
- getTile(z, x, y) {
- const key = this._generateKey(z, x, y);
- return this._cache.get(key);
- }
-
- setTile(tile, z, x, y) {
- const key = this._generateKey(z, x, y);
- this._cache.set(key, tile);
- }
- _generateKey(z, x, y) {
- return [ z, x, y ].join('_');
- }
- destory() {
- this._cache.clear();
- }
-}
diff --git a/src/layer/tile/tile.js b/src/layer/tile/tile.js
index 8ca5d10b48..261800150c 100644
--- a/src/layer/tile/tile.js
+++ b/src/layer/tile/tile.js
@@ -1,59 +1,90 @@
-// 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';
+const r2d = 180 / Math.PI;
+const tileURLRegex = /\{([zxy])\}/g;
-// }
-// _createMesh() {}
-// _createDebugMesh() {}
+export default class Tile {
+ constructor(key, url, layer) {
+ this.layer = layer;
+ this._tile = key.split('_').map(v => v * 1);
+ this._path = url;
+ 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();
+ this.requestTileAsync();
-// 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 ne = this.layer.scene.project([ lnglatBound.getNorthWest().lng, lnglatBound.getNorthEast().lat ]);
+ const sw = this.layer.scene.project([ lnglatBound.getSouthEast().lng, lnglatBound.getSouthWest().lat ]);
+ return toBounds(sw, ne);
+ }
+ getMesh() {
+ return this.Object3D;
+ }
-// _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)));
-// }
-// _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._tile2lng(tile[0] + 1, tile[2]);
+ const w = this._tile2lng(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)));
+ }
+ destroy() {
+ if (this._object3D && this._object3D.children) {
+ let child;
+ for (let i = 0; i < this._object3D.children.length; i++) {
+ child = this._object3D.children[i];
+ if (!child) {
+ continue;
+ }
+ this.remove(child);
+ if (child.geometry) {
+ // child.geometry.dispose();
+ child.geometry = null;
+ }
+ if (child.material) {
+ if (child.material.map) {
+ child.material.map.dispose();
+ child.material.map = null;
+ }
+
+ child.material.dispose();
+ child.material = null;
+ }
+ child = null;
+ }
+ }
+ this._object3D = null;
+ }
+}
diff --git a/src/layer/tile/tileCache.js b/src/layer/tile/tileCache.js
new file mode 100644
index 0000000000..9681b739f5
--- /dev/null
+++ b/src/layer/tile/tileCache.js
@@ -0,0 +1,17 @@
+import LRUCache from '../../util/lru-cache';
+export default class TileCache {
+ constructor(limit = 50, tileDestroy) {
+ this._cache = new LRUCache(limit, tileDestroy);
+ }
+
+ getTile(key) {
+ return this._cache.get(key);
+ }
+
+ setTile(tile, key) {
+ this._cache.set(key, tile);
+ }
+ destory() {
+ this._cache.clear();
+ }
+}
diff --git a/src/layer/tile/tileLayer.js b/src/layer/tile/tileLayer.js
new file mode 100644
index 0000000000..a3bc44afc9
--- /dev/null
+++ b/src/layer/tile/tileLayer.js
@@ -0,0 +1,138 @@
+import Layer from '../../core/layer';
+import * as THREE from '../../core/three';
+import TileCache from './tileCache';
+import { throttle } from '@antv/util';
+import { toLngLat } from '@antv/geo-coord';
+import { epsg3857 } from '@antv/geo-coord/lib/geo/crs/crs-epsg3857';
+export default class TileLayer extends Layer {
+ constructor(scene, cfg) {
+ super(scene, cfg);
+ this._tileCache = new TileCache(50, this._destroyTile);
+ this._crs = epsg3857;
+ this._tiles = new THREE.Object3D();
+ this._tileKeys = [];
+ this.tileList = [];
+
+
+ }
+ source(url) {
+ this.url = url;
+ return this;
+ }
+ render() {
+ this._initMapEvent();
+ this.draw();
+ }
+ draw() {
+ this._object3D.add(this._tiles);
+ this._calculateLOD();
+ }
+ drawTile() {
+
+ }
+ zoomchange(ev) {
+ super.zoomchange(ev);
+ throttle(this._calculateLOD, 200);
+ this._calculateLOD();
+ }
+ dragend(ev) {
+ super.dragend(ev);
+ this._calculateLOD();
+
+ }
+ _calculateLOD() {
+ const viewPort = this.scene.getBounds().toBounds();
+ const SE = viewPort.getSouthEast();
+ const NW = viewPort.getNorthWest();
+ const zoom = Math.round(this.scene.getZoom()) - 1;
+ const tileCount = Math.pow(2, zoom);
+ const center = this.scene.getCenter();
+ const NWPoint = this._crs.lngLatToPoint(toLngLat(NW.lng, NW.lat), zoom);
+ const SEPoint = this._crs.lngLatToPoint(toLngLat(SE.lng, SE.lat), zoom);
+ const centerPoint = this._crs.lngLatToPoint(toLngLat(center.lng, center.lat), zoom);
+ const centerXY = centerPoint.divideBy(256).round();
+ const minXY = NWPoint.divideBy(256).round();
+ const maxXY = SEPoint.divideBy(256).round();
+ // console.log(NW.lng, NW.lat, SE.lng, SE.lat, NWPonint, SEPonint);
+ let updateTileList = [];
+ this.tileList = [];
+ const halfx = Math.floor((maxXY.x - minXY.x) / 2) + 1;
+ const halfy = Math.floor((maxXY.y - minXY.y) / 2) + 1;
+ if (!(centerPoint.x > NWPoint.x && centerPoint.x < SEPoint.x)) { // 地图循环的问题
+ for (let i = 0; i < minXY.x; i++) {
+ for (let j = Math.min(0, minXY.y - halfy); j < Math.max(maxXY.y + halfy, tileCount); j++) {
+ this._updateTileList(updateTileList, i, j, zoom);
+ }
+ }
+ for (let i = maxXY.x; i < tileCount; i++) {
+ for (let j = Math.min(0, minXY.y - halfy); j < Math.max(maxXY.y + halfy, tileCount); j++) {
+ this._updateTileList(updateTileList, i, j, zoom);
+ }
+ }
+ }
+ for (let i = Math.max(0, minXY.x - halfx); i < Math.min(maxXY.x + halfx, tileCount); i++) {
+ for (let j = Math.max(0, minXY.y - halfy); j < Math.min(maxXY.y + halfy, tileCount); j++) {
+ this._updateTileList(updateTileList, i, j, zoom);
+ }
+ }
+ // 过滤掉已经存在的
+ // tileList = tileList.filter(tile => {
+ // })
+ updateTileList = updateTileList.sort((a, b) => {
+ const tile1 = a.split('_');
+ const tile2 = b.split('_');
+ const d1 = Math.pow((tile1[0] * 1 - centerXY.x), 2) + Math.pow((tile1[1] * 1 - centerXY.y), 2);
+ const d2 = Math.pow((tile2[0] * 1 - centerXY.x), 2) + Math.pow((tile2[1] * 1 - centerXY.y), 2);
+ return d1 - d2;
+ });
+ updateTileList.forEach(key => {
+ this._requestTile(key, this);
+ });
+ this._removeOutTiles();
+ }
+ _updateTileList(updateTileList, x, y, z) {
+ const key = [ x, y, z ].join('_');
+ this.tileList.push(key);
+ if (this._tileKeys.indexOf(key) === -1) {
+ updateTileList.push(key);
+ }
+ }
+ _requestTile(key, layer) {
+ let tile = this._tileCache.getTile(key);
+ if (!tile) {
+ tile = this._createTile(key, layer);
+ const mesh = tile.getMesh();
+ mesh.name = key;
+ this._tileCache.setTile(tile, key);
+ this._tileKeys.push(key);
+ // this.scene._engine.update();
+ }
+ this._tiles.add(tile.getMesh());
+ this._tileKeys.push(key);
+ }
+ // 移除视野外的tile
+ _removeOutTiles() {
+ for (let i = this._tiles.children.length - 1; i >= 0; i--) {
+ const tile = this._tiles.children[i];
+ const key = tile.name;
+ if (this.tileList.indexOf(key) === -1) {
+ this._tiles.remove(tile);
+ }
+ this._tileKeys = [].concat(this.tileList);
+ }
+ }
+ _removeTiles() {
+ if (!this._tiles || !this._tiles.children) {
+ return;
+ }
+
+ for (let i = this._tiles.children.length - 1; i >= 0; i--) {
+ this._tiles.remove(this._tiles.children[i]);
+ }
+ }
+ _destroyTile(tile) {
+ tile.destroy();
+ }
+ desttroy() {
+ }
+}
diff --git a/src/map/AMap.js b/src/map/AMap.js
index 8ac662f838..d5bf7aae89 100644
--- a/src/map/AMap.js
+++ b/src/map/AMap.js
@@ -103,6 +103,7 @@ export default class GaodeMap extends Base {
}
mixMap(scene) {
const map = this.map;
+ scene.project = GaodeMap.project;
scene.getZoom = () => {
return map.getZoom();
};
diff --git a/src/source/parser/geojson.js b/src/source/parser/geojson.js
index 791dd2de0d..0e7d4de3f1 100644
--- a/src/source/parser/geojson.js
+++ b/src/source/parser/geojson.js
@@ -3,6 +3,10 @@ import { getCoords } from '@turf/invariant';
export default function geoJSON(data) {
const resultData = [];
+ data.features = data.features.filter(item => {
+ return item != null && item.geometry && item.geometry.type && item.geometry.coordinates && item.geometry.coordinates.length > 0;
+ });
+
// 数据为空时处理
turfMeta.flattenEach(data, (currentFeature, featureIndex) => { // 多个polygon 拆成一个
const coord = getCoords(currentFeature);
diff --git a/src/util/lru-cache.js b/src/util/lru-cache.js
index 8b417e53e2..ab7a78339b 100644
--- a/src/util/lru-cache.js
+++ b/src/util/lru-cache.js
@@ -6,9 +6,9 @@
*/
export default class LRUCache {
- constructor(limit = 5) {
+ constructor(limit = 50, destroy = () => {}) {
this.limit = limit;
-
+ this.destroy = destroy;
this.clear();
}
@@ -48,6 +48,7 @@ export default class LRUCache {
delete(key) {
const value = this._cache[key];
+ this.destroy(value);
if (value) {
this._deleteCache(key);
this._deleteOrder(key);
diff --git a/test/unit/layer/tile/tile-layer-spec.js b/test/unit/layer/tile/tile-layer-spec.js
new file mode 100644
index 0000000000..060127bb11
--- /dev/null
+++ b/test/unit/layer/tile/tile-layer-spec.js
@@ -0,0 +1,25 @@
+// import { expect } from 'chai';
+// import {Scene} from '../../../../src/core/scene';
+// import TileLayer from '../../../../src/layer/tile/tileLayer';
+
+// describe('tile layer', function() {
+
+// const amapscript = document.createElement('script');
+// amapscript.type = 'text/javascript';
+// amapscript.src = 'https://webapi.amap.com/maps?v=1.4.8&key=15cd8a57710d40c9b7c0e3cc120f1200&plugin=Map3D';
+// document.body.appendChild(amapscript);
+// const div = document.createElement('div');
+// div.id = 'map';
+// div.style.cssText = 'width:500px;height:500px;position:absolute';
+// document.body.appendChild(div);
+// const scene = new Scene({
+// id: 'map',
+// mapStyle: 'light', // 样式URL
+// center: [ 120.19382669582967, 30.258134 ],
+// pitch: 0,
+// zoom: 2,
+// maxZoom: 20,
+// minZoom: 0
+// });
+// // const TileLayer = new TileLayer(null, {});
+// });