From c4f0063a68d189a59450a5bba658fc3092bc936b Mon Sep 17 00:00:00 2001 From: Paul Davis Date: Mon, 9 Dec 2013 17:24:34 -0500 Subject: [PATCH] make PolyLine use distance_to_segment_squared(), and add separate (null, for now) method Curve::covers(Duple) because the math there needs to be different, maybe --- libs/canvas/canvas/curve.h | 2 ++ libs/canvas/curve.cc | 8 +++++++ libs/canvas/lookup_table.cc | 1 + libs/canvas/poly_item.cc | 14 ++++++------- libs/canvas/poly_line.cc | 42 ++++++++++++++++++++++++++++--------- 5 files changed, 50 insertions(+), 17 deletions(-) diff --git a/libs/canvas/canvas/curve.h b/libs/canvas/canvas/curve.h index 4cf69e19e3..2d60f0f6d7 100644 --- a/libs/canvas/canvas/curve.h +++ b/libs/canvas/canvas/curve.h @@ -32,6 +32,8 @@ public: void render (Rect const & area, Cairo::RefPtr) const; void set (Points const &); + bool covers (Duple const &) const; + protected: void render_path (Rect const &, Cairo::RefPtr) const; void render_curve (Rect const &, Cairo::RefPtr) const; diff --git a/libs/canvas/curve.cc b/libs/canvas/curve.cc index 5bbd33799d..df65cf491c 100644 --- a/libs/canvas/curve.cc +++ b/libs/canvas/curve.cc @@ -103,6 +103,8 @@ Curve::render (Rect const & area, Cairo::RefPtr context) const void Curve::render_path (Rect const & area, Cairo::RefPtr context) const { + std::cerr << whatami() << '/' << name << " render curve w/" << _points.size() << " points, " << first_control_points.size() << " first and " + << second_control_points.size() << " second\n"; PolyItem::render_curve (area, context, first_control_points, second_control_points); } @@ -209,3 +211,9 @@ Curve::solve (std::vector const & rhs) return x; } + +bool +Curve::covers (Duple const & point) const +{ + return false; +} diff --git a/libs/canvas/lookup_table.cc b/libs/canvas/lookup_table.cc index 0cae7c9c4f..8fd929d325 100644 --- a/libs/canvas/lookup_table.cc +++ b/libs/canvas/lookup_table.cc @@ -64,6 +64,7 @@ DumbLookupTable::items_at_point (Duple point) const } if ((*i)->covers (point)) { + std::cerr << "\t\t" << (*i)->whatami() << '/' << (*i)->name << " covers " << point << std::endl; vitems.push_back (*i); } } diff --git a/libs/canvas/poly_item.cc b/libs/canvas/poly_item.cc index b054b70bbf..239ae06e18 100644 --- a/libs/canvas/poly_item.cc +++ b/libs/canvas/poly_item.cc @@ -94,7 +94,13 @@ PolyItem::render_curve (Rect const & area, Cairo::RefPtr context for (Points::const_iterator i = _points.begin(); i != _points.end(); ++i) { - if (done_first) { + if (!done_first) { + + Duple c = item_to_window (Duple (i->x, i->y)); + context->move_to (c.x, c.y); + done_first = true; + + } else { Duple c1 = item_to_window (Duple (cp1->x, cp1->y)); Duple c2 = item_to_window (Duple (cp2->x, cp2->y)); @@ -104,12 +110,6 @@ PolyItem::render_curve (Rect const & area, Cairo::RefPtr context cp1++; cp2++; - - } else { - - Duple c = item_to_window (Duple (i->x, i->y)); - context->move_to (c.x, c.y); - done_first = true; } } } diff --git a/libs/canvas/poly_line.cc b/libs/canvas/poly_line.cc index 2441e4e3dc..7118e47555 100644 --- a/libs/canvas/poly_line.cc +++ b/libs/canvas/poly_line.cc @@ -17,7 +17,11 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include + #include "canvas/poly_line.h" +#include "canvas/canvas.h" +#include "canvas/utils.h" using namespace ArdourCanvas; @@ -53,21 +57,39 @@ PolyLine::covers (Duple const & point) const Points::size_type j; /* repeat for each line segment */ - + + const Rect visible (_canvas->visible_area()); + static const double threshold = 2.0; + for (i = 1, j = 0; i < npoints; ++i, ++j) { - /* compute area of triangle computed by the two line points and the one - we are being asked about. If zero (within a given tolerance), the - points are co-linear and the argument is on the line. + Duple at; + double t; + Duple a (_points[j]); + Duple b (_points[i]); + + /* + Clamp the line endpoints to the visible area of the canvas. If we do + not do this, we may have a line segment extending to COORD_MAX and our + math goes wrong. */ - - double area = fabs (_points[j].x * (_points[j].y - p.y)) + - (_points[i].x * (p.y - _points[j].y)) + - (p.x * (_points[j].y - _points[i].y)); - if (area < 0.001) { + + a.x = std::min (a.x, visible.x1); + a.y = std::min (a.y, visible.y1); + b.x = std::min (b.x, visible.x1); + b.y = std::min (b.y, visible.y1); + + double d = distance_to_segment_squared (p, a, b, t, at); + + if (t < 0.0 || t > 1.0) { + return false; + } + + if (d < threshold) { return true; } + } - + return false; } -- 2.30.2