1 /*global foodev, eniro*/
  2 eniro.Package('maps');
  3 
  4 /**
  5  * @requires eniro/maps/Srs.js
  6  * @requires eniro/maps/Point.js
  7  */
  8 eniro.maps.Class('Coordinate', /** @lends eniro.maps.Coordinate.prototype */ {
  9 
 10     Extends: eniro.maps.Point,
 11 
 12     /** @private */
 13     srs: null,
 14 
 15     /**
 16      * A (typed) coordinate which is a variant of point. The type is the spatial
 17      * reference system used.
 18      *
 19      * <p>
 20      * Class is considered a value type.
 21      *
 22      * @param {number}
 23      *            x The x (east-west) value.
 24      * @param {number}
 25      *            y The y (north-south) value.
 26      * @param {eniro.maps.Srs}
 27      *            srs The spatial reference system.
 28      * @constructs
 29      * @extends eniro.maps.Point
 30      */
 31     initialize: function (x, y, srs) {
 32         eniro.maps.Point.prototype.initialize.apply(this, [
 33             x, y
 34         ]);
 35         foodev.assert(srs, 'srs', eniro.maps.Srs);
 36         this.srs = srs;
 37     },
 38 
 39     /**
 40      * Returns she spatial reference system.
 41      *
 42      * @return {eniro.maps.Srs} The spatial reference system.
 43      */
 44     getSrs: function () {
 45         return this.srs;
 46     },
 47 
 48     /**
 49      * Compare this coordinate with the given one and tell if they are
 50      * approximately equal using an optional tolerance. If the tolerance isn't
 51      * specified it defaults to 5 meters.
 52      *
 53      * @param {eniro.maps.Coordinate}
 54      *            other The coordinate to compare to.
 55      * @param {number}
 56      *            [tol=5] The approximation tolerance in meters.
 57      *
 58      * @return true if this coordinate roughly equals the given one within the
 59      *         tolerance.
 60      */
 61     approxEquals: function (other, tol) {
 62         foodev.assert(other, 'other', eniro.maps.Coordinate);
 63         if (this.getSrs() !== other.getSrs()) {
 64             throw new Error('Srs mismatch');
 65         }
 66         if (!tol) {
 67             tol = 5;
 68         }
 69         return this.srs.approxEquals(this.getX(), this.getY(), other.getX(), other.getY(), tol);
 70     },
 71 
 72     /**
 73      * Transforms this coordinate to the spatial reference system given.
 74      *
 75      * @param {eniro.maps.Srs}
 76      *            srs The target srs to transform to.
 77      *
 78      * @return {eniro.maps.Coordinate} If srs differ, a new Coordinate otherwise
 79      *         this.
 80      */
 81     transform: function (srs) {
 82         foodev.assert(srs, 'srs', eniro.maps.Srs);
 83         if (this.srs.equals(srs)) {
 84             return this;
 85         } else {
 86             var $result = this.$transform(srs);
 87             foodev.assert($result, '$result', eniro.maps.Coordinate);
 88             return $result;
 89         }
 90     }
 91 
 92 });
 93 
 94 eniro.maps.Coordinate.prototype.toString = function () {
 95     return this.getClassName() + '(' + this.getX() + ',' + this.getY() + ':' + this.srs.getName() + ')';
 96 };
 97 
 98 eniro.maps.Coordinate.prototype.$transform = function (srs) {
 99     eniro.$IMPLEMENT.apply(this, arguments);
100 };
101 
102 /**
103  * Compare this instance with another instance.
104  *
105  * @param {eniro.maps.Coordinate}
106  *            other The instance to compare this instance to.
107  *
108  * @return {boolean} true If this instance is equal to the given one.
109  * @function
110  */
111 eniro.maps.Coordinate.prototype.equals = foodev.makeEquals(eniro.maps.Coordinate);
112