summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 842c238)
raw | patch | inline | side by side (parent: 842c238)
author | Josh Andler <scislac@gmail.com> | |
Sat, 24 Jul 2010 16:43:29 +0000 (09:43 -0700) | ||
committer | Josh Andler <scislac@gmail.com> | |
Sat, 24 Jul 2010 16:43:29 +0000 (09:43 -0700) |
src/ui/tool/control-point-selection.cpp | patch | blob | history | |
src/ui/tool/control-point-selection.h | patch | blob | history |
index f880d2ddfe2c9faf604f3add7c9588b7d1257951..615587eebb7aaa62bc38277c7978bae2b936ca48 100644 (file)
_grabbed_point = point;
_farthest_point = point;
double maxdist = 0;
+ Geom::Matrix m;
+ m.setIdentity();
for (iterator i = _points.begin(); i != _points.end(); ++i) {
_original_positions.insert(std::make_pair(*i, (*i)->position()));
+ _last_trans.insert(std::make_pair(*i, m));
double dist = Geom::distance(*_grabbed_point, **i);
if (dist > maxdist) {
maxdist = dist;
@@ -288,12 +291,52 @@ void ControlPointSelection::_pointDragged(Geom::Point &new_pos, GdkEventMotion *
Geom::Point abs_delta = new_pos - _original_positions[_grabbed_point];
double fdist = Geom::distance(_original_positions[_grabbed_point], _original_positions[_farthest_point]);
if (held_alt(*event) && fdist > 0) {
- // sculpting
+ // Sculpting
for (iterator i = _points.begin(); i != _points.end(); ++i) {
SelectableControlPoint *cur = (*i);
+ Geom::Matrix trans;
+ trans.setIdentity();
double dist = Geom::distance(_original_positions[cur], _original_positions[_grabbed_point]);
double deltafrac = 0.5 + 0.5 * cos(M_PI * dist/fdist);
- cur->move(_original_positions[cur] + abs_delta * deltafrac);
+ if (dist != 0.0) {
+ // The sculpting transformation is not affine, but it can be
+ // locally approximated by one. Here we compute the local
+ // affine approximation of the sculpting transformation near
+ // the currently transformed point. We then transform the point
+ // by this approximation. This gives us sensible behavior for node handles.
+ // NOTE: probably it would be better to transform the node handles,
+ // but ControlPointSelection is supposed to work for any
+ // SelectableControlPoints, not only Nodes. We could create a specialized
+ // NodeSelection class that inherits from this one and move sculpting there.
+ Geom::Point origdx(Geom::EPSILON, 0);
+ Geom::Point origdy(0, Geom::EPSILON);
+ Geom::Point origp = _original_positions[cur];
+ Geom::Point origpx = _original_positions[cur] + origdx;
+ Geom::Point origpy = _original_positions[cur] + origdy;
+ double distdx = Geom::distance(origpx, _original_positions[_grabbed_point]);
+ double distdy = Geom::distance(origpy, _original_positions[_grabbed_point]);
+ double deltafracdx = 0.5 + 0.5 * cos(M_PI * distdx/fdist);
+ double deltafracdy = 0.5 + 0.5 * cos(M_PI * distdy/fdist);
+ Geom::Point newp = origp + abs_delta * deltafrac;
+ Geom::Point newpx = origpx + abs_delta * deltafracdx;
+ Geom::Point newpy = origpy + abs_delta * deltafracdy;
+ Geom::Point newdx = (newpx - newp) / Geom::EPSILON;
+ Geom::Point newdy = (newpy - newp) / Geom::EPSILON;
+
+ Geom::Matrix itrans(newdx[Geom::X], newdx[Geom::Y], newdy[Geom::X], newdy[Geom::Y], 0, 0);
+ if (itrans.isSingular())
+ itrans.setIdentity();
+
+ trans *= Geom::Translate(-cur->position());
+ trans *= _last_trans[cur].inverse();
+ trans *= itrans;
+ trans *= Geom::Translate(_original_positions[cur] + abs_delta * deltafrac);
+ _last_trans[cur] = itrans;
+ } else {
+ trans *= Geom::Translate(-cur->position() + _original_positions[cur] + abs_delta * deltafrac);
+ }
+ cur->transform(trans);
+ //cur->move(_original_positions[cur] + abs_delta * deltafrac);
}
} else {
Geom::Point delta = new_pos - _grabbed_point->position();
@@ -309,6 +352,7 @@ void ControlPointSelection::_pointDragged(Geom::Point &new_pos, GdkEventMotion *
void ControlPointSelection::_pointUngrabbed()
{
_original_positions.clear();
+ _last_trans.clear();
_dragging = false;
_grabbed_point = _farthest_point = NULL;
_updateBounds();
index 514ecb2e3df13d6eb1940f16ae39def34cde88e2..8023c3e2884825f8eb28942ce110b0fe89c22f31 100644 (file)
/** @file
- * Node selection - stores a set of nodes and applies transformations
+ * Control point selection - stores a set of control points and applies transformations
* to them
*/
/* Authors:
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#ifndef SEEN_UI_TOOL_NODE_SELECTION_H
-#define SEEN_UI_TOOL_NODE_SELECTION_H
+#ifndef SEEN_UI_TOOL_CONTROL_POINT_SELECTION_H
+#define SEEN_UI_TOOL_CONTROL_POINT_SELECTION_H
#include <memory>
#include <boost/optional.hpp>
set_type _points;
set_type _all_points;
INK_UNORDERED_MAP<SelectableControlPoint *, Geom::Point> _original_positions;
+ INK_UNORDERED_MAP<SelectableControlPoint *, Geom::Matrix> _last_trans;
boost::optional<double> _rot_radius;
boost::optional<double> _mouseover_rot_radius;
Geom::OptRect _bounds;