This page is part of the MapGuide Future section, where ideas are proposed and refined before being turned into RFCs (or discarded). Visit the Future page to view more!
Overview
This page is a living proposal for implementing a client-side vector map viewer.
Motivation
All of our client-side viewing technologies (AJAX/Fusion/AIMS Mobile Viewer/Pure OpenLayers) are cut from the same cloth:
- Rendering is done server-side
- Map state is managed server-side
- Session state is managed server-side
- They are all inherently connected. If we lose connectivity with the MapGuide Server, all our viewers break down.
If we want to use a MapGuide 6.5 analogy, these are all glorified LiteView clients. We lack the modern contemporary to the MapGuide 6.5 ActiveX viewer where rendering is done client-side and limited offline capabilities can be achieved through the use of static MWF layers.
Having a client-side vector map viewer will significantly reduce the processing burden on a MapGuide Server as its role under a client-side vector viewer would now be reduced to being simply an efficient vector/raster/tile delivery platform. Under a client-side viewer all rendering and map state management can be offloaded from the MapGuide Server onto the client machine
Choosing the technological base for our client-side vector viewer
Previous discussions on the matter has put forth the following possible contenders:
- Silverlight
- SVG
- Flash
- HTML5
Silverlight's future was sealed due to Microsoft's move towards WinRT/Metro. It is effectively an EOL'ed technology.
SVG is a mature technology but is hindered by Internet Explorer and potential drawing complexity (Even if not desirable, we must allow for scenarios of a map with 10000-100000 features on screen)
Flash is in a state of terminal decline slowly being supplanted by HTML5
Which leaves HTML5 as the clear winner. Assuming IE8 as a legacy browser, HTML5 is unanimously supported for the browsers we intend to target and the subset of HTML5 features we intend to mainly use. HTML5 support is continually improving and more and more complex applications are being built on top of HTML5. Even Autodesk's AutoCAD 360 web is built on HTML5 technologies. If this isn't a clear sign that HTML5 is ready for prime time, then nothing is.
The key problems to solve with HTML5
Rendering/Stylization
This is the most important problem to solve. The easiest thing to do would be to just leverage OpenLayers/Leaflet/etc and just serve vector data to it from MapGuide.
While this is indeed the simplest approach. The problem with this is that you are putting rendering/stylization concerns into the client library which may either have a different or simplified opinion on how your features are to be rendered. In other words, there is a major loss of visual fidelity offloading rendering/stylization concerns to a thirdparty JS mapping library. We ideally want to able to leverage our existing Layer Definitions and have the settings defined within be respected by our client-side viewer.
This means of course that we'll need to somehow re-use our existing Rendering/Stylization code. mg-desktop and a particular AU presentation in 2009 have proven this Rendering/Stylization core is pretty self-contained and re-usable outside of the MapGuide Server context with zero dependencies on ACE and other thirdparty libraries. But that code is in C++, and our target platform is HTML/JavaScript. Is there a way to easily leverage our existing C++ code in JavaScript instead of having to re-implement all this from scratch?
It just so happens there is a way. Using a tool called emscripten, we can "transpile" C++ code to JavaScript. The pedigree and readiness of emscripten can be verified with the fact that monstrously complex C++ codebases like the Unreal Engine 3 and Qt was able to be transpiled via emscripten and run within a web browser.
Advancements in improving JavaScript performance such as asm.js from Mozilla means this emscripten approach has a lot of viability for reusing C++ code in a web browser. Our client-side viewer is not a 3D game engine or a windowing/application framework, so the bar for us to reach isn't exactly high, but also isn't exactly low either.
Preparing the rendering/stylization code
NOTE: This section was based on light reading of emscripten documentation and blogs. The feasibility of this approach is not proven yet and is purely theoretical
A straight run of emscripten on the Rendering/Stylization code is not going to magically give us our magical HTML5 canvas rendering/stylization library. We need to do some preparation/modifications on the code:
- We have to use SDL as this is how we automagically get HTML5 canvas support. Emscripten converts SDL calls to HTML5 canvas calls. We need to implement a SE_Renderer that uses the SDL library
- We need to reduce the dependency set. This means our emscripten build profile should not have:
- DWFRenderer, EPlotRenderer, EMapRenderer (dependency on DWF Toolkit)
- GDRenderer (dependency on GD)
- AGGRenderer (dependency on AGG)
- KMLRenderer (dependency on parts of the C++ standard library that probably have no emscripten equivalent)
- We basically only want one concrete SE_Renderer implementation: The one using SDL
- Replace FreeType calls with SDL (is this even possible?)
- We also need to eliminate dependency on FDO. This means stubbing out or replacing references to the FDO Expression Engine and replacing any FDO enums/types with our own internally defined ones.
- We need an implementation of RS_FeatureReader that can callback into JavaScript via emscripten
- We need a way to marshal byte arrays in JS (however emscripten suggests we should represent them) to FGF byte arrays. LineBuffer objects have support for direct initialization from FGF byte arrays, so FDO does not have to play a part. We'll need some support libraries in JS to support conversion to FGF from common formats like GeoJSON.
The final set of libraries that will be transpiled to JS are:
- MdfModel
- Renderers
- Stylization
It is envisioned the final transpiled core can render features off of a HTML5 canvas element and a JS-proxied RS_FeatureReader instance which wraps a collection of GeoJSON features or OpenLayers vectors, with a library like Proj4js taking over the role of CS-Map for client-side coordinate transformation needs.
Current roadblocks with this approach
- The Stylization library is still tightly bound to the FDO Expression Engine. Ideally expression evaluation should be abstracted out to a separate class and all FDO-specific things happen within this class. A common base class should then be extracted out of this one so that we can provide an emscripten-compatible alternative and exclude the FDO-based one from the emscripten build profile.
Building a new client-side API around this core
TBD
Offline storage
TBD
MapGuide Server delivery of content/rasters/vectors/tiles
TBD