Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(850)

Unified Diff: experimental/Intersection/thingsToDo.txt

Issue 867213004: remove prototype pathops code (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « experimental/Intersection/qc.htm ('k') | gyp/pixman_test.gyp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: experimental/Intersection/thingsToDo.txt
diff --git a/experimental/Intersection/thingsToDo.txt b/experimental/Intersection/thingsToDo.txt
deleted file mode 100644
index f74d3ee1268f9fede56b2b8225809fcb5a47ff32..0000000000000000000000000000000000000000
--- a/experimental/Intersection/thingsToDo.txt
+++ /dev/null
@@ -1,525 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-add unit test for quadratic horizontal intersection
-add unit test for cubic horizontal intersection with left/right
-add unit test for ActiveEdge::calcLeft (can currently loop forever)
-does ActiveEdge::isCoincidentWith need to support quad, cubic?
-figure out why variation in ActiveEdge::tooCloseToCall isn't better
-why does 'lastPtr - 2' in addIntersectingTs break testSimplifyTriangle22?
-add code to promote quad to cubic, or add quad/cubic intersection
-figure out why testSimplifySkinnyTriangle13 fails
-
-for quadratics and cubics, once various T values are added, see if consecutive
-Ts have ys that go up instead of down. If so, the edge needs to be broken.
-
-when splitting curves at inflection pts, should I retain the original curve
-data and note that the first/last T are no longer 0/1 ?
-I need to figure this out before I can proceed
-
-would it make sense to leave the InEdge alone, and add multiple copies of
-ActiveEdge, pointing to the same InEdge, where the copy has only the subset
-of Ts that need to be walked in reverse order?
-
-
--- A Digression Which Shows Why Resolving Coincidence Does Not Make Sense --
-
-Consider the following fine ASCII art:
-
- +------>-------+ +------>-------+
- | | | |
- ^ V ^ V
- | | | |
- +------<-------+ +------<-------+
- +------>-------+ +------<-------+
- | | | |
- ^ V V ^
- | | | |
- +------<-------+ +------>-------+
-
-(assume the bottom and top of the stacked rectangles are coincident)
-
-Simplifying said rectangles, regardless of rectangle direction, and regardless
-of winding or even/odd, eliminates the coincident edge, i.e., the result is
-always:
-
- +------>-------+
- | |
- | |
- | |
- ^ V
- | |
- | |
- | |
- +------<-------+
-
-But when the rectangles are enclosed in a larger rectangle:
-
-+-------->---------+ +-------->---------+
-| +------>-------+ | | +------>-------+ |
-| | | | | | | |
-| ^ V | | ^ V |
-| | | | | | | |
-| +------<-------+ | | +------<-------+ |
-| +------>-------+ | | +------<-------+ |
-| | | | | | | |
-| ^ V | | V ^ |
-| | | | | | | |
-| +------<-------+ | | +------>-------+ |
-+--------<---------+ +--------<---------+
-
-Simplifying them gives different results depending on the winding setting:
-
-winding:
-+-------->---------+ +-------->---------+
-| | | |
-| | | |
-| | | |
-| | | |
-| | | +------<-------+ |
-| | | | | |
-| | | V ^ |
-| | | | | |
-| | | +------>-------+ |
-+--------<---------+ +--------<---------+
-
-even odd:
-+-------->---------+ +-------->---------+
-| +------<-------+ | | +------<-------+ |
-| | | | | | | |
-| | | | | | | |
-| | | | | | | |
-| | | | | | | |
-| V ^ | | V ^ |
-| | | | | | | |
-| | | | | | | |
-| | | | | | | |
-| +------>-------+ | | +------>-------+ |
-+--------<---------+ +--------<---------+
-
-So, given the inner rectangles alone (e.g., given coincident pairs in some local
-context), we can't know whether to keep the coincident edges or not.
-
-
--- Thoughts About Sortless Ops --
-
-I can't come up with anything truly sortless. It seems that the crossings need
-to be sorted to know which segment is next on the outside, although sometimes
-we can use that it is not coincident just to follow the direction.
-
-If it is coincident or if there's more than two crossing segments, sorting
-seems inevitable.
-
-Likewise, to resolve whether one contour is inside another, it seems that
-sorting is required. Given a pair of segments on different contours, to know
-if one is inside of the other, I need to know for each which side of the edge
-is the inside/filled side. When the outer contour is walked, it seems like I
-could record the inside info. I guess when the inner contour is found, its
-inside sense is reversed (inside is above the top). But how do I know if the
-next contour is inside another? Maybe shoot out a line and brute-force
-intersect it with all the segments in all the other contours? If every contour
-has an extra segment when the intersections are computed, this may not be as
-crazy as it seems.
-
-Suppose each contour has one extra segment shooting straight up from the top
-(or straight up from any point on the segment). This ray is not intersected
-with the home contour, but is intersected with all other contours as part of
-the normal intersection engine. If it is possible to get from the T values to
-the other segments to the other contours, it would be straightforward to
-count the contour crossings and determine if the home contour is in another
-contour or not (if the count is even, not, if odd, is inside). By itself that
-doesn't tell us about winding, but it's a start.
-
-
-Since intersecting these rays is unrelated to computing other intersections,
-it can be lazily done once the contour is found.
-
-So
-repeat the following
-find the top segment of all contours
-trace the outside, marking touching first and last segments as inside
-continue tracing the touched segments with reversed outside/inside sense
-once the edges are exhausted, remaining must be disjoint contours
-send a ray from a disjoint point through all other contours
-count the crossings, determine if disjoint is inside or outside, then continue
-
-===
-
-On Quadratic (and Cubic) Intersections
-
-Currently, if only the end points touch, QuadracticIntersections does a lot of
-work to figure that out. Can I test for that up front, then short circuit the
-recursive search for the end points?
-
-Or, is there something defective in the current approach that makes the end
-point recursion go so deep? I'm seeing 56 stack frames (about 28 divides, but
-thankfully, no splits) to find one matching endpoint.
-
-
-Bezier curve focus may allow more quickly determining that end points with
-identical tangents are practically coicident for some range of T, but I don't
-understand the math yet to know.
-
-Another approach is to determine how flat the curve is to make good guesses
-about how far to move away in T before doing the intersection for the remainder
-and/or to determine whether one curve is to the inside or outside of another.
-According to Mike/Rob, the flatness for quadratics increases by 4 for each
-subdivision, and a crude guess of the curvature can be had by comparing P1 to
-(P0+P2)/2. By looking at the ULPS of the numbers, I can guess what value of
-T may be far enough that the curves diverge but don't cross.
-
-====
-
-Code I May Not Need Any More
-
- static bool CoincidentCandidate(const Angle* current) {
- const Segment* segment = current->segment();
- int min = SkMin32(current->start(), current->end());
- do {
- const Span& span = segment->fTs[min];
- if (span.fCoincident == Span::kStart_Coincidence) {
- return true;
- }
- } while (--min >= 0);
- return false;
- }
-
- static bool CoincidentHalf(const Angle* current, const Angle* next) {
- const Segment* other = next->segment();
- const Segment* segment = current->segment();
- int min = SkMin32(current->start(), current->end());
- const Span& minSpan = segment->fTs[min];
- if (minSpan.fOther == other) {
- return minSpan.fCoincident == Span::kStart_Coincidence;
- }
- int index = min;
- int spanCount = segment->fTs.count();
- while (++index < spanCount) {
- const Span& span = segment->fTs[index];
- if (minSpan.fT != span.fT) {
- break;
- }
- if (span.fOther != other) {
- continue;
- }
- return span.fCoincident == Span::kStart_Coincidence;
- }
- index = min;
- while (--index >= 0) {
- const Span& span = segment->fTs[index];
- if (span.fOther != other) {
- continue;
- }
- return span.fCoincident == Span::kStart_Coincidence;
- }
- return false;
- }
-
- static bool Coincident(const Angle* current, const Angle* next) {
- return CoincidentHalf(current, next) &&
- CoincidentHalf(next, current);
- }
-
- // If three lines cancel in a - b - c order, a - b may or may not
- // eliminate the edge that describes the b - c cancellation. Check done to
- // determine this.
- static bool CoincidentCancels(const Angle* current, const Angle* next) {
- int curMin = SkMin32(current->start(), current->end());
- if (current->segment()->fTs[curMin].fDone) {
- return false;
- }
- int nextMin = SkMin32(next->start(), next->end());
- if (next->segment()->fTs[nextMin].fDone) {
- return false;
- }
- return SkSign32(current->start() - current->end())
- != SkSign32(next->start() - next->end());
- }
-
- // FIXME: at this point, just have two functions for the different steps
- int coincidentEnd(int from, int step) const {
- double fromT = fTs[from].fT;
- int count = fTs.count();
- int to = from;
- while (step > 0 ? ++to < count : --to >= 0) {
- const Span& span = fTs[to];
- if ((step > 0 ? span.fT - fromT : fromT - span.fT) >= FLT_EPSILON ) {
- // FIXME: we assume that if the T changes, we don't care about
- // coincident -- but in nextSpan, we require that both the T
- // and actual loc change to represent a span. This asymettry may
- // be OK or may be trouble -- if trouble, probably will need to
- // detect coincidence earlier or sort differently
- break;
- }
-#if 01
- if (span.fCoincident == (step < 0 ? Span::kStart_Coincidence :
- Span::kEnd_Coincidence)) {
- from = to;
- }
-#else
- from = to;
-#endif
- }
- return from;
- }
-
- // once past current span, if step>0, look for coicident==1
- // if step<0, look for coincident==-1
- int nextSpanEnd(int from, int step) const {
- int result = nextSpan(from, step);
- if (result < 0) {
- return result;
- }
- return coincidentEnd(result, step);
- }
-
-
- void adjustFirst(const SkTDArray<Angle*>& sorted, int& first, int& winding,
- bool outside) {
- int firstIndex = first;
- int angleCount = sorted.count();
- if (true || outside) {
- const Angle* angle = sorted[firstIndex];
- int prior = firstIndex;
- do {
- if (--prior < 0) {
- prior = angleCount - 1;
- }
- if (prior == firstIndex) { // all are coincident with each other
- return;
- }
- if (!Coincident(sorted[prior], sorted[first])) {
- return;
- }
- winding += angle->sign();
- first = prior;
- angle = sorted[prior];
- winding -= angle->sign();
- } while (true);
- }
- do {
- int next = first + 1;
- if (next == angleCount) {
- next = 0;
- }
- if (next == firstIndex) { // all are coincident with each other
- return;
- }
- if (!Coincident(sorted[first], sorted[next])) {
- return;
- }
- first = next;
- } while (true);
- }
-
- bool nextIsCoincident = CoincidentCandidate(nextAngle);
- bool finalOrNoCoincident = true;
- bool pairCoincides = false;
- bool pairCancels = false;
- if (nextIsCoincident) {
- int followIndex = nextIndex + 1;
- if (followIndex == angleCount) {
- followIndex = 0;
- }
- const Angle* followAngle = sorted[followIndex];
- finalOrNoCoincident = !Coincident(nextAngle, followAngle);
- if ((pairCoincides = Coincident(angle, nextAngle))) {
- pairCancels = CoincidentCancels(angle, nextAngle);
- }
- }
- if (pairCancels && !foundAngle && !nextSegment->done()) {
- Segment* aSeg = angle->segment();
- // alreadyMarked |= aSeg == sorted[firstIndex]->segment();
- aSeg->markAndChaseCoincident(angle->start(), angle->end(),
- nextSegment);
- if (firstEdge) {
- return NULL;
- }
- }
- if (pairCoincides) {
- if (pairCancels) {
- goto doNext;
- }
- int minT = SkMin32(nextAngle->start(), nextAngle->end());
- bool markNext = abs(maxWinding) < abs(winding);
- if (markNext) {
- nextSegment->markDone(minT, winding);
- }
- int oldMinT = SkMin32(angle->start(), angle->end());
- if (true || !foundAngle) {
- // SkASSERT(0); // do we ever get here?
- Segment* aSeg = angle->segment();
- // alreadyMarked |= aSeg == sorted[firstIndex]->segment();
- aSeg->markDone(oldMinT, maxWinding);
- }
- }
-
- // OPTIMIZATION: uses tail recursion. Unwise?
- void innerCoincidentChase(int step, Segment* other) {
- // find other at index
- // SkASSERT(!done());
- const Span* start = NULL;
- const Span* end = NULL;
- int index, startIndex, endIndex;
- int count = fTs.count();
- for (index = 0; index < count; ++index) {
- const Span& span = fTs[index];
- if (!span.fCoincident || span.fOther != other) {
- continue;
- }
- if (!start) {
- startIndex = index;
- start = &span;
- } else {
- SkASSERT(!end);
- endIndex = index;
- end = &span;
- }
- }
- if (!end) {
- return;
- }
- bool thisDone = fTs[SkMin32(startIndex, endIndex)].fDone;
- bool otherDone = other->fTs[SkMin32(start->fOtherIndex,
- end->fOtherIndex)].fDone;
- if (thisDone && otherDone) {
- return;
- }
- Segment* next;
- Segment* nextOther;
- if (step < 0) {
- next = start->fT == 0 ? NULL : this;
- nextOther = other->fTs[start->fOtherIndex].fT > 1 - FLT_EPSILON ? NULL : other;
- } else {
- next = end->fT == 1 ? NULL : this;
- nextOther = other->fTs[end->fOtherIndex].fT < FLT_EPSILON ? NULL : other;
- }
- SkASSERT(!next || !nextOther);
- for (index = 0; index < count; ++index) {
- const Span& span = fTs[index];
- if (span.fCoincident || span.fOther == other) {
- continue;
- }
- bool checkNext = !next && (step < 0 ? span.fT < FLT_EPSILON
- && span.fOtherT > 1 - FLT_EPSILON : span.fT > 1 - FLT_EPSILON
- && span.fOtherT < FLT_EPSILON);
- bool checkOther = !nextOther && (step < 0 ? fabs(span.fT - start->fT) < FLT_EPSILON
- && span.fOtherT < FLT_EPSILON : fabs(span.fT - end->fT) < FLT_EPSILON
- && span.fOtherT > 1 - FLT_EPSILON);
- if (!checkNext && !checkOther) {
- continue;
- }
- Segment* oSegment = span.fOther;
- if (oSegment->done()) {
- continue;
- }
- int oCount = oSegment->fTs.count();
- for (int oIndex = 0; oIndex < oCount; ++oIndex) {
- const Span& oSpan = oSegment->fTs[oIndex];
- if (oSpan.fT >= FLT_EPSILON && oSpan.fT <= 1 - FLT_EPSILON) {
- continue;
- }
- if (!oSpan.fCoincident) {
- continue;
- }
- if (checkNext && (oSpan.fT < FLT_EPSILON ^ step < 0)) {
- next = oSegment;
- checkNext = false;
- }
- if (checkOther && (oSpan.fT > 1 - FLT_EPSILON ^ step < 0)) {
- nextOther = oSegment;
- checkOther = false;
- }
- }
- }
- // this needs to walk both spans in lock step, skipping edges that
- // are already marked done on one or the other
- markCanceled(startIndex, endIndex);
- if (next && nextOther) {
- next->innerCoincidentChase(step, nextOther);
- }
- }
-
- // cancel coincident edges in lock step
- void markCanceled(int start, int end) {
- if (done()) {
- return;
- }
- Segment* other = fTs[start].fOther;
- if (other->done()) {
- return;
- }
- if (start > end) {
- SkTSwap<int>(start, end);
- }
- double maxT = fTs[end].fT - FLT_EPSILON;
- int spanCount = fTs.count();
- // since these cancel, this walks up and other walks down
- int oStart = fTs[start].fOtherIndex;
- double oStartT = other->fTs[oStart].fT;
- while (oStartT - other->fTs[--oStart].fT < FLT_EPSILON)
- ;
- double startT = fTs[start].fT;
- while (start > 0 && startT - fTs[start - 1].fT < FLT_EPSILON) {
- --start;
- }
- do {
- Span* span = &fTs[start];
- Span* oSpan = &other->fTs[oStart];
- // find start of each, and see if both are not done
- bool markDone = !span->fDone && !oSpan->fDone;
- double spanT = span->fT;
- do {
- if (markDone) {
- span->fCanceled = true;
- #if DEBUG_MARK_DONE
- const SkPoint& pt = xyAtT(span);
- SkDebugf("%s segment=%d index=%d t=%1.9g pt=(%1.9g,%1.9g)\n",
- __FUNCTION__, fID, start, span->fT, pt.fX, pt.fY);
- #endif
- SkASSERT(!span->fDone);
- span->fDone = true;
- span->fWinding = 0;
- fDoneSpans++;
- }
- if (++start == spanCount) {
- break;
- }
- span = &fTs[start];
- } while (span->fT - spanT < FLT_EPSILON);
- double oSpanT = oSpan->fT;
- do {
- if (markDone) {
- oSpan->fCanceled = true;
- #if DEBUG_MARK_DONE
- const SkPoint& oPt = xyAtT(oSpan);
- SkDebugf("%s segment=%d index=%d t=%1.9g pt=(%1.9g,%1.9g)\n",
- __FUNCTION__, other->fID, oStart, oSpan->fT,
- oPt.fX, oPt.fY);
- #endif
- SkASSERT(!oSpan->fDone);
- oSpan->fDone = true;
- oSpan->fWinding = 0;
- other->fDoneSpans++;
- }
- if (--oStart < 0) {
- break;
- }
- oSpan = &other->fTs[oStart];
- } while (oSpanT - oSpan->fT < FLT_EPSILON);
- } while (fTs[start].fT <= maxT);
- }
-
- bool canceled(int start, int end) const {
- int min = SkMin32(start, end);
- return fTs[min].fCanceled;
- }
-
- void markAndChaseCoincident(int index, int endIndex, Segment* other) {
- int step = SkSign32(endIndex - index);
- innerCoincidentChase(step, other);
- }
-
« no previous file with comments | « experimental/Intersection/qc.htm ('k') | gyp/pixman_test.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698