Merge pull request #13546 from drnextgis/draw_stride
Add geometryLayout property to Draw interaction
This commit is contained in:
@@ -5,6 +5,7 @@ import Circle from '../geom/Circle.js';
|
|||||||
import Event from '../events/Event.js';
|
import Event from '../events/Event.js';
|
||||||
import EventType from '../events/EventType.js';
|
import EventType from '../events/EventType.js';
|
||||||
import Feature from '../Feature.js';
|
import Feature from '../Feature.js';
|
||||||
|
import GeometryLayout from '../geom/GeometryLayout.js';
|
||||||
import GeometryType from '../geom/GeometryType.js';
|
import GeometryType from '../geom/GeometryType.js';
|
||||||
import InteractionProperty from './Property.js';
|
import InteractionProperty from './Property.js';
|
||||||
import LineString from '../geom/LineString.js';
|
import LineString from '../geom/LineString.js';
|
||||||
@@ -29,6 +30,7 @@ import {
|
|||||||
} from '../extent.js';
|
} from '../extent.js';
|
||||||
import {createEditingStyle} from '../style/Style.js';
|
import {createEditingStyle} from '../style/Style.js';
|
||||||
import {fromUserCoordinate, getUserProjection} from '../proj.js';
|
import {fromUserCoordinate, getUserProjection} from '../proj.js';
|
||||||
|
import {getStrideForLayout} from '../geom/SimpleGeometry.js';
|
||||||
import {squaredDistance as squaredCoordinateDistance} from '../coordinate.js';
|
import {squaredDistance as squaredCoordinateDistance} from '../coordinate.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -82,6 +84,8 @@ import {squaredDistance as squaredCoordinateDistance} from '../coordinate.js';
|
|||||||
* Shift key activates freehand drawing.
|
* Shift key activates freehand drawing.
|
||||||
* @property {boolean} [wrapX=false] Wrap the world horizontally on the sketch
|
* @property {boolean} [wrapX=false] Wrap the world horizontally on the sketch
|
||||||
* overlay.
|
* overlay.
|
||||||
|
* @property {GeometryLayout} [geometryLayout='XY'] Layout of the
|
||||||
|
* feature geometries created by the draw interaction.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -335,6 +339,14 @@ class Draw extends PointerInteraction {
|
|||||||
? options.finishCondition
|
? options.finishCondition
|
||||||
: TRUE;
|
: TRUE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @type {import("../geom/GeometryLayout").default}
|
||||||
|
*/
|
||||||
|
this.geometryLayout_ = options.geometryLayout
|
||||||
|
? options.geometryLayout
|
||||||
|
: GeometryLayout.XY;
|
||||||
|
|
||||||
let geometryFunction = options.geometryFunction;
|
let geometryFunction = options.geometryFunction;
|
||||||
if (!geometryFunction) {
|
if (!geometryFunction) {
|
||||||
const mode = this.mode_;
|
const mode = this.mode_;
|
||||||
@@ -354,7 +366,11 @@ class Draw extends PointerInteraction {
|
|||||||
center,
|
center,
|
||||||
fromUserCoordinate(coordinates[coordinates.length - 1], projection)
|
fromUserCoordinate(coordinates[coordinates.length - 1], projection)
|
||||||
);
|
);
|
||||||
circle.setCenterAndRadius(center, Math.sqrt(squaredLength));
|
circle.setCenterAndRadius(
|
||||||
|
center,
|
||||||
|
Math.sqrt(squaredLength),
|
||||||
|
this.geometryLayout_
|
||||||
|
);
|
||||||
const userProjection = getUserProjection();
|
const userProjection = getUserProjection();
|
||||||
if (userProjection) {
|
if (userProjection) {
|
||||||
circle.transform(projection, userProjection);
|
circle.transform(projection, userProjection);
|
||||||
@@ -381,17 +397,18 @@ class Draw extends PointerInteraction {
|
|||||||
if (mode === Mode.POLYGON) {
|
if (mode === Mode.POLYGON) {
|
||||||
if (coordinates[0].length) {
|
if (coordinates[0].length) {
|
||||||
// Add a closing coordinate to match the first
|
// Add a closing coordinate to match the first
|
||||||
geometry.setCoordinates([
|
geometry.setCoordinates(
|
||||||
coordinates[0].concat([coordinates[0][0]]),
|
[coordinates[0].concat([coordinates[0][0]])],
|
||||||
]);
|
this.geometryLayout_
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
geometry.setCoordinates([]);
|
geometry.setCoordinates([], this.geometryLayout_);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
geometry.setCoordinates(coordinates);
|
geometry.setCoordinates(coordinates, this.geometryLayout_);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
geometry = new Constructor(coordinates);
|
geometry = new Constructor(coordinates, this.geometryLayout_);
|
||||||
}
|
}
|
||||||
return geometry;
|
return geometry;
|
||||||
};
|
};
|
||||||
@@ -803,6 +820,10 @@ class Draw extends PointerInteraction {
|
|||||||
*/
|
*/
|
||||||
startDrawing_(start) {
|
startDrawing_(start) {
|
||||||
const projection = this.getMap().getView().getProjection();
|
const projection = this.getMap().getView().getProjection();
|
||||||
|
const stride = getStrideForLayout(this.geometryLayout_);
|
||||||
|
while (start.length < stride) {
|
||||||
|
start.push(0);
|
||||||
|
}
|
||||||
this.finishCoordinate_ = start;
|
this.finishCoordinate_ = start;
|
||||||
if (this.mode_ === Mode.POINT) {
|
if (this.mode_ === Mode.POINT) {
|
||||||
this.sketchCoords_ = start.slice();
|
this.sketchCoords_ = start.slice();
|
||||||
@@ -840,7 +861,11 @@ class Draw extends PointerInteraction {
|
|||||||
const map = this.getMap();
|
const map = this.getMap();
|
||||||
const geometry = this.sketchFeature_.getGeometry();
|
const geometry = this.sketchFeature_.getGeometry();
|
||||||
const projection = map.getView().getProjection();
|
const projection = map.getView().getProjection();
|
||||||
|
const stride = getStrideForLayout(this.geometryLayout_);
|
||||||
let coordinates, last;
|
let coordinates, last;
|
||||||
|
while (coordinate.length < stride) {
|
||||||
|
coordinate.push(0);
|
||||||
|
}
|
||||||
if (this.mode_ === Mode.POINT) {
|
if (this.mode_ === Mode.POINT) {
|
||||||
last = this.sketchCoords_;
|
last = this.sketchCoords_;
|
||||||
} else if (this.mode_ === Mode.POLYGON) {
|
} else if (this.mode_ === Mode.POLYGON) {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import Draw, {
|
|||||||
createRegularPolygon,
|
createRegularPolygon,
|
||||||
} from '../../../../../src/ol/interaction/Draw.js';
|
} from '../../../../../src/ol/interaction/Draw.js';
|
||||||
import Feature from '../../../../../src/ol/Feature.js';
|
import Feature from '../../../../../src/ol/Feature.js';
|
||||||
|
import GeometryLayout from '../../../../../src/ol/geom/GeometryLayout.js';
|
||||||
import GeometryType from '../../../../../src/ol/geom/GeometryType.js';
|
import GeometryType from '../../../../../src/ol/geom/GeometryType.js';
|
||||||
import Interaction from '../../../../../src/ol/interaction/Interaction.js';
|
import Interaction from '../../../../../src/ol/interaction/Interaction.js';
|
||||||
import LineString from '../../../../../src/ol/geom/LineString.js';
|
import LineString from '../../../../../src/ol/geom/LineString.js';
|
||||||
@@ -162,6 +163,15 @@ describe('ol.interaction.Draw', function () {
|
|||||||
unByKey(clickKey);
|
unByKey(clickKey);
|
||||||
//}, 300);
|
//}, 300);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('accepts a geometryLayout option', function () {
|
||||||
|
const draw = new Draw({
|
||||||
|
source: source,
|
||||||
|
type: 'Point',
|
||||||
|
geometryLayout: 'XYZ',
|
||||||
|
});
|
||||||
|
expect(draw.geometryLayout_).to.be('XYZ');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('specifying a geometryName', function () {
|
describe('specifying a geometryName', function () {
|
||||||
@@ -1946,4 +1956,247 @@ describe('ol.interaction.Draw', function () {
|
|||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('drawing with geometryLayout', function () {
|
||||||
|
let draw;
|
||||||
|
function createDrawInteraction(type, geometryLayout) {
|
||||||
|
draw = new Draw({
|
||||||
|
source: source,
|
||||||
|
type: type,
|
||||||
|
geometryLayout: geometryLayout,
|
||||||
|
});
|
||||||
|
map.addInteraction(draw);
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawPoint(geometryLayout) {
|
||||||
|
createDrawInteraction(GeometryType.POINT, geometryLayout);
|
||||||
|
simulateEvent('pointermove', 10, 20);
|
||||||
|
simulateEvent('pointerdown', 10, 20);
|
||||||
|
simulateEvent('pointerup', 10, 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawLineString(geometryLayout) {
|
||||||
|
createDrawInteraction(GeometryType.LINE_STRING, geometryLayout);
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawPolygon(geometryLayout) {
|
||||||
|
createDrawInteraction(GeometryType.POLYGON, geometryLayout);
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawCircle(geometryLayout) {
|
||||||
|
createDrawInteraction(GeometryType.CIRCLE, geometryLayout);
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
it('respects XY layout for POINT type', function () {
|
||||||
|
drawPoint(GeometryLayout.XY);
|
||||||
|
const features = source.getFeatures();
|
||||||
|
const geometry = features[0].getGeometry();
|
||||||
|
expect(geometry.getCoordinates()).to.eql([10, -20]);
|
||||||
|
expect(geometry.getLayout()).to.eql(GeometryLayout.XY);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('respects XYZ layout for POINT type', function () {
|
||||||
|
drawPoint(GeometryLayout.XYZ);
|
||||||
|
const features = source.getFeatures();
|
||||||
|
const geometry = features[0].getGeometry();
|
||||||
|
expect(geometry.getCoordinates()).to.eql([10, -20, 0]);
|
||||||
|
expect(geometry.getLayout()).to.eql(GeometryLayout.XYZ);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('respects XYM layout for POINT type', function () {
|
||||||
|
drawPoint(GeometryLayout.XYM);
|
||||||
|
const features = source.getFeatures();
|
||||||
|
const geometry = features[0].getGeometry();
|
||||||
|
expect(geometry.getCoordinates()).to.eql([10, -20, 0]);
|
||||||
|
expect(geometry.getLayout()).to.eql(GeometryLayout.XYM);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('respects XYZM layout for POINT type', function () {
|
||||||
|
drawPoint(GeometryLayout.XYZM);
|
||||||
|
const features = source.getFeatures();
|
||||||
|
const geometry = features[0].getGeometry();
|
||||||
|
expect(geometry.getCoordinates()).to.eql([10, -20, 0, 0]);
|
||||||
|
expect(geometry.getLayout()).to.eql(GeometryLayout.XYZM);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('respects XY layout for LINESTRING type', function () {
|
||||||
|
drawLineString(GeometryLayout.XY);
|
||||||
|
const features = source.getFeatures();
|
||||||
|
const geometry = features[0].getGeometry();
|
||||||
|
expect(geometry.getCoordinates()).to.eql([
|
||||||
|
[10, -20],
|
||||||
|
[30, -20],
|
||||||
|
]);
|
||||||
|
expect(geometry.getLayout()).to.eql(GeometryLayout.XY);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('respects XYZ layout for LINESTRING type', function () {
|
||||||
|
drawLineString(GeometryLayout.XYZ);
|
||||||
|
const features = source.getFeatures();
|
||||||
|
const geometry = features[0].getGeometry();
|
||||||
|
expect(geometry.getCoordinates()).to.eql([
|
||||||
|
[10, -20, 0],
|
||||||
|
[30, -20, 0],
|
||||||
|
]);
|
||||||
|
expect(geometry.getLayout()).to.eql(GeometryLayout.XYZ);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('respects XYM layout for LINESTRING type', function () {
|
||||||
|
drawLineString(GeometryLayout.XYM);
|
||||||
|
const features = source.getFeatures();
|
||||||
|
const geometry = features[0].getGeometry();
|
||||||
|
expect(geometry.getCoordinates()).to.eql([
|
||||||
|
[10, -20, 0],
|
||||||
|
[30, -20, 0],
|
||||||
|
]);
|
||||||
|
expect(geometry.getLayout()).to.eql(GeometryLayout.XYM);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('respects XYZM layout for LINESTRING type', function () {
|
||||||
|
drawLineString(GeometryLayout.XYZM);
|
||||||
|
const features = source.getFeatures();
|
||||||
|
const geometry = features[0].getGeometry();
|
||||||
|
expect(geometry.getCoordinates()).to.eql([
|
||||||
|
[10, -20, 0, 0],
|
||||||
|
[30, -20, 0, 0],
|
||||||
|
]);
|
||||||
|
expect(geometry.getLayout()).to.eql(GeometryLayout.XYZM);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('respects XY layout for POLYGON type', function () {
|
||||||
|
drawPolygon(GeometryLayout.XY);
|
||||||
|
const features = source.getFeatures();
|
||||||
|
const geometry = features[0].getGeometry();
|
||||||
|
expect(geometry.getCoordinates()).to.eql([
|
||||||
|
[
|
||||||
|
[10, -20],
|
||||||
|
[30, -20],
|
||||||
|
[40, -10],
|
||||||
|
[10, -20],
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
expect(geometry.getLayout()).to.eql(GeometryLayout.XY);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('respects XYZ layout for POLYGON type', function () {
|
||||||
|
drawPolygon(GeometryLayout.XYZ);
|
||||||
|
const features = source.getFeatures();
|
||||||
|
const geometry = features[0].getGeometry();
|
||||||
|
expect(geometry.getCoordinates()).to.eql([
|
||||||
|
[
|
||||||
|
[10, -20, 0],
|
||||||
|
[30, -20, 0],
|
||||||
|
[40, -10, 0],
|
||||||
|
[10, -20, 0],
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
expect(geometry.getLayout()).to.eql(GeometryLayout.XYZ);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('respects XYM layout for POLYGON type', function () {
|
||||||
|
drawPolygon(GeometryLayout.XYM);
|
||||||
|
const features = source.getFeatures();
|
||||||
|
const geometry = features[0].getGeometry();
|
||||||
|
expect(geometry.getCoordinates()).to.eql([
|
||||||
|
[
|
||||||
|
[10, -20, 0],
|
||||||
|
[30, -20, 0],
|
||||||
|
[40, -10, 0],
|
||||||
|
[10, -20, 0],
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
expect(geometry.getLayout()).to.eql(GeometryLayout.XYM);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('respects XYZM layout for POLYGON type', function () {
|
||||||
|
drawPolygon(GeometryLayout.XYZM);
|
||||||
|
const features = source.getFeatures();
|
||||||
|
const geometry = features[0].getGeometry();
|
||||||
|
expect(geometry.getCoordinates()).to.eql([
|
||||||
|
[
|
||||||
|
[10, -20, 0, 0],
|
||||||
|
[30, -20, 0, 0],
|
||||||
|
[40, -10, 0, 0],
|
||||||
|
[10, -20, 0, 0],
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
expect(geometry.getLayout()).to.eql(GeometryLayout.XYZM);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('respects XY layout for CIRCLE type', function () {
|
||||||
|
drawCircle(GeometryLayout.XY);
|
||||||
|
const features = source.getFeatures();
|
||||||
|
const geometry = features[0].getGeometry();
|
||||||
|
expect(geometry.getCenter()).to.eql([10, -20]);
|
||||||
|
expect(geometry.getRadius()).to.eql(20);
|
||||||
|
expect(geometry.getLayout()).to.eql(GeometryLayout.XY);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('respects XYZ layout for CIRCLE type', function () {
|
||||||
|
drawCircle(GeometryLayout.XYZ);
|
||||||
|
const features = source.getFeatures();
|
||||||
|
const geometry = features[0].getGeometry();
|
||||||
|
expect(geometry.getCenter()).to.eql([10, -20, 0]);
|
||||||
|
expect(geometry.getRadius()).to.eql(20);
|
||||||
|
expect(geometry.getLayout()).to.eql(GeometryLayout.XYZ);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('respects XYM layout for CIRCLE type', function () {
|
||||||
|
drawCircle(GeometryLayout.XYM);
|
||||||
|
const features = source.getFeatures();
|
||||||
|
const geometry = features[0].getGeometry();
|
||||||
|
expect(geometry.getCenter()).to.eql([10, -20, 0]);
|
||||||
|
expect(geometry.getRadius()).to.eql(20);
|
||||||
|
expect(geometry.getLayout()).to.eql(GeometryLayout.XYM);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('respects XYZM layout for CIRCLE type', function () {
|
||||||
|
drawCircle(GeometryLayout.XYZM);
|
||||||
|
const features = source.getFeatures();
|
||||||
|
const geometry = features[0].getGeometry();
|
||||||
|
expect(geometry.getCenter()).to.eql([10, -20, 0, 0]);
|
||||||
|
expect(geometry.getRadius()).to.eql(20);
|
||||||
|
expect(geometry.getLayout()).to.eql(GeometryLayout.XYZM);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user