Leaflet Get Bounds w/ only top padding - leaflet

I am aware of the pad method when calling getBounds(), but is there a way I can specify padding ONLY on the top of the map?
For example, this pads all side equally:
const box = map.getBounds().pad(-.2).toBBoxString()
I am basically looking to do in Leaflet what Mapbox does here.

Just spitballing.
# Expand the northern boundary (and the others) to the correct size
tmp_expanded = map.getBounds().pad( -0.2 );
# Get a coordinate along the northern boundary
northern_coord = tmp_expanded.getNorthEast();
# Expand the northern boundary only by encompassing the northern coord
box = map.getBounds().extend( northern_coord ).toBBoxString();
It's not pretty, but it may do the trick.

Related

Why does my Leaflet circle only show as a dot?

I'm trying to add circles to my map, but for some reason the circles only show as dots, irrespective of the radius size.
var circle = L.circle(map.unproject([9541, 7658], map.getMaxZoom()), {
radius: 500
}).addTo(map);
I'm using pixel coordinates, but as you can see I'm converting them, so even though I only get dots on the map, they show at the right coordinates. I would hope this isn't the issue, but...?
I've successfully added circleMarkers, but the radius doesn't grow when zooming. At least not that I could see.
So the question is: how can I get the dots to show as circles?
Using Leaflet 1.9.3
Update
It appears that with pixel coordinates you need to enter a really high value for the radius. Thought I had already tried this before asking the question but apparently not.
var circle = L.circle(map.unproject([9541, 7658], map.getMaxZoom()), {
radius: 50000
}).addTo(map);
Unfortunately they're all showing at different sizes, even with the same radius, but that's a different question...
I originally misread your question and gave an incorrect answer, sorry. Circle radius is static. I think that the best way to change it with zoom level would be to use a zoom event listener:
let currZoom = map.getZoom();
let circles = [/* Store your circles here as you create them */];
map.on("zoomend", () => {
const zoomDiff = map.getZoom() - currZoom;
currZoom = map.getZoom();
for (const circle of circles) {
circle.setRadius(circle.getRadius() * 2 ** zoomDiff);
}
});
It's been a while since I've worked with Leaflet, but I think that will do the trick.
Edited to account for your comment regarding multiple circles.

leaflet editable restrict draw to a specific area

In Leaflet.Editable I want to confine/limit my customers to draw only in a specific area/bounds.
actually im trying to limit them to (90, -90, 180, -180) bounds of map..
maxBounds: [[-90, -180], [90, 180]]
I was not able to find anything anywhere and it seems that i am missing something.
CODEPEN DEMO
please help.
EDIT:
the Y axis is blocking correctly and mouse cannot stretch shape beyond top and bottom.
the problem is in X axis (as seen in pictures)
as for now i solved it with after save check and clear shape if it out of map bounds (BAD USER EXPERIENCE). i need a mouse confinement just like y axis does.
Without knowing your use case (why the whole world map??) Quickest and easiest fix would be to simply set the map's minZoom to something a bit higher, for example, I found that minZoom: 5 was adequate except for cases where the map was both really short and really wide (which is rarely the case in most apps I've seen).
But the real fix involves writing your own custom overrides for dragging markers and shapes.
According to API doc the L.Editable plugin allows you to override a bunch of stuff including the VertexMarker class, via map.editTools.options.vertexMarkerClass.
Fixed codepen: http://codepen.io/anon/pen/GrPpRY?editors=0010
This snippet of code that allows you to constrain the longitude for dragging vertex markers by correcting values under -180 and over 180 is this:
// create custom vertex marker editor
var vertexMarkerClass = L.Editable.VertexMarker.extend({
onDrag: function(e) {
e.vertex = this;
var iconPos = L.DomUtil.getPosition(this._icon),
latlng = this._map.layerPointToLatLng(iconPos);
// fix out of range vertex
if (latlng.lng < -180) {
e.latlng.lng = latlng.lng = -180;
this.setLatLng(latlng);
}
if (latlng.lng > 180) {
e.latlng.lng = latlng.lng = 180;
this.setLatLng(latlng);
}
this.editor.onVertexMarkerDrag(e);
this.latlng.update(latlng);
this._latlng = this.latlng; // Push back to Leaflet our reference.
this.editor.refresh();
if (this.middleMarker) this.middleMarker.updateLatLng();
var next = this.getNext();
if (next && next.middleMarker) next.middleMarker.updateLatLng();
}
});
// attach custom editor
map.editTools.options.vertexMarkerClass = vertexMarkerClass;
I didn't code for dragging the shape as a whole (the rectangle, in this case). While the VertexMarker fix should address all kinds of vertex dragging, you need to override each shape's drag handler to properly constrain the bounds. And if bounds are exceeded, crop the shape appropriately. As was pointed out, Leaflet already does this for latitude, but because Leaflet allows wrapping the map around horizontally you have your essential problem. Using rec.on("drag") to correct the bounds when they cross over your min/max longitude is the only way to address it. It is basically the same solution as I have laid out for the vertexMarkerClass - actual code left as exercise for the diligent reader.

How to remove horizontal and vertical lines

I need to remove horizontal and vertical lines in a binary image. Is there any method for filtering these lines? bwareaopen() is not good method to remove these lines and also Dilation and Erosion are not good for these cases.
Does any one know a solution?
Example image:
EDIT:(added more example images:
http://s1.upload7.ir/downloads/pPqTDnmsmjHUGTEpbwnksf3uUkzncDwr/example%202.png
source file of images:
https://www.dropbox.com/sh/tamcdqk244ktoyp/AAAuxkmYgBkB8erNS9SajkGVa?dl=0
www.directexe.com/9cg/pics.rar
Use regionprops and remove regions with high eccentricity (meaning the region is long and thin) and orientation near 0 or near 90 degrees (regions which are vertical or horizontal).
Code:
img = im2double(rgb2gray(imread('removelines.jpg')));
mask = ~im2bw(img);
rp = regionprops(mask, 'PixelIdxList', 'Eccentricity', 'Orientation');
% Get high eccentricity and orientations at 90 and 0 degrees
rp = rp([rp.Eccentricity] > 0.95 & (abs([rp.Orientation]) < 2 | abs([rp.Orientation]) > 88));
mask(vertcat(rp.PixelIdxList)) = false;
imshow(mask);
Output:
If all of your images are the same where the horizontal and vertical lines are touching the border, a simple call to imclearborder will do the trick. imclearborder removes any object pixels that are touching the borders of the image. You'll need to invert the image so that the characters are white and the background is dark, then reinvert back, but I'm assuming that isn't an issue. However, to be sure that none of the actual characters get removed because they may also be touching the border, it may be prudent to artificially pad the top border of the image with a single pixel thickness, clear the border, then recrop.
im = imread('http://i.stack.imgur.com/L1hUa.jpg'); %// Read image directly from StackOverflow
im = ~im2bw(im); %// Convert to black and white and invert
im_pad = zeros(size(im,1)+1, size(im,2)) == 1; %// Pad the image too with a single pixel border
im_pad(2:end,:) = im;
out = ~imclearborder(im_pad); %// Clear border pixels then reinvert
out = out(2:end,:); %// Crop out padded pixels
imshow(out); %// Show image
We get this:
You can firstly find the horizontal and vertical lines. Since, the edge map will also be binary so you can perform a logical subtraction operation in between the images. To find vertical lines, you can use (in MATLAB)
BW = edge(I,'sobel','vertical');
For horizontal lines, you can use
% Generate horizontal edge emphasis kernel
h = fspecial('sobel');
% invert kernel to detect vertical edges
h = h';
J = imfilter(I,h);

leaflet pixel size depending on zoom level

I have to display 5x5 degrees pie chart on a leaflet map. I can display pie chart using the great leaflet-dvf library, but I have to provide the radius in pixel, and it is static so far.
I would like to have it dynamic so that at any zoom level, the pie chart fills the 5x5 square (aka radius = 5x5 degree length).
How can I know the length in pixel of the side of a 5x5 degrees square, depending on the zoom level?
Thanks
This will work out metres per pixel
metresPerPixel = 40075016.686 * Math.abs(Math.cos(map.getCenter().lat / 180 * Math.PI)) / Math.pow(2, map.getZoom()+8);
I used the following page that provides the pixel per meter on a leaflet map depending on the zoom level:
http://wiki.openstreetmap.org/wiki/Zoom_levels
Then I computed the length of a 5x5 square at the equator: 556000 meters.
Then I store the length ratio for zoom level = 0:
$scope.lengthRatio = 556000 / 156412 // in meter / pixel
Finally, I get the radius of a pie chart depending on the zoom level ($scope.mapZoom):
var radius = $scope.lengthRatio * Math.pow(2,$scope.mapZoom)) / 2
The /2 is because I want the radius and not the diameter
Simple!

Method Replace in Core Plot 1.0 ?

I want to used this method in core plot 1.0 but that method now work with core plot 1.0 so what will be alternative for this ?
CPTXYAxis *y = axisSet.yAxis;
**//this all method are not work**
y.majorGridLineStyle = majorGridLineStyle;
y.minorGridLineStyle = minorGridLineStyle;
y.visibleRange = [CPTPlotRange plotRangeWithLocation:CPTDecimalFromFloat(0.0f) length:CPTDecimalFromFloat(100.0f)];
CPTConstraints yConstraints = {CPTConstraintFixed, CPTConstraintFixed};
y.isFloatingAxis=YES;
y.constraints=yConstraints;
i want to try this Example but that give me error Example link
The way constraints are handled changed. See the announcement on the Core Plot discussion board.
Here's a summary of the change:
CPTConstraints allows two basic types of constraint. Note that when
used for floating axis positioning, the axis doesn't clip the
constrained position to the visible area so it is possible to use an
offset that will push the floating axis outside the visible area.
Fixed offset from either the lower or upper bound of the range.
Note that for axes, this range is in view coordinates, so the lower
bound is to the left for a horizontal axis and at the bottom for a
vertical axis. The offset is towards the middle of the range, so a
positive offset from the lower bound goes in the positive direction
but a positive offset from the upper bound goes in a negative
direction.
Relative offset. This is used to maintain a position that is a
certain fraction of the range—0.0 is the lower bound, 1.0 is the
upper bound, and 0.5 is the middle. It is not restricted to these
values; any CGFloat value can be used.
CPTConstraints is immutable, so you have to create a new object
whenever you want to change the constraints.