<!-- Leaflet --> <link rel="stylesheet" href="https://unpkg.com/leaflet@1.4.0/dist/leaflet.css" integrity="sha512-puBpdR0798OZvTTbP4A8Ix/l+A4dHDD0DGqYW6RQ+9jxkRFclaxxQb/SJAWZfWAkuyeQUytO7+7N4QKrDh+drA==" crossorigin=""/> <?php $currentFile = ''; foreach ($modelBasesArchivos as $archivo) { if($archivo->idTipoArchivo->nombre == 'GeoJSON'){ $currentFile = $archivo->archivo; } } ?> <div class="row"> <div class="col-md-2"> <h3>Filtros</h3> <h4>Lista de Propiedades</h4> <div id="propertyList"></div> </div> <div class="col-md-10"> <div id="mapid" style="height: 720px; z-index: 4;"></div> <div id="propertiesLegend"></div> </div> </div> <!-- Leaflet --> <script src="https://unpkg.com/leaflet@1.4.0/dist/leaflet.js" integrity="sha512-QVftwZFqvtRNi0ZyCtsznlKSWOStnDORoefr1enyq5mVL4tmKB3S/EnC3rRJcxCPavG10IcrVGSmPh6Qw5lwrg==" crossorigin=""></script> <script src="/RIR/js/palette.js"></script> <script> let geomap = L.map('mapid').setView([21.95774, -101.62595], 5); let mapLayer = L.tileLayer('http://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png ', { attribution: 'Map data © <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, <a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>' }); mapLayer.addTo(geomap); document.getElementById('geojson').style.display = 'block'; geomap.invalidateSize(false); document.getElementById('geojson').style.display = 'none'; $('li[class="nav-item"]').click(function(){ if($(this)[0].id === 'geojson_tab'){ document.getElementById('geojson').style.display = 'block'; let fileName = '<?php echo $currentFile;?>'; if(fileName != ''){ let target = document.getElementById(fileName); loadGeojson(fileName); } } else{ document.getElementById('geojson').style.display = 'none'; } }) $('#meta_tab').click(function(){ document.getElementById('geojson').style.display = 'none'; }); let currentLayer; let currentProperties = []; function onEachFeature(feature, layer) { if (feature.properties) { if (!(Object.entries(feature.properties).length === 0 && feature.properties.constructor === Object)){ let popupContent = '<table class="table table-striped">'; popupContent += '<thead>'; popupContent += '<tr>'; popupContent += '<th>Propiedad</th>'; popupContent += '<th>Valor</th>'; popupContent += '</tr>'; popupContent += '</thead>'; popupContent += '<tbody>'; Object.keys(feature.properties).forEach(function (key, index){ if(feature.geometry.type == 'Polygon' || feature.geometry.type == 'MultiPolygon'){ if(!currentProperties.includes(key)){ currentProperties.push(key); let nodeString = '<div class="radio"><label>'; nodeString += '<input type="radio" name="geoProperty" id="' + key + '" value="' + key + '" onclick="reloadGeojson()">'; nodeString += key; nodeString += '</label></div>'; $('#propertyList').append(nodeString); } } popupContent += '<tr>'; popupContent += '<td>' + key + '</td>'; popupContent += '<td>' + feature.properties[key] + '</td>'; popupContent += '</tr>'; }); popupContent += '</tbody>'; popupContent += '</table>'; layer.bindPopup(popupContent); } else { let popupContent = '<p>Sin información adicional.</p>'; layer.bindPopup(popupContent); } } } let currentFeatures = [] function loadGeojson(filename){ $('#propertiesLegend').hide(); $.getJSON('/RIR/archivos/' + filename, function(data){ let geometryType = data.features[0].geometry.type; let color = '#000'; if(geometryType != 'Polygon' && geometryType != 'MultiPolygon'){ color = '#00b140' } currentFeatures = data.features; currentLayer = L.geoJson(data, { style: { fillColor: "#00b140", color: color, fillOpacity: 0.7 }, onEachFeature: onEachFeature }).addTo(geomap); geomap.fitBounds(currentLayer.getBounds()); }); } let property = ''; let type = ''; let frequency = []; let colorsProperty = []; let stats = {}; function reloadGeojson(){ property = $('input[name=geoProperty]:checked').val(); type = typeof currentFeatures[0].properties[property]; colorsProperty = []; geomap.removeLayer(currentLayer); let propertiesData = []; for(let i = 0; i < currentFeatures.length; i++){ propertiesData.push(currentFeatures[i].properties[property]); } if(type === 'string'){ frequency = sortByFrequency(propertiesData); frequency = frequency.slice(0,5); colorByFrequency(frequency); } if(type === 'number'){ stats = calculateStatistics(propertiesData); colorByQuartile(stats); } } function sortByFrequency(array) { var frequency = {}; array.forEach(function(value) { frequency[value] = 0; }); var uniques = array.filter(function(value) { return ++frequency[value] == 1; }); return uniques.sort(function(a, b) { return frequency[b] - frequency[a]; }); } function colorByFrequency(array){ let fileName = '<?php echo $currentFile;?>'; colorsProperty = palette('cb-YlOrRd', array.length + 1); colorsProperty = colorsProperty.reverse() $.getJSON('/RIR/archivos/' + fileName, function(data){ currentLayer = L.geoJson(data, { style: styleBy, onEachFeature: onEachFeature }).addTo(geomap); geomap.fitBounds(currentLayer.getBounds()); }); let legendContainer = document.getElementById('propertiesLegend'); while(legendContainer.hasChildNodes()){ legendContainer.removeChild(legendContainer.lastChild); } for(let i = 0; i < array.length; i++){ let nodeString = '<p><div style="float: left;width: 25px;height: 25px;background-color:#'+ colorsProperty[i] +'"></div> ' + array[i] + '</p>'; $('#propertiesLegend').append(nodeString); } let otherNode = '<p><div style="float: left;width: 25px;height: 25px;background-color:#'+ colorsProperty[array.length] +'"></div> Otros</p>'; $('#propertiesLegend').append(otherNode); $('#propertiesLegend').show(); } function styleBy(feature){ return { fillColor: assignColor(feature.properties[property]), color: '#000', fillOpacity: 0.7 } } function colorByQuartile(stats){ let fileName = '<?php echo $currentFile;?>'; colorsProperty = palette('cb-YlOrRd', 4); $.getJSON('/RIR/archivos/' + fileName, function(data){ currentLayer = L.geoJson(data, { style: styleBy, onEachFeature: onEachFeature }).addTo(geomap); geomap.fitBounds(currentLayer.getBounds()); }); let legendContainer = document.getElementById('propertiesLegend'); while(legendContainer.hasChildNodes()){ legendContainer.removeChild(legendContainer.lastChild); } let upper_quartile = '<p><div style="float: left;width: 25px;height: 25px;background-color:#'+ colorsProperty[3] +'"></div> ≥' + stats.upper_quartile + '</p>'; $('#propertiesLegend').append(upper_quartile); let median = '<p><div style="float: left;width: 25px;height: 25px;background-color:#'+ colorsProperty[2] +'"></div> ≥' + stats.median + '</p>'; $('#propertiesLegend').append(median); let lower_quartile = '<p><div style="float: left;width: 25px;height: 25px;background-color:#'+ colorsProperty[1] +'"></div> ≥' + stats.lower_quartile + '</p>'; $('#propertiesLegend').append(lower_quartile); let other = '<p><div style="float: left;width: 25px;height: 25px;background-color:#'+ colorsProperty[0] +'"></div> <' + stats.lower_quartile + '</p>'; $('#propertiesLegend').append(other); $('#propertiesLegend').show(); } function assignColor(propertyValue){ if(type === 'string'){ for(let i = 0; i < frequency.length; i++){ if(propertyValue == frequency[i]){ return '#' + colorsProperty[i]; } } return '#' + colorsProperty[frequency.length]; } if(type === 'number') { if(propertyValue >= stats.upper_quartile) { return '#' + colorsProperty[3]; } else { if(propertyValue >= stats.median) { return '#' + colorsProperty[2]; } else { if(propertyValue >= stats.lower_quartile) { return '#' + colorsProperty[1]; } else { if(propertyValue < stats.lower_quartile){ return '#' + colorsProperty[0]; } } } } } } function calculateStatistics(data) { let stats = {}; let sum_of_squares = 0; let lower_quartile_index_1; let lower_quartile_index_2; // data needs to be sorted for median etc data = data.sort(function(a, b){return a - b}); // count is just the size of the data set stats.count = data.length; // initialize total to 0, and then iterate data // calculating total and sum of squares stats.total = 0; for(let i = 0; i < stats.count; i++) { stats.total += data[i]; sum_of_squares += Math.pow(data[i], 2); } // the arithmetic mean is simply the total divided by the count stats.arithmetic_mean = stats.total / stats.count; // method of calculating median and quartiles is different for odd and even count if(is_even(stats.count)) { stats.median = (data[((stats.count) / 2) - 1] + data[stats.count / 2]) / 2; // even / even if(is_even(stats.count / 2)) { lower_quartile_index_1 = (stats.count / 2) / 2; lower_quartile_index_2 = lower_quartile_index_1 - 1; stats.lower_quartile = (data[lower_quartile_index_1] + data[lower_quartile_index_2]) / 2; stats.upper_quartile = (data[stats.count - 1 - lower_quartile_index_1] + data[stats.count - 1 - lower_quartile_index_2]) / 2; } // even / odd else { lower_quartile_index_1 = ((stats.count / 2) - 1) / 2; stats.lower_quartile = data[lower_quartile_index_1]; stats.upper_quartile = data[stats.count - 1 - lower_quartile_index_1]; } } else { stats.median = data[((stats.count + 1) / 2) - 1]; // odd / even if(is_even((stats.count - 1) / 2)) { lower_quartile_index_1 = ((stats.count - 1) / 2) / 2; lower_quartile_index_2 = lower_quartile_index_1 - 1; stats.lower_quartile = (data[lower_quartile_index_1] + data[lower_quartile_index_2]) / 2; stats.upper_quartile = (data[stats.count - 1 - lower_quartile_index_1] + data[stats.count - 1 - lower_quartile_index_2]) / 2; } // odd / odd else { lower_quartile_index_1 = (((stats.count - 1) / 2) - 1) / 2; stats.lower_quartile = data[lower_quartile_index_1]; stats.upper_quartile = data[stats.count - 1 - lower_quartile_index_1]; } } // the data is sorted so the mimimum and maximum are the first and last values stats.minimum = data[0]; stats.maximum = data[stats.count - 1]; // the range is difference between the minimum and the maximum stats.range = stats.maximum - stats.minimum; // and the inter-quartile range is the difference between the upper and lower quartiles stats.inter_quartile_range = stats.upper_quartile - stats.lower_quartile; // this is the formula for the POPULATION variance stats.variance_population = (sum_of_squares - ((Math.pow(stats.total, 2)) / stats.count)) / stats.count; // the standard deviation is the square root of the variance stats.standard_deviation_population = Math.sqrt(stats.variance_population); // the formula for the sample variance is slightly different in that it use count -1 stats.variance_sample = (sum_of_squares - ((Math.pow(stats.total, 2)) / stats.count)) / (stats.count - 1); // the sample standard deviation is the square root of the sample variance stats.standard_deviation_sample = Math.sqrt(stats.variance_sample); // this is Pearson's second skewness coefficient, one of many measures of skewness stats.skew = (3.0 * (stats.arithmetic_mean - stats.median)) / stats.standard_deviation_population; return stats; } function is_even(n) { return n % 2 == 0; } </script>