TimeDimension с Leaflet и Python бэкэнд - PullRequest
1 голос
/ 07 марта 2019

Я работаю над тем, чтобы показать перегруженность через систему автострад.

Возникли трудности с добавлением Bounty.

Я создал пример, через который я работаю с JS bin здесь (https://jsbin.com/lebeqam/edit?html,js,output)

Я создал листовую карту с указанием длинных и идентификационных номеров детекторов.

У меня также есть CSV с данными о занятости, важным значением трафика, с течением времени для каждого детектора..

Мне интересно, как мне следует создать тепловую карту с этими данными, которые показаны на карте.Я хотел бы иметь возможность изменять время и даже воспроизводить время вперед или назад, чтобы получить представление о заторе и о том, как остановить его в его корне.

Это html и jscript для страницы, в настоящее время с некоторымиудаленные части

    <div id="mapid" style="height:1858px; border-right: 1px solid #d7d7d7; position: fixed; top: 0px;width: 67%;z-index: 0;cursor: -webkit-grab;cursor: -moz-grab;background: #fff;
    color: #404040;color: rgba(0,0,0,.75);outline: 0;overflow: hidden;-ms-touch-action: none;
    box-sizing: border-box;"></div>

  </div>

<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js"
        integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy"
        crossorigin="anonymous"></script>

<script src="https://use.fontawesome.com/releases/v5.0.8/js/all.js"></script>

</body>


<script>

var myIcon = L.divIcon({
    html: '<i class="fas fa-map-pin"></i>',
    iconSize: [20, 20],
    className: 'dummy' // We don't want to use the default class
});

    var mymap = L.map('mapid').setView([-37.735018, 144.894947], 13);

    L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw', {
        maxZoom: 18,
        attribution: 'Map data &copy; <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, ' +
            '<a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, ' +
            'Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
        id: 'mapbox.streets'
    }).addTo(mymap);

    L.geoJSON(myGeojsonData, {
    pointToLayer: function (getJsonPoint, latlng) {
        return L.marker(latlng, { icon: myIcon });
    }
}).bindPopup(function(layer) {
    return 'ID #: ' + layer.feature.properties.IDnumber + '<br />Area: ' + layer.feature.properties.Area;
}).addTo(mymap);

    var circle = L.circle([-37.735018, 144.894947], {
    color: 'red',
    fillColor: '#f03',
    fillOpacity: 0.5,
    radius: 50
}).addTo(mymap);

</script>

Это часть geoJson (весь файл огромен, но вы получите изображение)

var myGeojsonData =
{
  "features": [
    {
      "geometry": {
        "coordinates": [
          144.829434,
          -37.825233
        ],
        "type": "Point"
      },
      "properties": {
        "Area": "Combined Entry MVT on Grieve Pde, West Gate Fwy North Ramps, Grieve Pde Byp Start EB between Grieve ",
        "IDnumber": "2541EL_P0"
      },
      "type": "Feature"
    },...etc

И это CSV с данными трафика (также только часть этого ради пространства.)

Traffic Occupancy

Я попытался немного упростить это, используя эти два файла json, чтобы простоначало работы (файл временного ряда находится в jsbin, так как он слишком велик для stackoverflow.

var myGeojsonData =
{
  "features": [
    {
      "geometry": {
        "coordinates": [
          144.827465,
          -37.82572
        ],
        "type": "Point"
      },
      "properties": {
        "Area": "Freeway MVT on West Gate Fwy WB between Grieve Pde Off Ramp (ob) & Split To PFW and WRR",
        "IDnumber": "7859OB_L_P0"
      },
      "type": "Feature"
    },
    ],
  "type": "FeatureCollection"
}
;

Если бы кто-нибудь мог показать мне, как они подошли бы к этому, это было бы замечательно.

Спасибо

Ответы [ 2 ]

2 голосов
/ 14 марта 2019

Я думаю, что у вас есть немало работы, чтобы создать функциональное приложение, но я быстро подошел к тому, чтобы развить ваш jsbin, чтобы сделать большинство «кусочков» того, что вам нужно.

Я составил несколько дополнительных фальшивых данных и включил их в "7859OB_L_P1" в jsbin.

По сути, у меня есть:

  • реструктурировал данные примера, чтобы быть немного более полезным для построения тепловых карт (хотя ... может быть, на самом деле было бы лучше использовать их для подготовки данных в формате, ожидаемом библиотекой тепловой карты)

    i.e. [[lat, lng, value], ...] rather than {'Time':[...], 'Data':{...}}

  • Использовал библиотеку nouislider, рекомендованную istopopoki

  • Использовал существующий плагин листовки для рисования тепловых карт: leaflet.heat

Большая часть новой "работы" выполняется в вызове обновления ползунка. Вы можете увидеть это здесь: https://jsbin.com/jeguwif/edit?html,js,output

// Register an update handler on the slider which:
//  - Updates the "timeSelected" element
//  - Calculates the new data for the time
//  - sets the values into the heatmap and updates the "max" value
//
//  NB: if there is LOTS of data, it might be too slow to recalculate these
//      on every change, in which case perhaps building the [lat, lng, val] arrays
//      for each time up front might be a better idea
slider.noUiSlider.on('update', function (values, handle) {
  var index = Number(values[0])

  timeSelected.value = tabular['Time'][index]
  var dataRow = tabular['Data'][index]
   // play with this val for scaling, i.e. depends how zoomed you are etc
  var max = Math.max.apply(null, dataRow) * 1.0
  var heatValues = tabular['Locations'].map((loc, idx) => {
    return [].concat(locationCoords[loc]).concat(dataRow[idx])
  })

  heat.setOptions({max: max})
  heat.setLatLngs(heatValues.concat(heatValues).concat(heatValues))

});

Кроме того, я добавил скриптовые включения в раздел HTML-заголовка.

2 голосов
/ 07 марта 2019

Попробуйте следующее:

  1. создать функцию, принимающую дату в качестве аргумента, которая будет отображать данные на вашей карте только за эту дату. Или два аргумента (startDate, enDate), и ваша функция будет отображать данные между этими двумя датами. Эта функция должна фильтровать данные и отображать их.

  2. создать функцию, которая очищает все данные на карте.

  3. Рядом с картой добавьте ползунок. Или даты выбора, или что-нибудь, что дает возможность выбрать дату начала и окончания. Например, вы можете использовать nouislider . Когда пользователь меняет диапазон дат, вы можете связать что-то с этим событием . То, что вы будете связывать, - это функция, которая сначала очищает карту (т.е. вызывает функцию шага 2) и отображает новые данные (то есть вызывает функцию шага 1).

...