Author: toshok
Date: 2008-01-24 18:23:26 -0500 (Thu, 24 Jan 2008)
New Revision: 93858

Modified:
   trunk/moon/src/ChangeLog
   trunk/moon/src/stylus.cpp
Log:
2008-01-24  Chris Toshok  <[EMAIL PROTECTED]>

        * stylus.cpp (Stroke::HitTestEndcapSegment): implement.
        (calc_perpendicular_intersection_points): new method.
        (Stroke::HitTestSegmentSegment): use
        calc_perpendicular_intersection_points to give us the end points
        of the outer line segments, and use those for hit testing.



Modified: trunk/moon/src/ChangeLog
===================================================================
--- trunk/moon/src/ChangeLog    2008-01-24 23:22:04 UTC (rev 93857)
+++ trunk/moon/src/ChangeLog    2008-01-24 23:23:26 UTC (rev 93858)
@@ -1,3 +1,11 @@
+2008-01-24  Chris Toshok  <[EMAIL PROTECTED]>
+
+       * stylus.cpp (Stroke::HitTestEndcapSegment): implement.
+       (calc_perpendicular_intersection_points): new method.
+       (Stroke::HitTestSegmentSegment): use
+       calc_perpendicular_intersection_points to give us the end points
+       of the outer line segments, and use those for hit testing.
+
 2008-01-24  Jeffrey Stedfast  <[EMAIL PROTECTED]>
 
        * media.cpp (UpdateProgress): When switching to Buffering mode,

Modified: trunk/moon/src/stylus.cpp
===================================================================
--- trunk/moon/src/stylus.cpp   2008-01-24 23:22:04 UTC (rev 93857)
+++ trunk/moon/src/stylus.cpp   2008-01-24 23:23:26 UTC (rev 93858)
@@ -13,6 +13,7 @@
 
 #include <config.h>
 #include <stdlib.h>
+#include <math.h>
 
 #include "stylus.h"
 #include "collection.h"
@@ -151,7 +152,27 @@
                p2.x, p2.y);
 #endif
 
-       return false;
+
+       double m = (p2.x - p1.x)/p2.y - p1.y;
+       double b_ = p1.y - m * p1.x;
+
+       double a, b;
+       if (w > h) {
+               a = w / 2;
+               b = h / 2;
+       }
+       else {
+               a = h / 2;
+               b = w / 2;
+       }
+
+       double aq = (m*m) / (b*b) + 1 / (a*a);
+       double cq = b_ * b_ - b * b;
+
+       double discr =  -4 * aq * cq;
+
+       /* discr == 0 means 1 intersection point, discr > 0 means 2 */
+       return discr >= 0;
 }
 
 static bool
@@ -178,6 +199,61 @@
        return false;
 }
 
+// given the line segment between @p1 and @p2, with an ellipse with
+// width = @w and height = @h centered at point @p, return the left
+// (lesser x coordinate if the x's are different, and lesser y
+// coordinate if they're the same) and right (greater x coordinate, or
+// greater y coordinate) intersection points of the line through the
+// same point @p but perpendicular to line @p2 - @p1.
+static void
+calc_perpendicular_intersection_points (Point p1, Point p2,
+                                       Point p,
+                                       double w, double h,
+                                       Point *left_point, Point *right_point)
+{
+       if (p2.y == p1.y) { // horizontal line
+               *left_point = Point (p.x, p.y - h / 2);
+               *right_point = Point (p.x, p.y + h / 2);
+       }
+       else if (p2.x == p1.x) { // vertical line
+               *left_point = Point (p.x - w / 2, p.y);
+               *right_point = Point (p.x + w / 2, p.y);
+       }
+       else {
+               // slope of the perpendicular line
+               double m = -(p2.x - p1.x)/p2.y - p1.y;
+
+               double a, b;
+               if (w > h) {
+                       a = w / 2;
+                       b = h / 2;
+               }
+               else {
+                       a = h / 2;
+                       b = w / 2;
+               }
+
+               double aq = (m*m) / (b*b) + 1 / (a*a);
+
+               double discr =  4 * aq;
+
+               if (discr <= 0) {
+                       g_warning ("should never happen, there should always be 
two roots");
+                       *left_point = p;
+                       *right_point = p;
+               }
+               else {
+                       double sqrt_discr = sqrt (discr);
+
+                       double root = (sqrt_discr) / (2 * aq);
+
+                       *left_point = Point (-root + p.x, (-root * m) + p.y);
+                       *right_point = Point (root + p.x, (root * m) + p.y);
+               }
+
+       }
+}
+
 bool
 Stroke::HitTestSegmentSegment (Point stroke_p1, Point stroke_p2,
                               double w, double h,
@@ -191,11 +267,18 @@
                p1.x, p1.y,
                p2.x, p2.y);
 #endif
-       bool rv = intersect_line_2d (stroke_p1, stroke_p2, p1, p2);
-#if DEBUG_HITTEST
-       printf (" + %s\n", rv ? "TRUE" : "FALSE");
-#endif
-       return rv;
+       Point left_stroke_p1, right_stroke_p1;
+       Point left_stroke_p2, right_stroke_p2;
+
+       calc_perpendicular_intersection_points (stroke_p1, stroke_p2, 
stroke_p1, w, h, &left_stroke_p1, &right_stroke_p1);
+       calc_perpendicular_intersection_points (stroke_p1, stroke_p2, 
stroke_p2, w, h, &left_stroke_p2, &right_stroke_p2);
+
+       if (intersect_line_2d (left_stroke_p1, left_stroke_p2, p1, p2))
+               return true;
+       if (intersect_line_2d (right_stroke_p1, right_stroke_p2, p1, p2))
+               return true;
+
+       return false;
 }
 
 bool

_______________________________________________
Mono-patches maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches

Reply via email to