Merge remote-tracking branch 'upstream/main' into feature/pressure-advance-pattern-method

This commit is contained in:
thewildmage
2023-07-14 10:39:02 -06:00
180 changed files with 17620 additions and 6753 deletions
-2769
View File
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
+74 -71
View File
@@ -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);
+13 -3
View File
@@ -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,
+20 -17
View File
@@ -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
View File
@@ -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);
File diff suppressed because it is too large Load Diff
+96 -98
View File
@@ -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
+3 -4
View File
@@ -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";
+1 -1
View File
@@ -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();
+2 -4
View File
@@ -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 &region = this->region();
const PrintRegionConfig &region_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 {
+1 -1
View File
@@ -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>());
+43 -10
View File
@@ -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())
+3 -3
View File
@@ -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
View File
@@ -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) {
+67 -3
View File
@@ -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");
+4 -3
View File
@@ -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))
+2
View File
@@ -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);
+1 -1
View File
@@ -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;
+4
View File
@@ -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();
+57 -12
View File
@@ -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();
}
+3
View File
@@ -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);
+6 -2
View File
@@ -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;
+2 -2
View File
@@ -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)
+1 -1
View File
@@ -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},
+5 -2
View File
@@ -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);
+13 -4
View File
@@ -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];
+6 -3
View File
@@ -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;
+1 -1
View File
@@ -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",
+34
View File
@@ -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
+1
View File
@@ -38,6 +38,7 @@ public:
void load_url(wxString& url);
void UpdateState();
void OnClose(wxCloseEvent& evt);
void OnError(wxWebViewEvent& evt);
private:
+5
View File
@@ -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");
+1 -1
View File
@@ -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;
+1 -1
View File
@@ -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:
+1 -1
View File
@@ -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
+1 -2
View File
@@ -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"