Flutter Engine
The Flutter Engine
Public Types | Public Member Functions | Static Public Member Functions | Protected Member Functions | List of all members
LineCubicIntersections Class Reference

Public Types

enum  PinTPoint { kPointUninitialized , kPointInitialized }
 

Public Member Functions

 LineCubicIntersections (const SkDCubic &c, const SkDLine &l, SkIntersections *i)
 
void allowNear (bool allow)
 
void checkCoincident ()
 
int intersectRay (double roots[3])
 
int intersect ()
 
int horizontalIntersect (double axisIntercept, double left, double right, bool flipped)
 
bool uniqueAnswer (double cubicT, const SkDPoint &pt)
 
int verticalIntersect (double axisIntercept, double top, double bottom, bool flipped)
 

Static Public Member Functions

static int HorizontalIntersect (const SkDCubic &c, double axisIntercept, double roots[3])
 
static int VerticalIntersect (const SkDCubic &c, double axisIntercept, double roots[3])
 

Protected Member Functions

void addExactEndPoints ()
 
void addNearEndPoints ()
 
void addLineNearEndPoints ()
 
void addExactHorizontalEndPoints (double left, double right, double y)
 
void addNearHorizontalEndPoints (double left, double right, double y)
 
void addExactVerticalEndPoints (double top, double bottom, double x)
 
void addNearVerticalEndPoints (double top, double bottom, double x)
 
double findLineT (double t)
 
bool pinTs (double *cubicT, double *lineT, SkDPoint *pt, PinTPoint ptSet)
 

Detailed Description

Definition at line 87 of file SkDCubicLineIntersection.cpp.

Member Enumeration Documentation

◆ PinTPoint

Enumerator
kPointUninitialized 
kPointInitialized 

Definition at line 89 of file SkDCubicLineIntersection.cpp.

Constructor & Destructor Documentation

◆ LineCubicIntersections()

LineCubicIntersections::LineCubicIntersections ( const SkDCubic c,
const SkDLine l,
SkIntersections i 
)
inline

Definition at line 94 of file SkDCubicLineIntersection.cpp.

95 : fCubic(c)
96 , fLine(l)
97 , fIntersections(i)
98 , fAllowNear(true) {
99 i->setMax(4);
100 }

Member Function Documentation

◆ addExactEndPoints()

void LineCubicIntersections::addExactEndPoints ( )
inlineprotected

Definition at line 280 of file SkDCubicLineIntersection.cpp.

280 {
281 for (int cIndex = 0; cIndex < 4; cIndex += 3) {
282 double lineT = fLine.exactPoint(fCubic[cIndex]);
283 if (lineT < 0) {
284 continue;
285 }
286 double cubicT = (double) (cIndex >> 1);
287 fIntersections->insert(cubicT, lineT, fCubic[cIndex]);
288 }
289 }
int insert(double one, double two, const SkDPoint &pt)
double exactPoint(const SkDPoint &xy) const

◆ addExactHorizontalEndPoints()

void LineCubicIntersections::addExactHorizontalEndPoints ( double  left,
double  right,
double  y 
)
inlineprotected

Definition at line 323 of file SkDCubicLineIntersection.cpp.

323 {
324 for (int cIndex = 0; cIndex < 4; cIndex += 3) {
325 double lineT = SkDLine::ExactPointH(fCubic[cIndex], left, right, y);
326 if (lineT < 0) {
327 continue;
328 }
329 double cubicT = (double) (cIndex >> 1);
330 fIntersections->insert(cubicT, lineT, fCubic[cIndex]);
331 }
332 }
static bool left(const SkPoint &p0, const SkPoint &p1)
static bool right(const SkPoint &p0, const SkPoint &p1)
double y
static double ExactPointH(const SkDPoint &xy, double left, double right, double y)

◆ addExactVerticalEndPoints()

void LineCubicIntersections::addExactVerticalEndPoints ( double  top,
double  bottom,
double  x 
)
inlineprotected

Definition at line 349 of file SkDCubicLineIntersection.cpp.

349 {
350 for (int cIndex = 0; cIndex < 4; cIndex += 3) {
351 double lineT = SkDLine::ExactPointV(fCubic[cIndex], top, bottom, x);
352 if (lineT < 0) {
353 continue;
354 }
355 double cubicT = (double) (cIndex >> 1);
356 fIntersections->insert(cubicT, lineT, fCubic[cIndex]);
357 }
358 }
double x
static double ExactPointV(const SkDPoint &xy, double top, double bottom, double x)

◆ addLineNearEndPoints()

void LineCubicIntersections::addLineNearEndPoints ( )
inlineprotected

Definition at line 308 of file SkDCubicLineIntersection.cpp.

308 {
309 for (int lIndex = 0; lIndex < 2; ++lIndex) {
310 double lineT = (double) lIndex;
311 if (fIntersections->hasOppT(lineT)) {
312 continue;
313 }
314 double cubicT = ((const SkDCurve*)&fCubic)
315 ->nearPoint(SkPath::kCubic_Verb, fLine[lIndex], fLine[!lIndex]);
316 if (cubicT < 0) {
317 continue;
318 }
319 fIntersections->insert(cubicT, lineT, fLine[lIndex]);
320 }
321 }
bool hasOppT(double t) const
@ kCubic_Verb
Definition: SkPath.h:1470

◆ addNearEndPoints()

void LineCubicIntersections::addNearEndPoints ( )
inlineprotected

Definition at line 293 of file SkDCubicLineIntersection.cpp.

293 {
294 for (int cIndex = 0; cIndex < 4; cIndex += 3) {
295 double cubicT = (double) (cIndex >> 1);
296 if (fIntersections->hasT(cubicT)) {
297 continue;
298 }
299 double lineT = fLine.nearPoint(fCubic[cIndex], nullptr);
300 if (lineT < 0) {
301 continue;
302 }
303 fIntersections->insert(cubicT, lineT, fCubic[cIndex]);
304 }
305 this->addLineNearEndPoints();
306 }
bool hasT(double t) const
double nearPoint(const SkDPoint &xy, bool *unequal) const

◆ addNearHorizontalEndPoints()

void LineCubicIntersections::addNearHorizontalEndPoints ( double  left,
double  right,
double  y 
)
inlineprotected

Definition at line 334 of file SkDCubicLineIntersection.cpp.

334 {
335 for (int cIndex = 0; cIndex < 4; cIndex += 3) {
336 double cubicT = (double) (cIndex >> 1);
337 if (fIntersections->hasT(cubicT)) {
338 continue;
339 }
340 double lineT = SkDLine::NearPointH(fCubic[cIndex], left, right, y);
341 if (lineT < 0) {
342 continue;
343 }
344 fIntersections->insert(cubicT, lineT, fCubic[cIndex]);
345 }
346 this->addLineNearEndPoints();
347 }
static double NearPointH(const SkDPoint &xy, double left, double right, double y)

◆ addNearVerticalEndPoints()

void LineCubicIntersections::addNearVerticalEndPoints ( double  top,
double  bottom,
double  x 
)
inlineprotected

Definition at line 360 of file SkDCubicLineIntersection.cpp.

360 {
361 for (int cIndex = 0; cIndex < 4; cIndex += 3) {
362 double cubicT = (double) (cIndex >> 1);
363 if (fIntersections->hasT(cubicT)) {
364 continue;
365 }
366 double lineT = SkDLine::NearPointV(fCubic[cIndex], top, bottom, x);
367 if (lineT < 0) {
368 continue;
369 }
370 fIntersections->insert(cubicT, lineT, fCubic[cIndex]);
371 }
372 this->addLineNearEndPoints();
373 }
static double NearPointV(const SkDPoint &xy, double top, double bottom, double x)

◆ allowNear()

void LineCubicIntersections::allowNear ( bool  allow)
inline

Definition at line 102 of file SkDCubicLineIntersection.cpp.

102 {
103 fAllowNear = allow;
104 }

◆ checkCoincident()

void LineCubicIntersections::checkCoincident ( )
inline

Definition at line 106 of file SkDCubicLineIntersection.cpp.

106 {
107 int last = fIntersections->used() - 1;
108 for (int index = 0; index < last; ) {
109 double cubicMidT = ((*fIntersections)[0][index] + (*fIntersections)[0][index + 1]) / 2;
110 SkDPoint cubicMidPt = fCubic.ptAtT(cubicMidT);
111 double t = fLine.nearPoint(cubicMidPt, nullptr);
112 if (t < 0) {
113 ++index;
114 continue;
115 }
116 if (fIntersections->isCoincident(index)) {
117 fIntersections->removeOne(index);
118 --last;
119 } else if (fIntersections->isCoincident(index + 1)) {
120 fIntersections->removeOne(index + 1);
121 --last;
122 } else {
123 fIntersections->setCoincident(index++);
124 }
125 fIntersections->setCoincident(index);
126 }
127 }
void removeOne(int index)
int used() const
void setCoincident(int index)
bool isCoincident(int index)
SkDPoint ptAtT(double t) const

◆ findLineT()

double LineCubicIntersections::findLineT ( double  t)
inlineprotected

Definition at line 375 of file SkDCubicLineIntersection.cpp.

375 {
376 SkDPoint xy = fCubic.ptAtT(t);
377 double dx = fLine[1].fX - fLine[0].fX;
378 double dy = fLine[1].fY - fLine[0].fY;
379 if (fabs(dx) > fabs(dy)) {
380 return (xy.fX - fLine[0].fX) / dx;
381 }
382 return (xy.fY - fLine[0].fY) / dy;
383 }
skia_private::AutoTArray< sk_sp< SkImageFilter > > filters TypedMatrix matrix TypedMatrix matrix SkScalar dx
Definition: SkRecords.h:208

◆ HorizontalIntersect()

static int LineCubicIntersections::HorizontalIntersect ( const SkDCubic c,
double  axisIntercept,
double  roots[3] 
)
inlinestatic

Definition at line 176 of file SkDCubicLineIntersection.cpp.

176 {
177 double A, B, C, D;
178 SkDCubic::Coefficients(&c[0].fY, &A, &B, &C, &D);
179 D -= axisIntercept;
181 for (int index = 0; index < count; ++index) {
182 SkDPoint calcPt = c.ptAtT(roots[index]);
183 if (!approximately_equal(calcPt.fY, axisIntercept)) {
184 double extremeTs[6];
185 int extrema = SkDCubic::FindExtrema(&c[0].fY, extremeTs);
186 count = c.searchRoots(extremeTs, extrema, axisIntercept, SkDCubic::kYAxis, roots);
187 break;
188 }
189 }
190 return count;
191 }
int count
Definition: FontMgrTest.cpp:50
bool approximately_equal(double x, double y)
#define C(TEST_CATEGORY)
Definition: colrv1.cpp:248
#define B
static int FindExtrema(const double src[], double tValue[2])
static void Coefficients(const double *cubic, double *A, double *B, double *C, double *D)
int searchRoots(double extremes[6], int extrema, double axisIntercept, SearchAxis xAxis, double *validRoots) const
static int RootsValidT(const double A, const double B, const double C, double D, double s[3])

◆ horizontalIntersect()

int LineCubicIntersections::horizontalIntersect ( double  axisIntercept,
double  left,
double  right,
bool  flipped 
)
inline

Definition at line 193 of file SkDCubicLineIntersection.cpp.

193 {
194 addExactHorizontalEndPoints(left, right, axisIntercept);
195 if (fAllowNear) {
196 addNearHorizontalEndPoints(left, right, axisIntercept);
197 }
198 double roots[3];
199 int count = HorizontalIntersect(fCubic, axisIntercept, roots);
200 for (int index = 0; index < count; ++index) {
201 double cubicT = roots[index];
202 SkDPoint pt = { fCubic.ptAtT(cubicT).fX, axisIntercept };
203 double lineT = (pt.fX - left) / (right - left);
204 if (pinTs(&cubicT, &lineT, &pt, kPointInitialized) && uniqueAnswer(cubicT, pt)) {
205 fIntersections->insert(cubicT, lineT, pt);
206 }
207 }
208 if (flipped) {
209 fIntersections->flip();
210 }
212 return fIntersections->used();
213 }
void addNearHorizontalEndPoints(double left, double right, double y)
bool pinTs(double *cubicT, double *lineT, SkDPoint *pt, PinTPoint ptSet)
static int HorizontalIntersect(const SkDCubic &c, double axisIntercept, double roots[3])
void addExactHorizontalEndPoints(double left, double right, double y)
bool uniqueAnswer(double cubicT, const SkDPoint &pt)

◆ intersect()

int LineCubicIntersections::intersect ( )
inline

Definition at line 157 of file SkDCubicLineIntersection.cpp.

157 {
159 if (fAllowNear) {
161 }
162 double rootVals[3];
163 int roots = intersectRay(rootVals);
164 for (int index = 0; index < roots; ++index) {
165 double cubicT = rootVals[index];
166 double lineT = findLineT(cubicT);
167 SkDPoint pt;
168 if (pinTs(&cubicT, &lineT, &pt, kPointUninitialized) && uniqueAnswer(cubicT, pt)) {
169 fIntersections->insert(cubicT, lineT, pt);
170 }
171 }
173 return fIntersections->used();
174 }

◆ intersectRay()

int LineCubicIntersections::intersectRay ( double  roots[3])
inline

Definition at line 130 of file SkDCubicLineIntersection.cpp.

130 {
131 double adj = fLine[1].fX - fLine[0].fX;
132 double opp = fLine[1].fY - fLine[0].fY;
133 SkDCubic c;
134 SkDEBUGCODE(c.fDebugGlobalState = fIntersections->globalState());
135 for (int n = 0; n < 4; ++n) {
136 c[n].fX = (fCubic[n].fY - fLine[0].fY) * adj - (fCubic[n].fX - fLine[0].fX) * opp;
137 }
138 double A, B, C, D;
139 SkDCubic::Coefficients(&c[0].fX, &A, &B, &C, &D);
141 for (int index = 0; index < count; ++index) {
142 SkDPoint calcPt = c.ptAtT(roots[index]);
143 if (!approximately_zero(calcPt.fX)) {
144 for (int n = 0; n < 4; ++n) {
145 c[n].fY = (fCubic[n].fY - fLine[0].fY) * opp
146 + (fCubic[n].fX - fLine[0].fX) * adj;
147 }
148 double extremeTs[6];
149 int extrema = SkDCubic::FindExtrema(&c[0].fX, extremeTs);
150 count = c.searchRoots(extremeTs, extrema, 0, SkDCubic::kXAxis, roots);
151 break;
152 }
153 }
154 return count;
155 }
static bool approximately_zero(double x)
Definition: SkCubics.cpp:153
SkDEBUGCODE(SK_SPI) SkThreadID SkGetThreadID()

◆ pinTs()

bool LineCubicIntersections::pinTs ( double *  cubicT,
double *  lineT,
SkDPoint pt,
PinTPoint  ptSet 
)
inlineprotected

Definition at line 385 of file SkDCubicLineIntersection.cpp.

385 {
386 if (!approximately_one_or_less(*lineT)) {
387 return false;
388 }
389 if (!approximately_zero_or_more(*lineT)) {
390 return false;
391 }
392 double cT = *cubicT = SkPinT(*cubicT);
393 double lT = *lineT = SkPinT(*lineT);
394 SkDPoint lPt = fLine.ptAtT(lT);
395 SkDPoint cPt = fCubic.ptAtT(cT);
396 if (!lPt.roughlyEqual(cPt)) {
397 return false;
398 }
399 // FIXME: if points are roughly equal but not approximately equal, need to do
400 // a binary search like quad/quad intersection to find more precise t values
401 if (lT == 0 || lT == 1 || (ptSet == kPointUninitialized && cT != 0 && cT != 1)) {
402 *pt = lPt;
403 } else if (ptSet == kPointUninitialized) {
404 *pt = cPt;
405 }
406 SkPoint gridPt = pt->asSkPoint();
407 if (gridPt == fLine[0].asSkPoint()) {
408 *lineT = 0;
409 } else if (gridPt == fLine[1].asSkPoint()) {
410 *lineT = 1;
411 }
412 if (gridPt == fCubic[0].asSkPoint() && approximately_equal(*cubicT, 0)) {
413 *cubicT = 0;
414 } else if (gridPt == fCubic[3].asSkPoint() && approximately_equal(*cubicT, 1)) {
415 *cubicT = 1;
416 }
417 return true;
418 }
double SkPinT(double t)
bool approximately_one_or_less(double x)
bool approximately_zero_or_more(double x)
SkDPoint ptAtT(double t) const
SkPoint asSkPoint() const
bool roughlyEqual(const SkDPoint &a) const

◆ uniqueAnswer()

bool LineCubicIntersections::uniqueAnswer ( double  cubicT,
const SkDPoint pt 
)
inline

Definition at line 215 of file SkDCubicLineIntersection.cpp.

215 {
216 for (int inner = 0; inner < fIntersections->used(); ++inner) {
217 if (fIntersections->pt(inner) != pt) {
218 continue;
219 }
220 double existingCubicT = (*fIntersections)[0][inner];
221 if (cubicT == existingCubicT) {
222 return false;
223 }
224 // check if midway on cubic is also same point. If so, discard this
225 double cubicMidT = (existingCubicT + cubicT) / 2;
226 SkDPoint cubicMidPt = fCubic.ptAtT(cubicMidT);
227 if (cubicMidPt.approximatelyEqual(pt)) {
228 return false;
229 }
230 }
231#if ONE_OFF_DEBUG
232 SkDPoint cPt = fCubic.ptAtT(cubicT);
233 SkDebugf("%s pt=(%1.9g,%1.9g) cPt=(%1.9g,%1.9g)\n", __FUNCTION__, pt.fX, pt.fY,
234 cPt.fX, cPt.fY);
235#endif
236 return true;
237 }
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
const SkDPoint & pt(int index) const
bool approximatelyEqual(const SkDPoint &a) const

◆ VerticalIntersect()

static int LineCubicIntersections::VerticalIntersect ( const SkDCubic c,
double  axisIntercept,
double  roots[3] 
)
inlinestatic

Definition at line 239 of file SkDCubicLineIntersection.cpp.

239 {
240 double A, B, C, D;
241 SkDCubic::Coefficients(&c[0].fX, &A, &B, &C, &D);
242 D -= axisIntercept;
244 for (int index = 0; index < count; ++index) {
245 SkDPoint calcPt = c.ptAtT(roots[index]);
246 if (!approximately_equal(calcPt.fX, axisIntercept)) {
247 double extremeTs[6];
248 int extrema = SkDCubic::FindExtrema(&c[0].fX, extremeTs);
249 count = c.searchRoots(extremeTs, extrema, axisIntercept, SkDCubic::kXAxis, roots);
250 break;
251 }
252 }
253 return count;
254 }

◆ verticalIntersect()

int LineCubicIntersections::verticalIntersect ( double  axisIntercept,
double  top,
double  bottom,
bool  flipped 
)
inline

Definition at line 256 of file SkDCubicLineIntersection.cpp.

256 {
257 addExactVerticalEndPoints(top, bottom, axisIntercept);
258 if (fAllowNear) {
259 addNearVerticalEndPoints(top, bottom, axisIntercept);
260 }
261 double roots[3];
262 int count = VerticalIntersect(fCubic, axisIntercept, roots);
263 for (int index = 0; index < count; ++index) {
264 double cubicT = roots[index];
265 SkDPoint pt = { axisIntercept, fCubic.ptAtT(cubicT).fY };
266 double lineT = (pt.fY - top) / (bottom - top);
267 if (pinTs(&cubicT, &lineT, &pt, kPointInitialized) && uniqueAnswer(cubicT, pt)) {
268 fIntersections->insert(cubicT, lineT, pt);
269 }
270 }
271 if (flipped) {
272 fIntersections->flip();
273 }
275 return fIntersections->used();
276 }
void addExactVerticalEndPoints(double top, double bottom, double x)
void addNearVerticalEndPoints(double top, double bottom, double x)
static int VerticalIntersect(const SkDCubic &c, double axisIntercept, double roots[3])

The documentation for this class was generated from the following file: