void CurveDragPoint::dragged(Geom::Point &new_pos, GdkEventMotion *event) { NodeList::iterator second = first.next(); // special cancel handling - retract handles when if the segment was degenerate if (_is_drag_cancelled(event) && _segment_was_degenerate) { first->front()->retract(); second->back()->retract(); _pm.update(); return; } if (_drag_initiated && !(event->state & GDK_SHIFT_MASK)) { SnapManager &m = _desktop->namedview->snap_manager; SPItem *path = static_cast<SPItem *>(_pm._path); m.setup(_desktop, true, path); // We will not try to snap to "path" itself Inkscape::SnapCandidatePoint scp(new_pos, Inkscape::SNAPSOURCE_OTHER_HANDLE); Inkscape::SnappedPoint sp = m.freeSnap(scp, Geom::OptRect(), false); new_pos = sp.getPoint(); m.unSetup(); } // Magic Bezier Drag Equations follow! // "weight" describes how the influence of the drag should be distributed // among the handles; 0 = front handle only, 1 = back handle only. double weight, t = _t; if (t <= 1.0 / 6.0) weight = 0; else if (t <= 0.5) weight = (pow((6 * t - 1) / 2.0, 3)) / 2; else if (t <= 5.0 / 6.0) weight = (1 - pow((6 * (1-t) - 1) / 2.0, 3)) / 2 + 0.5; else weight = 1; Geom::Point delta = new_pos - position(); Geom::Point offset0 = ((1-weight)/(3*t*(1-t)*(1-t))) * delta; Geom::Point offset1 = (weight/(3*t*t*(1-t))) * delta; //modified so that, if the trace is bspline, it only acts if the SHIFT key is pressed if(!_pm._isBSpline()){ first->front()->move(first->front()->position() + offset0); second->back()->move(second->back()->position() + offset1); }else if(weight>=0.8){ if(held_shift(*event)){ second->back()->move(new_pos); } else { second->move(second->position() + delta); } }else if(weight<=0.2){ if(held_shift(*event)){ first->back()->move(new_pos); } else { first->move(first->position() + delta); } }else{ first->move(first->position() + delta); second->move(second->position() + delta); } _pm.update(); }
bool CurveDragPoint::grabbed(GdkEventMotion */*event*/) { _pm._selection.hideTransformHandles(); NodeList::iterator second = first.next(); // move the handles to 1/3 the length of the segment for line segments if (first->front()->isDegenerate() && second->back()->isDegenerate()) { _segment_was_degenerate = true; // delta is a vector equal 1/3 of distance from first to second Geom::Point delta = (second->position() - first->position()) / 3.0; // only update the nodes if the mode is bspline if(!_pm._isBSpline()){ first->front()->move(first->front()->position() + delta); second->back()->move(second->back()->position() - delta); } _pm.update(); } else { _segment_was_degenerate = false; } return false; }