In leaflet and mapbox I would like to get rid of the two gray bars above and under the map as seen on the picture below. My #map DOM element takes the full screen and the gray bars disappear when I zoom in (e.g., zoomLevel = 3). So the gray bars seem to be caused by the fact that a zoomLevel has a given height (in px) of the tiles which is smaller than my screen.
I want to keep the tiles of the same zoom level but make sure the height of the tiles cover at least the full screen.
Here is my map setup code:
vm.map = L.map('map', {
center: [35, 15],
zoom: 2,
maxZoom: 21,
scrollWheelZoom: true,
maxBounds: [
[89.9, 160.9],
[-89.9, -160.9]
],
zoomControl: false,
noWrap: true,
zoomAnimation: true,
markerZoomAnimation: true,
});
I am using angular and my screen dimensions are 1920 x 1080
Sounds like you need to calculate the minimum zoom level at which the map only shows the area between 85°N and 85°S.
The getBoundsZoom() method of L.Map helps with this, e.g.:
var bounds = L.latLngBounds([[85, 180],[-85, -180]]);
var wantedZoom = map.getBoundsZoom(bounds, true);
var center = bounds.getCenter();
map.setView(center, wantedZoom);
Note that this is a generic solution, and works for any size of the map container.
You could also set the minZoom of the map to that value, and experiment with fractional zoom (see the zoomSnap option). If you want the user to be unable to drag outside the painted area, use the map's maxBounds option with something like [[85, Infinity],[-85, -Infinity]].
(And if you are wondering why 85°N and 85°S, do read https://en.wikipedia.org/wiki/Web_Mercator )
Related
I have a dataset that consists of an (x,y) pair and v which describes a value at (x,y). The data needs to produce a figure that looks like:
This was created by using a surface plot, changing the eye and up values, and then turning the aspectratio on the z-axis to 0.01:
layout= {{
...
aspectmode: "manual",
aspectratio: {x: "3", y: "1", z: ".01"},
scene: {
...
zaxis: {
visible: false
}
}
}}
Notice that the x/y axes are still raised and awkwardly placed. I have two parts to my question:
Is there a better graph to show this data like this using Plotly? The end product needs to be the same, but the way I get there can change.
If this is the best way, how do I "lower" the x/y axes to make it look like a 2D plot?
The original reason I went the route of using a surface plot is because of Matlab. When building a surface plot and rotating it to one of the planes (x/y/z), it will essentially turn into a 2D figure.
After a good walk and looking at the documentation, using:
layout = {{
...
scene: {
...
xaxis: {
...
tickangle: 0
}
}
}}
Removed the '3D' effects. I also changed the aspectratio of z to be: .001
I'm having a problem on the texture coordinates of planes geometries being updated by ARKit. Texture images get stretched, I want to avoid that.
Right now I'm detecting horizontal and vertical walls and applying a texture to them. It's working like a charm...
But when the geometry gets updated because it extents the detection of the wall/floor, the texture coordinates get stretched instead of re-mapping, causing the texture to look stretched like image below.
You can also see an un-edited video of the problem happening: https://www.youtube.com/watch?v=wfwYPwzND74
This is the piece of code where the geometry gets updated:
func renderer(_ renderer: SCNSceneRenderer, didUpdate node: SCNNode, for anchor: ARAnchor) {
guard let planeAnchor = anchor as? ARPlaneAnchor else {
return
}
let planeGeometry = ARSCNPlaneGeometry(device: device)!
planeGeometry.update(from: planeAnchor.geometry)
//I suppose I need to do some texture re-mapping here.
planeGeometry.materials = node.geometry!.materials
node.geometry = planeGeometry
}
I have seen that you can define the texture coordinates by defining it as a source like this:
let textCords = [] //Array of coordinates
let uvData = Data(bytes: textCords, count: textCords.count * MemoryLayout<vector_float2>.size)
let textureSource = SCNGeometrySource(data: uvData,
semantic: .texcoord,
vectorCount: textCords.count,
usesFloatComponents: true,
componentsPerVector: 2,
bytesPerComponent: MemoryLayout<Float>.size,
dataOffset: 0,
dataStride: MemoryLayout<vector_float2>.size)
But I have no idea how to fill the textCords array to make it fit correctly accordingly to the updated planeGeometry
Edit:
Re-defining the approach:
Thinking deeply on the problem, I came with the idea that I need to modify the texture's transform to fix the stretching part, but then I have two options if I do that:
Either keep the texture big enough to fill the entire geometry but
keeping a ratio of 1:1 to avoid stretching
Or keep the texture the
original size but with 1:1 aspect ratio and repeat the texture
multiple times to fit the entire geometry.
Any of these approaches I'm still lost of how to do it. What would you suggest?
I have a chartjs(wrapped by react-chartjs-2) line graph which is zoomable. The zoom functionality was enabled by using javascript library chartjs-plugin-zoom and passing the following configuration to chartjs.ChartOptions:
pan: {
enabled: true,
mode: 'xy'
},
zoom: {
enabled: true,
mode: 'xy'
}
On X axis I display the time and on Y axis some values related to my application. When I zoom or pan the chart the X axis min and max values change, here I need to obtain these values in order to perform a backend call(to update the chart) and also to synchronise it with another component in React.
Is there any possibility to obtain the new values for min and max upon a zoom or pan? I tried to look for a callback function which would provide this but found none so far.
I have an object with 4 fields, each field holding an array with 600 datapoints.
I'd like to plot each array on a separate d3.js graph -- small multiples i think it's called. I'm still a little shaky on the data-binding part of it and can't seem to go from a container to multiple svg appends.
I understand this following basic example, but I think, am missing something about the nature of data-binding in d3:
circleData = [[10, "rgb(246, 239, 247)"], [15, "rgb(189,201,225)"],
[20, "rgb(103,169,207)"], [25, "rgb(28,144,153)"], [30, "rgb(1,108,89)"]];
//Select the div element
selectExample = d3.select("#data_example2");
//We'll select all the circle from within the selected <div> element
selectExample.selectAll("circle")
.data(circleData)//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
.enter()
.append("circle")
.attr("cx", function(d){return d[0]*14})
.attr("cy", 50)
.attr("r", function(d){return d[0]})
.style("fill", function(d){return d[1]});
Basically what i would do right now is just replace circleData in .data(circleData) with my own data object and keep appending axes and labels below it, basically expecting that for every of 4 fields(subarrays), a graph will pop up. .(i.e.
svgSelection.
.data(my_multi-field_array_object)
.enter()
.append("g")
... //continue with the individual plot's code
This, unsurprisingly, does not work. What am i doing wrong?
Renesting the object of arrays to be an array of objects did the trick.
Not sure why that wouldn't be covered by the function.
Do my tiles need to adhere to any particular specs?
I have a large image file which I'd like to turn into a map with LeafletJS. I am going to be using the Python Imaging Library to cut it up into all the various tiles I need.
However, I can't find any information about using custom maps in Leaflet. Do I provide Leaflet with the range of X,Y,Z info somehow? Do I give it the pixel size of each tile? Does it figure this out on its own?
To put my question into one concise question: What do I need to do in order to have image files that can double as map tiles with LeafletJS, and what, if anything, do I need to do in my front-end script? (beyond the obvious specifying of my custom URL)
You are looking for a TileLayer. In this TileLayer, you give the URL for the to-be-fetched images to leaflet with a template like this:
http://{s}.somedomain.com/blabla/{z}/{x}/{y}.png
When you are at the specified zoom, x and y level, Leaflet will automatically fetch the tiles on the URL you gave.
Depending on the image you want to show, the bigger part of the work will however be in the tile generation. Tiles by default have a 256x256px size (can be changed in the TileLayer options), and if you are using geodata the used projection is Mercator projection. It may take some time to get the tile ids right. Here is an example on how the tile ids work.
You can even serve tiles directly from a database.
The format leaflet specifies is very flexible.
Leaflet just uses the z,x,y place holders to request specific tiles.
For example:
L.tileLayer('http://localhost/tileserver/tile.aspx?z={z}&x={x}&y={y}', {
minZoom: 7, maxZoom: 16,
attribution: 'My Tile Server'
}).addTo(map);
where Tiles.aspx
Option Strict On
Partial Class tile
Inherits System.Web.UI.Page
Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load
Dim z, x, y As Integer
z = CInt(Request.QueryString("z"))
x = CInt(Request.QueryString("x"))
y = CInt(Request.QueryString("y"))
Dim b() As Byte = DB.GetTile(z, x, y)
Response.Buffer = True
Response.Charset = ""
'Response.Cache.SetCacheability(HttpCacheability.NoCache)
Response.ContentType = "image/png"
Response.AddHeader("content-disposition", "attachment;filename=" & y & ".png")
Response.BinaryWrite(b)
Response.Flush()
Response.End()
End Sub