Skip to content

Instantly share code, notes, and snippets.

@XavierGimenez
Last active April 13, 2017 14:10
Show Gist options
  • Save XavierGimenez/ad54cb01f190538a334a40a07dd356db to your computer and use it in GitHub Desktop.
Save XavierGimenez/ad54cb01f190538a334a40a07dd356db to your computer and use it in GitHub Desktop.
Flow lines with openlayers maps

A way to visualize flows between points in a map. Since this is done by modifying the segments that shape the line feature, width, color, opacity and other attributes can be controlled through all the line. In this case, increasing the line width and the opacity as the line goes from a source to a target.

As this example does clustering on the features, each change on the zoom resolution recalculates the flow lines.

Check flow-lines.js for the relevant stuff

Arcs are created by calculating Great Circles, thanks to arc.js

Not tested with hundreds or thousands of connections, so need to think about this beyond inmediate solutions such reducing the resolution of the arcs.

'use strict';
var D2R = Math.PI / 180;
var R2D = 180 / Math.PI;
var Coord = function(lon,lat) {
this.lon = lon;
this.lat = lat;
this.x = D2R * lon;
this.y = D2R * lat;
};
Coord.prototype.view = function() {
return String(this.lon).slice(0, 4) + ',' + String(this.lat).slice(0, 4);
};
Coord.prototype.antipode = function() {
var anti_lat = -1 * this.lat;
var anti_lon = (this.lon < 0) ? 180 + this.lon : (180 - this.lon) * -1;
return new Coord(anti_lon, anti_lat);
};
var LineString = function() {
this.coords = [];
this.length = 0;
};
LineString.prototype.move_to = function(coord) {
this.length++;
this.coords.push(coord);
};
var Arc = function(properties) {
this.properties = properties || {};
this.geometries = [];
};
Arc.prototype.json = function() {
if (this.geometries.length <= 0) {
return {'geometry': { 'type': 'LineString', 'coordinates': null },
'type': 'Feature', 'properties': this.properties
};
} else if (this.geometries.length == 1) {
return {'geometry': { 'type': 'LineString', 'coordinates': this.geometries[0].coords },
'type': 'Feature', 'properties': this.properties
};
} else {
var multiline = [];
for (var i = 0; i < this.geometries.length; i++) {
multiline.push(this.geometries[i].coords);
}
return {'geometry': { 'type': 'MultiLineString', 'coordinates': multiline },
'type': 'Feature', 'properties': this.properties
};
}
};
// TODO - output proper multilinestring
Arc.prototype.wkt = function() {
var wkt_string = '';
var wkt = 'LINESTRING(';
var collect = function(c) { wkt += c[0] + ' ' + c[1] + ','; };
for (var i = 0; i < this.geometries.length; i++) {
if (this.geometries[i].coords.length === 0) {
return 'LINESTRING(empty)';
} else {
var coords = this.geometries[i].coords;
coords.forEach(collect);
wkt_string += wkt.substring(0, wkt.length - 1) + ')';
}
}
return wkt_string;
};
/*
* http://en.wikipedia.org/wiki/Great-circle_distance
*
*/
var GreatCircle = function(start,end,properties) {
if (!start || start.x === undefined || start.y === undefined) {
throw new Error("GreatCircle constructor expects two args: start and end objects with x and y properties");
}
if (!end || end.x === undefined || end.y === undefined) {
throw new Error("GreatCircle constructor expects two args: start and end objects with x and y properties");
}
this.start = new Coord(start.x,start.y);
this.end = new Coord(end.x,end.y);
this.properties = properties || {};
var w = this.start.x - this.end.x;
var h = this.start.y - this.end.y;
var z = Math.pow(Math.sin(h / 2.0), 2) +
Math.cos(this.start.y) *
Math.cos(this.end.y) *
Math.pow(Math.sin(w / 2.0), 2);
this.g = 2.0 * Math.asin(Math.sqrt(z));
if (this.g == Math.PI) {
throw new Error('it appears ' + start.view() + ' and ' + end.view() + " are 'antipodal', e.g diametrically opposite, thus there is no single route but rather infinite");
} else if (isNaN(this.g)) {
throw new Error('could not calculate great circle between ' + start + ' and ' + end);
}
};
/*
* http://williams.best.vwh.net/avform.htm#Intermediate
*/
GreatCircle.prototype.interpolate = function(f) {
var A = Math.sin((1 - f) * this.g) / Math.sin(this.g);
var B = Math.sin(f * this.g) / Math.sin(this.g);
var x = A * Math.cos(this.start.y) * Math.cos(this.start.x) + B * Math.cos(this.end.y) * Math.cos(this.end.x);
var y = A * Math.cos(this.start.y) * Math.sin(this.start.x) + B * Math.cos(this.end.y) * Math.sin(this.end.x);
var z = A * Math.sin(this.start.y) + B * Math.sin(this.end.y);
var lat = R2D * Math.atan2(z, Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)));
var lon = R2D * Math.atan2(y, x);
return [lon, lat];
};
/*
* Generate points along the great circle
*/
GreatCircle.prototype.Arc = function(npoints,options) {
var first_pass = [];
if (!npoints || npoints <= 2) {
first_pass.push([this.start.lon, this.start.lat]);
first_pass.push([this.end.lon, this.end.lat]);
} else {
var delta = 1.0 / (npoints - 1);
for (var i = 0; i < npoints; ++i) {
var step = delta * i;
var pair = this.interpolate(step);
first_pass.push(pair);
}
}
/* partial port of dateline handling from:
gdal/ogr/ogrgeometryfactory.cpp
TODO - does not handle all wrapping scenarios yet
*/
var bHasBigDiff = false;
var dfMaxSmallDiffLong = 0;
// from http://www.gdal.org/ogr2ogr.html
// -datelineoffset:
// (starting with GDAL 1.10) offset from dateline in degrees (default long. = +/- 10deg, geometries within 170deg to -170deg will be splited)
var dfDateLineOffset = options && options.offset ? options.offset : 10;
var dfLeftBorderX = 180 - dfDateLineOffset;
var dfRightBorderX = -180 + dfDateLineOffset;
var dfDiffSpace = 360 - dfDateLineOffset;
// https://github.com/OSGeo/gdal/blob/7bfb9c452a59aac958bff0c8386b891edf8154ca/gdal/ogr/ogrgeometryfactory.cpp#L2342
for (var j = 1; j < first_pass.length; ++j) {
var dfPrevX = first_pass[j-1][0];
var dfX = first_pass[j][0];
var dfDiffLong = Math.abs(dfX - dfPrevX);
if (dfDiffLong > dfDiffSpace &&
((dfX > dfLeftBorderX && dfPrevX < dfRightBorderX) || (dfPrevX > dfLeftBorderX && dfX < dfRightBorderX))) {
bHasBigDiff = true;
} else if (dfDiffLong > dfMaxSmallDiffLong) {
dfMaxSmallDiffLong = dfDiffLong;
}
}
var poMulti = [];
if (bHasBigDiff && dfMaxSmallDiffLong < dfDateLineOffset) {
var poNewLS = [];
poMulti.push(poNewLS);
for (var k = 0; k < first_pass.length; ++k) {
var dfX0 = parseFloat(first_pass[k][0]);
if (k > 0 && Math.abs(dfX0 - first_pass[k-1][0]) > dfDiffSpace) {
var dfX1 = parseFloat(first_pass[k-1][0]);
var dfY1 = parseFloat(first_pass[k-1][1]);
var dfX2 = parseFloat(first_pass[k][0]);
var dfY2 = parseFloat(first_pass[k][1]);
if (dfX1 > -180 && dfX1 < dfRightBorderX && dfX2 == 180 &&
k+1 < first_pass.length &&
first_pass[k-1][0] > -180 && first_pass[k-1][0] < dfRightBorderX)
{
poNewLS.push([-180, first_pass[k][1]]);
k++;
poNewLS.push([first_pass[k][0], first_pass[k][1]]);
continue;
} else if (dfX1 > dfLeftBorderX && dfX1 < 180 && dfX2 == -180 &&
k+1 < first_pass.length &&
first_pass[k-1][0] > dfLeftBorderX && first_pass[k-1][0] < 180)
{
poNewLS.push([180, first_pass[k][1]]);
k++;
poNewLS.push([first_pass[k][0], first_pass[k][1]]);
continue;
}
if (dfX1 < dfRightBorderX && dfX2 > dfLeftBorderX)
{
// swap dfX1, dfX2
var tmpX = dfX1;
dfX1 = dfX2;
dfX2 = tmpX;
// swap dfY1, dfY2
var tmpY = dfY1;
dfY1 = dfY2;
dfY2 = tmpY;
}
if (dfX1 > dfLeftBorderX && dfX2 < dfRightBorderX) {
dfX2 += 360;
}
if (dfX1 <= 180 && dfX2 >= 180 && dfX1 < dfX2)
{
var dfRatio = (180 - dfX1) / (dfX2 - dfX1);
var dfY = dfRatio * dfY2 + (1 - dfRatio) * dfY1;
poNewLS.push([first_pass[k-1][0] > dfLeftBorderX ? 180 : -180, dfY]);
poNewLS = [];
poNewLS.push([first_pass[k-1][0] > dfLeftBorderX ? -180 : 180, dfY]);
poMulti.push(poNewLS);
}
else
{
poNewLS = [];
poMulti.push(poNewLS);
}
poNewLS.push([dfX0, first_pass[k][1]]);
} else {
poNewLS.push([first_pass[k][0], first_pass[k][1]]);
}
}
} else {
// add normally
var poNewLS0 = [];
poMulti.push(poNewLS0);
for (var l = 0; l < first_pass.length; ++l) {
poNewLS0.push([first_pass[l][0],first_pass[l][1]]);
}
}
var arc = new Arc(this.properties);
for (var m = 0; m < poMulti.length; ++m) {
var line = new LineString();
arc.geometries.push(line);
var points = poMulti[m];
for (var j0 = 0; j0 < points.length; ++j0) {
line.move_to(points[j0]);
}
}
return arc;
};
if (typeof window === 'undefined') {
// nodejs
module.exports.Coord = Coord;
module.exports.Arc = Arc;
module.exports.GreatCircle = GreatCircle;
} else {
// browser
var arc = {};
arc.Coord = Coord;
arc.Arc = Arc;
arc.GreatCircle = GreatCircle;
}
// data with source and target connections
var data = [
{
"TargetPlaceLongitude":7.537148310785445,
"TargetPlaceLatitude":48.05013590883186,
"SourcePlaceLongitude":-73.935242,
"SourcePlaceLatitude":40.730610
},
{
"TargetPlaceLongitude":0.9,
"TargetPlaceLatitude":51.883333,
"SourcePlaceLongitude":-73.935242,
"SourcePlaceLatitude":40.730610
},
{
"TargetPlaceLongitude":0.9,
"TargetPlaceLatitude":51.883333,
"SourcePlaceLongitude":-73.935242,
"SourcePlaceLatitude":40.730610
},
{
"TargetPlaceLongitude":-6.115818,
"TargetPlaceLatitude":34.60144,
"SourcePlaceLongitude":-73.935242,
"SourcePlaceLatitude":40.730610
},
{
"TargetPlaceLongitude":7.110187967092899,
"TargetPlaceLatitude":50.70588797011724,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":6.972946051369628,
"TargetPlaceLatitude":50.94579677501803,
"SourcePlaceLongitude":-73.935242,
"SourcePlaceLatitude":40.730610
},
{
"TargetPlaceLongitude":5.478970083150136,
"TargetPlaceLatitude":48.3925857410519,
"SourcePlaceLongitude":-73.935242,
"SourcePlaceLatitude":40.730610
},
{
"TargetPlaceLongitude":-5.64613913717677,
"TargetPlaceLatitude":37.63719595406285,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-2.016667,
"TargetPlaceLatitude":54.966667,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":5.859722,
"TargetPlaceLatitude":49.540278,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":8.97683927730332,
"TargetPlaceLatitude":50.085588186218686,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":0.9,
"TargetPlaceLatitude":51.883333,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-1.083333,
"TargetPlaceLatitude":53.966667,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-5.557032,
"TargetPlaceLatitude":34.073697,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":9.330391,
"TargetPlaceLatitude":49.539523,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-5.64613913717677,
"TargetPlaceLatitude":37.63719595406285,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-5.64613913717677,
"TargetPlaceLatitude":37.63719595406285,
"SourcePlaceLongitude":-73.935242,
"SourcePlaceLatitude":40.730610
},
{
"TargetPlaceLongitude":0.9,
"TargetPlaceLatitude":51.883333,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-1.983333,
"TargetPlaceLatitude":51.733333,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":8.241355718583725,
"TargetPlaceLatitude":49.974235538721146,
"SourcePlaceLongitude":-73.935242,
"SourcePlaceLatitude":40.730610
},
{
"TargetPlaceLongitude":0.9,
"TargetPlaceLatitude":51.883333,
"SourcePlaceLongitude":-73.935242,
"SourcePlaceLatitude":40.730610
},
{
"TargetPlaceLongitude":-0.093145,
"TargetPlaceLatitude":51.514248,
"SourcePlaceLongitude":-73.935242,
"SourcePlaceLatitude":40.730610
},
{
"TargetPlaceLongitude":-5.64613913717677,
"TargetPlaceLatitude":37.63719595406285,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":8.97683927730332,
"TargetPlaceLatitude":50.085588186218686,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":0.9,
"TargetPlaceLatitude":51.883333,
"SourcePlaceLongitude":-73.935242,
"SourcePlaceLatitude":40.730610
},
{
"TargetPlaceLongitude":-1.083333,
"TargetPlaceLatitude":53.966667,
"SourcePlaceLongitude":-73.935242,
"SourcePlaceLatitude":40.730610
},
{
"TargetPlaceLongitude":7.110187967092899,
"TargetPlaceLatitude":50.70588797011724,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-1.983333,
"TargetPlaceLatitude":51.733333,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":8.97683927730332,
"TargetPlaceLatitude":50.085588186218686,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":0.9,
"TargetPlaceLatitude":51.883333,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-1.083333,
"TargetPlaceLatitude":53.966667,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":8.97683927730332,
"TargetPlaceLatitude":50.085588186218686,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-1.083333,
"TargetPlaceLatitude":53.966667,
"SourcePlaceLongitude":-73.935242,
"SourcePlaceLatitude":40.730610
},
{
"TargetPlaceLongitude":5.859722,
"TargetPlaceLatitude":49.540278,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-5.557032,
"TargetPlaceLatitude":34.073697,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-1.066667,
"TargetPlaceLatitude":51.35,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":5.478970083150136,
"TargetPlaceLatitude":48.3925857410519,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-0.093145,
"TargetPlaceLatitude":51.514248,
"SourcePlaceLongitude":-73.935242,
"SourcePlaceLatitude":40.730610
},
{
"TargetPlaceLongitude":-1.083333,
"TargetPlaceLatitude":53.966667,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":6.972946051369628,
"TargetPlaceLatitude":50.94579677501803,
"SourcePlaceLongitude":null,
"SourcePlaceLatitude":null
},
{
"TargetPlaceLongitude":0.6371623361290796,
"TargetPlaceLatitude":43.22707597466809,
"SourcePlaceLongitude":-73.935242,
"SourcePlaceLatitude":40.730610
},
{
"TargetPlaceLongitude":9.330391,
"TargetPlaceLatitude":49.539523,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-2.916667,
"TargetPlaceLatitude":53.2,
"SourcePlaceLongitude":-73.935242,
"SourcePlaceLatitude":40.730610
},
{
"TargetPlaceLongitude":7.110187967092899,
"TargetPlaceLatitude":50.70588797011724,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-0.5568138715542259,
"TargetPlaceLatitude":47.476690907826885,
"SourcePlaceLongitude":-73.935242,
"SourcePlaceLatitude":40.730610
},
{
"TargetPlaceLongitude":0.9,
"TargetPlaceLatitude":51.883333,
"SourcePlaceLongitude":null,
"SourcePlaceLatitude":null
},
{
"TargetPlaceLongitude":-1.066667,
"TargetPlaceLatitude":51.35,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-5.64613913717677,
"TargetPlaceLatitude":37.63719595406285,
"SourcePlaceLongitude":null,
"SourcePlaceLatitude":null
},
{
"TargetPlaceLongitude":5.478970083150136,
"TargetPlaceLatitude":48.3925857410519,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":3.443291,
"TargetPlaceLatitude":43.280977,
"SourcePlaceLongitude":null,
"SourcePlaceLatitude":null
},
{
"TargetPlaceLongitude":0.9,
"TargetPlaceLatitude":51.883333,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-0.093145,
"TargetPlaceLatitude":51.514248,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-1.083333,
"TargetPlaceLatitude":53.966667,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":8.97683927730332,
"TargetPlaceLatitude":50.085588186218686,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-2.016667,
"TargetPlaceLatitude":54.966667,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":5.859722,
"TargetPlaceLatitude":49.540278,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-5.64613913717677,
"TargetPlaceLatitude":37.63719595406285,
"SourcePlaceLongitude":-73.935242,
"SourcePlaceLatitude":40.730610
},
{
"TargetPlaceLongitude":9.330391,
"TargetPlaceLatitude":49.539523,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-0.093145,
"TargetPlaceLatitude":51.514248,
"SourcePlaceLongitude":-73.935242,
"SourcePlaceLatitude":40.730610
},
{
"TargetPlaceLongitude":7.537148310785445,
"TargetPlaceLatitude":48.05013590883186,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-1.983333,
"TargetPlaceLatitude":51.733333,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":8.97683927730332,
"TargetPlaceLatitude":50.085588186218686,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-5.64613913717677,
"TargetPlaceLatitude":37.63719595406285,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":0.9,
"TargetPlaceLatitude":51.883333,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":0.9,
"TargetPlaceLatitude":51.883333,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":6.972946051369628,
"TargetPlaceLatitude":50.94579677501803,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-5.64613913717677,
"TargetPlaceLatitude":37.63719595406285,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":7.110187967092899,
"TargetPlaceLatitude":50.70588797011724,
"SourcePlaceLongitude":-73.935242,
"SourcePlaceLatitude":40.730610
},
{
"TargetPlaceLongitude":-6.115818,
"TargetPlaceLatitude":34.60144,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-1.083333,
"TargetPlaceLatitude":53.966667,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-5.64613913717677,
"TargetPlaceLatitude":37.63719595406285,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":0.9,
"TargetPlaceLatitude":51.883333,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":0.9,
"TargetPlaceLatitude":51.883333,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-2.678333,
"TargetPlaceLatitude":51.007222,
"SourcePlaceLongitude":-73.935242,
"SourcePlaceLatitude":40.730610
},
{
"TargetPlaceLongitude":8.241355718583725,
"TargetPlaceLatitude":49.974235538721146,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":5.478970083150136,
"TargetPlaceLatitude":48.3925857410519,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-5.64613913717677,
"TargetPlaceLatitude":37.63719595406285,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-2.958889,
"TargetPlaceLatitude":51.613333,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":0.9,
"TargetPlaceLatitude":51.883333,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":5.478970083150136,
"TargetPlaceLatitude":48.3925857410519,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-0.75,
"TargetPlaceLatitude":45.5,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":4.942851,
"TargetPlaceLatitude":43.383543,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-5.557032,
"TargetPlaceLatitude":34.073697,
"SourcePlaceLongitude":-73.935242,
"SourcePlaceLatitude":40.730610
},
{
"TargetPlaceLongitude":-0.093145,
"TargetPlaceLatitude":51.514248,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-1.083333,
"TargetPlaceLatitude":53.966667,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":8.97683927730332,
"TargetPlaceLatitude":50.085588186218686,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-0.533333,
"TargetPlaceLatitude":53.233333,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":7.110187967092899,
"TargetPlaceLatitude":50.70588797011724,
"SourcePlaceLongitude":-73.935242,
"SourcePlaceLatitude":40.730610
},
{
"TargetPlaceLongitude":0.6371623361290796,
"TargetPlaceLatitude":43.22707597466809,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-2.916667,
"TargetPlaceLatitude":53.2,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-2.678333,
"TargetPlaceLatitude":51.007222,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":8.97683927730332,
"TargetPlaceLatitude":50.085588186218686,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-5.64613913717677,
"TargetPlaceLatitude":37.63719595406285,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":0.9,
"TargetPlaceLatitude":51.883333,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":5.478970083150136,
"TargetPlaceLatitude":48.3925857410519,
"SourcePlaceLongitude":-73.935242,
"SourcePlaceLatitude":40.730610
},
{
"TargetPlaceLongitude":7.537148310785445,
"TargetPlaceLatitude":48.05013590883186,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":6.972946051369628,
"TargetPlaceLatitude":50.94579677501803,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-2.958889,
"TargetPlaceLatitude":51.613333,
"SourcePlaceLongitude":-73.935242,
"SourcePlaceLatitude":40.730610
},
{
"TargetPlaceLongitude":5.478970083150136,
"TargetPlaceLatitude":48.3925857410519,
"SourcePlaceLongitude":-73.935242,
"SourcePlaceLatitude":40.730610
},
{
"TargetPlaceLongitude":0.9,
"TargetPlaceLatitude":51.883333,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":0.9,
"TargetPlaceLatitude":51.883333,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-0.75,
"TargetPlaceLatitude":45.5,
"SourcePlaceLongitude":-73.935242,
"SourcePlaceLatitude":40.730610
},
{
"TargetPlaceLongitude":8.820762299133417,
"TargetPlaceLatitude":49.90610992846929,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-6.115818,
"TargetPlaceLatitude":34.60144,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-1.083333,
"TargetPlaceLatitude":53.966667,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":5.478970083150136,
"TargetPlaceLatitude":48.3925857410519,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":0.9,
"TargetPlaceLatitude":51.883333,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-0.093145,
"TargetPlaceLatitude":51.514248,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":4.942851,
"TargetPlaceLatitude":43.383543,
"SourcePlaceLongitude":-73.935242,
"SourcePlaceLatitude":40.730610
},
{
"TargetPlaceLongitude":-5.557032,
"TargetPlaceLatitude":34.073697,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-2.016667,
"TargetPlaceLatitude":54.966667,
"SourcePlaceLongitude":null,
"SourcePlaceLatitude":null
},
{
"TargetPlaceLongitude":-2.016667,
"TargetPlaceLatitude":54.966667,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":7.110187967092899,
"TargetPlaceLatitude":50.70588797011724,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-0.533333,
"TargetPlaceLatitude":53.233333,
"SourcePlaceLongitude":-73.935242,
"SourcePlaceLatitude":40.730610
},
{
"TargetPlaceLongitude":-1.066667,
"TargetPlaceLatitude":51.35,
"SourcePlaceLongitude":-73.935242,
"SourcePlaceLatitude":40.730610
},
{
"TargetPlaceLongitude":-0.093145,
"TargetPlaceLatitude":51.514248,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-1.083333,
"TargetPlaceLatitude":53.966667,
"SourcePlaceLongitude":-73.935242,
"SourcePlaceLatitude":40.730610
},
{
"TargetPlaceLongitude":-0.5568138715542259,
"TargetPlaceLatitude":47.476690907826885,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":5.859722,
"TargetPlaceLatitude":49.540278,
"SourcePlaceLongitude":-73.935242,
"SourcePlaceLatitude":40.730610
},
{
"TargetPlaceLongitude":8.97683927730332,
"TargetPlaceLatitude":50.085588186218686,
"SourcePlaceLongitude":-73.935242,
"SourcePlaceLatitude":40.730610
},
{
"TargetPlaceLongitude":-1.083333,
"TargetPlaceLatitude":53.966667,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":8.97683927730332,
"TargetPlaceLatitude":50.085588186218686,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":0.6371623361290796,
"TargetPlaceLatitude":43.22707597466809,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":9.330391,
"TargetPlaceLatitude":49.539523,
"SourcePlaceLongitude":-73.935242,
"SourcePlaceLatitude":40.730610
},
{
"TargetPlaceLongitude":-2.916667,
"TargetPlaceLatitude":53.2,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-5.64613913717677,
"TargetPlaceLatitude":37.63719595406285,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":8.241355718583725,
"TargetPlaceLatitude":49.974235538721146,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-0.093145,
"TargetPlaceLatitude":51.514248,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":3.484632753011144,
"TargetPlaceLatitude":43.308831654101574,
"SourcePlaceLongitude":null,
"SourcePlaceLatitude":null
},
{
"TargetPlaceLongitude":-0.093145,
"TargetPlaceLatitude":51.514248,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-5.64613913717677,
"TargetPlaceLatitude":37.63719595406285,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":0.9,
"TargetPlaceLatitude":51.883333,
"SourcePlaceLongitude":-73.935242,
"SourcePlaceLatitude":40.730610
},
{
"TargetPlaceLongitude":-1.983333,
"TargetPlaceLatitude":51.733333,
"SourcePlaceLongitude":-73.935242,
"SourcePlaceLatitude":40.730610
},
{
"TargetPlaceLongitude":7.110187967092899,
"TargetPlaceLatitude":50.70588797011724,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":0.9,
"TargetPlaceLatitude":51.883333,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-5.64613913717677,
"TargetPlaceLatitude":37.63719595406285,
"SourcePlaceLongitude":-73.935242,
"SourcePlaceLatitude":40.730610
},
{
"TargetPlaceLongitude":-5.64613913717677,
"TargetPlaceLatitude":37.63719595406285,
"SourcePlaceLongitude":-73.935242,
"SourcePlaceLatitude":40.730610
},
{
"TargetPlaceLongitude":8.97683927730332,
"TargetPlaceLatitude":50.085588186218686,
"SourcePlaceLongitude":-73.935242,
"SourcePlaceLatitude":40.730610
},
{
"TargetPlaceLongitude":5.478970083150136,
"TargetPlaceLatitude":48.3925857410519,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-0.093145,
"TargetPlaceLatitude":51.514248,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":5.478970083150136,
"TargetPlaceLatitude":48.3925857410519,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-0.75,
"TargetPlaceLatitude":45.5,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-2.958889,
"TargetPlaceLatitude":51.613333,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":3.484632753011144,
"TargetPlaceLatitude":43.308831654101574,
"SourcePlaceLongitude":null,
"SourcePlaceLatitude":null
},
{
"TargetPlaceLongitude":-1.083333,
"TargetPlaceLatitude":53.966667,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-0.093145,
"TargetPlaceLatitude":51.514248,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-0.5568138715542259,
"TargetPlaceLatitude":47.476690907826885,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":4.942851,
"TargetPlaceLatitude":43.383543,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-0.5568138715542259,
"TargetPlaceLatitude":47.476690907826885,
"SourcePlaceLongitude":null,
"SourcePlaceLatitude":null
},
{
"TargetPlaceLongitude":0.6371623361290796,
"TargetPlaceLatitude":43.22707597466809,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-2.916667,
"TargetPlaceLatitude":53.2,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-0.533333,
"TargetPlaceLatitude":53.233333,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-1.066667,
"TargetPlaceLatitude":51.35,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-0.093145,
"TargetPlaceLatitude":51.514248,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":7.110187967092899,
"TargetPlaceLatitude":50.70588797011724,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":8.97683927730332,
"TargetPlaceLatitude":50.085588186218686,
"SourcePlaceLongitude":-73.935242,
"SourcePlaceLatitude":40.730610
},
{
"TargetPlaceLongitude":0.9,
"TargetPlaceLatitude":51.883333,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-2.678333,
"TargetPlaceLatitude":51.007222,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-5.64613913717677,
"TargetPlaceLatitude":37.63719595406285,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-1.083333,
"TargetPlaceLatitude":53.966667,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-5.64613913717677,
"TargetPlaceLatitude":37.63719595406285,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-2.016667,
"TargetPlaceLatitude":54.966667,
"SourcePlaceLongitude":-73.935242,
"SourcePlaceLatitude":40.730610
},
{
"TargetPlaceLongitude":-0.5568138715542259,
"TargetPlaceLatitude":47.476690907826885,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":4.942851,
"TargetPlaceLatitude":43.383543,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":0.9,
"TargetPlaceLatitude":51.883333,
"SourcePlaceLongitude":-73.935242,
"SourcePlaceLatitude":40.730610
},
{
"TargetPlaceLongitude":-0.533333,
"TargetPlaceLatitude":53.233333,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":5.478970083150136,
"TargetPlaceLatitude":48.3925857410519,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-5.64613913717677,
"TargetPlaceLatitude":37.63719595406285,
"SourcePlaceLongitude":-73.935242,
"SourcePlaceLatitude":40.730610
},
{
"TargetPlaceLongitude":-5.64613913717677,
"TargetPlaceLatitude":37.63719595406285,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":8.241355718583725,
"TargetPlaceLatitude":49.974235538721146,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-0.093145,
"TargetPlaceLatitude":51.514248,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":7.04043866023253,
"TargetPlaceLatitude":46.8810261270914,
"SourcePlaceLongitude":null,
"SourcePlaceLatitude":null
},
{
"TargetPlaceLongitude":5.478970083150136,
"TargetPlaceLatitude":48.3925857410519,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-0.75,
"TargetPlaceLatitude":45.5,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-2.958889,
"TargetPlaceLatitude":51.613333,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":0.9,
"TargetPlaceLatitude":51.883333,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":7.537148310785445,
"TargetPlaceLatitude":48.05013590883186,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-2.678333,
"TargetPlaceLatitude":51.007222,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-6.115818,
"TargetPlaceLatitude":34.60144,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-5.64613913717677,
"TargetPlaceLatitude":37.63719595406285,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":0.9,
"TargetPlaceLatitude":51.883333,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":0.9,
"TargetPlaceLatitude":51.883333,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":6.972946051369628,
"TargetPlaceLatitude":50.94579677501803,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
},
{
"TargetPlaceLongitude":-5.64613913717677,
"TargetPlaceLatitude":37.63719595406285,
"SourcePlaceLongitude":44.783333,
"SourcePlaceLatitude":41.716667
}
];
// width scale for connections. Domain will change
// every time the zoom changes and features are
// reclustered
var lineWidthScale = d3.scale.linear().range([1, 35]);
// connections will be gradients, set here the
// maximum alpha they can reach
var maxOpacityLine = .5;
// radius range for cluster features
var scale = d3.scale.linear()
.range([10, 75])
.domain([1, data.length]);
// define map
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.XYZ({
url:'http://server.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Light_Gray_Base/MapServer/tile/{z}/{y}/{x}'
})
})
],
view: new ol.View({
center: ol.proj.fromLonLat([2.36, 41.19]),
zoom: 4,
minZoom : 1,
maxZoom : 10
})
});
// create feature from data
var features = _(data)
.map(function(place) {
return new ol.Feature({
geometry : new ol.geom.Point(
ol.proj.fromLonLat([
place.TargetPlaceLongitude,
place.TargetPlaceLatitude], 'EPSG:3857')),
place : place
})
})
.value();
// assign style to the clustered feature based on data
var getFeatureStyles = function(feature) {
var size = feature.get('features').length,
styleInner = new ol.style.Style({
image: new ol.style.Circle({
radius: 1,
fill: new ol.style.Fill({
color: 'rgba(200, 0, 0, 5)'
})
})
}),
styleOuter = new ol.style.Style({
image: new ol.style.Circle({
radius: scale(size),
stroke: new ol.style.Stroke({
color : 'rgba(200, 0, 0, .5)',
width: 1
}),
fill: new ol.style.Fill({
color : 'rgba(200, 0, 0, .5)'
})
})
});
return [styleOuter, styleInner];
}
var listenSourceChanges = function(layer) {
// the cluster source changes as the map resolution changes,
// so the connections layer does the same. Listen for change
// event and update the connection accordingly, throttling the
// listener to avoid too updates
layer.getSource().on('change',
_.throttle(function() {
createConnectionLayer(layer);
},
500,
{ 'leading': false, 'trailing': true })
);
}
// add layer with clustered features
var layer = new ol.layer.Vector({
source: new ol.source.Cluster({
distance: 40,
source: new ol.source.Vector({ features: features })
}),
style: function(feature) {
return getFeatureStyles(feature)
}
});
layer.on('change:source', function() {
listenSourceChanges(layer);
});
listenSourceChanges(layer);
map.addLayer(layer);
map.getView().on('change:resolution', function(event) {
map.removeLayer(connectionLayer);
});
// create connections
var connectionLayer;
var createConnectionLayer = function(cluster_layer) {
// for each clustered feature, summarize the
// connections between this point and the
// production places connected with it
var connectionsSummary =
_(cluster_layer.getSource().getFeatures())
// get array of production places and
// its occurrences for this cluster
.map(function(clusteredFeature) {
return {
cluster: clusteredFeature,
summary : dl.groupby(function(feature) {
return feature.get('place').SourcePlaceLongitude + '@' + feature.get('place').SourcePlaceLatitude;
})
.execute(
_.filter(clusteredFeature.get('features'),
function(feature) {
return !!feature.get('place').SourcePlaceLatitude && !!feature.get('place').SourcePlaceLongitude;
})
)
}
})
// remove clusters with all its binding
// without Production Places
.filter(function(connectionSummary) {
return connectionSummary.summary.length > 0
})
.value();
if(connectionsSummary.length == 0)
return;
// update domain for line width and opacity connectors
lineWidthScale.domain([
d3.min(connectionsSummary, function(connectionSummary) {
return d3.min(connectionSummary.summary, function(summary) {
return summary.values.length;
})
}),
d3.max(connectionsSummary, function(connectionSummary) {
return d3.max(connectionSummary.summary, function(summary) {
return summary.values.length;
})
})
]);
// generate the Arc features
var arcFeatures = [];
(connectionsSummary).forEach(function(connectionSummary, index) {
// get coordinates for one point of the arc (finding place)
// which is the coords of the cluster feature
var clusterCoord = ol.proj.transform(
connectionSummary.cluster.getGeometry().getCoordinates(),
'EPSG:3857', 'EPSG:4326'
);
connectionSummary.summary.forEach(function(summary) {
// arc has the direction:
// start: findingPlace
// end: production place
var sourceCoord = summary['_0'].split('@');
var arcGenerator = new arc.GreatCircle(
{
x: clusterCoord[0], // lon
y: clusterCoord[1], // lat
},
{
x: sourceCoord[0], //lon
y: sourceCoord[1] //lat
}),
arcLine = arcGenerator.Arc(100, { offset: 10} ),
line = new ol.geom.LineString(arcLine.geometries[0].coords);
line.transform(ol.proj.get('EPSG:4326'), ol.proj.get('EPSG:3857'));
arcFeatures.push(
new ol.Feature({
geometry : line,
bindings : summary.values
})
);
});
});
connectionLayer = new ol.layer.Image({
source: new ol.source.ImageVector({
source: new ol.source.Vector({
wrapX: false,
features : arcFeatures
}),
updateWhileAnimating: false,
updateWhileInteracting: false,
style: function(feature) {
var i = 0,
geometry = feature.getGeometry(),
styles = [],
strokeWidthIncrement = (lineWidthScale(feature.get('bindings').length) - lineWidthScale.range()[0]) / (geometry.getCoordinates().length - 1),
opacityIncrement = maxOpacityLine / (geometry.getCoordinates().length - 1);
geometry.forEachSegment(function (start, end) {
styles.push(new ol.style.Style({
geometry: new ol.geom.LineString([start, end]),
stroke: new ol.style.Stroke({
lineCap : (i==0)? 'round' : 'butt',
lineJoin : 'miter',
color: 'rgba(200, 0, 0, ' + (maxOpacityLine - (opacityIncrement * i)) + ')',
width: lineWidthScale(feature.get('bindings').length) - (strokeWidthIncrement * i)
})
}));
i++;
});
return styles;
}
})
});
map.addLayer(connectionLayer);
};
createConnectionLayer(layer);
console.log("done! ", map);
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>OpenLayers flow lines</title>
<meta name="description" content="The HTML5 Herald">
<meta name="author" content="SitePoint">
<link rel="stylesheet" href="https://openlayers.org/en/v4.0.1/css/ol.css" type="text/css">
<style>
.map {
height: 100%;
width: 100%;
}
</style>
<script src="https://cdn.jsdelivr.net/lodash/4.17.4/lodash.min.js" type="text/javascript"></script>
<script src="https://d3js.org/d3.v3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/datalib/1.7.3/datalib.min.js" type="text/javascript"></script>
<script src="https://openlayers.org/en/v4.0.1/build/ol.js" type="text/javascript"></script>
<script src="arc.js"></script>
</head>
<body>
<div id="map" class="map"></div>
<script src="flow-lines.js"></script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment