mirror of
https://github.com/FoggedLens/iD.git
synced 2026-05-20 23:44:47 +02:00
Add rotate shape operation (addresses #838)
This commit is contained in:
@@ -108,6 +108,7 @@
|
||||
<script src='js/id/actions/merge.js'></script>
|
||||
<script src='js/id/actions/move_node.js'></script>
|
||||
<script src='js/id/actions/move_way.js'></script>
|
||||
<script src='js/id/actions/rotate_way.js'></script>
|
||||
<script src='js/id/actions/circularize.js'></script>
|
||||
<script src='js/id/actions/orthogonalize.js'></script>
|
||||
<script src='js/id/actions/noop.js'></script>
|
||||
@@ -133,6 +134,7 @@
|
||||
<script src='js/id/modes/draw_area.js'></script>
|
||||
<script src='js/id/modes/draw_line.js'></script>
|
||||
<script src='js/id/modes/move.js'></script>
|
||||
<script src='js/id/modes/rotate_way.js'></script>
|
||||
<script src='js/id/modes/select.js'></script>
|
||||
|
||||
<script src='js/id/operations.js'></script>
|
||||
@@ -142,6 +144,7 @@
|
||||
<script src='js/id/operations/disconnect.js'></script>
|
||||
<script src='js/id/operations/merge.js'></script>
|
||||
<script src='js/id/operations/move.js'></script>
|
||||
<script src='js/id/operations/rotate.js'></script>
|
||||
<script src='js/id/operations/reverse.js'></script>
|
||||
<script src='js/id/operations/split.js'></script>
|
||||
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
iD.actions.RotateWay = function(wayId, ref_points, pivot, mousePoint, projection) {
|
||||
return function(graph) {
|
||||
return graph.update(function(graph) {
|
||||
var way = graph.entity(wayId),
|
||||
nodes = _.uniq(graph.childNodes(way)),
|
||||
angle, i, points;
|
||||
|
||||
points = deepCopy(ref_points);
|
||||
|
||||
angle = Math.atan2(mousePoint[1] - pivot[1], mousePoint[0] - pivot[0]);
|
||||
|
||||
for (i = 0; i < points.length; i++) {
|
||||
var radial = [0,0];
|
||||
|
||||
radial[0] = points[i][0] - pivot[0];
|
||||
radial[1] = points[i][1] - pivot[1];
|
||||
|
||||
points[i][0] = radial[0] * Math.cos(angle) - radial[1] * Math.sin(angle) + pivot[0];
|
||||
points[i][1] = radial[0] * Math.sin(angle) + radial[1] * Math.cos(angle) + pivot[1];
|
||||
|
||||
}
|
||||
|
||||
for (i = 0; i < points.length; i++) {
|
||||
graph = graph.replace(graph.entity(nodes[i].id).move(projection.invert(points[i])));
|
||||
}
|
||||
|
||||
function deepCopy(o) {
|
||||
var copy = o,k;
|
||||
if (o && typeof o === 'object') {
|
||||
copy = Object.prototype.toString.call(o) === '[object Array]' ? [] : {};
|
||||
for (k in o) {
|
||||
copy[k] = deepCopy(o[k]);
|
||||
}
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
});
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,74 @@
|
||||
iD.modes.RotateWay = function(context, wayId) {
|
||||
var mode = {
|
||||
id: 'rotate-way',
|
||||
button: 'browse'
|
||||
};
|
||||
|
||||
var keybinding = d3.keybinding('rotate-way');
|
||||
|
||||
mode.enter = function() {
|
||||
|
||||
var annotation = t('operations.rotate.annotation.' + context.geometry(wayId)),
|
||||
way = context.graph().entity(wayId),
|
||||
nodes = _.uniq(context.graph().childNodes(way)),
|
||||
ref_points = nodes.map(function(n) { return context.projection(n.loc); }),
|
||||
pivot = d3.geom.polygon(ref_points).centroid();
|
||||
|
||||
context.perform(
|
||||
iD.actions.Noop(),
|
||||
annotation);
|
||||
|
||||
function point() {
|
||||
return d3.mouse(context.map().surface.node());
|
||||
}
|
||||
|
||||
function rotate() {
|
||||
var mousePoint = point();
|
||||
|
||||
context.replace(
|
||||
iD.actions.RotateWay(wayId, ref_points, pivot, mousePoint, context.projection),
|
||||
annotation);
|
||||
}
|
||||
|
||||
function finish() {
|
||||
d3.event.stopPropagation();
|
||||
context.enter(iD.modes.Select(context, [wayId], true));
|
||||
}
|
||||
|
||||
function cancel() {
|
||||
context.pop();
|
||||
context.enter(iD.modes.Select(context, [wayId], true));
|
||||
}
|
||||
|
||||
function undone() {
|
||||
context.enter(iD.modes.Browse(context));
|
||||
}
|
||||
|
||||
context.surface()
|
||||
.on('mousemove.rotate-way', rotate)
|
||||
.on('click.rotate-way', finish);
|
||||
|
||||
context.history()
|
||||
.on('undone.rotate-way', undone);
|
||||
|
||||
keybinding
|
||||
.on('⎋', cancel)
|
||||
.on('↩', finish);
|
||||
|
||||
d3.select(document)
|
||||
.call(keybinding);
|
||||
};
|
||||
|
||||
mode.exit = function() {
|
||||
context.surface()
|
||||
.on('mousemove.rotate-way', null)
|
||||
.on('click.rotate-way', null);
|
||||
|
||||
context.history()
|
||||
.on('undone.rotate-way', null);
|
||||
|
||||
keybinding.off();
|
||||
};
|
||||
|
||||
return mode;
|
||||
};
|
||||
@@ -0,0 +1,24 @@
|
||||
iD.operations.Rotate = function(selection, context) {
|
||||
var entityId = selection[0];
|
||||
|
||||
var operation = function() {
|
||||
context.enter(iD.modes.RotateWay(context, entityId));
|
||||
};
|
||||
|
||||
operation.available = function() {
|
||||
return selection.length === 1 &&
|
||||
context.entity(entityId).type === 'way' &&
|
||||
context.entity(entityId).isClosed();
|
||||
};
|
||||
|
||||
operation.enabled = function() {
|
||||
return true;
|
||||
};
|
||||
|
||||
operation.id = "rotate";
|
||||
operation.key = t('operations.rotate.key');
|
||||
operation.title = t('operations.rotate.title');
|
||||
operation.description = t('operations.rotate.description');
|
||||
|
||||
return operation;
|
||||
};
|
||||
@@ -115,6 +115,15 @@ locale.en = {
|
||||
multiple: "Moved multiple objects"
|
||||
}
|
||||
},
|
||||
rotate: {
|
||||
title: "Rotate",
|
||||
description: "Rotate this object around its centre point.",
|
||||
key: "R",
|
||||
annotation: {
|
||||
line: "Rotated a line.",
|
||||
area: "Rotated an area."
|
||||
}
|
||||
},
|
||||
reverse: {
|
||||
title: "Reverse",
|
||||
description: "Make this line go in the opposite direction.",
|
||||
|
||||
Reference in New Issue
Block a user