aboutsummaryrefslogtreecommitdiffhomepage
path: root/experimental/Intersection/Simplify.cpp
diff options
context:
space:
mode:
authorGravatar caryclark@google.com <caryclark@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-07-27 18:26:38 +0000
committerGravatar caryclark@google.com <caryclark@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-07-27 18:26:38 +0000
commit27c449af06cd1d05db441593d08b84f3530fba52 (patch)
tree17c8261aa2234d2f16fc25ac3c7be4e3071228e5 /experimental/Intersection/Simplify.cpp
parentbe8cefcc07b5797a2275ed6bf5f57e3c70c79ac6 (diff)
shape ops work in progress
git-svn-id: http://skia.googlecode.com/svn/trunk@4815 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'experimental/Intersection/Simplify.cpp')
-rw-r--r--experimental/Intersection/Simplify.cpp163
1 files changed, 91 insertions, 72 deletions
diff --git a/experimental/Intersection/Simplify.cpp b/experimental/Intersection/Simplify.cpp
index 7f1e7c7866..c6236d513a 100644
--- a/experimental/Intersection/Simplify.cpp
+++ b/experimental/Intersection/Simplify.cpp
@@ -50,7 +50,7 @@ const bool gRunTestsInOneThread = true;
#define DEBUG_ACTIVE_SPANS 1
#define DEBUG_ADD_INTERSECTING_TS 0
#define DEBUG_ADD_T_PAIR 0
-#define DEBUG_CONCIDENT 01
+#define DEBUG_CONCIDENT 0
#define DEBUG_CROSS 1
#define DEBUG_DUMP 1
#define DEBUG_MARK_DONE 1
@@ -656,7 +656,7 @@ struct Bounds : public SkRect {
struct Span {
Segment* fOther;
- mutable SkPoint const* fPt; // lazily computed as needed
+ mutable SkPoint fPt; // lazily computed as needed
double fT;
double fOtherT; // value at fOther[fOtherIndex].fT
int fOtherIndex; // can't be used during intersection
@@ -792,10 +792,10 @@ public:
#if DEBUG_CONCIDENT
SkDebugf("%s 1 this=%d other=%d t [%d] %1.9g (%1.9g,%1.9g)\n",
__FUNCTION__, fID, other.fID, tIndexStart - 1,
- fTs[tIndexStart - 1].fT, xyAtT(tIndexStart - 1).fX,
- xyAtT(tIndexStart - 1).fY);
+ fTs[tIndexStart].fT, xyAtT(tIndexStart).fX,
+ xyAtT(tIndexStart).fY);
#endif
- SkASSERT(0); // incomplete
+ addTPair(fTs[tIndexStart].fT, other, other.fTs[oIndex].fT);
}
if (nextT < 1 && fTs[tIndex].fWindValue) {
#if DEBUG_CONCIDENT
@@ -812,10 +812,10 @@ public:
#if DEBUG_CONCIDENT
SkDebugf("%s 3 this=%d other=%d t [%d] %1.9g (%1.9g,%1.9g)\n",
__FUNCTION__, fID, other.fID, oIndexStart - 1,
- other.fTs[oIndexStart - 1].fT, other.xyAtT(oIndexStart - 1).fX,
- other.xyAtT(oIndexStart - 1).fY);
+ other.fTs[oIndexStart].fT, other.xyAtT(oIndexStart).fX,
+ other.xyAtT(oIndexStart).fY);
+ other.debugAddTPair(other.fTs[oIndexStart].fT, *this, fTs[tIndex].fT);
#endif
- SkASSERT(0); // incomplete
}
if (oNextT < 1 && other.fTs[oIndex].fWindValue) {
#if DEBUG_CONCIDENT
@@ -965,7 +965,7 @@ public:
}
span->fT = newT;
span->fOther = other;
- span->fPt = NULL;
+ span->fPt.fX = SK_ScalarNaN;
span->fWindSum = SK_MinS32;
span->fWindValue = 1;
if ((span->fDone = newT == 1)) {
@@ -1068,7 +1068,7 @@ public:
do {
if (transfer) {
if (decrementOther) {
- SkASSERT(abs(end->fWindValue) < gDebugMaxWindValue);
+ SkASSERT(abs(end->fWindValue) <= gDebugMaxWindValue);
++(end->fWindValue);
} else if (decrementSpan(end)) {
TrackOutside(outsideTs, end->fT, oStartT);
@@ -1085,7 +1085,7 @@ public:
do {
if (transfer) {
if (!decrementOther) {
- SkASSERT(abs(oEnd->fWindValue) < gDebugMaxWindValue);
+ SkASSERT(abs(oEnd->fWindValue) <= gDebugMaxWindValue);
++(oEnd->fWindValue);
} else if (other.decrementSpan(oEnd)) {
TrackOutside(oOutsideTs, oEnd->fT, startT);
@@ -1320,28 +1320,21 @@ public:
// it is guaranteed to have an end which describes a non-zero length (?)
// winding -1 means ccw, 1 means cw
// firstFind allows coincident edges to be treated differently
- Segment* findNext(SkTDArray<Span*>& chase, int winding,
- int contourWinding, bool firstFind, bool active,
+ Segment* findNext(SkTDArray<Span*>& chase, bool firstFind, bool active,
const int startIndex, const int endIndex, int& nextStart,
- int& nextEnd, int& spanWinding) {
-
- start here;
- // winding is a mess
- // try to simplify what we got
-
- int flipped = 1;
+ int& nextEnd, int& winding, int& spanWinding) {
int sumWinding = winding + spanWinding;
- if (sumWinding == 0 || (false && contourWinding && !firstFind)) {
+ if (sumWinding == 0) {
sumWinding = spanWinding;
}
- bool insideContour = contourWinding && contourWinding * sumWinding < 0;
- if (insideContour && (true || !firstFind)) {
- sumWinding = contourWinding;
+ bool insideContour = active && winding && winding * sumWinding < 0;
+ if (insideContour) {
+ sumWinding = winding;
}
#if DEBUG_WINDING
- SkDebugf("%s winding=%d contourWinding=%d spanWinding=%d sumWinding=%d\n",
- __FUNCTION__, winding, contourWinding, spanWinding, sumWinding);
+ SkDebugf("%s winding=%d spanWinding=%d sumWinding=%d\n",
+ __FUNCTION__, winding, spanWinding, sumWinding);
#endif
SkASSERT(startIndex != endIndex);
int count = fTs.count();
@@ -1378,7 +1371,7 @@ public:
int firstIndex = findStartingEdge(sorted, startIndex, end);
SkASSERT(firstIndex >= 0);
#if DEBUG_SORT
- debugShowSort(sorted, firstIndex, contourWinding, sumWinding);
+ debugShowSort(sorted, firstIndex, winding, sumWinding);
#endif
bool doBump = sorted[firstIndex]->firstBump(sumWinding);
#if DEBUG_WINDING
@@ -1396,8 +1389,9 @@ public:
const Angle* foundAngle = NULL;
bool foundDone = false;
// iterate through the angle, and compute everyone's winding
- bool firstEdge = true;
- bool flopped = false;
+ bool toggleWinding = false;
+ bool flipFound = false;
+ int flipped = 1;
Segment* nextSegment;
do {
if (nextIndex == angleCount) {
@@ -1413,13 +1407,12 @@ public:
maxWinding, sumWinding, nextAngle->sign());
#endif
if (maxWinding * sumWinding < 0) {
- flipped = -flipped;
- flopped = true;
+ flipFound ^= true;
#if DEBUG_WINDING
- SkDebugf("flipped sign %d %d\n", maxWinding, sumWinding);
+ SkDebugf("flipFound maxWinding=%d sumWinding=%d\n",
+ maxWinding, sumWinding);
#endif
}
- firstEdge = false;
if (!sumWinding) {
if (!active) {
markDone(SkMin32(startIndex, endIndex), startWinding);
@@ -1433,10 +1426,11 @@ public:
if (!foundAngle || foundDone) {
foundAngle = nextAngle;
foundDone = nextSegment->done(*nextAngle);
- if (!flopped && maxWinding * startWinding < 0) {
+ if (flipFound || (maxWinding * startWinding < 0)) {
flipped = -flipped;
#if DEBUG_WINDING
- SkDebugf("flopped sign %d %d\n", maxWinding, startWinding);
+ SkDebugf("flipped flipFound=%d maxWinding=%d startWinding=%d\n",
+ flipFound, maxWinding, startWinding);
#endif
}
}
@@ -1444,10 +1438,20 @@ public:
}
if (!maxWinding && innerSwap && !foundAngle) {
if (sumWinding * startWinding < 0 && flipped > 0) {
- SkDebugf("%s flip?\n");
- // flipped = -flipped;
+ #if DEBUG_WINDING
+ SkDebugf("%s toggleWinding\n");
+ #endif
+ toggleWinding = true;
+ } else if (startWinding != sumWinding) {
+ winding = sumWinding;
}
foundAngle = nextAngle;
+ if (flipFound) {
+ flipped = -1;
+ #if DEBUG_WINDING
+ SkDebugf("flipped flipFound=%d\n", flipFound);
+ #endif
+ }
}
if (nextSegment->done()) {
continue;
@@ -1481,9 +1485,23 @@ public:
nextSegment = foundAngle->segment();
spanWinding = SkSign32(spanWinding) * flipped * nextSegment->windValue(
SkMin32(nextStart, nextEnd));
- #if DEBUG_WINDING
- SkDebugf("%s spanWinding=%d\n", __FUNCTION__, spanWinding);
- #endif
+ if (toggleWinding) {
+ if (winding) {
+ winding = 0;
+ } else {
+ winding = -startWinding;
+ }
+ }
+ #if 0
+ int min = SkMin32(nextStart, nextEnd);
+ int sign = foundAngle->sign();
+ int windSum = nextSegment->windSum(min);
+ int windValue = nextSegment->windValue(min);
+ SkASSERT(winding + sign * windValue == windSum);
+ #endif
+ #if DEBUG_WINDING
+ SkDebugf("%s spanWinding=%d\n", __FUNCTION__, spanWinding);
+ #endif
return nextSegment;
}
@@ -2013,18 +2031,16 @@ public:
}
const SkPoint& xyAtT(const Span* span) const {
- if (!span->fPt) {
+ if (SkScalarIsNaN(span->fPt.fX)) {
if (span->fT == 0) {
- span->fPt = &fPts[0];
+ span->fPt = fPts[0];
} else if (span->fT == 1) {
- span->fPt = &fPts[fVerb];
+ span->fPt = fPts[fVerb];
} else {
- SkPoint* pt = fIntersections.append();
- (*SegmentXYAtT[fVerb])(fPts, span->fT, pt);
- span->fPt = pt;
+ (*SegmentXYAtT[fVerb])(fPts, span->fT, &span->fPt);
}
}
- return *span->fPt;
+ return span->fPt;
}
SkScalar yAtT(int index) const {
@@ -2153,10 +2169,6 @@ private:
SkPath::Verb fVerb;
Bounds fBounds;
SkTDArray<Span> fTs; // two or more (always includes t=0 t=1)
- // OPTIMIZATION:if intersections array is a pointer, the it could only
- // be allocated as needed instead of always initialized -- though maybe
- // the initialization is lightweight enough that it hardly matters
- mutable SkTDArray<SkPoint> fIntersections;
int fDoneSpans; // used for quick check that segment is finished
#if DEBUG_DUMP
int fID;
@@ -3250,6 +3262,11 @@ static void debugShowActiveSpans(SkTDArray<Contour*>& contourList) {
}
#endif
+static bool windingIsActive(int winding, int spanWinding) {
+ return winding * spanWinding <= 0 && abs(winding) <= abs(spanWinding)
+ && (!winding || !spanWinding || winding == -spanWinding);
+}
+
// Each segment may have an inside or an outside. Segments contained within
// winding may have insides on either side, and form a contour that should be
// ignored. Segments that are coincident with opposing direction segments may
@@ -3286,21 +3303,26 @@ static void bridge(SkTDArray<Contour*>& contourList, SkPath& simple) {
bool firstTime = true;
int winding = contourWinding;
int spanWinding = current->spanSign(index, endIndex);
- // int firstWinding = contourWinding + spanWinding;
+ int spanWindSum = current->windSum(SkMin32(index, endIndex));
+ if (spanWindSum != SK_MinS32) {
+ int calcWinding = spanWindSum;
+ if (spanWinding > 0) {
+ // calcWinding -= spanWinding;
+ }
+ SkDebugf("%s *** winding=%d calcWinding=%d\n", __FUNCTION__,
+ winding, calcWinding);
+ winding = calcWinding;
+ }
// FIXME: needs work. While it works in limited situations, it does
// not always compute winding correctly. Active should be removed and instead
// the initial winding should be correctly passed in so that if the
// inner contour is wound the same way, it never finds an accumulated
// winding of zero. Inside 'find next', we need to look for transitions
// other than zero when resolving sorted angles.
+ bool active = windingIsActive(winding, spanWinding);
SkTDArray<Span*> chaseArray;
do {
- bool active = winding * spanWinding <= 0
- && abs(winding) <= abs(spanWinding);
#if DEBUG_WINDING
- if (abs(winding) > abs(spanWinding) && winding * spanWinding < 0) {
- SkDebugf("%s *** unexpected active?\n", __FUNCTION__);
- }
SkDebugf("%s active=%s winding=%d spanWinding=%d\n",
__FUNCTION__, active ? "true" : "false",
winding, spanWinding);
@@ -3309,9 +3331,9 @@ static void bridge(SkTDArray<Contour*>& contourList, SkPath& simple) {
do {
SkASSERT(!current->done());
int nextStart, nextEnd;
- Segment* next = current->findNext(chaseArray, winding,
- contourWinding, firstTime, active, index, endIndex,
- nextStart, nextEnd, spanWinding);
+ Segment* next = current->findNext(chaseArray,
+ firstTime, active, index, endIndex,
+ nextStart, nextEnd, winding, spanWinding);
if (!next) {
break;
}
@@ -3341,30 +3363,27 @@ static void bridge(SkTDArray<Contour*>& contourList, SkPath& simple) {
spanWinding = current->windSum(lesser);
int spanValue = current->windValue(lesser);
SkASSERT(spanWinding != SK_MinS32);
- int spanSign = current->spanSign(index, endIndex);
#if DEBUG_WINDING
- SkDebugf("%s spanWinding=%d spanSign=%d winding=%d spanValue=%d\n",
- __FUNCTION__, spanWinding, spanSign, winding, spanValue);
+ SkDebugf("%s spanWinding=%d winding=%d spanValue=%d\n",
+ __FUNCTION__, spanWinding, winding, spanValue);
#endif
- if (spanWinding * spanSign < 0) {
- #if DEBUG_WINDING
- SkDebugf("%s spanWinding * spanSign < 0\n", __FUNCTION__);
- #endif
- // SkTSwap<int>(index, endIndex);
- }
- if (abs(spanWinding) > spanValue) {
+ if (abs(spanWinding) != spanValue) {
winding = spanWinding;
spanWinding = spanValue * SkSign32(spanWinding);
winding -= spanWinding;
#if DEBUG_WINDING
- SkDebugf("%s spanWinding=%d winding=%d\n", __FUNCTION__,
+ SkDebugf("%s != spanWinding=%d winding=%d\n", __FUNCTION__,
spanWinding, winding);
#endif
- } else {
+ active = windingIsActive(winding, spanWinding);
+ } else if (winding) {
#if DEBUG_WINDING
SkDebugf("%s ->0 contourWinding=%d winding=%d\n", __FUNCTION__,
contourWinding, winding);
#endif
+ // start here;
+ // set active=false if it was false when chase was created
+ active = abs(winding) <= abs(spanWinding);
winding = 0;
}
} while (true);