diff --git a/src/core/controller/geom.js b/src/core/controller/geom.js deleted file mode 100644 index b0d474ac01..0000000000 --- a/src/core/controller/geom.js +++ /dev/null @@ -1,36 +0,0 @@ -import geom from '../../geom/geom'; -import { GeoBuffer, bufferGeometry, Material } from '../../geom/index'; - - -// geom shape buffer geometry material -// shape name type() -// buffer 1:n geometry -// geometry -// -export default function polygonGeom(shape, coordinates, properties, layerid) { - const polygongeom = geom.polygon; - const { buffer, geometry, material } = polygongeom[shape];// polygon 映射表 - const bufferData = new GeoBuffer[buffer]({ - coordinates, - properties, - shape - }); - bufferData.bufferStruct.name = layerid; - const bg = new bufferGeometry[geometry](bufferData.bufferStruct); - const mtl = Material[material](); - return { - geometry: bg, - mtl - }; -} - -export function pointGeom(shape, bufferData) { - const pointgeom = geom.point; - const { geometry, material } = pointgeom[shape]; - const bg = new bufferGeometry[geometry](bufferData.bufferStruct); - const mtl = Material[material](); - return { - geometry: bg, - mtl - }; -} diff --git a/src/core/controller/map.js b/src/core/controller/map.js new file mode 100644 index 0000000000..3068e61cfe --- /dev/null +++ b/src/core/controller/map.js @@ -0,0 +1,24 @@ + +import { getMap } from '../../map'; +import Base from '../base'; +export default class MapContorller extends Base { + constructor(cfg, engine, scene) { + super(cfg); + this._engine = engine; + this.scene = scene; + } + _init() { + const mapType = this.get('mapType'); + const mapCfg = this.get('mapCfg'); + this.map = new getMap(mapType)(mapCfg); + this.map('mapLoad', this._mapload.bind(this)); + } + _mapload() { + this.map.asyncCamera(this._engine); + this.emit('loaded'); + } + _bindMapMethod() { + + } + +} diff --git a/src/core/engine/index.js b/src/core/engine/index.js index d3a8eee42b..a12f2e06f6 100644 --- a/src/core/engine/index.js +++ b/src/core/engine/index.js @@ -11,6 +11,9 @@ export default class Engine extends EventEmitter { this._camera = new Camera(container).camera; this._renderer = new Renderer(container).renderer; this._world = world; + // for MapBox + this.world = new THREE.Group(); + this._scene.add(this.world); this._picking = Picking(this._world, this._renderer, this._camera, this._scene); this.clock = new THREE.Clock(); } diff --git a/src/core/layer.js b/src/core/layer.js index 50f2858587..4517ef695b 100644 --- a/src/core/layer.js +++ b/src/core/layer.js @@ -63,7 +63,8 @@ export default class Layer extends Base { const layerId = this._getUniqueId(); this.layerId = layerId; this._activeIds = null; - scene._engine._scene.add(this._object3D); + const world = scene._engine.world; + world.add(this._object3D); this.layerMesh = null; this.layerLineMesh = null; this._initEvents(); @@ -110,7 +111,6 @@ export default class Layer extends Base { const { type = dataType } = cfg; cfg.data = data; cfg.mapType = this.get('mapType'); - this.layerSource = new source[type](cfg); // this.scene.workerPool.runTask({ // command: 'geojson', diff --git a/src/core/scene.js b/src/core/scene.js index 8879215fe2..115db9fdcd 100644 --- a/src/core/scene.js +++ b/src/core/scene.js @@ -3,8 +3,8 @@ import * as layers from '../layer'; import Base from './base'; import LoadImage from './image'; import WorkerPool from './worker'; -import { MapProvider } from '../map/provider'; -import GaodeMap from '../map/gaodeMap'; +// import { MapProvider } from '../map/AMap'; +import { getMap } from '../map/index'; import Global from '../global'; export default class Scene extends Base { getDefaultCfg() { @@ -13,7 +13,7 @@ export default class Scene extends Base { constructor(cfg) { super(cfg); this._initMap(); - this._initAttribution(); + // this._initAttribution(); this.addImage(); this._layers = []; } @@ -29,16 +29,14 @@ export default class Scene extends Base { } _initMap() { this.mapContainer = this.get('id'); - this._container = document.getElementById(this.mapContainer); - const Map = new MapProvider(this.mapContainer, this._attrs); + this.mapType = this.get('mapType'); + const MapProvider = getMap(this.mapType); + const Map = new MapProvider(this._attrs); + Map.mixMap(this); + this._container = document.getElementById(Map.container); + // const Map = new MapProvider(this.mapContainer, this._attrs); Map.on('mapLoad', () => { this._initEngine(Map.renderDom); - const sceneMap = new GaodeMap(Map.map); - // eslint-disable-next-line - Object.getOwnPropertyNames(sceneMap.__proto__).forEach((key)=>{ - // eslint-disable-next-line - if ('key' !== 'constructor') { this.__proto__[key] = sceneMap.__proto__[key]; } - }); this.map = Map.map; Map.asyncCamera(this._engine); this.initLayer(); diff --git a/src/core/source.js b/src/core/source.js index 3a61aead88..7b7cad5d10 100644 --- a/src/core/source.js +++ b/src/core/source.js @@ -1,12 +1,6 @@ -/* - * @Author: ThinkGIS - * @Date: 2018-06-08 11:19:06 - * @Last Modified by: mikey.zhaopeng - * @Last Modified time: 2018-11-01 11:50:43 - */ import Base from './base'; const Controller = require('./controller/index'); -import { aProjectFlat } from '../geo/project'; +import { getMap } from '../map/index'; export default class Source extends Base { getDefaultCfg() { return { @@ -50,6 +44,8 @@ export default class Source extends Base { } _initControllers() { const defs = this.get('defs'); + const mapType = this.get('mapType'); + this.projectFlat = getMap(mapType).project; const scaleController = new Controller.Scale({ defs }); @@ -83,8 +79,8 @@ export default class Source extends Base { } _coorConvert(geo) { - const ll = aProjectFlat(geo); - return [ ll.x, -ll.y, geo[2] || 0 ]; + const ll = this.projectFlat(geo); + return [ ll.x, ll.y, geo[2] || 0 ]; } diff --git a/src/core/three.js b/src/core/three.js index 75cbe58b5d..03359e840d 100644 --- a/src/core/three.js +++ b/src/core/three.js @@ -4,6 +4,7 @@ export { Scene } from 'three/src/scenes/Scene.js'; export { WebGLRenderer } from 'three/src/renderers/WebGLRenderer.js'; export { CanvasTexture } from 'three/src/textures/CanvasTexture.js'; export { Object3D } from 'three/src/core/Object3D.js'; +export { Group } from 'three/src/objects/Group'; export { Clock } from 'three/src/core/Clock'; export { Points } from 'three/src/objects/Points.js'; export { LineSegments } from 'three/src/objects/LineSegments.js'; diff --git a/src/map/provider.js b/src/map/AMap.js similarity index 57% rename from src/map/provider.js rename to src/map/AMap.js index 19763e8f45..e54615b94a 100644 --- a/src/map/provider.js +++ b/src/map/AMap.js @@ -1,18 +1,34 @@ import Base from '../core/base'; +import { scene } from '../global'; import * as Theme from '../theme/index'; import Util from '../util'; -import { scene } from '../global'; const DEG2RAD = Math.PI / 180; -export class MapProvider extends Base { +export default class GaodeMap extends Base { getDefaultCfg() { return Util.assign(scene, { resizeEnable: true, viewMode: '3D' }); } - constructor(container, cfg) { + static project(lnglat) { + const maxs = 85.0511287798; + const lat = Math.max(Math.min(maxs, lnglat[1]), -maxs); + const scale = 256 << 20; + let d = Math.PI / 180; + let x = lnglat[0] * d; + let y = lat * d; + y = Math.log(Math.tan((Math.PI / 4) + (y / 2))); + const a = 0.5 / Math.PI, + b = 0.5, + c = -0.5 / Math.PI; + d = 0.5; + x = scale * (a * x + b) - 215440491; + y = -(scale * (c * y + d) - 106744817); + return { x, y }; + } + constructor(cfg) { super(cfg); - this.container = container; + this.container = this.get('id'); this.initMap(); this.addOverLayer(); setTimeout(() => { @@ -85,4 +101,31 @@ export class MapProvider extends Base { this.renderDom.id = 'l7_canvaslayer'; canvasContainer.appendChild(this.renderDom); } + mixMap(scene) { + const map = this.map; + scene.getZoom = () => { return map.getZoom(); }; + scene.getCenter = () => { return map.getCenter(); }; + scene.getSize = () => { return map.getSize(); }; + scene.getPitch = () => { return map.getPitch(); }; + scene.getRotation = () => { return map.getRotation(); }; + scene.getStatus = () => { return map.getStatus(); }; + scene.getScale = () => { return map.getScale(); }; + scene.getZoom = () => { return map.getZoom(); }; + scene.setZoom = () => { return map.setZoom(); }; + scene.setBounds = () => { return map.setBounds(); }; + scene.setRotation = () => { return map.setRotation(); }; + scene.zoomIn = () => { return map.zoomIn(); }; + scene.setRotation = () => { return map.setRotation(); }; + scene.zoomOut = () => { return map.zoomOut(); }; + scene.panTo = () => { return map.panTo(); }; + scene.panBy = () => { return map.panBy(); }; + scene.setPitch = () => { return map.setPitch(); }; + scene.pixelToLngLat = () => { return map.pixelToLngLat(); }; + scene.lngLatToPixel = () => { return map.lngLatToPixel(); }; + scene.setMapStyle = () => { return map.setMapStyle(); }; + scene.containerToLngLat = pixel => { + const ll = new AMap.Pixel(pixel.x, pixel.y); + return map.containerToLngLat(ll); + }; + } } diff --git a/src/map/gaodeMap.js b/src/map/gaodeMap.js index 70f9dd8829..07301a8d3b 100644 --- a/src/map/gaodeMap.js +++ b/src/map/gaodeMap.js @@ -21,7 +21,7 @@ export default class GaodeMap { return this.map.getStatus(); } getScale() { - return this.getScale(); + return this.map.getScale(); } setZoom(zoom) { return this.map.setZoom(zoom); diff --git a/src/map/index.js b/src/map/index.js new file mode 100644 index 0000000000..ae5b7dbb7d --- /dev/null +++ b/src/map/index.js @@ -0,0 +1,22 @@ +import MapBox from './mapbox'; +import { default as AMap } from './AMap'; +export { + AMap, + MapBox +}; +const MapType = { + amap: AMap, + mapbox: MapBox +}; +export const getMap = type => { + return MapType[type.toLowerCase()]; +}; + +export const registerMap = (type, map) => { + if (getMap(type)) { + throw new Error(`Map type '${type}' existed.`); + } + map.type = type; + // 存储到 map 中 + MapType[type.toLowerCase()] = map; +}; diff --git a/src/map/mapbox.js b/src/map/mapbox.js index 3512c51150..b95fec04a1 100644 --- a/src/map/mapbox.js +++ b/src/map/mapbox.js @@ -3,22 +3,27 @@ import Util from '../util'; import { scene } from '../global'; import * as THREE from '../core/three'; const WORLD_SIZE = 512; -export class MapBoxProvider extends Base { +const MERCATOR_A = 6378137.0; +const WORLD_SCALE = 1.0; +const PROJECTION_WORLD_SIZE = WORLD_SIZE / (MERCATOR_A * Math.PI) / 2; +export default class MapBox extends Base { getDefaultCfg() { return Util.assign(scene, { resizeEnable: true, viewMode: '3D' }); } - constructor(container, cfg, engine) { + static project(lnglat) { + const d = Math.PI / 180; + const x = -MERCATOR_A * lnglat[0] * d * PROJECTION_WORLD_SIZE; + const y = -MERCATOR_A * Math.log(Math.tan((Math.PI * 0.25) + (0.5 * lnglat[1] * d))) * PROJECTION_WORLD_SIZE; + return { x, y }; + } + constructor(cfg) { super(cfg); - this.container = container; - this.engine = engine; - const scene = engine._scene; + this.container = this.get('container'); this.initMap(); this.addOverLayer(); - scene.position.x = scene.position.y = WORLD_SIZE / 2; - scene.matrixAutoUpdate = false; setTimeout(() => { this.emit('mapLoad'); }, 100); @@ -28,15 +33,24 @@ export class MapBoxProvider extends Base { initMap() { mapboxgl.accessToken = 'pk.eyJ1IjoibHp4dWUiLCJhIjoiYnhfTURyRSJ9.Ugm314vAKPHBzcPmY1p4KQ'; this.map = new mapboxgl.Map(this._attrs); + } + asyncCamera(engine) { + this.engine = engine; + const camera = engine._camera; + const scene = engine.world; + camera.matrixAutoUpdate = false; + scene.position.x = scene.position.y = WORLD_SIZE / 2; + scene.matrixAutoUpdate = false; + scene.autoUpdate = false; + this.updateCamera(); this.map.on('move', () => { this.updateCamera(); }); - this.updateCamera(); } - asyncCamera() { + updateCamera() { const engine = this.engine; + const scene = engine.world; const camera = engine._camera; - const scene = engine._scene; // Build a projection matrix, paralleling the code found in Mapbox GL JS const fov = 0.6435011087932844; const cameraToCenterDistance = 0.5 / Math.tan(fov / 2) * this.map.transform.height; @@ -49,25 +63,22 @@ export class MapBoxProvider extends Base { // Add a bit extra to avoid precision problems when a fragment's distance is exactly `furthestDistance` const farZ = furthestDistance * 1.01; - + const { x, y } = this.map.transform.point; camera.projectionMatrix = this.makePerspectiveMatrix(fov, this.map.transform.width / this.map.transform.height, 1, farZ); - - const cameraWorldMatrix = new THREE.Matrix4(); const cameraTranslateZ = new THREE.Matrix4().makeTranslation(0, 0, cameraToCenterDistance); const cameraRotateX = new THREE.Matrix4().makeRotationX(this.map.transform._pitch); const cameraRotateZ = new THREE.Matrix4().makeRotationZ(this.map.transform.angle); + // const cameraTranslateCenter = new THREE.Matrix4().makeTranslation(0, 0, cameraToCenterDistance); // Unlike the Mapbox GL JS camera, separate camera translation and rotation out into its world matrix // If this is applied directly to the projection matrix, it will work OK but break raycasting cameraWorldMatrix .premultiply(cameraTranslateZ) .premultiply(cameraRotateX) .premultiply(cameraRotateZ); - camera.matrixWorld.copy(cameraWorldMatrix); - const zoomPow = this.map.transform.scale; // Handle scaling and translation of objects in the map in the world's matrix transform, not the camera const scale = new THREE.Matrix4(); @@ -82,7 +93,6 @@ export class MapBoxProvider extends Base { .makeTranslation(-this.map.transform.x, this.map.transform.y, 0); rotateMap .makeRotationZ(Math.PI); - scene.matrix = new THREE.Matrix4(); scene.matrix .premultiply(rotateMap) @@ -117,8 +127,15 @@ export class MapBoxProvider extends Base { const canvasContainer = document.getElementById(this.container); this.canvasContainer = canvasContainer; this.renderDom = document.createElement('div'); - this.renderDom.style.cssText += 'position: absolute;top: 0; z-index:1;height: 100%;width: 100%;pointer-events: none;'; + this.renderDom.style.cssText += 'position: absolute;top: 0; z-index:10;height: 100%;width: 100%;pointer-events: none;'; this.renderDom.id = 'l7_canvaslayer'; canvasContainer.appendChild(this.renderDom); } + mixMap(scene) { + const map = this.map; + scene.getZoom = () => { return map.getZoom(); }; + scene.getCenter = () => { return map.getCenter(); }; + scene.getPitch = () => { return map.getPitch(); }; + + } }