From 4ae59497561578babddaead4e00183ee30f5f641 Mon Sep 17 00:00:00 2001 From: cutealien Date: Wed, 21 Mar 2012 15:13:41 +0000 Subject: [PATCH] - line2d::getClosestPoint can now also get the closest point on the line additional to only checking for closest point on the line-segment. - Avoid division by zero in line2d::getClosestPoint when start- and endpoint are identical. git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@4112 dfc29bdd-3216-0410-991c-e03cc46cb475 --- changes.txt | 4 ++++ include/line2d.h | 26 +++++++++++++++++++------- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/changes.txt b/changes.txt index e15fe4fd..e9c619a4 100644 --- a/changes.txt +++ b/changes.txt @@ -1,5 +1,9 @@ Changes in 1.8 (??.??.2011) + - line2d::getClosestPoint can now also get the closest point on the line additional to only checking for closest point on the line-segment. + + - avoid division by zero in line2d::getClosestPoint when start- and endpoint are identical + - Support for better collada texture wrapping support on loading. - XML-reader now ignores all whitespace-only EXN_TEXT elements as old way didn't work in cross-platform way (and arguably also not well on Windows). diff --git a/include/line2d.h b/include/line2d.h index 64da19e4..98f409b8 100644 --- a/include/line2d.h +++ b/include/line2d.h @@ -211,16 +211,23 @@ class line2d } //! Get the closest point on this line to a point - vector2d getClosestPoint(const vector2d& point) const + /** \param checkOnlySegments: Default (true) is to return a point on the line-segment (between begin and end) of the line. + When set to false the function will check for the first the closest point on the the line even when outside the segment. */ + vector2d getClosestPoint(const vector2d& point, bool checkOnlySegments=true) const { vector2d c((f64)(point.X-start.X), (f64)(point.Y- start.Y)); vector2d v((f64)(end.X-start.X), (f64)(end.Y-start.Y)); f64 d = v.getLength(); + if ( d == 0 ) // can't tell much when the line is just a single point + return start; v /= d; f64 t = v.dotProduct(c); - if (t < 0) return vector2d((T)start.X, (T)start.Y); - if (t > d) return vector2d((T)end.X, (T)end.Y); + if ( checkOnlySegments ) + { + if (t < 0) return vector2d((T)start.X, (T)start.Y); + if (t > d) return vector2d((T)end.X, (T)end.Y); + } v *= t; return vector2d((T)(start.X + v.X), (T)(start.Y + v.Y)); @@ -232,18 +239,23 @@ class line2d vector2d end; }; - // partial specialization to optimize lines + // partial specialization to optimize lines (avoiding casts) template <> - inline vector2df line2d::getClosestPoint(const vector2df& point) const + inline vector2df line2d::getClosestPoint(const vector2df& point, bool checkOnlySegments) const { vector2df c = point - start; vector2df v = end - start; f32 d = (f32)v.getLength(); + if ( d == 0 ) // can't tell much when the line is just a single point + return start; v /= d; f32 t = v.dotProduct(c); - if (t < 0) return start; - if (t > d) return end; + if ( checkOnlySegments ) + { + if (t < 0) return start; + if (t > d) return end; + } v *= t; return start + v;