I had more than 600 kml files to load in a single google map.
Initially I tried with KmlLayer(), but it didn't work due to the amount of kml files, so I found GeoXML3, and it works really fine.
Now I need to retrieve the path's coords for every polygon created with GeoXML3. Here I found the method getPaths() that seems to be just what I'm looking for, but it doesn't work because now I don't create polygons using the class Polygon but using the class geoxml3
for (i=0; i < controlli.length; i++)
{
appo = kmlurl + controlli[i].id + ".kml";
appo = appo.replace(" ", '_');
area[controlli[i].id] = new geoXML3.parser({
map: map,
zoom: false,
});
area[controlli[i].id].parse(appo);
//here I would like to do something like: 'area[controlli[i].id].getPaths()'
}
How can I do this?
The google.maps.Polygon objects created by geoXml3 to represent the KML polygons can be accessed 2 ways:
area[controlli[0].id].docs[0].placemarks[0].polygon.getPath()
working jsfiddle
area[controlli[0].id].docs[0].gpolygons[0].getPath()
working jsfiddle
where geoXml is a reference to the parser object (your area[controlli[i].id])
and i is a sequential reference to the placemarks (or the polygons) in the KML).
If you are using it on a KML file loaded asynchronously, you need to wait for the parsed event, or use the data in the afterParse function.
Related
I have a bokeh Google maps plot with several Lat/ Lng data points, and I would like to use the fitBounds() method of the Google Maps v3 API to set the zoom level.
I have a Google Maps plot up and running, displaying on my site and showing the data points, but I need to set the zoom manually.
import bokeh.io
import bokeh.models
import bokeh.plotting
import pandas as pd
data = {
'Latitude [deg]': [18.46, 25.7, 32.3],
'Longitude [deg]': [-66, -80.2, -64.8],
}
data_frame = pd.DataFrame.from_dict(data)
data_source = bokeh.models.ColumnDataSource(data_frame)
mean_lat = data_frame['Latitude [deg]'].mean()
mean_lng = data_frame['Longitude [deg]'].mean()
gmap_options = bokeh.models.GMapOptions(lat=mean_lat, lng=mean_lng, zoom=10, map_type='satellite')
xy_gmap = bokeh.plotting.gmap('SuPeRSeCrEtAPIkey', gmap_options)
xy_gmap.circle(x='Longitude [deg]', y='Latitude [deg]', source=data_source, color="red")
# A callback like this? Could make the call in JavaScript after the page is loaded, and update map zoom??
# xy_gmap.fitBounds(x='Longitude [deg]', y='Latitude [deg]', source=data_source)
bokeh.io.show(xy_gmap)
I would like the bounds of the map to enclose all points in my dataframe, at the lowest zoom possible (as is done in Javascript by fitBounds() ). Currently, the map can only zoom to the manually set level.
As of Bokeh 1.2, there is no built-in way to accomplish this. The only suggestion I can offer is to note that there is a global Bokeh.index on the JavaScript side, and in that there is GMapPlotView for the corresponding GmapPlot that you made. This view has an attribute .map that is the actual Google map object. You could call the fitBounds method on that from JavaScript code. Bokeh GMapPlot objects follow Google's lead wrt to plot bounds, so if they get updated, the axes, etc. should respond.
Otherwise, I can only suggest opening a GitHub issue to discuss adding this as a new feature.
Starting an answer for both methods described by bigreddot (using JS Bokeh.index and Python integration)
Bokeh.index
In the Javascript Console, you can use the following commands (should be self explanatory to get this into some JS code)
> var gmapPlotView;
> for (var property in Bokeh.index) { if (Bokeh.index[property].constructor.name == 'GMapPlotView') {gmapPlotView = Bokeh.index[property];} } // Get the correct object, in the case that you have multiple plots, but only one map plot
> var bounds = gmapPlotView.map.getBounds(); // To start from existing bounds
> var bounds = google.maps.LatLngBounds(); // To start with fresh bounds
> var place = new google.maps.LatLng(45.5983128 ,8.9172776); // Coordinates of place to put bounds, repeat for all points
> bounds.extend(place); // Add each place to the bounds object
> gmapPlotView.map.fitBounds(bounds); // Set the maps new bounds
Note that the Bokeh google maps implementation does not plot your data on the Google Maps data layer, but on a bokeh canvas above the map (that is why there is a lag when panning the map between map tiles and your graphs).
Python Integration
In process....
I'm trying to create an custom stationary map using the Leaflet JavaScript library and keep running into a major issue where most of the map tiles for the coordinates do not render. I'm defining & showing the map like so
function initmap() {
map = new L.Map('map');
var osmUrl = 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer/tile/{z}/{y}/{x}.png';
var osm = new L.TileLayer(osmUrl);
map.addLayer(osm);
}
var lat = 40.120910;
var lng = -74.978602;
var startLatLng = new L.LatLng(lat, lng);
initmap();
map.setView(startLatLng, 16);
It seems like it should work, but the map div never shows the full map/all tiles. I know there is coverage for this particular area because I've been using another person's service that using this library and map to look at this location. This code is structured based off of their code.
This website is using the exact coordinates, map server, and the leaflet js script and is able to render all tiles fine.
Here's a JSFiddle to show the code (and issue) in action. Any idea why this is happening or how to fix it?
Missing Leaflet CSS: https://npmcdn.com/leaflet#1.0.0-rc.1/dist/leaflet.css
Updated JSFiddle: https://jsfiddle.net/t14rLknv/7/
(BTW you can upgrade to Leaflet 1.0.0-rc.3, new official CDN on unpkg.com, see http://leafletjs.com/download.html)
I have two geoJSON feature collections that I need to add to the map, and I also want them to be toggled on and off via the layer visibility controllers as shown in http://leafletjs.com/examples/layers-control.html
how can I do this?
There is also a very good tutorial on the usage of L.GeoJSON, Leaflet's GeoJSON layer, which can be found here: http://leafletjs.com/examples/geojson.html and here is the reference for L.GeoJSON: http://leafletjs.com/reference.html#geojson You already found the tutorial on L.control.layers, here is the reference for it: http://leafletjs.com/reference.html#control-layers
It's actually quite simple to do, it's just a matter of creating a layercontrol, loading a GeoJSON file into your script by using your favorite XHR library, use the retrieved data to defined a L.GeoJSON layer and add it to the layercontrol. In code:
// Create the layercontrol and add it to the map
var controlLayers = L.control.layers().addTo(map);
// Loading a GeoJSON file (using jQuery's $.getJSON)
$.getJSON('/my-folder/my-file.json', function (data) {
// Use the data to create a GeoJSON layer and add it to the map
var geojsonLayer = L.geoJson(data).addTo(map);
// Add the geojson layer to the layercontrol
controlLayers.addOverlay(geojsonLayer, 'My GeoJSON layer title');
});
A working example on Plunker: http://plnkr.co/edit/tFVrrq?p=preview
Since you create a layer when loading a GeoJSON, you can add it to the layer control as an Overlay Layer (simply modify that example and replace the cities layer.
I am using a simple Mapbox layer control calling MB data layers (below).
I need to add a few more marker layers to this, but not sure how to get a mapbox ID. How can I accomplish this?
L.mapbox.accessToken = 'pk.eyJ1IjoibWFwc3RlciIsImEiOiI3RmFfME5ZIn0.73sdzUFNqSsGQzjlsnimaA';
var map = L.map('map').setView([38.8922,-77.0348], 14);
var layers = document.getElementById('menu-ui');
addLayer(L.mapbox.tileLayer('examples.map-i87786ca'), 'Base Map', 1);
addLayer(L.mapbox.tileLayer('examples.bike-lanes'), 'Bike Lanes', 2);
addLayer(L.mapbox.tileLayer('examples.bike-locations'), 'Bike Stations', 3);
function addLayer(layer, name, zIndex) {
layer
.setZIndex(zIndex)
.addTo(map);
code is from Mapbox toggling layers template
At the moment you're using their example ID and maps. You're not supposed to do that. If you would have read at the bottom of the page you posted it says:
Use this example by copying its source into your own HTML page and replacing the Map ID with one of your own from your projects.
Where "your projects" is linked to https://www.mapbox.com/projects/. When you're not logged in you get a nice dialog which asks you to login or register. Once you've done that you'll get your very own ID and you are able to create projects. When creating a project you'll get a Map ID per project. It's all pretty selfexplanatory.
EDIT: If you want to insert a separate layer with features, you've got to create a project with only a markerlayer. Save it and copy the id. You can include that in another map by using L.mapbox.featureLayer:
var mapId = 'examples.map-zr0njcqy'; // use your feature mapid
var features = L.mapbox.featureLayer(mapId); // declare featureLayer
features.on('ready', function () { // Wait untill features are loaded
addLayer(features); // add it the same your tilelayers
}
You can also use this to load external geojson files by just using an URL instead of a mapid.
See the example: https://www.mapbox.com/mapbox.js/example/v1.0.0/features-from-another-map/
And the reference: https://www.mapbox.com/mapbox.js/api/v2.1.5/l-mapbox-featurelayer/
I'm trying to create map (using the Google Maps JavaScript API V3) which consists of several partially-transparent layers. By default, these layers should all be overlaid on top of one another to form a complete map, but the user should be able to turn any combination of them on or off (while preserving order) to create whatever view they prefer.
So far, I've had a great deal of luck getting this working for a single layer using map.mapTypes, but when adding all the layers via map.overlayMapTypes, I've hit a couple of snags:
The map doesn't seem to get fully initialized if map.setMapTypeId() is not called (no controls appear and the map is not correctly centered) and it cannot be called with an overlay.
It isn't clear how to toggle the visibility of an overlay without directly modifying the map.overlayMapTypes array, which complicates keeping them correctly ordered. I'd much prefer something analogous to the Traffic/Transit/Photos/etc. control available within Google Maps itself.
Here's the initialize function I'm working with. I'd post a link, but the map imagery isn't publicly available:
function initialize() {
map = new google.maps.Map(document.getElementById("map_canvas"), {
zoom: 0,
center: center
});
/* if these lines are uncommented, the single layer displays perfectly */
//map.mapTypes.set("Layer 3", layers[3]);
//map.setMapTypeId("Layer 3");
//return;
var dummy = new google.maps.ImageMapType({
name: "Dummy",
minZoom: 0,
maxZoom: 6,
tileSize: new google.maps.Size(256, 256),
getTileUrl: function() {return null; }
});
map.mapTypes.set("Dummy", dummy);
map.setMapTypeId("Dummy");
// layers is an array of ImageMapTypes
for (var i = 0; i < layers.length; i++) {
map.overlayMapTypes.push(layers[i]);
}
}
As you can see, I've tried creating a "dummy" maptype (which always returns null for tile URLs) to serve as the base map. While this does cause the controls to display, it still doesn't center correctly.
What's the best way to create a map which consists only of toggleable overlays?
Update: Turns out the dummy maptype works perfectly well if you also remember to set a projection. That's one problem solved, at least. :-)
I use ImageMapType, but I don't add it to mapTypes. I just add it to overlayMapTypes and when I need to remove it I use setAt to set the entry in overlayMapTypes to null.
You will need to add individual controls to the UI that toggle the individual layers.