From 29b1527f9bdcb4ac48c0e7e4730c366abb7a5bcb Mon Sep 17 00:00:00 2001 From: jfbarraud Date: Mon, 9 Mar 2009 01:49:44 +0000 Subject: [PATCH] knot lpe: enable groups + cleanups/simplifications --- src/live_effects/lpe-knot.cpp | 504 +++++++++++++++++++--------------- src/live_effects/lpe-knot.h | 32 ++- 2 files changed, 296 insertions(+), 240 deletions(-) diff --git a/src/live_effects/lpe-knot.cpp b/src/live_effects/lpe-knot.cpp index 8f8230a6a..f362afab8 100644 --- a/src/live_effects/lpe-knot.cpp +++ b/src/live_effects/lpe-knot.cpp @@ -19,12 +19,12 @@ #include <2geom/sbasis.h> #include <2geom/d2.h> #include <2geom/d2-sbasis.h> -#include <2geom/piecewise.h> #include <2geom/path.h> -#include <2geom/d2.h> #include <2geom/crossing.h> -#include <2geom/path-intersection.h> -#include <2geom/elliptical-arc.h> +#include <2geom/bezier-to-sbasis.h> +#include <2geom/basic-intersection.h> +#include <2geom/exception.h> +//#include "2geom/recursive-bezier-intersection.cpp" #include @@ -69,184 +69,141 @@ std::vector complementOf(Geom::Interval I, std::vector const &pt_and_dir, + double const ta, double const width){ using namespace Geom; - double curveidx, timeoncurve = modf(crossing.getOtherTime(idx),&curveidx); - if(curveidx == pathb.size() ) { curveidx--; timeoncurve = 1.;}//FIXME: 0.99999; needed? - assert(curveidx >= 0 && curveidx < pathb.size()); - - std::vector MV = pathb[unsigned(curveidx)].pointAndDerivatives(timeoncurve,1); - Point T = unit_vector(MV.at(1)); + Point T = unit_vector(pt_and_dir[1]); Point N = T.cw(); - Point A = MV.at(0)-3*width*T, B = MV.at(0)+3*width*T; - - std::vector cutter; - Geom::Path cutterPath(A-width*N); - cutterPath.appendNew (B-width*N); - cutterPath.appendNew (B+width*N); - cutterPath.appendNew (A+width*N); - cutterPath.close(); - //cutterPath.appendNew (A-width*N); - cutter.push_back(cutterPath); - - std::vector patha_as_vect = std::vector(1,patha); - - CrossingSet crossingTable = crossings (patha_as_vect, cutter); - double t0 = crossing.getTime(idx); - double tmin = 0,tmax = patha.size();//-0.00001;FIXME: FIXED? - assert(crossingTable.size()>=1); - for (unsigned c=0; ctmin and tt0) tmax = t; + Point A = pt_and_dir[0]-3*width*T, B = A+6*width*T; + + Matrix mat = from_basis( T, N, pt_and_dir[0] ); + mat = mat.inverse(); + Path p = patha * mat; + std::vector times; + for (unsigned i = 0; i f = p[i].toSBasis(); + std::vector times_i, temptimes; + //TODO: explore the path fwd/backward from ta to avoid all those useless computations. + temptimes = roots(f[Y]-width); + times_i.insert(times_i.end(), temptimes.begin(), temptimes.end() ); + temptimes = roots(f[Y]+width); + times_i.insert(times_i.end(), temptimes.begin(), temptimes.end() ); + temptimes = roots(f[X]-3*width); + times_i.insert(times_i.end(), temptimes.begin(), temptimes.end() ); + temptimes = roots(f[X]+3*width); + times_i.insert(times_i.end(), temptimes.begin(), temptimes.end() ); + for (unsigned k=0; k0){ + unsigned rk = upper_bound( times.begin(), times.end(), ta ) - times.begin(); + if ( rk < times.size() ) + tmax = times[rk]; + else if ( patha.closed() ) + tmax = times[0]+period; + + if ( rk > 0 ) + tmin = times[rk-1]; + else if ( patha.closed() ) + tmin = times.back()-period; } return Interval(tmin,tmax); } -// TODO: Fix all this in 2geom!!!! //--------------------------------------------------------------------------- -// some 2Geom work around. +//LPEKnot specific Crossing Data manipulation. //--------------------------------------------------------------------------- -//Cubic Bezier curves might self intersect; the 2geom code used to miss them. -//This is a quick work around; maybe not needed anymore? -- TODO: check! -//TODO/TOCHECK/TOFIX: I think the BUG is in path-intersection.cpp -> curve_mono_split(...): -//the derivative of the curve should be used instead of the curve itself. -std::vector -split_at_horiz_vert_tgt (std::vector const & path_in){ - std::vector ret; - - using namespace Geom; - - Piecewise > f = paths_to_pw(path_in); - D2 > df = make_cuts_independent(derivative(f)); - std::vector xyroots = roots(df[X]); - std::vector yroots = roots(df[Y]); - xyroots.insert(xyroots.end(), yroots.begin(), yroots.end()); - std::sort(xyroots.begin(),xyroots.end()); - Piecewise > newf = partition(f,xyroots); - ret = path_from_piecewise(newf,LPE_CONVERSION_TOLERANCE); - - return ret; -} - -//TODO: Fix this in 2Geom; I think CrossingSets should not contain duplicates. -Geom::CrossingSet crossingSet_remove_double(Geom::CrossingSet const &input){ - Geom::CrossingSet result(input.size()); - //Yeah, I know, there is a "unique" algorithm for that... - //Note: I'm not sure the duplicates are always consecutive!! (can be first and last, I think) - //Note: I also found crossings c with c.a==c.b and c.ta==c.tb . Is it normal? - //Note: I also found crossings c with c.ta or c.tb not in path[a] or path[b] domain. This is definitely not normal. - Geom::Crossing last; - for( unsigned i=0; i const &paths) : std::vector(){ + //std::cout<<"\nCrossingPoints creation from path vector\n"; + for( unsigned i=0; i > times; + if ( i==j && ii==jj){ + +// std::cout<<"--(self int)\n"; +// std::cout << paths[i][ii].toSBasis()[Geom::X] <<"\n"; +// std::cout << paths[i][ii].toSBasis()[Geom::Y] <<"\n"; + + find_self_intersections( times, paths[i][ii].toSBasis() ); + }else{ +// std::cout<<"--(pair int)\n"; +// std::cout << paths[i][ii].toSBasis()[Geom::X] <<"\n"; +// std::cout << paths[i][ii].toSBasis()[Geom::Y] <<"\n"; +// std::cout<<"with\n"; +// std::cout << paths[j][jj].toSBasis()[Geom::X] <<"\n"; +// std::cout << paths[j][jj].toSBasis()[Geom::Y] <<"\n"; + + find_intersections( times, paths[i][ii].toSBasis(), paths[j][jj].toSBasis() ); + } + for (unsigned k=0; kGiven a point, you immediately know which strings are meeting there, -// and the index of the crossing along each string. This makes it easy to check -// topology change. In a CrossingSet, you have to do some search to know the index -// of the crossing along "the second" string (i.e. find the symetric crossing)... -// >Each point is stored only once. -// However, we don't have so many crossing points in general, so none of these points might be relevant. -// -// -: one more clumsy data representation, and "parallelism" failures to expect... -// (in particular, duplicates are hateful with this respect...) - -CrossingPoints::CrossingPoints(Geom::CrossingSet const &input, std::vector const &path) : std::vector() -{ - using namespace Geom; - //g_print("DBG>\nCrossing set content:\n"); - for( unsigned i=0; i [%u,%u]:(%u,%u) at times (%f,%f) ----->",i,n,c.a,c.b,c.ta,c.tb); - unsigned j = c.getOther(i); - if (i 1)g_print("oops! -->"); - if (ti > 1) ti=1; - if (ti < 0) ti=0; - - cp.pt = path[i].pointAt(c.getTime(i)); - cp.i = i; - cp.j = j; - cp.ni = n; - Crossing c_bar = c; - if (i==j){ - c_bar.a = c.b; - c_bar.b = c.a; - c_bar.ta = c.tb; - c_bar.tb = c.ta; - c_bar.dir = !c.dir; - } - cp.nj = std::find(input[j].begin(),input[j].end(),c_bar)-input[j].begin(); - cp.sign = 1; - push_back(cp); - //g_print("i=%u, ni=%u, j=%u, nj=%u\n",cp.i,cp.ni,cp.j,cp.nj); - }/* - else{ - //debug purpose only: - //This crossing is already registered in output. Just make sure it has a "mirror". - g_print("deja trouve?"); - get(i,n); - bool found = false; - for( unsigned ii=0; ii cuts; + for( unsigned k=0; k::iterator m=cuts.begin(); m!=cuts.end(); m++ ){ + if ( (*this)[m->second].i == i && (*this)[m->second].ti == m->first ){ + (*this)[m->second].ni = count; + }else{ + (*this)[m->second].nj = count; } - */ + count++; } } - - //g_print("CrossingPoints reslut:\n"); - //for (unsigned k=0; k const &input) : std::vector() { - if (input.size()>0 && input.size()%7 ==0){ + if (input.size()>0 && input.size()%9 ==0){ using namespace Geom; for( unsigned n=0; n const &input) : std::vector