/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
void DottedCornerFinder::FindPointAndRadius(Point& C, Float& r, const Point& innerTangent, const Point& normal, Float t) { // Find radius for the given tangent point on the inner curve such that the // circle is also tangent to the outer curve.
NS_ASSERTION(mType == OTHER, "Wrong mType");
Float lower = 0.0f; Float upper = mMaxR; constFloat DIST_MARGIN = 0.1f; for (size_t i = 0; i < MAX_LOOP; i++) {
r = (upper + lower) / 2.0f;
C = innerTangent + normal * r;
Point Near = FindBezierNearestPoint(mOuterBezier, C, t); Float distSquare = (C - Near).LengthSquare();
constFloat DIST_MARGIN = 0.1f; if (mType == SINGLE_CURVE_AND_RADIUS) {
r = mR0;
expectedDist = (r + mLastR) * factor;
// Find C_i on the center curve. for (size_t i = 0; i < MAX_LOOP; i++) {
t = (upper + lower) / 2.0f;
C = GetBezierPoint(mCenterBezier, t);
// Check overlap along arc.
circlesDist = GetBezierLength(mCenterBezier, mLastT, t); if (circlesDist < expectedDist - DIST_MARGIN) {
lower = t;
} elseif (circlesDist > expectedDist + DIST_MARGIN) {
upper = t;
} else { break;
}
}
} elseif (mType == SINGLE_CURVE) { // Find C_i on the center curve, and calculate r_i. for (size_t i = 0; i < MAX_LOOP; i++) {
t = (upper + lower) / 2.0f;
C = GetBezierPoint(mCenterBezier, t);
Point Diff = GetBezierDifferential(mCenterBezier, t); Float DiffLength = Diff.Length(); if (DiffLength == 0.0f) { // Basically this shouldn't happen. // If differential is 0, we cannot calculate tangent circle, // skip this point.
t = (t + upper) / 2.0f; continue;
}
Point normal = PointRotateCCW90(Diff / DiffLength) * (-mNormalSign);
r = CalculateDistanceToEllipticArc(C, normal, mInnerCurveOrigin,
mInnerWidth, mInnerHeight);
// Find C_i and r_i. for (size_t i = 0; i < MAX_LOOP; i++) {
t = (upper + lower) / 2.0f;
Point innerTangent = GetBezierPoint(mInnerBezier, t); if ((innerTangent - mLastC).LengthSquare() > distSquareMax) { // It's clear that this tangent point is too far, skip it.
upper = t; continue;
}
Point Diff = GetBezierDifferential(mInnerBezier, t); Float DiffLength = Diff.Length(); if (DiffLength == 0.0f) { // Basically this shouldn't happen. // If differential is 0, we cannot calculate tangent circle, // skip this point.
t = (t + upper) / 2.0f; continue;
}
Point normal = PointRotateCCW90(Diff / DiffLength) * mNormalSign;
FindPointAndRadius(C, r, innerTangent, normal, t);
if (mHasZeroBorderWidth) { // When calculating circle around r=0, it may result in wrong radius that // is bigger than previous circle. Detect it and stop calculating. constFloat R_MARGIN = 0.1f; if (mLastR < R_MARGIN && r > mLastR) {
mHasMore = false;
mLastR = 0.0f; return 0.0f;
}
}
void DottedCornerFinder::FindBestOverlap(Float aMinR, Float aMinBorderRadius, Float aMaxBorderRadius) { // If overlap is not calculateable, find it with binary search, // such that there exists i that C_i == C_n with the given overlap.
if (count == targetCount) {
mBestOverlap = overlap;
if (fabs(actualOverlap - overlap) < OVERLAP_MARGIN) { break;
}
// We started from upper bound, no need to update range when j == 0. if (j > 0) { if (actualOverlap > overlap) {
lower = overlap;
} else {
upper = overlap;
}
}
} else { // |j == 0 && count != targetCount| means that |targetCount = count + 1|, // and we started from upper bound, no need to update range when j == 0. if (j > 0) { if (count > targetCount) {
upper = overlap;
} else {
lower = overlap;
}
}
}
bool DottedCornerFinder::GetCountAndLastOverlap(Float aOverlap, size_t* aCount, Float* aActualOverlap) { // Return the number of circles and the last circles' overlap for the // given overlap.
Reset();
constFloat T_MARGIN = 0.001f; constFloat DIST_MARGIN = 0.1f; constFloat DIST_MARGIN_SQUARE = Square(DIST_MARGIN); for (size_t i = 0; i < mMaxCount; i++) { Float actualOverlap = FindNext(aOverlap); if (mLastT >= 1.0f - T_MARGIN ||
(mLastC - mCn).LengthSquare() < DIST_MARGIN_SQUARE) {
*aCount = i + 1;
*aActualOverlap = actualOverlap; returntrue;
}
}
returnfalse;
}
} // namespace mozilla
¤ Dauer der Verarbeitung: 0.15 Sekunden
(vorverarbeitet)
¤
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 ist noch experimentell.