153 lines
4.3 KiB
JavaScript
153 lines
4.3 KiB
JavaScript
|
|
import * as echarts from 'echarts/lib/echarts';
|
||
|
|
import glmatrix from 'claygl/src/dep/glmatrix';
|
||
|
|
var vec3 = glmatrix.vec3;
|
||
|
|
var mat4 = glmatrix.mat4;
|
||
|
|
import textCoord from 'echarts/lib/coord/geo/fix/textCoord';
|
||
|
|
import geoCoord from 'echarts/lib/coord/geo/fix/geoCoord'; // Geo fix functions
|
||
|
|
|
||
|
|
var geoFixFuncs = [textCoord, geoCoord];
|
||
|
|
|
||
|
|
function Geo3D(name, map, geoJson, specialAreas, nameMap) {
|
||
|
|
this.name = name;
|
||
|
|
this.map = map;
|
||
|
|
this.regionHeight = 0;
|
||
|
|
this.regions = [];
|
||
|
|
this._nameCoordMap = {};
|
||
|
|
this.loadGeoJson(geoJson, specialAreas, nameMap);
|
||
|
|
this.transform = mat4.identity(new Float64Array(16));
|
||
|
|
this.invTransform = mat4.identity(new Float64Array(16)); // Which dimension to extrude. Y or Z
|
||
|
|
|
||
|
|
this.extrudeY = true;
|
||
|
|
this.altitudeAxis;
|
||
|
|
}
|
||
|
|
|
||
|
|
Geo3D.prototype = {
|
||
|
|
constructor: Geo3D,
|
||
|
|
type: 'geo3D',
|
||
|
|
dimensions: ['lng', 'lat', 'alt'],
|
||
|
|
containPoint: function () {},
|
||
|
|
loadGeoJson: function (geoJson, specialAreas, nameMap) {
|
||
|
|
var parseGeoJSON = echarts.parseGeoJSON || echarts.parseGeoJson;
|
||
|
|
|
||
|
|
try {
|
||
|
|
this.regions = geoJson ? parseGeoJSON(geoJson) : [];
|
||
|
|
} catch (e) {
|
||
|
|
throw 'Invalid geoJson format\n' + e;
|
||
|
|
}
|
||
|
|
|
||
|
|
specialAreas = specialAreas || {};
|
||
|
|
nameMap = nameMap || {};
|
||
|
|
var regions = this.regions;
|
||
|
|
var regionsMap = {};
|
||
|
|
|
||
|
|
for (var i = 0; i < regions.length; i++) {
|
||
|
|
var regionName = regions[i].name; // Try use the alias in nameMap
|
||
|
|
|
||
|
|
regionName = nameMap[regionName] || regionName;
|
||
|
|
regions[i].name = regionName;
|
||
|
|
regionsMap[regionName] = regions[i]; // Add geoJson
|
||
|
|
|
||
|
|
this.addGeoCoord(regionName, regions[i].getCenter()); // Some area like Alaska in USA map needs to be tansformed
|
||
|
|
// to look better
|
||
|
|
|
||
|
|
var specialArea = specialAreas[regionName];
|
||
|
|
|
||
|
|
if (specialArea) {
|
||
|
|
regions[i].transformTo(specialArea.left, specialArea.top, specialArea.width, specialArea.height);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
this._regionsMap = regionsMap;
|
||
|
|
this._geoRect = null;
|
||
|
|
geoFixFuncs.forEach(function (fixFunc) {
|
||
|
|
fixFunc(this);
|
||
|
|
}, this);
|
||
|
|
},
|
||
|
|
getGeoBoundingRect: function () {
|
||
|
|
if (this._geoRect) {
|
||
|
|
return this._geoRect;
|
||
|
|
}
|
||
|
|
|
||
|
|
var rect;
|
||
|
|
var regions = this.regions;
|
||
|
|
|
||
|
|
for (var i = 0; i < regions.length; i++) {
|
||
|
|
var regionRect = regions[i].getBoundingRect();
|
||
|
|
rect = rect || regionRect.clone();
|
||
|
|
rect.union(regionRect);
|
||
|
|
} // FIXME Always return new ?
|
||
|
|
|
||
|
|
|
||
|
|
return this._geoRect = rect || new echarts.graphic.BoundingRect(0, 0, 0, 0);
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Add geoCoord for indexing by name
|
||
|
|
* @param {string} name
|
||
|
|
* @param {Array.<number>} geoCoord
|
||
|
|
*/
|
||
|
|
addGeoCoord: function (name, geoCoord) {
|
||
|
|
this._nameCoordMap[name] = geoCoord;
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @param {string} name
|
||
|
|
* @return {module:echarts/coord/geo/Region}
|
||
|
|
*/
|
||
|
|
getRegion: function (name) {
|
||
|
|
return this._regionsMap[name];
|
||
|
|
},
|
||
|
|
getRegionByCoord: function (coord) {
|
||
|
|
var regions = this.regions;
|
||
|
|
|
||
|
|
for (var i = 0; i < regions.length; i++) {
|
||
|
|
if (regions[i].contain(coord)) {
|
||
|
|
return regions[i];
|
||
|
|
}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
setSize: function (width, height, depth) {
|
||
|
|
this.size = [width, height, depth];
|
||
|
|
var rect = this.getGeoBoundingRect();
|
||
|
|
var scaleX = width / rect.width;
|
||
|
|
var scaleZ = -depth / rect.height;
|
||
|
|
var translateX = -width / 2 - rect.x * scaleX;
|
||
|
|
var translateZ = depth / 2 - rect.y * scaleZ;
|
||
|
|
var position = this.extrudeY ? [translateX, 0, translateZ] : [translateX, translateZ, 0];
|
||
|
|
var scale = this.extrudeY ? [scaleX, 1, scaleZ] : [scaleX, scaleZ, 1];
|
||
|
|
var m = this.transform;
|
||
|
|
mat4.identity(m);
|
||
|
|
mat4.translate(m, m, position);
|
||
|
|
mat4.scale(m, m, scale);
|
||
|
|
mat4.invert(this.invTransform, m);
|
||
|
|
},
|
||
|
|
dataToPoint: function (data, out) {
|
||
|
|
out = out || [];
|
||
|
|
var extrudeCoordIndex = this.extrudeY ? 1 : 2;
|
||
|
|
var sideCoordIndex = this.extrudeY ? 2 : 1;
|
||
|
|
var altitudeVal = data[2]; // PENDING.
|
||
|
|
|
||
|
|
if (isNaN(altitudeVal)) {
|
||
|
|
altitudeVal = 0;
|
||
|
|
} // lng
|
||
|
|
|
||
|
|
|
||
|
|
out[0] = data[0]; // lat
|
||
|
|
|
||
|
|
out[sideCoordIndex] = data[1];
|
||
|
|
|
||
|
|
if (this.altitudeAxis) {
|
||
|
|
out[extrudeCoordIndex] = this.altitudeAxis.dataToCoord(altitudeVal);
|
||
|
|
} else {
|
||
|
|
out[extrudeCoordIndex] = 0;
|
||
|
|
} // PENDING different region height.
|
||
|
|
|
||
|
|
|
||
|
|
out[extrudeCoordIndex] += this.regionHeight;
|
||
|
|
vec3.transformMat4(out, out, this.transform);
|
||
|
|
return out;
|
||
|
|
},
|
||
|
|
pointToData: function (point, out) {// TODO
|
||
|
|
}
|
||
|
|
};
|
||
|
|
export default Geo3D;
|