Centering a leaflet map when marker is close to the edges - leaflet

I am not sure what the exact technical term for this question would be so please pardon the noobish question.
I have a leaflet map like this:
var map = L.map("dvMapContainer",
{
}).setView([39.782388193, -86.14135265], 14);
I am adding a marker to this map like this:
var vehicleMarker = new L.Marker([39.782388193, -86.14135265], { id: 'vehicle', icon: cssIcon });
map.addLayer(vehicleMarker);
Every few seconds, I update the position of the vehicleMarker and center the map
vehicleMarker.setLatLng(newLatLng);
map.setView(newLatLng, 18);
This works fine however the effect is not very visually pleasing as the map is constantly moving. I would like to move only the marker until it gets close to the edge of the map and then recenter the map. Is that possible ? Any hints/solutions will be much appreciated.

Each time you check (every few seconds), you can compare your marker location with the map bounds:
var bounds = map.getBounds();
if(vehicleMarker.getLatLng().lng > bounds.getEast()-.001 || vehicleMarker.getLatLng().lng < bounds.getWest()+.001 || vehicleMarker.getLatLng().lat > bounds.getNorth()-.001 || vehicleMarker.getLatLng().lat < bounds.getSouth()+.001)
//change bounds
If your next marker location is close to your current bounds, then change your map's current bounds.
You can change the .001 depending on how far zoomed out you are.
More info on bounds here: http://leafletjs.com/reference.html#latlngbounds

Related

gdal2tiles.py: Slice an image with its center being (0,0)

I made a map for my Minetest Game I play.
The project is here : https://github.com/amelaye/aiwMapping I created the map with the Python script gdal2tiles, like this : ./gdal2tiles.py -l -p raster -z 0-10 -w none ../map.png ../tiles
Here is the interesting part of code :
var minZoom = 0
var maxZoom = 9
var img = [
20000, // original width of image
20000 // original height of image
]
// create the map
var map = L.map(mapid, {
minZoom: minZoom,
maxZoom: maxZoom
})
var rc = new L.RasterCoords(map, img)
map.setView(rc.unproject([9000, 10554]), 7)
L.control.layers({
'Spawn': layerGeoGlobal(window.geoInfoSpawn, map, rc, 'red', 'star', 'fa'),
}, {
'Bounds': layerBounds(map, rc, img),
}).addTo(map)
L.tileLayer('./tiles/{z}/{x}/{y}.png', {
noWrap: true,
attribution: ''
}).addTo(map)
It works like a charm, but there is a problem : in Minetest, the coords (lat and lon) go to -10000 to 10000. In my Leaflet map, the coords still positive, then they go from 0 to 20000.
How can I solve this problem ?
CRS SIMPLE does not work.
PS : No relative questions have been posted, please read my message carefully.
When gdal2tiles is not given a georeferenced image (or a world file accompanying the image), it will assume that the (0,0) coordinate is at one of the corners of the image, and that one pixel equals one map unit (both horizontally and vertically).
Since your input image is a .png file, the most straightforward way of working around the issue will be creating an appropriate world file.
If your input image is map.png, create a new plain text file named map.pgw with the following contents...
1
0
0
1
-10000
-10000
...then run gdal2tiles.py again. Note that this worldfile assumes that one pixel equals one map unit, and the image's first corner is at the (-10000,-10000) coordinate.

How to get current frame from Animated Tile/Tilemap.animationFrameRate in Unity

I am using tilemaps and animated tiles from the 2dExtras in unity.
My tiles have 6 frames, at speed=2f, and my tilemap frame rate is 2.
New tiles placed always start on frame 1 and then immediately jump to the current frame of the other tiles already placed, the tilemap is keeping every tile at the same pace, which is working as I want.
However I would like the newly placed tiles to start at the frame the others are currently on,(instead of placing a tile that jumps from frame 1 to frame 4) I would like the new tile to start on frame 4
I've found how to pick the frame I want to start on, however I am having trouble retrieving which frame the animation is currently on, so I was wondering how exactly can I access the current frame of animation of a given tilemap ( Or a given tile, I can create a dummy tile and just read the info out of it, how can I get the current frame of an animated tile? )
The animated tilemaps feature seems to lack the feature to retrieve this information, also when I try tilemap.getsprite it always returns the first frame of the sequence(does not return the sprite currently displayed), and there doesn't seem to be any method to poll info from tilemap.animationFrameRate.
I thought another method would be to set a clock and sync it to the rate of the animation but since I can't get the exact framerate duration the clock eventually goes out of sync.
Any help would be appreciated!
I found a way to solve this question. But it's not 100% insurance.
First of all, I used SuperTile2Unity. That doesn't seem to be the point.
private void LateUpdate()
{
// I use this variable to monitor the run time of the game
this.totalTime += Time.deltaTime;
}
private void func()
{
// ...
TileBase[] currentTiles = tilemap.GetTilesBlock(new BoundsInt(new Vector3Int(0, 0, 0), new Vector3Int(x, y, 1)));
Dictionary<string, Sprite> tempTiles = new Dictionary<string, Sprite>();
//I use SuperTiled2Unity. But it doesn't matter, the point is to find animated tile
foreach (SuperTiled2Unity.SuperTile tile in currentTiles)
{
if (tile == null)
{
continue;
}
if (tile.m_AnimationSprites.Length > 1 && !tempTiles.ContainsKey(tile.name))
{
// find animated tile current frame
// You can easily find that the way SuperTile2Unity is used to process animation is to generate a sprite array based on the time of each frame set by Tiled animation and the value of AnimationFrameRate parameter.
// The length of array is always n times of AnimationFrameRate. You can debug to find this.
tempTiles.Add(tile.name, tile.m_AnimationSprites[GetProbablyFrameIndex(tile.m_AnimationSprites.Length)]);
}
}
//...
}
private int GetProbablyFrameIndex(int totalFrame)
{
//According to the total running time and the total length of tile animation and AnimationFrameRate, the approximate frame index can be deduced.
int overFrameTime = (int)(totalTime * animationFrameRate);
return overFrameTime % totalFrame;
}
I have done some tests. At least in 30 minutes, there will be no deviation in animations, but there may be a critical value. If the critical time is exceeded, there may be errors. It depends on the size of AnimationFrameRate and the accumulation mode of totalTime. After all, we don't know when and how the unity deals with animatedTile.
You could try using implementation presented in [1] which looks as follows:
MyAnimator.GetCurrentAnimatorClipInfo(0)[0].clip.length * (MyAnimator.GetCurrentAnimatorStateInfo(0).normalizedTime % 1) * MyAnimator.GetCurrentAnimatorClipInfo(0)[0].clip.frameRate;
[1] https://gamedev.stackexchange.com/questions/165289/how-to-fetch-a-frame-number-from-animation-clip

Mapbox heatmap by point value

There is an example of the heatmap https://www.mapbox.com/mapbox-gl-js/example/heatmap/ by the number of markers/points on the area. But is there a way to display a heatmap by average pins/markers values? For example if I have 5 pins and their average prop value speed=3 then it will be shown as green cluster/heatmap and if their av. prop val is 6 then it will be red cluster/heatmap.
I found that "clusterAggregates" property can help, but can't find any example of using it.
Thanks
I'll leave my way to do so. Old question, which is sometimes risen, but there are no nice sollution, so... Turf's hexgrid (http://turfjs.org/docs/#hexGrid) can help:
const hexagons = hexGrid(bbox, size);
const collection = // collection of your points;
const hexagonsWithin = collect(hexagons, collection, "propertyToAgretateFrom", "propertyToAggregateIn");
const notEmptyHexagonValues = hexagonsWithin.features.filter(({ properties }) => properties.propertyToAggregateIn.length !== 0);
const notEmptyHexagons = {
"type": "FeatureCollection",
"features": notEmptyHexagonValues,
};
// at this point you're having not empty hexagons as a geojson, which you can add to the map
collect is another method from turf, whatcollection should be you can look up in the docs, because it's changing a lot.
The general idea behind is to "divide" visible part of map (bbox) into hexagons by hexGrid method and and aggregate some properties that you need from every marker inside of every hexagon you'll have into the array, so you can get an average value, for example. And assign a color based on it.
Let's say we have feature.properties.propertyToAgretateFrom as 4 and 5 in two markers. After the aggregation, if these markers were inside one polygon, you'll have it feature.properties.propertyToAggregateIn: [4, 5] - this feature is polygon. From this on you can do pretty much everything you want.

How to save and restore NSScrollView scroll position in Swift?

In a macOS project I'm trying to get and set the scroll cursor position of a NSTableView the code seems to work because don't appairs errors but the cursor don't update.
var clipOrigin = tableView.enclosingScrollView?.contentView.bounds.origin // get the position
clipOrigin = CGPoint (x: 0.0, y: 3.0) // set a new position
tableView.enclosingScrollView?.contentView.scroll(to: clipOrigin!) // set the new position
Am I forgetting something?
contentView.bounds.origin will almost certainly give you a point at 0,0 pretty much always as that's not the value you are expecting. bounds tell you an information about a position of the view which displays the canvas, not the inner offset of the scrolled document.
I guess one -documentRect or -documentVisibleRect properties contains the proper offset value you're looking for.

Leaflet: adding layer group to map is very slow

I am trying to add some 2500 icons (2 Kb each) to a leaflet map. Filling the array is no problem. Adding the layer group to the map, however, takes between 2 and 5 seconds. Any suggestion how to improve the performance?
var icongroup = [];
for (id in reclist) {
var recname = reclist[id][0];
var posn = reclist[id][1];
var pose = reclist[id][2];
var mapicon = L.icon({iconUrl: icon, iconSize: [26, 29]});
icongroup.push(L.marker([posn, pose], {icon: mapicon}));
}
L.layerGroup(icongroup).addTo(map);
Adding thousands of markers to the page stresses the browser ressources for sure. There is a high chance this is the reason for your delay.
You should consider replacing your markers by a canvas, or clustering them.
See also: Plotting 140K points in leafletjs