var webmap = webmap || {}; webmap.models = {}; /// Namespace for models. webmap.modules = {}; /// Namespace for modules. /// XML namespace for SVG elements. webmap.svgns = "http://www.w3.org/2000/svg"; /// XML namespace for XLink attributes. webmap.xlinkns = "http://www.w3.org/1999/xlink"; /// SVG root element for creating matrices. webmap.svg = document.createElementNS(webmap.svgns, "svg"); /// Counter to generate locally unique ID's. webmap.id_counter = 1; /// Generate a locally unique ID. webmap.generateId = function() { return "WebMap-" + (webmap.id_counter++); } /// Set up one class as a subclass of another. webmap.extend = function(base, sub) { var dummy = function(){}; dummy.prototype = base.prototype; sub.prototype = new dummy(); sub.prototype.constructor = sub; }; /// Base for classes that can be extended with modules. webmap.Extendable = function(namespace) { this.modules = []; this.module_ns = namespace; } /// Add a module. /** * Pass in any additional module arguments after the name argument. * The modules constructor will be called with the map as the first argument, * followed by any additional arguments you specify here. * * \param name The name of the modules. * \param ... The remaining arguments for the module constructor. * \return A reference to the created module, which can be passed to removeModule(). */ webmap.Extendable.prototype.addModule = function(name /*, ...*/) { // Prepare the arguments for the module constructor. var args = Array.prototype.slice.call(arguments, 1); args.unshift(this); var module = webmap.construct(this.module_ns[name], args); this.modules.push(module); return module; } /// Remove a module. /** * \param module The module to remove, as returned by the addModule method. */ webmap.Extendable.prototype.removeModule = function(module) { var i = this.modules.indexOf(modules) if (i != -1) { if (module.destroy) module.destroy(); this.modules.splice(i, 1); } } /// Notify all modules by calling a member function, if it exists. /** * \param handler The name of the member function to call. * \param ... Any arguments to pass to the member function. */ webmap.Extendable.prototype.notifyModules = function(handler /*, ... */) { var args = Array.prototype.slice.call(arguments, 1); for (var i = 0; i < this.modules.length; ++i) { var module = this.modules[i]; if (module[handler]) module[handler].apply(module, args); } } /// Test if two vectors have the same X, Y and Z components. Any other difference is ignored. /** * \param a Vector A. * \param b Vector B. * \return True if vector A and B have the same X, Y and Z components. */ webmap.vectorEqual = function(a, b) { return a.x === b.x && a.y === b.y && a.z === b.z; } /// Test if two quaternions have the same X, Y, Z and W components. Any other difference is ignored. /** * \param a Quaternion A. * \param b Quaternion B. * \return True if vector A and B have the same X, Y, Z and W componentss. */ webmap.quaternionEqual = function(a, b) { return a.x === b.x && a.y === b.y && a.z === b.z && a.w === b.w; } /// Get the absolute rotation around the Z axis of an orientation quaternion. /** * \param Q A unit quaternion representing an orientation. * \return The angle in degrees. * * This function applies the rotation to the vector (1, 0, 0), * projects it on the XY plane and takes the angle with the X axis. */ webmap.quaternionZ = function(q) { var x = q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z; var y = 2*q.x*q.y + 2*q.w*q.z; return Math.atan2(y, x) / Math.PI * 180.0; } /// Construct an object from a constructor and an array of arguments. /** * \param constructor The constructor. * \param args The arguments as an array. */ webmap.construct = function(constructor, args) { function F() { return constructor.apply(this, args); } F.prototype = constructor.prototype; return new F(); }