From: buliabyak Date: Mon, 27 Aug 2007 00:36:33 +0000 (+0000) Subject: repel/attract methods X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=9801a23a9d72474d0760d18388c38ff1772e10e8;p=inkscape.git repel/attract methods --- diff --git a/src/livarot/Shape.h b/src/livarot/Shape.h index 9413cf927..6e25fd405 100644 --- a/src/livarot/Shape.h +++ b/src/livarot/Shape.h @@ -283,6 +283,8 @@ 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); diff --git a/src/livarot/ShapeMisc.cpp b/src/livarot/ShapeMisc.cpp index 7590500af..199457a0b 100644 --- a/src/livarot/ShapeMisc.cpp +++ b/src/livarot/ShapeMisc.cpp @@ -812,7 +812,145 @@ Shape::MakePush (Shape * a, JoinType join, double miter, bool do_profile, NR::Po return (done_something? 0 : shape_nothing_to_do); } -// pushing + +// 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) + { + 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++) + { + 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; + NR::Point c (cx, cy); + NR::Point to_center = ptP * (*i2doc) - c; + double x = (NR::L2(to_center)/radius); + if (x > 1) { + this_vec = NR::Point(0,0); + } else if (x <= 0) { + this_vec = NR::Point(0,0); + } 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; + } + } else { + this_vec = NR::Point(0,0); + } + + 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); +} + + +// 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)