From e3d8c95258fb754412be519fbccceee487bccff9 Mon Sep 17 00:00:00 2001 From: buliabyak Date: Fri, 9 Nov 2007 06:16:01 +0000 Subject: [PATCH] refactoring, one MakeTweak method instead of a bunch largely similar methods --- src/livarot/Shape.h | 13 +- src/livarot/ShapeMisc.cpp | 435 ++++++++++---------------------------- src/tweak-context.cpp | 16 +- 3 files changed, 127 insertions(+), 337 deletions(-) diff --git a/src/livarot/Shape.h b/src/livarot/Shape.h index 3c7010bbe..d1ba63a54 100644 --- a/src/livarot/Shape.h +++ b/src/livarot/Shape.h @@ -23,6 +23,13 @@ struct SweepTree; struct SweepTreeList; struct SweepEventQueue; +enum { + tweak_mode_grow, + tweak_mode_push, + tweak_mode_repel, + tweak_mode_roughen +}; + /* * the Shape class (was the Digraph class, as the header says) stores digraphs (no kidding!) of which * a very interesting kind are polygons. @@ -283,11 +290,7 @@ public: // the result is NOT a polygon; you need a subsequent call to ConvertToShape to get a real polygon int MakeOffset(Shape *of, double dec, JoinType join, double miter, bool do_profile=false, double cx = 0, double cy = 0, double radius = 0, NR::Matrix *i2doc = NULL); - int MakeRepel(Shape *of, double dec, JoinType join, double miter, bool do_profile=false, double cx = 0, double cy = 0, double radius = 0, NR::Matrix *i2doc = NULL); - - int MakePush (Shape * a, JoinType join, double miter, bool do_profile, NR::Point c, NR::Point vector, double radius, NR::Matrix *i2doc = NULL); - - int MakeJitter (Shape * a, JoinType join, double miter, bool do_profile, NR::Point c, double power, double radius, NR::Matrix *i2doc = NULL); + int MakeTweak (int mode, Shape *a, double dec, JoinType join, double miter, bool do_profile, NR::Point c, NR::Point vector, double radius, NR::Matrix *i2doc); int PtWinding(const NR::Point px) const; // plus rapide int Winding(const NR::Point px) const; diff --git a/src/livarot/ShapeMisc.cpp b/src/livarot/ShapeMisc.cpp index 199457a0b..ac59d0544 100644 --- a/src/livarot/ShapeMisc.cpp +++ b/src/livarot/ShapeMisc.cpp @@ -522,20 +522,23 @@ Shape::ConvertToFormeNested (Path * dest, int nbP, Path * *orig, int wildPath,in MakeSweepDestData (false); } -// offsets -// take each edge, offset it, and make joins with previous at edge start and next at edge end (previous and -// next being with respect to the clockwise order) -// you gotta be very careful with the join, as anything but the right one will fuck everything up -// see PathStroke.cpp for the "right" joins + int -Shape::MakeOffset (Shape * a, double dec, JoinType join, double miter, bool do_profile, double cx, double cy, double radius, NR::Matrix *i2doc) +Shape::MakeTweak (int mode, Shape *a, double dec, JoinType join, double miter, bool do_profile, NR::Point c, NR::Point vector, double radius, NR::Matrix *i2doc) { Reset (0, 0); MakeBackData(a->_has_back_data); bool done_something = false; + + double power; + if (mode == tweak_mode_push) { + power = NR::L2(vector); + } else { + power = dec; + } - if (dec == 0) + if (power == 0) { _pts = a->_pts; if (numberOfPoints() > maxPt) @@ -553,7 +556,7 @@ Shape::MakeOffset (Shape * a, double dec, JoinType join, double miter, bool do_p { maxAr = numberOfEdges(); if (_has_edges_data) - eData.resize(maxAr); + eData.resize(maxAr); if (_has_sweep_src_data) swsData.resize(maxAr); if (_has_sweep_dest_data) @@ -575,17 +578,13 @@ Shape::MakeOffset (Shape * a, double dec, JoinType join, double miter, bool do_p for (int i = 0; i < a->numberOfEdges(); i++) { - // int stP=a->swsData[i].stPt/*,enP=a->swsData[i].enPt*/; int stB = -1, enB = -1; - if (dec > 0) - { - stB = a->CycleNextAt (a->getEdge(i).st, i); - enB = a->CyclePrevAt (a->getEdge(i).en, i); - } - else - { + if (power <= 0 || mode == tweak_mode_push || mode == tweak_mode_repel || mode == tweak_mode_roughen) { stB = a->CyclePrevAt (a->getEdge(i).st, i); enB = a->CycleNextAt (a->getEdge(i).en, i); + } else { + stB = a->CycleNextAt (a->getEdge(i).st, i); + enB = a->CyclePrevAt (a->getEdge(i).en, i); } NR::Point stD, seD, enD; @@ -605,24 +604,54 @@ Shape::MakeOffset (Shape * a, double dec, JoinType join, double miter, bool do_p int stNo, enNo; ptP = a->getPoint(a->getEdge(i).st).x; - double this_dec; + if (mode == tweak_mode_push) { + power = 1; + } + + NR::Point to_center = ptP * (*i2doc) - c; + NR::Point to_center_normalized = (1/NR::L2(to_center)) * to_center; + + double this_power; if (do_profile && i2doc) { double alpha = 1; - double x = (NR::L2(ptP * (*i2doc) - NR::Point(cx,cy))/radius); + double x; + if (mode == tweak_mode_repel) { + x = (NR::L2(to_center)/radius); + } else { + x = (NR::L2(ptP * (*i2doc) - c)/radius); + } if (x > 1) { - this_dec = 0; + this_power = 0; } else if (x <= 0) { - this_dec = dec; + if (mode == tweak_mode_repel) { + this_power = 0; + } else { + this_power = power; + } } else { - this_dec = dec * (0.5 * cos (M_PI * (pow(x, alpha))) + 0.5); + this_power = power * (0.5 * cos (M_PI * (pow(x, alpha))) + 0.5); } } else { - this_dec = dec; + if (mode == tweak_mode_repel) { + this_power = 0; + } else { + this_power = power; + } } - if (this_dec != 0) + if (this_power != 0) done_something = true; + NR::Point this_vec(0,0); + if (mode == tweak_mode_push) { + this_vec = this_power * vector; + } else if (mode == tweak_mode_repel) { + this_vec = this_power * to_center_normalized; + } else if (mode == tweak_mode_roughen) { + double angle = g_random_double_range(0, 2*M_PI); + this_vec = g_random_double_range(0, 1) * this_power * NR::Point(sin(angle), cos(angle)); + } + int usePathID=-1; int usePieceID=0; double useT=0.0; @@ -638,23 +667,28 @@ Shape::MakeOffset (Shape * a, double dec, JoinType join, double miter, bool do_p useT=0; } } - if (dec > 0) - { - Path::DoRightJoin (this, this_dec, join, ptP, stD, seD, miter, stL, seL, - stNo, enNo,usePathID,usePieceID,useT); - a->swsData[i].stPt = enNo; - a->swsData[stB].enPt = stNo; - } - else - { - Path::DoLeftJoin (this, -this_dec, join, ptP, stD, seD, miter, stL, seL, - stNo, enNo,usePathID,usePieceID,useT); - a->swsData[i].stPt = enNo; - a->swsData[stB].enPt = stNo; - } + + if (mode == tweak_mode_push || mode == tweak_mode_repel || mode == tweak_mode_roughen) { + Path::DoLeftJoin (this, 0, join, ptP+this_vec, stD+this_vec, seD+this_vec, miter, stL, seL, + stNo, enNo,usePathID,usePieceID,useT); + a->swsData[i].stPt = enNo; + a->swsData[stB].enPt = stNo; + } else { + if (power > 0) { + Path::DoRightJoin (this, this_power, join, ptP, stD, seD, miter, stL, seL, + stNo, enNo,usePathID,usePieceID,useT); + a->swsData[i].stPt = enNo; + a->swsData[stB].enPt = stNo; + } else { + Path::DoLeftJoin (this, -this_power, join, ptP, stD, seD, miter, stL, seL, + stNo, enNo,usePathID,usePieceID,useT); + a->swsData[i].stPt = enNo; + a->swsData[stB].enPt = stNo; + } + } } - if (dec < 0) + if (power < 0 || mode == tweak_mode_push || mode == tweak_mode_repel || mode == tweak_mode_roughen) { for (int i = 0; i < numberOfEdges(); i++) Inverse (i); @@ -679,17 +713,21 @@ Shape::MakeOffset (Shape * a, double dec, JoinType join, double miter, bool do_p return (done_something? 0 : shape_nothing_to_do); } -// pushing -// modeled after MakeOffset black magic, the only difference being in the DoRight/LeftJoin parameters + +// offsets +// take each edge, offset it, and make joins with previous at edge start and next at edge end (previous and +// next being with respect to the clockwise order) +// you gotta be very careful with the join, as anything but the right one will fuck everything up +// see PathStroke.cpp for the "right" joins int -Shape::MakePush (Shape * a, JoinType join, double miter, bool do_profile, NR::Point c, NR::Point vector, double radius, NR::Matrix *i2doc) +Shape::MakeOffset (Shape * a, double dec, JoinType join, double miter, bool do_profile, double cx, double cy, double radius, NR::Matrix *i2doc) { Reset (0, 0); MakeBackData(a->_has_back_data); bool done_something = false; - - if (NR::L2(vector) == 0) + + if (dec == 0) { _pts = a->_pts; if (numberOfPoints() > maxPt) @@ -729,143 +767,18 @@ Shape::MakePush (Shape * a, JoinType join, double miter, bool do_profile, NR::Po for (int i = 0; i < a->numberOfEdges(); i++) { + // int stP=a->swsData[i].stPt/*,enP=a->swsData[i].enPt*/; int stB = -1, enB = -1; - stB = a->CyclePrevAt (a->getEdge(i).st, i); - enB = a->CycleNextAt (a->getEdge(i).en, i); - - NR::Point stD, seD, enD; - double stL, seL, enL; - stD = a->getEdge(stB).dx; - seD = a->getEdge(i).dx; - enD = a->getEdge(enB).dx; - - stL = sqrt (dot(stD,stD)); - seL = sqrt (dot(seD,seD)); - enL = sqrt (dot(enD,enD)); - MiscNormalize (stD); - MiscNormalize (enD); - MiscNormalize (seD); - - NR::Point ptP; - int stNo, enNo; - ptP = a->getPoint(a->getEdge(i).st).x; - - NR::Point this_vec; - if (do_profile && i2doc) { - double alpha = 1; - double x = (NR::L2(ptP * (*i2doc) - c)/radius); - if (x > 1) { - this_vec = NR::Point(0,0); - } else if (x <= 0) { - this_vec = vector; - } else { - this_vec = (0.5 * cos (M_PI * (pow(x, alpha))) + 0.5) * vector; - } - } else { - this_vec = vector; - } - - if (NR::L2(this_vec) != 0) - done_something = true; - - int usePathID=-1; - int usePieceID=0; - double useT=0.0; - if ( a->_has_back_data ) { - if ( a->ebData[i].pathID >= 0 && a->ebData[stB].pathID == a->ebData[i].pathID && a->ebData[stB].pieceID == a->ebData[i].pieceID - && a->ebData[stB].tEn == a->ebData[i].tSt ) { - usePathID=a->ebData[i].pathID; - usePieceID=a->ebData[i].pieceID; - useT=a->ebData[i].tSt; - } else { - usePathID=a->ebData[i].pathID; - usePieceID=0; - useT=0; - } - } - Path::DoLeftJoin (this, 0, join, ptP+this_vec, stD+this_vec, seD+this_vec, miter, stL, seL, - stNo, enNo,usePathID,usePieceID,useT); - a->swsData[i].stPt = enNo; - a->swsData[stB].enPt = stNo; - } - - - for (int i = 0; i < numberOfEdges(); i++) - Inverse (i); - - if ( _has_back_data ) { - for (int i = 0; i < a->numberOfEdges(); i++) - { - int nEd=AddEdge (a->swsData[i].stPt, a->swsData[i].enPt); - ebData[nEd]=a->ebData[i]; - } - } else { - for (int i = 0; i < a->numberOfEdges(); i++) - { - AddEdge (a->swsData[i].stPt, a->swsData[i].enPt); - } - } - - a->MakeSweepSrcData (false); - a->MakeSweepDestData (false); - - return (done_something? 0 : shape_nothing_to_do); -} - - -// attracting/repelling -// modeled after MakeOffset black magic, the only difference being in the DoRight/LeftJoin parameters -int -Shape::MakeRepel (Shape * a, double dec, JoinType join, double miter, bool do_profile, double cx, double cy, double radius, NR::Matrix *i2doc) -{ - Reset (0, 0); - MakeBackData(a->_has_back_data); - - bool done_something = false; - - if (dec == 0) - { - _pts = a->_pts; - if (numberOfPoints() > maxPt) + if (dec > 0) { - maxPt = numberOfPoints(); - if (_has_points_data) { - pData.resize(maxPt); - _point_data_initialised = false; - _bbox_up_to_date = false; - } + stB = a->CycleNextAt (a->getEdge(i).st, i); + enB = a->CyclePrevAt (a->getEdge(i).en, i); } - - _aretes = a->_aretes; - if (numberOfEdges() > maxAr) + else { - maxAr = numberOfEdges(); - if (_has_edges_data) - eData.resize(maxAr); - if (_has_sweep_src_data) - swsData.resize(maxAr); - if (_has_sweep_dest_data) - swdData.resize(maxAr); - if (_has_raster_data) - swrData.resize(maxAr); - if (_has_back_data) - ebData.resize(maxAr); + stB = a->CyclePrevAt (a->getEdge(i).st, i); + enB = a->CycleNextAt (a->getEdge(i).en, i); } - return 0; - } - if (a->numberOfPoints() <= 1 || a->numberOfEdges() <= 1 || a->type != shape_polygon) - return shape_input_err; - - a->SortEdges (); - - a->MakeSweepDestData (true); - a->MakeSweepSrcData (true); - - for (int i = 0; i < a->numberOfEdges(); i++) - { - int stB = -1, enB = -1; - stB = a->CyclePrevAt (a->getEdge(i).st, i); - enB = a->CycleNextAt (a->getEdge(i).en, i); NR::Point stD, seD, enD; double stL, seL, enL; @@ -884,25 +797,22 @@ Shape::MakeRepel (Shape * a, double dec, JoinType join, double miter, bool do_pr int stNo, enNo; ptP = a->getPoint(a->getEdge(i).st).x; - NR::Point this_vec; + double this_dec; if (do_profile && i2doc) { double alpha = 1; - NR::Point c (cx, cy); - NR::Point to_center = ptP * (*i2doc) - c; - double x = (NR::L2(to_center)/radius); + double x = (NR::L2(ptP * (*i2doc) - NR::Point(cx,cy))/radius); if (x > 1) { - this_vec = NR::Point(0,0); + this_dec = 0; } else if (x <= 0) { - this_vec = NR::Point(0,0); + this_dec = dec; } else { - this_vec = (1/NR::L2(to_center)) * to_center; // normalize - this_vec = dec * (0.5 * cos (M_PI * (pow(x, alpha))) + 0.5) * this_vec; + this_dec = dec * (0.5 * cos (M_PI * (pow(x, alpha))) + 0.5); } } else { - this_vec = NR::Point(0,0); + this_dec = dec; } - if (NR::L2(this_vec) != 0) + if (this_dec != 0) done_something = true; int usePathID=-1; @@ -920,153 +830,27 @@ Shape::MakeRepel (Shape * a, double dec, JoinType join, double miter, bool do_pr useT=0; } } - Path::DoLeftJoin (this, 0, join, ptP+this_vec, stD+this_vec, seD+this_vec, miter, stL, seL, - stNo, enNo,usePathID,usePieceID,useT); - a->swsData[i].stPt = enNo; - a->swsData[stB].enPt = stNo; - } - - - for (int i = 0; i < numberOfEdges(); i++) - Inverse (i); - - if ( _has_back_data ) { - for (int i = 0; i < a->numberOfEdges(); i++) + if (dec > 0) { - int nEd=AddEdge (a->swsData[i].stPt, a->swsData[i].enPt); - ebData[nEd]=a->ebData[i]; + Path::DoRightJoin (this, this_dec, join, ptP, stD, seD, miter, stL, seL, + stNo, enNo,usePathID,usePieceID,useT); + a->swsData[i].stPt = enNo; + a->swsData[stB].enPt = stNo; } - } else { - for (int i = 0; i < a->numberOfEdges(); i++) + else { - AddEdge (a->swsData[i].stPt, a->swsData[i].enPt); + Path::DoLeftJoin (this, -this_dec, join, ptP, stD, seD, miter, stL, seL, + stNo, enNo,usePathID,usePieceID,useT); + a->swsData[i].stPt = enNo; + a->swsData[stB].enPt = stNo; } } - a->MakeSweepSrcData (false); - a->MakeSweepDestData (false); - - return (done_something? 0 : shape_nothing_to_do); -} - - -// roughening -// modeled after MakeOffset black magic, the only difference being in the DoRight/LeftJoin parameters -int -Shape::MakeJitter (Shape * a, JoinType join, double miter, bool do_profile, NR::Point c, double power, double radius, NR::Matrix *i2doc) -{ - Reset (0, 0); - MakeBackData(a->_has_back_data); - - bool done_something = false; - - if (power == 0) - { - _pts = a->_pts; - if (numberOfPoints() > maxPt) - { - maxPt = numberOfPoints(); - if (_has_points_data) { - pData.resize(maxPt); - _point_data_initialised = false; - _bbox_up_to_date = false; - } - } - - _aretes = a->_aretes; - if (numberOfEdges() > maxAr) - { - maxAr = numberOfEdges(); - if (_has_edges_data) - eData.resize(maxAr); - if (_has_sweep_src_data) - swsData.resize(maxAr); - if (_has_sweep_dest_data) - swdData.resize(maxAr); - if (_has_raster_data) - swrData.resize(maxAr); - if (_has_back_data) - ebData.resize(maxAr); - } - - return 0; - } - if (a->numberOfPoints() <= 1 || a->numberOfEdges() <= 1 || a->type != shape_polygon) - return shape_input_err; - - a->SortEdges (); - - a->MakeSweepDestData (true); - a->MakeSweepSrcData (true); - - for (int i = 0; i < a->numberOfEdges(); i++) + if (dec < 0) { - int stB = -1, enB = -1; - stB = a->CyclePrevAt (a->getEdge(i).st, i); - enB = a->CycleNextAt (a->getEdge(i).en, i); - - NR::Point stD, seD, enD; - double stL, seL, enL; - stD = a->getEdge(stB).dx; - seD = a->getEdge(i).dx; - enD = a->getEdge(enB).dx; - - stL = sqrt (dot(stD,stD)); - seL = sqrt (dot(seD,seD)); - enL = sqrt (dot(enD,enD)); - MiscNormalize (stD); - MiscNormalize (enD); - MiscNormalize (seD); - - NR::Point ptP; - int stNo, enNo; - ptP = a->getPoint(a->getEdge(i).st).x; - - double this_power; - if (do_profile && i2doc) { - double alpha = 1; - double x = (NR::L2(ptP * (*i2doc) - c)/radius); - if (x > 1) { - this_power = 0; - } else if (x <= 0) { - this_power = power; - } else { - this_power = (0.5 * cos (M_PI * (pow(x, alpha))) + 0.5) * power; - } - } else { - this_power = power; - } - - if (this_power != 0) - done_something = true; - - double angle = g_random_double_range(0, 2*M_PI); - NR::Point this_vec = g_random_double_range(0, 1) * this_power * NR::Point(sin(angle), cos(angle)); - - int usePathID=-1; - int usePieceID=0; - double useT=0.0; - if ( a->_has_back_data ) { - if ( a->ebData[i].pathID >= 0 && a->ebData[stB].pathID == a->ebData[i].pathID && a->ebData[stB].pieceID == a->ebData[i].pieceID - && a->ebData[stB].tEn == a->ebData[i].tSt ) { - usePathID=a->ebData[i].pathID; - usePieceID=a->ebData[i].pieceID; - useT=a->ebData[i].tSt; - } else { - usePathID=a->ebData[i].pathID; - usePieceID=0; - useT=0; - } - } - Path::DoLeftJoin (this, 0, join, ptP+this_vec, stD+this_vec, seD+this_vec, miter, stL, seL, - stNo, enNo,usePathID,usePieceID,useT); - a->swsData[i].stPt = enNo; - a->swsData[stB].enPt = stNo; - } - - - for (int i = 0; i < numberOfEdges(); i++) + for (int i = 0; i < numberOfEdges(); i++) Inverse (i); + } if ( _has_back_data ) { for (int i = 0; i < a->numberOfEdges(); i++) @@ -1083,11 +867,12 @@ Shape::MakeJitter (Shape * a, JoinType join, double miter, bool do_profile, NR:: a->MakeSweepSrcData (false); a->MakeSweepDestData (false); - + return (done_something? 0 : shape_nothing_to_do); } + // we found a contour, now reassemble the edges on it, instead of dumping them in the Path "dest" as a // polyline. since it was a DFS, the precParc and suivParc make a nice doubly-linked list of the edges in // the contour. the first and last edges of the contour are startBord and curBord diff --git a/src/tweak-context.cpp b/src/tweak-context.cpp index b662ca2de..4f761d8c3 100644 --- a/src/tweak-context.cpp +++ b/src/tweak-context.cpp @@ -400,26 +400,28 @@ sp_tweak_dilate_recursive (Inkscape::Selection *selection, SPItem *item, NR::Poi bool did_this = false; NR::Matrix i2doc(sp_item_i2doc_affine(item)); if (mode == TWEAK_MODE_SHRINK || mode == TWEAK_MODE_GROW) { - if (theShape->MakeOffset(theRes, + if (theShape->MakeTweak(tweak_mode_grow, theRes, mode == TWEAK_MODE_GROW? force : -force, join_straight, 4.0, - true, p[NR::X], p[NR::Y], radius, &i2doc) == 0) // 0 means the shape was actually changed + true, p, NR::Point(0,0), radius, &i2doc) == 0) // 0 means the shape was actually changed did_this = true; } else if (mode == TWEAK_MODE_ATTRACT || mode == TWEAK_MODE_REPEL) { - if (theShape->MakeRepel(theRes, + if (theShape->MakeTweak(tweak_mode_repel, theRes, mode == TWEAK_MODE_REPEL? force : -force, join_straight, 4.0, - true, p[NR::X], p[NR::Y], radius, &i2doc) == 0) + true, p, NR::Point(0,0), radius, &i2doc) == 0) did_this = true; } else if (mode == TWEAK_MODE_PUSH) { - if (theShape->MakePush(theRes, + if (theShape->MakeTweak(tweak_mode_push, theRes, + 0, join_straight, 4.0, true, p, force*2*vector, radius, &i2doc) == 0) did_this = true; } else if (mode == TWEAK_MODE_ROUGHEN) { - if (theShape->MakeJitter(theRes, + if (theShape->MakeTweak(tweak_mode_roughen, theRes, + force, join_straight, 4.0, - true, p, force, radius, &i2doc) == 0) + true, p, NR::Point(0,0), radius, &i2doc) == 0) did_this = true; } -- 2.30.2