void convex_hull_marching(Bezier src_bz, Bezier bz, std::vector<double> &solutions, double left_t, double right_t) { while(bz.order() > 0 and bz[0] == 0) { std::cout << "deflate\n"; bz = bz.deflate(); solutions.push_back(left_t); } if (bz.order() > 0) { int old_sign = SGN(bz[0]); int sign; double left_bound = 0; double dt = 0; for (size_t i = 1; i < bz.size(); i++) { sign = SGN(bz[i]); if (sign != old_sign) { dt = double(i) / bz.order(); left_bound = dt * bz[0] / (bz[0] - bz[i]); break; } old_sign = sign; } if (dt == 0) return; std::cout << bz << std::endl; std::cout << "dt = " << dt << std::endl; std::cout << "left_t = " << left_t << std::endl; std::cout << "right_t = " << right_t << std::endl; std::cout << "left bound = " << left_bound << " = " << bz(left_bound) << std::endl; double new_left_t = left_bound * (right_t - left_t) + left_t; std::cout << "new_left_t = " << new_left_t << std::endl; Bezier bzr = subRight(src_bz, new_left_t); while(bzr.order() > 0 and bzr[0] == 0) { std::cout << "deflate\n"; bzr = bzr.deflate(); solutions.push_back(new_left_t); } if (left_t < new_left_t) { convex_hull_marching(src_bz, bzr, solutions, new_left_t, right_t); } else { std::cout << "epsilon reached\n"; while(bzr.order() > 0 and fabs(bzr[0]) <= 1e-10) { std::cout << "deflate\n"; bzr = bzr.deflate(); std::cout << bzr << std::endl; solutions.push_back(new_left_t); } } } }
void Bezier::find_bezier_roots(std::vector<double> &solutions, double left_t, double right_t) const { Bezier bz = *this; //convex_hull_marching(bz, bz, solutions, left_t, right_t); //return; // a constant bezier, even if identically zero, has no roots if (bz.isConstant()) { return; } while(bz[0] == 0) { debug(std::cout << "deflate\n"); bz = bz.deflate(); solutions.push_back(0); } if (bz.degree() == 1) { debug(std::cout << "linear\n"); if (SGN(bz[0]) != SGN(bz[1])) { double d = bz[0] - bz[1]; if(d != 0) { double r = bz[0] / d; if(0 <= r && r <= 1) solutions.push_back(r); } } return; } //std::cout << "initial = " << bz << std::endl; Bernsteins B(solutions); B.find_bernstein_roots(bz, 0, left_t, right_t); //std::cout << solutions << std::endl; }
for(int i = 0; i < a.size(); i++) { EXPECT_FLOAT_EQ(a[i], b[i]); } } vector<double> find_all_roots(Bezier b) { vector<double> rts = b.roots(); if(b.at0() == 0) rts.push_back(0); if(b.at1() == 0) rts.push_back(1); return rts; } TEST_F(ChainTest, Deflate) { Bezier b = array_roots(vector_from_array((const double[]){0,0.25,0.5})); EXPECT_FLOAT_EQ(0, b.at0()); b = b.deflate(); EXPECT_FLOAT_EQ(0, b.valueAt(0.25)); b = b.subdivide(0.25).second; EXPECT_FLOAT_EQ(0, b.at0()); b = b.deflate(); const double rootposition = (0.5-0.25) / (1-0.25); EXPECT_FLOAT_EQ(0, b.valueAt(rootposition)); b = b.subdivide(rootposition).second; EXPECT_FLOAT_EQ(0, b.at0()); } TEST_F(ChainTest, Roots) { expect_array((const double[]){0.5}, wiggle.roots()); Bezier bigun(Bezier::Order(30)); for(unsigned i = 0; i < bigun.size(); i++) {