Color intersection leaflet circle - leaflet

I have a question about leaflet/folium. I have multiple circles on a map.
All these circles does have some overlap with each other.
Wat I want to do is to draw a line/Polygon in a different color, where all circles meet (intersection).
This is an example of what I want to achieve. The blue line is the intersection and need a different color. Is this possible in folium or in pure leaflet? If so, how do I do that?

You can use the turfjs library and the turf.intersect method for this
/* eslint-disable no-undef */
/**
* intersection with turfjs
*/
// config map
let config = {
minZoom: 7,
maxZomm: 18,
};
// magnification with which the map will start
const zoom = 18;
// co-ordinates
const lat = 52.22977;
const lng = 21.01178;
// calling map
const map = L.map('map', config).setView([lat, lng], zoom);
// Used to load and display tile layers on the map
// Most tile servers require attribution, which you can set under `Layer`
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors',
}).addTo(map);
// three coordinate
const centers = [{
lat: 52.22990558765487,
lng: 21.01168513298035
},
{
lat: 52.22962958994604,
lng: 21.011593937873844
},
{
lat: 52.2297445891999,
lng: 21.012012362480167
}
]
// turf.circle option
const options = {
steps: 64,
units: 'meters',
options: {}
}
// circle radius
const radius = 30;
// array polygons
let polygons = [];
// set marker, add
centers.map(({
lat,
lng
}) => {
const polygon = turf.circle([lng, lat], radius, options);
// add cirkle polygon to map
L.geoJSON(polygon, {
color: "red",
weight: 2
}).addTo(map);
// add object to array
polygons.push(polygon);
})
// get intersection
const intersection = turf.intersect(...polygons);
// style intersection
const intersectionColor = {
color: "yellow",
weight: 2,
opacity: 1,
fillColor: "yellow",
fillOpacity: 0.7
};
// adding an intersection to the map
// and styling to this element
L.geoJSON(intersection, {
style: intersectionColor
}).addTo(map);
*,
:after,
:before {
box-sizing: border-box;
padding: 0;
margin: 0;
}
html {
height: 100%;
}
body,
html,
#map {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.6.0/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet#1.6.0/dist/leaflet.js"></script>
<script src="https://cdn.jsdelivr.net/npm/#turf/turf#5/turf.min.js"></script>
<div id="map"></div>

Related

How to automatically add roofs as polygons in Mapbox

Currently I am getting streets from the geocoding api then displying houses in that street in satelite view. Is there a way to automatically detect house roofs and automatically draw polygons over them?
mapboxgl.accessToken = accessToken;
const map = new mapboxgl.Map({
container: 'map', // container ID
style: 'mapbox://styles/mapbox/satellite-v9', // style URL
center: [lng, lat], // starting position [lng, lat]
zoom: 17, // starting zoom
});
const draw = new MapboxDraw({
displayControlsDefault: false,
controls: {
polygon: true,
trash: true
},
// Set mapbox-gl-draw to draw by default.
// The user does not have to click the polygon control button first.
defaultMode: 'draw_polygon'
});
map.addControl(draw)
map.addControl(new mapboxgl.NavigationControl())
map.on('draw.create', updateArea)
map.on('draw.delete', updateArea)
map.on('draw.update', updateArea)
function updateArea(e) {
const data = draw.getAll()
const answer = document.getElementById('calculated-area')
if (data.features.length > 0) {
const area = turf.area(data)
// Restrict the area to 2 decimal points.
const rounded_area = Math.round(area * 100) / 100
const areaInCM = rounded_area * 10000
answer.innerHTML =
`<p><strong>${areaInCM.toLocaleString('en-US')}</strong> square centimeters</p>`;
} else {
answer.innerHTML = ''
if (e.type !== 'draw.delete')
alert('Click the map to draw a polygon.')
}
}

Changing leaflet markers to circleMarkers

I'm trying to Change Leaflet markers to circleMarker on data coming from geoJSON file.
Until now her is how I display data on map:
const geodesic = new L.Geodesic().addTo(map); /* Affiche les ligne géodésiques*/
geodesic.fromGeoJson(waypoints);
function pointFilter(feature) {
if (feature.geometry.type === "Point") return true
}
var points = new L.geoJson(waypoints, {filter: pointFilter}).addTo(map);
My geoJSON file contains LineStrings and Points.
The geodesic lines and standard icon markers are displayed, but I would change them by circleMarker between each lines.
Hope I'm clear enough.
Thanks
Pierre
This is what the code may look like, change it as you see fit.
Here'a a whole example - autocomplete-with-geojson
const geojsonlayer = L.geoJSON(object, {
style: function (feature) {
return {
color: feature.properties.color || "red",
weight: 7,
opacity: 1,
fillOpacity: 0.7,
};
},
pointToLayer: (feature, latlng) => {
if (feature.properties.type === "Point") {
return new L.circleMarker(latlng, {
radius: 20,
});
}
},
onEachFeature: function (feature, layer) {},
});

Getting county from click on OSM

Is it possible to detect state and county based on coordinates from a click on OSM map (US only)?
I can get the coordinated using click event in Leaflet JS:
map.on('click', function(ev) {
console.log(ev.latlng);
});
I can also get location data by doing something l;like this:
map.on("click", function(ev) {
var ln = ev.latlng["lng"],
lt = ev.latlng["lat"];
pt = "https://nominatim.openstreetmap.org/reverse?format=jsonv2&lat="+lt+"&lon="+ln;
});
Which will return json data that looks like this:
https://nominatim.openstreetmap.org/reverse?format=jsonv2&lat=28.964162684075685&lon=-98.29776763916017
But I can't seem to be able to figure out what to do next... How do I get the county and state values from it?
You can just fetch, Ajax from jquery or use axios.
let config = {
minZoom: 2,
maxZoom: 18,
};
const zoom = 5;
const lat = 28.964162684075685;
const lng = -98.29776763916017;
const map = L.map("map", config).setView([lat, lng], zoom);
L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
attribution: '© OpenStreetMap contributors',
}).addTo(map);
map.on("click", function(e) {
const { lat, lng } = e.latlng;
const api = `https://nominatim.openstreetmap.org/reverse?format=json&lat=${lat}&lon=${lng}&zoom=18&addressdetails=1`;
fetchData(api).then((data) => {
const { county, state } = data.address;
console.log(county, state);
});
});
async function fetchData(url) {
try {
const response = await fetch(url);
const data = await response.json();
return data;
} catch (err) {
console.error(err);
}
}
*,
:after,
:before {
box-sizing: border-box;
padding: 0;
margin: 0;
}
html {
height: 100%;
}
body,
html,
#map {
width: 100%;
height: 100%;
}
body {
position: relative;
min-height: 100%;
margin: 0;
padding: 0;
background-color: #f1f1f1;
}
<script src="https://unpkg.com/leaflet#1.7.1/dist/leaflet.js"></script>
<link href="https://unpkg.com/leaflet#1.7.1/dist/leaflet.css" rel="stylesheet" />
<div id="map"></div>

Bound popup removed when layer changed in control

I have a map with a layer control that has overlays specified in the baselayer parameter:
var overlays = {
'Layer 1': mylayer1,
'Layer 2': mylayer2
};
L.control.layers( overlays, null, { collapsed: false } ).addTo( map );
I specify my layers as follows:
var mylayer1 = L.esri.featureLayer({
url: 'https://.../MapServer/5'
}).on( 'load', function ( e ) {
...
}).on( 'loading', function ( e ) {
...
}).bindPopup( function ( layer ) {
return L.Util.template( '<p>{_score}</p>', layer.feature.properties );
});
The issue is that when I change layers in the control the bindPopup event no longer gets called.
It's almost like the layer z-index is not updated. Would appreciate any insight on how I can address this.
See: https://codepen.io/jvanulde/pen/LYyOWZo
I see no one has given an answer.
A little around, but it works.
You add the id: x to each layer. Later in the loop you check which layer is active, and all the rest of the layers you add the style display: none.
window.addEventListener('DOMContentLoaded', () => {
let tiles = L.tileLayer('//{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors, Points &copy 2012 LINZ'
});
let l1 = L.esri.featureLayer({
url: 'https://maps-cartes.services.geo.ca/server_serveur/rest/services/NRCan/nhsl_en/MapServer/1',
id: 0, // required
simplifyFactor: 0.25,
precision: 5,
fields: ['OBJECTID'],
renderer: L.canvas()
}).bindPopup(function(layer) {
return L.Util.template('<p>Layer 1: <strong>{OBJECTID}</strong></p>', layer.feature.properties);
});
let l2 = L.esri.featureLayer({
url: 'https://maps-cartes.services.geo.ca/server_serveur/rest/services/NRCan/nhsl_en/MapServer/2',
id: 1, // required
simplifyFactor: 0.25,
precision: 5,
fields: ['OBJECTID'],
renderer: L.canvas()
}).bindPopup(function(layer) {
return L.Util.template('<p>Layer 2: <strong>{OBJECTID}</strong></p>', layer.feature.properties);
});
let map = L.map('map', {
center: [49.2827, -123.1207],
zoom: 12,
layers: [tiles]
});
let overlays = {
'Layer 1': l1,
'Layer 2': l2
};
L.control.layers(overlays, null, {
collapsed: false
}).addTo(map);
l1.addTo(map);
map.on('baselayerchange', function(e) {
const layersCanvas = document.querySelectorAll('.leaflet-overlay-pane > canvas');
layersCanvas.forEach((layer, index) => {
layer.style.display = '';
if (index !== e.layer.options.id) {
layer.style.display = 'none';
}
});
});
});
html {
height: 100%;
}
body {
min-height: 100%;
margin: 0;
padding: 0;
}
#map {
width: 100%;
height: 100vh;
}
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.7.1/dist/leaflet.css" />
<script src="https://unpkg.com/leaflet#1.7.1/dist/leaflet.js"></script>
<script src="https://unpkg.com/esri-leaflet#3.0.2/dist/esri-leaflet.js"></script>
<div id="map"></div>

How to show list of locations on google map

I am creating an iPhone application in which i need to fetch the latitude longitude from gps.Now i am calling update-location delegate method and adding new location to the array after that i need to show all latitude longitude(locations ) on goggle map and the route between all locations.
Please help me out in showing the route.
Thanks in advance
Here is how you might do it with the GoogleMaps javascript api.
<style>
#map_canvas {
height: 190px;
width: 300px;
margin-top: 0.6em;
}
</style>
<script src="https://maps.googleapis.com/maps/api/js?sensor=false&libraries=places"></script>
<div id="map_canvas" ></div>
<script language="javascript" type="text/javascript">
var latitude = 44.056389;
var longitude = -121.308056;
function initialize() {
var mapOptions = {
center: new google.maps.LatLng(latitude,longitude),
zoom: 9,
streetViewControl: false,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById('map_canvas'),
mapOptions);
// Create a draggable marker which will later on be binded to a
// Circle overlay.
var marker = new google.maps.Marker({
map: map,
position: new google.maps.LatLng(latitude,longitude),
draggable: true
});
// Add a Circle overlay to the map.
var circle = new google.maps.Circle({
strokeColor: "#0000FF",
strokeOpacity: 0.4,
strokeWeight: 2,
fillColor: "#0000FF",
fillOpacity: 0.20,
map: map,
radius: 16000 // meters
});
circle.bindTo('center', marker, 'position');
google.maps.event.addListener(marker, 'dragend', function() {
var location = marker.getPosition();
latitude = location.lat();
longitude = location.lng();
});
google.maps.event.addListener(autocomplete, 'place_changed', function() {
var place = autocomplete.getPlace();
var location = place.geometry.location;
map.setCenter(location);
map.setZoom(9); // Why 9? Because it looks good.
marker.setPosition(location);
latitude = location.lat();
longitude = location.lng();
});
}
</script>