blob: cc86f0cb597b77ac869b65b7cb212f7ffa6a14bf [file] [log] [blame]
caryclark@google.com9e49fb62012-08-27 14:11:33 +00001/*
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.comc6825902012-02-03 22:07:47 +00007#include "CurveIntersection.h"
caryclark@google.com639df892012-01-10 21:46:10 +00008#include "Intersections.h"
caryclark@google.comc6825902012-02-03 22:07:47 +00009#include "IntersectionUtilities.h"
caryclark@google.com639df892012-01-10 21:46:10 +000010#include "LineIntersection.h"
11
caryclark@google.comc6825902012-02-03 22:07:47 +000012class CubicIntersections : public Intersections {
13public:
14
rmistry@google.comd6176b02012-08-23 18:14:13 +000015CubicIntersections(const Cubic& c1, const Cubic& c2, Intersections& i)
caryclark@google.comc6825902012-02-03 22:07:47 +000016 : cubic1(c1)
17 , cubic2(c2)
18 , intersections(i)
rmistry@google.comd6176b02012-08-23 18:14:13 +000019 , depth(0)
caryclark@google.comc6825902012-02-03 22:07:47 +000020 , splits(0) {
caryclark@google.com639df892012-01-10 21:46:10 +000021}
22
caryclark@google.comc6825902012-02-03 22:07:47 +000023bool intersect() {
caryclark@google.com639df892012-01-10 21:46:10 +000024 double minT1, minT2, maxT1, maxT2;
25 if (!bezier_clip(cubic2, cubic1, minT1, maxT1)) {
26 return false;
27 }
28 if (!bezier_clip(cubic1, cubic2, minT2, maxT2)) {
29 return false;
30 }
caryclark@google.comc6825902012-02-03 22:07:47 +000031 int split;
caryclark@google.com639df892012-01-10 21:46:10 +000032 if (maxT1 - minT1 < maxT2 - minT2) {
33 intersections.swap();
caryclark@google.comc6825902012-02-03 22:07:47 +000034 minT2 = 0;
35 maxT2 = 1;
36 split = maxT1 - minT1 > tClipLimit;
37 } else {
38 minT1 = 0;
39 maxT1 = 1;
40 split = (maxT2 - minT2 > tClipLimit) << 1;
41 }
42 return chop(minT1, maxT1, minT2, maxT2, split);
caryclark@google.com639df892012-01-10 21:46:10 +000043}
caryclark@google.comc6825902012-02-03 22:07:47 +000044
45protected:
rmistry@google.comd6176b02012-08-23 18:14:13 +000046
caryclark@google.comc6825902012-02-03 22:07:47 +000047bool intersect(double minT1, double maxT1, double minT2, double maxT2) {
48 Cubic smaller, larger;
rmistry@google.comd6176b02012-08-23 18:14:13 +000049 // FIXME: carry last subdivide and reduceOrder result with cubic
caryclark@google.comc6825902012-02-03 22:07:47 +000050 sub_divide(cubic1, minT1, maxT1, intersections.swapped() ? larger : smaller);
51 sub_divide(cubic2, minT2, maxT2, intersections.swapped() ? smaller : larger);
52 Cubic smallResult;
53 if (reduceOrder(smaller, smallResult,
54 kReduceOrder_NoQuadraticsAllowed) <= 2) {
55 Cubic largeResult;
56 if (reduceOrder(larger, largeResult,
57 kReduceOrder_NoQuadraticsAllowed) <= 2) {
58 const _Line& smallLine = (const _Line&) smallResult;
59 const _Line& largeLine = (const _Line&) largeResult;
60 double smallT[2];
61 double largeT[2];
62 // FIXME: this doesn't detect or deal with coincident lines
63 if (!::intersect(smallLine, largeLine, smallT, largeT)) {
64 return false;
65 }
66 if (intersections.swapped()) {
rmistry@google.comd6176b02012-08-23 18:14:13 +000067 smallT[0] = interp(minT2, maxT2, smallT[0]);
68 largeT[0] = interp(minT1, maxT1, largeT[0]);
caryclark@google.comc6825902012-02-03 22:07:47 +000069 } else {
rmistry@google.comd6176b02012-08-23 18:14:13 +000070 smallT[0] = interp(minT1, maxT1, smallT[0]);
71 largeT[0] = interp(minT2, maxT2, largeT[0]);
caryclark@google.comc6825902012-02-03 22:07:47 +000072 }
73 intersections.add(smallT[0], largeT[0]);
74 return true;
75 }
76 }
77 double minT, maxT;
78 if (!bezier_clip(smaller, larger, minT, maxT)) {
79 if (minT == maxT) {
80 if (intersections.swapped()) {
81 minT1 = (minT1 + maxT1) / 2;
82 minT2 = interp(minT2, maxT2, minT);
83 } else {
84 minT1 = interp(minT1, maxT1, minT);
85 minT2 = (minT2 + maxT2) / 2;
86 }
87 intersections.add(minT1, minT2);
88 return true;
89 }
90 return false;
91 }
rmistry@google.comd6176b02012-08-23 18:14:13 +000092
caryclark@google.comc6825902012-02-03 22:07:47 +000093 int split;
94 if (intersections.swapped()) {
95 double newMinT1 = interp(minT1, maxT1, minT);
96 double newMaxT1 = interp(minT1, maxT1, maxT);
97 split = (newMaxT1 - newMinT1 > (maxT1 - minT1) * tClipLimit) << 1;
98#define VERBOSE 0
99#if VERBOSE
100 printf("%s d=%d s=%d new1=(%g,%g) old1=(%g,%g) split=%d\n",
101 __FUNCTION__, depth, splits, newMinT1, newMaxT1, minT1, maxT1,
102 split);
103#endif
104 minT1 = newMinT1;
105 maxT1 = newMaxT1;
106 } else {
107 double newMinT2 = interp(minT2, maxT2, minT);
108 double newMaxT2 = interp(minT2, maxT2, maxT);
109 split = newMaxT2 - newMinT2 > (maxT2 - minT2) * tClipLimit;
110#if VERBOSE
111 printf("%s d=%d s=%d new2=(%g,%g) old2=(%g,%g) split=%d\n",
112 __FUNCTION__, depth, splits, newMinT2, newMaxT2, minT2, maxT2,
113 split);
114#endif
115 minT2 = newMinT2;
116 maxT2 = newMaxT2;
117 }
118 return chop(minT1, maxT1, minT2, maxT2, split);
119}
120
121bool chop(double minT1, double maxT1, double minT2, double maxT2, int split) {
122 ++depth;
123 intersections.swap();
124 if (split) {
125 ++splits;
126 if (split & 2) {
127 double middle1 = (maxT1 + minT1) / 2;
128 intersect(minT1, middle1, minT2, maxT2);
129 intersect(middle1, maxT1, minT2, maxT2);
130 } else {
131 double middle2 = (maxT2 + minT2) / 2;
132 intersect(minT1, maxT1, minT2, middle2);
133 intersect(minT1, maxT1, middle2, maxT2);
134 }
135 --splits;
136 intersections.swap();
137 --depth;
138 return intersections.intersected();
139 }
140 bool result = intersect(minT1, maxT1, minT2, maxT2);
141 intersections.swap();
142 --depth;
143 return result;
144}
145
146private:
147
caryclark@google.com9f3e9a52012-12-10 12:50:53 +0000148const double tClipLimit = 0.8; // http://cagd.cs.byu.edu/~tom/papers/bezclip.pdf see Multiple intersections
caryclark@google.comc6825902012-02-03 22:07:47 +0000149const Cubic& cubic1;
150const Cubic& cubic2;
151Intersections& intersections;
152int depth;
153int splits;
154};
155
156bool intersect(const Cubic& c1, const Cubic& c2, Intersections& i) {
157 CubicIntersections c(c1, c2, i);
158 return c.intersect();
159}
160