caryclark@google.com | 9e49fb6 | 2012-08-27 14:11:33 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2012 Google Inc. |
| 3 | * |
| 4 | * Use of this source code is governed by a BSD-style license that can be |
| 5 | * found in the LICENSE file. |
| 6 | */ |
caryclark@google.com | c682590 | 2012-02-03 22:07:47 +0000 | [diff] [blame] | 7 | #include "CurveIntersection.h" |
caryclark@google.com | 639df89 | 2012-01-10 21:46:10 +0000 | [diff] [blame] | 8 | #include "IntersectionUtilities.h" |
caryclark@google.com | 9d5f99b | 2013-01-22 12:55:54 +0000 | [diff] [blame^] | 9 | #include "QuadraticUtilities.h" |
caryclark@google.com | 639df89 | 2012-01-10 21:46:10 +0000 | [diff] [blame] | 10 | |
| 11 | /* |
| 12 | Given a quadratic q, t1, and t2, find a small quadratic segment. |
| 13 | |
| 14 | The new quadratic is defined by A, B, and C, where |
| 15 | A = c[0]*(1 - t1)*(1 - t1) + 2*c[1]*t1*(1 - t1) + c[2]*t1*t1 |
| 16 | C = c[3]*(1 - t1)*(1 - t1) + 2*c[2]*t1*(1 - t1) + c[1]*t1*t1 |
| 17 | |
| 18 | To find B, compute the point halfway between t1 and t2: |
| 19 | |
| 20 | q(at (t1 + t2)/2) == D |
| 21 | |
| 22 | Next, compute where D must be if we know the value of B: |
| 23 | |
| 24 | _12 = A/2 + B/2 |
| 25 | 12_ = B/2 + C/2 |
| 26 | 123 = A/4 + B/2 + C/4 |
| 27 | = D |
rmistry@google.com | d6176b0 | 2012-08-23 18:14:13 +0000 | [diff] [blame] | 28 | |
caryclark@google.com | 639df89 | 2012-01-10 21:46:10 +0000 | [diff] [blame] | 29 | Group the known values on one side: |
| 30 | |
| 31 | B = D*2 - A/2 - C/2 |
| 32 | */ |
| 33 | |
| 34 | static double interp_quad_coords(const double* src, double t) |
| 35 | { |
| 36 | double ab = interp(src[0], src[2], t); |
| 37 | double bc = interp(src[2], src[4], t); |
| 38 | double abc = interp(ab, bc, t); |
| 39 | return abc; |
| 40 | } |
| 41 | |
| 42 | void sub_divide(const Quadratic& src, double t1, double t2, Quadratic& dst) { |
| 43 | double ax = dst[0].x = interp_quad_coords(&src[0].x, t1); |
| 44 | double ay = dst[0].y = interp_quad_coords(&src[0].y, t1); |
| 45 | double dx = interp_quad_coords(&src[0].x, (t1 + t2) / 2); |
| 46 | double dy = interp_quad_coords(&src[0].y, (t1 + t2) / 2); |
| 47 | double cx = dst[2].x = interp_quad_coords(&src[0].x, t2); |
| 48 | double cy = dst[2].y = interp_quad_coords(&src[0].y, t2); |
| 49 | /* bx = */ dst[1].x = 2*dx - (ax + cx)/2; |
| 50 | /* by = */ dst[1].y = 2*dy - (ay + cy)/2; |
| 51 | } |
| 52 | |
| 53 | /* classic one t subdivision */ |
| 54 | static void interp_quad_coords(const double* src, double* dst, double t) |
| 55 | { |
| 56 | double ab = interp(src[0], src[2], t); |
| 57 | double bc = interp(src[2], src[4], t); |
| 58 | |
| 59 | dst[0] = src[0]; |
| 60 | dst[2] = ab; |
| 61 | dst[4] = interp(ab, bc, t); |
| 62 | dst[6] = bc; |
| 63 | dst[8] = src[4]; |
| 64 | } |
| 65 | |
| 66 | void chop_at(const Quadratic& src, QuadraticPair& dst, double t) |
| 67 | { |
| 68 | interp_quad_coords(&src[0].x, &dst.pts[0].x, t); |
| 69 | interp_quad_coords(&src[0].y, &dst.pts[0].y, t); |
| 70 | } |