Author: toshok
Date: 2008-01-23 18:12:16 -0500 (Wed, 23 Jan 2008)
New Revision: 93735

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

        * stylus.cpp, stylus.h: initial hit testing stuff.  right now the
        only tests that are implemented are endcap (ellipse) vs. point,
        and segment vs. segment (although this one isn't the full test, as
        we're using the stroke line, as opposed to the exterior lines
        created by the ellipse pen tracing that line).

        * rect.h: add PointInside (Point p).



Modified: trunk/moon/src/ChangeLog
===================================================================
--- trunk/moon/src/ChangeLog    2008-01-23 23:10:07 UTC (rev 93734)
+++ trunk/moon/src/ChangeLog    2008-01-23 23:12:16 UTC (rev 93735)
@@ -1,3 +1,13 @@
+2008-01-23  Chris Toshok  <[EMAIL PROTECTED]>
+
+       * stylus.cpp, stylus.h: initial hit testing stuff.  right now the
+       only tests that are implemented are endcap (ellipse) vs. point,
+       and segment vs. segment (although this one isn't the full test, as
+       we're using the stroke line, as opposed to the exterior lines
+       created by the ellipse pen tracing that line).
+
+       * rect.h: add PointInside (Point p).
+       
 2008-01-23  Jeffrey Stedfast  <[EMAIL PROTECTED]>
 
        * pipeline-ffmpeg.cpp: Don't #include "asf/asf-ffmpeg.h" anymore,

Modified: trunk/moon/src/rect.h
===================================================================
--- trunk/moon/src/rect.h       2008-01-23 23:10:07 UTC (rev 93734)
+++ trunk/moon/src/rect.h       2008-01-23 23:12:16 UTC (rev 93735)
@@ -14,6 +14,8 @@
 #include <math.h>
 #include <gtk/gtk.h>
 
+#include "point.h"
+
 // map to System.Windows.Rect
 struct Rect {
  public:
@@ -41,6 +43,11 @@
                return px > x && px < (x + w) && py > y && py < (y + h);
        }
 
+       bool PointInside (Point p)
+       {
+               return p.x > x && p.x < (x + w) && p.y > y && p.y < (y + h);
+       }
+
        bool IntersectsWith (const Rect& rect)
        {
                return ((x < rect.x + rect.w) && (x + w > rect.x) && (y < 
rect.y + rect.h) && (y + h > rect.y));

Modified: trunk/moon/src/stylus.cpp
===================================================================
--- trunk/moon/src/stylus.cpp   2008-01-23 23:10:07 UTC (rev 93734)
+++ trunk/moon/src/stylus.cpp   2008-01-23 23:12:16 UTC (rev 93735)
@@ -139,19 +139,268 @@
 }
 
 bool
-Stroke::HitTest (StylusPointCollection *stylusPoints)
+Stroke::HitTestEndcapSegment (Point c,
+                             double w, double h,
+                             Point p1, Point p2)
 {
+#if DEBUG_HITTEST
+       printf ("HitTestEndcapSegment: (%g,%g / %g, %g) hits segment (%g,%g  - 
%g,%g)?\n",
+               c.x, c.y,
+               w, h,
+               p1.x, p1.y,
+               p2.x, p2.y);
+#endif
+
+       return false;
+}
+
+static bool
+intersect_line_2d (Point p1, Point p2, Point p3, Point p4)
+{
+       // taken from http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/
+       // line segments are p1 - p2 and p3 - p4
+
+       double denom = (p4.y - p3.y) * (p2.x - p1.x) - (p4.x - p3.x) * (p2.y - 
p1.y);
+
+       if (denom == 0) // they're parallel
+               return false;
+
+       double ua = (p4.x - p3.x) * (p1.y - p3.y) - (p4.y - p3.y) * (p1.x - 
p3.x);
+       ua /= denom;
+       if (ua >= 0 && ua <= 1)
+               return true;
+
+       double ub = (p2.x - p1.x) * (p1.y - p3.y) - (p2.y - p1.y) * (p1.x - 
p3.x);
+       ub /= denom;
+       if (ub >= 0 && ub <= 1)
+               return true;
+
+       return false;
+}
+
+bool
+Stroke::HitTestSegmentSegment (Point stroke_p1, Point stroke_p2,
+                              double w, double h,
+                              Point p1, Point p2)
+{
+#if DEBUG_HITTEST
+       printf ("HitTestSegmentSegment: (%g,%g - %g,%g / %g, %g) hits segment 
(%g,%g - %g,%g) ?\n",
+               stroke_p1.x, stroke_p1.y,
+               stroke_p2.x, stroke_p2.y,
+               w, h,
+               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;
+}
+
+bool
+Stroke::HitTestEndcapPoint (Point c,
+                           double w, double h,
+                           Point p)
+{
+#if DEBUG_HITTEST
+       printf ("HitTestEndcapPoint: (%g,%g / %g, %g) hits point %g,%g ?\n",
+               c.x, c.y,
+               w, h,
+               p.x, p.y);
+#endif
+
+       Point dp = p - c;
+       double a, b;
+
+       if (w > h) {
+               a = w / 2;
+               b = h / 2;
+       }
+       else {
+               a = h / 2;
+               b = w / 2;
+       }
+
+       bool rv = ((dp.x * dp.x) / (a * a) + (dp.y * dp.y) / (b * b)) < 1;
+#if DEBUG_HITTEST
+       printf (" + %s\n", rv ? "TRUE" : "FALSE");
+#endif
+       return rv;
+}
+
+bool
+Stroke::HitTestSegmentPoint (Point stroke_p1, Point stroke_p2,
+                            double w, double h,
+                            Point p)
+{
+#if DEBUG_HITTEST
+       printf ("HitTestSegment: (%g,%g - %g,%g / %g, %g) hits point (%g,%g) 
?\n",
+               stroke_p1.x, stroke_p1.y,
+               stroke_p2.x, stroke_p2.y,
+               w, h,
+               p.x, p.y);
+#endif
+
+       return false;
+}
+                             
+
+bool
+Stroke::HitTestSegment (Point p1, Point p2, double w, double h, 
StylusPointCollection *stylusPoints)
+{
        Collection::Node *n;
+       StylusPoint *sp;
 
-       Rect bounds = GetBounds();
+       if (HitTestEndcap (p1, w, h, stylusPoints))
+               return true;
 
+       if (HitTestEndcap (p2, w, h, stylusPoints))
+               return true;
+
        for (n = (Collection::Node *) stylusPoints->list->First (); n; n = 
(Collection::Node *) n->next) {
-               StylusPoint *sp = (StylusPoint*)n->obj;
+               sp = (StylusPoint*)n->obj;
+
+               if (n->next == NULL) {
+                       Point p (stylus_point_get_x (sp),
+                                stylus_point_get_y (sp));
+
+                       if (!bounds.PointInside (p))
+                               continue;
+
+                       if (HitTestSegmentPoint (p1, p2,
+                                                w, h,
+                                                p))
+                               return true;
+               }
+               else  {
+                       n = (Collection::Node *) n->next;
+                       StylusPoint *next_sp = (StylusPoint*)n->obj;
+
+                       Point p (stylus_point_get_x (sp),
+                                stylus_point_get_y (sp));
+                       Point next_p (stylus_point_get_x (next_sp),
+                                     stylus_point_get_y (next_sp));
+
+                       if (!bounds.PointInside (p)
+                           && !bounds.PointInside (next_p))
+                               continue;
+
+                       if (HitTestSegmentSegment (p1, p2,
+                                                  w, h,
+                                                  p, next_p))
+                               return true;
+               }
        }
 
        return false;
 }
 
+bool
+Stroke::HitTestEndcap (Point p, double w, double h, StylusPointCollection 
*stylusPoints)
+{
+       Collection::Node *n;
+       StylusPoint *sp;
+
+       for (n = (Collection::Node *) stylusPoints->list->First (); n; n = 
(Collection::Node *) n->next) {
+               sp = (StylusPoint*)n->obj;
+               if (n->next == NULL) {
+                       Point p (stylus_point_get_x (sp),
+                                stylus_point_get_y (sp));
+
+                       if (!bounds.PointInside (p))
+                               continue;
+
+                       if (HitTestEndcapPoint (p,
+                                               w, h,
+                                               Point (stylus_point_get_x (sp),
+                                                      stylus_point_get_y 
(sp))))
+                         return true;
+               }
+               else  {
+                       n = (Collection::Node *) n->next;
+                       StylusPoint *next_sp = (StylusPoint*)n->obj;
+
+                       Point p (stylus_point_get_x (sp),
+                                stylus_point_get_y (sp));
+                       Point next_p (stylus_point_get_x (next_sp),
+                                     stylus_point_get_y (next_sp));
+
+                       if (!bounds.PointInside (p)
+                           && !bounds.PointInside (next_p))
+                               continue;
+
+                       if (HitTestEndcapSegment (p,
+                                                 w, h,
+                                                 Point (stylus_point_get_x 
(sp),
+                                                        stylus_point_get_y 
(sp)),
+                                                 Point (stylus_point_get_x 
(next_sp),
+                                                        stylus_point_get_y 
(next_sp))))
+                               return true;
+               }
+       }
+
+       return false;
+}
+
+bool
+Stroke::HitTest (StylusPointCollection *stylusPoints)
+{
+       StylusPointCollection *myStylusPoints = stroke_get_stylus_points (this);
+
+       if (myStylusPoints->list->Length() == 0) {
+               printf ("no points in the collection, returning false!\n");
+               return false;
+       }
+
+       DrawingAttributes *da = stroke_get_drawing_attributes (this);
+       Collection::Node *n;
+       StylusPoint *sp;
+
+       double height, width;
+
+       if (da) {
+               height = drawing_attributes_get_height (da) + 4.0;
+               width = drawing_attributes_get_width (da) + 4.0;
+       }
+       else {
+               height = width = 6.0;
+
+       }
+
+       /* test the beginning endcap */
+       n = (Collection::Node *) myStylusPoints->list->First ();
+       sp = (StylusPoint*)n->obj;
+       if (HitTestEndcap (Point (stylus_point_get_x (sp),
+                                 stylus_point_get_y (sp)),
+                          width, height, stylusPoints))
+               return true;
+
+       /* test all the interior line segments */
+       StylusPoint *prev_point = sp;
+       for (n = (Collection::Node *)n->next; n; n = (Collection::Node *) 
n->next) {
+               sp = (StylusPoint*)n->obj;
+               if (HitTestSegment (Point (stylus_point_get_x (prev_point),
+                                          stylus_point_get_y (prev_point)),
+                                   Point (stylus_point_get_x (sp),
+                                          stylus_point_get_y (sp)),
+                                   width, height, stylusPoints))
+                       return true;
+       }
+
+       /* the the ending endcap */
+       if (myStylusPoints->list->Length() > 1) {
+               n = (Collection::Node *) myStylusPoints->list->Last ();
+               sp = (StylusPoint*)n->obj;
+               if (HitTestEndcap (Point (stylus_point_get_x (sp),
+                                         stylus_point_get_y (sp)),
+                                  width, height, stylusPoints))
+                       return true;
+       }
+
+       return false;
+}
+
 void
 Stroke::AddStylusPointToBounds (StylusPoint *stylus_point)
 {

Modified: trunk/moon/src/stylus.h
===================================================================
--- trunk/moon/src/stylus.h     2008-01-23 23:10:07 UTC (rev 93734)
+++ trunk/moon/src/stylus.h     2008-01-23 23:12:16 UTC (rev 93735)
@@ -122,6 +122,14 @@
 
        void AddStylusPointToBounds (StylusPoint *stylus_point);
        void ComputeBounds ();
+
+       bool HitTestEndcapSegment (Point c, double w, double h, Point p1, Point 
p2);
+       bool HitTestEndcapPoint (Point c, double w, double h, Point p1);
+       bool HitTestEndcap (Point p, double w, double h, StylusPointCollection 
*stylusPoints);
+
+       bool HitTestSegmentSegment (Point stroke_p1, Point stroke_p2, double w, 
double h, Point p1, Point p2);
+       bool HitTestSegmentPoint (Point stroke_p1, Point stroke_p2, double w, 
double h, Point p1);
+       bool HitTestSegment (Point stroke_p1, Point stroke_p2, double w, double 
h, StylusPointCollection *stylusPoints);
 };
 
 Stroke*                stroke_new ();

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

Reply via email to