mirror of
https://github.com/FoggedLens/iD.git
synced 2026-05-15 05:30:35 +02:00
Refactor rotation code to geoRotate, add tests
This commit is contained in:
@@ -6,7 +6,8 @@ import {
|
||||
|
||||
import {
|
||||
geoEuclideanDistance,
|
||||
geoExtent
|
||||
geoExtent,
|
||||
geoRotate
|
||||
} from '../geo';
|
||||
|
||||
|
||||
@@ -14,15 +15,6 @@ import {
|
||||
export function actionReflect(wayId, projection) {
|
||||
var useLongAxis = true;
|
||||
|
||||
function rotatePolygon(polygon, angle, centroid) {
|
||||
return polygon.map(function(point) {
|
||||
var radial = [point[0] - centroid[0], point[1] - centroid[1]];
|
||||
return [
|
||||
radial[0] * Math.cos(angle) - radial[1] * Math.sin(angle) + centroid[0],
|
||||
radial[0] * Math.sin(angle) + radial[1] * Math.cos(angle) + centroid[1]
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
// http://gis.stackexchange.com/questions/22895/finding-minimum-area-rectangle-for-given-points
|
||||
// http://gis.stackexchange.com/questions/3739/generalisation-strategies-for-building-outlines/3756#3756
|
||||
@@ -39,7 +31,7 @@ export function actionReflect(wayId, projection) {
|
||||
for (var i = 0; i < hull.length - 1; i++) {
|
||||
var c2 = hull[i + 1],
|
||||
angle = Math.atan2(c2[1] - c1[1], c2[0] - c1[0]),
|
||||
poly = rotatePolygon(hull, -angle, centroid),
|
||||
poly = geoRotate(hull, -angle, centroid),
|
||||
extent = poly.reduce(function(extent, point) {
|
||||
return extent.extend(geoExtent(point));
|
||||
}, geoExtent()),
|
||||
@@ -54,7 +46,7 @@ export function actionReflect(wayId, projection) {
|
||||
}
|
||||
|
||||
return {
|
||||
poly: rotatePolygon(ssrExtent.polygon(), ssrAngle, centroid),
|
||||
poly: geoRotate(ssrExtent.polygon(), ssrAngle, centroid),
|
||||
angle: ssrAngle
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,29 +1,19 @@
|
||||
import _ from 'lodash';
|
||||
import { geoRotate } from '../geo';
|
||||
|
||||
|
||||
export function actionRotate(wayId, pivot, angle, projection) {
|
||||
return function(graph) {
|
||||
var action = function(graph) {
|
||||
return graph.update(function(graph) {
|
||||
var way = graph.entity(wayId);
|
||||
|
||||
_.uniq(way.nodes).forEach(function(id) {
|
||||
|
||||
var node = graph.entity(id),
|
||||
point = projection(node.loc),
|
||||
radial = [0,0];
|
||||
|
||||
radial[0] = point[0] - pivot[0];
|
||||
radial[1] = point[1] - pivot[1];
|
||||
|
||||
point = [
|
||||
radial[0] * Math.cos(angle) - radial[1] * Math.sin(angle) + pivot[0],
|
||||
radial[0] * Math.sin(angle) + radial[1] * Math.cos(angle) + pivot[1]
|
||||
];
|
||||
point = geoRotate([projection(node.loc)], angle, pivot)[0];
|
||||
|
||||
graph = graph.replace(node.move(projection.invert(point)));
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
return action;
|
||||
}
|
||||
|
||||
@@ -104,6 +104,18 @@ export function geoAngle(a, b, projection) {
|
||||
}
|
||||
|
||||
|
||||
// Rotate all points counterclockwise around a pivot point by given angle
|
||||
export function geoRotate(points, angle, around) {
|
||||
return points.map(function(point) {
|
||||
var radial = [point[0] - around[0], point[1] - around[1]];
|
||||
return [
|
||||
radial[0] * Math.cos(angle) - radial[1] * Math.sin(angle) + around[0],
|
||||
radial[0] * Math.sin(angle) + radial[1] * Math.cos(angle) + around[1]
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// Choose the edge with the minimal distance from `point` to its orthogonal
|
||||
// projection onto that edge, if such a projection exists, or the distance to
|
||||
// the closest vertex on that edge. Returns an object with the `index` of the
|
||||
|
||||
@@ -7,6 +7,7 @@ export { geoExtent } from './extent.js';
|
||||
export { geoInterp } from './geo.js';
|
||||
export { geoRawMercator } from './raw_mercator.js';
|
||||
export { geoRoundCoords } from './geo.js';
|
||||
export { geoRotate } from './geo.js';
|
||||
export { geoLatToMeters } from './geo.js';
|
||||
export { geoLineIntersection } from './geo.js';
|
||||
export { geoLonToMeters } from './geo.js';
|
||||
|
||||
@@ -185,6 +185,54 @@ describe('iD.geo', function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('geoEdgeEqual', function() {
|
||||
it('returns false for inequal edges', function() {
|
||||
expect(iD.geoEdgeEqual(['a','b'], ['a','c'])).to.be.false;
|
||||
});
|
||||
|
||||
it('returns true for equal edges along same direction', function() {
|
||||
expect(iD.geoEdgeEqual(['a','b'], ['a','b'])).to.be.true;
|
||||
});
|
||||
|
||||
it('returns true for equal edges along opposite direction', function() {
|
||||
expect(iD.geoEdgeEqual(['a','b'], ['b','a'])).to.be.true;
|
||||
});
|
||||
});
|
||||
|
||||
describe('geoAngle', function() {
|
||||
it('returns angle between a and b', function() {
|
||||
var projection = function (_) { return _; };
|
||||
expect(iD.geoAngle({loc:[0, 0]}, {loc:[1, 0]}, projection)).to.be.closeTo(0, 1e-6);
|
||||
expect(iD.geoAngle({loc:[0, 0]}, {loc:[0, 1]}, projection)).to.be.closeTo(Math.PI / 2, 1e-6);
|
||||
expect(iD.geoAngle({loc:[0, 0]}, {loc:[-1, 0]}, projection)).to.be.closeTo(Math.PI, 1e-6);
|
||||
expect(iD.geoAngle({loc:[0, 0]}, {loc:[0, -1]}, projection)).to.be.closeTo(-Math.PI / 2, 1e-6);
|
||||
});
|
||||
});
|
||||
|
||||
describe('geoRotate', function() {
|
||||
it('rotates points around [0, 0]', function() {
|
||||
var points = [[5, 0], [5, 1]],
|
||||
angle = Math.PI,
|
||||
around = [0, 0],
|
||||
result = iD.geoRotate(points, angle, around);
|
||||
expect(result[0][0]).to.be.closeTo(-5, 1e-6);
|
||||
expect(result[0][1]).to.be.closeTo(0, 1e-6);
|
||||
expect(result[1][0]).to.be.closeTo(-5, 1e-6);
|
||||
expect(result[1][1]).to.be.closeTo(-1, 1e-6);
|
||||
});
|
||||
|
||||
it('rotates points around [3, 0]', function() {
|
||||
var points = [[5, 0], [5, 1]],
|
||||
angle = Math.PI,
|
||||
around = [3, 0],
|
||||
result = iD.geoRotate(points, angle, around);
|
||||
expect(result[0][0]).to.be.closeTo(1, 1e-6);
|
||||
expect(result[0][1]).to.be.closeTo(0, 1e-6);
|
||||
expect(result[1][0]).to.be.closeTo(1, 1e-6);
|
||||
expect(result[1][1]).to.be.closeTo(-1, 1e-6);
|
||||
});
|
||||
});
|
||||
|
||||
describe('geoChooseEdge', function() {
|
||||
var projection = function (l) { return l; };
|
||||
projection.invert = projection;
|
||||
|
||||
Reference in New Issue
Block a user