geojs 1.8.3 → 1.8.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/geo.js CHANGED
@@ -41,13 +41,11 @@ module.exports = geo_action;
41
41
 
42
42
  /***/ }),
43
43
 
44
- /***/ 7800:
44
+ /***/ 5784:
45
45
  /***/ (function(module, __unused_webpack_exports, __webpack_require__) {
46
46
 
47
47
  var $ = __webpack_require__(5638);
48
48
 
49
- var inherit = __webpack_require__(5699);
50
-
51
49
  var geo_event = __webpack_require__(5108);
52
50
 
53
51
  var geo_action = __webpack_require__(7839);
@@ -56,16 +54,6 @@ var transform = __webpack_require__(6853);
56
54
 
57
55
  var util = __webpack_require__(4634);
58
56
 
59
- var registerAnnotation = (__webpack_require__(4647).registerAnnotation);
60
-
61
- var lineFeature = __webpack_require__(4708);
62
-
63
- var markerFeature = __webpack_require__(7098);
64
-
65
- var pointFeature = __webpack_require__(2557);
66
-
67
- var polygonFeature = __webpack_require__(4343);
68
-
69
57
  var textFeature = __webpack_require__(9757);
70
58
 
71
59
  var annotationId = 0;
@@ -1542,186 +1530,282 @@ function continuousVerticesProcessAction(m_this, evt, name) {
1542
1530
  }
1543
1531
  }
1544
1532
  /**
1545
- * Rectangle annotation specification. Extends {@link geo.annotation.spec}.
1533
+ * Return a function that can be used as a selectionConstraint that requires
1534
+ * that the aspect ratio of a rectangle-like selection is a specific value or
1535
+ * range of values.
1546
1536
  *
1547
- * @typedef {object} geo.rectangleAnnotation.spec
1548
- * @extends geo.annotation.spec
1549
- * @property {geo.geoPosition[]} [corners] A list of four corners in map gcs
1550
- * coordinates. These must be in order around the perimeter of the
1551
- * rectangle (in either direction).
1552
- * @property {geo.geoPosition[]} [coordinates] An alternate name for `corners`.
1553
- * @property {geo.polygonFeature.styleSpec} [style] The style to apply to a
1554
- * finished rectangle. This uses styles for {@link geo.polygonFeature}.
1555
- * @property {geo.polygonFeature.styleSpec} [editStyle] The style to apply to a
1556
- * rectangle in edit mode.
1557
- * @property {number|number[]|function} [constraint] If specified, an aspect
1558
- * ratio or list of aspect ratios to constraint the rectangle to. If a
1559
- * function, a selection constraint function to call to adjust the
1560
- * rectangle.
1537
+ * @param {number|number[]|geo.geoSize|geo.geoSize[]} ratio Either a single
1538
+ * aspect ratio, a single size, or a list of allowed aspect ratios and sizes.
1539
+ * For instance, 1 will require that the selection square, 2 would require
1540
+ * that it is twice as wide as tall, [2, 1/2] would allow it to be twice as
1541
+ * wide or half as wide as it is tall. Sizes (e.g., {width: 400, height:
1542
+ * 500}) snap to that size.
1543
+ * @returns {function} A function that can be passed to the mapIterator
1544
+ * selectionConstraint or to an annotation constraint function.
1561
1545
  */
1562
1546
 
1547
+
1548
+ function constrainAspectRatio(ratio) {
1549
+ var ratios = Array.isArray(ratio) ? ratio : [ratio];
1550
+ /**
1551
+ * Constrain a mouse action or annotation action to a list of aspect ratios.
1552
+ *
1553
+ * @param {geo.geoPosition} pos Mouse or new location in map gcs.
1554
+ * @param {geo.geoPosition} origin Origin in map gcs when the activity
1555
+ * started.
1556
+ * @param {geo.geoPosition} [corners] If specified, an array of corner
1557
+ * locations in mapgcs. This may be modified.
1558
+ * @param {string?} [mode] 'edge', 'vertex' or falsy. A falsy value implies
1559
+ * this is just the most recent point in the annotation, otherwise it is
1560
+ * the portion of the annotation being modified.
1561
+ * @param {number} [ang] A list of angles of each side of the polygon
1562
+ * represented by corners or the original annotation.
1563
+ * @param {integer} [index] The specific vertex or edge that is being
1564
+ * modified.
1565
+ * @returns {object} An object with the ``origin`` (this is what is passed
1566
+ * in), a new position as ``pos``, and the updated corners as ``corners``.
1567
+ */
1568
+
1569
+ function constraintFunction(pos, origin, corners, mode, ang, index) {
1570
+ var newpos = pos;
1571
+ var best;
1572
+
1573
+ if (!corners) {
1574
+ corners = [{
1575
+ x: origin.x,
1576
+ y: origin.y
1577
+ }, {
1578
+ x: pos.x,
1579
+ y: origin.y
1580
+ }, {
1581
+ x: pos.x,
1582
+ y: pos.y
1583
+ }, {
1584
+ x: origin.x,
1585
+ y: pos.y
1586
+ }];
1587
+ }
1588
+
1589
+ if (mode) {
1590
+ /* Edit a vertex or edge */
1591
+ var i1 = (index + 1) % 4;
1592
+ var i2 = (index + 2) % 4;
1593
+ var i3 = (index + 3) % 4;
1594
+ var dist1 = Math.pow(Math.pow(corners[index].x - corners[i1].x, 2) + Math.pow(corners[index].y - corners[i1].y, 2), 0.5);
1595
+ var dist3 = Math.pow(Math.pow(corners[index].x - corners[i3].x, 2) + Math.pow(corners[index].y - corners[i3].y, 2), 0.5);
1596
+ var area = Math.abs(dist1 * dist3);
1597
+ var shape, edge;
1598
+ ratios.forEach(function (ratio) {
1599
+ var width, height;
1600
+
1601
+ if (ratio.width) {
1602
+ width = ratio.width;
1603
+ height = ratio.height;
1604
+ } else {
1605
+ width = Math.pow(area * ratio, 0.5);
1606
+ height = width / ratio;
1607
+ }
1608
+
1609
+ if (width !== height && !(index % 2)) {
1610
+ var _ref = [height, width];
1611
+ width = _ref[0];
1612
+ height = _ref[1];
1613
+ }
1614
+
1615
+ var score = Math.pow(width - dist3, 2) + Math.pow(height - dist1, 2);
1616
+
1617
+ if (best === undefined || score < best) {
1618
+ best = score;
1619
+ shape = {
1620
+ w: width,
1621
+ h: height
1622
+ };
1623
+ }
1624
+ });
1625
+ var ang1 = ang[i1];
1626
+ var delta1 = {
1627
+ x: -shape.w * Math.cos(ang1),
1628
+ y: -shape.w * Math.sin(ang1)
1629
+ };
1630
+ var ang2 = ang[index];
1631
+ var delta2 = {
1632
+ x: -shape.h * Math.cos(ang2),
1633
+ y: -shape.h * Math.sin(ang2)
1634
+ };
1635
+
1636
+ switch (mode) {
1637
+ case 'vertex':
1638
+ corners[index].x = corners[i2].x + delta1.x + delta2.x;
1639
+ corners[index].y = corners[i2].y + delta1.y + delta2.y;
1640
+ corners[i1].x = corners[i2].x + delta1.x;
1641
+ corners[i1].y = corners[i2].y + delta1.y;
1642
+ corners[i3].x = corners[i2].x + delta2.x;
1643
+ corners[i3].y = corners[i2].y + delta2.y;
1644
+ break;
1645
+
1646
+ case 'edge':
1647
+ edge = {
1648
+ x: (corners[i2].x + corners[i3].x) * 0.5,
1649
+ y: (corners[i2].y + corners[i3].y) * 0.5
1650
+ };
1651
+ corners[i2].x = edge.x + delta2.x / 2;
1652
+ corners[i2].y = edge.y + delta2.y / 2;
1653
+ corners[index].x = edge.x + delta1.x - delta2.x / 2;
1654
+ corners[index].y = edge.y + delta1.y - delta2.y / 2;
1655
+ corners[i1].x = edge.x + delta1.x + delta2.x / 2;
1656
+ corners[i1].y = edge.y + delta1.y + delta2.y / 2;
1657
+ corners[i3].x = edge.x - delta2.x / 2;
1658
+ corners[i3].y = edge.y - delta2.y / 2;
1659
+ break;
1660
+ }
1661
+ } else {
1662
+ /* Not in edit vertex or edge mode */
1663
+ var _area = Math.abs((pos.x - origin.x) * (pos.y - origin.y));
1664
+
1665
+ ratios.forEach(function (ratio) {
1666
+ var width, height;
1667
+
1668
+ if (ratio.width) {
1669
+ width = ratio.width;
1670
+ height = ratio.height;
1671
+ } else {
1672
+ width = Math.pow(_area * ratio, 0.5);
1673
+ height = width / ratio;
1674
+ }
1675
+
1676
+ var adjusted = {
1677
+ x: origin.x + Math.sign(pos.x - origin.x) * width,
1678
+ y: origin.y + Math.sign(pos.y - origin.y) * height
1679
+ };
1680
+ var score = Math.pow(adjusted.x - pos.x, 2) + Math.pow(adjusted.y - pos.y, 2);
1681
+
1682
+ if (best === undefined || score < best) {
1683
+ best = score;
1684
+ newpos = adjusted;
1685
+ }
1686
+ });
1687
+ corners[0].y = corners[1].y = origin.y;
1688
+ corners[0].x = corners[3].x = origin.x;
1689
+ corners[1].x = corners[2].x = newpos.x;
1690
+ corners[2].y = corners[3].y = newpos.y;
1691
+ }
1692
+
1693
+ return {
1694
+ corners: corners,
1695
+ origin: origin,
1696
+ pos: newpos
1697
+ };
1698
+ }
1699
+
1700
+ return constraintFunction;
1701
+ }
1702
+
1703
+ module.exports = {
1704
+ state: annotationState,
1705
+ actionOwner: annotationActionOwner,
1706
+ annotation: annotation,
1707
+ _editHandleFeatureLevel: editHandleFeatureLevel,
1708
+ defaultEditHandleStyle: defaultEditHandleStyle,
1709
+ constrainAspectRatio: constrainAspectRatio,
1710
+ // these aren't exposed in index.js
1711
+ annotationActionOwner: annotationActionOwner,
1712
+ continuousVerticesActions: continuousVerticesActions,
1713
+ continuousVerticesProcessAction: continuousVerticesProcessAction
1714
+ };
1715
+
1716
+ /***/ }),
1717
+
1718
+ /***/ 7196:
1719
+ /***/ (function(module, __unused_webpack_exports, __webpack_require__) {
1720
+
1721
+ var $ = __webpack_require__(5638);
1722
+
1723
+ var inherit = __webpack_require__(5699);
1724
+
1725
+ var registerAnnotation = (__webpack_require__(4647).registerAnnotation);
1726
+
1727
+ var markerFeature = __webpack_require__(7098);
1728
+
1729
+ var ellipseAnnotation = __webpack_require__(7505);
1563
1730
  /**
1564
- * Rectangle annotation class.
1731
+ * Circle annotation class.
1565
1732
  *
1566
- * Rectangles are always rendered as polygons. This could be changed -- if no
1567
- * stroke is specified, the quad feature would be sufficient and work on more
1568
- * renderers.
1733
+ * Circles are a subset of rectangles with a fixed aspect ratio.
1569
1734
  *
1570
1735
  * @class
1571
- * @alias geo.rectangleAnnotation
1736
+ * @alias geo.circleAnnotation
1572
1737
  * @extends geo.annotation
1573
1738
  *
1574
- * @param {geo.rectangleAnnotation.spec?} [args] Options for the annotation.
1575
- * @param {string} [annotationName='rectangle'] Override the annotation name.
1739
+ * @param {geo.circleAnnotation.spec?} [args] Options for the annotation.
1740
+ * @param {string} [annotationName='circle'] Override the annotation name.
1576
1741
  */
1577
1742
 
1578
1743
 
1579
- var rectangleAnnotation = function rectangleAnnotation(args, annotationName) {
1744
+ var circleAnnotation = function circleAnnotation(args, annotationName) {
1580
1745
  'use strict';
1581
1746
 
1582
- if (!(this instanceof rectangleAnnotation)) {
1583
- return new rectangleAnnotation(args, annotationName);
1747
+ args = $.extend({}, args, {
1748
+ constraint: 1
1749
+ });
1750
+
1751
+ if (!(this instanceof circleAnnotation)) {
1752
+ return new circleAnnotation(args, annotationName);
1584
1753
  }
1585
1754
 
1586
- args = $.extend(true, {}, {
1587
- style: {
1588
- fill: true,
1589
- fillColor: {
1590
- r: 0,
1591
- g: 1,
1592
- b: 0
1593
- },
1594
- fillOpacity: 0.25,
1595
- polygon: function polygon(d) {
1596
- return d.polygon;
1597
- },
1598
- stroke: true,
1599
- strokeColor: {
1600
- r: 0,
1601
- g: 0,
1602
- b: 0
1603
- },
1604
- strokeOpacity: 1,
1605
- strokeWidth: 3,
1606
- uniformPolygon: true
1607
- },
1608
- highlightStyle: {
1609
- fillColor: {
1610
- r: 0,
1611
- g: 1,
1612
- b: 1
1613
- },
1614
- fillOpacity: 0.5,
1615
- strokeWidth: 5
1616
- },
1617
- createStyle: {
1618
- fillColor: {
1619
- r: 0.3,
1620
- g: 0.3,
1621
- b: 0.3
1622
- },
1623
- fillOpacity: 0.25,
1624
- strokeColor: {
1625
- r: 0,
1626
- g: 0,
1627
- b: 1
1628
- }
1629
- }
1630
- }, args || {});
1631
- args.corners = args.corners || args.coordinates || [];
1632
- delete args.coordinates;
1633
- annotation.call(this, annotationName || 'rectangle', args);
1634
- var m_this = this,
1635
- s_actions = this.actions,
1636
- s_processEditAction = this.processEditAction;
1637
- /**
1638
- * Return actions needed for the specified state of this annotation.
1639
- *
1640
- * @param {string} [state] The state to return actions for. Defaults to
1641
- * the current state.
1642
- * @returns {geo.actionRecord[]} A list of actions.
1643
- */
1755
+ ellipseAnnotation.call(this, args, annotationName || 'circle');
1756
+ };
1644
1757
 
1645
- this.actions = function (state) {
1646
- if (!state) {
1647
- state = m_this.state();
1648
- }
1758
+ inherit(circleAnnotation, ellipseAnnotation);
1759
+ var circleRequiredFeatures = {};
1760
+ circleRequiredFeatures[markerFeature.capabilities.feature] = true;
1761
+ registerAnnotation('circle', circleAnnotation, circleRequiredFeatures);
1762
+ module.exports = circleAnnotation;
1649
1763
 
1650
- switch (state) {
1651
- case annotationState.create:
1652
- return [{
1653
- action: geo_action.annotation_rectangle,
1654
- name: 'rectangle create',
1655
- owner: annotationActionOwner,
1656
- input: 'left',
1657
- modifiers: {
1658
- shift: false,
1659
- ctrl: false
1660
- },
1661
- selectionRectangle: true,
1662
- selectionConstraint: this._selectionConstraint
1663
- }];
1764
+ /***/ }),
1664
1765
 
1665
- default:
1666
- return s_actions.apply(m_this, arguments);
1667
- }
1668
- };
1669
- /**
1670
- * Process any actions for this annotation.
1671
- *
1672
- * @param {geo.event} evt The action event.
1673
- * @returns {boolean|string} `true` to update the annotation, `'done'` if the
1674
- * annotation was completed (changed from create to done state),
1675
- * `'remove'` if the annotation should be removed, falsy to not update
1676
- * anything.
1677
- */
1766
+ /***/ 7505:
1767
+ /***/ (function(module, __unused_webpack_exports, __webpack_require__) {
1678
1768
 
1769
+ var $ = __webpack_require__(5638);
1679
1770
 
1680
- this.processAction = function (evt) {
1681
- var layer = m_this.layer();
1771
+ var inherit = __webpack_require__(5699);
1682
1772
 
1683
- if (m_this.state() !== annotationState.create || !layer || evt.event !== geo_event.actionselection || evt.state.action !== geo_action.annotation_rectangle) {
1684
- return;
1685
- }
1773
+ var registerAnnotation = (__webpack_require__(4647).registerAnnotation);
1686
1774
 
1687
- var map = layer.map(),
1688
- corners = [
1689
- /* Keep in map gcs, not interface gcs to avoid wrapping issues */
1690
- map.displayToGcs({
1691
- x: evt.lowerLeft.x,
1692
- y: evt.lowerLeft.y
1693
- }, null), map.displayToGcs({
1694
- x: evt.lowerLeft.x,
1695
- y: evt.upperRight.y
1696
- }, null), map.displayToGcs({
1697
- x: evt.upperRight.x,
1698
- y: evt.upperRight.y
1699
- }, null), map.displayToGcs({
1700
- x: evt.upperRight.x,
1701
- y: evt.lowerLeft.y
1702
- }, null)];
1775
+ var markerFeature = __webpack_require__(7098);
1703
1776
 
1704
- if (this._selectionConstraint && evt.mouse && evt.state.origin) {
1705
- this._selectionConstraint(evt.mouse.mapgcs, evt.state.origin.mapgcs, corners);
1706
- }
1707
- /* Don't keep rectangles that have nearly zero area in display pixels */
1777
+ var annotationState = (__webpack_require__(5784).state);
1708
1778
 
1779
+ var rectangleAnnotation = __webpack_require__(3442);
1780
+ /**
1781
+ * Ellipse annotation class.
1782
+ *
1783
+ * Ellipses are always rendered as markers.
1784
+ *
1785
+ * @class
1786
+ * @alias geo.ellipseAnnotation
1787
+ * @extends geo.annotation
1788
+ *
1789
+ * @param {geo.ellipseAnnotation.spec?} [args] Options for the annotation.
1790
+ * @param {string} [annotationName='ellipse'] Override the annotation name.
1791
+ */
1709
1792
 
1710
- if (layer.displayDistance(corners[0], null, corners[1], null) * layer.displayDistance(corners[0], null, corners[3], null) < 0.01) {
1711
- return 'remove';
1712
- }
1713
1793
 
1714
- m_this.options('corners', corners);
1715
- m_this.state(annotationState.done);
1716
- return 'done';
1717
- };
1794
+ var ellipseAnnotation = function ellipseAnnotation(args, annotationName) {
1795
+ 'use strict';
1796
+
1797
+ if (!(this instanceof ellipseAnnotation)) {
1798
+ return new ellipseAnnotation(args, annotationName);
1799
+ }
1800
+
1801
+ rectangleAnnotation.call(this, args, annotationName || 'ellipse');
1802
+ var m_this = this;
1718
1803
  /**
1719
1804
  * Get a list of renderable features for this annotation.
1720
1805
  *
1721
1806
  * @returns {array} An array of features.
1722
1807
  */
1723
1808
 
1724
-
1725
1809
  this.features = function () {
1726
1810
  var opt = m_this.options(),
1727
1811
  state = m_this.state(),
@@ -1729,10 +1813,27 @@ var rectangleAnnotation = function rectangleAnnotation(args, annotationName) {
1729
1813
  features = [];
1730
1814
 
1731
1815
  if (opt.corners && opt.corners.length >= 4) {
1816
+ var style = m_this.styleForState(state);
1817
+ var w = Math.pow(Math.pow(opt.corners[0].x - opt.corners[1].x, 2) + Math.pow(opt.corners[0].y - opt.corners[1].y, 2), 0.5);
1818
+ var h = Math.pow(Math.pow(opt.corners[0].x - opt.corners[3].x, 2) + Math.pow(opt.corners[0].y - opt.corners[3].y, 2), 0.5);
1819
+ var radius = Math.max(w, h) / 2 / m_this.layer().map().unitsPerPixel(0);
1820
+ var aspect = w ? h / w : 1e20;
1821
+ var rotation = -Math.atan2(opt.corners[1].y - opt.corners[0].y, opt.corners[1].x - opt.corners[0].x);
1732
1822
  features = [{
1733
- polygon: {
1734
- polygon: opt.corners,
1735
- style: m_this.styleForState(state)
1823
+ marker: {
1824
+ x: (opt.corners[0].x + opt.corners[1].x + opt.corners[2].x + opt.corners[3].x) / 4,
1825
+ y: (opt.corners[0].y + opt.corners[1].y + opt.corners[2].y + opt.corners[3].y) / 4,
1826
+ style: $.extend({}, style, {
1827
+ radius: radius,
1828
+ symbolValue: aspect,
1829
+ rotation: rotation,
1830
+ strokeOffset: 0,
1831
+ radiusIncludesStroke: false,
1832
+ scaleWithZoom: markerFeature.scaleMode.fill,
1833
+ rotateWithMap: true,
1834
+ strokeOpacity: style.stroke === false ? 0 : style.strokeOpacity,
1835
+ fillOpacity: style.fill === false ? 0 : style.fillOpacity
1836
+ })
1736
1837
  }
1737
1838
  }];
1738
1839
  }
@@ -1743,123 +1844,223 @@ var rectangleAnnotation = function rectangleAnnotation(args, annotationName) {
1743
1844
 
1744
1845
  return features;
1745
1846
  };
1746
- /**
1747
- * Get and optionally set coordinates associated with this annotation in the
1748
- * map gcs coordinate system.
1749
- *
1750
- * @param {geo.geoPosition[]} [coordinates] An optional array of coordinates
1751
- * to set.
1752
- * @returns {geo.geoPosition[]} The current array of coordinates.
1753
- */
1754
-
1847
+ };
1755
1848
 
1756
- this._coordinates = function (coordinates) {
1757
- if (coordinates && coordinates.length >= 4) {
1758
- m_this.options('corners', coordinates.slice(0, 4));
1759
- /* Should we ensure that the four points form a rectangle in the current
1760
- * projection, though this might not be rectangular in another gcs? */
1761
- }
1849
+ inherit(ellipseAnnotation, rectangleAnnotation);
1850
+ var ellipseRequiredFeatures = {};
1851
+ ellipseRequiredFeatures[markerFeature.capabilities.feature] = true;
1852
+ registerAnnotation('ellipse', ellipseAnnotation, ellipseRequiredFeatures);
1853
+ module.exports = ellipseAnnotation;
1762
1854
 
1763
- return m_this.options('corners');
1764
- };
1855
+ /***/ }),
1765
1856
 
1766
- this._coordinateOption = 'corners';
1767
- /**
1768
- * Return the coordinates to be stored in a geojson geometry object.
1769
- *
1770
- * @param {string|geo.transform|null} [gcs] `undefined` to use the interface
1771
- * gcs, `null` to use the map gcs, or any other transform.
1772
- * @returns {array} An array of flattened coordinates in the interface gcs
1773
- * coordinate system. `undefined` if this annotation is incomplete.
1774
- */
1857
+ /***/ 4213:
1858
+ /***/ (function(module, __unused_webpack_exports, __webpack_require__) {
1775
1859
 
1776
- this._geojsonCoordinates = function (gcs) {
1777
- var src = m_this.coordinates(gcs);
1860
+ var annotation = __webpack_require__(5784);
1861
+ /**
1862
+ * @namespace geo.annotation
1863
+ */
1778
1864
 
1779
- if (!src || m_this.state() === annotationState.create || src.length < 4) {
1780
- return;
1781
- }
1782
1865
 
1783
- var coord = [];
1866
+ module.exports = {
1867
+ state: annotation.state,
1868
+ actionOwner: annotation.actionOwner,
1869
+ annotation: annotation.annotation,
1870
+ _editHandleFeatureLevel: annotation._editHandleFeatureLevel,
1871
+ defaultEditHandleStyle: annotation.defaultEditHandleStyle,
1872
+ constrainAspectRatio: annotation.constrainAspectRatio,
1873
+ baseAnnotation: annotation,
1874
+ circleAnnotation: __webpack_require__(7196),
1875
+ ellipseAnnotation: __webpack_require__(7505),
1876
+ lineAnnotation: __webpack_require__(3984),
1877
+ pointAnnotation: __webpack_require__(8296),
1878
+ polygonAnnotation: __webpack_require__(56),
1879
+ rectangleAnnotation: __webpack_require__(3442),
1880
+ squareAnnotation: __webpack_require__(4932)
1881
+ };
1784
1882
 
1785
- for (var i = 0; i < 4; i += 1) {
1786
- coord.push([src[i].x, src[i].y]);
1787
- }
1883
+ /***/ }),
1788
1884
 
1789
- coord.push([src[0].x, src[0].y]);
1790
- return [coord];
1791
- };
1792
- /**
1793
- * Return the geometry type that is used to store this annotation in geojson.
1794
- *
1795
- * @returns {string} A geojson geometry type.
1796
- */
1885
+ /***/ 3984:
1886
+ /***/ (function(module, __unused_webpack_exports, __webpack_require__) {
1797
1887
 
1888
+ var $ = __webpack_require__(5638);
1798
1889
 
1799
- this._geojsonGeometryType = function () {
1800
- return 'Polygon';
1801
- };
1802
- /**
1803
- * Return a list of styles that should be preserved in a geojson
1804
- * representation of the annotation.
1805
- *
1806
- * @returns {string[]} A list of style names to store.
1807
- */
1890
+ var inherit = __webpack_require__(5699);
1808
1891
 
1892
+ var registerAnnotation = (__webpack_require__(4647).registerAnnotation);
1809
1893
 
1810
- this._geojsonStyles = function () {
1811
- return ['fill', 'fillColor', 'fillOpacity', 'lineCap', 'lineJoin', 'stroke', 'strokeColor', 'strokeOffset', 'strokeOpacity', 'strokeWidth'];
1812
- };
1813
- /**
1814
- * Set three corners based on an initial corner and a mouse event.
1815
- *
1816
- * @param {geo.geoPosition} corners An array of four corners to update.
1817
- * @param {geo.event} evt The mouse move event.
1818
- */
1894
+ var lineFeature = __webpack_require__(4708);
1819
1895
 
1896
+ var annotation = (__webpack_require__(5784).annotation);
1820
1897
 
1821
- this._setCornersFromMouse = function (corners, evt) {
1822
- var map = m_this.layer().map(),
1823
- c0 = map.gcsToDisplay({
1824
- x: corners[0].x,
1825
- y: corners[0].y
1826
- }, null),
1827
- c2 = map.gcsToDisplay(evt.mapgcs, null),
1828
- c1 = {
1829
- x: c2.x,
1830
- y: c0.y
1831
- },
1832
- c3 = {
1833
- x: c0.x,
1834
- y: c2.y
1835
- };
1836
- corners[2] = $.extend({}, evt.mapgcs);
1837
- corners[1] = map.displayToGcs(c1, null);
1838
- corners[3] = map.displayToGcs(c3, null);
1898
+ var annotationState = (__webpack_require__(5784).state);
1839
1899
 
1840
- if (this._selectionConstraint) {
1841
- this._selectionConstraint(evt.mapgcs, corners[0], corners);
1842
- }
1843
- };
1844
- /**
1845
- * Handle a mouse move on this annotation.
1846
- *
1847
- * @param {geo.event} evt The mouse move event.
1848
- * @returns {boolean} Truthy to update the annotation, falsy to not
1849
- * update anything.
1850
- */
1900
+ var continuousVerticesActions = (__webpack_require__(5784).continuousVerticesActions);
1851
1901
 
1902
+ var continuousVerticesProcessAction = (__webpack_require__(5784).continuousVerticesProcessAction);
1903
+ /**
1904
+ * Line annotation specification. Extends {@link geo.annotation.spec}.
1905
+ *
1906
+ * @typedef {object} geo.lineAnnotation.spec
1907
+ * @extends geo.annotation.spec
1908
+ * @property {geo.geoPosition[]} [vertices] A list of vertices in map gcs
1909
+ * coordinates.
1910
+ * @property {geo.geoPosition[]} [coordinates] An alternate name for
1911
+ * `vertices`.
1912
+ * @property {geo.lineFeature.styleSpec} [style] The style to apply to a
1913
+ * finished line. This uses styles for {@link geo.lineFeature}.
1914
+ * @property {geo.lineFeature.styleSpec} [editStyle] The style to apply to a
1915
+ * line in edit mode.
1916
+ */
1852
1917
 
1853
- this.mouseMove = function (evt) {
1854
- if (m_this.state() !== annotationState.create) {
1855
- return;
1918
+ /**
1919
+ * Line annotation class.
1920
+ *
1921
+ * @class
1922
+ * @alias geo.lineAnnotation
1923
+ * @extends geo.annotation
1924
+ *
1925
+ * @param {geo.lineAnnotation.spec?} [args] Options for the annotation.
1926
+ */
1927
+
1928
+
1929
+ var lineAnnotation = function lineAnnotation(args) {
1930
+ 'use strict';
1931
+
1932
+ if (!(this instanceof lineAnnotation)) {
1933
+ return new lineAnnotation(args);
1934
+ }
1935
+
1936
+ args = $.extend(true, {}, {
1937
+ style: {
1938
+ line: function line(d) {
1939
+ /* Return an array that has the same number of items as we have
1940
+ * vertices. */
1941
+ return Array.apply(null, Array(m_this.options('vertices').length)).map(function () {
1942
+ return d;
1943
+ });
1944
+ },
1945
+ position: function position(d, i) {
1946
+ return m_this.options('vertices')[i];
1947
+ },
1948
+ strokeColor: {
1949
+ r: 0,
1950
+ g: 0,
1951
+ b: 0
1952
+ },
1953
+ strokeOpacity: 1,
1954
+ strokeWidth: 3,
1955
+ closed: false,
1956
+ lineCap: 'butt',
1957
+ lineJoin: 'miter'
1958
+ },
1959
+ highlightStyle: {
1960
+ strokeWidth: 5
1961
+ },
1962
+ createStyle: {
1963
+ line: function line(d) {
1964
+ /* Return an array that has the same number of items as we have
1965
+ * vertices. */
1966
+ return Array.apply(null, Array(m_this.options('vertices').length)).map(function () {
1967
+ return d;
1968
+ });
1969
+ },
1970
+ position: function position(d, i) {
1971
+ return m_this.options('vertices')[i];
1972
+ },
1973
+ strokeColor: {
1974
+ r: 0,
1975
+ g: 0,
1976
+ b: 1
1977
+ },
1978
+ strokeOpacity: 1,
1979
+ strokeWidth: 3,
1980
+ closed: false,
1981
+ lineCap: 'butt',
1982
+ lineJoin: 'miter'
1856
1983
  }
1984
+ }, args || {});
1985
+ args.vertices = args.vertices || args.coordinates || [];
1986
+ delete args.coordinates;
1987
+ annotation.call(this, 'line', args);
1988
+ var m_this = this,
1989
+ s_actions = this.actions,
1990
+ s_processEditAction = this.processEditAction;
1991
+ /**
1992
+ * Get a list of renderable features for this annotation.
1993
+ *
1994
+ * @returns {array} An array of features.
1995
+ */
1857
1996
 
1858
- var corners = m_this.options('corners');
1997
+ this.features = function () {
1998
+ var opt = m_this.options(),
1999
+ state = m_this.state(),
2000
+ features;
1859
2001
 
1860
- if (corners.length) {
1861
- m_this._setCornersFromMouse(corners, evt);
2002
+ switch (state) {
2003
+ case annotationState.create:
2004
+ features = [{
2005
+ line: {
2006
+ line: opt.vertices,
2007
+ style: m_this.styleForState(state)
2008
+ }
2009
+ }];
2010
+ break;
1862
2011
 
2012
+ default:
2013
+ features = [{
2014
+ line: {
2015
+ line: opt.vertices,
2016
+ style: m_this.styleForState(state)
2017
+ }
2018
+ }];
2019
+
2020
+ if (state === annotationState.edit) {
2021
+ m_this._addEditHandles(features, opt.vertices, undefined, !m_this.style('closed'));
2022
+ }
2023
+
2024
+ break;
2025
+ }
2026
+
2027
+ return features;
2028
+ };
2029
+ /**
2030
+ * Get and optionally set coordinates associated with this annotation in the
2031
+ * map gcs coordinate system.
2032
+ *
2033
+ * @param {geo.geoPosition[]} [coordinates] An optional array of coordinates
2034
+ * to set.
2035
+ * @returns {geo.geoPosition[]} The current array of coordinates.
2036
+ */
2037
+
2038
+
2039
+ this._coordinates = function (coordinates) {
2040
+ if (coordinates) {
2041
+ m_this.options('vertices', coordinates);
2042
+ }
2043
+
2044
+ return m_this.options('vertices');
2045
+ };
2046
+ /**
2047
+ * Handle a mouse move on this annotation.
2048
+ *
2049
+ * @param {geo.event} evt The mouse move event.
2050
+ * @returns {boolean} Truthy to update the annotation, falsy to not
2051
+ * update anything.
2052
+ */
2053
+
2054
+
2055
+ this.mouseMove = function (evt) {
2056
+ if (m_this.state() !== annotationState.create) {
2057
+ return;
2058
+ }
2059
+
2060
+ var vertices = m_this.options('vertices');
2061
+
2062
+ if (vertices.length) {
2063
+ vertices[vertices.length - 1] = evt.mapgcs;
1863
2064
  return true;
1864
2065
  }
1865
2066
  };
@@ -1882,313 +2083,257 @@ var rectangleAnnotation = function rectangleAnnotation(args, annotationName) {
1882
2083
  return;
1883
2084
  }
1884
2085
 
2086
+ var end = !!evt.buttonsDown.right,
2087
+ skip;
2088
+
1885
2089
  if (!evt.buttonsDown.left && !evt.buttonsDown.right) {
1886
2090
  return;
1887
2091
  }
1888
2092
 
1889
- var corners = m_this.options('corners');
2093
+ var vertices = m_this.options('vertices');
1890
2094
 
1891
- if (evt.buttonsDown.right && !corners.length) {
2095
+ if (evt.buttonsDown.right && !vertices.length) {
1892
2096
  return;
1893
2097
  }
1894
2098
 
1895
2099
  evt.handled = true;
1896
2100
 
1897
- if (corners.length) {
1898
- m_this._setCornersFromMouse(corners, evt);
1899
- /* Don't keep rectangles that have nearly zero area in display pixels */
2101
+ if (evt.buttonsDown.left) {
2102
+ if (vertices.length) {
2103
+ if (vertices.length >= 2 && layer.displayDistance(vertices[vertices.length - 2], null, evt.map, 'display') <= layer.options('adjacentPointProximity')) {
2104
+ skip = true;
1900
2105
 
2106
+ if (m_this._lastClick && evt.time - m_this._lastClick < layer.options('dblClickTime')) {
2107
+ end = true;
2108
+ }
2109
+ } else if (vertices.length >= 2 && layer.displayDistance(vertices[0], null, evt.map, 'display') <= layer.options('finalPointProximity')) {
2110
+ end = 'close';
2111
+ } else {
2112
+ vertices[vertices.length - 1] = evt.mapgcs;
2113
+ }
2114
+ } else {
2115
+ vertices.push(evt.mapgcs);
2116
+ }
1901
2117
 
1902
- if (layer.displayDistance(corners[0], null, corners[1], null) * layer.displayDistance(corners[0], null, corners[3], null) < 0.01) {
2118
+ if (!end && !skip) {
2119
+ vertices.push(evt.mapgcs);
2120
+ }
2121
+
2122
+ m_this._lastClick = evt.time;
2123
+ m_this._lastClickVertexCount = vertices.length;
2124
+ }
2125
+
2126
+ if (end) {
2127
+ if (vertices.length < 3) {
1903
2128
  return 'remove';
1904
2129
  }
1905
2130
 
2131
+ vertices.pop();
2132
+ m_this.options('style').closed = end === 'close';
1906
2133
  m_this.state(annotationState.done);
1907
2134
  return 'done';
1908
2135
  }
1909
2136
 
1910
- if (evt.buttonsDown.left) {
1911
- corners.push($.extend({}, evt.mapgcs));
1912
- corners.push($.extend({}, evt.mapgcs));
1913
- corners.push($.extend({}, evt.mapgcs));
1914
- corners.push($.extend({}, evt.mapgcs));
1915
- return true;
1916
- }
2137
+ return !skip;
1917
2138
  };
1918
2139
  /**
1919
- * Process any edit actions for this annotation.
2140
+ * Return actions needed for the specified state of this annotation.
2141
+ *
2142
+ * @param {string} [state] The state to return actions for. Defaults to
2143
+ * the current state.
2144
+ * @returns {geo.actionRecord[]} A list of actions.
2145
+ */
2146
+
2147
+
2148
+ this.actions = function (state) {
2149
+ return continuousVerticesActions(m_this, s_actions, state, 'line', arguments);
2150
+ };
2151
+ /**
2152
+ * Process any actions for this annotation.
1920
2153
  *
1921
2154
  * @param {geo.event} evt The action event.
1922
- * @returns {boolean|string} `true` to update the annotation, falsy to not
1923
- * update anything.
2155
+ * @returns {boolean|string} `true` to update the annotation, `'done'` if the
2156
+ * annotation was completed (changed from create to done state),
2157
+ * `'remove'` if the annotation should be removed, falsy to not update
2158
+ * anything.
1924
2159
  */
1925
2160
 
1926
2161
 
1927
- this.processEditAction = function (evt) {
1928
- var start = m_this._editHandle.startCoordinates,
1929
- delta = {
1930
- x: evt.mouse.mapgcs.x - evt.state.origin.mapgcs.x,
1931
- y: evt.mouse.mapgcs.y - evt.state.origin.mapgcs.y
1932
- },
1933
- type = m_this._editHandle.handle.type,
1934
- index = m_this._editHandle.handle.index,
1935
- ang = [Math.atan2(start[1].y - start[0].y, start[1].x - start[0].x), Math.atan2(start[2].y - start[1].y, start[2].x - start[1].x), Math.atan2(start[3].y - start[2].y, start[3].x - start[2].x), Math.atan2(start[0].y - start[3].y, start[0].x - start[3].x)],
1936
- corners,
1937
- delta1,
1938
- delta2,
1939
- ang1,
1940
- ang2; // an angle can be zero because it is horizontal or undefined. If opposite
1941
- // angles are both zero, this is a degenerate rectangle (a line or a point)
2162
+ this.processAction = function (evt) {
2163
+ return continuousVerticesProcessAction(m_this, evt, 'line');
2164
+ };
2165
+ /**
2166
+ * Return the coordinates to be stored in a geojson geometry object.
2167
+ *
2168
+ * @param {string|geo.transform|null} [gcs] `undefined` to use the interface
2169
+ * gcs, `null` to use the map gcs, or any other transform.
2170
+ * @returns {array} An array of flattened coordinates in the interface gcs
2171
+ * coordinate system. `undefined` if this annotation is incomplete.
2172
+ */
1942
2173
 
1943
- if (!ang[0] && !ang[1] && !ang[2] && !ang[3]) {
1944
- ang[1] = Math.PI / 2;
1945
- ang[2] = Math.PI;
1946
- ang[3] = -Math.PI / 2;
1947
- }
1948
2174
 
1949
- if (!ang[0] && !ang[2]) {
1950
- ang[0] = ang[1] - Math.PI / 2;
1951
- ang[2] = ang[1] + Math.PI / 2;
2175
+ this._geojsonCoordinates = function (gcs) {
2176
+ var src = m_this.coordinates(gcs);
2177
+
2178
+ if (!src || src.length < 2 || m_this.state() === annotationState.create) {
2179
+ return;
1952
2180
  }
1953
2181
 
1954
- if (!ang[1] && !ang[3]) {
1955
- ang[1] = ang[2] - Math.PI / 2;
1956
- ang[3] = ang[2] + Math.PI / 2;
2182
+ var coord = [];
2183
+
2184
+ for (var i = 0; i < src.length; i += 1) {
2185
+ coord.push([src[i].x, src[i].y]);
1957
2186
  }
1958
2187
 
1959
- switch (type) {
1960
- case 'vertex':
1961
- corners = start.map(function (elem) {
1962
- return {
1963
- x: elem.x,
1964
- y: elem.y
1965
- };
1966
- });
1967
- ang1 = ang[(index + 1) % 4];
1968
- delta1 = {
1969
- x: (delta.x * Math.cos(ang1) + delta.y * Math.sin(ang1)) * Math.cos(ang1),
1970
- y: (delta.y * Math.sin(ang1) + delta.x * Math.cos(ang1)) * Math.sin(ang1)
1971
- };
1972
- ang2 = ang[index];
1973
- delta2 = {
1974
- x: (delta.x * Math.cos(ang2) + delta.y * Math.sin(ang2)) * Math.cos(ang2),
1975
- y: (delta.y * Math.sin(ang2) + delta.x * Math.cos(ang2)) * Math.sin(ang2)
1976
- };
1977
- corners[index].x += delta.x;
1978
- corners[index].y += delta.y;
1979
- corners[(index + 1) % 4].x += delta1.x;
1980
- corners[(index + 1) % 4].y += delta1.y;
1981
- corners[(index + 3) % 4].x += delta2.x;
1982
- corners[(index + 3) % 4].y += delta2.y;
2188
+ return coord;
2189
+ };
2190
+ /**
2191
+ * Return the geometry type that is used to store this annotation in geojson.
2192
+ *
2193
+ * @returns {string} A geojson geometry type.
2194
+ */
1983
2195
 
1984
- if (this._selectionConstraint) {
1985
- corners = this._selectionConstraint(evt.mouse.mapgcs, evt.state.origin.mapgcs, corners, 'vertex', ang, index).corners;
1986
- }
1987
2196
 
1988
- m_this.options('corners', corners);
1989
- return true;
2197
+ this._geojsonGeometryType = function () {
2198
+ return 'LineString';
2199
+ };
2200
+ /**
2201
+ * Return a list of styles that should be preserved in a geojson
2202
+ * representation of the annotation.
2203
+ *
2204
+ * @returns {string[]} A list of style names to store.
2205
+ */
1990
2206
 
1991
- case 'edge':
1992
- corners = start.map(function (elem) {
1993
- return {
1994
- x: elem.x,
1995
- y: elem.y
1996
- };
1997
- });
1998
- ang1 = ang[(index + 1) % 4];
1999
- delta = {
2000
- x: (delta.x * Math.cos(ang1) + delta.y * Math.sin(ang1)) * Math.cos(ang1),
2001
- y: (delta.y * Math.sin(ang1) + delta.x * Math.cos(ang1)) * Math.sin(ang1)
2002
- };
2003
- corners[index].x += delta.x;
2004
- corners[index].y += delta.y;
2005
- corners[(index + 1) % 4].x += delta.x;
2006
- corners[(index + 1) % 4].y += delta.y;
2007
2207
 
2008
- if (this._selectionConstraint) {
2009
- corners = this._selectionConstraint(evt.mouse.mapgcs, evt.state.origin.mapgcs, corners, 'edge', ang, index).corners;
2010
- }
2208
+ this._geojsonStyles = function () {
2209
+ return ['closed', 'lineCap', 'lineJoin', 'strokeColor', 'strokeOffset', 'strokeOpacity', 'strokeWidth'];
2210
+ };
2211
+ /**
2212
+ * Process any edit actions for this annotation.
2213
+ *
2214
+ * @param {geo.event} evt The action event.
2215
+ * @returns {boolean|string} `true` to update the annotation, falsy to not
2216
+ * update anything.
2217
+ */
2011
2218
 
2012
- m_this.options('corners', corners);
2013
- return true;
2219
+
2220
+ this.processEditAction = function (evt) {
2221
+ switch (m_this._editHandle.handle.type) {
2222
+ case 'vertex':
2223
+ return m_this._processEditActionVertex(evt, true);
2014
2224
  }
2015
2225
 
2016
2226
  return s_processEditAction.apply(m_this, arguments);
2017
2227
  };
2018
- };
2019
-
2020
- inherit(rectangleAnnotation, annotation);
2021
- var rectangleRequiredFeatures = {};
2022
- rectangleRequiredFeatures[polygonFeature.capabilities.feature] = true;
2023
- registerAnnotation('rectangle', rectangleAnnotation, rectangleRequiredFeatures);
2024
- /**
2025
- * Square annotation class.
2026
- *
2027
- * Squares are a subset of rectangles with a fixed aspect ratio.
2028
- *
2029
- * @class
2030
- * @alias geo.squareAnnotation
2031
- * @extends geo.annotation
2032
- *
2033
- * @param {geo.squareAnnotation.spec?} [args] Options for the annotation.
2034
- * @param {string} [annotationName='square'] Override the annotation name.
2035
- */
2228
+ /**
2229
+ * Handle a mouse click on this annotation when in edit mode. If the event
2230
+ * is processed, evt.handled should be set to `true` to prevent further
2231
+ * processing.
2232
+ *
2233
+ * @param {geo.event} evt The mouse click event.
2234
+ * @returns {boolean|string} `true` to update the annotation, `'done'` if
2235
+ * the annotation was completed (changed from create to done state),
2236
+ * `'remove'` if the annotation should be removed, falsy to not update
2237
+ * anything.
2238
+ */
2036
2239
 
2037
- var squareAnnotation = function squareAnnotation(args, annotationName) {
2038
- 'use strict';
2039
2240
 
2040
- args = $.extend({}, args, {
2041
- constraint: 1
2042
- });
2241
+ this.mouseClickEdit = function (evt) {
2242
+ // if we get a left double click on an edge on a closed line, break the
2243
+ // line at that edge
2244
+ var layer = m_this.layer(),
2245
+ handle = m_this._editHandle,
2246
+ split; // ensure we are in edit mode and this is a left click
2043
2247
 
2044
- if (!(this instanceof squareAnnotation)) {
2045
- return new squareAnnotation(args, annotationName);
2046
- }
2248
+ if (m_this.state() !== annotationState.edit || !layer || !evt.buttonsDown.left) {
2249
+ return;
2250
+ } // ensure this is an edge on a closed line
2047
2251
 
2048
- rectangleAnnotation.call(this, args, annotationName || 'square');
2049
- };
2050
2252
 
2051
- inherit(squareAnnotation, rectangleAnnotation);
2052
- var squareRequiredFeatures = {};
2053
- squareRequiredFeatures[polygonFeature.capabilities.feature] = true;
2054
- registerAnnotation('square', squareAnnotation, squareRequiredFeatures);
2055
- /**
2056
- * Ellipse annotation class.
2057
- *
2058
- * Ellipses are always rendered as markers.
2059
- *
2060
- * @class
2061
- * @alias geo.ellipseAnnotation
2062
- * @extends geo.annotation
2063
- *
2064
- * @param {geo.ellipseAnnotation.spec?} [args] Options for the annotation.
2065
- * @param {string} [annotationName='ellipse'] Override the annotation name.
2066
- */
2253
+ if (!handle || !handle.handle.selected || handle.handle.type !== 'edge' || !m_this.options('style').closed) {
2254
+ return;
2255
+ }
2067
2256
 
2068
- var ellipseAnnotation = function ellipseAnnotation(args, annotationName) {
2069
- 'use strict';
2257
+ evt.handled = true;
2070
2258
 
2071
- if (!(this instanceof ellipseAnnotation)) {
2072
- return new ellipseAnnotation(args, annotationName);
2073
- }
2259
+ if (m_this._lastClick && evt.time - m_this._lastClick < layer.options('dblClickTime')) {
2260
+ split = true;
2261
+ }
2074
2262
 
2075
- rectangleAnnotation.call(this, args, annotationName || 'ellipse');
2076
- var m_this = this;
2077
- /**
2078
- * Get a list of renderable features for this annotation.
2079
- *
2080
- * @returns {array} An array of features.
2081
- */
2263
+ m_this._lastClick = evt.time;
2082
2264
 
2083
- this.features = function () {
2084
- var opt = m_this.options(),
2085
- state = m_this.state(),
2086
- features;
2087
- features = [];
2265
+ if (split) {
2266
+ var index = handle.handle.index,
2267
+ curPts = m_this._coordinates(),
2268
+ pts = curPts.slice(index + 1).concat(curPts.slice(0, index + 1));
2088
2269
 
2089
- if (opt.corners && opt.corners.length >= 4) {
2090
- var style = m_this.styleForState(state);
2091
- var w = Math.pow(Math.pow(opt.corners[0].x - opt.corners[1].x, 2) + Math.pow(opt.corners[0].y - opt.corners[1].y, 2), 0.5);
2092
- var h = Math.pow(Math.pow(opt.corners[0].x - opt.corners[3].x, 2) + Math.pow(opt.corners[0].y - opt.corners[3].y, 2), 0.5);
2093
- var radius = Math.max(w, h) / 2 / m_this.layer().map().unitsPerPixel(0);
2094
- var aspect = w ? h / w : 1e20;
2095
- var rotation = -Math.atan2(opt.corners[1].y - opt.corners[0].y, opt.corners[1].x - opt.corners[0].x);
2096
- features = [{
2097
- marker: {
2098
- x: (opt.corners[0].x + opt.corners[1].x + opt.corners[2].x + opt.corners[3].x) / 4,
2099
- y: (opt.corners[0].y + opt.corners[1].y + opt.corners[2].y + opt.corners[3].y) / 4,
2100
- style: $.extend({}, style, {
2101
- radius: radius,
2102
- symbolValue: aspect,
2103
- rotation: rotation,
2104
- strokeOffset: 0,
2105
- radiusIncludesStroke: false,
2106
- scaleWithZoom: markerFeature.scaleMode.fill,
2107
- rotateWithMap: true,
2108
- strokeOpacity: style.stroke === false ? 0 : style.strokeOpacity,
2109
- fillOpacity: style.fill === false ? 0 : style.fillOpacity
2110
- })
2111
- }
2112
- }];
2113
- }
2270
+ m_this._coordinates(pts);
2114
2271
 
2115
- if (state === annotationState.edit) {
2116
- m_this._addEditHandles(features, opt.corners);
2272
+ m_this.options('style').closed = false;
2273
+ handle.handle.index = undefined;
2274
+ return true;
2117
2275
  }
2118
-
2119
- return features;
2120
2276
  };
2121
2277
  };
2122
2278
 
2123
- inherit(ellipseAnnotation, rectangleAnnotation);
2124
- var ellipseRequiredFeatures = {};
2125
- ellipseRequiredFeatures[markerFeature.capabilities.feature] = true;
2126
- registerAnnotation('ellipse', ellipseAnnotation, ellipseRequiredFeatures);
2127
- /**
2128
- * Circle annotation class.
2129
- *
2130
- * Circles are a subset of rectangles with a fixed aspect ratio.
2131
- *
2132
- * @class
2133
- * @alias geo.circleAnnotation
2134
- * @extends geo.annotation
2135
- *
2136
- * @param {geo.circleAnnotation.spec?} [args] Options for the annotation.
2137
- * @param {string} [annotationName='circle'] Override the annotation name.
2138
- */
2279
+ inherit(lineAnnotation, annotation);
2280
+ var lineRequiredFeatures = {};
2281
+ lineRequiredFeatures[lineFeature.capabilities.basic] = [annotationState.create];
2282
+ registerAnnotation('line', lineAnnotation, lineRequiredFeatures);
2283
+ module.exports = lineAnnotation;
2139
2284
 
2140
- var circleAnnotation = function circleAnnotation(args, annotationName) {
2141
- 'use strict';
2285
+ /***/ }),
2142
2286
 
2143
- args = $.extend({}, args, {
2144
- constraint: 1
2145
- });
2287
+ /***/ 8296:
2288
+ /***/ (function(module, __unused_webpack_exports, __webpack_require__) {
2146
2289
 
2147
- if (!(this instanceof circleAnnotation)) {
2148
- return new circleAnnotation(args, annotationName);
2149
- }
2290
+ var $ = __webpack_require__(5638);
2150
2291
 
2151
- ellipseAnnotation.call(this, args, annotationName || 'circle');
2152
- };
2292
+ var inherit = __webpack_require__(5699);
2153
2293
 
2154
- inherit(circleAnnotation, ellipseAnnotation);
2155
- var circleRequiredFeatures = {};
2156
- circleRequiredFeatures[markerFeature.capabilities.feature] = true;
2157
- registerAnnotation('circle', circleAnnotation, circleRequiredFeatures);
2294
+ var util = __webpack_require__(4634);
2295
+
2296
+ var registerAnnotation = (__webpack_require__(4647).registerAnnotation);
2297
+
2298
+ var pointFeature = __webpack_require__(2557);
2299
+
2300
+ var annotation = (__webpack_require__(5784).annotation);
2301
+
2302
+ var annotationState = (__webpack_require__(5784).state);
2158
2303
  /**
2159
- * Polygon annotation specification. Extends {@link geo.annotation.spec}.
2304
+ * Point annotation specification. Extends {@link geo.annotation.spec}.
2160
2305
  *
2161
- * @typedef {object} geo.polygonAnnotation.spec
2306
+ * @typedef {object} geo.pointAnnotation.spec
2162
2307
  * @extends geo.annotation.spec
2163
- * @property {geo.geoPosition[]} [vertices] A list of vertices in map gcs
2164
- * coordinates. These must be in order around the perimeter of the polygon
2165
- * (in either direction).
2166
- * @property {geo.geoPosition[]} [coordinates] An alternate name for
2167
- * `vertices`.
2168
- * @property {geo.polygonFeature.styleSpec} [style] The style to apply to a
2169
- * finished polygon. This uses styles for {@link geo.polygonFeature}.
2170
- * @property {geo.polygonFeature.styleSpec} [editStyle] The style to apply to ai
2171
- * polygon in edit mode.
2308
+ * @property {geo.geoPosition} [position] A coordinate in map gcs coordinates.
2309
+ * @property {geo.geoPosition[]} [coordinates] An array with one coordinate to
2310
+ * use in place of `position`.
2311
+ * @property {geo.pointFeature.styleSpec} [style] The style to apply to a
2312
+ * finished point. This uses styles for {@link geo.pointFeature}.
2313
+ * @property {boolean|number} [style.scaled=false] If `false`, the point is not
2314
+ * scaled with zoom level. If `true`, the radius is based on the zoom level
2315
+ * at first instantiation. If a number, the radius is used at the `scaled`
2316
+ * zoom level.
2317
+ * @property {geo.pointFeature.styleSpec} [editStyle] The style to apply to a
2318
+ * point in edit mode.
2172
2319
  */
2173
2320
 
2174
2321
  /**
2175
- * Polygon annotation class
2176
- *
2177
- * When complete, polygons are rendered as polygons. During creation they are
2178
- * rendered as lines and polygons.
2322
+ * Point annotation class.
2179
2323
  *
2180
2324
  * @class
2181
- * @alias geo.polygonAnnotation
2325
+ * @alias geo.pointAnnotation
2182
2326
  * @extends geo.annotation
2183
2327
  *
2184
- * @param {geo.polygonAnnotation.spec?} [args] Options for the annotation.
2328
+ * @param {geo.pointAnnotation.spec?} [args] Options for the annotation.
2185
2329
  */
2186
2330
 
2187
- var polygonAnnotation = function polygonAnnotation(args) {
2331
+
2332
+ var pointAnnotation = function pointAnnotation(args) {
2188
2333
  'use strict';
2189
2334
 
2190
- if (!(this instanceof polygonAnnotation)) {
2191
- return new polygonAnnotation(args);
2335
+ if (!(this instanceof pointAnnotation)) {
2336
+ return new pointAnnotation(args);
2192
2337
  }
2193
2338
 
2194
2339
  args = $.extend(true, {}, {
@@ -2200,9 +2345,8 @@ var polygonAnnotation = function polygonAnnotation(args) {
2200
2345
  b: 0
2201
2346
  },
2202
2347
  fillOpacity: 0.25,
2203
- polygon: function polygon(d) {
2204
- return d.polygon;
2205
- },
2348
+ radius: 10,
2349
+ scaled: false,
2206
2350
  stroke: true,
2207
2351
  strokeColor: {
2208
2352
  r: 0,
@@ -2210,60 +2354,37 @@ var polygonAnnotation = function polygonAnnotation(args) {
2210
2354
  b: 0
2211
2355
  },
2212
2356
  strokeOpacity: 1,
2213
- strokeWidth: 3,
2214
- uniformPolygon: true
2215
- },
2216
- highlightStyle: {
2217
- fillColor: {
2218
- r: 0,
2219
- g: 1,
2220
- b: 1
2221
- },
2222
- fillOpacity: 0.5,
2223
- strokeWidth: 5
2357
+ strokeWidth: 3
2224
2358
  },
2225
2359
  createStyle: {
2226
- closed: false,
2227
2360
  fillColor: {
2228
2361
  r: 0.3,
2229
2362
  g: 0.3,
2230
2363
  b: 0.3
2231
2364
  },
2232
2365
  fillOpacity: 0.25,
2233
- line: function line(d) {
2234
- var coord = m_this._coordinates();
2235
- /* Return an array that has the same number of items as we have
2236
- * vertices. */
2237
-
2238
-
2239
- return Array.apply(null, Array((coord.outer || coord).length)).map(function () {
2240
- return d;
2241
- });
2242
- },
2243
- position: function position(d, i) {
2244
- if (d.x !== undefined) {
2245
- return d.x;
2246
- }
2247
-
2248
- return m_this.options('vertices')[i];
2249
- },
2250
- stroke: false,
2251
2366
  strokeColor: {
2252
2367
  r: 0,
2253
2368
  g: 0,
2254
2369
  b: 1
2255
2370
  }
2371
+ },
2372
+ highlightStyle: {
2373
+ fillColor: {
2374
+ r: 0,
2375
+ g: 1,
2376
+ b: 1
2377
+ },
2378
+ fillOpacity: 0.5,
2379
+ strokeWidth: 5
2256
2380
  }
2257
2381
  }, args || {});
2258
- args.vertices = args.vertices || args.coordinates || [];
2382
+ args.position = args.position || (args.coordinates ? args.coordinates[0] : undefined);
2259
2383
  delete args.coordinates;
2260
- annotation.call(this, 'polygon', args);
2261
- var m_this = this,
2262
- s_actions = this.actions;
2384
+ annotation.call(this, 'point', args);
2385
+ var m_this = this;
2263
2386
  /**
2264
- * Get a list of renderable features for this annotation. When the polygon
2265
- * is done, this is just a single polygon. During creation this can be a
2266
- * polygon and line at z-levels 1 and 2.
2387
+ * Get a list of renderable features for this annotation.
2267
2388
  *
2268
2389
  * @returns {array} An array of features.
2269
2390
  */
@@ -2271,43 +2392,55 @@ var polygonAnnotation = function polygonAnnotation(args) {
2271
2392
  this.features = function () {
2272
2393
  var opt = m_this.options(),
2273
2394
  state = m_this.state(),
2274
- style = m_this.styleForState(state),
2275
- features;
2395
+ features,
2396
+ style,
2397
+ scaleOnZoom;
2276
2398
 
2277
2399
  switch (state) {
2278
2400
  case annotationState.create:
2279
2401
  features = [];
2402
+ break;
2280
2403
 
2281
- if (opt.vertices && (opt.vertices.outer || opt.vertices.length >= 3)) {
2282
- features[1] = {
2283
- polygon: {
2284
- polygon: opt.vertices,
2285
- style: style
2286
- }
2287
- };
2288
- }
2404
+ default:
2405
+ style = m_this.styleForState(state);
2289
2406
 
2290
- if (opt.vertices && opt.vertices.length >= 2) {
2291
- features[2] = {
2292
- line: {
2293
- line: opt.vertices,
2294
- style: style
2407
+ if (opt.style.scaled || opt.style.scaled === 0) {
2408
+ if (opt.style.scaled === true) {
2409
+ opt.style.scaled = m_this.layer().map().zoom();
2410
+ }
2411
+
2412
+ style = $.extend({}, style, {
2413
+ radius: function radius() {
2414
+ var radius = opt.style.radius,
2415
+ zoom = m_this.layer().map().zoom();
2416
+
2417
+ if (util.isFunction(radius)) {
2418
+ radius = radius.apply(m_this, arguments);
2419
+ }
2420
+
2421
+ radius *= Math.pow(2, zoom - opt.style.scaled);
2422
+ return radius;
2295
2423
  }
2296
- };
2424
+ });
2425
+ scaleOnZoom = true;
2297
2426
  }
2298
2427
 
2299
- break;
2300
-
2301
- default:
2302
2428
  features = [{
2303
- polygon: {
2304
- polygon: opt.vertices,
2305
- style: style
2429
+ point: {
2430
+ x: opt.position.x,
2431
+ y: opt.position.y,
2432
+ style: style,
2433
+ scaleOnZoom: scaleOnZoom
2306
2434
  }
2307
2435
  }];
2308
2436
 
2309
2437
  if (state === annotationState.edit) {
2310
- m_this._addEditHandles(features, opt.vertices);
2438
+ m_this._addEditHandles(features, [opt.position], {
2439
+ edge: false,
2440
+ center: false,
2441
+ resize: false,
2442
+ rotate: false
2443
+ });
2311
2444
  }
2312
2445
 
2313
2446
  break;
@@ -2326,129 +2459,53 @@ var polygonAnnotation = function polygonAnnotation(args) {
2326
2459
 
2327
2460
 
2328
2461
  this._coordinates = function (coordinates) {
2329
- if (coordinates) {
2330
- m_this.options('vertices', coordinates);
2331
- }
2332
-
2333
- return m_this.options('vertices');
2334
- };
2335
- /**
2336
- * Handle a mouse move on this annotation.
2337
- *
2338
- * @param {geo.event} evt The mouse move event.
2339
- * @returns {boolean} Truthy to update the annotation, falsy to not
2340
- * update anything.
2341
- */
2342
-
2343
-
2344
- this.mouseMove = function (evt) {
2345
- if (m_this.state() !== annotationState.create) {
2346
- return;
2347
- }
2348
-
2349
- var vertices = m_this.options('vertices');
2350
-
2351
- if (vertices.length) {
2352
- vertices[vertices.length - 1] = evt.mapgcs;
2353
- return true;
2354
- }
2355
- };
2356
- /**
2357
- * Handle a mouse click on this annotation. If the event is processed,
2358
- * evt.handled should be set to `true` to prevent further processing.
2359
- *
2360
- * @param {geo.event} evt The mouse click event.
2361
- * @returns {boolean|string} `true` to update the annotation, `'done'` if
2362
- * the annotation was completed (changed from create to done state),
2363
- * `'remove'` if the annotation should be removed, falsy to not update
2364
- * anything.
2365
- */
2366
-
2367
-
2368
- this.mouseClick = function (evt) {
2369
- var layer = m_this.layer();
2370
-
2371
- if (m_this.state() !== annotationState.create || !layer) {
2372
- return;
2373
- }
2374
-
2375
- var end = !!evt.buttonsDown.right,
2376
- skip;
2377
-
2378
- if (!evt.buttonsDown.left && !evt.buttonsDown.right) {
2379
- return;
2380
- }
2381
-
2382
- var vertices = m_this.options('vertices');
2383
-
2384
- if (evt.buttonsDown.right && !vertices.length) {
2385
- return;
2386
- }
2387
-
2388
- evt.handled = true;
2389
-
2390
- if (evt.buttonsDown.left) {
2391
- if (vertices.length) {
2392
- if (vertices.length >= 2 && layer.displayDistance(vertices[vertices.length - 2], null, evt.map, 'display') <= layer.options('adjacentPointProximity')) {
2393
- skip = true;
2394
-
2395
- if (m_this._lastClick && evt.time - m_this._lastClick < layer.options('dblClickTime')) {
2396
- end = true;
2397
- }
2398
- } else if (vertices.length >= 2 && layer.displayDistance(vertices[0], null, evt.map, 'display') <= layer.options('finalPointProximity')) {
2399
- end = true;
2400
- } else {
2401
- vertices[vertices.length - 1] = evt.mapgcs;
2402
- }
2403
- } else {
2404
- vertices.push(evt.mapgcs);
2405
- }
2406
-
2407
- if (!end && !skip) {
2408
- vertices.push(evt.mapgcs);
2409
- }
2410
-
2411
- m_this._lastClick = evt.time;
2412
- m_this._lastClickVertexCount = vertices.length;
2462
+ if (coordinates && coordinates.length >= 1) {
2463
+ m_this.options('position', coordinates[0]);
2413
2464
  }
2414
2465
 
2415
- if (end) {
2416
- if (vertices.length < 4) {
2417
- return 'remove';
2418
- }
2419
-
2420
- vertices.pop();
2421
- m_this.state(annotationState.done);
2422
- return 'done';
2466
+ if (m_this.state() === annotationState.create) {
2467
+ return [];
2423
2468
  }
2424
2469
 
2425
- return !skip;
2470
+ return [m_this.options('position')];
2426
2471
  };
2472
+
2473
+ this._coordinateOption = 'position';
2427
2474
  /**
2428
- * Return actions needed for the specified state of this annotation.
2475
+ * Handle a mouse click on this annotation. If the event is processed,
2476
+ * evt.handled should be set to `true` to prevent further processing.
2429
2477
  *
2430
- * @param {string} [state] The state to return actions for. Defaults to
2431
- * the current state.
2432
- * @returns {geo.actionRecord[]} A list of actions.
2478
+ * @param {geo.event} evt The mouse click event.
2479
+ * @returns {boolean|string} `true` to update the annotation, `'done'` if
2480
+ * the annotation was completed (changed from create to done state),
2481
+ * `'remove'` if the annotation should be removed, falsy to not update
2482
+ * anything.
2433
2483
  */
2434
2484
 
2485
+ this.mouseClick = function (evt) {
2486
+ if (m_this.state() !== annotationState.create) {
2487
+ return;
2488
+ }
2435
2489
 
2436
- this.actions = function (state) {
2437
- return continuousVerticesActions(m_this, s_actions, state, 'polygon', arguments);
2490
+ if (!evt.buttonsDown.left) {
2491
+ return;
2492
+ }
2493
+
2494
+ evt.handled = true;
2495
+ m_this.options('position', evt.mapgcs);
2496
+ m_this.state(annotationState.done);
2497
+ return 'done';
2438
2498
  };
2439
2499
  /**
2440
- * Process any actions for this annotation.
2500
+ * Return a list of styles that should be preserved in a geojson
2501
+ * representation of the annotation.
2441
2502
  *
2442
- * @param {geo.event} evt The action event.
2443
- * @returns {boolean|string} `true` to update the annotation, `'done'` if the
2444
- * annotation was completed (changed from create to done state),
2445
- * `'remove'` if the annotation should be removed, falsy to not update
2446
- * anything.
2503
+ * @returns {string[]} A list of style names to store.
2447
2504
  */
2448
2505
 
2449
2506
 
2450
- this.processAction = function (evt) {
2451
- return continuousVerticesProcessAction(m_this, evt, 'polygon');
2507
+ this._geojsonStyles = function () {
2508
+ return ['fill', 'fillColor', 'fillOpacity', 'radius', 'scaled', 'stroke', 'strokeColor', 'strokeOpacity', 'strokeWidth'];
2452
2509
  };
2453
2510
  /**
2454
2511
  * Return the coordinates to be stored in a geojson geometry object.
@@ -2463,32 +2520,11 @@ var polygonAnnotation = function polygonAnnotation(args) {
2463
2520
  this._geojsonCoordinates = function (gcs) {
2464
2521
  var src = m_this.coordinates(gcs);
2465
2522
 
2466
- if (!src || !src.outer && src.length < 3 || m_this.state() === annotationState.create) {
2523
+ if (!src || m_this.state() === annotationState.create || src.length < 1 || src[0] === undefined) {
2467
2524
  return;
2468
2525
  }
2469
2526
 
2470
- var coord = [];
2471
-
2472
- if (!src.outer) {
2473
- coord = [src.map(function (pt) {
2474
- return [pt.x, pt.y];
2475
- })];
2476
- coord[0].push(coord[0][0].slice());
2477
- } else {
2478
- coord = [src.outer.map(function (pt) {
2479
- return [pt.x, pt.y];
2480
- })];
2481
- coord[0].push(coord[0][0].slice());
2482
- (src.inner || []).forEach(function (h) {
2483
- var poly = h.map(function (pt) {
2484
- return [pt.x, pt.y];
2485
- });
2486
- poly.push(poly[0].slice());
2487
- coord.push(poly);
2488
- });
2489
- }
2490
-
2491
- return coord;
2527
+ return [src[0].x, src[0].y];
2492
2528
  };
2493
2529
  /**
2494
2530
  * Return the geometry type that is used to store this annotation in geojson.
@@ -2498,70 +2534,88 @@ var polygonAnnotation = function polygonAnnotation(args) {
2498
2534
 
2499
2535
 
2500
2536
  this._geojsonGeometryType = function () {
2501
- return 'Polygon';
2537
+ return 'Point';
2502
2538
  };
2503
- /**
2504
- * Return a list of styles that should be preserved in a geojson
2505
- * representation of the annotation.
2506
- *
2507
- * @returns {string[]} A list of style names to store.
2508
- */
2539
+ };
2509
2540
 
2541
+ inherit(pointAnnotation, annotation);
2542
+ var pointRequiredFeatures = {};
2543
+ pointRequiredFeatures[pointFeature.capabilities.feature] = true;
2544
+ registerAnnotation('point', pointAnnotation, pointRequiredFeatures);
2545
+ module.exports = pointAnnotation;
2510
2546
 
2511
- this._geojsonStyles = function () {
2512
- return ['fill', 'fillColor', 'fillOpacity', 'lineCap', 'lineJoin', 'stroke', 'strokeColor', 'strokeOffset', 'strokeOpacity', 'strokeWidth'];
2513
- };
2514
- };
2547
+ /***/ }),
2515
2548
 
2516
- inherit(polygonAnnotation, annotation);
2517
- var polygonRequiredFeatures = {};
2518
- polygonRequiredFeatures[polygonFeature.capabilities.feature] = true;
2519
- polygonRequiredFeatures[lineFeature.capabilities.basic] = [annotationState.create];
2520
- registerAnnotation('polygon', polygonAnnotation, polygonRequiredFeatures);
2549
+ /***/ 56:
2550
+ /***/ (function(module, __unused_webpack_exports, __webpack_require__) {
2551
+
2552
+ var $ = __webpack_require__(5638);
2553
+
2554
+ var inherit = __webpack_require__(5699);
2555
+
2556
+ var registerAnnotation = (__webpack_require__(4647).registerAnnotation);
2557
+
2558
+ var lineFeature = __webpack_require__(4708);
2559
+
2560
+ var polygonFeature = __webpack_require__(4343);
2561
+
2562
+ var annotation = (__webpack_require__(5784).annotation);
2563
+
2564
+ var annotationState = (__webpack_require__(5784).state);
2565
+
2566
+ var continuousVerticesActions = (__webpack_require__(5784).continuousVerticesActions);
2567
+
2568
+ var continuousVerticesProcessAction = (__webpack_require__(5784).continuousVerticesProcessAction);
2521
2569
  /**
2522
- * Line annotation specification. Extends {@link geo.annotation.spec}.
2570
+ * Polygon annotation specification. Extends {@link geo.annotation.spec}.
2523
2571
  *
2524
- * @typedef {object} geo.lineAnnotation.spec
2572
+ * @typedef {object} geo.polygonAnnotation.spec
2525
2573
  * @extends geo.annotation.spec
2526
2574
  * @property {geo.geoPosition[]} [vertices] A list of vertices in map gcs
2527
- * coordinates.
2575
+ * coordinates. These must be in order around the perimeter of the polygon
2576
+ * (in either direction).
2528
2577
  * @property {geo.geoPosition[]} [coordinates] An alternate name for
2529
2578
  * `vertices`.
2530
- * @property {geo.lineFeature.styleSpec} [style] The style to apply to a
2531
- * finished line. This uses styles for {@link geo.lineFeature}.
2532
- * @property {geo.lineFeature.styleSpec} [editStyle] The style to apply to a
2533
- * line in edit mode.
2579
+ * @property {geo.polygonFeature.styleSpec} [style] The style to apply to a
2580
+ * finished polygon. This uses styles for {@link geo.polygonFeature}.
2581
+ * @property {geo.polygonFeature.styleSpec} [editStyle] The style to apply to ai
2582
+ * polygon in edit mode.
2534
2583
  */
2535
2584
 
2536
2585
  /**
2537
- * Line annotation class.
2586
+ * Polygon annotation class
2587
+ *
2588
+ * When complete, polygons are rendered as polygons. During creation they are
2589
+ * rendered as lines and polygons.
2538
2590
  *
2539
2591
  * @class
2540
- * @alias geo.lineAnnotation
2592
+ * @alias geo.polygonAnnotation
2541
2593
  * @extends geo.annotation
2542
2594
  *
2543
- * @param {geo.lineAnnotation.spec?} [args] Options for the annotation.
2595
+ * @param {geo.polygonAnnotation.spec?} [args] Options for the annotation.
2544
2596
  */
2545
2597
 
2546
- var lineAnnotation = function lineAnnotation(args) {
2598
+
2599
+ var polygonAnnotation = function polygonAnnotation(args) {
2547
2600
  'use strict';
2548
2601
 
2549
- if (!(this instanceof lineAnnotation)) {
2550
- return new lineAnnotation(args);
2602
+ if (!(this instanceof polygonAnnotation)) {
2603
+ return new polygonAnnotation(args);
2551
2604
  }
2552
2605
 
2553
2606
  args = $.extend(true, {}, {
2554
2607
  style: {
2555
- line: function line(d) {
2556
- /* Return an array that has the same number of items as we have
2557
- * vertices. */
2558
- return Array.apply(null, Array(m_this.options('vertices').length)).map(function () {
2559
- return d;
2560
- });
2608
+ fill: true,
2609
+ fillColor: {
2610
+ r: 0,
2611
+ g: 1,
2612
+ b: 0
2561
2613
  },
2562
- position: function position(d, i) {
2563
- return m_this.options('vertices')[i];
2614
+ fillOpacity: 0.25,
2615
+ polygon: function polygon(d) {
2616
+ return d.polygon;
2564
2617
  },
2618
+ stroke: true,
2565
2619
  strokeColor: {
2566
2620
  r: 0,
2567
2621
  g: 0,
@@ -2569,44 +2623,59 @@ var lineAnnotation = function lineAnnotation(args) {
2569
2623
  },
2570
2624
  strokeOpacity: 1,
2571
2625
  strokeWidth: 3,
2572
- closed: false,
2573
- lineCap: 'butt',
2574
- lineJoin: 'miter'
2626
+ uniformPolygon: true
2575
2627
  },
2576
2628
  highlightStyle: {
2629
+ fillColor: {
2630
+ r: 0,
2631
+ g: 1,
2632
+ b: 1
2633
+ },
2634
+ fillOpacity: 0.5,
2577
2635
  strokeWidth: 5
2578
2636
  },
2579
2637
  createStyle: {
2638
+ closed: false,
2639
+ fillColor: {
2640
+ r: 0.3,
2641
+ g: 0.3,
2642
+ b: 0.3
2643
+ },
2644
+ fillOpacity: 0.25,
2580
2645
  line: function line(d) {
2646
+ var coord = m_this._coordinates();
2581
2647
  /* Return an array that has the same number of items as we have
2582
2648
  * vertices. */
2583
- return Array.apply(null, Array(m_this.options('vertices').length)).map(function () {
2649
+
2650
+
2651
+ return Array.apply(null, Array((coord.outer || coord).length)).map(function () {
2584
2652
  return d;
2585
2653
  });
2586
2654
  },
2587
2655
  position: function position(d, i) {
2656
+ if (d.x !== undefined) {
2657
+ return d.x;
2658
+ }
2659
+
2588
2660
  return m_this.options('vertices')[i];
2589
2661
  },
2662
+ stroke: false,
2590
2663
  strokeColor: {
2591
2664
  r: 0,
2592
2665
  g: 0,
2593
2666
  b: 1
2594
- },
2595
- strokeOpacity: 1,
2596
- strokeWidth: 3,
2597
- closed: false,
2598
- lineCap: 'butt',
2599
- lineJoin: 'miter'
2667
+ }
2600
2668
  }
2601
2669
  }, args || {});
2602
2670
  args.vertices = args.vertices || args.coordinates || [];
2603
2671
  delete args.coordinates;
2604
- annotation.call(this, 'line', args);
2672
+ annotation.call(this, 'polygon', args);
2605
2673
  var m_this = this,
2606
- s_actions = this.actions,
2607
- s_processEditAction = this.processEditAction;
2674
+ s_actions = this.actions;
2608
2675
  /**
2609
- * Get a list of renderable features for this annotation.
2676
+ * Get a list of renderable features for this annotation. When the polygon
2677
+ * is done, this is just a single polygon. During creation this can be a
2678
+ * polygon and line at z-levels 1 and 2.
2610
2679
  *
2611
2680
  * @returns {array} An array of features.
2612
2681
  */
@@ -2614,28 +2683,43 @@ var lineAnnotation = function lineAnnotation(args) {
2614
2683
  this.features = function () {
2615
2684
  var opt = m_this.options(),
2616
2685
  state = m_this.state(),
2686
+ style = m_this.styleForState(state),
2617
2687
  features;
2618
2688
 
2619
2689
  switch (state) {
2620
2690
  case annotationState.create:
2621
- features = [{
2622
- line: {
2623
- line: opt.vertices,
2624
- style: m_this.styleForState(state)
2625
- }
2626
- }];
2691
+ features = [];
2692
+
2693
+ if (opt.vertices && (opt.vertices.outer || opt.vertices.length >= 3)) {
2694
+ features[1] = {
2695
+ polygon: {
2696
+ polygon: opt.vertices,
2697
+ style: style
2698
+ }
2699
+ };
2700
+ }
2701
+
2702
+ if (opt.vertices && opt.vertices.length >= 2) {
2703
+ features[2] = {
2704
+ line: {
2705
+ line: opt.vertices,
2706
+ style: style
2707
+ }
2708
+ };
2709
+ }
2710
+
2627
2711
  break;
2628
2712
 
2629
2713
  default:
2630
2714
  features = [{
2631
- line: {
2632
- line: opt.vertices,
2633
- style: m_this.styleForState(state)
2715
+ polygon: {
2716
+ polygon: opt.vertices,
2717
+ style: style
2634
2718
  }
2635
2719
  }];
2636
2720
 
2637
2721
  if (state === annotationState.edit) {
2638
- m_this._addEditHandles(features, opt.vertices, undefined, !m_this.style('closed'));
2722
+ m_this._addEditHandles(features, opt.vertices);
2639
2723
  }
2640
2724
 
2641
2725
  break;
@@ -2724,7 +2808,7 @@ var lineAnnotation = function lineAnnotation(args) {
2724
2808
  end = true;
2725
2809
  }
2726
2810
  } else if (vertices.length >= 2 && layer.displayDistance(vertices[0], null, evt.map, 'display') <= layer.options('finalPointProximity')) {
2727
- end = 'close';
2811
+ end = true;
2728
2812
  } else {
2729
2813
  vertices[vertices.length - 1] = evt.mapgcs;
2730
2814
  }
@@ -2741,12 +2825,11 @@ var lineAnnotation = function lineAnnotation(args) {
2741
2825
  }
2742
2826
 
2743
2827
  if (end) {
2744
- if (vertices.length < 3) {
2828
+ if (vertices.length < 4) {
2745
2829
  return 'remove';
2746
2830
  }
2747
2831
 
2748
2832
  vertices.pop();
2749
- m_this.options('style').closed = end === 'close';
2750
2833
  m_this.state(annotationState.done);
2751
2834
  return 'done';
2752
2835
  }
@@ -2763,7 +2846,7 @@ var lineAnnotation = function lineAnnotation(args) {
2763
2846
 
2764
2847
 
2765
2848
  this.actions = function (state) {
2766
- return continuousVerticesActions(m_this, s_actions, state, 'line', arguments);
2849
+ return continuousVerticesActions(m_this, s_actions, state, 'polygon', arguments);
2767
2850
  };
2768
2851
  /**
2769
2852
  * Process any actions for this annotation.
@@ -2777,7 +2860,7 @@ var lineAnnotation = function lineAnnotation(args) {
2777
2860
 
2778
2861
 
2779
2862
  this.processAction = function (evt) {
2780
- return continuousVerticesProcessAction(m_this, evt, 'line');
2863
+ return continuousVerticesProcessAction(m_this, evt, 'polygon');
2781
2864
  };
2782
2865
  /**
2783
2866
  * Return the coordinates to be stored in a geojson geometry object.
@@ -2792,14 +2875,29 @@ var lineAnnotation = function lineAnnotation(args) {
2792
2875
  this._geojsonCoordinates = function (gcs) {
2793
2876
  var src = m_this.coordinates(gcs);
2794
2877
 
2795
- if (!src || src.length < 2 || m_this.state() === annotationState.create) {
2878
+ if (!src || !src.outer && src.length < 3 || m_this.state() === annotationState.create) {
2796
2879
  return;
2797
2880
  }
2798
2881
 
2799
2882
  var coord = [];
2800
2883
 
2801
- for (var i = 0; i < src.length; i += 1) {
2802
- coord.push([src[i].x, src[i].y]);
2884
+ if (!src.outer) {
2885
+ coord = [src.map(function (pt) {
2886
+ return [pt.x, pt.y];
2887
+ })];
2888
+ coord[0].push(coord[0][0].slice());
2889
+ } else {
2890
+ coord = [src.outer.map(function (pt) {
2891
+ return [pt.x, pt.y];
2892
+ })];
2893
+ coord[0].push(coord[0][0].slice());
2894
+ (src.inner || []).forEach(function (h) {
2895
+ var poly = h.map(function (pt) {
2896
+ return [pt.x, pt.y];
2897
+ });
2898
+ poly.push(poly[0].slice());
2899
+ coord.push(poly);
2900
+ });
2803
2901
  }
2804
2902
 
2805
2903
  return coord;
@@ -2812,7 +2910,7 @@ var lineAnnotation = function lineAnnotation(args) {
2812
2910
 
2813
2911
 
2814
2912
  this._geojsonGeometryType = function () {
2815
- return 'LineString';
2913
+ return 'Polygon';
2816
2914
  };
2817
2915
  /**
2818
2916
  * Return a list of styles that should be preserved in a geojson
@@ -2823,113 +2921,79 @@ var lineAnnotation = function lineAnnotation(args) {
2823
2921
 
2824
2922
 
2825
2923
  this._geojsonStyles = function () {
2826
- return ['closed', 'lineCap', 'lineJoin', 'strokeColor', 'strokeOffset', 'strokeOpacity', 'strokeWidth'];
2827
- };
2828
- /**
2829
- * Process any edit actions for this annotation.
2830
- *
2831
- * @param {geo.event} evt The action event.
2832
- * @returns {boolean|string} `true` to update the annotation, falsy to not
2833
- * update anything.
2834
- */
2835
-
2836
-
2837
- this.processEditAction = function (evt) {
2838
- switch (m_this._editHandle.handle.type) {
2839
- case 'vertex':
2840
- return m_this._processEditActionVertex(evt, true);
2841
- }
2842
-
2843
- return s_processEditAction.apply(m_this, arguments);
2924
+ return ['fill', 'fillColor', 'fillOpacity', 'lineCap', 'lineJoin', 'stroke', 'strokeColor', 'strokeOffset', 'strokeOpacity', 'strokeWidth'];
2844
2925
  };
2845
- /**
2846
- * Handle a mouse click on this annotation when in edit mode. If the event
2847
- * is processed, evt.handled should be set to `true` to prevent further
2848
- * processing.
2849
- *
2850
- * @param {geo.event} evt The mouse click event.
2851
- * @returns {boolean|string} `true` to update the annotation, `'done'` if
2852
- * the annotation was completed (changed from create to done state),
2853
- * `'remove'` if the annotation should be removed, falsy to not update
2854
- * anything.
2855
- */
2926
+ };
2856
2927
 
2928
+ inherit(polygonAnnotation, annotation);
2929
+ var polygonRequiredFeatures = {};
2930
+ polygonRequiredFeatures[polygonFeature.capabilities.feature] = true;
2931
+ polygonRequiredFeatures[lineFeature.capabilities.basic] = [annotationState.create];
2932
+ registerAnnotation('polygon', polygonAnnotation, polygonRequiredFeatures);
2933
+ module.exports = polygonAnnotation;
2857
2934
 
2858
- this.mouseClickEdit = function (evt) {
2859
- // if we get a left double click on an edge on a closed line, break the
2860
- // line at that edge
2861
- var layer = m_this.layer(),
2862
- handle = m_this._editHandle,
2863
- split; // ensure we are in edit mode and this is a left click
2935
+ /***/ }),
2864
2936
 
2865
- if (m_this.state() !== annotationState.edit || !layer || !evt.buttonsDown.left) {
2866
- return;
2867
- } // ensure this is an edge on a closed line
2937
+ /***/ 3442:
2938
+ /***/ (function(module, __unused_webpack_exports, __webpack_require__) {
2868
2939
 
2940
+ var $ = __webpack_require__(5638);
2869
2941
 
2870
- if (!handle || !handle.handle.selected || handle.handle.type !== 'edge' || !m_this.options('style').closed) {
2871
- return;
2872
- }
2942
+ var inherit = __webpack_require__(5699);
2873
2943
 
2874
- evt.handled = true;
2944
+ var geo_event = __webpack_require__(5108);
2875
2945
 
2876
- if (m_this._lastClick && evt.time - m_this._lastClick < layer.options('dblClickTime')) {
2877
- split = true;
2878
- }
2946
+ var geo_action = __webpack_require__(7839);
2879
2947
 
2880
- m_this._lastClick = evt.time;
2948
+ var registerAnnotation = (__webpack_require__(4647).registerAnnotation);
2881
2949
 
2882
- if (split) {
2883
- var index = handle.handle.index,
2884
- curPts = m_this._coordinates(),
2885
- pts = curPts.slice(index + 1).concat(curPts.slice(0, index + 1));
2950
+ var polygonFeature = __webpack_require__(4343);
2886
2951
 
2887
- m_this._coordinates(pts);
2952
+ var annotation = (__webpack_require__(5784).annotation);
2888
2953
 
2889
- m_this.options('style').closed = false;
2890
- handle.handle.index = undefined;
2891
- return true;
2892
- }
2893
- };
2894
- };
2954
+ var annotationState = (__webpack_require__(5784).state);
2895
2955
 
2896
- inherit(lineAnnotation, annotation);
2897
- var lineRequiredFeatures = {};
2898
- lineRequiredFeatures[lineFeature.capabilities.basic] = [annotationState.create];
2899
- registerAnnotation('line', lineAnnotation, lineRequiredFeatures);
2956
+ var annotationActionOwner = (__webpack_require__(5784).annotationActionOwner);
2900
2957
  /**
2901
- * Point annotation specification. Extends {@link geo.annotation.spec}.
2958
+ * Rectangle annotation specification. Extends {@link geo.annotation.spec}.
2902
2959
  *
2903
- * @typedef {object} geo.pointAnnotation.spec
2960
+ * @typedef {object} geo.rectangleAnnotation.spec
2904
2961
  * @extends geo.annotation.spec
2905
- * @property {geo.geoPosition} [position] A coordinate in map gcs coordinates.
2906
- * @property {geo.geoPosition[]} [coordinates] An array with one coordinate to
2907
- * use in place of `position`.
2908
- * @property {geo.pointFeature.styleSpec} [style] The style to apply to a
2909
- * finished point. This uses styles for {@link geo.pointFeature}.
2910
- * @property {boolean|number} [style.scaled=false] If `false`, the point is not
2911
- * scaled with zoom level. If `true`, the radius is based on the zoom level
2912
- * at first instantiation. If a number, the radius is used at the `scaled`
2913
- * zoom level.
2914
- * @property {geo.pointFeature.styleSpec} [editStyle] The style to apply to a
2915
- * point in edit mode.
2962
+ * @property {geo.geoPosition[]} [corners] A list of four corners in map gcs
2963
+ * coordinates. These must be in order around the perimeter of the
2964
+ * rectangle (in either direction).
2965
+ * @property {geo.geoPosition[]} [coordinates] An alternate name for `corners`.
2966
+ * @property {geo.polygonFeature.styleSpec} [style] The style to apply to a
2967
+ * finished rectangle. This uses styles for {@link geo.polygonFeature}.
2968
+ * @property {geo.polygonFeature.styleSpec} [editStyle] The style to apply to a
2969
+ * rectangle in edit mode.
2970
+ * @property {number|number[]|function} [constraint] If specified, an aspect
2971
+ * ratio or list of aspect ratios to constraint the rectangle to. If a
2972
+ * function, a selection constraint function to call to adjust the
2973
+ * rectangle.
2916
2974
  */
2917
2975
 
2918
2976
  /**
2919
- * Point annotation class.
2977
+ * Rectangle annotation class.
2978
+ *
2979
+ * Rectangles are always rendered as polygons. This could be changed -- if no
2980
+ * stroke is specified, the quad feature would be sufficient and work on more
2981
+ * renderers.
2920
2982
  *
2921
2983
  * @class
2922
- * @alias geo.pointAnnotation
2984
+ * @alias geo.rectangleAnnotation
2923
2985
  * @extends geo.annotation
2924
2986
  *
2925
- * @param {geo.pointAnnotation.spec?} [args] Options for the annotation.
2987
+ * @param {geo.rectangleAnnotation.spec?} [args] Options for the annotation.
2988
+ * @param {string} [annotationName='rectangle'] Override the annotation name.
2926
2989
  */
2927
2990
 
2928
- var pointAnnotation = function pointAnnotation(args) {
2991
+
2992
+ var rectangleAnnotation = function rectangleAnnotation(args, annotationName) {
2929
2993
  'use strict';
2930
2994
 
2931
- if (!(this instanceof pointAnnotation)) {
2932
- return new pointAnnotation(args);
2995
+ if (!(this instanceof rectangleAnnotation)) {
2996
+ return new rectangleAnnotation(args, annotationName);
2933
2997
  }
2934
2998
 
2935
2999
  args = $.extend(true, {}, {
@@ -2941,8 +3005,9 @@ var pointAnnotation = function pointAnnotation(args) {
2941
3005
  b: 0
2942
3006
  },
2943
3007
  fillOpacity: 0.25,
2944
- radius: 10,
2945
- scaled: false,
3008
+ polygon: function polygon(d) {
3009
+ return d.polygon;
3010
+ },
2946
3011
  stroke: true,
2947
3012
  strokeColor: {
2948
3013
  r: 0,
@@ -2950,7 +3015,17 @@ var pointAnnotation = function pointAnnotation(args) {
2950
3015
  b: 0
2951
3016
  },
2952
3017
  strokeOpacity: 1,
2953
- strokeWidth: 3
3018
+ strokeWidth: 3,
3019
+ uniformPolygon: true
3020
+ },
3021
+ highlightStyle: {
3022
+ fillColor: {
3023
+ r: 0,
3024
+ g: 1,
3025
+ b: 1
3026
+ },
3027
+ fillOpacity: 0.5,
3028
+ strokeWidth: 5
2954
3029
  },
2955
3030
  createStyle: {
2956
3031
  fillColor: {
@@ -2964,82 +3039,119 @@ var pointAnnotation = function pointAnnotation(args) {
2964
3039
  g: 0,
2965
3040
  b: 1
2966
3041
  }
2967
- },
2968
- highlightStyle: {
2969
- fillColor: {
2970
- r: 0,
2971
- g: 1,
2972
- b: 1
2973
- },
2974
- fillOpacity: 0.5,
2975
- strokeWidth: 5
2976
3042
  }
2977
3043
  }, args || {});
2978
- args.position = args.position || (args.coordinates ? args.coordinates[0] : undefined);
3044
+ args.corners = args.corners || args.coordinates || [];
2979
3045
  delete args.coordinates;
2980
- annotation.call(this, 'point', args);
2981
- var m_this = this;
3046
+ annotation.call(this, annotationName || 'rectangle', args);
3047
+ var m_this = this,
3048
+ s_actions = this.actions,
3049
+ s_processEditAction = this.processEditAction;
2982
3050
  /**
2983
- * Get a list of renderable features for this annotation.
3051
+ * Return actions needed for the specified state of this annotation.
2984
3052
  *
2985
- * @returns {array} An array of features.
3053
+ * @param {string} [state] The state to return actions for. Defaults to
3054
+ * the current state.
3055
+ * @returns {geo.actionRecord[]} A list of actions.
2986
3056
  */
2987
3057
 
2988
- this.features = function () {
2989
- var opt = m_this.options(),
2990
- state = m_this.state(),
2991
- features,
2992
- style,
2993
- scaleOnZoom;
3058
+ this.actions = function (state) {
3059
+ if (!state) {
3060
+ state = m_this.state();
3061
+ }
2994
3062
 
2995
3063
  switch (state) {
2996
3064
  case annotationState.create:
2997
- features = [];
2998
- break;
3065
+ return [{
3066
+ action: geo_action.annotation_rectangle,
3067
+ name: 'rectangle create',
3068
+ owner: annotationActionOwner,
3069
+ input: 'left',
3070
+ modifiers: {
3071
+ shift: false,
3072
+ ctrl: false
3073
+ },
3074
+ selectionRectangle: true,
3075
+ selectionConstraint: this._selectionConstraint
3076
+ }];
2999
3077
 
3000
3078
  default:
3001
- style = m_this.styleForState(state);
3079
+ return s_actions.apply(m_this, arguments);
3080
+ }
3081
+ };
3082
+ /**
3083
+ * Process any actions for this annotation.
3084
+ *
3085
+ * @param {geo.event} evt The action event.
3086
+ * @returns {boolean|string} `true` to update the annotation, `'done'` if the
3087
+ * annotation was completed (changed from create to done state),
3088
+ * `'remove'` if the annotation should be removed, falsy to not update
3089
+ * anything.
3090
+ */
3002
3091
 
3003
- if (opt.style.scaled || opt.style.scaled === 0) {
3004
- if (opt.style.scaled === true) {
3005
- opt.style.scaled = m_this.layer().map().zoom();
3006
- }
3007
3092
 
3008
- style = $.extend({}, style, {
3009
- radius: function radius() {
3010
- var radius = opt.style.radius,
3011
- zoom = m_this.layer().map().zoom();
3093
+ this.processAction = function (evt) {
3094
+ var layer = m_this.layer();
3095
+
3096
+ if (m_this.state() !== annotationState.create || !layer || evt.event !== geo_event.actionselection || evt.state.action !== geo_action.annotation_rectangle) {
3097
+ return;
3098
+ }
3099
+
3100
+ var map = layer.map(),
3101
+ corners = [
3102
+ /* Keep in map gcs, not interface gcs to avoid wrapping issues */
3103
+ map.displayToGcs({
3104
+ x: evt.lowerLeft.x,
3105
+ y: evt.lowerLeft.y
3106
+ }, null), map.displayToGcs({
3107
+ x: evt.lowerLeft.x,
3108
+ y: evt.upperRight.y
3109
+ }, null), map.displayToGcs({
3110
+ x: evt.upperRight.x,
3111
+ y: evt.upperRight.y
3112
+ }, null), map.displayToGcs({
3113
+ x: evt.upperRight.x,
3114
+ y: evt.lowerLeft.y
3115
+ }, null)];
3116
+
3117
+ if (this._selectionConstraint && evt.mouse && evt.state.origin) {
3118
+ this._selectionConstraint(evt.mouse.mapgcs, evt.state.origin.mapgcs, corners);
3119
+ }
3120
+ /* Don't keep rectangles that have nearly zero area in display pixels */
3121
+
3122
+
3123
+ if (layer.displayDistance(corners[0], null, corners[1], null) * layer.displayDistance(corners[0], null, corners[3], null) < 0.01) {
3124
+ return 'remove';
3125
+ }
3012
3126
 
3013
- if (util.isFunction(radius)) {
3014
- radius = radius.apply(m_this, arguments);
3015
- }
3127
+ m_this.options('corners', corners);
3128
+ m_this.state(annotationState.done);
3129
+ return 'done';
3130
+ };
3131
+ /**
3132
+ * Get a list of renderable features for this annotation.
3133
+ *
3134
+ * @returns {array} An array of features.
3135
+ */
3016
3136
 
3017
- radius *= Math.pow(2, zoom - opt.style.scaled);
3018
- return radius;
3019
- }
3020
- });
3021
- scaleOnZoom = true;
3022
- }
3023
3137
 
3024
- features = [{
3025
- point: {
3026
- x: opt.position.x,
3027
- y: opt.position.y,
3028
- style: style,
3029
- scaleOnZoom: scaleOnZoom
3030
- }
3031
- }];
3138
+ this.features = function () {
3139
+ var opt = m_this.options(),
3140
+ state = m_this.state(),
3141
+ features;
3142
+ features = [];
3032
3143
 
3033
- if (state === annotationState.edit) {
3034
- m_this._addEditHandles(features, [opt.position], {
3035
- edge: false,
3036
- center: false,
3037
- resize: false,
3038
- rotate: false
3039
- });
3144
+ if (opt.corners && opt.corners.length >= 4) {
3145
+ features = [{
3146
+ polygon: {
3147
+ polygon: opt.corners,
3148
+ style: m_this.styleForState(state)
3040
3149
  }
3150
+ }];
3151
+ }
3041
3152
 
3042
- break;
3153
+ if (state === annotationState.edit) {
3154
+ m_this._addEditHandles(features, opt.corners);
3043
3155
  }
3044
3156
 
3045
3157
  return features;
@@ -3055,42 +3167,50 @@ var pointAnnotation = function pointAnnotation(args) {
3055
3167
 
3056
3168
 
3057
3169
  this._coordinates = function (coordinates) {
3058
- if (coordinates && coordinates.length >= 1) {
3059
- m_this.options('position', coordinates[0]);
3060
- }
3061
-
3062
- if (m_this.state() === annotationState.create) {
3063
- return [];
3170
+ if (coordinates && coordinates.length >= 4) {
3171
+ m_this.options('corners', coordinates.slice(0, 4));
3172
+ /* Should we ensure that the four points form a rectangle in the current
3173
+ * projection, though this might not be rectangular in another gcs? */
3064
3174
  }
3065
3175
 
3066
- return [m_this.options('position')];
3176
+ return m_this.options('corners');
3067
3177
  };
3068
3178
 
3069
- this._coordinateOption = 'position';
3179
+ this._coordinateOption = 'corners';
3070
3180
  /**
3071
- * Handle a mouse click on this annotation. If the event is processed,
3072
- * evt.handled should be set to `true` to prevent further processing.
3181
+ * Return the coordinates to be stored in a geojson geometry object.
3073
3182
  *
3074
- * @param {geo.event} evt The mouse click event.
3075
- * @returns {boolean|string} `true` to update the annotation, `'done'` if
3076
- * the annotation was completed (changed from create to done state),
3077
- * `'remove'` if the annotation should be removed, falsy to not update
3078
- * anything.
3183
+ * @param {string|geo.transform|null} [gcs] `undefined` to use the interface
3184
+ * gcs, `null` to use the map gcs, or any other transform.
3185
+ * @returns {array} An array of flattened coordinates in the interface gcs
3186
+ * coordinate system. `undefined` if this annotation is incomplete.
3079
3187
  */
3080
3188
 
3081
- this.mouseClick = function (evt) {
3082
- if (m_this.state() !== annotationState.create) {
3189
+ this._geojsonCoordinates = function (gcs) {
3190
+ var src = m_this.coordinates(gcs);
3191
+
3192
+ if (!src || m_this.state() === annotationState.create || src.length < 4) {
3083
3193
  return;
3084
3194
  }
3085
3195
 
3086
- if (!evt.buttonsDown.left) {
3087
- return;
3196
+ var coord = [];
3197
+
3198
+ for (var i = 0; i < 4; i += 1) {
3199
+ coord.push([src[i].x, src[i].y]);
3088
3200
  }
3089
3201
 
3090
- evt.handled = true;
3091
- m_this.options('position', evt.mapgcs);
3092
- m_this.state(annotationState.done);
3093
- return 'done';
3202
+ coord.push([src[0].x, src[0].y]);
3203
+ return [coord];
3204
+ };
3205
+ /**
3206
+ * Return the geometry type that is used to store this annotation in geojson.
3207
+ *
3208
+ * @returns {string} A geojson geometry type.
3209
+ */
3210
+
3211
+
3212
+ this._geojsonGeometryType = function () {
3213
+ return 'Polygon';
3094
3214
  };
3095
3215
  /**
3096
3216
  * Return a list of styles that should be preserved in a geojson
@@ -3101,207 +3221,269 @@ var pointAnnotation = function pointAnnotation(args) {
3101
3221
 
3102
3222
 
3103
3223
  this._geojsonStyles = function () {
3104
- return ['fill', 'fillColor', 'fillOpacity', 'radius', 'scaled', 'stroke', 'strokeColor', 'strokeOpacity', 'strokeWidth'];
3224
+ return ['fill', 'fillColor', 'fillOpacity', 'lineCap', 'lineJoin', 'stroke', 'strokeColor', 'strokeOffset', 'strokeOpacity', 'strokeWidth'];
3105
3225
  };
3106
3226
  /**
3107
- * Return the coordinates to be stored in a geojson geometry object.
3227
+ * Set three corners based on an initial corner and a mouse event.
3108
3228
  *
3109
- * @param {string|geo.transform|null} [gcs] `undefined` to use the interface
3110
- * gcs, `null` to use the map gcs, or any other transform.
3111
- * @returns {array} An array of flattened coordinates in the interface gcs
3112
- * coordinate system. `undefined` if this annotation is incomplete.
3229
+ * @param {geo.geoPosition} corners An array of four corners to update.
3230
+ * @param {geo.event} evt The mouse move event.
3113
3231
  */
3114
3232
 
3115
3233
 
3116
- this._geojsonCoordinates = function (gcs) {
3117
- var src = m_this.coordinates(gcs);
3234
+ this._setCornersFromMouse = function (corners, evt) {
3235
+ var map = m_this.layer().map(),
3236
+ c0 = map.gcsToDisplay({
3237
+ x: corners[0].x,
3238
+ y: corners[0].y
3239
+ }, null),
3240
+ c2 = map.gcsToDisplay(evt.mapgcs, null),
3241
+ c1 = {
3242
+ x: c2.x,
3243
+ y: c0.y
3244
+ },
3245
+ c3 = {
3246
+ x: c0.x,
3247
+ y: c2.y
3248
+ };
3249
+ corners[2] = $.extend({}, evt.mapgcs);
3250
+ corners[1] = map.displayToGcs(c1, null);
3251
+ corners[3] = map.displayToGcs(c3, null);
3118
3252
 
3119
- if (!src || m_this.state() === annotationState.create || src.length < 1 || src[0] === undefined) {
3253
+ if (this._selectionConstraint) {
3254
+ this._selectionConstraint(evt.mapgcs, corners[0], corners);
3255
+ }
3256
+ };
3257
+ /**
3258
+ * Handle a mouse move on this annotation.
3259
+ *
3260
+ * @param {geo.event} evt The mouse move event.
3261
+ * @returns {boolean} Truthy to update the annotation, falsy to not
3262
+ * update anything.
3263
+ */
3264
+
3265
+
3266
+ this.mouseMove = function (evt) {
3267
+ if (m_this.state() !== annotationState.create) {
3120
3268
  return;
3121
3269
  }
3122
3270
 
3123
- return [src[0].x, src[0].y];
3271
+ var corners = m_this.options('corners');
3272
+
3273
+ if (corners.length) {
3274
+ m_this._setCornersFromMouse(corners, evt);
3275
+
3276
+ return true;
3277
+ }
3124
3278
  };
3125
3279
  /**
3126
- * Return the geometry type that is used to store this annotation in geojson.
3280
+ * Handle a mouse click on this annotation. If the event is processed,
3281
+ * evt.handled should be set to `true` to prevent further processing.
3127
3282
  *
3128
- * @returns {string} A geojson geometry type.
3283
+ * @param {geo.event} evt The mouse click event.
3284
+ * @returns {boolean|string} `true` to update the annotation, `'done'` if
3285
+ * the annotation was completed (changed from create to done state),
3286
+ * `'remove'` if the annotation should be removed, falsy to not update
3287
+ * anything.
3129
3288
  */
3130
3289
 
3131
3290
 
3132
- this._geojsonGeometryType = function () {
3133
- return 'Point';
3134
- };
3135
- };
3291
+ this.mouseClick = function (evt) {
3292
+ var layer = m_this.layer();
3136
3293
 
3137
- inherit(pointAnnotation, annotation);
3138
- var pointRequiredFeatures = {};
3139
- pointRequiredFeatures[pointFeature.capabilities.feature] = true;
3140
- registerAnnotation('point', pointAnnotation, pointRequiredFeatures);
3141
- /**
3142
- * Return a function that can be used as a selectionConstraint that requires
3143
- * that the aspect ratio of a rectangle-like selection is a specific value or
3144
- * range of values.
3145
- *
3146
- * @param {number|number[]} ratio Either a single aspect ratio or a list of
3147
- * allowed aspect ratios. For instance, 1 will require that the selection
3148
- * square, 2 would require that it is twice as wide as tall, [2, 1/2] would
3149
- * allow it to be twice as wide or half as wide as it is tall.
3150
- * @returns {function} A function that can be passed to the mapIterator
3151
- * selectionConstraint or to an annotation constraint function.
3152
- */
3294
+ if (m_this.state() !== annotationState.create || !layer) {
3295
+ return;
3296
+ }
3153
3297
 
3154
- function constrainAspectRatio(ratio) {
3155
- var ratios = Array.isArray(ratio) ? ratio : [ratio];
3298
+ if (!evt.buttonsDown.left && !evt.buttonsDown.right) {
3299
+ return;
3300
+ }
3301
+
3302
+ var corners = m_this.options('corners');
3303
+
3304
+ if (evt.buttonsDown.right && !corners.length) {
3305
+ return;
3306
+ }
3307
+
3308
+ evt.handled = true;
3309
+
3310
+ if (corners.length) {
3311
+ m_this._setCornersFromMouse(corners, evt);
3312
+ /* Don't keep rectangles that have nearly zero area in display pixels */
3313
+
3314
+
3315
+ if (layer.displayDistance(corners[0], null, corners[1], null) * layer.displayDistance(corners[0], null, corners[3], null) < 0.01) {
3316
+ return 'remove';
3317
+ }
3318
+
3319
+ m_this.state(annotationState.done);
3320
+ return 'done';
3321
+ }
3322
+
3323
+ if (evt.buttonsDown.left) {
3324
+ corners.push($.extend({}, evt.mapgcs));
3325
+ corners.push($.extend({}, evt.mapgcs));
3326
+ corners.push($.extend({}, evt.mapgcs));
3327
+ corners.push($.extend({}, evt.mapgcs));
3328
+ return true;
3329
+ }
3330
+ };
3156
3331
  /**
3157
- * Constrain a mouse action or annotation action to a list of aspect ratios.
3332
+ * Process any edit actions for this annotation.
3158
3333
  *
3159
- * @param {geo.geoPosition} pos Mouse or new location in map gcs.
3160
- * @param {geo.geoPosition} origin Origin in map gcs when the activity
3161
- * started.
3162
- * @param {geo.geoPosition} [corners] If specified, an array of corner
3163
- * locations in mapgcs. This may be modified.
3164
- * @param {string?} [mode] 'edge', 'vertex' or falsy. A falsy value implies
3165
- * this is just the most recent point in the annotation, otherwise it is
3166
- * the portion of the annotation being modified.
3167
- * @param {number} [ang] A list of angles of each side of the polygon
3168
- * represented by corners or the original annotation.
3169
- * @param {integer} [index] The specific vertex or edge that is being
3170
- * modified.
3171
- * @returns {object} An object with the ``origin`` (this is what is passed
3172
- * in), a new position as ``pos``, and the updated corners as ``corners``.
3334
+ * @param {geo.event} evt The action event.
3335
+ * @returns {boolean|string} `true` to update the annotation, falsy to not
3336
+ * update anything.
3173
3337
  */
3174
3338
 
3175
- function constraintFunction(pos, origin, corners, mode, ang, index) {
3176
- var newpos = pos;
3177
- var best;
3178
3339
 
3179
- if (!corners) {
3180
- corners = [{
3181
- x: origin.x,
3182
- y: origin.y
3183
- }, {
3184
- x: pos.x,
3185
- y: origin.y
3186
- }, {
3187
- x: pos.x,
3188
- y: pos.y
3189
- }, {
3190
- x: origin.x,
3191
- y: pos.y
3192
- }];
3340
+ this.processEditAction = function (evt) {
3341
+ var start = m_this._editHandle.startCoordinates,
3342
+ delta = {
3343
+ x: evt.mouse.mapgcs.x - evt.state.origin.mapgcs.x,
3344
+ y: evt.mouse.mapgcs.y - evt.state.origin.mapgcs.y
3345
+ },
3346
+ type = m_this._editHandle.handle.type,
3347
+ index = m_this._editHandle.handle.index,
3348
+ ang = [Math.atan2(start[1].y - start[0].y, start[1].x - start[0].x), Math.atan2(start[2].y - start[1].y, start[2].x - start[1].x), Math.atan2(start[3].y - start[2].y, start[3].x - start[2].x), Math.atan2(start[0].y - start[3].y, start[0].x - start[3].x)],
3349
+ corners,
3350
+ delta1,
3351
+ delta2,
3352
+ ang1,
3353
+ ang2; // an angle can be zero because it is horizontal or undefined. If opposite
3354
+ // angles are both zero, this is a degenerate rectangle (a line or a point)
3355
+
3356
+ if (!ang[0] && !ang[1] && !ang[2] && !ang[3]) {
3357
+ ang[1] = Math.PI / 2;
3358
+ ang[2] = Math.PI;
3359
+ ang[3] = -Math.PI / 2;
3193
3360
  }
3194
3361
 
3195
- if (mode) {
3196
- /* Edit a vertex or edge */
3197
- var i1 = (index + 1) % 4;
3198
- var i2 = (index + 2) % 4;
3199
- var i3 = (index + 3) % 4;
3200
- var dist1 = Math.pow(Math.pow(corners[index].x - corners[i1].x, 2) + Math.pow(corners[index].y - corners[i1].y, 2), 0.5);
3201
- var dist3 = Math.pow(Math.pow(corners[index].x - corners[i3].x, 2) + Math.pow(corners[index].y - corners[i3].y, 2), 0.5);
3202
- var area = Math.abs(dist1 * dist3);
3203
- var shape, edge;
3204
- ratios.forEach(function (ratio) {
3205
- if (ratio !== 1 && !(index % 2)) {
3206
- ratio = 1.0 / ratio;
3207
- }
3362
+ if (!ang[0] && !ang[2]) {
3363
+ ang[0] = ang[1] - Math.PI / 2;
3364
+ ang[2] = ang[1] + Math.PI / 2;
3365
+ }
3208
3366
 
3209
- var width = Math.pow(area * ratio, 0.5);
3210
- var score = Math.pow(width - dist3, 2) + Math.pow(width / ratio - dist1, 2);
3367
+ if (!ang[1] && !ang[3]) {
3368
+ ang[1] = ang[2] - Math.PI / 2;
3369
+ ang[3] = ang[2] + Math.PI / 2;
3370
+ }
3211
3371
 
3212
- if (best === undefined || score < best) {
3213
- best = score;
3214
- shape = {
3215
- w: width,
3216
- h: width / ratio
3372
+ switch (type) {
3373
+ case 'vertex':
3374
+ corners = start.map(function (elem) {
3375
+ return {
3376
+ x: elem.x,
3377
+ y: elem.y
3217
3378
  };
3379
+ });
3380
+ ang1 = ang[(index + 1) % 4];
3381
+ delta1 = {
3382
+ x: (delta.x * Math.cos(ang1) + delta.y * Math.sin(ang1)) * Math.cos(ang1),
3383
+ y: (delta.y * Math.sin(ang1) + delta.x * Math.cos(ang1)) * Math.sin(ang1)
3384
+ };
3385
+ ang2 = ang[index];
3386
+ delta2 = {
3387
+ x: (delta.x * Math.cos(ang2) + delta.y * Math.sin(ang2)) * Math.cos(ang2),
3388
+ y: (delta.y * Math.sin(ang2) + delta.x * Math.cos(ang2)) * Math.sin(ang2)
3389
+ };
3390
+ corners[index].x += delta.x;
3391
+ corners[index].y += delta.y;
3392
+ corners[(index + 1) % 4].x += delta1.x;
3393
+ corners[(index + 1) % 4].y += delta1.y;
3394
+ corners[(index + 3) % 4].x += delta2.x;
3395
+ corners[(index + 3) % 4].y += delta2.y;
3396
+
3397
+ if (this._selectionConstraint) {
3398
+ corners = this._selectionConstraint(evt.mouse.mapgcs, evt.state.origin.mapgcs, corners, 'vertex', ang, index).corners;
3218
3399
  }
3219
- });
3220
- var ang1 = ang[i1];
3221
- var delta1 = {
3222
- x: -shape.w * Math.cos(ang1),
3223
- y: -shape.w * Math.sin(ang1)
3224
- };
3225
- var ang2 = ang[index];
3226
- var delta2 = {
3227
- x: -shape.h * Math.cos(ang2),
3228
- y: -shape.h * Math.sin(ang2)
3229
- };
3230
3400
 
3231
- switch (mode) {
3232
- case 'vertex':
3233
- corners[index].x = corners[i2].x + delta1.x + delta2.x;
3234
- corners[index].y = corners[i2].y + delta1.y + delta2.y;
3235
- corners[i1].x = corners[i2].x + delta1.x;
3236
- corners[i1].y = corners[i2].y + delta1.y;
3237
- corners[i3].x = corners[i2].x + delta2.x;
3238
- corners[i3].y = corners[i2].y + delta2.y;
3239
- break;
3401
+ m_this.options('corners', corners);
3402
+ return true;
3240
3403
 
3241
- case 'edge':
3242
- edge = {
3243
- x: (corners[i2].x + corners[i3].x) * 0.5,
3244
- y: (corners[i2].y + corners[i3].y) * 0.5
3404
+ case 'edge':
3405
+ corners = start.map(function (elem) {
3406
+ return {
3407
+ x: elem.x,
3408
+ y: elem.y
3245
3409
  };
3246
- corners[i2].x = edge.x + delta2.x / 2;
3247
- corners[i2].y = edge.y + delta2.y / 2;
3248
- corners[index].x = edge.x + delta1.x - delta2.x / 2;
3249
- corners[index].y = edge.y + delta1.y - delta2.y / 2;
3250
- corners[i1].x = edge.x + delta1.x + delta2.x / 2;
3251
- corners[i1].y = edge.y + delta1.y + delta2.y / 2;
3252
- corners[i3].x = edge.x - delta2.x / 2;
3253
- corners[i3].y = edge.y - delta2.y / 2;
3254
- break;
3255
- }
3256
- } else {
3257
- /* Not in edit vertex or edge mode */
3258
- var _area = Math.abs((pos.x - origin.x) * (pos.y - origin.y));
3259
-
3260
- ratios.forEach(function (ratio) {
3261
- var width = Math.pow(_area * ratio, 0.5);
3262
- var adjusted = {
3263
- x: origin.x + Math.sign(pos.x - origin.x) * width,
3264
- y: origin.y + Math.sign(pos.y - origin.y) * width / ratio
3410
+ });
3411
+ ang1 = ang[(index + 1) % 4];
3412
+ delta = {
3413
+ x: (delta.x * Math.cos(ang1) + delta.y * Math.sin(ang1)) * Math.cos(ang1),
3414
+ y: (delta.y * Math.sin(ang1) + delta.x * Math.cos(ang1)) * Math.sin(ang1)
3265
3415
  };
3266
- var score = Math.pow(adjusted.x - pos.x, 2) + Math.pow(adjusted.y - pos.y, 2);
3416
+ corners[index].x += delta.x;
3417
+ corners[index].y += delta.y;
3418
+ corners[(index + 1) % 4].x += delta.x;
3419
+ corners[(index + 1) % 4].y += delta.y;
3267
3420
 
3268
- if (best === undefined || score < best) {
3269
- best = score;
3270
- newpos = adjusted;
3421
+ if (this._selectionConstraint) {
3422
+ corners = this._selectionConstraint(evt.mouse.mapgcs, evt.state.origin.mapgcs, corners, 'edge', ang, index).corners;
3271
3423
  }
3272
- });
3273
- corners[0].y = corners[1].y = origin.y;
3274
- corners[0].x = corners[3].x = origin.x;
3275
- corners[1].x = corners[2].x = newpos.x;
3276
- corners[2].y = corners[3].y = newpos.y;
3424
+
3425
+ m_this.options('corners', corners);
3426
+ return true;
3277
3427
  }
3278
3428
 
3279
- return {
3280
- corners: corners,
3281
- origin: origin,
3282
- pos: newpos
3283
- };
3284
- }
3429
+ return s_processEditAction.apply(m_this, arguments);
3430
+ };
3431
+ };
3285
3432
 
3286
- return constraintFunction;
3287
- }
3433
+ inherit(rectangleAnnotation, annotation);
3434
+ var rectangleRequiredFeatures = {};
3435
+ rectangleRequiredFeatures[polygonFeature.capabilities.feature] = true;
3436
+ registerAnnotation('rectangle', rectangleAnnotation, rectangleRequiredFeatures);
3437
+ module.exports = rectangleAnnotation;
3288
3438
 
3289
- module.exports = {
3290
- state: annotationState,
3291
- actionOwner: annotationActionOwner,
3292
- annotation: annotation,
3293
- lineAnnotation: lineAnnotation,
3294
- pointAnnotation: pointAnnotation,
3295
- polygonAnnotation: polygonAnnotation,
3296
- rectangleAnnotation: rectangleAnnotation,
3297
- squareAnnotation: squareAnnotation,
3298
- ellipseAnnotation: ellipseAnnotation,
3299
- circleAnnotation: circleAnnotation,
3300
- _editHandleFeatureLevel: editHandleFeatureLevel,
3301
- defaultEditHandleStyle: defaultEditHandleStyle,
3302
- constrainAspectRatio: constrainAspectRatio
3439
+ /***/ }),
3440
+
3441
+ /***/ 4932:
3442
+ /***/ (function(module, __unused_webpack_exports, __webpack_require__) {
3443
+
3444
+ var $ = __webpack_require__(5638);
3445
+
3446
+ var inherit = __webpack_require__(5699);
3447
+
3448
+ var registerAnnotation = (__webpack_require__(4647).registerAnnotation);
3449
+
3450
+ var polygonFeature = __webpack_require__(4343);
3451
+
3452
+ var rectangleAnnotation = __webpack_require__(3442);
3453
+ /**
3454
+ * Square annotation class.
3455
+ *
3456
+ * Squares are a subset of rectangles with a fixed aspect ratio.
3457
+ *
3458
+ * @class
3459
+ * @alias geo.squareAnnotation
3460
+ * @extends geo.annotation
3461
+ *
3462
+ * @param {geo.squareAnnotation.spec?} [args] Options for the annotation.
3463
+ * @param {string} [annotationName='square'] Override the annotation name.
3464
+ */
3465
+
3466
+
3467
+ var squareAnnotation = function squareAnnotation(args, annotationName) {
3468
+ 'use strict';
3469
+
3470
+ args = $.extend({}, args, {
3471
+ constraint: 1
3472
+ });
3473
+
3474
+ if (!(this instanceof squareAnnotation)) {
3475
+ return new squareAnnotation(args, annotationName);
3476
+ }
3477
+
3478
+ rectangleAnnotation.call(this, args, annotationName || 'square');
3303
3479
  };
3304
3480
 
3481
+ inherit(squareAnnotation, rectangleAnnotation);
3482
+ var squareRequiredFeatures = {};
3483
+ squareRequiredFeatures[polygonFeature.capabilities.feature] = true;
3484
+ registerAnnotation('square', squareAnnotation, squareRequiredFeatures);
3485
+ module.exports = squareAnnotation;
3486
+
3305
3487
  /***/ }),
3306
3488
 
3307
3489
  /***/ 836:
@@ -3311,7 +3493,7 @@ var inherit = __webpack_require__(5699);
3311
3493
 
3312
3494
  var featureLayer = __webpack_require__(3715);
3313
3495
 
3314
- var geo_annotation = __webpack_require__(7800);
3496
+ var geo_annotation = __webpack_require__(4213);
3315
3497
 
3316
3498
  var geo_event = __webpack_require__(5108);
3317
3499
 
@@ -4165,16 +4347,31 @@ var annotationLayer = function annotationLayer(arg) {
4165
4347
  } // make a copy of the position array to avoid mutating the original.
4166
4348
 
4167
4349
 
4168
- position = position.outer.slice();
4350
+ position = {
4351
+ outer: position.outer.slice(),
4352
+ inner: (position.inner || []).map(function (h) {
4353
+ return h.slice();
4354
+ })
4355
+ };
4169
4356
 
4170
- if (position[position.length - 1][0] === position[0][0] && position[position.length - 1][1] === position[0][1]) {
4171
- position.splice(position.length - 1, 1);
4357
+ if (position.outer[position.outer.length - 1][0] === position.outer[0][0] && position.outer[position.outer.length - 1][1] === position.outer[0][1]) {
4358
+ position.outer.splice(position.outer.length - 1, 1);
4172
4359
 
4173
- if (position.length < 3) {
4360
+ if (position.outer.length < 3) {
4174
4361
  return;
4175
4362
  }
4176
4363
  }
4177
4364
 
4365
+ position.inner.forEach(function (h) {
4366
+ if (h.length > 3 && h[h.length - 1][0] === h[0][0] && h[h.length - 1][1] === h[0][1]) {
4367
+ h.splice(h.length - 1, 1);
4368
+ }
4369
+ });
4370
+
4371
+ if (!position.inner || !position.inner.length) {
4372
+ position = position.outer;
4373
+ }
4374
+
4178
4375
  break;
4179
4376
 
4180
4377
  case 'marker':
@@ -4186,16 +4383,20 @@ var annotationLayer = function annotationLayer(arg) {
4186
4383
  break;
4187
4384
  }
4188
4385
 
4189
- for (i = 0; i < position.length; i += 1) {
4190
- position[i] = util.normalizeCoordinates(position[i]);
4191
- }
4192
-
4193
4386
  datagcs = data.crs && data.crs.type === 'name' && data.crs.properties && data.crs.properties.type === 'proj4' && data.crs.properties.name ? data.crs.properties.name : gcs;
4387
+ [position.outer || position].concat(position.inner || []).forEach(function (poslist) {
4388
+ for (i = 0; i < poslist.length; i += 1) {
4389
+ poslist[i] = util.normalizeCoordinates(poslist[i]);
4390
+ }
4194
4391
 
4195
- if (datagcs !== map.gcs()) {
4196
- position = transform.transformCoordinates(datagcs, map.gcs(), position);
4197
- }
4392
+ if (datagcs !== map.gcs()) {
4393
+ var transposlist = transform.transformCoordinates(datagcs, map.gcs(), poslist);
4198
4394
 
4395
+ for (i = 0; i < poslist.length; i += 1) {
4396
+ poslist[i] = transposlist[i];
4397
+ }
4398
+ }
4399
+ });
4199
4400
  options.coordinates = position;
4200
4401
  /* For each style listed in the geojsonStyleProperties object, check if
4201
4402
  * is given under any of the variety of keys as a valid instance of the
@@ -10761,6 +10962,7 @@ var fetchQueue = function fetchQueue(options) {
10761
10962
  this._size = options.size || 6;
10762
10963
  this._initialSize = options.initialSize || 0;
10763
10964
  this._track = options.track || 600;
10965
+ this._initialTrack = this._track;
10764
10966
  this._needed = options.needed || null;
10765
10967
  this._batch = false;
10766
10968
  var m_this = this,
@@ -10801,6 +11003,38 @@ var fetchQueue = function fetchQueue(options) {
10801
11003
  m_this.next_item();
10802
11004
  }
10803
11005
  });
11006
+ /**
11007
+ * Get/set the track size. This is used to determine when to check if
11008
+ * entries can be discarded.
11009
+ * @property {number} track The number of entries to track without checking
11010
+ * for discards.
11011
+ * @name geo.fetchQueue#track
11012
+ */
11013
+
11014
+ Object.defineProperty(this, 'track', {
11015
+ get: function get() {
11016
+ return m_this._track;
11017
+ },
11018
+ set: function set(n) {
11019
+ m_this._track = n;
11020
+ }
11021
+ });
11022
+ /**
11023
+ * Get/set the initial track size. Unless changed, this is the value used
11024
+ * for track on class initialization.
11025
+ * @property {number} initialTrack The number of entries to track without
11026
+ * checking for discards.
11027
+ * @name geo.fetchQueue#intitialTrack
11028
+ */
11029
+
11030
+ Object.defineProperty(this, 'initialTrack', {
11031
+ get: function get() {
11032
+ return m_this._initialTrack;
11033
+ },
11034
+ set: function set(n) {
11035
+ m_this._initialTrack = n;
11036
+ }
11037
+ });
10804
11038
  /**
10805
11039
  * Get the current queue size. Read only.
10806
11040
  * @property {number} length The current queue size.
@@ -10853,9 +11087,8 @@ var fetchQueue = function fetchQueue(options) {
10853
11087
  var pos = $.inArray(defer, m_this._queue);
10854
11088
 
10855
11089
  if (pos >= 0) {
10856
- m_this._queue.splice(pos, 1);
10857
-
10858
- m_this._addToQueue(defer, atEnd);
11090
+ // m_this._queue.splice(pos, 1);
11091
+ m_this._addToQueue(defer, atEnd, pos);
10859
11092
 
10860
11093
  return defer;
10861
11094
  }
@@ -10889,24 +11122,40 @@ var fetchQueue = function fetchQueue(options) {
10889
11122
  * @param {boolean} atEnd If falsy, add the item to the front of the queue
10890
11123
  * if batching is turned off or at the end of the current batch if it is
10891
11124
  * turned on. If truthy, always add the item to the end of the queue.
11125
+ * @param {number} [pos] If specified, the current location in the queue of
11126
+ * the object being added. This avoids having to splice, push, or unshift
11127
+ * the queue.
10892
11128
  */
10893
11129
 
10894
11130
 
10895
- this._addToQueue = function (defer, atEnd) {
11131
+ this._addToQueue = function (defer, atEnd, pos) {
11132
+ var move = atEnd ? m_this._queue.length - 1 : 0;
10896
11133
  defer.__fetchQueue._batch = m_this._batch;
10897
11134
 
10898
- if (atEnd) {
10899
- m_this._queue.push(defer);
10900
- } else if (!this._batch) {
10901
- m_this._queue.unshift(defer);
10902
- } else {
10903
- for (var i = 0; i < m_this._queue.length; i += 1) {
10904
- if (m_this._queue[i].__fetchQueue._batch !== m_this._batch) {
11135
+ if (!atEnd && m_this._batch) {
11136
+ for (move = 0; move < m_this._queue.length - (pos === undefined ? 0 : 1); move += 1) {
11137
+ if (m_this._queue[move].__fetchQueue._batch !== m_this._batch) {
10905
11138
  break;
10906
11139
  }
10907
11140
  }
11141
+ }
11142
+
11143
+ if (pos === undefined) {
11144
+ if (atEnd) {
11145
+ m_this._queue.push(defer);
11146
+ } else if (!move) {
11147
+ m_this._queue.unshift(defer);
11148
+ } else {
11149
+ m_this._queue.splice(move, 0, defer);
11150
+ }
11151
+ } else if (pos !== move) {
11152
+ var dir = pos < move ? 1 : -1;
11153
+
11154
+ for (var i = pos; i !== move; i += dir) {
11155
+ m_this._queue[i] = m_this._queue[i + dir];
11156
+ }
10908
11157
 
10909
- m_this._queue.splice(i, 0, defer);
11158
+ m_this._queue[move] = defer;
10910
11159
  }
10911
11160
  };
10912
11161
  /**
@@ -12749,7 +12998,6 @@ $.htmlPrefilter = function (html) {
12749
12998
  __webpack_require__(8701);
12750
12999
 
12751
13000
  module.exports = $.extend({
12752
- annotation: __webpack_require__(7800),
12753
13001
  annotationLayer: __webpack_require__(836),
12754
13002
  camera: __webpack_require__(9986),
12755
13003
  choroplethFeature: __webpack_require__(8719),
@@ -12795,6 +13043,7 @@ module.exports = $.extend({
12795
13043
  inherit: __webpack_require__(5699),
12796
13044
  version: __webpack_require__(2978),
12797
13045
  sha: __webpack_require__(5381),
13046
+ annotation: __webpack_require__(4213),
12798
13047
  util: __webpack_require__(4634),
12799
13048
  jQuery: $,
12800
13049
  canvas: __webpack_require__(7562),
@@ -26804,7 +27053,7 @@ module.exports = sceneObject;
26804
27053
  * @constant
26805
27054
  * @type {string}
26806
27055
  */
26807
- module.exports = "06c78d577d1a9dd6332ee47b20fe441d239225ca";
27056
+ module.exports = "819c5c82371d5348c2f142a62331b89ed86e01ff";
26808
27057
 
26809
27058
  /***/ }),
26810
27059
 
@@ -29647,7 +29896,7 @@ var featureLayer = __webpack_require__(3715);
29647
29896
  * @property {function} [tilesAtZoom=null] A function that is given a zoom
29648
29897
  * level and returns `{x: (num), y: (num)}` with the number of tiles at that
29649
29898
  * zoom level.
29650
- * @property {number} [cacheSize=400] The maximum number of tiles to cache.
29899
+ * @property {number} [cacheSize=600] The maximum number of tiles to cache.
29651
29900
  * The default is 200 if keepLower is false.
29652
29901
  * @property {geo.fetchQueue} [queue] A fetch queue to use. If unspecified, a
29653
29902
  * new queue is created.
@@ -29832,6 +30081,10 @@ var tileLayer = function tileLayer(arg) {
29832
30081
 
29833
30082
  if (!arg.cacheSize) {
29834
30083
  // this size should be sufficient for a 4k display
30084
+ // where display size is (w, h), minimum tile dimension is ts, and total
30085
+ // number of levels is ml, this is roughly
30086
+ // sum([(math.ceil((w**2+h**2)**0.5 / (ts*2**l)) + 1) *
30087
+ // (math.ceil(min(w, h) / (ts*2**l)) + 1) for l in range(ml)])
29835
30088
  arg.cacheSize = arg.keepLower ? 600 : 200;
29836
30089
  }
29837
30090
 
@@ -29909,6 +30162,10 @@ var tileLayer = function tileLayer(arg) {
29909
30162
 
29910
30163
  this._queue._tileLayers.push(m_this);
29911
30164
 
30165
+ if (this._queue.initialTrack && this._queue.track) {
30166
+ this._queue.track = this._queue.initialTrack * this._queue._tileLayers.length;
30167
+ }
30168
+
29912
30169
  var m_tileOffsetValues = {};
29913
30170
  /**
29914
30171
  * Readonly accessor to the options object.
@@ -29965,12 +30222,20 @@ var tileLayer = function tileLayer(arg) {
29965
30222
  if (m_this._queue !== queue) {
29966
30223
  if (this._queue && this._queue._tileLayers && this._queue._tileLayers.indexOf(m_this) >= 0) {
29967
30224
  this._queue._tileLayers.splice(this._queue._tileLayers.indexOf(m_this), 1);
30225
+
30226
+ if (this._queue.initialTrack && this._queue.track && this._queue._tileLayers.length) {
30227
+ this._queue.track = this._queue.initialTrack * this._queue._tileLayers.length;
30228
+ }
29968
30229
  }
29969
30230
 
29970
30231
  m_this._queue = queue;
29971
30232
  m_this._queue._tileLayers = m_this._queue._tileLayers || [];
29972
30233
 
29973
30234
  m_this._queue._tileLayers.push(m_this);
30235
+
30236
+ if (m_this._queue.initialTrack && m_this._queue.track) {
30237
+ m_this._queue.track = m_this._queue.initialTrack * m_this._queue._tileLayers.length;
30238
+ }
29974
30239
  }
29975
30240
  }
29976
30241
  });
@@ -31579,6 +31844,10 @@ var tileLayer = function tileLayer(arg) {
31579
31844
 
31580
31845
  if (this._queue && this._queue._tileLayers && this._queue._tileLayers.indexOf(m_this) >= 0) {
31581
31846
  this._queue._tileLayers.splice(this._queue._tileLayers.indexOf(m_this), 1);
31847
+
31848
+ if (this._queue.initialTrack && this._queue.track && this._queue._tileLayers.length) {
31849
+ this._queue.track = this._queue.initialTrack * this._queue._tileLayers.length;
31850
+ }
31582
31851
  }
31583
31852
 
31584
31853
  return m_this;
@@ -31615,7 +31884,7 @@ tileLayer.defaults = {
31615
31884
  topDown: false,
31616
31885
  keepLower: true,
31617
31886
  idleAfter: 'view',
31618
- // cacheSize: 400, // set depending on keepLower
31887
+ // cacheSize: 600, // set depending on keepLower
31619
31888
  tileRounding: Math.round,
31620
31889
  attribution: '',
31621
31890
  animationDuration: 0
@@ -33739,6 +34008,15 @@ module.exports = transform;
33739
34008
  * @property {number} [z=0] Altitude coordinate, often zero.
33740
34009
  */
33741
34010
 
34011
+ /**
34012
+ * Represention of a size in gcs coordinates.
34013
+ *
34014
+ * @typedef geo.geoSize
34015
+ * @type {object}
34016
+ * @property {number} width Width in gcs coordinates.
34017
+ * @property {number} height Height in gcs coordinates.
34018
+ */
34019
+
33742
34020
  /**
33743
34021
  * Represention of a size in pixels.
33744
34022
  *
@@ -39274,7 +39552,7 @@ module.exports = vectorFeature;
39274
39552
  * @constant
39275
39553
  * @type {string}
39276
39554
  */
39277
- module.exports = "1.8.3";
39555
+ module.exports = "1.8.6";
39278
39556
 
39279
39557
  /***/ }),
39280
39558