Subversion Repositories Projects

Rev

Blame | Last modification | View Log | RSS feed

L.Proj = {};

L.Proj._isProj4Proj = function(a) {
        return typeof a['projName'] !== 'undefined';
}

L.Proj.Projection = L.Class.extend({
        initialize: function(a, def) {
                if (L.Proj._isProj4Proj(a)) {
                        this._proj = a;
                } else {
                        var code = a;
                        Proj4js.defs[code] = def;
                        this._proj = new Proj4js.Proj(code);
                }
        },

        project: function (latlng) {
                var point = new L.Point(latlng.lng, latlng.lat);
                return Proj4js.transform(Proj4js.WGS84, this._proj, point);
        },

        unproject: function (point, unbounded) {
                var point2 = Proj4js.transform(this._proj, Proj4js.WGS84, point.clone());
                return new L.LatLng(point2.y, point2.x, unbounded);
        }
});

L.Proj.CRS = L.Class.extend({
        includes: L.CRS,

        options: {
                transformation: new L.Transformation(1, 0, -1, 0)
        },

        initialize: function(a, b, c) {
                var code, proj, def, options;

                if (L.Proj._isProj4Proj(a)) {
                        proj = a;
                        code = proj.srsCode;
                        options = b || {};

                        this.projection = new L.Proj.Projection(proj);
                } else {
                        code = a;
                        def = b;
                        options = c || {};
                        this.projection = new L.Proj.Projection(code, def);
                }

                L.Util.setOptions(this, options);
                this.code = code;
                this.transformation = this.options.transformation;

                if (this.options.origin) {
                        this.transformation =
                                new L.Transformation(1, -this.options.origin[0],
                                        -1, this.options.origin[1]);
                }

                if (this.options.scales) {
                        this.scale = function(zoom) {
                                return this.options.scales[zoom];
                        }
                } else if (this.options.resolutions) {
                        this.scale = function(zoom) {
                                return 1 / this.options.resolutions[zoom];
                        }
                }
        }
});

L.Proj.CRS.TMS = L.Proj.CRS.extend({
        initialize: function(a, b, c, d) {
                if (L.Proj._isProj4Proj(a)) {
                        var proj = a,
                                projectedBounds = b,
                                options = c || {};
                        options.origin = [projectedBounds[0], projectedBounds[3]];
                        L.Proj.CRS.prototype.initialize(proj, options);
                } else {
                        var code = a,
                                def = b,
                                projectedBounds = c,
                                options = d || {};
                        options.origin = [projectedBounds[0], projectedBounds[3]];
                        L.Proj.CRS.prototype.initialize(code, def, options);
                }

                this.projectedBounds = projectedBounds;
        }
});

L.Proj.TileLayer = {};

L.Proj.TileLayer.TMS = L.TileLayer.extend({
        options: {
                tms: true,
                continuousWorld: true
        },

        initialize: function(urlTemplate, crs, options) {
                if (!(crs instanceof L.Proj.CRS.TMS)) {
                        throw new Error("CRS is not L.Proj.CRS.TMS.");
                }

                L.TileLayer.prototype.initialize.call(this, urlTemplate, options);
                this.crs = crs;

                // Verify grid alignment
                for (var i = this.options.minZoom; i < this.options.maxZoom; i++) {
                        var gridHeight = (this.crs.projectedBounds[3] - this.crs.projectedBounds[1]) /
                                this._projectedTileSize(i);
                        if (Math.abs(gridHeight - Math.round(gridHeight)) > 1e-3) {
                                throw new Error("Projected bounds does not match grid at zoom " + i);
                        }
                }
        },

        getTileUrl: function(tilePoint) {
                var gridHeight =
                        Math.round((this.crs.projectedBounds[3] - this.crs.projectedBounds[1]) /
                        this._projectedTileSize(this._map.getZoom()));

                // TODO: relies on some of TileLayer's internals
                return L.Util.template(this._url, L.Util.extend({
                        s: this._getSubdomain(tilePoint),
                        z: this._getZoomForUrl(),
                        x: tilePoint.x,
                        y: gridHeight - tilePoint.y - 1
                }, this.options));
        },

        _projectedTileSize: function(zoom) {
                return (this.options.tileSize / this.crs.scale(zoom));
        }
});

if (typeof module !== 'undefined') module.exports = L.Proj;

if (typeof L !== 'undefined' && typeof L.CRS !== 'undefined') {
        // This is left here for backwards compatibility
        L.CRS.proj4js = (function () {
                return function (code, def, transformation, options) {
                        options = options || {};
                        if (transformation) options.transformation = transformation;

                        return new L.Proj.CRS(code, def, options);
                };
        }());
}