index df27c2a72ad1929b3654d042e235493919d85e51..517e90da22d5e6a6e5bcaca6c6237e7011c1f227 100644 (file)
}
}
-void ControlPointSelection::_pointGrabbed()
+void ControlPointSelection::_pointGrabbed(SelectableControlPoint *point)
{
hideTransformHandles();
_dragging = true;
+ _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;
+ _farthest_point = *i;
+ }
+ }
}
-void ControlPointSelection::_pointDragged(Geom::Point const &old_pos, Geom::Point &new_pos,
- GdkEventMotion */*event*/)
-{
- Geom::Point delta = new_pos - old_pos;
- for (iterator i = _points.begin(); i != _points.end(); ++i) {
- SelectableControlPoint *cur = (*i);
- cur->move(cur->position() + delta);
+void ControlPointSelection::_pointDragged(Geom::Point &new_pos, GdkEventMotion *event)
+{
+ Geom::Point abs_delta = new_pos - _original_positions[_grabbed_point];
+ double fdist = Geom::distance(_original_positions[_grabbed_point], _original_positions[_farthest_point]);
+ if (held_only_alt(*event) && fdist > 0) {
+ // 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);
+ 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();
+ for (iterator i = _points.begin(); i != _points.end(); ++i) {
+ SelectableControlPoint *cur = (*i);
+ cur->move(_original_positions[cur] + abs_delta);
+ }
+ _handles->rotationCenter().move(_handles->rotationCenter().position() + delta);
}
- _handles->rotationCenter().move(_handles->rotationCenter().position() + delta);
signal_update.emit();
}
void ControlPointSelection::_pointUngrabbed()
{
+ _original_positions.clear();
+ _last_trans.clear();
_dragging = false;
- _grabbed_point = NULL;
+ _grabbed_point = _farthest_point = NULL;
_updateBounds();
restoreTransformHandles();
signal_commit.emit(COMMIT_MOUSE_MOVE);
return false;
}
+std::vector<Inkscape::SnapCandidatePoint> ControlPointSelection::getOriginalPoints()
+{
+ std::vector<Inkscape::SnapCandidatePoint> points;
+ for (iterator i = _points.begin(); i != _points.end(); ++i) {
+ points.push_back(Inkscape::SnapCandidatePoint(_original_positions[*i], SNAPSOURCE_NODE_HANDLE));
+ }
+ return points;
+}
+
+void ControlPointSelection::setOriginalPoints()
+{
+ _original_positions.clear();
+ for (iterator i = _points.begin(); i != _points.end(); ++i) {
+ _original_positions.insert(std::make_pair(*i, (*i)->position()));
+ }
+}
+
+
} // namespace UI
} // namespace Inkscape
fill-column:99
End:
*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :