mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-16 21:42:43 +00:00
Merge remote-tracking branch 'upstream/main' into feature/pressure-advance-pattern-method
This commit is contained in:
-2769
File diff suppressed because it is too large
Load Diff
@@ -17,6 +17,8 @@ constexpr auto CLIPPER2_VERSION = "1.0.6";
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include "clipper.core.h"
|
||||
|
||||
namespace Clipper2Lib {
|
||||
@@ -31,19 +33,19 @@ namespace Clipper2Lib {
|
||||
|
||||
//Note: all clipping operations except for Difference are commutative.
|
||||
enum class ClipType { None, Intersection, Union, Difference, Xor };
|
||||
|
||||
|
||||
enum class PathType { Subject, Clip };
|
||||
|
||||
enum class VertexFlags : uint32_t {
|
||||
None = 0, OpenStart = 1, OpenEnd = 2, LocalMax = 4, LocalMin = 8
|
||||
};
|
||||
|
||||
constexpr enum VertexFlags operator &(enum VertexFlags a, enum VertexFlags b)
|
||||
constexpr enum VertexFlags operator &(enum VertexFlags a, enum VertexFlags b)
|
||||
{
|
||||
return (enum VertexFlags)(uint32_t(a) & uint32_t(b));
|
||||
}
|
||||
|
||||
constexpr enum VertexFlags operator |(enum VertexFlags a, enum VertexFlags b)
|
||||
constexpr enum VertexFlags operator |(enum VertexFlags a, enum VertexFlags b)
|
||||
{
|
||||
return (enum VertexFlags)(uint32_t(a) | uint32_t(b));
|
||||
}
|
||||
@@ -97,7 +99,7 @@ namespace Clipper2Lib {
|
||||
//Important: UP and DOWN here are premised on Y-axis positive down
|
||||
//displays, which is the orientation used in Clipper's development.
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
struct Active {
|
||||
Point64 bot;
|
||||
Point64 top;
|
||||
@@ -168,7 +170,7 @@ namespace Clipper2Lib {
|
||||
std::vector<LocalMinima*>::iterator current_locmin_iter_;
|
||||
std::vector<Vertex*> vertex_lists_;
|
||||
std::priority_queue<int64_t> scanline_list_;
|
||||
std::vector<IntersectNode> intersect_nodes_;
|
||||
std::vector<IntersectNode> intersect_nodes_;
|
||||
std::vector<Joiner*> joiner_list_; //pointers in case of memory reallocs
|
||||
void Reset();
|
||||
void InsertScanline(int64_t y);
|
||||
@@ -197,7 +199,7 @@ namespace Clipper2Lib {
|
||||
void ProcessIntersectList();
|
||||
void SwapPositionsInAEL(Active& edge1, Active& edge2);
|
||||
OutPt* AddOutPt(const Active &e, const Point64& pt);
|
||||
OutPt* AddLocalMinPoly(Active &e1, Active &e2,
|
||||
OutPt* AddLocalMinPoly(Active &e1, Active &e2,
|
||||
const Point64& pt, bool is_new = false);
|
||||
OutPt* AddLocalMaxPoly(Active &e1, Active &e2, const Point64& pt);
|
||||
void DoHorizontal(Active &horz);
|
||||
@@ -254,7 +256,7 @@ namespace Clipper2Lib {
|
||||
PolyPath* parent_;
|
||||
public:
|
||||
PolyPath(PolyPath* parent = nullptr): parent_(parent){}
|
||||
virtual ~PolyPath() { Clear(); };
|
||||
virtual ~PolyPath() { Clear(); };
|
||||
//https://en.cppreference.com/w/cpp/language/rule_of_three
|
||||
PolyPath(const PolyPath&) = delete;
|
||||
PolyPath& operator=(const PolyPath&) = delete;
|
||||
@@ -274,7 +276,7 @@ namespace Clipper2Lib {
|
||||
|
||||
const PolyPath* Parent() const { return parent_; }
|
||||
|
||||
bool IsHole() const
|
||||
bool IsHole() const
|
||||
{
|
||||
const PolyPath* pp = parent_;
|
||||
bool is_hole = pp;
|
||||
@@ -364,13 +366,13 @@ namespace Clipper2Lib {
|
||||
PathD polygon_;
|
||||
typedef typename std::vector<PolyPathD*>::const_iterator ppD_itor;
|
||||
public:
|
||||
PolyPathD(PolyPathD* parent = nullptr) : PolyPath(parent)
|
||||
PolyPathD(PolyPathD* parent = nullptr) : PolyPath(parent)
|
||||
{
|
||||
inv_scale_ = parent ? parent->inv_scale_ : 1.0;
|
||||
}
|
||||
PolyPathD* operator [] (size_t index)
|
||||
{
|
||||
return static_cast<PolyPathD*>(childs_[index]);
|
||||
PolyPathD* operator [] (size_t index)
|
||||
{
|
||||
return static_cast<PolyPathD*>(childs_[index]);
|
||||
}
|
||||
ppD_itor begin() const { return childs_.cbegin(); }
|
||||
ppD_itor end() const { return childs_.cend(); }
|
||||
@@ -437,7 +439,7 @@ namespace Clipper2Lib {
|
||||
return Execute(clip_type, fill_rule, closed_paths, dummy);
|
||||
}
|
||||
|
||||
bool Execute(ClipType clip_type, FillRule fill_rule,
|
||||
bool Execute(ClipType clip_type, FillRule fill_rule,
|
||||
Paths64& closed_paths, Paths64& open_paths)
|
||||
{
|
||||
closed_paths.clear();
|
||||
@@ -509,12 +511,12 @@ namespace Clipper2Lib {
|
||||
void CheckCallback()
|
||||
{
|
||||
if(zCallback_)
|
||||
// if the user defined float point callback has been assigned
|
||||
// if the user defined float point callback has been assigned
|
||||
// then assign the proxy callback function
|
||||
ClipperBase::zCallback_ =
|
||||
ClipperBase::zCallback_ =
|
||||
std::bind(&ClipperD::ZCB, this, std::placeholders::_1,
|
||||
std::placeholders::_2, std::placeholders::_3,
|
||||
std::placeholders::_4, std::placeholders::_5);
|
||||
std::placeholders::_4, std::placeholders::_5);
|
||||
else
|
||||
ClipperBase::zCallback_ = nullptr;
|
||||
}
|
||||
@@ -581,6 +583,6 @@ namespace Clipper2Lib {
|
||||
|
||||
};
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
#endif // CLIPPER_ENGINE_H
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
#include <algorithm>
|
||||
#include "clipper2/clipper.engine.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
namespace Clipper2Lib {
|
||||
|
||||
static const double FloatingPointTolerance = 1.0e-12;
|
||||
@@ -94,7 +97,7 @@ namespace Clipper2Lib {
|
||||
|
||||
inline bool IsOpenEnd(const Vertex& v)
|
||||
{
|
||||
return (v.flags & (VertexFlags::OpenStart | VertexFlags::OpenEnd)) !=
|
||||
return (v.flags & (VertexFlags::OpenStart | VertexFlags::OpenEnd)) !=
|
||||
VertexFlags::None;
|
||||
}
|
||||
|
||||
@@ -189,8 +192,8 @@ namespace Clipper2Lib {
|
||||
}
|
||||
|
||||
inline Point64 GetEndE1ClosestToEndE2(
|
||||
const Active& e1, const Active& e2)
|
||||
{
|
||||
const Active& e1, const Active& e2)
|
||||
{
|
||||
double d[] = {
|
||||
DistanceSqr(e1.bot, e2.bot),
|
||||
DistanceSqr(e1.top, e2.top),
|
||||
@@ -204,7 +207,7 @@ namespace Clipper2Lib {
|
||||
if (d[i] < d[idx]) idx = i;
|
||||
if (d[i] == 0) break;
|
||||
}
|
||||
switch (idx)
|
||||
switch (idx)
|
||||
{
|
||||
case 1: case 2: return e1.top;
|
||||
default: return e1.bot;
|
||||
@@ -214,7 +217,7 @@ namespace Clipper2Lib {
|
||||
Point64 GetIntersectPoint(const Active& e1, const Active& e2)
|
||||
{
|
||||
double b1, b2, q = (e1.dx - e2.dx);
|
||||
if (std::abs(q) < 1e-5) // 1e-5 is a rough empirical limit
|
||||
if (std::abs(q) < 1e-5) // 1e-5 is a rough empirical limit
|
||||
return GetEndE1ClosestToEndE2(e1, e2); // ie almost parallel
|
||||
|
||||
if (e1.dx == 0)
|
||||
@@ -235,7 +238,7 @@ namespace Clipper2Lib {
|
||||
{
|
||||
b1 = e1.bot.x - e1.bot.y * e1.dx;
|
||||
b2 = e2.bot.x - e2.bot.y * e2.dx;
|
||||
|
||||
|
||||
q = (b2 - b1) / q;
|
||||
return (abs(e1.dx) < abs(e2.dx)) ?
|
||||
Point64(static_cast<int64_t>(e1.dx * q + b1),
|
||||
@@ -306,7 +309,7 @@ namespace Clipper2Lib {
|
||||
|
||||
|
||||
//PrevPrevVertex: useful to get the (inverted Y-axis) top of the
|
||||
//alternate edge (ie left or right bound) during edge insertion.
|
||||
//alternate edge (ie left or right bound) during edge insertion.
|
||||
inline Vertex* PrevPrevVertex(const Active& ae)
|
||||
{
|
||||
if (ae.wind_dx > 0)
|
||||
@@ -353,7 +356,7 @@ namespace Clipper2Lib {
|
||||
while (result->next->pt.y == result->pt.y) result = result->next;
|
||||
else
|
||||
while (result->prev->pt.y == result->pt.y) result = result->prev;
|
||||
if (!IsMaxima(*result)) result = nullptr; // not a maxima
|
||||
if (!IsMaxima(*result)) result = nullptr; // not a maxima
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -494,7 +497,7 @@ namespace Clipper2Lib {
|
||||
return result * 0.5;
|
||||
}
|
||||
|
||||
inline double AreaTriangle(const Point64& pt1,
|
||||
inline double AreaTriangle(const Point64& pt1,
|
||||
const Point64& pt2, const Point64& pt3)
|
||||
{
|
||||
return (static_cast<double>(pt3.y + pt1.y) * static_cast<double>(pt3.x - pt1.x) +
|
||||
@@ -630,7 +633,7 @@ namespace Clipper2Lib {
|
||||
Clear();
|
||||
}
|
||||
|
||||
void ClipperBase::DeleteEdges(Active*& e)
|
||||
void ClipperBase::DeleteEdges(Active*& e)
|
||||
{
|
||||
while (e)
|
||||
{
|
||||
@@ -681,7 +684,7 @@ namespace Clipper2Lib {
|
||||
void ClipperBase::SetZ(const Active& e1, const Active& e2, Point64& ip)
|
||||
{
|
||||
if (!zCallback_) return;
|
||||
// prioritize subject over clip vertices by passing
|
||||
// prioritize subject over clip vertices by passing
|
||||
// subject vertices before clip vertices in the callback
|
||||
if (GetPolyType(e1) == PathType::Subject)
|
||||
{
|
||||
@@ -872,19 +875,19 @@ namespace Clipper2Lib {
|
||||
case FillRule::EvenOdd:
|
||||
break;
|
||||
case FillRule::NonZero:
|
||||
if (abs(e.wind_cnt) != 1) return false;
|
||||
if (abs(e.wind_cnt) != 1) return false;
|
||||
break;
|
||||
case FillRule::Positive:
|
||||
if (e.wind_cnt != 1) return false;
|
||||
if (e.wind_cnt != 1) return false;
|
||||
break;
|
||||
case FillRule::Negative:
|
||||
if (e.wind_cnt != -1) return false;
|
||||
if (e.wind_cnt != -1) return false;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (cliptype_)
|
||||
{
|
||||
case ClipType::None:
|
||||
case ClipType::None:
|
||||
return false;
|
||||
case ClipType::Intersection:
|
||||
switch (fillrule_)
|
||||
@@ -914,17 +917,17 @@ namespace Clipper2Lib {
|
||||
bool result;
|
||||
switch (fillrule_)
|
||||
{
|
||||
case FillRule::Positive:
|
||||
result = (e.wind_cnt2 <= 0);
|
||||
case FillRule::Positive:
|
||||
result = (e.wind_cnt2 <= 0);
|
||||
break;
|
||||
case FillRule::Negative:
|
||||
result = (e.wind_cnt2 >= 0);
|
||||
result = (e.wind_cnt2 >= 0);
|
||||
break;
|
||||
default:
|
||||
default:
|
||||
result = (e.wind_cnt2 == 0);
|
||||
}
|
||||
if (GetPolyType(e) == PathType::Subject)
|
||||
return result;
|
||||
return result;
|
||||
else
|
||||
return !result;
|
||||
break;
|
||||
@@ -940,15 +943,15 @@ namespace Clipper2Lib {
|
||||
bool is_in_clip, is_in_subj;
|
||||
switch (fillrule_)
|
||||
{
|
||||
case FillRule::Positive:
|
||||
is_in_clip = e.wind_cnt2 > 0;
|
||||
case FillRule::Positive:
|
||||
is_in_clip = e.wind_cnt2 > 0;
|
||||
is_in_subj = e.wind_cnt > 0;
|
||||
break;
|
||||
case FillRule::Negative:
|
||||
is_in_clip = e.wind_cnt2 < 0;
|
||||
case FillRule::Negative:
|
||||
is_in_clip = e.wind_cnt2 < 0;
|
||||
is_in_subj = e.wind_cnt < 0;
|
||||
break;
|
||||
default:
|
||||
default:
|
||||
is_in_clip = e.wind_cnt2 != 0;
|
||||
is_in_subj = e.wind_cnt != 0;
|
||||
}
|
||||
@@ -1085,15 +1088,15 @@ namespace Clipper2Lib {
|
||||
//the direction they're about to turn
|
||||
if (!IsMaxima(resident) && (resident.top.y > newcomer.top.y))
|
||||
{
|
||||
return CrossProduct(newcomer.bot,
|
||||
return CrossProduct(newcomer.bot,
|
||||
resident.top, NextVertex(resident)->pt) <= 0;
|
||||
}
|
||||
else if (!IsMaxima(newcomer) && (newcomer.top.y > resident.top.y))
|
||||
else if (!IsMaxima(newcomer) && (newcomer.top.y > resident.top.y))
|
||||
{
|
||||
return CrossProduct(newcomer.bot,
|
||||
newcomer.top, NextVertex(newcomer)->pt) >= 0;
|
||||
}
|
||||
|
||||
|
||||
int64_t y = newcomer.bot.y;
|
||||
bool newcomerIsLeft = newcomer.is_left_bound;
|
||||
|
||||
@@ -1103,7 +1106,7 @@ namespace Clipper2Lib {
|
||||
else if (resident.is_left_bound != newcomerIsLeft)
|
||||
return newcomerIsLeft;
|
||||
else if (CrossProduct(PrevPrevVertex(resident)->pt,
|
||||
resident.bot, resident.top) == 0) return true;
|
||||
resident.bot, resident.top) == 0) return true;
|
||||
else
|
||||
//compare turning direction of the alternate bound
|
||||
return (CrossProduct(PrevPrevVertex(resident)->pt,
|
||||
@@ -1319,7 +1322,7 @@ namespace Clipper2Lib {
|
||||
SetSides(*outrec, e1, e2);
|
||||
else
|
||||
SetSides(*outrec, e2, e1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Active* prevHotEdge = GetPrevHotEdge(e1);
|
||||
@@ -1335,7 +1338,7 @@ namespace Clipper2Lib {
|
||||
else
|
||||
SetSides(*outrec, e1, e2);
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
outrec->owner = nullptr;
|
||||
if (is_new)
|
||||
@@ -1344,7 +1347,7 @@ namespace Clipper2Lib {
|
||||
SetSides(*outrec, e2, e1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
OutPt* op = new OutPt(pt, outrec);
|
||||
outrec->pts = op;
|
||||
return op;
|
||||
@@ -1359,7 +1362,7 @@ namespace Clipper2Lib {
|
||||
SwapFrontBackSides(*e1.outrec);
|
||||
else if (IsOpenEnd(e2))
|
||||
SwapFrontBackSides(*e2.outrec);
|
||||
else
|
||||
else
|
||||
{
|
||||
succeeded_ = false;
|
||||
return nullptr;
|
||||
@@ -1369,7 +1372,7 @@ namespace Clipper2Lib {
|
||||
OutPt* result = AddOutPt(e1, pt);
|
||||
if (e1.outrec == e2.outrec)
|
||||
{
|
||||
OutRec& outrec = *e1.outrec;
|
||||
OutRec& outrec = *e1.outrec;
|
||||
outrec.pts = result;
|
||||
|
||||
UncoupleOutRec(e1);
|
||||
@@ -1523,7 +1526,7 @@ namespace Clipper2Lib {
|
||||
|
||||
void ClipperBase::DoSplitOp(OutRec* outrec, OutPt* splitOp)
|
||||
{
|
||||
// splitOp.prev -> splitOp &&
|
||||
// splitOp.prev -> splitOp &&
|
||||
// splitOp.next -> splitOp.next.next are intersecting
|
||||
OutPt* prevOp = splitOp->prev;
|
||||
OutPt* nextNextOp = splitOp->next->next;
|
||||
@@ -1572,7 +1575,7 @@ namespace Clipper2Lib {
|
||||
SafeDeleteOutPtJoiners(splitOp->next);
|
||||
SafeDeleteOutPtJoiners(splitOp);
|
||||
|
||||
if (absArea2 >= 1 &&
|
||||
if (absArea2 >= 1 &&
|
||||
(absArea2 > absArea1 || (area2 > 0) == (area1 > 0)))
|
||||
{
|
||||
OutRec* newOutRec = new OutRec();
|
||||
@@ -1762,7 +1765,7 @@ namespace Clipper2Lib {
|
||||
else result = result->next_in_ael;
|
||||
}
|
||||
result = e->prev_in_ael;
|
||||
while (result)
|
||||
while (result)
|
||||
{
|
||||
if (result->local_min == e->local_min) return result;
|
||||
else if (!IsHorizontal(*result) && e->bot != result->bot) return nullptr;
|
||||
@@ -1791,14 +1794,14 @@ namespace Clipper2Lib {
|
||||
edge_c = &e1;
|
||||
}
|
||||
|
||||
if (abs(edge_c->wind_cnt) != 1) return nullptr;
|
||||
if (abs(edge_c->wind_cnt) != 1) return nullptr;
|
||||
switch (cliptype_)
|
||||
{
|
||||
case ClipType::Union:
|
||||
if (!IsHotEdge(*edge_c)) return nullptr;
|
||||
case ClipType::Union:
|
||||
if (!IsHotEdge(*edge_c)) return nullptr;
|
||||
break;
|
||||
default:
|
||||
if (edge_c->local_min->polytype == PathType::Subject)
|
||||
default:
|
||||
if (edge_c->local_min->polytype == PathType::Subject)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -1821,11 +1824,11 @@ namespace Clipper2Lib {
|
||||
edge_o->outrec = nullptr;
|
||||
return resultOp;
|
||||
}
|
||||
|
||||
|
||||
//horizontal edges can pass under open paths at a LocMins
|
||||
else if (pt == edge_o->local_min->vertex->pt &&
|
||||
!IsOpenEnd(*edge_o->local_min->vertex))
|
||||
{
|
||||
{
|
||||
//find the other side of the LocMin and
|
||||
//if it's 'hot' join up with it ...
|
||||
Active* e3 = FindEdgeWithMatchingLocMin(edge_o);
|
||||
@@ -1833,7 +1836,7 @@ namespace Clipper2Lib {
|
||||
{
|
||||
edge_o->outrec = e3->outrec;
|
||||
if (edge_o->wind_dx > 0)
|
||||
SetSides(*e3->outrec, *edge_o, *e3);
|
||||
SetSides(*e3->outrec, *edge_o, *e3);
|
||||
else
|
||||
SetSides(*e3->outrec, *e3, *edge_o);
|
||||
return e3->outrec->pts;
|
||||
@@ -1847,7 +1850,7 @@ namespace Clipper2Lib {
|
||||
|
||||
|
||||
//MANAGING CLOSED PATHS FROM HERE ON
|
||||
|
||||
|
||||
//UPDATE WINDING COUNTS...
|
||||
|
||||
int old_e1_windcnt, old_e2_windcnt;
|
||||
@@ -1913,7 +1916,7 @@ namespace Clipper2Lib {
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
//NOW PROCESS THE INTERSECTION ...
|
||||
OutPt* resultOp = nullptr;
|
||||
//if both edges are 'hot' ...
|
||||
@@ -2282,7 +2285,7 @@ namespace Clipper2Lib {
|
||||
inline bool HorzIsSpike(const Active& horzEdge)
|
||||
{
|
||||
Point64 nextPt = NextVertex(horzEdge)->pt;
|
||||
return (nextPt.y == horzEdge.bot.y) &&
|
||||
return (nextPt.y == horzEdge.bot.y) &&
|
||||
(horzEdge.bot.x < horzEdge.top.x) != (horzEdge.top.x < nextPt.x);
|
||||
}
|
||||
|
||||
@@ -2295,7 +2298,7 @@ namespace Clipper2Lib {
|
||||
//always trim 180 deg. spikes (in closed paths)
|
||||
//but otherwise break if preserveCollinear = true
|
||||
if (preserveCollinear &&
|
||||
((pt.x < horzEdge.top.x) != (horzEdge.bot.x < horzEdge.top.x)))
|
||||
((pt.x < horzEdge.top.x) != (horzEdge.bot.x < horzEdge.top.x)))
|
||||
break;
|
||||
|
||||
horzEdge.vertex_top = NextVertex(horzEdge);
|
||||
@@ -2353,11 +2356,11 @@ namespace Clipper2Lib {
|
||||
|
||||
OutPt* op;
|
||||
while (true) // loop through consec. horizontal edges
|
||||
{
|
||||
{
|
||||
if (horzIsOpen && IsMaxima(horz) && !IsOpenEnd(horz))
|
||||
{
|
||||
vertex_max = GetCurrYMaximaVertex(horz);
|
||||
if (vertex_max)
|
||||
if (vertex_max)
|
||||
max_pair = GetHorzMaximaPair(horz, vertex_max);
|
||||
}
|
||||
|
||||
@@ -2388,7 +2391,7 @@ namespace Clipper2Lib {
|
||||
|
||||
//if horzEdge is a maxima, keep going until we reach
|
||||
//its maxima pair, otherwise check for break conditions
|
||||
if (vertex_max != horz.vertex_top || IsOpenEnd(horz))
|
||||
if (vertex_max != horz.vertex_top || IsOpenEnd(horz))
|
||||
{
|
||||
//otherwise stop when 'ae' is beyond the end of the horizontal line
|
||||
if ((is_left_to_right && e->curr_x > horz_right) ||
|
||||
@@ -2467,15 +2470,15 @@ namespace Clipper2Lib {
|
||||
{
|
||||
AddOutPt(horz, horz.top);
|
||||
if (IsFront(horz))
|
||||
horz.outrec->front_edge = nullptr;
|
||||
horz.outrec->front_edge = nullptr;
|
||||
else
|
||||
horz.outrec->back_edge = nullptr;
|
||||
horz.outrec = nullptr;
|
||||
}
|
||||
DeleteFromAEL(horz);
|
||||
DeleteFromAEL(horz);
|
||||
return;
|
||||
}
|
||||
else if (NextVertex(horz)->pt.y != horz.top.y)
|
||||
else if (NextVertex(horz)->pt.y != horz.top.y)
|
||||
break;
|
||||
|
||||
//still more horizontals in bound to process ...
|
||||
@@ -2486,7 +2489,7 @@ namespace Clipper2Lib {
|
||||
if (PreserveCollinear && !horzIsOpen && HorzIsSpike(horz))
|
||||
TrimHorz(horz, true);
|
||||
|
||||
is_left_to_right =
|
||||
is_left_to_right =
|
||||
ResetHorzDirection(horz, max_pair, horz_left, horz_right);
|
||||
}
|
||||
|
||||
@@ -2499,7 +2502,7 @@ namespace Clipper2Lib {
|
||||
else
|
||||
op = nullptr;
|
||||
|
||||
if ((horzIsOpen && !IsOpenEnd(horz)) ||
|
||||
if ((horzIsOpen && !IsOpenEnd(horz)) ||
|
||||
(!horzIsOpen && vertex_max != horz.vertex_top))
|
||||
{
|
||||
UpdateEdgeIntoAEL(&horz); // this is the end of an intermediate horiz.
|
||||
@@ -2516,7 +2519,7 @@ namespace Clipper2Lib {
|
||||
AddJoin(op2, op);
|
||||
}
|
||||
}
|
||||
else if (IsHotEdge(horz))
|
||||
else if (IsHotEdge(horz))
|
||||
AddLocalMaxPoly(horz, *max_pair, horz.top);
|
||||
else
|
||||
{
|
||||
@@ -2966,7 +2969,7 @@ namespace Clipper2Lib {
|
||||
OutRec* outrec = ProcessJoin(j);
|
||||
CleanCollinear(outrec);
|
||||
}
|
||||
else
|
||||
else
|
||||
delete j;
|
||||
}
|
||||
|
||||
@@ -3015,7 +3018,7 @@ namespace Clipper2Lib {
|
||||
bool CollinearSegsOverlap(const Point64& seg1a, const Point64& seg1b,
|
||||
const Point64& seg2a, const Point64& seg2b)
|
||||
{
|
||||
//precondition: seg1 and seg2 are collinear
|
||||
//precondition: seg1 and seg2 are collinear
|
||||
if (seg1a.x == seg1b.x)
|
||||
{
|
||||
if (seg2a.x != seg1a.x || seg2a.x != seg2b.x) return false;
|
||||
@@ -3146,7 +3149,7 @@ namespace Clipper2Lib {
|
||||
{
|
||||
or1->pts = op1;
|
||||
or2->pts = nullptr;
|
||||
if (or1->owner && (!or2->owner ||
|
||||
if (or1->owner && (!or2->owner ||
|
||||
or2->owner->idx < or1->owner->idx))
|
||||
or1->owner = or2->owner;
|
||||
or2->owner = or1;
|
||||
@@ -3156,7 +3159,7 @@ namespace Clipper2Lib {
|
||||
result = or2;
|
||||
or2->pts = op1;
|
||||
or1->pts = nullptr;
|
||||
if (or2->owner && (!or1->owner ||
|
||||
if (or2->owner && (!or1->owner ||
|
||||
or1->owner->idx < or2->owner->idx))
|
||||
or2->owner = or1->owner;
|
||||
or1->owner = or2;
|
||||
@@ -3207,7 +3210,7 @@ namespace Clipper2Lib {
|
||||
{
|
||||
or1->pts = op1;
|
||||
or2->pts = nullptr;
|
||||
if (or1->owner && (!or2->owner ||
|
||||
if (or1->owner && (!or2->owner ||
|
||||
or2->owner->idx < or1->owner->idx))
|
||||
or1->owner = or2->owner;
|
||||
or2->owner = or1;
|
||||
@@ -3217,9 +3220,9 @@ namespace Clipper2Lib {
|
||||
result = or2;
|
||||
or2->pts = op1;
|
||||
or1->pts = nullptr;
|
||||
if (or2->owner && (!or1->owner ||
|
||||
if (or2->owner && (!or1->owner ||
|
||||
or1->owner->idx < or2->owner->idx))
|
||||
or2->owner = or1->owner;
|
||||
or2->owner = or1->owner;
|
||||
or1->owner = or2;
|
||||
}
|
||||
}
|
||||
@@ -3310,11 +3313,11 @@ namespace Clipper2Lib {
|
||||
if (pt.y > result.bottom) result.bottom = pt.y;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
bool BuildPath64(OutPt* op, bool reverse, bool isOpen, Path64& path)
|
||||
{
|
||||
if (op->next == op || (!isOpen && op->next == op->prev))
|
||||
if (op->next == op || (!isOpen && op->next == op->prev))
|
||||
return false;
|
||||
|
||||
path.resize(0);
|
||||
@@ -3355,9 +3358,9 @@ namespace Clipper2Lib {
|
||||
if (owner->bounds.IsEmpty()) owner->bounds = GetBounds(owner->path);
|
||||
bool is_inside_owner_bounds = owner->bounds.Contains(outrec->bounds);
|
||||
|
||||
// while looking for the correct owner, check the owner's
|
||||
// splits **before** checking the owner itself because
|
||||
// splits can occur internally, and checking the owner
|
||||
// while looking for the correct owner, check the owner's
|
||||
// splits **before** checking the owner itself because
|
||||
// splits can occur internally, and checking the owner
|
||||
// first would miss the inner split's true ownership
|
||||
if (owner->splits)
|
||||
{
|
||||
@@ -3388,7 +3391,7 @@ namespace Clipper2Lib {
|
||||
{
|
||||
if (is_inside_owner_bounds && Path1InsidePath2(outrec, outrec->owner))
|
||||
return true;
|
||||
// otherwise keep trying with owner's owner
|
||||
// otherwise keep trying with owner's owner
|
||||
outrec->owner = outrec->owner->owner;
|
||||
if (!outrec->owner) return true; // true or false
|
||||
is_inside_owner_bounds = outrec->owner->bounds.Contains(outrec->bounds);
|
||||
|
||||
@@ -185,7 +185,7 @@ std::vector<SurfaceFill> group_fills(const Layer &layer)
|
||||
params.bridge = is_bridge || Fill::use_bridge_flow(params.pattern);
|
||||
params.flow = params.bridge ?
|
||||
//BBS: always enable thick bridge for internal bridge
|
||||
layerm.bridging_flow(extrusion_role, (surface.is_bridge() && !surface.is_external()) || object_config.thick_bridges, surface.is_external() ? region_config.bridge_density.get_abs_value(1.0) : 1.0f) :
|
||||
layerm.bridging_flow(extrusion_role, (surface.is_bridge() && !surface.is_external()) || object_config.thick_bridges) :
|
||||
layerm.flow(extrusion_role, (surface.thickness == -1) ? layer.height : surface.thickness);
|
||||
|
||||
// Calculate flow spacing for infill pattern generation.
|
||||
@@ -199,8 +199,13 @@ std::vector<SurfaceFill> group_fills(const Layer &layer)
|
||||
// so that internall infill will be aligned over all layers of the current region.
|
||||
params.spacing = layerm.region().flow(*layer.object(), frInfill, layer.object()->config().layer_height, false).spacing();
|
||||
// Anchor a sparse infill to inner perimeters with the following anchor length:
|
||||
params.anchor_length = float(Fill::infill_anchor * 0.01 * params.spacing);
|
||||
params.anchor_length_max = Fill::infill_anchor_max;
|
||||
// Anchor a sparse infill to inner perimeters with the following anchor length:
|
||||
params.anchor_length = float(region_config.infill_anchor);
|
||||
if (region_config.infill_anchor.percent)
|
||||
params.anchor_length = float(params.anchor_length * 0.01 * params.spacing);
|
||||
params.anchor_length_max = float(region_config.infill_anchor_max);
|
||||
if (region_config.infill_anchor_max.percent)
|
||||
params.anchor_length_max = float(params.anchor_length_max * 0.01 * params.spacing);
|
||||
params.anchor_length = std::min(params.anchor_length, params.anchor_length_max);
|
||||
}
|
||||
|
||||
@@ -494,6 +499,11 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
|
||||
// Spacing is modified by the filler to indicate adjustments. Reset it for each expolygon.
|
||||
f->spacing = surface_fill.params.spacing;
|
||||
surface_fill.surface.expolygon = std::move(expoly);
|
||||
|
||||
if(surface_fill.params.bridge && surface_fill.surface.is_external() && surface_fill.params.density > 99.0){
|
||||
params.density = layerm->region().config().bridge_density.get_abs_value(1.0);
|
||||
params.dont_adjust = true;
|
||||
}
|
||||
// BBS: make fill
|
||||
f->fill_surface_extrusion(&surface_fill.surface,
|
||||
params,
|
||||
|
||||
@@ -154,8 +154,8 @@ const std::string BBS_MODEL_CONFIG_FILE = "Metadata/model_settings.config";
|
||||
const std::string BBS_MODEL_CONFIG_RELS_FILE = "Metadata/_rels/model_settings.config.rels";
|
||||
const std::string SLICE_INFO_CONFIG_FILE = "Metadata/slice_info.config";
|
||||
const std::string BBS_LAYER_HEIGHTS_PROFILE_FILE = "Metadata/layer_heights_profile.txt";
|
||||
/*const std::string LAYER_CONFIG_RANGES_FILE = "Metadata/Prusa_Slicer_layer_config_ranges.xml";
|
||||
const std::string SLA_SUPPORT_POINTS_FILE = "Metadata/Slic3r_PE_sla_support_points.txt";
|
||||
const std::string LAYER_CONFIG_RANGES_FILE = "Metadata/layer_config_ranges.xml";
|
||||
/*const std::string SLA_SUPPORT_POINTS_FILE = "Metadata/Slic3r_PE_sla_support_points.txt";
|
||||
const std::string SLA_DRAIN_HOLES_FILE = "Metadata/Slic3r_PE_sla_drain_holes.txt";*/
|
||||
const std::string CUSTOM_GCODE_PER_PRINT_Z_FILE = "Metadata/custom_gcode_per_layer.xml";
|
||||
const std::string AUXILIARY_DIR = "Auxiliaries/";
|
||||
@@ -751,8 +751,8 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||
typedef std::map<int, CutObjectInfo> IdToCutObjectInfoMap;
|
||||
//typedef std::map<Id, Geometry> IdToGeometryMap;
|
||||
typedef std::map<int, std::vector<coordf_t>> IdToLayerHeightsProfileMap;
|
||||
/*typedef std::map<int, t_layer_config_ranges> IdToLayerConfigRangesMap;
|
||||
typedef std::map<int, std::vector<sla::SupportPoint>> IdToSlaSupportPointsMap;
|
||||
typedef std::map<int, t_layer_config_ranges> IdToLayerConfigRangesMap;
|
||||
/*typedef std::map<int, std::vector<sla::SupportPoint>> IdToSlaSupportPointsMap;
|
||||
typedef std::map<int, std::vector<sla::DrainHole>> IdToSlaDrainHolesMap;*/
|
||||
|
||||
struct ObjectImporter
|
||||
@@ -942,8 +942,8 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||
IdToMetadataMap m_objects_metadata;
|
||||
IdToCutObjectInfoMap m_cut_object_infos;
|
||||
IdToLayerHeightsProfileMap m_layer_heights_profiles;
|
||||
/*IdToLayerConfigRangesMap m_layer_config_ranges;
|
||||
IdToSlaSupportPointsMap m_sla_support_points;
|
||||
IdToLayerConfigRangesMap m_layer_config_ranges;
|
||||
/*IdToSlaSupportPointsMap m_sla_support_points;
|
||||
IdToSlaDrainHolesMap m_sla_drain_holes;*/
|
||||
std::string m_curr_metadata_name;
|
||||
std::string m_curr_characters;
|
||||
@@ -1199,7 +1199,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||
m_curr_config.volume_id = -1;
|
||||
m_objects_metadata.clear();
|
||||
m_layer_heights_profiles.clear();
|
||||
//m_layer_config_ranges.clear();
|
||||
m_layer_config_ranges.clear();
|
||||
//m_sla_support_points.clear();
|
||||
m_curr_metadata_name.clear();
|
||||
m_curr_characters.clear();
|
||||
@@ -1510,10 +1510,10 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||
_extract_layer_heights_profile_config_from_archive(archive, stat);
|
||||
}
|
||||
else
|
||||
/*if (boost::algorithm::iequals(name, LAYER_CONFIG_RANGES_FILE)) {
|
||||
if (boost::algorithm::iequals(name, LAYER_CONFIG_RANGES_FILE)) {
|
||||
// extract slic3r layer config ranges file
|
||||
_extract_layer_config_ranges_from_archive(archive, stat, config_substitutions);
|
||||
}*/
|
||||
}
|
||||
//BBS: disable SLA related files currently
|
||||
/*else if (boost::algorithm::iequals(name, SLA_SUPPORT_POINTS_FILE)) {
|
||||
// extract sla support points file
|
||||
@@ -1687,12 +1687,12 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||
model_object->layer_height_profile.set(std::move(obj_layer_heights_profile->second));
|
||||
|
||||
// m_layer_config_ranges are indexed by a 1 based model object index.
|
||||
/*IdToLayerConfigRangesMap::iterator obj_layer_config_ranges = m_layer_config_ranges.find(object.second + 1);
|
||||
IdToLayerConfigRangesMap::iterator obj_layer_config_ranges = m_layer_config_ranges.find(object.second + 1);
|
||||
if (obj_layer_config_ranges != m_layer_config_ranges.end())
|
||||
model_object->layer_config_ranges = std::move(obj_layer_config_ranges->second);
|
||||
|
||||
// m_sla_support_points are indexed by a 1 based model object index.
|
||||
IdToSlaSupportPointsMap::iterator obj_sla_support_points = m_sla_support_points.find(object.second + 1);
|
||||
/*IdToSlaSupportPointsMap::iterator obj_sla_support_points = m_sla_support_points.find(object.second + 1);
|
||||
if (obj_sla_support_points != m_sla_support_points.end() && !obj_sla_support_points->second.empty()) {
|
||||
model_object->sla_support_points = std::move(obj_sla_support_points->second);
|
||||
model_object->sla_points_status = sla::PointsStatus::UserModified;
|
||||
@@ -2437,7 +2437,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
|
||||
void _BBS_3MF_Importer::_extract_layer_config_ranges_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat, ConfigSubstitutionContext& config_substitutions)
|
||||
{
|
||||
if (stat.m_uncomp_size > 0) {
|
||||
@@ -2495,7 +2495,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
void _BBS_3MF_Importer::_extract_sla_support_points_from_archive(mz_zip_archive& archive, const mz_zip_archive_file_stat& stat)
|
||||
{
|
||||
if (stat.m_uncomp_size > 0) {
|
||||
@@ -5363,14 +5363,16 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||
proFn(EXPORT_STAGE_ADD_LAYER_RANGE, 0, 1, cb_cancel);
|
||||
if (cb_cancel)
|
||||
return false;
|
||||
}
|
||||
}*/
|
||||
|
||||
// Adds layer config ranges file ("Metadata/Slic3r_PE_layer_config_ranges.txt").
|
||||
// All layer height profiles of all ModelObjects are stored here, indexed by 1 based index of the ModelObject in Model.
|
||||
// The index differes from the index of an object ID of an object instance of a 3MF file!
|
||||
if (!_add_layer_config_ranges_file_to_archive(archive, model)) {
|
||||
close_zip_writer(&archive);
|
||||
boost::filesystem::remove(filename);
|
||||
return false;
|
||||
}*/
|
||||
}
|
||||
|
||||
// BBS progress point
|
||||
/*BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ":" <<__LINE__ << boost::format("export 3mf EXPORT_STAGE_ADD_SUPPORT\n");
|
||||
@@ -6417,7 +6419,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||
|
||||
return true;
|
||||
}
|
||||
/*
|
||||
|
||||
bool _BBS_3MF_Exporter::_add_layer_config_ranges_file_to_archive(mz_zip_archive& archive, Model& model)
|
||||
{
|
||||
std::string out = "";
|
||||
@@ -6477,6 +6479,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
bool _BBS_3MF_Exporter::_add_sla_support_points_file_to_archive(mz_zip_archive& archive, Model& model)
|
||||
{
|
||||
assert(is_decimal_separator_point());
|
||||
@@ -6810,7 +6813,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result)
|
||||
stream << " <" << PLATE_TAG << ">\n";
|
||||
//plate index
|
||||
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << PLATERID_ATTR << "\" " << VALUE_ATTR << "=\"" << plate_data->plate_index + 1 << "\"/>\n";
|
||||
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << PLATER_NAME_ATTR << "\" " << VALUE_ATTR << "=\"" << plate_data->plate_name << "\"/>\n";
|
||||
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << PLATER_NAME_ATTR << "\" " << VALUE_ATTR << "=\"" << xml_escape(plate_data->plate_name) << "\"/>\n";
|
||||
stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << LOCK_ATTR << "\" " << VALUE_ATTR << "=\"" << std::boolalpha<< plate_data->locked<< "\"/>\n";
|
||||
ConfigOption* bed_type_opt = plate_data->config.option("curr_bed_type");
|
||||
t_config_enum_names bed_type_names = ConfigOptionEnum<BedType>::get_enum_names();
|
||||
|
||||
+14
-26
@@ -1433,7 +1433,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
||||
// modifies m_silent_time_estimator_enabled
|
||||
DoExport::init_gcode_processor(print.config(), m_processor, m_silent_time_estimator_enabled);
|
||||
const bool is_bbl_printers = print.is_BBL_printer();
|
||||
|
||||
m_calib_config.clear();
|
||||
// resets analyzer's tracking data
|
||||
m_last_height = 0.f;
|
||||
m_last_layer_z = 0.f;
|
||||
@@ -1727,7 +1727,11 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
||||
//m_placeholder_parser.set("has_single_extruder_multi_material_priming", has_wipe_tower && print.config().single_extruder_multi_material_priming);
|
||||
m_placeholder_parser.set("total_toolchanges", std::max(0, print.wipe_tower_data().number_of_toolchanges)); // Check for negative toolchanges (single extruder mode) and set to 0 (no tool change).
|
||||
|
||||
std::vector<unsigned char> is_extruder_used(print.config().filament_diameter.size(), 0);
|
||||
// PlaceholderParser currently substitues non-existent vector values with the zero'th value, which is harmful in the
|
||||
// case of "is_extruder_used[]" as Slicer may lie about availability of such non-existent extruder. We rather
|
||||
// sacrifice 256B of memory before we change the behavior of the PlaceholderParser, which should really only fill in
|
||||
// the non-existent vector elements for filament parameters.
|
||||
std::vector<unsigned char> is_extruder_used(std::max(size_t(255), print.config().filament_diameter.size()), 0);
|
||||
for (unsigned int extruder : tool_ordering.all_extruders())
|
||||
is_extruder_used[extruder] = true;
|
||||
m_placeholder_parser.set("is_extruder_used", new ConfigOptionBools(is_extruder_used));
|
||||
@@ -1775,6 +1779,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
||||
m_placeholder_parser.set("max_print_height",new ConfigOptionInt(m_config.printable_height));
|
||||
m_placeholder_parser.set("z_offset", new ConfigOptionFloat(0.0f));
|
||||
m_placeholder_parser.set("plate_name", new ConfigOptionString(print.get_plate_name()));
|
||||
m_placeholder_parser.set("first_layer_height", new ConfigOptionFloat(m_config.initial_layer_print_height.value));
|
||||
|
||||
//BBS: calculate the volumetric speed of outer wall. Ignore pre-object setting and multi-filament, and just use the default setting
|
||||
{
|
||||
@@ -3640,14 +3645,6 @@ std::string GCode::extrude_loop(ExtrusionLoop loop, std::string description, dou
|
||||
gcode += m_writer.extrude_to_xy(this->point_to_gcode(pt), 0,"move inwards before travel",true);
|
||||
}
|
||||
|
||||
//BBS: don't reset acceleration when printing first layer. During first layer, acceleration is always same value.
|
||||
if (!this->on_first_layer()) {
|
||||
// reset acceleration
|
||||
if (m_config.default_acceleration.value > 0)
|
||||
gcode += m_writer.set_acceleration((unsigned int)(m_config.default_acceleration.value + 0.5));
|
||||
if (m_config.default_jerk.value > 0)
|
||||
gcode += m_writer.set_jerk_xy(m_config.default_jerk.value);
|
||||
}
|
||||
return gcode;
|
||||
}
|
||||
|
||||
@@ -3671,14 +3668,7 @@ std::string GCode::extrude_multi_path(ExtrusionMultiPath multipath, std::string
|
||||
}
|
||||
m_wipe.path.reverse();
|
||||
}
|
||||
//BBS: don't reset acceleration when printing first layer. During first layer, acceleration is always same value.
|
||||
if (!this->on_first_layer()) {
|
||||
// reset acceleration
|
||||
if (m_config.default_acceleration.value > 0)
|
||||
gcode += m_writer.set_acceleration((unsigned int)floor(m_config.default_acceleration.value + 0.5));
|
||||
if(m_config.default_jerk.value > 0)
|
||||
gcode += m_writer.set_jerk_xy(m_config.default_jerk.value);
|
||||
}
|
||||
|
||||
return gcode;
|
||||
}
|
||||
|
||||
@@ -3703,15 +3693,7 @@ std::string GCode::extrude_path(ExtrusionPath path, std::string description, dou
|
||||
m_wipe.path = std::move(path.polyline);
|
||||
m_wipe.path.reverse();
|
||||
}
|
||||
//BBS: don't reset acceleration when printing first layer. During first layer, acceleration is always same value.
|
||||
if (!this->on_first_layer()){
|
||||
// reset acceleration
|
||||
if (m_config.default_acceleration.value > 0)
|
||||
gcode += m_writer.set_acceleration((unsigned int)floor(m_config.default_acceleration.value + 0.5));
|
||||
if(m_config.default_jerk.value > 0)
|
||||
gcode += m_writer.set_jerk_xy(m_config.default_jerk.value);
|
||||
|
||||
}
|
||||
return gcode;
|
||||
}
|
||||
|
||||
@@ -4020,6 +4002,12 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
|
||||
}
|
||||
}
|
||||
}
|
||||
// Override skirt speed if set
|
||||
if (path.role() == erSkirt) {
|
||||
const double skirt_speed = m_config.get_abs_value("skirt_speed");
|
||||
if (skirt_speed > 0.0)
|
||||
speed = skirt_speed;
|
||||
}
|
||||
//BBS: remove this config
|
||||
//else if (this->object_layer_over_raft())
|
||||
// speed = m_config.get_abs_value("first_layer_speed_over_raft", speed);
|
||||
|
||||
+1363
-1155
File diff suppressed because it is too large
Load Diff
@@ -27,138 +27,136 @@ class Grid;
|
||||
|
||||
namespace SeamPlacerImpl {
|
||||
|
||||
// ************ FOR BACKPORT COMPATIBILITY ONLY ***************
|
||||
// Angle from v1 to v2, returning double atan2(y, x) normalized to <-PI, PI>.
|
||||
template<typename Derived, typename Derived2> inline double angle(const Eigen::MatrixBase<Derived> &v1, const Eigen::MatrixBase<Derived2> &v2)
|
||||
{
|
||||
static_assert(Derived::IsVectorAtCompileTime && int(Derived::SizeAtCompileTime) == 2, "angle(): first parameter is not a 2D vector");
|
||||
static_assert(Derived2::IsVectorAtCompileTime && int(Derived2::SizeAtCompileTime) == 2, "angle(): second parameter is not a 2D vector");
|
||||
auto v1d = v1.template cast<double>();
|
||||
auto v2d = v2.template cast<double>();
|
||||
return atan2(cross2(v1d, v2d), v1d.dot(v2d));
|
||||
}
|
||||
// ***************************
|
||||
|
||||
struct GlobalModelInfo;
|
||||
struct SeamComparator;
|
||||
|
||||
enum class EnforcedBlockedSeamPoint {
|
||||
Blocked = 0,
|
||||
Neutral = 1,
|
||||
Enforced = 2,
|
||||
Blocked = 0,
|
||||
Neutral = 1,
|
||||
Enforced = 2,
|
||||
};
|
||||
|
||||
// struct representing single perimeter loop
|
||||
struct Perimeter
|
||||
{
|
||||
size_t start_index{};
|
||||
size_t end_index{}; // inclusive!
|
||||
size_t seam_index{};
|
||||
float flow_width{};
|
||||
struct Perimeter {
|
||||
size_t start_index{};
|
||||
size_t end_index{}; //inclusive!
|
||||
size_t seam_index{};
|
||||
float flow_width{};
|
||||
|
||||
// During alignment, a final position may be stored here. In that case, finalized is set to true.
|
||||
// Note that final seam position is not limited to points of the perimeter loop. In theory it can be any position
|
||||
// Random position also uses this flexibility to set final seam point position
|
||||
bool finalized = false;
|
||||
Vec3f final_seam_position = Vec3f::Zero();
|
||||
// During alignment, a final position may be stored here. In that case, finalized is set to true.
|
||||
// Note that final seam position is not limited to points of the perimeter loop. In theory it can be any position
|
||||
// Random position also uses this flexibility to set final seam point position
|
||||
bool finalized = false;
|
||||
Vec3f final_seam_position = Vec3f::Zero();
|
||||
};
|
||||
|
||||
// Struct over which all processing of perimeters is done. For each perimeter point, its respective candidate is created,
|
||||
//Struct over which all processing of perimeters is done. For each perimeter point, its respective candidate is created,
|
||||
// then all the needed attributes are computed and finally, for each perimeter one point is chosen as seam.
|
||||
// This seam position can be then further aligned
|
||||
struct SeamCandidate
|
||||
{
|
||||
SeamCandidate(const Vec3f &pos, Perimeter &perimeter, float local_ccw_angle, EnforcedBlockedSeamPoint type)
|
||||
: position(pos), perimeter(perimeter), visibility(0.0f), overhang(0.0f), embedded_distance(0.0f), local_ccw_angle(local_ccw_angle), type(type), central_enforcer(false)
|
||||
{}
|
||||
const Vec3f position;
|
||||
// pointer to Perimeter loop of this point. It is shared across all points of the loop
|
||||
Perimeter &perimeter;
|
||||
float visibility;
|
||||
float overhang;
|
||||
// distance inside the merged layer regions, for detecting perimeter points which are hidden indside the print (e.g. multimaterial join)
|
||||
// Negative sign means inside the print, comes from EdgeGrid structure
|
||||
float embedded_distance;
|
||||
float local_ccw_angle;
|
||||
EnforcedBlockedSeamPoint type;
|
||||
bool central_enforcer; // marks this candidate as central point of enforced segment on the perimeter - important for alignment
|
||||
struct SeamCandidate {
|
||||
SeamCandidate(const Vec3f &pos, Perimeter &perimeter,
|
||||
float local_ccw_angle,
|
||||
EnforcedBlockedSeamPoint type) :
|
||||
position(pos), perimeter(perimeter), visibility(0.0f), overhang(0.0f), embedded_distance(0.0f), local_ccw_angle(
|
||||
local_ccw_angle), type(type), central_enforcer(false) {
|
||||
}
|
||||
const Vec3f position;
|
||||
// pointer to Perimeter loop of this point. It is shared across all points of the loop
|
||||
Perimeter &perimeter;
|
||||
float visibility;
|
||||
float overhang;
|
||||
// distance inside the merged layer regions, for detecting perimeter points which are hidden indside the print (e.g. multimaterial join)
|
||||
// Negative sign means inside the print, comes from EdgeGrid structure
|
||||
float embedded_distance;
|
||||
float local_ccw_angle;
|
||||
EnforcedBlockedSeamPoint type;
|
||||
bool central_enforcer; //marks this candidate as central point of enforced segment on the perimeter - important for alignment
|
||||
};
|
||||
|
||||
struct SeamCandidateCoordinateFunctor
|
||||
{
|
||||
SeamCandidateCoordinateFunctor(const std::vector<SeamCandidate> &seam_candidates) : seam_candidates(seam_candidates) {}
|
||||
const std::vector<SeamCandidate> &seam_candidates;
|
||||
float operator()(size_t index, size_t dim) const { return seam_candidates[index].position[dim]; }
|
||||
struct SeamCandidateCoordinateFunctor {
|
||||
SeamCandidateCoordinateFunctor(const std::vector<SeamCandidate> &seam_candidates) :
|
||||
seam_candidates(seam_candidates) {
|
||||
}
|
||||
const std::vector<SeamCandidate> &seam_candidates;
|
||||
float operator()(size_t index, size_t dim) const {
|
||||
return seam_candidates[index].position[dim];
|
||||
}
|
||||
};
|
||||
} // namespace SeamPlacerImpl
|
||||
|
||||
struct PrintObjectSeamData
|
||||
{
|
||||
using SeamCandidatesTree = KDTreeIndirect<3, float, SeamPlacerImpl::SeamCandidateCoordinateFunctor>;
|
||||
using SeamCandidatesTree = KDTreeIndirect<3, float, SeamPlacerImpl::SeamCandidateCoordinateFunctor>;
|
||||
|
||||
struct LayerSeams
|
||||
{
|
||||
Slic3r::deque<SeamPlacerImpl::Perimeter> perimeters;
|
||||
std::vector<SeamPlacerImpl::SeamCandidate> points;
|
||||
std::unique_ptr<SeamCandidatesTree> points_tree;
|
||||
};
|
||||
// Map of PrintObjects (PO) -> vector of layers of PO -> vector of perimeter
|
||||
std::vector<LayerSeams> layers;
|
||||
// Map of PrintObjects (PO) -> vector of layers of PO -> unique_ptr to KD
|
||||
// tree of all points of the given layer
|
||||
struct LayerSeams
|
||||
{
|
||||
Slic3r::deque<SeamPlacerImpl::Perimeter> perimeters;
|
||||
std::vector<SeamPlacerImpl::SeamCandidate> points;
|
||||
std::unique_ptr<SeamCandidatesTree> points_tree;
|
||||
};
|
||||
// Map of PrintObjects (PO) -> vector of layers of PO -> vector of perimeter
|
||||
std::vector<LayerSeams> layers;
|
||||
// Map of PrintObjects (PO) -> vector of layers of PO -> unique_ptr to KD
|
||||
// tree of all points of the given layer
|
||||
|
||||
void clear() { layers.clear(); }
|
||||
void clear()
|
||||
{
|
||||
layers.clear();
|
||||
}
|
||||
};
|
||||
|
||||
class SeamPlacer
|
||||
{
|
||||
class SeamPlacer {
|
||||
public:
|
||||
// Number of samples generated on the mesh. There are sqr_rays_per_sample_point*sqr_rays_per_sample_point rays casted from each samples
|
||||
static constexpr size_t raycasting_visibility_samples_count = 30000;
|
||||
// square of number of rays per sample point
|
||||
static constexpr size_t sqr_rays_per_sample_point = 5;
|
||||
// Number of samples generated on the mesh. There are sqr_rays_per_sample_point*sqr_rays_per_sample_point rays casted from each samples
|
||||
static constexpr size_t raycasting_visibility_samples_count = 30000;
|
||||
static constexpr size_t fast_decimation_triangle_count_target = 16000;
|
||||
//square of number of rays per sample point
|
||||
static constexpr size_t sqr_rays_per_sample_point = 5;
|
||||
|
||||
// snapping angle - angles larger than this value will be snapped to during seam painting
|
||||
static constexpr float sharp_angle_snapping_threshold = 55.0f * float(PI) / 180.0f;
|
||||
// overhang angle for seam placement that still yields good results, in degrees, measured from vertical direction
|
||||
//BBS
|
||||
static constexpr float overhang_angle_threshold = 45.0f * float(PI) / 180.0f;
|
||||
// snapping angle - angles larger than this value will be snapped to during seam painting
|
||||
static constexpr float sharp_angle_snapping_threshold = 55.0f * float(PI) / 180.0f;
|
||||
// overhang angle for seam placement that still yields good results, in degrees, measured from vertical direction
|
||||
static constexpr float overhang_angle_threshold = 50.0f * float(PI) / 180.0f;
|
||||
|
||||
// determines angle importance compared to visibility ( neutral value is 1.0f. )
|
||||
static constexpr float angle_importance_aligned = 0.6f;
|
||||
static constexpr float angle_importance_nearest = 1.0f; // use much higher angle importance for nearest mode, to combat the visibility info noise
|
||||
// determines angle importance compared to visibility ( neutral value is 1.0f. )
|
||||
static constexpr float angle_importance_aligned = 0.6f;
|
||||
static constexpr float angle_importance_nearest = 1.0f; // use much higher angle importance for nearest mode, to combat the visibility info noise
|
||||
|
||||
// For long polygon sides, if they are close to the custom seam drawings, they are oversampled with this step size
|
||||
static constexpr float enforcer_oversampling_distance = 0.2f;
|
||||
// For long polygon sides, if they are close to the custom seam drawings, they are oversampled with this step size
|
||||
static constexpr float enforcer_oversampling_distance = 0.2f;
|
||||
|
||||
// When searching for seam clusters for alignment:
|
||||
// following value describes, how much worse score can point have and still be picked into seam cluster instead of original seam point on the same layer
|
||||
static constexpr float seam_align_score_tolerance = 0.3f;
|
||||
// seam_align_tolerable_dist_factor - how far to search for seam from current position, final dist is seam_align_tolerable_dist_factor * flow_width
|
||||
static constexpr float seam_align_tolerable_dist_factor = 4.0f;
|
||||
// minimum number of seams needed in cluster to make alignment happen
|
||||
static constexpr size_t seam_align_minimum_string_seams = 6;
|
||||
// millimeters covered by spline; determines number of splines for the given string
|
||||
static constexpr size_t seam_align_mm_per_segment = 4.0f;
|
||||
// When searching for seam clusters for alignment:
|
||||
// following value describes, how much worse score can point have and still be picked into seam cluster instead of original seam point on the same layer
|
||||
static constexpr float seam_align_score_tolerance = 0.3f;
|
||||
// seam_align_tolerable_dist_factor - how far to search for seam from current position, final dist is seam_align_tolerable_dist_factor * flow_width
|
||||
static constexpr float seam_align_tolerable_dist_factor = 4.0f;
|
||||
// minimum number of seams needed in cluster to make alignment happen
|
||||
static constexpr size_t seam_align_minimum_string_seams = 6;
|
||||
// millimeters covered by spline; determines number of splines for the given string
|
||||
static constexpr size_t seam_align_mm_per_segment = 4.0f;
|
||||
|
||||
// The following data structures hold all perimeter points for all PrintObject.
|
||||
std::unordered_map<const PrintObject *, PrintObjectSeamData> m_seam_per_object;
|
||||
//The following data structures hold all perimeter points for all PrintObject.
|
||||
std::unordered_map<const PrintObject*, PrintObjectSeamData> m_seam_per_object;
|
||||
|
||||
void init(const Print &print, std::function<void(void)> throw_if_canceled_func);
|
||||
void init(const Print &print, std::function<void(void)> throw_if_canceled_func);
|
||||
|
||||
void place_seam(const Layer *layer, ExtrusionLoop &loop, bool external_first, const Point &last_pos) const;
|
||||
void place_seam(const Layer *layer, ExtrusionLoop &loop, bool external_first, const Point &last_pos) const;
|
||||
|
||||
private:
|
||||
void gather_seam_candidates(const PrintObject *po, const SeamPlacerImpl::GlobalModelInfo &global_model_info, const SeamPosition configured_seam_preference);
|
||||
void calculate_candidates_visibility(const PrintObject *po, const SeamPlacerImpl::GlobalModelInfo &global_model_info);
|
||||
void calculate_overhangs_and_layer_embedding(const PrintObject *po);
|
||||
void align_seam_points(const PrintObject *po, const SeamPlacerImpl::SeamComparator &comparator);
|
||||
std::vector<std::pair<size_t, size_t>> find_seam_string(const PrintObject *po, std::pair<size_t, size_t> start_seam, const SeamPlacerImpl::SeamComparator &comparator) const;
|
||||
std::optional<std::pair<size_t, size_t>> find_next_seam_in_layer(const std::vector<PrintObjectSeamData::LayerSeams> &layers,
|
||||
const Vec3f & projected_position,
|
||||
const size_t layer_idx,
|
||||
const float max_distance,
|
||||
const SeamPlacerImpl::SeamComparator & comparator) const;
|
||||
void gather_seam_candidates(const PrintObject *po, const SeamPlacerImpl::GlobalModelInfo &global_model_info);
|
||||
void calculate_candidates_visibility(const PrintObject *po,
|
||||
const SeamPlacerImpl::GlobalModelInfo &global_model_info);
|
||||
void calculate_overhangs_and_layer_embedding(const PrintObject *po);
|
||||
void align_seam_points(const PrintObject *po, const SeamPlacerImpl::SeamComparator &comparator);
|
||||
std::vector<std::pair<size_t, size_t>> find_seam_string(const PrintObject *po,
|
||||
std::pair<size_t, size_t> start_seam,
|
||||
const SeamPlacerImpl::SeamComparator &comparator) const;
|
||||
std::optional<std::pair<size_t, size_t>> find_next_seam_in_layer(
|
||||
const std::vector<PrintObjectSeamData::LayerSeams> &layers,
|
||||
const Vec3f& projected_position,
|
||||
const size_t layer_idx, const float max_distance,
|
||||
const SeamPlacerImpl::SeamComparator &comparator) const;
|
||||
};
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
@@ -177,14 +177,13 @@ std::string GCodeWriter::set_acceleration(unsigned int acceleration)
|
||||
// Use M204 P, we don't want to override travel acc by M204 S (which is deprecated anyway).
|
||||
gcode << "M204 P" << acceleration;
|
||||
} else if (FLAVOR_IS(gcfKlipper) && this->config.accel_to_decel_enable) {
|
||||
gcode << "SET_VELOCITY_LIMIT ACCEL_TO_DECEL=" << acceleration * this->config.accel_to_decel_factor / 100;
|
||||
gcode << "SET_VELOCITY_LIMIT ACCEL=" << acceleration
|
||||
<< " ACCEL_TO_DECEL=" << acceleration * this->config.accel_to_decel_factor / 100;
|
||||
if (GCodeWriter::full_gcode_comment)
|
||||
gcode << " ; adjust ACCEL_TO_DECEL";
|
||||
gcode << "\nM204 S" << acceleration;
|
||||
// Set max accel to decel to half of acceleration
|
||||
} else
|
||||
gcode << "M204 S" << acceleration;
|
||||
|
||||
|
||||
//BBS
|
||||
if (GCodeWriter::full_gcode_comment) gcode << " ; adjust acceleration";
|
||||
gcode << "\n";
|
||||
|
||||
@@ -72,7 +72,7 @@ public:
|
||||
|
||||
Flow flow(FlowRole role) const;
|
||||
Flow flow(FlowRole role, double layer_height) const;
|
||||
Flow bridging_flow(FlowRole role, bool thick_bridge = false , float bridge_density = 1.0f) const;
|
||||
Flow bridging_flow(FlowRole role, bool thick_bridge = false) const;
|
||||
|
||||
void slices_to_fill_surfaces_clipped();
|
||||
void prepare_fill_surfaces();
|
||||
|
||||
@@ -26,7 +26,7 @@ Flow LayerRegion::flow(FlowRole role, double layer_height) const
|
||||
return m_region->flow(*m_layer->object(), role, layer_height, m_layer->id() == 0);
|
||||
}
|
||||
|
||||
Flow LayerRegion::bridging_flow(FlowRole role, bool thick_bridge, float bridge_density) const
|
||||
Flow LayerRegion::bridging_flow(FlowRole role, bool thick_bridge) const
|
||||
{
|
||||
const PrintRegion ®ion = this->region();
|
||||
const PrintRegionConfig ®ion_config = region.config();
|
||||
@@ -43,8 +43,6 @@ Flow LayerRegion::bridging_flow(FlowRole role, bool thick_bridge, float bridge_d
|
||||
// The same way as other slicers: Use normal extrusions. Apply bridge_flow while maintaining the original spacing.
|
||||
bridge_flow = this->flow(role).with_flow_ratio(region_config.bridge_flow);
|
||||
}
|
||||
bridge_density = boost::algorithm::clamp(bridge_density, 0.1f, 1.0f);
|
||||
bridge_flow.set_spacing(bridge_flow.spacing() + bridge_flow.width() * ((1.0f / bridge_density) - 1.0f));
|
||||
return bridge_flow;
|
||||
|
||||
}
|
||||
@@ -245,7 +243,7 @@ void LayerRegion::process_external_surfaces(const Layer *lower_layer, const Poly
|
||||
// Grown by 3mm.
|
||||
//BBS: eliminate too narrow area to avoid generating bridge on top layer when wall loop is 1
|
||||
//Polygons polys = offset(bridges[i].expolygon, bridge_margin, EXTERNAL_SURFACES_OFFSET_PARAMETERS);
|
||||
Polygons polys = offset2({ bridges[i].expolygon }, -scale_(nozzle_diameter * 0.1), bridge_margin + scale_((1.0 / this->region().config().bridge_density.get_abs_value(1.0) - 1.0)*nozzle_diameter/2.0), EXTERNAL_SURFACES_OFFSET_PARAMETERS);
|
||||
Polygons polys = offset2({ bridges[i].expolygon }, -scale_(nozzle_diameter * 0.1), bridge_margin, EXTERNAL_SURFACES_OFFSET_PARAMETERS);
|
||||
if (idx_island == -1) {
|
||||
BOOST_LOG_TRIVIAL(trace) << "Bridge did not fall into the source region!";
|
||||
} else {
|
||||
|
||||
@@ -1856,7 +1856,7 @@ void ModelObject::process_connector_cut(
|
||||
|
||||
// Perform cut
|
||||
TriangleMesh upper_mesh, lower_mesh;
|
||||
process_volume_cut(volume, instance_matrix, cut_matrix, attributes, upper_mesh, lower_mesh);
|
||||
process_volume_cut(volume, Transform3d::Identity(), cut_matrix, attributes, upper_mesh, lower_mesh);
|
||||
|
||||
// add small Z offset to better preview
|
||||
upper_mesh.translate((-0.05 * Vec3d::UnitZ()).cast<float>());
|
||||
|
||||
@@ -1374,7 +1374,8 @@ void PerimeterGenerator::process_arachne()
|
||||
|
||||
bool is_outer_wall_first =
|
||||
this->config->wall_infill_order == WallInfillOrder::OuterInnerInfill ||
|
||||
this->config->wall_infill_order == WallInfillOrder::InfillOuterInner;
|
||||
this->config->wall_infill_order == WallInfillOrder::InfillOuterInner ||
|
||||
this->config->wall_infill_order == WallInfillOrder::InnerOuterInnerInfill;
|
||||
if (is_outer_wall_first) {
|
||||
start_perimeter = 0;
|
||||
end_perimeter = int(perimeters.size());
|
||||
@@ -1501,17 +1502,49 @@ void PerimeterGenerator::process_arachne()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (this->config->wall_infill_order == WallInfillOrder::InnerOuterInnerInfill)
|
||||
if (ordered_extrusions.size() > 1) {
|
||||
int last_outer = 0;
|
||||
int outer = 0;
|
||||
for (; outer < ordered_extrusions.size(); ++outer)
|
||||
if (ordered_extrusions[outer].extrusion->inset_idx == 0 && outer - last_outer > 1) {
|
||||
std::swap(ordered_extrusions[outer], ordered_extrusions[outer - 1]);
|
||||
last_outer = outer;
|
||||
|
||||
if (this->config->wall_infill_order == WallInfillOrder::InnerOuterInnerInfill) {
|
||||
if (ordered_extrusions.size() > 2) { // 3 walls minimum needed to do inner outer inner ordering
|
||||
int position = 0; // index to run the re-ordering for multiple external perimeters in a single island.
|
||||
int arr_i = 0; // index to run through the walls
|
||||
int outer, first_internal, second_internal; // allocate index values
|
||||
// run the re-ordering for all wall loops in the same island
|
||||
while (position < ordered_extrusions.size()) {
|
||||
outer = first_internal = second_internal = -1; // initialise all index values to -1
|
||||
// run through the walls to get the index values that need re-ordering until the first one for each
|
||||
// is found. Start at "position" index to enable the for loop to iterate for multiple external
|
||||
// perimeters in a single island
|
||||
for (arr_i = position; arr_i < ordered_extrusions.size(); ++arr_i) {
|
||||
switch (ordered_extrusions[arr_i].extrusion->inset_idx) {
|
||||
case 0: // external perimeter
|
||||
if (outer == -1)
|
||||
outer = arr_i;
|
||||
break;
|
||||
case 1: // first internal wall
|
||||
if (first_internal == -1 && arr_i > outer)
|
||||
first_internal = arr_i;
|
||||
break;
|
||||
case 2: // second internal wall
|
||||
if (ordered_extrusions[arr_i].extrusion->inset_idx == 2 && second_internal == -1 &&
|
||||
arr_i > first_internal)
|
||||
second_internal = arr_i;
|
||||
break;
|
||||
}
|
||||
if (second_internal != -1)
|
||||
break; // found all three perimeters to re-order
|
||||
}
|
||||
if (outer > -1 && first_internal > -1 && second_internal > -1) { // found perimeters to re-order?
|
||||
const auto temp = ordered_extrusions[second_internal];
|
||||
ordered_extrusions[second_internal] = ordered_extrusions[first_internal];
|
||||
ordered_extrusions[first_internal] = ordered_extrusions[outer];
|
||||
ordered_extrusions[outer] = temp;
|
||||
} else
|
||||
break; // did not find any more candidates to re-order, so stop the while loop early
|
||||
// go to the next perimeter to continue scanning for external walls in the same island
|
||||
position = arr_i + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (ExtrusionEntityCollection extrusion_coll = traverse_extrusions(*this, ordered_extrusions); !extrusion_coll.empty())
|
||||
|
||||
@@ -708,7 +708,7 @@ static std::vector<std::string> s_Preset_print_options {
|
||||
"layer_height", "initial_layer_print_height", "wall_loops", "slice_closing_radius", "spiral_mode", "slicing_mode",
|
||||
"top_shell_layers", "top_shell_thickness", "bottom_shell_layers", "bottom_shell_thickness",
|
||||
"ensure_vertical_shell_thickness", "reduce_crossing_wall", "detect_thin_wall", "detect_overhang_wall",
|
||||
"seam_position", "wall_infill_order", "sparse_infill_density", "sparse_infill_pattern", "top_surface_pattern", "bottom_surface_pattern",
|
||||
"seam_position", "staggered_inner_seams", "wall_infill_order", "sparse_infill_density", "sparse_infill_pattern", "top_surface_pattern", "bottom_surface_pattern",
|
||||
"infill_direction",
|
||||
"minimum_sparse_infill_area", "reduce_infill_retraction",
|
||||
"ironing_type", "ironing_flow", "ironing_speed", "ironing_spacing",
|
||||
@@ -720,7 +720,7 @@ static std::vector<std::string> s_Preset_print_options {
|
||||
"inner_wall_speed", "outer_wall_speed", "sparse_infill_speed", "internal_solid_infill_speed",
|
||||
"top_surface_speed", "support_speed", "support_object_xy_distance", "support_interface_speed",
|
||||
"bridge_speed", "gap_infill_speed", "travel_speed", "travel_speed_z", "initial_layer_speed",
|
||||
"outer_wall_acceleration", "initial_layer_acceleration", "top_surface_acceleration", "default_acceleration", "skirt_loops", "skirt_distance", "skirt_height", "draft_shield",
|
||||
"outer_wall_acceleration", "initial_layer_acceleration", "top_surface_acceleration", "default_acceleration", "skirt_loops", "skirt_speed", "skirt_distance", "skirt_height", "draft_shield",
|
||||
"brim_width", "brim_object_gap", "brim_type", "enable_support", "support_type", "support_threshold_angle", "enforce_support_layers",
|
||||
"raft_layers", "raft_first_layer_density", "raft_first_layer_expansion", "raft_contact_distance", "raft_expansion",
|
||||
"support_base_pattern", "support_base_pattern_spacing", "support_expansion", "support_style",
|
||||
@@ -756,7 +756,7 @@ static std::vector<std::string> s_Preset_print_options {
|
||||
"bridge_density", "precise_outer_wall", "overhang_speed_classic", "bridge_acceleration",
|
||||
"sparse_infill_acceleration", "internal_solid_infill_acceleration", "tree_support_adaptive_layer_height", "tree_support_auto_brim",
|
||||
"tree_support_brim_width", "gcode_comments", "gcode_label_objects",
|
||||
"initial_layer_travel_speed", "exclude_object", "slow_down_layers"
|
||||
"initial_layer_travel_speed", "exclude_object", "slow_down_layers", "infill_anchor", "infill_anchor_max"
|
||||
|
||||
};
|
||||
|
||||
|
||||
+26
-4
@@ -185,6 +185,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|
||||
// These steps have no influence on the G-code whatsoever. Just ignore them.
|
||||
} else if (
|
||||
opt_key == "skirt_loops"
|
||||
|| opt_key == "skirt_speed"
|
||||
|| opt_key == "skirt_height"
|
||||
|| opt_key == "draft_shield"
|
||||
|| opt_key == "skirt_distance"
|
||||
@@ -197,6 +198,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|
||||
opt_key == "initial_layer_print_height"
|
||||
|| opt_key == "nozzle_diameter"
|
||||
|| opt_key == "filament_shrink"
|
||||
|| opt_key == "resolution"
|
||||
// Spiral Vase forces different kind of slicing than the normal model:
|
||||
// In Spiral Vase mode, holes are closed and only the largest area contour is kept at each layer.
|
||||
// Therefore toggling the Spiral Vase on / off requires complete reslicing.
|
||||
@@ -248,7 +250,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|
||||
opt_key == "initial_layer_line_width"
|
||||
|| opt_key == "min_layer_height"
|
||||
|| opt_key == "max_layer_height"
|
||||
|| opt_key == "resolution"
|
||||
//|| opt_key == "resolution"
|
||||
//BBS: when enable arc fitting, we must re-generate perimeter
|
||||
|| opt_key == "enable_arc_fitting"
|
||||
|| opt_key == "wall_infill_order") {
|
||||
@@ -912,9 +914,29 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons*
|
||||
return { L("No extrusions under current settings.") };
|
||||
|
||||
if (extruders.size() > 1 && m_config.print_sequence != PrintSequence::ByObject) {
|
||||
auto ret = check_multi_filament_valid(*this);
|
||||
if (!ret.string.empty())
|
||||
return ret;
|
||||
if (m_config.single_extruder_multi_material) {
|
||||
auto ret = check_multi_filament_valid(*this);
|
||||
if (!ret.string.empty())
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (warning) {
|
||||
for (unsigned int extruder_a: extruders) {
|
||||
const ConfigOptionInts* bed_temp_opt = m_config.option<ConfigOptionInts>(get_bed_temp_key(m_config.curr_bed_type));
|
||||
const ConfigOptionInts* bed_temp_1st_opt = m_config.option<ConfigOptionInts>(get_bed_temp_1st_layer_key(m_config.curr_bed_type));
|
||||
int bed_temp_a = bed_temp_opt->get_at(extruder_a);
|
||||
int bed_temp_1st_a = bed_temp_1st_opt->get_at(extruder_a);
|
||||
for (unsigned int extruder_b: extruders) {
|
||||
int bed_temp_b = bed_temp_opt->get_at(extruder_b);
|
||||
int bed_temp_1st_b = bed_temp_1st_opt->get_at(extruder_b);
|
||||
if (std::abs(bed_temp_a - bed_temp_b) > 15 || std::abs(bed_temp_1st_a - bed_temp_1st_b) > 15) {
|
||||
warning->string = L("Bed temperatures for the used filaments differ significantly.");
|
||||
goto DONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
DONE:;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_config.print_sequence == PrintSequence::ByObject) {
|
||||
|
||||
@@ -1008,7 +1008,7 @@ void PrintConfigDef::init_fff_params()
|
||||
def = this->add("internal_bridge_support_thickness", coFloat);
|
||||
def->label = L("Internal bridge support thickness");
|
||||
def->category = L("Strength");
|
||||
def->tooltip = L("If enabled, Studio will generate support loops under the contours of internal bridges."
|
||||
def->tooltip = L("If enabled, support loops will be generated under the contours of internal bridges."
|
||||
"These support loops could prevent internal bridges from extruding over the air and improve the top surface quality, especially when the sparse infill density is low."
|
||||
"This value determines the thickness of the support loops. 0 means disable this feature");
|
||||
def->sidetext = L("mm");
|
||||
@@ -1434,6 +1434,55 @@ void PrintConfigDef::init_fff_params()
|
||||
def->enum_labels.push_back(L("Lightning"));
|
||||
def->set_default_value(new ConfigOptionEnum<InfillPattern>(ipCubic));
|
||||
|
||||
auto def_infill_anchor_min = def = this->add("infill_anchor", coFloatOrPercent);
|
||||
def->label = L("Sparse infill anchor length");
|
||||
def->category = L("Strength");
|
||||
def->tooltip = L("Connect an infill line to an internal perimeter with a short segment of an additional perimeter. "
|
||||
"If expressed as percentage (example: 15%) it is calculated over infill extrusion width. Slic3r tries to connect two close infill lines to a short perimeter segment. If no such perimeter segment "
|
||||
"shorter than infill_anchor_max is found, the infill line is connected to a perimeter segment at just one side "
|
||||
"and the length of the perimeter segment taken is limited to this parameter, but no longer than anchor_length_max. "
|
||||
"\nSet this parameter to zero to disable anchoring perimeters connected to a single infill line.");
|
||||
def->sidetext = L("mm or %");
|
||||
def->ratio_over = "sparse_infill_line_width";
|
||||
def->max_literal = 1000;
|
||||
def->gui_type = ConfigOptionDef::GUIType::f_enum_open;
|
||||
def->enum_values.push_back("0");
|
||||
def->enum_values.push_back("1");
|
||||
def->enum_values.push_back("2");
|
||||
def->enum_values.push_back("5");
|
||||
def->enum_values.push_back("10");
|
||||
def->enum_values.push_back("1000");
|
||||
def->enum_labels.push_back(L("0 (no open anchors)"));
|
||||
def->enum_labels.push_back("1 mm");
|
||||
def->enum_labels.push_back("2 mm");
|
||||
def->enum_labels.push_back("5 mm");
|
||||
def->enum_labels.push_back("10 mm");
|
||||
def->enum_labels.push_back(L("1000 (unlimited)"));
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloatOrPercent(400, true));
|
||||
|
||||
def = this->add("infill_anchor_max", coFloatOrPercent);
|
||||
def->label = L("Maximum length of the infill anchor");
|
||||
def->category = L("Strength");
|
||||
def->tooltip = L("Connect an infill line to an internal perimeter with a short segment of an additional perimeter. "
|
||||
"If expressed as percentage (example: 15%) it is calculated over infill extrusion width. Slic3r tries to connect two close infill lines to a short perimeter segment. If no such perimeter segment "
|
||||
"shorter than this parameter is found, the infill line is connected to a perimeter segment at just one side "
|
||||
"and the length of the perimeter segment taken is limited to infill_anchor, but no longer than this parameter. "
|
||||
"\nIf set to 0, the old algorithm for infill connection will be used, it should create the same result as with 1000 & 0.");
|
||||
def->sidetext = def_infill_anchor_min->sidetext;
|
||||
def->ratio_over = def_infill_anchor_min->ratio_over;
|
||||
def->gui_type = def_infill_anchor_min->gui_type;
|
||||
def->enum_values = def_infill_anchor_min->enum_values;
|
||||
def->max_literal = def_infill_anchor_min->max_literal;
|
||||
def->enum_labels.push_back(L("0 (Simple connect)"));
|
||||
def->enum_labels.push_back("1 mm");
|
||||
def->enum_labels.push_back("2 mm");
|
||||
def->enum_labels.push_back("5 mm");
|
||||
def->enum_labels.push_back("10 mm");
|
||||
def->enum_labels.push_back(L("1000 (unlimited)"));
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloatOrPercent(20, false));
|
||||
|
||||
def = this->add("outer_wall_acceleration", coFloat);
|
||||
def->label = L("Outer wall");
|
||||
def->tooltip = L("Acceleration of outer walls");
|
||||
@@ -2564,6 +2613,12 @@ void PrintConfigDef::init_fff_params()
|
||||
def->enum_labels.push_back(L("Random"));
|
||||
def->mode = comSimple;
|
||||
def->set_default_value(new ConfigOptionEnum<SeamPosition>(spAligned));
|
||||
|
||||
def = this->add("staggered_inner_seams", coBool);
|
||||
def->label = L("Staggered inner seams");
|
||||
def->tooltip = L("This option causes the inner seams to be shifted backwards based on their depth, forming a zigzag pattern.");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
def = this->add("seam_gap", coFloatOrPercent);
|
||||
def->label = L("Seam gap");
|
||||
@@ -2585,7 +2640,7 @@ void PrintConfigDef::init_fff_params()
|
||||
def->label = L("Wipe on loops");
|
||||
def->tooltip = L("To minimize the visibility of the seam in a closed loop extrusion, a small inward movement is executed before the extruder leaves the loop.");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionBool(true));
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
def = this->add("wipe_speed", coFloatOrPercent);
|
||||
def->label = L("Wipe speed");
|
||||
@@ -2642,6 +2697,15 @@ void PrintConfigDef::init_fff_params()
|
||||
def->mode = comSimple;
|
||||
def->set_default_value(new ConfigOptionInt(1));
|
||||
|
||||
def = this->add("skirt_speed", coFloat);
|
||||
def->label = L("Skirt speed");
|
||||
def->full_label = L("Skirt speed");
|
||||
def->tooltip = L("Speed of skirt, in mm/s. Zero means use default layer extrusion speed.");
|
||||
def->min = 0;
|
||||
def->sidetext = L("mm/s");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloat(0.0));
|
||||
|
||||
def = this->add("slow_down_layer_time", coFloats);
|
||||
def->label = L("Layer time");
|
||||
def->tooltip = L("The printing speed in exported gcode will be slowed down, when the estimated layer time is shorter than this value, to "
|
||||
@@ -3287,7 +3351,7 @@ void PrintConfigDef::init_fff_params()
|
||||
def->sidetext = L("mm");
|
||||
def->min = 0;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloats { 2. });
|
||||
def->set_default_value(new ConfigOptionFloats { 1. });
|
||||
|
||||
def = this->add("enable_prime_tower", coBool);
|
||||
def->label = L("Enable");
|
||||
|
||||
@@ -646,6 +646,7 @@ PRINT_CONFIG_CLASS_DEFINE(
|
||||
((ConfigOptionFloat, raft_first_layer_expansion))
|
||||
((ConfigOptionInt, raft_layers))
|
||||
((ConfigOptionEnum<SeamPosition>, seam_position))
|
||||
((ConfigOptionBool, staggered_inner_seams))
|
||||
((ConfigOptionFloat, slice_closing_radius))
|
||||
((ConfigOptionEnum<SlicingMode>, slicing_mode))
|
||||
((ConfigOptionBool, enable_support))
|
||||
@@ -780,9 +781,8 @@ PRINT_CONFIG_CLASS_DEFINE(
|
||||
((ConfigOptionFloat, small_perimeter_threshold))
|
||||
((ConfigOptionFloat, top_solid_infill_flow_ratio))
|
||||
((ConfigOptionFloat, bottom_solid_infill_flow_ratio))
|
||||
|
||||
|
||||
|
||||
((ConfigOptionFloatOrPercent, infill_anchor))
|
||||
((ConfigOptionFloatOrPercent, infill_anchor_max))
|
||||
|
||||
)
|
||||
|
||||
@@ -969,6 +969,7 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE(
|
||||
((ConfigOptionFloat, skirt_distance))
|
||||
((ConfigOptionInt, skirt_height))
|
||||
((ConfigOptionInt, skirt_loops))
|
||||
((ConfigOptionFloat, skirt_speed))
|
||||
((ConfigOptionFloats, slow_down_layer_time))
|
||||
((ConfigOptionBool, spiral_mode))
|
||||
((ConfigOptionInt, standby_temperature_delta))
|
||||
|
||||
@@ -831,6 +831,8 @@ bool PrintObject::invalidate_state_by_config_options(
|
||||
|| opt_key == "bottom_surface_pattern"
|
||||
|| opt_key == "external_fill_link_max_length"
|
||||
|| opt_key == "sparse_infill_pattern"
|
||||
|| opt_key == "infill_anchor"
|
||||
|| opt_key == "infill_anchor_max"
|
||||
|| opt_key == "top_surface_line_width"
|
||||
|| opt_key == "initial_layer_line_width") {
|
||||
steps.emplace_back(posInfill);
|
||||
|
||||
@@ -140,7 +140,7 @@ static std::vector<VolumeSlices> slice_volumes_inner(
|
||||
params_base.trafo = object_trafo;
|
||||
//BBS: 0.0025mm is safe enough to simplify the data to speed slicing up for high-resolution model.
|
||||
//Also has on influence on arc fitting which has default resolution 0.0125mm.
|
||||
params_base.resolution = 0.0025;
|
||||
params_base.resolution = print_config.resolution <= 0.001 ? 0.0f : 0.0025;
|
||||
switch (print_object_config.slicing_mode.value) {
|
||||
case SlicingMode::Regular: params_base.mode = MeshSlicingParams::SlicingMode::Regular; break;
|
||||
case SlicingMode::EvenOdd: params_base.mode = MeshSlicingParams::SlicingMode::EvenOdd; break;
|
||||
|
||||
@@ -1378,6 +1378,10 @@ void TreeSupport::generate_toolpaths()
|
||||
coordf_t layer_height = object_config.layer_height.value;
|
||||
const size_t wall_count = object_config.tree_support_wall_count.value;
|
||||
|
||||
// Check if set to zero, use default if so.
|
||||
if (support_extrusion_width <= 0.0)
|
||||
support_extrusion_width = Flow::auto_extrusion_width(FlowRole::frSupportMaterial, (float)nozzle_diameter);
|
||||
|
||||
// coconut: use same intensity settings as SupportMaterial.cpp
|
||||
auto m_support_material_interface_flow = support_material_interface_flow(m_object, float(m_slicing_params.layer_height));
|
||||
coordf_t interface_spacing = object_config.support_interface_spacing.value + m_support_material_interface_flow.spacing();
|
||||
|
||||
@@ -669,17 +669,6 @@ void AMSMaterialsSetting::on_clr_picker(wxMouseEvent &event)
|
||||
m_color_picker_popup.set_ams_colours(ams_colors);
|
||||
m_color_picker_popup.set_def_colour(m_clr_picker->m_colour);
|
||||
m_color_picker_popup.Popup();
|
||||
|
||||
/*auto clr_dialog = new wxColourDialog(this, m_clrData);
|
||||
if (clr_dialog->ShowModal() == wxID_OK) {
|
||||
m_clrData = &(clr_dialog->GetColourData());
|
||||
m_clr_picker->SetBackgroundColor(wxColour(
|
||||
m_clrData->GetColour().Red(),
|
||||
m_clrData->GetColour().Green(),
|
||||
m_clrData->GetColour().Blue(),
|
||||
254
|
||||
));
|
||||
}*/
|
||||
}
|
||||
|
||||
bool AMSMaterialsSetting::is_virtual_tray()
|
||||
@@ -1114,7 +1103,7 @@ ColorPickerPopup::ColorPickerPopup(wxWindow* parent)
|
||||
}
|
||||
|
||||
wxBoxSizer* m_sizer_other = new wxBoxSizer(wxHORIZONTAL);
|
||||
auto m_title_other = new wxStaticText(m_def_color_box, wxID_ANY, _L("Other color"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
auto m_title_other = new wxStaticText(m_def_color_box, wxID_ANY, _L("Other Color"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_title_other->SetFont(::Label::Body_14);
|
||||
m_title_other->SetBackgroundColour(wxColour(238, 238, 238));
|
||||
m_sizer_other->Add(m_title_other, 0, wxALL, 5);
|
||||
@@ -1124,11 +1113,43 @@ ColorPickerPopup::ColorPickerPopup(wxWindow* parent)
|
||||
other_line->SetBackgroundColour(wxColour(0xCECECE));
|
||||
m_sizer_other->Add(other_line, 1, wxALIGN_CENTER, 0);
|
||||
|
||||
//custom color
|
||||
wxBoxSizer* m_sizer_custom = new wxBoxSizer(wxHORIZONTAL);
|
||||
auto m_title_custom = new wxStaticText(m_def_color_box, wxID_ANY, _L("Custom Color"), wxDefaultPosition, wxDefaultSize, 0);
|
||||
m_title_custom->SetFont(::Label::Body_14);
|
||||
m_title_custom->SetBackgroundColour(wxColour(238, 238, 238));
|
||||
auto custom_line = new wxPanel(m_def_color_box, wxID_ANY, wxDefaultPosition, wxSize(-1, 1), wxTAB_TRAVERSAL);
|
||||
custom_line->SetBackgroundColour(wxColour(0xCECECE));
|
||||
custom_line->SetMinSize(wxSize(-1, 1));
|
||||
custom_line->SetMaxSize(wxSize(-1, 1));
|
||||
m_sizer_custom->Add(m_title_custom, 0, wxALL, 5);
|
||||
m_sizer_custom->Add(custom_line, 1, wxALIGN_CENTER, 0);
|
||||
|
||||
m_custom_cp = new StaticBox(m_def_color_box);
|
||||
m_custom_cp->SetSize(FromDIP(60), FromDIP(25));
|
||||
m_custom_cp->SetMinSize(wxSize(FromDIP(60), FromDIP(25)));
|
||||
m_custom_cp->SetMaxSize(wxSize(FromDIP(60), FromDIP(25)));
|
||||
m_custom_cp->SetBorderColor(StateColor(std::pair<wxColour, int>(wxColour(238, 238, 238), StateColor::Normal)));
|
||||
m_custom_cp->Bind(wxEVT_LEFT_DOWN, &ColorPickerPopup::on_custom_clr_picker, this);
|
||||
m_custom_cp->Bind(wxEVT_ENTER_WINDOW, [this](auto& e) {
|
||||
SetCursor(wxCURSOR_HAND);
|
||||
});
|
||||
m_custom_cp->Bind(wxEVT_LEAVE_WINDOW, [this](auto& e) {
|
||||
SetCursor(wxCURSOR_ARROW);
|
||||
});
|
||||
|
||||
m_clrData = new wxColourData();
|
||||
m_clrData->SetChooseFull(true);
|
||||
m_clrData->SetChooseAlpha(false);
|
||||
|
||||
|
||||
m_sizer_box->Add(0, 0, 0, wxTOP, FromDIP(10));
|
||||
m_sizer_box->Add(m_sizer_ams, 1, wxEXPAND|wxLEFT|wxRIGHT, FromDIP(10));
|
||||
m_sizer_box->Add(m_ams_fg_sizer, 0, wxEXPAND|wxLEFT|wxRIGHT, FromDIP(10));
|
||||
m_sizer_box->Add(m_sizer_other, 1, wxEXPAND|wxLEFT|wxRIGHT, FromDIP(10));
|
||||
m_sizer_box->Add(fg_sizer, 0, wxEXPAND|wxLEFT|wxRIGHT, FromDIP(10));
|
||||
m_sizer_box->Add(m_sizer_custom, 0, wxEXPAND|wxLEFT|wxRIGHT, FromDIP(10));
|
||||
m_sizer_box->Add(m_custom_cp, 0, wxEXPAND|wxLEFT|wxRIGHT, FromDIP(16));
|
||||
m_sizer_box->Add(0, 0, 0, wxTOP, FromDIP(10));
|
||||
|
||||
|
||||
@@ -1145,6 +1166,28 @@ ColorPickerPopup::ColorPickerPopup(wxWindow* parent)
|
||||
wxGetApp().UpdateDarkUIWin(this);
|
||||
}
|
||||
|
||||
void ColorPickerPopup::on_custom_clr_picker(wxMouseEvent& event)
|
||||
{
|
||||
auto clr_dialog = new wxColourDialog(nullptr, m_clrData);
|
||||
wxColour picker_color;
|
||||
|
||||
if (clr_dialog->ShowModal() == wxID_OK) {
|
||||
m_clrData = &(clr_dialog->GetColourData());
|
||||
|
||||
picker_color = wxColour(
|
||||
m_clrData->GetColour().Red(),
|
||||
m_clrData->GetColour().Green(),
|
||||
m_clrData->GetColour().Blue(),
|
||||
254
|
||||
);
|
||||
m_custom_cp->SetBackgroundColor(picker_color);
|
||||
set_def_colour(picker_color);
|
||||
wxCommandEvent evt(EVT_SELECTED_COLOR);
|
||||
unsigned long g_col = ((picker_color.Red() & 0xff) << 16) + ((picker_color.Green() & 0xff) << 8) + (picker_color.Blue() & 0xff);
|
||||
evt.SetInt(g_col);
|
||||
wxPostEvent(GetParent(), evt);
|
||||
}
|
||||
}
|
||||
|
||||
void ColorPickerPopup::set_ams_colours(std::vector<wxColour> ams)
|
||||
{
|
||||
@@ -1202,6 +1245,8 @@ void ColorPickerPopup::set_def_colour(wxColour col)
|
||||
}
|
||||
}
|
||||
|
||||
m_custom_cp->SetBackgroundColor(m_def_col);
|
||||
|
||||
Dismiss();
|
||||
}
|
||||
|
||||
|
||||
@@ -54,6 +54,8 @@ public:
|
||||
class ColorPickerPopup : public PopupWindow
|
||||
{
|
||||
public:
|
||||
StaticBox* m_custom_cp;
|
||||
wxColourData* m_clrData;
|
||||
StaticBox* m_def_color_box;
|
||||
wxFlexGridSizer* m_ams_fg_sizer;
|
||||
wxColour m_def_col;
|
||||
@@ -65,6 +67,7 @@ public:
|
||||
public:
|
||||
ColorPickerPopup(wxWindow* parent);
|
||||
~ColorPickerPopup() {};
|
||||
void on_custom_clr_picker(wxMouseEvent& event);
|
||||
void set_ams_colours(std::vector<wxColour> ams);
|
||||
void set_def_colour(wxColour col);
|
||||
void paintEvent(wxPaintEvent& evt);
|
||||
|
||||
@@ -540,15 +540,19 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig *config, co
|
||||
|
||||
bool have_perimeters = config->opt_int("wall_loops") > 0;
|
||||
for (auto el : { "ensure_vertical_shell_thickness", "detect_thin_wall", "detect_overhang_wall",
|
||||
"seam_position", "wall_infill_order", "outer_wall_line_width",
|
||||
"seam_position", "staggered_inner_seams", "wall_infill_order", "outer_wall_line_width",
|
||||
"inner_wall_speed", "outer_wall_speed", "small_perimeter_speed", "small_perimeter_threshold" })
|
||||
toggle_field(el, have_perimeters);
|
||||
|
||||
bool have_infill = config->option<ConfigOptionPercent>("sparse_infill_density")->value > 0;
|
||||
// sparse_infill_filament uses the same logic as in Print::extruders()
|
||||
for (auto el : { "sparse_infill_pattern", "infill_combination",
|
||||
"minimum_sparse_infill_area", "sparse_infill_filament"})
|
||||
"minimum_sparse_infill_area", "sparse_infill_filament", "infill_anchor_max"})
|
||||
toggle_line(el, have_infill);
|
||||
|
||||
// Only allow configuration of open anchors if the anchoring is enabled.
|
||||
bool has_infill_anchors = have_infill && config->option<ConfigOptionFloatOrPercent>("infill_anchor_max")->value > 0;
|
||||
toggle_field("infill_anchor", has_infill_anchors);
|
||||
|
||||
bool has_spiral_vase = config->opt_bool("spiral_mode");
|
||||
bool has_top_solid_infill = config->opt_int("top_shell_layers") > 0;
|
||||
|
||||
@@ -3085,7 +3085,7 @@ void GUI_App::init_fonts()
|
||||
// wxSYS_OEM_FIXED_FONT and wxSYS_ANSI_FIXED_FONT use the same as
|
||||
// DEFAULT in wxGtk. Use the TELETYPE family as a work-around
|
||||
m_code_font = wxFont(wxFontInfo().Family(wxFONTFAMILY_TELETYPE));
|
||||
m_code_font.SetPointSize(m_normal_font.GetPointSize());
|
||||
m_code_font.SetPointSize(m_small_font.GetPointSize());
|
||||
}
|
||||
|
||||
void GUI_App::update_fonts(const MainFrame *main_frame)
|
||||
@@ -3102,7 +3102,7 @@ void GUI_App::update_fonts(const MainFrame *main_frame)
|
||||
m_bold_font = m_normal_font.Bold();
|
||||
m_link_font = m_bold_font.Underlined();
|
||||
m_em_unit = main_frame->em_unit();
|
||||
m_code_font.SetPointSize(m_normal_font.GetPointSize());
|
||||
m_code_font.SetPointSize(m_small_font.GetPointSize());
|
||||
}
|
||||
|
||||
void GUI_App::set_label_clr_modified(const wxColour& clr)
|
||||
|
||||
@@ -95,7 +95,7 @@ std::map<std::string, std::vector<SimpleSettingData>> SettingsFactory::PART_CAT
|
||||
}},
|
||||
{ L("Strength"), {{"wall_loops", "",1},{"top_shell_layers", L("Top Solid Layers"),1},{"top_shell_thickness", L("Top Minimum Shell Thickness"),1},
|
||||
{"bottom_shell_layers", L("Bottom Solid Layers"),1}, {"bottom_shell_thickness", L("Bottom Minimum Shell Thickness"),1},
|
||||
{"sparse_infill_density", "",1},{"sparse_infill_pattern", "",1},{"top_surface_pattern", "",1},{"bottom_surface_pattern", "",1},
|
||||
{"sparse_infill_density", "",1},{"sparse_infill_pattern", "",1},{"infill_anchor", "",1},{"infill_anchor_max", "",1},{"top_surface_pattern", "",1},{"bottom_surface_pattern", "",1},
|
||||
{"infill_combination", "",1}, {"infill_wall_overlap", "",1}, {"infill_direction", "",1}, {"bridge_angle", "",1}, {"minimum_sparse_infill_area", "",1}
|
||||
}},
|
||||
{ L("Speed"), {{"outer_wall_speed", "",1},{"inner_wall_speed", "",2},{"sparse_infill_speed", "",3},{"top_surface_speed", "",4}, {"internal_solid_infill_speed", "",5},
|
||||
|
||||
@@ -2900,7 +2900,10 @@ DynamicPrintConfig ObjectList::get_default_layer_config(const int obj_idx)
|
||||
wxGetApp().preset_bundle->prints.get_edited_preset().config.opt_float("layer_height");
|
||||
config.set_key_value("layer_height",new ConfigOptionFloat(layer_height));
|
||||
// BBS
|
||||
config.set_key_value("extruder", new ConfigOptionInt(1));
|
||||
int extruder = object(obj_idx)->config.has("extruder") ?
|
||||
object(obj_idx)->config.opt_int("extruder") :
|
||||
wxGetApp().preset_bundle->prints.get_edited_preset().config.opt_float("extruder");
|
||||
config.set_key_value("extruder", new ConfigOptionInt(extruder));
|
||||
|
||||
return config;
|
||||
}
|
||||
@@ -3314,7 +3317,7 @@ void ObjectList::part_selection_changed()
|
||||
Sidebar& panel = wxGetApp().sidebar();
|
||||
panel.Freeze();
|
||||
|
||||
wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event("", false);
|
||||
//wxGetApp().plater()->canvas3D()->handle_sidebar_focus_event("", false);
|
||||
// BBS
|
||||
//wxGetApp().obj_manipul() ->UpdateAndShow(update_and_show_manipulations);
|
||||
wxGetApp().obj_settings()->UpdateAndShow(update_and_show_settings);
|
||||
|
||||
@@ -771,10 +771,12 @@ void GLGizmoText::on_render_input_window(float x, float y, float bottom_limit)
|
||||
m_imgui->text(_L("Thickness"));
|
||||
ImGui::SameLine(caption_size);
|
||||
ImGui::PushItemWidth(list_width);
|
||||
if(ImGui::InputFloat("###text_thickness", &m_thickness,0.0f, 0.0f, "%.2f"))
|
||||
m_need_update_text = true;
|
||||
float old_value = m_thickness;
|
||||
ImGui::InputFloat("###text_thickness", &m_thickness, 0.0f, 0.0f, "%.2f");
|
||||
if (m_thickness < 0.1f)
|
||||
m_thickness = 0.1f;
|
||||
if (old_value != m_thickness)
|
||||
m_need_update_text = true;
|
||||
|
||||
const float slider_icon_width = m_imgui->get_slider_icon_size().x;
|
||||
const float slider_width = list_width - 1.5 * slider_icon_width - space_size;
|
||||
@@ -806,10 +808,12 @@ void GLGizmoText::on_render_input_window(float x, float y, float bottom_limit)
|
||||
m_imgui->text(_L("Embeded\ndepth"));
|
||||
ImGui::SameLine(caption_size);
|
||||
ImGui::PushItemWidth(list_width);
|
||||
if (ImGui::InputFloat("###text_embeded_depth", &m_embeded_depth, 0.0f, 0.0f, "%.2f"))
|
||||
m_need_update_text = true;
|
||||
old_value = m_embeded_depth;
|
||||
ImGui::InputFloat("###text_embeded_depth", &m_embeded_depth, 0.0f, 0.0f, "%.2f");
|
||||
if (m_embeded_depth < 0.f)
|
||||
m_embeded_depth = 0.f;
|
||||
if (old_value != m_embeded_depth)
|
||||
m_need_update_text = true;
|
||||
|
||||
ImGui::AlignTextToFramePadding();
|
||||
m_imgui->text(_L("Input text"));
|
||||
@@ -1468,6 +1472,11 @@ void GLGizmoText::generate_text_volume(bool is_temp)
|
||||
|
||||
TextInfo text_info = get_text_info();
|
||||
if (m_is_modify && m_need_update_text) {
|
||||
if (m_object_idx == -1 || m_volume_idx == -1) {
|
||||
BOOST_LOG_TRIVIAL(error) << boost::format("Text: selected object_idx = %1%, volume_idx = %2%") % m_object_idx % m_volume_idx;
|
||||
return;
|
||||
}
|
||||
|
||||
plater->take_snapshot("Modify Text");
|
||||
const Selection &selection = m_parent.get_selection();
|
||||
ModelObject * model_object = selection.get_model()->objects[m_object_idx];
|
||||
|
||||
@@ -160,6 +160,12 @@ static wxIcon main_frame_icon(GUI_App::EAppMode app_mode)
|
||||
|
||||
wxDEFINE_EVENT(EVT_SYNC_CLOUD_PRESET, SimpleEvent);
|
||||
|
||||
#ifdef __APPLE__
|
||||
static const wxString ctrl = ("Ctrl+");
|
||||
#else
|
||||
static const wxString ctrl = _L("Ctrl+");
|
||||
#endif
|
||||
|
||||
MainFrame::MainFrame() :
|
||||
DPIFrame(NULL, wxID_ANY, "", wxDefaultPosition, wxDefaultSize, BORDERLESS_FRAME_STYLE, "mainframe")
|
||||
, m_printhost_queue_dlg(new PrintHostQueueDialog(this))
|
||||
@@ -2026,7 +2032,6 @@ static void add_common_publish_menu_items(wxMenu* publish_menu, MainFrame* mainF
|
||||
|
||||
static void add_common_view_menu_items(wxMenu* view_menu, MainFrame* mainFrame, std::function<bool(void)> can_change_view)
|
||||
{
|
||||
const wxString ctrl = _L("Ctrl+");
|
||||
// The camera control accelerators are captured by GLCanvas3D::on_char().
|
||||
append_menu_item(view_menu, wxID_ANY, _L("Default View") + "\t" + ctrl + "0", _L("Default View"), [mainFrame](wxCommandEvent&) {
|
||||
mainFrame->select_view("plate");
|
||||
@@ -2056,8 +2061,6 @@ void MainFrame::init_menubar_as_editor()
|
||||
wxMenuBar::SetAutoWindowMenu(false);
|
||||
m_menubar = new wxMenuBar();
|
||||
#endif
|
||||
|
||||
const wxString ctrl = _L("Ctrl+");
|
||||
|
||||
// File menu
|
||||
wxMenu* fileMenu = new wxMenu;
|
||||
|
||||
@@ -2233,7 +2233,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
|
||||
//BBS: add bed_exclude_area
|
||||
, config(Slic3r::DynamicPrintConfig::new_from_defaults_keys({
|
||||
"printable_area", "bed_exclude_area", "bed_custom_texture", "bed_custom_model", "print_sequence",
|
||||
"extruder_clearance_radius", "extruder_clearance_height_to_lid", "extruder_clearance_height_to_rod", "skirt_loops", "skirt_distance",
|
||||
"extruder_clearance_radius", "extruder_clearance_height_to_lid", "extruder_clearance_height_to_rod", "skirt_loops", "skirt_speed", "skirt_distance",
|
||||
"brim_width", "brim_object_gap", "brim_type", "nozzle_diameter", "single_extruder_multi_material",
|
||||
"enable_prime_tower", "wipe_tower_x", "wipe_tower_y", "prime_tower_width", "prime_tower_brim_width", "prime_volume",
|
||||
"extruder_colour", "filament_colour", "material_colour", "printable_height", "printer_model", "printer_technology",
|
||||
|
||||
@@ -30,6 +30,8 @@ PrinterWebView::PrinterWebView(wxWindow *parent)
|
||||
return;
|
||||
}
|
||||
|
||||
Bind(wxEVT_WEBVIEW_ERROR, &PrinterWebView::OnError, this);
|
||||
|
||||
SetSizer(topsizer);
|
||||
|
||||
topsizer->Add(m_browser, wxSizerFlags().Expand().Proportion(1));
|
||||
@@ -83,6 +85,38 @@ void PrinterWebView::OnClose(wxCloseEvent& evt)
|
||||
this->Hide();
|
||||
}
|
||||
|
||||
void PrinterWebView::OnError(wxWebViewEvent &evt)
|
||||
{
|
||||
auto e = "unknown error";
|
||||
switch (evt.GetInt()) {
|
||||
case wxWEBVIEW_NAV_ERR_CONNECTION:
|
||||
e = "wxWEBVIEW_NAV_ERR_CONNECTION";
|
||||
break;
|
||||
case wxWEBVIEW_NAV_ERR_CERTIFICATE:
|
||||
e = "wxWEBVIEW_NAV_ERR_CERTIFICATE";
|
||||
break;
|
||||
case wxWEBVIEW_NAV_ERR_AUTH:
|
||||
e = "wxWEBVIEW_NAV_ERR_AUTH";
|
||||
break;
|
||||
case wxWEBVIEW_NAV_ERR_SECURITY:
|
||||
e = "wxWEBVIEW_NAV_ERR_SECURITY";
|
||||
break;
|
||||
case wxWEBVIEW_NAV_ERR_NOT_FOUND:
|
||||
e = "wxWEBVIEW_NAV_ERR_NOT_FOUND";
|
||||
break;
|
||||
case wxWEBVIEW_NAV_ERR_REQUEST:
|
||||
e = "wxWEBVIEW_NAV_ERR_REQUEST";
|
||||
break;
|
||||
case wxWEBVIEW_NAV_ERR_USER_CANCELLED:
|
||||
e = "wxWEBVIEW_NAV_ERR_USER_CANCELLED";
|
||||
break;
|
||||
case wxWEBVIEW_NAV_ERR_OTHER:
|
||||
e = "wxWEBVIEW_NAV_ERR_OTHER";
|
||||
break;
|
||||
}
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__<< boost::format(": error loading page %1% %2% %3% %4%") %evt.GetURL() %evt.GetTarget() %e %evt.GetString();
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // GUI
|
||||
|
||||
@@ -38,6 +38,7 @@ public:
|
||||
void load_url(wxString& url);
|
||||
void UpdateState();
|
||||
void OnClose(wxCloseEvent& evt);
|
||||
void OnError(wxWebViewEvent& evt);
|
||||
|
||||
private:
|
||||
|
||||
|
||||
@@ -1845,6 +1845,7 @@ void TabPrint::build()
|
||||
|
||||
optgroup = page->new_optgroup(L("Seam"), L"param_seam");
|
||||
optgroup->append_single_option_line("seam_position", "Seam");
|
||||
optgroup->append_single_option_line("staggered_inner_seams", "Seam");
|
||||
optgroup->append_single_option_line("seam_gap","Seam");
|
||||
optgroup->append_single_option_line("role_based_wipe_speed","Seam");
|
||||
optgroup->append_single_option_line("wipe_speed", "Seam");
|
||||
@@ -1905,6 +1906,9 @@ void TabPrint::build()
|
||||
optgroup = page->new_optgroup(L("Infill"), L"param_infill");
|
||||
optgroup->append_single_option_line("sparse_infill_density");
|
||||
optgroup->append_single_option_line("sparse_infill_pattern", "fill-patterns#infill types and their properties of sparse");
|
||||
optgroup->append_single_option_line("infill_anchor");
|
||||
optgroup->append_single_option_line("infill_anchor_max");
|
||||
|
||||
optgroup->append_single_option_line("filter_out_gap_fill");
|
||||
|
||||
optgroup = page->new_optgroup(L("Advanced"), L"param_advanced");
|
||||
@@ -2030,6 +2034,7 @@ void TabPrint::build()
|
||||
optgroup->append_single_option_line("skirt_loops");
|
||||
optgroup->append_single_option_line("skirt_distance");
|
||||
optgroup->append_single_option_line("skirt_height");
|
||||
optgroup->append_single_option_line("skirt_speed");
|
||||
//optgroup->append_single_option_line("draft_shield");
|
||||
optgroup->append_single_option_line("brim_type", "auto-brim");
|
||||
optgroup->append_single_option_line("brim_width", "auto-brim#manual");
|
||||
|
||||
@@ -218,7 +218,7 @@ wxWebView* WebView::CreateWebView(wxWindow * parent, wxString const & url)
|
||||
#ifndef __WIN32__
|
||||
});
|
||||
#endif
|
||||
webView->EnableContextMenu(false);
|
||||
webView->EnableContextMenu(true);
|
||||
} else {
|
||||
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ": failed. Use fake web view.";
|
||||
webView = new FakeWebView;
|
||||
|
||||
@@ -376,7 +376,7 @@ void Temp_Calibration_Dlg::on_filament_type_changed(wxCommandEvent& event) {
|
||||
end = 230;
|
||||
break;
|
||||
case tPETG:
|
||||
start = 260;
|
||||
start = 250;
|
||||
end = 230;
|
||||
break;
|
||||
case tTPU:
|
||||
|
||||
@@ -156,7 +156,7 @@ bool Repetier::upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, Error
|
||||
|
||||
bool Repetier::validate_version_text(const boost::optional<std::string> &version_text) const
|
||||
{
|
||||
return version_text ? boost::starts_with(*version_text, "Repetier") : true;
|
||||
return version_text ? (!version_text->empty()) : true;
|
||||
}
|
||||
|
||||
void Repetier::set_auth(Http &http) const
|
||||
|
||||
@@ -41,8 +41,7 @@ namespace BBL {
|
||||
|
||||
#define BAMBU_NETWORK_LIBRARY "bambu_networking"
|
||||
#define BAMBU_NETWORK_AGENT_NAME "bambu_network_agent"
|
||||
#define BAMBU_NETWORK_AGENT_VERSION "01.06.00.01"
|
||||
|
||||
#define BAMBU_NETWORK_AGENT_VERSION "01.06.02.01"
|
||||
|
||||
//iot preset type strings
|
||||
#define IOT_PRINTER_TYPE_STRING "printer"
|
||||
|
||||
Reference in New Issue
Block a user