/* started with at_most_end_pts_in_common from SkDQuadIntersection.cpp */ // Do a quick reject by rotating all points relative to a line formed by // a pair of one quad's points. If the 2nd quad's points // are on the line or on the opposite side from the 1st quad's 'odd man', the // curves at most intersect at the endpoints. /* if returning true, check contains true if quad's hull collapsed, making the cubic linear ifreturningfalse,checkcontainstrueifthethequadpairhaveonlytheendpointincommon
*/ bool SkDQuad::hullIntersects(const SkDQuad& q2, bool* isLinear) const { bool linear = true; for (int oddMan = 0; oddMan < kPointCount; ++oddMan) { const SkDPoint* endPt[2];
this->otherPts(oddMan, endPt); double origX = endPt[0]->fX; double origY = endPt[0]->fY; double adj = endPt[1]->fX - origX; double opp = endPt[1]->fY - origY; double sign = (fPts[oddMan].fY - origY) * adj - (fPts[oddMan].fX - origX) * opp; if (approximately_zero(sign)) { continue;
}
linear = false; bool foundOutlier = false; for (int n = 0; n < kPointCount; ++n) { double test = (q2[n].fY - origY) * adj - (q2[n].fX - origX) * opp; if (test * sign > 0 && !precisely_zero(test)) {
foundOutlier = true; break;
}
} if (!foundOutlier) { returnfalse;
}
} if (linear && !matchesEnd(fPts, q2.fPts[0]) && !matchesEnd(fPts, q2.fPts[2])) { // if the end point of the opposite quad is inside the hull that is nearly a line, // then representing the quad as a line may cause the intersection to be missed. // Check to see if the endpoint is in the triangle. if (pointInTriangle(fPts, q2.fPts[0]) || pointInTriangle(fPts, q2.fPts[2])) {
linear = false;
}
}
*isLinear = linear; return true;
}
/* bit twiddling for finding the off curve index (x&~m is the pair in [0,1,2] excluding oddMan) oddManoppx=oddMan^oppx=x-oddManm=x>>2x&~m 011101 22202 110-1-10 23202 213101 20-2-10
*/ void SkDQuad::otherPts(int oddMan, const SkDPoint* endPt[2]) const { for (int opp = 1; opp < kPointCount; ++opp) { int end = (oddMan ^ opp) - oddMan; // choose a value not equal to oddMan
end &= ~(end >> 2); // if the value went negative, set it to zero
endPt[opp - 1] = &fPts[end];
}
}
int SkDQuad::AddValidTs(double s[], int realRoots, double* t) { int foundRoots = 0; for (int index = 0; index < realRoots; ++index) { double tValue = s[index]; if (approximately_zero_or_more(tValue) && approximately_one_or_less(tValue)) { if (approximately_less_than_zero(tValue)) {
tValue = 0;
} elseif (approximately_greater_than_one(tValue)) {
tValue = 1;
} for (int idx2 = 0; idx2 < foundRoots; ++idx2) { if (approximately_equal(t[idx2], tValue)) { goto nextRoot;
}
}
t[foundRoots++] = tValue;
}
nextRoot:
{}
} return foundRoots;
}
// note: caller expects multiple results to be sorted smaller first // note: http://en.wikipedia.org/wiki/Loss_of_significance has an interesting // analysis of the quadratic equation, suggesting why the following looks at // the sign of B -- and further suggesting that the greatest loss of precision // is in b squared less two a c int SkDQuad::RootsValidT(double A, double B, double C, double t[2]) { double s[2]; int realRoots = RootsReal(A, B, C, s); int foundRoots = AddValidTs(s, realRoots, t); return foundRoots;
}
staticint valid_unit_divide(double numer, double denom, double* ratio)
{ if (numer < 0) {
numer = -numer;
denom = -denom;
} if (denom == 0 || numer == 0 || numer >= denom) { return0;
} double r = numer / denom; if (r == 0) { // catch underflow if numer <<<< denom return0;
}
*ratio = r; return1;
}
/** Quad'(t) = At + B, where A=2(a-2b+c) B=2(b-a) Solvefort,onlyifitfitsbetween0<t<1
*/ int SkDQuad::FindExtrema(constdouble src[], double tValue[1]) { /* At + B == 0 t=-B/A
*/ double a = src[0]; double b = src[2]; double c = src[4]; return valid_unit_divide(a - b, a - b - b + c, tValue);
}
/* Parameterization form, given A*t*t + 2*B*t*(1-t) + C*(1-t)*(1-t) * *a=A-2*B+C *b=2*B-2*C *c=C
*/ void SkDQuad::SetABC(constdouble* quad, double* a, double* b, double* c) {
*a = quad[0]; // a = A
*b = 2 * quad[2]; // b = 2*B
*c = quad[4]; // c = C
*b -= *c; // b = 2*B - C
*a -= *b; // a = A - 2*B + C
*b -= *c; // b = 2*B - 2*C
}
int SkTQuad::intersectRay(SkIntersections* i, const SkDLine& line) const { return i->intersectRay(fQuad, line);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.