blob: a09cfcda9c553909b3527e8901b616790d42d2c1 [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.coma5764232012-03-28 16:20:21 +00007#ifndef Intersections_DEFINE
8#define Intersections_DEFINE
9
caryclark@google.com235f56a2012-09-14 14:19:30 +000010#include <algorithm> // for std::min
11
caryclark@google.com639df892012-01-10 21:46:10 +000012class Intersections {
13public:
14 Intersections()
15 : fUsed(0)
caryclark@google.com235f56a2012-09-14 14:19:30 +000016 , fUsed2(0)
caryclark@google.coma7e483d2012-08-28 20:44:43 +000017 , fCoincidentUsed(0)
caryclark@google.com639df892012-01-10 21:46:10 +000018 , fSwap(0)
19 {
caryclark@google.coma7e483d2012-08-28 20:44:43 +000020 // OPTIMIZE: don't need to be initialized in release
caryclark@google.com639df892012-01-10 21:46:10 +000021 bzero(fT, sizeof(fT));
caryclark@google.coma7e483d2012-08-28 20:44:43 +000022 bzero(fCoincidentT, sizeof(fCoincidentT));
caryclark@google.com639df892012-01-10 21:46:10 +000023 }
24
25 void add(double one, double two) {
caryclark@google.com32546db2012-08-31 20:55:07 +000026 for (int index = 0; index < fUsed; ++index) {
27 if (approximately_equal(fT[fSwap][index], one)
28 && approximately_equal(fT[fSwap ^ 1][index], two)) {
29 return;
30 }
caryclark@google.com639df892012-01-10 21:46:10 +000031 }
caryclark@google.com235f56a2012-09-14 14:19:30 +000032 assert(fUsed < 9);
caryclark@google.com639df892012-01-10 21:46:10 +000033 fT[fSwap][fUsed] = one;
34 fT[fSwap ^ 1][fUsed] = two;
35 ++fUsed;
36 }
37
caryclark@google.coma7e483d2012-08-28 20:44:43 +000038 // start if index == 0 : end if index == 1
caryclark@google.com235f56a2012-09-14 14:19:30 +000039 void addCoincident(double one, double two) {
caryclark@google.com32546db2012-08-31 20:55:07 +000040 for (int index = 0; index < fCoincidentUsed; ++index) {
41 if (approximately_equal(fCoincidentT[fSwap][index], one)
42 && approximately_equal(fCoincidentT[fSwap ^ 1][index], two)) {
caryclark@google.com32546db2012-08-31 20:55:07 +000043 return;
44 }
caryclark@google.coma7e483d2012-08-28 20:44:43 +000045 }
caryclark@google.com235f56a2012-09-14 14:19:30 +000046 assert(fCoincidentUsed < 9);
caryclark@google.coma7e483d2012-08-28 20:44:43 +000047 fCoincidentT[fSwap][fCoincidentUsed] = one;
48 fCoincidentT[fSwap ^ 1][fCoincidentUsed] = two;
49 ++fCoincidentUsed;
50 }
51
caryclark@google.com235f56a2012-09-14 14:19:30 +000052 void addCoincident(double s1, double e1, double s2, double e2) {
53 assert((fCoincidentUsed & 1) != 1);
54 for (int index = 0; index < fCoincidentUsed; index += 2) {
55 double cs1 = fCoincidentT[fSwap][index];
56 double ce1 = fCoincidentT[fSwap][index + 1];
57 bool s1in = approximately_between(cs1, s1, ce1);
58 bool e1in = approximately_between(cs1, e1, ce1);
59 double cs2 = fCoincidentT[fSwap ^ 1][index];
60 double ce2 = fCoincidentT[fSwap ^ 1][index + 1];
61 bool s2in = approximately_between(cs2, s2, ce2);
62 bool e2in = approximately_between(cs2, e2, ce2);
63 if ((s1in | e1in) & (s2in | e2in)) {
64 double lesser1 = std::min(cs1, ce1);
65 index += cs1 > ce1;
66 if (s1in < lesser1) {
67 fCoincidentT[fSwap][index] = s1in;
68 } else if (e1in < lesser1) {
69 fCoincidentT[fSwap][index] = e1in;
70 }
71 index ^= 1;
72 double greater1 = fCoincidentT[fSwap][index];
73 if (s1in > greater1) {
74 fCoincidentT[fSwap][index] = s1in;
75 } else if (e1in > greater1) {
76 fCoincidentT[fSwap][index] = e1in;
77 }
78 index &= ~1;
79 double lesser2 = std::min(cs2, ce2);
80 index += cs2 > ce2;
81 if (s2in < lesser2) {
82 fCoincidentT[fSwap ^ 1][index] = s2in;
83 } else if (e2in < lesser2) {
84 fCoincidentT[fSwap ^ 1][index] = e2in;
85 }
86 index ^= 1;
87 double greater2 = fCoincidentT[fSwap ^ 1][index];
88 if (s2in > greater2) {
89 fCoincidentT[fSwap ^ 1][index] = s2in;
90 } else if (e2in > greater2) {
91 fCoincidentT[fSwap ^ 1][index] = e2in;
92 }
93 return;
94 }
95 }
96 assert(fCoincidentUsed < 9);
97 fCoincidentT[fSwap][fCoincidentUsed] = s1;
98 fCoincidentT[fSwap ^ 1][fCoincidentUsed] = s2;
99 ++fCoincidentUsed;
100 fCoincidentT[fSwap][fCoincidentUsed] = e1;
101 fCoincidentT[fSwap ^ 1][fCoincidentUsed] = e2;
102 ++fCoincidentUsed;
103 }
104
105 // FIXME: this is necessary because curve/curve intersections are noisy
106 // remove once curve/curve intersections are improved
107 void cleanUp();
108
caryclark@google.com32546db2012-08-31 20:55:07 +0000109 int coincidentUsed() {
110 return fCoincidentUsed;
111 }
112
caryclark@google.com639df892012-01-10 21:46:10 +0000113 void offset(int base, double start, double end) {
114 for (int index = base; index < fUsed; ++index) {
115 double val = fT[fSwap][index];
116 val *= end - start;
117 val += start;
118 fT[fSwap][index] = val;
119 }
120 }
skia.committer@gmail.com055c7c22012-09-15 02:01:41 +0000121
caryclark@google.com235f56a2012-09-14 14:19:30 +0000122 void insert(double one, double two) {
123 assert(fUsed <= 1 || fT[0][0] < fT[0][1]);
124 int index;
125 for (index = 0; index < fUsed; ++index) {
126 if (approximately_equal(fT[0][index], one)
127 && approximately_equal(fT[1][index], two)) {
128 return;
129 }
130 if (fT[0][index] > one) {
131 break;
132 }
133 }
134 assert(fUsed < 9);
135 int remaining = fUsed - index;
136 if (remaining > 0) {
137 memmove(&fT[0][index + 1], &fT[0][index], sizeof(fT[0][0]) * remaining);
138 memmove(&fT[1][index + 1], &fT[1][index], sizeof(fT[1][0]) * remaining);
139 }
140 fT[0][index] = one;
141 fT[1][index] = two;
142 ++fUsed;
143 }
skia.committer@gmail.com055c7c22012-09-15 02:01:41 +0000144
caryclark@google.com235f56a2012-09-14 14:19:30 +0000145 void insertOne(double t, int side) {
146 int used = side ? fUsed2 : fUsed;
147 assert(used <= 1 || fT[side][0] < fT[side][1]);
148 int index;
149 for (index = 0; index < used; ++index) {
150 if (approximately_equal(fT[side][index], t)) {
151 return;
152 }
153 if (fT[side][index] > t) {
154 break;
155 }
156 }
157 assert(used < 9);
158 int remaining = used - index;
159 if (remaining > 0) {
160 memmove(&fT[side][index + 1], &fT[side][index], sizeof(fT[side][0]) * remaining);
161 }
162 fT[side][index] = t;
163 side ? ++fUsed2 : ++fUsed;
164 }
caryclark@google.com639df892012-01-10 21:46:10 +0000165
caryclark@google.com235f56a2012-09-14 14:19:30 +0000166 bool intersected() const {
caryclark@google.com639df892012-01-10 21:46:10 +0000167 return fUsed > 0;
168 }
skia.committer@gmail.com055c7c22012-09-15 02:01:41 +0000169
caryclark@google.com235f56a2012-09-14 14:19:30 +0000170 bool insertBalanced() const {
171 return fUsed == fUsed2;
172 }
caryclark@google.com639df892012-01-10 21:46:10 +0000173
174 void swap() {
175 fSwap ^= 1;
176 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000177
caryclark@google.com639df892012-01-10 21:46:10 +0000178 bool swapped() {
179 return fSwap;
180 }
181
182 int used() {
183 return fUsed;
184 }
185
186 double fT[2][9];
caryclark@google.coma7e483d2012-08-28 20:44:43 +0000187 double fCoincidentT[2][9];
caryclark@google.com639df892012-01-10 21:46:10 +0000188 int fUsed;
caryclark@google.com235f56a2012-09-14 14:19:30 +0000189 int fUsed2;
caryclark@google.coma7e483d2012-08-28 20:44:43 +0000190 int fCoincidentUsed;
caryclark@google.coma5764232012-03-28 16:20:21 +0000191private:
caryclark@google.com639df892012-01-10 21:46:10 +0000192 int fSwap;
193};
caryclark@google.coma5764232012-03-28 16:20:21 +0000194
195#endif
196