mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-07-27 04:42:33 +00:00
Merge branch 'main' into libvgcode
This commit is contained in:
@@ -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
|
||||
|
||||
211
src/libslic3r/Clipper2Utils.cpp
Normal file
211
src/libslic3r/Clipper2Utils.cpp
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
18
src/libslic3r/Clipper2Utils.hpp
Normal file
18
src/libslic3r/Clipper2Utils.hpp
Normal 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
|
||||
167
src/libslic3r/Clipper2ZUtils.hpp
Normal file
167
src/libslic3r/Clipper2ZUtils.hpp
Normal 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_
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user