2016-06-17 2 views
2

Как применять гексагоны ко всему миру. Я нашел this пример в Интернете, но не смог применить его для всего мира var bbox = [-180, -90, 180, 90];, но он не работает должным образом.Как применять гексагон для всего мира

///////////////////////////////////////////////////////////////////////////////////////////// 
 
//setting up the map// 
 
///////////////////////////////////////////////////////////////////////////////////////////// 
 

 
// set center coordinates 
 
var centerlat = 40.758896; 
 
var centerlon = -73.985130; 
 

 
// set default zoom level 
 
var zoomLevel = 11; 
 

 
// initialize map 
 
var map = L.map('map').setView([centerlat, centerlon], zoomLevel); 
 

 
// set source for map tiles 
 
ATTR = '&copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, ' + 
 
    '<a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a> | ' + 
 
    '&copy; <a href="http://cartodb.com/attributions">CartoDB</a>'; 
 

 
CDB_URL = 'http://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png'; 
 

 
// add tiles to map 
 
L.tileLayer(CDB_URL, { 
 
    attribution: ATTR 
 
}).addTo(map); 
 

 
///////////////////////////////////////////////////////////////////////////////////////////// 
 
//generating the GeoJSON objects// 
 
///////////////////////////////////////////////////////////////////////////////////////////// 
 

 
//create some GeoJSON points to be sampled (function below) 
 
var dotcount = 200000; 
 
var dots = make_dots(dotcount); 
 

 
//parameters for hex grid 
 
var bbox = [-74.035492, 40.706523, -73.908463, 40.825095]; 
 
var cellWidth = 0.3; 
 
var units = 'miles'; 
 

 
//create hex grid and count points within each cell 
 
var hexgrid = turf.hexGrid(bbox, cellWidth, units); 
 
var hexcounts = turf.count(hexgrid, dots, 'pt_count'); 
 
L.geoJson(hexcounts, { 
 
    onEachFeature: onEachHex 
 
}).addTo(map); 
 

 
function getRandomCoordinates(radius, uniform) { 
 
    // Generate two random numbers 
 
    var a = Math.random(), 
 
    b = Math.random(); 
 

 
    // Flip for more uniformity. 
 
    if (uniform) { 
 
    if (b < a) { 
 
     var c = b; 
 
     b = a; 
 
     a = c; 
 
    } 
 
    } 
 

 
    // It's all triangles. 
 
    return [ 
 
    b * radius * Math.cos(2 * Math.PI * a/b), 
 
    b * radius * Math.sin(2 * Math.PI * a/b) 
 
    ]; 
 
} 
 

 
function getRandomLocation(latitude, longitude, radiusInMeters) { 
 
    var randomCoordinates = getRandomCoordinates(radiusInMeters, true); 
 

 
    // Earths radius in meters via WGS 84 model. 
 
    var earth = 6378137; 
 

 
    // Offsets in meters. 
 
    var northOffset = randomCoordinates[0], 
 
    eastOffset = randomCoordinates[1]; 
 

 
    // Offset coordinates in radians. 
 
    var offsetLatitude = northOffset/earth, 
 
    offsetLongitude = eastOffset/(earth * Math.cos(Math.PI * (latitude/180))); 
 

 
    // Offset position in decimal degrees. 
 
    return { 
 
    latitude: latitude + (offsetLatitude * (180/Math.PI)), 
 
    longitude: longitude + (offsetLongitude * (180/Math.PI)) 
 
    } 
 
} 
 

 
/*function make_dots() { 
 
    var dots = { 
 
    type: "FeatureCollection", 
 
    features: [] 
 
    }; 
 

 
    for (var i = 0; i < dotcount; ++i) { 
 
    var loc = getRandomLocation(40.767915, -73.972321, 1000); 
 

 
    var t = L.marker([loc.latitude, loc.longitude]); 
 

 
    dots.features.push(t.toGeoJSON()); 
 
    } 
 

 
    return dots; 
 
} 
 
*/ 
 

 
///////////////////////////////////////////////////////////////////////////////////////////// 
 
//legend// 
 
///////////////////////////////////////////////////////////////////////////////////////////// 
 

 
//create legend 
 
var hexlegend = L.control({ 
 
    position: 'topright' 
 
}); 
 
//generate legend contents 
 
hexlegend.onAdd = function(map) { 
 
    //set up legend grades and labels 
 
    var div = L.DomUtil.create('div', 'info legend'), 
 
    grades = [1, 2, 5, 10, 20, 50, 100], 
 
    labels = ['<strong>Point Count</strong>'], 
 
    from, to; 
 

 
    //iterate through grades and create a color field and label for each 
 
    for (var i = 0; i < grades.length; i++) { 
 
    from = grades[i]; 
 
    to = grades[i + 1]; 
 
    labels.push(
 
     '<i style="background:' + getColor(from + 0.5) + '"></i> ' + from + (to ? '&ndash;' + to : '+')); 
 
    } 
 
    div.innerHTML = labels.join('<br>'); 
 
    return div; 
 
}; 
 
hexlegend.addTo(map); 
 

 
///////////////////////////////////////////////////////////////////////////////////////////// 
 
//styling functions// 
 
///////////////////////////////////////////////////////////////////////////////////////////// 
 

 
//highlight style 
 
var hexStyleHighlight = { 
 
    color: "#336", 
 
    weight: 2, 
 
    opacity: 1, 
 
}; 
 

 
//create color ramp 
 
function getColor(y) { 
 
    return y == undefined ? '#888' : 
 
    y < 1 ? '#ffffe9' : 
 
    y < 2 ? '#edf8b1' : 
 
    y < 5 ? '#c7e9b4' : 
 
    y < 10 ? '#7fcdbb' : 
 
    y < 20 ? '#41b6c4' : 
 
    y < 50 ? '#1d91c0' : 
 
    y < 100 ? '#225ea8' : 
 
    '#0c2c84'; 
 
} 
 

 
//create style, with fillColor picked from color ramp 
 
function style(feature) { 
 
    return { 
 
    fillColor: getColor(feature.properties.pt_count), 
 
    color: "#888", 
 
    weight: 0.5, 
 
    opacity: 1, 
 
    fillOpacity: 0.4//0.8 
 
    }; 
 
} 
 

 
//attach styles and popups to the hex layer 
 
function highlightHex(e) { 
 
    var layer = e.target; 
 
    layer.setStyle(hexStyleHighlight); 
 
    if (!L.Browser.ie && !L.Browser.opera) { 
 
    layer.bringToFront(); 
 
    } 
 
} 
 

 
function resetHexHighlight(e) { 
 
    var layer = e.target; 
 
    var hexStyleDefault = style(layer.feature); 
 
    layer.setStyle(hexStyleDefault); 
 
} 
 

 
function onEachHex(feature, layer) { 
 
    layer.on({ 
 
    mouseover: highlightHex, 
 
    mouseout: resetHexHighlight 
 
    }); 
 
    var hexStyleDefault = style(layer.feature); 
 
    layer.setStyle(hexStyleDefault); 
 
    //for the sake of grammar 
 
    if (feature.properties.pt_count == 1) { 
 
    var be_verb = "There is"; 
 
    var point_s = "point"; 
 
    } else { 
 
    var be_verb = "There are"; 
 
    var point_s = "points"; 
 
    } 
 
    layer.bindPopup(be_verb + ' <b>' + feature.properties.pt_count + '</b> ' + point_s + ' in this cell.'); 
 

 
} 
 

 
///////////////////////////////////////////////////////////////////////////////////////////// 
 
//synthetic GeoJSON functions// 
 
///////////////////////////////////////////////////////////////////////////////////////////// 
 

 
//cheapo normrand function 
 
function normish(mean, range) { 
 
    var num_out = ((Math.random() + Math.random() + Math.random() + Math.random() + Math.random() + Math.random() + Math.random() + Math.random() - 4)/4) * range + mean; 
 
    return num_out; 
 
} 
 

 
//create geojson data with random ~normal distribution 
 
function make_dots(dotcount) { 
 

 
    var dots = { 
 
    type: "FeatureCollection", 
 
    features: [] 
 
    }; 
 

 
    for (var i = 0; i < dotcount; ++i) { 
 

 
    //set up random variables 
 
    /*x = normish(0, 4); 
 
    y = normish(0, 4); 
 

 
    //create points randomly distributed about center coordinates 
 
    var g = { 
 
     "type": "Point", 
 
      "coordinates": [((x * 0.11) + centerlon), ((y * 0.1) + centerlat)] 
 
    }; 
 

 
    //create feature properties, roughly proportional to distance from center coordinates 
 
    var p = { 
 
     "id": i, 
 
      "popup": "Dot_" + i, 
 
      "year": parseInt(Math.sqrt(x * x + y * y) * 60 * (1 - Math.random()/1.5) + 1900), 
 
      "size": Math.round((parseFloat(Math.abs((normish(y*y, 2) + normish(x*x, 2)) * 50) + 10)) * 100)/100 
 
    };*/ 
 

 
    var loc = getRandomLocation(40.769996, -73.973007, 5000); 
 

 
    var t = L.marker([loc.latitude, loc.longitude]); 
 

 
    dots.features.push(t.toGeoJSON()); 
 

 
    //create features with proper geojson structure   
 
    //dots.features.push({ 
 
    // "geometry" : g, 
 
    // "type": "Feature", 
 
    // "properties": p 
 
    //}); 
 
    } 
 
    return dots; 
 
}
html, 
 
body, 
 
#map { 
 
    height: 100%; 
 
    width: 100%; 
 
    padding: 0px; 
 
    margin: 0px; 
 
} 
 

 
.info { 
 
    padding: 6px 8px; 
 
    font: 14px/16px Arial, Helvetica, sans-serif; 
 
    background: white; 
 
    background: rgba(255, 255, 255, 0.8); 
 
    box-shadow: 0 0 15px rgba(0, 0, 0, 0.2); 
 
    border-radius: 5px; 
 
} 
 

 
.legend { 
 
    text-align: left; 
 
    line-height: 18px; 
 
    color: #555; 
 
} 
 

 
.legend i { 
 
    width: 18px; 
 
    height: 18px; 
 
    float: left; 
 
    margin-right: 8px; 
 
    opacity: 0.7; 
 
} 
 

 
.legend .colorcircle { 
 
    border-radius: 50%; 
 
    width: 15px; 
 
    height: 15px; 
 
    margin-top: 0px; 
 
}
<script src="https://api.mapbox.com/mapbox.js/plugins/turf/v2.0.2/turf.min.js"></script> 
 
<script src="http://cdn.leafletjs.com/leaflet-0.7.2/leaflet.js"></script> 
 
<link href="http://cdn.leafletjs.com/leaflet-0.7.2/leaflet.css" rel="stylesheet"/> 
 

 
<div id="map"></div>

EDIT: Вместо того, чтобы использовать turf.js, который является третьей библиотекой партии Я пытался создать свои собственные шестиугольники с помощью L.multiPolygon все работает нормально, но это работает только для небольшой части карты, если Я добавляю больше шестиугольников, с которыми столкнулся браузер. Поэтому я хотел избежать загрузки всех шестерен одновременно, но только тех, которые можно увидеть на экране. Я нашел способ L.PolyUtil.clipPolygon, но я не знаю, как это работает, вот jsfiddle

///////////////////////////////////////////////////////////////////////////////////////////// 
 
//setting up the map// 
 
///////////////////////////////////////////////////////////////////////////////////////////// 
 
// set center coordinates 
 
var lat = 35.15; 
 
var lng = 33.35; 
 
var R = 500; 
 

 
// set default zoom level 
 
var zoomLevel = 13; 
 

 
// initialize map 
 
var map = L.map('map').setView([lat, lng], zoomLevel); 
 

 
// set source for map tiles 
 
ATTR = '&copy; <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, ' + 
 
    '<a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a> | ' + 
 
    '&copy; <a href="http://cartodb.com/attributions">CartoDB</a>'; 
 

 
CDB_URL = 'http://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png'; 
 

 
// add tiles to map 
 
L.tileLayer(CDB_URL, { 
 
    attribution: ATTR, 
 
    noWrap: true 
 
}).addTo(map); 
 

 
var b = new L.Circle([lat, lng], R).getBounds(); 
 
var r = (b._northEast.lat - b._southWest.lat)/2; 
 
var h = (b._northEast.lng - b._southWest.lng)/2; 
 
var d = Math.sqrt(3 * h * h/4); 
 

 
var grid_x = 100; 
 
var grid_y = 100; 
 

 
var la = lat; 
 
var lo = lng; 
 
var multiPolygonLatLongs = []; 
 
for (var i = 0; i < grid_x; i++) { 
 
    for (var j = 0; j < grid_y; j++) { 
 
     multiPolygonLatLongs.push([ 
 
      [la + r, lo], 
 
      [la + r/2, lo + d], 
 
      [la - r/2, lo + d], 
 
      [la - r, lo], 
 
      [la - r/2, lo - d], 
 
      [la + r/2, lo - d] 
 
     ]); 
 
     lo += d * 2; 
 
    } 
 
    lo = i % 2 == 0 ? lng + d : lng; 
 
    la += r * 1.5; 
 
} 
 

 
var p1 = map.getPixelOrigin(); 
 
var bounds = map.getPixelBounds(); 
 

 
var clipped = L.PolyUtil.clipPolygon(multiPolygonLatLongs, bounds); 
 

 
L.multiPolygon(clipped, { 
 
    weight: 1, 
 
    opacity: 0.2, 
 
    fill: false 
 
}).addTo(map);
html, body, #map { 
 
     height: 100%; 
 
     width:100%; 
 
     padding:0px; 
 
     margin:0px; 
 
    }
<script src="http://cdn.leafletjs.com/leaflet-0.7.2/leaflet.js"></script> 
 
<link href="http://cdn.leafletjs.com/leaflet-0.7.2/leaflet.css" rel="stylesheet"/> 
 

 
<div id="map"></div>

ответ

2

Вы можете сделать это в CartoDB с запросом, как этот:

SELECT 
    CDB_HexagonGrid(
    ST_Transform(
     ST_SetSRID( 
     ST_MakeEnvelope(
      -179.99, 
      -89.99, 
      179.99, 
      89.99), 
     4326), 
     3857), 
    150000) 
    AS the_geom_webmercator 

Запустите его в редакторе и нажмите «создать набор данных из запроса».

После этого вы можете использовать этот слой как еще один слой в CartoDB. Проверьте this example, чтобы узнать, как загрузить его, используя cartodb.createLayer() с пользовательской интерактивностью.

Кроме того, если вы хотите, чтобы загрузить данные в формате GeoJSON, которые будут использоваться в листовке вместо этого, вы могли бы использовать что-то вроде:

var sql=new cartodb.SQL({user:'USERNAME', format:'geojson'}); 
    sql.execute("SELECT * FROM table_name").done(function(geojson){ 
    data=geojson; 
    }); 

После этого, вы можете использовать шестнадцатеричный сетку как geoJSON layer в листовке ,

+0

Я хотел бы иметь контроль над своим шестнадцатеричным, я хочу знать, когда его нажмут – Almis

+0

не могли бы вы сделать jsfiddle? – Almis

Смежные вопросы