diff -Nru libarea-0.0.20160313.121+git8f8bac8+201804251917~ubuntu18.04.1/Arc.cpp libarea-0.0.20160313.122+git2752cd9+201910311732~ubuntu18.04.1/Arc.cpp --- libarea-0.0.20160313.121+git8f8bac8+201804251917~ubuntu18.04.1/Arc.cpp 2018-04-25 19:17:15.000000000 +0000 +++ libarea-0.0.20160313.122+git2752cd9+201910311732~ubuntu18.04.1/Arc.cpp 2019-10-31 17:32:00.000000000 +0000 @@ -35,13 +35,13 @@ return fabs(ange - angs); } -bool CArc::AlmostALine()const +bool CArc::AlmostALine(double accuracy)const { Point mid_point = MidParam(0.5); - if(Line(m_s, m_e - m_s).Dist(mid_point) <= Point::tolerance) + if(Line2d(m_s, m_e - m_s).Dist(mid_point) <= accuracy) return true; - const double max_arc_radius = 1.0 / Point::tolerance; + const double max_arc_radius = 1.0 / geoff_geometry::TOLERANCE; double radius = m_c.dist(m_s); if (radius > max_arc_radius) { diff -Nru libarea-0.0.20160313.121+git8f8bac8+201804251917~ubuntu18.04.1/Arc.h libarea-0.0.20160313.122+git2752cd9+201910311732~ubuntu18.04.1/Arc.h --- libarea-0.0.20160313.121+git8f8bac8+201804251917~ubuntu18.04.1/Arc.h 2018-04-25 19:17:15.000000000 +0000 +++ libarea-0.0.20160313.122+git2752cd9+201910311732~ubuntu18.04.1/Arc.h 2019-10-31 17:32:00.000000000 +0000 @@ -19,7 +19,7 @@ void SetDirWithPoint(const Point& p); // set m_dir, such that this point lies between m_s and m_e double IncludedAngle()const; // always > 0 - bool AlmostALine()const; + bool AlmostALine(double accuracy)const; Point MidParam(double param)const; void GetSegments(void(*callbackfunc)(const double *p), double pixels_per_mm)const; }; \ No newline at end of file diff -Nru libarea-0.0.20160313.121+git8f8bac8+201804251917~ubuntu18.04.1/Circle.cpp libarea-0.0.20160313.122+git2752cd9+201910311732~ubuntu18.04.1/Circle.cpp --- libarea-0.0.20160313.121+git8f8bac8+201804251917~ubuntu18.04.1/Circle.cpp 2018-04-25 19:17:15.000000000 +0000 +++ libarea-0.0.20160313.122+git2752cd9+201910311732~ubuntu18.04.1/Circle.cpp 2019-10-31 17:32:00.000000000 +0000 @@ -2,9 +2,13 @@ // Copyright 2011, Dan Heeks // This program is released under the BSD license. See the file COPYING for details. +// Circle.cpp +// Copyright 2011, Dan Heeks +// This program is released under the BSD license. See the file COPYING for details. + #include "Circle.h" -Circle::Circle(const Point& p0, const Point& p1, const Point& p2) +CircleOrLine::CircleOrLine(const Point& p0, const Point& p1, const Point& p2) { // from TangentCircles in http://code.google.com/p/heekscad/source/browse/trunk/src/Geom.cpp @@ -12,6 +16,34 @@ m_radius = 0.0; m_c = Point(0, 0); + if (p0 == p2) + { + if (p1 == p0) + { + m_is_a_line = true; + m_p0 = p0; + m_p1 = p0; + } + else + { + m_is_a_line = false; + m_c = (p0 + p1) * 0.5; + m_radius = p0.dist(m_c); + } + return; + } + + geoff_geometry::CLine line(geoff_geometry::Point(p0.x, p0.y), geoff_geometry::Point(p2.x, p2.y)); + if(fabs(line.Dist(geoff_geometry::Point(p1.x, p1.y))) <= Point::tolerance) + { + m_is_a_line = true; + m_p0 = p0; + m_p1 = p2; + return; + } + + m_is_a_line = false; + double x1 = p0.x; double y1 = p0.y; double x2 = p1.x; @@ -27,29 +59,29 @@ double B = 2 * (y1 - y3); double D = (x1 * x1 + y1 * y1) - (x3 * x3 + y3 * y3); - double aBmbA = (a*B - b*A); // aB - bA + double aBmbA = (a*B - b * A); // aB - bA // x = k + Kr where - double k = (B*d - b*D) / aBmbA; + double k = (B*d - b * D) / aBmbA; // y = l + Lr where - double l = (-A*d + a*D)/ aBmbA; + double l = (-A * d + a * D) / aBmbA; double qa = -1; double qb = 0.0; - double qc = k*k + x1*x1 -2*k*x1 + l*l + y1*y1 - 2*l*y1; + double qc = k * k + x1 * x1 - 2 * k*x1 + l * l + y1 * y1 - 2 * l*y1; // solve the quadratic equation, r = (-b +- sqrt(b*b - 4*a*c))/(2 * a) - for(int qs = 0; qs<2; qs++){ - double bb = qb*qb; - double ac4 = 4*qa*qc; - if(ac4 <= bb){ - double r = (-qb + ((qs == 0) ? 1 : -1) * sqrt(bb - ac4))/(2 * qa); + for (int qs = 0; qs < 2; qs++) { + double bb = qb * qb; + double ac4 = 4 * qa*qc; + if (ac4 <= bb) { + double r = (-qb + ((qs == 0) ? 1 : -1) * sqrt(bb - ac4)) / (2 * qa); double x = k; double y = l; // set the circle - if(r >= 0.0){ + if (r >= 0.0) { m_c = Point(x, y); m_radius = r; } @@ -57,22 +89,39 @@ } } -bool Circle::PointIsOn(const Point& p, double accuracy) +bool CircleOrLine::PointIsOn(const Point& p, double accuracy) { + if (m_is_a_line) + { + geoff_geometry::CLine line(geoff_geometry::Point(m_p0.x, m_p0.y), geoff_geometry::Point(m_p1.x, m_p1.y)); + return (fabs(line.Dist(geoff_geometry::Point(p.x, p.y))) <= accuracy); + } double rp = p.dist(m_c); bool on = fabs(m_radius - rp) < accuracy; return on; } -bool Circle::LineIsOn(const Point& p0, const Point& p1, double accuracy) +bool CircleOrLine::LineIsOn(const Point& p0, const Point& p1, double accuracy) { // checks the points are on the arc, to the given accuracy, and the mid point of the line. - if(!PointIsOn(p0, accuracy))return false; - if(!PointIsOn(p1, accuracy))return false; + if (this->m_is_a_line) + { + if (!PointIsOn(p0, accuracy))return false; + if (!PointIsOn(p1, accuracy))return false; + + Point this_dir = m_p1 - m_p0; + this_dir.normalize(); + Point dir = p1 - p0; + dir.normalize(); + return ((dir * this_dir) >= -0.0000000001); // they are going in the same direction + } + + if (!PointIsOn(p0, accuracy))return false; + if (!PointIsOn(p1, accuracy))return false; - Point mid = Point((p0 + p1)/2); - if(!PointIsOn(mid, accuracy))return false; + Point mid = Point((p0 + p1) / 2); + if (!PointIsOn(mid, accuracy))return false; return true; } \ No newline at end of file diff -Nru libarea-0.0.20160313.121+git8f8bac8+201804251917~ubuntu18.04.1/Circle.h libarea-0.0.20160313.122+git2752cd9+201910311732~ubuntu18.04.1/Circle.h --- libarea-0.0.20160313.121+git8f8bac8+201804251917~ubuntu18.04.1/Circle.h 2018-04-25 19:17:15.000000000 +0000 +++ libarea-0.0.20160313.122+git2752cd9+201910311732~ubuntu18.04.1/Circle.h 2019-10-31 17:32:00.000000000 +0000 @@ -6,14 +6,18 @@ #include "Point.h" -class Circle{ + +class CircleOrLine { public: - Point m_c; - double m_radius; + bool m_is_a_line; // true for line, false for circle + Point m_c; // just for circle + double m_radius; // just for circle + Point m_p0; // just for line + Point m_p1; // just for line + + CircleOrLine(const Point& c, double radius) :m_c(c), m_radius(radius), m_is_a_line(false) {} + CircleOrLine(const Point& p0, const Point& p1, const Point& p2); // circle through three points - Circle(const Point& c, double radius):m_c(c), m_radius(radius){} - Circle(const Point& p0, const Point& p1, const Point& p2); // circle through three points - bool PointIsOn(const Point& p, double accuracy); bool LineIsOn(const Point& p0, const Point& p1, double accuracy); }; \ No newline at end of file diff -Nru libarea-0.0.20160313.121+git8f8bac8+201804251917~ubuntu18.04.1/Curve.cpp libarea-0.0.20160313.122+git2752cd9+201910311732~ubuntu18.04.1/Curve.cpp --- libarea-0.0.20160313.121+git8f8bac8+201804251917~ubuntu18.04.1/Curve.cpp 2018-04-25 19:17:15.000000000 +0000 +++ libarea-0.0.20160313.122+git2752cd9+201910311732~ubuntu18.04.1/Curve.cpp 2019-10-31 17:32:00.000000000 +0000 @@ -25,12 +25,12 @@ *this = (*this) / len; return len; } - -Line::Line(const Point& P0, const Point& V):p0(P0), v(V) + +Line2d::Line2d(const Point& P0, const Point& V) :p0(P0), v(V) { } -double Line::Dist(const Point& p)const +double Line2d::Dist(const Point& p)const { Point vn = v; vn.normalize(); @@ -53,8 +53,19 @@ { m_vertices.push_back(vertex); } + + +class CArcOrLine +{ +public: + CArc m_arc; + bool m_is_a_line; + + CArcOrLine(const CArc& arc, bool is_a_line) :m_arc(arc), m_is_a_line(is_a_line){} +}; + -bool CCurve::CheckForArc(const CVertex& prev_vt, std::list& might_be_an_arc, CArc &arc_returned) +bool CCurve::CheckForArc(const CVertex& prev_vt, std::list& might_be_an_arc, CArcOrLine &arc_or_line_returned) { // this examines the vertices in might_be_an_arc // if they do fit an arc, set arc to be the arc that they fit and return true @@ -62,7 +73,7 @@ if(might_be_an_arc.size() < 2)return false; // find middle point - int num = might_be_an_arc.size(); + unsigned int num = (unsigned int)might_be_an_arc.size(); int i = 0; const CVertex* mid_vt = NULL; int mid_i = (num-1)/2; @@ -79,151 +90,187 @@ Point p0(prev_vt.m_p); Point p1(mid_vt->m_p); Point p2(might_be_an_arc.back()->m_p); - Circle c(p0, p1, p2); + CircleOrLine c(p0, p1, p2); - const CVertex* current_vt = &prev_vt; - double accuracy = CArea::m_accuracy * 1.4 / CArea::m_units; + const CVertex* current_vt = &prev_vt; for(std::list::iterator It = might_be_an_arc.begin(); It != might_be_an_arc.end(); It++) { const CVertex* vt = *It; - - if(!c.LineIsOn(current_vt->m_p, vt->m_p, accuracy)) + if(!c.PointIsOn(vt->m_p, CArea::m_accuracy / CArea::m_units * 0.1)) return false; - current_vt = vt; + if(!c.LineIsOn(current_vt->m_p, vt->m_p, CArea::m_accuracy * 2.0 / CArea::m_units)) + return false; + current_vt = vt; } - CArc arc; - arc.m_c = c.m_c; - arc.m_s = prev_vt.m_p; - arc.m_e = might_be_an_arc.back()->m_p; - arc.SetDirWithPoint(might_be_an_arc.front()->m_p); - arc.m_user_data = might_be_an_arc.back()->m_user_data; - - double angs = atan2(arc.m_s.y - arc.m_c.y, arc.m_s.x - arc.m_c.x); - double ange = atan2(arc.m_e.y - arc.m_c.y, arc.m_e.x - arc.m_c.x); - if(arc.m_dir) + CArc arc; + arc.m_s = prev_vt.m_p; + arc.m_e = might_be_an_arc.back()->m_p; + if (c.m_is_a_line) { - // make sure ange > angs - if(ange < angs)ange += 6.2831853071795864; - } - else - { - // make sure angs > ange - if(angs < ange)angs += 6.2831853071795864; + arc_or_line_returned = CArcOrLine(arc, true); + return true; } + arc.m_c = c.m_c; + arc.SetDirWithPoint(might_be_an_arc.front()->m_p); + arc.m_user_data = might_be_an_arc.back()->m_user_data; + + double angs = atan2(arc.m_s.y - arc.m_c.y, arc.m_s.x - arc.m_c.x); + double ange = atan2(arc.m_e.y - arc.m_c.y, arc.m_e.x - arc.m_c.x); + if(arc.m_dir) + { + // make sure ange > angs + if(ange < angs)ange += 6.2831853071795864; + } + else + { + // make sure angs > ange + if(angs < ange)angs += 6.2831853071795864; + } if(arc.IncludedAngle() >= 3.15)return false; // We don't want full arcs, so limit to about 180 degrees for(std::list::iterator It = might_be_an_arc.begin(); It != might_be_an_arc.end(); It++) { const CVertex* vt = *It; - double angp = atan2(vt->m_p.y - arc.m_c.y, vt->m_p.x - arc.m_c.x); - if(arc.m_dir) - { - // make sure angp > angs - if(angp < angs)angp += 6.2831853071795864; - if(angp > ange)return false; - } - else - { - // make sure angp > ange - if(angp < ange)angp += 6.2831853071795864; - if(angp > angs)return false; - } - } - - arc_returned = arc; - return true; -} - -void CCurve::AddArcOrLines(bool check_for_arc, std::list &new_vertices, std::list& might_be_an_arc, CArc &arc, bool &arc_found, bool &arc_added) -{ - if(check_for_arc && CheckForArc(new_vertices.back(), might_be_an_arc, arc)) - { - arc_found = true; - } - else - { - if(arc_found) + double angp = atan2(vt->m_p.y - arc.m_c.y, vt->m_p.x - arc.m_c.x); + if(arc.m_dir) { - if(arc.AlmostALine()) - { - new_vertices.push_back(CVertex(arc.m_e, arc.m_user_data)); - } - else - { - new_vertices.push_back(CVertex(arc.m_dir ? 1:-1, arc.m_e, arc.m_c, arc.m_user_data)); - } - - arc_added = true; - arc_found = false; - const CVertex* back_vt = might_be_an_arc.back(); - might_be_an_arc.clear(); - if(check_for_arc)might_be_an_arc.push_back(back_vt); + // make sure angp > angs + if(angp < angs)angp += 6.2831853071795864; + if(angp > ange)return false; } else { - const CVertex* back_vt = might_be_an_arc.back(); - if(check_for_arc)might_be_an_arc.pop_back(); - for(std::list::iterator It = might_be_an_arc.begin(); It != might_be_an_arc.end(); It++) - { - const CVertex* v = *It; - if(It != might_be_an_arc.begin() || (new_vertices.size() == 0) || (new_vertices.back().m_p != v->m_p)) - { - new_vertices.push_back(*v); - } - } - might_be_an_arc.clear(); - if(check_for_arc)might_be_an_arc.push_back(back_vt); + // make sure angp > ange + if(angp < ange)angp += 6.2831853071795864; + if(angp > angs)return false; } } -} -void CCurve::FitArcs() -{ - std::list new_vertices; + arc_or_line_returned = CArcOrLine(arc, false); + return true; +} + +bool CheckAddedRadii(const std::list &new_vertices) +{ + if (new_vertices.size() > 1) + { + std::list::const_iterator It = new_vertices.end(); + It--; + const CVertex& v = *It; + if (v.m_type != 0) + { + It--; + const CVertex& p = *It; + double r1 = p.m_p.dist(v.m_c); + double r2 = v.m_p.dist(v.m_c); + if (fabs(r1 - r2) > 0.0001) + { + return false; + } + } + } + + return true; +} - std::list might_be_an_arc; - CArc arc; - bool arc_found = false; - bool arc_added = false; - int i = 0; - for(std::list::iterator It = m_vertices.begin(); It != m_vertices.end(); It++, i++) - { - CVertex& vt = *It; - if(vt.m_type || i == 0) - { - if (i != 0) +void CCurve::AddArcOrLines(bool check_for_arc, std::list &new_vertices, std::list& might_be_an_arc, CArcOrLine &arc_or_line, bool &arc_found, bool &arc_added) +{ + if (check_for_arc && CheckForArc(new_vertices.back(), might_be_an_arc, arc_or_line)) + { + arc_found = true; + } + else + { + if (arc_found) + { + if (arc_or_line.m_is_a_line || arc_or_line.m_arc.AlmostALine(CArea::m_accuracy)) { - AddArcOrLines(false, new_vertices, might_be_an_arc, arc, arc_found, arc_added); + new_vertices.push_back(CVertex(arc_or_line.m_arc.m_e, arc_or_line.m_arc.m_user_data)); } - new_vertices.push_back(vt); - } - else - { - might_be_an_arc.push_back(&vt); - - if(might_be_an_arc.size() == 1) - { - } - else - { - AddArcOrLines(true, new_vertices, might_be_an_arc, arc, arc_found, arc_added); - } - } - } + else + { + new_vertices.push_back(CVertex(arc_or_line.m_arc.m_dir ? 1 : -1, arc_or_line.m_arc.m_e, arc_or_line.m_arc.m_c, arc_or_line.m_arc.m_user_data)); + CheckAddedRadii(new_vertices); + } + + arc_added = true; + arc_found = false; + const CVertex* back_vt = might_be_an_arc.back(); + might_be_an_arc.clear(); + if (check_for_arc)might_be_an_arc.push_back(back_vt); + } + else + { + const CVertex* back_vt = might_be_an_arc.back(); + if (check_for_arc)might_be_an_arc.pop_back(); + for (std::list::iterator It = might_be_an_arc.begin(); It != might_be_an_arc.end(); It++) + { + const CVertex* v = *It; + if (It != might_be_an_arc.begin() || (new_vertices.size() == 0) || (new_vertices.back().m_p != v->m_p)) + { + new_vertices.push_back(*v); + CheckAddedRadii(new_vertices); + } + } + might_be_an_arc.clear(); + if (check_for_arc)might_be_an_arc.push_back(back_vt); + } + } +} - if(might_be_an_arc.size() > 0)AddArcOrLines(false, new_vertices, might_be_an_arc, arc, arc_found, arc_added); - if(arc_added) - { - m_vertices.clear(); - for(std::list::iterator It = new_vertices.begin(); It != new_vertices.end(); It++)m_vertices.push_back(*It); - for(std::list::iterator It = might_be_an_arc.begin(); It != might_be_an_arc.end(); It++)m_vertices.push_back(*(*It)); - } +void CCurve::FitArcs() +{ + std::list new_vertices; + + std::list might_be_an_arc; + CArcOrLine arc_or_line(CArc(), false); + bool arc_found = false; + bool arc_added = false; + + int i = 0; + const CVertex* prev_vt = NULL; + for (std::list::iterator It = m_vertices.begin(); It != m_vertices.end(); It++, i++) + { + CVertex& vt = *It; + if (vt.m_type || i == 0) + { + if (i != 0) + { + AddArcOrLines(false, new_vertices, might_be_an_arc, arc_or_line, arc_found, arc_added); + } + new_vertices.push_back(vt); + } + else + { + if (vt.m_p != prev_vt->m_p) + { + might_be_an_arc.push_back(&vt); + + if (might_be_an_arc.size() == 1) + { + } + else + { + AddArcOrLines(true, new_vertices, might_be_an_arc, arc_or_line, arc_found, arc_added); + } + } + } + prev_vt = &vt; + } + + if (might_be_an_arc.size() > 0)AddArcOrLines(false, new_vertices, might_be_an_arc, arc_or_line, arc_found, arc_added); + + if (arc_added) + { + m_vertices.clear(); + for (std::list::iterator It = new_vertices.begin(); It != new_vertices.end(); It++)m_vertices.push_back(*It); + for (std::list::iterator It = might_be_an_arc.begin(); It != might_be_an_arc.end(); It++)m_vertices.push_back(*(*It)); + } } - void CCurve::UnFitArcs() { std::list new_pts; @@ -282,8 +329,8 @@ if (Segments < 1) Segments=1; - if (Segments > 100) - Segments=100; + if (Segments > 5000) + Segments=5000; dphi=phit/(Segments); diff -Nru libarea-0.0.20160313.121+git8f8bac8+201804251917~ubuntu18.04.1/Curve.h libarea-0.0.20160313.122+git2752cd9+201910311732~ubuntu18.04.1/Curve.h --- libarea-0.0.20160313.121+git8f8bac8+201804251917~ubuntu18.04.1/Curve.h 2018-04-25 19:17:15.000000000 +0000 +++ libarea-0.0.20160313.122+git2752cd9+201910311732~ubuntu18.04.1/Curve.h 2019-10-31 17:32:00.000000000 +0000 @@ -10,13 +10,13 @@ #include "Point.h" #include "Box2D.h" -class Line{ +class Line2d{ public: Point p0; Point v; // constructors - Line(const Point& P0, const Point& V); + Line2d(const Point& P0, const Point& V); double Dist(const Point& p)const; }; @@ -64,13 +64,15 @@ void Intersect(const Span& s, std::list &pts)const; // finds all the intersection points between two spans }; +class CArcOrLine; + class CCurve { // a closed curve, please make sure you add an end point, the same as the start point protected: - void AddArcOrLines(bool check_for_arc, std::list &new_vertices, std::list& might_be_an_arc, CArc &arc, bool &arc_found, bool &arc_added); - bool CheckForArc(const CVertex& prev_vt, std::list& might_be_an_arc, CArc &arc); + void AddArcOrLines(bool check_for_arc, std::list &new_vertices, std::list& might_be_an_arc, CArcOrLine &arc_or_line, bool &arc_found, bool &arc_added); + bool CheckForArc(const CVertex& prev_vt, std::list& might_be_an_arc, CArcOrLine &arc_or_line); public: std::list m_vertices; diff -Nru libarea-0.0.20160313.121+git8f8bac8+201804251917~ubuntu18.04.1/debian/bzr-builder.manifest libarea-0.0.20160313.122+git2752cd9+201910311732~ubuntu18.04.1/debian/bzr-builder.manifest --- libarea-0.0.20160313.121+git8f8bac8+201804251917~ubuntu18.04.1/debian/bzr-builder.manifest 2018-04-25 19:17:15.000000000 +0000 +++ libarea-0.0.20160313.122+git2752cd9+201910311732~ubuntu18.04.1/debian/bzr-builder.manifest 2019-10-31 17:32:00.000000000 +0000 @@ -1,2 +1,2 @@ -# bzr-builder format 0.4 deb-version 0.0.20160313.121+git8f8bac8+201804251917 -lp:libarea revid:git-v1:8f8bac811c10f1f01fda0d742a18591f61dd76ee +# bzr-builder format 0.4 deb-version 0.0.20160313.122+git2752cd9+201910311732 +lp:libarea revid:git-v1:2752cd989f53e9e2f52663e731ebfdf3bff2ebe8 diff -Nru libarea-0.0.20160313.121+git8f8bac8+201804251917~ubuntu18.04.1/debian/changelog libarea-0.0.20160313.122+git2752cd9+201910311732~ubuntu18.04.1/debian/changelog --- libarea-0.0.20160313.121+git8f8bac8+201804251917~ubuntu18.04.1/debian/changelog 2018-04-25 19:17:15.000000000 +0000 +++ libarea-0.0.20160313.122+git2752cd9+201910311732~ubuntu18.04.1/debian/changelog 2019-10-31 17:32:00.000000000 +0000 @@ -1,8 +1,8 @@ -libarea (0.0.20160313.121+git8f8bac8+201804251917~ubuntu18.04.1) bionic; urgency=low +libarea (0.0.20160313.122+git2752cd9+201910311732~ubuntu18.04.1) bionic; urgency=low * Auto build. - -- neomilium Wed, 25 Apr 2018 19:17:15 +0000 + -- neomilium Thu, 31 Oct 2019 17:32:00 +0000 libarea (0.0.20160313-0) unstable; urgency=low