Reduced memory consumption of GeoJSONTile

master
Robin Hawkes 2016-03-14 21:46:47 +00:00
rodzic 5164240ceb
commit a91f5b843e
9 zmienionych plików z 326 dodań i 720 usunięć

525
dist/vizicities.js vendored
Wyświetl plik

@ -13348,12 +13348,6 @@ return /******/ (function(modules) { // webpackBootstrap
var _enginePickingMaterial2 = _interopRequireDefault(_enginePickingMaterial);
// TODO: Bring styling and output in line with GeoJSON and Geometry layers, if
// not adopting those layers for outputting tiles
// TODO: Look into using a GeoJSONLayer to represent and output the tile data
// instead of duplicating a lot of effort within this class
// TODO: Map picking IDs to some reference within the tile data / geometry so
// that something useful can be done when an object is picked / clicked on
@ -13413,7 +13407,8 @@ return /******/ (function(modules) { // webpackBootstrap
pointGeometry: null,
pointMaterial: null,
onPointMesh: null,
style: _utilGeoJSON2['default'].defaultStyle
style: _utilGeoJSON2['default'].defaultStyle,
keepFeatures: false
};
var _options = (0, _lodashAssign2['default'])({}, defaults, options);
@ -13479,39 +13474,10 @@ return /******/ (function(modules) { // webpackBootstrap
}
var mesh = new _three2['default'].Object3D();
// var geom = new THREE.PlaneBufferGeometry(this._side, this._side, 1);
//
// var material = new THREE.MeshBasicMaterial({
// depthWrite: false
// });
//
// var localMesh = new THREE.Mesh(geom, material);
// localMesh.rotation.x = -90 * Math.PI / 180;
//
// mesh.add(localMesh);
//
// var box = new BoxHelper(localMesh);
// mesh.add(box);
//
// mesh.add(this._createDebugMesh());
return mesh;
}
// _createPickingMesh() {
// if (!this._center) {
// return;
// }
//
// var mesh = new THREE.Object3D();
//
// mesh.position.x = this._center[0];
// mesh.position.z = this._center[1];
//
// return mesh;
// }
}, {
key: '_createDebugMesh',
value: function _createDebugMesh() {
@ -13645,339 +13611,65 @@ return /******/ (function(modules) { // webpackBootstrap
this._mesh = this._geojsonLayer._object3D;
this._pickingMesh = this._geojsonLayer._pickingMesh;
// var geojson = GeoJSON.collectFeatures(data, this._options.topojson);
// Free the GeoJSON memory as we don't need it
//
// // TODO: Check that GeoJSON is valid / usable
// TODO: This should probably be a method within GeoJSONLayer
this._geojsonLayer._geojson = null;
// TODO: Fix or store shadow canvas stuff and get rid of this code
// Draw footprint on shadow canvas
//
// var features = geojson.features;
// TODO: Disabled for the time-being until it can be sped up / moved to
// a worker
// this._addShadow(coordinates);
// Output shadow canvas
// TODO: Disabled for the time-being until it can be sped up / moved to
// a worker
// var texture = new THREE.Texture(this._shadowCanvas);
//
// // Run filter, if provided
// if (this._options.filter) {
// features = geojson.features.filter(this._options.filter);
// }
// // Silky smooth images when tilted
// texture.magFilter = THREE.LinearFilter;
// texture.minFilter = THREE.LinearMipMapLinearFilter;
//
// var style = this._options.style;
// // TODO: Set this to renderer.getMaxAnisotropy() / 4
// texture.anisotropy = 4;
//
// var offset = Point(0, 0);
// offset.x = -1 * this._center[0];
// offset.y = -1 * this._center[1];
// texture.needsUpdate = true;
//
// // TODO: Wrap into a helper method so this isn't duplicated in the non-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
// //
// // Also unsure as to whether it's wise to lump so much into a black box
// //
// // var meshes = GeoJSON.createMeshes(features, offset, style);
//
// var polygons = {
// vertices: [],
// faces: [],
// colours: [],
// facesCount: 0,
// allFlat: true
// };
//
// var lines = {
// vertices: [],
// colours: [],
// verticesCount: 0
// };
//
// if (this._options.picking) {
// polygons.pickingIds = [];
// lines.pickingIds = [];
// }
//
// var colour = new THREE.Color();
//
// features.forEach(feature => {
// // feature.geometry, feature.properties
//
// // Skip features that aren't supported
// //
// // TODO: Add support for all GeoJSON geometry types, including Multi...
// // geometry types
// if (
// feature.geometry.type !== 'Polygon' &&
// feature.geometry.type !== 'LineString' &&
// feature.geometry.type !== 'MultiLineString'
// ) {
// return;
// }
//
// // Get style object, if provided
// if (typeof this._options.style === 'function') {
// style = extend({}, this._defaultStyle, this._options.style(feature));
// }
//
// var coordinates = feature.geometry.coordinates;
//
// // if (feature.geometry.type === 'LineString') {
// if (feature.geometry.type === 'LineString') {
// colour.set(style.lineColor);
//
// coordinates = coordinates.map(coordinate => {
// var latlon = LatLon(coordinate[1], coordinate[0]);
// var point = this._layer._world.latLonToPoint(latlon);
// return [point.x, point.y];
// });
//
// var height = 0;
//
// if (style.lineHeight) {
// height = this._world.metresToWorld(style.lineHeight, this._pointScale);
// }
//
// var linestringAttributes = GeoJSON.lineStringAttributes(coordinates, colour, height);
//
// lines.vertices.push(linestringAttributes.vertices);
// lines.colours.push(linestringAttributes.colours);
//
// if (this._options.picking) {
// var pickingId = this._layer.getPickingId();
//
// // Inject picking ID
// //
// // TODO: Perhaps handle this within the GeoJSON helper
// lines.pickingIds.push(pickingId);
//
// if (this._options.onClick) {
// // TODO: Find a way to properly remove this listener on destroy
// this._world.on('pick-' + pickingId, (point2d, point3d, intersects) => {
// this._options.onClick(feature, point2d, point3d, intersects);
// });
// }
// }
//
// lines.verticesCount += linestringAttributes.vertices.length;
// }
//
// if (feature.geometry.type === 'MultiLineString') {
// colour.set(style.lineColor);
//
// coordinates = coordinates.map(_coordinates => {
// return _coordinates.map(coordinate => {
// var latlon = LatLon(coordinate[1], coordinate[0]);
// var point = this._layer._world.latLonToPoint(latlon);
// return [point.x, point.y];
// });
// });
//
// var height = 0;
//
// if (style.lineHeight) {
// height = this._world.metresToWorld(style.lineHeight, this._pointScale);
// }
//
// var multiLinestringAttributes = GeoJSON.multiLineStringAttributes(coordinates, colour, height);
//
// lines.vertices.push(multiLinestringAttributes.vertices);
// lines.colours.push(multiLinestringAttributes.colours);
//
// if (this._options.picking) {
// var pickingId = this._layer.getPickingId();
//
// // Inject picking ID
// //
// // TODO: Perhaps handle this within the GeoJSON helper
// lines.pickingIds.push(pickingId);
//
// if (this._options.onClick) {
// // TODO: Find a way to properly remove this listener on destroy
// this._world.on('pick-' + pickingId, (point2d, point3d, intersects) => {
// this._options.onClick(feature, point2d, point3d, intersects);
// });
// }
// }
//
// lines.verticesCount += multiLinestringAttributes.vertices.length;
// }
//
// if (feature.geometry.type === 'Polygon') {
// colour.set(style.color);
//
// coordinates = coordinates.map(ring => {
// return ring.map(coordinate => {
// var latlon = LatLon(coordinate[1], coordinate[0]);
// var point = this._layer._world.latLonToPoint(latlon);
// return [point.x, point.y];
// });
// });
//
// var height = 0;
//
// if (style.height) {
// height = this._world.metresToWorld(style.height, this._pointScale);
// }
//
// // Draw footprint on shadow canvas
// //
// // TODO: Disabled for the time-being until it can be sped up / moved to
// // a worker
// // this._addShadow(coordinates);
//
// var polygonAttributes = GeoJSON.polygonAttributes(coordinates, colour, height);
//
// polygons.vertices.push(polygonAttributes.vertices);
// polygons.faces.push(polygonAttributes.faces);
// polygons.colours.push(polygonAttributes.colours);
//
// if (this._options.picking) {
// var pickingId = this._layer.getPickingId();
//
// // Inject picking ID
// //
// // TODO: Perhaps handle this within the GeoJSON helper
// polygons.pickingIds.push(pickingId);
//
// if (this._options.onClick) {
// // TODO: Find a way to properly remove this listener on destroy
// this._world.on('pick-' + pickingId, (point2d, point3d, intersects) => {
// this._options.onClick(feature, point2d, point3d, intersects);
// });
// }
// }
//
// if (polygons.allFlat && !polygonAttributes.flat) {
// polygons.allFlat = false;
// }
//
// polygons.facesCount += polygonAttributes.faces.length;
// }
// });
//
// // Output shadow canvas
// //
// // TODO: Disabled for the time-being until it can be sped up / moved to
// // a worker
//
// // var texture = new THREE.Texture(this._shadowCanvas);
// //
// // // Silky smooth images when tilted
// // texture.magFilter = THREE.LinearFilter;
// // texture.minFilter = THREE.LinearMipMapLinearFilter;
// //
// // // TODO: Set this to renderer.getMaxAnisotropy() / 4
// // texture.anisotropy = 4;
// //
// // texture.needsUpdate = true;
// //
// // var material;
// // if (!this._world._environment._skybox) {
// // material = new THREE.MeshBasicMaterial({
// // map: texture,
// // transparent: true,
// // depthWrite: false
// // });
// // } else {
// // material = new THREE.MeshStandardMaterial({
// // map: texture,
// // transparent: true,
// // depthWrite: false
// // });
// // material.roughness = 1;
// // material.metalness = 0.1;
// // material.envMap = this._world._environment._skybox.getRenderTarget();
// // }
// //
// // var geom = new THREE.PlaneBufferGeometry(this._side, this._side, 1);
// // var mesh = new THREE.Mesh(geom, material);
// //
// // mesh.castShadow = false;
// // mesh.receiveShadow = false;
// // mesh.renderOrder = 1;
// //
// // mesh.rotation.x = -90 * Math.PI / 180;
// //
// // this._mesh.add(mesh);
//
// var geometry;
// var material;
// var mesh;
//
// // Output lines
// if (lines.vertices.length > 0) {
// geometry = Buffer.createLineGeometry(lines, offset);
//
// material = new THREE.LineBasicMaterial({
// vertexColors: THREE.VertexColors,
// linewidth: style.lineWidth,
// transparent: style.lineTransparent,
// opacity: style.lineOpacity,
// blending: style.lineBlending
// if (!this._world._environment._skybox) {
// material = new THREE.MeshBasicMaterial({
// map: texture,
// transparent: true,
// depthWrite: false
// });
//
// mesh = new THREE.LineSegments(geometry, material);
//
// if (style.lineRenderOrder !== undefined) {
// material.depthWrite = false;
// mesh.renderOrder = style.lineRenderOrder;
// }
//
// // TODO: Can a line cast a shadow?
// // mesh.castShadow = true;
//
// this._mesh.add(mesh);
//
// if (this._options.picking) {
// 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);
// }
// } else {
// material = new THREE.MeshStandardMaterial({
// map: texture,
// transparent: true,
// depthWrite: false
// });
// material.roughness = 1;
// material.metalness = 0.1;
// material.envMap = this._world._environment._skybox.getRenderTarget();
// }
//
// // Output polygons
// if (polygons.facesCount > 0) {
// geometry = Buffer.createGeometry(polygons, offset);
// var geom = new THREE.PlaneBufferGeometry(this._side, this._side, 1);
// var mesh = new THREE.Mesh(geom, material);
//
// if (!this._world._environment._skybox) {
// 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();
// }
// mesh.castShadow = false;
// mesh.receiveShadow = false;
// mesh.renderOrder = 1;
//
// mesh = new THREE.Mesh(geometry, material);
// mesh.rotation.x = -90 * Math.PI / 180;
//
// mesh.castShadow = true;
// mesh.receiveShadow = true;
//
// if (polygons.allFlat) {
// material.depthWrite = false;
// mesh.renderOrder = 1;
// }
//
// this._mesh.add(mesh);
//
// if (this._options.picking) {
// material = new PickingMaterial();
// material.side = THREE.BackSide;
//
// var pickingMesh = new THREE.Mesh(geometry, material);
// this._pickingMesh.add(pickingMesh);
// }
// }
// this._mesh.add(mesh);
this._ready = true;
console.timeEnd(this._tile);
console.log(this._tile + ': ' + this._geojsonLayer._geojson.features.length + ' features');
}
}, {
key: '_abortRequest',
@ -14023,6 +13715,11 @@ return /******/ (function(modules) { // webpackBootstrap
// TODO: Consider adopting GeoJSON CSS
// http://wiki.openstreetmap.org/wiki/Geojson_CSS
// TODO: Allow interaction to be defined per-layer to save on resources
//
// For example, only allow polygons to be interactive via a polygonInteractive
// option
var _LayerGroup2 = __webpack_require__(73);
var _LayerGroup3 = _interopRequireDefault(_LayerGroup2);
@ -14080,7 +13777,8 @@ return /******/ (function(modules) { // webpackBootstrap
pointGeometry: null,
pointMaterial: null,
onPointMesh: null,
style: _utilGeoJSON2['default'].defaultStyle
style: _utilGeoJSON2['default'].defaultStyle,
keepFeatures: true
};
var _options = (0, _lodashAssign2['default'])({}, defaults, options);
@ -14187,7 +13885,12 @@ return /******/ (function(modules) { // webpackBootstrap
return;
}
layer.feature = feature;
// Sometimes you don't want to store a reference to the feature
//
// For example, to save memory when being used by tile layers
if (_this2._options.keepFeatures) {
layer.feature = feature;
}
// If defined, call a function for each feature
//
@ -14244,6 +13947,15 @@ return /******/ (function(modules) { // webpackBootstrap
this._setPointMesh(mergedPointAttributes);
this.add(this._pointMesh);
}
// Clean up layers
//
// TODO: Are there ever situations where the unmerged buffer attributes
// and coordinates would still be required?
this._layers.forEach(function (layer) {
layer.clearBufferAttributes();
layer.clearCoordinates();
});
}
// Create and store mesh from buffer attributes
@ -14536,6 +14248,8 @@ return /******/ (function(modules) { // webpackBootstrap
// Clear request reference
this._request = null;
this._geojson = null;
if (this._pickingMesh) {
// TODO: Properly dispose of picking mesh
this._pickingMesh = null;
@ -17365,7 +17079,7 @@ return /******/ (function(modules) { // webpackBootstrap
}, {
key: 'getCenter',
value: function getCenter() {
return this._coordinates[0][0][0];
return this._center;
}
// Return polygon bounds in geographic coordinates
@ -17508,6 +17222,9 @@ return /******/ (function(modules) { // webpackBootstrap
}
this._bufferAttributes = _utilBuffer2['default'].mergeAttributes(attributes);
// Original attributes are no longer required so free the memory
attributes = null;
}
}, {
key: 'getBufferAttributes',
@ -17515,6 +17232,29 @@ return /******/ (function(modules) { // webpackBootstrap
return this._bufferAttributes;
}
// Used by external components to clear some memory when the attributes
// are no longer required to be stored in this layer
//
// For example, you would want to clear the attributes here after merging them
// using something like the GeoJSONLayer
}, {
key: 'clearBufferAttributes',
value: function clearBufferAttributes() {
this._bufferAttributes = null;
}
// Used by external components to clear some memory when the coordinates
// are no longer required to be stored in this layer
//
// For example, you would want to clear the coordinates here after this
// layer is merged in something like the GeoJSONLayer
}, {
key: 'clearCoordinates',
value: function clearCoordinates() {
this._coordinates = null;
this._projectedCoordinates = null;
}
// Create and store mesh from buffer attributes
//
// This is only called if the layer is controlling its own output
@ -17598,6 +17338,8 @@ return /******/ (function(modules) { // webpackBootstrap
this._projectedBounds = [];
this._projectedCoordinates = this._projectCoordinates();
this._center = this._coordinates[0][0][0];
}
// Recursively convert input coordinates into LatLon objects
@ -17840,12 +17582,17 @@ return /******/ (function(modules) { // webpackBootstrap
// For example, not coordinates for a MultiPolygon GeoJSON feature
}, {
key: 'destroy',
// TODO: Make sure this is cleaning everything
value: function destroy() {
if (this._pickingMesh) {
// TODO: Properly dispose of picking mesh
this._pickingMesh = null;
}
this.clearCoordinates();
this.clearBufferAttributes();
// Run common destruction logic from parent
_get(Object.getPrototypeOf(PolygonLayer.prototype), 'destroy', this).call(this);
}
@ -18005,7 +17752,7 @@ return /******/ (function(modules) { // webpackBootstrap
}, {
key: 'getCenter',
value: function getCenter() {
return this._coordinates[0][0];
return this._center;
}
// Return line bounds in geographic coordinates
@ -18096,6 +17843,9 @@ return /******/ (function(modules) { // webpackBootstrap
}
this._bufferAttributes = _utilBuffer2['default'].mergeAttributes(attributes);
// Original attributes are no longer required so free the memory
attributes = null;
}
}, {
key: 'getBufferAttributes',
@ -18103,6 +17853,29 @@ return /******/ (function(modules) { // webpackBootstrap
return this._bufferAttributes;
}
// Used by external components to clear some memory when the attributes
// are no longer required to be stored in this layer
//
// For example, you would want to clear the attributes here after merging them
// using something like the GeoJSONLayer
}, {
key: 'clearBufferAttributes',
value: function clearBufferAttributes() {
this._bufferAttributes = null;
}
// Used by external components to clear some memory when the coordinates
// are no longer required to be stored in this layer
//
// For example, you would want to clear the coordinates here after this
// layer is merged in something like the GeoJSONLayer
}, {
key: 'clearCoordinates',
value: function clearCoordinates() {
this._coordinates = null;
this._projectedCoordinates = null;
}
// Create and store mesh from buffer attributes
//
// This is only called if the layer is controlling its own output
@ -18185,6 +17958,8 @@ return /******/ (function(modules) { // webpackBootstrap
this._projectedBounds = [];
this._projectedCoordinates = this._projectCoordinates();
this._center = this._coordinates[0][0];
}
// Recursively convert input coordinates into LatLon objects
@ -18336,6 +18111,9 @@ return /******/ (function(modules) { // webpackBootstrap
this._pickingMesh = null;
}
this.clearCoordinates();
this.clearBufferAttributes();
// Run common destruction logic from parent
_get(Object.getPrototypeOf(PolylineLayer.prototype), 'destroy', this).call(this);
}
@ -18498,7 +18276,7 @@ return /******/ (function(modules) { // webpackBootstrap
}, {
key: 'getCenter',
value: function getCenter() {
return this._coordinates;
return this._center;
}
// Return point bounds in geographic coordinates
@ -18612,6 +18390,9 @@ return /******/ (function(modules) { // webpackBootstrap
});
this._bufferAttributes = _utilBuffer2['default'].mergeAttributes(attributes);
// Original attributes are no longer required so free the memory
attributes = null;
}
}, {
key: 'getBufferAttributes',
@ -18619,6 +18400,29 @@ return /******/ (function(modules) { // webpackBootstrap
return this._bufferAttributes;
}
// Used by external components to clear some memory when the attributes
// are no longer required to be stored in this layer
//
// For example, you would want to clear the attributes here after merging them
// using something like the GeoJSONLayer
}, {
key: 'clearBufferAttributes',
value: function clearBufferAttributes() {
this._bufferAttributes = null;
}
// Used by external components to clear some memory when the coordinates
// are no longer required to be stored in this layer
//
// For example, you would want to clear the coordinates here after this
// layer is merged in something like the GeoJSONLayer
}, {
key: 'clearCoordinates',
value: function clearCoordinates() {
this._coordinates = null;
this._projectedCoordinates = null;
}
// Create and store mesh from buffer attributes
//
// This is only called if the layer is controlling its own output
@ -18692,6 +18496,8 @@ return /******/ (function(modules) { // webpackBootstrap
this._projectedBounds = [];
this._projectedCoordinates = this._projectCoordinates();
this._center = this._coordinates;
}
// Recursively convert input coordinates into LatLon objects
@ -18813,6 +18619,9 @@ return /******/ (function(modules) { // webpackBootstrap
this._pickingMesh = null;
}
this.clearCoordinates();
this.clearBufferAttributes();
// Run common destruction logic from parent
_get(Object.getPrototypeOf(PointLayer.prototype), 'destroy', this).call(this);
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Wyświetl plik

@ -42,7 +42,7 @@ var imageTileLayer = VIZI.imageTileLayer('http://{s}.basemaps.cartocdn.com/light
// Building and roads from Mapzen (polygons and linestrings)
var topoJSONTileLayer = VIZI.topoJSONTileLayer('https://vector.mapzen.com/osm/buildings,roads/{z}/{x}/{y}.topojson?api_key=vector-tiles-NT5Emiw', {
interactive: true,
interactive: false,
style: function(feature) {
var height;

Wyświetl plik

@ -1,6 +1,11 @@
// TODO: Consider adopting GeoJSON CSS
// http://wiki.openstreetmap.org/wiki/Geojson_CSS
// TODO: Allow interaction to be defined per-layer to save on resources
//
// For example, only allow polygons to be interactive via a polygonInteractive
// option
import LayerGroup from './LayerGroup';
import extend from 'lodash.assign';
import reqwest from 'reqwest';
@ -28,7 +33,8 @@ class GeoJSONLayer extends LayerGroup {
pointGeometry: null,
pointMaterial: null,
onPointMesh: null,
style: GeoJSON.defaultStyle
style: GeoJSON.defaultStyle,
keepFeatures: true
};
var _options = extend({}, defaults, options);
@ -126,7 +132,12 @@ class GeoJSONLayer extends LayerGroup {
return;
}
layer.feature = feature;
// 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;
}
// If defined, call a function for each feature
//
@ -183,6 +194,15 @@ class GeoJSONLayer extends LayerGroup {
this._setPointMesh(mergedPointAttributes);
this.add(this._pointMesh);
}
// 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();
});
}
// Create and store mesh from buffer attributes
@ -466,6 +486,8 @@ class GeoJSONLayer extends LayerGroup {
// Clear request reference
this._request = null;
this._geojson = null;
if (this._pickingMesh) {
// TODO: Properly dispose of picking mesh
this._pickingMesh = null;

Wyświetl plik

@ -97,7 +97,7 @@ class PointLayer extends Layer {
//
// This is used for things like placing popups / UI elements on the layer
getCenter() {
return this._coordinates;
return this._center;
}
// Return point bounds in geographic coordinates
@ -199,12 +199,34 @@ class PointLayer extends Layer {
});
this._bufferAttributes = Buffer.mergeAttributes(attributes);
// Original attributes are no longer required so free the memory
attributes = null;
}
getBufferAttributes() {
return this._bufferAttributes;
}
// Used by external components to clear some memory when the attributes
// are no longer required to be stored in this layer
//
// For example, you would want to clear the attributes here after merging them
// using something like the GeoJSONLayer
clearBufferAttributes() {
this._bufferAttributes = null;
}
// Used by external components to clear some memory when the coordinates
// are no longer required to be stored in this layer
//
// For example, you would want to clear the coordinates here after this
// layer is merged in something like the GeoJSONLayer
clearCoordinates() {
this._coordinates = null;
this._projectedCoordinates = null;
}
// Create and store mesh from buffer attributes
//
// This is only called if the layer is controlling its own output
@ -274,6 +296,8 @@ class PointLayer extends Layer {
this._projectedBounds = [];
this._projectedCoordinates = this._projectCoordinates();
this._center = this._coordinates;
}
// Recursively convert input coordinates into LatLon objects
@ -387,6 +411,9 @@ class PointLayer extends Layer {
this._pickingMesh = null;
}
this.clearCoordinates();
this.clearBufferAttributes();
// Run common destruction logic from parent
super.destroy();
}

Wyświetl plik

@ -91,7 +91,7 @@ class PolygonLayer extends Layer {
// TODO: Find proper center position instead of returning first coordinate
// SEE: https://github.com/Leaflet/Leaflet/blob/master/src/layer/vector/Polygon.js#L15
getCenter() {
return this._coordinates[0][0][0];
return this._center;
}
// Return polygon bounds in geographic coordinates
@ -222,12 +222,34 @@ class PolygonLayer extends Layer {
}
this._bufferAttributes = Buffer.mergeAttributes(attributes);
// Original attributes are no longer required so free the memory
attributes = null;
}
getBufferAttributes() {
return this._bufferAttributes;
}
// Used by external components to clear some memory when the attributes
// are no longer required to be stored in this layer
//
// For example, you would want to clear the attributes here after merging them
// using something like the GeoJSONLayer
clearBufferAttributes() {
this._bufferAttributes = null;
}
// Used by external components to clear some memory when the coordinates
// are no longer required to be stored in this layer
//
// For example, you would want to clear the coordinates here after this
// layer is merged in something like the GeoJSONLayer
clearCoordinates() {
this._coordinates = null;
this._projectedCoordinates = null;
}
// Create and store mesh from buffer attributes
//
// This is only called if the layer is controlling its own output
@ -307,6 +329,8 @@ class PolygonLayer extends Layer {
this._projectedBounds = [];
this._projectedCoordinates = this._projectCoordinates();
this._center = this._coordinates[0][0][0];
}
// Recursively convert input coordinates into LatLon objects
@ -537,12 +561,16 @@ class PolygonLayer extends Layer {
return !Array.isArray(coordinates[0][0][0]);
}
// TODO: Make sure this is cleaning everything
destroy() {
if (this._pickingMesh) {
// TODO: Properly dispose of picking mesh
this._pickingMesh = null;
}
this.clearCoordinates();
this.clearBufferAttributes();
// Run common destruction logic from parent
super.destroy();
}

Wyświetl plik

@ -94,7 +94,7 @@ class PolylineLayer extends Layer {
// TODO: Find proper center position instead of returning first coordinate
// SEE: https://github.com/Leaflet/Leaflet/blob/master/src/layer/vector/Polyline.js#L59
getCenter() {
return this._coordinates[0][0];
return this._center;
}
// Return line bounds in geographic coordinates
@ -173,12 +173,34 @@ class PolylineLayer extends Layer {
}
this._bufferAttributes = Buffer.mergeAttributes(attributes);
// Original attributes are no longer required so free the memory
attributes = null;
}
getBufferAttributes() {
return this._bufferAttributes;
}
// Used by external components to clear some memory when the attributes
// are no longer required to be stored in this layer
//
// For example, you would want to clear the attributes here after merging them
// using something like the GeoJSONLayer
clearBufferAttributes() {
this._bufferAttributes = null;
}
// Used by external components to clear some memory when the coordinates
// are no longer required to be stored in this layer
//
// For example, you would want to clear the coordinates here after this
// layer is merged in something like the GeoJSONLayer
clearCoordinates() {
this._coordinates = null;
this._projectedCoordinates = null;
}
// Create and store mesh from buffer attributes
//
// This is only called if the layer is controlling its own output
@ -257,6 +279,8 @@ class PolylineLayer extends Layer {
this._projectedBounds = [];
this._projectedCoordinates = this._projectCoordinates();
this._center = this._coordinates[0][0];
}
// Recursively convert input coordinates into LatLon objects
@ -400,6 +424,9 @@ class PolylineLayer extends Layer {
this._pickingMesh = null;
}
this.clearCoordinates();
this.clearBufferAttributes();
// Run common destruction logic from parent
super.destroy();
}

Wyświetl plik

@ -11,12 +11,6 @@ import GeoJSON from '../../util/GeoJSON';
import Buffer from '../../util/Buffer';
import PickingMaterial from '../../engine/PickingMaterial';
// TODO: Bring styling and output in line with GeoJSON and Geometry layers, if
// not adopting those layers for outputting tiles
// TODO: Look into using a GeoJSONLayer to represent and output the tile data
// instead of duplicating a lot of effort within this class
// TODO: Map picking IDs to some reference within the tile data / geometry so
// that something useful can be done when an object is picked / clicked on
@ -72,7 +66,8 @@ class GeoJSONTile extends Tile {
pointGeometry: null,
pointMaterial: null,
onPointMesh: null,
style: GeoJSON.defaultStyle
style: GeoJSON.defaultStyle,
keepFeatures: false
};
var _options = extend({}, defaults, options);
@ -130,39 +125,11 @@ class GeoJSONTile extends Tile {
}
var mesh = new THREE.Object3D();
// var geom = new THREE.PlaneBufferGeometry(this._side, this._side, 1);
//
// var material = new THREE.MeshBasicMaterial({
// depthWrite: false
// });
//
// var localMesh = new THREE.Mesh(geom, material);
// localMesh.rotation.x = -90 * Math.PI / 180;
//
// mesh.add(localMesh);
//
// var box = new BoxHelper(localMesh);
// mesh.add(box);
//
// mesh.add(this._createDebugMesh());
return mesh;
}
// _createPickingMesh() {
// if (!this._center) {
// return;
// }
//
// var mesh = new THREE.Object3D();
//
// mesh.position.x = this._center[0];
// mesh.position.z = this._center[1];
//
// return mesh;
// }
_createDebugMesh() {
var canvas = document.createElement('canvas');
canvas.width = 256;
@ -289,339 +256,65 @@ class GeoJSONTile extends Tile {
this._mesh = this._geojsonLayer._object3D;
this._pickingMesh = this._geojsonLayer._pickingMesh;
// var geojson = GeoJSON.collectFeatures(data, this._options.topojson);
// Free the GeoJSON memory as we don't need it
//
// // TODO: Check that GeoJSON is valid / usable
// TODO: This should probably be a method within GeoJSONLayer
this._geojsonLayer._geojson = null;
// TODO: Fix or store shadow canvas stuff and get rid of this code
// Draw footprint on shadow canvas
//
// var features = geojson.features;
// TODO: Disabled for the time-being until it can be sped up / moved to
// a worker
// this._addShadow(coordinates);
// Output shadow canvas
// TODO: Disabled for the time-being until it can be sped up / moved to
// a worker
// var texture = new THREE.Texture(this._shadowCanvas);
//
// // Run filter, if provided
// if (this._options.filter) {
// features = geojson.features.filter(this._options.filter);
// }
// // Silky smooth images when tilted
// texture.magFilter = THREE.LinearFilter;
// texture.minFilter = THREE.LinearMipMapLinearFilter;
//
// var style = this._options.style;
// // TODO: Set this to renderer.getMaxAnisotropy() / 4
// texture.anisotropy = 4;
//
// var offset = Point(0, 0);
// offset.x = -1 * this._center[0];
// offset.y = -1 * this._center[1];
// texture.needsUpdate = true;
//
// // TODO: Wrap into a helper method so this isn't duplicated in the non-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
// //
// // Also unsure as to whether it's wise to lump so much into a black box
// //
// // var meshes = GeoJSON.createMeshes(features, offset, style);
//
// var polygons = {
// vertices: [],
// faces: [],
// colours: [],
// facesCount: 0,
// allFlat: true
// };
//
// var lines = {
// vertices: [],
// colours: [],
// verticesCount: 0
// };
//
// if (this._options.picking) {
// polygons.pickingIds = [];
// lines.pickingIds = [];
// }
//
// var colour = new THREE.Color();
//
// features.forEach(feature => {
// // feature.geometry, feature.properties
//
// // Skip features that aren't supported
// //
// // TODO: Add support for all GeoJSON geometry types, including Multi...
// // geometry types
// if (
// feature.geometry.type !== 'Polygon' &&
// feature.geometry.type !== 'LineString' &&
// feature.geometry.type !== 'MultiLineString'
// ) {
// return;
// }
//
// // Get style object, if provided
// if (typeof this._options.style === 'function') {
// style = extend({}, this._defaultStyle, this._options.style(feature));
// }
//
// var coordinates = feature.geometry.coordinates;
//
// // if (feature.geometry.type === 'LineString') {
// if (feature.geometry.type === 'LineString') {
// colour.set(style.lineColor);
//
// coordinates = coordinates.map(coordinate => {
// var latlon = LatLon(coordinate[1], coordinate[0]);
// var point = this._layer._world.latLonToPoint(latlon);
// return [point.x, point.y];
// });
//
// var height = 0;
//
// if (style.lineHeight) {
// height = this._world.metresToWorld(style.lineHeight, this._pointScale);
// }
//
// var linestringAttributes = GeoJSON.lineStringAttributes(coordinates, colour, height);
//
// lines.vertices.push(linestringAttributes.vertices);
// lines.colours.push(linestringAttributes.colours);
//
// if (this._options.picking) {
// var pickingId = this._layer.getPickingId();
//
// // Inject picking ID
// //
// // TODO: Perhaps handle this within the GeoJSON helper
// lines.pickingIds.push(pickingId);
//
// if (this._options.onClick) {
// // TODO: Find a way to properly remove this listener on destroy
// this._world.on('pick-' + pickingId, (point2d, point3d, intersects) => {
// this._options.onClick(feature, point2d, point3d, intersects);
// });
// }
// }
//
// lines.verticesCount += linestringAttributes.vertices.length;
// }
//
// if (feature.geometry.type === 'MultiLineString') {
// colour.set(style.lineColor);
//
// coordinates = coordinates.map(_coordinates => {
// return _coordinates.map(coordinate => {
// var latlon = LatLon(coordinate[1], coordinate[0]);
// var point = this._layer._world.latLonToPoint(latlon);
// return [point.x, point.y];
// });
// });
//
// var height = 0;
//
// if (style.lineHeight) {
// height = this._world.metresToWorld(style.lineHeight, this._pointScale);
// }
//
// var multiLinestringAttributes = GeoJSON.multiLineStringAttributes(coordinates, colour, height);
//
// lines.vertices.push(multiLinestringAttributes.vertices);
// lines.colours.push(multiLinestringAttributes.colours);
//
// if (this._options.picking) {
// var pickingId = this._layer.getPickingId();
//
// // Inject picking ID
// //
// // TODO: Perhaps handle this within the GeoJSON helper
// lines.pickingIds.push(pickingId);
//
// if (this._options.onClick) {
// // TODO: Find a way to properly remove this listener on destroy
// this._world.on('pick-' + pickingId, (point2d, point3d, intersects) => {
// this._options.onClick(feature, point2d, point3d, intersects);
// });
// }
// }
//
// lines.verticesCount += multiLinestringAttributes.vertices.length;
// }
//
// if (feature.geometry.type === 'Polygon') {
// colour.set(style.color);
//
// coordinates = coordinates.map(ring => {
// return ring.map(coordinate => {
// var latlon = LatLon(coordinate[1], coordinate[0]);
// var point = this._layer._world.latLonToPoint(latlon);
// return [point.x, point.y];
// });
// });
//
// var height = 0;
//
// if (style.height) {
// height = this._world.metresToWorld(style.height, this._pointScale);
// }
//
// // Draw footprint on shadow canvas
// //
// // TODO: Disabled for the time-being until it can be sped up / moved to
// // a worker
// // this._addShadow(coordinates);
//
// var polygonAttributes = GeoJSON.polygonAttributes(coordinates, colour, height);
//
// polygons.vertices.push(polygonAttributes.vertices);
// polygons.faces.push(polygonAttributes.faces);
// polygons.colours.push(polygonAttributes.colours);
//
// if (this._options.picking) {
// var pickingId = this._layer.getPickingId();
//
// // Inject picking ID
// //
// // TODO: Perhaps handle this within the GeoJSON helper
// polygons.pickingIds.push(pickingId);
//
// if (this._options.onClick) {
// // TODO: Find a way to properly remove this listener on destroy
// this._world.on('pick-' + pickingId, (point2d, point3d, intersects) => {
// this._options.onClick(feature, point2d, point3d, intersects);
// });
// }
// }
//
// if (polygons.allFlat && !polygonAttributes.flat) {
// polygons.allFlat = false;
// }
//
// polygons.facesCount += polygonAttributes.faces.length;
// }
// });
//
// // Output shadow canvas
// //
// // TODO: Disabled for the time-being until it can be sped up / moved to
// // a worker
//
// // var texture = new THREE.Texture(this._shadowCanvas);
// //
// // // Silky smooth images when tilted
// // texture.magFilter = THREE.LinearFilter;
// // texture.minFilter = THREE.LinearMipMapLinearFilter;
// //
// // // TODO: Set this to renderer.getMaxAnisotropy() / 4
// // texture.anisotropy = 4;
// //
// // texture.needsUpdate = true;
// //
// // var material;
// // if (!this._world._environment._skybox) {
// // material = new THREE.MeshBasicMaterial({
// // map: texture,
// // transparent: true,
// // depthWrite: false
// // });
// // } else {
// // material = new THREE.MeshStandardMaterial({
// // map: texture,
// // transparent: true,
// // depthWrite: false
// // });
// // material.roughness = 1;
// // material.metalness = 0.1;
// // material.envMap = this._world._environment._skybox.getRenderTarget();
// // }
// //
// // var geom = new THREE.PlaneBufferGeometry(this._side, this._side, 1);
// // var mesh = new THREE.Mesh(geom, material);
// //
// // mesh.castShadow = false;
// // mesh.receiveShadow = false;
// // mesh.renderOrder = 1;
// //
// // mesh.rotation.x = -90 * Math.PI / 180;
// //
// // this._mesh.add(mesh);
//
// var geometry;
// var material;
// var mesh;
//
// // Output lines
// if (lines.vertices.length > 0) {
// geometry = Buffer.createLineGeometry(lines, offset);
//
// material = new THREE.LineBasicMaterial({
// vertexColors: THREE.VertexColors,
// linewidth: style.lineWidth,
// transparent: style.lineTransparent,
// opacity: style.lineOpacity,
// blending: style.lineBlending
// if (!this._world._environment._skybox) {
// material = new THREE.MeshBasicMaterial({
// map: texture,
// transparent: true,
// depthWrite: false
// });
//
// mesh = new THREE.LineSegments(geometry, material);
//
// if (style.lineRenderOrder !== undefined) {
// material.depthWrite = false;
// mesh.renderOrder = style.lineRenderOrder;
// }
//
// // TODO: Can a line cast a shadow?
// // mesh.castShadow = true;
//
// this._mesh.add(mesh);
//
// if (this._options.picking) {
// 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);
// }
// } else {
// material = new THREE.MeshStandardMaterial({
// map: texture,
// transparent: true,
// depthWrite: false
// });
// material.roughness = 1;
// material.metalness = 0.1;
// material.envMap = this._world._environment._skybox.getRenderTarget();
// }
//
// // Output polygons
// if (polygons.facesCount > 0) {
// geometry = Buffer.createGeometry(polygons, offset);
// var geom = new THREE.PlaneBufferGeometry(this._side, this._side, 1);
// var mesh = new THREE.Mesh(geom, material);
//
// if (!this._world._environment._skybox) {
// 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();
// }
// mesh.castShadow = false;
// mesh.receiveShadow = false;
// mesh.renderOrder = 1;
//
// mesh = new THREE.Mesh(geometry, material);
// mesh.rotation.x = -90 * Math.PI / 180;
//
// mesh.castShadow = true;
// mesh.receiveShadow = true;
//
// if (polygons.allFlat) {
// material.depthWrite = false;
// mesh.renderOrder = 1;
// }
//
// this._mesh.add(mesh);
//
// if (this._options.picking) {
// material = new PickingMaterial();
// material.side = THREE.BackSide;
//
// var pickingMesh = new THREE.Mesh(geometry, material);
// this._pickingMesh.add(pickingMesh);
// }
// }
// this._mesh.add(mesh);
this._ready = true;
console.timeEnd(this._tile);
console.log(`${this._tile}: ${this._geojsonLayer._geojson.features.length} features`);
}
_abortRequest() {