Code

fixed some bugs (bad render of thick/thin parts + reversed bending + occasional crash...
authorjfbarraud <jfbarraud@users.sourceforge.net>
Thu, 26 Mar 2009 06:37:02 +0000 (06:37 +0000)
committerjfbarraud <jfbarraud@users.sourceforge.net>
Thu, 26 Mar 2009 06:37:02 +0000 (06:37 +0000)
src/live_effects/lpe-rough-hatches.cpp

index 7fa865c01098ca49ba18d50c65711ec453685abd..8b2c8aaf8bd2a67f88ef586fd56399c62b2f8c0a 100644 (file)
@@ -51,7 +51,8 @@ struct LevelCrossing{
 };\r
 struct LevelCrossingOrder {\r
     bool operator()(LevelCrossing a, LevelCrossing b) {\r
-        return a.pt[Y] < b.pt[Y];\r
+        return ( a.pt[Y] < b.pt[Y] );// a.pt[X] == b.pt[X] since we are supposed to be on the same level...\r
+        //return ( a.pt[X] < b.pt[X] || ( a.pt[X] == b.pt[X]  && a.pt[Y] < b.pt[Y] ) );\r
     }\r
 };\r
 struct LevelCrossingInfo{\r
@@ -182,7 +183,7 @@ public:
         }\r
         double t = (*this)[level][idx].t;\r
         double sign = ((*this)[level][idx].sign ? 1 : -1);\r
-        double next_t = t;\r
+        //---double next_t = t;\r
         //level += 1;\r
         direction = (direction + 1)%4;\r
         if (level == size()){\r
@@ -202,36 +203,6 @@ public:
         }\r
         level = next.first;\r
         idx = next.second;\r
-\r
-/*********************\r
-        //look for next time on the same level\r
-        for (unsigned j=0; j<(*this)[level].size(); j++){\r
-            double tj = (*this)[level][j].t;\r
-            if ( sign*(tj-t) > 0 ){\r
-                if( next_t == t ||  sign*(tj-next_t)<0 ){\r
-                    next_t = tj;\r
-                    idx = j;\r
-                }\r
-            }\r
-        }\r
-        if ( next_t == t ){//not found? look at max/min time in this component, as time is "periodic".\r
-            for (unsigned j=0; j<(*this)[level].size(); j++){\r
-                double tj = (*this)[level][j].t;\r
-                if ( -sign*(tj-next_t) > 0 ){\r
-                    next_t = tj;\r
-                    idx = j;\r
-                }\r
-            }\r
-        }\r
-        if ( next_t == t ){//still not found? houch! this should not happen.\r
-            level = size();\r
-            return;\r
-        }\r
-        if ( (*this)[level][idx].used ) {\r
-            level = size();\r
-            return;\r
-        }\r
-*************************/\r
         return;\r
     }\r
 };\r
@@ -259,7 +230,7 @@ LPERoughHatches::LPERoughHatches(LivePathEffectObject *lpeobject) :
     scale_tb(_("1st side, out"), _("Set smoothness/sharpness of path when leaving a 'bottom' halfturn. 0=sharp, 1=default"), "scale_bb", &wr, this, 1.),\r
     scale_bf(_("2nd side, in "), _("Set smoothness/sharpness of path when reaching a 'top' halfturn. 0=sharp, 1=default"), "scale_tf", &wr, this, 1.),\r
     scale_bb(_("2nd side, out"), _("Set smoothness/sharpness of path when leaving a 'top' halfturn. 0=sharp, 1=default"), "scale_tb", &wr, this, 1.),\r
-    top_smth_variation(_("variance: 1st side"), _("Randomness of 'bottom' halfturns smoothness"), "bottom_smth_variation", &wr, this, 0),\r
+    top_smth_variation(_("variance: 1st side"), _("Randomness of 'bottom' halfturns smoothness"), "top_smth_variation", &wr, this, 0),\r
     bot_smth_variation(_("2nd side"), _("Randomness of 'top' halfturns smoothness"), "bottom_smth_variation", &wr, this, 0),\r
 //\r
     top_edge_variation(_("Magnitude jitter: 1st side"), _("Randomly moves 'bottom' halfsturns to produce magnitude variations."), "bottom_edge_variation", &wr, this, 0),\r
@@ -272,7 +243,7 @@ LPERoughHatches::LPERoughHatches(LivePathEffectObject *lpeobject) :
     bender(_("Global bending"), _("Relative position to ref point defines global bending direction and amount"), "bender", &wr, this, Geom::Point(-5,0)),\r
 //\r
     fat_output(_("Generate thick/thin path"), _("Simulate a stroke of varrying width"), "fat_output", &wr, this, true),\r
-    stroke_width_top(_("Thikness: at 1st side"), _("Width at 'bottom' half turns"), "stroke_width_bottom", &wr, this, 1.),\r
+    stroke_width_top(_("Thikness: at 1st side"), _("Width at 'bottom' half turns"), "stroke_width_top", &wr, this, 1.),\r
     stroke_width_bot(_("at 2nd side"), _("Width at 'top' halfturns"), "stroke_width_bottom", &wr, this, 1.),\r
     front_thickness(_("from 2nd to 1st side"), _("Width of paths from 'top' to 'bottom' halfturns"), "front_thickness", &wr, this, 1.),\r
     back_thickness(_("from 1st to 2nd side"), _("Width of paths from 'top' to 'bottom' halfturns"), "back_thickness", &wr, this, .25)\r
@@ -299,7 +270,7 @@ LPERoughHatches::LPERoughHatches(LivePathEffectObject *lpeobject) :
     registerParameter( dynamic_cast<Parameter *>(&back_thickness) );\r
 \r
     //hatch_dist.param_set_range(0.1, NR_HUGE);\r
-    growth.param_set_range(-0.95, NR_HUGE);\r
+    growth.param_set_range(0, NR_HUGE);\r
     dist_rdm.param_set_range(0, 99.);\r
     stroke_width_top.param_set_range(0,  NR_HUGE);\r
     stroke_width_bot.param_set_range(0,  NR_HUGE);\r
@@ -318,6 +289,8 @@ LPERoughHatches::~LPERoughHatches()
 Geom::Piecewise<Geom::D2<Geom::SBasis> > \r
 LPERoughHatches::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in){\r
 \r
+    //std::cout<<"doEffect_pwd2:\n";\r
+\r
     Piecewise<D2<SBasis> > result;\r
     \r
     Piecewise<D2<SBasis> > transformed_pwd2_in = pwd2_in;\r
@@ -326,13 +299,11 @@ LPERoughHatches::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const &
     Matrix bend_mat;//used to bend the hatches\r
 \r
     if (do_bend.get_value()){\r
-        //Point bend_dir = -rot90(unit_vector(direction.getOrigin() - bender));\r
-        //double bend_amount = L2(direction.getOrigin() - bender);\r
-        Point bend_dir = -rot90(unit_vector(direction.getVector()));\r
-        double bend_amount = L2(direction.getVector());\r
+        Point bend_dir = -rot90(unit_vector(bender.getVector()));\r
+        double bend_amount = L2(bender.getVector());\r
         bend_mat = Matrix(-bend_dir[Y], bend_dir[X], bend_dir[X], bend_dir[Y],0,0);\r
         transformed_pwd2_in = pwd2_in * bend_mat;\r
-        tilter = Piecewise<SBasis>(shift(Linear(bend_amount),1));\r
+        tilter = Piecewise<SBasis>(shift(Linear(-bend_amount),1));\r
         OptRect bbox = bounds_exact( transformed_pwd2_in );\r
         if (not(bbox)) return pwd2_in;\r
         tilter.setDomain((*bbox)[Y]);\r
@@ -389,8 +360,8 @@ LPERoughHatches::generateLevels(Interval const &domain, double x_org){
 std::vector<std::vector<Point> > \r
 LPERoughHatches::linearSnake(Piecewise<D2<SBasis> > const &f, Point const &org){\r
 \r
+    //std::cout<<"linearSnake:\n";\r
     std::vector<std::vector<Point> > result;\r
-\r
     Piecewise<SBasis> x = make_cuts_independent(f)[X];\r
     //Remark: derivative is computed twice in the 2 lines below!!\r
     Piecewise<SBasis> dx = derivative(x);\r
@@ -400,7 +371,6 @@ LPERoughHatches::linearSnake(Piecewise<D2<SBasis> > const &f, Point const &org){
     std::vector<double> levels = generateLevels(*range, org[X]);\r
     std::vector<std::vector<double> > times;\r
     times = multi_roots(x,levels);\r
-\r
 //TODO: fix multi_roots!!!*****************************************\r
 //remove doubles :-(\r
     std::vector<std::vector<double> > cleaned_times(levels.size(),std::vector<double>());\r
@@ -416,27 +386,24 @@ LPERoughHatches::linearSnake(Piecewise<D2<SBasis> > const &f, Point const &org){
         }\r
     }\r
     times = cleaned_times;\r
-//     for (unsigned i=0; i<times.size(); i++){\r
-//         std::cout << "roots on level "<<i<<": ";\r
-//         for (unsigned j=0; j<times[i].size(); j++){\r
-//             std::cout << times[i][j] <<" ";\r
-//         }\r
-//         std::cout <<"\n";\r
-//     }\r
 //*******************************************************************\r
+\r
     LevelsCrossings lscs(times,f,dx);\r
+\r
     unsigned i,j;\r
     lscs.findFirstUnused(i,j);\r
     \r
     std::vector<Point> result_component;\r
     int n = int((range->min()-org[X])/hatch_dist);\r
+    \r
     while ( i < lscs.size() ){ \r
         int dir = 0;\r
-        //switch orientation of first segment according to org position.\r
-        if (n % 2 == 0){\r
-            j = lscs[i].size()-1;\r
+        //switch orientation of first segment according to starting point.\r
+        if (i % 2 == n%2 && j < lscs[i].size()-1 && !lscs[i][j].used){\r
+            j += 1;\r
             dir = 2;\r
         }\r
+\r
         while ( i < lscs.size() ){\r
             result_component.push_back(lscs[i][j].pt);\r
             lscs[i][j].used = true;\r
@@ -458,7 +425,6 @@ LPERoughHatches::smoothSnake(std::vector<std::vector<Point> > const &linearSnake
     Piecewise<D2<SBasis> > result;\r
     for (unsigned comp=0; comp<linearSnake.size(); comp++){\r
         if (linearSnake[comp].size()>=2){\r
-            bool is_top = true;//Inversion here; due to downward y? \r
             Point last_pt = linearSnake[comp][0];\r
             Point last_top = linearSnake[comp][0];\r
             Point last_bot = linearSnake[comp][0];\r
@@ -469,6 +435,9 @@ LPERoughHatches::smoothSnake(std::vector<std::vector<Point> > const &linearSnake
             Geom::Path res_comp_top(last_pt);\r
             Geom::Path res_comp_bot(last_pt);\r
             unsigned i=1;\r
+            //bool is_top = true;//Inversion here; due to downward y? \r
+            bool is_top = ( linearSnake[comp][0][Y] < linearSnake[comp][1][Y] );\r
+\r
             while( i+1<linearSnake[comp].size() ){\r
                 Point pt0 = linearSnake[comp][i];\r
                 Point pt1 = linearSnake[comp][i+1];\r
@@ -498,14 +467,21 @@ LPERoughHatches::smoothSnake(std::vector<std::vector<Point> > const &linearSnake
                 Point new_hdle_out = new_pt - (pt0-pt1) * (scale_out/2.);\r
                 \r
                 if ( fat_output.get_value() ){\r
-                    double scaled_width = double((is_top ? stroke_width_top : stroke_width_bot))/(pt1[X]-pt0[X]);\r
+                    //double scaled_width = double((is_top ? stroke_width_top : stroke_width_bot))/(pt1[X]-pt0[X]);\r
+                    double scaled_width = 1./(pt1[X]-pt0[X]);\r
                     Point hdle_offset = (pt1-pt0)*scaled_width;\r
                     Point inside = new_pt;\r
                     Point inside_hdle_in;\r
                     Point inside_hdle_out;\r
                     inside[Y]+= double((is_top ? -stroke_width_top : stroke_width_bot));\r
-                    inside_hdle_in  = inside + (new_hdle_in -new_pt) + hdle_offset * double((is_top ? front_thickness : back_thickness));\r
-                    inside_hdle_out = inside + (new_hdle_out-new_pt) - hdle_offset * double((is_top ? back_thickness : front_thickness));\r
+                    inside_hdle_in  = inside + (new_hdle_in -new_pt);// + hdle_offset * double((is_top ? front_thickness : back_thickness));\r
+                    inside_hdle_out = inside + (new_hdle_out-new_pt);// - hdle_offset * double((is_top ? back_thickness : front_thickness));\r
+\r
+                    inside_hdle_in  +=  (pt1-pt0)/2*( double((is_top ? front_thickness : back_thickness)) / (pt1[X]-pt0[X]) );\r
+                    inside_hdle_out -=  (pt1-pt0)/2*( double((is_top ? back_thickness : front_thickness)) / (pt1[X]-pt0[X]) );\r
+\r
+                    new_hdle_in  -=  (pt1-pt0)/2*( double((is_top ? front_thickness : back_thickness)) / (pt1[X]-pt0[X]) );\r
+                    new_hdle_out +=  (pt1-pt0)/2*( double((is_top ? back_thickness : front_thickness)) / (pt1[X]-pt0[X]) );\r
                     //TODO: find a good way to handle limit cases (small smthness, large stroke).\r
                     //if (inside_hdle_in[X]  > inside[X]) inside_hdle_in = inside;\r
                     //if (inside_hdle_out[X] < inside[X]) inside_hdle_out = inside;\r
@@ -529,13 +505,14 @@ LPERoughHatches::smoothSnake(std::vector<std::vector<Point> > const &linearSnake
                 i+=2;\r
                 is_top = !is_top;\r
             }\r
-            if ( i<linearSnake[comp].size() )\r
+            if ( i<linearSnake[comp].size() ){\r
                 if ( fat_output.get_value() ){\r
                     res_comp_top.appendNew<CubicBezier>(last_top_hdle,linearSnake[comp][i],linearSnake[comp][i]);\r
                     res_comp_bot.appendNew<CubicBezier>(last_bot_hdle,linearSnake[comp][i],linearSnake[comp][i]);\r
                 }else{\r
                     res_comp.appendNew<CubicBezier>(last_hdle,linearSnake[comp][i],linearSnake[comp][i]);\r
                 }\r
+            }\r
             if ( fat_output.get_value() ){\r
                 res_comp = res_comp_bot;\r
                 res_comp.append(res_comp_top.reverse(),Geom::Path::STITCH_DISCONTINUOUS);\r
@@ -575,6 +552,8 @@ LPERoughHatches::resetDefaults(SPItem * item)
         vector = Geom::Point((*bbox)[X].extent()/4, 0.);\r
         top_edge_variation.param_set_value( (*bbox)[Y].extent()/10, 0 );\r
         bot_edge_variation.param_set_value( (*bbox)[Y].extent()/10, 0 );\r
+        top_edge_variation.write_to_SVG();\r
+        bot_edge_variation.write_to_SVG();\r
     }\r
     //direction.set_and_write_new_values(origin, vector);\r
     //bender.param_set_and_write_new_value( origin + Geom::Point(5,0) );\r