Can I use OpenLayers for a simple custom tile grid system? - javascript

I have a table in my database with like 2.500 tiles, so 50 x 50. Frontend size is 256px x 256px per tile and there should be no zoom levels.
Then the are tables which hold other data (buildings, objects) and every one of this objects may belong to a certain tile.
In the frontend I want to use fullscreen OpenLayers to display a set of tiles to fill the screen and JUST use the dragging and async. reloading of tiles that OpenLayers provides. If possible even automatically stopping the dragging if the border of the world map is reached.
I also don't want to render images (pngs) - the tiles should be empty <div>s or at least transparent because the background of the body is a repeated grass texture anyway and I want to include <img>s depending on the objects which are associated to the tile in the model.
Can anyone familiar with OpenLayers tell me if this is possible with such a simple custom model on the backend? Any resources on this particular case would be very helpful!

Yes, this is possible in OpenLayers if each tile in your table has some geospatial data associated with it, such as a Bounds or the Lat/Lon of a corner.
OpenLayers wants to place base layers (your tiles as WMS) and features (your buildings and objects as WMS, WFS, or Vector) geospatially within the browser's viewport. The trick is to restrict OpenLayers to a single zoom level (resolution) to match the implicit resolution of your stored tiles, and then set the maxExtent of your OpenLayers.Map object to match the extent of all your tiles such that each WMS tile request generated by OpenLayers has a bounding box that matches one of your tiles.
Here is a WMS request generated by OpenLayers for a simple base layer I have (the BBOX is in meters). The link is behind a firewall so it won't work for you:
http://kpnatsp8:9080/WmsServlet?SERVICE=USSTATES&TRANSPARENT=FALSE&FORMAT=image/png&LAYERS=USSTATES&SCALE=4000000.0000000005&SPHERICALMERCATOR=true&MAXEXTENT=-20037508.34,-20037508.34,20037508.34,20037508.34&REQUEST=GetMap&STYLES=&SRS=EPSG:900913&BBOX=-12812623.352549,3443367.869216,-11909512.729118,4346478.492647&WIDTH=640&HEIGHT=640
I have a Java servlet that takes that request and returns a tile image. You would write your own servlet or server-side script to take the request, determine which tile in your database matches the BBOX bounds, and return that tile as an image response.
Sorry if I'm being pedantic here but you sounded new to OpenLayers. This is the way I would start but I'm open to better ideas.

Related

Leaflet / Progressive Web App - quick turnaround on tile 404 (perhaps using Workbox)?

I have a Leaflet map with two sets of my own tiles (this is for a campground map). The tiles are limited to the boundaries of the camp, so I don't have a lot of them. I've built a progressive web app (using Workbox for caching) and got to thinking about the following situation:
There are a significant number of requests for non-existent tiles, where the TileLayer knows to serve a default tile via errorTileUrl, which means quite a few 404 requests even when offline (since the tiles won't be in the cache). However, this seems a bit silly to me because I know which tiles should be present ahead of time, so I should be able to prevent the off-map 404s (looking at about 20 failed requests at start up).
I do need to be able to show (blank) off-map tiles because I can't guarantee orientation/geometry of the full-screen map on the device.
My primary question is: is it worth worrying about this? The app works as is now; just trying to make it a bit more network-efficient.
If so, one option I had considered is creating a new workbox.router route to handle calls to retrieve tiles and just quickly return a 404 if it's not in the list, otherwise go to cache/network. Or is there something I'm missing in Leaflet (or a plug in) that already handles this?
Thanks for thoughts and ideas.
You should be able to specify available tiles of your Leaflet Tile Layer on a rectangular area and a zoom range, using options:
bounds: If set, tiles will only be loaded inside the set LatLngBounds.
minNativeZoom: Minimum zoom number the tile source has available. If it is specified, the tiles on all zoom levels lower than minNativeZoom will be loaded from minNativeZoom level and auto-scaled.
maxNativeZoom: Maximum zoom number the tile source has available. If it is specified, the tiles on all zoom levels higher than maxNativeZoom will be loaded from maxNativeZoom level and auto-scaled.
If your available tiles do not fill a rectangular area, you can provide dummy tiles to fill the uncovered area. Using a service worker router can help in redirecting to a common dummy tile in cache indeed.
For the outside area, you could just use the container background. Or if you really want a similar effect as a Tile Layer, use dummy ones that point to a common dummy / "no tile available" constant url template.

Wrap GeoJSON objects around Leaflet.js map

I have a Leaflet.js map consisting of Marker and GeoJSON objects. Is there a simple way to wrap these so they appear periodically every 360 degrees? Basically, I want the entire map to become periodic.
Here is an illustration of the sort of objects I have (excluding the background TileLayer, which I don't have):
How can I periodically repeat this data so the great circles aren't broken, but appear intact every 360 degrees as the map is scrolled left or right?
One approach is to leverage Leaflet.VectorGrid. As you can see in the Leaflet.VectorGrid GeoJSON example, the data will wrap. (Architecturally, this happens because VectorGrid loads a vector tile with the same coordinates when wrapping around). Be advised that some artifacts might appear.
Another approach is to simply duplicate your data (adding 360 to each longitude). Do it a couple of times per side, and use the WorldCopyJump option to prevent users from scrolling too far.

Performant GL Triangles Mapbox GL JS

I am working on trying to create a basic, grid-based, but performant weather-arrow visualization system.
EDIT 2:
Up-to-date version here: ( Mapbox Tracker ) of the system using the workflow which is described below
Usage Instructions:
- Click on Wind icon (on the left)
- Wait for triangles to occupy screen
- Pan time-slider (at the bottom)
As you will observe (especially on larger resolutions or when panning time slider quickly) there is quite a performance hit when drawing the triangles.
I would greatly appreciate any advice on where to start with either using something in the current API which would help, or any ideas on how to tap into the current graphics pipeline with some type of custom buffer where I would only need to rotate, scale, change color of triangles already populated in screen space.
I feel as though my specific use-case would greatly benefit from something like this, I really just don't know how to approach it.
I have a naive implementation running using this workflow:
Create a geojson FeatureCollection source
Create a fill layer
Using Data Driven property: fill-color
Data function:
Get map bounds
Project sw & ne into screen points (map.project(LatLng))
Divide height and width into portions
Loop through width and height portions
Lookup data
Access data rotation property
Create vertices based on center point + size
Rotate vertices
Create Point objects for vertices
Unproject Point Object and wrap map.unproject(Point).wrap()
Create Feature Object, assign Data driven Color
Assign unprojected LatLng as Coordinates to Polygon geometry
Add to Feature Array for Collection
Call setData on layer
So while this works, I'm looking for advice for a more performance friendly approach.
What I'm thinking here is whether I can somehow create a custom layer, one where I only need to draw to screen co-ordinates to represent the data relative to its LatLng point. So that I can draw colored, scaled, rotated triangles in screen space, and then have them update to relevant data from the new relative LatLng position.
E.g. Update some type of Mesh on screen instead of having to: unproject, then update feature collection source using map.getSource('arrows').setData(d), requestAnimationFrame(function) etc.
I've done similar in three.js in other projects but I would much rather use something that is more mapbox native. Does this sound feasible? Am I going to see a decent performance boost if so?
I've not dealt with raw gl calls before etc so I might need a pointer or two in the right direction if its going to need to get as low level as that.
EDIT:
Previous Implementation using gmaps / three.js : volvooceanrace
(wait for button on left to go from grey to black) click on top button which shows a 'wind' label when hovered over, slide red time bar underneath to change data.
Added screenshot of current working implementation
Mapbox GL Arrows
Not sure what was available in 2016, but a reasonable approach these days might be to use symbol layers, and the icon-rotate data-driven property to rotate each icon based on the property of its data point.

How can I implement a zoomable draggable interface the same as seatgeek?

Seatgeek has a zoomable draggable tiled interface.
An example is here:
http://seatgeek.com/sf-bulls-yankees-tickets/3-2-2012-tampa-george-steinbrenner-field/mlb/785875/#
I want to implement a scrollable draggable interface like this but I cannot use Google's code for google maps.
Also I need the tile system like google maps where it pulls tiles from the server for rendering the map.
Need to implement in javascript. What library can I use? How can I do it?
How does seatgeek do it?
I de-compiled their javascript http://pastebin.com/PVjahhnH
Map Client
OpenLayers
OpenLayers Examples
Map Data
OpenStreetMap
This kind of interface seems complex to implement, but it is just some math tricks. If you decide to implement your own algorithm, try this out:
Take the full image and create tiles in different scales and consequently with different depth.
The user start looking at the scene in real scale, composed by 16 tiles created from the original scene.
If the user drags, all tiles moves equaly. If the user zoom in, all tiles are scaled up.
If the user zoom more than X, you change the 16 tiles by their 16 child tiles! Got it? Higher the zoom, higher the detail. To avoid having 36000 tiles at the same time, generate with different depth and switch them on the fly.
You just need to load and move the tiles. Multiply tile x, y, width, height by the zoom. Keep the focus of the scene in the mouse position. Take a look at this example. It does exactly the steps above, but with a lot of microscope images. It is the same idea of google maps.
CloudMade map tile is one of the server based map tile service. Please read this page server http://cloudmade.com/documentation/map-tiles or contact with alex#cloudmade.com for more information.

Hybrid static/dynamic Google Map

Ever noticed that when you go to maps.google.com and do a search (say, car wash), it renders a lot of results (represented by small circles) and a few prominent ones (seen as regular-size pins)?
Notice how quickly it does this?
From what I can tell from analyzing this in Firebug, much of this is generated on the server and sent to the client as a static image.
However, it's still dynamic. You can still zoom in and out, or click on a result and see a dynamic InfoWindow rendered.
Google have made the map quick and smooth using static images, while still making it flexible.
Is there a way to do this kind of 'pre-loading' with my own Google Map (implemented with the Google Maps API)?
The technology that maps.google.com uses is similar to that used in a GLayer. The server dynamically builds tiles and "hotspot" info. The GLayer tiles are also constructed dynamically (and possibly cached) even though the underlying data is fairly static. From the client side, the searched dots technology is identical to the Wikipedia or Panoramio GLayer. The only new trick is that the dot information is generated dynamically on Google's big fast servers.
The API does not (yet) provide any tools for creating custom GLayers. If you want to do the same sort of thing yourself, using your own database of locations, there are three steps that you need to code:
Create your own custom tileserver
which searches your database for
items in the tile area and uses a
graphics library like gd or
imagemagic to place dots on the
tile. Use those tiles to create a
GTileLayerOverlay on the client.
When the user clicks on the map,
send the location of that click to a
second server. That server should
check your database and return the
infowindow text for the dot at that
location, if any. Returning all the infowindow contents from all the dots imaged by the tileserver would be unacceptably slow, so you have to fetch them one by one, as needed.
Changing the cursor when the mouse
is over a dot is more tricky. What Google
do is return a list of hotspot
coordinates for all the dots on each
tile. Whenever the mouse moves, the
API determines which tile the
pointer is over and uses a quadtree
algorithm to see if the pointer is
over a hotspot, and change the
cursor if necessary. If you only
have a modest number of hotspots per
tile, then a linear search would
probably be acceptably fast. If you might have thousands of dots per tile, then you'll probably need to write your own quadtree algorithm. The Google quadtree code is not exposed, so you can't use it.
Here's a page where somebody has done all that. In this case the hotspots are calculated as circles, by comparing the distance from the centre point, even though the dots are square. On maps.google.com the hotspots are calculated as rectangles, by using GBounds.containsPoint(), even though the dots are round.
I'm doing something similar - but instead using a tile layer, I just send server-clustered markers to the browser whenever the view changes. If your data is static, you can pre-cluster your markers and it would be incredibly fast with tens of thousands of markers.
Our site can't use pre-clustering because the markers can be searched and filtered, but it's still pretty fast up to about 20,000 markers. Still working on it...

Categories