kopia lustrzana https://github.com/robhawkes/vizicities
Refined GeoJSON and geometry layers
rodzic
f6b3fa86fd
commit
b9bca78d32
Plik diff jest za duży
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -5,11 +5,11 @@ var world = VIZI.world('world', {
|
|||
// Add controls
|
||||
VIZI.Controls.orbit().addTo(world);
|
||||
|
||||
// // http://{s}.tile.osm.org/{z}/{x}/{y}.png
|
||||
// // http://{s}.tiles.wmflabs.org/osm-no-labels/{z}/{x}/{y}.png
|
||||
// var imageTileLayer = VIZI.imageTileLayer('http://{s}.basemaps.cartocdn.com/light_nolabels/{z}/{x}/{y}.png', {
|
||||
// attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, © <a href="http://cartodb.com/attributions">CartoDB</a>'
|
||||
// }).addTo(world);
|
||||
// http://{s}.tile.osm.org/{z}/{x}/{y}.png
|
||||
// http://{s}.tiles.wmflabs.org/osm-no-labels/{z}/{x}/{y}.png
|
||||
var imageTileLayer = VIZI.imageTileLayer('http://{s}.basemaps.cartocdn.com/light_nolabels/{z}/{x}/{y}.png', {
|
||||
attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, © <a href="http://cartodb.com/attributions">CartoDB</a>'
|
||||
}).addTo(world);
|
||||
|
||||
// var layer = VIZI.geoJSONLayer('http://vector.mapzen.com/osm/buildings,roads/13/4088/2722.json', {
|
||||
// output: true,
|
||||
|
@ -24,14 +24,19 @@ VIZI.Controls.orbit().addTo(world);
|
|||
// }
|
||||
// }).addTo(world);
|
||||
|
||||
var layer = VIZI.pointLayer([-0.09, 51.505], {
|
||||
interactive: true
|
||||
var layer = VIZI.geoJSONLayer('http://vector.mapzen.com/osm/pois/13/4088/2722.json', {
|
||||
output: true,
|
||||
interactive: true,
|
||||
style: {
|
||||
pointColor: '#ff0000'
|
||||
},
|
||||
onEachFeature: function(feature, layer) {
|
||||
layer.on('click', function(layer, point2d, point3d, intersects) {
|
||||
console.log(layer, point2d, point3d, intersects);
|
||||
});
|
||||
}
|
||||
}).addTo(world);
|
||||
|
||||
layer.on('click', function(layer, point2d, point3d, intersects) {
|
||||
console.log(layer, point2d, point3d, intersects);
|
||||
});
|
||||
|
||||
// // 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', {
|
||||
// style: function(feature) {
|
||||
|
@ -82,28 +87,29 @@ layer.on('click', function(layer, point2d, point3d, intersects) {
|
|||
// }).addTo(world);
|
||||
|
||||
// London Underground lines
|
||||
// var geoJSONLayer = VIZI.geoJSONLayer('https://rawgit.com/robhawkes/4acb9d6a6a5f00a377e2/raw/30ae704a44e10f2e13fb7e956e80c3b22e8e7e81/tfl_lines.json', {
|
||||
// interactive: true,
|
||||
// style: function(feature) {
|
||||
// var colour = feature.properties.lines[0].colour || '#ffffff';
|
||||
//
|
||||
// return {
|
||||
// lineColor: colour,
|
||||
// // lineHeight: 20,
|
||||
// lineWidth: 3,
|
||||
// // lineTransparent: true,
|
||||
// // lineOpacity: 0.5,
|
||||
// // lineBlending: THREE.AdditiveBlending,
|
||||
// lineRenderOrder: 2
|
||||
// };
|
||||
// },
|
||||
// onEachFeature: function(feature, layer) {
|
||||
// layer.on('click', function(layer, point2d, point3d, intersects) {
|
||||
// console.log(layer, point2d, point3d, intersects);
|
||||
// });
|
||||
// },
|
||||
// attribution: '© Transport for London.'
|
||||
// }).addTo(world);
|
||||
var geoJSONLayer = VIZI.geoJSONLayer('https://rawgit.com/robhawkes/4acb9d6a6a5f00a377e2/raw/30ae704a44e10f2e13fb7e956e80c3b22e8e7e81/tfl_lines.json', {
|
||||
output: true,
|
||||
interactive: true,
|
||||
style: function(feature) {
|
||||
var colour = feature.properties.lines[0].colour || '#ffffff';
|
||||
|
||||
return {
|
||||
lineColor: colour,
|
||||
// lineHeight: 20,
|
||||
lineWidth: 3,
|
||||
// lineTransparent: true,
|
||||
// lineOpacity: 0.5,
|
||||
// lineBlending: THREE.AdditiveBlending,
|
||||
lineRenderOrder: 2
|
||||
};
|
||||
},
|
||||
onEachFeature: function(feature, layer) {
|
||||
layer.on('click', function(layer, point2d, point3d, intersects) {
|
||||
console.log(layer, point2d, point3d, intersects);
|
||||
});
|
||||
},
|
||||
attribution: '© Transport for London.'
|
||||
}).addTo(world);
|
||||
|
||||
// Set up render debug stats
|
||||
var rendererStats = new THREEx.RendererStats();
|
||||
|
|
|
@ -6,6 +6,7 @@ import Buffer from '../util/Buffer';
|
|||
import PickingMaterial from '../engine/PickingMaterial';
|
||||
import PolygonLayer from './geometry/PolygonLayer';
|
||||
import PolylineLayer from './geometry/PolylineLayer';
|
||||
import PointLayer from './geometry/PointLayer';
|
||||
|
||||
class GeoJSONLayer extends LayerGroup {
|
||||
constructor(geojson, options) {
|
||||
|
@ -76,15 +77,15 @@ class GeoJSONLayer extends LayerGroup {
|
|||
// Collects features into a single FeatureCollection
|
||||
//
|
||||
// Also converts TopoJSON to GeoJSON if instructed
|
||||
var geojson = GeoJSON.collectFeatures(data, this._options.topojson);
|
||||
this._geojson = GeoJSON.collectFeatures(data, this._options.topojson);
|
||||
|
||||
// TODO: Check that GeoJSON is valid / usable
|
||||
|
||||
var features = geojson.features;
|
||||
var features = this._geojson.features;
|
||||
|
||||
// Run filter, if provided
|
||||
if (this._options.filter) {
|
||||
features = geojson.features.filter(this._options.filter);
|
||||
features = this._geojson.features.filter(this._options.filter);
|
||||
}
|
||||
|
||||
var defaults = {};
|
||||
|
@ -96,7 +97,7 @@ class GeoJSONLayer extends LayerGroup {
|
|||
features.forEach(feature => {
|
||||
// Get per-feature style object, if provided
|
||||
if (typeof this._options.style === 'function') {
|
||||
style = extend(GeoJSON.defaultStyle, this._options.style(feature));
|
||||
style = extend({}, GeoJSON.defaultStyle, this._options.style(feature));
|
||||
}
|
||||
|
||||
options = extend({}, defaults, {
|
||||
|
@ -137,6 +138,7 @@ class GeoJSONLayer extends LayerGroup {
|
|||
var polygonFlat = true;
|
||||
|
||||
var polylineAttributes = [];
|
||||
var pointAttributes = [];
|
||||
|
||||
this._layers.forEach(layer => {
|
||||
if (layer instanceof PolygonLayer) {
|
||||
|
@ -147,23 +149,36 @@ class GeoJSONLayer extends LayerGroup {
|
|||
}
|
||||
} else if (layer instanceof PolylineLayer) {
|
||||
polylineAttributes.push(layer.getBufferAttributes());
|
||||
} else if (layer instanceof PointLayer) {
|
||||
pointAttributes.push(layer.getBufferAttributes());
|
||||
}
|
||||
});
|
||||
|
||||
var mergedPolygonAttributes = Buffer.mergeAttributes(polygonAttributes);
|
||||
var mergedPolylineAttributes = Buffer.mergeAttributes(polylineAttributes);
|
||||
if (polygonAttributes.length > 0) {
|
||||
var mergedPolygonAttributes = Buffer.mergeAttributes(polygonAttributes);
|
||||
this._setPolygonMesh(mergedPolygonAttributes, polygonFlat);
|
||||
this.add(this._polygonMesh);
|
||||
}
|
||||
|
||||
this._setPolygonMesh(mergedPolygonAttributes, polygonFlat);
|
||||
this.add(this._polygonMesh);
|
||||
if (polylineAttributes.length > 0) {
|
||||
var mergedPolylineAttributes = Buffer.mergeAttributes(polylineAttributes);
|
||||
this._setPolylineMesh(mergedPolylineAttributes);
|
||||
this.add(this._polylineMesh);
|
||||
}
|
||||
|
||||
this._setPolylineMesh(mergedPolylineAttributes);
|
||||
this.add(this._polylineMesh);
|
||||
if (pointAttributes.length > 0) {
|
||||
var mergedPointAttributes = Buffer.mergeAttributes(pointAttributes);
|
||||
this._setPointMesh(mergedPointAttributes);
|
||||
this.add(this._pointMesh);
|
||||
}
|
||||
}
|
||||
|
||||
// Create and store mesh from buffer attributes
|
||||
//
|
||||
// TODO: De-dupe this from the individual mesh creation logic within each
|
||||
// geometry layer (materials, settings, etc)
|
||||
//
|
||||
// Could make this an abstract method for each geometry layer
|
||||
_setPolygonMesh(attributes, flat) {
|
||||
var geometry = new THREE.BufferGeometry();
|
||||
|
||||
|
@ -230,7 +245,9 @@ class GeoJSONLayer extends LayerGroup {
|
|||
geometry.computeBoundingBox();
|
||||
|
||||
// TODO: Make this work when style is a function per feature
|
||||
var style = this._options.style;
|
||||
var style = (typeof this._options.style === 'function') ? this._options.style(this._geojson.features[0]) : this._options.style;
|
||||
style = extend({}, GeoJSON.defaultStyle, style);
|
||||
|
||||
var material = new THREE.LineBasicMaterial({
|
||||
vertexColors: THREE.VertexColors,
|
||||
linewidth: style.lineWidth,
|
||||
|
@ -246,12 +263,12 @@ class GeoJSONLayer extends LayerGroup {
|
|||
mesh.renderOrder = style.lineRenderOrder;
|
||||
}
|
||||
|
||||
// TODO: Can a line cast a shadow?
|
||||
// mesh.castShadow = true;
|
||||
mesh.castShadow = true;
|
||||
// mesh.receiveShadow = true;
|
||||
|
||||
if (this._options.interactive && this._pickingMesh) {
|
||||
material = new PickingMaterial();
|
||||
material.side = THREE.BackSide;
|
||||
// material.side = THREE.BackSide;
|
||||
|
||||
// Make the line wider / easier to pick
|
||||
material.linewidth = style.lineWidth + material.linePadding;
|
||||
|
@ -263,6 +280,53 @@ class GeoJSONLayer extends LayerGroup {
|
|||
this._polylineMesh = mesh;
|
||||
}
|
||||
|
||||
_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;
|
||||
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 = new THREE.Mesh(geometry, material);
|
||||
|
||||
mesh.castShadow = true;
|
||||
// mesh.receiveShadow = true;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
// TODO: Support all GeoJSON geometry types
|
||||
_featureToLayer(feature, options) {
|
||||
var geometry = feature.geometry;
|
||||
|
@ -279,6 +343,10 @@ class GeoJSONLayer extends LayerGroup {
|
|||
if (geometry.type === 'LineString' || geometry.type === 'MultiLineString') {
|
||||
return new PolylineLayer(coordinates, options);
|
||||
}
|
||||
|
||||
if (geometry.type === 'Point' || geometry.type === 'MultiPoint') {
|
||||
return new PointLayer(coordinates, options);
|
||||
}
|
||||
}
|
||||
|
||||
_abortRequest() {
|
||||
|
|
|
@ -10,6 +10,10 @@
|
|||
// Can probably use fromGeometry() or setFromObject() from THREE.BufferGeometry
|
||||
// and pull out the attributes
|
||||
|
||||
// TODO: Support sprite objects using textures
|
||||
|
||||
// TODO: Provide option to billboard geometry so it always faces the camera
|
||||
|
||||
import Layer from '../Layer';
|
||||
import extend from 'lodash.assign';
|
||||
import THREE from 'three';
|
||||
|
@ -23,10 +27,13 @@ class PointLayer extends Layer {
|
|||
var defaults = {
|
||||
output: true,
|
||||
interactive: false,
|
||||
// THREE.Geometry or THREE.BufferGeometry to use for point output
|
||||
//
|
||||
// TODO: Make this customisable per point via a callback (like style)
|
||||
geometry: null,
|
||||
// This default style is separate to Util.GeoJSON.defaultStyle
|
||||
style: {
|
||||
pointColor: '#ff0000',
|
||||
pointHeight: 0
|
||||
pointColor: '#ff0000'
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -115,15 +122,26 @@ class PointLayer extends Layer {
|
|||
var colour = new THREE.Color();
|
||||
colour.set(this._options.style.pointColor);
|
||||
|
||||
// Debug geometry for points
|
||||
//
|
||||
// TODO: Allow point geometry to be customised / overridden
|
||||
var debugGeomWidth = this._world.metresToWorld(5, this._pointScale);
|
||||
var debugGeomHeight = this._world.metresToWorld(100, this._pointScale);
|
||||
var debugGeom = new THREE.BoxGeometry(debugGeomWidth, debugGeomHeight, debugGeomWidth);
|
||||
var geometry;
|
||||
|
||||
// Pull attributes out of debug geometry
|
||||
var debugBufferGeom = new THREE.BufferGeometry().fromGeometry(debugGeom);
|
||||
// Use default geometry if none has been provided or the provided geometry
|
||||
// isn't valid
|
||||
if (!this._options.geometry || (!this._options.geometry instanceof THREE.Geometry || !this._options.geometry instanceof THREE.BufferGeometry)) {
|
||||
// Debug geometry for points is a thin bar
|
||||
//
|
||||
// TODO: Allow point geometry to be customised / overridden
|
||||
var geometryWidth = this._world.metresToWorld(5, this._pointScale);
|
||||
var geometryHeight = this._world.metresToWorld(200, this._pointScale);
|
||||
var _geometry = new THREE.BoxGeometry(geometryWidth, geometryHeight, geometryWidth);
|
||||
|
||||
// Shift geometry up so it sits on the ground
|
||||
_geometry.translate(0, geometryHeight * 0.5, 0);
|
||||
|
||||
// Pull attributes out of debug geometry
|
||||
geometry = new THREE.BufferGeometry().fromGeometry(_geometry);
|
||||
} else {
|
||||
geometry = this._options.geometry;
|
||||
}
|
||||
|
||||
// For each point
|
||||
var attributes = this._projectedCoordinates.map(coordinate => {
|
||||
|
@ -131,13 +149,13 @@ class PointLayer extends Layer {
|
|||
var _normals = [];
|
||||
var _colours = [];
|
||||
|
||||
var _debugBufferGeom = debugBufferGeom.clone();
|
||||
var _geometry = geometry.clone();
|
||||
|
||||
_debugBufferGeom.translate(coordinate.x, height, coordinate.y);
|
||||
_geometry.translate(coordinate.x, height, coordinate.y);
|
||||
|
||||
var _vertices = _debugBufferGeom.attributes.position.clone().array;
|
||||
var _normals = _debugBufferGeom.attributes.normal.clone().array;
|
||||
var _colours = _debugBufferGeom.attributes.color.clone().array;
|
||||
var _vertices = _geometry.attributes.position.clone().array;
|
||||
var _normals = _geometry.attributes.normal.clone().array;
|
||||
var _colours = _geometry.attributes.color.clone().array;
|
||||
|
||||
for (var i = 0; i < _colours.length; i += 3) {
|
||||
_colours[i] = colour.r;
|
||||
|
@ -145,26 +163,10 @@ class PointLayer extends Layer {
|
|||
_colours[i + 2] = colour.b;
|
||||
}
|
||||
|
||||
// Connect coordinate with the next to make a pair
|
||||
//
|
||||
// LineSegments requires pairs of vertices so repeat the last point if
|
||||
// there's an odd number of vertices
|
||||
// var nextCoord;
|
||||
// _projectedCoordinates.forEach((coordinate, index) => {
|
||||
// _colours.push([colour.r, colour.g, colour.b]);
|
||||
// _vertices.push([coordinate.x, height, coordinate.y]);
|
||||
//
|
||||
// nextCoord = (_projectedCoordinates[index + 1]) ? _projectedCoordinates[index + 1] : coordinate;
|
||||
//
|
||||
// _colours.push([colour.r, colour.g, colour.b]);
|
||||
// _vertices.push([nextCoord.x, height, nextCoord.y]);
|
||||
// });
|
||||
|
||||
var _point = {
|
||||
vertices: _vertices,
|
||||
normals: _normals,
|
||||
colours: _colours
|
||||
// verticesCount: _vertices.length
|
||||
};
|
||||
|
||||
if (this._options.interactive && this._pickingId) {
|
||||
|
@ -225,7 +227,7 @@ class PointLayer extends Layer {
|
|||
var mesh = new THREE.Mesh(geometry, material);
|
||||
|
||||
mesh.castShadow = true;
|
||||
mesh.receiveShadow = true;
|
||||
// mesh.receiveShadow = true;
|
||||
|
||||
if (this.isFlat()) {
|
||||
material.depthWrite = false;
|
||||
|
|
|
@ -107,7 +107,7 @@ class PolylineLayer extends Layer {
|
|||
}
|
||||
|
||||
var colour = new THREE.Color();
|
||||
colour.set(this._options.style.color);
|
||||
colour.set(this._options.style.lineColor);
|
||||
|
||||
// For each line
|
||||
var attributes = this._projectedCoordinates.map(_projectedCoordinates => {
|
||||
|
@ -183,8 +183,8 @@ class PolylineLayer extends Layer {
|
|||
mesh.renderOrder = style.lineRenderOrder;
|
||||
}
|
||||
|
||||
// TODO: Can a line cast a shadow?
|
||||
// mesh.castShadow = true;
|
||||
mesh.castShadow = true;
|
||||
// mesh.receiveShadow = true;
|
||||
|
||||
if (this._options.interactive && this._pickingMesh) {
|
||||
material = new PickingMaterial();
|
||||
|
|
|
@ -5,8 +5,6 @@
|
|||
import THREE from 'three';
|
||||
import topojson from 'topojson';
|
||||
import geojsonMerge from 'geojson-merge';
|
||||
import earcut from 'earcut';
|
||||
import extrudePolygon from './extrudePolygon';
|
||||
|
||||
// TODO: Make it so height can be per-coordinate / point but connected together
|
||||
// as a linestring (eg. GPS points with an elevation at each point)
|
||||
|
@ -69,170 +67,9 @@ var GeoJSON = (function() {
|
|||
}
|
||||
};
|
||||
|
||||
var lineStringAttributes = function(coordinates, colour, height) {
|
||||
var _coords = [];
|
||||
var _colours = [];
|
||||
|
||||
var nextCoord;
|
||||
|
||||
// Connect coordinate with the next to make a pair
|
||||
//
|
||||
// LineSegments requires pairs of vertices so repeat the last point if
|
||||
// there's an odd number of vertices
|
||||
coordinates.forEach((coordinate, index) => {
|
||||
_colours.push([colour.r, colour.g, colour.b]);
|
||||
_coords.push([coordinate[0], height, coordinate[1]]);
|
||||
|
||||
nextCoord = (coordinates[index + 1]) ? coordinates[index + 1] : coordinate;
|
||||
|
||||
_colours.push([colour.r, colour.g, colour.b]);
|
||||
_coords.push([nextCoord[0], height, nextCoord[1]]);
|
||||
});
|
||||
|
||||
return {
|
||||
vertices: _coords,
|
||||
colours: _colours
|
||||
};
|
||||
};
|
||||
|
||||
var multiLineStringAttributes = function(coordinates, colour, height) {
|
||||
var _coords = [];
|
||||
var _colours = [];
|
||||
|
||||
var result;
|
||||
coordinates.forEach(coordinate => {
|
||||
result = lineStringAttributes(coordinate, colour, height);
|
||||
|
||||
result.vertices.forEach(coord => {
|
||||
_coords.push(coord);
|
||||
});
|
||||
|
||||
result.colours.forEach(colour => {
|
||||
_colours.push(colour);
|
||||
});
|
||||
});
|
||||
|
||||
return {
|
||||
vertices: _coords,
|
||||
colours: _colours
|
||||
};
|
||||
};
|
||||
|
||||
var polygonAttributes = function(coordinates, colour, height) {
|
||||
var earcutData = _toEarcut(coordinates);
|
||||
|
||||
var faces = _triangulate(earcutData.vertices, earcutData.holes, earcutData.dimensions);
|
||||
|
||||
var groupedVertices = [];
|
||||
for (i = 0, il = earcutData.vertices.length; i < il; i += earcutData.dimensions) {
|
||||
groupedVertices.push(earcutData.vertices.slice(i, i + earcutData.dimensions));
|
||||
}
|
||||
|
||||
var extruded = extrudePolygon(groupedVertices, faces, {
|
||||
bottom: 0,
|
||||
top: height
|
||||
});
|
||||
|
||||
var topColor = colour.clone().multiply(light);
|
||||
var bottomColor = colour.clone().multiply(shadow);
|
||||
|
||||
var _vertices = extruded.positions;
|
||||
var _faces = [];
|
||||
var _colours = [];
|
||||
|
||||
var _colour;
|
||||
extruded.top.forEach((face, fi) => {
|
||||
_colour = [];
|
||||
|
||||
_colour.push([colour.r, colour.g, colour.b]);
|
||||
_colour.push([colour.r, colour.g, colour.b]);
|
||||
_colour.push([colour.r, colour.g, colour.b]);
|
||||
|
||||
_faces.push(face);
|
||||
_colours.push(_colour);
|
||||
});
|
||||
|
||||
var allFlat = true;
|
||||
|
||||
if (extruded.sides) {
|
||||
if (allFlat) {
|
||||
allFlat = false;
|
||||
}
|
||||
|
||||
// Set up colours for every vertex with poor-mans AO on the sides
|
||||
extruded.sides.forEach((face, fi) => {
|
||||
_colour = [];
|
||||
|
||||
// First face is always bottom-bottom-top
|
||||
if (fi % 2 === 0) {
|
||||
_colour.push([bottomColor.r, bottomColor.g, bottomColor.b]);
|
||||
_colour.push([bottomColor.r, bottomColor.g, bottomColor.b]);
|
||||
_colour.push([topColor.r, topColor.g, topColor.b]);
|
||||
// Reverse winding for the second face
|
||||
// top-top-bottom
|
||||
} else {
|
||||
_colour.push([topColor.r, topColor.g, topColor.b]);
|
||||
_colour.push([topColor.r, topColor.g, topColor.b]);
|
||||
_colour.push([bottomColor.r, bottomColor.g, bottomColor.b]);
|
||||
}
|
||||
|
||||
_faces.push(face);
|
||||
_colours.push(_colour);
|
||||
});
|
||||
}
|
||||
|
||||
// Skip bottom as there's no point rendering it
|
||||
// allFaces.push(extruded.faces);
|
||||
|
||||
return {
|
||||
vertices: _vertices,
|
||||
faces: _faces,
|
||||
colours: _colours,
|
||||
flat: allFlat
|
||||
};
|
||||
};
|
||||
|
||||
var _toEarcut = function(data) {
|
||||
var dim = data[0][0].length;
|
||||
var result = {vertices: [], holes: [], dimensions: dim};
|
||||
var holeIndex = 0;
|
||||
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
for (var j = 0; j < data[i].length; j++) {
|
||||
for (var d = 0; d < dim; d++) {
|
||||
result.vertices.push(data[i][j][d]);
|
||||
}
|
||||
}
|
||||
if (i > 0) {
|
||||
holeIndex += data[i - 1].length;
|
||||
result.holes.push(holeIndex);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
var _triangulate = function(contour, holes, dim) {
|
||||
// console.time('earcut');
|
||||
|
||||
var faces = earcut(contour, holes, dim);
|
||||
var result = [];
|
||||
|
||||
for (i = 0, il = faces.length; i < il; i += 3) {
|
||||
result.push(faces.slice(i, i + 3));
|
||||
}
|
||||
|
||||
// console.timeEnd('earcut');
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
return {
|
||||
defaultStyle: defaultStyle,
|
||||
collectFeatures: collectFeatures,
|
||||
lineStringAttributes: lineStringAttributes,
|
||||
multiLineStringAttributes: multiLineStringAttributes,
|
||||
polygonAttributes: polygonAttributes
|
||||
collectFeatures: collectFeatures
|
||||
};
|
||||
})();
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue