I find it fun how idioms change from culture to culture. When a native-english speaker wants to ask for something outrageously hard to attain, they say they’re «asking for the moon». But we Spaniards say «pedir el oro y el moro», literally translated as «asking for the gold and the moor»; the saying dates back to 1426, when the army of a christian king successfuly captured high-ranking enemies, and the rumor was that the king quite literally wanted to keep both the ransom gold and the moor prisoner.

Last month I was talking to an american friend (you know, a person who lives in the Americas) about this, and they told me that the idiom they use in Argentina is «la chancha, los veinte, y la máquina de hacer chorizos», literally «The sow, the twenty [piglets] and the sausage-making machine», meaning that one wants a (living) sow after given birth to an unreasonable amount of piglets, plus the piglets, plus the meat products from all the animals.

Why am I sharing this piece of trivia? Because I’m going to ask for stuff. A lot of radical stuff. Stuff that might seem too much to ask, but stuff that I’d like to get nonetheless, and even if I don’t get it, the mere act of asking for it doesn’t really hurt me and it might swear things a little towards my way.

Or, as the late Sir Terry Pratchett beautifully wrote in his novel The Truth:

«There are, it has been said, two types of people in the world. There are those who, when presented with a glass that is exactly half full, say: this glass is half full. And then there are those who say: this glass is half empty.

The world belongs, however, to those who can look at the glass and say: What’s up with this glass? Excuse me? Excuse me? This is my glass? I don’t think so. My glass was full! And it was a bigger glass! Who’s been pinching my beer?»

So, I’m gonna push any sliver of shame aside and ask for…

Part 5: The Gold, the Moor, and the Sausage Machine

Let’s see, I’ll start with…

Let’s stop the mutants

I don’t like GoogleMutant nor MapkitMutant. They work, but they’re just big ugly hacks to overcome a lack of interoperability.

I feel obliged to make a direct request to any people representing Google or Apple who is reading this: allow your users to access your map tiles outside of your JS frontend libraries; both basemap and thematic maps, both raster and vector tiles; preferably via a well-known protocol such as OSGeo’s TMS or OGC’s WMTS. (This should go without saying, but restricting that at the ToS level, or performing market segmentation by offering standard tile access at a different pricing tier would be…. smartass tactics, to put it mildly).

To the rest: let’s consider labelling web map implementations as non-compliant if the underlying data cannot be accessed easily (in both technical and practical terms) in a different web map implementation.

IIRC, OGC has specific interoperability criteria: there must be at least 3 reference implementations before a standard passes. I suggest using similar criteria here: a web map implementation should qualify as standard-compliant only if it doesn’t have default basemaps, or the default basemaps can be used (without hacks!) in at least 3 web map implementations.

GPL your code already

I consider that there’s a real risk of a E-E-E scenario when it comes to web maps implementations. And based not just on FLOSS-y moral grounds, but on egoist reasons: I don’t want you implementing something than then I have to reimplement or hack around.

My (very) radical proposal for this is naïvely simple: Make strong copyleft licensing a neccesary condition for standards compliance. This reduces incentives for E-E-E scenarios, and makes all of our lives simpler, by letting all of us not waste time by implementing the same thing.

Now, this is radical, and there’s people who seem to frontally oppose such an idea; but I see it as the next logical step in standarization. Standards bodies such as the OGC pride themselves in enforcing certain legal requirements on the compliant implementations. After all, the whole “patent-litigation free” thing is there to enforce all players to play in a level field - I just see strong copyleft as a more radical way of achieving the same goal.

Stop calling things “layers”

An HTML element with a z-index inside a stacking context is a «layer». A nested stacking context is a «layer» as well. A GIS dataset with distinct symbolization is a «layer». In datasets with several symbols per feature, each of those symbols is a «layer». Each thematic feature set inside a MVT-formatted vector tile is a «layer». Each level of a pyramid tileset can also be a «layer». A basemap is the bottom-most «layer» of a map.

So changing the z-indexes of the HTML elements for the symbols of a feature in the representation of a thematic set of a given vector tile in a given pyramid level for a given basemap is… layering the layers of a layer of a layer of a layer of a layer of a layer.

Just, stop using the word “layer” liberally. Please.

Distributed P2P tile pyramids

Serving a world-wide tile pyramid is an interesting problem. On one hand, tiles can be efficiently cached (which is why WMS never really gained a lot of traction for the non-tecnhical end user). On the other hand, it’s a lot of data, and the resources needed to serve tiles if a service is popular can be quite demanding. So much that there are businesses dedicated to serving tile pyramids, and OSM has sempiternal struggles with tileserver bandwith.

Since I’m biased towards OSM and towards the end user over businesses, I want there to be a better way to serve tiles. I also want to avoid the cost of serving tiles as an excuse for the lack of interoperability, just in case.

A moderate approach would be “please let users and web authors cache your tiles”, but I want to aim for something better.

I wish for a distributed, P2P, IPFS-like protocol for decentralized map tiles.

There’s a lot of potential here - but possibly a lot of work, since the amount of tiles in a world-wide tile grid is huge, and their numbering might not play nice with existing decentralized protocols.

I’ve toyed with the idea of leveraging WebRTC in order to let browsers exchange the bounding boxes of their viewports - hence exchanging peers by bounding box collisions. I expect the algorithms for this to be different than protocols optimized for uniquely addressable assets. Hopefully this idea can be developed further.

<slippy> element

I’m not a fan of a web map HTML component fully implemented in the browser - rather, I’d like to be provided more building blocks to author webpages and libraries.

One of the proposals that make sense is that of a <slippy> HTML element, with a very narrow purpose: capture pointer interaction, and pan/scale its contents. The idea is to get rid of the warnings about passive pointer event handlers, and transform the contents of the <slippy> element via the equivalent of a translate3d CSS transform. And not make it geographical, since it’d be useful for plain images as well.

I could get behind such a proposal… but.

This doesn’t cover the use case of 3D globes. Could then a different element handle a 3D spheroid, up to the point of handling 3-pointer interactions to change the perspective? I’m skeptical that a 2D <slippy> would cover all use cases.

A WebGL interface that makes sense

This is the big one, folks.

Some of the reasons why people are advocating for a native web map standard is performance, since “native” implementations are perceived as more performant than JS ones.

But I think this argument is moot. We have WASM and WebGL, so that we can bypass the JS JIT compiler/interpreter and most of the graphics composer if we want to. Ultimately, performance is about detecting and avoiding bottlenecks, rather than cargo-culting performant implementations.

The worst offender when it comes to web map performance is the newbie developer who goes ahead with displaying thousands of markers in React+Leaflet. Since React has a tendency to build whole virtual DOM trees of everything, each map interaction has the potential to recalculate thousands of DOM elements (one per marker), and most implementations slow down to a crawl. Even without React, a DOM tree with a few thousands of elements will be slow.

But the reality is that the problem of thousands of markers doesn’t need a non-DOM implementation to be performant. I demonstrated this a few years ago by displaying a few thousand pictures of cats on a map with Leaflet.GLMarkers. WebGL is impressively performant when care is taken in order to avoid overhead.

Unfortunately, WebGL is infamously hard to work with; I’ve ranted extensively about this in the past. The WebGL data structures are a straightforward port of the C/C++ OpenGL structures, but without the C struct datatype. The worst offender is the fact that we WebGL devs need to care about attribute locations; since I’ve read the dragon book during my stay in university, I know that attribute locations are really pointer offsets of a symbol table, and the fact that a high-level language such a JS needs manual handling of symbol table offsets is insane. That’s literally the stuff that compilers are supposed to take care of.

WebGL frameworks are supposed to take care of this; but in my experience, they either overshoot (assuming a 3D environment, a camera, and a mesh model; glTF also suffers from this) or undershoot (needing duplicate definitions and not even having triangles as data primitives and needing raw DataViews on top of ArrayBuffers).

I think web authors need a way to work with GPU graphics that doesn’t suck. And I think the best way to achieve that is with a SVG-like language, with triangles as first-class citizens.

I hereby propose the Triangle Graphics Markup, <tgm>.

A top-level <tgm> element behaves like a <canvas>, e.g.

<tgm width=640 height=480>
</tgm>

Then, add triangles as <trig> elements:

<tgm width=640 height=480>
  <trig/>
  <trig/>
</tgm>

Now, a <tgm> has default vertex and fragment shaders…

/* Vertex shader */
attribute vec2 pos;
attribute vec4 color;
void main(void) {
	gl_Position = vec4(pos, 1., 1.);
	vColor = color;
}

/* Varyings common to both shaders */
varying vec4 vColor;

/* Fragment shader */
void main(void) {
	gl_FragColor = vColor;
}

…and the attributes available to triangles (as well as their types) are derived from the shader; attributes could be defined within space-separated strings:

<tgm width=640 height=480>
  <trig pos="-0.5,-0.5 0.5,0.5 1,0" color="#f00f #f00f #f00f"/>
</tgm>

Define different vertex attributes within the shader, and the triangles can specify it:

<tgm width=640 height=480 vertexShader="attribute float foobar; /* etc */">
  <trig foobar="111 222 333"/>
</tgm>

And after the “hello world” triangles, implement quadrangles (AKA “quads”) for convenience…

<tgm width=640 height=480>
  <quad pos="-1,-1 -1,1 1,1 1,-1" color="#f00f #f00f #f00f #f00f"/>
</tgm>

…textures from HTMLImageElements (or HTMLCanvasElements!)…

<tgm width=640 height=480 fragmentShader="/* etc */ gl_FragColor = texture2D(textureImage, pos.st); /* etc */">
  <texture name="textureImage"><img src="foobar.png"/></texture>
  <quad pos="-1,-1 -1,1 1,1 1,-1" color="#f00f #f00f #f00f #f00f"/>
</tgm>

…then nested <tgm>s for render-to-framebuffer-texture and post-processing; <tgm><shader><trig/></shader><shader><trig/></shader></tgm> for sequential draw calls; <uniform>s; automatic clear and re-draw when on attribute/uniform changes; grouping triangles and quads in named groups to apply several shaders to them. Off the top of my head, that would make for a nice MVP.

It’s just like SVG, but instead of leveraging the power of 2D graphics APIs, it would leverage low-ish level OpenGL ES structures and concepts.

A lot of my issues with WWW technology are not technical, but political - and this is political as well. WebGL has been geared towards OpenGL programmers, making it pretty much inaccessible to web authors who can’t (or won’t) do scripting. This <tgm> proposal reverses that: the aim is to provide functionality to web authors who deal in markup, even if that angers a few people from ACM’s SIGGRAPH.

I think that this concept is viable, and could boon maps and graphics on the WWW.

A few random things about HTML/DOM

Finally, there are a few things about HTML or the DOM that I’d wish were there. They’re not specific to GIS; this is the web author part of me doing wishful thinking.

I never quite understood Shadow DOM. I mean, I understand it when the browser has to internally mock some elements, but I fail to appreciate the benefits of letting web authors encapsulate DOM tree inside a DOM tree in an opaque way.

Perhaps that’s because of my point of view as a hacker/tinkerer who likes to see how things work internally, and I just don’t like when stuff is hidden from me, e.g. minified/obfuscated javascript. (How I yearn for the halcyon days of yore, when user-facing HTML was indented and human-readable)

In fact, something that I think is missing is having third-party content directly in the DOM tree, subject to the author’s own CSS and such. Like an <iframe>, but instead of a complete HTML document it asks for a document fragment, and instead of being a block element, it can also be flow content. I dub this hypothetical HTML element a <flowframe>.

So having a .html file with something like…

<html><body>Hello <flowframe src='name.htmlfragment'/>!</body></html>

…and name.htmlfragment with something like…

<span>world</span>

…the final DOM tree would look like…

<html><body>Hello <flowframe><span>world</span></flowframe>!</body></html>

That’s it. It’s doable today by leveraging a bit of JS (with something like fetch(url).then(r=>r.text()).then(t=>foo.innerHTML=t))… but having it in the browser could easily get rid of half the reasons to use reactive frameworks.

More importantly IMHO would be that this would prompt a clean separation of frontend and backend, and lead us back to the times where WWW APIs were actually useful.

Add a couple of hooks to the hypothetical HTMLFlowFrameElement to fire events, change src and reload, the usual CORS and frame sandboxing safeguard to prevent XSS, and it’d be good.

Since I’m asking for the gold, the moor and the sausage machine, I must say I also want adverts wrapped in a <sponsored> tag - that gives them a clear semantic meaning! Also <notmine> when embedding content from a 3rd party, and <userprovided> for when the content comes from a user of the platform. That would greatly help with EU GDPR stuff IMHO.

Oh, and since the whole cookies thing has spawned a classification of cookies into categories (functional, preferences, analytics, ad-tracking, targeting and so on), it should be the right time to redo cookies from scratch, call them “tracker headers” this time, specify categories, and let the browsers handle whole categories of trackers from the browser preferences/plugins/whatever.


Hey, a man can dream, right?