Added option to link curved segment control points in pathedit mode

git-svn-id: http://svg-edit.googlecode.com/svn/trunk@985 eee81c28-f429-11dd-99c0-75d572ba1ddd
This commit is contained in:
Alexis Deveria
2009-12-01 19:26:33 +00:00
parent 7cbb5ebddc
commit 5173ad7eea
4 changed files with 126 additions and 45 deletions

View File

@@ -533,6 +533,16 @@
</svg>
</g>
<g id="link_controls">
<svg viewBox="0 0 24 24" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg">
<path fill="none" stroke="#8dd35f" d="m12.4375,22.75c-4.75,-12.625 -0.375,-14.375 10.375,-11.5" id="svg_102"/>
<line x1="4" y1="19" x2="19" y2="4" id="svg_109" stroke="#606060" fill="none"/>
<circle cx="11.5" cy="11.5" r="2.17578" id="svg_111" fill="#00ffff" stroke="#0000ff"/>
<circle cx="19" cy="4" r="2.26172" fill="#00ffff" stroke="#0000ff" id="svg_121" stroke-width="0.5"/>
<circle cx="4" cy="19" r="2.26172" fill="#00ffff" stroke="#0000ff" stroke-width="0.5" id="svg_123"/>
</svg>
</g>
<g id="reorient">
<svg viewBox="0 0 24 24" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg">
<defs>

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 44 KiB

View File

@@ -232,6 +232,9 @@ script type="text/javascript" src="locale/locale.min.js"></script-->
</div>
<div id="path_node_panel">
<div class="tool_sep"></div>
<div class="tool_button" id="tool_node_link" title="Link Control Points"></div>
<div class="tool_sep"></div>
<label class="path_node_tool">x:</label>
<input id="path_node_x" class="path_node_tool attr_changer" title="Change node's x coordinate" size="3" data-attr="x"/>
<label class="path_node_tool">y:</label>

View File

@@ -364,8 +364,10 @@ function svg_edit_setup() {
// Get BBox vals for g, polyline and path
if($.inArray(elname, ['g', 'polyline', 'path']) != -1) {
var bb = svgCanvas.getStrokedBBox([elem]);
x = bb.x;
y = bb.y;
if(bb) {
x = bb.x;
y = bb.y;
}
} else {
x = elem.getAttribute('x');
y = elem.getAttribute('y');
@@ -900,6 +902,12 @@ function svg_edit_setup() {
}
};
var linkControlPoints = function() {
$('#tool_node_link').toggleClass('push_button_pressed');
var linked = $('#tool_node_link').hasClass('push_button_pressed');
svgCanvas.linkControlPoints(linked);
}
var clonePathNode = function() {
if (svgCanvas.getNodePoint()) {
svgCanvas.clonePathNode();
@@ -1012,7 +1020,7 @@ function svg_edit_setup() {
}
var clickWireframe = function() {
$('#tool_wireframe').toggleClass('push_button_pressed');
$('#tool_wireframe').toggleClass('push_button_pressed');
$('#workarea').toggleClass('wireframe');
if(supportsNonSS) return;
@@ -1380,6 +1388,7 @@ function svg_edit_setup() {
$('#tool_delete').click(deleteSelected);
$('#tool_delete_multi').click(deleteSelected);
$('#tool_reorient').click(reorientPath);
$('#tool_node_link').click(linkControlPoints);
$('#tool_node_clone').click(clonePathNode);
$('#tool_node_delete').click(deletePathNode);
$('#tool_move_top').click(moveToTopSelected);
@@ -2208,6 +2217,7 @@ function setSVGIcons() {
'#tool_move_top':'move_top',
'#tool_move_bottom':'move_bottom',
'#tool_topath':'to_path',
'#tool_node_link':'link_controls',
'#tool_reorient':'reorient',
'#tool_group':'group',
'#tool_ungroup':'ungroup',

View File

@@ -861,6 +861,7 @@ function BatchCommand(text) {
var current_path_pt_drag = -1;
var current_path_oldd = null;
var current_ctrl_pt_drag = -1;
var link_control_pts = false;
var current_zoom = 1;
// this will hold all the currently selected elements
// default size of 1 until it needs to grow bigger
@@ -1928,7 +1929,7 @@ function BatchCommand(text) {
// Currently only one node can be selected at a time, should allow more later
// Should point be the index or the grip element?
var is_closed = current_path.getAttribute('d').toLowerCase().indexOf('z') != -1;
var is_closed = pathIsClosed();
if(is_closed && point == current_path_pts.length/2 - 1) {
current_path_pt = 0;
@@ -2647,40 +2648,39 @@ function BatchCommand(text) {
} else if (current_ctrl_pt_drag != -1 && current_path) {
// Moving the control point. Since only one segment is altered,
// we only need to do a pathSegList replace.
var data = current_ctrl_pt_drag.split('c');
var index = data[0]-0;
var ctrl_num = data[1]-0;
var c_item = current_path.pathSegList.getItem(index+1);
var angle = canvas.getRotationAngle(current_path) * Math.PI / 180.0;
if (angle) {
// calculate the shape's old center that was used for rotation
var box = selectedBBoxes[0];
var cx = round(box.x + box.width/2) * current_zoom,
cy = round(box.y + box.height/2) * current_zoom;
var dx = mouse_x - cx, dy = mouse_y - cy;
var r = Math.sqrt( dx*dx + dy*dy );
var theta = Math.atan2(dy,dx) - angle;
current_path_pts[i] = mouse_x = cx + r * Math.cos(theta);
current_path_pts[i+1] = mouse_y = cy + r * Math.sin(theta);
x = mouse_x / current_zoom;
y = mouse_y / current_zoom;
}
c_item['x' + ctrl_num] = x;
c_item['y' + ctrl_num] = y;
replacePathSeg(6, index+1, [c_item.x,c_item.y, c_item.x1,c_item.y1, c_item.x2,c_item.y2]);
updateSegLine(true);
var grip = document.getElementById("ctrlpointgrip_" + current_ctrl_pt_drag);
if(grip) {
grip.setAttribute("cx", mouse_x);
grip.setAttribute("cy", mouse_y);
var pt_index;
var pt_count = current_path_pts.length/2;
updateCurvedSegment(mouse_x, mouse_y, index, ctrl_num);
if(link_control_pts) {
var is_closed = pathIsClosed();
if(ctrl_num == 1) {
ctrl_num = 2;
index--;
pt_index = index+1;
if(index < 0) {
index = pt_count - 2;
if(!is_closed) break;
}
} else {
ctrl_num = 1;
index++;
pt_index = index;
if(index >= pt_count - 1) {
index = 0;
if(!is_closed) break;
}
}
var line = document.getElementById("ctrlLine_"+current_ctrl_pt_drag);
line.setAttribute("x2", mouse_x);
line.setAttribute("y2", mouse_y);
var pt = getPathPoint(pt_index, true);
var new_x = pt[0] - (mouse_x - pt[0]);
var new_y = pt[1] - (mouse_y - pt[1]);
updateCurvedSegment(new_x, new_y, index, ctrl_num, true);
}
}
break;
@@ -3203,6 +3203,11 @@ function BatchCommand(text) {
});
};
var pathIsClosed = function() {
if(!current_path) return;
return current_path.getAttribute('d').substr(-1,1).toLowerCase() == 'z';
}
var updateSegLine = function(next_node) {
// create segment line
var segLine = document.getElementById("segline");
@@ -3247,7 +3252,7 @@ function BatchCommand(text) {
var x = mouse_x / current_zoom;
var y = mouse_y / current_zoom;
var is_closed = current_path.getAttribute('d').toLowerCase().indexOf('z') != -1;
var is_closed = pathIsClosed();
var i = current_path_pt_drag * 2;
var last_index = current_path_pts.length/2 - 1;
@@ -3257,7 +3262,7 @@ function BatchCommand(text) {
// if the image is rotated, then we must modify the x,y mouse coordinates
// and rotate them into the shape's rotated coordinate system
// we also re-map mouse_x/y and x/y into the rotated coordinate system
var angle = canvas.getRotationAngle(current_path) * Math.PI / 180.0;
var angle = canvas.getRotationAngle(current_path, true);
if (angle) {
// calculate the shape's old center that was used for rotation
var box = selectedBBoxes[0];
@@ -3392,6 +3397,55 @@ function BatchCommand(text) {
}
}
var updateCurvedSegment = function(mouse_x, mouse_y, index, ctrl_num) {
var list = current_path.pathSegList;
if(index+1 >= list.numberOfItems) {
index = -1;
}
var c_item = list.getItem(index+1);
// Only do curves
if(c_item.pathSegType != 6) return;
ctrl_pt_drag = index + 'c' + ctrl_num;
var x = mouse_x / current_zoom;
var y = mouse_y / current_zoom;
var angle = canvas.getRotationAngle(current_path, true);
// TODO: Make sure this works for linked control points
if (angle) {
// calculate the shape's old center that was used for rotation
var box = selectedBBoxes[0];
var cx = round(box.x + box.width/2) * current_zoom,
cy = round(box.y + box.height/2) * current_zoom;
var dx = mouse_x - cx, dy = mouse_y - cy;
var r = Math.sqrt( dx*dx + dy*dy );
var theta = Math.atan2(dy,dx) - angle;
mouse_x = cx + r * Math.cos(theta);
mouse_y = cy + r * Math.sin(theta);
x = mouse_x / current_zoom;
y = mouse_y / current_zoom;
}
c_item['x' + ctrl_num] = x;
c_item['y' + ctrl_num] = y;
replacePathSeg(6, index+1, [c_item.x,c_item.y, c_item.x1,c_item.y1, c_item.x2,c_item.y2]);
updateSegLine(true);
var grip = document.getElementById("ctrlpointgrip_" + ctrl_pt_drag);
if(grip) {
grip.setAttribute("cx", mouse_x);
grip.setAttribute("cy", mouse_y);
var line = document.getElementById("ctrlLine_"+ctrl_pt_drag);
line.setAttribute("x2", mouse_x);
line.setAttribute("y2", mouse_y);
}
}
var getPathPoint = function(index, raw_val) {
var len = current_path_pts.length;
var pt_num = len/2;
@@ -3791,7 +3845,7 @@ function BatchCommand(text) {
// Every path point must be rotated into the rotated coordinate system of
// its old center, then determine the new center, then rotate it back
// This is because we want the path to remember its rotation
var angle = canvas.getRotationAngle(current_path) * Math.PI / 180.0;
var angle = canvas.getRotationAngle(current_path, true);
if (angle) {
var box = canvas.getBBox(current_path);
@@ -3875,7 +3929,7 @@ function BatchCommand(text) {
call("changed", [current_path]);
// If connected, last point should equal first
if(current_path.getAttribute('d').toLowerCase().indexOf('z') != -1) {
if(pathIsClosed()) {
current_path_pts[current_path_pts.length-2] = getPathPoint(0,true)[0];
current_path_pts[current_path_pts.length-1] = getPathPoint(0,true)[1];
}
@@ -4556,6 +4610,10 @@ function BatchCommand(text) {
}
}
this.linkControlPoints = function(linkPoints) {
link_control_pts = linkPoints;
}
this.clonePathNode = function() {
var pt = current_path_pt, list = current_path.pathSegList;
@@ -5045,7 +5103,7 @@ function BatchCommand(text) {
};
// TODO: do we need to sum up all rotation angles?
this.getRotationAngle = function(elem) {
this.getRotationAngle = function(elem, to_rad) {
var selected = elem || selectedElements[0];
// find the rotation transform (if any) and set it
var tlist = canvas.getTransformList(selected);
@@ -5053,7 +5111,7 @@ function BatchCommand(text) {
while (t--) {
var xform = tlist.getItem(t);
if (xform.type == 4) {
return xform.angle;
return to_rad ? xform.angle * Math.PI / 180.0 : xform.angle;
}
}
return 0;
@@ -5206,7 +5264,7 @@ function BatchCommand(text) {
var index = grip[0].id.split('_')[1] - 0;
var last_index = current_path_pts.length/2 - 1;
var is_closed = current_path.getAttribute('d').toLowerCase().indexOf('z') != -1;
var is_closed = pathIsClosed();
if(!is_closed && index == last_index) {
return; // Last point of unclosed path should do nothing
@@ -5346,10 +5404,10 @@ function BatchCommand(text) {
// var box=canvas.getBBox(elem), left=box.x, top=box.y, width=box.width,
// height=box.height, dx = width - old_w, dy=0;
// var angle = canvas.getRotationAngle(elem);
// var angle = canvas.getRotationAngle(elem, true);
// if (angle) {
// var r = Math.sqrt( dx*dx + dy*dy );
// var theta = Math.atan2(dy,dx) - angle * Math.PI / 180.0;
// var theta = Math.atan2(dy,dx) - angle;
// dx = r * Math.cos(theta);
// dy = r * Math.sin(theta);
//
@@ -5497,7 +5555,7 @@ function BatchCommand(text) {
var gbox = g.getBBox(),
gx = gbox.x + gbox.width/2,
gy = gbox.y + gbox.height/2;
var gangle = canvas.getRotationAngle(g) * Math.PI / 180.0;
var gangle = canvas.getRotationAngle(g, true);
while (g.firstChild) {
var elem = g.firstChild;
var oldNextSibling = elem.nextSibling;
@@ -5519,7 +5577,7 @@ function BatchCommand(text) {
// now we add the angle that the element was rotated by
// if it's non-zero, we need to set the new transform
// otherwise, we clear it
var angle = gangle + canvas.getRotationAngle(elem) * Math.PI / 180.0;
var angle = gangle + canvas.getRotationAngle(elem, true);
var changes = {};
changes["transform"] = elem.getAttribute("transform");
if (angle != 0) {