Shrink leaflet map's bounds by some padding or ratio - maps

I'd like to shrink a Leaflet map's bounds by some factor (say 50px or 5%).
I've tried the following:
marginPoint = new L.Point(50, 50);
bounds = map.getPixelBounds();
bottomLeft = bounds.getBottomLeft();
topRight = bounds.getTopRight();
bounds = new L.LatLngBounds(
map.unproject(bottomLeft.subtract(marginPoint)),
map.unproject(topRight.subtract(marginPoint))
);
However, this does not shrink the map, it just moves/translates the current box / current map's bounds.

Since you subtract the same amount to both map containers' corners, the result is that you just shift the map view to the South West (bottom left).
If you are trying to "zoom in" (i.e. the map displays a smaller portion of geographic area, but within the same container dimensions), you would add some pixels to your bottom left corners, and remove some to your top left.
But be noted that you could also simply use the latLngBounds.pad() method (with a negative bufferRatio argument) to achieve the same result.

Related

Stuck in figuring out how to adjust scrollbar position when zooming

I am implementing a zoom feature of a 20x20 grid that also has a 640x480 grid on top, where each made up square is called a resolution. The entire space is for instance 3x3 resolutions (640 * 3) in width and (480 * 3) in height and there is a scrollbar that can scroll over this area.
The first zoom level is 100% and so:
I set the grid size to *2, the resolutions also twice as big and the entire space * 2.
However, I'll also have to re-adjust the scrollbar position so that it remains on the same visual location after the zoom and I am really not that good in math. How do I do that?
A diagram:
*where the visible area should be after zoom
Edit: I create this simulator to quickly and easily do real-time simulations:
https://youtu.be/RfiaUXWNjQE
this one works with the following:
hNew = hCurrent * 2 + resolution.width / 2;
it obviously works with the first zoom level.
later update:
hNew = hCurrent * (1 + zoomLevels) + resolution.width / 2;
appears to be working for every zoom level.
The aforementioned approach works, but it can only map from a no-zoomed world to any zoom level rather than from every zoom level to every zoom level.
A better more conventional way is to convert current (before zoom) values of the horizontal/vertical scrollbar to %
then after zoom calculations and resizing get the value of that % of the new world size.
so for horizontal adjustment it would look like this:
h% = hValue * 100.0 / hValueMax;
// ...zoom...
hValueNew = h% * hValueNewMax / 100.0;

Sprite alignment in a Sprite Packing C application

I am creating the "perfect" sprite packer. This is a sprite packer that makes sure the output sprite is compatible with most if not all game engines and animation software. It is a program that merges images into a horizontal sprite sheet.
It converts (if needed) the source frames to BMP in memory
It considers the top-left pixel fully transparent for the entire image (can be configured)
It parses the frames each individually to find the real coordinates rect (where the actual frame starts, ends, its width and height (sometimes images may have a lot of extra transparent pixels).
It determines the frame box, which have the width and height of the frame with the largest width/height so that it is long enough to contain every frame. (For extra compatibility, every frame must have the same dimensions).
Creates output sprite with width of nFrames * wFrameBox
The problem is - anchor alignment. Currently, it tries to align each frame so that its center is on the frame box center.
if((wBox / 2) > (frame->realCoordinates.w / 2))
{
xpos = xBoxOffset + ((wBox / 2) - (frame->realCoordinates.w / 2));
}
else
{
xpos = xBoxOffset + ((frame->realCoordinates.w / 2) - (wBox / 2));
}
When animated, it looks better with it, but there is still this inconsistent horizontal frame position so that a walking animation looks like walking and shaking.
I also tried the following:
store the real x pixel position of the widest frame and use it as a reference point:
xpos = xBoxOffset + (frame->realCoordinates.x - xRef);
It also gives a little better results, showing that this is still not the correct algorithm.
Honestly, I don't know what am I doing.
What will be the correct way to align sprite frames (obtain the appropriate x position for drawing the next frame) given that the output sprite sheet have width of the number of frames multiplied by the width of the widest frame?
Your problem is that you first calculate the center then calculate the size of the required bounding box. That is why your image 'shakes' because in each image that center is different to the original center.
You should use the center of the original bounding box as your origin, then find out the size of each sprite, keeping track of the leftmost, rightmost, topmost and bottommost non transparent pixels. That would give you the bounding box you need to use to avoid the shaking.
The problem is that you will find that most sprites are already done that way, so the original bounding box is actually defined as to the minimum space to paint the whole sprite's sequence covering these non transparent pixels.
The only way to remove unused sprite space is to store the first sprite complete, and then the origin and dimensions of each other sprite, like is done in animated GIF and APNG ( Animated PNG -> https://en.wikipedia.org/wiki/APNG )

Smooth Zoom with mouse in Mandelbrot set (C)

I've been working on a C Mandelbrot set program for the past few days and I managed to make it work fine, however, my end goal is to be able to smoothly zoom in the set with my mouse and that's something I haven't yet been able to do yet so I might need a bit of help !
Here's part of my code (well, the full mandelbrot function) :
//removed to free space
Here's a picture of the output :
(Sorry, it's not very pretty, colors were not my priority but I'll be sure to work on them as soon as I figure out the zoom !)
Mandelbrot
What I want to be able to do :
left click -> center of the image becomes mouse_x an mouse_y. Then, it starts zooming in as long as left click is held
right click -> [...] it starts zooming out as long as right click is held
move mouse -> if currently zooming in/out, the center of the image moves to the mouse's coordinates with it. Else nothing happens.
(already have a function that gets mouse's position and button being pressed)
Thanks a lot for your help !
The visible area is a rectangle defined by (Re.min, Im.min) and (Re.max, Im.max). When you click on a particular point, you can map the mouse position to a point (mouseRe, mouseIm) by using the same mapping as you use when rendering:
double mouseRe = (double)mouse_x / (WIN_L / (e->Re.max - e->Re.min)) + e->Re.min;
double mouseIm = (double)mouse_y / (WIN_H / (e->Im.max - e->Im.min)) + e->Im.min;
To zoom in, imagine drawing a line from the (mouseRe, mouseIm) zooming centerpoint to each of the corners of the visible area, forming a lopsided X. Based on the zoom amount, find 4 new points a certain fraction of the distance along these lines, these points will give you your new rectangle. For example, if you are zooming in by a factor of 3, find a point 1/3rd of the way from the centerpoint to the corners. This will produce a new rectangle with sides 1/3rd the size of the original and an area 1/9th the size.
To do this you can define a simple interpolation function:
double interpolate(double start, double end, double interpolation)
{
return start + ((end - start) * interpolation);
}
Then use the function to find your new points:
void applyZoom(t_fractal* e, double mouseRe, double mouseIm, double zoomFactor)
{
double interpolation = 1.0 / zoomFactor;
e->Re.min = interpolate(mouseRe, e->Re.min, interpolation);
e->Im.min = interpolate(mouseIm, e->Im.min, interpolation);
e->Re.max = interpolate(mouseRe, e->Re.max, interpolation);
e->Im.max = interpolate(mouseIm, e->Im.max, interpolation);
}
Based on my description, you might think you need to find 8 values (4 points for the 4 legs of the X with 2 dimension each) but in practise there are only 4 unique values because each of the sides is axis aligned.
For a smooth zoom, call it with a zoom factor of a little over 1.0 e.g. 1.01. To zoom out, pass the inverse e.g. 1.0 / 1.01.
Alternatively, if you want the center of the view to jump to a certain position when you click the mouse, calculate mouseRe and mouseIm as above and then offset the corners of the view rectangle by the difference between these values and the center of the view rectangle. You could store these values at the time the mouse button was first pressed down, and use them to zoom in as long as it is held.

Grid image values to 2D array

I have a grid like the image below which I want to put in an array in this format:
;x = wall(black cells and grey boxes), s= start (red circle), g = goal(blue circle), 0 = available path(everything else)
$data[5][5] = [["x","x","x","x","x"], _
["x","s","0","x","x"], _
["x","x","0","x","x"], _
["x","x","0","g","x"], _
["x","x","x","x","x"]]
I thought I could use the colors but I'm not sure how.
looks like you have the view with fixed angles
create function that converts screen position to grid position and back. It should be easy just 2x linear interpolation. if the camera pan is not with cell based step then you need the corner point of grid lines and use that as a start point ...
for example something like this (hope I measured the pixels correctly):
x = 236 + (+(u-uh)-(v-vh))*60;
y = 133 + (-(u-uh)-(v-vh))*30;
60,30is the cell size in x,y
(236,133) is position of center of mid cell (uh,vh) in pixels
uh,vh are coordinates in your grid of center cell
add the views pan offset to (uv,hv) or (236,133) now just compute the also the reverse transform from this (u=?,v=?). Do not forget that the map is not rectangle! It is something like this:
0000x0000,
000xxx000,
00xxxxx00,
0xxxxxxx0,
xxxxxxxxx,
0xxxxxxx0,
00xxxxx00,
000xxx000,
0000x0000,
create a set of images of all objects that you can encounter
this can be done on the run, each time you do not found a match add cell to item list as new object type.
loop through all grid cell locations and compare to object types
for pixel precise rendered images you can compare directly pixels 1:1 if that is not the case the you need to compare objects more robustly. But to make a valid algorithm we need to see all the types of object you can encounter usually you can compare:
average,min and max colors, histograms,
aspect ratio,...
FFT/DCT
center of mass position,density, and more
do not forget to mask comparison to area of cell only to not include the neighboring cells on corners of bounding rectangle
[Notes]
Can not be more specific without further info

Show geometry of constant size on a canvas irrespective zoomed in/out

I have a canvas which shows a surface, and there is an option to mark some points on the surface. These points are displayed as stars using the PathGeometry object(which means I have computed the points and created a polyline), the size of the star increases/decreases as we zoom in/out.
Now I want to make the size of the star always constant irrespective of zooming.
Is there a way to achieve this, like modifying the stroke shape or something?

Resources