remove invalid assertion - #6634
[ardour.git] / libs / canvas / poly_line.cc
1 /*
2     Copyright (C) 2011-2013 Paul Davis
3     Author: Carl Hetherington <cth@carlh.net>
4
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 #include <algorithm>
21
22 #include "canvas/poly_line.h"
23 #include "canvas/canvas.h"
24 #include "canvas/utils.h"
25
26 using namespace ArdourCanvas;
27
28 PolyLine::PolyLine (Canvas* c)
29         : PolyItem (c)
30         , _threshold (1.0)
31 {
32 }
33
34 PolyLine::PolyLine (Item* parent)
35         : PolyItem (parent)
36         , _threshold (1.0)
37 {
38 }
39
40 void
41 PolyLine::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) const
42 {
43         if (_outline) {
44                 setup_outline_context (context);
45                 render_path (area, context);
46                 context->stroke ();
47         }
48 }
49
50 void
51 PolyLine::set_steps (Points const & points, bool stepped)
52 {
53         if (!stepped) {
54                 PolyItem::set(points);
55                 return;
56         }
57
58         Points copy;
59         for (Points::const_iterator p = points.begin(); p != points.end();) {
60                 Points::const_iterator next = p;
61                 ++next;
62
63                 copy.push_back(*p);
64                 if (next != points.end() && next->x != p->x) {
65                         copy.push_back(Duple(next->x, p->y));
66                 }
67
68                 p = next;
69         }
70
71         PolyItem::set(copy);
72 }
73
74 bool
75 PolyLine::covers (Duple const & point) const
76 {
77         Duple p = window_to_item (point);
78
79         const Points::size_type npoints = _points.size();
80
81         if (npoints < 2) {
82                 return false;
83         }
84
85         Points::size_type i;
86         Points::size_type j;
87
88         /* repeat for each line segment */
89
90         const Rect visible (window_to_item (_canvas->visible_area()));
91
92         for (i = 1, j = 0; i < npoints; ++i, ++j) {
93
94                 Duple at;
95                 double t;
96                 Duple a (_points[j]);
97                 Duple b (_points[i]);
98
99                 /*
100                   Clamp the line endpoints to the visible area of the canvas. If we do
101                   not do this, we may have a line segment extending to COORD_MAX and our
102                   math goes wrong.
103                 */
104
105                 a.x = std::min (a.x, visible.x1);
106                 a.y = std::min (a.y, visible.y1);
107                 b.x = std::min (b.x, visible.x1);
108                 b.y = std::min (b.y, visible.y1);
109
110                 double d = distance_to_segment_squared (p, a, b, t, at);
111
112                 if (t < 0.0 || t > 1.0) {
113                         continue;
114                 }
115
116                 if (d < _threshold + _outline_width) {
117                         return true;
118                 }
119
120         }
121
122         return false;
123 }
124
125 void
126 PolyLine::set_covers_threshold (double t)
127 {
128         _threshold = t;
129 }