mirror of
https://github.com/grafana/grafana.git
synced 2025-02-15 10:03:33 -06:00
removed map2panel
This commit is contained in:
parent
569df6c88f
commit
9cf6a524df
@ -1,92 +0,0 @@
|
|||||||
/**
|
|
||||||
* Hexagonal binning
|
|
||||||
* Rendered as normally projected svg paths, which mean they *do not*
|
|
||||||
* clip on spheres appropriately. To fix this, we would need to translate
|
|
||||||
* the svg path into a geo-path
|
|
||||||
*/
|
|
||||||
function displayBinning(scope, dr, dimensions) {
|
|
||||||
|
|
||||||
var hexbin = d3.hexbin()
|
|
||||||
.size(dimensions)
|
|
||||||
.radius(scope.panel.display.binning.hexagonSize);
|
|
||||||
|
|
||||||
|
|
||||||
var binPoints = [],
|
|
||||||
binnedPoints = [],
|
|
||||||
binRange = 0;
|
|
||||||
|
|
||||||
|
|
||||||
if (scope.panel.display.binning.enabled) {
|
|
||||||
/**
|
|
||||||
* primary field is just binning raw counts
|
|
||||||
*
|
|
||||||
* Secondary field is binning some metric like mean/median/total. Hexbins doesn't support that,
|
|
||||||
* so we cheat a little and just add more points to compensate.
|
|
||||||
* However, we don't want to add a million points, so normalize against the largest value
|
|
||||||
*/
|
|
||||||
if (scope.panel.display.binning.areaEncodingField === 'secondary') {
|
|
||||||
var max = Math.max.apply(Math, _.map(scope.data, function(k,v){return k;})),
|
|
||||||
scale = 50/max;
|
|
||||||
|
|
||||||
_.map(scope.data, function (k, v) {
|
|
||||||
var decoded = geohash.decode(v);
|
|
||||||
return _.map(_.range(0, k*scale), function(a,b) {
|
|
||||||
binPoints.push(dr.projection([decoded.longitude, decoded.latitude]));
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
} else {
|
|
||||||
binPoints = dr.projectedPoints;
|
|
||||||
}
|
|
||||||
|
|
||||||
//bin and sort the points, so we can set the various ranges appropriately
|
|
||||||
binnedPoints = hexbin(binPoints).sort(function(a, b) { return b.length - a.length; });
|
|
||||||
binRange = binnedPoints[0].length;
|
|
||||||
|
|
||||||
//clean up some memory
|
|
||||||
binPoints = [];
|
|
||||||
} else {
|
|
||||||
|
|
||||||
//not enabled, so just set an empty array. D3.exit will take care of the rest
|
|
||||||
binnedPoints = [];
|
|
||||||
binRange = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var radius = d3.scale.sqrt()
|
|
||||||
.domain([0, binRange])
|
|
||||||
.range([0, scope.panel.display.binning.hexagonSize]);
|
|
||||||
|
|
||||||
var color = d3.scale.linear()
|
|
||||||
.domain([0,binRange])
|
|
||||||
.range(["white", "steelblue"])
|
|
||||||
.interpolate(d3.interpolateLab);
|
|
||||||
|
|
||||||
|
|
||||||
var hex = dr.g.selectAll(".hexagon")
|
|
||||||
.data(binnedPoints);
|
|
||||||
|
|
||||||
hex.enter().append("path")
|
|
||||||
.attr("d", function (d) {
|
|
||||||
if (scope.panel.display.binning.areaEncoding === false) {
|
|
||||||
return hexbin.hexagon();
|
|
||||||
} else {
|
|
||||||
return hexbin.hexagon(radius(d.length));
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.attr("class", "hexagon")
|
|
||||||
.attr("transform", function (d) {
|
|
||||||
return "translate(" + d.x + "," + d.y + ")";
|
|
||||||
})
|
|
||||||
.style("fill", function (d) {
|
|
||||||
if (scope.panel.display.binning.colorEncoding === false) {
|
|
||||||
return color(binnedPoints[0].length / 2);
|
|
||||||
} else {
|
|
||||||
return color(d.length);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.attr("opacity", scope.panel.display.binning.hexagonAlpha);
|
|
||||||
|
|
||||||
hex.exit().remove();
|
|
||||||
}
|
|
@ -1,28 +0,0 @@
|
|||||||
/**
|
|
||||||
* Renders bullseyes as geo-json poly gon entities
|
|
||||||
* Allows for them to clip on spheres correctly
|
|
||||||
*/
|
|
||||||
function displayBullseye(scope, dr) {
|
|
||||||
|
|
||||||
var degrees = 180 / Math.PI
|
|
||||||
var circle = d3.geo.circle();
|
|
||||||
var data = [];
|
|
||||||
|
|
||||||
if (scope.panel.display.bullseye.enabled) {
|
|
||||||
data = [
|
|
||||||
circle.origin(parseFloat(scope.panel.display.bullseye.coord.lat), parseFloat(scope.panel.display.bullseye.coord.lon)).angle(1000 / 6371 * degrees)()
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
var arcs = dr.g.selectAll(".arc")
|
|
||||||
.data(data);
|
|
||||||
|
|
||||||
arcs.enter().append("path")
|
|
||||||
|
|
||||||
.attr("d", dr.path)
|
|
||||||
.attr("class", "arc");
|
|
||||||
|
|
||||||
arcs.exit().remove();
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,44 +0,0 @@
|
|||||||
/**
|
|
||||||
* Renders geopoints as geo-json poly gon entities
|
|
||||||
* Allows for them to clip on spheres correctly
|
|
||||||
*/
|
|
||||||
function displayGeopoints(scope, dr) {
|
|
||||||
|
|
||||||
var points = [];
|
|
||||||
var circle = d3.geo.circle();
|
|
||||||
var degrees = 180 / Math.PI
|
|
||||||
|
|
||||||
if (scope.panel.display.geopoints.enabled) {
|
|
||||||
//points = dr.points;
|
|
||||||
|
|
||||||
points = _.map(dr.points, function(v) {
|
|
||||||
return {
|
|
||||||
type: "Point",
|
|
||||||
coordinates: [v[0], v[1]]
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
dr.geopoints = dr.g.selectAll("path.geopoint")
|
|
||||||
.data(points);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
dr.geopoints.enter().append("path")
|
|
||||||
/*
|
|
||||||
.datum(function(d) {
|
|
||||||
return circle.origin([d[0], d[1]]).angle(scope.panel.display.geopoints.pointSize / 6371 * degrees)();
|
|
||||||
})
|
|
||||||
*/
|
|
||||||
.attr("class", "geopoint")
|
|
||||||
.attr("d", dr.path);
|
|
||||||
|
|
||||||
dr.geopoints.exit().remove();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,287 +0,0 @@
|
|||||||
<style>
|
|
||||||
.tabDetails {
|
|
||||||
border-bottom: 1px solid #ddd;
|
|
||||||
padding-bottom:20px;
|
|
||||||
}
|
|
||||||
.tabDetails td {
|
|
||||||
padding-right: 10px;
|
|
||||||
padding-bottom:10px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<div ng-controller="map2">
|
|
||||||
<div class="row-fluid" style="margin-bottom:20px">
|
|
||||||
<div class="span11">
|
|
||||||
The map panel is compatible with either Geopoints or two-letter country codes, depending on the graphing options. Left click to drag/pan map, scroll wheel (or double click) to zoom. Globes can be spun using ctrl-key + drag.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="row-fluid">
|
|
||||||
<div class="span10">
|
|
||||||
<form class="form-horizontal">
|
|
||||||
<div class="control-group">
|
|
||||||
<label class="control-label" for="panelfield">Primary Field</label>
|
|
||||||
<div class="controls">
|
|
||||||
<input type="text" id="panelfield" class="input"
|
|
||||||
ng-model="panel.field"
|
|
||||||
ng-change="get_data()" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="control-group">
|
|
||||||
<label class="control-label" for="panelsecondaryfield">Secondary Field</label>
|
|
||||||
<div class="controls">
|
|
||||||
<input type="text" id="panelsecondaryfield" class="input"
|
|
||||||
ng-model="panel.secondaryfield"
|
|
||||||
ng-change="get_data()"
|
|
||||||
data-placement="right"
|
|
||||||
placeholder="Optional"
|
|
||||||
bs-tooltip="'Allows aggregating on Primary field, while counting stats on a secondary (e.g. Group By user_id, Sum(purchase_price)).'" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="control-group">
|
|
||||||
<label class="control-label" for="panelquery">Query</label>
|
|
||||||
<div class="controls">
|
|
||||||
<input type="text" id="panelquery" class="input" ng-model="panel.query">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row-fluid">
|
|
||||||
<div class="span11">
|
|
||||||
<h4>Display Options</h4>
|
|
||||||
</div>
|
|
||||||
<!--
|
|
||||||
Rolling our own tab control here because the Angular-Strap Tab directive doesn't allow
|
|
||||||
updates to components inside, which is quite bizarre. Or I just can't figure it out...
|
|
||||||
-->
|
|
||||||
|
|
||||||
<div class="span11">
|
|
||||||
<ul class="nav nav-tabs" ng-cloak="">
|
|
||||||
<li ng-repeat="tab in ['Geopoints', 'Binning', 'Choropleth', 'Bullseye', 'Data']" ng-class="{active:isActive(tab)}">
|
|
||||||
<a ng-click="tabClick(tab)">{{tab}}</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row-fluid tabDetails" ng-show="isActive('geopoints')">
|
|
||||||
<div class="span8 offset1">
|
|
||||||
<table>
|
|
||||||
<tbody >
|
|
||||||
<tr>
|
|
||||||
<td>Geopoints</td>
|
|
||||||
<td>
|
|
||||||
<button type="button" class="btn" bs-button
|
|
||||||
data-placement="right"
|
|
||||||
bs-tooltip="'Compatible with Geopoint Type'"
|
|
||||||
ng-change="$emit('render')"
|
|
||||||
ng-class="{'btn-success': panel.display.geopoints.enabled}"
|
|
||||||
ng-model="panel.display.geopoints.enabled">{{panel.display.geopoints.enabled|enabledText}}</button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Point size</td>
|
|
||||||
<td>
|
|
||||||
<input type="text" style="width:100px"
|
|
||||||
ng-change="$emit('render')"
|
|
||||||
data-placement="right"
|
|
||||||
bs-tooltip="'Controls the size of the geopoints on the map.'"
|
|
||||||
ng-model="panel.display.geopoints.pointSize"
|
|
||||||
value="{{panel.display.geopoints.pointSize}}" />
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Point Transparency</td>
|
|
||||||
<td>
|
|
||||||
<input type="text" style="width:100px"
|
|
||||||
ng-change="$emit('render')"
|
|
||||||
data-placement="right"
|
|
||||||
bs-tooltip="'Controls the transparency of geopoints. Valid numbers are between 0.0 and 1.0'"
|
|
||||||
ng-model="panel.display.geopoints.pointAlpha"
|
|
||||||
value="{{panel.display.geopoints.pointAlpha}}" />
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Autosizing</td>
|
|
||||||
<td>
|
|
||||||
<input type="checkbox"
|
|
||||||
ng-change="$emit('render')"
|
|
||||||
data-placement="right"
|
|
||||||
ng-model="panel.display.geopoints.autosize"
|
|
||||||
bs-tooltip="'Allows point sizes to scale as you zoom in and out of the map.'" />
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row-fluid tabDetails" ng-show="isActive('binning')">
|
|
||||||
<div class="span8 offset1">
|
|
||||||
<table>
|
|
||||||
<tbody >
|
|
||||||
<tr>
|
|
||||||
<td>Binning</td>
|
|
||||||
<td>
|
|
||||||
<button type="button" class="btn" bs-button
|
|
||||||
data-placement="right"
|
|
||||||
bs-tooltip="'Compatible with Geopoint Type'"
|
|
||||||
ng-change="$emit('render')"
|
|
||||||
ng-class="{'btn-success': panel.display.binning.enabled}"
|
|
||||||
ng-model="panel.display.binning.enabled">{{panel.display.binning.enabled|enabledText}}</button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Hexagon size</td>
|
|
||||||
<td>
|
|
||||||
<input type="text" style="width:100px"
|
|
||||||
ng-change="$emit('render')"
|
|
||||||
data-placement="right"
|
|
||||||
bs-tooltip="'Controls the size of the hexagonal binning'"
|
|
||||||
ng-model="panel.display.binning.hexagonSize"
|
|
||||||
value="{{panel.display.binning.hexagonSize}}" />
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Hexagon Transparency</td>
|
|
||||||
<td>
|
|
||||||
<input type="text" style="width:100px"
|
|
||||||
ng-change="$emit('render')"
|
|
||||||
data-placement="right"
|
|
||||||
bs-tooltip="'Controls the transparency of hexagonal bins. Valid numbers are between 0.0 and 1.0'"
|
|
||||||
ng-model="panel.display.binning.hexagonAlpha"
|
|
||||||
value="{{panel.display.binning.hexagonAlpha}}" />
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<button type="button" class="btn" bs-button
|
|
||||||
ng-change="$emit('render')"
|
|
||||||
ng-class="{'btn-success': panel.display.binning.areaEncoding}"
|
|
||||||
ng-model="panel.display.binning.areaEncoding">Area</button>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div class="btn-group" ng-model="panel.display.binning.areaEncodingField" bs-buttons-radio ng-change="$emit('render')">
|
|
||||||
<button type="button" class="btn" value="primary">Primary Field</button>
|
|
||||||
<button type="button" class="btn" value="secondary">Secondary Field</button>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<button type="button" class="btn" bs-button
|
|
||||||
ng-change="$emit('render')"
|
|
||||||
ng-class="{'btn-success': panel.display.binning.colorEncoding}"
|
|
||||||
ng-model="panel.display.binning.colorEncoding">Color</button>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div class="btn-group" ng-model="panel.display.binning.colorEncodingField" bs-buttons-radio ng-change="$emit('render')">
|
|
||||||
<button type="button" class="btn" value="primary">Primary Field</button>
|
|
||||||
<button type="button" class="btn" value="secondary">Secondary Field</button>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row-fluid tabDetails" ng-show="isActive('choropleth')">
|
|
||||||
<div class="span8 offset1">
|
|
||||||
<table>
|
|
||||||
<tbody >
|
|
||||||
<tr>
|
|
||||||
<td>Choropleth</td>
|
|
||||||
<td>
|
|
||||||
<button type="button" class="btn" bs-button
|
|
||||||
data-placement="right"
|
|
||||||
bs-tooltip="'Choropleths color country regions according to your selected field. Compatible with Country-Coded fields'"
|
|
||||||
ng-change="$emit('render')"
|
|
||||||
ng-class="{'btn-success': panel.display.choropleth.enabled}"
|
|
||||||
ng-model="panel.display.choropleth.enabled">{{panel.display.choropleth.enabled|enabledText}}</button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row-fluid tabDetails" ng-show="isActive('bullseye')">
|
|
||||||
<div class="span8 offset1">
|
|
||||||
<table>
|
|
||||||
<tbody >
|
|
||||||
<tr>
|
|
||||||
<td>Bullseye</td>
|
|
||||||
<td>
|
|
||||||
<button type="button" class="btn" bs-button
|
|
||||||
ng-change="$emit('render')"
|
|
||||||
ng-class="{'btn-success': panel.display.bullseye.enabled}"
|
|
||||||
ng-model="panel.display.bullseye.enabled">{{panel.display.bullseye.enabled|enabledText}}</button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Bullseye Coordinates</td>
|
|
||||||
<td>
|
|
||||||
<input type="text" style="width:100px"
|
|
||||||
ng-change="$emit('render')"
|
|
||||||
placeholder="Latitude"
|
|
||||||
data-placement="right"
|
|
||||||
bs-tooltip="'Latitude of Bullseye'"
|
|
||||||
ng-model="panel.display.bullseye.coord.lat"
|
|
||||||
value="{{panel.display.bullseye.coord.lat}}" />
|
|
||||||
|
|
||||||
<input type="text" style="width:100px"
|
|
||||||
placeholder="Longitude"
|
|
||||||
ng-change="$emit('render')"
|
|
||||||
data-placement="right"
|
|
||||||
bs-tooltip="'Longitude of Bullseye'"
|
|
||||||
ng-model="panel.display.bullseye.coord.lon"
|
|
||||||
value="{{panel.display.bullseye.coord.lon}}" />
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row-fluid tabDetails" ng-show="isActive('data')">
|
|
||||||
<div class="span8 offset1">
|
|
||||||
<table>
|
|
||||||
<tbody >
|
|
||||||
<tr>
|
|
||||||
<td>Data Points</td>
|
|
||||||
<td>
|
|
||||||
<input type="text" style="width:100px"
|
|
||||||
ng-change="get_data()"
|
|
||||||
data-placement="right"
|
|
||||||
bs-tooltip="'Controls the number of samples used in the map. Be careful with this value!'"
|
|
||||||
ng-model="panel.display.data.samples"
|
|
||||||
value="{{panel.display.data.samples}}" />
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Map Projection</td>
|
|
||||||
<td>
|
|
||||||
<select ng-model="panel.display.data.type" ng-options="option.id as option.text for option in panel.display.data.dropdown"></select>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h5>Panel Spy</h5>
|
|
||||||
|
|
||||||
<div class="row-fluid">
|
|
||||||
<div class="span2">
|
|
||||||
<label class="small">Spyable</label> <input type="checkbox" ng-model=
|
|
||||||
"panel.spyable" ng-checked="panel.spyable">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="span9 small">
|
|
||||||
The panel spy shows 'behind the scenes' information about a panel. It can be
|
|
||||||
accessed by clicking the in the top right of the panel.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
1
panels/map2/lib/d3.hexbin.v0.min.js
vendored
1
panels/map2/lib/d3.hexbin.v0.min.js
vendored
@ -1 +0,0 @@
|
|||||||
(function(){d3.hexbin=function(){function u(n){var r={};return n.forEach(function(n,t){var a=s.call(u,n,t)/o,e=Math.round(a),h=f.call(u,n,t)/i-(1&e?.5:0),c=Math.round(h),l=a-e;if(3*Math.abs(l)>1){var g=h-c,v=c+(c>h?-1:1)/2,M=e+(e>a?-1:1),m=h-v,d=a-M;g*g+l*l>m*m+d*d&&(c=v+(1&e?1:-1)/2,e=M)}var x=c+"-"+e,j=r[x];j?j.push(n):(j=r[x]=[n],j.x=(c+(1&e?.5:0))*i,j.y=e*o)}),d3.values(r)}function a(r){var t=0,u=0;return n.map(function(n){var a=Math.sin(n)*r,e=-Math.cos(n)*r,i=a-t,o=e-u;return t=a,u=e,[i,o]})}var e,i,o,h=1,c=1,f=r,s=t;return u.x=function(n){return arguments.length?(f=n,u):f},u.y=function(n){return arguments.length?(s=n,u):s},u.hexagon=function(n){return 1>arguments.length&&(n=e),"m"+a(n).join("l")+"z"},u.mesh=function(){for(var n=[],r=a(e).slice(0,4).join("l"),t=0,u=!1;c+e>t;t+=o,u=!u)for(var f=u?i/2:0;h>f;f+=i)n.push("M",f,",",t,"m",r);return n.join("")},u.size=function(n){return arguments.length?(h=+n[0],c=+n[1],u):[h,c]},u.radius=function(n){return arguments.length?(e=+n,i=2*e*Math.sin(Math.PI/3),o=1.5*e,u):e},u.radius(1)};var n=d3.range(0,2*Math.PI,Math.PI/3),r=function(n){return n[0]},t=function(n){return n[1]}})();
|
|
@ -1,137 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) 2011, Sun Ning.
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
var BASE32_CODES = "0123456789bcdefghjkmnpqrstuvwxyz";
|
|
||||||
var BASE32_CODES_DICT = {};
|
|
||||||
for(var i=0; i<BASE32_CODES.length; i++) {
|
|
||||||
BASE32_CODES_DICT[BASE32_CODES.charAt(i)]=i;
|
|
||||||
}
|
|
||||||
|
|
||||||
var encode = function(latitude, longitude, numberOfChars){
|
|
||||||
numberOfChars = numberOfChars || 9;
|
|
||||||
var chars = [], bits = 0;
|
|
||||||
var hash_value = 0;
|
|
||||||
|
|
||||||
var maxlat = 90, minlat = -90;
|
|
||||||
var maxlon = 180, minlon = -180;
|
|
||||||
|
|
||||||
var mid;
|
|
||||||
var islon = true;
|
|
||||||
while(chars.length < numberOfChars) {
|
|
||||||
if (islon){
|
|
||||||
mid = (maxlon+minlon)/2;
|
|
||||||
if(longitude > mid){
|
|
||||||
hash_value = (hash_value << 1) + 1;
|
|
||||||
minlon=mid;
|
|
||||||
} else {
|
|
||||||
hash_value = (hash_value << 1) + 0;
|
|
||||||
maxlon=mid;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
mid = (maxlat+minlat)/2;
|
|
||||||
if(latitude > mid ){
|
|
||||||
hash_value = (hash_value << 1) + 1;
|
|
||||||
minlat = mid;
|
|
||||||
} else {
|
|
||||||
hash_value = (hash_value << 1) + 0;
|
|
||||||
maxlat = mid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
islon = !islon;
|
|
||||||
|
|
||||||
bits++;
|
|
||||||
if (bits == 5) {
|
|
||||||
var code = BASE32_CODES[hash_value];
|
|
||||||
chars.push(code);
|
|
||||||
bits = 0;
|
|
||||||
hash_value = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return chars.join('')
|
|
||||||
};
|
|
||||||
|
|
||||||
var decode_bbox = function(hash_string){
|
|
||||||
var islon = true;
|
|
||||||
var maxlat = 90, minlat = -90;
|
|
||||||
var maxlon = 180, minlon = -180;
|
|
||||||
|
|
||||||
var hash_value = 0;
|
|
||||||
for(var i=0,l=hash_string.length; i<l; i++) {
|
|
||||||
var code = hash_string[i].toLowerCase();
|
|
||||||
hash_value = BASE32_CODES_DICT[code];
|
|
||||||
|
|
||||||
for (var bits=4; bits>=0; bits--) {
|
|
||||||
var bit = (hash_value >> bits) & 1;
|
|
||||||
if (islon){
|
|
||||||
var mid = (maxlon+minlon)/2;
|
|
||||||
if(bit == 1){
|
|
||||||
minlon = mid;
|
|
||||||
} else {
|
|
||||||
maxlon = mid;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
var mid = (maxlat+minlat)/2;
|
|
||||||
if(bit == 1){
|
|
||||||
minlat = mid;
|
|
||||||
} else {
|
|
||||||
maxlat = mid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
islon = !islon;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return [minlat, minlon, maxlat, maxlon];
|
|
||||||
}
|
|
||||||
|
|
||||||
var decode = function(hash_string){
|
|
||||||
var bbox = decode_bbox(hash_string);
|
|
||||||
var lat = (bbox[0]+bbox[2])/2;
|
|
||||||
var lon = (bbox[1]+bbox[3])/2;
|
|
||||||
var laterr = bbox[2]-lat;
|
|
||||||
var lonerr = bbox[3]-lon;
|
|
||||||
return {latitude:lat, longitude:lon,
|
|
||||||
error:{latitude:laterr, longitude:lonerr}};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* direction [lat, lon], i.e.
|
|
||||||
* [1,0] - north
|
|
||||||
* [1,1] - northeast
|
|
||||||
* ...
|
|
||||||
*/
|
|
||||||
var neighbor = function(hashstring, direction) {
|
|
||||||
var lonlat = decode(hashstring);
|
|
||||||
var neighbor_lat = lonlat.latitude
|
|
||||||
+ direction[0] * lonlat.error.latitude * 2;
|
|
||||||
var neighbor_lon = lonlat.longitude
|
|
||||||
+ direction[1] * lonlat.error.longitude * 2;
|
|
||||||
return encode(neighbor_lat, neighbor_lon, hashstring.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
var geohash = {
|
|
||||||
'encode': encode,
|
|
||||||
'decode': decode,
|
|
||||||
'decode_bbox': decode_bbox,
|
|
||||||
'neighbor': neighbor,
|
|
||||||
}
|
|
||||||
module.exports = geohash;
|
|
1
panels/map2/lib/queue.v1.min.js
vendored
1
panels/map2/lib/queue.v1.min.js
vendored
@ -1 +0,0 @@
|
|||||||
(function(){function n(n){function t(){for(;f=a<c.length&&n>p;){var u=a++,t=c[u],r=l.call(t,1);r.push(e(u)),++p,t[0].apply(null,r)}}function e(n){return function(u,l){--p,null==d&&(null!=u?(d=u,a=s=0/0,r()):(c[n]=l,--s?f||t():r()))}}function r(){null!=d?v(d):i?v(d,c):v.apply(null,[d].concat(c))}var o,f,i,c=[],a=0,p=0,s=0,d=null,v=u;return n||(n=1/0),o={defer:function(){return d||(c.push(arguments),++s,t()),o},await:function(n){return v=n,i=!1,s||r(),o},awaitAll:function(n){return v=n,i=!0,s||r(),o}}}function u(){}"undefined"==typeof module?self.queue=n:module.exports=n,n.version="1.0.4";var l=[].slice})();
|
|
1
panels/map2/lib/topojson.v1.min.js
vendored
1
panels/map2/lib/topojson.v1.min.js
vendored
@ -1 +0,0 @@
|
|||||||
topojson=function(){function t(t,e){function n(e){var n=t.arcs[e],r=n[0],o=[0,0];return n.forEach(function(t){o[0]+=t[0],o[1]+=t[1]}),[r,o]}var r={},o={},a={};e.forEach(function(t){var e=n(t);(r[e[0]]||(r[e[0]]=[])).push(t),(r[e[1]]||(r[e[1]]=[])).push(~t)}),e.forEach(function(t){var e,r,i=n(t),u=i[0],c=i[1];if(e=a[u])if(delete a[e.end],e.push(t),e.end=c,r=o[c]){delete o[r.start];var s=r===e?e:e.concat(r);o[s.start=e.start]=a[s.end=r.end]=s}else if(r=a[c]){delete o[r.start],delete a[r.end];var s=e.concat(r.map(function(t){return~t}).reverse());o[s.start=e.start]=a[s.end=r.start]=s}else o[e.start]=a[e.end]=e;else if(e=o[c])if(delete o[e.start],e.unshift(t),e.start=u,r=a[u]){delete a[r.end];var f=r===e?e:r.concat(e);o[f.start=r.start]=a[f.end=e.end]=f}else if(r=o[u]){delete o[r.start],delete a[r.end];var f=r.map(function(t){return~t}).reverse().concat(e);o[f.start=r.end]=a[f.end=e.end]=f}else o[e.start]=a[e.end]=e;else if(e=o[u])if(delete o[e.start],e.unshift(~t),e.start=c,r=a[c]){delete a[r.end];var f=r===e?e:r.concat(e);o[f.start=r.start]=a[f.end=e.end]=f}else if(r=o[c]){delete o[r.start],delete a[r.end];var f=r.map(function(t){return~t}).reverse().concat(e);o[f.start=r.end]=a[f.end=e.end]=f}else o[e.start]=a[e.end]=e;else if(e=a[c])if(delete a[e.end],e.push(~t),e.end=u,r=a[u]){delete o[r.start];var s=r===e?e:e.concat(r);o[s.start=e.start]=a[s.end=r.end]=s}else if(r=o[u]){delete o[r.start],delete a[r.end];var s=e.concat(r.map(function(t){return~t}).reverse());o[s.start=e.start]=a[s.end=r.start]=s}else o[e.start]=a[e.end]=e;else e=[t],o[e.start=u]=a[e.end=c]=e});var i=[];for(var u in a)i.push(a[u]);return i}function e(e,n,r){function a(t){0>t&&(t=~t),(l[t]||(l[t]=[])).push(f)}function i(t){t.forEach(a)}function u(t){t.forEach(i)}function c(t){t.type==="GeometryCollection"?t.geometries.forEach(c):t.type in d&&(f=t,d[t.type](t.arcs))}var s=[];if(arguments.length>1){var f,l=[],d={LineString:i,MultiLineString:u,Polygon:u,MultiPolygon:function(t){t.forEach(u)}};c(n),l.forEach(arguments.length<3?function(t,e){s.push([e])}:function(t,e){r(t[0],t[t.length-1])&&s.push([e])})}else for(var p=0,h=e.arcs.length;h>p;++p)s.push([p]);return o(e,{type:"MultiLineString",arcs:t(e,s)})}function n(t,e){return e.type==="GeometryCollection"?{type:"FeatureCollection",features:e.geometries.map(function(e){return r(t,e)})}:r(t,e)}function r(t,e){var n={type:"Feature",id:e.id,properties:e.properties||{},geometry:o(t,e)};return e.id==null&&delete n.id,n}function o(t,e){function n(t,e){e.length&&e.pop();for(var n,r=h[0>t?~t:t],o=0,i=r.length,u=0,c=0;i>o;++o)e.push([(u+=(n=r[o])[0])*f+d,(c+=n[1])*l+p]);0>t&&a(e,i)}function r(t){return[t[0]*f+d,t[1]*l+p]}function o(t){for(var e=[],r=0,o=t.length;o>r;++r)n(t[r],e);return e.length<2&&e.push(e[0]),e}function i(t){for(var e=o(t);e.length<4;)e.push(e[0]);return e}function u(t){return t.map(i)}function c(t){var e=t.type;return"GeometryCollection"===e?{type:e,geometries:t.geometries.map(c)}:e in v?{type:e,coordinates:v[e](t)}:null}var s=t.transform,f=s.scale[0],l=s.scale[1],d=s.translate[0],p=s.translate[1],h=t.arcs,v={Point:function(t){return r(t.coordinates)},MultiPoint:function(t){return t.coordinates.map(r)},LineString:function(t){return o(t.arcs)},MultiLineString:function(t){return t.arcs.map(o)},Polygon:function(t){return u(t.arcs)},MultiPolygon:function(t){return t.arcs.map(u)}};return c(e)}function a(t,e){for(var n,r=t.length,o=r-e;o<--r;)n=t[o],t[o++]=t[r],t[r]=n}function i(t,e){for(var n=0,r=t.length;r>n;){var o=n+r>>>1;t[o]<e?n=o+1:r=o}return n}function u(t){function e(t,e){t.forEach(function(t){0>t&&(t=~t);var n=o[t]||(o[t]=[]);n[e]||(n.forEach(function(t){var n,r;r=i(n=a[e],t),n[r]!==t&&n.splice(r,0,t),r=i(n=a[t],e),n[r]!==e&&n.splice(r,0,e)}),n[e]=e)})}function n(t,n){t.forEach(function(t){e(t,n)})}function r(t,e){t.type==="GeometryCollection"?t.geometries.forEach(function(t){r(t,e)}):t.type in u&&u[t.type](t.arcs,e)}var o=[],a=t.map(function(){return[]}),u={LineString:e,MultiLineString:n,Polygon:n,MultiPolygon:function(t,e){t.forEach(function(t){n(t,e)})}};return t.forEach(r),a}return{version:"1.0.0pre",mesh:e,feature:n,neighbors:u}}();
|
|
File diff suppressed because one or more lines are too long
@ -1,251 +0,0 @@
|
|||||||
id short name
|
|
||||||
4 AF Afghanistan
|
|
||||||
8 AL Albania
|
|
||||||
10 AQ Antarctica
|
|
||||||
12 DZ Algeria
|
|
||||||
16 AS American Samoa
|
|
||||||
20 AD Andorra
|
|
||||||
24 AO Angola
|
|
||||||
28 AG Antigua and Barbuda
|
|
||||||
31 AZ Azerbaijan
|
|
||||||
32 AR Argentina
|
|
||||||
36 AU Australia
|
|
||||||
40 AT Austria
|
|
||||||
44 BS Bahamas
|
|
||||||
48 BH Bahrain
|
|
||||||
50 BD Bangladesh
|
|
||||||
51 AM Armenia
|
|
||||||
52 BB Barbados
|
|
||||||
56 BE Belgium
|
|
||||||
60 BM Bermuda
|
|
||||||
64 BT Bhutan
|
|
||||||
68 BO Bolivia, Plurinational State of
|
|
||||||
70 BA Bosnia and Herzegovina
|
|
||||||
72 BW Botswana
|
|
||||||
74 BV Bouvet Island
|
|
||||||
76 BR Brazil
|
|
||||||
84 BZ Belize
|
|
||||||
86 IO British Indian Ocean Territory
|
|
||||||
90 SB Solomon Islands
|
|
||||||
92 VG Virgin Islands, British
|
|
||||||
96 BN Brunei Darussalam
|
|
||||||
100 BG Bulgaria
|
|
||||||
104 MM Myanmar
|
|
||||||
108 BI Burundi
|
|
||||||
112 BY Belarus
|
|
||||||
116 KH Cambodia
|
|
||||||
120 CM Cameroon
|
|
||||||
124 CA Canada
|
|
||||||
132 CV Cape Verde
|
|
||||||
136 KY Cayman Islands
|
|
||||||
140 CF Central African Republic
|
|
||||||
144 LK Sri Lanka
|
|
||||||
148 TD Chad
|
|
||||||
152 CL Chile
|
|
||||||
156 CN China
|
|
||||||
158 TW Taiwan, Province of China
|
|
||||||
162 CX Christmas Island
|
|
||||||
166 CC Cocos (Keeling) Islands
|
|
||||||
170 CO Colombia
|
|
||||||
174 KM Comoros
|
|
||||||
175 YT Mayotte
|
|
||||||
178 CG Congo
|
|
||||||
180 CD Congo, the Democratic Republic of the
|
|
||||||
184 CK Cook Islands
|
|
||||||
188 CR Costa Rica
|
|
||||||
191 HR Croatia
|
|
||||||
192 CU Cuba
|
|
||||||
196 CY Cyprus
|
|
||||||
203 CZ Czech Republic
|
|
||||||
204 BJ Benin
|
|
||||||
208 DK Denmark
|
|
||||||
212 DM Dominica
|
|
||||||
214 DO Dominican Republic
|
|
||||||
218 EC Ecuador
|
|
||||||
222 SV El Salvador
|
|
||||||
226 GQ Equatorial Guinea
|
|
||||||
231 ET Ethiopia
|
|
||||||
232 ER Eritrea
|
|
||||||
233 EE Estonia
|
|
||||||
234 FO Faroe Islands
|
|
||||||
238 FK Falkland Islands (Malvinas)
|
|
||||||
239 GS South Georgia and the South Sandwich Islands
|
|
||||||
242 FJ Fiji
|
|
||||||
246 FI Finland
|
|
||||||
248 AX Åland Islands
|
|
||||||
250 FR France
|
|
||||||
254 GF French Guiana
|
|
||||||
258 PF French Polynesia
|
|
||||||
260 TF French Southern Territories
|
|
||||||
262 DJ Djibouti
|
|
||||||
266 GA Gabon
|
|
||||||
268 GE Georgia
|
|
||||||
270 GM Gambia
|
|
||||||
275 Palestinian Territory, Occupied
|
|
||||||
276 DE Germany
|
|
||||||
288 GH Ghana
|
|
||||||
292 GI Gibraltar
|
|
||||||
296 KI Kiribati
|
|
||||||
300 GR Greece
|
|
||||||
304 GL Greenland
|
|
||||||
308 GD Grenada
|
|
||||||
312 GP Guadeloupe
|
|
||||||
316 GU Guam
|
|
||||||
320 GT Guatemala
|
|
||||||
324 GN Guinea
|
|
||||||
328 GY Guyana
|
|
||||||
332 HT Haiti
|
|
||||||
334 HM Heard Island and McDonald Islands
|
|
||||||
336 VA Holy See (Vatican City State)
|
|
||||||
340 HN Honduras
|
|
||||||
344 HK Hong Kong
|
|
||||||
348 HU Hungary
|
|
||||||
352 IS Iceland
|
|
||||||
356 IN India
|
|
||||||
360 ID Indonesia
|
|
||||||
364 IR Iran, Islamic Republic of
|
|
||||||
368 IQ Iraq
|
|
||||||
372 IE Ireland
|
|
||||||
376 IL Israel
|
|
||||||
380 IT Italy
|
|
||||||
384 Côte d'Ivoire
|
|
||||||
388 JM Jamaica
|
|
||||||
392 JP Japan
|
|
||||||
398 KZ Kazakhstan
|
|
||||||
400 JO Jordan
|
|
||||||
404 KE Kenya
|
|
||||||
408 KP Korea, Democratic People's Republic of
|
|
||||||
410 KR Korea, Republic of
|
|
||||||
414 KW Kuwait
|
|
||||||
417 KG Kyrgyzstan
|
|
||||||
418 LA Lao People's Democratic Republic
|
|
||||||
422 LB Lebanon
|
|
||||||
426 LS Lesotho
|
|
||||||
428 LV Latvia
|
|
||||||
430 LR Liberia
|
|
||||||
434 LY Libya
|
|
||||||
438 LI Liechtenstein
|
|
||||||
440 LT Lithuania
|
|
||||||
442 LU Luxembourg
|
|
||||||
446 MO Macao
|
|
||||||
450 MG Madagascar
|
|
||||||
454 MW Malawi
|
|
||||||
458 MY Malaysia
|
|
||||||
462 MV Maldives
|
|
||||||
466 ML Mali
|
|
||||||
470 MT Malta
|
|
||||||
474 MQ Martinique
|
|
||||||
478 MR Mauritania
|
|
||||||
480 MU Mauritius
|
|
||||||
484 MX Mexico
|
|
||||||
492 MC Monaco
|
|
||||||
496 MN Mongolia
|
|
||||||
498 MD Moldova, Republic of
|
|
||||||
499 ME Montenegro
|
|
||||||
500 MS Montserrat
|
|
||||||
504 MA Morocco
|
|
||||||
508 MZ Mozambique
|
|
||||||
512 OM Oman
|
|
||||||
516 NA Namibia
|
|
||||||
520 NR Nauru
|
|
||||||
524 NP Nepal
|
|
||||||
528 NL Netherlands
|
|
||||||
531 Curaçao
|
|
||||||
533 AW Aruba
|
|
||||||
534 SX Sint Maarten (Dutch part)
|
|
||||||
535 BQ Bonaire, Sint Eustatius and Saba
|
|
||||||
540 NC New Caledonia
|
|
||||||
548 VU Vanuatu
|
|
||||||
554 NZ New Zealand
|
|
||||||
558 NI Nicaragua
|
|
||||||
562 NE Niger
|
|
||||||
566 NG Nigeria
|
|
||||||
570 NU Niue
|
|
||||||
574 NF Norfolk Island
|
|
||||||
578 NO Norway
|
|
||||||
580 MP Northern Mariana Islands
|
|
||||||
581 UM United States Minor Outlying Islands
|
|
||||||
583 FM Micronesia, Federated States of
|
|
||||||
584 MH Marshall Islands
|
|
||||||
585 PW Palau
|
|
||||||
586 PK Pakistan
|
|
||||||
591 PA Panama
|
|
||||||
598 PG Papua New Guinea
|
|
||||||
600 PY Paraguay
|
|
||||||
604 PE Peru
|
|
||||||
608 PH Philippines
|
|
||||||
612 PN Pitcairn
|
|
||||||
616 PL Poland
|
|
||||||
620 PT Portugal
|
|
||||||
624 GW Guinea-Bissau
|
|
||||||
626 TL Timor-Leste
|
|
||||||
630 PR Puerto Rico
|
|
||||||
634 QA Qatar
|
|
||||||
638 Réunion
|
|
||||||
642 RO Romania
|
|
||||||
643 RU Russian Federation
|
|
||||||
646 RW Rwanda
|
|
||||||
652 Saint Barthélemy
|
|
||||||
654 SH Saint Helena, Ascension and Tristan da Cunha
|
|
||||||
659 KN Saint Kitts and Nevis
|
|
||||||
660 AI Anguilla
|
|
||||||
662 LC Saint Lucia
|
|
||||||
663 MF Saint Martin (French part)
|
|
||||||
666 PM Saint Pierre and Miquelon
|
|
||||||
670 VC Saint Vincent and the Grenadines
|
|
||||||
674 SM San Marino
|
|
||||||
678 ST Sao Tome and Principe
|
|
||||||
682 SA Saudi Arabia
|
|
||||||
686 SN Senegal
|
|
||||||
688 RS Serbia
|
|
||||||
690 SC Seychelles
|
|
||||||
694 SL Sierra Leone
|
|
||||||
702 SG Singapore
|
|
||||||
703 SK Slovakia
|
|
||||||
704 VN Viet Nam
|
|
||||||
705 SI Slovenia
|
|
||||||
706 SO Somalia
|
|
||||||
710 ZA South Africa
|
|
||||||
716 ZW Zimbabwe
|
|
||||||
724 ES Spain
|
|
||||||
728 SS South Sudan
|
|
||||||
729 SD Sudan
|
|
||||||
732 EH Western Sahara
|
|
||||||
740 SR Suriname
|
|
||||||
744 SJ Svalbard and Jan Mayen
|
|
||||||
748 SZ Swaziland
|
|
||||||
752 SE Sweden
|
|
||||||
756 CH Switzerland
|
|
||||||
760 SY Syrian Arab Republic
|
|
||||||
762 TJ Tajikistan
|
|
||||||
764 TH Thailand
|
|
||||||
768 TG Togo
|
|
||||||
772 TK Tokelau
|
|
||||||
776 TO Tonga
|
|
||||||
780 TT Trinidad and Tobago
|
|
||||||
784 AE United Arab Emirates
|
|
||||||
788 TN Tunisia
|
|
||||||
792 TR Turkey
|
|
||||||
795 TM Turkmenistan
|
|
||||||
796 TC Turks and Caicos Islands
|
|
||||||
798 TV Tuvalu
|
|
||||||
800 UG Uganda
|
|
||||||
804 UA Ukraine
|
|
||||||
807 MK Macedonia, the former Yugoslav Republic of
|
|
||||||
818 EG Egypt
|
|
||||||
826 GB United Kingdom
|
|
||||||
831 GG Guernsey
|
|
||||||
832 JE Jersey
|
|
||||||
833 IM Isle of Man
|
|
||||||
834 TZ Tanzania, United Republic of
|
|
||||||
840 US United States
|
|
||||||
850 VI Virgin Islands, U.S.
|
|
||||||
854 BF Burkina Faso
|
|
||||||
858 UY Uruguay
|
|
||||||
860 UZ Uzbekistan
|
|
||||||
862 VE Venezuela, Bolivarian Republic of
|
|
||||||
876 WF Wallis and Futuna
|
|
||||||
882 WS Samoa
|
|
||||||
887 YE Yemen
|
|
||||||
894 ZM Zambia
|
|
||||||
|
|
|
@ -1,58 +0,0 @@
|
|||||||
<kibana-panel ng-controller='map2' ng-init="init()">
|
|
||||||
<style>
|
|
||||||
.overlay {
|
|
||||||
fill: none;
|
|
||||||
pointer-events: all;
|
|
||||||
}
|
|
||||||
|
|
||||||
.land {
|
|
||||||
fill: #D1D1D1;
|
|
||||||
stroke: #595959;
|
|
||||||
stroke-linejoin: round;
|
|
||||||
stroke-linecap: round;
|
|
||||||
stroke-width: .1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.boundary {
|
|
||||||
fill: none;
|
|
||||||
stroke: #000;
|
|
||||||
stroke-linejoin: round;
|
|
||||||
stroke-linecap: round;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hexagon {
|
|
||||||
fill: none;
|
|
||||||
stroke: #000;
|
|
||||||
stroke-width: .1px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.q1 { fill:rgb(247,251,255); }
|
|
||||||
.q2 { fill:rgb(222,235,247); }
|
|
||||||
.q3 { fill:rgb(198,219,239); }
|
|
||||||
.q4 { fill:rgb(158,202,225); }
|
|
||||||
.q5 { fill:rgb(107,174,214); }
|
|
||||||
.q6 { fill:rgb(66,146,198); }
|
|
||||||
.q7 { fill:rgb(33,113,181); }
|
|
||||||
.q8 { fill:rgb(8,81,156); }
|
|
||||||
.q9 { fill:rgb(8,48,107); }
|
|
||||||
|
|
||||||
.arc {
|
|
||||||
stroke: #f00;
|
|
||||||
stroke-width: .5px;
|
|
||||||
fill: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.geopoint {
|
|
||||||
stroke: #000;
|
|
||||||
stroke-width: .5px;
|
|
||||||
fill: #000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dropdown-menu{position:absolute;top:auto;left:auto;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;background-color:#ffffff;border:1px solid #ccc;border:1px solid rgba(0, 0, 0, 0.2);*border-right-width:2px;*border-bottom-width:2px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);-moz-box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);box-shadow:0 5px 10px rgba(0, 0, 0, 0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box;}
|
|
||||||
</style>
|
|
||||||
<span ng-show="panel.spyable" style="position:absolute;right:0px;top:0px" class='panelextra pointer'>
|
|
||||||
<i bs-modal="'partials/modal.html'" class="icon-eye-open"></i>
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<div map2 params="{{panel}}" style="height:{{panel.height || row.height}}"></div>
|
|
||||||
</kibana-panel>
|
|
@ -1,452 +0,0 @@
|
|||||||
angular.module('kibana.map2', [])
|
|
||||||
.controller('map2', function ($scope, eventBus, keylistener) {
|
|
||||||
|
|
||||||
// Set and populate defaults
|
|
||||||
var _d = {
|
|
||||||
status : "Broken",
|
|
||||||
query: "*",
|
|
||||||
map: "world",
|
|
||||||
colors: ['#C8EEFF', '#0071A4'],
|
|
||||||
size: 100,
|
|
||||||
exclude: [],
|
|
||||||
spyable: true,
|
|
||||||
group: "default",
|
|
||||||
index_limit: 0,
|
|
||||||
display: {
|
|
||||||
translate:[0, 0],
|
|
||||||
scale:-1,
|
|
||||||
data: {
|
|
||||||
samples: 1000,
|
|
||||||
type: "mercator",
|
|
||||||
dropdown:[
|
|
||||||
{
|
|
||||||
"text": "Mercator (Flat)",
|
|
||||||
id: "mercator"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: "Orthographic (Sphere)",
|
|
||||||
id: "orthographic"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
geopoints: {
|
|
||||||
enabled: false,
|
|
||||||
enabledText: "Enabled",
|
|
||||||
pointSize: 0.3,
|
|
||||||
pointAlpha: 0.6
|
|
||||||
},
|
|
||||||
binning: {
|
|
||||||
enabled: false,
|
|
||||||
hexagonSize: 2,
|
|
||||||
hexagonAlpha: 1.0,
|
|
||||||
areaEncoding: true,
|
|
||||||
areaEncodingField: "primary",
|
|
||||||
colorEncoding: true,
|
|
||||||
colorEncodingField: "primary"
|
|
||||||
},
|
|
||||||
choropleth: {
|
|
||||||
enabled: false
|
|
||||||
},
|
|
||||||
bullseye: {
|
|
||||||
enabled: false,
|
|
||||||
coord: {
|
|
||||||
lat: 0,
|
|
||||||
lon: 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
activeDisplayTab:"Geopoints"
|
|
||||||
};
|
|
||||||
|
|
||||||
_.defaults($scope.panel, _d)
|
|
||||||
|
|
||||||
$scope.init = function () {
|
|
||||||
eventBus.register($scope, 'time', function (event, time) {
|
|
||||||
set_time(time)
|
|
||||||
});
|
|
||||||
eventBus.register($scope, 'query', function (event, query) {
|
|
||||||
$scope.panel.query = _.isArray(query) ? query[0] : query;
|
|
||||||
$scope.get_data();
|
|
||||||
});
|
|
||||||
// Now that we're all setup, request the time from our group
|
|
||||||
eventBus.broadcast($scope.$id, $scope.panel.group, 'get_time');
|
|
||||||
|
|
||||||
$scope.keylistener = keylistener;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.get_data = function () {
|
|
||||||
|
|
||||||
// Make sure we have everything for the request to complete
|
|
||||||
if (_.isUndefined($scope.index) || _.isUndefined($scope.time))
|
|
||||||
return
|
|
||||||
|
|
||||||
$scope.panel.loading = true;
|
|
||||||
var request = $scope.ejs.Request().indices($scope.index);
|
|
||||||
|
|
||||||
|
|
||||||
var metric = 'count';
|
|
||||||
|
|
||||||
//Use a regular term facet if there is no secondary field
|
|
||||||
if (typeof $scope.panel.secondaryfield === "undefined") {
|
|
||||||
var facet = $scope.ejs.TermsFacet('map')
|
|
||||||
.field($scope.panel.field)
|
|
||||||
.size($scope.panel.display.data.samples)
|
|
||||||
.exclude($scope.panel.exclude)
|
|
||||||
.facetFilter(ejs.QueryFilter(
|
|
||||||
ejs.FilteredQuery(
|
|
||||||
ejs.QueryStringQuery($scope.panel.query || '*'),
|
|
||||||
ejs.RangeFilter($scope.time.field)
|
|
||||||
.from($scope.time.from)
|
|
||||||
.to($scope.time.to))));
|
|
||||||
|
|
||||||
metric = 'count';
|
|
||||||
} else {
|
|
||||||
//otherwise, use term stats
|
|
||||||
//NOTE: this will break if valueField is a geo_point
|
|
||||||
// need to put in checks for that
|
|
||||||
var facet = $scope.ejs.TermStatsFacet('map')
|
|
||||||
.keyField($scope.panel.field)
|
|
||||||
.valueField($scope.panel.secondaryfield)
|
|
||||||
.size($scope.panel.display.data.samples)
|
|
||||||
.facetFilter(ejs.QueryFilter(
|
|
||||||
ejs.FilteredQuery(
|
|
||||||
ejs.QueryStringQuery($scope.panel.query || '*'),
|
|
||||||
ejs.RangeFilter($scope.time.field)
|
|
||||||
.from($scope.time.from)
|
|
||||||
.to($scope.time.to))));
|
|
||||||
|
|
||||||
metric = 'total';
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Then the insert into facet and make the request
|
|
||||||
var request = request.facet(facet).size(0);
|
|
||||||
|
|
||||||
$scope.populate_modal(request);
|
|
||||||
|
|
||||||
var results = request.doSearch();
|
|
||||||
|
|
||||||
// Populate scope when we have results
|
|
||||||
results.then(function (results) {
|
|
||||||
$scope.panel.loading = false;
|
|
||||||
$scope.hits = results.hits.total;
|
|
||||||
$scope.data = {};
|
|
||||||
|
|
||||||
_.each(results.facets.map.terms, function (v) {
|
|
||||||
|
|
||||||
if (!_.isNumber(v.term)) {
|
|
||||||
$scope.data[v.term.toUpperCase()] = v[metric];
|
|
||||||
} else {
|
|
||||||
$scope.data[v.term] = v[metric];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$scope.$emit('render')
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// I really don't like this function, too much dom manip. Break out into directive?
|
|
||||||
$scope.populate_modal = function (request) {
|
|
||||||
$scope.modal = {
|
|
||||||
title: "Inspector",
|
|
||||||
body: "<h5>Last Elasticsearch Query</h5><pre>" + 'curl -XGET ' + config.elasticsearch + '/' + $scope.index + "/_search?pretty -d'\n" + angular.toJson(JSON.parse(request.toString()), true) + "'</pre>"
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function set_time(time) {
|
|
||||||
$scope.time = time;
|
|
||||||
$scope.index = _.isUndefined(time.index) ? $scope.index : time.index
|
|
||||||
$scope.get_data();
|
|
||||||
}
|
|
||||||
|
|
||||||
$scope.build_search = function (field, value) {
|
|
||||||
$scope.panel.query = add_to_query($scope.panel.query, field, value, false)
|
|
||||||
$scope.get_data();
|
|
||||||
eventBus.broadcast($scope.$id, $scope.panel.group, 'query', $scope.panel.query);
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.isActive = function(tab) {
|
|
||||||
return (tab.toLowerCase() === $scope.panel.activeDisplayTab.toLowerCase());
|
|
||||||
}
|
|
||||||
|
|
||||||
$scope.tabClick = function(tab) {
|
|
||||||
$scope.panel.activeDisplayTab = tab;
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
|
||||||
.filter('enabledText', function() {
|
|
||||||
return function (value) {
|
|
||||||
if (value === true) {
|
|
||||||
return "Enabled";
|
|
||||||
} else {
|
|
||||||
return "Disabled";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.directive('map2', function () {
|
|
||||||
return {
|
|
||||||
restrict: 'A',
|
|
||||||
link: function (scope, elem, attrs) {
|
|
||||||
|
|
||||||
//directive level variables related to d3
|
|
||||||
var dr = {};
|
|
||||||
|
|
||||||
scope.initializing = false;
|
|
||||||
|
|
||||||
|
|
||||||
dr.worldData = null;
|
|
||||||
dr.worldNames = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize the panels if new, or render existing panels
|
|
||||||
*/
|
|
||||||
scope.init_or_render = function() {
|
|
||||||
if (typeof dr.svg === 'undefined') {
|
|
||||||
console.log("init");
|
|
||||||
|
|
||||||
//prevent duplicate initialization steps, if render is called again
|
|
||||||
//before the svg is setup
|
|
||||||
if (!scope.initializing) {
|
|
||||||
init_panel();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
console.log("render");
|
|
||||||
render_panel();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Receive render events
|
|
||||||
*/
|
|
||||||
scope.$on('render', function () {
|
|
||||||
scope.init_or_render();
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* On window resize, re-render the panel
|
|
||||||
*/
|
|
||||||
angular.element(window).bind('resize', function () {
|
|
||||||
scope.init_or_render();
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load the various panel-specific scripts, map data, then initialize
|
|
||||||
* the svg and set appropriate D3 settings
|
|
||||||
*/
|
|
||||||
function init_panel() {
|
|
||||||
|
|
||||||
scope.initializing = true;
|
|
||||||
// Using LABjs, wait until all scripts are loaded before rendering panel
|
|
||||||
var scripts = $LAB.script("common/lib/d3.v3.min.js?rand="+Math.floor(Math.random()*10000))
|
|
||||||
.script("panels/map2/lib/topojson.v1.min.js?rand="+Math.floor(Math.random()*10000))
|
|
||||||
.script("panels/map2/lib/node-geohash.js?rand="+Math.floor(Math.random()*10000))
|
|
||||||
.script("panels/map2/lib/d3.hexbin.v0.min.js?rand="+Math.floor(Math.random()*10000))
|
|
||||||
.script("panels/map2/lib/queue.v1.min.js?rand="+Math.floor(Math.random()*10000))
|
|
||||||
.script("panels/map2/display/binning.js?rand="+Math.floor(Math.random()*10000))
|
|
||||||
.script("panels/map2/display/geopoints.js?rand="+Math.floor(Math.random()*10000))
|
|
||||||
.script("panels/map2/display/bullseye.js?rand="+Math.floor(Math.random()*10000));
|
|
||||||
|
|
||||||
// Populate element. Note that jvectormap appends, does not replace.
|
|
||||||
scripts.wait(function () {
|
|
||||||
|
|
||||||
queue()
|
|
||||||
.defer(d3.json, "panels/map2/lib/world-110m.json")
|
|
||||||
.defer(d3.tsv, "panels/map2/lib/world-country-names.tsv")
|
|
||||||
.await(function(error, world, names) {
|
|
||||||
dr.worldData = world;
|
|
||||||
dr.worldNames = names;
|
|
||||||
|
|
||||||
//Better way to get these values? Seems kludgy to use jQuery on the div...
|
|
||||||
var width = $(elem[0]).width(),
|
|
||||||
height = $(elem[0]).height();
|
|
||||||
|
|
||||||
//scale to whichever dimension is smaller, helps to ensure the whole map is displayed
|
|
||||||
dr.scale = (width > height) ? (height/5) : (width/5);
|
|
||||||
|
|
||||||
dr.zoom = d3.behavior.zoom()
|
|
||||||
.scaleExtent([1, 20])
|
|
||||||
.on("zoom", translate_map);
|
|
||||||
|
|
||||||
//used by choropleth
|
|
||||||
//@todo change domain so that it reflects the domain of the data
|
|
||||||
dr.quantize = d3.scale.quantize()
|
|
||||||
.domain([0, 1000])
|
|
||||||
.range(d3.range(9).map(function(i) { return "q" + (i+1); }));
|
|
||||||
|
|
||||||
//Extract name and two-letter codes for our countries
|
|
||||||
dr.countries = topojson.feature(dr.worldData, dr.worldData.objects.countries).features;
|
|
||||||
|
|
||||||
dr.countries = dr.countries.filter(function(d) {
|
|
||||||
return dr.worldNames.some(function(n) {
|
|
||||||
if (d.id == n.id) {
|
|
||||||
d.name = n.name;
|
|
||||||
return d.short = n.short;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}).sort(function(a, b) {
|
|
||||||
return a.name.localeCompare(b.name);
|
|
||||||
});
|
|
||||||
|
|
||||||
//create the new svg
|
|
||||||
dr.svg = d3.select(elem[0]).append("svg")
|
|
||||||
.attr("width", "100%")
|
|
||||||
.attr("height", "100%")
|
|
||||||
.attr("viewBox", "0 0 " + width + " " + height)
|
|
||||||
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")")
|
|
||||||
.call(dr.zoom);
|
|
||||||
dr.g = dr.svg.append("g");
|
|
||||||
|
|
||||||
scope.initializing = false;
|
|
||||||
render_panel();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Render updates to the SVG. Typically happens when the data changes (time, query)
|
|
||||||
* or when new options are selected
|
|
||||||
*/
|
|
||||||
function render_panel() {
|
|
||||||
|
|
||||||
var width = $(elem[0]).width(),
|
|
||||||
height = $(elem[0]).height();
|
|
||||||
|
|
||||||
//Projection is dependant on the map-type
|
|
||||||
if (scope.panel.display.data.type === 'mercator') {
|
|
||||||
dr.projection = d3.geo.mercator()
|
|
||||||
.translate([width/2, height/2])
|
|
||||||
.scale(dr.scale);
|
|
||||||
|
|
||||||
} else if (scope.panel.display.data.type === 'orthographic') {
|
|
||||||
dr.projection = d3.geo.orthographic()
|
|
||||||
.translate([width/2, height/2])
|
|
||||||
.scale(100)
|
|
||||||
.clipAngle(90);
|
|
||||||
|
|
||||||
//recenters the sphere more towards the US...not really necessary
|
|
||||||
dr.projection.rotate([100 / 2, 20 / 2, dr.projection.rotate()[2]]);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
dr.path = d3.geo.path()
|
|
||||||
.projection(dr.projection).pointRadius(0.2);
|
|
||||||
|
|
||||||
console.log(scope.data);
|
|
||||||
|
|
||||||
//Geocoded points are decoded into lonlat
|
|
||||||
dr.points = _.map(scope.data, function (k, v) {
|
|
||||||
//console.log(k,v);
|
|
||||||
var decoded = geohash.decode(v);
|
|
||||||
return [decoded.longitude, decoded.latitude];
|
|
||||||
});
|
|
||||||
|
|
||||||
//And also projected projected to x/y. Both sets of points are used
|
|
||||||
//by different functions
|
|
||||||
dr.projectedPoints = _.map(dr.points, function (coords) {
|
|
||||||
return dr.projection(coords);
|
|
||||||
});
|
|
||||||
|
|
||||||
dr.svg.select(".overlay").remove();
|
|
||||||
|
|
||||||
dr.svg.append("rect")
|
|
||||||
.attr("class", "overlay")
|
|
||||||
.attr("width", width)
|
|
||||||
.attr("height", height)
|
|
||||||
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
|
|
||||||
|
|
||||||
|
|
||||||
//Draw the countries, if this is a choropleth, draw with fancy colors
|
|
||||||
var countryPath = dr.g.selectAll(".land")
|
|
||||||
.data(dr.countries);
|
|
||||||
|
|
||||||
countryPath.enter().append("path")
|
|
||||||
.attr("class", function(d) {
|
|
||||||
if (scope.panel.display.choropleth.enabled) {
|
|
||||||
return 'land ' + dr.quantize(scope.data[d.short]);
|
|
||||||
} else {
|
|
||||||
return 'land';
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.attr("d", dr.path);
|
|
||||||
|
|
||||||
countryPath.exit().remove();
|
|
||||||
|
|
||||||
//If this is a sphere, set up drag and keypress listeners
|
|
||||||
if (scope.panel.display.data.type === 'orthographic') {
|
|
||||||
dr.svg.style("cursor", "move")
|
|
||||||
.call(d3.behavior.drag()
|
|
||||||
.origin(function() { var rotate = dr.projection.rotate(); return {x: 2 * rotate[0], y: -2 * rotate[1]}; })
|
|
||||||
.on("drag", function() {
|
|
||||||
if (scope.keylistener.keyActive(17)) {
|
|
||||||
dr.projection.rotate([d3.event.x / 2, -d3.event.y / 2, dr.projection.rotate()[2]]);
|
|
||||||
|
|
||||||
//dr.svg.selectAll("path").attr("d", dr.path);
|
|
||||||
dr.g.selectAll("path").attr("d", dr.path);
|
|
||||||
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//Special fix for when the user changes from mercator -> orthographic
|
|
||||||
//The globe won't redraw automatically, we need to force it
|
|
||||||
if (scope.panel.display.data.type === 'orthographic') {
|
|
||||||
dr.svg.selectAll("path").attr("d", dr.path);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Display option rendering
|
|
||||||
* Order is important to render order here!
|
|
||||||
*/
|
|
||||||
|
|
||||||
//@todo fix this
|
|
||||||
var dimensions = [width, height];
|
|
||||||
displayBinning(scope, dr, dimensions);
|
|
||||||
displayGeopoints(scope, dr);
|
|
||||||
displayBullseye(scope, dr);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//If the panel scale is not default (e.g. the user has moved the maps around)
|
|
||||||
//set the scale and position to the last saved config
|
|
||||||
if (scope.panel.display.scale != -1) {
|
|
||||||
dr.zoom.scale(scope.panel.display.scale).translate(scope.panel.display.translate);
|
|
||||||
dr.g.style("stroke-width", 1 / scope.panel.display.scale).attr("transform", "translate(" + scope.panel.display.translate + ") scale(" + scope.panel.display.scale + ")");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* On D3 zoom events, pan/zoom the map
|
|
||||||
* Only applies if the ctrl-key is not pressed, so it doesn't clobber
|
|
||||||
* sphere dragging
|
|
||||||
*/
|
|
||||||
function translate_map() {
|
|
||||||
|
|
||||||
var width = $(elem[0]).width(),
|
|
||||||
height = $(elem[0]).height();
|
|
||||||
|
|
||||||
if (! scope.keylistener.keyActive(17)) {
|
|
||||||
var t = d3.event.translate,
|
|
||||||
s = d3.event.scale;
|
|
||||||
t[0] = Math.min(width / 2 * (s - 1), Math.max(width / 2 * (1 - s), t[0]));
|
|
||||||
t[1] = Math.min(height / 2 * (s - 1) + 230 * s, Math.max(height / 2 * (1 - s) - 230 * s, t[1]));
|
|
||||||
dr.zoom.translate(t);
|
|
||||||
|
|
||||||
scope.panel.display.translate = t;
|
|
||||||
scope.panel.display.scale = s;
|
|
||||||
dr.g.style("stroke-width", 1 / s).attr("transform", "translate(" + t + ") scale(" + s + ")");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
Loading…
Reference in New Issue
Block a user