| caryclark@google.com | c682590 | 2012-02-03 22:07:47 +0000 | [diff] [blame] | 1 | #include "CurveIntersection.h" | 
| caryclark@google.com | 8dcf114 | 2012-07-02 20:27:02 +0000 | [diff] [blame] | 2 | #include "CurveUtilities.h" | 
| caryclark@google.com | 639df89 | 2012-01-10 21:46:10 +0000 | [diff] [blame] | 3 | #include "LineParameters.h" | 
 | 4 | #include <algorithm> // used for std::swap | 
 | 5 |  | 
 | 6 | // return false if unable to clip (e.g., unable to create implicit line) | 
 | 7 | // caller should subdivide, or create degenerate if the values are too small | 
 | 8 | bool bezier_clip(const Cubic& cubic1, const Cubic& cubic2, double& minT, double& maxT) { | 
 | 9 |     minT = 1; | 
 | 10 |     maxT = 0; | 
 | 11 |     // determine normalized implicit line equation for pt[0] to pt[3] | 
 | 12 |     //   of the form ax + by + c = 0, where a*a + b*b == 1 | 
| rmistry@google.com | d6176b0 | 2012-08-23 18:14:13 +0000 | [diff] [blame^] | 13 |  | 
| caryclark@google.com | 639df89 | 2012-01-10 21:46:10 +0000 | [diff] [blame] | 14 |     // find the implicit line equation parameters | 
 | 15 |     LineParameters endLine; | 
 | 16 |     endLine.cubicEndPoints(cubic1); | 
 | 17 |     if (!endLine.normalize()) { | 
 | 18 |         printf("line cannot be normalized: need more code here\n"); | 
 | 19 |         return false; | 
 | 20 |     } | 
 | 21 |  | 
 | 22 |     double distance[2]; | 
 | 23 |     endLine.controlPtDistance(cubic1, distance); | 
| rmistry@google.com | d6176b0 | 2012-08-23 18:14:13 +0000 | [diff] [blame^] | 24 |  | 
| caryclark@google.com | 639df89 | 2012-01-10 21:46:10 +0000 | [diff] [blame] | 25 |     // find fat line | 
 | 26 |     double top = distance[0]; | 
 | 27 |     double bottom = distance[1]; | 
 | 28 |     if (top > bottom) { | 
 | 29 |         std::swap(top, bottom); | 
 | 30 |     } | 
 | 31 |     if (top * bottom >= 0) { | 
 | 32 |         const double scale = 3/4.0; // http://cagd.cs.byu.edu/~tom/papers/bezclip.pdf (13) | 
 | 33 |         if (top < 0) { | 
 | 34 |             top *= scale; | 
 | 35 |             bottom = 0; | 
 | 36 |         } else { | 
 | 37 |             top = 0; | 
 | 38 |             bottom *= scale; | 
 | 39 |         } | 
 | 40 |     } else { | 
 | 41 |         const double scale = 4/9.0; // http://cagd.cs.byu.edu/~tom/papers/bezclip.pdf (15) | 
 | 42 |         top *= scale; | 
 | 43 |         bottom *= scale; | 
 | 44 |     } | 
| rmistry@google.com | d6176b0 | 2012-08-23 18:14:13 +0000 | [diff] [blame^] | 45 |  | 
| caryclark@google.com | 639df89 | 2012-01-10 21:46:10 +0000 | [diff] [blame] | 46 |     // compute intersecting candidate distance | 
 | 47 |     Cubic distance2y; // points with X of (0, 1/3, 2/3, 1) | 
 | 48 |     endLine.cubicDistanceY(cubic2, distance2y); | 
| rmistry@google.com | d6176b0 | 2012-08-23 18:14:13 +0000 | [diff] [blame^] | 49 |  | 
| caryclark@google.com | 639df89 | 2012-01-10 21:46:10 +0000 | [diff] [blame] | 50 |     int flags = 0; | 
 | 51 |     if (approximately_lesser(distance2y[0].y, top)) { | 
 | 52 |         flags |= kFindTopMin; | 
 | 53 |     } else if (approximately_greater(distance2y[0].y, bottom)) { | 
 | 54 |         flags |= kFindBottomMin; | 
 | 55 |     } else { | 
 | 56 |         minT = 0; | 
 | 57 |     } | 
 | 58 |  | 
 | 59 |     if (approximately_lesser(distance2y[3].y, top)) { | 
 | 60 |         flags |= kFindTopMax; | 
 | 61 |     } else if (approximately_greater(distance2y[3].y, bottom)) { | 
 | 62 |         flags |= kFindBottomMax; | 
 | 63 |     } else { | 
 | 64 |         maxT = 1; | 
 | 65 |     } | 
 | 66 |     // Find the intersection of distance convex hull and fat line. | 
 | 67 |     char to_0[2]; | 
 | 68 |     char to_3[2]; | 
 | 69 |     bool do_1_2_edge = convex_x_hull(distance2y, to_0, to_3); | 
 | 70 |     x_at(distance2y[0], distance2y[to_0[0]], top, bottom, flags, minT, maxT); | 
 | 71 |     if (to_0[0] != to_0[1]) { | 
 | 72 |         x_at(distance2y[0], distance2y[to_0[1]], top, bottom, flags, minT, maxT); | 
 | 73 |     } | 
 | 74 |     x_at(distance2y[to_3[0]], distance2y[3], top, bottom, flags, minT, maxT); | 
 | 75 |     if (to_3[0] != to_3[1]) { | 
 | 76 |         x_at(distance2y[to_3[1]], distance2y[3], top, bottom, flags, minT, maxT); | 
 | 77 |     } | 
 | 78 |     if (do_1_2_edge) { | 
 | 79 |         x_at(distance2y[1], distance2y[2], top, bottom, flags, minT, maxT); | 
 | 80 |     } | 
| rmistry@google.com | d6176b0 | 2012-08-23 18:14:13 +0000 | [diff] [blame^] | 81 |  | 
| caryclark@google.com | 639df89 | 2012-01-10 21:46:10 +0000 | [diff] [blame] | 82 |     return minT < maxT; // returns false if distance shows no intersection | 
 | 83 | } | 
 | 84 |  |