leaflet invert when there are multiple polygons - javascript

I'm using this library to invert leaflet layers.
https://github.com/ebrelsford/Leaflet.snogylop
This works perfectly when there is only one polygon. But when are there are multiple polygons, the invert applies for each and every polygon so it overlaps resulting invert feature applies on top of each polygon. Like the image attached below.
When trying on a single polygon it works perfectly.
How can i fix this issue when multiple polygons are there.
function handleJson(data) {
var selectedArea = L.geoJson(data, {
invert: true,
worldLatLngs: [
L.latLng([90, 360]),
L.latLng([90, -180]),
L.latLng([-90, -180]),
L.latLng([-90, 360])
]
});
selectedArea.addTo(lmap);
lmap.fitBounds(selectedArea.getBounds());
}
PS:
poly.toGeoJSON()
{"type":"Feature","properties":{},"geometry":{"type":"MultiPolygon","coordinates":[[[[null,null],[null,null]]],[[[null,null],[null,null]]],[[[null,null],[null,null]]],[[[null,null],[null,null]]],[[[null,null],[null,null]]],[[[null,null],[null,null]]],[[[null,null],[null,null]]]]}}
multipolyCoords
[[[[{"lat":35.41263883,"lng":63.02502113},{"lat":35.41251986,"lng":63.02571771},{"lat":35.41329411,"lng":63.02584793},{"lat":35.41378402,"lng":63.02643689},{"lat":35.41402821,"lng":63.02723164},{"lat":35.41342648,"lng":63.02885513},{"lat":35.41342962,"lng":63.02891854},{"lat":35.4100508,"lng":63.02941312},
.....................
]]]],"_initHooksCalled":true

You have to create a MultiPolygon out of the polygons.
Try this (I'm assuming that you only have polygons in data):
var layers = L.geoJSON(data);
var multipolyCoords = [];
layers.eachLayer((l)=>{
if(l instanceof L.Polygon){
multipolyCoords.push(l.getLatLngs())
}
})
var poly = L.polygon(multipolyCoords);
var selectedArea = L.geoJson(poly.toGeoJSON(), {
invert: true,
worldLatLngs: [
L.latLng([90, 360]),
L.latLng([90, -180]),
L.latLng([-90, -180]),
L.latLng([-90, 360])
]
});

Related

Leaflet control not filtering markers

I'm trying to implement a 'filter' feature into my leaflet map alongside marker clusterer, I have got as far as having the control box and plotting the markers however upon unticking a 'category' nothing updates on the map I have attatched an example of which this feature is working http://jsfiddle.net/RogerHN/31v2afte/2/
this is how I plot the marker.
case 'antisocialbehaviour':
marker = L.marker(new L.LatLng(a[0], a[1]), {
icon: icons,
title: 'antisocialbehaviour'
});
markers_cluster.addLayer(marker);
break;
required code for control box ( top of javascript )
var groupA = L.layerGroup(markersA);
var groupB = L.layerGroup(markersB);
var markersA = [];
var markersB = [];
var overlayMaps = {
"A": groupA,
"B": groupB
};
L.control.layers(tileLayer, overlayMaps, {position:'topleft'}).addTo(map);
My code on JSFiddle if anybody needs to see the problem.
https://jsfiddle.net/jgov83fg/25/
I made a copy of your JSFiddle and made some changes to it.
I included the Leaflet.MarkerCluster.LayerSupport sub plugin in the body tag of the JSFiddle's HTML:
<script src="https://unpkg.com/leaflet.markercluster.layersupport#2.0.1/dist/leaflet.markercluster.layersupport.js"></script>
I added the following to the JavaScript code:
var mcgLayerSupportGroup = L.markerClusterGroup.layerSupport(),
group1 = L.layerGroup(),
group2 = L.layerGroup(),
group3 = L.layerGroup(),
group4 = L.layerGroup(),
control = L.control.layers(null, null, {
collapsed: false
}),
i, a, title, marker;
mcgLayerSupportGroup.addTo(mymap);
mcgLayerSupportGroup.checkIn([group1, group2, group3, group4]);
control.addOverlay(group1, 'Anti-Social Behaviour');
control.addOverlay(group2, 'Violent Crime');
control.addOverlay(group3, 'Bicycle Theft');
control.addOverlay(group4, 'Burglary');
control.addTo(mymap);
group1.addTo(mymap); // Adding to map or to AutoMCG are now equivalent.
group2.addTo(mymap);
group3.addTo(mymap);
group4.addTo(mymap);
Then, in the create_marker function, I call either marker.addTo(group1), marker2.addTo(group2), marker3.addTo(group3) or marker4.addTo(group4) based on the type of the crime the marker is associated with.
Hope this helps, let me know if you have any questions.

Leaflet offline grid layer

I want leaflet to work offline, without title, to show only a grid as titles. To have all the features of Leaflet, add plugins to draw a line, pin a marker, draw a polygon, zoom in / zoom out on shapes etc.
Is there a simple way to show just a simple grid?
Here's a custom GridLayer (that's already been implemented by the Leaflet authors). All you have to do is copy L.GridLayer.DebugCoords where you would normally load a tile layer.
var map = L.map('map', {
center: [0, 0],
zoom: 0
});
L.GridLayer.DebugCoords = L.GridLayer.extend({
createTile: function (coords, done) {
var tile = document.createElement('div');
//this adds tile coordinates; you may or may not want this
tile.innerHTML = [coords.x, coords.y, coords.z].join(', ');
tile.style.outline = '1px solid red';
/* // you don't need this artificial timeout for your application
setTimeout(function () {
done(null, tile); // Syntax is 'done(error, tile)'
}, 500 + Math.random() * 1500);
*/
return tile;
}
});
L.gridLayer.debugCoords = function(opts) {
return new L.GridLayer.DebugCoords(opts);
};
map.addLayer( L.gridLayer.debugCoords() );
Stand-alone, working example: http://leafletjs.com/examples/extending/gridcoords.html
Code taken from: http://leafletjs.com/examples/extending/extending-2-layers.html

Rendering Issue for Openstreet Maps with Yii

I have had issue previouslys with jquery and Yii and how it renders.
using the following code:
<div id="mapdiv" height="1000" width="1000"></div>
<script src="http://www.openlayers.org/api/OpenLayers.js"></script>
<script>
var mainLonLat = [0.166081 ,38.789011];
map = new OpenLayers.Map("mapdiv");
map.addLayer(new OpenLayers.Layer.OSM());
epsg4326 = new OpenLayers.Projection("EPSG:4326"); //WGS 1984 projection
projectTo = map.getProjectionObject(); //The map projection (Spherical Mercator)
var lonLat = new OpenLayers.LonLat( 0.166081 ,38.789011 ).transform(epsg4326, projectTo);
var zoom=14;
map.setCenter (lonLat, zoom);
var mastsOneK = [new OpenLayers.LonLat(0.154539,38.738778)];
//Create the Circle
circleLayer = new OpenLayers.Layer.Vector("circleLayer");
circleLayer.addFeatures(createCircle());
function createCircle()
{
var x = 0;
var extent = map.getExtent();
var features = [];
while(x < mastsOneK.length)
{
var threeKStyle = {
strokeWidth: 1,
strokeColor: '#FF6600',
fill: 1,
fillColor: '#FF6600',
fillOpacity: 0.4,
strokeOpacity: 0.4,
};
var newThreeK = new OpenLayers.Feature.Vector(
new OpenLayers.Geometry.Polygon.createRegularPolygon(
new OpenLayers.Geometry.Point(mastsOneK[x].lon,mastsOneK[x].lat).transform(
epsg4326, projectTo),
2000,
40),"",threeKStyle);
features.push(newThreeK);
x++;
}
return features;
}
map.addLayer(circleLayer);
</script>
I am able to get a map showing with a single circle using just a standard html page, this is the desired result. However, when using the same code and pasting this into a Yii view. The map does not appear. I get a blank white area where the map should be.
If I use chrome inspector and set a height and width to the element (I have set width and height to the element before and this does not make a difference), I can begin to see a slice of the map.
If I then zoom in on the page, the full map then appears as expected.
I have tried to do various workarounds such as resize, redraw, refresh the image etc. Using the codes below and many more for example:
$("#mapdiv").resize();
$.fn.redraw = function(){
$(this).each(function(){
var redraw = this.offsetHeight;
});
};
$('#mapdiv').redraw();
However the map still does not show. Strangely enough if I remove the DOCTYPE tag at the start of the document, then the map appears, but obviously this causes many other issues.
Could any one suggest why this is happening and any potential fixes they may have come across as I have used every snippet I have got my hands on to no avail.
Similarly when using the highcharts extensions and trying to render the charts in a tab I also get an issue where a zoom in/out is required to see the chart and I can't help but think that the solution to the above would be the solution to this also.
Any help is appreciated.
You may have to manually call map.updateSize() ( http://dev.openlayers.org/apidocs/files/OpenLayers/Map-js.html#OpenLayers.Map.updateSize ) when the containing element size has changed after initialisation.

Rendering GeoJSON with LeafletJS how can I avoid line endings being connected?

I am rendering GeoJSON containing LineStrings on a Leaflet map. For some reason the end points of each path are connected like in a circle (see blue line in the screenshot).
Here is the relevant portion of code ..
renderGeoJson = function(link) {
var url = $(link).attr("href");
$.getJSON(url, function(data) {
var feature = data.features[0];
var color = nameToColor(feature.properties.name);
var geojson = L.geoJson(data, {
style: {
type: "LineString",
color: color,
weight: 3,
opacity: 0.75
}
});
geojson.addTo(map);
});
}
It may that the originial GeoJSON file has errors - it may be some option on Leaflet - please tell me.
Pointing to the specific GeoJSON file would make this answerable - would guess that it's an issue with the data since other data in that repository has issues.

Activation/deactivation of OpenLayers.Controls.DrawFeature fails

When I break on the first line in the call back function and do this
this.active --> true
this.deactivate() --> true
this.activate() --> true
this.deactivate() --> false
HOW CAN THIS HAPPEN?
Let me explain where this occurs.
This map has two layers and each layer has an EditingToolbar associated with it.
When the user pressed polygon draw (in the EditingToolbar), its being draw on the "polygon_layer".
When the user presses line draw or point draw the layer is switched and the user now draws on the "vectors" layer.
When I switch layers, I need to activate the correct button in the EditingToolbar, example:
The user draws polygons in the "polygon_layer" and now he want to draw lines. He presses draw lines button (in the EditingToolbar associated with the polygon_layer).
I switch layers and activate draw lines button on the EditingToolbar for that layer.
After a while, the user now wants to draw polygons again, so i deactivate all buttons in this layer, switch layers and activate the draw polygon button in the
EditingToolbar for the polygon_layer. and so on.
Now when I do this enough times (3 switches) I notice that the buttons don't get deactivate anymore.
So I tried to debug and got this totally unexpected error described above ( at the very top).
Please tell me what am I doing wrong.
I've appended my code and I'll put ERROR HERE where this occurs. This code is ready to run.
You can use the HTML code below, just change the reference to the JavaScript file that I've provided ( I've provided the contents of the JavaScript file)
JS FILE:
var map;
var editing_toolbar_polygon=null;
var editing_toolbar_vector=null;
var drag_control=null;
var vectors;
var polygon_layer=null;
var epsg900913 = new OpenLayers.Projection('EPSG:900913');
var epsg4326 = new OpenLayers.Projection('EPSG:4326');
//var epsg900913 = new OpenLayers.Projection('EPSG:900913');
// var epsg4326 = new OpenLayers.Projection('EPSG:4326');
var line_control;
var polygon_control;
var renderer;
function initialize() {
line_control, renderer=OpenLayers.Util.getParameters(window.location.href).renderer;
renderer= (renderer) ? [renderer] : OpenLayers.Layer.Vector.prototype.renderers;
// Create the map object
map = new OpenLayers.Map('map');
//Create a Google layer
var gmap = new OpenLayers.Layer.Google(
"Google Streets", // the default
{
numZoomLevels: 20,
projection: new OpenLayers.Projection("EPSG:900913")
}
);
var wms = new OpenLayers.Layer.WMS( "OpenLayers WMS",
"http://vmap0.tiles.osgeo.org/wms/vmap0?", {layers: 'basic',
projection: new OpenLayers.Projection("EPSG:4326")});
var mystyle=new OpenLayers.StyleMap({
"default": new OpenLayers.Style({
fillColor: "#66ccff",
strokeColor: "#3399ff",
graphicZIndex: 2,
strokeWidth: 5,
}),
"temporary": new OpenLayers.Style({
fillColor:"#3399ff",
strokeColor: "#3399ff",
strokeWidth:5,
pointRadius:10
})
});
polygon_layer=new OpenLayers.Layer.Vector(
"Polygon Layer",
{
//renderers:renderer,
}
);
vectors= new OpenLayers.Layer.Vector(
"Vector Layer",
{
//renderers:renderer,
}
);
editing_toolbar_polygon=new OpenLayers.Control.EditingToolbar(polygon_layer);
editing_toolbar_vector=new OpenLayers.Control.EditingToolbar(vectors);
map.addLayers([gmap,wms,vectors,polygon_layer]);
map.addControl(new OpenLayers.Control.LayerSwitcher());
//map.addControl(new OpenLayers.Control.MousePosition());
map.addControl(editing_toolbar_polygon);
map.addControl(editing_toolbar_vector);
editing_toolbar_vector.deactivate();
//for the drag control to work you need to activate it
drag_control=new OpenLayers.Control.DragFeature(vectors);
map.addControl(drag_control);
find_control(editing_toolbar_polygon.getControlsByClass(new RegExp(".*DrawFeature")),"Point").events.register("activate",null,function(e){
//ERROR HERE
this.deactivate();
var picked_button=find_same_control(editing_toolbar_vector.controls,e.object);
change_layer(polygon_layer,vectors);
change_control(editing_toolbar_polygon,editing_toolbar_vector);
picked_button.activate();
});
find_control(editing_toolbar_polygon.getControlsByClass(new RegExp(".*DrawFeature")),"Path").events.register("activate",null,function(e){
//ERROR HERE
this.deactivate();
var picked_button=find_same_control(editing_toolbar_vector.controls,e.object);
change_layer(polygon_layer,vectors);
change_control(editing_toolbar_polygon,editing_toolbar_vector);
picked_button.activate();
});
find_control(editing_toolbar_vector.getControlsByClass(new RegExp(".*DrawFeature")),"Polygon").events.register("activate",null,function(e){
//ERROR HERE
this.deactivate();
var picked_button=find_same_control(editing_toolbar_polygon.controls,e.object);
change_layer(vectors,polygon_layer);
change_control(editing_toolbar_vector,editing_toolbar_polygon);
picked_button.activate();
});
polygon_layer.events.register("beforefeatureadded",null,function(e){
polygon_layer.removeAllFeatures();
});
// line_control=new OpenLayers.Control.DrawFeature(vectors,OpenLayers.Handler.Path);
//polygon_control=new OpenLayers.Control.DrawFeature(vectors,OpenLayers.Handler.RegularPolygon);
//map.addControl(line_control);
//line_control.activate();
//map.addControl(polygon_control);
//polygon_control.activate();
// Zoom to Vancouver, BC
map.setCenter(new OpenLayers.LonLat(-123.12, 49.28).transform(epsg4326, epsg900913), 13);
}
function change_layer(current_layer,next_layer){
current_layer.setVisibility(false);
next_layer.setVisibility(true);
}
function change_control(current_control,next_control){
current_control.deactivate();
map.addControl(next_control);
}
//use this when you want to find a specific control type:
// DrawFeature cntrol has many types, Line, Polygon, Point.
// So what you do is pass an array of DrawFeature controls and a type(string), lets say "Point",
// then this function will return a DrawFeature thats specifically for drawing points
function find_control(controls,type){
var control;
for(var x in controls){
if(controls[x].displayClass.search(new RegExp(type+"$"))>0){
return controls[x];
}
}
return -1;
}
I just tried with a simple test.
When you desactivate a controller, you just remove the events of the controller.
So for OpenLayers.Control.LayerSwitcher, desactivate this controller is useless because nothing change and you can still choose a layer.
I think the best way is to remove the controller for your polygon and to add that for the lines.
When you select the "polygon_layer" :
map.addControl(editing_toolbar_polygon);
map.removeControl(editing_toolbar_vector);
When you select the "vectors" :
map.addControl(editing_toolbar_vector);
map.removeControl(editing_toolbar_polygon);

Categories