Merge branch 'master' into cairocanvas
[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 (Group* parent)
29         : Item (parent)
30         , PolyItem (parent)
31 {
32
33 }
34
35 void
36 PolyLine::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) const
37 {
38         if (_outline) {
39                 setup_outline_context (context);
40                 render_path (area, context);
41                 context->stroke ();
42         }
43 }
44
45 bool
46 PolyLine::covers (Duple const & point) const
47 {
48         Duple p = canvas_to_item (point);
49
50         const Points::size_type npoints = _points.size();
51         
52         if (npoints < 2) {
53                 return false;
54         }
55
56         Points::size_type i;
57         Points::size_type j;
58
59         /* repeat for each line segment */
60
61         const Rect visible (_canvas->visible_area());
62         static const double threshold = 2.0;
63
64         for (i = 1, j = 0; i < npoints; ++i, ++j) {
65
66                 Duple at;
67                 double t;
68                 Duple a (_points[j]);
69                 Duple b (_points[i]);
70                 
71                 /*
72                   Clamp the line endpoints to the visible area of the canvas. If we do
73                   not do this, we may have a line segment extending to COORD_MAX and our
74                   math goes wrong.
75                 */
76                 
77                 a.x = std::min (a.x, visible.x1);
78                 a.y = std::min (a.y, visible.y1);
79                 b.x = std::min (b.x, visible.x1);
80                 b.y = std::min (b.y, visible.y1);
81                 
82                 double d = distance_to_segment_squared (p, a, b, t, at);
83                 
84                 if (t < 0.0 || t > 1.0) {
85                         return false;
86                 }
87                 
88                 if (d < threshold) {
89                         return true;
90                 }
91                 
92         }
93         
94         return false;
95 }