25#include <glibmm/timer.h>
52 snapprefs(preferences),
56 distribution(this, 0),
58 _rotation_center_source_items(
std::vector<
SPItem*>()),
61 _unselected_nodes(nullptr)
82 s.splice(s.begin(),
gs);
93 s.push_back(grid->snapper());
112 SnapperList::const_iterator i = s.begin();
113 while (i != s.end() && (*i)->ThisSnapperMightSnap() ==
false) {
117 return (i != s.end());
127 SnapperList::const_iterator i = s.begin();
128 while (i != s.end() && (*i)->ThisSnapperMightSnap() ==
false) {
132 return (i != s.end());
145 bool to_paths_only)
const
154 for (
auto snapper : snappers) {
158 return findBestSnap(p, isr,
false,
false, to_paths_only);
185 bool success =
false;
203 Geom::Point const t_offset = t + grid->getOrigin();
216 nearest_multiple = s.
getPoint() - grid->getOrigin();
218 bestSnappedPoint = s;
226 return nearest_multiple;
265 if (
result.getSnapped()) {
279 for (
auto snapper : snappers) {
286 if (
result.getSnapped()) {
307 std::vector<Inkscape::Snapper::SnapConstraint>
const &constraints,
313 if (constraints.size() == 0) {
321 std::vector<Geom::Point> projections;
322 for (
const auto & constraint : constraints) {
326 projections.push_back(pp);
330 no_snap.
setPoint(projections.front());
333 std::vector<Inkscape::Snapper::SnapConstraint>::const_iterator
c = constraints.begin();
334 std::vector<Geom::Point>::iterator pp = projections.begin();
335 for (; pp != projections.end(); ++pp) {
350 bool snap_mouse = prefs->
getBool(
"/options/snapmousepointer/value",
false);
363 for (
auto snapper : snappers) {
373 std::optional<Geom::Point>
const &p_ref,
375 unsigned const snaps)
const
384 double angle_incr = M_PI / snaps;
385 double angle_offset = 0;
390 double angle_ceil = round_to_upper_multiple_plus(angle, angle_incr, angle_offset);
391 double angle_floor = round_to_lower_multiple_plus(angle, angle_incr, angle_offset);
395 std::vector<Inkscape::Snapper::SnapConstraint> constraints;
396 constraints.emplace_back(
Geom::Line(o, angle_ceil - M_PI/2));
397 constraints.emplace_back(
Geom::Line(o, angle_floor - M_PI/2));
410 if (freeze_angle &&
origin) {
411 g_warning(
"Dear developer, when snapping guides you shouldn't ask me to freeze the guide's vector when you haven't specified one");
429 for (SnapperList::const_iterator i = snappers.begin(); i != snappers.end(); ++i) {
430 (*i)->freeSnap(isr, candidate,
Geom::OptRect(),
nullptr,
nullptr);
457 for (SnapperList::const_iterator i = snappers.begin(); i != snappers.end(); ++i) {
458 (*i)->constrainedSnap(isr, candidate,
Geom::OptRect(), cl,
nullptr,
nullptr);
466 std::vector<Inkscape::SnapCandidatePoint>
const &points,
476 if (points.size() == 0) {
487 transform.
snap(
this, points, pointer);
500 if (points.size() == 1) {
509 bool to_path_only)
const
539 std::list<Inkscape::SnappedPoint> sp_list;
544 sp_list.push_back(closestPoint);
553 sp_list.emplace_back(closestCurve);
562 sp_list.emplace_back(closestGridLine);
569 sp_list.emplace_back(closestGuideLine);
584 sp_list.push_back(closestCurvesIntersection);
593 sp_list.push_back(closestCurveGuideIntersection);
602 sp_list.push_back(closestGridPoint);
610 sp_list.push_back(closestGuidePoint);
619 sp_list.push_back(closestGridGuidePoint);
635 for (std::list<Inkscape::SnappedPoint>::const_iterator i = sp_list.begin(); i != sp_list.end(); ++i) {
638 if (onScreen || allowOffScreen) {
639 if ((*i).getAlwaysSnap() || (*i).getSnapDistance() <= (*i).getTolerance()) {
643 bestSnappedPoint = *i;
660 return bestSnappedPoint;
666 std::vector<Inkscape::SnapCandidatePoint> *unselected_nodes)
670 g_warning(
"The snapmanager has been set up before, but unSetup() hasn't been called afterwards. It possibly held invalid pointers");
673 if (item_to_ignore) {
685 std::vector<SPObject const *> &objects_to_ignore,
686 std::vector<Inkscape::SnapCandidatePoint> *unselected_nodes)
690 g_warning(
"The snapmanager has been set up before, but unSetup() hasn't been called afterwards. It possibly held invalid pointers");
703 std::vector<Inkscape::SnapCandidatePoint> *unselected_nodes)
708 g_warning(
"The snapmanager has been set up before, but unSetup() hasn't been called afterwards. It possibly held invalid pointers");
719 for (
auto i=
items.begin();i!=
items.end();++i) {
783 if (prefs->
getBool(
"/options/snapclosestonly/value")) {
810 if (
auto page = cast<SPPage>(
item)) {
819 std::vector<SPObject const *>
const *it,
821 bool const clip_or_mask,
826 g_error(
"desktop == NULL, so we cannot snap; please inform the developers of this bug");
831 static int recursion_level = 0;
833 if (recursion_level == 0) {
844 bbox_to_snap_incl.
expandBy(
object.getSnapperTolerance());
846 for (
auto& o:
parent->children) {
847 auto item = cast<SPItem>(&o);
853 if (filt && filt->
getId() && strcmp(filt->
getId(),
"selectable_hidder_filter") == 0) {
856 auto lpeitem = cast<SPLPEItem>(
item);
863 for (
auto skipitem : *it) {
864 if (skipitem && skipitem->style) {
865 auto toskip = cast<SPItem>(
const_cast<SPObject *
>(skipitem));
868 if (filt && filt->
getId() && strcmp(filt->
getId(),
"selectable_hidder_filter") == 0) {
873 auto lpeitem = cast<SPLPEItem>(toskip);
874 if (!stop && lpeitem &&
889 std::vector<SPObject const *>::const_iterator i;
892 while (i != it->end() && *i != &o) {
897 if (it ==
nullptr || i == it->end()) {
913 if (is<SPGroup>(
item)) {
914 _findCandidates(&o, it, bbox_to_snap, clip_or_mask, additional_affine);
918 int prefs_bbox = prefs->
getBool(
"/tools/bounding_box",
false);
932 bool overflow =
false;
935 if (display_area.intersects(*bbox_of_item)) {
942 if (bbox_to_snap_incl.
intersects(*bbox_of_item)
957 static Glib::Timer timer;
958 if (timer.elapsed() > 1.0) {
960 std::cerr <<
"Warning: limit of 200 snap target paths reached, some will be ignored" << std::endl;
3x3 matrix representing an affine transformation.
bool contains(GenericRect< C > const &r) const
Check whether the rectangle includes all points in the given rectangle.
bool intersects(GenericRect< C > const &r) const
Check whether the rectangles have any common points.
void expandBy(C amount)
Expand the rectangle in both directions by the specified amount.
Infinite line on a plane.
Axis-aligned rectangle that can be empty.
Rect bounds() const
Axis-aligned bounding box.
bool contains(Point const &) const
Two-dimensional point that doubles as a vector.
Axis aligned, non-empty rectangle.
void set_new_snapsource(Inkscape::SnapCandidatePoint const &p)
void remove_snaptarget(bool only_if_presnap=false)
void set_new_snaptarget(Inkscape::SnappedPoint const &p, bool pre_snap=false)
SPItemRange items()
Returns a range of selected SPItems.
Preference storage class.
bool getBool(Glib::ustring const &pref_path, bool def=false)
Retrieve a Boolean value.
static Preferences * get()
Access the singleton Preferences object.
The set of selected SPObjects for a given document and layer model.
Class to store data for points which are snap candidates, either as a source or as a target.
Inkscape::SnapSourceType getSourceType() const
Geom::Point const & getPoint() const
bool isSingleHandle() const
void addOrigin(Geom::Point pt)
long getSourceNum() const
void addVector(Geom::Point v)
Storing of snapping preferences.
bool getSnapPostponedGlobally() const
bool getSnapEnabledGlobally() const
bool isTargetSnappable(Inkscape::SnapTargetType const target) const
Class describing the result of an attempt to snap to a curve.
Class describing the result of an attempt to snap to a line.
Class describing the result of an attempt to snap.
void setPoint(Geom::Point const &p)
void getPointIfSnapped(Geom::Point &p) const
void setSource(SnapSourceType const source)
Geom::Point getPoint() const
Geom::Coord getSnapDistance() const
Geom::Point getTangent() const
void setTarget(SnapTargetType const target)
bool isOtherSnapBetter(SnappedPoint const &other_one, bool weighted) const
Geom::Point projection(Geom::Point const &p) const
Parent for classes that can snap points to something.
virtual bool ThisSnapperMightSnap() const
virtual void freeSnap(IntermSnapResults &, Inkscape::SnapCandidatePoint const &, Geom::OptRect const &, std::vector< SPObject const * > const *, std::vector< SnapCandidatePoint > *) const
To do: update description of desktop.
Geom::Parallelogram get_display_area() const
Return canvas viewbox in desktop coordinates.
bool itemIsHidden(SPItem const *item) const
Geom::Affine const & dt2doc() const
Inkscape::Display::SnapIndicator * getSnapIndicator() const
SPNamedView * getNamedView() const
Inkscape::Selection * getSelection() const
Geom::Affine const & doc2dt() const
Typed SVG document implementation.
Geom::Point getNormal() const
Geom::Point getPoint() const
Base class for visual SVG elements.
Geom::OptRect bounds(BBoxType type, Geom::Affine const &transform=Geom::identity()) const
Geom::OptRect desktopBounds(BBoxType type) const
Geom::Point getCenter(bool ensure_uptodate=true) const
SPMask * getMaskObject() const
Geom::Affine i2doc_affine() const
Returns the accumulated transformation of the item and all its ancestors, including root's viewport.
SPClipPath * getClipObject() const
std::vector< SPGrid * > grids
SPObject is an abstract base class of all of the document nodes at the SVG document level.
char const * getId() const
Returns the objects current ID string.
SPStyle * style
Represents the style properties, whether from presentation attributes, the style attribute,...
SPDesktop const * _desktop
SnapperList getGridSnappers() const
Return a list of gridsnappers.
void guideConstrainedSnap(Geom::Point &p, SPGuide const &guideline) const
Wrapper method to make snapping of the guide origin a bit easier (i.e.
bool _findCandidates_already_called
void displaySnapsource(Inkscape::SnapCandidatePoint const &p) const
Mark the location of the snap source (not the snap target!) on the canvas by drawing a symbol.
std::vector< SPItem * > _rotation_center_source_items
std::unique_ptr< std::vector< Inkscape::SnapCandidateItem > > _obj_snapper_candidates
void constrainedSnapReturnByRef(Geom::Point &p, Inkscape::SnapSourceType const source_type, Inkscape::Snapper::SnapConstraint const &constraint, Geom::OptRect const &bbox_to_snap=Geom::OptRect()) const
Try to snap a point along a constraint line to grids, guides or objects.
void setup(SPDesktop const *desktop, bool snapindicator=true, SPObject const *item_to_ignore=nullptr, std::vector< Inkscape::SnapCandidatePoint > *unselected_nodes=nullptr)
Convenience shortcut when there is only one item to ignore.
void _findCandidates(SPObject *parent, std::vector< SPObject const * > const *it, Geom::Rect const &bbox_to_snap, bool const _clip_or_mask, Geom::Affine const additional_affine)
Find all items within snapping range.
std::unique_ptr< std::vector< Inkscape::SnapCandidateItem > > _align_snapper_candidates
Inkscape::AlignmentSnapper alignment
snapper to align with other objects
void guideFreeSnap(Geom::Point &p, Geom::Point &origin_or_vector, bool origin, bool freeze_angle) const
Wrapper method to make snapping of the guide origin a bit easier (i.e.
Geom::Point multipleOfGridPitch(Geom::Point const &t, Geom::Point const &origin)
Snap to the closest multiple of a grid pitch.
SPGuide const * getGuideToIgnore() const
std::vector< SPObject const * > _objects_to_ignore
Items that should not be snapped to, for example the items that are currently being dragged....
void setupIgnoreSelection(SPDesktop const *desktop, bool snapindicator=true, std::vector< Inkscape::SnapCandidatePoint > *unselected_nodes=nullptr)
Setup, taking the list of items to ignore from the desktop's selection.
Inkscape::SnappedPoint findBestSnap(Inkscape::SnapCandidatePoint const &p, IntermSnapResults const &isr, bool constrained, bool allowOffScreen=false, bool to_paths_only=false) const
Given a set of possible snap targets, find the best target (which is not necessarily also the nearest...
bool gridSnapperMightSnap() const
void freeSnapReturnByRef(Geom::Point &p, Inkscape::SnapSourceType const source_type, Geom::OptRect const &bbox_to_snap=Geom::OptRect()) const
Try to snap a point to grids, guides or objects.
std::list< const Inkscape::Snapper * > SnapperList
void preSnap(Inkscape::SnapCandidatePoint const &p, bool to_path_only=false)
SPDocument * getDocument() const
Inkscape::SnappedPoint constrainedSnap(Inkscape::SnapCandidatePoint const &p, Inkscape::Snapper::SnapConstraint const &constraint, Geom::OptRect const &bbox_to_snap=Geom::OptRect()) const
Try to snap a point along a constraint line to grids, guides or objects.
SnapManager(SPNamedView const *v, Inkscape::SnapPreferences &preferences)
Construct a SnapManager for a SPNamedView.
bool _snapindicator
When true, an indicator will be drawn at the position that was being snapped to.
Inkscape::SnappedPoint constrainedAngularSnap(Inkscape::SnapCandidatePoint const &p, std::optional< Geom::Point > const &p_ref, Geom::Point const &o, unsigned const snaps) const
Try to snap a point to something at a specific angle.
Inkscape::DistributionSnapper distribution
SnapperList getSnappers() const
Return a list of snappers.
void snapTransformed(std::vector< Inkscape::SnapCandidatePoint > const &points, Geom::Point const &pointer, Inkscape::PureTransform &transform)
Method for snapping sets of points while they are being transformed.
Inkscape::SnappedPoint multipleConstrainedSnaps(Inkscape::SnapCandidatePoint const &p, std::vector< Inkscape::Snapper::SnapConstraint > const &constraints, bool dont_snap=false, Geom::OptRect const &bbox_to_snap=Geom::OptRect()) const
Inkscape::SnapPreferences & snapprefs
SPPage const * getPageToIgnore() const
SPNamedView const * _named_view
Inkscape::GuideSnapper guide
guide snapper
Inkscape::SnappedPoint freeSnap(Inkscape::SnapCandidatePoint const &p, Geom::OptRect const &bbox_to_snap=Geom::OptRect(), bool to_path_only=false) const
Try to snap a point to grids, guides or objects.
bool someSnapperMightSnap(bool immediately=true) const
Return true if any snapping might occur, whether its to grids, guides or objects.
SPDesktop const * getDesktop() const
std::vector< Inkscape::SnapCandidatePoint > * _unselected_nodes
Nodes of the path that is currently being edited and which have not been selected and which will ther...
Editable view implementation.
static char const *const parent
constexpr Coord infinity()
Get a value representing infinity.
double Coord
Floating point type used to store coordinates.
double angle_between(Line const &l1, Line const &l2)
SBasis L2(D2< SBasis > const &a, unsigned k)
bool are_near(Affine const &a1, Affine const &a2, Coord eps=EPSILON)
D2< T > rot90(D2< T > const &a)
double round_to_upper_multiple_plus(double x, double const c1, double const c0=0)
double round_to_lower_multiple_plus(double x, double c1, double c0=0.0)
SnapSourceType
enumerations of snap source types and snap target types.
@ SNAPSOURCE_OTHERS_CATEGORY
@ SNAPSOURCE_DATUMS_CATEGORY
@ SNAPSOURCE_GUIDE_ORIGIN
@ SNAPSOURCE_NODE_CATEGORY
@ SNAPSOURCE_BBOX_CATEGORY
@ SNAPTARGET_PATH_GUIDE_INTERSECTION
@ SNAPTARGET_ROTATION_CENTER
@ SNAPTARGET_GRID_INTERSECTION
@ SNAPTARGET_NODE_CATEGORY
@ SNAPTARGET_GRID_GUIDE_INTERSECTION
@ SNAPTARGET_GUIDE_INTERSECTION
@ SNAPTARGET_PATH_INTERSECTION
@ SNAPTARGET_BBOX_CATEGORY
@ SNAPTARGET_CONSTRAINED_ANGLE
Singleton class to access the preferences file in a convenient way.
Provides a class that shows a temporary indicator on the canvas of where the snap was,...
bool getClosestIntersectionCS(std::list< Inkscape::SnappedCurve > const &list, Geom::Point const &p, Inkscape::SnappedPoint &result, Geom::Affine dt2doc)
bool getClosestIntersectionCL(std::list< Inkscape::SnappedCurve > const &curve_list, std::list< Inkscape::SnappedLine > const &line_list, Geom::Point const &p, Inkscape::SnappedPoint &result, Geom::Affine dt2doc)
bool getClosestCurve(std::list< Inkscape::SnappedCurve > const &list, Inkscape::SnappedCurve &result, bool exclude_paths, bool paths_only)
bool getClosestSL(std::list< Inkscape::SnappedLine > const &list, Inkscape::SnappedLine &result)
bool getClosestIntersectionSL(std::list< Inkscape::SnappedLine > const &list, Inkscape::SnappedPoint &result)
bool getClosestSP(std::list< Inkscape::SnappedPoint > const &list, Inkscape::SnappedPoint &result)
std::list< Inkscape::SnappedCurve > curves
std::list< Inkscape::SnappedLine > grid_lines
std::list< Inkscape::SnappedPoint > points
std::list< Inkscape::SnappedLine > guide_lines
SPStyle - a style object for SPItem objects.