Make predefined geometry functions compatible with removeLastPoint Add undo to example Make geometry function for Star compatible with use of removeLastPoint Additional createRegularPolygon tests
1814 lines
55 KiB
JavaScript
1814 lines
55 KiB
JavaScript
import Circle from '../../../../src/ol/geom/Circle.js';
|
|
import Draw, {
|
|
createBox,
|
|
createRegularPolygon,
|
|
} from '../../../../src/ol/interaction/Draw.js';
|
|
import Feature from '../../../../src/ol/Feature.js';
|
|
import Interaction from '../../../../src/ol/interaction/Interaction.js';
|
|
import LineString from '../../../../src/ol/geom/LineString.js';
|
|
import Map from '../../../../src/ol/Map.js';
|
|
import MapBrowserEvent from '../../../../src/ol/MapBrowserEvent.js';
|
|
import MultiLineString from '../../../../src/ol/geom/MultiLineString.js';
|
|
import MultiPoint from '../../../../src/ol/geom/MultiPoint.js';
|
|
import MultiPolygon from '../../../../src/ol/geom/MultiPolygon.js';
|
|
import Point from '../../../../src/ol/geom/Point.js';
|
|
import Polygon from '../../../../src/ol/geom/Polygon.js';
|
|
import VectorLayer from '../../../../src/ol/layer/Vector.js';
|
|
import VectorSource from '../../../../src/ol/source/Vector.js';
|
|
import View from '../../../../src/ol/View.js';
|
|
import proj4 from 'proj4';
|
|
import {
|
|
altKeyOnly,
|
|
always,
|
|
shiftKeyOnly,
|
|
} from '../../../../src/ol/events/condition.js';
|
|
import {
|
|
clearUserProjection,
|
|
setUserProjection,
|
|
transform,
|
|
} from '../../../../src/ol/proj.js';
|
|
import {equals} from '../../../../src/ol/array.js';
|
|
import {listen} from '../../../../src/ol/events.js';
|
|
import {register} from '../../../../src/ol/proj/proj4.js';
|
|
|
|
describe('ol.interaction.Draw', function () {
|
|
let target, map, source;
|
|
|
|
const width = 360;
|
|
const height = 180;
|
|
|
|
beforeEach(function (done) {
|
|
target = document.createElement('div');
|
|
const style = target.style;
|
|
style.position = 'absolute';
|
|
style.left = '-1000px';
|
|
style.top = '-1000px';
|
|
style.width = width + 'px';
|
|
style.height = height + 'px';
|
|
document.body.appendChild(target);
|
|
source = new VectorSource();
|
|
const layer = new VectorLayer({source: source});
|
|
map = new Map({
|
|
target: target,
|
|
layers: [layer],
|
|
view: new View({
|
|
projection: 'EPSG:4326',
|
|
center: [0, 0],
|
|
resolution: 1,
|
|
}),
|
|
});
|
|
map.once('postrender', function () {
|
|
done();
|
|
});
|
|
});
|
|
|
|
afterEach(function () {
|
|
map.dispose();
|
|
document.body.removeChild(target);
|
|
clearUserProjection();
|
|
});
|
|
|
|
/**
|
|
* Simulates a browser event on the map viewport. The client x/y location
|
|
* will be adjusted as if the map were centered at 0,0.
|
|
* @param {string} type Event type.
|
|
* @param {number} x Horizontal offset from map center.
|
|
* @param {number} y Vertical offset from map center.
|
|
* @param {boolean=} opt_shiftKey Shift key is pressed.
|
|
* @return {module:ol/MapBrowserEvent} The simulated event.
|
|
*/
|
|
function simulateEvent(type, x, y, opt_shiftKey) {
|
|
const viewport = map.getViewport();
|
|
// calculated in case body has top < 0 (test runner with small window)
|
|
const position = viewport.getBoundingClientRect();
|
|
const shiftKey = opt_shiftKey !== undefined ? opt_shiftKey : false;
|
|
const event = {};
|
|
event.type = type;
|
|
event.target = viewport.firstChild;
|
|
event.clientX = position.left + x + width / 2;
|
|
event.clientY = position.top + y + height / 2;
|
|
event.shiftKey = shiftKey;
|
|
event.preventDefault = function () {};
|
|
event.pointerType = 'mouse';
|
|
event.pointerId = 0;
|
|
const simulatedEvent = new MapBrowserEvent(type, map, event);
|
|
map.handleMapBrowserEvent(simulatedEvent);
|
|
return simulatedEvent;
|
|
}
|
|
|
|
describe('constructor', function () {
|
|
it('creates a new interaction', function () {
|
|
const draw = new Draw({
|
|
source: source,
|
|
type: 'Point',
|
|
});
|
|
expect(draw).to.be.a(Draw);
|
|
expect(draw).to.be.a(Interaction);
|
|
});
|
|
|
|
it('accepts a freehand option', function () {
|
|
const draw = new Draw({
|
|
source: source,
|
|
type: 'LineString',
|
|
freehand: true,
|
|
});
|
|
|
|
const event = new PointerEvent('pointerdown', {
|
|
clientX: 0,
|
|
clientY: 0,
|
|
shiftKey: false,
|
|
});
|
|
|
|
expect(draw.freehandCondition_(event)).to.be(true);
|
|
});
|
|
|
|
it('accepts a dragVertexDelay option', function () {
|
|
const draw = new Draw({
|
|
source: source,
|
|
type: 'LineString',
|
|
dragVertexDelay: 42,
|
|
});
|
|
expect(draw.dragVertexDelay_).to.be(42);
|
|
});
|
|
});
|
|
|
|
describe('specifying a geometryName', function () {
|
|
beforeEach(function () {
|
|
const draw = new Draw({
|
|
source: source,
|
|
geometryName: 'the_geom',
|
|
type: 'Point',
|
|
});
|
|
map.addInteraction(draw);
|
|
});
|
|
|
|
it('creates a feature with the correct geometryName', function () {
|
|
simulateEvent('pointermove', 10, 20);
|
|
simulateEvent('pointerdown', 10, 20);
|
|
simulateEvent('pointerup', 10, 20);
|
|
const features = source.getFeatures();
|
|
const geometry = features[0].getGeometry();
|
|
expect(features[0].getGeometryName()).to.equal('the_geom');
|
|
expect(geometry).to.be.a(Point);
|
|
});
|
|
});
|
|
|
|
describe('specifying a clickTolerance', function () {
|
|
beforeEach(function () {
|
|
const draw = new Draw({
|
|
source: source,
|
|
type: 'Point',
|
|
clickTolerance: 6,
|
|
});
|
|
map.addInteraction(draw);
|
|
});
|
|
|
|
it('adds a point when below the tolerance', function () {
|
|
let features;
|
|
|
|
simulateEvent('pointermove', 10, 20);
|
|
simulateEvent('pointerdown', 10, 20);
|
|
simulateEvent('pointerup', 15, 25);
|
|
features = source.getFeatures();
|
|
expect(features).to.length(0);
|
|
|
|
simulateEvent('pointermove', 10, 20);
|
|
simulateEvent('pointerdown', 10, 20);
|
|
simulateEvent('pointerup', 14, 24);
|
|
features = source.getFeatures();
|
|
expect(features).to.length(1);
|
|
});
|
|
});
|
|
|
|
describe('drawing points', function () {
|
|
let draw;
|
|
|
|
beforeEach(function () {
|
|
draw = new Draw({
|
|
source: source,
|
|
type: 'Point',
|
|
});
|
|
map.addInteraction(draw);
|
|
});
|
|
|
|
it('draws a point on click', function () {
|
|
simulateEvent('pointermove', 10, 20);
|
|
simulateEvent('pointerdown', 10, 20);
|
|
simulateEvent('pointerup', 10, 20);
|
|
const features = source.getFeatures();
|
|
expect(features).to.have.length(1);
|
|
const geometry = features[0].getGeometry();
|
|
expect(geometry).to.be.a(Point);
|
|
expect(geometry.getCoordinates()).to.eql([10, -20]);
|
|
});
|
|
|
|
it('does not draw a point with a significant drag', function () {
|
|
simulateEvent('pointermove', 10, 20);
|
|
simulateEvent('pointerdown', 10, 20);
|
|
simulateEvent('pointermove', 18, 20);
|
|
simulateEvent('pointerup', 18, 20);
|
|
const features = source.getFeatures();
|
|
expect(features).to.have.length(0);
|
|
});
|
|
|
|
it('does not draw a point when modifier key is pressed', function () {
|
|
simulateEvent('pointermove', 10, 20);
|
|
simulateEvent('pointerdown', 10, 20, true);
|
|
simulateEvent('pointerup', 10, 20);
|
|
const features = source.getFeatures();
|
|
expect(features).to.have.length(0);
|
|
});
|
|
|
|
it('triggers draw events', function () {
|
|
const ds = sinon.spy();
|
|
const de = sinon.spy();
|
|
const da = sinon.spy();
|
|
listen(draw, 'drawstart', ds);
|
|
listen(draw, 'drawend', de);
|
|
listen(draw, 'drawabort', da);
|
|
simulateEvent('pointermove', 10, 20);
|
|
simulateEvent('pointerdown', 10, 20);
|
|
simulateEvent('pointerup', 10, 20);
|
|
expect(ds.called).to.be(true);
|
|
expect(de.called).to.be(true);
|
|
expect(da.called).to.be(false);
|
|
simulateEvent('pointermove', 20, 20);
|
|
expect(ds.callCount).to.be(1);
|
|
expect(de.callCount).to.be(1);
|
|
expect(da.callCount).to.be(0);
|
|
});
|
|
|
|
it('triggers drawend event before inserting the feature', function () {
|
|
const receivedEvents = {
|
|
end: 0,
|
|
addfeature: 0,
|
|
};
|
|
listen(draw, 'drawend', function () {
|
|
expect(receivedEvents.end).to.be(0);
|
|
expect(receivedEvents.addfeature).to.be(0);
|
|
++receivedEvents.end;
|
|
});
|
|
source.on('addfeature', function () {
|
|
expect(receivedEvents.end).to.be(1);
|
|
expect(receivedEvents.addfeature).to.be(0);
|
|
receivedEvents.addfeature++;
|
|
});
|
|
simulateEvent('pointermove', 10, 20);
|
|
simulateEvent('pointerdown', 10, 20);
|
|
simulateEvent('pointerup', 10, 20);
|
|
simulateEvent('pointermove', 20, 20);
|
|
expect(receivedEvents.end).to.be(1);
|
|
expect(receivedEvents.addfeature).to.be(1);
|
|
});
|
|
|
|
it('works if finishDrawing is called when the sketch feature is not defined', function () {
|
|
expect(function () {
|
|
draw.finishDrawing();
|
|
}).to.not.throwException();
|
|
});
|
|
});
|
|
|
|
describe('drawing multipoints', function () {
|
|
let draw;
|
|
|
|
beforeEach(function () {
|
|
draw = new Draw({
|
|
source: source,
|
|
type: 'MultiPoint',
|
|
});
|
|
map.addInteraction(draw);
|
|
});
|
|
|
|
it('draws multipoint on click', function () {
|
|
simulateEvent('pointermove', 30, 15);
|
|
simulateEvent('pointerdown', 30, 15);
|
|
simulateEvent('pointerup', 30, 15);
|
|
const features = source.getFeatures();
|
|
expect(features).to.have.length(1);
|
|
const geometry = features[0].getGeometry();
|
|
expect(geometry).to.be.a(MultiPoint);
|
|
expect(geometry.getCoordinates()).to.eql([[30, -15]]);
|
|
});
|
|
|
|
it('works if finishDrawing is called when the sketch feature is not defined', function () {
|
|
expect(function () {
|
|
draw.finishDrawing();
|
|
}).to.not.throwException();
|
|
});
|
|
});
|
|
|
|
describe('drawing linestrings', function () {
|
|
let draw;
|
|
|
|
beforeEach(function () {
|
|
draw = new Draw({
|
|
source: source,
|
|
type: 'LineString',
|
|
});
|
|
map.addInteraction(draw);
|
|
});
|
|
|
|
it('draws linestring with clicks, finishing on last point', function () {
|
|
// first point
|
|
simulateEvent('pointermove', 10, 20);
|
|
simulateEvent('pointerdown', 10, 20);
|
|
simulateEvent('pointerup', 10, 20);
|
|
|
|
// second point
|
|
simulateEvent('pointermove', 30, 20);
|
|
simulateEvent('pointerdown', 30, 20);
|
|
simulateEvent('pointerup', 30, 20);
|
|
|
|
// finish on second point
|
|
simulateEvent('pointerdown', 30, 20);
|
|
simulateEvent('pointerup', 30, 20);
|
|
|
|
const features = source.getFeatures();
|
|
expect(features).to.have.length(1);
|
|
const geometry = features[0].getGeometry();
|
|
expect(geometry).to.be.a(LineString);
|
|
expect(geometry.getCoordinates()).to.eql([
|
|
[10, -20],
|
|
[30, -20],
|
|
]);
|
|
});
|
|
|
|
it('supports removeLastPoint while drawing', function () {
|
|
draw.removeLastPoint();
|
|
|
|
// first point
|
|
simulateEvent('pointermove', 10, 20);
|
|
simulateEvent('pointerdown', 10, 20);
|
|
simulateEvent('pointerup', 10, 20);
|
|
|
|
// second point
|
|
simulateEvent('pointermove', 40, 30);
|
|
simulateEvent('pointerdown', 40, 30);
|
|
simulateEvent('pointerup', 40, 30);
|
|
|
|
simulateEvent('pointermove', 100, 100);
|
|
draw.removeLastPoint();
|
|
|
|
// click near the removed point
|
|
simulateEvent('pointermove', 39, 31);
|
|
simulateEvent('pointerdown', 38, 31);
|
|
simulateEvent('pointerup', 38, 31);
|
|
|
|
expect(source.getFeatures()).to.have.length(0);
|
|
});
|
|
|
|
it('supports freehand drawing for linestrings', function () {
|
|
// freehand sequence
|
|
simulateEvent('pointermove', 10, 20);
|
|
simulateEvent('pointerdown', 10, 20, true);
|
|
simulateEvent('pointermove', 20, 30, true);
|
|
simulateEvent('pointerdrag', 20, 30, true);
|
|
simulateEvent('pointermove', 20, 40, true);
|
|
simulateEvent('pointerdrag', 20, 40, true);
|
|
simulateEvent('pointerup', 20, 40, true);
|
|
|
|
const features = source.getFeatures();
|
|
expect(features).to.have.length(1);
|
|
const geometry = features[0].getGeometry();
|
|
expect(geometry).to.be.a(LineString);
|
|
expect(geometry.getCoordinates()).to.eql([
|
|
[10, -20],
|
|
[20, -30],
|
|
[20, -40],
|
|
]);
|
|
});
|
|
|
|
it('allows freehand mode for part of the drawing', function () {
|
|
// non-freehand
|
|
simulateEvent('pointerdown', 10, 20);
|
|
simulateEvent('pointerup', 10, 20);
|
|
simulateEvent('pointermove', 20, 30);
|
|
|
|
// freehand
|
|
simulateEvent('pointermove', 20, 30, true);
|
|
simulateEvent('pointerdrag', 20, 30, true);
|
|
simulateEvent('pointermove', 30, 40, true);
|
|
simulateEvent('pointerdrag', 30, 40, true);
|
|
simulateEvent('pointermove', 40, 50, true);
|
|
simulateEvent('pointerdrag', 40, 50, true);
|
|
|
|
// non-freehand
|
|
simulateEvent('pointerup', 40, 50);
|
|
simulateEvent('pointermove', 50, 60);
|
|
simulateEvent('pointerdown', 50, 60);
|
|
simulateEvent('pointerup', 50, 60);
|
|
simulateEvent('pointermove', 60, 70);
|
|
simulateEvent('pointerdown', 60, 70);
|
|
simulateEvent('pointerup', 60, 70);
|
|
|
|
// finish
|
|
simulateEvent('pointerdown', 60, 70);
|
|
simulateEvent('pointerup', 60, 70);
|
|
|
|
const features = source.getFeatures();
|
|
const geometry = features[0].getGeometry();
|
|
expect(geometry).to.be.a(LineString);
|
|
expect(geometry.getCoordinates()).to.eql([
|
|
[10, -20],
|
|
[20, -30],
|
|
[30, -40],
|
|
[40, -50],
|
|
[50, -60],
|
|
[60, -70],
|
|
]);
|
|
});
|
|
|
|
it('does not add a point with a significant drag', function () {
|
|
// first point
|
|
simulateEvent('pointermove', 10, 20);
|
|
simulateEvent('pointerdown', 10, 20);
|
|
simulateEvent('pointerup', 10, 20);
|
|
|
|
// drag map
|
|
simulateEvent('pointermove', 15, 20);
|
|
simulateEvent('pointerdown', 15, 20);
|
|
simulateEvent('pointermove', 23, 20);
|
|
simulateEvent('pointerup', 23, 20);
|
|
|
|
// second point
|
|
simulateEvent('pointermove', 30, 20);
|
|
simulateEvent('pointerdown', 30, 20);
|
|
simulateEvent('pointerup', 30, 20);
|
|
|
|
// finish on second point
|
|
simulateEvent('pointerdown', 30, 20);
|
|
simulateEvent('pointerup', 30, 20);
|
|
|
|
const features = source.getFeatures();
|
|
expect(features).to.have.length(1);
|
|
const geometry = features[0].getGeometry();
|
|
expect(geometry).to.be.a(LineString);
|
|
expect(geometry.getCoordinates()).to.eql([
|
|
[10, -20],
|
|
[30, -20],
|
|
]);
|
|
});
|
|
|
|
it('allows dragging of the vertex after dragVertexDelay', function (done) {
|
|
// first point
|
|
simulateEvent('pointermove', 10, 20);
|
|
simulateEvent('pointerdown', 10, 20);
|
|
simulateEvent('pointerup', 10, 20);
|
|
|
|
// second point, drag vertex
|
|
simulateEvent('pointermove', 15, 20);
|
|
simulateEvent('pointerdown', 15, 20);
|
|
setTimeout(function () {
|
|
simulateEvent('pointermove', 20, 10);
|
|
simulateEvent('pointerdrag', 20, 10);
|
|
simulateEvent('pointerup', 20, 10);
|
|
// third point
|
|
simulateEvent('pointermove', 30, 20);
|
|
simulateEvent('pointerdown', 30, 20);
|
|
simulateEvent('pointerup', 30, 20);
|
|
|
|
// finish on third point
|
|
simulateEvent('pointerdown', 30, 20);
|
|
simulateEvent('pointerup', 30, 20);
|
|
|
|
const features = source.getFeatures();
|
|
expect(features).to.have.length(1);
|
|
const geometry = features[0].getGeometry();
|
|
expect(geometry).to.be.a(LineString);
|
|
expect(geometry.getCoordinates()).to.eql([
|
|
[10, -20],
|
|
[20, -10],
|
|
[30, -20],
|
|
]);
|
|
|
|
done();
|
|
}, 600);
|
|
});
|
|
|
|
it('triggers draw events', function () {
|
|
const ds = sinon.spy();
|
|
const de = sinon.spy();
|
|
const da = sinon.spy();
|
|
listen(draw, 'drawstart', ds);
|
|
listen(draw, 'drawend', de);
|
|
listen(draw, 'drawabort', da);
|
|
|
|
// first point
|
|
simulateEvent('pointermove', 10, 20);
|
|
simulateEvent('pointerdown', 10, 20);
|
|
simulateEvent('pointerup', 10, 20);
|
|
|
|
// second point
|
|
simulateEvent('pointermove', 30, 20);
|
|
simulateEvent('pointerdown', 30, 20);
|
|
simulateEvent('pointerup', 30, 20);
|
|
|
|
// finish on second point
|
|
simulateEvent('pointerdown', 30, 20);
|
|
simulateEvent('pointerup', 30, 20);
|
|
simulateEvent('pointermove', 10, 20);
|
|
|
|
expect(ds.called).to.be(true);
|
|
expect(ds.callCount).to.be(1);
|
|
expect(de.called).to.be(true);
|
|
expect(de.callCount).to.be(1);
|
|
expect(da.called).to.be(false);
|
|
expect(da.callCount).to.be(0);
|
|
});
|
|
|
|
it('works if finishDrawing is called when the sketch feature is not defined', function () {
|
|
expect(function () {
|
|
draw.finishDrawing();
|
|
}).to.not.throwException();
|
|
});
|
|
});
|
|
|
|
describe('drawing with a condition', function () {
|
|
let draw;
|
|
beforeEach(function () {
|
|
draw = new Draw({
|
|
source: source,
|
|
type: 'LineString',
|
|
condition: shiftKeyOnly,
|
|
freehandCondition: altKeyOnly,
|
|
});
|
|
map.addInteraction(draw);
|
|
});
|
|
|
|
it('finishes draw sequence correctly', function () {
|
|
// first point
|
|
simulateEvent('pointermove', 10, 20, true);
|
|
simulateEvent('pointerdown', 10, 20, true);
|
|
simulateEvent('pointerup', 10, 20, true);
|
|
|
|
// second point
|
|
simulateEvent('pointermove', 30, 20, true);
|
|
simulateEvent('pointerdown', 30, 20, true);
|
|
simulateEvent('pointerup', 30, 20, true);
|
|
|
|
// finish on second point
|
|
simulateEvent('pointerdown', 30, 20, true);
|
|
simulateEvent('pointerup', 30, 20, true);
|
|
|
|
const features = source.getFeatures();
|
|
expect(features).to.have.length(1);
|
|
const geometry = features[0].getGeometry();
|
|
expect(geometry).to.be.a(LineString);
|
|
expect(geometry.getCoordinates()).to.eql([
|
|
[10, -20],
|
|
[30, -20],
|
|
]);
|
|
|
|
// without modifier, to be handled by the map's DragPan interaction
|
|
simulateEvent('pointermove', 20, 20);
|
|
simulateEvent('pointerdown', 20, 20);
|
|
simulateEvent('pointermove', 10, 30);
|
|
expect(draw.lastDragTime_).to.be(undefined);
|
|
});
|
|
});
|
|
|
|
describe('drawing with a finishCondition', function () {
|
|
beforeEach(function () {
|
|
const draw = new Draw({
|
|
source: source,
|
|
type: 'LineString',
|
|
finishCondition: function (event) {
|
|
if (equals(event.coordinate, [30, -20])) {
|
|
return true;
|
|
}
|
|
return false;
|
|
},
|
|
});
|
|
map.addInteraction(draw);
|
|
});
|
|
|
|
it('draws a linestring failing to finish it first, the finishes it', function () {
|
|
let features;
|
|
|
|
// first point
|
|
simulateEvent('pointermove', 10, 20);
|
|
simulateEvent('pointerdown', 10, 20);
|
|
simulateEvent('pointerup', 10, 20);
|
|
|
|
// second point
|
|
simulateEvent('pointermove', 40, 30);
|
|
simulateEvent('pointerdown', 40, 30);
|
|
simulateEvent('pointerup', 40, 30);
|
|
|
|
// try to finish on this point
|
|
simulateEvent('pointerdown', 40, 30);
|
|
simulateEvent('pointerup', 40, 30);
|
|
|
|
features = source.getFeatures();
|
|
expect(features).to.have.length(0);
|
|
|
|
// third point
|
|
simulateEvent('pointermove', 30, 20);
|
|
simulateEvent('pointerdown', 30, 20);
|
|
simulateEvent('pointerup', 30, 20);
|
|
|
|
// finish on this point
|
|
simulateEvent('pointerdown', 30, 20);
|
|
simulateEvent('pointerup', 30, 20);
|
|
|
|
features = source.getFeatures();
|
|
expect(features).to.have.length(1);
|
|
});
|
|
});
|
|
|
|
describe('drawing multi-linestrings', function () {
|
|
let draw;
|
|
|
|
beforeEach(function () {
|
|
draw = new Draw({
|
|
source: source,
|
|
type: 'MultiLineString',
|
|
});
|
|
map.addInteraction(draw);
|
|
});
|
|
|
|
it('draws multi with clicks, finishing on last point', function () {
|
|
// first point
|
|
simulateEvent('pointermove', 10, 20);
|
|
simulateEvent('pointerdown', 10, 20);
|
|
simulateEvent('pointerup', 10, 20);
|
|
|
|
// second point
|
|
simulateEvent('pointermove', 30, 20);
|
|
simulateEvent('pointerdown', 30, 20);
|
|
simulateEvent('pointerup', 30, 20);
|
|
|
|
// finish on second point
|
|
simulateEvent('pointerdown', 30, 20);
|
|
simulateEvent('pointerup', 30, 20);
|
|
|
|
const features = source.getFeatures();
|
|
expect(features).to.have.length(1);
|
|
const geometry = features[0].getGeometry();
|
|
expect(geometry).to.be.a(MultiLineString);
|
|
expect(geometry.getCoordinates()).to.eql([
|
|
[
|
|
[10, -20],
|
|
[30, -20],
|
|
],
|
|
]);
|
|
});
|
|
|
|
it('works if finishDrawing is called when the sketch feature is not defined', function () {
|
|
expect(function () {
|
|
draw.finishDrawing();
|
|
}).to.not.throwException();
|
|
});
|
|
});
|
|
|
|
describe('drawing polygons', function () {
|
|
let draw;
|
|
|
|
beforeEach(function () {
|
|
draw = new Draw({
|
|
source: source,
|
|
type: 'Polygon',
|
|
});
|
|
map.addInteraction(draw);
|
|
});
|
|
|
|
function isClosed(polygon) {
|
|
const first = polygon.getFirstCoordinate();
|
|
const last = polygon.getLastCoordinate();
|
|
expect(first).to.eql(last);
|
|
}
|
|
|
|
it('draws polygon with clicks, finishing on first point', function () {
|
|
// first point
|
|
simulateEvent('pointermove', 10, 20);
|
|
simulateEvent('pointerdown', 10, 20);
|
|
simulateEvent('pointerup', 10, 20);
|
|
isClosed(draw.sketchFeature_.getGeometry());
|
|
|
|
// second point
|
|
simulateEvent('pointermove', 30, 20);
|
|
simulateEvent('pointerdown', 30, 20);
|
|
simulateEvent('pointerup', 30, 20);
|
|
isClosed(draw.sketchFeature_.getGeometry());
|
|
|
|
// third point
|
|
simulateEvent('pointermove', 40, 10);
|
|
simulateEvent('pointerdown', 40, 10);
|
|
simulateEvent('pointerup', 40, 10);
|
|
isClosed(draw.sketchFeature_.getGeometry());
|
|
|
|
// finish on first point
|
|
simulateEvent('pointermove', 10, 20);
|
|
simulateEvent('pointerdown', 10, 20);
|
|
simulateEvent('pointerup', 10, 20);
|
|
|
|
const features = source.getFeatures();
|
|
expect(features).to.have.length(1);
|
|
const geometry = features[0].getGeometry();
|
|
expect(geometry).to.be.a(Polygon);
|
|
|
|
expect(geometry.getCoordinates()).to.eql([
|
|
[
|
|
[10, -20],
|
|
[30, -20],
|
|
[40, -10],
|
|
[10, -20],
|
|
],
|
|
]);
|
|
});
|
|
|
|
it('supports removeLastPoint while drawing', function () {
|
|
draw.removeLastPoint();
|
|
|
|
// first point
|
|
simulateEvent('pointermove', 10, 20);
|
|
simulateEvent('pointerdown', 10, 20);
|
|
simulateEvent('pointerup', 10, 20);
|
|
|
|
// second point
|
|
simulateEvent('pointermove', 40, 30);
|
|
simulateEvent('pointerdown', 40, 30);
|
|
simulateEvent('pointerup', 40, 30);
|
|
|
|
simulateEvent('pointermove', 100, 100);
|
|
draw.removeLastPoint();
|
|
|
|
// click near the removed point
|
|
simulateEvent('pointermove', 39, 31);
|
|
simulateEvent('pointerdown', 39, 31);
|
|
simulateEvent('pointerup', 39, 31);
|
|
|
|
expect(source.getFeatures()).to.have.length(0);
|
|
});
|
|
|
|
it('will tolerate removeLastPoint being called when no coordinates', function () {
|
|
// first point
|
|
simulateEvent('pointermove', 10, 20);
|
|
simulateEvent('pointerdown', 10, 20);
|
|
simulateEvent('pointerup', 10, 20);
|
|
|
|
// second point
|
|
simulateEvent('pointermove', 40, 30);
|
|
simulateEvent('pointerdown', 40, 30);
|
|
simulateEvent('pointerup', 40, 30);
|
|
|
|
simulateEvent('pointermove', 100, 100);
|
|
|
|
expect(function () {
|
|
draw.removeLastPoint();
|
|
draw.removeLastPoint();
|
|
draw.removeLastPoint();
|
|
}).to.not.throwException();
|
|
});
|
|
|
|
it('draws polygon with clicks, finishing on last point', function () {
|
|
// first point
|
|
simulateEvent('pointermove', 10, 20);
|
|
simulateEvent('pointerdown', 10, 20);
|
|
simulateEvent('pointerup', 10, 20);
|
|
|
|
// second point
|
|
simulateEvent('pointermove', 30, 20);
|
|
simulateEvent('pointerdown', 30, 20);
|
|
simulateEvent('pointerup', 30, 20);
|
|
|
|
// third point
|
|
simulateEvent('pointermove', 40, 10);
|
|
simulateEvent('pointerdown', 40, 10);
|
|
simulateEvent('pointerup', 40, 10);
|
|
|
|
// finish on last point
|
|
simulateEvent('pointerdown', 40, 10);
|
|
simulateEvent('pointerup', 40, 10);
|
|
|
|
const features = source.getFeatures();
|
|
expect(features).to.have.length(1);
|
|
const geometry = features[0].getGeometry();
|
|
expect(geometry).to.be.a(Polygon);
|
|
|
|
expect(geometry.getCoordinates()).to.eql([
|
|
[
|
|
[10, -20],
|
|
[30, -20],
|
|
[40, -10],
|
|
[10, -20],
|
|
],
|
|
]);
|
|
});
|
|
|
|
it('supports freehand drawing for polygons', function () {
|
|
// freehand sequence
|
|
simulateEvent('pointermove', 10, 20);
|
|
simulateEvent('pointerdown', 10, 20, true);
|
|
simulateEvent('pointermove', 30, 20, true);
|
|
simulateEvent('pointerdrag', 30, 20, true);
|
|
simulateEvent('pointermove', 40, 10, true);
|
|
simulateEvent('pointerdrag', 40, 10, true);
|
|
simulateEvent('pointerup', 40, 10, true);
|
|
|
|
// finish on last point
|
|
simulateEvent('pointerdown', 40, 10);
|
|
simulateEvent('pointerup', 40, 10);
|
|
|
|
const features = source.getFeatures();
|
|
expect(features).to.have.length(1);
|
|
const geometry = features[0].getGeometry();
|
|
expect(geometry).to.be.a(Polygon);
|
|
|
|
expect(geometry.getCoordinates()).to.eql([
|
|
[
|
|
[10, -20],
|
|
[30, -20],
|
|
[40, -10],
|
|
[10, -20],
|
|
],
|
|
]);
|
|
});
|
|
|
|
it('triggers draw events', function () {
|
|
const ds = sinon.spy();
|
|
const de = sinon.spy();
|
|
const da = sinon.spy();
|
|
listen(draw, 'drawstart', ds);
|
|
listen(draw, 'drawend', de);
|
|
listen(draw, 'drawabort', da);
|
|
|
|
// first point
|
|
simulateEvent('pointermove', 10, 20);
|
|
simulateEvent('pointerdown', 10, 20);
|
|
simulateEvent('pointerup', 10, 20);
|
|
|
|
// second point
|
|
simulateEvent('pointermove', 30, 20);
|
|
simulateEvent('pointerdown', 30, 20);
|
|
simulateEvent('pointerup', 30, 20);
|
|
|
|
// third point
|
|
simulateEvent('pointermove', 30, 10);
|
|
simulateEvent('pointerdown', 30, 10);
|
|
simulateEvent('pointerup', 30, 10);
|
|
|
|
// finish on first point
|
|
simulateEvent('pointermove', 10, 20);
|
|
simulateEvent('pointerdown', 10, 20);
|
|
simulateEvent('pointerup', 10, 20);
|
|
|
|
expect(ds.called).to.be(true);
|
|
expect(ds.callCount).to.be(1);
|
|
expect(de.called).to.be(true);
|
|
expect(de.callCount).to.be(1);
|
|
expect(da.called).to.be(false);
|
|
expect(da.callCount).to.be(0);
|
|
});
|
|
|
|
it('works if finishDrawing is called when the sketch feature is not defined', function () {
|
|
expect(function () {
|
|
draw.finishDrawing();
|
|
}).to.not.throwException();
|
|
});
|
|
});
|
|
|
|
describe('drawing multi-polygons', function () {
|
|
let draw;
|
|
|
|
beforeEach(function () {
|
|
draw = new Draw({
|
|
source: source,
|
|
type: 'MultiPolygon',
|
|
});
|
|
map.addInteraction(draw);
|
|
});
|
|
|
|
it('draws multi with clicks, finishing on first point', function () {
|
|
// first point
|
|
simulateEvent('pointermove', 10, 20);
|
|
simulateEvent('pointerdown', 10, 20);
|
|
simulateEvent('pointerup', 10, 20);
|
|
|
|
// second point
|
|
simulateEvent('pointermove', 30, 20);
|
|
simulateEvent('pointerdown', 30, 20);
|
|
simulateEvent('pointerup', 30, 20);
|
|
|
|
// third point
|
|
simulateEvent('pointermove', 40, 10);
|
|
simulateEvent('pointerdown', 40, 10);
|
|
simulateEvent('pointerup', 40, 10);
|
|
|
|
// finish on first point
|
|
simulateEvent('pointermove', 10, 20);
|
|
simulateEvent('pointerdown', 10, 20);
|
|
simulateEvent('pointerup', 10, 20);
|
|
|
|
const features = source.getFeatures();
|
|
expect(features).to.have.length(1);
|
|
const geometry = features[0].getGeometry();
|
|
expect(geometry).to.be.a(MultiPolygon);
|
|
const coordinates = geometry.getCoordinates();
|
|
expect(coordinates).to.have.length(1);
|
|
|
|
expect(coordinates[0]).to.eql([
|
|
[
|
|
[10, -20],
|
|
[30, -20],
|
|
[40, -10],
|
|
[10, -20],
|
|
],
|
|
]);
|
|
});
|
|
|
|
it('draws multi with clicks, finishing on last point', function () {
|
|
// first point
|
|
simulateEvent('pointermove', 10, 20);
|
|
simulateEvent('pointerdown', 10, 20);
|
|
simulateEvent('pointerup', 10, 20);
|
|
|
|
// second point
|
|
simulateEvent('pointermove', 30, 20);
|
|
simulateEvent('pointerdown', 30, 20);
|
|
simulateEvent('pointerup', 30, 20);
|
|
|
|
// third point
|
|
simulateEvent('pointermove', 40, 10);
|
|
simulateEvent('pointerdown', 40, 10);
|
|
simulateEvent('pointerup', 40, 10);
|
|
|
|
// finish on last point
|
|
simulateEvent('pointerdown', 40, 10);
|
|
simulateEvent('pointerup', 40, 10);
|
|
|
|
const features = source.getFeatures();
|
|
expect(features).to.have.length(1);
|
|
const geometry = features[0].getGeometry();
|
|
expect(geometry).to.be.a(MultiPolygon);
|
|
const coordinates = geometry.getCoordinates();
|
|
expect(coordinates).to.have.length(1);
|
|
|
|
expect(coordinates[0]).to.eql([
|
|
[
|
|
[10, -20],
|
|
[30, -20],
|
|
[40, -10],
|
|
[10, -20],
|
|
],
|
|
]);
|
|
});
|
|
|
|
it('works if finishDrawing is called when the sketch feature is not defined', function () {
|
|
expect(function () {
|
|
draw.finishDrawing();
|
|
}).to.not.throwException();
|
|
});
|
|
});
|
|
|
|
describe('drawing circles', function () {
|
|
let draw;
|
|
|
|
beforeEach(function () {
|
|
draw = new Draw({
|
|
source: source,
|
|
type: 'Circle',
|
|
});
|
|
map.addInteraction(draw);
|
|
});
|
|
|
|
it('draws circle with clicks, finishing on second point along x axis', function () {
|
|
// first point
|
|
simulateEvent('pointermove', 10, 20);
|
|
simulateEvent('pointerdown', 10, 20);
|
|
simulateEvent('pointerup', 10, 20);
|
|
|
|
// finish on second point
|
|
simulateEvent('pointermove', 30, 20);
|
|
simulateEvent('pointerdown', 30, 20);
|
|
simulateEvent('pointerup', 30, 20);
|
|
|
|
const features = source.getFeatures();
|
|
expect(features).to.have.length(1);
|
|
const geometry = features[0].getGeometry();
|
|
expect(geometry).to.be.a(Circle);
|
|
expect(geometry.getCenter()).to.eql([10, -20]);
|
|
expect(geometry.getRadius()).to.eql(20);
|
|
});
|
|
|
|
it('draws circle with clicks, finishing on second point along y axis', function () {
|
|
// first point
|
|
simulateEvent('pointermove', 10, 20);
|
|
simulateEvent('pointerdown', 10, 20);
|
|
simulateEvent('pointerup', 10, 20);
|
|
|
|
// finish on second point
|
|
simulateEvent('pointermove', 10, 40);
|
|
simulateEvent('pointerdown', 10, 40);
|
|
simulateEvent('pointerup', 10, 40);
|
|
|
|
const features = source.getFeatures();
|
|
expect(features).to.have.length(1);
|
|
const geometry = features[0].getGeometry();
|
|
expect(geometry).to.be.a(Circle);
|
|
expect(geometry.getCenter()).to.eql([10, -20]);
|
|
expect(geometry.getRadius()).to.eql(20);
|
|
});
|
|
|
|
it('draws circle with clicks in a user projection, finishing on second point along x axis', function () {
|
|
const userProjection = 'EPSG:3857';
|
|
setUserProjection(userProjection);
|
|
|
|
// first point
|
|
simulateEvent('pointermove', 10, 20);
|
|
simulateEvent('pointerdown', 10, 20);
|
|
simulateEvent('pointerup', 10, 20);
|
|
|
|
// finish on second point
|
|
simulateEvent('pointermove', 30, 20);
|
|
simulateEvent('pointerdown', 30, 20);
|
|
simulateEvent('pointerup', 30, 20);
|
|
|
|
const features = source.getFeatures();
|
|
expect(features).to.have.length(1);
|
|
const geometry = features[0].getGeometry();
|
|
expect(geometry).to.be.a(Circle);
|
|
const viewProjection = map.getView().getProjection();
|
|
expect(geometry.getCenter()).to.eql(
|
|
transform([10, -20], viewProjection, userProjection)
|
|
);
|
|
const radius = geometry
|
|
.clone()
|
|
.transform(userProjection, viewProjection)
|
|
.getRadius();
|
|
expect(radius).to.roughlyEqual(20, 1e-9);
|
|
});
|
|
|
|
it('draws circle with clicks in a user projection, finishing on second point along y axis', function () {
|
|
const userProjection = 'EPSG:3857';
|
|
setUserProjection(userProjection);
|
|
|
|
// first point
|
|
simulateEvent('pointermove', 10, 20);
|
|
simulateEvent('pointerdown', 10, 20);
|
|
simulateEvent('pointerup', 10, 20);
|
|
|
|
// finish on second point
|
|
simulateEvent('pointermove', 10, 40);
|
|
simulateEvent('pointerdown', 10, 40);
|
|
simulateEvent('pointerup', 10, 40);
|
|
|
|
const features = source.getFeatures();
|
|
expect(features).to.have.length(1);
|
|
const geometry = features[0].getGeometry();
|
|
expect(geometry).to.be.a(Circle);
|
|
const viewProjection = map.getView().getProjection();
|
|
expect(geometry.getCenter()).to.eql(
|
|
transform([10, -20], viewProjection, userProjection)
|
|
);
|
|
const radius = geometry
|
|
.clone()
|
|
.transform(userProjection, viewProjection)
|
|
.getRadius();
|
|
expect(radius).to.roughlyEqual(20, 1e-9);
|
|
});
|
|
|
|
it('supports freehand drawing for circles', function () {
|
|
draw.freehand_ = true;
|
|
draw.freehandCondition_ = always;
|
|
|
|
// no feature created when not moved
|
|
simulateEvent('pointermove', 10, 20);
|
|
simulateEvent('pointerdown', 10, 20);
|
|
simulateEvent('pointerup', 10, 20);
|
|
expect(source.getFeatures()).to.have.length(0);
|
|
|
|
// feature created when moved
|
|
simulateEvent('pointermove', 10, 20);
|
|
simulateEvent('pointerdown', 10, 20);
|
|
simulateEvent('pointermove', 30, 20);
|
|
simulateEvent('pointerup', 30, 20);
|
|
expect(source.getFeatures()).to.have.length(1);
|
|
});
|
|
|
|
it('triggers draw events', function () {
|
|
const ds = sinon.spy();
|
|
const de = sinon.spy();
|
|
const da = sinon.spy();
|
|
listen(draw, 'drawstart', ds);
|
|
listen(draw, 'drawend', de);
|
|
listen(draw, 'drawabort', da);
|
|
|
|
// first point
|
|
simulateEvent('pointermove', 10, 20);
|
|
simulateEvent('pointerdown', 10, 20);
|
|
simulateEvent('pointerup', 10, 20);
|
|
|
|
// finish on second point
|
|
simulateEvent('pointermove', 30, 20);
|
|
simulateEvent('pointerdown', 30, 20);
|
|
simulateEvent('pointerup', 30, 20);
|
|
|
|
expect(ds.called).to.be(true);
|
|
expect(ds.callCount).to.be(1);
|
|
expect(de.called).to.be(true);
|
|
expect(de.callCount).to.be(1);
|
|
expect(da.called).to.be(false);
|
|
expect(da.callCount).to.be(0);
|
|
});
|
|
});
|
|
|
|
describe('#abortDrawing()', function () {
|
|
let draw;
|
|
|
|
beforeEach(function () {
|
|
draw = new Draw({
|
|
source: source,
|
|
type: 'LineString',
|
|
});
|
|
map.addInteraction(draw);
|
|
});
|
|
|
|
it('aborts the current drawing', function () {
|
|
// first point
|
|
simulateEvent('pointermove', 10, 20);
|
|
simulateEvent('pointerdown', 10, 20);
|
|
simulateEvent('pointerup', 10, 20);
|
|
|
|
// second point
|
|
simulateEvent('pointermove', 30, 20);
|
|
simulateEvent('pointerdown', 30, 20);
|
|
simulateEvent('pointerup', 30, 20);
|
|
|
|
draw.abortDrawing();
|
|
|
|
expect(source.getFeatures()).to.have.length(0);
|
|
expect(draw.sketchFeature_).to.be(null);
|
|
});
|
|
|
|
it('triggers draw events', function () {
|
|
const ds = sinon.spy();
|
|
const de = sinon.spy();
|
|
const da = sinon.spy();
|
|
listen(draw, 'drawstart', ds);
|
|
listen(draw, 'drawend', de);
|
|
listen(draw, 'drawabort', da);
|
|
|
|
// first point
|
|
simulateEvent('pointermove', 10, 20);
|
|
simulateEvent('pointerdown', 10, 20);
|
|
simulateEvent('pointerup', 10, 20);
|
|
|
|
// second point
|
|
simulateEvent('pointermove', 30, 20);
|
|
simulateEvent('pointerdown', 30, 20);
|
|
simulateEvent('pointerup', 30, 20);
|
|
|
|
draw.abortDrawing();
|
|
|
|
expect(ds.called).to.be(true);
|
|
expect(ds.callCount).to.be(1);
|
|
expect(de.called).to.be(false);
|
|
expect(de.callCount).to.be(0);
|
|
expect(da.called).to.be(true);
|
|
expect(da.callCount).to.be(1);
|
|
|
|
// first point
|
|
simulateEvent('pointermove', 10, 20);
|
|
simulateEvent('pointerdown', 10, 20);
|
|
simulateEvent('pointerup', 10, 20);
|
|
|
|
// second point
|
|
simulateEvent('pointermove', 30, 20);
|
|
simulateEvent('pointerdown', 30, 20);
|
|
simulateEvent('pointerup', 30, 20);
|
|
|
|
draw.removeLastPoint();
|
|
draw.removeLastPoint();
|
|
draw.removeLastPoint();
|
|
|
|
expect(ds.called).to.be(true);
|
|
expect(ds.callCount).to.be(2);
|
|
expect(de.called).to.be(false);
|
|
expect(de.callCount).to.be(0);
|
|
expect(da.called).to.be(true);
|
|
expect(da.callCount).to.be(2);
|
|
});
|
|
|
|
it('works if finishDrawing is called when the sketch feature is not defined', function () {
|
|
expect(function () {
|
|
draw.finishDrawing();
|
|
}).to.not.throwException();
|
|
});
|
|
});
|
|
|
|
describe('#setActive()', function () {
|
|
let interaction;
|
|
|
|
beforeEach(function () {
|
|
interaction = new Draw({
|
|
type: 'LineString',
|
|
});
|
|
|
|
expect(interaction.getActive()).to.be(true);
|
|
|
|
map.addInteraction(interaction);
|
|
|
|
// first point
|
|
simulateEvent('pointermove', 10, 20);
|
|
simulateEvent('pointerdown', 10, 20);
|
|
simulateEvent('pointerup', 10, 20);
|
|
|
|
expect(interaction.sketchFeature_).not.to.be(null);
|
|
});
|
|
|
|
afterEach(function () {
|
|
map.removeInteraction(interaction);
|
|
});
|
|
|
|
describe('#setActive(false)', function () {
|
|
it('unsets the map from the feature overlay', function () {
|
|
const spy = sinon.spy(interaction.overlay_, 'setMap');
|
|
interaction.setActive(false);
|
|
expect(spy.getCall(0).args[0]).to.be(null);
|
|
});
|
|
it('aborts the drawing', function () {
|
|
interaction.setActive(false);
|
|
expect(interaction.sketchFeature_).to.be(null);
|
|
});
|
|
it('fires change:active', function () {
|
|
const spy = sinon.spy(interaction.overlay_, 'setMap');
|
|
const listenerSpy = sinon.spy(function () {
|
|
// test that the interaction's change:active listener is called first
|
|
expect(spy.getCall(0).args[0]).to.be(null);
|
|
});
|
|
interaction.on('change:active', listenerSpy);
|
|
interaction.setActive(false);
|
|
expect(listenerSpy.callCount).to.be(1);
|
|
});
|
|
});
|
|
|
|
describe('#setActive(true)', function () {
|
|
beforeEach(function () {
|
|
interaction.setActive(false);
|
|
});
|
|
it('sets the map into the feature overlay', function () {
|
|
const spy = sinon.spy(interaction.overlay_, 'setMap');
|
|
interaction.setActive(true);
|
|
expect(spy.getCall(0).args[0]).to.be(map);
|
|
});
|
|
it('fires change:active', function () {
|
|
const spy = sinon.spy(interaction.overlay_, 'setMap');
|
|
const listenerSpy = sinon.spy(function () {
|
|
// test that the interaction's change:active listener is called first
|
|
expect(spy.getCall(0).args[0]).to.be(map);
|
|
});
|
|
interaction.on('change:active', listenerSpy);
|
|
interaction.setActive(true);
|
|
expect(listenerSpy.callCount).to.be(1);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('#setMap()', function () {
|
|
let interaction;
|
|
|
|
beforeEach(function () {
|
|
interaction = new Draw({
|
|
type: 'LineString',
|
|
});
|
|
expect(interaction.getActive()).to.be(true);
|
|
});
|
|
|
|
describe('#setMap(null)', function () {
|
|
beforeEach(function () {
|
|
map.addInteraction(interaction);
|
|
// first point
|
|
simulateEvent('pointermove', 10, 20);
|
|
simulateEvent('pointerdown', 10, 20);
|
|
simulateEvent('pointerup', 10, 20);
|
|
expect(interaction.sketchFeature_).not.to.be(null);
|
|
});
|
|
afterEach(function () {
|
|
map.removeInteraction(interaction);
|
|
});
|
|
describe('#setMap(null) when interaction is active', function () {
|
|
it('unsets the map from the feature overlay', function () {
|
|
const spy = sinon.spy(interaction.overlay_, 'setMap');
|
|
interaction.setMap(null);
|
|
expect(spy.getCall(0).args[0]).to.be(null);
|
|
});
|
|
it('aborts the drawing', function () {
|
|
interaction.setMap(null);
|
|
expect(interaction.sketchFeature_).to.be(null);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('#setMap(null) when no drawing is in progress', function () {
|
|
beforeEach(function () {
|
|
map.addInteraction(interaction);
|
|
simulateEvent('pointermove', 10, 20);
|
|
expect(interaction.sketchFeature_).to.be(null);
|
|
expect(interaction.sketchPoint_).not.to.be(null);
|
|
});
|
|
afterEach(function () {
|
|
map.removeInteraction(interaction);
|
|
});
|
|
it('clears the sketch features', function () {
|
|
interaction.setMap(null);
|
|
expect(interaction.sketchFeature_).to.be(null);
|
|
expect(interaction.sketchPoint_).to.be(null);
|
|
expect(interaction.sketchLine_).to.be(null);
|
|
});
|
|
});
|
|
|
|
describe('#setMap(map)', function () {
|
|
describe('#setMap(map) when interaction is active', function () {
|
|
it('sets the map into the feature overlay', function () {
|
|
const spy = sinon.spy(interaction.overlay_, 'setMap');
|
|
interaction.setMap(map);
|
|
expect(spy.getCall(0).args[0]).to.be(map);
|
|
});
|
|
});
|
|
describe('#setMap(map) when interaction is not active', function () {
|
|
it('does not set the map into the feature overlay', function () {
|
|
interaction.setActive(false);
|
|
const spy = sinon.spy(interaction.overlay_, 'setMap');
|
|
interaction.setMap(map);
|
|
expect(spy.getCall(0).args[0]).to.be(null);
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('#getOverlay', function () {
|
|
it('returns the feature overlay layer', function () {
|
|
const draw = new Draw({});
|
|
expect(draw.getOverlay()).to.eql(draw.overlay_);
|
|
});
|
|
});
|
|
|
|
describe('createRegularPolygon', function () {
|
|
it('creates a regular polygon in Circle mode', function () {
|
|
const draw = new Draw({
|
|
source: source,
|
|
type: 'Circle',
|
|
geometryFunction: createRegularPolygon(4),
|
|
});
|
|
map.addInteraction(draw);
|
|
|
|
// first point
|
|
simulateEvent('pointermove', 0, 0);
|
|
simulateEvent('pointerdown', 0, 0);
|
|
simulateEvent('pointerup', 0, 0);
|
|
|
|
// finish on second point
|
|
simulateEvent('pointermove', 20, 20);
|
|
simulateEvent('pointerdown', 20, 20);
|
|
simulateEvent('pointerup', 20, 20);
|
|
|
|
const features = source.getFeatures();
|
|
const geometry = features[0].getGeometry();
|
|
expect(geometry).to.be.a(Polygon);
|
|
const coordinates = geometry.getCoordinates();
|
|
expect(coordinates[0].length).to.eql(5);
|
|
expect(coordinates[0][0][0]).to.roughlyEqual(20, 1e-9);
|
|
expect(coordinates[0][0][1]).to.roughlyEqual(-20, 1e-9);
|
|
});
|
|
|
|
it('creates a regular polygon at specified angle', function () {
|
|
const draw = new Draw({
|
|
source: source,
|
|
type: 'Circle',
|
|
geometryFunction: createRegularPolygon(4, Math.PI / 4),
|
|
});
|
|
map.addInteraction(draw);
|
|
|
|
// first point
|
|
simulateEvent('pointermove', 0, 0);
|
|
simulateEvent('pointerdown', 0, 0);
|
|
simulateEvent('pointerup', 0, 0);
|
|
|
|
// finish on second point
|
|
simulateEvent('pointermove', 20, 20);
|
|
simulateEvent('pointerdown', 20, 20);
|
|
simulateEvent('pointerup', 20, 20);
|
|
|
|
const features = source.getFeatures();
|
|
const geometry = features[0].getGeometry();
|
|
expect(geometry).to.be.a(Polygon);
|
|
const coordinates = geometry.getCoordinates();
|
|
expect(coordinates[0].length).to.eql(5);
|
|
expect(coordinates[0][0][0]).to.roughlyEqual(20, 1e-9);
|
|
expect(coordinates[0][0][1]).to.roughlyEqual(20, 1e-9);
|
|
});
|
|
|
|
it('creates a regular polygon at specified 0 angle', function () {
|
|
const draw = new Draw({
|
|
source: source,
|
|
type: 'Circle',
|
|
geometryFunction: createRegularPolygon(4, 0),
|
|
});
|
|
map.addInteraction(draw);
|
|
|
|
// first point
|
|
simulateEvent('pointermove', 0, 0);
|
|
simulateEvent('pointerdown', 0, 0);
|
|
simulateEvent('pointerup', 0, 0);
|
|
|
|
// finish on second point
|
|
simulateEvent('pointermove', 20, 20);
|
|
simulateEvent('pointerdown', 20, 20);
|
|
simulateEvent('pointerup', 20, 20);
|
|
|
|
const features = source.getFeatures();
|
|
const geometry = features[0].getGeometry();
|
|
expect(geometry).to.be.a(Polygon);
|
|
const coordinates = geometry.getCoordinates();
|
|
expect(coordinates[0].length).to.eql(5);
|
|
expect(coordinates[0][0][0]).to.roughlyEqual(28.2842712474619, 1e-9);
|
|
expect(coordinates[0][0][1]).to.roughlyEqual(0, 1e-9);
|
|
});
|
|
|
|
it('creates a regular polygon in Circle mode in a user projection', function () {
|
|
const userProjection = 'EPSG:3857';
|
|
setUserProjection(userProjection);
|
|
|
|
const draw = new Draw({
|
|
source: source,
|
|
type: 'Circle',
|
|
geometryFunction: createRegularPolygon(4, Math.PI / 4),
|
|
});
|
|
map.addInteraction(draw);
|
|
|
|
// first point
|
|
simulateEvent('pointermove', 0, 0);
|
|
simulateEvent('pointerdown', 0, 0);
|
|
simulateEvent('pointerup', 0, 0);
|
|
|
|
// finish on second point
|
|
simulateEvent('pointermove', 20, 20);
|
|
simulateEvent('pointerdown', 20, 20);
|
|
simulateEvent('pointerup', 20, 20);
|
|
|
|
const features = source.getFeatures();
|
|
const geometry = features[0].getGeometry();
|
|
expect(geometry).to.be.a(Polygon);
|
|
const coordinates = geometry.getCoordinates();
|
|
expect(coordinates[0].length).to.eql(5);
|
|
const viewProjection = map.getView().getProjection();
|
|
const coordinate = transform([20, 20], viewProjection, userProjection);
|
|
expect(coordinates[0][0][0]).to.roughlyEqual(coordinate[0], 1e-9);
|
|
expect(coordinates[0][0][1]).to.roughlyEqual(coordinate[1], 1e-9);
|
|
});
|
|
|
|
it('sketch start point always matches the mouse point', function () {
|
|
const draw = new Draw({
|
|
source: source,
|
|
type: 'Circle',
|
|
geometryFunction: createRegularPolygon(3),
|
|
});
|
|
map.addInteraction(draw);
|
|
|
|
// regular polygon center point
|
|
simulateEvent('pointermove', 60, 60);
|
|
simulateEvent('pointerdown', 60, 60);
|
|
simulateEvent('pointerup', 60, 60);
|
|
|
|
// move to first quadrant
|
|
simulateEvent('pointermove', 79, 80);
|
|
let event = simulateEvent('pointermove', 80, 80);
|
|
let coordinate = event.coordinate;
|
|
const firstQuadrantCoordinate = draw.sketchFeature_
|
|
.getGeometry()
|
|
.getFirstCoordinate();
|
|
expect(firstQuadrantCoordinate[0]).to.roughlyEqual(coordinate[0], 1e-9);
|
|
expect(firstQuadrantCoordinate[1]).to.roughlyEqual(coordinate[1], 1e-9);
|
|
|
|
// move to second quadrant
|
|
simulateEvent('pointermove', 41, 80);
|
|
event = simulateEvent('pointermove', 40, 80);
|
|
coordinate = event.coordinate;
|
|
const secondQuadrantCoordinate = draw.sketchFeature_
|
|
.getGeometry()
|
|
.getFirstCoordinate();
|
|
expect(secondQuadrantCoordinate[0]).to.roughlyEqual(coordinate[0], 1e-9);
|
|
expect(secondQuadrantCoordinate[1]).to.roughlyEqual(coordinate[1], 1e-9);
|
|
|
|
// move to third quadrant
|
|
simulateEvent('pointermove', 40, 41);
|
|
event = simulateEvent('pointermove', 40, 40);
|
|
coordinate = event.coordinate;
|
|
const thirdQuadrantCoordinate = draw.sketchFeature_
|
|
.getGeometry()
|
|
.getFirstCoordinate();
|
|
expect(thirdQuadrantCoordinate[0]).to.roughlyEqual(coordinate[0], 1e-9);
|
|
expect(thirdQuadrantCoordinate[1]).to.roughlyEqual(coordinate[1], 1e-9);
|
|
|
|
// move to fourth quadrant
|
|
simulateEvent('pointermove', 79, 40);
|
|
event = simulateEvent('pointermove', 80, 40);
|
|
coordinate = event.coordinate;
|
|
const fourthQuadrantCoordinate = draw.sketchFeature_
|
|
.getGeometry()
|
|
.getFirstCoordinate();
|
|
expect(fourthQuadrantCoordinate[0]).to.roughlyEqual(coordinate[0], 1e-9);
|
|
expect(fourthQuadrantCoordinate[1]).to.roughlyEqual(coordinate[1], 1e-9);
|
|
});
|
|
});
|
|
|
|
describe('createBox', function () {
|
|
it('creates a box-shaped polygon in Circle mode', function () {
|
|
const draw = new Draw({
|
|
source: source,
|
|
type: 'Circle',
|
|
geometryFunction: createBox(),
|
|
});
|
|
map.addInteraction(draw);
|
|
|
|
// first point
|
|
simulateEvent('pointermove', 0, 0);
|
|
simulateEvent('pointerdown', 0, 0);
|
|
simulateEvent('pointerup', 0, 0);
|
|
|
|
// finish on second point
|
|
simulateEvent('pointermove', 20, 20);
|
|
simulateEvent('pointerdown', 20, 20);
|
|
simulateEvent('pointerup', 20, 20);
|
|
|
|
const features = source.getFeatures();
|
|
const geometry = features[0].getGeometry();
|
|
expect(geometry).to.be.a(Polygon);
|
|
const coordinates = geometry.getCoordinates();
|
|
expect(coordinates[0]).to.have.length(5);
|
|
expect(geometry.getArea()).to.equal(400);
|
|
expect(geometry.getExtent()).to.eql([0, -20, 20, 0]);
|
|
});
|
|
|
|
it('creates a box-shaped polygon in Circle mode in a user projection', function () {
|
|
proj4.defs(
|
|
'ESRI:54009',
|
|
'+proj=moll +lon_0=0 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs'
|
|
);
|
|
register(proj4);
|
|
const userProjection = 'ESRI:54009';
|
|
setUserProjection(userProjection);
|
|
|
|
const draw = new Draw({
|
|
source: source,
|
|
type: 'Circle',
|
|
geometryFunction: createBox(),
|
|
});
|
|
map.addInteraction(draw);
|
|
|
|
// first point
|
|
simulateEvent('pointermove', 0, 0);
|
|
simulateEvent('pointerdown', 0, 0);
|
|
simulateEvent('pointerup', 0, 0);
|
|
|
|
// finish on second point
|
|
simulateEvent('pointermove', 20, 20);
|
|
simulateEvent('pointerdown', 20, 20);
|
|
simulateEvent('pointerup', 20, 20);
|
|
|
|
const features = source.getFeatures();
|
|
const geometry = features[0].getGeometry();
|
|
expect(geometry).to.be.a(Polygon);
|
|
const coordinates = geometry.getCoordinates();
|
|
expect(coordinates[0]).to.have.length(5);
|
|
const viewProjection = map.getView().getProjection();
|
|
const area = geometry
|
|
.clone()
|
|
.transform(userProjection, viewProjection)
|
|
.getArea();
|
|
expect(area).to.roughlyEqual(400, 1e-9);
|
|
const extent = geometry
|
|
.clone()
|
|
.transform(userProjection, viewProjection)
|
|
.getExtent();
|
|
expect(extent[0]).to.roughlyEqual(0, 1e-9);
|
|
expect(extent[1]).to.roughlyEqual(-20, 1e-9);
|
|
expect(extent[2]).to.roughlyEqual(20, 1e-9);
|
|
expect(extent[3]).to.roughlyEqual(0, 1e-9);
|
|
});
|
|
});
|
|
|
|
describe('extend an existing feature', function () {
|
|
let draw;
|
|
let feature;
|
|
|
|
beforeEach(function () {
|
|
draw = new Draw({
|
|
source: source,
|
|
type: 'LineString',
|
|
});
|
|
map.addInteraction(draw);
|
|
feature = new Feature(
|
|
new LineString([
|
|
[0, 0],
|
|
[1, 1],
|
|
[2, 0],
|
|
])
|
|
);
|
|
});
|
|
|
|
it('sets the initial state', function () {
|
|
draw.extend(feature);
|
|
expect(draw.sketchCoords_).to.have.length(4);
|
|
expect(draw.sketchCoords_).to.eql([
|
|
[0, 0],
|
|
[1, 1],
|
|
[2, 0],
|
|
[2, 0],
|
|
]);
|
|
expect(draw.finishCoordinate_).to.eql([2, 0]);
|
|
});
|
|
|
|
it('dispatches a drawstart event', function () {
|
|
const spy = sinon.spy();
|
|
listen(draw, 'drawstart', spy);
|
|
draw.extend(feature);
|
|
expect(spy.callCount).to.be(1);
|
|
});
|
|
});
|
|
|
|
describe('append coordinates when drawing a Polygon feature', function () {
|
|
let draw;
|
|
let coordinates;
|
|
let coordinates2;
|
|
|
|
beforeEach(function () {
|
|
draw = new Draw({
|
|
source: source,
|
|
type: 'Polygon',
|
|
});
|
|
map.addInteraction(draw);
|
|
coordinates = [
|
|
[0, 0],
|
|
[1, 1],
|
|
[2, 0],
|
|
[0, 3],
|
|
[3, 2],
|
|
[4, 4],
|
|
];
|
|
coordinates2 = [
|
|
[10, 10],
|
|
[11, 11],
|
|
[12, 10],
|
|
[10, 13],
|
|
[13, 12],
|
|
[14, 14],
|
|
];
|
|
});
|
|
|
|
function isClosed(polygon) {
|
|
const first = polygon.getFirstCoordinate();
|
|
const last = polygon.getLastCoordinate();
|
|
expect(first).to.eql(last);
|
|
}
|
|
|
|
it('draws polygon with clicks, adds coordinates to drawing, finishing on first point', function () {
|
|
// first point
|
|
simulateEvent('pointermove', 10, 20);
|
|
simulateEvent('pointerdown', 10, 20);
|
|
simulateEvent('pointerup', 10, 20);
|
|
isClosed(draw.sketchFeature_.getGeometry());
|
|
|
|
// add coordinates
|
|
draw.appendCoordinates(coordinates);
|
|
|
|
// finish on first point
|
|
simulateEvent('pointermove', 10, 20);
|
|
simulateEvent('pointerdown', 10, 20);
|
|
simulateEvent('pointerup', 10, 20);
|
|
|
|
const features = source.getFeatures();
|
|
expect(features).to.have.length(1);
|
|
const geometry = features[0].getGeometry();
|
|
expect(geometry).to.be.a(Polygon);
|
|
|
|
expect(geometry.getCoordinates()).to.eql([
|
|
[
|
|
[10, -20],
|
|
[0, 0],
|
|
[1, 1],
|
|
[2, 0],
|
|
[0, 3],
|
|
[3, 2],
|
|
[4, 4],
|
|
[10, -20],
|
|
],
|
|
]);
|
|
});
|
|
|
|
it('adds coordinates to empty drawing', function () {
|
|
// first point
|
|
simulateEvent('pointermove', 0, 0);
|
|
simulateEvent('pointerdown', 0, 0);
|
|
simulateEvent('pointerup', 0, 0);
|
|
draw.removeLastPoint();
|
|
draw.appendCoordinates(coordinates);
|
|
isClosed(draw.sketchFeature_.getGeometry());
|
|
|
|
// finish drawing
|
|
simulateEvent('pointerdown', 0, 0);
|
|
simulateEvent('pointerup', 0, 0);
|
|
|
|
const features = source.getFeatures();
|
|
expect(features).to.have.length(1);
|
|
const geometry = features[0].getGeometry();
|
|
expect(geometry).to.be.a(Polygon);
|
|
|
|
expect(geometry.getCoordinates()).to.eql([
|
|
[
|
|
[0, 0],
|
|
[1, 1],
|
|
[2, 0],
|
|
[0, 3],
|
|
[3, 2],
|
|
[4, 4],
|
|
[0, 0],
|
|
],
|
|
]);
|
|
});
|
|
|
|
it('keeps updating the sketch feature after appending coordinates', function () {
|
|
// first point
|
|
simulateEvent('pointermove', 10, 20);
|
|
simulateEvent('pointerdown', 10, 20);
|
|
simulateEvent('pointerup', 10, 20);
|
|
isClosed(draw.sketchFeature_.getGeometry());
|
|
|
|
// add coordinates
|
|
draw.appendCoordinates(coordinates);
|
|
|
|
// add another point
|
|
simulateEvent('pointermove', 30, 20);
|
|
simulateEvent('pointerdown', 30, 20);
|
|
simulateEvent('pointerup', 30, 20);
|
|
|
|
// sketchGeom should have a complete ring, with a double coordinate for cursor
|
|
const sketchGeom = draw.sketchFeature_.getGeometry();
|
|
expect(sketchGeom.getCoordinates()).to.eql([
|
|
[
|
|
[10, -20],
|
|
[0, 0],
|
|
[1, 1],
|
|
[2, 0],
|
|
[0, 3],
|
|
[3, 2],
|
|
[4, 4],
|
|
[30, -20],
|
|
[30, -20],
|
|
[10, -20],
|
|
],
|
|
]);
|
|
});
|
|
|
|
it('keeps updating the sketch feature after multiple appendiges', function () {
|
|
// first point
|
|
simulateEvent('pointermove', 10, 20);
|
|
simulateEvent('pointerdown', 10, 20);
|
|
simulateEvent('pointerup', 10, 20);
|
|
isClosed(draw.sketchFeature_.getGeometry());
|
|
|
|
// add coordinates
|
|
draw.appendCoordinates(coordinates);
|
|
|
|
// another point
|
|
simulateEvent('pointermove', 100, 100);
|
|
simulateEvent('pointerdown', 100, 100);
|
|
simulateEvent('pointerup', 100, 100);
|
|
|
|
// add another array of coordinates
|
|
draw.appendCoordinates(coordinates2);
|
|
|
|
// finish on first point
|
|
simulateEvent('pointermove', 10, 20);
|
|
simulateEvent('pointerdown', 10, 20);
|
|
simulateEvent('pointerup', 10, 20);
|
|
|
|
const features = source.getFeatures();
|
|
expect(features).to.have.length(1);
|
|
const geometry = features[0].getGeometry();
|
|
expect(geometry).to.be.a(Polygon);
|
|
|
|
expect(geometry.getCoordinates()).to.eql([
|
|
[
|
|
[10, -20],
|
|
[0, 0],
|
|
[1, 1],
|
|
[2, 0],
|
|
[0, 3],
|
|
[3, 2],
|
|
[4, 4],
|
|
[100, -100],
|
|
[10, 10],
|
|
[11, 11],
|
|
[12, 10],
|
|
[10, 13],
|
|
[13, 12],
|
|
[14, 14],
|
|
[10, -20],
|
|
],
|
|
]);
|
|
});
|
|
});
|
|
});
|