2016-03-09 16:32:48 +00:00
|
|
|
// TODO: Consider adopting GeoJSON CSS
|
|
|
|
// http://wiki.openstreetmap.org/wiki/Geojson_CSS
|
|
|
|
|
2016-03-14 21:46:47 +00:00
|
|
|
// TODO: Allow interaction to be defined per-layer to save on resources
|
|
|
|
//
|
|
|
|
// For example, only allow polygons to be interactive via a polygonInteractive
|
|
|
|
// option
|
|
|
|
|
2016-03-08 15:38:11 +00:00
|
|
|
import LayerGroup from './LayerGroup';
|
2016-02-28 20:29:52 +00:00
|
|
|
import extend from 'lodash.assign';
|
2016-03-08 15:38:11 +00:00
|
|
|
import reqwest from 'reqwest';
|
2016-02-28 20:29:52 +00:00
|
|
|
import GeoJSON from '../util/GeoJSON';
|
|
|
|
import Buffer from '../util/Buffer';
|
2016-02-29 23:04:07 +00:00
|
|
|
import PickingMaterial from '../engine/PickingMaterial';
|
2016-03-08 15:38:11 +00:00
|
|
|
import PolygonLayer from './geometry/PolygonLayer';
|
|
|
|
import PolylineLayer from './geometry/PolylineLayer';
|
2016-03-09 12:26:41 +00:00
|
|
|
import PointLayer from './geometry/PointLayer';
|
2016-02-28 20:29:52 +00:00
|
|
|
|
2016-03-08 15:38:11 +00:00
|
|
|
class GeoJSONLayer extends LayerGroup {
|
2016-02-28 20:29:52 +00:00
|
|
|
constructor(geojson, options) {
|
|
|
|
var defaults = {
|
2016-03-08 15:38:11 +00:00
|
|
|
output: false,
|
|
|
|
interactive: false,
|
2016-02-28 20:29:52 +00:00
|
|
|
topojson: false,
|
|
|
|
filter: null,
|
2016-03-08 15:38:11 +00:00
|
|
|
onEachFeature: null,
|
2016-03-11 09:07:03 +00:00
|
|
|
polygonMaterial: null,
|
|
|
|
onPolygonMesh: null,
|
|
|
|
onPolygonBufferAttributes: null,
|
|
|
|
polylineMaterial: null,
|
|
|
|
onPolylineMesh: null,
|
|
|
|
onPolylineBufferAttributes: null,
|
2016-03-09 16:15:38 +00:00
|
|
|
pointGeometry: null,
|
2016-03-11 09:07:03 +00:00
|
|
|
pointMaterial: null,
|
|
|
|
onPointMesh: null,
|
2016-03-14 21:46:47 +00:00
|
|
|
style: GeoJSON.defaultStyle,
|
|
|
|
keepFeatures: true
|
2016-02-28 20:29:52 +00:00
|
|
|
};
|
|
|
|
|
2016-03-07 19:25:11 +00:00
|
|
|
var _options = extend({}, defaults, options);
|
|
|
|
|
2016-02-28 20:29:52 +00:00
|
|
|
if (typeof options.style === 'function') {
|
2016-03-08 15:38:11 +00:00
|
|
|
_options.style = options.style;
|
2016-02-28 20:29:52 +00:00
|
|
|
} else {
|
2016-03-08 15:38:11 +00:00
|
|
|
_options.style = extend({}, defaults.style, options.style);
|
2016-02-28 20:29:52 +00:00
|
|
|
}
|
2016-02-29 23:04:07 +00:00
|
|
|
|
2016-03-08 15:38:11 +00:00
|
|
|
super(_options);
|
2016-03-07 19:25:11 +00:00
|
|
|
|
|
|
|
this._geojson = geojson;
|
2016-02-28 20:29:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
_onAdd(world) {
|
2016-03-08 15:38:11 +00:00
|
|
|
// Only add to picking mesh if this layer is controlling output
|
|
|
|
//
|
|
|
|
// Otherwise, assume another component will eventually add a mesh to
|
|
|
|
// the picking scene
|
|
|
|
if (this.isOutput()) {
|
|
|
|
this._pickingMesh = new THREE.Object3D();
|
|
|
|
this.addToPicking(this._pickingMesh);
|
|
|
|
}
|
2016-02-29 23:04:07 +00:00
|
|
|
|
2016-02-28 20:29:52 +00:00
|
|
|
// Request data from URL if needed
|
|
|
|
if (typeof this._geojson === 'string') {
|
2016-08-30 15:46:04 +00:00
|
|
|
return this._requestData(this._geojson);
|
2016-02-28 20:29:52 +00:00
|
|
|
} else {
|
|
|
|
// Process and add GeoJSON to layer
|
2016-08-30 15:46:04 +00:00
|
|
|
return this._processData(this._geojson);
|
2016-02-28 20:29:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
_requestData(url) {
|
2016-08-30 15:46:04 +00:00
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
this._request = reqwest({
|
|
|
|
url: url,
|
|
|
|
type: 'json',
|
|
|
|
crossOrigin: true
|
|
|
|
}).then(res => {
|
|
|
|
// Clear request reference
|
|
|
|
this._request = null;
|
|
|
|
this._processData(res).then(() => {
|
|
|
|
resolve(this);
|
|
|
|
});
|
|
|
|
}).catch(err => {
|
|
|
|
console.error(err);
|
|
|
|
|
|
|
|
// Clear request reference
|
|
|
|
this._request = null;
|
2016-09-01 16:09:40 +00:00
|
|
|
|
|
|
|
reject(err);
|
2016-08-30 15:46:04 +00:00
|
|
|
});
|
2016-02-28 20:29:52 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2016-03-08 15:38:11 +00:00
|
|
|
// TODO: Wrap into a helper method so this isn't duplicated in the tiled
|
|
|
|
// GeoJSON output layer
|
|
|
|
//
|
|
|
|
// Need to be careful as to not make it impossible to fork this off into a
|
|
|
|
// worker script at a later stage
|
2016-02-28 20:29:52 +00:00
|
|
|
_processData(data) {
|
2016-09-08 13:02:55 +00:00
|
|
|
return new Promise((resolve) => {
|
|
|
|
// Collects features into a single FeatureCollection
|
|
|
|
//
|
|
|
|
// Also converts TopoJSON to GeoJSON if instructed
|
|
|
|
this._geojson = GeoJSON.collectFeatures(data, this._options.topojson);
|
2016-02-28 20:29:52 +00:00
|
|
|
|
2016-09-08 13:02:55 +00:00
|
|
|
// TODO: Check that GeoJSON is valid / usable
|
2016-02-28 20:29:52 +00:00
|
|
|
|
2016-09-08 13:02:55 +00:00
|
|
|
var features = this._geojson.features;
|
2016-02-28 20:29:52 +00:00
|
|
|
|
2016-09-08 13:02:55 +00:00
|
|
|
// Run filter, if provided
|
|
|
|
if (this._options.filter) {
|
|
|
|
features = this._geojson.features.filter(this._options.filter);
|
|
|
|
}
|
2016-02-28 20:29:52 +00:00
|
|
|
|
2016-09-08 13:02:55 +00:00
|
|
|
var defaults = {};
|
2016-02-28 20:29:52 +00:00
|
|
|
|
2016-09-08 13:02:55 +00:00
|
|
|
// Assume that a style won't be set per feature
|
|
|
|
var style = this._options.style;
|
2016-02-28 20:29:52 +00:00
|
|
|
|
2016-09-08 13:02:55 +00:00
|
|
|
var layerPromises = [];
|
2016-02-29 23:04:07 +00:00
|
|
|
|
2016-09-08 13:02:55 +00:00
|
|
|
var options;
|
|
|
|
features.forEach(feature => {
|
|
|
|
// Get per-feature style object, if provided
|
|
|
|
if (typeof this._options.style === 'function') {
|
|
|
|
style = extend({}, GeoJSON.defaultStyle, this._options.style(feature));
|
|
|
|
}
|
2016-02-29 23:04:07 +00:00
|
|
|
|
2016-09-08 13:02:55 +00:00
|
|
|
options = extend({}, defaults, {
|
|
|
|
// If merging feature layers, stop them outputting themselves
|
|
|
|
// If not, let feature layers output themselves to the world
|
|
|
|
output: !this.isOutput(),
|
|
|
|
interactive: this._options.interactive,
|
|
|
|
style: style
|
|
|
|
});
|
2016-02-28 20:29:52 +00:00
|
|
|
|
2016-09-08 13:02:55 +00:00
|
|
|
var layer = this._featureToLayer(feature, options);
|
2016-02-28 20:29:52 +00:00
|
|
|
|
2016-09-08 13:02:55 +00:00
|
|
|
if (!layer) {
|
|
|
|
return;
|
|
|
|
}
|
2016-02-28 20:29:52 +00:00
|
|
|
|
2016-09-08 13:02:55 +00:00
|
|
|
// Sometimes you don't want to store a reference to the feature
|
|
|
|
//
|
|
|
|
// For example, to save memory when being used by tile layers
|
|
|
|
if (this._options.keepFeatures) {
|
|
|
|
layer.feature = feature;
|
|
|
|
}
|
2016-02-28 20:29:52 +00:00
|
|
|
|
2016-09-08 13:02:55 +00:00
|
|
|
// If defined, call a function for each feature
|
|
|
|
//
|
|
|
|
// This is commonly used for adding event listeners from the user script
|
|
|
|
if (this._options.onEachFeature) {
|
|
|
|
this._options.onEachFeature(feature, layer);
|
|
|
|
}
|
2016-02-28 20:29:52 +00:00
|
|
|
|
2016-09-08 13:02:55 +00:00
|
|
|
// TODO: Make this a promise array and only continue on completion
|
|
|
|
layerPromises.push(this.addLayer(layer));
|
|
|
|
});
|
2016-02-28 20:29:52 +00:00
|
|
|
|
2016-09-08 13:02:55 +00:00
|
|
|
Promise.all(layerPromises).then((results) => {
|
|
|
|
// If merging layers do that now, otherwise skip as the geometry layers
|
|
|
|
// should have already outputted themselves
|
|
|
|
if (!this.isOutput()) {
|
|
|
|
resolve();
|
|
|
|
return;
|
|
|
|
}
|
2016-02-29 23:04:07 +00:00
|
|
|
|
2016-09-08 13:02:55 +00:00
|
|
|
// From here on we can assume that we want to merge the layers
|
|
|
|
|
|
|
|
var polygonAttributes = [];
|
|
|
|
var polygonAttributeLengths = {
|
|
|
|
positions: 3,
|
|
|
|
normals: 3,
|
|
|
|
colors: 3
|
|
|
|
};
|
|
|
|
var polygonFlat = true;
|
|
|
|
|
|
|
|
var polylineAttributes = [];
|
2016-09-08 15:32:26 +00:00
|
|
|
var polylineAttributeLengths = {
|
|
|
|
positions: 3,
|
|
|
|
colors: 3
|
|
|
|
};
|
|
|
|
var polylineFlat = true;
|
|
|
|
|
2016-09-08 13:02:55 +00:00
|
|
|
var pointAttributes = [];
|
|
|
|
|
|
|
|
this._layers.forEach(layer => {
|
|
|
|
if (layer instanceof PolygonLayer) {
|
|
|
|
polygonAttributes.push(layer.getBufferAttributes());
|
|
|
|
|
|
|
|
if (polygonFlat && !layer.isFlat()) {
|
|
|
|
polygonFlat = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this._options.interactive) {
|
|
|
|
polygonAttributeLengths.pickingIds = 1;
|
|
|
|
}
|
|
|
|
} else if (layer instanceof PolylineLayer) {
|
|
|
|
polylineAttributes.push(layer.getBufferAttributes());
|
2016-09-08 15:32:26 +00:00
|
|
|
|
|
|
|
if (polylineFlat && !layer.isFlat()) {
|
|
|
|
polylineFlat = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this._options.interactive) {
|
|
|
|
polylineAttributeLengths.pickingIds = 1;
|
|
|
|
}
|
2016-09-08 13:02:55 +00:00
|
|
|
} else if (layer instanceof PointLayer) {
|
|
|
|
pointAttributes.push(layer.getBufferAttributes());
|
|
|
|
}
|
|
|
|
});
|
2016-02-29 23:04:07 +00:00
|
|
|
|
2016-09-08 13:02:55 +00:00
|
|
|
if (polygonAttributes.length > 0) {
|
|
|
|
var mergedPolygonAttributes = Buffer.mergeAttributes(polygonAttributes);
|
|
|
|
this._setPolygonMesh(mergedPolygonAttributes, polygonAttributeLengths, polygonFlat).then((result) => {
|
|
|
|
this._polygonMesh = result.mesh;
|
|
|
|
this.add(this._polygonMesh);
|
2016-02-29 23:04:07 +00:00
|
|
|
|
2016-09-08 13:02:55 +00:00
|
|
|
if (result.pickingMesh) {
|
|
|
|
this._pickingMesh.add(pickingMesh);
|
|
|
|
}
|
|
|
|
});
|
2016-02-29 23:04:07 +00:00
|
|
|
}
|
2016-02-28 20:29:52 +00:00
|
|
|
|
2016-09-08 13:02:55 +00:00
|
|
|
if (polylineAttributes.length > 0) {
|
|
|
|
var mergedPolylineAttributes = Buffer.mergeAttributes(polylineAttributes);
|
2016-09-08 15:32:26 +00:00
|
|
|
this._setPolylineMesh(mergedPolylineAttributes, polylineAttributeLengths, polylineFlat).then((result) => {
|
|
|
|
this._polylineMesh = result.mesh;
|
|
|
|
this.add(this._polylineMesh);
|
|
|
|
|
|
|
|
if (result.pickingMesh) {
|
|
|
|
this._pickingMesh.add(pickingMesh);
|
|
|
|
}
|
|
|
|
});
|
2016-09-08 13:02:55 +00:00
|
|
|
}
|
2016-02-28 20:29:52 +00:00
|
|
|
|
2016-09-08 13:02:55 +00:00
|
|
|
if (pointAttributes.length > 0) {
|
|
|
|
var mergedPointAttributes = Buffer.mergeAttributes(pointAttributes);
|
|
|
|
this._setPointMesh(mergedPointAttributes);
|
|
|
|
this.add(this._pointMesh);
|
|
|
|
}
|
2016-02-28 20:29:52 +00:00
|
|
|
|
2016-09-08 13:02:55 +00:00
|
|
|
// Clean up layers
|
|
|
|
//
|
|
|
|
// TODO: Are there ever situations where the unmerged buffer attributes
|
|
|
|
// and coordinates would still be required?
|
|
|
|
this._layers.forEach(layer => {
|
|
|
|
layer.clearBufferAttributes();
|
|
|
|
layer.clearCoordinates();
|
|
|
|
});
|
2016-03-14 21:46:47 +00:00
|
|
|
|
2016-09-08 13:02:55 +00:00
|
|
|
resolve();
|
|
|
|
});
|
2016-03-14 21:46:47 +00:00
|
|
|
});
|
2016-03-08 15:38:11 +00:00
|
|
|
}
|
2016-02-28 20:29:52 +00:00
|
|
|
|
2016-03-08 15:38:11 +00:00
|
|
|
// Create and store mesh from buffer attributes
|
|
|
|
//
|
2016-09-08 13:02:55 +00:00
|
|
|
// TODO: Probably remove this and call static method directly as it's just a proxy
|
|
|
|
_setPolygonMesh(attributes, attributeLengths, flat) {
|
2016-03-13 13:47:45 +00:00
|
|
|
// TODO: Make this work when style is a function per feature
|
|
|
|
var style = (typeof this._options.style === 'function') ? this._options.style(this._geojson.features[0]) : this._options.style;
|
|
|
|
style = extend({}, GeoJSON.defaultStyle, style);
|
|
|
|
|
2016-09-08 13:02:55 +00:00
|
|
|
return PolygonLayer.SetMesh(attributes, attributeLengths, flat, style, this._options, this._world._environment._skybox);
|
2016-03-08 15:38:11 +00:00
|
|
|
}
|
2016-02-28 20:29:52 +00:00
|
|
|
|
2016-09-08 15:32:26 +00:00
|
|
|
_setPolylineMesh(attributes, attributeLengths, flat) {
|
|
|
|
// TODO: Make this work when style is a function per feature
|
|
|
|
var style = (typeof this._options.style === 'function') ? this._options.style(this._geojson.features[0]) : this._options.style;
|
|
|
|
style = extend({}, GeoJSON.defaultStyle, style);
|
2016-02-28 20:29:52 +00:00
|
|
|
|
2016-09-08 15:32:26 +00:00
|
|
|
return PolylineLayer.SetMesh(attributes, attributeLengths, flat, style, this._options);
|
2016-03-11 20:22:15 +00:00
|
|
|
|
2016-09-08 15:32:26 +00:00
|
|
|
// var geometry = new THREE.BufferGeometry();
|
2016-03-11 20:22:15 +00:00
|
|
|
|
2016-09-08 15:32:26 +00:00
|
|
|
// // itemSize = 3 because there are 3 values (components) per vertex
|
|
|
|
// geometry.addAttribute('position', new THREE.BufferAttribute(attributes.vertices, 3));
|
2016-02-28 20:29:52 +00:00
|
|
|
|
2016-09-08 15:32:26 +00:00
|
|
|
// if (attributes.normals) {
|
|
|
|
// geometry.addAttribute('normal', new THREE.BufferAttribute(attributes.normals, 3));
|
|
|
|
// }
|
2016-02-28 20:29:52 +00:00
|
|
|
|
2016-09-08 15:32:26 +00:00
|
|
|
// geometry.addAttribute('color', new THREE.BufferAttribute(attributes.colours, 3));
|
2016-02-29 23:04:07 +00:00
|
|
|
|
2016-09-08 15:32:26 +00:00
|
|
|
// if (attributes.pickingIds) {
|
|
|
|
// geometry.addAttribute('pickingId', new THREE.BufferAttribute(attributes.pickingIds, 1));
|
|
|
|
// }
|
2016-03-09 12:26:41 +00:00
|
|
|
|
2016-09-08 15:32:26 +00:00
|
|
|
// geometry.computeBoundingBox();
|
2016-02-29 23:04:07 +00:00
|
|
|
|
2016-09-08 15:32:26 +00:00
|
|
|
// // TODO: Make this work when style is a function per feature
|
|
|
|
// var style = (typeof this._options.style === 'function') ? this._options.style(this._geojson.features[0]) : this._options.style;
|
|
|
|
// style = extend({}, GeoJSON.defaultStyle, style);
|
2016-02-29 23:04:07 +00:00
|
|
|
|
2016-09-08 15:32:26 +00:00
|
|
|
// var material;
|
|
|
|
// if (this._options.polylineMaterial && this._options.polylineMaterial instanceof THREE.Material) {
|
|
|
|
// material = this._options.polylineMaterial;
|
|
|
|
// } else {
|
|
|
|
// material = new THREE.LineBasicMaterial({
|
|
|
|
// vertexColors: THREE.VertexColors,
|
|
|
|
// linewidth: style.lineWidth,
|
|
|
|
// transparent: style.lineTransparent,
|
|
|
|
// opacity: style.lineOpacity,
|
|
|
|
// blending: style.lineBlending
|
|
|
|
// });
|
|
|
|
// }
|
2016-02-28 20:29:52 +00:00
|
|
|
|
2016-09-08 15:32:26 +00:00
|
|
|
// var mesh;
|
2016-03-11 20:22:15 +00:00
|
|
|
|
2016-09-08 15:32:26 +00:00
|
|
|
// // Pass mesh through callback, if defined
|
|
|
|
// if (typeof this._options.onPolylineMesh === 'function') {
|
|
|
|
// mesh = this._options.onPolylineMesh(geometry, material);
|
|
|
|
// } else {
|
|
|
|
// mesh = new THREE.LineSegments(geometry, material);
|
2016-02-28 20:29:52 +00:00
|
|
|
|
2016-09-08 15:32:26 +00:00
|
|
|
// if (style.lineRenderOrder !== undefined) {
|
|
|
|
// material.depthWrite = false;
|
|
|
|
// mesh.renderOrder = style.lineRenderOrder;
|
|
|
|
// }
|
2016-02-28 20:29:52 +00:00
|
|
|
|
2016-09-08 15:32:26 +00:00
|
|
|
// mesh.castShadow = true;
|
|
|
|
// // mesh.receiveShadow = true;
|
|
|
|
// }
|
2016-02-28 20:29:52 +00:00
|
|
|
|
2016-09-08 15:32:26 +00:00
|
|
|
// // TODO: Allow this to be overridden, or copy mesh instead of creating a new
|
|
|
|
// // one just for picking
|
|
|
|
// if (this._options.interactive && this._pickingMesh) {
|
|
|
|
// material = new PickingMaterial();
|
|
|
|
// // material.side = THREE.BackSide;
|
|
|
|
|
|
|
|
// // Make the line wider / easier to pick
|
|
|
|
// material.linewidth = style.lineWidth + material.linePadding;
|
|
|
|
|
|
|
|
// var pickingMesh = new THREE.LineSegments(geometry, material);
|
|
|
|
// this._pickingMesh.add(pickingMesh);
|
|
|
|
// }
|
2016-02-28 20:29:52 +00:00
|
|
|
|
2016-09-08 15:32:26 +00:00
|
|
|
// this._polylineMesh = mesh;
|
2016-03-08 15:38:11 +00:00
|
|
|
}
|
2016-02-29 23:04:07 +00:00
|
|
|
|
2016-03-09 12:26:41 +00:00
|
|
|
_setPointMesh(attributes) {
|
|
|
|
var geometry = new THREE.BufferGeometry();
|
|
|
|
|
|
|
|
// itemSize = 3 because there are 3 values (components) per vertex
|
|
|
|
geometry.addAttribute('position', new THREE.BufferAttribute(attributes.vertices, 3));
|
|
|
|
geometry.addAttribute('normal', new THREE.BufferAttribute(attributes.normals, 3));
|
|
|
|
geometry.addAttribute('color', new THREE.BufferAttribute(attributes.colours, 3));
|
|
|
|
|
|
|
|
if (attributes.pickingIds) {
|
|
|
|
geometry.addAttribute('pickingId', new THREE.BufferAttribute(attributes.pickingIds, 1));
|
|
|
|
}
|
|
|
|
|
|
|
|
geometry.computeBoundingBox();
|
|
|
|
|
|
|
|
var material;
|
2016-03-11 09:07:03 +00:00
|
|
|
if (this._options.pointMaterial && this._options.pointMaterial instanceof THREE.Material) {
|
2016-03-11 20:22:15 +00:00
|
|
|
material = this._options.pointMaterial;
|
2016-03-11 09:07:03 +00:00
|
|
|
} else if (!this._world._environment._skybox) {
|
2016-03-09 12:26:41 +00:00
|
|
|
material = new THREE.MeshPhongMaterial({
|
|
|
|
vertexColors: THREE.VertexColors
|
|
|
|
// side: THREE.BackSide
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
material = new THREE.MeshStandardMaterial({
|
|
|
|
vertexColors: THREE.VertexColors
|
|
|
|
// side: THREE.BackSide
|
|
|
|
});
|
|
|
|
material.roughness = 1;
|
|
|
|
material.metalness = 0.1;
|
|
|
|
material.envMapIntensity = 3;
|
|
|
|
material.envMap = this._world._environment._skybox.getRenderTarget();
|
|
|
|
}
|
|
|
|
|
2016-03-11 20:22:15 +00:00
|
|
|
var mesh;
|
|
|
|
|
|
|
|
// Pass mesh callback, if defined
|
|
|
|
if (typeof this._options.onPointMesh === 'function') {
|
|
|
|
mesh = this._options.onPointMesh(geometry, material);
|
|
|
|
} else {
|
|
|
|
mesh = new THREE.Mesh(geometry, material);
|
2016-03-09 12:26:41 +00:00
|
|
|
|
2016-03-11 20:22:15 +00:00
|
|
|
mesh.castShadow = true;
|
|
|
|
// mesh.receiveShadow = true;
|
|
|
|
}
|
2016-03-09 12:26:41 +00:00
|
|
|
|
|
|
|
if (this._options.interactive && this._pickingMesh) {
|
|
|
|
material = new PickingMaterial();
|
|
|
|
// material.side = THREE.BackSide;
|
|
|
|
|
|
|
|
var pickingMesh = new THREE.Mesh(geometry, material);
|
|
|
|
this._pickingMesh.add(pickingMesh);
|
|
|
|
}
|
|
|
|
|
|
|
|
this._pointMesh = mesh;
|
|
|
|
}
|
|
|
|
|
2016-03-08 15:38:11 +00:00
|
|
|
// TODO: Support all GeoJSON geometry types
|
|
|
|
_featureToLayer(feature, options) {
|
|
|
|
var geometry = feature.geometry;
|
|
|
|
var coordinates = (geometry.coordinates) ? geometry.coordinates : null;
|
2016-02-29 23:04:07 +00:00
|
|
|
|
2016-03-08 15:38:11 +00:00
|
|
|
if (!coordinates || !geometry) {
|
|
|
|
return;
|
2016-02-28 20:29:52 +00:00
|
|
|
}
|
|
|
|
|
2016-03-08 15:38:11 +00:00
|
|
|
if (geometry.type === 'Polygon' || geometry.type === 'MultiPolygon') {
|
2016-03-11 09:07:03 +00:00
|
|
|
// Get material instance to use for polygon, if provided
|
|
|
|
if (typeof this._options.polygonMaterial === 'function') {
|
|
|
|
options.geometry = this._options.polygonMaterial(feature);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (typeof this._options.onPolygonMesh === 'function') {
|
|
|
|
options.onMesh = this._options.onPolygonMesh;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Pass onBufferAttributes callback, if defined
|
|
|
|
if (typeof this._options.onPolygonBufferAttributes === 'function') {
|
|
|
|
options.onBufferAttributes = this._options.onPolygonBufferAttributes;
|
|
|
|
}
|
|
|
|
|
2016-03-08 15:38:11 +00:00
|
|
|
return new PolygonLayer(coordinates, options);
|
|
|
|
}
|
2016-02-28 20:29:52 +00:00
|
|
|
|
2016-03-08 15:38:11 +00:00
|
|
|
if (geometry.type === 'LineString' || geometry.type === 'MultiLineString') {
|
2016-03-11 09:07:03 +00:00
|
|
|
// Get material instance to use for line, if provided
|
|
|
|
if (typeof this._options.lineMaterial === 'function') {
|
|
|
|
options.geometry = this._options.lineMaterial(feature);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (typeof this._options.onPolylineMesh === 'function') {
|
|
|
|
options.onMesh = this._options.onPolylineMesh;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Pass onBufferAttributes callback, if defined
|
|
|
|
if (typeof this._options.onPolylineBufferAttributes === 'function') {
|
|
|
|
options.onBufferAttributes = this._options.onPolylineBufferAttributes;
|
|
|
|
}
|
|
|
|
|
2016-03-08 15:38:11 +00:00
|
|
|
return new PolylineLayer(coordinates, options);
|
|
|
|
}
|
2016-03-09 12:26:41 +00:00
|
|
|
|
|
|
|
if (geometry.type === 'Point' || geometry.type === 'MultiPoint') {
|
2016-03-09 16:15:38 +00:00
|
|
|
// Get geometry object to use for point, if provided
|
|
|
|
if (typeof this._options.pointGeometry === 'function') {
|
|
|
|
options.geometry = this._options.pointGeometry(feature);
|
|
|
|
}
|
|
|
|
|
2016-03-11 09:07:03 +00:00
|
|
|
// Get material instance to use for point, if provided
|
|
|
|
if (typeof this._options.pointMaterial === 'function') {
|
|
|
|
options.geometry = this._options.pointMaterial(feature);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (typeof this._options.onPointMesh === 'function') {
|
|
|
|
options.onMesh = this._options.onPointMesh;
|
|
|
|
}
|
|
|
|
|
2016-03-09 12:26:41 +00:00
|
|
|
return new PointLayer(coordinates, options);
|
|
|
|
}
|
2016-02-28 20:29:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
_abortRequest() {
|
|
|
|
if (!this._request) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
this._request.abort();
|
|
|
|
}
|
|
|
|
|
2016-03-08 15:38:11 +00:00
|
|
|
// Destroy the layers and remove them from the scene and memory
|
2016-02-28 20:29:52 +00:00
|
|
|
destroy() {
|
|
|
|
// Cancel any pending requests
|
|
|
|
this._abortRequest();
|
|
|
|
|
|
|
|
// Clear request reference
|
|
|
|
this._request = null;
|
|
|
|
|
2016-03-14 21:46:47 +00:00
|
|
|
this._geojson = null;
|
|
|
|
|
2016-03-08 15:38:11 +00:00
|
|
|
if (this._pickingMesh) {
|
|
|
|
// TODO: Properly dispose of picking mesh
|
|
|
|
this._pickingMesh = null;
|
|
|
|
}
|
2016-02-29 23:04:07 +00:00
|
|
|
|
2016-03-14 22:01:28 +00:00
|
|
|
if (this._polygonMesh) {
|
|
|
|
this._polygonMesh = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this._polylineMesh) {
|
|
|
|
this._polylineMesh = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this._pointMesh) {
|
|
|
|
this._pointMesh = null;
|
|
|
|
}
|
|
|
|
|
2016-02-28 20:29:52 +00:00
|
|
|
// Run common destruction logic from parent
|
|
|
|
super.destroy();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-01 20:34:53 +00:00
|
|
|
export default GeoJSONLayer;
|
|
|
|
|
|
|
|
var noNew = function(geojson, options) {
|
2016-02-28 20:29:52 +00:00
|
|
|
return new GeoJSONLayer(geojson, options);
|
|
|
|
};
|
2016-03-01 20:34:53 +00:00
|
|
|
|
|
|
|
export {noNew as geoJSONLayer};
|