/*
9 * Copyright (C) 2018 Authors
10 * Released under GNU GPL v2+, read the file
'COPYING' for more information.
62 lastMoveTo =
AddPoint(curX, 0, 0.0,
true);
66 std::vector<double> cuts;
76 cuts.emplace_back(cuts_it->t);
91 lastMoveTo =
AddPoint(nextX, curP, 0.0,
true);
97 nextX =
pts[lastMoveTo].p;
98 int n =
AddPoint(nextX, curP, 1.0,
false);
106 if (n > 0)
pts[n].closed =
true;
124 RecCubicTo(curX, cmd->start, nextX, cmd->end, treshhold, 8, 0, 1, curP, relative, cuts);
134 DoArc(curX, nextX, cmd->rx, cmd->ry, cmd->angle, cmd->large, cmd->clockwise, treshhold, curP, relative, cuts);
163 int const firstTyp =
descr_cmd[0]->getType();
168 curX[0] = curX[1] = 0;
177 int const nType =
descr_cmd[curP]->getType();
191 descr_cmd[curP]->associated = lastMoveTo;
199 nextX =
pts[lastMoveTo].p;
234 RecCubicTo(curX, nData->
start, nextX, nData->
end, treshhold, 8);
288 int const firstTyp =
descr_cmd[0]->getType();
293 curX[0] = curX[1] = 0;
302 int const nType =
descr_cmd[curP]->getType();
316 descr_cmd[curP]->associated = lastMoveTo;
324 nextX =
pts[lastMoveTo].p;
327 nexcur = nextX - curX;
328 const double segL =
Geom::L2(nexcur);
329 if ( (segL > treshhold) && (treshhold > 0) ) {
330 for (
double i = treshhold; i < segL; i += treshhold) {
332 nX = (segL - i) * curX + i * nextX;
358 const double segL = L2(nexcur);
359 if ( (segL > treshhold) && (treshhold > 0)) {
360 for (
double i = treshhold; i < segL; i += treshhold) {
361 Geom::Point nX = ((segL - i) * curX + i * nextX) / segL;
382 RecCubicTo(curX, nData->
start, nextX, nData->
end, treshhold, 8, 4 * treshhold);
446 g_assert_not_reached();
455 Geom::Point const ax = ieD - 2 * iE + 2 * iS + isD;
456 Geom::Point const bx = 3 * iE - ieD - 2 * isD - 3 * iS;
459 oPt = 3 * t * t * ax + 2 * t * bx + cx;
464 double rx,
double ry,
double angle,
465 bool large,
bool wise,
469 double rx,
double ry,
double angle,
bool large,
bool wise,
double &sang,
double &eang)
477 double rx,
double ry,
double angle,
478 bool large,
bool wise,
486 double const lensq =
dot(cse,cse);
488 ? sqrt( 1/lensq - .25 )
495 }
else if ( ra[0] >= 1 ) {
500 sang = 2 * M_PI - sang;
504 ra = -csd + 0.5 * cse;
507 }
else if ( ra[0] >= 1 ) {
512 eang = 2 * M_PI - eang;
520 dr[0] =
dot(ca, csd);
521 dr[1] = cross(ca, csd);
534 if ( eang >= 2*M_PI ) {
537 if ( sang >= 2*M_PI ) {
550 if ( eang >= 2*M_PI ) {
553 if ( sang >= 2*M_PI ) {
559 dr += 0.5 * (iS + iE);
565 double const rx,
double const ry,
double const angle,
566 bool const large,
bool const wise,
double const tresh)
571 if ( rx <= 0.0001 || ry <= 0.0001 || tresh <= 1e-8) {
580 ArcAnglesAndCenter(iS, iE, rx, ry, angle*M_PI/180.0, large, wise, sang, eang, dr_temp);
588 double max_ang = 2 * acos ( 1 - tresh / (fmax(rx, ry) ) );
589 max_ang = fmin (max_ang, M_PI / 2 );
590 int const num_sectors = abs(sang - eang) / max_ang + 1;
598 double const incr = (eang - sang) / num_sectors;
600 for (
double b = sang + incr ; b > eang ; b += incr) {
602 AddPoint( cb.vector() * ar * cbangle + dr );
610 double const incr = (eang - sang) / num_sectors;
612 for (
double b = sang + incr ; b < eang ; b += incr) {
614 AddPoint( cb.vector() * ar * cbangle + dr);
622 double tresh,
int lev,
double maxL)
632 const double sC =
dot(isD,isD);
633 const double eC =
dot(ieD,ieD);
635 if ( sC < tresh && eC < tresh ) {
643 const double sC = fabs(
cross(se, isD)) / dC;
644 const double eC = fabs(
cross(se, ieD)) / dC;
645 if ( sC < tresh && eC < tresh ) {
649 if ( maxL > 0 && dC > maxL ) {
654 Geom::Point m = 0.5 * (iS + iE) + 0.125 * (isD - ieD);
655 Geom::Point md = 0.75 * (iE - iS) - 0.125 * (isD + ieD);
660 RecCubicTo(iS, hisD, m, md, tresh, lev - 1, maxL);
662 RecCubicTo(m, md, iE, hieD, tresh, lev - 1,maxL);
673 Geom::Point m = 0.5 * (iS + iE) + 0.125 * (isD - ieD);
674 Geom::Point md = 0.75 * (iE - iS) - 0.125 * (isD + ieD);
679 RecCubicTo(iS, hisD, m, md, tresh, lev - 1, maxL);
681 RecCubicTo(m, md, iE, hieD, tresh, lev - 1,maxL);
686 double const rx,
double const ry,
double const angle,
687 bool const large,
bool const wise,
double const thresh,
int const piece,
688 bool relative, std::vector<double>
const &cuts)
693 if (rx <= 0.0001 || ry <= 0.0001 || thresh <= 1e-8) {
699 auto const angle_rad = Geom::rad_from_deg(angle);
721 auto const max_ang = std::min(relative
722 ? std::sqrt(thresh) / 2
723 : 2 *
std::acos(1 - thresh /
std::
max(rx, ry)),
728 auto arc = [&,
this] (
double st,
double et,
bool last) {
731 int const num_sectors = std::ceil(std::abs(eang - sang) * (et - st) / max_ang);
733 auto const dt = (et - st) / num_sectors;
738 for (
int i = 1; i < num_sectors + last; i++) {
746 for (
auto c : cuts) {
750 arc(prev, 1.0,
false);
755 double thresh,
int lev,
double st,
double et,
int piece,
756 bool relative, std::span<double>
const &cuts)
759 RecCubicTo(iS, isD, iE, ieD, thresh, lev, st, et, piece, relative);
763 int const mid = cuts.size() / 2;
764 double const midt = cuts[mid];
765 double const midt_scaled = (midt - st) / (et - st);
767 auto split = [&] (std::array<double, 4> &left, std::array<double, 4> &right,
Geom::Dim2 dim) {
768 auto const in = std::array<double, 4>{iS[dim], iS[dim] + isD[dim] / 3, iE[dim] - ieD[dim] / 3, iE[dim]};
772 std::array<double, 4> xsl, ysl, xsr, ysr;
776 auto l = [&] (
int i) {
return Geom::Point(xsl[i], ysl[i]); };
777 auto r = [&] (
int i) {
return Geom::Point(xsr[i], ysr[i]); };
779 auto cutsl = cuts.subspan(0, mid);
780 auto cutsr = cuts.subspan(mid + 1);
782 RecCubicTo(l(0), 3 * (l(1) - l(0)), l(3), 3 * (l(3) - l(2)), thresh, lev, st, midt, piece, relative, cutsl);
784 RecCubicTo(r(0), 3 * (r(1) - r(0)), r(3), 3 * (r(3) - r(2)), thresh, lev, midt, et, piece, relative, cutsr);
789 double tresh,
int lev,
double st,
double et,
int piece,
796 auto const se = iE - iS;
800 auto const bound = se.
lengthSq() * tresh;
801 if (y1 < bound && y2 < bound) {
809 auto const bound = se.
length() * tresh;
810 if (y1 < bound && y2 < bound) {
815 Geom::Point m = 0.5 * (iS + iE) + 0.125 * (isD - ieD);
816 Geom::Point md = 0.75 * (iE - iS) - 0.125 * (isD + ieD);
817 double mt = (st + et) / 2;
822 RecCubicTo(iS, hisD, m, md, tresh, lev - 1, st, mt, piece, relative);
824 RecCubicTo(m, md, iE, hieD, tresh, lev - 1, mt, et, piece, relative);
835 if ( dest ==
nullptr ) {
839 if ( justAdd ==
false ) {
843 if (
pts.size() <= 1 ) {
857 for (
auto & pt :
pts) {
866 while ( curP <
int(
pts.size()) ) {
873 if ( closeIfNeeded ) {
874 if ( closed && lEdge >= 0 ) {
878 lEdge = dest->
AddEdge(first + lastM, first+pathEnd);
880 dest->
ebData[lEdge].pathID = pathID;
881 dest->
ebData[lEdge].pieceID =
pts[lm].piece;
882 dest->
ebData[lEdge].tSt = 1.0;
883 dest->
ebData[lEdge].tEn = 0.0;
896 lEdge = dest->
AddEdge(first + curP, first + pathEnd);
898 dest->
ebData[lEdge].pathID = pathID;
899 dest->
ebData[lEdge].pieceID =
pts[sbp].piece;
900 if (
pts[sbp].piece ==
pts[prp].piece ) {
905 dest->
ebData[lEdge].tEn = 0.0;
920 if ( closeIfNeeded ) {
921 if ( closed && lEdge >= 0 ) {
926 lEdge = dest->
AddEdge(first + lastM, first + pathEnd);
928 dest->
ebData[lEdge].pathID = pathID;
929 dest->
ebData[lEdge].pieceID =
pts[lm].piece;
930 dest->
ebData[lEdge].tSt = 1.0;
931 dest->
ebData[lEdge].tEn = 0.0;
941 for (
auto & pt :
pts) {
949 while ( curP <
int(
pts.size()) ) {
954 if ( closeIfNeeded ) {
955 if ( closed && lEdge >= 0 ) {
959 dest->
AddEdge(first + lastM, first + pathEnd);
968 lEdge = dest->
AddEdge(first+curP, first+pathEnd);
980 if ( closeIfNeeded ) {
981 if ( closed && lEdge >= 0 ) {
985 dest->
AddEdge(first + lastM, first + pathEnd);
999 for (
auto & pt :
pts) {
1006 bool closed =
false;
1008 while ( curP <
int(
pts.size()) ) {
1013 if ( closeIfNeeded ) {
1014 if ( closed && lEdge >= 0 ) {
1018 lEdge = dest->
AddEdge(first + pathEnd, first+lastM);
1020 dest->
ebData[lEdge].pathID = pathID;
1021 dest->
ebData[lEdge].pieceID =
pts[lm].piece;
1022 dest->
ebData[lEdge].tSt = 0.0;
1023 dest->
ebData[lEdge].tEn = 1.0;
1033 lEdge = dest->
AddEdge(first + pathEnd, first + curP);
1034 dest->
ebData[lEdge].pathID = pathID;
1035 dest->
ebData[lEdge].pieceID =
pts[sbp].piece;
1036 if (
pts[sbp].piece ==
pts[prp].piece ) {
1040 dest->
ebData[lEdge].tSt = 0.0;
1054 if ( closeIfNeeded ) {
1055 if ( closed && lEdge >= 0 ) {
1060 lEdge = dest->
AddEdge(first + pathEnd, first + lastM);
1062 dest->
ebData[lEdge].pathID = pathID;
1063 dest->
ebData[lEdge].pieceID =
pts[lm].piece;
1064 dest->
ebData[lEdge].tSt = 0.0;
1065 dest->
ebData[lEdge].tEn = 1.0;
1074 for (
auto & pt :
pts) {
1081 bool closed =
false;
1083 while ( curP <
int(
pts.size()) ) {
1088 if ( closeIfNeeded ) {
1089 if ( closed && lEdge >= 0 ) {
1093 dest->
AddEdge(first + pathEnd, first + lastM);
1102 lEdge = dest->
AddEdge(first+pathEnd, first+curP);
1114 if ( closeIfNeeded ) {
1115 if ( closed && lEdge >= 0 ) {
1119 dest->
AddEdge(first + pathEnd, first + lastM);
static void ArcAnglesAndCenter(Geom::Point const &iS, Geom::Point const &iE, double rx, double ry, double angle, bool large, bool wise, double &sang, double &eang, Geom::Point &dr)
TODO: insert short description here.
TODO: insert short description here.
Bernstein-Bezier polynomial.
Two-dimensional point that doubles as a vector.
Coord length() const
Compute the distance from origin.
constexpr Point ccw() const
Return a point like this point but rotated -90 degrees.
constexpr Coord lengthSq() const
Rotation around the origin.
void ConvertWithBackData(double threshhold, bool relative=false)
Creates a polyline approximation of the path.
void SetBackData(bool nVal)
Sets the back variable to the value passed in and clears the polyline approximation.
void ResetPoints()
Clears the polyline approximation.
void Fill(Shape *dest, int pathID=-1, bool justAdd=false, bool closeIfNeeded=true, bool invert=false)
Fills the shape with the polyline approximation stored in this object.
int AddForcedPoint()
Adds a forced point to the polyline approximation's list of points.
std::vector< path_lineto > pts
void ConvertEvenLines(double treshhold)
Creates a polyline approximation of the path.
std::vector< ForcedSubdivision > forced_subdivisions
const Geom::Point PrevPoint(const int i) const
void DoArc(Geom::Point const &iS, Geom::Point const &iE, double rx, double ry, double angle, bool large, bool wise, double tresh)
The function is quite similar to RecCubicTo.
std::vector< PathDescr * > descr_cmd
int AddPoint(Geom::Point const &iPt, bool mvto=false)
Adds a point to the polyline approximation's list of points.
void Convert(double treshhold)
Creates a polyline approximation of the path.
A class to store/manipulate directed graphs.
void MakeBackData(bool nVal)
void DisconnectStart(int b)
int AddEdge(int st, int en)
std::vector< back_data > ebData
void ConnectEnd(int p, int b)
int numberOfPoints() const
Returns number of points.
void Reset(int n=0, int m=0)
Clear all data.
void ConnectStart(int p, int b)
int AddPoint(const Geom::Point x)
void DisconnectEnd(int b)
Dim2
2D axis enumeration (X or Y).
T casteljau_subdivision(double t, T const *v, T *left, T *right, unsigned order)
Perform Casteljau subdivision of a Bezier polynomial.
MultiDegree< n > max(MultiDegree< n > const &p, MultiDegree< n > const &q)
Returns the maximal degree appearing in the two arguments for each variables.
void split(vector< Point > const &p, double t, vector< Point > &left, vector< Point > &right)
Piecewise< SBasis > cross(Piecewise< D2< SBasis > > const &a, Piecewise< D2< SBasis > > const &b)
SBasis L2(D2< SBasis > const &a, unsigned k)
Coord LInfty(Point const &p)
TODO: insert short description here.
void invert(const double v[16], double alpha[16])
Elliptical Arc path command.
Cubic Bezier path command.
void dot(Cairo::RefPtr< Cairo::Context > &cr, double x, double y)