kopia lustrzana https://github.com/robhawkes/vizicities
Merge pull request #173 from UDST/feature/polygon-outlines
Added 2D outline support for polygonsfeature/threejs-update
commit
c7793b21f6
|
@ -19,6 +19,8 @@ VIZI.geoJSONLayer('http://vector.mapzen.com/osm/roads,pois,buildings/14/4824/615
|
|||
output: true,
|
||||
style: {
|
||||
color: '#ff0000',
|
||||
outline: true,
|
||||
outlineColor: '#580000',
|
||||
lineColor: '#0000ff',
|
||||
lineRenderOrder: 1,
|
||||
pointColor: '#00cc00'
|
||||
|
|
|
@ -23,6 +23,8 @@ world.createWorkers(7).then(() => {
|
|||
output: true,
|
||||
style: {
|
||||
color: '#ff0000',
|
||||
outline: true,
|
||||
outlineColor: '#580000',
|
||||
lineColor: '#0000ff',
|
||||
lineRenderOrder: 1,
|
||||
pointColor: '#00cc00'
|
||||
|
|
|
@ -170,6 +170,7 @@ class GeoJSONLayer extends LayerGroup {
|
|||
// From here on we can assume that we want to merge the layers
|
||||
|
||||
var polygonAttributes = [];
|
||||
var polygonOutlineAttributes = [];
|
||||
var polygonAttributeLengths = {
|
||||
positions: 3,
|
||||
normals: 3,
|
||||
|
@ -196,6 +197,11 @@ class GeoJSONLayer extends LayerGroup {
|
|||
if (layer instanceof PolygonLayer) {
|
||||
polygonAttributes.push(layer.getBufferAttributes());
|
||||
|
||||
var outlineBufferAttributes = layer.getOutlineBufferAttributes();
|
||||
if (outlineBufferAttributes) {
|
||||
polygonOutlineAttributes.push(outlineBufferAttributes);
|
||||
}
|
||||
|
||||
if (polygonFlat && !layer.isFlat()) {
|
||||
polygonFlat = false;
|
||||
}
|
||||
|
@ -228,10 +234,22 @@ class GeoJSONLayer extends LayerGroup {
|
|||
|
||||
if (polygonAttributes.length > 0) {
|
||||
var mergedPolygonAttributes = Buffer.mergeAttributes(polygonAttributes);
|
||||
|
||||
var mergedPolygonOutlineAttributes;
|
||||
if (polygonOutlineAttributes.length > 0) {
|
||||
mergedPolygonOutlineAttributes = Buffer.mergeAttributes(polygonOutlineAttributes);
|
||||
}
|
||||
|
||||
this._setPolygonMesh(mergedPolygonAttributes, polygonAttributeLengths, polygonFlat).then((result) => {
|
||||
this._polygonMesh = result.mesh;
|
||||
this.add(this._polygonMesh);
|
||||
|
||||
if (mergedPolygonOutlineAttributes) {
|
||||
this._setPolylineMesh(mergedPolygonOutlineAttributes, polylineAttributeLengths, true).then((result) => {
|
||||
this.add(result.mesh);
|
||||
});
|
||||
}
|
||||
|
||||
if (result.pickingMesh) {
|
||||
this._pickingMesh.add(result.pickingMesh);
|
||||
}
|
||||
|
|
|
@ -141,6 +141,14 @@ class GeoJSONWorkerLayer extends Layer {
|
|||
var splitNormals = Buffer.splitFloat32Array(results.attributes.normals);
|
||||
var splitColors = Buffer.splitFloat32Array(results.attributes.colors);
|
||||
|
||||
var splitOutlinePositions;
|
||||
var splitOutlineColors;
|
||||
|
||||
if (results.outlineAttributes) {
|
||||
splitOutlinePositions = Buffer.splitFloat32Array(results.outlineAttributes.positions);
|
||||
splitOutlineColors = Buffer.splitFloat32Array(results.outlineAttributes.colors);
|
||||
}
|
||||
|
||||
var splitProperties;
|
||||
if (results.properties) {
|
||||
splitProperties = Buffer.splitUint8Array(results.properties);
|
||||
|
@ -149,6 +157,8 @@ class GeoJSONWorkerLayer extends Layer {
|
|||
var flats = results.flats;
|
||||
|
||||
var objects = [];
|
||||
var outlineObjects = [];
|
||||
|
||||
var obj;
|
||||
var pickingId;
|
||||
var pickingIds;
|
||||
|
@ -160,6 +170,11 @@ class GeoJSONWorkerLayer extends Layer {
|
|||
colors: 3
|
||||
};
|
||||
|
||||
var polygonOutlineAttributeLengths = {
|
||||
positions: 3,
|
||||
colors: 3
|
||||
};
|
||||
|
||||
for (var i = 0; i < splitPositions.length; i++) {
|
||||
if (splitProperties && splitProperties[i]) {
|
||||
properties = JSON.parse(Buffer.uint8ArrayToString(splitProperties[i]));
|
||||
|
@ -208,7 +223,20 @@ class GeoJSONWorkerLayer extends Layer {
|
|||
objects.push(obj);
|
||||
}
|
||||
|
||||
for (var i = 0; i < splitOutlinePositions.length; i++) {
|
||||
obj = {
|
||||
attributes: [{
|
||||
positions: splitOutlinePositions[i],
|
||||
colors: splitOutlineColors[i]
|
||||
}],
|
||||
flat: true
|
||||
};
|
||||
|
||||
outlineObjects.push(obj);
|
||||
}
|
||||
|
||||
var polygonAttributes = [];
|
||||
var polygonOutlineAttributes = [];
|
||||
|
||||
var polygonFlat = true;
|
||||
|
||||
|
@ -224,6 +252,13 @@ class GeoJSONWorkerLayer extends Layer {
|
|||
polygonAttributes.push(bufferAttributes);
|
||||
};
|
||||
|
||||
for (var i = 0; i < outlineObjects.length; i++) {
|
||||
obj = outlineObjects[i];
|
||||
|
||||
var bufferAttributes = Buffer.mergeAttributes(obj.attributes);
|
||||
polygonOutlineAttributes.push(bufferAttributes);
|
||||
};
|
||||
|
||||
if (polygonAttributes.length > 0) {
|
||||
var mergedPolygonAttributes = Buffer.mergeAttributes(polygonAttributes);
|
||||
|
||||
|
@ -240,6 +275,17 @@ class GeoJSONWorkerLayer extends Layer {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (polygonOutlineAttributes.length > 0) {
|
||||
var mergedPolygonOutlineAttributes = Buffer.mergeAttributes(polygonOutlineAttributes);
|
||||
|
||||
var style = (typeof this._options.style === 'function') ? this._options.style(objects[0]) : this._options.style;
|
||||
style = extend({}, GeoJSON.defaultStyle, style);
|
||||
|
||||
this._setPolylineMesh(mergedPolygonOutlineAttributes, polygonOutlineAttributeLengths, style, true).then((result) => {
|
||||
this.add(result.mesh);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Dedupe with polygon method
|
||||
|
@ -683,6 +729,9 @@ class GeoJSONWorkerLayer extends Layer {
|
|||
var normals = [];
|
||||
var colors = [];
|
||||
|
||||
var outlinePositions = [];
|
||||
var outlineColors = [];
|
||||
|
||||
var properties = [];
|
||||
|
||||
var flats = [];
|
||||
|
@ -713,6 +762,14 @@ class GeoJSONWorkerLayer extends Layer {
|
|||
properties.push(Buffer.stringToUint8Array(JSON.stringify(polygon.properties)));
|
||||
}
|
||||
};
|
||||
|
||||
var outlineAttributes;
|
||||
for (var j = 0; j < result.outlineAttributes.length; j++) {
|
||||
outlineAttributes = result.outlineAttributes[j];
|
||||
|
||||
outlinePositions.push(outlineAttributes.positions);
|
||||
outlineColors.push(outlineAttributes.colors);
|
||||
};
|
||||
};
|
||||
|
||||
var mergedAttributes = {
|
||||
|
@ -721,6 +778,11 @@ class GeoJSONWorkerLayer extends Layer {
|
|||
colors: Buffer.mergeFloat32Arrays(colors)
|
||||
};
|
||||
|
||||
var mergedOutlineAttributes = {
|
||||
positions: Buffer.mergeFloat32Arrays(outlinePositions),
|
||||
colors: Buffer.mergeFloat32Arrays(outlineColors)
|
||||
};
|
||||
|
||||
transferrables.push(mergedAttributes.positions[0].buffer);
|
||||
transferrables.push(mergedAttributes.positions[1].buffer);
|
||||
|
||||
|
@ -730,6 +792,12 @@ class GeoJSONWorkerLayer extends Layer {
|
|||
transferrables.push(mergedAttributes.colors[0].buffer);
|
||||
transferrables.push(mergedAttributes.colors[1].buffer);
|
||||
|
||||
transferrables.push(mergedOutlineAttributes.positions[0].buffer);
|
||||
transferrables.push(mergedOutlineAttributes.positions[1].buffer);
|
||||
|
||||
transferrables.push(mergedOutlineAttributes.colors[0].buffer);
|
||||
transferrables.push(mergedOutlineAttributes.colors[1].buffer);
|
||||
|
||||
var mergedProperties;
|
||||
if (_properties) {
|
||||
mergedProperties = Buffer.mergeUint8Arrays(properties);
|
||||
|
@ -740,6 +808,7 @@ class GeoJSONWorkerLayer extends Layer {
|
|||
|
||||
var output = {
|
||||
attributes: mergedAttributes,
|
||||
outlineAttributes: mergedOutlineAttributes,
|
||||
flats: flats
|
||||
};
|
||||
|
||||
|
|
|
@ -76,8 +76,14 @@ class PolygonLayer extends Layer {
|
|||
|
||||
PolygonLayer.SetBufferAttributes(this._projectedCoordinates, this._options).then((result) => {
|
||||
this._bufferAttributes = Buffer.mergeAttributes(result.attributes);
|
||||
|
||||
if (result.outlineAttributes.length > 0) {
|
||||
this._outlineBufferAttributes = Buffer.mergeAttributes(result.outlineAttributes);
|
||||
}
|
||||
|
||||
this._flat = result.flat;
|
||||
|
||||
if (this.isOutput()) {
|
||||
var attributeLengths = {
|
||||
positions: 3,
|
||||
normals: 3,
|
||||
|
@ -88,7 +94,6 @@ class PolygonLayer extends Layer {
|
|||
attributeLengths.pickingIds = 1;
|
||||
}
|
||||
|
||||
if (this.isOutput()) {
|
||||
var style = this._options.style;
|
||||
|
||||
// Set mesh if not merging elsewhere
|
||||
|
@ -103,6 +108,7 @@ class PolygonLayer extends Layer {
|
|||
}
|
||||
|
||||
result.attributes = null;
|
||||
result.outlineAttributes = null;
|
||||
result = null;
|
||||
|
||||
resolve(this);
|
||||
|
@ -158,6 +164,8 @@ class PolygonLayer extends Layer {
|
|||
|
||||
var flat = true;
|
||||
|
||||
var outlineAttributes = [];
|
||||
|
||||
// For each polygon
|
||||
var attributes = coordinates.map(_coordinates => {
|
||||
// Convert coordinates to earcut format
|
||||
|
@ -230,6 +238,13 @@ class PolygonLayer extends Layer {
|
|||
facesCount: _faces.length
|
||||
};
|
||||
|
||||
if (options.style.outline) {
|
||||
var outlineColour = new THREE.Color();
|
||||
outlineColour.set(options.style.outlineColor || 0x000000);
|
||||
|
||||
outlineAttributes.push(PolygonLayer.Set2DOutline(_coordinates, outlineColour));
|
||||
}
|
||||
|
||||
if (options.interactive && options.pickingId) {
|
||||
// Inject picking ID
|
||||
polygon.pickingId = options.pickingId;
|
||||
|
@ -241,6 +256,7 @@ class PolygonLayer extends Layer {
|
|||
|
||||
resolve({
|
||||
attributes: attributes,
|
||||
outlineAttributes: outlineAttributes,
|
||||
flat: flat
|
||||
});
|
||||
});
|
||||
|
@ -250,6 +266,10 @@ class PolygonLayer extends Layer {
|
|||
return this._bufferAttributes;
|
||||
}
|
||||
|
||||
getOutlineBufferAttributes() {
|
||||
return this._outlineBufferAttributes;
|
||||
}
|
||||
|
||||
// Used by external components to clear some memory when the attributes
|
||||
// are no longer required to be stored in this layer
|
||||
//
|
||||
|
@ -257,6 +277,64 @@ class PolygonLayer extends Layer {
|
|||
// using something like the GeoJSONLayer
|
||||
clearBufferAttributes() {
|
||||
this._bufferAttributes = null;
|
||||
this._outlineBufferAttributes = null;
|
||||
}
|
||||
|
||||
// Threshold angle is currently in rads
|
||||
static Set2DOutline(coordinates, colour) {
|
||||
var _vertices = [];
|
||||
|
||||
coordinates.forEach((ring) => {
|
||||
var _ring = ring.map((coordinate) => {
|
||||
return [coordinate.x, 0, coordinate.y];
|
||||
});
|
||||
|
||||
// Add in duplicate vertices for line segments to work
|
||||
var verticeCount = _ring.length;
|
||||
var first = true;
|
||||
while (--verticeCount) {
|
||||
if (first || verticeCount === 0) {
|
||||
first = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
_ring.splice(verticeCount + 1, 0, _ring[verticeCount]);
|
||||
}
|
||||
|
||||
_vertices = _vertices.concat(_ring);
|
||||
});
|
||||
|
||||
_colour = [colour.r, colour.g, colour.b];
|
||||
|
||||
var vertices = new Float32Array(_vertices.length * 3);
|
||||
var colours = new Float32Array(_vertices.length * 3);
|
||||
|
||||
var lastIndex = 0;
|
||||
|
||||
for (var i = 0; i < _vertices.length; i++) {
|
||||
var ax = _vertices[i][0];
|
||||
var ay = _vertices[i][1];
|
||||
var az = _vertices[i][2];
|
||||
|
||||
var c1 = _colour;
|
||||
|
||||
vertices[lastIndex * 3 + 0] = ax;
|
||||
vertices[lastIndex * 3 + 1] = ay;
|
||||
vertices[lastIndex * 3 + 2] = az;
|
||||
|
||||
colours[lastIndex * 3 + 0] = c1[0];
|
||||
colours[lastIndex * 3 + 1] = c1[1];
|
||||
colours[lastIndex * 3 + 2] = c1[2];
|
||||
|
||||
lastIndex++;
|
||||
}
|
||||
|
||||
var attributes = {
|
||||
positions: vertices,
|
||||
colors: colours
|
||||
};
|
||||
|
||||
return attributes;
|
||||
}
|
||||
|
||||
// Used by external components to clear some memory when the coordinates
|
||||
|
|
|
@ -23,6 +23,8 @@ var shadow = new THREE.Color(0x666666);
|
|||
var GeoJSON = (function() {
|
||||
var defaultStyle = {
|
||||
color: '#ffffff',
|
||||
outline: false,
|
||||
outlineColor: '#000000',
|
||||
transparent: false,
|
||||
opacity: 1,
|
||||
blending: THREE.NormalBlending,
|
||||
|
|
Ładowanie…
Reference in New Issue