Don't create intermediate colinear points on a line.
When dragging a line annotation, don't create points that are nearly
colinear.
MODIFY
src/annotation.js
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;

MODIFY
src/annotationLayer.js
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);

MODIFY
tests/cases/annotation.js
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);
});
});

Don't create intermediate colinear points on a line.

When dragging a line annotation, don't create points that are nearly
colinear.