blob: fe12b259028048ba69a3f835e12cd7838e65ae65 [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)
caryclark@google.com6aea33f2012-10-09 14:11:58 +000019 , fFlip(0)
caryclark@google.com639df892012-01-10 21:46:10 +000020 {
caryclark@google.coma7e483d2012-08-28 20:44:43 +000021 // OPTIMIZE: don't need to be initialized in release
caryclark@google.com639df892012-01-10 21:46:10 +000022 bzero(fT, sizeof(fT));
caryclark@google.coma7e483d2012-08-28 20:44:43 +000023 bzero(fCoincidentT, sizeof(fCoincidentT));
caryclark@google.com639df892012-01-10 21:46:10 +000024 }
25
26 void add(double one, double two) {
caryclark@google.com32546db2012-08-31 20:55:07 +000027 for (int index = 0; index < fUsed; ++index) {
28 if (approximately_equal(fT[fSwap][index], one)
29 && approximately_equal(fT[fSwap ^ 1][index], two)) {
30 return;
31 }
caryclark@google.com639df892012-01-10 21:46:10 +000032 }
caryclark@google.com235f56a2012-09-14 14:19:30 +000033 assert(fUsed < 9);
caryclark@google.com639df892012-01-10 21:46:10 +000034 fT[fSwap][fUsed] = one;
35 fT[fSwap ^ 1][fUsed] = two;
36 ++fUsed;
37 }
38
caryclark@google.coma7e483d2012-08-28 20:44:43 +000039 // start if index == 0 : end if index == 1
caryclark@google.com235f56a2012-09-14 14:19:30 +000040 void addCoincident(double one, double two) {
caryclark@google.com32546db2012-08-31 20:55:07 +000041 for (int index = 0; index < fCoincidentUsed; ++index) {
42 if (approximately_equal(fCoincidentT[fSwap][index], one)
43 && approximately_equal(fCoincidentT[fSwap ^ 1][index], two)) {
caryclark@google.com32546db2012-08-31 20:55:07 +000044 return;
45 }
caryclark@google.coma7e483d2012-08-28 20:44:43 +000046 }
caryclark@google.com235f56a2012-09-14 14:19:30 +000047 assert(fCoincidentUsed < 9);
caryclark@google.coma7e483d2012-08-28 20:44:43 +000048 fCoincidentT[fSwap][fCoincidentUsed] = one;
49 fCoincidentT[fSwap ^ 1][fCoincidentUsed] = two;
50 ++fCoincidentUsed;
51 }
52
caryclark@google.com235f56a2012-09-14 14:19:30 +000053 void addCoincident(double s1, double e1, double s2, double e2) {
54 assert((fCoincidentUsed & 1) != 1);
55 for (int index = 0; index < fCoincidentUsed; index += 2) {
56 double cs1 = fCoincidentT[fSwap][index];
57 double ce1 = fCoincidentT[fSwap][index + 1];
58 bool s1in = approximately_between(cs1, s1, ce1);
59 bool e1in = approximately_between(cs1, e1, ce1);
60 double cs2 = fCoincidentT[fSwap ^ 1][index];
61 double ce2 = fCoincidentT[fSwap ^ 1][index + 1];
62 bool s2in = approximately_between(cs2, s2, ce2);
63 bool e2in = approximately_between(cs2, e2, ce2);
64 if ((s1in | e1in) & (s2in | e2in)) {
65 double lesser1 = std::min(cs1, ce1);
66 index += cs1 > ce1;
67 if (s1in < lesser1) {
68 fCoincidentT[fSwap][index] = s1in;
69 } else if (e1in < lesser1) {
70 fCoincidentT[fSwap][index] = e1in;
71 }
72 index ^= 1;
73 double greater1 = fCoincidentT[fSwap][index];
74 if (s1in > greater1) {
75 fCoincidentT[fSwap][index] = s1in;
76 } else if (e1in > greater1) {
77 fCoincidentT[fSwap][index] = e1in;
78 }
79 index &= ~1;
80 double lesser2 = std::min(cs2, ce2);
81 index += cs2 > ce2;
82 if (s2in < lesser2) {
83 fCoincidentT[fSwap ^ 1][index] = s2in;
84 } else if (e2in < lesser2) {
85 fCoincidentT[fSwap ^ 1][index] = e2in;
86 }
87 index ^= 1;
88 double greater2 = fCoincidentT[fSwap ^ 1][index];
89 if (s2in > greater2) {
90 fCoincidentT[fSwap ^ 1][index] = s2in;
91 } else if (e2in > greater2) {
92 fCoincidentT[fSwap ^ 1][index] = e2in;
93 }
94 return;
95 }
96 }
97 assert(fCoincidentUsed < 9);
98 fCoincidentT[fSwap][fCoincidentUsed] = s1;
99 fCoincidentT[fSwap ^ 1][fCoincidentUsed] = s2;
100 ++fCoincidentUsed;
101 fCoincidentT[fSwap][fCoincidentUsed] = e1;
102 fCoincidentT[fSwap ^ 1][fCoincidentUsed] = e2;
103 ++fCoincidentUsed;
104 }
105
106 // FIXME: this is necessary because curve/curve intersections are noisy
107 // remove once curve/curve intersections are improved
108 void cleanUp();
109
caryclark@google.com32546db2012-08-31 20:55:07 +0000110 int coincidentUsed() {
111 return fCoincidentUsed;
112 }
113
caryclark@google.com639df892012-01-10 21:46:10 +0000114 void offset(int base, double start, double end) {
115 for (int index = base; index < fUsed; ++index) {
116 double val = fT[fSwap][index];
117 val *= end - start;
118 val += start;
119 fT[fSwap][index] = val;
120 }
121 }
skia.committer@gmail.com055c7c22012-09-15 02:01:41 +0000122
caryclark@google.com235f56a2012-09-14 14:19:30 +0000123 void insert(double one, double two) {
124 assert(fUsed <= 1 || fT[0][0] < fT[0][1]);
125 int index;
126 for (index = 0; index < fUsed; ++index) {
127 if (approximately_equal(fT[0][index], one)
128 && approximately_equal(fT[1][index], two)) {
129 return;
130 }
131 if (fT[0][index] > one) {
132 break;
133 }
134 }
135 assert(fUsed < 9);
136 int remaining = fUsed - index;
137 if (remaining > 0) {
138 memmove(&fT[0][index + 1], &fT[0][index], sizeof(fT[0][0]) * remaining);
139 memmove(&fT[1][index + 1], &fT[1][index], sizeof(fT[1][0]) * remaining);
140 }
141 fT[0][index] = one;
142 fT[1][index] = two;
143 ++fUsed;
144 }
skia.committer@gmail.com055c7c22012-09-15 02:01:41 +0000145
caryclark@google.comfb51afb2012-10-19 15:54:16 +0000146 // FIXME: all callers should be moved to regular insert. Failures are likely
147 // if two separate callers differ on whether ts are equal or not
caryclark@google.com235f56a2012-09-14 14:19:30 +0000148 void insertOne(double t, int side) {
149 int used = side ? fUsed2 : fUsed;
150 assert(used <= 1 || fT[side][0] < fT[side][1]);
151 int index;
152 for (index = 0; index < used; ++index) {
153 if (approximately_equal(fT[side][index], t)) {
154 return;
155 }
156 if (fT[side][index] > t) {
157 break;
158 }
159 }
160 assert(used < 9);
161 int remaining = used - index;
162 if (remaining > 0) {
163 memmove(&fT[side][index + 1], &fT[side][index], sizeof(fT[side][0]) * remaining);
164 }
165 fT[side][index] = t;
166 side ? ++fUsed2 : ++fUsed;
167 }
caryclark@google.com639df892012-01-10 21:46:10 +0000168
caryclark@google.com235f56a2012-09-14 14:19:30 +0000169 bool intersected() const {
caryclark@google.com639df892012-01-10 21:46:10 +0000170 return fUsed > 0;
171 }
skia.committer@gmail.com055c7c22012-09-15 02:01:41 +0000172
caryclark@google.com235f56a2012-09-14 14:19:30 +0000173 bool insertBalanced() const {
174 return fUsed == fUsed2;
175 }
caryclark@google.com639df892012-01-10 21:46:10 +0000176
177 void swap() {
178 fSwap ^= 1;
179 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000180
caryclark@google.com639df892012-01-10 21:46:10 +0000181 bool swapped() {
182 return fSwap;
183 }
184
185 int used() {
186 return fUsed;
187 }
188
189 double fT[2][9];
caryclark@google.coma7e483d2012-08-28 20:44:43 +0000190 double fCoincidentT[2][9];
caryclark@google.com639df892012-01-10 21:46:10 +0000191 int fUsed;
caryclark@google.com235f56a2012-09-14 14:19:30 +0000192 int fUsed2;
caryclark@google.coma7e483d2012-08-28 20:44:43 +0000193 int fCoincidentUsed;
caryclark@google.com6aea33f2012-10-09 14:11:58 +0000194 int fFlip;
caryclark@google.coma5764232012-03-28 16:20:21 +0000195private:
caryclark@google.com639df892012-01-10 21:46:10 +0000196 int fSwap;
197};
caryclark@google.coma5764232012-03-28 16:20:21 +0000198
199#endif
200