Merge branch 'main' into libvgcode

This commit is contained in:
Noisyfox
2025-11-22 19:35:32 +08:00
committed by GitHub
25 changed files with 8998 additions and 25 deletions

View File

@@ -92,6 +92,8 @@ set(lisbslic3r_sources
clipper.hpp
ClipperUtils.cpp
ClipperUtils.hpp
Clipper2Utils.cpp
Clipper2Utils.hpp
ClipperZUtils.hpp
Color.cpp
Color.hpp
@@ -580,6 +582,7 @@ target_link_libraries(libslic3r
boost_libs
cereal::cereal
clipper
Clipper2
eigen
glu-libtess
JPEG::JPEG

View File

@@ -0,0 +1,211 @@
#include "Clipper2Utils.hpp"
#include "libslic3r.h"
#include "clipper2/clipper.h"
namespace Slic3r {
//BBS: FIXME
Slic3r::Polylines Paths64_to_polylines(const Clipper2Lib::Paths64& in)
{
Slic3r::Polylines out;
out.reserve(in.size());
for (const Clipper2Lib::Path64& path64 : in) {
Slic3r::Points points;
points.reserve(path64.size());
for (const Clipper2Lib::Point64& point64 : path64)
points.emplace_back(std::move(Slic3r::Point(point64.x, point64.y)));
out.emplace_back(std::move(Slic3r::Polyline(points)));
}
return out;
}
//BBS: FIXME
template <typename Container>
Clipper2Lib::Paths64 Slic3rPoints_to_Paths64(const Container& in)
{
Clipper2Lib::Paths64 out;
out.reserve(in.size());
for (const auto& item : in) {
Clipper2Lib::Path64 path;
path.reserve(item.size());
for (const Slic3r::Point& point : item.points)
path.emplace_back(std::move(Clipper2Lib::Point64(point.x(), point.y())));
out.emplace_back(std::move(path));
}
return out;
}
Points Path64ToPoints(const Clipper2Lib::Path64& path64)
{
Points points;
points.reserve(path64.size());
for (const Clipper2Lib::Point64 &point64 : path64) points.emplace_back(std::move(Slic3r::Point(point64.x, point64.y)));
return points;
}
static ExPolygons PolyTreeToExPolygons(Clipper2Lib::PolyTree64 &&polytree)
{
struct Inner
{
static void PolyTreeToExPolygonsRecursive(Clipper2Lib::PolyTree64 &&polynode, ExPolygons *expolygons)
{
size_t cnt = expolygons->size();
expolygons->resize(cnt + 1);
(*expolygons)[cnt].contour.points = Path64ToPoints(polynode.Polygon());
(*expolygons)[cnt].holes.resize(polynode.Count());
for (int i = 0; i < polynode.Count(); ++i) {
(*expolygons)[cnt].holes[i].points = Path64ToPoints(polynode[i]->Polygon());
// Add outer polygons contained by (nested within) holes.
for (int j = 0; j < polynode[i]->Count(); ++j) PolyTreeToExPolygonsRecursive(std::move(*polynode[i]->Child(j)), expolygons);
}
}
static size_t PolyTreeCountExPolygons(const Clipper2Lib::PolyPath64& polynode)
{
size_t cnt = 1;
for (size_t i = 0; i < polynode.Count(); ++i) {
for (size_t j = 0; j < polynode.Child(i)->Count(); ++j) cnt += PolyTreeCountExPolygons(*polynode.Child(i)->Child(j));
}
return cnt;
}
};
ExPolygons retval;
size_t cnt = 0;
for (int i = 0; i < polytree.Count(); ++i) cnt += Inner::PolyTreeCountExPolygons(*polytree[i]);
retval.reserve(cnt);
for (int i = 0; i < polytree.Count(); ++i) Inner::PolyTreeToExPolygonsRecursive(std::move(*polytree[i]), &retval);
return retval;
}
void SimplifyPolyTree(const Clipper2Lib::PolyPath64 &polytree, double epsilon, Clipper2Lib::PolyPath64 &result)
{
for (const auto &child : polytree) {
Clipper2Lib::PolyPath64 *newchild = result.AddChild(Clipper2Lib::SimplifyPath(child->Polygon(), epsilon));
SimplifyPolyTree(*child, epsilon, *newchild);
}
}
Clipper2Lib::Paths64 Slic3rPolygons_to_Paths64(const Polygons &in)
{
Clipper2Lib::Paths64 out;
out.reserve(in.size());
for (const Polygon &poly : in) {
Clipper2Lib::Path64 path;
path.reserve(poly.points.size());
for (const Slic3r::Point &point : poly.points) path.emplace_back(std::move(Clipper2Lib::Point64(point.x(), point.y())));
out.emplace_back(std::move(path));
}
return out;
}
Clipper2Lib::Paths64 Slic3rExPolygons_to_Paths64(const ExPolygons& in)
{
Clipper2Lib::Paths64 out;
out.reserve(in.size());
for (const ExPolygon& expolygon : in) {
for (size_t i = 0; i < expolygon.num_contours(); i++) {
const auto &poly = expolygon.contour_or_hole(i);
Clipper2Lib::Path64 path;
path.reserve(poly.points.size());
for (const Slic3r::Point &point : poly.points) path.emplace_back(std::move(Clipper2Lib::Point64(point.x(), point.y())));
out.emplace_back(std::move(path));
}
}
return out;
}
Polylines _clipper2_pl_open(Clipper2Lib::ClipType clipType, const Slic3r::Polylines& subject, const Slic3r::Polygons& clip)
{
Clipper2Lib::Clipper64 c;
c.AddOpenSubject(Slic3rPoints_to_Paths64(subject));
c.AddClip(Slic3rPoints_to_Paths64(clip));
Clipper2Lib::ClipType ct = clipType;
Clipper2Lib::FillRule fr = Clipper2Lib::FillRule::NonZero;
Clipper2Lib::Paths64 solution, solution_open;
c.Execute(ct, fr, solution, solution_open);
Slic3r::Polylines out;
out.reserve(solution.size() + solution_open.size());
polylines_append(out, std::move(Paths64_to_polylines(solution)));
polylines_append(out, std::move(Paths64_to_polylines(solution_open)));
return out;
}
Slic3r::Polylines intersection_pl_2(const Slic3r::Polylines& subject, const Slic3r::Polygons& clip)
{ return _clipper2_pl_open(Clipper2Lib::ClipType::Intersection, subject, clip); }
Slic3r::Polylines diff_pl_2(const Slic3r::Polylines& subject, const Slic3r::Polygons& clip)
{ return _clipper2_pl_open(Clipper2Lib::ClipType::Difference, subject, clip); }
ExPolygons union_ex_2(const Polygons& polygons)
{
Clipper2Lib::Clipper64 c;
c.AddSubject(Slic3rPolygons_to_Paths64(polygons));
Clipper2Lib::ClipType ct = Clipper2Lib::ClipType::Union;
Clipper2Lib::FillRule fr = Clipper2Lib::FillRule::NonZero;
Clipper2Lib::PolyTree64 solution;
c.Execute(ct, fr, solution);
ExPolygons results = PolyTreeToExPolygons(std::move(solution));
return results;
}
ExPolygons union_ex_2(const ExPolygons &expolygons)
{
Clipper2Lib::Clipper64 c;
c.AddSubject(Slic3rExPolygons_to_Paths64(expolygons));
Clipper2Lib::ClipType ct = Clipper2Lib::ClipType::Union;
Clipper2Lib::FillRule fr = Clipper2Lib::FillRule::NonZero;
Clipper2Lib::PolyTree64 solution;
c.Execute(ct, fr, solution);
ExPolygons results = PolyTreeToExPolygons(std::move(solution));
return results;
}
// 对 ExPolygons 进行偏移
ExPolygons offset_ex_2(const ExPolygons &expolygons, double delta)
{
Clipper2Lib::Paths64 subject = Slic3rExPolygons_to_Paths64(expolygons);
Clipper2Lib::ClipperOffset offsetter;
offsetter.AddPaths(subject, Clipper2Lib::JoinType::Round, Clipper2Lib::EndType::Polygon);
Clipper2Lib::PolyPath64 polytree;
offsetter.Execute(delta, polytree);
ExPolygons results = PolyTreeToExPolygons(std::move(polytree));
return results;
}
ExPolygons offset2_ex_2(const ExPolygons& expolygons, double delta1, double delta2)
{
// 1st offset
Clipper2Lib::Paths64 subject = Slic3rExPolygons_to_Paths64(expolygons);
Clipper2Lib::ClipperOffset offsetter;
offsetter.AddPaths(subject, Clipper2Lib::JoinType::Round, Clipper2Lib::EndType::Polygon);
Clipper2Lib::PolyPath64 polytree;
offsetter.Execute(delta1, polytree);
// simplify the result
Clipper2Lib::PolyPath64 polytree2;
SimplifyPolyTree(polytree, SCALED_EPSILON, polytree2);
// 2nd offset
offsetter.Clear();
offsetter.AddPaths(Clipper2Lib::PolyTreeToPaths64(polytree2), Clipper2Lib::JoinType::Round, Clipper2Lib::EndType::Polygon);
polytree.Clear();
offsetter.Execute(delta2, polytree);
// convert back to expolygons
ExPolygons results = PolyTreeToExPolygons(std::move(polytree));
return results;
}
}

View File

@@ -0,0 +1,18 @@
#ifndef slic3r_Clipper2Utils_hpp_
#define slic3r_Clipper2Utils_hpp_
#include "ExPolygon.hpp"
#include "Polygon.hpp"
#include "Polyline.hpp"
namespace Slic3r {
Slic3r::Polylines intersection_pl_2(const Slic3r::Polylines& subject, const Slic3r::Polygons& clip);
Slic3r::Polylines diff_pl_2(const Slic3r::Polylines& subject, const Slic3r::Polygons& clip);
ExPolygons union_ex_2(const Polygons &expolygons);
ExPolygons union_ex_2(const ExPolygons &expolygons);
ExPolygons offset_ex_2(const ExPolygons &expolygons, double delta);
ExPolygons offset2_ex_2(const ExPolygons &expolygons, double delta1, double delta2);
}
#endif

View File

@@ -0,0 +1,167 @@
#ifndef slic3r_Clipper2ZUtils_hpp_
#define slic3r_Clipper2ZUtils_hpp_
#include <numeric>
#include <vector>
#include <algorithm>
#include <clipper2/clipper2_z.hpp>
#include <libslic3r/Point.hpp>
namespace Slic3r { namespace Clipper2ZUtils {
using ZPoint64 = Clipper2Lib_Z::Point64;
using ZPoints64 = Clipper2Lib_Z::Path64;
using ZPath64 = Clipper2Lib_Z::Path64;
using ZPaths64 = Clipper2Lib_Z::Paths64;
inline bool zpoint64_lower(const ZPoint64 &l, const ZPoint64 &r) {
return l.x < r.x || (l.x == r.x && (l.y < r.y || (l.y == r.y && l.z < r.z)));
}
// Convert a single path to zpath with a given Z coordinate.
// If Open, then duplicate the first point at the end.
template<bool Open = false>
inline ZPath64 to_zpath64(const Points &path, int64_t z)
{
ZPath64 out;
if (!path.empty()) {
out.reserve(path.size() + (Open ? 1 : 0));
for (const Point &p : path) out.emplace_back(p.x(), p.y(), z);
if (Open) out.emplace_back(out.front());
}
return out;
}
template<bool Open = false>
inline ZPath64 to_zpath64(const Clipper2Lib_Z::Path64 &path, int64_t z)
{
ZPath64 out;
if (!path.empty()) {
out.reserve(path.size() + (Open ? 1 : 0));
for (const Clipper2Lib_Z::Point64 &p : path) out.emplace_back(p.x, p.y, z);
if (Open) out.emplace_back(out.front());
}
return out;
}
// Convert multiple paths to zpaths with a given Z coordinate.
template<bool Open = false>
inline ZPaths64 to_zpaths64(const VecOfPoints &paths, int64_t z)
{
ZPaths64 out;
out.reserve(paths.size());
for (const Points &path : paths) out.emplace_back(to_zpath64<Open>(path, z));
return out;
}
template<bool Open = false>
inline ZPaths64 to_zpaths64(const Clipper2Lib_Z::Paths64 &paths, int64_t z)
{
ZPaths64 out;
out.reserve(paths.size());
for (const Clipper2Lib_Z::Path64 &path : paths) out.emplace_back(to_zpath64<Open>(path, z));
return out;
}
// Convert multiple expolygons into zpaths with Z specified by index
// offset by base_idx.
template<bool Open = false>
inline ZPaths64 expolygons_to_zpaths64(const ExPolygons &src, int64_t &base_idx)
{
ZPaths64 out;
out.reserve(std::accumulate(src.begin(), src.end(), size_t(0),
[](const size_t acc, const ExPolygon &expoly) { return acc + expoly.num_contours(); }));
for (const ExPolygon &expoly : src) {
out.emplace_back(to_zpath64<Open>(expoly.contour.points, base_idx));
for (const Polygon &hole : expoly.holes)
out.emplace_back(to_zpath64<Open>(hole.points, base_idx));
++base_idx;
}
return out;
}
// Convert multiple expolygons into zpaths with the same Z.
template<bool Open = false>
inline ZPaths64 expolygons_to_zpaths64_with_same_z(const ExPolygons &src, int64_t z)
{
ZPaths64 out;
out.reserve(std::accumulate(src.begin(), src.end(), size_t(0),
[](const size_t acc, const ExPolygon &expoly) { return acc + expoly.num_contours(); }));
for (const ExPolygon &expoly : src) {
out.emplace_back(to_zpath64<Open>(expoly.contour.points, z));
for (const Polygon &hole : expoly.holes)
out.emplace_back(to_zpath64<Open>(hole.points, z));
}
return out;
}
// Convert a zpath back to 2D Points.
// If Open, then duplicate the first point at the end.
template<bool Open = false>
inline Points from_zpath64(const ZPath64 &path)
{
Points out;
if (!path.empty()) {
out.reserve(path.size() + (Open ? 1 : 0));
for (const ZPoint64 &p : path) out.emplace_back(p.x, p.y);
if (Open) out.emplace_back(out.front());
}
return out;
}
// Convert multiple zpaths back to 2D paths.
template<bool Open = false>
inline void from_zpaths64(const ZPaths64 &paths, VecOfPoints &out)
{
out.reserve(out.size() + paths.size());
for (const ZPath64 &path : paths) out.emplace_back(from_zpath64<Open>(path));
}
template<bool Open = false>
inline VecOfPoints from_zpaths64(const ZPaths64 &paths)
{
VecOfPoints out;
from_zpaths64<Open>(paths, out);
return out;
}
// Intersection visitor for Clipper2 (zCallback_).
class Clipper2ZIntersectionVisitor
{
public:
using Intersection = std::pair<int64_t, int64_t>;
using Intersections = std::vector<Intersection>;
Clipper2ZIntersectionVisitor(Intersections &intersections) : m_intersections(intersections) {}
void reset() { m_intersections.clear(); }
void operator()(const ZPoint64 &e1bot, const ZPoint64 &e1top, const ZPoint64 &e2bot, const ZPoint64 &e2top, ZPoint64 &pt)
{
std::array<int64_t, 4> srcs{e1bot.z, e1top.z, e2bot.z, e2top.z};
std::sort(srcs.begin(), srcs.end());
auto it = std::unique(srcs.begin(), srcs.end());
int new_size = std::distance(srcs.begin(), it);
assert(new_size == 1 || new_size == 2);
if (new_size == 1) {
pt.z = srcs[0];
}
else if(new_size == 2){
m_intersections.emplace_back(srcs[0], srcs[1]);
pt.z = -int64_t(m_intersections.size());
}
}
auto clipper_callback()
{
return [this](const ZPoint64 &e1bot, const ZPoint64 &e1top,
const ZPoint64 &e2bot, const ZPoint64 &e2top, ZPoint64 &pt) {
return (*this)(e1bot, e1top, e2bot, e2top, pt); };
}
const Intersections &intersections() const { return m_intersections; }
private:
Intersections &m_intersections;
};
}} // namespace Slic3r::Clipper2ZUtils
#endif // slic3r_Clipper2ZUtils_hpp_

View File

@@ -2731,7 +2731,7 @@ Preset* PresetCollection::find_preset(const std::string &name, bool first_visibl
first_visible_if_not_found ? &this->first_visible() : nullptr;
}
Preset* PresetCollection::find_preset2(const std::string& name, bool auto_match)
Preset* PresetCollection::find_preset2(const std::string& name, bool auto_match/* = true */)
{
auto preset = find_preset(name,false,true);
if (preset == nullptr) {

View File

@@ -1089,7 +1089,7 @@ bool PresetBundle::import_json_presets(PresetsConfigSubstitutions & s
if (inherits_config) {
ConfigOptionString *option_str = dynamic_cast<ConfigOptionString *>(inherits_config);
inherits_value = option_str->value;
inherit_preset = collection->find_preset(inherits_value, false, true);
inherit_preset = collection->find_preset2(inherits_value);
}
if (inherit_preset) {
new_config = inherit_preset->config;