~valavanisalex/ubuntu/oneiric/inkscape/inkscape_0.48.1-2ubuntu4

« back to all changes in this revision

Viewing changes to src/snapped-point.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Kees Cook, Ted Gould, Kees Cook
  • Date: 2009-06-24 14:00:43 UTC
  • mfrom: (1.1.8 upstream)
  • Revision ID: james.westby@ubuntu.com-20090624140043-07stp20mry48hqup
Tags: 0.47~pre0-0ubuntu1
* New upstream release

[ Ted Gould ]
* debian/control: Adding libgsl0 and removing version specifics on boost

[ Kees Cook ]
* debian/watch: updated to run uupdate and mangle pre-release versions.
* Dropped patches that have been taken upstream:
  - 01_mips
  - 02-poppler-0.8.3
  - 03-chinese-inkscape
  - 05_fix_latex_patch
  - 06_gcc-4.4
  - 07_cdr2svg
  - 08_skip-bad-utf-on-pdf-import
  - 09_gtk-clist
  - 10_belarussian
  - 11_libpng
  - 12_desktop
  - 13_slider
  - 100_svg_import_improvements
  - 102_sp_pattern_painter_free
  - 103_bitmap_type_print

Show diffs side-by-side

added added

removed removed

Lines of Context:
9
9
 *  Released under GNU GPL, read the file 'COPYING' for more information.
10
10
 */
11
11
 
 
12
#include <gtk/gtk.h>
12
13
#include "snapped-point.h"
 
14
#include "preferences.h"
13
15
 
14
16
// overloaded constructor
15
 
Inkscape::SnappedPoint::SnappedPoint(NR::Point p, NR::Coord d, NR::Coord t, bool a)
16
 
    : _point(p), _distance(d), _tolerance(t), _always_snap(a)
 
17
Inkscape::SnappedPoint::SnappedPoint(Geom::Point const &p, SnapSourceType const &source, SnapTargetType const &target, Geom::Coord const &d, Geom::Coord const &t, bool const &a, bool const &fully_constrained)
 
18
    : _point(p), _source(source), _target(target), _distance(d), _tolerance(std::max(t,1.0)), _always_snap(a)
17
19
{
 
20
    // tolerance should never be smaller than 1 px, as it is used for normalization in isOtherSnapBetter. We don't want a division by zero.
18
21
    _at_intersection = false;
 
22
    _fully_constrained = fully_constrained;
19
23
    _second_distance = NR_HUGE;
20
 
    _second_tolerance = 0;
 
24
    _second_tolerance = 1;
21
25
    _second_always_snap = false;
 
26
    _transformation = Geom::Point(1,1);
 
27
    _pointer_distance = NR_HUGE;
22
28
}
23
29
 
24
 
Inkscape::SnappedPoint::SnappedPoint(NR::Point p, NR::Coord d, NR::Coord t, bool a, bool at_intersection, NR::Coord d2, NR::Coord t2, bool a2)
25
 
    : _point(p), _distance(d), _tolerance(t), _always_snap(a), _at_intersection(at_intersection), 
26
 
    _second_distance(d2), _second_tolerance(t2), _second_always_snap(a2)
 
30
Inkscape::SnappedPoint::SnappedPoint(Geom::Point const &p, SnapSourceType const &source, SnapTargetType const &target, Geom::Coord const &d, Geom::Coord const &t, bool const &a, bool const &at_intersection, bool const &fully_constrained, Geom::Coord const &d2, Geom::Coord const &t2, bool const &a2)
 
31
    : _point(p), _source(source), _target(target), _at_intersection(at_intersection), _fully_constrained(fully_constrained), _distance(d), _tolerance(std::max(t,1.0)), _always_snap(a),
 
32
    _second_distance(d2), _second_tolerance(std::max(t2,1.0)), _second_always_snap(a2)
27
33
{
 
34
    // tolerance should never be smaller than 1 px, as it is used for normalization in
 
35
    // isOtherSnapBetter. We don't want a division by zero.
 
36
    _transformation = Geom::Point(1,1);
 
37
    _pointer_distance = NR_HUGE;
28
38
}
29
39
 
30
40
Inkscape::SnappedPoint::SnappedPoint()
31
41
{
32
 
    _point = NR::Point(0,0);
 
42
    _point = Geom::Point(0,0);
 
43
    _source = SNAPSOURCE_UNDEFINED,
 
44
    _target = SNAPTARGET_UNDEFINED,
 
45
    _at_intersection = false;
 
46
    _fully_constrained = false;
33
47
    _distance = NR_HUGE;
34
 
    _tolerance = 0;
 
48
    _tolerance = 1;
35
49
    _always_snap = false;
36
 
    _at_intersection = false;
37
50
    _second_distance = NR_HUGE;
38
 
    _second_tolerance = 0;
 
51
    _second_tolerance = 1;
39
52
    _second_always_snap = false;
 
53
    _transformation = Geom::Point(1,1);
 
54
    _pointer_distance = NR_HUGE;
40
55
}
41
56
 
42
 
 
43
 
 
44
57
Inkscape::SnappedPoint::~SnappedPoint()
45
58
{
46
59
}
47
60
 
48
 
NR::Coord Inkscape::SnappedPoint::getDistance() const
49
 
{
50
 
    return _distance;
51
 
}
52
 
 
53
 
NR::Coord Inkscape::SnappedPoint::getTolerance() const
54
 
{
55
 
    return _tolerance;
56
 
}
57
 
 
58
 
bool Inkscape::SnappedPoint::getAlwaysSnap() const
59
 
{
60
 
    return _always_snap;
61
 
}
62
 
 
63
 
NR::Coord Inkscape::SnappedPoint::getSecondDistance() const
64
 
{
65
 
    return _second_distance;
66
 
}
67
 
 
68
 
NR::Coord Inkscape::SnappedPoint::getSecondTolerance() const
69
 
{
70
 
    return _second_tolerance;
71
 
}
72
 
 
73
 
bool Inkscape::SnappedPoint::getSecondAlwaysSnap() const
74
 
{
75
 
    return _second_always_snap;
76
 
}
77
 
 
78
 
 
79
 
NR::Point Inkscape::SnappedPoint::getPoint() const
80
 
{
81
 
    return _point;
 
61
void Inkscape::SnappedPoint::getPoint(Geom::Point &p) const
 
62
{
 
63
    // When we have snapped
 
64
    if (getSnapped()) {
 
65
        // then return the snapped point by overwriting p
 
66
        p = _point;
 
67
    } //otherwise p will be left untouched; this way the caller doesn't have to check wether we've snapped
82
68
}
83
69
 
84
70
// search for the closest snapped point
85
 
bool getClosestSP(std::list<Inkscape::SnappedPoint> &list, Inkscape::SnappedPoint &result) 
 
71
bool getClosestSP(std::list<Inkscape::SnappedPoint> &list, Inkscape::SnappedPoint &result)
86
72
{
87
73
    bool success = false;
88
 
    
 
74
 
89
75
    for (std::list<Inkscape::SnappedPoint>::const_iterator i = list.begin(); i != list.end(); i++) {
90
 
        if ((i == list.begin()) || (*i).getDistance() < result.getDistance()) {
 
76
        if ((i == list.begin()) || (*i).getSnapDistance() < result.getSnapDistance()) {
91
77
            result = *i;
92
78
            success = true;
93
 
        }    
 
79
        }
94
80
    }
95
 
    
 
81
 
96
82
    return success;
97
83
}
98
84
 
 
85
bool Inkscape::SnappedPoint::isOtherSnapBetter(Inkscape::SnappedPoint const &other_one, bool weighted) const
 
86
{
 
87
 
 
88
    double dist_other = other_one.getSnapDistance();
 
89
    double dist_this = getSnapDistance();
 
90
 
 
91
    // The distance to the pointer should only be taken into account when finding the best snapped source node (when
 
92
    // there's more than one). It is not useful when trying to find the best snapped target point.
 
93
    // (both the snap distance and the pointer distance are measured in document pixels, not in screen pixels)
 
94
    if (weighted) {
 
95
 
 
96
        Geom::Coord const dist_pointer_other = other_one.getPointerDistance();
 
97
        Geom::Coord const dist_pointer_this = getPointerDistance();
 
98
        // Weight factor: controls which node should be preferred for snapping, which is either
 
99
        // the node with the closest snap (w = 0), or the node closest to the mousepointer (w = 1)
 
100
        Inkscape::Preferences *prefs = Inkscape::Preferences::get();
 
101
        double w = prefs->getDoubleLimited("/options/snapweight/value", 0.5, 0, 1);
 
102
        if (prefs->getBool("/options/snapclosestonly/value", false)) {
 
103
            w = 1;
 
104
        }
 
105
        if (w > 0) {
 
106
                if (!(w == 1 && dist_pointer_this == dist_pointer_other)) {
 
107
                        // When accounting for the distance to the mouse pointer, then at least one of the snapped points should
 
108
                                // have that distance set. If not, then this is a bug. Either "weighted" must be set to false, or the
 
109
                                // mouse pointer distance must be set.
 
110
                                g_assert(dist_pointer_this != NR_HUGE || dist_pointer_other != NR_HUGE);
 
111
                                // The snap distance will always be smaller than the tolerance set for the snapper. The pointer distance can
 
112
                                // however be very large. To compare these in a fair way, we will have to normalize these metrics first
 
113
                                // The closest pointer distance will be normalized to 1.0; the other one will be > 1.0
 
114
                                // The snap distance will be normalized to 1.0 if it's equal to the snapper tolerance
 
115
                                double const norm_p = std::min(dist_pointer_this, dist_pointer_other);
 
116
                                double const norm_t_other = std::min(50.0, other_one.getTolerance());
 
117
                                double const norm_t_this = std::min(50.0, getTolerance());
 
118
                                dist_other = w * dist_pointer_other / norm_p + (1-w) * dist_other / norm_t_other;
 
119
                                dist_this = w * dist_pointer_this / norm_p + (1-w) * dist_this / norm_t_this;
 
120
                }
 
121
        }
 
122
    }
 
123
 
 
124
    // If it's closer
 
125
    bool c1 = dist_other < dist_this;
 
126
    // or, if it's for a snapper with "always snap" turned on, and the previous wasn't
 
127
    bool c2 = other_one.getAlwaysSnap() && !getAlwaysSnap();
 
128
    // But in no case fall back from a snapper with "always snap" on to one with "always snap" off
 
129
    bool c2n = !other_one.getAlwaysSnap() && getAlwaysSnap();
 
130
    // or, if we have a fully constrained snappoint (e.g. to a node or an intersection), while the previous one was only partly constrained (e.g. to a line)
 
131
    bool c3 = other_one.getFullyConstrained() && !getFullyConstrained();
 
132
    // But in no case fall back; (has less priority than c3n, so it is allowed to fall back when c3 is true, see below)
 
133
    bool c3n = !other_one.getFullyConstrained() && getFullyConstrained();
 
134
 
 
135
    // When both are fully constrained AND coincident, then prefer nodes over intersections
 
136
    bool d = other_one.getFullyConstrained() && getFullyConstrained() && (Geom::L2(other_one.getPoint() - getPoint()) < 1e-9);
 
137
    bool c4 = d && !other_one.getAtIntersection() && getAtIntersection();
 
138
    // But don't fall back...
 
139
    bool c4n = d && other_one.getAtIntersection() && !getAtIntersection();
 
140
 
 
141
    // or, if it's just as close then consider the second distance
 
142
    bool c5a = (dist_other == dist_this);
 
143
    bool c5b = other_one.getSecondSnapDistance() < getSecondSnapDistance();
 
144
 
 
145
    // std::cout << other_one.getPoint() << " (Other one, dist = " << dist_other << ") vs. " << getPoint() << " (this one, dist = " << dist_this << ") ---> ";
 
146
    // std::cout << "c1 = " << c1 << " | c2 = " << c2 << " | c2n = " << c2n << " | c3 = " << c3 << " | c3n = " << c3n << " | c4 = " << c4 << " | c4n = " << c4n << " | c5a = " << c5a << " | c5b = " << c5b << std::endl;
 
147
    return (c1 || c2 || c3 || c4 || (c5a && c5b)) && !c2n && (!c3n || c2) && !c4n;
 
148
}
 
149
 
99
150
/*
100
151
  Local Variables:
101
152
  mode:c++