Skip to content

Commit

Permalink
Merge pull request #1205 from OpenGeoscience/fixed-size-annotations
Browse files Browse the repository at this point in the history
perf: Fixed size annotations.
  • Loading branch information
manthey authored May 13, 2022
2 parents 610139f + be5f125 commit 819c5c8
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 12 deletions.
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
# GeoJS Change Log

## Version 1.8.6

### Improvements

- Allow constraining rectangle and ellipse annotations to a list of fixed sizes ([#1205](../../pull/1205))

## Version 1.8.5

### Improvements

-Optimize reordering fetch queue ([#1203](../../pull/1203))
- Optimize reordering fetch queue ([#1203](../../pull/1203))

## Version 1.8.4

Expand Down
38 changes: 27 additions & 11 deletions src/annotation/annotation.js
Original file line number Diff line number Diff line change
Expand Up @@ -1266,10 +1266,12 @@ function continuousVerticesProcessAction(m_this, evt, name) {
* that the aspect ratio of a rectangle-like selection is a specific value or
* range of values.
*
* @param {number|number[]} ratio Either a single aspect ratio or a list of
* allowed aspect ratios. For instance, 1 will require that the selection
* square, 2 would require that it is twice as wide as tall, [2, 1/2] would
* allow it to be twice as wide or half as wide as it is tall.
* @param {number|number[]|geo.geoSize|geo.geoSize[]} ratio Either a single
* aspect ratio, a single size, or a list of allowed aspect ratios and sizes.
* For instance, 1 will require that the selection square, 2 would require
* that it is twice as wide as tall, [2, 1/2] would allow it to be twice as
* wide or half as wide as it is tall. Sizes (e.g., {width: 400, height:
* 500}) snap to that size.
* @returns {function} A function that can be passed to the mapIterator
* selectionConstraint or to an annotation constraint function.
*/
Expand Down Expand Up @@ -1315,16 +1317,23 @@ function constrainAspectRatio(ratio) {
const area = Math.abs(dist1 * dist3);
let shape, edge;
ratios.forEach((ratio) => {
if (ratio !== 1 && !(index % 2)) {
ratio = 1.0 / ratio;
let width, height;
if (ratio.width) {
width = ratio.width;
height = ratio.height;
} else {
width = (area * ratio) ** 0.5;
height = width / ratio;
}
const width = (area * ratio) ** 0.5;
const score = (width - dist3) ** 2 + (width / ratio - dist1) ** 2;
if (width !== height && !(index % 2)) {
[width, height] = [height, width];
}
const score = (width - dist3) ** 2 + (height - dist1) ** 2;
if (best === undefined || score < best) {
best = score;
shape = {
w: width,
h: width / ratio
h: height
};
}
});
Expand Down Expand Up @@ -1366,10 +1375,17 @@ function constrainAspectRatio(ratio) {
/* Not in edit vertex or edge mode */
const area = Math.abs((pos.x - origin.x) * (pos.y - origin.y));
ratios.forEach((ratio) => {
const width = (area * ratio) ** 0.5;
let width, height;
if (ratio.width) {
width = ratio.width;
height = ratio.height;
} else {
width = (area * ratio) ** 0.5;
height = width / ratio;
}
const adjusted = {
x: origin.x + Math.sign(pos.x - origin.x) * width,
y: origin.y + Math.sign(pos.y - origin.y) * width / ratio
y: origin.y + Math.sign(pos.y - origin.y) * height
};
const score = (adjusted.x - pos.x) ** 2 + (adjusted.y - pos.y) ** 2;
if (best === undefined || score < best) {
Expand Down
9 changes: 9 additions & 0 deletions src/typedef.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,15 @@
* @property {number} [z=0] Altitude coordinate, often zero.
*/

/**
* Represention of a size in gcs coordinates.
*
* @typedef geo.geoSize
* @type {object}
* @property {number} width Width in gcs coordinates.
* @property {number} height Height in gcs coordinates.
*/

/**
* Represention of a size in pixels.
*
Expand Down
65 changes: 65 additions & 0 deletions tests/cases/annotation.js
Original file line number Diff line number Diff line change
Expand Up @@ -1583,6 +1583,71 @@ describe('geo.annotation', function () {
});
});

describe('contrainAspectRatio', function () {
it('ratio', function () {
const func = geo.annotation.constrainAspectRatio([2, 0.5]);

let result;
result = func(
{x: 40, y: 5},
{x: 0, y: 0});
expect(result.pos).toEqual({x: 20, y: 10});
result = func(
{x: 40, y: 5},
{x: 0, y: 0},
[{x: 0, y: 0}, {x: 10, y: 0}, {x: 10, y: 10}, {x: 0, y: 10}]);
expect(result.pos).toEqual({x: 20, y: 10});
result = func(
{x: 5, y: 40},
{x: 0, y: 0},
[{x: 0, y: 0}, {x: 10, y: 0}, {x: 10, y: 10}, {x: 0, y: 10}]);
expect(result.pos).toEqual({x: 10, y: 20});
result = func(
{x: 0, y: 0},
{x: 0, y: 0},
[{x: -10, y: 5}, {x: 30, y: 5}, {x: 30, y: 10}, {x: -10, y: 10}],
'edge', [0, -Math.PI / 2, Math.PI, Math.PI / 2], 0);
expect(result.corners).toEqual([{x: 20, y: 20}, {x: 0, y: 20}, {x: 0, y: 10}, {x: 20, y: 10}]);
result = func(
{x: 0, y: 0},
{x: 0, y: 0},
[{x: -10, y: 5}, {x: 30, y: 5}, {x: 30, y: 10}, {x: -10, y: 10}],
'vertex', [0, -Math.PI / 2, Math.PI, Math.PI / 2], 0);
expect(result.corners).toEqual([{x: 10, y: 20}, {x: 30, y: 20}, {x: 30, y: 10}, {x: 10, y: 10}]);
});
it('fixed size', function () {
const func = geo.annotation.constrainAspectRatio({width: 20, height: 10});

let result;
result = func(
{x: 40, y: 5},
{x: 0, y: 0});
expect(result.pos).toEqual({x: 20, y: 10});
result = func(
{x: 40, y: 5},
{x: 0, y: 0},
[{x: 0, y: 0}, {x: 10, y: 0}, {x: 10, y: 10}, {x: 0, y: 10}]);
expect(result.pos).toEqual({x: 20, y: 10});
result = func(
{x: 5, y: 40},
{x: 0, y: 0},
[{x: 0, y: 0}, {x: 10, y: 0}, {x: 10, y: 10}, {x: 0, y: 10}]);
expect(result.pos).toEqual({x: 20, y: 10});
result = func(
{x: 0, y: 0},
{x: 0, y: 0},
[{x: -10, y: 5}, {x: 30, y: 5}, {x: 30, y: 10}, {x: -10, y: 10}],
'edge', [0, -Math.PI / 2, Math.PI, Math.PI / 2], 0);
expect(result.corners).toEqual([{x: 20, y: 20}, {x: 0, y: 20}, {x: 0, y: 10}, {x: 20, y: 10}]);
result = func(
{x: 0, y: 0},
{x: 0, y: 0},
[{x: -10, y: 5}, {x: 30, y: 5}, {x: 30, y: 10}, {x: -10, y: 10}],
'vertex', [0, -Math.PI / 2, Math.PI, Math.PI / 2], 0);
expect(result.corners).toEqual([{x: 10, y: 20}, {x: 30, y: 20}, {x: 30, y: 10}, {x: 10, y: 10}]);
});
});

describe('annotation registry', function () {
var newshapeCount = 0;
it('listAnnotations', function () {
Expand Down

0 comments on commit 819c5c8

Please sign in to comment.