| caryclark@google.com | 198e054 | 2012-03-30 18:47:02 +0000 | [diff] [blame] | 1 | add unit test for quadratic horizontal intersection |
| 2 | add unit test for cubic horizontal intersection with left/right |
| 3 | add unit test for ActiveEdge::calcLeft (can currently loop forever) |
| 4 | does ActiveEdge::isCoincidentWith need to support quad, cubic? |
| 5 | figure out why variation in ActiveEdge::tooCloseToCall isn't better |
| 6 | why does 'lastPtr - 2' in addIntersectingTs break testSimplifyTriangle22? |
| 7 | add code to promote quad to cubic, or add quad/cubic intersection |
| 8 | figure out why testSimplifySkinnyTriangle13 fails |
| 9 | |
| 10 | for quadratics and cubics, once various T values are added, see if consecutive |
| 11 | Ts have ys that go up instead of down. If so, the edge needs to be broken. |
| 12 | |
| 13 | when splitting curves at inflection pts, should I retain the original curve |
| 14 | data and note that the first/last T are no longer 0/1 ? |
| 15 | I need to figure this out before I can proceed |
| 16 | |
| 17 | would it make sense to leave the InEdge alone, and add multiple copies of |
| 18 | ActiveEdge, pointing to the same InEdge, where the copy has only the subset |
| 19 | of Ts that need to be walked in reverse order? |
| 20 | |
| caryclark@google.com | 15fa138 | 2012-05-07 20:49:36 +0000 | [diff] [blame] | 21 | |
| 22 | -- A Digression Which Shows Why Resolving Coincidence Does Not Make Sense -- |
| 23 | |
| 24 | Consider the following fine ASCII art: |
| 25 | |
| 26 | +------>-------+ +------>-------+ |
| 27 | | | | | |
| 28 | ^ V ^ V |
| 29 | | | | | |
| 30 | +------<-------+ +------<-------+ |
| 31 | +------>-------+ +------<-------+ |
| 32 | | | | | |
| 33 | ^ V V ^ |
| 34 | | | | | |
| 35 | +------<-------+ +------>-------+ |
| 36 | |
| 37 | (assume the bottom and top of the stacked rectangles are coincident) |
| 38 | |
| 39 | Simplifying said rectangles, regardless of rectangle direction, and regardless |
| 40 | of winding or even/odd, eliminates the coincident edge, i.e., the result is |
| 41 | always: |
| 42 | |
| 43 | +------>-------+ |
| 44 | | | |
| 45 | | | |
| 46 | | | |
| 47 | ^ V |
| 48 | | | |
| 49 | | | |
| 50 | | | |
| 51 | +------<-------+ |
| 52 | |
| 53 | But when the rectangles are enclosed in a larger rectangle: |
| 54 | |
| 55 | +-------->---------+ +-------->---------+ |
| 56 | | +------>-------+ | | +------>-------+ | |
| 57 | | | | | | | | | |
| 58 | | ^ V | | ^ V | |
| 59 | | | | | | | | | |
| 60 | | +------<-------+ | | +------<-------+ | |
| 61 | | +------>-------+ | | +------<-------+ | |
| 62 | | | | | | | | | |
| 63 | | ^ V | | V ^ | |
| 64 | | | | | | | | | |
| 65 | | +------<-------+ | | +------>-------+ | |
| 66 | +--------<---------+ +--------<---------+ |
| 67 | |
| 68 | Simplifying them gives different results depending on the winding setting: |
| 69 | |
| 70 | winding: |
| 71 | +-------->---------+ +-------->---------+ |
| 72 | | | | | |
| 73 | | | | | |
| 74 | | | | | |
| 75 | | | | | |
| 76 | | | | +------<-------+ | |
| 77 | | | | | | | |
| 78 | | | | V ^ | |
| 79 | | | | | | | |
| 80 | | | | +------>-------+ | |
| 81 | +--------<---------+ +--------<---------+ |
| 82 | |
| 83 | even odd: |
| 84 | +-------->---------+ +-------->---------+ |
| 85 | | +------<-------+ | | +------<-------+ | |
| 86 | | | | | | | | | |
| 87 | | | | | | | | | |
| 88 | | | | | | | | | |
| 89 | | | | | | | | | |
| 90 | | V ^ | | V ^ | |
| 91 | | | | | | | | | |
| 92 | | | | | | | | | |
| 93 | | | | | | | | | |
| 94 | | +------>-------+ | | +------>-------+ | |
| 95 | +--------<---------+ +--------<---------+ |
| 96 | |
| 97 | So, given the inner rectangles alone (e.g., given coincident pairs in some local |
| 98 | context), we can't know whether to keep the coincident edges or not. |
| 99 | |
| 100 | |
| 101 | -- Thoughts About Sortless Ops -- |
| 102 | |
| 103 | I can't come up with anything truly sortless. It seems that the crossings need |
| 104 | to be sorted to know which segment is next on the outside, although sometimes |
| 105 | we can use that it is not coincident just to follow the direction. |
| 106 | |
| 107 | If it is coincident or if there's more than two crossing segments, sorting |
| 108 | seems inevitable. |
| 109 | |
| 110 | Likewise, to resolve whether one contour is inside another, it seems that |
| 111 | sorting is required. Given a pair of segments on different contours, to know |
| 112 | if one is inside of the other, I need to know for each which side of the edge |
| 113 | is the inside/filled side. When the outer contour is walked, it seems like I |
| 114 | could record the inside info. I guess when the inner contour is found, its |
| 115 | inside sense is reversed (inside is above the top). But how do I know if the |
| 116 | next contour is inside another? Maybe shoot out a line and brute-force |
| 117 | intersect it with all the segments in all the other contours? If every contour |
| 118 | has an extra segment when the intersections are computed, this may not be as |
| 119 | crazy as it seems. |
| 120 | |
| 121 | Suppose each contour has one extra segment shooting straight up from the top |
| 122 | (or straight up from any point on the segment). This ray is not intersected |
| 123 | with the home contour, but is intersected with all other contours as part of |
| 124 | the normal intersection engine. If it is possible to get from the T values to |
| 125 | the other segments to the other contours, it would be straightforward to |
| 126 | count the contour crossings and determine if the home contour is in another |
| 127 | contour or not (if the count is even, not, if odd, is inside). By itself that |
| 128 | doesn't tell us about winding, but it's a start. |
| 129 | |
| 130 | |
| 131 | Since intersecting these rays is unrelated to computing other intersections, |
| 132 | it can be lazily done once the contour is found. |
| 133 | |
| 134 | So |
| 135 | repeat the following |
| 136 | find the top segment of all contours |
| 137 | trace the outside, marking touching first and last segments as inside |
| 138 | continue tracing the touched segments with reversed outside/inside sense |
| 139 | once the edges are exhausted, remaining must be disjoint contours |
| 140 | send a ray from a disjoint point through all other contours |
| 141 | count the crossings, determine if disjoint is inside or outside, then continue |
| caryclark@google.com | b45a1b4 | 2012-05-18 20:50:33 +0000 | [diff] [blame^] | 142 | |
| 143 | === |
| 144 | |
| 145 | On Quadratic (and Cubic) Intersections |
| 146 | |
| 147 | Currently, if only the end points touch, QuadracticIntersections does a lot of |
| 148 | work to figure that out. Can I test for that up front, then short circuit the |
| 149 | recursive search for the end points? |
| 150 | |
| 151 | Or, is there something defective in the current approach that makes the end |
| 152 | point recursion go so deep? I'm seeing 56 stack frames (about 28 divides, but |
| 153 | thankfully, no splits) to find one matching endpoint. |
| 154 | |
| 155 | |
| 156 | Bezier curve focus may allow more quickly determining that end points with |
| 157 | identical tangents are practically coicident for some range of T, but I don't |
| 158 | understand the math yet to know. |
| 159 | |
| 160 | Another approach is to determine how flat the curve is to make good guesses |
| 161 | about how far to move away in T before doing the intersection for the remainder |
| 162 | and/or to determine whether one curve is to the inside or outside of another. |
| 163 | According to Mike/Rob, the flatness for quadratics increases by 4 for each |
| 164 | subdivision, and a crude guess of the curvature can be had by comparing P1 to |
| 165 | (P0+P2)/2. By looking at the ULPS of the numbers, I can guess what value of |
| 166 | T may be far enough that the curves diverge but don't cross. |