88 assert(sb.
size() > 0);
95 if (sb[q-1][0] == sb[q-1][1])
109 q = (sz > 2*sb.
size()-1) ? sb.
size() : (sz+1)/2;
115 for (
size_t k = 0; k < q; ++k)
118 for (
size_t j = k; j < n-k; ++j)
120 bz[j] += (Tjk * sb[k][0]);
121 bz[n-j] += (Tjk * sb[k][1]);
133 for (
size_t j = 1; j < n; ++j)
176 double delx[2], dely[2];
177 double xprime[2], yprime[2];
180 double midx_0, midy_0;
181 double numer[2], numer_0[2];
185 if ((sb[
X].
size() == 0) || (sb[
Y].
size() == 0)) {
186 THROW_RANGEERROR(
"size of sb is too small");
196 for (
int i = 0; i < 2; ++i) {
197 xprime[i] = sb[
X][0][1] - sb[
X][0][0];
198 yprime[i] = sb[
Y][0][1] - sb[
Y][0][0];
200 if (sb[
X].
size() > 1) {
201 xprime[0] += sb[
X][1][0];
202 xprime[1] -= sb[
X][1][1];
204 if (sb[
Y].
size() > 1) {
205 yprime[0] += sb[
Y][1][0];
206 yprime[1] -= sb[
Y][1][1];
212 for (
auto i : sb[
X]) {
213 midx += (i[0] + i[1])/div;
218 for (
auto i : sb[
Y]) {
219 midy += (i[0] + i[1])/div;
230 midx = 8*midx - 4*bz[0][
X] - 4*bz[3][
X];
231 midy = 8*midy - 4*bz[0][
Y] - 4*bz[3][
Y];
232 midx_0 = sb[
X].size() > 1 ? sb[
X][1][0] + sb[
X][1][1] : 0;
233 midy_0 = sb[
Y].size() > 1 ? sb[
Y][1][0] + sb[
Y][1][1] : 0;
235 if ((std::abs(xprime[0]) <
EPSILON) && (std::abs(yprime[0]) <
EPSILON)
236 && ((std::abs(xprime[1]) >
EPSILON) || (std::abs(yprime[1]) >
EPSILON))) {
237 numer[0] = midx*xprime[1] + midy*yprime[1];
238 denom = 3.0*(xprime[1]*xprime[1] + yprime[1]*yprime[1]);
241 delx[1] = -xprime[1]*numer[0]/denom;
242 dely[1] = -yprime[1]*numer[0]/denom;
243 }
else if ((std::abs(xprime[1]) <
EPSILON) && (std::abs(yprime[1]) <
EPSILON)
244 && ((std::abs(xprime[0]) >
EPSILON) || (std::abs(yprime[0]) >
EPSILON))) {
245 numer[1] = midx*xprime[0] + midy*yprime[0];
246 denom = 3.0*(xprime[0]*xprime[0] + yprime[0]*yprime[0]);
247 delx[0] = xprime[0]*numer[1]/denom;
248 dely[0] = yprime[0]*numer[1]/denom;
251 }
else if (std::abs(xprime[1]*yprime[0] - yprime[1]*xprime[0]) >
252 0.002 * std::abs(xprime[1]*xprime[0] + yprime[1]*yprime[0])) {
253 double test1 = (bz[1][
Y] - bz[0][
Y])*(bz[3][
X] - bz[0][
X]) - (bz[1][
X] - bz[0][
X])*(bz[3][
Y] - bz[0][
Y]);
254 double test2 = (bz[2][
Y] - bz[0][
Y])*(bz[3][
X] - bz[0][
X]) - (bz[2][
X] - bz[0][
X])*(bz[3][
Y] - bz[0][
Y]);
257 denom = 3.0*(xprime[1]*yprime[0] - yprime[1]*xprime[0]);
258 for (
int i = 0; i < 2; ++i) {
259 numer_0[i] = xprime[1 - i]*midy_0 - yprime[1 - i]*midx_0;
260 numer[i] = xprime[1 - i]*midy - yprime[1 - i]*midx;
261 delx[i] = xprime[i]*numer[i]/denom;
262 dely[i] = yprime[i]*numer[i]/denom;
263 if (numer_0[i]*numer[i] < 0)
266 if (std::abs((numer[0] - numer_0[0])*numer_0[1]) > 10.0*std::abs((numer[1] - numer_0[1])*numer_0[0])
267 || std::abs((numer[1] - numer_0[1])*numer_0[0]) > 10.0*std::abs((numer[0] - numer_0[0])*numer_0[1]))
269 }
else if ((xprime[0]*xprime[1] < 0) || (yprime[0]*yprime[1] < 0)) {
270 numer[0] = midx*xprime[0] + midy*yprime[0];
271 denom = 6.0*(xprime[0]*xprime[0] + yprime[0]*yprime[0]);
272 delx[0] = xprime[0]*numer[0]/denom;
273 dely[0] = yprime[0]*numer[0]/denom;
280 for (
auto i : sb[
X]) {
281 midx += (i[1] - i[0])/div;
286 for (
auto i : sb[
Y]) {
287 midy += (i[1] - i[0])/div;
290 if (midx*yprime[0] != midy*xprime[0]) {
291 denom = midx*yprime[0] - midy*xprime[0];
292 numer[0] = midx*(bz[3][
Y] - bz[0][
Y]) - midy*(bz[3][
X] - bz[0][
X]);
293 for (
int i = 0; i < 2; ++i) {
294 delx[i] = xprime[0]*numer[0]/denom;
295 dely[i] = yprime[0]*numer[0]/denom;
298 for (
int i = 0; i < 2; ++i) {
299 delx[i] = (bz[3][
X] - bz[0][
X])/3;
300 dely[i] = (bz[3][
Y] - bz[0][
Y])/3;
304 bz[1][
X] = bz[0][
X] + delx[0];
305 bz[1][
Y] = bz[0][
Y] + dely[0];
306 bz[2][
X] = bz[3][
X] - delx[1];
307 bz[2][
Y] = bz[3][
Y] - dely[1];
320 size_t n = bz.
order();
321 size_t q = (n+1) / 2;
322 size_t even = (n & 1u) ? 0 : 1;
326 for (
size_t k = 0; k < q; ++k)
329 for (
size_t j = k; j < q; ++j)
331 sb[j][0] += (Tjk * bz[k]);
332 sb[j][1] += (Tjk * bz[n-k]);
339 for (
size_t j = k+1; j < q; ++j)
341 sb[j][0] += (Tjk * bz[n-k]);
342 sb[j][1] += (Tjk * bz[k]);
353 int Tjk = q & 1 ? -1 : 1;
354 for (
size_t k = 0; k < q; ++k)
356 sb[q][0] += (Tjk * (bz[k] + bz[n-k]));
362 sb[q][0] += Tjk * bz[q];
379 size_t n = bz.size() - 1;
380 size_t q = (n+1) / 2;
381 size_t even = (n & 1u) ? 0 : 1;
384 sb[
X].resize(q + even,
Linear(0, 0));
385 sb[
Y].resize(q + even,
Linear(0, 0));
387 for (
size_t k = 0; k < q; ++k)
390 for (
size_t j = k; j < q; ++j)
392 sb[
X][j][0] += (Tjk * bz[k][
X]);
393 sb[
X][j][1] += (Tjk * bz[n-k][
X]);
394 sb[
Y][j][0] += (Tjk * bz[k][
Y]);
395 sb[
Y][j][1] += (Tjk * bz[n-k][
Y]);
402 for (
size_t j = k+1; j < q; ++j)
404 sb[
X][j][0] += (Tjk * bz[n-k][
X]);
405 sb[
X][j][1] += (Tjk * bz[k][
X]);
406 sb[
Y][j][0] += (Tjk * bz[n-k][
Y]);
407 sb[
Y][j][1] += (Tjk * bz[k][
Y]);
418 int Tjk = q & 1 ? -1 : 1;
419 for (
size_t k = 0; k < q; ++k)
421 sb[
X][q][0] += (Tjk * (bz[k][
X] + bz[n-k][
X]));
422 sb[
Y][q][0] += (Tjk * (bz[k][
Y] + bz[n-k][
Y]));
428 sb[
X][q][0] += Tjk * bz[q][
X];
429 sb[
X][q][1] = sb[
X][q][0];
430 sb[
Y][q][0] += Tjk * bz[q][
Y];
431 sb[
Y][q][1] = sb[
Y][q][0];
433 sb[
X][0][0] = bz[0][
X];
434 sb[
X][0][1] = bz[n][
X];
435 sb[
Y][0][0] = bz[0][
Y];
436 sb[
Y][0][1] = bz[n][
Y];
452 const unsigned k = 2;
453 double te = B.tail_error(k);
454 assert(B[0].std::isfinite());
455 assert(B[1].std::isfinite());
459 double A = std::sqrt(tol/te);
462 A = std::min(A, 0.25);
463 a = 0.5 - std::sqrt(0.25 - A);
470 D2<SBasis> Bs =
compose(B, Linear(0, a));
471 assert(Bs.tail_error(k));
472 std::vector<Geom::Point> bez = sbasis_to_bezier(Bs, 2);
473 reverse(bez.begin(), bez.end());
475 pb.start_subpath(bez[0]);
478 pb.push_cubic(bez[1], bez[2], bez[3]);
483 te = B.tail_error(k);
499 THROW_EXCEPTION(
"assertion failed: B.isFinite()");
502 if( !only_cubicbeziers && (
sbasis_size(B) <= 1) ) {
505 std::vector<Geom::Point> bez;
508 pb.
curveTo(bez[1], bez[2], bez[3]);
541 if(B.size() == 0)
return pb.
peek();
544 for(
unsigned i = 0; ; i++) {
545 if ( (i+1 == B.size())
546 || !
are_near(B[i+1].at0(), B[i].at1(), tol) )
560 if (i+1 >= B.size()) {
563 start = B[i+1].at0();
Defines the different types of exceptions that 2geom can throw.
Calculation of binomial cefficients.
Polynomial in Bernstein-Bezier basis.
void resize(unsigned int n, Coord v=0)
Convex hull based on the Andrew's monotone chain algorithm.
bool contains(Point const &p) const
Check whether the given point is inside the hull.
Adaptor that creates 2D functions from 1D ones.
Function that interpolates linearly between two values.
Store paths to a PathVector.
PathVector const & peek() const
Retrieve the path.
void moveTo(Point const &p) override
Move to a different point without creating a segment.
void lineTo(Point const &p) override
Output a line segment.
void flush() override
Flush any internal state of the generator.
void curveTo(Point const &c0, Point const &c1, Point const &p) override
Output a quadratic Bezier segment.
void closePath() override
Close the current path with a line segment.
Function defined as discrete pieces.
Two-dimensional point that doubles as a vector.
Polynomial in symmetric power basis.
Path and its polyline approximation.
Convex hull data structures.
SBasisOf< double > compose(SBasisOf< SBasisOf< double > > const &f, SBasisOf< double > const &x, SBasisOf< double > const &y)
Lifts one dimensional objects into 2D.
constexpr Coord EPSILON
Default "acceptably small" value.
Various utility functions.
Path path_from_sbasis(D2< SBasis > const &B, double tol, bool only_cubicbeziers=false)
Make a path from a d2 sbasis.
std::vector< Point > bezier_points(const D2< Bezier > &a)
constexpr void binomial_decrement_n(T &b, int n, int k)
Given a multiple of binomial(n, k), modify it to the same multiple of binomial(n - 1,...
void sbasis_to_cubic_bezier(std::vector< Point > &bz, D2< SBasis > const &sb)
Changes the basis of p to be Bernstein.
constexpr void binomial_increment_k(T &b, int n, int k)
Given a multiple of binomial(n, k), modify it to the same multiple of binomial(n, k + 1).
void build_from_sbasis(PathBuilder &pb, D2< SBasis > const &B, double tol, bool only_cubicbeziers)
Make a path from a d2 sbasis.
unsigned sbasis_size(D2< SBasis > const &a)
PathVector path_from_piecewise(Piecewise< D2< SBasis > > const &B, double tol, bool only_cubicbeziers=false)
Make a path from a d2 sbasis.
double tail_error(D2< SBasis > const &a, unsigned tail)
D2< T > compose(D2< T > const &a, T const &b)
void sbasis_to_bezier(Bezier &bz, SBasis const &sb, size_t sz=0)
Changes the basis of p to be bernstein.
bool are_near(Affine const &a1, Affine const &a2, Coord eps=EPSILON)
SBasis bezier_to_sbasis(Coord const *handles, unsigned order)
callback interface for SVG path data
void subpath_from_sbasis_incremental(Geom::OldPathSetBuilder &pb, D2< SBasis > B, double tol, bool initial)
Conversion between SBasis and Bezier basis polynomials.