virtual void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save) { cairo_set_source_rgba (cr, 0., 0., 0., 1); cairo_set_line_width (cr, 1); Piecewise<SBasis> pws; //pws = Geom::cos(Linear(0,100)) + 3; pws = Geom::sqrt(Linear(0,100)); //pws = log(Interval(1,8)); //Piecewise<SBasis> l(Linear(-100,100)); //Piecewise<SBasis> one(Linear(1,1)); //pws = Geom::reciprocal(l*l + one)*l + l; //pws = xlogx(Interval(0.5,3)); //pws = Geom::reciprocal(pws); //pws = -integral(Geom::reciprocal(Linear(1,2)))*Piecewise<SBasis>(Linear(1,2)); pws = -pws*width/4 + width/2; pws.scaleDomain(width/2); pws.offsetDomain(width/4); cairo_pw(cr, pws); cairo_stroke(cr); cairo_set_source_rgba (cr, 0., 0., .5, 1.); cairo_horiz(cr, 500, pws.cuts); cairo_stroke(cr); *notify << "total pieces: " << pws.size(); Toy::draw(cr, notify, width, height, save); }
/** Reparameterise M to have unit speed. \param M the Element. \param tol the maximum error allowed. \param order the maximum degree to use for approximation \relates Piecewise, D2 */ Piecewise<D2<SBasis> > Geom::arc_length_parametrization(D2<SBasis> const &M, unsigned order, double tol){ Piecewise<D2<SBasis> > u; u.push_cut(0); Piecewise<SBasis> s = arcLengthSb(Piecewise<D2<SBasis> >(M),tol); for (unsigned i=0; i < s.size();i++){ double t0=s.cuts[i],t1=s.cuts[i+1]; if ( are_near(s(t0),s(t1)) ) { continue; } D2<SBasis> sub_M = compose(M,Linear(t0,t1)); D2<SBasis> sub_u; for (unsigned dim=0;dim<2;dim++){ SBasis sub_s = s.segs[i]; sub_s-=sub_s.at0(); sub_s/=sub_s.at1(); sub_u[dim]=compose_inverse(sub_M[dim],sub_s, order, tol); } u.push(sub_u,s(t1)); } return u; }
void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save) { D2<SBasis> B1 = b1_handle.asBezier(); D2<SBasis> B2 = b2_handle.asBezier(); Piecewise<D2<SBasis> >B; B.concat(Piecewise<D2<SBasis> >(B1)); B.concat(Piecewise<D2<SBasis> >(B2)); // testing fuse_nearby_ends std::vector< Piecewise<D2<SBasis> > > pieces; pieces = fuse_nearby_ends(split_at_discontinuities(B),9); Piecewise<D2<SBasis> > C; for (unsigned i=0; i<pieces.size(); i++){ C.concat(pieces[i]); } // testing fuse_nearby_ends cairo_set_line_width (cr, .5); cairo_set_source_rgba (cr, 0., 0.5, 0., 1); //cairo_d2_sb(cr, B1); cairo_pw_d2_sb(cr, C); //cairo_pw_d2_sb(cr, B); cairo_stroke(cr); Piecewise<D2<SBasis> > uniform_B = arc_length_parametrization(B); cairo_set_source_rgba (cr, 0., 0., 0.9, 1); dot_plot(cr,uniform_B); cairo_stroke(cr); *notify << "pieces = " << uniform_B.size() << ";\n"; Toy::draw(cr, notify, width, height, save); }
Geom::Piecewise<Geom::D2<Geom::SBasis> > LPEOffset::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in) { using namespace Geom; Piecewise<D2<SBasis> > output; double t = nearest_point(offset_pt, pwd2_in); Point A = pwd2_in.valueAt(t); double offset = L2(A - offset_pt); Piecewise<D2<SBasis> > der = unitVector(derivative(pwd2_in)); Piecewise<D2<SBasis> > n = rot90(der); output = pwd2_in + n * offset; append_half_circle(output, pwd2_in.lastValue(), n.lastValue() * offset); output.continuousConcat(reverse(pwd2_in - n * offset)); append_half_circle(output, pwd2_in.firstValue(), -n.firstValue() * offset); // TODO: here we should remove self-overlaps by applying the "union" boolop // but we'd need to convert the path to a Shape, which is currently // broken in 2geom, so we return the unaltered path return output; }
Geom::Piecewise<Geom::D2<Geom::SBasis> > LPECopyRotate::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in) { using namespace Geom; // I first suspected the minus sign to be a bug in 2geom but it is // likely due to SVG's choice of coordinate system orientation (max) start_pos = origin + dir * Rotate(-deg_to_rad(starting_angle)) * dist_angle_handle; double rotation_angle_end = rotation_angle; if(copiesTo360){ rotation_angle_end = 360.0/(double)num_copies; } rot_pos = origin + dir * Rotate(-deg_to_rad(starting_angle + rotation_angle_end)) * dist_angle_handle; A = pwd2_in.firstValue(); B = pwd2_in.lastValue(); dir = unit_vector(B - A); Piecewise<D2<SBasis> > output; Affine pre = Translate(-origin) * Rotate(-deg_to_rad(starting_angle)); for (int i = 0; i < num_copies; ++i) { // I first suspected the minus sign to be a bug in 2geom but it is // likely due to SVG's choice of coordinate system orientation (max) Rotate rot(-deg_to_rad(rotation_angle_end * i)); Affine t = pre * rot * Translate(origin); output.concat(pwd2_in * t); } return output; }
void draw(cairo_t *cr, int t) { if(t - last_time > path.domain().max()) add_section(random_d2()); if(t - last_time - length > path.cuts[1]) { Piecewise<D2<SBasis> > new_path; new_path.push_cut(0); for(unsigned i = 1; i < path.size(); i++) { new_path.push(path[i], path.cuts[i+1] - path.cuts[1]); } last_time = t - length; path = new_path; } cairo_set_source_rgb(cr, red, green, blue); Piecewise<D2<SBasis> > port = portion(path, std::max(t - last_time - length, 0.), t - last_time); cairo_pw_d2_sb(cr, port); cairo_stroke(cr); double d = 4; cairo_set_dash(cr, &d, 1, 0); for(unsigned i = 1; i < path.size(); i++) { if(path[i].at0() != path[i-1].at1()) { draw_line_seg(cr, path[i].at0(), path[i-1].at1()); } } cairo_stroke(cr); cairo_set_dash(cr, &d, 0, 0); cairo_set_source_rgb(cr, 0., 0., 1.); dot_plot(cr, path, std::max(t - last_time - length, 0.), t - last_time); }
/** Compute the cosine of a function. \param f function \param tol maximum error \param order maximum degree polynomial to use */ Piecewise<SBasis> cos(Piecewise<SBasis> const &f, double tol, int order){ Piecewise<SBasis> result; for (unsigned i=0; i<f.size(); i++){ Piecewise<SBasis> cosfi = cos(f.segs[i],tol,order); cosfi.setDomain(Interval(f.cuts[i],f.cuts[i+1])); result.concat(cosfi); } return result; }
/** Reparameterise M to have unit speed. \param M the Element. \param tol the maximum error allowed. \param order the maximum degree to use for approximation \relates Piecewise */ Piecewise<D2<SBasis> > Geom::arc_length_parametrization(Piecewise<D2<SBasis> > const &M, unsigned order, double tol){ Piecewise<D2<SBasis> > result; for (unsigned i=0; i<M.size(); i++) { result.concat( arc_length_parametrization(M[i],order,tol) ); } return result; }
/** returns a function giving the curvature at each point in M. \param M the Element. \param tol the maximum error allowed. \relates Piecewise \todo claimed incomplete. Check. */ Piecewise<SBasis> Geom::curvature(Piecewise<D2<SBasis> > const &V, double tol){ Piecewise<SBasis> result; Piecewise<D2<SBasis> > VV = cutAtRoots(V); result.cuts.push_back(VV.cuts.front()); for (unsigned i=0; i<VV.size(); i++){ Piecewise<SBasis> curv_seg; curv_seg = curvature(VV.segs[i],tol); curv_seg.setDomain(Interval(VV.cuts[i],VV.cuts[i+1])); result.concat(curv_seg); } return result; }
/** Return a Piecewise<D2<SBasis> > which points in the same direction as V_in, but has unit_length. \param V_in the original path. \param tol the maximum error allowed. \param order the maximum degree to use for approximation unitVector(x,y) is computed as (b,-a) where a and b are solutions of: ax+by=0 (eqn1) and a^2+b^2=1 (eqn2) \relates Piecewise */ Piecewise<D2<SBasis> > Geom::unitVector(Piecewise<D2<SBasis> > const &V, double tol, unsigned order){ Piecewise<D2<SBasis> > result; Piecewise<D2<SBasis> > VV = cutAtRoots(V); result.cuts.push_back(VV.cuts.front()); for (unsigned i=0; i<VV.size(); i++){ Piecewise<D2<SBasis> > unit_seg; unit_seg = unitVector(VV.segs[i],tol, order); unit_seg.setDomain(Interval(VV.cuts[i],VV.cuts[i+1])); result.concat(unit_seg); } return result; }
Piecewise<SBasis> convole(SBasisOf<double> const &f, Interval dom_f, SBasisOf<double> const &g, Interval dom_g, bool f_cst_ends = false){ if ( dom_f.extent() < dom_g.extent() ) return convole(g, dom_g, f, dom_f); Piecewise<SBasis> result; SBasisOf<SBasisOf<double> > u,v; u.push_back(LinearOf<SBasisOf<double> >(SBasisOf<double>(LinearOf<double>(0,1)))); v.push_back(LinearOf<SBasisOf<double> >(SBasisOf<double>(LinearOf<double>(0,0)), SBasisOf<double>(LinearOf<double>(1,1)))); SBasisOf<SBasisOf<double> > v_u = (v - u)*(dom_f.extent()/dom_g.extent()); v_u += SBasisOf<SBasisOf<double> >(SBasisOf<double>(-dom_g.min()/dom_g.extent())); SBasisOf<SBasisOf<double> > gg = multi_compose(g,v_u); SBasisOf<SBasisOf<double> > ff = SBasisOf<SBasisOf<double> >(f); SBasisOf<SBasisOf<double> > hh = integral(ff*gg,0); result.cuts.push_back(dom_f.min()+dom_g.min()); //Note: we know dom_f.extent() >= dom_g.extent()!! //double rho = dom_f.extent()/dom_g.extent(); double t0 = dom_g.min()/dom_f.extent(); double t1 = dom_g.max()/dom_f.extent(); double t2 = t0+1; double t3 = t1+1; SBasisOf<double> a,b,t; SBasis seg; a = SBasisOf<double>(LinearOf<double>(0,0)); b = SBasisOf<double>(LinearOf<double>(0,t1-t0)); t = SBasisOf<double>(LinearOf<double>(t0,t1)); seg = toSBasis(compose(hh,b,t)-compose(hh,a,t)); result.push(seg,dom_f.min() + dom_g.max()); if (dom_f.extent() > dom_g.extent()){ a = SBasisOf<double>(LinearOf<double>(0,t2-t1)); b = SBasisOf<double>(LinearOf<double>(t1-t0,1)); t = SBasisOf<double>(LinearOf<double>(t1,t2)); seg = toSBasis(compose(hh,b,t)-compose(hh,a,t)); result.push(seg,dom_f.max() + dom_g.min()); } a = SBasisOf<double>(LinearOf<double>(t2-t1,1.)); b = SBasisOf<double>(LinearOf<double>(1.,1.)); t = SBasisOf<double>(LinearOf<double>(t2,t3)); seg = toSBasis(compose(hh,b,t)-compose(hh,a,t)); result.push(seg,dom_f.max() + dom_g.max()); result*=dom_f.extent(); //--constant ends correction-------------- if (f_cst_ends){ SBasis ig = toSBasis(integraaal(g))*dom_g.extent(); ig -= ig.at0(); Piecewise<SBasis> cor; cor.cuts.push_back(dom_f.min()+dom_g.min()); cor.push(reverse(ig)*f.at0(),dom_f.min()+dom_g.max()); cor.push(Linear(0),dom_f.max()+dom_g.min()); cor.push(ig*f.at1(),dom_f.max()+dom_g.max()); result+=cor; } //---------------------------------------- return result; }
void plot3d(cairo_t *cr, Piecewise<SBasis> const &x, Piecewise<SBasis> const &y, Piecewise<SBasis> const &z, Frame frame){ Piecewise<SBasis> xx = partition(x,y.cuts); Piecewise<SBasis> xxx = partition(xx,z.cuts); Piecewise<SBasis> yyy = partition(y,xxx.cuts); Piecewise<SBasis> zzz = partition(z,xxx.cuts); for (unsigned i=0; i<xxx.size(); i++){ plot3d(cr, xxx[i], yyy[i], zzz[i], frame); } }
static void dot_plot(cairo_t *cr, Piecewise<D2<SBasis> > const &M, double min, double max, double space=10){ for( double t = min; t < max; t += space) { Point pos = M(t), perp = M.valueAndDerivatives(t, 2)[1].cw() * 3; draw_line_seg(cr, pos + perp, pos - perp); } cairo_stroke(cr); }
void add_section(const D2<SBasis> x) { Piecewise<D2<SBasis> > new_path(path); D2<SBasis> seg(x); seg[0][0][0] = path.segs.back()[0][0][1]; seg[1][0][0] = path.segs.back()[1][0][1]; new_path.push(seg, path.domain().max()+1); path = arc_length_parametrization(new_path); }
void cairo_pw(cairo_t *cr, Piecewise<SBasis> p, double hscale=1., double vscale=1.) { for(unsigned i = 0; i < p.size(); i++) { D2<SBasis> B; B[0] = Linear(150+p.cuts[i]*hscale, 150+p.cuts[i+1]*hscale); B[1] = Linear(450) - p[i]*vscale; cairo_d2_sb(cr, B); } }
void reverse_direction(int t) { path = portion(path, 0, t - last_time); D2<SBasis> seg = random_d2(), last = path[path.size()-1]; for(unsigned c = 0; c < 2; c++) for(unsigned d = 1; d < seg[c].size() && d < last[c].size(); d++) seg[c][d][0] = -last[c][d][1]; add_section(seg); }
void cairo_pw(cairo_t *cr, Piecewise<SBasis> p) { for(unsigned i = 0; i < p.size(); i++) { D2<SBasis> B; B[0] = Linear(p.cuts[i], p.cuts[i+1]); B[1] = p[i]; cairo_d2_sb(cr, B); } }
/** * \brief Retruns a Piecewise SBasis with prescribed values at prescribed times. * * \param times: vector of times at which the values are given. Should be sorted in increasing order. * \param values: vector of prescribed values. Should have the same size as times and be sorted accordingly. * \param smoothness: (defaults to 1) regularity class of the result: 0=piecewise linear, 1=continuous derivative, etc... */ Piecewise<SBasis> interpolate(std::vector<double> times, std::vector<double> values, unsigned smoothness){ assert ( values.size() == times.size() ); if ( values.size() == 0 ) return Piecewise<SBasis>(); if ( values.size() == 1 ) return Piecewise<SBasis>(values[0]);//what about time?? SBasis sk = shift(Linear(1.),smoothness); SBasis bump_in = integral(sk); bump_in -= bump_in.at0(); bump_in /= bump_in.at1(); SBasis bump_out = reverse( bump_in ); Piecewise<SBasis> result; result.cuts.push_back(times[0]); for (unsigned i = 0; i<values.size()-1; i++){ result.push(bump_out*values[i]+bump_in*values[i+1],times[i+1]); } return result; }
void testIntegralAndDerivative(const Piecewise<F, BreakType>& piecewise, const Arg& value_at_start_time) { // differentiate integral, get original back auto piecewise_integral = integral(piecewise, value_at_start_time); Piecewise<F, BreakType> piecewise_back = weakDerivative(piecewise_integral); uniform_real_distribution<Arg> distribution(piecewise.domainStart(), piecewise.domainEnd()); Arg arg = distribution(engine); valueCheck(piecewise(arg), piecewise_back(arg), 1e-8 * (Arg) 1); valueCheck(value_at_start_time, piecewise_integral(piecewise.domainStart()), 1e-8 * (Arg) 1); // check continuity at knot points for (int i = 0; i < piecewise.numberOfSegments() - 1; ++i) { const auto& f_this = (piecewise_integral.getSubfunction(i)); const auto& f_next = piecewise_integral.getSubfunction(i + 1); valueCheck(f_this(piecewise_integral.segmentEnd(i) - piecewise_integral.segmentStart(i)), f_next(0.0), 1e-8 * (Arg) 1); } }
/** Calculates the length of a Piecewise<D2<SBasis> > through gsl integration. \param s the Element. \param tol the maximum error allowed. \relates Piecewise If you only want the total length, this routine faster and more accurate than constructing an arcLengthSb. */ double Geom::length(Piecewise<D2<SBasis> > const &s, double tol){ double result = 0; double abs_error = 0; for (unsigned i=0; i < s.size();i++){ length_integrating(s[i], result, abs_error, tol); } return result; }
static void plot_graph(cairo_t *cr, Piecewise<SBasis> const &f, double x_scale=300, double y_scale=100){ //double dt=(M[0].cuts.back()-M[0].cuts.front())/space; D2<Piecewise<SBasis> > g; g[X] = Piecewise<SBasis>( SBasis(Linear(100+f.cuts.front()*x_scale, 100+f.cuts.back()*x_scale))); g[X].setDomain(f.domain()); g[Y] = -f*y_scale+400; cairo_d2_pw_sb(cr, g); }
/** Return a function which gives the angle of vect at each point. \param vect a piecewise parameteric curve. \param tol the maximum error allowed. \param order the maximum degree to use for approximation \relates Piecewise */ Piecewise<SBasis> Geom::atan2(Piecewise<D2<SBasis> > const &vect, double tol, unsigned order){ Piecewise<SBasis> result; Piecewise<D2<SBasis> > v = cutAtRoots(vect,tol); result.cuts.push_back(v.cuts.front()); for (unsigned i=0; i<v.size(); i++){ D2<SBasis> vi = RescaleForNonVanishingEnds(v.segs[i]); SBasis x=vi[0], y=vi[1]; Piecewise<SBasis> angle; angle = divide (x*derivative(y)-y*derivative(x), x*x+y*y, tol, order); //TODO: I don't understand this - sign. angle = integral(-angle); Point vi0 = vi.at0(); angle += -std::atan2(vi0[1],vi0[0]) - angle[0].at0(); //TODO: deal with 2*pi jumps form one seg to the other... //TODO: not exact at t=1 because of the integral. //TODO: force continuity? angle.setDomain(Interval(v.cuts[i],v.cuts[i+1])); result.concat(angle); } return result; }
void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save, std::ostringstream *timer_stream) { Geom::Point dir(1,-2); for(unsigned dim = 0; dim < 2; dim++) { Geom::Point dir(0,0); dir[dim] = 1; for(unsigned vi = 0; vi < sb2[dim].vs; vi++) for(unsigned ui = 0; ui < sb2[dim].us; ui++) for(unsigned iv = 0; iv < 2; iv++) for(unsigned iu = 0; iu < 2; iu++) { unsigned corner = iu + 2*iv; unsigned i = ui + vi*sb2[dim].us; Geom::Point base((2*(iu+ui)/(2.*ui+1)+1)*width/4., (2*(iv+vi)/(2.*vi+1)+1)*width/4.); if(vi == 0 && ui == 0) { base = Geom::Point(width/4., width/4.); } double dl = dot((hand.pts[corner+4*i] - base), dir)/dot(dir,dir); sb2[dim][i][corner] = dl/(width/2)*pow(4.0,(double)ui+vi); } } cairo_d2_sb2d(cr, sb2, dir*0.1, width); cairo_set_source_rgba (cr, 0., 0., 0, 0.5); cairo_stroke(cr); for(unsigned i = 0; i < path_a_pw.size(); i++) { D2<SBasis> B = path_a_pw[i]; //const int depth = sb2[0].us*sb2[0].vs; //const int surface_hand.pts = 4*depth; //D2<SBasis> B = hand.pts_to_sbasis<3>(hand.pts.begin() + surface_hand.pts); cairo_d2_sb(cr, B); for(unsigned dim = 0; dim < 2; dim++) { std::vector<double> r = roots(B[dim]); for(unsigned i = 0; i < r.size(); i++) draw_cross(cr, B(r[i])); r = roots(Linear(width/4) - B[dim]); for(unsigned i = 0; i < r.size(); i++) draw_cross(cr, B(r[i])); } cairo_set_source_rgba (cr, 0., 0.125, 0, 1); cairo_stroke(cr); B *= (4./width); D2<SBasis> tB = compose_each(sb2, B); B = B*(width/2) + Geom::Point(width/4, width/4); tB = tB*(width/2) + Geom::Point(width/4, width/4); cairo_d2_sb(cr, tB); } //*notify << "bo = " << sb2.index(0,0); Toy::draw(cr, notify, width, height, save,timer_stream); }
//================================================================= //TODO: what's this for?!?! Piecewise<D2<SBasis> > Geom::cutAtRoots(Piecewise<D2<SBasis> > const &M, double ZERO){ vector<double> rts; for (unsigned i=0; i<M.size(); i++){ vector<double> seg_rts = roots((M.segs[i])[0]); seg_rts = vect_intersect(seg_rts, roots((M.segs[i])[1]), ZERO); Linear mapToDom = Linear(M.cuts[i],M.cuts[i+1]); for (unsigned r=0; r<seg_rts.size(); r++){ seg_rts[r]= mapToDom(seg_rts[r]); } rts.insert(rts.end(),seg_rts.begin(),seg_rts.end()); } return partition(M,rts); }
/** Compute the sqrt of a function. \param f function */ Piecewise<SBasis> sqrt(Piecewise<SBasis> const &f, double tol, int order){ Piecewise<SBasis> result; Piecewise<SBasis> zero = Piecewise<SBasis>(Linear(tol*tol)); zero.setDomain(f.domain()); Piecewise<SBasis> ff=max(f,zero); for (unsigned i=0; i<ff.size(); i++){ Piecewise<SBasis> sqrtfi = sqrt_internal(ff.segs[i],tol,order); sqrtfi.setDomain(Interval(ff.cuts[i],ff.cuts[i+1])); result.concat(sqrtfi); } return result; }
/** * Centroid using sbasis integration. \param p the Element. \param centroid on return contains the centroid of the shape \param area on return contains the signed area of the shape. \relates Piecewise This approach uses green's theorem to compute the area and centroid using integrals. For curved shapes this is much faster than converting to polyline. Note that without an uncross operation the output is not the absolute area. * Returned values: 0 for normal execution; 2 if area is zero, meaning centroid is meaningless. */ unsigned Geom::centroid(Piecewise<D2<SBasis> > const &p, Point& centroid, double &area) { Point centroid_tmp(0,0); double atmp = 0; for(unsigned i = 0; i < p.size(); i++) { SBasis curl = dot(p[i], rot90(derivative(p[i]))); SBasis A = integral(curl); D2<SBasis> C = integral(multiply(curl, p[i])); atmp += A.at1() - A.at0(); centroid_tmp += C.at1()- C.at0(); // first moment. } // join ends centroid_tmp *= 2; Point final = p[p.size()-1].at1(), initial = p[0].at0(); const double ai = cross(final, initial); atmp += ai; centroid_tmp += (final + initial)*ai; // first moment. area = atmp / 2; if (atmp != 0) { centroid = centroid_tmp / (3 * atmp); return 0; } return 2; }
Geom::Piecewise<Geom::D2<Geom::SBasis> > doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > & pwd2_in, Geom::Piecewise<Geom::D2<Geom::SBasis> > & pattern) { using namespace Geom; Piecewise<D2<SBasis> > uskeleton = arc_length_parametrization(pwd2_in, 2, .1); uskeleton = remove_short_cuts(uskeleton,.01); Piecewise<D2<SBasis> > n = rot90(derivative(uskeleton)); n = force_continuity(remove_short_cuts(n,.1)); D2<Piecewise<SBasis> > patternd2 = make_cuts_independent(pattern); Piecewise<SBasis> x = Piecewise<SBasis>(patternd2[0]); Piecewise<SBasis> y = Piecewise<SBasis>(patternd2[1]); Interval pattBnds = *bounds_exact(x); x -= pattBnds.min(); Interval pattBndsY = *bounds_exact(y); y -= (pattBndsY.max()+pattBndsY.min())/2; int nbCopies = int(uskeleton.cuts.back()/pattBnds.extent()); double scaling = 1; double pattWidth = pattBnds.extent() * scaling; if (scaling != 1.0) { x*=scaling; } double offs = 0; Piecewise<D2<SBasis> > output; for (int i=0; i<nbCopies; i++){ output.concat(compose(uskeleton,x+offs)+y*compose(n,x+offs)); offs+=pattWidth; } return output; }
static void plot(cairo_t* cr, Piecewise<SBasis> const &f,double vscale=1){ D2<Piecewise<SBasis> > plot; plot[1]=-f; plot[1]*=vscale; plot[1]+=300; plot[0].cuts.push_back(f.cuts.front()); plot[0].cuts.push_back(f.cuts.back()); plot[0].segs.push_back(Linear(150,450)); cairo_d2_pw_sb(cr, plot); for (unsigned i=1; i<f.size(); i++){ cairo_move_to(cr, Point(150+f.cuts[i]*300,300)); cairo_line_to(cr, Point(150+f.cuts[i]*300,300-vscale*f.segs[i].at0())); } }
void draw(cairo_t *cr, std::ostringstream *notify, int width, int height, bool save) { Geom::Point dir(1,-2); D2<Piecewise<SBasis> > B = make_cuts_independent(path_a_pw); cairo_set_source_rgba (cr, 0., 0.125, 0, 1); if(0) { D2<Piecewise<SBasis> > tB(cos(B[0]*0.1)*(brush_handle.pos[0]/100) + B[0], cos(B[1]*0.1)*(brush_handle.pos[1]/100) + B[1]); cairo_d2_pw_sb(cr, tB); } else { Piecewise<SBasis> r2 = (dot(path_a_pw - brush_handle.pos, path_a_pw - brush_handle.pos)); Piecewise<SBasis> rc; rc.push_cut(0); rc.push(SBasis(Linear(1, 1)), 2); rc.push(SBasis(Linear(1, 0)), 4); rc.push(SBasis(Linear(0, 0)), 30); rc *= 10; rc.scaleDomain(1000); Piecewise<SBasis> swr; swr.push_cut(0); swr.push(SBasis(Linear(0, 1)), 2); swr.push(SBasis(Linear(1, 0)), 4); swr.push(SBasis(Linear(0, 0)), 30); swr *= 10; swr.scaleDomain(1000); cairo_pw(cr, swr);// + (height - 100)); D2<Piecewise<SBasis> > uB = make_cuts_independent(unitVector(path_a_pw - brush_handle.pos)); D2<Piecewise<SBasis> > tB(compose(rc, (r2))*uB[0] + B[0], compose(rc, (r2))*uB[1] + B[1]); cairo_d2_pw_sb(cr, tB); //path_a_pw = sectionize(tB); } cairo_stroke(cr); *notify << path_a_pw.size(); Toy::draw(cr, notify, width, height, save); }
void tele(int t) { Piecewise<D2<SBasis> > new_path(portion(path, 0, t - last_time)); new_path.push(random_d2(), path.domain().max()+1); path = arc_length_parametrization(new_path); }