Code

7ae94e4f4b79181834cc5d0a36e8f4b5aa6af8e8
[inkscape.git] / src / snapped-line.cpp
1 /**
2  *    \file src/snapped-line.cpp
3  *    \brief SnappedLine class.
4  *
5  *    Authors:
6  *      Diederik van Lierop <mail@diedenrezi.nl>
7  *
8  *    Released under GNU GPL, read the file 'COPYING' for more information.
9  */
11 #include "snapped-line.h"
12 #include <2geom/geom.h>
13 #include "libnr/nr-values.h"
15 Inkscape::SnappedLineSegment::SnappedLineSegment(NR::Point snapped_point, NR::Coord snapped_distance, NR::Point start_point_of_line, NR::Point end_point_of_line)
16     : _start_point_of_line(start_point_of_line), _end_point_of_line(end_point_of_line) 
17 {
18         _distance = snapped_distance;
19         _point = snapped_point;
20         _at_intersection = false;
21 }
23 Inkscape::SnappedLineSegment::SnappedLineSegment() 
24 {
25         _start_point_of_line = NR::Point(0,0);
26         _end_point_of_line = NR::Point(0,0);
27         _distance = NR_HUGE;
28         _point = NR::Point(0,0);
29         _at_intersection = false;
30 }
33 Inkscape::SnappedLineSegment::~SnappedLineSegment()
34 {
35 }
37 Inkscape::SnappedPoint Inkscape::SnappedLineSegment::intersect(SnappedLineSegment const &line) const 
38 {
39         Geom::Point intersection_2geom(NR_HUGE, NR_HUGE);
40         NR::Coord distance = NR_HUGE;
41          
42         Geom::IntersectorKind result = segment_intersect(_start_point_of_line.to_2geom(), _end_point_of_line.to_2geom(),
43                                                                          line._start_point_of_line.to_2geom(), line._end_point_of_line.to_2geom(),
44                                                                          intersection_2geom);
45         NR::Point intersection(intersection_2geom);
46         
47         if (result == Geom::intersects) {
48                 /* The relevant snapped distance is the distance to the closest snapped line, not the
49                 distance to the intersection. See the comment in Inkscape::SnappedLine::intersect
50                 */
51                 distance = std::min(_distance, line.getDistance());
52         }
53         return SnappedPoint(intersection, distance, result == Geom::intersects);
54 };
58 Inkscape::SnappedLine::SnappedLine(NR::Point snapped_point, NR::Coord snapped_distance, NR::Point normal_to_line, NR::Point point_on_line)
59     : _normal_to_line(normal_to_line), _point_on_line(point_on_line)
60 {
61         _distance = snapped_distance;
62         _point = snapped_point;
63         _at_intersection = false;
64 }
66 Inkscape::SnappedLine::SnappedLine() 
67 {
68         _normal_to_line = NR::Point(0,0);
69         _point_on_line = NR::Point(0,0);
70         _distance = NR_HUGE;
71         _point = NR::Point(0,0);
72         _at_intersection = false;
73 }
75 Inkscape::SnappedLine::~SnappedLine()
76 {
77 }
79 Inkscape::SnappedPoint Inkscape::SnappedLine::intersect(SnappedLine const &line) const 
80 {
81         // Calculate the intersection of to lines, which are both within snapping range
82         // The point of intersection should be considered for snapping, but might be outside the snapping range
83         
84         Geom::Point intersection_2geom(NR_HUGE, NR_HUGE);
85         NR::Coord distance = NR_HUGE;
86         
87     Geom::IntersectorKind result = Geom::line_intersection(getNormal().to_2geom(), getConstTerm(), 
88                                    line.getNormal().to_2geom(), line.getConstTerm(), intersection_2geom);
89         NR::Point intersection(intersection_2geom);
90          
91         if (result == Geom::intersects) {
92                 /* The relevant snapped distance is the distance to the closest snapped line, not the
93                 distance to the intersection. For example, when a box is almost aligned with a grid
94                 in both horizontal and vertical directions, the distance to the intersection of the
95                 grid lines will always be larger then the distance to a grid line. We will be snapping
96                 to the closest snapped point however, so if we ever want to snap to the intersection
97                 then the distance to it should at least be equal to the other distance, not greater 
98                 than it, as that would rule the intersection out
99                 */
100                 distance = std::min(_distance, line.getDistance());
101         }
103     return SnappedPoint(intersection, distance, result == Geom::intersects);
106 // search for the closest snapped line segment
107 bool getClosestSLS(std::list<Inkscape::SnappedLineSegment> &list, Inkscape::SnappedLineSegment &result) 
109         bool success = false;
110         
111         for (std::list<Inkscape::SnappedLineSegment>::const_iterator i = list.begin(); i != list.end(); i++) {
112                 if ((i == list.begin()) || (*i).getDistance() < result.getDistance()) {
113                         result = *i;
114                         success = true;
115                 }       
116         }
117         
118         return success; 
121 // search for the closest intersection of two snapped line segments, which are both member of the same collection
122 bool getClosestIntersectionSLS(std::list<Inkscape::SnappedLineSegment> &list, Inkscape::SnappedPoint &result)
124         bool success = false;
125         
126         for (std::list<Inkscape::SnappedLineSegment>::const_iterator i = list.begin(); i != list.end(); i++) {
127                 std::list<Inkscape::SnappedLineSegment>::const_iterator j = i;
128                 j++;
129                 for (; j != list.end(); j++) {
130                         Inkscape::SnappedPoint sp = (*i).intersect(*j);
131                         if (sp.getAtIntersection()) {
132                                 if (!success || sp.getDistance() < result.getDistance()) {  
133                                         // !success because the first intersection cannot be compared to a previous one
134                                         result = sp;
135                                         success = true;
136                                 }
137                         }
138                 }
139         }
140         
141         return success; 
144 // search for the closest snapped line
145 bool getClosestSL(std::list<Inkscape::SnappedLine> &list, Inkscape::SnappedLine &result) 
147         bool success = false;
148         
149         for (std::list<Inkscape::SnappedLine>::const_iterator i = list.begin(); i != list.end(); i++) {
150                 if ((i == list.begin()) || (*i).getDistance() < result.getDistance()) {
151                         result = *i;
152                         success = true;
153                 }       
154         }
155         
156         return success; 
159 // search for the closest intersection of two snapped lines, which are both member of the same collection
160 bool getClosestIntersectionSL(std::list<Inkscape::SnappedLine> &list, Inkscape::SnappedPoint &result)
162         bool success = false;
163         
164         for (std::list<Inkscape::SnappedLine>::const_iterator i = list.begin(); i != list.end(); i++) {
165                 std::list<Inkscape::SnappedLine>::const_iterator j = i;
166                 j++;
167                 for (; j != list.end(); j++) {
168                         Inkscape::SnappedPoint sp = (*i).intersect(*j);
169                         if (sp.getAtIntersection()) {
170                                 if (!success || sp.getDistance() < result.getDistance()) {  
171                                         // !success because the first intersection cannot be compared to a previous one
172                                         result = sp;
173                                         success = true;
174                                 }
175                         }                               
176                 }
177         }
178         
179         return success; 
182 // search for the closest intersection of two snapped lines, which are in two different collections
183 bool getClosestIntersectionSL(std::list<Inkscape::SnappedLine> &list1, std::list<Inkscape::SnappedLine> &list2, Inkscape::SnappedPoint &result)
185         bool success = false;
186         
187         for (std::list<Inkscape::SnappedLine>::const_iterator i = list1.begin(); i != list1.end(); i++) {
188                 for (std::list<Inkscape::SnappedLine>::const_iterator j = list2.begin(); j != list2.end(); j++) {
189                         Inkscape::SnappedPoint sp = (*i).intersect(*j);
190                         if (sp.getAtIntersection()) {
191                                 if (!success || sp.getDistance() < result.getDistance()) {
192                                         // !success because the first intersection cannot be compared to a previous one
193                                         result = sp;
194                                         success = true;
195                                 }
196                         }                               
197                 }
198         }
199         
200         return success;
203 /*
204   Local Variables:
205   mode:c++
206   c-file-style:"stroustrup"
207   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
208   indent-tabs-mode:nil
209   fill-column:99
210   End:
211 */
212 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :