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 //TODO: Diederik, implement the intersection
40 NR::Point const intersection = NR::Point(NR_HUGE, NR_HUGE);
42 //if (result == INTERSECTS) {
43 /* The relevant snapped distance is the distance to the closest snapped line, not the
44 distance to the intersection. For example, when a box is almost aligned with a grid
45 in both horizontal and vertical directions, the distance to the intersection of the
46 grid lines will always be larger then the distance to a grid line. We will be snapping
47 to the closest snapped point however, so if we ever want to snap to the intersection
48 then the distance to it should at least be equal to the other distance, not greater
49 than it, as that would rule the intersection out
50 */
51 NR::Coord distance = std::min(_distance, line.getDistance());
52 //}
53 return SnappedPoint(intersection, distance);
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
84 Geom::Point intersection_2geom(NR_HUGE, NR_HUGE);
85 NR::Coord distance = NR_HUGE;
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);
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 //std::cout << "Intersected nicely, now getSIL distance = " << distance << std::endl;
102 }
104 return SnappedPoint(intersection, distance, result == Geom::intersects);
105 }
107 // search for the closest snapped line
108 bool getClosestSL(std::list<Inkscape::SnappedLine> &list, Inkscape::SnappedLine &result)
109 {
110 bool success = false;
112 for (std::list<Inkscape::SnappedLine>::const_iterator i = list.begin(); i != list.end(); i++) {
113 if ((i == list.begin()) || (*i).getDistance() < result.getDistance()) {
114 result = *i;
115 success = true;
116 }
117 }
119 return success;
120 }
122 // search for the closest intersection of two snapped lines, which are both member of the same collection
123 bool getClosestIntersectionSL(std::list<Inkscape::SnappedLine> &list, Inkscape::SnappedPoint &result)
124 {
125 bool success = false;
127 for (std::list<Inkscape::SnappedLine>::const_iterator i = list.begin(); i != list.end(); i++) {
128 std::list<Inkscape::SnappedLine>::const_iterator j = i;
129 j++;
130 for (; j != list.end(); j++) {
131 Inkscape::SnappedPoint sp = (*i).intersect(*j);
132 if (sp.getAtIntersection()) {
133 if (!success || sp.getDistance() < result.getDistance()) {
134 // !success because the first intersection cannot be compared to a previous one
135 result = sp;
136 success = true;
137 }
138 }
139 }
140 }
142 return success;
143 }
145 // search for the closest intersection of two snapped lines, which are in two different collections
146 bool getClosestIntersectionSL(std::list<Inkscape::SnappedLine> &list1, std::list<Inkscape::SnappedLine> &list2, Inkscape::SnappedPoint &result)
147 {
148 bool success = false;
150 for (std::list<Inkscape::SnappedLine>::const_iterator i = list1.begin(); i != list1.end(); i++) {
151 for (std::list<Inkscape::SnappedLine>::const_iterator j = list2.begin(); j != list2.end(); j++) {
152 Inkscape::SnappedPoint sp = (*i).intersect(*j);
153 if (sp.getAtIntersection()) {
154 if (!success || sp.getDistance() < result.getDistance()) {
155 // !success because the first intersection cannot be compared to a previous one
156 result = sp;
157 success = true;
158 }
159 }
160 }
161 }
163 return success;
164 }
166 /*
167 Local Variables:
168 mode:c++
169 c-file-style:"stroustrup"
170 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
171 indent-tabs-mode:nil
172 fill-column:99
173 End:
174 */
175 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :