Inside Google Street View, moving the mouse around over different buildings and stuff, it highlights the 3D plane in which that surface of the building is located.
How does it recognize this thing? Is it done automatically by machine algorithms, or manually in the preprocessing?
Read this to get your answer. What Google does is it gets a panoramic view by stitching multiple images together, and then the device measures the relative distance of every object around it (through lasers), and constructs a 3D model of the surroundings based on that.
You want to look into space-filling-curves. A sfc reduce the 3d complexity to a 1d complexity. A sfc subdivide the 3d space into 8 tiles thus it resemble an octree.
Related
Is it possible to highlight rivers in Mapbox?
I would like to look at the world and see a list of specific rivers standing out as if highlighted with a yellow marker on a paper map. As I zoom in, the highlights would get more precise and ultimately coincide with the actual geometry of the rivers, or at least follow a line equidistant to their banks…
Is this at all possible?
I understand I can draw anything I want at specific geographic coordinates, but I can't figure out how to extract the river geometry from Mapbox to compute the paths for my highlighter strokes…
Or perhaps this kind of thing would be easier with another provider? How do people usually handle this kind of thing?
As far as I know there is not a way to highlight specific rivers in Mapbox's water related layers by an attribute like name. However, if you are looking to filter features based on size/prominence it is possible to filter features using the "class" or "type" property on the Mapbox waterway layer. This will at least allow you to filter/style features based on their type (i.e. river, stream, canal, etc...).
An alternative approach would be to pull together spatial data outside of the Mapbox platform and then bring it into Mapbox as your own tilset or dataset. I have done this before using the National Hydrography Dataset (this is just for the US) when I wanted to highlight specific rivers (i.e. only show the Rio Grande, Arkansas, and Colorado Rivers). I brought the NHD into my desktop GIS application (QGIS), filtered the features to just those rivers, exported the filtered features as GeoJSON and then uploaded to Mapbox and did all the desired styling in Mapbox Studio.
Hope this helps! I have been writing a series of guides for Mapbox that you might be interested in too. Here are some links:
The Mapbox Developer's Handbook
A Complete Guide to Sources and Layers in React and Mapbox GL JS
Here's something you can try:
Use the waterway line layer in the Mapbox Streets vector tileset and set a filter to show only the river feature type. This will show all rivers at low zoom levels, but because this is a line layer, it will not show the rivers' widths at high (close to the ground) zoom levels. Set the layer to 0 opacity at higher zoom levels so it disappears.
At higher zoom levels, you can use the water polygon layer in the Mapbox Streets vector tileset, but it includes oceans, rivers, lakes, ponds, reservoirs, and fountains all smashed into a simple polygon layer of undifferentiated, merged shapes:
there is no way to filter out or highlight specific water bodies or a partial subset of them.
If you want to isolate one specific waterway (like only the Rio Grande), you will need to import that data yourself as #tylerben suggests.
If you feel adventurous, you could try using mask in Turf.js to hide features in the water layer that are more than, say, ten miles from the centerline of a river from the waterway layer.
You can learn more about Mapbox map data in the core tilesets documentation.
I would like to create a webapp where I can display my own geotiffs, with NDVI and other data layers, as well as 3D geometries, providing a seamless rendering of both 2D tiles and textured 3D shapes, exactly like maps.google.com achieves in switching from "map" to "earth" views.
After much research, the closest I came to a viable solution is to build the infrastructure from the ground up based on http://cesiumjs.org/, and while this seems doable, it is extremely low level, and will require an exotic cocktail of libraries and a buttload of man-hours.
Before going down that road, I want to make sure there isn't a cost effective alternative that takes all the heavy lifting out of my app's shoulders and gives me a friendly set of APIs to base my app on.
Mapbox comes close to perfection in this regard, but unfortunately, it only handles 2D.
On the other hand, on the Google side, amid Earth API and Maps Engine deprecation, it's hard to tell what exactly is currently possible and will remain available long term.
Bottom line, for a future-proof Google-centric solution built today, are there Google APIs in place that allow building a webapp that displays custom 2D and 3D data with a seamless rendering experience?
https://cesiumjs.org/ is a library very similar to google maps that provides support for 3d shapes on top of maps.
I know that Cesium offers several different interpolation methods, including linear (or bilinear in 2D), Hermite, and Lagrange. One can use these methods to resample sets of points and/or create curves that approximate sampled points, etc.
However, the question I have is what method does Cesium use internally when it is rendering a 3D scene and the user is zooming/panning all over the place? This is not a case where the programmer has access to the raster, etc, so one can't just get in the middle of it all and call the interpolation functions directly. Cesium is doing its own thing as quickly as it can in response to user control.
My hunch is that the default is bilinear, but I don't know that nor can I find any documentation that explicitly says what is used. Further, is there a way I can force Cesium to use a specific resampling method during these activities, such as Lagrange resampling? That, in fact, is what I need to do: force Cesium to employ Lagrange resampling during scene rendering. Any suggestions would be appreciated.
EDIT: Here's a more detailed description of the problem…
Suppose I use Cesium to set up a 3-D model of the Earth including a greyscale image chip at its proper location on the model Earth's surface, and then I display the results in a Cesium window. If the view point is far enough from the Earth's surface, then the number of pixels displayed in the image chip part of the window will be fewer than the actual number of pixels that are available in the image chip source. Some downsampling will occur. Likewise, if the user zooms in repeatedly, there will come a point at which there are more pixels displayed across the image chip than the actual number of pixels in the image chip source. Some upsampling will occur. In general, every time Cesium draws a frame that includes a pixel data source there is resampling happening. It could be nearest neighbor (doubt it), linear (probably), cubic, Lagrange, Hermite, or any one of a number of different resampling techniques. At my company, we are using Cesium as part of a large government program which requires the use of Lagrange resampling to ensure image quality. (The NGA has deemed that best for its programs and analyst tools, and they have made it a compliance requirement. So we have no choice.)
So here's the problem: while the user is interacting with the model, for instance zooming in, the drawing process is not in the programmer's control. The resampling is either happening in the Cesium layer itself (hopefully) or in even still lower layers (for instance, the WebGL functions that Cesium may be relying on). So I have no clue which technique is used for this resampling. Worse, if that technique is not Lagrange, then I don't have any clue how to change it.
So the question(s) would be this: is Cesium doing the resampling explicitly? If so, then what technique is it using? If not, then what drawing packages and functions are Cesium relying on to render an image file onto the map? (I can try to dig down and determine what techniques those layers may be using, and/or have available.)
UPDATE: Wow, my original answer was a total misunderstanding of your question, so I've rewritten from scratch.
With the new edits, it's clear your question is about how images are resampled for the screen while rendering. These
images are texturemaps, in WebGL, and the process of getting them to the screen quickly is implemented in hardware,
on the graphics card itself. Software on the CPU is not performant enough to map individual pixels to the screen
one at a time, which is why we have hardware-accelerated 3D cards.
Now for the bad news: This hardware supports nearest neighbor, linear, and mapmapping. That's it. 3D graphics
cards do not use any fancier interpolation, as it needs to be done in a fraction of a second to keep frame rate as high as possible.
Mapmapping is described well by #gman in his article WebGL 3D Textures. It's
a long article but search for the word "mipmap" and skip ahead to his description of that. Basically a single image is reduced
into smaller images prior to rendering, so an appropriately-sized starting point can be chosen at render time. But there will
always be a final mapping to the screen, and as you can see, the choices are NEAREST or LINEAR.
Quoting #gman's article here:
You can choose what WebGL does by setting the texture filtering for each texture. There are 6 modes
NEAREST = choose 1 pixel from the biggest mip
LINEAR = choose 4 pixels from the biggest mip and blend them
NEAREST_MIPMAP_NEAREST = choose the best mip, then pick one pixel from that mip
LINEAR_MIPMAP_NEAREST = choose the best mip, then blend 4 pixels from that mip
NEAREST_MIPMAP_LINEAR = choose the best 2 mips, choose 1 pixel from each, blend them
LINEAR_MIPMAP_LINEAR = choose the best 2 mips. choose 4 pixels from each, blend them
I guess the best news I can give you is that Cesium uses the best of those, LINEAR_MIPMAP_LINEAR to
do its own rendering. If you have a strict requirement for more time-consuming imagery interpolation, that means you
have a requirement to not use a realtime 3D hardware-accelerated graphics card, as there is no way to do Lagrange image interpolation during a realtime render.
First time asking a question on the stack exchange, hopefully this is the right place.
I can't seem to develop a close enough approximation algorithm for my situation as I'm not exactly the best in terms of 3D math.
I have a 3d environment in which I can access the position and rotation of any object, including my camera, as well as run trace lines from any two points to get distances between a point and a point of collision. I also have my camera's field of view. I do not have any form of access to the world/view/projection matrices however.
I also have a collection of 2d images that are basically a set of screenshots of the 3d environment from the camera, each collection is from the same point and angle and the average set is taken at about an average of a 60 degree angle down from the horizon.
I have been able to get to the point of using "registration point entities" that can be placed in the 3d world that represent the corners of the 2d image, and then when a point is picked on the 2d image it is read as a coordinate with range 0-1, which is then interpolated between the 3d positions of the registration points. This seems to work well, but only if the image is a perfect top down angle. When the camera is tilted and another dimension of perspective is introduced, the results become more grossly inaccurate as there no compensation for this perspective.
I don't need to be able to calculate the height of a point, say a window on a sky scraper, but at least the coordinate at the base of the image plane, or which if I extend a line out from my image from a specified image space point I need at least the point that the line will intersect with the ground if there was nothing in the way.
All of the material I found about this says to just deproject the point using the world/view/projection matrices, which I find straightforward in itself except I don't have access to these matrices, just data I can collect at screenshot time and other algorithms use complex maths I simply don't grasp yet.
One end goal of this would be able to place markers in the 3d environment where a user clicks in the image, while not being able to run a simple deprojection from the user's view.
Any help would be appreciated, thanks.
Edit: Herp derp, while my implementation for doing so is a bit odd due to the limitations of my situation, the solution essentially boiled down to ananthonline's answer about simply recalculating the view/projection matrices.
Between position, rotation and FOV of the camera, could you not calculate the View/Projection matrices of the camera (songho.ca/opengl/gl_projectionmatrix.html) - thus allowing you to unproject known 3D points?
I have an image of a basic game map. Think of it as just horizontal and vertical walls which can't be crossed. How can I go from a png image of the walls to something in code easily?
The hard way is pretty straight forward... it's just if I change the image map I would like an easy way to translate that to code.
Thanks!
edit: The map is not tile-based. It's top down 2D.
I dabble in video games, and I personally would not want the hassle of checking the boundaries of pictures on the map. Wouldn't it be cleaner if these walls were objects that just happened to have an image property (or something like it)? The image would display, but the object would have well defined coordinates and a function could decide whether an object was hit every time the player moved.
I need more details.
Is your game tile based? Is it 3d?
If its tile based, you could downsample your image to the tile resolution and then do a 1:1 conversion with each pixel representing a tile.
I suggest writing a script that takes each individual pixel and determines if it represents part of a wall or not (ie black or white). Then, code your game so that walls are built from individual little block, represented by the pixels. Shouldn't be TOO hard...
If you don't need to precompute anything using the map info. You can just check in runtime logic using getPixel(x,y) like function.
Well, i can see two cases with two different "best solution" depending on where your graphic comes from:
Your graphics is tiled, and thus you can easily "recognize" a block because it's using the same graphics as other blocks and all you would have to do is a program that, when given a list of "blocking tiles" and a map can produce a "collision map" by comparing each tile with tiles in the "blocking list".
Your graphics is just some graphics (e.g. it could be a picture, or some CG graphics) and you don't expect pixels for a block to be the same as pixels from another block. You could still try to apply an "edge detection" algorithm on your picture, but my guess is then that you should rather split your picture in a BG layer and a FG layer so that the FG layer has a pre-defined color (or alpha=0) and test pixels against that color to define whether things are blocking or not.
You don't have much blocking shapes, but they are usually complex (polygons, ellipses) and would be unefficient to render using a bitmap of the world or to pack as "tile attributes". This is typically the case for point-and-click adventure games, for instance. In that case, you're probably to create path that match your boundaries with a vector drawing program and dig for a library that does polygon intersection or bezier collisions.
Good luck and have fun.