From 017baca81295aa0c664e69d8d3b2b7b47674f845 Mon Sep 17 00:00:00 2001 From: David Manthey Date: Mon, 1 Jan 2018 14:49:59 -0500 Subject: [PATCH] Don't create intermediate colinear points on a line. When dragging a line annotation, don't create points that are nearly colinear. --- src/annotation.js | 30 +++++++++++++++++++++--------- src/annotationLayer.js | 9 ++++++++- tests/cases/annotation.js | 25 +++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 10 deletions(-) diff --git a/src/annotation.js b/src/annotation.js index 2159bca396..0cf9e0b16c 100644 --- a/src/annotation.js +++ b/src/annotation.js @@ -1065,8 +1065,8 @@ var polygonAnnotation = function (args) { vertices[vertices.length - 2], null, evt.map, 'display') <= layer.options('adjacentPointProximity')) { skip = true; - if (this.lastClick && - evt.time - this.lastClick < layer.options('dblClickTime')) { + if (m_this._lastClick && + evt.time - m_this._lastClick < layer.options('dblClickTime')) { end = true; } } else if (vertices.length >= 2 && layer.displayDistance( @@ -1082,7 +1082,7 @@ var polygonAnnotation = function (args) { if (!end && !skip) { vertices.push(evt.mapgcs); } - this.lastClick = evt.time; + m_this._lastClick = evt.time; } if (end) { if (vertices.length < 4) { @@ -1312,8 +1312,8 @@ var lineAnnotation = function (args) { vertices[vertices.length - 2], null, evt.map, 'display') <= layer.options('adjacentPointProximity')) { skip = true; - if (this.lastClick && - evt.time - this.lastClick < layer.options('dblClickTime')) { + if (m_this._lastClick && + evt.time - m_this._lastClick < layer.options('dblClickTime')) { end = true; } } else if (vertices.length >= 2 && layer.displayDistance( @@ -1329,7 +1329,8 @@ var lineAnnotation = function (args) { if (!end && !skip) { vertices.push(evt.mapgcs); } - this.lastClick = evt.time; + m_this._lastClick = evt.time; + m_this._lastClickVertexCount = vertices.length; } if (end) { if (vertices.length < 3) { @@ -1389,6 +1390,7 @@ var lineAnnotation = function (args) { return; } var cpp = layer.options('continuousPointProximity'); + var cpc = layer.options('continuousPointColinearity'); if (cpp || cpp === 0) { var vertices = this.options('vertices'); if (!vertices.length) { @@ -1396,10 +1398,20 @@ var lineAnnotation = function (args) { vertices.push(evt.mouse.mapgcs); return true; } - var dist = layer.displayDistance( - vertices[vertices.length - 2], null, evt.mouse.map, 'display'); + var dist = layer.displayDistance(vertices[vertices.length - 2], null, evt.mouse.map, 'display'); if (dist && dist > cpp) { - // we should combine nearly colinear points, but we don't + // combine nearly colinear points + if (vertices.length >= (m_this._lastClickVertexCount || 1) + 3) { + var d01 = layer.displayDistance(vertices[vertices.length - 3], null, vertices[vertices.length - 2], null), + d12 = dist, + d02 = layer.displayDistance(vertices[vertices.length - 3], null, evt.mouse.map, 'display'); + if (d01 && d02) { + var costheta = (d02 * d02 - d01 * d01 - d12 * d12) / (2 * d01 * d12); + if (costheta > Math.cos(cpc)) { + vertices.pop(); + } + } + } vertices[vertices.length - 1] = evt.mouse.mapgcs; vertices.push(evt.mouse.mapgcs); return true; diff --git a/src/annotationLayer.js b/src/annotationLayer.js index 631ad327b9..7f340ac8ab 100644 --- a/src/annotationLayer.js +++ b/src/annotationLayer.js @@ -30,9 +30,13 @@ var textFeature = require('./textFeature'); * @param {number} [args.adjacentPointProximity=5] The minimum distance in * display coordinates (pixels) between two adjacent points when creating a * polygon or line. A value of 0 requires an exact match. - * @param {number} [args.continousPointProximity=5] The minimum distance in + * @param {number} [args.continuousPointProximity=5] The minimum distance in * display coordinates (pixels) between two adjacent points when dragging * to create an annotation. `false` disables continuous drawing mode. + * @param {number} [args.continuousPointColinearity=1.0deg] The minimum + * angle between a series of three points when dragging to not interpret + * them as colinear. Only applies if `continuousPointProximity` is not + * `false`. * @param {number} [args.finalPointProximity=10] The maximum distance in * display coordinates (pixels) between the starting point and the mouse * coordinates to signal closing a polygon. A value of 0 requires an exact @@ -105,6 +109,9 @@ var annotationLayer = function (args) { // in pixels; set to continuousPointProximity to false to disable // continuous drawing modes. continuousPointProximity: 5, + // in radians, minimum angle between continuous points to interpret them as + // being coliner + continuousPointColinearity: 1.0 * Math.PI / 180, finalPointProximity: 10, // in pixels, 0 is exact showLabels: true }, args); diff --git a/tests/cases/annotation.js b/tests/cases/annotation.js index 3407f681ca..18751b2b5c 100644 --- a/tests/cases/annotation.js +++ b/tests/cases/annotation.js @@ -848,6 +848,31 @@ describe('geo.annotation', function () { expect(ann.options('vertices').length).toBe(3); expect(ann.processAction(evt)).not.toBe(true); expect(ann.options('vertices').length).toBe(3); + // add a point that will be colinear with the next one + var halfway = { + x: (vertices[1].x + vertices[2].x) / 2, + y: (vertices[1].y + vertices[2].y) / 2 + }; + evt = { + state: {action: geo.geo_action.annotation_line}, + mouse: { + map: halfway, + mapgcs: map.displayToGcs(halfway, null) + } + }; + expect(ann.processAction(evt)).toBe(true); + expect(ann.options('vertices').length).toBe(4); + evt = { + state: {action: geo.geo_action.annotation_line}, + mouse: { + map: vertices[2], + mapgcs: map.displayToGcs(vertices[2], null) + } + }; + // a new colinear point will replace the previous point, so we still have + // the same point count + expect(ann.processAction(evt)).toBe(true); + expect(ann.options('vertices').length).toBe(4); }); });