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

Public Types

enum  PinTPoint { kPointUninitialized , kPointInitialized }
 

Public Member Functions

 LineQuadraticIntersections (const SkDQuad &q, const SkDLine &l, SkIntersections *i)
 
 LineQuadraticIntersections (const SkDQuad &q)
 
void allowNear (bool allow)
 
void checkCoincident ()
 
int intersectRay (double roots[2])
 
int intersect ()
 
int horizontalIntersect (double axisIntercept, double roots[2])
 
int horizontalIntersect (double axisIntercept, double left, double right, bool flipped)
 
bool uniqueAnswer (double quadT, const SkDPoint &pt)
 
int verticalIntersect (double axisIntercept, double roots[2])
 
int verticalIntersect (double axisIntercept, double top, double bottom, bool flipped)
 

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 *quadT, double *lineT, SkDPoint *pt, PinTPoint ptSet)
 

Detailed Description

Definition at line 98 of file SkDQuadLineIntersection.cpp.

Member Enumeration Documentation

◆ PinTPoint

Enumerator
kPointUninitialized 
kPointInitialized 

Definition at line 100 of file SkDQuadLineIntersection.cpp.

Constructor & Destructor Documentation

◆ LineQuadraticIntersections() [1/2]

LineQuadraticIntersections::LineQuadraticIntersections ( const SkDQuad q,
const SkDLine l,
SkIntersections i 
)
inline

Definition at line 105 of file SkDQuadLineIntersection.cpp.

106 : fQuad(q)
107 , fLine(&l)
108 , fIntersections(i)
109 , fAllowNear(true) {
110 i->setMax(5); // allow short partial coincidence plus discrete intersections
111 }

◆ LineQuadraticIntersections() [2/2]

LineQuadraticIntersections::LineQuadraticIntersections ( const SkDQuad q)
inline

Definition at line 113 of file SkDQuadLineIntersection.cpp.

114 : fQuad(q)
115 SkDEBUGPARAMS(fLine(nullptr))
116 SkDEBUGPARAMS(fIntersections(nullptr))
117 SkDEBUGPARAMS(fAllowNear(false)) {
118 }
#define SkDEBUGPARAMS(...)

Member Function Documentation

◆ addExactEndPoints()

void LineQuadraticIntersections::addExactEndPoints ( )
inlineprotected

Definition at line 286 of file SkDQuadLineIntersection.cpp.

286 {
287 for (int qIndex = 0; qIndex < 3; qIndex += 2) {
288 double lineT = fLine->exactPoint(fQuad[qIndex]);
289 if (lineT < 0) {
290 continue;
291 }
292 double quadT = (double) (qIndex >> 1);
293 fIntersections->insert(quadT, lineT, fQuad[qIndex]);
294 }
295 }
int insert(double one, double two, const SkDPoint &pt)
double exactPoint(const SkDPoint &xy) const

◆ addExactHorizontalEndPoints()

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

Definition at line 327 of file SkDQuadLineIntersection.cpp.

327 {
328 for (int qIndex = 0; qIndex < 3; qIndex += 2) {
329 double lineT = SkDLine::ExactPointH(fQuad[qIndex], left, right, y);
330 if (lineT < 0) {
331 continue;
332 }
333 double quadT = (double) (qIndex >> 1);
334 fIntersections->insert(quadT, lineT, fQuad[qIndex]);
335 }
336 }
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 LineQuadraticIntersections::addExactVerticalEndPoints ( double  top,
double  bottom,
double  x 
)
inlineprotected

Definition at line 353 of file SkDQuadLineIntersection.cpp.

353 {
354 for (int qIndex = 0; qIndex < 3; qIndex += 2) {
355 double lineT = SkDLine::ExactPointV(fQuad[qIndex], top, bottom, x);
356 if (lineT < 0) {
357 continue;
358 }
359 double quadT = (double) (qIndex >> 1);
360 fIntersections->insert(quadT, lineT, fQuad[qIndex]);
361 }
362 }
double x
static double ExactPointV(const SkDPoint &xy, double top, double bottom, double x)

◆ addLineNearEndPoints()

void LineQuadraticIntersections::addLineNearEndPoints ( )
inlineprotected

Definition at line 312 of file SkDQuadLineIntersection.cpp.

312 {
313 for (int lIndex = 0; lIndex < 2; ++lIndex) {
314 double lineT = (double) lIndex;
315 if (fIntersections->hasOppT(lineT)) {
316 continue;
317 }
318 double quadT = ((const SkDCurve*) &fQuad)->nearPoint(SkPath::kQuad_Verb,
319 (*fLine)[lIndex], (*fLine)[!lIndex]);
320 if (quadT < 0) {
321 continue;
322 }
323 fIntersections->insert(quadT, lineT, (*fLine)[lIndex]);
324 }
325 }
bool hasOppT(double t) const
@ kQuad_Verb
Definition: SkPath.h:1468

◆ addNearEndPoints()

void LineQuadraticIntersections::addNearEndPoints ( )
inlineprotected

Definition at line 297 of file SkDQuadLineIntersection.cpp.

297 {
298 for (int qIndex = 0; qIndex < 3; qIndex += 2) {
299 double quadT = (double) (qIndex >> 1);
300 if (fIntersections->hasT(quadT)) {
301 continue;
302 }
303 double lineT = fLine->nearPoint(fQuad[qIndex], nullptr);
304 if (lineT < 0) {
305 continue;
306 }
307 fIntersections->insert(quadT, lineT, fQuad[qIndex]);
308 }
309 this->addLineNearEndPoints();
310 }
bool hasT(double t) const
double nearPoint(const SkDPoint &xy, bool *unequal) const

◆ addNearHorizontalEndPoints()

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

Definition at line 338 of file SkDQuadLineIntersection.cpp.

338 {
339 for (int qIndex = 0; qIndex < 3; qIndex += 2) {
340 double quadT = (double) (qIndex >> 1);
341 if (fIntersections->hasT(quadT)) {
342 continue;
343 }
344 double lineT = SkDLine::NearPointH(fQuad[qIndex], left, right, y);
345 if (lineT < 0) {
346 continue;
347 }
348 fIntersections->insert(quadT, lineT, fQuad[qIndex]);
349 }
350 this->addLineNearEndPoints();
351 }
static double NearPointH(const SkDPoint &xy, double left, double right, double y)

◆ addNearVerticalEndPoints()

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

Definition at line 364 of file SkDQuadLineIntersection.cpp.

364 {
365 for (int qIndex = 0; qIndex < 3; qIndex += 2) {
366 double quadT = (double) (qIndex >> 1);
367 if (fIntersections->hasT(quadT)) {
368 continue;
369 }
370 double lineT = SkDLine::NearPointV(fQuad[qIndex], top, bottom, x);
371 if (lineT < 0) {
372 continue;
373 }
374 fIntersections->insert(quadT, lineT, fQuad[qIndex]);
375 }
376 this->addLineNearEndPoints();
377 }
static double NearPointV(const SkDPoint &xy, double top, double bottom, double x)

◆ allowNear()

void LineQuadraticIntersections::allowNear ( bool  allow)
inline

Definition at line 120 of file SkDQuadLineIntersection.cpp.

120 {
121 fAllowNear = allow;
122 }

◆ checkCoincident()

void LineQuadraticIntersections::checkCoincident ( )
inline

Definition at line 124 of file SkDQuadLineIntersection.cpp.

124 {
125 int last = fIntersections->used() - 1;
126 for (int index = 0; index < last; ) {
127 double quadMidT = ((*fIntersections)[0][index] + (*fIntersections)[0][index + 1]) / 2;
128 SkDPoint quadMidPt = fQuad.ptAtT(quadMidT);
129 double t = fLine->nearPoint(quadMidPt, nullptr);
130 if (t < 0) {
131 ++index;
132 continue;
133 }
134 if (fIntersections->isCoincident(index)) {
135 fIntersections->removeOne(index);
136 --last;
137 } else if (fIntersections->isCoincident(index + 1)) {
138 fIntersections->removeOne(index + 1);
139 --last;
140 } else {
141 fIntersections->setCoincident(index++);
142 }
143 fIntersections->setCoincident(index);
144 }
145 }
void removeOne(int index)
int used() const
void setCoincident(int index)
bool isCoincident(int index)
SkDPoint ptAtT(double t) const

◆ findLineT()

double LineQuadraticIntersections::findLineT ( double  t)
inlineprotected

Definition at line 379 of file SkDQuadLineIntersection.cpp.

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

◆ horizontalIntersect() [1/2]

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

Definition at line 206 of file SkDQuadLineIntersection.cpp.

206 {
207 addExactHorizontalEndPoints(left, right, axisIntercept);
208 if (fAllowNear) {
209 addNearHorizontalEndPoints(left, right, axisIntercept);
210 }
211 double rootVals[2];
212 int roots = horizontalIntersect(axisIntercept, rootVals);
213 for (int index = 0; index < roots; ++index) {
214 double quadT = rootVals[index];
215 SkDPoint pt = fQuad.ptAtT(quadT);
216 double lineT = (pt.fX - left) / (right - left);
217 if (pinTs(&quadT, &lineT, &pt, kPointInitialized) && uniqueAnswer(quadT, pt)) {
218 fIntersections->insert(quadT, lineT, pt);
219 }
220 }
221 if (flipped) {
222 fIntersections->flip();
223 }
225 return fIntersections->used();
226 }
void addExactHorizontalEndPoints(double left, double right, double y)
void addNearHorizontalEndPoints(double left, double right, double y)
bool uniqueAnswer(double quadT, const SkDPoint &pt)
int horizontalIntersect(double axisIntercept, double roots[2])
bool pinTs(double *quadT, double *lineT, SkDPoint *pt, PinTPoint ptSet)

◆ horizontalIntersect() [2/2]

int LineQuadraticIntersections::horizontalIntersect ( double  axisIntercept,
double  roots[2] 
)
inline

Definition at line 196 of file SkDQuadLineIntersection.cpp.

196 {
197 double D = fQuad[2].fY; // f
198 double E = fQuad[1].fY; // e
199 double F = fQuad[0].fY; // d
200 D += F - 2 * E; // D = d - 2*e + f
201 E -= F; // E = -(d - e)
202 F -= axisIntercept;
203 return SkDQuad::RootsValidT(D, 2 * E, F, roots);
204 }
#define F(x)
Definition: SkMD5.cpp:120
static int RootsValidT(const double A, const double B, const double C, double s[2])

◆ intersect()

int LineQuadraticIntersections::intersect ( )
inline

Definition at line 177 of file SkDQuadLineIntersection.cpp.

177 {
179 if (fAllowNear) {
181 }
182 double rootVals[2];
183 int roots = intersectRay(rootVals);
184 for (int index = 0; index < roots; ++index) {
185 double quadT = rootVals[index];
186 double lineT = findLineT(quadT);
187 SkDPoint pt;
188 if (pinTs(&quadT, &lineT, &pt, kPointUninitialized) && uniqueAnswer(quadT, pt)) {
189 fIntersections->insert(quadT, lineT, pt);
190 }
191 }
193 return fIntersections->used();
194 }

◆ intersectRay()

int LineQuadraticIntersections::intersectRay ( double  roots[2])
inline

Definition at line 147 of file SkDQuadLineIntersection.cpp.

147 {
148 /*
149 solve by rotating line+quad so line is horizontal, then finding the roots
150 set up matrix to rotate quad to x-axis
151 |cos(a) -sin(a)|
152 |sin(a) cos(a)|
153 note that cos(a) = A(djacent) / Hypoteneuse
154 sin(a) = O(pposite) / Hypoteneuse
155 since we are computing Ts, we can ignore hypoteneuse, the scale factor:
156 | A -O |
157 | O A |
158 A = line[1].fX - line[0].fX (adjacent side of the right triangle)
159 O = line[1].fY - line[0].fY (opposite side of the right triangle)
160 for each of the three points (e.g. n = 0 to 2)
161 quad[n].fY' = (quad[n].fY - line[0].fY) * A - (quad[n].fX - line[0].fX) * O
162 */
163 double adj = (*fLine)[1].fX - (*fLine)[0].fX;
164 double opp = (*fLine)[1].fY - (*fLine)[0].fY;
165 double r[3];
166 for (int n = 0; n < 3; ++n) {
167 r[n] = (fQuad[n].fY - (*fLine)[0].fY) * adj - (fQuad[n].fX - (*fLine)[0].fX) * opp;
168 }
169 double A = r[2];
170 double B = r[1];
171 double C = r[0];
172 A += C - 2 * B; // A = a - 2*b + c
173 B -= C; // B = -(b - c)
174 return SkDQuad::RootsValidT(A, 2 * B, C, roots);
175 }
#define C(TEST_CATEGORY)
Definition: colrv1.cpp:248
#define B

◆ pinTs()

bool LineQuadraticIntersections::pinTs ( double *  quadT,
double *  lineT,
SkDPoint pt,
PinTPoint  ptSet 
)
inlineprotected

Definition at line 389 of file SkDQuadLineIntersection.cpp.

389 {
391 return false;
392 }
394 return false;
395 }
396 double qT = *quadT = SkPinT(*quadT);
397 double lT = *lineT = SkPinT(*lineT);
398 if (lT == 0 || lT == 1 || (ptSet == kPointUninitialized && qT != 0 && qT != 1)) {
399 *pt = (*fLine).ptAtT(lT);
400 } else if (ptSet == kPointUninitialized) {
401 *pt = fQuad.ptAtT(qT);
402 }
403 SkPoint gridPt = pt->asSkPoint();
404 if (SkDPoint::ApproximatelyEqual(gridPt, (*fLine)[0].asSkPoint())) {
405 *pt = (*fLine)[0];
406 *lineT = 0;
407 } else if (SkDPoint::ApproximatelyEqual(gridPt, (*fLine)[1].asSkPoint())) {
408 *pt = (*fLine)[1];
409 *lineT = 1;
410 }
411 if (fIntersections->used() > 0 && approximately_equal((*fIntersections)[1][0], *lineT)) {
412 return false;
413 }
414 if (gridPt == fQuad[0].asSkPoint()) {
415 *pt = fQuad[0];
416 *quadT = 0;
417 } else if (gridPt == fQuad[2].asSkPoint()) {
418 *pt = fQuad[2];
419 *quadT = 1;
420 }
421 return true;
422 }
bool approximately_equal(double x, double y)
bool approximately_one_or_less_double(double x)
double SkPinT(double t)
bool approximately_zero_or_more_double(double x)
SkPoint asSkPoint() const
static bool ApproximatelyEqual(const SkPoint &a, const SkPoint &b)

◆ uniqueAnswer()

bool LineQuadraticIntersections::uniqueAnswer ( double  quadT,
const SkDPoint pt 
)
inline

Definition at line 228 of file SkDQuadLineIntersection.cpp.

228 {
229 for (int inner = 0; inner < fIntersections->used(); ++inner) {
230 if (fIntersections->pt(inner) != pt) {
231 continue;
232 }
233 double existingQuadT = (*fIntersections)[0][inner];
234 if (quadT == existingQuadT) {
235 return false;
236 }
237 // check if midway on quad is also same point. If so, discard this
238 double quadMidT = (existingQuadT + quadT) / 2;
239 SkDPoint quadMidPt = fQuad.ptAtT(quadMidT);
240 if (quadMidPt.approximatelyEqual(pt)) {
241 return false;
242 }
243 }
244#if ONE_OFF_DEBUG
245 SkDPoint qPt = fQuad.ptAtT(quadT);
246 SkDebugf("%s pt=(%1.9g,%1.9g) cPt=(%1.9g,%1.9g)\n", __FUNCTION__, pt.fX, pt.fY,
247 qPt.fX, qPt.fY);
248#endif
249 return true;
250 }
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
const SkDPoint & pt(int index) const
bool approximatelyEqual(const SkDPoint &a) const

◆ verticalIntersect() [1/2]

int LineQuadraticIntersections::verticalIntersect ( double  axisIntercept,
double  roots[2] 
)
inline

Definition at line 252 of file SkDQuadLineIntersection.cpp.

252 {
253 double D = fQuad[2].fX; // f
254 double E = fQuad[1].fX; // e
255 double F = fQuad[0].fX; // d
256 D += F - 2 * E; // D = d - 2*e + f
257 E -= F; // E = -(d - e)
258 F -= axisIntercept;
259 return SkDQuad::RootsValidT(D, 2 * E, F, roots);
260 }

◆ verticalIntersect() [2/2]

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

Definition at line 262 of file SkDQuadLineIntersection.cpp.

262 {
263 addExactVerticalEndPoints(top, bottom, axisIntercept);
264 if (fAllowNear) {
265 addNearVerticalEndPoints(top, bottom, axisIntercept);
266 }
267 double rootVals[2];
268 int roots = verticalIntersect(axisIntercept, rootVals);
269 for (int index = 0; index < roots; ++index) {
270 double quadT = rootVals[index];
271 SkDPoint pt = fQuad.ptAtT(quadT);
272 double lineT = (pt.fY - top) / (bottom - top);
273 if (pinTs(&quadT, &lineT, &pt, kPointInitialized) && uniqueAnswer(quadT, pt)) {
274 fIntersections->insert(quadT, lineT, pt);
275 }
276 }
277 if (flipped) {
278 fIntersections->flip();
279 }
281 return fIntersections->used();
282 }
int verticalIntersect(double axisIntercept, double roots[2])
void addExactVerticalEndPoints(double top, double bottom, double x)
void addNearVerticalEndPoints(double top, double bottom, double x)

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