

var pi = Math.PI / 180;
function toRadian(d) {
  return d * pi;
}
function wrap(n, min, max) {
  if (n === max || n === min) {
    return n;
  }

  var d = max - min;
  var w = ((n - min) % d + d) % d + min;
  return w;
}
function isString(obj) {
  if (isNil(obj)) {
    return false;
  }

  return typeof obj === 'string' || obj.constructor !== null && obj.constructor === String;
}


function isInteger(n) {
  return (n | 0) === n;
}


var hasOwnProperty = Object.prototype.hasOwnProperty;
function hasOwn(obj, key) {
  return hasOwnProperty.call(obj, key);
}

function extend(dest) {
  for (var i = 1; i < arguments.length; i++) {
    var src = arguments[i];

    for (var k in src) {
      dest[k] = src[k];
    }
  }

  return dest;
}

function parseJSON(str) {
  if (!str || !isString(str)) {
    return str;
  }

  return JSON.parse(str);
}

function pushIn(dest) {
  for (var i = 1; i < arguments.length; i++) {
    var src = arguments[i];

    if (src) {
      for (var ii = 0, ll = src.length; ii < ll; ii++) {
        dest.push(src[ii]);
      }
    }
  }

  return dest.length;
}

function isNil(obj) {
  return obj == null;
}

function isArrayHasData(obj) {
  return Array.isArray(obj) && obj.length > 0;
}

function _inheritsLoose(subClass, superClass) {
  subClass.prototype = superClass ? Object.create(superClass.prototype) : {};
  subClass.prototype.constructor = subClass;
  subClass.__proto__ = superClass;
}


function isNumber(val) {
  return typeof val === 'number' && !isNaN(val);
}
function isObject(obj) {
  return typeof obj === 'object' && !!obj;
}

function isFunction(obj) {
  if (isNil(obj)) {
    return false;
  }

  return typeof obj === 'function' || obj.constructor !== null && obj.constructor === Function;
}

var Common = {
  project: function project() { },
  unproject: function unproject() { },
  projectCoords: function projectCoords(coordinates) {
    var _this = this;

    if (!coordinates) {
      return [];
    }

    if (!Array.isArray(coordinates)) {
      return this.project(coordinates);
    }

    if (coordinates.length === 0) {
      return [];
    }

    if (!this.isSphere()) {
      return forEachCoord(coordinates, this.project, this);
    }

    if (Array.isArray(coordinates[0])) {
      return coordinates.map(function (coords) {
        return _this.projectCoords(coords);
      });
    } else {
      var circum = this.getCircum();
      var extent = this.getSphereExtent(),
        sx = extent.sx,
        sy = extent.sy;
      var wrapX, wrapY;
      var pre = coordinates[0],
        current,
        dx,
        dy,
        p;
      var prj = [this.project(pre)];

      for (var i = 1, l = coordinates.length; i < l; i++) {
        current = coordinates[i];
        dx = current.x - pre.x;
        dy = current.y - pre.y;
        p = this.project(current);

        if (Math.abs(dx) > 180) {
          if (wrapX === undefined) {
            wrapX = current.x < pre.x;
          }

          if (wrapX) {
            p._add(-circum.x * sign(dx) * sx, 0);

            current._add(-360 * sign(dx), 0);
          }
        }

        if (Math.abs(dy) > 90) {
          if (wrapY === undefined) {
            wrapY = current.y < pre.y;
          }

          if (wrapY) {
            p._add(0, -circum.y * sign(dy) * sy);

            current._add(0, -180 * sign(dy));
          }
        }

        pre = current;
        prj.push(p);
      }

      return prj;
    }
  },
  unprojectCoords: function unprojectCoords(projCoords) {
    if (!projCoords) {
      return [];
    }

    if (!Array.isArray(projCoords)) {
      return this.unproject(projCoords);
    }

    return forEachCoord(projCoords, this.unproject, this);
  },
  isSphere: function isSphere() {
    return !!this.sphere;
  },
  isOutSphere: function isOutSphere(pcoord) {
    if (!this.isSphere()) {
      return false;
    }

    var extent = this.getSphereExtent();
    return !extent.contains(pcoord);
  },
  wrapCoord: function wrapCoord(pcoord) {
    if (!this.isSphere()) {
      return pcoord;
    }

    var extent = this.getSphereExtent();
    var wrapped = new Coordinate(pcoord);

    if (!extent.contains(wrapped)) {
      wrapped.x = wrap(pcoord.x, extent.xmin, extent.xmax);
      wrapped.y = wrap(pcoord.y, extent.ymin, extent.ymax);
    }

    return wrapped;
  },
  getCircum: function getCircum() {
    if (!this.circum && this.isSphere()) {
      var extent = this.getSphereExtent();
      this.circum = {
        x: extent.getWidth(),
        y: extent.getHeight()
      };
    }

    return this.circum;
  },
  getSphereExtent: function getSphereExtent() {
    if (!this.extent && this.isSphere()) {
      var max = this.project(new Coordinate(180, 90)),
        min = this.project(new Coordinate(-180, -90));
      this.extent = new Extent(min, max, this);
      this.extent.sx = max.x > min.x ? 1 : -1;
      this.extent.sy = max.y > min.y ? 1 : -1;
    }

    return this.extent;
  }
};

var Common$1 = {
  measureLength: function measureLength(c1, c2) {
    if (!Array.isArray(c1)) {
      return this.measureLenBetween(c1, c2);
    }

    var len = 0;

    for (var i = 0, l = c1.length; i < l - 1; i++) {
      len += this.measureLenBetween(c1[i], c1[i + 1]);
    }

    return len;
  }
};



var types = ['Unknown', 'Point', 'LineString', 'Polygon', 'MultiPoint', 'MultiLineString', 'MultiPolygon', 'GeometryCollection'];
function createFilter(filter) {
  return new Function('f', "var p = (f && f.properties || {}); return " + compile(filter));
}

function compile(filter) {
  if (!filter) return 'true';
  var op = filter[0];
  if (filter.length <= 1) return op === 'any' ? 'false' : 'true';
  var str = op === '==' ? compileComparisonOp(filter[1], filter[2], '===', false) : op === '!=' ? compileComparisonOp(filter[1], filter[2], '!==', false) : op === '<' || op === '>' || op === '<=' || op === '>=' ? compileComparisonOp(filter[1], filter[2], op, true) : op === 'any' ? compileLogicalOp(filter.slice(1), '||') : op === 'all' ? compileLogicalOp(filter.slice(1), '&&') : op === 'none' ? compileNegation(compileLogicalOp(filter.slice(1), '||')) : op === 'in' ? compileInOp(filter[1], filter.slice(2)) : op === '!in' ? compileNegation(compileInOp(filter[1], filter.slice(2))) : op === 'has' ? compileHasOp(filter[1]) : op === '!has' ? compileNegation(compileHasOp(filter[1])) : 'true';
  return "(" + str + ")";
}

function compilePropertyReference(property) {
  return property[0] === '$' ? 'f.' + property.substring(1) : 'p[' + JSON.stringify(property) + ']';
}

function compileComparisonOp(property, value, op, checkType) {
  var left = compilePropertyReference(property);
  var right = property === '$type' ? types.indexOf(value) : JSON.stringify(value);
  return (checkType ? "typeof " + left + "=== typeof " + right + "&&" : '') + left + op + right;
}

function getFilterFeature(geometry) {
  var json = geometry._toJSON(),
    g = json['feature'];

  g['type'] = types.indexOf(g['geometry']['type']);
  g['subType'] = json['subType'];
  return g;
}


var Sphere = function () {
  function Sphere(radius) {
    this.radius = radius;
  }

  var _proto = Sphere.prototype;

  _proto.measureLenBetween = function measureLenBetween(c1, c2) {
    if (!c1 || !c2) {
      return 0;
    }

    var b = toRadian(c1.y);
    var d = toRadian(c2.y),
      e = b - d,
      f = toRadian(c1.x) - toRadian(c2.x);
    b = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(e / 2), 2) + Math.cos(b) * Math.cos(d) * Math.pow(Math.sin(f / 2), 2)));
    b *= this.radius;
    return Math.round(b * 1E5) / 1E5;
  };

  _proto.measureArea = function measureArea(coordinates) {
    var a = toRadian(this.radius);
    var b = 0,
      c = coordinates,
      d = c.length;

    if (d < 3) {
      return 0;
    }

    var i;

    for (i = 0; i < d - 1; i++) {
      var e = c[i],
        f = c[i + 1];
      b += e.x * a * Math.cos(toRadian(e.y)) * f.y * a - f.x * a * Math.cos(toRadian(f.y)) * e.y * a;
    }

    d = c[i];
    c = c[0];
    b += d.x * a * Math.cos(toRadian(d.y)) * c.y * a - c.x * a * Math.cos(toRadian(c.y)) * d.y * a;
    return 0.5 * Math.abs(b);
  };

  _proto.locate = function locate(c, xDist, yDist) {
    c = new Coordinate(c.x, c.y);
    return this._locate(c, xDist, yDist);
  };

  _proto._locate = function _locate(c, xDist, yDist) {
    if (!c) {
      return null;
    }

    if (!xDist) {
      xDist = 0;
    }

    if (!yDist) {
      yDist = 0;
    }

    if (!xDist && !yDist) {
      return c;
    }

    var x, y;
    var ry = toRadian(c.y);

    if (yDist !== 0) {
      var dy = Math.abs(yDist);
      var sy = Math.sin(dy / (2 * this.radius)) * 2;
      ry = ry + sy * (yDist > 0 ? 1 : -1);
      y = wrap(ry * 180 / Math.PI, -90, 90);
    } else {
      y = c.y;
    }

    if (xDist !== 0) {
      var dx = Math.abs(xDist);
      var rx = toRadian(c.x);
      var sx = 2 * Math.sqrt(Math.pow(Math.sin(dx / (2 * this.radius)), 2) / Math.pow(Math.cos(ry), 2));
      rx = rx + sx * (xDist > 0 ? 1 : -1);
      x = wrap(rx * 180 / Math.PI, -180, 180);
    } else {
      x = c.x;
    }

    c.x = x;
    c.y = y;
    return c;
  };

  _proto.rotate = function rotate(c, pivot, angle) {
    c = new Coordinate(c);
    return this._rotate(c, pivot, angle);
  };

  _proto._rotate = function _rotate(c, pivot, angle) {
    var initialAngle = rhumbBearing(pivot, c);
    var finalAngle = initialAngle - angle;
    var distance = this.measureLenBetween(pivot, c);
    c.x = pivot.x;
    c.y = pivot.y;
    return calculateRhumbDestination(c, distance, finalAngle, this.radius);
  };

  return Sphere;
}();

var WGS84Sphere = extend({
  'measure': 'EPSG:4326',
  sphere: new Sphere(6378137),
  measureLenBetween: function measureLenBetween() {
    return this.sphere.measureLenBetween.apply(this.sphere, arguments);
  },
  measureArea: function measureArea() {
    return this.sphere.measureArea.apply(this.sphere, arguments);
  },
  _locate: function _locate() {
    return this.sphere._locate.apply(this.sphere, arguments);
  },
  locate: function locate() {
    return this.sphere.locate.apply(this.sphere, arguments);
  },
  _rotate: function _rotate() {
    return this.sphere._rotate.apply(this.sphere, arguments);
  },
  rotate: function rotate() {
    return this.sphere.rotate.apply(this.sphere, arguments);
  }
}, Common$1);
var BaiduSphere = extend({
  'measure': 'BAIDU',
  sphere: new Sphere(6370996.81),
  measureLenBetween: function measureLenBetween() {
    return this.sphere.measureLenBetween.apply(this.sphere, arguments);
  },
  measureArea: function measureArea() {
    return this.sphere.measureArea.apply(this.sphere, arguments);
  },
  _locate: function _locate() {
    return this.sphere._locate.apply(this.sphere, arguments);
  },
  locate: function locate() {
    return this.sphere.locate.apply(this.sphere, arguments);
  },
  _rotate: function _rotate() {
    return this.sphere._rotate.apply(this.sphere, arguments);
  },
  rotate: function rotate() {
    return this.sphere.rotate.apply(this.sphere, arguments);
  }
}, Common$1);

var DEFAULT = WGS84Sphere;

var EPSG3857 = extend({}, Common, {
  code: 'EPSG:3857',
  rad: Math.PI / 180,
  metersPerDegree: 6378137 * Math.PI / 180,
  maxLatitude: 85.0511287798,
  project: function project(lnglat) {
    var rad = this.rad,
      metersPerDegree = this.metersPerDegree,
      max = this.maxLatitude;
    var lng = lnglat.x,
      lat = Math.max(Math.min(max, lnglat.y), -max);
    var c;

    if (lat === 0) {
      c = 0;
    } else {
      c = Math.log(Math.tan((90 + lat) * rad / 2)) / rad;
    }

    return new Coordinate(lng * metersPerDegree, c * metersPerDegree);
  },
  unproject: function unproject(pLnglat) {
    var x = pLnglat.x,
      y = pLnglat.y;
    var rad = this.rad,
      metersPerDegree = this.metersPerDegree;
    var c;

    if (y === 0) {
      c = 0;
    } else {
      c = y / metersPerDegree;
      c = (2 * Math.atan(Math.exp(c * rad)) - Math.PI / 2) / rad;
    }

    return new Coordinate(wrap(x / metersPerDegree, -180, 180), wrap(c, -this.maxLatitude, this.maxLatitude));
  }
}, WGS84Sphere);

var PROJ4326 = extend({}, Common, {
  code: 'EPSG:4326',
  project: function project(p) {
    return new Coordinate(p);
  },
  unproject: function unproject(p) {
    return new Coordinate(p);
  }
}, WGS84Sphere);

var DEFAULT$1 = EPSG3857;

var Projection_EPSG4490 = extend({}, PROJ4326, {
  code: 'EPSG:4490'
});

var Projection_Baidu = extend({}, Common, {
  code: 'BAIDU',
  project: function project(p) {
    return this.convertLL2MC(p);
  },
  unproject: function unproject(p) {
    return this.convertMC2LL(p);
  }
}, BaiduSphere, {
    EARTHRADIUS: 6370996.81,
    MCBAND: [12890594.86, 8362377.87, 5591021, 3481989.83, 1678043.12, 0],
    LLBAND: [75, 60, 45, 30, 15, 0],
    MC2LL: [[1.410526172116255e-8, 0.00000898305509648872, -1.9939833816331, 200.9824383106796, -187.2403703815547, 91.6087516669843, -23.38765649603339, 2.57121317296198, -0.03801003308653, 17337981.2], [-7.435856389565537e-9, 0.000008983055097726239, -0.78625201886289, 96.32687599759846, -1.85204757529826, -59.36935905485877, 47.40033549296737, -16.50741931063887, 2.28786674699375, 10260144.86], [-3.030883460898826e-8, 0.00000898305509983578, 0.30071316287616, 59.74293618442277, 7.357984074871, -25.38371002664745, 13.45380521110908, -3.29883767235584, 0.32710905363475, 6856817.37], [-1.981981304930552e-8, 0.000008983055099779535, 0.03278182852591, 40.31678527705744, 0.65659298677277, -4.44255534477492, 0.85341911805263, 0.12923347998204, -0.04625736007561, 4482777.06], [3.09191371068437e-9, 0.000008983055096812155, 0.00006995724062, 23.10934304144901, -0.00023663490511, -0.6321817810242, -0.00663494467273, 0.03430082397953, -0.00466043876332, 2555164.4], [2.890871144776878e-9, 0.000008983055095805407, -3.068298e-8, 7.47137025468032, -0.00000353937994, -0.02145144861037, -0.00001234426596, 0.00010322952773, -0.00000323890364, 826088.5]],
    LL2MC: [[-0.0015702102444, 111320.7020616939, 1704480524535203, -10338987376042340, 26112667856603880, -35149669176653700, 26595700718403920, -10725012454188240, 1800819912950474, 82.5], [0.0008277824516172526, 111320.7020463578, 647795574.6671607, -4082003173.641316, 10774905663.51142, -15171875531.51559, 12053065338.62167, -5124939663.577472, 913311935.9512032, 67.5], [0.00337398766765, 111320.7020202162, 4481351.045890365, -23393751.19931662, 79682215.47186455, -115964993.2797253, 97236711.15602145, -43661946.33752821, 8477230.501135234, 52.5], [0.00220636496208, 111320.7020209128, 51751.86112841131, 3796837.749470245, 992013.7397791013, -1221952.21711287, 1340652.697009075, -620943.6990984312, 144416.9293806241, 37.5], [-0.0003441963504368392, 111320.7020576856, 278.2353980772752, 2485758.690035394, 6070.750963243378, 54821.18345352118, 9540.606633304236, -2710.55326746645, 1405.483844121726, 22.5], [-0.0003218135878613132, 111320.7020701615, 0.00369383431289, 823725.6402795718, 0.46104986909093, 2351.343141331292, 1.58060784298199, 8.77738589078284, 0.37238884252424, 7.45]],
    convertMC2LL: function convertMC2LL(cB) {
      var cC = {
        x: Math.abs(cB.x),
        y: Math.abs(cB.y)
      };
      var cE;

      for (var cD = 0, len = this.MCBAND.length; cD < len; cD++) {
        if (cC.y >= this.MCBAND[cD]) {
          cE = this.MC2LL[cD];
          break;
        }
      }

      var T = this.convertor(cB, cE);
      var result = new Coordinate(T.x, T.y);
      return result;
    },
    convertLL2MC: function convertLL2MC(T) {
      var cD, cC, len;
      T.x = this.getLoop(T.x, -180, 180);
      T.y = this.getRange(T.y, -74, 74);
      var cB = new Coordinate(T.x, T.y);

      for (cC = 0, len = this.LLBAND.length; cC < len; cC++) {
        if (cB.y >= this.LLBAND[cC]) {
          cD = this.LL2MC[cC];
          break;
        }
      }

      if (!cD) {
        for (cC = this.LLBAND.length - 1; cC >= 0; cC--) {
          if (cB.y <= -this.LLBAND[cC]) {
            cD = this.LL2MC[cC];
            break;
          }
        }
      }

      var cE = this.convertor(T, cD);
      var result = new Coordinate(cE.x, cE.y);
      return result;
    },
    convertor: function convertor(cC, cD) {
      if (!cC || !cD) {
        return null;
      }

      var T = cD[0] + cD[1] * Math.abs(cC.x);
      var cB = Math.abs(cC.y) / cD[9];
      var cE = cD[2] + cD[3] * cB + cD[4] * cB * cB + cD[5] * cB * cB * cB + cD[6] * cB * cB * cB * cB + cD[7] * cB * cB * cB * cB * cB + cD[8] * cB * cB * cB * cB * cB * cB;
      T *= cC.x < 0 ? -1 : 1;
      cE *= cC.y < 0 ? -1 : 1;
      return new Coordinate(T, cE);
    },
    toRadians: function toRadians(T) {
      return Math.PI * T / 180;
    },
    toDegrees: function toDegrees(T) {
      return 180 * T / Math.PI;
    },
    getRange: function getRange(cC, cB, T) {
      if (cB != null) {
        cC = Math.max(cC, cB);
      }

      if (T != null) {
        cC = Math.min(cC, T);
      }

      return cC;
    },
    getLoop: function getLoop(cC, cB, T) {
      while (cC > T) {
        cC -= T - cB;
      }

      while (cC < cB) {
        cC += T - cB;
      }

      return cC;
    }
  });

var Projection_IDENTITY = extend({}, Common, {
  code: 'IDENTITY',
  project: function project(p) {
    return p.copy();
  },
  unproject: function unproject(p) {
    return p.copy();
  }
}, Identity);

var projections = /*#__PURE__*/Object.freeze({
  EPSG3857: EPSG3857,
  DEFAULT: DEFAULT$1,
  EPSG4326: PROJ4326,
  EPSG4490: Projection_EPSG4490,
  BAIDU: Projection_Baidu,
  IDENTITY: Projection_IDENTITY,
  Common: Common
});

var SpatialReference = function () {
  function SpatialReference(options) {
    if (options === void 0) {
      options = {};
    }

    this.options = options;

    this._initSpatialRef();
  }

  SpatialReference.getProjectionInstance = function getProjectionInstance(prjName) {
    if (!prjName) {
      return null;
    }

    if (isObject(prjName)) {
      return prjName;
    }

    prjName = (prjName + '').toLowerCase();

    for (var p in projections) {
      if (hasOwn(projections, p)) {
        var code = projections[p]['code'];

        if (code && code.toLowerCase() === prjName) {
          return projections[p];
        }
      }
    }

    return null;
  };

  SpatialReference.equals = function equals(sp1, sp2) {
    if (!sp1 && !sp2) {
      return true;
    } else if (!sp1 || !sp2) {
      return false;
    }

    if (sp1.projection !== sp2.projection) {
      return false;
    }

    var f1 = sp1.fullExtent,
      f2 = sp2.fullExtent;

    if (f1 && f2) {
      if (f1.top !== f2.top || f1.bottom !== f2.bottom || f1.left !== f2.left || f1.right !== f2.right) {
        return false;
      }
    }

    var r1 = sp1.resolutions,
      r2 = sp2.resolutions;

    if (r1 && r2) {
      if (r1.length !== r2.length) {
        return false;
      }

      for (var i = 0; i < r1.length; i++) {
        if (r1[i] !== r2[i]) {
          return false;
        }
      }
    }

    return true;
  };

  var _proto = SpatialReference.prototype;

  _proto._initSpatialRef = function _initSpatialRef() {
    var projection = this.options['projection'];

    if (projection) {
      projection = SpatialReference.getProjectionInstance(projection);
    } else {
      projection = DEFAULT$1;
    }

    if (!projection) {
      throw new Error('must provide a valid projection in map\'s spatial reference.');
    }

    projection = extend({}, Common, projection);

    if (!projection.measureLength) {
      extend(projection, Measurer.DEFAULT);
    }

    this._projection = projection;
    var defaultSpatialRef,
      resolutions = this.options['resolutions'];

    if (!resolutions) {
      if (projection['code']) {
        defaultSpatialRef = DefaultSpatialRef[projection['code']];

        if (defaultSpatialRef) {
          resolutions = defaultSpatialRef['resolutions'];
        }
      }

      if (!resolutions) {
        throw new Error('must provide valid resolutions in map\'s spatial reference.');
      }
    }

    this._resolutions = resolutions;
    var fullExtent = this.options['fullExtent'];

    if (!fullExtent) {
      if (projection['code']) {
        defaultSpatialRef = DefaultSpatialRef[projection['code']];

        if (defaultSpatialRef) {
          fullExtent = defaultSpatialRef['fullExtent'];
        }
      }

      if (!fullExtent) {
        throw new Error('must provide a valid fullExtent in map\'s spatial reference.');
      }
    }

    if (!isNil(fullExtent['left'])) {
      this._fullExtent = new Extent(new Coordinate(fullExtent['left'], fullExtent['top']), new Coordinate(fullExtent['right'], fullExtent['bottom']));
    } else {
      this._fullExtent = new Extent(fullExtent);
      fullExtent['left'] = fullExtent['xmin'];
      fullExtent['right'] = fullExtent['xmax'];
      fullExtent['top'] = fullExtent['ymax'];
      fullExtent['bottom'] = fullExtent['ymin'];
    }

    if (isNil(fullExtent['top']) || isNil(fullExtent['bottom']) || isNil(fullExtent['left']) || isNil(fullExtent['right'])) {
      throw new Error('must provide valid top/bottom/left/right in fullExtent.');
    }

    extend(this._fullExtent, fullExtent);
    this._projection.fullExtent = fullExtent;
    var a = fullExtent['right'] >= fullExtent['left'] ? 1 : -1,
      b = fullExtent['top'] >= fullExtent['bottom'] ? -1 : 1;
    this._transformation = new Transformation([a, b, 0, 0]);
  };

  _proto.getResolutions = function getResolutions() {
    return this._resolutions || [];
  };

  _proto.getResolution = function getResolution(zoom) {
    var z = zoom | 0;

    if (z < 0) {
      z = 0;
    } else if (z > this._resolutions.length - 1) {
      z = this._resolutions.length - 1;
    }

    var res = this._resolutions[z];

    if (!isInteger(zoom) && z !== this._resolutions.length - 1) {
      var next = this._resolutions[z + 1];
      return res + (next - res) * (zoom - z);
    }

    return res;
  };

  _proto.getProjection = function getProjection() {
    return this._projection;
  };

  _proto.getFullExtent = function getFullExtent() {
    return this._fullExtent;
  };

  _proto.getTransformation = function getTransformation() {
    return this._transformation;
  };

  _proto.getMinZoom = function getMinZoom() {
    for (var i = 0; i < this._resolutions.length; i++) {
      if (!isNil(this._resolutions[i])) {
        return i;
      }
    }

    return 0;
  };

  _proto.getMaxZoom = function getMaxZoom() {
    for (var i = this._resolutions.length - 1; i >= 0; i--) {
      if (!isNil(this._resolutions[i])) {
        return i;
      }
    }

    return this._resolutions.length - 1;
  };

  _proto.getZoomDirection = function getZoomDirection() {
    return sign(this._resolutions[this.getMinZoom()] - this._resolutions[this.getMaxZoom()]);
  };

  _proto.toJSON = function toJSON() {
    if (!this.json) {
      this.json = {
        'resolutions': this._resolutions,
        'fullExtent': {
          'top': this._fullExtent.top,
          'left': this._fullExtent.left,
          'bottom': this._fullExtent.bottom,
          'right': this._fullExtent.right
        },
        'projection': this._projection.code
      };
    }

    return this.json;
  };

  return SpatialReference;
}();

var Eventable = function Eventable(Base) {
  return function (_Base) {
    _inheritsLoose(_class, _Base);

    function _class() {
      return _Base.apply(this, arguments) || this;
    }

    var _proto = _class.prototype;

    _proto.on = function on$$1(eventsOn, handler, context) {
      if (!eventsOn) {
        return this;
      }

      if (!isString(eventsOn)) {
        return this._switch('on', eventsOn, handler);
      }

      if (!handler) {
        return this;
      }

      if (!this._eventMap) {
        this._eventMap = {};
      }

      var eventTypes = eventsOn.toLowerCase().split(' ');
      var evtType;

      if (!context) {
        context = this;
      }

      var handlerChain;

      for (var ii = 0, ll = eventTypes.length; ii < ll; ii++) {
        evtType = eventTypes[ii];
        handlerChain = this._eventMap[evtType];

        if (!handlerChain) {
          handlerChain = [];
          this._eventMap[evtType] = handlerChain;
        }

        var l = handlerChain.length;

        if (l > 0) {
          for (var i = 0; i < l; i++) {
            if (handler === handlerChain[i].handler && handlerChain[i].context === context) {
              return this;
            }
          }
        }

        handlerChain.push({
          handler: handler,
          context: context
        });
      }

      return this;
    };

    _proto.addEventListener = function addEventListener() {
      return this.on.apply(this, arguments);
    };

    _proto.once = function once(eventTypes, handler, context) {
      if (!isString(eventTypes)) {
        var once = {};

        for (var p in eventTypes) {
          if (eventTypes.hasOwnProperty(p)) {
            once[p] = this._wrapOnceHandler(p, eventTypes[p], context);
          }
        }

        return this._switch('on', once);
      }

      var evetTypes = eventTypes.split(' ');

      for (var i = 0, l = evetTypes.length; i < l; i++) {
        this.on(evetTypes[i], this._wrapOnceHandler(evetTypes[i], handler, context));
      }

      return this;
    };

    _proto.off = function off$$1(eventsOff, handler, context) {
      if (!this._eventMap || !eventsOff) {
        return this;
      }

      if (!isString(eventsOff)) {
        return this._switch('off', eventsOff, handler);
      }

      if (!handler) {
        return this;
      }

      var eventTypes = eventsOff.split(' ');
      var eventType, listeners, wrapKey;

      if (!context) {
        context = this;
      }

      for (var j = 0, jl = eventTypes.length; j < jl; j++) {
        eventType = eventTypes[j].toLowerCase();
        wrapKey = 'Z__' + eventType;
        listeners = this._eventMap[eventType];

        if (!listeners) {
          return this;
        }

        for (var i = listeners.length - 1; i >= 0; i--) {
          var listener = listeners[i];

          if ((handler === listener.handler || handler === listener.handler[wrapKey]) && listener.context === context) {
            delete listener.handler[wrapKey];
            listeners.splice(i, 1);
          }
        }
      }

      return this;
    };

    _proto.removeEventListener = function removeEventListener() {
      return this.off.apply(this, arguments);
    };

    _proto.listens = function listens(eventType, handler, context) {
      if (!this._eventMap || !isString(eventType)) {
        return 0;
      }

      var handlerChain = this._eventMap[eventType.toLowerCase()];

      if (!handlerChain || !handlerChain.length) {
        return 0;
      }

      var count = 0;

      for (var i = 0, len = handlerChain.length; i < len; i++) {
        if (handler) {
          if (handler === handlerChain[i].handler && (isNil(context) || handlerChain[i].context === context)) {
            return 1;
          }
        } else {
          count++;
        }
      }

      return count;
    };

    _proto.copyEventListeners = function copyEventListeners(target) {
      var eventMap = target._eventMap;

      if (!eventMap) {
        return this;
      }

      var handlerChain;

      for (var eventType in eventMap) {
        handlerChain = eventMap[eventType];

        for (var i = 0, len = handlerChain.length; i < len; i++) {
          this.on(eventType, handlerChain[i].handler, handlerChain[i].context);
        }
      }

      return this;
    };

    _proto.fire = function fire() {
      if (this._eventParent) {
        return this._eventParent.fire.apply(this._eventParent, arguments);
      }

      return this._fire.apply(this, arguments);
    };

    _proto._wrapOnceHandler = function _wrapOnceHandler(evtType, handler, context) {
      var me = this;
      var key = 'Z__' + evtType;
      var called = false;

      var fn = function onceHandler() {
        if (called) {
          return;
        }

        delete fn[key];
        called = true;

        if (context) {
          handler.apply(context, arguments);
        } else {
          handler.apply(this, arguments);
        }

        me.off(evtType, onceHandler, this);
      };

      fn[key] = handler;
      return fn;
    };

    _proto._switch = function _switch(to, eventKeys, context) {
      for (var p in eventKeys) {
        if (eventKeys.hasOwnProperty(p)) {
          this[to](p, eventKeys[p], context);
        }
      }

      return this;
    };

    _proto._clearListeners = function _clearListeners(eventType) {
      if (!this._eventMap || !isString(eventType)) {
        return;
      }

      var handlerChain = this._eventMap[eventType.toLowerCase()];

      if (!handlerChain) {
        return;
      }

      this._eventMap[eventType] = null;
    };

    _proto._clearAllListeners = function _clearAllListeners() {
      this._eventMap = null;
    };

    _proto._setEventParent = function _setEventParent(parent) {
      this._eventParent = parent;
      return this;
    };

    _proto._fire = function _fire(eventType, param) {
      if (!this._eventMap) {
        return this;
      }

      var handlerChain = this._eventMap[eventType.toLowerCase()];

      if (!handlerChain) {
        return this;
      }

      if (!param) {
        param = {};
      }

      param['type'] = eventType;
      param['target'] = this;
      var queue = handlerChain.slice(0);
      var context, bubble, passed;

      for (var i = 0, len = queue.length; i < len; i++) {
        if (!queue[i]) {
          continue;
        }

        context = queue[i].context;
        bubble = true;
        passed = extend({}, param);

        if (context) {
          bubble = queue[i].handler.call(context, passed);
        } else {
          bubble = queue[i].handler(passed);
        }

        if (bubble === false) {
          if (param['domEvent']) {
            stopPropagation(param['domEvent']);
          }
        }
      }

      return this;
    };

    return _class;
  }(Base);
};
var Handler = function () {
  function Handler(target) {
    this.target = target;
  }

  var _proto = Handler.prototype;

  _proto.enable = function enable() {
    if (this._enabled) {
      return this;
    }

    this._enabled = true;
    this.addHooks();
    return this;
  };

  _proto.disable = function disable() {
    if (!this._enabled) {
      return this;
    }

    this._enabled = false;
    this.removeHooks();
    return this;
  };

  _proto.enabled = function enabled() {
    return !!this._enabled;
  };

  _proto.remove = function remove() {
    this.disable();
    delete this.target;
    delete this.dom;
  };

  return Handler;
}();

var Handler$1 = Eventable(Handler);

function Handlerable(Base) {
  return function (_Base) {
    _inheritsLoose(_class, _Base);

    function _class() {
      return _Base.apply(this, arguments) || this;
    }

    var _proto = _class.prototype;

    _proto.addHandler = function addHandler(name, handlerClass) {
      if (!handlerClass) {
        return this;
      }

      if (!this._handlers) {
        this._handlers = [];
      }

      if (this[name]) {
        this[name].enable();
        return this;
      }

      var handler = this[name] = new handlerClass(this);

      this._handlers.push(handler);

      if (this.options[name]) {
        handler.enable();
      }

      return this;
    };

    _proto.removeHandler = function removeHandler(name) {
      if (!name) {
        return this;
      }

      var handler = this[name];

      if (handler) {
        var hit = this._handlers.indexOf(handler);

        if (hit >= 0) {
          this._handlers.splice(hit, 1);
        }

        this[name].remove();
        delete this[name];
      }

      return this;
    };

    _proto._clearHandlers = function _clearHandlers() {
      for (var i = 0, len = this._handlers.length; i < len; i++) {
        this._handlers[i].remove();
      }

      this._handlers = [];
    };

    return _class;
  }(Base);
}

var registeredTypes = {};
var JSONAble = (function (Base) {
  return function (_Base) {
    _inheritsLoose(_class, _Base);

    function _class() {
      return _Base.apply(this, arguments) || this;
    }

    _class.registerJSONType = function registerJSONType(type) {
      if (!type) {
        return this;
      }

      registeredTypes[type] = this;
      return this;
    };

    _class.getJSONClass = function getJSONClass(type) {
      if (!type) {
        return null;
      }

      return registeredTypes[type];
    };

    var _proto = _class.prototype;

    _proto.getJSONType = function getJSONType() {
      if (this._jsonType === undefined) {
        var clazz = Object.getPrototypeOf(this).constructor;

        for (var p in registeredTypes) {
          if (registeredTypes[p] === clazz) {
            this._jsonType = p;
            break;
          }
        }
      }

      if (!this._jsonType) {
        throw new Error('Found an unregistered geometry class!');
      }

      return this._jsonType;
    };

    return _class;
  }(Base);
});


var Class = function () {
  function Class(options) {
    if (!this || !this.setOptions) {
      throw new Error('Class instance is being created without "new" operator.');
    }

    this.setOptions(options);
    this.callInitHooks();
  }

  var _proto = Class.prototype;

  _proto.callInitHooks = function callInitHooks() {
    var proto = Object.getPrototypeOf(this);

    this._visitInitHooks(proto);

    return this;
  };

  _proto.setOptions = function setOptions(options) {
    if (!this.hasOwnProperty('options')) {
      this.options = this.options ? Object.create(this.options) : {};
    }

    if (!options) {
      return this;
    }

    for (var i in options) {
      this.options[i] = options[i];
    }

    return this;
  };

  _proto.config = function config(conf) {
    if (!conf) {
      var config = {};

      for (var p in this.options) {
        if (this.options.hasOwnProperty(p)) {
          config[p] = this.options[p];
        }
      }

      return config;
    } else {
      if (arguments.length === 2) {
        var t = {};
        t[conf] = arguments[1];
        conf = t;
      }

      for (var i in conf) {
        this.options[i] = conf[i];

        if (this[i] && this[i] instanceof Handler$1) {
          if (conf[i]) {
            this[i].enable();
          } else {
            this[i].disable();
          }
        }
      }

      this.onConfig(conf);
    }

    return this;
  };

  _proto.onConfig = function onConfig() { };

  _proto._visitInitHooks = function _visitInitHooks(proto) {
    if (this._initHooksCalled) {
      return;
    }

    var parentProto = Object.getPrototypeOf(proto);

    if (parentProto._visitInitHooks) {
      parentProto._visitInitHooks.call(this, parentProto);
    }

    this._initHooksCalled = true;
    var hooks = proto._initHooks;

    if (hooks && hooks !== parentProto._initHooks) {
      for (var i = 0; i < hooks.length; i++) {
        hooks[i].call(this);
      }
    }
  };

  Class.addInitHook = function addInitHook(fn) {
    for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
      args[_key - 1] = arguments[_key];
    }

    var init = typeof fn === 'function' ? fn : function () {
      this[fn].apply(this, args);
    };
    var proto = this.prototype;
    var parentProto = Object.getPrototypeOf(proto);

    if (!proto._initHooks || proto._initHooks === parentProto._initHooks) {
      proto._initHooks = [];
    }

    proto._initHooks.push(init);

    return this;
  };

  Class.include = function include() {
    for (var i = 0; i < arguments.length; i++) {
      extend(this.prototype, i < 0 || arguments.length <= i ? undefined : arguments[i]);
    }

    return this;
  };

  Class.mergeOptions = function mergeOptions(options) {
    var proto = this.prototype;
    var parentProto = Object.getPrototypeOf(proto);

    if (!proto.options || proto.options === parentProto.options) {
      proto.options = proto.options ? Object.create(proto.options) : {};
    }

    extend(proto.options, options);
    return this;
  };

  return Class;
}();

var options$2 = {
  'id': null,
  'visible': true,
  'editable': true,
  'cursor': null,
  'defaultProjection': 'EPSG:4326'
};

var Geometry = function (_JSONAble) {
  _inheritsLoose(Geometry, _JSONAble);

  function Geometry(options) {
    var _this;

    var opts = extend({}, options);
    var symbol = opts['symbol'];
    var properties = opts['properties'];
    var id = opts['id'];
    delete opts['symbol'];
    delete opts['id'];
    delete opts['properties'];
    _this = _JSONAble.call(this, opts) || this;

    if (symbol) {
      _this.setSymbol(symbol);
    }

    if (properties) {
      _this.setProperties(properties);
    }

    if (!isNil(id)) {
      _this.setId(id);
    }

    return _this;
  }

  var _proto = Geometry.prototype;

  _proto.getFirstCoordinate = function getFirstCoordinate() {
    if (this.type === 'GeometryCollection') {
      var geometries = this.getGeometries();

      if (!geometries.length) {
        return null;
      }

      return geometries[0].getFirstCoordinate();
    }

    var coordinates = this.getCoordinates();

    if (!Array.isArray(coordinates)) {
      return coordinates;
    }

    do {
      coordinates = coordinates[0];
    } while (Array.isArray(coordinates) && coordinates.length > 0);

    return coordinates;
  };

  _proto.getLastCoordinate = function getLastCoordinate() {
    if (this.type === 'GeometryCollection') {
      var geometries = this.getGeometries();

      if (!geometries.length) {
        return null;
      }

      return geometries[geometries.length - 1].getLastCoordinate();
    }

    var coordinates = this.getCoordinates();

    if (!Array.isArray(coordinates)) {
      return coordinates;
    }

    do {
      coordinates = coordinates[coordinates.length - 1];
    } while (Array.isArray(coordinates) && coordinates.length > 0);

    return coordinates;
  };

  _proto.addTo = function addTo(layer, fitview) {
    layer.addGeometry(this, fitview);
    return this;
  };

  _proto.getLayer = function getLayer() {
    if (!this._layer) {
      return null;
    }

    return this._layer;
  };

  _proto.getMap = function getMap() {
    if (!this._layer) {
      return null;
    }

    return this._layer.getMap();
  };

  _proto.getId = function getId() {
    return this._id;
  };

  _proto.setId = function setId(id) {
    var oldId = this.getId();
    this._id = id;

    this._fireEvent('idchange', {
      'old': oldId,
      'new': id
    });

    return this;
  };

  _proto.getProperties = function getProperties() {
    if (!this.properties) {
      if (this._getParent()) {
        return this._getParent().getProperties();
      }

      return null;
    }

    return this.properties;
  };

  _proto.setProperties = function setProperties(properties) {
    var old = this.properties;
    this.properties = isObject(properties) ? extend({}, properties) : properties;

    this._repaint();

    this._fireEvent('propertieschange', {
      'old': old,
      'new': properties
    });

    return this;
  };

  _proto.getType = function getType() {
    return this.type;
  };

  _proto.getSymbol = function getSymbol() {
    var s = this._symbol;

    if (s) {
      if (!Array.isArray(s)) {
        return extend({}, s);
      } else {
        return extendSymbol(s);
      }
    }

    return null;
  };

  _proto.setSymbol = function setSymbol(symbol) {
    this._symbol = this._prepareSymbol(symbol);
    this.onSymbolChanged();
    return this;
  };

  _proto.updateSymbol = function updateSymbol(props) {
    if (!props) {
      return this;
    }

    var s = this._getSymbol();

    if (s) {
      s = extendSymbol(s, props);
    } else {
      s = extendSymbol(this._getInternalSymbol(), props);
    }

    return this.setSymbol(s);
  };

  _proto.getCenter = function getCenter() {
    return this._computeCenter(this._getMeasurer());
  };

  _proto.getExtent = function getExtent() {
    var prjExt = this._getPrjExtent();

    if (prjExt) {
      var p = this._getProjection();

      var min = p.unproject(new Coordinate(prjExt['xmin'], prjExt['ymin'])),
        max = p.unproject(new Coordinate(prjExt['xmax'], prjExt['ymax']));
      return new Extent(min, max, this._getProjection());
    } else {
      return this._computeExtent(this._getMeasurer());
    }
  };

  _proto.getContainerExtent = function getContainerExtent() {
    var painter = this._getPainter();

    return painter ? painter.getContainerExtent() : null;
  };

  _proto.getSize = function getSize() {
    var extent = this.getContainerExtent();
    return extent ? extent.getSize() : null;
  };

  _proto.containsPoint = function containsPoint(containerPoint, t) {
    if (!this.getMap()) {
      throw new Error('The geometry is required to be added on a map to perform "containsPoint".');
    }

    if (containerPoint instanceof Coordinate) {
      containerPoint = this.getMap().coordToContainerPoint(containerPoint);
    }

    return this._containsPoint(containerPoint, t);
  };

  _proto._containsPoint = function _containsPoint(containerPoint, t) {
    var painter = this._getPainter();

    if (!painter) {
      return false;
    }

    if (isNil(t) && this._hitTestTolerance) {
      t = this._hitTestTolerance();
    }

    return painter.hitTest(containerPoint, t);
  };

  _proto.show = function show() {
    this.options['visible'] = true;

    if (this.getMap()) {
      var painter = this._getPainter();

      if (painter) {
        painter.show();
      }

      this._fireEvent('show');
    }

    return this;
  };

  _proto.hide = function hide() {
    this.options['visible'] = false;

    if (this.getMap()) {
      this.onHide();

      var painter = this._getPainter();

      if (painter) {
        painter.hide();
      }

      this._fireEvent('hide');
    }

    return this;
  };

  _proto.isVisible = function isVisible() {
    if (!this.options['visible']) {
      return false;
    }

    var symbol = this._getInternalSymbol();

    if (!symbol) {
      return true;
    }

    if (Array.isArray(symbol)) {
      if (!symbol.length) {
        return true;
      }

      for (var i = 0, l = symbol.length; i < l; i++) {
        if (isNil(symbol[i]['opacity']) || symbol[i]['opacity'] > 0) {
          return true;
        }
      }

      return false;
    } else {
      return isNil(symbol['opacity']) || isNumber(symbol['opacity']) && symbol['opacity'] > 0;
    }
  };

  _proto.getZIndex = function getZIndex() {
    return this.options['zIndex'] || 0;
  };

  _proto.setZIndex = function setZIndex(zIndex) {
    var old = this.options['zIndex'];
    this.options['zIndex'] = zIndex;

    this._fireEvent('zindexchange', {
      'old': old,
      'new': zIndex
    });

    return this;
  };

  _proto.setZIndexSilently = function setZIndexSilently(zIndex) {
    this.options['zIndex'] = zIndex;
    return this;
  };

  _proto.bringToFront = function bringToFront() {
    var layer = this.getLayer();

    if (!layer || !layer.getGeoMaxZIndex) {
      return this;
    }

    var topZ = layer.getGeoMaxZIndex();
    this.setZIndex(topZ + 1);
    return this;
  };

  _proto.bringToBack = function bringToBack() {
    var layer = this.getLayer();

    if (!layer || !layer.getGeoMinZIndex) {
      return this;
    }

    var bottomZ = layer.getGeoMinZIndex();
    this.setZIndex(bottomZ - 1);
    return this;
  };

  _proto.translate = function translate(x, y) {
    if (isNil(x)) {
      return this;
    }

    var offset = new Coordinate(x, y);

    if (offset.x === 0 && offset.y === 0) {
      return this;
    }

    var coordinates = this.getCoordinates();

    if (coordinates) {
      if (Array.isArray(coordinates)) {
        var translated = forEachCoord(coordinates, function (coord) {
          return coord.add(offset);
        });
        this.setCoordinates(translated);
      } else {
        this.setCoordinates(coordinates.add(offset));
      }
    }

    return this;
  };

  _proto.flash = function flash$$1(interval, count, cb, context) {
    return flash.call(this, interval, count, cb, context);
  };

  _proto.copy = function copy() {
    var json = this.toJSON();
    var ret = Geometry.fromJSON(json);
    ret.options['visible'] = true;
    return ret;
  };

  _proto.remove = function remove() {
    var layer = this.getLayer();

    if (!layer) {
      return this;
    }

    this._fireEvent('removestart');

    this._unbind();

    this._fireEvent('removeend');

    this._fireEvent('remove');

    return this;
  };

  _proto.toGeoJSONGeometry = function toGeoJSONGeometry() {
    var gJson = this._exportGeoJSONGeometry();

    return gJson;
  };

  _proto.toGeoJSON = function toGeoJSON(opts) {
    if (!opts) {
      opts = {};
    }

    var feature = {
      'type': 'Feature',
      'geometry': null
    };

    if (isNil(opts['geometry']) || opts['geometry']) {
      var geoJSON = this._exportGeoJSONGeometry();

      feature['geometry'] = geoJSON;
    }

    var id = this.getId();

    if (!isNil(id)) {
      feature['id'] = id;
    }

    var properties;

    if (isNil(opts['properties']) || opts['properties']) {
      properties = this._exportProperties();
    }

    feature['properties'] = properties;
    return feature;
  };

  _proto.toJSON = function toJSON(options) {
    if (!options) {
      options = {};
    }

    var json = this._toJSON(options);

    var other = this._exportGraphicOptions(options);

    extend(json, other);
    return json;
  };

  _proto.getLength = function getLength() {
    return this._computeGeodesicLength(this._getMeasurer());
  };

  _proto.getArea = function getArea() {
    return this._computeGeodesicArea(this._getMeasurer());
  };

  _proto.rotate = function rotate(angle, pivot) {
    if (this.type === 'GeometryCollection') {
      var geometries = this.getGeometries();
      geometries.forEach(function (g) {
        return g.rotate(angle, pivot);
      });
      return this;
    }

    if (!pivot) {
      pivot = this.getCenter();
    } else {
      pivot = new Coordinate(pivot);
    }

    var measurer = this._getMeasurer();

    var coordinates = this.getCoordinates();

    if (!Array.isArray(coordinates)) {
      if (pivot.x !== coordinates.x || pivot.y !== coordinates.y) {
        var c = measurer._rotate(coordinates, pivot, angle);

        this.setCoordinates(c);
      }

      return this;
    }

    forEachCoord(coordinates, function (c) {
      return measurer._rotate(c, pivot, angle);
    });
    this.setCoordinates(coordinates);
    return this;
  };

  _proto._getConnectPoints = function _getConnectPoints() {
    return [this.getCenter()];
  };

  _proto._initOptions = function _initOptions(options) {
    var opts = extend({}, options);
    var symbol = opts['symbol'];
    var properties = opts['properties'];
    var id = opts['id'];
    delete opts['symbol'];
    delete opts['id'];
    delete opts['properties'];
    this.setOptions(opts);

    if (symbol) {
      this.setSymbol(symbol);
    }

    if (properties) {
      this.setProperties(properties);
    }

    if (!isNil(id)) {
      this.setId(id);
    }
  };

  _proto._bindLayer = function _bindLayer(layer) {
    if (this.getLayer()) {
      throw new Error('Geometry cannot be added to two or more layers at the same time.');
    }

    this._layer = layer;

    this._clearCache();

    this._clearProjection();
  };

  _proto._prepareSymbol = function _prepareSymbol(symbol) {
    if (Array.isArray(symbol)) {
      var cookedSymbols = [];

      for (var i = 0; i < symbol.length; i++) {
        cookedSymbols.push(convertResourceUrl(this._checkAndCopySymbol(symbol[i])));
      }

      return cookedSymbols;
    } else if (symbol) {
      symbol = this._checkAndCopySymbol(symbol);
      return convertResourceUrl(symbol);
    }

    return null;
  };

  _proto._checkAndCopySymbol = function _checkAndCopySymbol(symbol) {
    var s = {};

    for (var i in symbol) {
      if (NUMERICAL_PROPERTIES[i] && isString(symbol[i])) {
        s[i] = +symbol[i];
      } else {
        s[i] = symbol[i];
      }
    }

    return s;
  };

  _proto._getSymbol = function _getSymbol() {
    return this._symbol;
  };

  _proto._setExternSymbol = function _setExternSymbol(symbol) {
    this._externSymbol = this._prepareSymbol(symbol);
    this.onSymbolChanged();
    return this;
  };

  _proto._getInternalSymbol = function _getInternalSymbol() {
    if (this._symbol) {
      return this._symbol;
    } else if (this._externSymbol) {
      return this._externSymbol;
    } else if (this.options['symbol']) {
      return this.options['symbol'];
    }

    return null;
  };

  _proto._getPrjExtent = function _getPrjExtent() {
    var p = this._getProjection();

    this._verifyProjection();

    if (!this._extent && p) {
      this._extent = this._computePrjExtent(p);
    }

    return this._extent;
  };

  _proto._unbind = function _unbind() {
    var layer = this.getLayer();

    if (!layer) {
      return;
    }

    if (this._animPlayer) {
      this._animPlayer.finish();
    }

    this._clearHandlers();

    this._unbindMenu();

    this._unbindInfoWindow();

    if (this.isEditing()) {
      this.endEdit();
    }

    this._removePainter();

    if (this.onRemove) {
      this.onRemove();
    }

    if (layer.onRemoveGeometry) {
      layer.onRemoveGeometry(this);
    }

    delete this._layer;
    delete this._internalId;
    delete this._extent;
  };

  _proto._getInternalId = function _getInternalId() {
    return this._internalId;
  };

  _proto._setInternalId = function _setInternalId(id) {
    this._internalId = id;
  };

  _proto._getMeasurer = function _getMeasurer() {
    if (this._getProjection()) {
      return this._getProjection();
    }

    return SpatialReference.getProjectionInstance(this.options['defaultProjection']);
  };

  _proto._getProjection = function _getProjection() {
    var map = this.getMap();

    if (map) {
      return map.getProjection();
    }

    return null;
  };

  _proto._verifyProjection = function _verifyProjection() {
    var projection = this._getProjection();

    if (this._projCode && (!projection || this._projCode !== projection.code)) {
      this._clearProjection();
    }

    this._projCode = projection ? projection.code : null;
  };

  _proto._getExternalResources = function _getExternalResources() {
    var symbol = this._getInternalSymbol();

    return getExternalResources(symbol);
  };

  _proto._getPainter = function _getPainter() {
    if (!this._painter && this.getMap()) {
      if (GEOMETRY_COLLECTION_TYPES.indexOf(this.type) !== -1) {
        this._painter = new CollectionPainter(this);
      } else {
        this._painter = new Painter(this);
      }
    }

    return this._painter;
  };

  _proto._removePainter = function _removePainter() {
    if (this._painter) {
      this._painter.remove();
    }

    delete this._painter;
  };

  _proto._paint = function _paint(extent) {
    if (this._painter) {
      this._painter.paint(extent);
    }
  };

  _proto._clearCache = function _clearCache() {
    delete this._extent;
  };

  _proto._clearProjection = function _clearProjection() {
    delete this._extent;
  };

  _proto._repaint = function _repaint() {
    if (this._painter) {
      this._painter.repaint();
    }
  };

  _proto.onHide = function onHide() {
    this.closeMenu();
    this.closeInfoWindow();
  };

  _proto.onShapeChanged = function onShapeChanged() {
    this._clearCache();

    this._repaint();

    this._fireEvent('shapechange');
  };

  _proto.onPositionChanged = function onPositionChanged() {
    this._clearCache();

    this._repaint();

    this._fireEvent('positionchange');
  };

  _proto.onSymbolChanged = function onSymbolChanged() {
    if (this._painter) {
      this._painter.refreshSymbol();
    }

    this._fireEvent('symbolchange');
  };

  _proto.onConfig = function onConfig(conf) {
    var properties;

    if (conf['properties']) {
      properties = conf['properties'];
      delete conf['properties'];
    }

    var needRepaint = false;

    for (var p in conf) {
      if (conf.hasOwnProperty(p)) {
        var prefix = p.slice(0, 5);

        if (prefix === 'arrow' || prefix === 'smoot') {
          needRepaint = true;
          break;
        }
      }
    }

    if (properties) {
      this.setProperties(properties);

      this._repaint();
    } else if (needRepaint) {
      this._repaint();
    }
  };

  _proto._setParent = function _setParent(geometry) {
    if (geometry) {
      this._parent = geometry;
    }
  };

  _proto._getParent = function _getParent() {
    return this._parent;
  };

  _proto._fireEvent = function _fireEvent(eventName, param) {
    if (this.getLayer() && this.getLayer()._onGeometryEvent) {
      if (!param) {
        param = {};
      }

      param['type'] = eventName;
      param['target'] = this;

      this.getLayer()._onGeometryEvent(param);
    }

    this.fire(eventName, param);
  };

  _proto._toJSON = function _toJSON(options) {
    return {
      'feature': this.toGeoJSON(options)
    };
  };

  _proto._exportGraphicOptions = function _exportGraphicOptions(options) {
    var json = {};

    if (isNil(options['options']) || options['options']) {
      json['options'] = this.config();
    }

    if (isNil(options['symbol']) || options['symbol']) {
      json['symbol'] = this.getSymbol();
    }

    if (isNil(options['infoWindow']) || options['infoWindow']) {
      if (this._infoWinOptions) {
        json['infoWindow'] = this._infoWinOptions;
      }
    }

    return json;
  };

  _proto._exportGeoJSONGeometry = function _exportGeoJSONGeometry() {
    var points = this.getCoordinates();
    var coordinates = Coordinate.toNumberArrays(points);
    return {
      'type': this.getType(),
      'coordinates': coordinates
    };
  };

  _proto._exportProperties = function _exportProperties() {
    var properties = null;
    var geoProperties = this.getProperties();

    if (!isNil(geoProperties)) {
      if (isObject(geoProperties)) {
        properties = extend({}, geoProperties);
      } else {
        properties = geoProperties;
      }
    }

    return properties;
  };

  return Geometry;
}(JSONAble(Eventable(Handlerable(Class))));

Geometry.mergeOptions(options$2);




var Marker = function (_CenterMixin) {
  _inheritsLoose(Marker, _CenterMixin);

  function Marker(coordinates, opts) {
    var _this;

    _this = _CenterMixin.call(this, opts) || this;
    _this.type = 'Point';

    if (coordinates) {
      _this.setCoordinates(coordinates);
    }

    return _this;
  }

  var _proto = Marker.prototype;

  _proto.getOutline = function getOutline() {
    var painter = this._getPainter();

    if (!painter) {
      return null;
    }

    var coord = this.getCoordinates();
    var extent = painter.getContainerExtent();
    var anchor = this.getMap().coordToContainerPoint(coord);
    return new Marker(coord, {
      'symbol': {
        'markerType': 'square',
        'markerWidth': extent.getWidth(),
        'markerHeight': extent.getHeight(),
        'markerLineWidth': 1,
        'markerLineColor': '6b707b',
        'markerFill': 'rgba(0, 0, 0, 0)',
        'markerDx': extent.xmin - (anchor.x - extent.getWidth() / 2),
        'markerDy': extent.ymin - (anchor.y - extent.getHeight() / 2)
      }
    });
  };

  _proto._isVectorMarker = function _isVectorMarker() {
    var symbol = this._getInternalSymbol();

    if (Array.isArray(symbol)) {
      return false;
    }

    return VectorMarkerSymbolizer.test(symbol);
  };

  _proto._canEdit = function _canEdit() {
    var symbol = this._getInternalSymbol();

    if (Array.isArray(symbol)) {
      return false;
    }

    return VectorMarkerSymbolizer.test(symbol) || VectorPathMarkerSymbolizer.test(symbol) || ImageMarkerSymbolizer.test(symbol);
  };

  _proto._containsPoint = function _containsPoint(point, t) {
    var extent = this.getContainerExtent();

    if (t) {
      extent = extent.expand(t);
    }

    if (extent.contains(point)) {
      if (this.options['hitTestForEvent']) {
        return _CenterMixin.prototype._containsPoint.call(this, point, t);
      } else {
        return true;
      }
    } else {
      return false;
    }
  };

  _proto._computeExtent = function _computeExtent() {
    return computeExtent.call(this, 'getCenter');
  };

  _proto._computePrjExtent = function _computePrjExtent() {
    return computeExtent.call(this, '_getPrjCoordinates');
  };

  _proto._computeGeodesicLength = function _computeGeodesicLength() {
    return 0;
  };

  _proto._computeGeodesicArea = function _computeGeodesicArea() {
    return 0;
  };

  _proto._getSprite = function _getSprite(resources, canvasClass) {
    if (this._getPainter()) {
      return this._getPainter().getSprite(resources, canvasClass);
    }

    return new Painter(this).getSprite(resources, canvasClass);
  };

  return Marker;
}(CenterMixin(Geometry));


var options$3 = {
  'smoothness': 0,
  'enableClip': true,
  'enableSimplify': true,
  'simplifyTolerance': 2,
  'symbol': {
    'lineColor': '#000',
    'lineWidth': 2,
    'lineOpacity': 1,
    'polygonFill': '#fff',
    'polygonOpacity': 1,
    'opacity': 1
  }
};

var Path = function (_Geometry) {
  _inheritsLoose(Path, _Geometry);

  function Path() {
    
    return _Geometry.apply(this, arguments) || this;
  }

  var _proto = Path.prototype;

  _proto.getOutline = function getOutline() {
    var painter = this._getPainter();

    if (!painter) {
      return null;
    }

    var map = this.getMap();
    var extent = painter.getContainerExtent().convertTo(function (c) {
      return map.containerPointToCoord(c);
    });
    return new Polygon(extent.toArray(), {
      symbol: {
        'lineWidth': 1,
        'lineColor': '6b707b'
      }
    });
  };

  _proto.animateShow = function animateShow(options, cb) {
    var _this = this;

    if (options === void 0) {
      options = {};
    }

    if (this._showPlayer) {
      this._showPlayer.finish();
    }

    if (isFunction(options)) {
      options = {};
      cb = options;
    }

    var coordinates = this.getCoordinates();

    if (coordinates.length === 0) {
      return this;
    }

    this._animIdx = 0;
    this._animLenSoFar = 0;
    this.show();
    var isPolygon = !!this.getShell;
    var animCoords = isPolygon ? this.getShell().concat(this.getShell()[0]) : this.getCoordinates();

    var projection = this._getProjection();

    this._aniShowCenter = projection.unproject(this._getPrjExtent().getCenter());
    var duration = options['duration'] || 1000,
      length = this.getLength(),
      easing = options['easing'] || 'out';
    this.setCoordinates([]);
    var player = this._showPlayer = Animation.animate({
      't': duration
    }, {
        'duration': duration,
        'easing': easing
      }, function (frame) {
        if (!_this.getMap()) {
          if (player.playState !== 'finished') {
            player.finish();

            if (cb) {
              var _coordinates = _this.getCoordinates();

              cb(frame, _coordinates[_coordinates.length - 1]);
            }
          }

          return;
        }

        var currentCoord = _this._drawAnimShowFrame(frame.styles.t, duration, length, animCoords);

        if (frame.state.playState === 'finished') {
          delete _this._showPlayer;
          delete _this._aniShowCenter;
          delete _this._animIdx;
          delete _this._animLenSoFar;
          delete _this._animTailRatio;

          _this.setCoordinates(coordinates);
        }

        if (cb) {
          cb(frame, currentCoord);
        }
      });
    player.play();
    return player;
  };

  _proto._drawAnimShowFrame = function _drawAnimShowFrame(t, duration, length, coordinates) {
    if (t === 0) {
      return coordinates[0];
    }

    var map = this.getMap();
    var targetLength = t / duration * length;
    var segLen = 0;
    var i, l;

    for (i = this._animIdx, l = coordinates.length; i < l - 1; i++) {
      segLen = map.computeLength(coordinates[i], coordinates[i + 1]);

      if (this._animLenSoFar + segLen > targetLength) {
        break;
      }

      this._animLenSoFar += segLen;
    }

    this._animIdx = i;

    if (this._animIdx >= l - 1) {
      this.setCoordinates(coordinates);
      return coordinates[coordinates.length - 1];
    }

    var idx = this._animIdx;
    var p1 = coordinates[idx],
      p2 = coordinates[idx + 1],
      span = targetLength - this._animLenSoFar,
      r = span / segLen;
    this._animTailRatio = r;
    var x = p1.x + (p2.x - p1.x) * r,
      y = p1.y + (p2.y - p1.y) * r,
      targetCoord = new Coordinate(x, y);
    var isPolygon = !!this.getShell;

    if (!isPolygon && this.options['smoothness'] > 0) {
      var animCoords = coordinates.slice(0, this._animIdx + 3);
      this.setCoordinates(animCoords);
    } else {
      var _animCoords = coordinates.slice(0, this._animIdx + 1);

      _animCoords.push(targetCoord);

      if (isPolygon) {
        this.setCoordinates([this._aniShowCenter].concat(_animCoords));
      } else {
        this.setCoordinates(_animCoords);
      }
    }

    return targetCoord;
  };

  _proto._getCenterInExtent = function _getCenterInExtent(extent, coordinates, clipFn) {
    var meExtent = this.getExtent();

    if (!extent.intersects(meExtent)) {
      return null;
    }

    var clipped = clipFn(coordinates, extent);

    if (clipped.length === 0) {
      return null;
    }

    var sumx = 0,
      sumy = 0,
      counter = 0;
    clipped.forEach(function (part) {
      if (Array.isArray(part)) {
        part.forEach(function (c) {
          if (c.point) {
            c = c.point;
          }

          sumx += c.x;
          sumy += c.y;
          counter++;
        });
      } else {
        if (part.point) {
          part = part.point;
        }

        sumx += part.x;
        sumy += part.y;
        counter++;
      }
    });

    var c = new Coordinate(sumx, sumy)._multi(1 / counter);

    c.count = counter;
    return c;
  };

  _proto._getPath2DPoints = function _getPath2DPoints(prjCoords, disableSimplify, zoom) {
    if (!isArrayHasData(prjCoords)) {
      return [];
    }

    var map = this.getMap(),
      isSimplify = !disableSimplify && this._shouldSimplify(),
      tolerance = this.options['simplifyTolerance'] * map._getResolution(),
      isMulti = Array.isArray(prjCoords[0]);

    delete this._simplified;

    if (isSimplify && !isMulti) {
      var count = prjCoords.length;
      prjCoords = simplify(prjCoords, tolerance, false);
      this._simplified = prjCoords.length < count;
    }

    if (isNil(zoom)) {
      zoom = map.getZoom();
    }

    return forEachCoord(prjCoords, function (c) {
      return map._prjToPoint(c, zoom);
    });
  };

  _proto._shouldSimplify = function _shouldSimplify() {
    var layer = this.getLayer(),
      properties = this.getProperties();
    var hasAltitude = properties && layer.options['enableAltitude'] && !isNil(properties[layer.options['altitudeProperty']]);
    return layer && layer.options['enableSimplify'] && !hasAltitude && this.options['enableSimplify'] && !this._showPlayer;
  };

  _proto._setPrjCoordinates = function _setPrjCoordinates(prjPoints) {
    this._prjCoords = prjPoints;
    this.onShapeChanged();
  };

  _proto._getPrjCoordinates = function _getPrjCoordinates() {
    var projection = this._getProjection();

    if (!projection) {
      return null;
    }

    this._verifyProjection();

    if (!this._prjCoords) {
      this._prjCoords = this._projectCoords(this._coordinates);
    }

    return this._prjCoords;
  };

  _proto._updateCache = function _updateCache() {
    this._clearCache();

    var projection = this._getProjection();

    if (!projection) {
      return;
    }

    if (this._prjCoords) {
      this._coordinates = this._unprojectCoords(this._getPrjCoordinates());
    }
  };

  _proto._clearProjection = function _clearProjection() {
    this._prjCoords = null;

    _Geometry.prototype._clearProjection.call(this);
  };

  _proto._projectCoords = function _projectCoords(points) {
    var projection = this._getProjection();

    if (projection) {
      return projection.projectCoords(points);
    }

    return [];
  };

  _proto._unprojectCoords = function _unprojectCoords(prjPoints) {
    var projection = this._getProjection();

    if (projection) {
      return projection.unprojectCoords(prjPoints);
    }

    return [];
  };

  _proto._computeCenter = function _computeCenter() {
    var ring = this._coordinates;

    if (!isArrayHasData(ring)) {
      return null;
    }

    var sumx = 0,
      sumy = 0,
      counter = 0;
    var size = ring.length;

    for (var i = 0; i < size; i++) {
      if (ring[i]) {
        if (isNumber(ring[i].x) && isNumber(ring[i].y)) {
          sumx += ring[i].x;
          sumy += ring[i].y;
          counter++;
        }
      }
    }

    return new Coordinate(sumx / counter, sumy / counter);
  };

  _proto._computeExtent = function _computeExtent() {
    var shell = this._coordinates;

    if (!isArrayHasData(shell)) {
      return null;
    }

    var rings = [shell];

    if (this.hasHoles && this.hasHoles()) {
      rings.push.apply(rings, this.getHoles());
    }

    return this._coords2Extent(rings, this._getProjection());
  };

  _proto._computePrjExtent = function _computePrjExtent() {
    var coords = [this._getPrjCoordinates()];

    if (this.hasHoles && this.hasHoles()) {
      coords.push.apply(coords, this._getPrjHoles());
    }

    return this._coords2Extent(coords);
  };

  _proto._get2DLength = function _get2DLength() {
    var vertexes = this._getPath2DPoints(this._getPrjCoordinates(), true);

    var len = 0;

    for (var i = 1, l = vertexes.length; i < l; i++) {
      len += vertexes[i].distanceTo(vertexes[i - 1]);
    }

    return len;
  };

  _proto._hitTestTolerance = function _hitTestTolerance() {
    var symbol = this._getInternalSymbol();

    var w;

    if (Array.isArray(symbol)) {
      w = 0;

      for (var i = 0; i < symbol.length; i++) {
        if (isNumber(symbol[i]['lineWidth'])) {
          if (symbol[i]['lineWidth'] > w) {
            w = symbol[i]['lineWidth'];
          }
        }
      }
    } else {
      w = symbol['lineWidth'];
    }

    return isNumber(w) ? w / 2 : 1.5;
  };

  _proto._coords2Extent = function _coords2Extent(coords, proj) {
    var result = new Extent(proj);

    for (var i = 0, l = coords.length; i < l; i++) {
      for (var j = 0, ll = coords[i].length; j < ll; j++) {
        result._combine(coords[i][j]);
      }
    }

    return result;
  };

  return Path;
}(Geometry);

Path.mergeOptions(options$3);


var Position = function () {
  function Position(x, y) {
    if (!isNil(x) && !isNil(y)) {
      this.x = +x;
      this.y = +y;
    } else if (!isNil(x.x) && !isNil(x.y)) {
      this.x = +x.x;
      this.y = +x.y;
    } else if (Array.isArray(x)) {
      this.x = +x[0];
      this.y = +x[1];
    }

    if (this._isNaN()) {
      throw new Error('Position is NaN');
    }
  }

  var _proto = Position.prototype;

  _proto.abs = function abs() {
    return new this.constructor(Math.abs(this.x), Math.abs(this.y));
  };

  _proto._abs = function _abs() {
    this.x = Math.abs(this.x);
    this.y = Math.abs(this.y);
    return this;
  };

  _proto._round = function _round() {
    this.x = Math.round(this.x);
    this.y = Math.round(this.y);
    return this;
  };

  _proto.round = function round() {
    return new this.constructor(Math.round(this.x), Math.round(this.y));
  };

  _proto._ceil = function _ceil() {
    this.x = Math.ceil(this.x);
    this.y = Math.ceil(this.y);
    return this;
  };

  _proto.ceil = function ceil() {
    return new this.constructor(Math.ceil(this.x), Math.ceil(this.y));
  };

  _proto._floor = function _floor() {
    this.x = Math.floor(this.x);
    this.y = Math.floor(this.y);
    return this;
  };

  _proto.floor = function floor() {
    return new this.constructor(Math.floor(this.x), Math.floor(this.y));
  };

  _proto.copy = function copy() {
    return new this.constructor(this.x, this.y);
  };

  _proto._add = function _add(x, y) {
    if (!isNil(x.x)) {
      this.x += x.x;
      this.y += x.y;
    } else if (!isNil(x[0])) {
      this.x += x[0];
      this.y += x[1];
    } else {
      this.x += x;
      this.y += y;
    }

    return this;
  };

  _proto.add = function add(x, y) {
    var nx, ny;

    if (!isNil(x.x)) {
      nx = this.x + x.x;
      ny = this.y + x.y;
    } else if (!isNil(x[0])) {
      nx = this.x + x[0];
      ny = this.y + x[1];
    } else {
      nx = this.x + x;
      ny = this.y + y;
    }

    return new this.constructor(nx, ny);
  };

  _proto._sub = function _sub(x, y) {
    if (!isNil(x.x)) {
      this.x -= x.x;
      this.y -= x.y;
    } else if (!isNil(x[0])) {
      this.x -= x[0];
      this.y -= x[1];
    } else {
      this.x -= x;
      this.y -= y;
    }

    return this;
  };

  _proto._substract = function _substract() {
    return this._sub.apply(this, arguments);
  };

  _proto.sub = function sub(x, y) {
    var nx, ny;

    if (!isNil(x.x)) {
      nx = this.x - x.x;
      ny = this.y - x.y;
    } else if (!isNil(x[0])) {
      nx = this.x - x[0];
      ny = this.y - x[1];
    } else {
      nx = this.x - x;
      ny = this.y - y;
    }

    return new this.constructor(nx, ny);
  };

  _proto.substract = function substract() {
    return this.sub.apply(this, arguments);
  };

  _proto.multi = function multi(ratio) {
    return new this.constructor(this.x * ratio, this.y * ratio);
  };

  _proto._multi = function _multi(ratio) {
    this.x *= ratio;
    this.y *= ratio;
    return this;
  };

  _proto.div = function div(n) {
    return this.multi(1 / n);
  };

  _proto._div = function _div(n) {
    return this._multi(1 / n);
  };

  _proto.equals = function equals(c) {
    if (!(c instanceof this.constructor)) {
      return false;
    }

    return this.x === c.x && this.y === c.y;
  };

  _proto._isNaN = function _isNaN() {
    return isNaN(this.x) || isNaN(this.y);
  };

  _proto.isZero = function isZero() {
    return this.x === 0 && this.y === 0;
  };

  _proto.toArray = function toArray() {
    return [this.x, this.y];
  };

  _proto.toFixed = function toFixed(n) {
    return new this.constructor(this.x.toFixed(n), this.y.toFixed(n));
  };

  _proto.toJSON = function toJSON() {
    return {
      x: this.x,
      y: this.y
    };
  };

  return Position;
}();

var Point = function (_Position) {
  _inheritsLoose(Point, _Position);

  function Point() {
    return _Position.apply(this, arguments) || this;
  }

  var _proto = Point.prototype;

  _proto.closeTo = function closeTo(p, delta) {
    if (!delta) {
      delta = 0;
    }

    return this.x >= p.x - delta && this.x <= p.x + delta && this.y >= p.y - delta && this.y <= p.y + delta;
  };

  _proto.distanceTo = function distanceTo(point) {
    var x = point.x - this.x,
      y = point.y - this.y;
    return Math.sqrt(x * x + y * y);
  };

  _proto.mag = function mag() {
    return Math.sqrt(this.x * this.x + this.y * this.y);
  };

  _proto.unit = function unit() {
    return this.copy()._unit();
  };

  _proto._unit = function _unit() {
    this._div(this.mag());

    return this;
  };

  _proto.perp = function perp() {
    return this.copy()._perp();
  };

  _proto._perp = function _perp() {
    var y = this.y;
    this.y = this.x;
    this.x = -y;
    return this;
  };

  _proto.angleWith = function angleWith(b) {
    return this.angleWithSep(b.x, b.y);
  };

  _proto.angleWithSep = function angleWithSep(x, y) {
    return Math.atan2(this.x * y - this.y * x, this.x * x + this.y * y);
  };

  _proto._rotate = function _rotate(angle) {
    var cos = Math.cos(angle),
      sin = Math.sin(angle),
      x = cos * this.x - sin * this.y,
      y = sin * this.x + cos * this.y;
    this.x = x;
    this.y = y;
    return this;
  };

  _proto.rotate = function rotate(a) {
    return this.copy()._rotate(a);
  };

  return Point;
}(Position);



var Identity = extend({
  'measure': 'IDENTITY',
  measureLenBetween: function measureLenBetween(c1, c2) {
    if (!c1 || !c2) {
      return 0;
    }

    try {
      return Math.sqrt(Math.pow(c1.x - c2.x, 2) + Math.pow(c1.y - c2.y, 2));
    } catch (err) {
      return 0;
    }
  },
  measureArea: function measureArea(coordinates) {
    if (!Array.isArray(coordinates)) {
      return 0;
    }

    var area = 0;

    for (var i = 0, len = coordinates.length; i < len; i++) {
      var c1 = coordinates[i];
      var c2 = null;

      if (i === len - 1) {
        c2 = coordinates[0];
      } else {
        c2 = coordinates[i + 1];
      }

      area += c1.x * c2.y - c1.y * c2.x;
    }

    return Math.abs(area / 2);
  },
  locate: function locate(c, xDist, yDist) {
    c = new Coordinate(c.x, c.y);
    return this._locate(c, xDist, yDist);
  },
  _locate: function _locate(c, xDist, yDist) {
    if (!c) {
      return null;
    }

    if (!xDist) {
      xDist = 0;
    }

    if (!yDist) {
      yDist = 0;
    }

    if (!xDist && !yDist) {
      return c;
    }

    c.x = c.x + xDist;
    c.y = c.y + yDist;
    return c;
  },
  rotate: function rotate(c, pivot, angle) {
    c = new Coordinate(c.x, c.y);
    return this._rotate(c, pivot, angle);
  },
  _rotate: function () {
    var tmp = new Point(0, 0);
    return function (c, pivot, angle) {
      tmp.x = c.x - pivot.x;
      tmp.y = c.y - pivot.y;

      tmp._rotate(angle * Math.PI / 180);

      c.x = pivot.x + tmp.x;
      c.y = pivot.y + tmp.y;
      return c;
    };
  }()
}, Common$1);

function _assertThisInitialized(self) {
  if (self === void 0) {
    throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
  }

  return self;
}

var uid = 0;
function UID() {
  return uid++;
}


var DefaultSpatialRef = {
  'EPSG:3857': {
    'resolutions': function () {
      var resolutions = [];
      var d = 2 * 6378137 * Math.PI;

      for (var i = 0; i < 21; i++) {
        resolutions[i] = d / (256 * Math.pow(2, i));
      }

      return resolutions;
    }(),
    'fullExtent': {
      'top': 6378137 * Math.PI,
      'left': -6378137 * Math.PI,
      'bottom': -6378137 * Math.PI,
      'right': 6378137 * Math.PI
    }
  },
  'EPSG:4326': {
    'fullExtent': {
      'top': 90,
      'left': -180,
      'bottom': -90,
      'right': 180
    },
    'resolutions': function () {
      var resolutions = [];

      for (var i = 0; i < 20; i++) {
        resolutions[i] = 180 / (Math.pow(2, i) * 128);
      }

      return resolutions;
    }()
  },
  'BAIDU': {
    'resolutions': function () {
      var res = Math.pow(2, 18);
      var resolutions = [];

      for (var i = 0; i < 20; i++) {
        resolutions[i] = res;
        res *= 0.5;
      }

      resolutions[0] = null;
      resolutions[1] = null;
      resolutions[2] = null;
      return resolutions;
    }(),
    'fullExtent': {
      'top': 33554432,
      'left': -33554432,
      'bottom': -33554432,
      'right': 33554432
    }
  },
  'IDENTITY': {
    'resolutions': function () {
      var res = Math.pow(2, 8);
      var resolutions = [];

      for (var i = 0; i < 18; i++) {
        resolutions[i] = res;
        res *= 0.5;
      }

      return resolutions;
    }(),
    'fullExtent': {
      'top': 200000,
      'left': -200000,
      'bottom': -200000,
      'right': 200000
    }
  }
};
DefaultSpatialRef['EPSG:4490'] = DefaultSpatialRef['EPSG:4326'];

var Coordinate = function (_Position) {
  _inheritsLoose(Coordinate, _Position);

  function Coordinate() {
    return _Position.apply(this, arguments) || this;
  }

  Coordinate.toNumberArrays = function toNumberArrays(coordinates) {
    if (!Array.isArray(coordinates)) {
      return [coordinates.x, coordinates.y];
    }

    return forEachCoord(coordinates, function (coord) {
      return [coord.x, coord.y];
    });
  };

  Coordinate.toCoordinates = function toCoordinates(coordinates) {
    if (isNumber(coordinates[0]) && isNumber(coordinates[1])) {
      return new Coordinate(coordinates);
    }

    var result = [];

    for (var i = 0, len = coordinates.length; i < len; i++) {
      var child = coordinates[i];

      if (Array.isArray(child)) {
        if (isNumber(child[0])) {
          result.push(new Coordinate(child));
        } else {
          result.push(Coordinate.toCoordinates(child));
        }
      } else {
        result.push(new Coordinate(child));
      }
    }

    return result;
  };

  return Coordinate;
}(Position);

var JSON_TYPE = 'Polygon';

var Polygon = function (_Path) {
  _inheritsLoose(Polygon, _Path);

  function Polygon(coordinates, opts) {
    var _this;

    _this = _Path.call(this, opts) || this;
    _this.type = 'Polygon';

    if (coordinates) {
      _this.setCoordinates(coordinates);
    }

    return _this;
  }

  var _proto = Polygon.prototype;

  _proto.setCoordinates = function setCoordinates(coordinates) {
    if (!coordinates) {
      this._coordinates = null;
      this._holes = null;

      this._projectRings();

      return this;
    }

    var rings = Coordinate.toCoordinates(coordinates);
    var len = rings.length;

    if (!Array.isArray(rings[0])) {
      this._coordinates = this._trimRing(rings);
    } else {
      this._coordinates = this._trimRing(rings[0]);

      if (len > 1) {
        var holes = [];

        for (var i = 1; i < len; i++) {
          if (!rings[i]) {
            continue;
          }

          holes.push(this._trimRing(rings[i]));
        }

        this._holes = holes;
      }
    }

    this._projectRings();

    return this;
  };

  _proto.getCoordinates = function getCoordinates() {
    if (!this._coordinates) {
      return [];
    }

    var holes = this.getHoles();
    var rings = [this._copyAndCloseRing(this._coordinates)];

    for (var i = 0, l = holes.length; i < l; i++) {
      rings.push(this._copyAndCloseRing(holes[i]));
    }

    return rings;
  };

  _proto.getCenterInExtent = function getCenterInExtent(extent) {
    return this._getCenterInExtent(extent, this.getShell(), clipPolygon);
  };

  _proto.getShell = function getShell() {
    return this._coordinates || [];
  };

  _proto.getHoles = function getHoles() {
    return this._holes || [];
  };

  _proto.hasHoles = function hasHoles() {
    return this.getHoles().length > 0;
  };

  _proto._projectRings = function _projectRings() {
    if (!this.getMap()) {
      this.onShapeChanged();
      return;
    }

    this._prjCoords = this._projectCoords(this._coordinates);
    this._prjHoles = this._projectCoords(this._holes);
    this.onShapeChanged();
  };

  _proto._cleanRing = function _cleanRing(ring) {
    for (var i = ring.length - 1; i >= 0; i--) {
      if (!ring[i]) {
        ring.splice(i, 1);
      }
    }
  };

  _proto._checkRing = function _checkRing(ring) {
    this._cleanRing(ring);

    if (!ring || !isArrayHasData(ring)) {
      return false;
    }

    var lastPoint = ring[ring.length - 1];
    var isClose = true;

    if (ring[0].x !== lastPoint.x || ring[0].y !== lastPoint.y) {
      isClose = false;
    }

    return isClose;
  };

  _proto._trimRing = function _trimRing(ring) {
    var isClose = this._checkRing(ring);

    if (isArrayHasData(ring) && isClose) {
      ring.splice(ring.length - 1, 1);
    }

    return ring;
  };

  _proto._copyAndCloseRing = function _copyAndCloseRing(ring) {
    ring = ring.slice(0);

    var isClose = this._checkRing(ring);

    if (isArrayHasData(ring) && !isClose) {
      ring.push(ring[0].copy());
      return ring;
    } else {
      return ring;
    }
  };

  _proto._getPrjShell = function _getPrjShell() {
    if (this.getJSONType() === JSON_TYPE) {
      return this._getPrjCoordinates();
    }

    var projection = this._getProjection();

    if (!projection) {
      return null;
    }

    this._verifyProjection();

    if (!this._prjShell) {
      this._prjShell = this._projectCoords(this.getShell());
    }

    return this._prjShell;
  };

  _proto._getPrjHoles = function _getPrjHoles() {
    var projection = this._getProjection();

    if (!projection) {
      return null;
    }

    this._verifyProjection();

    if (!this._prjHoles) {
      this._prjHoles = this._projectCoords(this.getHoles());
    }

    return this._prjHoles;
  };

  _proto._computeGeodesicLength = function _computeGeodesicLength(measurer) {
    var rings = this.getCoordinates();

    if (!isArrayHasData(rings)) {
      return 0;
    }

    var result = 0;

    for (var i = 0, len = rings.length; i < len; i++) {
      result += measurer.measureLength(rings[i]);
    }

    return result;
  };

  _proto._computeGeodesicArea = function _computeGeodesicArea(measurer) {
    var rings = this.getCoordinates();

    if (!isArrayHasData(rings)) {
      return 0;
    }

    var result = measurer.measureArea(rings[0]);

    for (var i = 1, len = rings.length; i < len; i++) {
      result -= measurer.measureArea(rings[i]);
    }

    return result;
  };

  _proto._updateCache = function _updateCache() {
    _Path.prototype._updateCache.call(this);

    if (this._prjHoles) {
      this._holes = this._unprojectCoords(this._getPrjHoles());
    }
  };

  _proto._clearCache = function _clearCache() {
    delete this._prjShell;
    return _Path.prototype._clearCache.call(this);
  };

  _proto._clearProjection = function _clearProjection() {
    if (this._prjHoles) {
      this._prjHoles = null;
    }

    if (this._prjShell) {
      this._prjShell = null;
    }

    _Path.prototype._clearProjection.call(this);
  };

  return Polygon;
}(Path);

Polygon.registerJSONType(JSON_TYPE);

var options$5 = {
  'arrowStyle': null,
  'arrowPlacement': 'vertex-last'
};

var LineString = function (_Path) {
  _inheritsLoose(LineString, _Path);

  function LineString(coordinates, options) {
    var _this;

    _this = _Path.call(this, options) || this;
    _this.type = 'LineString';

    if (coordinates) {
      _this.setCoordinates(coordinates);
    }

    return _this;
  }

  var _proto = LineString.prototype;

  _proto.setCoordinates = function setCoordinates(coordinates) {
    if (!coordinates) {
      this._coordinates = null;

      this._setPrjCoordinates(null);

      return this;
    }

    this._coordinates = Coordinate.toCoordinates(coordinates);

    if (this.getMap()) {
      this._setPrjCoordinates(this._projectCoords(this._coordinates));
    } else {
      this.onShapeChanged();
    }

    return this;
  };

  _proto.getCoordinates = function getCoordinates() {
    return this._coordinates || [];
  };

  _proto.getCenterInExtent = function getCenterInExtent(extent) {
    return this._getCenterInExtent(extent, this.getCoordinates(), clipLine);
  };

  _proto._computeGeodesicLength = function _computeGeodesicLength(measurer) {
    return measurer.measureLength(this.getCoordinates());
  };

  _proto._computeGeodesicArea = function _computeGeodesicArea() {
    return 0;
  };

  return LineString;
}(Path);

LineString.mergeOptions(options$5);
LineString.registerJSONType('LineString');



var GeometryCollection = function (_Geometry) {
  _inheritsLoose(GeometryCollection, _Geometry);

  function GeometryCollection(geometries, opts) {
    var _this;

    _this = _Geometry.call(this, opts) || this;
    _this.type = 'GeometryCollection';

    _this.setGeometries(geometries);

    return _this;
  }

  var _proto = GeometryCollection.prototype;

  _proto.setGeometries = function setGeometries(_geometries) {
    var geometries = this._checkGeometries(_geometries || []);

    var symbol = this._getSymbol();

    var options = this.config();

    for (var i = geometries.length - 1; i >= 0; i--) {
      geometries[i]._initOptions(options);

      geometries[i]._setParent(this);

      geometries[i]._setEventParent(this);

      if (symbol) {
        geometries[i].setSymbol(symbol);
      }
    }

    this._geometries = geometries;

    if (this.getLayer()) {
      this._bindGeometriesToLayer();

      this.onShapeChanged();
    }

    return this;
  };

  _proto.getGeometries = function getGeometries() {
    return this._geometries || [];
  };

  _proto.forEach = function forEach(fn, context) {
    var geometries = this.getGeometries();

    for (var i = 0, l = geometries.length; i < l; i++) {
      if (!geometries[i]) {
        continue;
      }

      if (!context) {
        fn(geometries[i], i);
      } else {
        fn.call(context, geometries[i], i);
      }
    }

    return this;
  };

  _proto.filter = function filter(fn, context) {
    if (!fn) {
      return new GeometryCollection();
    }

    var selected = [];
    var isFn = isFunction(fn);
    var filter = isFn ? fn : createFilter(fn);
    this.forEach(function (geometry) {
      var g = isFn ? geometry : getFilterFeature(geometry);

      if (context ? filter.call(context, g) : filter(g)) {
        selected.push(geometry);
      }
    }, this);
    return new GeometryCollection(selected);
  };

  _proto.translate = function translate(offset) {
    if (!offset) {
      return this;
    }

    if (this.isEmpty()) {
      return this;
    }

    var args = arguments;
    this.forEach(function (geometry) {
      if (geometry && geometry.translate) {
        geometry.translate.apply(geometry, args);
      }
    });
    return this;
  };

  _proto.isEmpty = function isEmpty() {
    return !isArrayHasData(this.getGeometries());
  };

  _proto.remove = function remove() {
    this.forEach(function (geometry) {
      geometry._unbind();
    });
    return Geometry.prototype.remove.apply(this, arguments);
  };

  _proto.show = function show() {
    this.options['visible'] = true;
    this.forEach(function (geometry) {
      geometry.show();
    });
    return this;
  };

  _proto.hide = function hide() {
    this.options['visible'] = false;
    this.forEach(function (geometry) {
      geometry.hide();
    });
    return this;
  };

  _proto.onConfig = function onConfig(config) {
    this.forEach(function (geometry) {
      geometry.config(config);
    });
  };

  _proto.getSymbol = function getSymbol() {
    var s = _Geometry.prototype.getSymbol.call(this);

    if (!s) {
      var symbols = [];
      var is = false;
      this.forEach(function (g) {
        var symbol = g.getSymbol();

        if (symbol && !is) {
          is = true;
        }

        symbols.push(g.getSymbol());
      });

      if (is) {
        s = {
          'children': symbols
        };
      }
    }

    return s;
  };

  _proto.setSymbol = function setSymbol(s) {
    if (s && s['children']) {
      this._symbol = null;
      this.forEach(function (g, i) {
        g.setSymbol(s['children'][i]);
      });
    } else {
      var symbol = this._prepareSymbol(s);

      this._symbol = symbol;
      this.forEach(function (g) {
        g.setSymbol(symbol);
      });
    }

    this.onSymbolChanged();
    return this;
  };

  _proto._setExternSymbol = function _setExternSymbol(symbol) {
    symbol = this._prepareSymbol(symbol);
    this._externSymbol = symbol;
    this.forEach(function (geometry) {
      geometry._setExternSymbol(symbol);
    });
    this.onSymbolChanged();
    return this;
  };

  _proto._bindLayer = function _bindLayer() {
    _Geometry.prototype._bindLayer.apply(this, arguments);

    this._bindGeometriesToLayer();
  };

  _proto._bindGeometriesToLayer = function _bindGeometriesToLayer() {
    var layer = this.getLayer();
    this.forEach(function (geometry) {
      geometry._bindLayer(layer);
    });
  };

  _proto._checkGeometries = function _checkGeometries(geometries) {
    var invalidGeoError = 'The geometry added to collection is invalid.';

    if (geometries && !Array.isArray(geometries)) {
      if (geometries instanceof Geometry) {
        return [geometries];
      } else {
        throw new Error(invalidGeoError);
      }
    } else {
      for (var i = 0, l = geometries.length; i < l; i++) {
        if (!this._checkGeo(geometries[i])) {
          throw new Error(invalidGeoError + ' Index: ' + i);
        }
      }

      return geometries;
    }
  };

  _proto._checkGeo = function _checkGeo(geo) {
    return geo instanceof Geometry;
  };

  _proto._updateCache = function _updateCache() {
    this._clearCache();

    if (this.isEmpty()) {
      return;
    }

    this.forEach(function (geometry) {
      if (geometry && geometry._updateCache) {
        geometry._updateCache();
      }
    });
  };

  _proto._removePainter = function _removePainter() {
    if (this._painter) {
      this._painter.remove();
    }

    delete this._painter;
    this.forEach(function (geometry) {
      geometry._removePainter();
    });
  };

  _proto._computeCenter = function _computeCenter(projection) {
    if (!projection || this.isEmpty()) {
      return null;
    }

    var sumX = 0,
      sumY = 0,
      counter = 0;
    var geometries = this.getGeometries();

    for (var i = 0, l = geometries.length; i < l; i++) {
      if (!geometries[i]) {
        continue;
      }

      var center = geometries[i]._computeCenter(projection);

      if (center) {
        sumX += center.x;
        sumY += center.y;
        counter++;
      }
    }

    if (counter === 0) {
      return null;
    }

    return new Coordinate(sumX / counter, sumY / counter);
  };

  _proto._containsPoint = function _containsPoint(point, t) {
    if (this.isEmpty()) {
      return false;
    }

    var geometries = this.getGeometries();

    for (var i = 0, l = geometries.length; i < l; i++) {
      if (geometries[i]._containsPoint(point, t)) {
        return true;
      }
    }

    return false;
  };

  _proto._computeExtent = function _computeExtent(projection) {
    return computeExtent$1.call(this, projection, '_computeExtent');
  };

  _proto._computePrjExtent = function _computePrjExtent(projection) {
    return computeExtent$1.call(this, projection, '_computePrjExtent');
  };

  _proto._computeGeodesicLength = function _computeGeodesicLength(projection) {
    if (!projection || this.isEmpty()) {
      return 0;
    }

    var geometries = this.getGeometries();
    var result = 0;

    for (var i = 0, l = geometries.length; i < l; i++) {
      if (!geometries[i]) {
        continue;
      }

      result += geometries[i]._computeGeodesicLength(projection);
    }

    return result;
  };

  _proto._computeGeodesicArea = function _computeGeodesicArea(projection) {
    if (!projection || this.isEmpty()) {
      return 0;
    }

    var geometries = this.getGeometries();
    var result = 0;

    for (var i = 0, l = geometries.length; i < l; i++) {
      if (!geometries[i]) {
        continue;
      }

      result += geometries[i]._computeGeodesicArea(projection);
    }

    return result;
  };

  _proto._exportGeoJSONGeometry = function _exportGeoJSONGeometry() {
    var children = [];

    if (!this.isEmpty()) {
      var geometries = this.getGeometries();

      for (var i = 0, l = geometries.length; i < l; i++) {
        if (!geometries[i]) {
          continue;
        }

        children.push(geometries[i]._exportGeoJSONGeometry());
      }
    }

    return {
      'type': 'GeometryCollection',
      'geometries': children
    };
  };

  _proto._clearProjection = function _clearProjection() {
    if (this.isEmpty()) {
      return;
    }

    var geometries = this.getGeometries();

    for (var i = 0, l = geometries.length; i < l; i++) {
      if (!geometries[i]) {
        continue;
      }

      geometries[i]._clearProjection();
    }
  };

  _proto._getConnectPoints = function _getConnectPoints() {
    var extent = this.getExtent();
    var anchors = [new Coordinate(extent.xmin, extent.ymax), new Coordinate(extent.xmax, extent.ymin), new Coordinate(extent.xmin, extent.ymin), new Coordinate(extent.xmax, extent.ymax)];
    return anchors;
  };

  _proto._getExternalResources = function _getExternalResources() {
    if (this.isEmpty()) {
      return [];
    }

    var geometries = this.getGeometries(),
      resources = [];
    var cache = {};
    var symbol, res, key;

    for (var i = 0, l = geometries.length; i < l; i++) {
      if (!geometries[i]) {
        continue;
      }

      symbol = geometries[i]._getInternalSymbol();
      res = getExternalResources(symbol);

      for (var ii = 0, ll = res.length; ii < ll; ii++) {
        key = res[ii].join();

        if (!cache[key]) {
          resources.push(res[ii]);
          cache[key] = 1;
        }
      }
    }

    return resources;
  };

  _proto.startEdit = function startEdit(opts) {
    var _this2 = this;

    if (this.isEmpty()) {
      return this;
    }

    if (!opts) {
      opts = {};
    }

    if (opts['symbol']) {
      this._originalSymbol = this.getSymbol();
      this.setSymbol(opts['symbol']);
    }

    this._draggbleBeforeEdit = this.options['draggable'];
    this.config('draggable', false);
    var geometries = this.getGeometries();

    for (var i = 0, l = geometries.length; i < l; i++) {
      geometries[i].startEdit(opts);
    }

    this._editing = true;
    this.hide();
    setTimeout(function () {
      _this2.fire('editstart');
    }, 1);
    return this;
  };

  _proto.endEdit = function endEdit() {
    if (this.isEmpty()) {
      return this;
    }

    var geometries = this.getGeometries();

    for (var i = 0, l = geometries.length; i < l; i++) {
      geometries[i].endEdit();
    }

    if (this._originalSymbol) {
      this.setSymbol(this._originalSymbol);
      delete this._originalSymbol;
    }

    this._editing = false;
    this.show();
    this.config('draggable', this._draggbleBeforeEdit);
    this.fire('editend');
    return this;
  };

  _proto.isEditing = function isEditing() {
    if (!this._editing) {
      return false;
    }

    return true;
  };

  return GeometryCollection;
}(Geometry);

GeometryCollection.registerJSONType('GeometryCollection');


function toGeometry(geoJSON) {
  if (isString(geoJSON)) {
    geoJSON = parseJSON(geoJSON);
  }
  if (Array.isArray(geoJSON)) {
    var resultGeos = [];

    for (var i = 0, len = geoJSON.length; i < len; i++) {
      var geo = _convert(geoJSON[i]);

      if (Array.isArray(geo)) {
        pushIn(resultGeos, geo);
      } else {
        resultGeos.push(geo);
      }
    }

    return resultGeos;
  } else {
    var resultGeo = GeoJSON._convert(geoJSON);

    return resultGeo;
  }
}


var MultiGeometry = function (_GeometryCollection) {
  _inheritsLoose(MultiGeometry, _GeometryCollection);

  function MultiGeometry(geoType, type, data, options) {
    var _this;

    _this = _GeometryCollection.call(this, null, options) || this;
    _this.GeometryType = geoType;
    _this.type = type;

    _this._initData(data);

    return _this;
  }

  var _proto = MultiGeometry.prototype;

  _proto.getCoordinates = function getCoordinates() {
    var coordinates = [];
    var geometries = this.getGeometries();

    for (var i = 0, l = geometries.length; i < l; i++) {
      var child = geometries[i];
      coordinates.push(child.getShell && child.getJSONType() !== 'Polygon' ? [child.getShell()] : child.getCoordinates());
    }

    return coordinates;
  };

  _proto.setCoordinates = function setCoordinates(coordinates) {
    coordinates = coordinates || [];
    var geometries = [];

    for (var i = 0, l = coordinates.length; i < l; i++) {
      var g = new this.GeometryType(coordinates[i], this.config());
      geometries.push(g);
    }

    this.setGeometries(geometries);
    return this;
  };

  _proto._initData = function _initData(data) {
    data = data || [];

    if (data.length) {
      if (data[0] instanceof this.GeometryType) {
        this.setGeometries(data);
      } else {
        this.setCoordinates(data);
      }
    }
  };

  _proto._checkGeo = function _checkGeo(geo) {
    return geo instanceof this.GeometryType;
  };

  _proto._exportGeoJSONGeometry = function _exportGeoJSONGeometry() {
    var points = this.getCoordinates();
    var coordinates = Coordinate.toNumberArrays(points);
    return {
      'type': this.getType(),
      'coordinates': coordinates
    };
  };

  return MultiGeometry;
}(GeometryCollection);

var MultiPoint = function (_MultiGeometry) {
  _inheritsLoose(MultiPoint, _MultiGeometry);

  function MultiPoint(data, opts) {
    return _MultiGeometry.call(this, Marker, 'MultiPoint', data, opts) || this;
  }

  var _proto = MultiPoint.prototype;

  _proto.findClosest = function findClosest(coordinate) {
    if (!coordinate) {
      return null;
    }

    var coords = this.getCoordinates();
    var hit = null;
    var max = Infinity;
    coords.forEach(function (c) {
      var dist = distanceTo(c, coordinate);

      if (dist < max) {
        hit = c;
        max = dist;
      }
    });
    return hit;
  };

  return MultiPoint;
}(MultiGeometry);

MultiPoint.registerJSONType('MultiPoint');

function distanceTo(p0, p1) {
  var x = p1.x - p0.x,
    y = p1.y - p0.y;
  return Math.sqrt(x * x + y * y);
}

var MultiPath = function (_MultiGeometry) {
  _inheritsLoose(MultiPath, _MultiGeometry);

  function MultiPath() {
    return _MultiGeometry.apply(this, arguments) || this;
  }

  var _proto = MultiPath.prototype;

  _proto.getCenterInExtent = function getCenterInExtent(extent) {
    var children = this.getGeometries();
    var sumx = 0,
      sumy = 0,
      counter = 0;
    children.forEach(function (l) {
      var c = l.getCenterInExtent(extent);

      if (c) {
        sumx += c.x * c.count;
        sumy += c.y * c.count;
        counter += c.count;
      }
    });

    if (counter === 0) {
      return null;
    }

    return new Coordinate(sumx, sumy)._multi(1 / counter);
  };

  return MultiPath;
}(MultiGeometry);

var MultiLineString = function (_MultiPath) {
  _inheritsLoose(MultiLineString, _MultiPath);

  function MultiLineString(data, options) {
    return _MultiPath.call(this, LineString, 'MultiLineString', data, options) || this;
  }

  return MultiLineString;
}(MultiPath);

MultiLineString.registerJSONType('MultiLineString');

var MultiPolygon = function (_MultiPath) {
  _inheritsLoose(MultiPolygon, _MultiPath);

  function MultiPolygon(data, opts) {
    return _MultiPath.call(this, Polygon, 'MultiPolygon', data, opts) || this;
  }

  return MultiPolygon;
}(MultiPath);

function CenterMixin(Base) {
  return function (_Base) {
    _inheritsLoose(_class, _Base);

    function _class() {
      return _Base.apply(this, arguments) || this;
    }

    var _proto = _class.prototype;

    _proto.getCoordinates = function getCoordinates() {
      return this._coordinates;
    };

    _proto.setCoordinates = function setCoordinates(coordinates) {
      var center = coordinates instanceof Coordinate ? coordinates : new Coordinate(coordinates);

      if (center.equals(this._coordinates)) {
        return this;
      }

      this._coordinates = center;

      if (!this.getMap()) {
        this.onPositionChanged();
        return this;
      }

      var projection = this._getProjection();

      this._setPrjCoordinates(projection.project(this._coordinates));

      return this;
    };

    _proto._getCenter2DPoint = function _getCenter2DPoint(zoom) {
      var map = this.getMap();

      if (!map) {
        return null;
      }

      var z = isNil(zoom) ? map.getZoom() : map.getGLZoom();

      var pcenter = this._getPrjCoordinates();

      if (!pcenter) {
        return null;
      }

      return map._prjToPoint(pcenter, z);
    };

    _proto._getPrjCoordinates = function _getPrjCoordinates() {
      var projection = this._getProjection();

      if (!projection) {
        return null;
      }

      this._verifyProjection();

      if (!this._pcenter) {
        if (this._coordinates) {
          this._pcenter = projection.project(this._coordinates);
        }
      }

      return this._pcenter;
    };

    _proto._setPrjCoordinates = function _setPrjCoordinates(pcenter) {
      this._pcenter = pcenter;
      this.onPositionChanged();
    };

    _proto._updateCache = function _updateCache() {
      this._clearCache();

      var projection = this._getProjection();

      if (this._pcenter && projection) {
        this._coordinates = projection.unproject(this._pcenter);
      }
    };

    _proto._clearProjection = function _clearProjection() {
      this._pcenter = null;

      _Base.prototype._clearProjection.call(this);
    };

    _proto._computeCenter = function _computeCenter() {
      return this._coordinates ? this._coordinates.copy() : null;
    };

    return _class;
  }(Base);
}

MultiPolygon.registerJSONType('MultiPolygon');

var types$1 = {
  'Marker': Marker,
  'LineString': LineString,
  'Polygon': Polygon,
  'MultiPoint': MultiPoint,
  'MultiLineString': MultiLineString,
  'MultiPolygon': MultiPolygon
};
function _convert(json) {
  if (!json || isNil(json['type'])) {
    return null;
  }

  var type = json['type'];

  if (type === 'Feature') {
    var g = json['geometry'];

    var geometry = _convert(g);

    if (!geometry) {
      return null;
    }

    geometry.setId(json['id']);
    geometry.setProperties(json['properties']);
    return geometry;
  } else if (type === 'FeatureCollection') {
    var features = json['features'];

    if (!features) {
      return null;
    }

    var result = toGeometry(features);
    return result;
  } else if (['Point', 'LineString', 'Polygon', 'MultiPoint', 'MultiLineString', 'MultiPolygon'].indexOf(type) >= 0) {
    var clazz = type === 'Point' ? 'Marker' : type;
    return new types$1[clazz](json['coordinates']);
  } else if (type === 'GeometryCollection') {
    var geometries = json['geometries'];

    if (!isArrayHasData(geometries)) {
      return new GeometryCollection();
    }

    var mGeos = [];
    var size = geometries.length;

    for (var i = 0; i < size; i++) {
      mGeos.push(_convert(geometries[i]));
    }

    return new GeometryCollection(mGeos);
  }

  return null;
}















































var Renderable = (function (Base) {
  return function (_Base) {
    _inheritsLoose(_class, _Base);

    function _class() {
      return _Base.apply(this, arguments) || this;
    }

    _class.registerRenderer = function registerRenderer(name, clazz) {
      var proto = this.prototype;
      var parentProto = Object.getPrototypeOf(proto);

      if (!proto._rendererClasses || proto._rendererClasses === parentProto._rendererClasses) {
        proto._rendererClasses = proto._rendererClasses ? Object.create(proto._rendererClasses) : {};
      }

      proto._rendererClasses[name.toLowerCase()] = clazz;
      return this;
    };

    _class.getRendererClass = function getRendererClass(name) {
      var proto = this.prototype;

      if (!proto._rendererClasses) {
        return null;
      }

      return proto._rendererClasses[name.toLowerCase()];
    };

    return _class;
  }(Base);
});
var IS_NODE = Object.prototype.toString.call(typeof process !== 'undefined' ? process : 0) === '[object process]' && !process.versions['electron'] && !process.versions['nw'] && !process.versions['node-webkit'];
var Browser = {};

// if (!IS_NODE) {
//   var ua = navigator.userAgent.toLowerCase(),
//     doc = document.documentElement,
//     ie = 'ActiveXObject' in window,
//     webkit = ua.indexOf('webkit') !== -1,
//     phantomjs = ua.indexOf('phantom') !== -1,
//     android23 = ua.search('android [23]') !== -1,
//     chrome = ua.indexOf('chrome') !== -1,
//     gecko = ua.indexOf('gecko') !== -1 && !webkit && !window.opera && !ie,
//     mobile = typeof orientation !== 'undefined' || ua.indexOf('mobile') !== -1,
//     msPointer = !window.PointerEvent && window.MSPointerEvent,
//     pointer = window.PointerEvent && navigator.pointerEnabled || msPointer,
//     ie3d = ie && 'transition' in doc.style,
//     webkit3d = 'WebKitCSSMatrix' in window && 'm11' in new window.WebKitCSSMatrix() && !android23,
//     gecko3d = 'MozPerspective' in doc.style,
//     opera12 = 'OTransition' in doc.style,
//     any3d = (ie3d || webkit3d || gecko3d) && !opera12 && !phantomjs;
//   var chromeVersion = 0;

//   if (chrome) {
//     chromeVersion = ua.match(/chrome\/([\d.]+)/)[1];
//   }

//   var touch = !phantomjs && (pointer || 'ontouchstart' in window || window.DocumentTouch && document instanceof window.DocumentTouch);
//   var webgl;

//   try {
//     var canvas = document.createElement('canvas');
//     var gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
//     webgl = gl && gl instanceof WebGLRenderingContext;
//   } catch (err) {
//     webgl = false;
//   }

//   Browser = {
//     ie: ie,
//     ielt9: ie && !document.addEventListener,
//     edge: 'msLaunchUri' in navigator && !('documentMode' in document),
//     webkit: webkit,
//     gecko: gecko,
//     android: ua.indexOf('android') !== -1,
//     android23: android23,
//     chrome: chrome,
//     chromeVersion: chromeVersion,
//     safari: !chrome && ua.indexOf('safari') !== -1,
//     phantomjs: phantomjs,
//     ie3d: ie3d,
//     webkit3d: webkit3d,
//     gecko3d: gecko3d,
//     opera12: opera12,
//     any3d: any3d,
//     mobile: mobile,
//     mobileWebkit: mobile && webkit,
//     mobileWebkit3d: mobile && webkit3d,
//     mobileOpera: mobile && window.opera,
//     mobileGecko: mobile && gecko,
//     touch: !!touch,
//     msPointer: !!msPointer,
//     pointer: !!pointer,
//     retina: (window.devicePixelRatio || window.screen.deviceXDPI / window.screen.logicalXDPI) > 1,
//     language: navigator.browserLanguage ? navigator.browserLanguage : navigator.language,
//     ie9: ie && document.documentMode === 9,
//     ie10: ie && document.documentMode === 10,
//     webgl: webgl
//   };
// }

var Extent = function () {
  function Extent(p1, p2, p3, p4) {
    this._clazz = Coordinate;
    var l = arguments.length;
    var proj = l > 0 ? arguments[l - 1] : null;

    if (proj && proj.unproject) {
      this.projection = arguments[l - 1];
    }

    this._dirty = true;

    this._initialize(p1, p2, p3, p4);
  }

  var _proto = Extent.prototype;

  _proto._initialize = function _initialize(p1, p2, p3, p4) {
    this.xmin = null;
    this.xmax = null;
    this.ymin = null;
    this.ymax = null;

    if (isNil(p1)) {
      return;
    }

    var projection = this.projection;

    if (isNumber(p1) && isNumber(p2) && isNumber(p3) && isNumber(p4)) {
      if (projection) {
        this['xmin'] = p1;
        this['ymin'] = p2;
        this['xmax'] = p3;
        this['ymax'] = p4;
      } else {
        this['xmin'] = Math.min(p1, p3);
        this['ymin'] = Math.min(p2, p4);
        this['xmax'] = Math.max(p1, p3);
        this['ymax'] = Math.max(p2, p4);
      }

      return;
    } else if (Array.isArray(p1)) {
      if (projection) {
        this['xmin'] = p1[0];
        this['ymin'] = p1[1];
        this['xmax'] = p1[2];
        this['ymax'] = p1[3];
      } else {
        this['xmin'] = Math.min(p1[0], p1[2]);
        this['ymin'] = Math.min(p1[1], p1[3]);
        this['xmax'] = Math.max(p1[0], p1[2]);
        this['ymax'] = Math.max(p1[1], p1[3]);
      }
    } else if (isNumber(p1.x) && isNumber(p2.x) && isNumber(p1.y) && isNumber(p2.y)) {
      if (projection) {
        this['xmin'] = p1.x;
        this['ymin'] = p1.y;
        this['xmax'] = p2.x;
        this['ymax'] = p2.y;
      } else {
        if (p1.x > p2.x) {
          this['xmin'] = p2.x;
          this['xmax'] = p1.x;
        } else {
          this['xmin'] = p1.x;
          this['xmax'] = p2.x;
        }

        if (p1.y > p2.y) {
          this['ymin'] = p2.y;
          this['ymax'] = p1.y;
        } else {
          this['ymin'] = p1.y;
          this['ymax'] = p2.y;
        }
      }
    } else if (isNumber(p1['xmin']) && isNumber(p1['xmax']) && isNumber(p1['ymin']) && isNumber(p1['ymax'])) {
      this['xmin'] = p1['xmin'];
      this['ymin'] = p1['ymin'];
      this['xmax'] = p1['xmax'];
      this['ymax'] = p1['ymax'];
    }
  };

  _proto._add = function _add(p) {
    this._dirty = true;

    if (!isNil(p.x)) {
      this['xmin'] += p.x;
      this['ymin'] += p.y;
      this['xmax'] += p.x;
      this['ymax'] += p.y;
    } else if (!isNil(p.xmin)) {
      this['xmin'] += p.xmin;
      this['ymin'] += p.ymin;
      this['xmax'] += p.xmax;
      this['ymax'] += p.ymax;
    } else if (!isNil(p[0])) {
      this['xmin'] += p[0];
      this['ymin'] += p[1];
      this['xmax'] += p[0];
      this['ymax'] += p[1];
    }

    return this;
  };

  _proto.add = function add() {
    var e = new this.constructor(this['xmin'], this['ymin'], this['xmax'], this['ymax'], this.projection);
    return e._add.apply(e, arguments);
  };

  _proto._sub = function _sub(p) {
    this._dirty = true;

    if (!isNil(p.x)) {
      this['xmin'] -= p.x;
      this['ymin'] -= p.y;
      this['xmax'] -= p.x;
      this['ymax'] -= p.y;
    } else if (!isNil(p.xmin)) {
      this['xmin'] -= p.xmin;
      this['ymin'] -= p.ymin;
      this['xmax'] -= p.xmax;
      this['ymax'] -= p.ymax;
    } else if (!isNil(p[0])) {
      this['xmin'] -= p[0];
      this['ymin'] -= p[1];
      this['xmax'] -= p[0];
      this['ymax'] -= p[1];
    }

    return this;
  };

  _proto._substract = function _substract() {
    return this._sub.apply(this, arguments);
  };

  _proto.sub = function sub() {
    var e = new this.constructor(this['xmin'], this['ymin'], this['xmax'], this['ymax'], this.projection);
    return e._sub.apply(e, arguments);
  };

  _proto.substract = function substract() {
    return this.sub.apply(this, arguments);
  };

  _proto.round = function round() {
    return new this.constructor(Math.round(this['xmin']), Math.round(this['ymin']), Math.round(this['xmax']), Math.round(this['ymax']), this.projection);
  };

  _proto._round = function _round() {
    this._dirty = true;
    this['xmin'] = Math.round(this['xmin']);
    this['ymin'] = Math.round(this['ymin']);
    this['xmax'] = Math.round(this['xmax']);
    this['ymax'] = Math.round(this['ymax']);
    return this;
  };

  _proto.getMin = function getMin() {
    return new this._clazz(this['xmin'], this['ymin']);
  };

  _proto.getMax = function getMax() {
    return new this._clazz(this['xmax'], this['ymax']);
  };

  _proto.getCenter = function getCenter() {
    return new this._clazz((this['xmin'] + this['xmax']) / 2, (this['ymin'] + this['ymax']) / 2);
  };

  _proto.isValid = function isValid() {
    return isNumber(this['xmin']) && isNumber(this['ymin']) && isNumber(this['xmax']) && isNumber(this['ymax']);
  };

  _proto.equals = function equals(ext2) {
    return this['xmin'] === ext2['xmin'] && this['xmax'] === ext2['xmax'] && this['ymin'] === ext2['ymin'] && this['ymax'] === ext2['ymax'];
  };

  _proto.intersects = function intersects(ext2) {
    this._project(this);

    this._project(ext2);

    var rxmin = Math.max(this['pxmin'], ext2['pxmin']);
    var rymin = Math.max(this['pymin'], ext2['pymin']);
    var rxmax = Math.min(this['pxmax'], ext2['pxmax']);
    var rymax = Math.min(this['pymax'], ext2['pymax']);
    var intersects = !(rxmin > rxmax || rymin > rymax);
    return intersects;
  };

  _proto.within = function within(extent) {
    this._project(this);

    this._project(extent);

    return this.pxmin >= extent.pxmin && this.pxmax <= extent.pxmax && this.pymin >= extent.pymin && this.pymax <= extent.pymax;
  };

  _proto.contains = function contains(c) {
    if (!c) {
      return false;
    }

    this._project(this);

    var proj = this.projection;

    if (Array.isArray(c)) {
      c = new this._clazz(c);
    }

    if (proj) {
      c = proj.project(c);
    }

    return c.x >= this.pxmin && c.x <= this.pxmax && c.y >= this.pymin && c.y <= this.pymax;
  };

  _proto.getWidth = function getWidth() {
    return Math.abs(this['xmax'] - this['xmin']);
  };

  _proto.getHeight = function getHeight() {
    return Math.abs(this['ymax'] - this['ymin']);
  };

  _proto.getSize = function getSize() {
    return new Size(this.getWidth(), this.getHeight());
  };

  _proto.__combine = function __combine(extent) {
    if (!(extent instanceof this.constructor)) {
      extent = new this.constructor(extent, extent);
    }

    this._project(extent);

    this._project(this);

    var xmin = this['pxmin'];

    if (!isNumber(xmin)) {
      xmin = extent['pxmin'];
    } else if (isNumber(extent['pxmin'])) {
      if (xmin > extent['pxmin']) {
        xmin = extent['pxmin'];
      }
    }

    var xmax = this['pxmax'];

    if (!isNumber(xmax)) {
      xmax = extent['pxmax'];
    } else if (isNumber(extent['pxmax'])) {
      if (xmax < extent['pxmax']) {
        xmax = extent['pxmax'];
      }
    }

    var ymin = this['pymin'];

    if (!isNumber(ymin)) {
      ymin = extent['pymin'];
    } else if (isNumber(extent['pymin'])) {
      if (ymin > extent['pymin']) {
        ymin = extent['pymin'];
      }
    }

    var ymax = this['pymax'];

    if (!isNumber(ymax)) {
      ymax = extent['pymax'];
    } else if (isNumber(extent['pymax'])) {
      if (ymax < extent['pymax']) {
        ymax = extent['pymax'];
      }
    }

    var proj = this.projection;

    if (proj) {
      var min = proj.unproject(new this._clazz(xmin, ymin)),
        max = proj.unproject(new this._clazz(xmax, ymax));
      xmin = min.x;
      ymin = min.y;
      xmax = max.x;
      ymax = max.y;
    }

    return [xmin, ymin, xmax, ymax];
  };

  _proto._combine = function _combine(extent) {
    if (!extent) {
      return this;
    }

    var ext = this.__combine(extent);

    this['xmin'] = ext[0];
    this['ymin'] = ext[1];
    this['xmax'] = ext[2];
    this['ymax'] = ext[3];
    this._dirty = true;
    return this;
  };

  _proto.combine = function combine(extent) {
    if (!extent) {
      return this;
    }

    var ext = this.__combine(extent);

    return new this.constructor(ext[0], ext[1], ext[2], ext[3], this.projection);
  };

  _proto.intersection = function intersection(extent) {
    if (!this.intersects(extent)) {
      return null;
    }

    var min = new this._clazz(Math.max(this['pxmin'], extent['pxmin']), Math.max(this['pymin'], extent['pymin'])),
      max = new this._clazz(Math.min(this['pxmax'], extent['pxmax']), Math.min(this['pymax'], extent['pymax']));
    var proj = this.projection;

    if (proj) {
      min = proj.unproject(min);
      max = proj.unproject(max);
    }

    return new this.constructor(min, max, proj);
  };

  _proto.expand = function expand(distance) {
    var w, h;

    if (!isNumber(distance)) {
      w = distance['width'] || distance['x'] || distance[0] || 0;
      h = distance['height'] || distance['y'] || distance[1] || 0;
    } else {
      w = h = distance;
    }

    return new this.constructor(this['xmin'] - w, this['ymin'] - h, this['xmax'] + w, this['ymax'] + h, this.projection);
  };

  _proto._expand = function _expand(distance) {
    var w, h;

    if (!isNumber(distance)) {
      w = distance['width'] || distance['x'] || distance[0] || 0;
      h = distance['height'] || distance['y'] || distance[1] || 0;
    } else {
      w = h = distance;
    }

    this['xmin'] -= w;
    this['ymin'] -= h;
    this['xmax'] += w;
    this['ymax'] += h;
    this._dirty = true;
    return this;
  };

  _proto.toJSON = function toJSON() {
    return {
      'xmin': this['xmin'],
      'ymin': this['ymin'],
      'xmax': this['xmax'],
      'ymax': this['ymax']
    };
  };

  _proto.toArray = function toArray() {
    var xmin = this['xmin'],
      ymin = this['ymin'],
      xmax = this['xmax'],
      ymax = this['ymax'];
    return [new this._clazz([xmin, ymax]), new this._clazz([xmax, ymax]), new this._clazz([xmax, ymin]), new this._clazz([xmin, ymin]), new this._clazz([xmin, ymax])];
  };

  _proto.toString = function toString() {
    return this.xmin + "," + this.ymin + "," + this.xmax + "," + this.ymax;
  };

  _proto.copy = function copy() {
    return new this.constructor(this['xmin'], this['ymin'], this['xmax'], this['ymax'], this.projection);
  };

  _proto.convertTo = function convertTo(fn) {
    if (!this.isValid()) {
      return null;
    }

    var e = new this.constructor();
    var coord = new this._clazz(this.xmin, this.ymax);

    e._combine(fn(coord));

    coord.x = this.xmax;

    e._combine(fn(coord));

    coord.y = this.ymin;

    e._combine(fn(coord));

    coord.x = this.xmin;

    e._combine(fn(coord));

    return e;
  };

  _proto._project = function _project(ext) {
    if (!ext || !ext.isValid()) {
      return;
    }

    var proj = this.projection;

    if (proj) {
      if (ext._dirty) {
        var minmax = [ext.getMin(), ext.getMax()];
        minmax = proj.projectCoords(minmax);
        var min = minmax[0],
          max = minmax[1];
        ext.pxmin = Math.min(min.x, max.x);
        ext.pymin = Math.min(min.y, max.y);
        ext.pxmax = Math.max(min.x, max.x);
        ext.pymax = Math.max(min.y, max.y);
      }

      delete ext._dirty;
    } else {
      ext.pxmin = ext.xmin;
      ext.pxmax = ext.xmax;
      ext.pymin = ext.ymin;
      ext.pymax = ext.ymax;
    }
  };

  return Extent;
}();

var Transformation = function () {
  function Transformation(matrix) {
    this.matrix = matrix;
  }

  var _proto = Transformation.prototype;

  _proto.transform = function transform(coordinates, scale) {
    return new Point(this.matrix[0] * (coordinates.x - this.matrix[2]) / scale, this.matrix[1] * (coordinates.y - this.matrix[3]) / scale);
  };

  _proto.untransform = function untransform(point, scale) {
    return new Coordinate(point.x * scale / this.matrix[0] + this.matrix[2], point.y * scale / this.matrix[1] + this.matrix[3]);
  };

  return Transformation;
}();

var Browser$1 = Browser;
var options$1 = {
  'maxVisualPitch': 60,
  'maxPitch': 80,
  'centerCross': false,
  'zoomInCenter': false,
  'zoomAnimation': function () {
    return !IS_NODE;
  }(),
  'zoomAnimationDuration': 330,
  'panAnimation': function () {
    return !IS_NODE;
  }(),
  'panAnimationDuration': 600,
  'zoomable': true,
  'enableInfoWindow': true,
  'hitDetect': function () {
    return false;
  }(),
  'hitDetectLimit': 5,
  'fpsOnInteracting': 25,
  'layerCanvasLimitOnInteracting': -1,
  'maxZoom': null,
  'minZoom': null,
  'maxExtent': null,
  'checkSize': true,
  'renderer': 'canvas'
};

var Map$1 = function (_Handlerable) {
  _inheritsLoose(Map, _Handlerable);

  function Map(container, options) {
    var _this;

    if (!options) {
      throw new Error('Invalid options when creating map.');
    }

    if (!options['center']) {
      throw new Error('Invalid center when creating map.');
    }

    var opts = extend({}, options);
    var zoom = opts['zoom'];
    delete opts['zoom'];
    var center = new Coordinate(opts['center']);
    delete opts['center'];
    var baseLayer = opts['baseLayer'];
    delete opts['baseLayer'];
    var layers = opts['layers'];
    delete opts['layers'];
    _this = _Handlerable.call(this, opts) || this;
    Object.defineProperty(_assertThisInitialized(_assertThisInitialized(_this)), 'id', {
      value: UID(),
      writable: false
    });
    _this._loaded = false;

    // _this._initContainer(container);

    _this._panels = {};
    _this._baseLayer = null;
    _this._layers = [];
    _this._zoomLevel = zoom;
    _this._center = center;

    _this.setSpatialReference(opts['spatialReference'] || opts['view']);

    _this._mapViewPoint = new Point(0, 0);

    // _this._initRenderer();

    // _this._updateMapSize(_this._getContainerDomSize());

    // if (baseLayer) {
    //   _this.setBaseLayer(baseLayer);
    // }

    // if (layers) {
    //   _this.addLayer(layers);
    // }

    // _this._Load();

    return _this;
  }

  Map.addOnLoadHook = function addOnLoadHook(fn) {
    var args = Array.prototype.slice.call(arguments, 1);
    var onload = typeof fn === 'function' ? fn : function () {
      this[fn].apply(this, args);
    };
    this.prototype._onLoadHooks = this.prototype._onLoadHooks || [];

    this.prototype._onLoadHooks.push(onload);

    return this;
  };

  var _proto = Map.prototype;

  _proto.isLoaded = function isLoaded() {
    return !!this._loaded;
  };

  _proto.getContainer = function getContainer() {
    return this._containerDOM;
  };

  _proto.getSpatialReference = function getSpatialReference() {
    return this._spatialReference;
  };

  _proto.setSpatialReference = function setSpatialReference(ref) {
    var oldRef = this.options['spatialReference'];

    if (this._loaded && SpatialReference.equals(oldRef, ref)) {
      return this;
    }

    ref = extend({}, ref);
    this._center = this.getCenter();
    this.options['spatialReference'] = ref;
    this._spatialReference = new SpatialReference(ref);

    if (this.options['spatialReference'] && isFunction(this.options['spatialReference']['projection'])) {
      var projection = this._spatialReference.getProjection();

      this.options['spatialReference']['projection'] = projection['code'];
    }

    this._resetMapStatus();

    this._fireEvent('spatialreferencechange', {
      'old': oldRef,
      'new': extend({}, this.options['spatialReference'])
    });

    return this;
  };

  _proto.onConfig = function onConfig(conf) {
    var ref = conf['spatialReference'] || conf['view'];

    if (!isNil(ref)) {
      this.setSpatialReference(ref);
    }

    return this;
  };

  _proto.getProjection = function getProjection() {
    if (!this._spatialReference) {
      return null;
    }

    return this._spatialReference.getProjection();
  };

  _proto.getFullExtent = function getFullExtent() {
    if (!this._spatialReference) {
      return null;
    }

    return this._spatialReference.getFullExtent();
  };

  _proto.setCursor = function setCursor(cursor) {
    delete this._cursor;

    this._trySetCursor(cursor);

    this._cursor = cursor;
    return this;
  };

  _proto.resetCursor = function resetCursor() {
    return this.setCursor(null);
  };

  _proto.getCenter = function getCenter() {
    if (!this._loaded || !this._prjCenter) {
      return this._center;
    }

    var projection = this.getProjection();
    return projection.unproject(this._prjCenter);
  };

  _proto.setCenter = function setCenter(center) {
    if (!center) {
      return this;
    }

    center = new Coordinate(center);

    if (!this._verifyExtent(center)) {
      return this;
    }

    if (!this._loaded) {
      this._center = center;
      return this;
    }

    this.onMoveStart();
    var projection = this.getProjection();

    var _pcenter = projection.project(center);

    this._setPrjCenter(_pcenter);

    this.onMoveEnd(this._parseEventFromCoord(this.getCenter()));
    return this;
  };

  _proto.getSize = function getSize() {
    if (isNil(this.width) || isNil(this.height)) {
      return this._getContainerDomSize();
    }

    return new Size(this.width, this.height);
  };

  _proto.getContainerExtent = function getContainerExtent() {
    var visualHeight = this.height;
    var pitch = this.getPitch(),
      maxVisualPitch = this.options['maxVisualPitch'];

    if (maxVisualPitch && pitch > maxVisualPitch) {
      visualHeight = this._getVisualHeight(maxVisualPitch);
    }

    return new PointExtent(0, this.height - visualHeight, this.width, this.height);
  };

  _proto._getVisualHeight = function _getVisualHeight(maxVisualPitch) {
    var pitch = this.getPitch();
    var visualDistance = this.height / 2 * Math.tan(maxVisualPitch * Math.PI / 180);
    return this.height / 2 + visualDistance * Math.tan((90 - pitch) * Math.PI / 180);
  };

  _proto.getExtent = function getExtent() {
    return this._pointToExtent(this._get2DExtent());
  };

  _proto.getProjExtent = function getProjExtent() {
    var extent2D = this._get2DExtent();

    return new Extent(this._pointToPrj(extent2D.getMin()), this._pointToPrj(extent2D.getMax()));
  };

  _proto.getPrjExtent = function getPrjExtent() {
    return this.getProjExtent();
  };

  _proto.getMaxExtent = function getMaxExtent() {
    if (!this.options['maxExtent']) {
      return null;
    }

    return new Extent(this.options['maxExtent'], this.getProjection());
  };

  _proto.setMaxExtent = function setMaxExtent(extent) {
    if (extent) {
      var maxExt = new Extent(extent, this.getProjection());
      this.options['maxExtent'] = maxExt;
      var center = this.getCenter();

      if (!this._verifyExtent(center)) {
        this.panTo(maxExt.getCenter());
      }
    } else {
      delete this.options['maxExtent'];
    }

    return this;
  };

  _proto.getZoom = function getZoom() {
    return this._zoomLevel;
  };

  _proto.getZoomForScale = function getZoomForScale(scale, fromZoom, isFraction) {
    var zoom = this.getZoom();

    if (isNil(fromZoom)) {
      fromZoom = zoom;
    }

    if (scale === 1 && fromZoom === zoom) {
      return zoom;
    }

    var res = this._getResolution(fromZoom),
      targetRes = res / scale;

    var scaleZoom = this.getZoomFromRes(targetRes);

    if (isFraction) {
      return scaleZoom;
    } else {
      var delta = 1E-6;
      return this.getSpatialReference().getZoomDirection() < 0 ? Math.ceil(scaleZoom - delta) : Math.floor(scaleZoom + delta);
    }
  };

  _proto.getZoomFromRes = function getZoomFromRes(res) {
    var resolutions = this._getResolutions(),
      minRes = this._getResolution(this.getMinZoom()),
      maxRes = this._getResolution(this.getMaxZoom());

    if (minRes <= maxRes) {
      if (res <= minRes) {
        return this.getMinZoom();
      } else if (res >= maxRes) {
        return this.getMaxZoom();
      }
    } else if (res >= minRes) {
      return this.getMinZoom();
    } else if (res <= maxRes) {
      return this.getMaxZoom();
    }

    var l = resolutions.length;

    for (var i = 0; i < l - 1; i++) {
      if (!resolutions[i]) {
        continue;
      }

      var gap = resolutions[i + 1] - resolutions[i];
      var test = res - resolutions[i];

      if (sign(gap) === sign(test) && Math.abs(gap) >= Math.abs(test)) {
        return i + test / gap;
      }
    }

    return l - 1;
  };

  _proto.setZoom = function setZoom(zoom, options) {
    if (options === void 0) {
      options = {
        'animation': true
      };
    }

    if (isNaN(zoom) || isNil(zoom)) {
      return this;
    }

    if (this._loaded && this.options['zoomAnimation'] && options['animation']) {
      this._zoomAnimation(zoom);
    } else {
      this._zoom(zoom);
    }

    return this;
  };

  _proto.getMaxZoom = function getMaxZoom() {
    if (!isNil(this.options['maxZoom'])) {
      return this.options['maxZoom'];
    }

    return this.getMaxNativeZoom();
  };

  _proto.setMaxZoom = function setMaxZoom(maxZoom) {
    var viewMaxZoom = this.getMaxNativeZoom();

    if (maxZoom > viewMaxZoom) {
      maxZoom = viewMaxZoom;
    }

    if (maxZoom !== null && maxZoom < this._zoomLevel) {
      this.setZoom(maxZoom);
    }

    this.options['maxZoom'] = maxZoom;
    return this;
  };

  _proto.getMinZoom = function getMinZoom() {
    if (!isNil(this.options['minZoom'])) {
      return this.options['minZoom'];
    }

    return this._spatialReference.getMinZoom();
  };

  _proto.setMinZoom = function setMinZoom(minZoom) {
    if (minZoom !== null) {
      var viewMinZoom = this._spatialReference.getMinZoom();

      if (minZoom < viewMinZoom) {
        minZoom = viewMinZoom;
      }

      if (minZoom > this._zoomLevel) {
        this.setZoom(minZoom);
      }
    }

    this.options['minZoom'] = minZoom;
    return this;
  };

  _proto.getMaxNativeZoom = function getMaxNativeZoom() {
    var ref = this.getSpatialReference();

    if (!ref) {
      return null;
    }

    return ref.getMaxZoom();
  };

  _proto.getGLZoom = function getGLZoom() {
    return this.getMaxNativeZoom() / 2;
  };

  _proto.getGLScale = function getGLScale(zoom) {
    if (isNil(zoom)) {
      zoom = this.getZoom();
    }

    return this.getScale(zoom) / this.getScale(this.getGLZoom());
  };

  _proto.zoomIn = function zoomIn() {
    return this.setZoom(this.getZoom() + 1);
  };

  _proto.zoomOut = function zoomOut() {
    return this.setZoom(this.getZoom() - 1);
  };

  _proto.isZooming = function isZooming() {
    return !!this._zooming;
  };

  _proto.isInteracting = function isInteracting() {
    return this.isZooming() || this.isMoving() || this.isRotating();
  };

  _proto.setCenterAndZoom = function setCenterAndZoom(center, zoom) {
    if (!isNil(zoom) && this._zoomLevel !== zoom) {
      this.setCenter(center);
      this.setZoom(zoom, {
        animation: false
      });
    } else {
      this.setCenter(center);
    }

    return this;
  };

  _proto.getFitZoom = function getFitZoom(extent) {
    var _this2 = this;

    if (!extent || !(extent instanceof Extent)) {
      return this._zoomLevel;
    }

    if (extent['xmin'] === extent['xmax'] && extent['ymin'] === extent['ymax']) {
      return this.getMaxZoom();
    }

    var size = this.getSize();
    var containerExtent = extent.convertTo(function (p) {
      return _this2.coordToContainerPoint(p);
    });
    var w = containerExtent.getWidth(),
      h = containerExtent.getHeight();
    var scaleX = size['width'] / w,
      scaleY = size['height'] / h;
    var scale = this.getSpatialReference().getZoomDirection() < 0 ? Math.max(scaleX, scaleY) : Math.min(scaleX, scaleY);
    var zoom = this.getZoomForScale(scale);
    return zoom;
  };

  _proto.getView = function getView() {
    return {
      'center': this.getCenter().toArray(),
      'zoom': this.getZoom(),
      'pitch': this.getPitch(),
      'bearing': this.getBearing()
    };
  };

  _proto.setView = function setView(view) {
    if (!view) {
      return this;
    }

    if (view['center']) {
      this.setCenter(view['center']);
    }

    if (view['zoom']) {
      this.setZoom(view['zoom'], {
        'animation': false
      });
    }

    if (view['pitch']) {
      this.setPitch(view['pitch']);
    }

    if (view['bearing']) {
      this.setBearing(view['bearing']);
    }

    return this;
  };

  _proto.getResolution = function getResolution(zoom) {
    return this._getResolution(zoom);
  };

  _proto.getScale = function getScale(zoom) {
    var z = isNil(zoom) ? this.getZoom() : zoom;

    var max = this._getResolution(this.getMaxNativeZoom()),
      res = this._getResolution(z);

    return res / max;
  };

  _proto.fitExtent = function fitExtent(extent, zoomOffset, options, step) {
    if (options === void 0) {
      options = {};
    }

    if (!extent) {
      return this;
    }

    extent = new Extent(extent, this.getProjection());
    var zoom = this.getFitZoom(extent) + (zoomOffset || 0);
    var center = extent.getCenter();
    if (typeof options['animation'] === 'undefined' || options['animation']) return this.animateTo({
      center: center,
      zoom: zoom
    }, {
        'duration': options['duration'] || this.options['zoomAnimationDuration'],
        'easing': options['easing'] || 'out'
      }, step); else return this.setCenterAndZoom(center, zoom);
  };

  _proto.getBaseLayer = function getBaseLayer() {
    return this._baseLayer;
  };

  _proto.setBaseLayer = function setBaseLayer(baseLayer) {
    var isChange = false;

    if (this._baseLayer) {
      isChange = true;

      this._fireEvent('baselayerchangestart');

      this._baseLayer.remove();
    }

    if (!baseLayer) {
      delete this._baseLayer;

      this._fireEvent('baselayerchangeend');

      this._fireEvent('setbaselayer');

      return this;
    }

    this._baseLayer = baseLayer;

    baseLayer._bindMap(this, -1);

    function onbaseLayerload() {
      this._fireEvent('baselayerload');

      if (isChange) {
        isChange = false;

        this._fireEvent('baselayerchangeend');
      }
    }

    this._baseLayer.on('layerload', onbaseLayerload, this);

    if (this._loaded) {
      this._baseLayer.load();
    }

    this._fireEvent('setbaselayer');

    return this;
  };

  _proto.removeBaseLayer = function removeBaseLayer() {
    if (this._baseLayer) {
      this._baseLayer.remove();

      delete this._baseLayer;

      this._fireEvent('baselayerremove');
    }

    return this;
  };

  _proto.getLayers = function getLayers(filter) {
    return this._getLayers(function (layer) {
      if (layer === this._baseLayer || layer.getId().indexOf(INTERNAL_LAYER_PREFIX) >= 0) {
        return false;
      }

      if (filter) {
        return filter(layer);
      }

      return true;
    });
  };

  _proto.getLayer = function getLayer(id) {
    if (!id) {
      return null;
    }

    var layer = this._layerCache ? this._layerCache[id] : null;

    if (layer) {
      return layer;
    }

    var baseLayer = this.getBaseLayer();

    if (baseLayer && baseLayer.getId() === id) {
      return baseLayer;
    }

    return null;
  };

  _proto.addLayer = function addLayer(layers) {
    if (!layers) {
      return this;
    }

    if (!Array.isArray(layers)) {
      layers = Array.prototype.slice.call(arguments, 0);
      return this.addLayer(layers);
    }

    if (!this._layerCache) {
      this._layerCache = {};
    }

    var mapLayers = this._layers;

    for (var i = 0, len = layers.length; i < len; i++) {
      var layer = layers[i];
      var id = layer.getId();

      if (isNil(id)) {
        throw new Error('Invalid id for the layer: ' + id);
      }

      if (layer.getMap() === this) {
        continue;
      }

      if (this._layerCache[id]) {
        throw new Error('Duplicate layer id in the map: ' + id);
      }

      this._layerCache[id] = layer;

      layer._bindMap(this);

      mapLayers.push(layer);

      if (this._loaded) {
        layer.load();
      }
    }

    this._sortLayersByZIndex();

    this._fireEvent('addlayer', {
      'layers': layers
    });

    return this;
  };

  _proto.removeLayer = function removeLayer(layers) {
    if (!layers) {
      return this;
    }

    if (!Array.isArray(layers)) {
      return this.removeLayer([layers]);
    }

    var removed = [];

    for (var i = 0, len = layers.length; i < len; i++) {
      var layer = layers[i];

      if (!(layer instanceof Layer)) {
        layer = this.getLayer(layer);
      }

      if (!layer) {
        continue;
      }

      var map = layer.getMap();

      if (!map || map !== this) {
        continue;
      }

      removed.push(layer);

      this._removeLayer(layer, this._layers);

      if (this._loaded) {
        layer._doRemove();
      }

      var id = layer.getId();

      if (this._layerCache) {
        delete this._layerCache[id];
      }
    }

    if (removed.length > 0) {
      this.once('frameend', function () {
        removed.forEach(function (layer) {
          layer.fire('remove');
        });
      });
    }

    this._fireEvent('removelayer', {
      'layers': layers
    });

    return this;
  };

  _proto.sortLayers = function sortLayers(layers) {
    if (!layers || !Array.isArray(layers)) {
      return this;
    }

    var layersToOrder = [];
    var minZ = Number.MAX_VALUE;

    for (var i = 0, l = layers.length; i < l; i++) {
      var layer = layers[i];

      if (isString(layers[i])) {
        layer = this.getLayer(layer);
      }

      if (!(layer instanceof Layer) || !layer.getMap() || layer.getMap() !== this) {
        throw new Error('It must be a layer added to this map to order.');
      }

      if (layer.getZIndex() < minZ) {
        minZ = layer.getZIndex();
      }

      layersToOrder.push(layer);
    }

    for (var _i = 0, _l = layersToOrder.length; _i < _l; _i++) {
      layersToOrder[_i].setZIndex(minZ + _i);
    }

    return this;
  };

  _proto.toDataURL = function toDataURL(options) {
    if (!options) {
      options = {};
    }

    var mimeType = options['mimeType'];

    if (!mimeType) {
      mimeType = 'image/png';
    }

    var save = options['save'];

    var renderer = this._getRenderer();

    if (renderer && renderer.toDataURL) {
      var file = options['fileName'];

      if (!file) {
        file = 'export';
      }

      var dataURL = renderer.toDataURL(mimeType);

      if (save && dataURL) {
        var imgURL;

        if (typeof Blob !== 'undefined' && typeof atob !== 'undefined') {
          var blob = b64toBlob(dataURL.replace(/^data:image\/(png|jpeg|jpg);base64,/, ''), mimeType);
          imgURL = URL.createObjectURL(blob);
        } else {
          imgURL = dataURL;
        }

        var dlLink = document.createElement('a');
        dlLink.download = file;
        dlLink.href = imgURL;
        document.body.appendChild(dlLink);
        dlLink.click();
        document.body.removeChild(dlLink);
      }

      return dataURL;
    }

    return null;
  };

  _proto.coordinateToPoint = function coordinateToPoint(coordinate, zoom) {
    var prjCoord = this.getProjection().project(coordinate);
    return this._prjToPoint(prjCoord, zoom);
  };

  _proto.coordToPoint = function coordToPoint(coordinate, zoom) {
    return this.coordinateToPoint(coordinate, zoom);
  };

  _proto.pointToCoordinate = function pointToCoordinate(point, zoom) {
    var prjCoord = this._pointToPrj(point, zoom);

    return this.getProjection().unproject(prjCoord);
  };

  _proto.pointToCoord = function pointToCoord(point, zoom) {
    return this.pointToCoordinate(point, zoom);
  };

  _proto.coordinateToViewPoint = function coordinateToViewPoint(coordinate) {
    return this._prjToViewPoint(this.getProjection().project(coordinate));
  };

  _proto.coordToViewPoint = function coordToViewPoint(coordinate) {
    return this.coordinateToViewPoint(coordinate);
  };

  _proto.viewPointToCoordinate = function viewPointToCoordinate(viewPoint) {
    return this.getProjection().unproject(this._viewPointToPrj(viewPoint));
  };

  _proto.viewPointToCoord = function viewPointToCoord(viewPoint) {
    return this.viewPointToCoordinate(viewPoint);
  };

  _proto.coordinateToContainerPoint = function coordinateToContainerPoint(coordinate, zoom) {
    var pCoordinate = this.getProjection().project(coordinate);
    return this._prjToContainerPoint(pCoordinate, zoom);
  };

  _proto.coordToContainerPoint = function coordToContainerPoint(coordinate, zoom) {
    return this.coordinateToContainerPoint(coordinate, zoom);
  };

  _proto.containerPointToCoordinate = function containerPointToCoordinate(containerPoint) {
    var pCoordinate = this._containerPointToPrj(containerPoint);

    return this.getProjection().unproject(pCoordinate);
  };

  _proto.containerPointToCoord = function containerPointToCoord(containerPoint) {
    return this.containerPointToCoordinate(containerPoint);
  };

  _proto.containerPointToViewPoint = function containerPointToViewPoint(containerPoint) {
    return containerPoint.sub(this.getViewPoint());
  };

  _proto.viewPointToContainerPoint = function viewPointToContainerPoint(viewPoint) {
    return viewPoint.add(this.getViewPoint());
  };

  _proto.containerToExtent = function containerToExtent(containerExtent) {
    var extent2D = new PointExtent(this._containerPointToPoint(containerExtent.getMin()), this._containerPointToPoint(containerExtent.getMax()));
    return this._pointToExtent(extent2D);
  };

  _proto.checkSize = function checkSize() {
    var justStart = now() - this._initTime < 1500 && this.width === 0 || this.height === 0;

    var watched = this._getContainerDomSize(),
      oldHeight = this.height,
      oldWidth = this.width;

    if (watched['width'] === oldWidth && watched['height'] === oldHeight) {
      return this;
    }

    var center = this.getCenter();

    this._updateMapSize(watched);

    var resizeOffset = new Point((oldWidth - watched.width) / 2, (oldHeight - watched.height) / 2);

    this._offsetCenterByPixel(resizeOffset);

    this._mapViewCoord = this._getPrjCenter();
    var hided = watched['width'] === 0 || watched['height'] === 0 || oldWidth === 0 || oldHeight === 0;

    if (justStart || hided) {
      this._noEvent = true;
      this.setCenter(center);
      delete this._noEvent;
    }

    this._fireEvent('resize');

    return this;
  };

  _proto.distanceToPixel = function distanceToPixel(xDist, yDist, zoom) {
    var projection = this.getProjection();

    if (!projection) {
      return null;
    }

    var scale = this.getScale() / this.getScale(zoom);
    var center = this.getCenter(),
      target = projection.locate(center, xDist, yDist);
    var p0 = this.coordToContainerPoint(center),
      p1 = this.coordToContainerPoint(target);

    p1._sub(p0)._multi(scale)._abs();

    return new Size(p1.x, p1.y);
  };

  _proto.distanceToPoint = function distanceToPoint(xDist, yDist, zoom) {
    var projection = this.getProjection();

    if (!projection) {
      return null;
    }

    var center = this.getCenter(),
      target = projection.locate(center, xDist, yDist);
    var p0 = this.coordToPoint(center, zoom),
      p1 = this.coordToPoint(target, zoom);

    p1._sub(p0)._abs();

    return p1;
  };

  _proto.pixelToDistance = function pixelToDistance(width, height) {
    var projection = this.getProjection();

    if (!projection) {
      return null;
    }

    var fullExt = this.getFullExtent();
    var d = fullExt['top'] > fullExt['bottom'] ? -1 : 1;
    var target = new Point(this.width / 2 + width, this.height / 2 + d * height);
    var coord = this.containerPointToCoord(target);
    return projection.measureLength(this.getCenter(), coord);
  };

  _proto.pointToDistance = function pointToDistance(dx, dy, zoom) {
    var projection = this.getProjection();

    if (!projection) {
      return null;
    }

    var c = this._prjToPoint(this._getPrjCenter(), zoom);

    c._add(dx, dy);

    var target = this.pointToCoord(c, zoom);
    return projection.measureLength(this.getCenter(), target);
  };

  _proto.locate = function locate(coordinate, dx, dy) {
    return this.getProjection()._locate(new Coordinate(coordinate), dx, dy);
  };

  _proto.locateByPoint = function locateByPoint(coordinate, px, py) {
    var point = this.coordToContainerPoint(coordinate);
    return this.containerPointToCoord(point._add(px, py));
  };

  _proto.getMainPanel = function getMainPanel() {
    return this._getRenderer().getMainPanel();
  };

  _proto.getPanels = function getPanels() {
    return this._panels;
  };

  _proto.remove = function remove() {
    if (this.isRemoved()) {
      return this;
    }

    this._fireEvent('removestart');

    this._removeDomEvents();

    this._clearHandlers();

    this.removeBaseLayer();
    var layers = this.getLayers();

    for (var i = 0; i < layers.length; i++) {
      layers[i].remove();
    }

    if (this._getRenderer()) {
      this._getRenderer().remove();
    }

    if (this._containerDOM.innerHTML) {
      this._containerDOM.innerHTML = '';
    }

    delete this._panels;
    delete this._containerDOM;
    delete this.renderer;

    this._fireEvent('removeend');

    this._clearAllListeners();

    return this;
  };

  _proto.isRemoved = function isRemoved() {
    return !this._containerDOM;
  };

  _proto.isMoving = function isMoving() {
    return !!this._moving;
  };

  _proto.onMoveStart = function onMoveStart(param) {
    this._originCenter = this.getCenter();
    this._moving = true;

    this._trySetCursor('move');

    this._fireEvent('movestart', this._parseEvent(param ? param['domEvent'] : null, 'movestart'));
  };

  _proto.onMoving = function onMoving(param) {
    this._fireEvent('moving', this._parseEvent(param ? param['domEvent'] : null, 'moving'));
  };

  _proto.onMoveEnd = function onMoveEnd(param) {
    this._moving = false;

    this._trySetCursor('default');

    this._fireEvent('moveend', param && param['domEvent'] ? this._parseEvent(param['domEvent'], 'moveend') : param);

    if (!this._verifyExtent(this.getCenter())) {
      var moveTo = this._originCenter;

      if (!this._verifyExtent(moveTo)) {
        moveTo = this.getMaxExtent().getCenter();
      }

      this.panTo(moveTo);
    }
  };

  _proto.onDragRotateStart = function onDragRotateStart(param) {
    this._dragRotating = true;

    this._fireEvent('dragrotatestart', this._parseEvent(param ? param['domEvent'] : null, 'dragrotatestart'));
  };

  _proto.onDragRotating = function onDragRotating(param) {
    this._fireEvent('dragrotating', this._parseEvent(param ? param['domEvent'] : null, 'dragrotating'));
  };

  _proto.onDragRotateEnd = function onDragRotateEnd(param) {
    this._dragRotating = false;

    this._fireEvent('dragrotateend', this._parseEvent(param ? param['domEvent'] : null, 'dragrotateend'));
  };

  _proto.isDragRotating = function isDragRotating() {
    return !!this._dragRotating;
  };

  _proto.getRenderer = function getRenderer() {
    return this._getRenderer();
  };

  _proto._initContainer = function _initContainer(container) {
    if (isString(container)) {
      this._containerDOM = document.getElementById(container);

      if (!this._containerDOM) {
        throw new Error('Invalid container when creating map: \'' + container + '\'');
      }
    } else {
      this._containerDOM = container;

      if (IS_NODE) {
        this.CanvasClass = this._containerDOM.constructor;
      }
    }

    if (this._containerDOM.childNodes && this._containerDOM.childNodes.length > 0) {
      if (this._containerDOM.childNodes[0].className === 'maptalks-wrapper') {
        throw new Error('Container is already loaded with another map instance, use map.remove() to clear it.');
      }
    }
  };

  _proto._trySetCursor = function _trySetCursor(cursor) {
    if (!this._cursor && !this._priorityCursor) {
      if (!cursor) {
        cursor = 'default';
      }

      this._setCursorToPanel(cursor);
    }

    return this;
  };

  _proto._setPriorityCursor = function _setPriorityCursor(cursor) {
    if (!cursor) {
      var hasCursor = false;

      if (this._priorityCursor) {
        hasCursor = true;
      }

      delete this._priorityCursor;

      if (hasCursor) {
        this.setCursor(this._cursor);
      }
    } else {
      this._priorityCursor = cursor;

      this._setCursorToPanel(cursor);
    }

    return this;
  };

  _proto._setCursorToPanel = function _setCursorToPanel(cursor) {
    var panel = this.getMainPanel();

    if (panel && panel.style && panel.style.cursor !== cursor) {
      panel.style.cursor = cursor;
    }
  };

  _proto._get2DExtent = function _get2DExtent(zoom) {
    var _this3 = this;

    var cExtent = this.getContainerExtent();
    return cExtent.convertTo(function (c) {
      return _this3._containerPointToPoint(c, zoom);
    });
  };

  _proto._pointToExtent = function _pointToExtent(extent2D) {
    var min2d = extent2D.getMin(),
      max2d = extent2D.getMax();
    var fullExtent = this.getFullExtent();

    var _ref = !fullExtent || fullExtent.left <= fullExtent.right ? [min2d.x, max2d.x] : [max2d.x, min2d.x],
      minx = _ref[0],
      maxx = _ref[1];

    var _ref2 = !fullExtent || fullExtent.top > fullExtent.bottom ? [max2d.y, min2d.y] : [min2d.y, max2d.y],
      miny = _ref2[0],
      maxy = _ref2[1];

    var min = new Coordinate(minx, miny),
      max = new Coordinate(maxx, maxy);
    return new Extent(this.pointToCoord(min), this.pointToCoord(max), this.getProjection());
  };

  _proto._removeLayer = function _removeLayer(layer, layerList) {
    if (!layer || !layerList) {
      return;
    }

    var index = layerList.indexOf(layer);

    if (index > -1) {
      layerList.splice(index, 1);
    }
  };

  _proto._sortLayersByZIndex = function _sortLayersByZIndex() {
    if (!this._layers) {
      return;
    }

    for (var i = 0, l = this._layers.length; i < l; i++) {
      this._layers[i]._order = i;
    }

    this._layers.sort(function (a, b) {
      var c = a.getZIndex() - b.getZIndex();

      if (c === 0) {
        return a._order - b._order;
      }

      return c;
    });
  };

  _proto._fireEvent = function _fireEvent(eventName, param) {
    if (this._noEvent) {
      return;
    }

    this.fire('_' + eventName, param);
    this.fire(eventName, param);
  };

  _proto._Load = function _Load() {
    this._resetMapStatus();

    if (this.options['pitch']) {
      this.setPitch(this.options['pitch']);
      delete this.options['pitch'];
    }

    if (this.options['bearing']) {
      this.setBearing(this.options['bearing']);
      delete this.options['bearing'];
    }

    this._loadAllLayers();

    this._getRenderer().onLoad();

    this._loaded = true;

    this._callOnLoadHooks();

    this._initTime = now();
  };

  _proto._initRenderer = function _initRenderer() {
    var renderer = this.options['renderer'];
    var clazz = Map.getRendererClass(renderer);
    this._renderer = new clazz(this);

    this._renderer.load();
  };

  _proto._getRenderer = function _getRenderer() {
    return this._renderer;
  };

  _proto._loadAllLayers = function _loadAllLayers() {
    function loadLayer(layer) {
      if (layer) {
        layer.load();
      }
    }

    if (this._baseLayer) {
      this._baseLayer.load();
    }

    this._eachLayer(loadLayer, this.getLayers());
  };

  _proto._getLayers = function _getLayers(filter) {
    var layers = this._baseLayer ? [this._baseLayer].concat(this._layers) : this._layers;
    var result = [];

    for (var i = 0; i < layers.length; i++) {
      if (!filter || filter.call(this, layers[i])) {
        result.push(layers[i]);
      }
    }

    return result;
  };

  _proto._eachLayer = function _eachLayer(fn) {
    if (arguments.length < 2) {
      return;
    }

    var layerLists = Array.prototype.slice.call(arguments, 1);

    if (layerLists && !Array.isArray(layerLists)) {
      layerLists = [layerLists];
    }

    var layers = [];

    for (var i = 0, len = layerLists.length; i < len; i++) {
      layers = layers.concat(layerLists[i]);
    }

    for (var j = 0, jlen = layers.length; j < jlen; j++) {
      fn.call(fn, layers[j]);
    }
  };

  _proto._onLayerEvent = function _onLayerEvent(param) {
    if (!param) {
      return;
    }

    if (param['type'] === 'idchange') {
      delete this._layerCache[param['old']];
      this._layerCache[param['new']] = param['target'];
    }
  };

  _proto._resetMapStatus = function _resetMapStatus() {
    var maxZoom = this.getMaxZoom(),
      minZoom = this.getMinZoom();

    var viewMaxZoom = this._spatialReference.getMaxZoom(),
      viewMinZoom = this._spatialReference.getMinZoom();

    if (isNil(maxZoom) || maxZoom === -1 || maxZoom > viewMaxZoom) {
      this.setMaxZoom(viewMaxZoom);
    }

    if (isNil(minZoom) || minZoom === -1 || minZoom < viewMinZoom) {
      this.setMinZoom(viewMinZoom);
    }

    maxZoom = this.getMaxZoom();
    minZoom = this.getMinZoom();

    if (maxZoom < minZoom) {
      this.setMaxZoom(minZoom);
    }

    if (isNil(this._zoomLevel) || this._zoomLevel > maxZoom) {
      this._zoomLevel = maxZoom;
    }

    if (this._zoomLevel < minZoom) {
      this._zoomLevel = minZoom;
    }

    delete this._prjCenter;
    var projection = this.getProjection();
    this._prjCenter = projection.project(this._center);

    // this._calcMatrices();

    // var renderer = this._getRenderer();

    // if (renderer) {
    //   renderer.resetContainer();
    // }
  };

  _proto._getContainerDomSize = function _getContainerDomSize() {
    if (!this._containerDOM) {
      return null;
    }

    var containerDOM = this._containerDOM;
    var width, height;

    if (!isNil(containerDOM.width) && !isNil(containerDOM.height)) {
      width = containerDOM.width;
      height = containerDOM.height;

      if (Browser$1.retina && containerDOM['layer']) {
        width /= 2;
        height /= 2;
      }
    } else if (!isNil(containerDOM.clientWidth) && !isNil(containerDOM.clientHeight)) {
      width = parseInt(containerDOM.clientWidth, 0);
      height = parseInt(containerDOM.clientHeight, 0);
    } else {
      throw new Error('can not get size of container');
    }

    return new Size(width, height);
  };

  _proto._updateMapSize = function _updateMapSize(mSize) {
    this.width = mSize['width'];
    this.height = mSize['height'];

    this._getRenderer().updateMapSize(mSize);

    this._calcMatrices();

    return this;
  };

  _proto._getPrjCenter = function _getPrjCenter() {
    return this._prjCenter;
  };

  _proto._setPrjCenter = function _setPrjCenter(pcenter) {
    this._prjCenter = pcenter;

    if (this.isInteracting() && !this.isMoving()) {
      this._mapViewCoord = pcenter;
    }

    this._calcMatrices();
  };

  _proto._setPrjCoordAtContainerPoint = function _setPrjCoordAtContainerPoint(coordinate, point) {
    if (point.x === this.width / 2 && point.y === this.height / 2) {
      return this;
    }

    var t = this._containerPointToPoint(point)._sub(this._prjToPoint(this._getPrjCenter()));

    var pcenter = this._pointToPrj(this._prjToPoint(coordinate).sub(t));

    this._setPrjCenter(pcenter);

    return this;
  };

  _proto._verifyExtent = function _verifyExtent(center) {
    if (!center) {
      return false;
    }

    var maxExt = this.getMaxExtent();

    if (!maxExt) {
      return true;
    }

    return maxExt.contains(center);
  };

  _proto._offsetCenterByPixel = function _offsetCenterByPixel(pixel) {
    var pos = new Point(this.width / 2 - pixel.x, this.height / 2 - pixel.y);

    var pCenter = this._containerPointToPrj(pos);

    this._setPrjCenter(pCenter);

    return pCenter;
  };

  _proto.offsetPlatform = function offsetPlatform(offset) {
    if (!offset) {
      return this._mapViewPoint;
    } else {
      this._getRenderer().offsetPlatform(offset);

      this._mapViewCoord = this._getPrjCenter();
      this._mapViewPoint = this._mapViewPoint.add(offset);
      return this;
    }
  };

  _proto.getViewPoint = function getViewPoint() {
    var offset = this._getViewPointFrameOffset();

    var panelOffset = this.offsetPlatform();

    if (offset) {
      panelOffset = panelOffset.add(offset);
    }

    return panelOffset;
  };

  _proto._getViewPointFrameOffset = function _getViewPointFrameOffset() {
    if (this.isZooming()) {
      return null;
    }

    var pcenter = this._getPrjCenter();

    if (this._mapViewCoord && !this._mapViewCoord.equals(pcenter)) {
      return this._prjToContainerPoint(this._mapViewCoord).sub(this._prjToContainerPoint(pcenter));
    }

    return null;
  };

  _proto._resetMapViewPoint = function _resetMapViewPoint() {
    this._mapViewPoint = new Point(0, 0);
    this._mapViewCoord = this._getPrjCenter();
  };

  _proto._getResolution = function _getResolution(zoom) {
    if (isNil(zoom)) {
      zoom = this.getZoom();
    }

    return this._spatialReference.getResolution(zoom);
  };

  _proto._getResolutions = function _getResolutions() {
    return this._spatialReference.getResolutions();
  };

  _proto._prjToPoint = function _prjToPoint(pCoord, zoom) {
    zoom = isNil(zoom) ? this.getZoom() : zoom;
    return this._spatialReference.getTransformation().transform(pCoord, this._getResolution(zoom));
  };

  _proto._pointToPrj = function _pointToPrj(point, zoom) {
    zoom = isNil(zoom) ? this.getZoom() : zoom;
    return this._spatialReference.getTransformation().untransform(point, this._getResolution(zoom));
  };

  _proto._pointToPoint = function _pointToPoint(point, zoom) {
    if (!isNil(zoom)) {
      return point.multi(this._getResolution(zoom) / this._getResolution());
    }

    return point.copy();
  };

  _proto._pointToPointAtZoom = function _pointToPointAtZoom(point, zoom) {
    if (!isNil(zoom)) {
      return point.multi(this._getResolution() / this._getResolution(zoom));
    }

    return point.copy();
  };

  _proto._containerPointToPrj = function _containerPointToPrj(containerPoint) {
    return this._pointToPrj(this._containerPointToPoint(containerPoint));
  };

  _proto._viewPointToPrj = function _viewPointToPrj(viewPoint) {
    return this._containerPointToPrj(this.viewPointToContainerPoint(viewPoint));
  };

  _proto._prjToContainerPoint = function _prjToContainerPoint(pCoordinate, zoom) {
    return this._pointToContainerPoint(this._prjToPoint(pCoordinate, zoom), zoom);
  };

  _proto._prjToViewPoint = function _prjToViewPoint(pCoordinate) {
    var containerPoint = this._prjToContainerPoint(pCoordinate);

    return this._containerPointToViewPoint(containerPoint);
  };

  _proto._containerPointToViewPoint = function _containerPointToViewPoint(containerPoint) {
    if (!containerPoint) {
      return null;
    }

    return containerPoint._sub(this.getViewPoint());
  };

  _proto._viewPointToPoint = function _viewPointToPoint(viewPoint, zoom) {
    return this._containerPointToPoint(this.viewPointToContainerPoint(viewPoint), zoom);
  };

  _proto._pointToViewPoint = function _pointToViewPoint(point, zoom) {
    return this._prjToViewPoint(this._pointToPrj(point, zoom));
  };

  _proto._callOnLoadHooks = function _callOnLoadHooks() {
    var proto = Map.prototype;

    if (!proto._onLoadHooks) {
      return;
    }

    for (var i = 0, l = proto._onLoadHooks.length; i < l; i++) {
      proto._onLoadHooks[i].call(this);
    }
  };

  return Map;
}(Handlerable(Eventable(Renderable(Class))));

Map$1.mergeOptions(options$1);


var RADIAN = Math.PI / 180;
var DEFAULT_FOV = 0.6435011087932844;
Map$1.include({
  getFov: function getFov() {
    if (!this._fov) {
      this._fov = DEFAULT_FOV;
    }

    return this._fov / RADIAN;
  },
  setFov: function setFov(fov) {
    if (this.isZooming()) {
      return this;
    }

    fov = Math.max(0.01, Math.min(60, fov));
    if (this._fov === fov) return this;
    var from = this.getFov();
    this._fov = fov * RADIAN;

    this._calcMatrices();

    this._renderLayers();

    this._fireEvent('fovchange', {
      'from': from,
      'to': this.getFov()
    });

    return this;
  },
  getBearing: function getBearing() {
    if (!this._angle) {
      return 0;
    }

    return -this._angle / RADIAN;
  },
  setBearing: function setBearing(bearing) {
    if (Browser$1.ie9) {
      throw new Error('map can\'t rotate in IE9.');
    }

    var b = -wrap(bearing, -180, 180) * RADIAN;
    if (this._angle === b) return this;
    var from = this.getBearing();

    this._fireEvent('rotatestart', {
      'from': from,
      'to': b
    });

    this._angle = b;

    this._calcMatrices();

    this._renderLayers();

    this._fireEvent('rotate', {
      'from': from,
      'to': b
    });

    this._fireEvent('rotateend', {
      'from': from,
      'to': b
    });

    return this;
  },
  getPitch: function getPitch() {
    if (!this._pitch) {
      return 0;
    }

    return this._pitch / Math.PI * 180;
  },
  setPitch: function setPitch(pitch) {
    if (Browser$1.ie9) {
      throw new Error('map can\'t tilt in IE9.');
    }

    var p = clamp(pitch, 0, this.options['maxPitch']) * RADIAN;
    if (this._pitch === p) return this;
    var from = this.getPitch();

    this._fireEvent('pitchstart', {
      'from': from,
      'to': p
    });

    this._pitch = p;

    this._calcMatrices();

    this._renderLayers();

    this._fireEvent('pitch', {
      'from': from,
      'to': p
    });

    this._fireEvent('pitchend', {
      'from': from,
      'to': p
    });

    return this;
  },
  isTransforming: function isTransforming() {
    return !!(this._pitch || this._angle);
  },
  getFrustumAltitude: function getFrustumAltitude() {
    var pitch = 90 - this.getPitch();
    var fov = this.getFov() / 2;
    var cameraAlt = this.cameraPosition ? this.cameraPosition[2] : 0;

    if (fov <= pitch) {
      return cameraAlt;
    }

    fov = Math.PI * fov / 180;
    var d1 = new Point(this.cameraPosition).distanceTo(new Point(this.cameraLookAt)),
      d2 = cameraAlt * Math.tan(fov * 2);
    var d = Math.tan(fov) * (d1 + d2);
    return cameraAlt + d;
  },
  _pointToContainerPoint: function () {
    var a = [0, 0, 0];
    return function (point, zoom, altitude) {
      if (altitude === void 0) {
        altitude = 0;
      }

      point = this._pointToPoint(point, zoom);

      if (this.isTransforming() || altitude) {
        altitude *= this.getResolution(zoom) / this.getResolution();
        var _scale = this._glScale;
        set$2(a, point.x * _scale, point.y * _scale, altitude * _scale);

        var t = this._projIfBehindCamera(a, this.cameraPosition, this.cameraForward);

        applyMatrix(t, t, this.projViewMatrix);
        var w2 = this.width / 2,
          h2 = this.height / 2;
        t[0] = t[0] * w2 + w2;
        t[1] = -(t[1] * h2) + h2;
        return new Point(t[0], t[1]);
      } else {
        var centerPoint = this._prjToPoint(this._getPrjCenter());

        return point._sub(centerPoint)._add(this.width / 2, this.height / 2);
      }
    };
  }(),
  _projIfBehindCamera: function () {
    var vectorFromCam = new Array(3);
    var proj = new Array(3);
    var sub = new Array(3);
    return function (position, cameraPos, camForward) {
      subtract(vectorFromCam, position, cameraPos);
      var camNormDot = dot(camForward, vectorFromCam);

      if (camNormDot <= 0) {
        scale$1(proj, camForward, camNormDot * 1.01);
        add(position, cameraPos, subtract(sub, vectorFromCam, proj));
      }

      return position;
    };
  }(),
  _containerPointToPoint: function () {
    var cp = [0, 0, 0],
      coord0 = [0, 0, 0, 1],
      coord1 = [0, 0, 0, 1];
    return function (p, zoom) {
      if (this.isTransforming()) {
        var w2 = this.width / 2 || 1,
          h2 = this.height / 2 || 1;
        set$2(cp, (p.x - w2) / w2, (h2 - p.y) / h2, 0);
        set$2(coord0, cp[0], cp[1], 0);
        set$2(coord1, cp[0], cp[1], 1);
        coord0[3] = coord1[3] = 1;
        applyMatrix(coord0, coord0, this.projViewMatrixInverse);
        applyMatrix(coord1, coord1, this.projViewMatrixInverse);
        var x0 = coord0[0];
        var x1 = coord1[0];
        var y0 = coord0[1];
        var y1 = coord1[1];
        var z0 = coord0[2];
        var z1 = coord1[2];
        var t = z0 === z1 ? 0 : (0 - z0) / (z1 - z0);

        var point = new Point(interpolate(x0, x1, t), interpolate(y0, y1, t))._multi(1 / this._glScale);

        return zoom === undefined || this.getZoom() === zoom ? point : this._pointToPointAtZoom(point, zoom);
      }

      var centerPoint = this._prjToPoint(this._getPrjCenter(), zoom),
        scale$$1 = zoom !== undefined ? this._getResolution() / this._getResolution(zoom) : 1;

      var x = scale$$1 * (p.x - this.width / 2),
        y = scale$$1 * (p.y - this.height / 2);
      return centerPoint._add(x, y);
    };
  }(),
  _calcMatrices: function () {
    var m0 = Browser$1.ie9 ? null : createMat4(),
      m1 = Browser$1.ie9 ? null : createMat4();
    return function () {
      if (Browser$1.ie9) {
        return;
      }

      var size = this.getSize();
      var w = size.width || 1,
        h = size.height || 1;
      this._glScale = this.getGLScale();
      var fov = this.getFov() * Math.PI / 180;
      var maxScale = this.getScale(this.getMinZoom()) / this.getScale(this.getMaxNativeZoom());
      var farZ = maxScale * h / 2 / this._getFovRatio() * 1.4;
      var projMatrix = this.projMatrix || createMat4();
      perspective(projMatrix, fov, w / h, 0.1, farZ);
      this.projMatrix = projMatrix;

      var worldMatrix = this._getCameraWorldMatrix();

      this.viewMatrix = invert(m0, worldMatrix);
      this.projViewMatrix = multiply(this.projViewMatrix || createMat4(), projMatrix, this.viewMatrix);
      this.projViewMatrixInverse = multiply(this.projViewMatrixInverse || createMat4(), worldMatrix, invert(m1, projMatrix));
      this.domCssMatrix = this._calcDomMatrix();
    };
  }(),
  _calcDomMatrix: function () {
    var m = Browser$1.ie9 ? null : createMat4(),
      minusY = [1, -1, 1],
      arr = [0, 0, 0];
    return function () {
      var cameraToCenterDistance = 0.5 / Math.tan(this._fov / 2) * this.height;
      scale(m, this.projMatrix, minusY);
      translate(m, m, set$2(arr, 0, 0, -cameraToCenterDistance));

      if (this._pitch) {
        rotateX(m, m, this._pitch);
      }

      if (this._angle) {
        rotateZ(m, m, this._angle);
      }

      var m1 = createMat4();
      scale(m1, m1, set$2(arr, this.width / 2, -this.height / 2, 1));
      return multiply(this.domCssMatrix || createMat4(), m1, m);
    };
  }(),
  _getCameraWorldMatrix: function () {
    var q = {},
      minusY = [1, -1, 1];
    return function () {
      var targetZ = this.getGLZoom();
      var size = this.getSize(),
        scale$$1 = this.getGLScale();

      var center2D = this._prjToPoint(this._prjCenter, targetZ);

      this.cameraLookAt = set$2(this.cameraLookAt || [0, 0, 0], center2D.x, center2D.y, 0);
      var pitch = this.getPitch() * RADIAN;
      var bearing = -this.getBearing() * RADIAN;

      var ratio = this._getFovRatio();

      var z = scale$$1 * (size.height || 1) / 2 / ratio;
      var cz = z * Math.cos(pitch);
      var dist = Math.sin(pitch) * z;
      var cx = center2D.x + dist * Math.sin(bearing);
      var cy = center2D.y + dist * Math.cos(bearing);
      this.cameraPosition = set$2(this.cameraPosition || [0, 0, 0], cx, cy, cz);
      var d = dist || 1;
      var up = this.cameraUp = set$2(this.cameraUp || [0, 0, 0], Math.sin(bearing) * d, Math.cos(bearing) * d, 0);
      var m = this.cameraWorldMatrix = this.cameraWorldMatrix || createMat4();
      lookAt(m, this.cameraPosition, this.cameraLookAt, up);
      var cameraForward = this.cameraForward || [0, 0, 0];
      subtract(cameraForward, this.cameraLookAt, this.cameraPosition);
      this.cameraForward = normalize(cameraForward, cameraForward);
      matrixToQuaternion(q, m);
      quaternionToMatrix(m, q);
      setPosition(m, this.cameraPosition);
      scale(m, m, minusY);
      return m;
    };
  }(),
  _getFovRatio: function _getFovRatio() {
    var fov = this.getFov();
    return Math.tan(fov / 2 * RADIAN);
  },
  _renderLayers: function _renderLayers() {
    if (this.isInteracting()) {
      return;
    }

    var layers = this._getLayers();

    layers.forEach(function (layer) {
      if (!layer) {
        return;
      }

      var renderer = layer._getRenderer();

      if (renderer && renderer.setToRedraw) {
        renderer.setToRedraw();
      }
    });
  }
});
function createMat4() {
  return identity(new Array(16));
}

function identity(out) {
  out[0] = 1;
  out[1] = 0;
  out[2] = 0;
  out[3] = 0;
  out[4] = 0;
  out[5] = 1;
  out[6] = 0;
  out[7] = 0;
  out[8] = 0;
  out[9] = 0;
  out[10] = 1;
  out[11] = 0;
  out[12] = 0;
  out[13] = 0;
  out[14] = 0;
  out[15] = 1;
  return out;
}



Map$1.include({
  _zoom: function _zoom(nextZoom, origin) {
    if (!this.options['zoomable'] || this.isZooming()) {
      return;
    }

    origin = this._checkZoomOrigin(origin);
    nextZoom = this._checkZoom(nextZoom);
    this.onZoomStart(nextZoom, origin);
    this._frameZoom = this.getZoom();
    this.onZoomEnd(nextZoom, origin);
  },
  _zoomAnimation: function _zoomAnimation(nextZoom, origin, startScale) {
    if (!this.options['zoomable'] || this.isZooming()) {
      return;
    }

    nextZoom = this._checkZoom(nextZoom);

    if (this.getZoom() === nextZoom) {
      return;
    }

    origin = this._checkZoomOrigin(origin);

    this._startZoomAnim(nextZoom, origin, startScale);
  },
  _checkZoomOrigin: function _checkZoomOrigin(origin) {
    if (!origin || this.options['zoomInCenter']) {
      origin = new Point(this.width / 2, this.height / 2);
    }

    return origin;
  },
  _startZoomAnim: function _startZoomAnim(nextZoom, origin, startScale) {
    if (isNil(startScale)) {
      startScale = 1;
    }

    var endScale = this._getResolution(this._startZoomVal) / this._getResolution(nextZoom);

    var duration = this.options['zoomAnimationDuration'] * Math.abs(endScale - startScale) / Math.abs(endScale - 1);
    this._frameZoom = this._startZoomVal;
    this.animateTo({
      'zoom': nextZoom,
      'around': origin
    }, {
        'continueOnViewChanged': true,
        'duration': duration
      });
  },
  onZoomStart: function onZoomStart(nextZoom, origin) {
    if (!this.options['zoomable'] || this.isZooming()) {
      return;
    }

    this._zooming = true;
    this._startZoomVal = this.getZoom();
    this._startZoomCoord = this._containerPointToPrj(origin);

    this._fireEvent('zoomstart', {
      'from': this._startZoomVal,
      'to': nextZoom
    });
  },
  onZooming: function onZooming(nextZoom, origin, startScale) {
    if (!this.options['zoomable']) {
      return;
    }

    var frameZoom = this._frameZoom;

    if (frameZoom === nextZoom) {
      return;
    }

    if (isNil(startScale)) {
      startScale = 1;
    }

    this._zoomTo(nextZoom, origin);

    var res = this.getResolution(nextZoom),
      fromRes = this.getResolution(this._startZoomVal),
      scale = fromRes / res / startScale,
      startPoint = this._prjToContainerPoint(this._startZoomCoord, this._startZoomVal);

    var offset = this.getViewPoint();

    if (!this.isRotating() && !startPoint.equals(origin) && scale !== 1) {
      var pitch = this.getPitch();

      var originOffset = startPoint._sub(origin)._multi(1 / (1 - scale));

      if (pitch) {
        originOffset.y /= Math.cos(pitch * Math.PI / 180);
      }

      origin = origin.add(originOffset);
    }

    var matrix = {
      'view': [scale, 0, 0, scale, (origin.x - offset.x) * (1 - scale), (origin.y - offset.y) * (1 - scale)]
    };

    if (Browser$1.retina) {
      origin = origin.multi(2);
    }

    matrix['container'] = [scale, 0, 0, scale, origin.x * (1 - scale), origin.y * (1 - scale)];

    this._fireEvent('zooming', {
      'from': this._startZoomVal,
      'to': nextZoom,
      'origin': origin,
      'matrix': matrix
    });

    this._frameZoom = nextZoom;
  },
  onZoomEnd: function onZoomEnd(nextZoom, origin) {
    if (!this.options['zoomable']) {
      return;
    }

    var startZoomVal = this._startZoomVal;

    this._zoomTo(nextZoom, origin);

    this._zooming = false;

    // this._getRenderer().onZoomEnd();

    this._fireEvent('zoomend', {
      'from': startZoomVal,
      'to': nextZoom
    });

    if (!this._verifyExtent(this.getCenter())) {
      this.panTo(this.getMaxExtent().getCenter());
    }
  },
  _zoomTo: function _zoomTo(nextZoom, origin) {
    this._zoomLevel = nextZoom;

    this._calcMatrices();

    if (origin) {
      this._setPrjCoordAtContainerPoint(this._startZoomCoord, origin);
    }
  },
  _checkZoom: function _checkZoom(nextZoom) {
    var maxZoom = this.getMaxZoom(),
      minZoom = this.getMinZoom();

    if (nextZoom < minZoom) {
      nextZoom = minZoom;
    }

    if (nextZoom > maxZoom) {
      nextZoom = maxZoom;
    }

    return nextZoom;
  }
});

var Size = function () {
  function Size(width, height) {
    if (isNumber(width) && isNumber(height)) {
      this.width = width;
      this.height = height;
    } else if (isNumber(width['width'])) {
      this.width = width.width;
      this.height = width.height;
    } else if (Array.isArray(width)) {
      this.width = width[0];
      this.height = width[1];
    }
  }

  var _proto = Size.prototype;

  _proto.copy = function copy() {
    return new Size(this['width'], this['height']);
  };

  _proto.add = function add(x, y) {
    var w, h;

    if (x instanceof Size) {
      w = this.width + x.width;
      h = this.height + x.height;
    } else {
      w = this.width + x;
      h = this.height + y;
    }

    return new Size(w, h);
  };

  _proto.equals = function equals(size) {
    return this['width'] === size['width'] && this['height'] === size['height'];
  };

  _proto.multi = function multi(ratio) {
    return new Size(this['width'] * ratio, this['height'] * ratio);
  };

  _proto._multi = function _multi(ratio) {
    this['width'] *= ratio;
    this['height'] *= ratio;
    return this;
  };

  _proto._round = function _round() {
    this['width'] = Math.round(this['width']);
    this['height'] = Math.round(this['height']);
    return this;
  };

  _proto.toPoint = function toPoint() {
    return new Point(this['width'], this['height']);
  };

  _proto.toArray = function toArray() {
    return [this['width'], this['height']];
  };

  _proto.toJSON = function toJSON() {
    return {
      'width': this['width'],
      'height': this['height']
    };
  };

  return Size;
}();

function perspective(out, fovy, aspect, near, far) {
  var f = 1.0 / Math.tan(fovy / 2),
    nf = 1 / (near - far);
  out[0] = f / aspect;
  out[1] = 0;
  out[2] = 0;
  out[3] = 0;
  out[4] = 0;
  out[5] = f;
  out[6] = 0;
  out[7] = 0;
  out[8] = 0;
  out[9] = 0;
  out[10] = (far + near) * nf;
  out[11] = -1;
  out[12] = 0;
  out[13] = 0;
  out[14] = 2 * far * near * nf;
  out[15] = 0;
  return out;
}

function set$2(out, x, y, z) {
  out[0] = x;
  out[1] = y;
  out[2] = z;
  return out;
}
function lookAt(te, eye, target, up) {
  var x = [0, 0, 0];
  var y = [0, 0, 0];
  var z = [0, 0, 0];
  subtract(z, eye, target);

  if (length(z) === 0) {
    z[2] = 1;
  }

  normalize(z, z);
  cross(x, up, z);

  if (length(z) === 0) {
    if (Math.abs(up[2]) === 1) {
      z[0] += 0.0001;
    } else {
      z[2] += 0.0001;
    }

    normalize(z, z);
    cross(x, up, z);
  }

  normalize(x, x);
  cross(y, z, x);
  te[0] = x[0];
  te[4] = y[0];
  te[8] = z[0];
  te[1] = x[1];
  te[5] = y[1];
  te[9] = z[1];
  te[2] = x[2];
  te[6] = y[2];
  te[10] = z[2];
  return te;
}

function subtract(out, a, b) {
  out[0] = a[0] - b[0];
  out[1] = a[1] - b[1];
  out[2] = a[2] - b[2];
  return out;
}
function length(a) {
  var x = a[0],
    y = a[1],
    z = a[2];
  return Math.sqrt(x * x + y * y + z * z);
}


function normalize(out, a) {
  var x = a[0],
    y = a[1],
    z = a[2];
  var len = x * x + y * y + z * z;

  if (len > 0) {
    len = 1 / Math.sqrt(len);
    out[0] = a[0] * len;
    out[1] = a[1] * len;
    out[2] = a[2] * len;
  }

  return out;
}


function cross(out, a, b) {
  var ax = a[0],
    ay = a[1],
    az = a[2],
    bx = b[0],
    by = b[1],
    bz = b[2];
  out[0] = ay * bz - az * by;
  out[1] = az * bx - ax * bz;
  out[2] = ax * by - ay * bx;
  return out;
}


function matrixToQuaternion(out, te) {
  var m11 = te[0],
    m12 = te[4],
    m13 = te[8],
    m21 = te[1],
    m22 = te[5],
    m23 = te[9],
    m31 = te[2],
    m32 = te[6],
    m33 = te[10],
    trace = m11 + m22 + m33;
  var s;

  if (trace > 0) {
    s = 0.5 / Math.sqrt(trace + 1.0);
    out.w = 0.25 / s;
    out.x = (m32 - m23) * s;
    out.y = (m13 - m31) * s;
    out.z = (m21 - m12) * s;
  } else if (m11 > m22 && m11 > m33) {
    s = 2.0 * Math.sqrt(1.0 + m11 - m22 - m33);
    out.w = (m32 - m23) / s;
    out.x = 0.25 * s;
    out.y = (m12 + m21) / s;
    out.z = (m13 + m31) / s;
  } else if (m22 > m33) {
    s = 2.0 * Math.sqrt(1.0 + m22 - m11 - m33);
    out.w = (m13 - m31) / s;
    out.x = (m12 + m21) / s;
    out.y = 0.25 * s;
    out.z = (m23 + m32) / s;
  } else {
    s = 2.0 * Math.sqrt(1.0 + m33 - m11 - m22);
    out.w = (m21 - m12) / s;
    out.x = (m13 + m31) / s;
    out.y = (m23 + m32) / s;
    out.z = 0.25 * s;
  }

  return this;
}
function quaternionToMatrix(out, q) {
  var te = out;
  var x = q.x,
    y = q.y,
    z = q.z,
    w = q.w;
  var x2 = x + x,
    y2 = y + y,
    z2 = z + z;
  var xx = x * x2,
    xy = x * y2,
    xz = x * z2;
  var yy = y * y2,
    yz = y * z2,
    zz = z * z2;
  var wx = w * x2,
    wy = w * y2,
    wz = w * z2;
  te[0] = 1 - (yy + zz);
  te[4] = xy - wz;
  te[8] = xz + wy;
  te[1] = xy + wz;
  te[5] = 1 - (xx + zz);
  te[9] = yz - wx;
  te[2] = xz - wy;
  te[6] = yz + wx;
  te[10] = 1 - (xx + yy);
  te[3] = 0;
  te[7] = 0;
  te[11] = 0;
  te[12] = 0;
  te[13] = 0;
  te[14] = 0;
  te[15] = 1;
  return te;
}
function setPosition(out, v) {
  var te = out;
  te[12] = v[0];
  te[13] = v[1];
  te[14] = v[2];
  return out;
}


function scale(out, a, v) {
  var x = v[0],
    y = v[1],
    z = v[2];
  out[0] = a[0] * x;
  out[1] = a[1] * x;
  out[2] = a[2] * x;
  out[3] = a[3] * x;
  out[4] = a[4] * y;
  out[5] = a[5] * y;
  out[6] = a[6] * y;
  out[7] = a[7] * y;
  out[8] = a[8] * z;
  out[9] = a[9] * z;
  out[10] = a[10] * z;
  out[11] = a[11] * z;
  out[12] = a[12];
  out[13] = a[13];
  out[14] = a[14];
  out[15] = a[15];
  return out;
}


function invert(out, a) {
  var a00 = a[0],
    a01 = a[1],
    a02 = a[2],
    a03 = a[3],
    a10 = a[4],
    a11 = a[5],
    a12 = a[6],
    a13 = a[7],
    a20 = a[8],
    a21 = a[9],
    a22 = a[10],
    a23 = a[11],
    a30 = a[12],
    a31 = a[13],
    a32 = a[14],
    a33 = a[15],
    b00 = a00 * a11 - a01 * a10,
    b01 = a00 * a12 - a02 * a10,
    b02 = a00 * a13 - a03 * a10,
    b03 = a01 * a12 - a02 * a11,
    b04 = a01 * a13 - a03 * a11,
    b05 = a02 * a13 - a03 * a12,
    b06 = a20 * a31 - a21 * a30,
    b07 = a20 * a32 - a22 * a30,
    b08 = a20 * a33 - a23 * a30,
    b09 = a21 * a32 - a22 * a31,
    b10 = a21 * a33 - a23 * a31,
    b11 = a22 * a33 - a23 * a32,
    det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;

  if (!det) {
    return null;
  }

  det = 1.0 / det;
  out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
  out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
  out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
  out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det;
  out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
  out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
  out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
  out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det;
  out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
  out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
  out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
  out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det;
  out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det;
  out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det;
  out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det;
  out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det;
  return out;
}


function multiply(out, a, b) {
  var a00 = a[0],
    a01 = a[1],
    a02 = a[2],
    a03 = a[3],
    a10 = a[4],
    a11 = a[5],
    a12 = a[6],
    a13 = a[7],
    a20 = a[8],
    a21 = a[9],
    a22 = a[10],
    a23 = a[11],
    a30 = a[12],
    a31 = a[13],
    a32 = a[14],
    a33 = a[15];
  var b0 = b[0],
    b1 = b[1],
    b2 = b[2],
    b3 = b[3];
  out[0] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
  out[1] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
  out[2] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
  out[3] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
  b0 = b[4];
  b1 = b[5];
  b2 = b[6];
  b3 = b[7];
  out[4] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
  out[5] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
  out[6] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
  out[7] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
  b0 = b[8];
  b1 = b[9];
  b2 = b[10];
  b3 = b[11];
  out[8] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
  out[9] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
  out[10] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
  out[11] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
  b0 = b[12];
  b1 = b[13];
  b2 = b[14];
  b3 = b[15];
  out[12] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
  out[13] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
  out[14] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
  out[15] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
  return out;
}


function translate(out, a, v) {
  var x = v[0],
    y = v[1],
    z = v[2],
    a00,
    a01,
    a02,
    a03,
    a10,
    a11,
    a12,
    a13,
    a20,
    a21,
    a22,
    a23;

  if (a === out) {
    out[12] = a[0] * x + a[4] * y + a[8] * z + a[12];
    out[13] = a[1] * x + a[5] * y + a[9] * z + a[13];
    out[14] = a[2] * x + a[6] * y + a[10] * z + a[14];
    out[15] = a[3] * x + a[7] * y + a[11] * z + a[15];
  } else {
    a00 = a[0];
    a01 = a[1];
    a02 = a[2];
    a03 = a[3];
    a10 = a[4];
    a11 = a[5];
    a12 = a[6];
    a13 = a[7];
    a20 = a[8];
    a21 = a[9];
    a22 = a[10];
    a23 = a[11];
    out[0] = a00;
    out[1] = a01;
    out[2] = a02;
    out[3] = a03;
    out[4] = a10;
    out[5] = a11;
    out[6] = a12;
    out[7] = a13;
    out[8] = a20;
    out[9] = a21;
    out[10] = a22;
    out[11] = a23;
    out[12] = a00 * x + a10 * y + a20 * z + a[12];
    out[13] = a01 * x + a11 * y + a21 * z + a[13];
    out[14] = a02 * x + a12 * y + a22 * z + a[14];
    out[15] = a03 * x + a13 * y + a23 * z + a[15];
  }

  return out;
}


Map$1.include({
  animateTo: function animateTo(view, options, step) {
    var _this = this;

    if (options === void 0) {
      options = {};
    }

    this._stopAnim(this._animPlayer);

    if (isFunction(options)) {
      step = options;
      options = {};
    }

    var projection = this.getProjection(),
      currView = this.getView(),
      props = {};
    var empty = true;

    for (var p in view) {
      if (hasOwn(view, p) && !isNil(currView[p])) {
        empty = false;

        if (p === 'center') {
          var from = new Coordinate(currView[p]).toFixed(7),
            to = new Coordinate(view[p]).toFixed(7);

          if (!from.equals(to)) {
            props['center'] = [from, to];
          }
        } else if (currView[p] !== view[p] && p !== 'around') {
          props[p] = [currView[p], view[p]];
        }
      }
    }

    if (empty) {
      return null;
    }

    var zoomOrigin = view['around'] || new Point(this.width / 2, this.height / 2);
    var preView = this.getView();

    var renderer = this._getRenderer(),
      framer = function framer(fn) {
        renderer.callInNextFrame(fn);
      };

    var player = this._animPlayer = Animation.animate(props, {
      'easing': options['easing'] || 'out',
      'duration': options['duration'] || this.options['zoomAnimationDuration'],
      'framer': framer
    }, function (frame) {
      if (_this.isRemoved()) {
        player.finish();
        return;
      }

      if (player.playState === 'running') {
        var _view = _this.getView();

        if (!options['continueOnViewChanged'] && !equalView(_view, preView)) {
          _this._stopAnim(player);

          return;
        }

        if (frame.styles['center']) {
          var center = frame.styles['center'];

          _this._setPrjCenter(projection.project(center));

          _this.onMoving(_this._parseEventFromCoord(_this.getCenter()));
        }

        if (!isNil(frame.styles['zoom'])) {
          _this.onZooming(frame.styles['zoom'], zoomOrigin);
        }

        if (!isNil(frame.styles['pitch'])) {
          _this.setPitch(frame.styles['pitch']);
        }

        if (!isNil(frame.styles['bearing'])) {
          _this.setBearing(frame.styles['bearing']);
        }

        preView = _this.getView();

        _this._fireEvent('animating');
      } else if (player.playState === 'finished') {
        if (!player._interupted) {
          if (props['center']) {
            _this._setPrjCenter(projection.project(props['center'][1]));
          }

          if (!isNil(props['pitch'])) {
            _this.setPitch(props['pitch'][1]);
          }

          if (!isNil(props['bearing'])) {
            _this.setBearing(props['bearing'][1]);
          }
        }

        _this._endAnim(player, props, zoomOrigin, options);

        preView = _this.getView();
      }

      if (step) {
        step(frame);
      }
    });

    this._startAnim(props, zoomOrigin);

    return player;
  },
  isAnimating: function isAnimating() {
    return !!this._animPlayer;
  },
  isRotating: function isRotating() {
    return this.isDragRotating() || !!this._animRotating;
  },
  _endAnim: function _endAnim(player, props, zoomOrigin, options) {
    delete this._animRotating;
    var evtType = player._interupted ? 'animateinterrupted' : 'animateend';

    if (player === this._animPlayer) {
      delete this._animPlayer;
    }

    if (props['center']) {
      var endCoord;

      if (player._interupted) {
        endCoord = this.getCenter();
      } else {
        endCoord = props['center'][1];
      }

      this.onMoveEnd(this._parseEventFromCoord(endCoord));
    }

    if (!isNil(props['zoom'])) {
      if (player._interupted) {
        this.onZoomEnd(this.getZoom(), zoomOrigin);
      } else if (!options['wheelZoom']) {
        this.onZoomEnd(props['zoom'][1], zoomOrigin);
      } else {
        this.onZooming(props['zoom'][1], zoomOrigin);
      }
    }

    if (evtType) {
      this._fireEvent(evtType);
    }

    if (!isNil(props['pitch']) && !this.getPitch()) {
      this.getRenderer().setToRedraw();
    }
  },
  _startAnim: function _startAnim(props, zoomOrigin) {
    if (!this._animPlayer) {
      return;
    }

    if (props['center']) {
      this.onMoveStart();
    }

    if (props['zoom'] && !this.isZooming()) {
      this.onZoomStart(props['zoom'][1], zoomOrigin);
    }

    if (props['pitch'] || props['bearing']) {
      this._animRotating = true;
    }

    this._fireEvent('animatestart');

    this._animPlayer.play();
  },
  _stopAnim: function _stopAnim(player) {
    if (player && player.playState !== 'finished') {
      player._interupted = true;
      player.finish();
    }
  }
});


function rotateZ(out, a, rad) {
  var s = Math.sin(rad),
    c = Math.cos(rad),
    a00 = a[0],
    a01 = a[1],
    a02 = a[2],
    a03 = a[3],
    a10 = a[4],
    a11 = a[5],
    a12 = a[6],
    a13 = a[7];

  if (a !== out) {
    out[8] = a[8];
    out[9] = a[9];
    out[10] = a[10];
    out[11] = a[11];
    out[12] = a[12];
    out[13] = a[13];
    out[14] = a[14];
    out[15] = a[15];
  }

  out[0] = a00 * c + a10 * s;
  out[1] = a01 * c + a11 * s;
  out[2] = a02 * c + a12 * s;
  out[3] = a03 * c + a13 * s;
  out[4] = a10 * c - a00 * s;
  out[5] = a11 * c - a01 * s;
  out[6] = a12 * c - a02 * s;
  out[7] = a13 * c - a03 * s;
  return out;
}


function clamp(n, min, max) {
  return Math.min(max, Math.max(min, n));
}


function rotateX(out, a, rad) {
  var s = Math.sin(rad),
    c = Math.cos(rad),
    a10 = a[4],
    a11 = a[5],
    a12 = a[6],
    a13 = a[7],
    a20 = a[8],
    a21 = a[9],
    a22 = a[10],
    a23 = a[11];

  if (a !== out) {
    out[0] = a[0];
    out[1] = a[1];
    out[2] = a[2];
    out[3] = a[3];
    out[12] = a[12];
    out[13] = a[13];
    out[14] = a[14];
    out[15] = a[15];
  }

  out[4] = a10 * c + a20 * s;
  out[5] = a11 * c + a21 * s;
  out[6] = a12 * c + a22 * s;
  out[7] = a13 * c + a23 * s;
  out[8] = a20 * c - a10 * s;
  out[9] = a21 * c - a11 * s;
  out[10] = a22 * c - a12 * s;
  out[11] = a23 * c - a13 * s;
  return out;
}


function applyMatrix(out, v, e) {
  var x = v[0],
    y = v[1],
    z = v[2];
  var w = 1 / (e[3] * x + e[7] * y + e[11] * z + e[15]);
  out[0] = (e[0] * x + e[4] * y + e[8] * z + e[12]) * w;
  out[1] = (e[1] * x + e[5] * y + e[9] * z + e[13]) * w;
  out[2] = (e[2] * x + e[6] * y + e[10] * z + e[14]) * w;
  return out;
}


function interpolate(a, b, t) {
  return a * (1 - t) + b * t;
}

export default toGeometry
export {
  Map$1,
  Coordinate,
  MultiPolygon,
  Polygon
}