From 16a0c1b758e414746ce693cdd8d9694135f3ba87 Mon Sep 17 00:00:00 2001 From: buliabyak Date: Wed, 8 Aug 2007 07:30:50 +0000 Subject: [PATCH] new methods for tweaking, modeled after MakeOffset --- src/livarot/Shape.h | 4 + src/livarot/ShapeMisc.cpp | 271 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 275 insertions(+) diff --git a/src/livarot/Shape.h b/src/livarot/Shape.h index 80a4d8c09..3d74a8b61 100644 --- a/src/livarot/Shape.h +++ b/src/livarot/Shape.h @@ -282,6 +282,10 @@ public: // the offset is dec, with joins between edges of type "join" (see LivarotDefs.h) // 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 MakePush (Shape * a, JoinType join, double miter, bool do_profile, NR::Point c, NR::Point vector, double radius, NR::Matrix *i2doc = NULL); + + int Shape::MakeJitter (Shape * a, JoinType join, double miter, bool do_profile, NR::Point c, double power, double radius, NR::Matrix *i2doc = NULL); 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 b269c1c9c..7590500af 100644 --- a/src/livarot/ShapeMisc.cpp +++ b/src/livarot/ShapeMisc.cpp @@ -679,6 +679,277 @@ 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 +int +Shape::MakePush (Shape * a, 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; + + if (NR::L2(vector) == 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; + 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); +} + +// pushing +// 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++) + { + 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++) + 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); +} + + // 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 -- 2.30.2