Joy of Open Source

*** update IV/2017:  from comment below, check this great raster plug-in  from Victor Veralde Gutiérrez too: https://github.com/IHCantabria/Leaflet.CanvasLayer.Field/  ***

I have got great, absolutely amazing  joy today from my own open source experiment. In 2014, nearly 2 years ago,  I have published on GitHub (gist)  L.CanvasOverlay a small class  to handle generic drawing on top of Leaflet, I was thinking let’s try to  contribute back to the open source with this little snippet –  I thought would be useful so I have added little description. Original blog post here: https://blog.sumbera.com/2014/04/20/leaflet-canvas/

After few months later I found it is used on http://windyty.com   one of the best 2015 geo-visualization with huge popularity. It is a small part of this great app, but makes me feel so good like I am part of it, I am looking on something where is my small piece, small share…meaning of the effort, sense of publishing and open sourcing.

Screen Shot 2016-02-02 at 23.16.13

And today I have got echo it is used also in Marine National Facility here: http://www.cmar.csiro.au/data/underway.test/

This makes me so happy … and just came across this quote : “Revenue is a lagging indicator, usage is a leading indicator,” can’t remember, who just said that ? :)

Advertisements

WMS overlay with MapBox-gl-js 0.5.2

alt textQuick and dirty test of the WMS capabilities of the new MapBox-gl-js 0.5.2 API. First of all, yes ! it is possible to overlay (legacy) WMS over the vector WebGL rendered base map … however the way is not straightforward:

 

  • Needs some ‘hacks’ as current version of the API doesn’t have enough events to supply custom URL before it is loaded. But check latest version of mapbox, it might have better support for this.
  • Another issue is that WMS server has to provide HTTP header with Access-Control-Allow-Origin:* to avoid WebGL CORS failure when loading image (gl.texImage2D). Usually WMS servers don’t care about this, as for normal img tags CORS doesn’t apply. Here WebGL has access to raw image data so WMS provider has to explicitly agree with this.
  • Build process of mapbox-gl-js tend to be as many other large js projects complicated, slow, complex. And specifically on Windows platform it is more difficult to get mapbox-gl-js install and build running then on Mac.

Code is documented to guide you through the process, few highlights:


 // -- rutine originaly found in GlobalMercator.js, simplified
 // -- calculates spherical mercator coordinates from tile coordinates
 function tileBounds(tx, ty, zoom, tileSize) {
    function pixelsToMeters(px, py, zoom) {
     var res = (2 * Math.PI * 6378137 / 256) / Math.pow(2, zoom),
         originShift = 2 * Math.PI * 6378137 / 2,
         x = px * res - originShift,
         y = py * res - originShift;
     return [Math.abs(x), Math.abs(y)];
     };
   var min = pixelsToMeters(tx * tileSize, ty * tileSize, zoom),
         max = pixelsToMeters((tx + 1) * tileSize, (ty + 1) * tileSize, zoom);
return min.concat(max);
}

 
]

// -- save orig _loadTile function so we can call it later
 // -- there was no good pre-load event at mapbox API to get hooked and patch url
// -- we need to use undocumented _loadTile
 var origFunc = sourceObj._loadTile;
    // -- replace _loadTile with own implementation
 sourceObj._loadTile = function (id) {
    // -- we have to patch sourceObj.url, dirty !
    // -- we basically change url on the fly with correct BBOX coordinates
    // -- and leave rest on original _loadTile processing
     var origUrl =sourceObj.tiles[0]
                      .substring(0,sourceObj.tiles[0].indexOf('&BBOX'));
     var origUrl = origUrl +"&BBOX={mleft},{mbottom},{mright},{mtop}";
     sourceObj.tiles[0] = patchUrl(id, [origUrl]);
     // -- call original method
     return  origFunc.call(sourceObj, id);
 }

 

 

gist available here

WebGL polyline tessellation with MapBox-GL-JS

update 09/20015 : test of tesspathy.js library here . Other sources to look:

  1.  http://mattdesl.svbtle.com/drawing-lines-is-hard
  2.  https://github.com/mattdesl/extrude-polyline
  3. https://forum.libcinder.org/topic/smooth-thick-lines-using-geometry-shader

*** original post ***

This post attempted to use pixi.js tessellation of the polyline, this time let’s look on how mapbox-gl-js can do this. In short much more better than pixi.js.

it took slightly more time to get the right routines from mapbox-gl-js and find-out where the tessellation is calculated and drawn. It is actually on two places – in LinBucket.js  and in line shader. FireFox shader editor helped a lot to simplify and extract needed calculations and bring it into the JavaScript (for simplification, note however that shader based approach is the right one as you can influence dynamically thickness of lines, while having precaluclated mesh means each time you need to change thickness of line you have to recalculate whol e mesh and update buffers )

 

// — module require mockups so we can use orig files unmodified
 module = {};
 reqMap = {
‘./elementgroups.js’: ‘ElementGroups’,
‘./buffer.js’ : ‘Buffer’
};
require = function (jsFile) { return eval(reqMap[jsFile]); };

 

   <!-- all mapbox dependency for tesselation of the polyline -->
 <script src="http://www.sumbera.com/gist/js/mapbox/pointGeometry.js"></script>
    <script src="http://www.sumbera.com/gist/js/mapbox/buffer.js"></script>
    <script src="http://www.sumbera.com/gist/js/mapbox/linevertexbuffer.js"></script>
    <script src="http://www.sumbera.com/gist/js/mapbox/lineelementbuffer.js"></script>
    <script src="http://www.sumbera.com/gist/js/mapbox/elementgroups.js"></script>
    <script src="http://www.sumbera.com/gist/js/mapbox/linebucket.js"></script>
    <script src="http://www.sumbera.com/gist/data/route.js" charset="utf-8"></script>
 // -- we don't use these buffers, override them later, just set them for addLine func
 var bucket = new LineBucket({}, {
 lineVertex: (LineVertexBuffer.prototype.defaultLength = 16, new LineVertexBuffer()),
 lineElement: (LineElementBuffer.prototype.defaultLength = 16, new LineElementBuffer())
 });

var u_linewidth = { x: 0.00015 };
// override .add to get calculated points
LineVertexBuffer.prototype.add = function (point, extrude, tx, ty, linesofar) {
    point.x = point.x + (u_linewidth.x * LineVertexBuffer.extrudeScale * extrude.x * 0.015873);
    point.y = point.y + (u_linewidth.x * LineVertexBuffer.extrudeScale * extrude.y * 0.015873);
    verts.push( point.x, point.y);
    return this.index;
};

// — pass vertexes into the addLine func that will calculate points
bucket.addLine(rawVerts,“miter”,“butt”,2,1);

prototype  code posted here

 

Data Visualisation with d3.js Cookbook

datavisbookbought this great book on  d3.js (Data-Driven documents), written by  Nick Qi Zhu

D3 can plot map in various projections, however do not expect to get same set of (overlapping) functionality as Leaflet or OpenLayers. D3 can extend these mapping frameworks. For OL3 simple  example is here for Leaflet, my favourite is  hexbins or check my own experiment here.

While D3 is kind of ‘base’ charting library (lot of utility functions, helpers) , there is upper , high level library too  that can provide lot of ‘boilerplate’ for common charts. Here comes great news:

Nick Qi Zhu   is also author of the open source javascript  lib dc.js   (Dimensional Charting) library  that is using crossfilter (Fast Multidimensional Filtering for Coordinated Views) . Part of the dc.js lib is set of most common charts and one of them is choropleth map .

Other resources:

D3 Animation : http://blog.visual.ly/creating-animations-and-transitions-with-d3-js/

Design selections: http://www.awwwards.com/fresh-ui-inspiration-in-the-era-of-google-material-and-design-patterns.html

Leaflet, WebGL / Canvas tiled vectors

Update June 2014: Simple point WebGL sample is here: https://blog.sumbera.com/2014/06/08/leaflet-webgl-many-points-rendering/
Cool WebGL and Canvas demo of vector drawing in Leaflet 0.8  !
WebGL: http://vector.io/vector-map/

leafletWebGL

Canvas : http://vector.io/vector-map/#canvas

GitHub project: https://github.com/bcamper/vector-map

 

Leaflet 0.7 vs. OpenLayers 3 beta 1 on iOS

leafol2Made quick test of these 2 +1 HTML5 renderers on iOS running inside iOS app in the WebView, that is without Nitro acceleration.  All run on iPad Air

Leaflet 0.7 : great , works fine, everywhere, doesn’t load while dragging map (on mobile only) , runs on Microsoft  Surface too.

OpenLayers 3 beta 1 : runs fine too, loads map during dragging, seems like smaller framerate, can over zoom OSM, doesn’t run in Microsoft Surface well.

Seznam Mapy Api v 4 – proprietary renderer from Seznam , bad rendering  on iOS, missing tiles, nice map sources

Videos and original web pages used: – screencasted by AirPlay – that is directly from iPad Air:

B. OpenLayers 3 beta1
C. Mapy Api v 4.8

OpenLayers or GoogleMap v3 for mobile web app ?

[2014 January] UPDATE : new Openlayers 3 beta 1 works quite well on iPad as well as Laeflet 0.7, check post here: https://blog.sumbera.com/2014/01/23/leaflet-0-7-vs-openlayers-3-beta-1-on-ios/

[2011 September] UPDATE : new Openlayers 2.11 works quite well on iPad/iPhone.

 

I have experimented with OpenLayers 2.9 using touch.js extension for capturing touch events from iPhone/iPad. Although stripped down version of OL is about 184KB, the performance is very bad. If you have iPhone/iPad check this experiment: http://www.sumbera.com/lab/iphone/katastr.htm (note it will not work from desktop browser)

OL team is working on v3 of OL to be more lighter, faster even for mobile devices, see here: http://trac.osgeo.org/openlayers/wiki/three  or here : http://openlayers.org/blog/2010/06/30/openlayers-3-on-github/

Meanwhile I have tested new GoogleMaps v3 how it works on iPhone/iPad. despite few problems (stability, problems with cached tiles or disconnected JavaScirpt  to load new tiles -iPad)  it works pretty well . Check yourself this page from your mobile touch device (iPhone.iPad,Android): http://www.ikatastr.cz/iKatastrM.htm

Conclusion : Google Maps v3 wins on mobile over the Openlayers 2.9