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

Unified Diff: experimental/Intersection/QuadraticIntersection.cpp

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
Index: experimental/Intersection/QuadraticIntersection.cpp
diff --git a/experimental/Intersection/QuadraticIntersection.cpp b/experimental/Intersection/QuadraticIntersection.cpp
deleted file mode 100644
index 07b8ecf8f3ea4913bbff1a98eb9045aa60c77b8a..0000000000000000000000000000000000000000
--- a/experimental/Intersection/QuadraticIntersection.cpp
+++ /dev/null
@@ -1,403 +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.
- */
-#include "CurveIntersection.h"
-#include "Intersections.h"
-#include "IntersectionUtilities.h"
-#include "LineIntersection.h"
-#include "LineUtilities.h"
-#include "QuadraticLineSegments.h"
-#include "QuadraticUtilities.h"
-#include <algorithm> // for swap
-
-static const double tClipLimit = 0.8; // http://cagd.cs.byu.edu/~tom/papers/bezclip.pdf see Multiple intersections
-
-class QuadraticIntersections {
-public:
-
-QuadraticIntersections(const Quadratic& q1, const Quadratic& q2, Intersections& i)
- : quad1(q1)
- , quad2(q2)
- , intersections(i)
- , depth(0)
- , splits(0)
- , coinMinT1(-1) {
-}
-
-bool intersect() {
- double minT1, minT2, maxT1, maxT2;
- if (!bezier_clip(quad2, quad1, minT1, maxT1)) {
- return false;
- }
- if (!bezier_clip(quad1, quad2, minT2, maxT2)) {
- return false;
- }
- quad1Divisions = 1 / subDivisions(quad1);
- quad2Divisions = 1 / subDivisions(quad2);
- int split;
- if (maxT1 - minT1 < maxT2 - minT2) {
- intersections.swap();
- minT2 = 0;
- maxT2 = 1;
- split = maxT1 - minT1 > tClipLimit;
- } else {
- minT1 = 0;
- maxT1 = 1;
- split = (maxT2 - minT2 > tClipLimit) << 1;
- }
- return chop(minT1, maxT1, minT2, maxT2, split);
-}
-
-protected:
-
-bool intersect(double minT1, double maxT1, double minT2, double maxT2) {
- bool t1IsLine = maxT1 - minT1 <= quad1Divisions;
- bool t2IsLine = maxT2 - minT2 <= quad2Divisions;
- if (t1IsLine | t2IsLine) {
- return intersectAsLine(minT1, maxT1, minT2, maxT2, t1IsLine, t2IsLine);
- }
- Quadratic smaller, larger;
- // FIXME: carry last subdivide and reduceOrder result with quad
- sub_divide(quad1, minT1, maxT1, intersections.swapped() ? larger : smaller);
- sub_divide(quad2, minT2, maxT2, intersections.swapped() ? smaller : larger);
- double minT, maxT;
- if (!bezier_clip(smaller, larger, minT, maxT)) {
- if (approximately_equal(minT, maxT)) {
- double smallT, largeT;
- _Point q2pt, q1pt;
- if (intersections.swapped()) {
- largeT = interp(minT2, maxT2, minT);
- xy_at_t(quad2, largeT, q2pt.x, q2pt.y);
- xy_at_t(quad1, minT1, q1pt.x, q1pt.y);
- if (AlmostEqualUlps(q2pt.x, q1pt.x) && AlmostEqualUlps(q2pt.y, q1pt.y)) {
- smallT = minT1;
- } else {
- xy_at_t(quad1, maxT1, q1pt.x, q1pt.y); // FIXME: debug code
- SkASSERT(AlmostEqualUlps(q2pt.x, q1pt.x) && AlmostEqualUlps(q2pt.y, q1pt.y));
- smallT = maxT1;
- }
- } else {
- smallT = interp(minT1, maxT1, minT);
- xy_at_t(quad1, smallT, q1pt.x, q1pt.y);
- xy_at_t(quad2, minT2, q2pt.x, q2pt.y);
- if (AlmostEqualUlps(q2pt.x, q1pt.x) && AlmostEqualUlps(q2pt.y, q1pt.y)) {
- largeT = minT2;
- } else {
- xy_at_t(quad2, maxT2, q2pt.x, q2pt.y); // FIXME: debug code
- SkASSERT(AlmostEqualUlps(q2pt.x, q1pt.x) && AlmostEqualUlps(q2pt.y, q1pt.y));
- largeT = maxT2;
- }
- }
- intersections.add(smallT, largeT);
- return true;
- }
- return false;
- }
- int split;
- if (intersections.swapped()) {
- double newMinT1 = interp(minT1, maxT1, minT);
- double newMaxT1 = interp(minT1, maxT1, maxT);
- split = (newMaxT1 - newMinT1 > (maxT1 - minT1) * tClipLimit) << 1;
-#define VERBOSE 0
-#if VERBOSE
- printf("%s d=%d s=%d new1=(%g,%g) old1=(%g,%g) split=%d\n", __FUNCTION__, depth,
- splits, newMinT1, newMaxT1, minT1, maxT1, split);
-#endif
- minT1 = newMinT1;
- maxT1 = newMaxT1;
- } else {
- double newMinT2 = interp(minT2, maxT2, minT);
- double newMaxT2 = interp(minT2, maxT2, maxT);
- split = newMaxT2 - newMinT2 > (maxT2 - minT2) * tClipLimit;
-#if VERBOSE
- printf("%s d=%d s=%d new2=(%g,%g) old2=(%g,%g) split=%d\n", __FUNCTION__, depth,
- splits, newMinT2, newMaxT2, minT2, maxT2, split);
-#endif
- minT2 = newMinT2;
- maxT2 = newMaxT2;
- }
- return chop(minT1, maxT1, minT2, maxT2, split);
-}
-
-bool intersectAsLine(double minT1, double maxT1, double minT2, double maxT2,
- bool treat1AsLine, bool treat2AsLine)
-{
- _Line line1, line2;
- if (intersections.swapped()) {
- SkTSwap(treat1AsLine, treat2AsLine);
- SkTSwap(minT1, minT2);
- SkTSwap(maxT1, maxT2);
- }
- if (coinMinT1 >= 0) {
- bool earlyExit;
- if ((earlyExit = coinMaxT1 == minT1)) {
- coinMaxT1 = maxT1;
- }
- if (coinMaxT2 == minT2) {
- coinMaxT2 = maxT2;
- return true;
- }
- if (earlyExit) {
- return true;
- }
- coinMinT1 = -1;
- }
- // do line/quadratic or even line/line intersection instead
- if (treat1AsLine) {
- xy_at_t(quad1, minT1, line1[0].x, line1[0].y);
- xy_at_t(quad1, maxT1, line1[1].x, line1[1].y);
- }
- if (treat2AsLine) {
- xy_at_t(quad2, minT2, line2[0].x, line2[0].y);
- xy_at_t(quad2, maxT2, line2[1].x, line2[1].y);
- }
- int pts;
- double smallT1, largeT1, smallT2, largeT2;
- if (treat1AsLine & treat2AsLine) {
- double t1[2], t2[2];
- pts = ::intersect(line1, line2, t1, t2);
- if (pts == 2) {
- smallT1 = interp(minT1, maxT1, t1[0]);
- largeT1 = interp(minT2, maxT2, t2[0]);
- smallT2 = interp(minT1, maxT1, t1[1]);
- largeT2 = interp(minT2, maxT2, t2[1]);
- intersections.addCoincident(smallT1, smallT2, largeT1, largeT2);
- } else {
- smallT1 = interp(minT1, maxT1, t1[0]);
- largeT1 = interp(minT2, maxT2, t2[0]);
- intersections.add(smallT1, largeT1);
- }
- } else {
- Intersections lq;
- pts = ::intersect(treat1AsLine ? quad2 : quad1,
- treat1AsLine ? line1 : line2, lq);
- if (pts == 2) { // if the line and edge are coincident treat differently
- _Point midQuad, midLine;
- double midQuadT = (lq.fT[0][0] + lq.fT[0][1]) / 2;
- xy_at_t(treat1AsLine ? quad2 : quad1, midQuadT, midQuad.x, midQuad.y);
- double lineT = t_at(treat1AsLine ? line1 : line2, midQuad);
- xy_at_t(treat1AsLine ? line1 : line2, lineT, midLine.x, midLine.y);
- if (AlmostEqualUlps(midQuad.x, midLine.x)
- && AlmostEqualUlps(midQuad.y, midLine.y)) {
- smallT1 = lq.fT[0][0];
- largeT1 = lq.fT[1][0];
- smallT2 = lq.fT[0][1];
- largeT2 = lq.fT[1][1];
- if (treat2AsLine) {
- smallT1 = interp(minT1, maxT1, smallT1);
- smallT2 = interp(minT1, maxT1, smallT2);
- } else {
- largeT1 = interp(minT2, maxT2, largeT1);
- largeT2 = interp(minT2, maxT2, largeT2);
- }
- intersections.addCoincident(smallT1, smallT2, largeT1, largeT2);
- goto setCoinMinMax;
- }
- }
- for (int index = 0; index < pts; ++index) {
- smallT1 = lq.fT[0][index];
- largeT1 = lq.fT[1][index];
- if (treat2AsLine) {
- smallT1 = interp(minT1, maxT1, smallT1);
- } else {
- largeT1 = interp(minT2, maxT2, largeT1);
- }
- intersections.add(smallT1, largeT1);
- }
- }
- if (pts > 0) {
-setCoinMinMax:
- coinMinT1 = minT1;
- coinMaxT1 = maxT1;
- coinMinT2 = minT2;
- coinMaxT2 = maxT2;
- }
- return pts > 0;
-}
-
-bool chop(double minT1, double maxT1, double minT2, double maxT2, int split) {
- ++depth;
- intersections.swap();
- if (split) {
- ++splits;
- if (split & 2) {
- double middle1 = (maxT1 + minT1) / 2;
- intersect(minT1, middle1, minT2, maxT2);
- intersect(middle1, maxT1, minT2, maxT2);
- } else {
- double middle2 = (maxT2 + minT2) / 2;
- intersect(minT1, maxT1, minT2, middle2);
- intersect(minT1, maxT1, middle2, maxT2);
- }
- --splits;
- intersections.swap();
- --depth;
- return intersections.intersected();
- }
- bool result = intersect(minT1, maxT1, minT2, maxT2);
- intersections.swap();
- --depth;
- return result;
-}
-
-private:
-
-const Quadratic& quad1;
-const Quadratic& quad2;
-Intersections& intersections;
-int depth;
-int splits;
-double quad1Divisions; // line segments to approximate original within error
-double quad2Divisions;
-double coinMinT1; // range of Ts where approximate line intersected curve
-double coinMaxT1;
-double coinMinT2;
-double coinMaxT2;
-};
-
-#include "LineParameters.h"
-
-static void hackToFixPartialCoincidence(const Quadratic& q1, const Quadratic& q2, Intersections& i) {
- // look to see if non-coincident data basically has unsortable tangents
-
- // look to see if a point between non-coincident data is on the curve
- int cIndex;
- for (int uIndex = 0; uIndex < i.fUsed; ) {
- double bestDist1 = 1;
- double bestDist2 = 1;
- int closest1 = -1;
- int closest2 = -1;
- for (cIndex = 0; cIndex < i.fCoincidentUsed; ++cIndex) {
- double dist = fabs(i.fT[0][uIndex] - i.fCoincidentT[0][cIndex]);
- if (bestDist1 > dist) {
- bestDist1 = dist;
- closest1 = cIndex;
- }
- dist = fabs(i.fT[1][uIndex] - i.fCoincidentT[1][cIndex]);
- if (bestDist2 > dist) {
- bestDist2 = dist;
- closest2 = cIndex;
- }
- }
- _Line ends;
- _Point mid;
- double t1 = i.fT[0][uIndex];
- xy_at_t(q1, t1, ends[0].x, ends[0].y);
- xy_at_t(q1, i.fCoincidentT[0][closest1], ends[1].x, ends[1].y);
- double midT = (t1 + i.fCoincidentT[0][closest1]) / 2;
- xy_at_t(q1, midT, mid.x, mid.y);
- LineParameters params;
- params.lineEndPoints(ends);
- double midDist = params.pointDistance(mid);
- // Note that we prefer to always measure t error, which does not scale,
- // instead of point error, which is scale dependent. FIXME
- if (!approximately_zero(midDist)) {
- ++uIndex;
- continue;
- }
- double t2 = i.fT[1][uIndex];
- xy_at_t(q2, t2, ends[0].x, ends[0].y);
- xy_at_t(q2, i.fCoincidentT[1][closest2], ends[1].x, ends[1].y);
- midT = (t2 + i.fCoincidentT[1][closest2]) / 2;
- xy_at_t(q2, midT, mid.x, mid.y);
- params.lineEndPoints(ends);
- midDist = params.pointDistance(mid);
- if (!approximately_zero(midDist)) {
- ++uIndex;
- continue;
- }
- // if both midpoints are close to the line, lengthen coincident span
- int cEnd = closest1 ^ 1; // assume coincidence always travels in pairs
- if (!between(i.fCoincidentT[0][cEnd], t1, i.fCoincidentT[0][closest1])) {
- i.fCoincidentT[0][closest1] = t1;
- }
- cEnd = closest2 ^ 1;
- if (!between(i.fCoincidentT[0][cEnd], t2, i.fCoincidentT[0][closest2])) {
- i.fCoincidentT[0][closest2] = t2;
- }
- int remaining = --i.fUsed - uIndex;
- if (remaining > 0) {
- memmove(&i.fT[0][uIndex], &i.fT[0][uIndex + 1], sizeof(i.fT[0][0]) * remaining);
- memmove(&i.fT[1][uIndex], &i.fT[1][uIndex + 1], sizeof(i.fT[1][0]) * remaining);
- }
- }
- // if coincident data is subjectively a tiny span, replace it with a single point
- for (cIndex = 0; cIndex < i.fCoincidentUsed; ) {
- double start1 = i.fCoincidentT[0][cIndex];
- double end1 = i.fCoincidentT[0][cIndex + 1];
- _Line ends1;
- xy_at_t(q1, start1, ends1[0].x, ends1[0].y);
- xy_at_t(q1, end1, ends1[1].x, ends1[1].y);
- if (!AlmostEqualUlps(ends1[0].x, ends1[1].x) || AlmostEqualUlps(ends1[0].y, ends1[1].y)) {
- cIndex += 2;
- continue;
- }
- double start2 = i.fCoincidentT[1][cIndex];
- double end2 = i.fCoincidentT[1][cIndex + 1];
- _Line ends2;
- xy_at_t(q2, start2, ends2[0].x, ends2[0].y);
- xy_at_t(q2, end2, ends2[1].x, ends2[1].y);
- // again, approximately should be used with T values, not points FIXME
- if (!AlmostEqualUlps(ends2[0].x, ends2[1].x) || AlmostEqualUlps(ends2[0].y, ends2[1].y)) {
- cIndex += 2;
- continue;
- }
- if (approximately_less_than_zero(start1) || approximately_less_than_zero(end1)) {
- start1 = 0;
- } else if (approximately_greater_than_one(start1) || approximately_greater_than_one(end1)) {
- start1 = 1;
- } else {
- start1 = (start1 + end1) / 2;
- }
- if (approximately_less_than_zero(start2) || approximately_less_than_zero(end2)) {
- start2 = 0;
- } else if (approximately_greater_than_one(start2) || approximately_greater_than_one(end2)) {
- start2 = 1;
- } else {
- start2 = (start2 + end2) / 2;
- }
- i.insert(start1, start2);
- i.fCoincidentUsed -= 2;
- int remaining = i.fCoincidentUsed - cIndex;
- if (remaining > 0) {
- memmove(&i.fCoincidentT[0][cIndex], &i.fCoincidentT[0][cIndex + 2], sizeof(i.fCoincidentT[0][0]) * remaining);
- memmove(&i.fCoincidentT[1][cIndex], &i.fCoincidentT[1][cIndex + 2], sizeof(i.fCoincidentT[1][0]) * remaining);
- }
- }
-}
-
-bool intersect(const Quadratic& q1, const Quadratic& q2, Intersections& i) {
- if (implicit_matches(q1, q2)) {
- // FIXME: compute T values
- // compute the intersections of the ends to find the coincident span
- bool useVertical = fabs(q1[0].x - q1[2].x) < fabs(q1[0].y - q1[2].y);
- double t;
- if ((t = axialIntersect(q1, q2[0], useVertical)) >= 0) {
- i.addCoincident(t, 0);
- }
- if ((t = axialIntersect(q1, q2[2], useVertical)) >= 0) {
- i.addCoincident(t, 1);
- }
- useVertical = fabs(q2[0].x - q2[2].x) < fabs(q2[0].y - q2[2].y);
- if ((t = axialIntersect(q2, q1[0], useVertical)) >= 0) {
- i.addCoincident(0, t);
- }
- if ((t = axialIntersect(q2, q1[2], useVertical)) >= 0) {
- i.addCoincident(1, t);
- }
- SkASSERT(i.fCoincidentUsed <= 2);
- return i.fCoincidentUsed > 0;
- }
- QuadraticIntersections q(q1, q2, i);
- bool result = q.intersect();
- // FIXME: partial coincidence detection is currently poor. For now, try
- // to fix up the data after the fact. In the future, revisit the error
- // term to try to avoid this kind of result in the first place.
- if (i.fUsed && i.fCoincidentUsed) {
- hackToFixPartialCoincidence(q1, q2, i);
- }
- return result;
-}
« no previous file with comments | « experimental/Intersection/QuadraticImplicit.cpp ('k') | experimental/Intersection/QuadraticIntersection_Test.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698