kopia lustrzana https://github.com/jaseg/gerbolyze
svg-flatten: Add cubic bezier support for newer usvg versions
rodzic
8ab0c9fa01
commit
00eb9594d6
|
@ -79,7 +79,7 @@ def paste(input_gerbers, input_svg, output_gerbers, is_zip,
|
|||
(('drill', 'plated'), stack.drill_pth),
|
||||
(('drill', 'nonplated'), stack.drill_npth)]:
|
||||
logging.info(f'Layer {side} {use}')
|
||||
if (soup_layer := soup.find(id=f'g-{side}-{use}')):
|
||||
if (soup_layer := soup.find('g', id=f'g-{side}-{use}')):
|
||||
if not soup_layer.contents:
|
||||
logging.info(f' Corresponding overlay layer is empty. Skipping.')
|
||||
else:
|
||||
|
|
|
@ -2,6 +2,28 @@
|
|||
#include "gerbolyze.hpp"
|
||||
|
||||
namespace gerbolyze {
|
||||
class curve3_div {
|
||||
public:
|
||||
curve3_div(double distance_tolerance=0.1, double angle_tolerance=0.0, double cusp_limit=0.0)
|
||||
: m_cusp_limit(cusp_limit),
|
||||
m_distance_tolerance_square(0.25*distance_tolerance*distance_tolerance),
|
||||
m_angle_tolerance(angle_tolerance)
|
||||
{
|
||||
}
|
||||
|
||||
void run(double x1, double y1, double x2, double y2, double x3, double y3);
|
||||
const std::vector<d2p> &points() { return m_points; }
|
||||
|
||||
private:
|
||||
void recursive_bezier(double x1, double y1, double x2, double y2,
|
||||
double x3, double y3,
|
||||
unsigned level);
|
||||
double m_cusp_limit;
|
||||
double m_distance_tolerance_square;
|
||||
double m_angle_tolerance;
|
||||
std::vector<d2p> m_points;
|
||||
};
|
||||
|
||||
class curve4_div {
|
||||
public:
|
||||
curve4_div(double distance_tolerance=0.1, double angle_tolerance=0.0, double cusp_limit=0.0)
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <iostream>
|
||||
#include <string>
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
|
||||
#include <pugixml.hpp>
|
||||
|
||||
|
|
|
@ -19,7 +19,107 @@ static inline double calc_sq_distance(double x1, double y1, double x2, double y2
|
|||
return dx * dx + dy * dy;
|
||||
}
|
||||
|
||||
void curve4_div::run(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4) {
|
||||
/* Quadratic beziers */
|
||||
|
||||
void curve3_div::run(double x1, double y1, double x2, double y2, double x3, double y3)
|
||||
{
|
||||
m_points.clear();
|
||||
m_points.emplace_back(d2p{x1, y1});
|
||||
recursive_bezier(x1, y1, x2, y2, x3, y3, 0);
|
||||
m_points.emplace_back(d2p{x3, y3});
|
||||
}
|
||||
|
||||
void curve3_div::recursive_bezier(double x1, double y1, double x2, double y2, double x3, double y3, unsigned level)
|
||||
{
|
||||
if(level > curve_recursion_limit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate all the mid-points of the line segments
|
||||
//----------------------
|
||||
double x12 = (x1 + x2) / 2;
|
||||
double y12 = (y1 + y2) / 2;
|
||||
double x23 = (x2 + x3) / 2;
|
||||
double y23 = (y2 + y3) / 2;
|
||||
double x123 = (x12 + x23) / 2;
|
||||
double y123 = (y12 + y23) / 2;
|
||||
|
||||
double dx = x3-x1;
|
||||
double dy = y3-y1;
|
||||
double d = fabs(((x2 - x3) * dy - (y2 - y3) * dx));
|
||||
double da;
|
||||
double pi = M_PI;
|
||||
|
||||
if(d > curve_collinearity_epsilon)
|
||||
{
|
||||
// Regular case
|
||||
//-----------------
|
||||
if(d * d <= m_distance_tolerance_square * (dx*dx + dy*dy))
|
||||
{
|
||||
// If the curvature doesn't exceed the distance_tolerance value
|
||||
// we tend to finish subdivisions.
|
||||
//----------------------
|
||||
if(m_angle_tolerance < curve_angle_tolerance_epsilon)
|
||||
{
|
||||
m_points.emplace_back(d2p{x123, y123});
|
||||
return;
|
||||
}
|
||||
|
||||
// Angle & Cusp Condition
|
||||
//----------------------
|
||||
da = fabs(atan2(y3 - y2, x3 - x2) - atan2(y2 - y1, x2 - x1));
|
||||
if(da >= pi) da = 2*pi - da;
|
||||
|
||||
if(da < m_angle_tolerance)
|
||||
{
|
||||
// Finally we can stop the recursion
|
||||
//----------------------
|
||||
m_points.emplace_back(d2p{x123, y123});
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Collinear case
|
||||
//------------------
|
||||
da = dx*dx + dy*dy;
|
||||
if(da == 0)
|
||||
{
|
||||
d = calc_sq_distance(x1, y1, x2, y2);
|
||||
}
|
||||
else
|
||||
{
|
||||
d = ((x2 - x1)*dx + (y2 - y1)*dy) / da;
|
||||
if(d > 0 && d < 1)
|
||||
{
|
||||
// Simple collinear case, 1---2---3
|
||||
// We can leave just two endpoints
|
||||
return;
|
||||
}
|
||||
if(d <= 0) d = calc_sq_distance(x2, y2, x1, y1);
|
||||
else if(d >= 1) d = calc_sq_distance(x2, y2, x3, y3);
|
||||
else d = calc_sq_distance(x2, y2, x1 + d*dx, y1 + d*dy);
|
||||
}
|
||||
if(d < m_distance_tolerance_square)
|
||||
{
|
||||
m_points.emplace_back(d2p{x2, y2});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Continue subdivision
|
||||
//----------------------
|
||||
recursive_bezier(x1, y1, x12, y12, x123, y123, level + 1);
|
||||
recursive_bezier(x123, y123, x23, y23, x3, y3, level + 1);
|
||||
}
|
||||
|
||||
|
||||
/* Cubic beziers */
|
||||
|
||||
void curve4_div::run(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4)
|
||||
{
|
||||
m_points.clear();
|
||||
m_points.emplace_back(d2p{x1, y1});
|
||||
recursive_bezier(x1, y1, x2, y2, x3, y3, x4, y4, 0);
|
||||
|
|
|
@ -77,8 +77,7 @@ static pair<bool, bool> flatten_path(ClipperLib::Paths &stroke_open, ClipperLib:
|
|||
(ClipperLib::cInt)round(a[1]*clipper_scale)
|
||||
});
|
||||
|
||||
} else { /* Curve to */
|
||||
assert(cmd == "C"); /* guaranteed by usvg */
|
||||
} else if (cmd == "C") { /* Curve to */
|
||||
in >> b[0] >> b[1]; /* first control point */
|
||||
in >> c[0] >> c[1]; /* second control point */
|
||||
in >> d[0] >> d[1]; /* end point */
|
||||
|
@ -95,6 +94,24 @@ static pair<bool, bool> flatten_path(ClipperLib::Paths &stroke_open, ClipperLib:
|
|||
}
|
||||
|
||||
a = d; /* set last point to curve end point */
|
||||
|
||||
} else { /* Curve to */
|
||||
assert(cmd == "Q"); /* guaranteed by usvg */
|
||||
in >> b[0] >> b[1]; /* control point */
|
||||
in >> c[0] >> c[1]; /* end point */
|
||||
assert (!in.fail()); /* guaranteed by usvg */
|
||||
|
||||
gerbolyze::curve3_div c3div(distance_tolerance_px);
|
||||
c3div.run(a[0], a[1], b[0], b[1], c[0], c[1]);
|
||||
|
||||
for (auto &pt : c3div.points()) {
|
||||
in_poly.emplace_back(ClipperLib::IntPoint{
|
||||
(ClipperLib::cInt)round(pt[0]*clipper_scale),
|
||||
(ClipperLib::cInt)round(pt[1]*clipper_scale)
|
||||
});
|
||||
}
|
||||
|
||||
a = c; /* set last point to curve end point */
|
||||
}
|
||||
|
||||
first = false;
|
||||
|
|
Ładowanie…
Reference in New Issue