Merge branch 'vb_optimizations'
This commit is contained in:
commit
ccc193959b
@ -546,6 +546,7 @@ foreach(po_file ${L10N_PO_FILES})
|
|||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
find_package(NLopt 1.4 REQUIRED)
|
find_package(NLopt 1.4 REQUIRED)
|
||||||
|
slic3r_remap_configs(NLopt::nlopt RelWithDebInfo Release)
|
||||||
|
|
||||||
if(SLIC3R_STATIC)
|
if(SLIC3R_STATIC)
|
||||||
set(OPENVDB_USE_STATIC_LIBS ON)
|
set(OPENVDB_USE_STATIC_LIBS ON)
|
||||||
|
@ -112,7 +112,7 @@ int PolyTree::Total() const
|
|||||||
void PolyNode::AddChild(PolyNode& child)
|
void PolyNode::AddChild(PolyNode& child)
|
||||||
{
|
{
|
||||||
unsigned cnt = (unsigned)Childs.size();
|
unsigned cnt = (unsigned)Childs.size();
|
||||||
Childs.push_back(&child);
|
Childs.emplace_back(&child);
|
||||||
child.Parent = this;
|
child.Parent = this;
|
||||||
child.Index = cnt;
|
child.Index = cnt;
|
||||||
}
|
}
|
||||||
@ -674,7 +674,7 @@ TEdge* ClipperBase::ProcessBound(TEdge* E, bool NextIsForward)
|
|||||||
locMin.RightBound = E;
|
locMin.RightBound = E;
|
||||||
E->WindDelta = 0;
|
E->WindDelta = 0;
|
||||||
Result = ProcessBound(E, NextIsForward);
|
Result = ProcessBound(E, NextIsForward);
|
||||||
m_MinimaList.push_back(locMin);
|
m_MinimaList.emplace_back(locMin);
|
||||||
}
|
}
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
@ -896,7 +896,7 @@ bool ClipperBase::AddPathInternal(const Path &pg, int highI, PolyType PolyTyp, b
|
|||||||
E->NextInLML = E->Next;
|
E->NextInLML = E->Next;
|
||||||
E = E->Next;
|
E = E->Next;
|
||||||
}
|
}
|
||||||
m_MinimaList.push_back(locMin);
|
m_MinimaList.emplace_back(locMin);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -949,7 +949,7 @@ bool ClipperBase::AddPathInternal(const Path &pg, int highI, PolyType PolyTyp, b
|
|||||||
locMin.LeftBound = 0;
|
locMin.LeftBound = 0;
|
||||||
else if (locMin.RightBound->OutIdx == Skip)
|
else if (locMin.RightBound->OutIdx == Skip)
|
||||||
locMin.RightBound = 0;
|
locMin.RightBound = 0;
|
||||||
m_MinimaList.push_back(locMin);
|
m_MinimaList.emplace_back(locMin);
|
||||||
if (!leftBoundIsForward) E = E2;
|
if (!leftBoundIsForward) E = E2;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -1177,7 +1177,7 @@ OutPt* Clipper::AllocateOutPt()
|
|||||||
pt = &m_OutPts.back()[m_OutPtsChunkLast ++];
|
pt = &m_OutPts.back()[m_OutPtsChunkLast ++];
|
||||||
} else {
|
} else {
|
||||||
// The last chunk is full. Allocate a new one.
|
// The last chunk is full. Allocate a new one.
|
||||||
m_OutPts.push_back({});
|
m_OutPts.emplace_back();
|
||||||
m_OutPtsChunkLast = 1;
|
m_OutPtsChunkLast = 1;
|
||||||
pt = &m_OutPts.back().front();
|
pt = &m_OutPts.back().front();
|
||||||
}
|
}
|
||||||
@ -1967,7 +1967,7 @@ void Clipper::AppendPolygon(TEdge *e1, TEdge *e2)
|
|||||||
|
|
||||||
OutRec* Clipper::CreateOutRec()
|
OutRec* Clipper::CreateOutRec()
|
||||||
{
|
{
|
||||||
m_PolyOuts.push_back({});
|
m_PolyOuts.emplace_back();
|
||||||
OutRec &result = m_PolyOuts.back();
|
OutRec &result = m_PolyOuts.back();
|
||||||
result.IsHole = false;
|
result.IsHole = false;
|
||||||
result.IsOpen = false;
|
result.IsOpen = false;
|
||||||
@ -2576,7 +2576,7 @@ void Clipper::ProcessEdgesAtTopOfScanbeam(const cInt topY)
|
|||||||
|
|
||||||
if(IsMaximaEdge)
|
if(IsMaximaEdge)
|
||||||
{
|
{
|
||||||
if (m_StrictSimple) m_Maxima.push_back(e->Top.x());
|
if (m_StrictSimple) m_Maxima.emplace_back(e->Top.x());
|
||||||
TEdge* ePrev = e->PrevInAEL;
|
TEdge* ePrev = e->PrevInAEL;
|
||||||
DoMaxima(e);
|
DoMaxima(e);
|
||||||
if( !ePrev ) e = m_ActiveEdges;
|
if( !ePrev ) e = m_ActiveEdges;
|
||||||
@ -3349,7 +3349,7 @@ void ClipperOffset::AddPath(const Path& path, JoinType joinType, EndType endType
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
newNode->Contour.reserve(highI + 1);
|
newNode->Contour.reserve(highI + 1);
|
||||||
newNode->Contour.push_back(path[0]);
|
newNode->Contour.emplace_back(path[0]);
|
||||||
int j = 0, k = 0;
|
int j = 0, k = 0;
|
||||||
for (int i = 1; i <= highI; i++) {
|
for (int i = 1; i <= highI; i++) {
|
||||||
bool same = false;
|
bool same = false;
|
||||||
@ -3362,7 +3362,7 @@ void ClipperOffset::AddPath(const Path& path, JoinType joinType, EndType endType
|
|||||||
if (same)
|
if (same)
|
||||||
continue;
|
continue;
|
||||||
j++;
|
j++;
|
||||||
newNode->Contour.push_back(path[i]);
|
newNode->Contour.emplace_back(path[i]);
|
||||||
if (path[i].y() > newNode->Contour[k].y() ||
|
if (path[i].y() > newNode->Contour[k].y() ||
|
||||||
(path[i].y() == newNode->Contour[k].y() &&
|
(path[i].y() == newNode->Contour[k].y() &&
|
||||||
path[i].x() < newNode->Contour[k].x())) k = j;
|
path[i].x() < newNode->Contour[k].x())) k = j;
|
||||||
@ -3490,7 +3490,7 @@ void ClipperOffset::DoOffset(double delta)
|
|||||||
{
|
{
|
||||||
PolyNode& node = *m_polyNodes.Childs[i];
|
PolyNode& node = *m_polyNodes.Childs[i];
|
||||||
if (node.m_endtype == etClosedPolygon)
|
if (node.m_endtype == etClosedPolygon)
|
||||||
m_destPolys.push_back(node.Contour);
|
m_destPolys.emplace_back(node.Contour);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -3532,7 +3532,7 @@ void ClipperOffset::DoOffset(double delta)
|
|||||||
double X = 1.0, Y = 0.0;
|
double X = 1.0, Y = 0.0;
|
||||||
for (cInt j = 1; j <= steps; j++)
|
for (cInt j = 1; j <= steps; j++)
|
||||||
{
|
{
|
||||||
m_destPoly.push_back(IntPoint2d(
|
m_destPoly.emplace_back(IntPoint2d(
|
||||||
Round(m_srcPoly[0].x() + X * delta),
|
Round(m_srcPoly[0].x() + X * delta),
|
||||||
Round(m_srcPoly[0].y() + Y * delta)));
|
Round(m_srcPoly[0].y() + Y * delta)));
|
||||||
double X2 = X;
|
double X2 = X;
|
||||||
@ -3545,7 +3545,7 @@ void ClipperOffset::DoOffset(double delta)
|
|||||||
double X = -1.0, Y = -1.0;
|
double X = -1.0, Y = -1.0;
|
||||||
for (int j = 0; j < 4; ++j)
|
for (int j = 0; j < 4; ++j)
|
||||||
{
|
{
|
||||||
m_destPoly.push_back(IntPoint2d(
|
m_destPoly.emplace_back(IntPoint2d(
|
||||||
Round(m_srcPoly[0].x() + X * delta),
|
Round(m_srcPoly[0].x() + X * delta),
|
||||||
Round(m_srcPoly[0].y() + Y * delta)));
|
Round(m_srcPoly[0].y() + Y * delta)));
|
||||||
if (X < 0) X = 1;
|
if (X < 0) X = 1;
|
||||||
@ -3553,32 +3553,32 @@ void ClipperOffset::DoOffset(double delta)
|
|||||||
else X = -1;
|
else X = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_destPolys.push_back(m_destPoly);
|
m_destPolys.emplace_back(m_destPoly);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
//build m_normals ...
|
//build m_normals ...
|
||||||
m_normals.clear();
|
m_normals.clear();
|
||||||
m_normals.reserve(len);
|
m_normals.reserve(len);
|
||||||
for (int j = 0; j < len - 1; ++j)
|
for (int j = 0; j < len - 1; ++j)
|
||||||
m_normals.push_back(GetUnitNormal(m_srcPoly[j], m_srcPoly[j + 1]));
|
m_normals.emplace_back(GetUnitNormal(m_srcPoly[j], m_srcPoly[j + 1]));
|
||||||
if (node.m_endtype == etClosedLine || node.m_endtype == etClosedPolygon)
|
if (node.m_endtype == etClosedLine || node.m_endtype == etClosedPolygon)
|
||||||
m_normals.push_back(GetUnitNormal(m_srcPoly[len - 1], m_srcPoly[0]));
|
m_normals.emplace_back(GetUnitNormal(m_srcPoly[len - 1], m_srcPoly[0]));
|
||||||
else
|
else
|
||||||
m_normals.push_back(DoublePoint(m_normals[len - 2]));
|
m_normals.emplace_back(DoublePoint(m_normals[len - 2]));
|
||||||
|
|
||||||
if (node.m_endtype == etClosedPolygon)
|
if (node.m_endtype == etClosedPolygon)
|
||||||
{
|
{
|
||||||
int k = len - 1;
|
int k = len - 1;
|
||||||
for (int j = 0; j < len; ++j)
|
for (int j = 0; j < len; ++j)
|
||||||
OffsetPoint(j, k, node.m_jointype);
|
OffsetPoint(j, k, node.m_jointype);
|
||||||
m_destPolys.push_back(m_destPoly);
|
m_destPolys.emplace_back(m_destPoly);
|
||||||
}
|
}
|
||||||
else if (node.m_endtype == etClosedLine)
|
else if (node.m_endtype == etClosedLine)
|
||||||
{
|
{
|
||||||
int k = len - 1;
|
int k = len - 1;
|
||||||
for (int j = 0; j < len; ++j)
|
for (int j = 0; j < len; ++j)
|
||||||
OffsetPoint(j, k, node.m_jointype);
|
OffsetPoint(j, k, node.m_jointype);
|
||||||
m_destPolys.push_back(m_destPoly);
|
m_destPolys.emplace_back(m_destPoly);
|
||||||
m_destPoly.clear();
|
m_destPoly.clear();
|
||||||
//re-build m_normals ...
|
//re-build m_normals ...
|
||||||
DoublePoint n = m_normals[len -1];
|
DoublePoint n = m_normals[len -1];
|
||||||
@ -3588,7 +3588,7 @@ void ClipperOffset::DoOffset(double delta)
|
|||||||
k = 0;
|
k = 0;
|
||||||
for (int j = len - 1; j >= 0; j--)
|
for (int j = len - 1; j >= 0; j--)
|
||||||
OffsetPoint(j, k, node.m_jointype);
|
OffsetPoint(j, k, node.m_jointype);
|
||||||
m_destPolys.push_back(m_destPoly);
|
m_destPolys.emplace_back(m_destPoly);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -3601,9 +3601,9 @@ void ClipperOffset::DoOffset(double delta)
|
|||||||
{
|
{
|
||||||
int j = len - 1;
|
int j = len - 1;
|
||||||
pt1 = IntPoint2d(Round(m_srcPoly[j].x() + m_normals[j].x() * delta), Round(m_srcPoly[j].y() + m_normals[j].y() * delta));
|
pt1 = IntPoint2d(Round(m_srcPoly[j].x() + m_normals[j].x() * delta), Round(m_srcPoly[j].y() + m_normals[j].y() * delta));
|
||||||
m_destPoly.push_back(pt1);
|
m_destPoly.emplace_back(pt1);
|
||||||
pt1 = IntPoint2d(Round(m_srcPoly[j].x() - m_normals[j].x() * delta), Round(m_srcPoly[j].y() - m_normals[j].y() * delta));
|
pt1 = IntPoint2d(Round(m_srcPoly[j].x() - m_normals[j].x() * delta), Round(m_srcPoly[j].y() - m_normals[j].y() * delta));
|
||||||
m_destPoly.push_back(pt1);
|
m_destPoly.emplace_back(pt1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -3628,9 +3628,9 @@ void ClipperOffset::DoOffset(double delta)
|
|||||||
if (node.m_endtype == etOpenButt)
|
if (node.m_endtype == etOpenButt)
|
||||||
{
|
{
|
||||||
pt1 = IntPoint2d(Round(m_srcPoly[0].x() - m_normals[0].x() * delta), Round(m_srcPoly[0].y() - m_normals[0].y() * delta));
|
pt1 = IntPoint2d(Round(m_srcPoly[0].x() - m_normals[0].x() * delta), Round(m_srcPoly[0].y() - m_normals[0].y() * delta));
|
||||||
m_destPoly.push_back(pt1);
|
m_destPoly.emplace_back(pt1);
|
||||||
pt1 = IntPoint2d(Round(m_srcPoly[0].x() + m_normals[0].x() * delta), Round(m_srcPoly[0].y() + m_normals[0].y() * delta));
|
pt1 = IntPoint2d(Round(m_srcPoly[0].x() + m_normals[0].x() * delta), Round(m_srcPoly[0].y() + m_normals[0].y() * delta));
|
||||||
m_destPoly.push_back(pt1);
|
m_destPoly.emplace_back(pt1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -3641,7 +3641,7 @@ void ClipperOffset::DoOffset(double delta)
|
|||||||
else
|
else
|
||||||
DoRound(0, 1);
|
DoRound(0, 1);
|
||||||
}
|
}
|
||||||
m_destPolys.push_back(m_destPoly);
|
m_destPolys.emplace_back(m_destPoly);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3657,7 +3657,7 @@ void ClipperOffset::OffsetPoint(int j, int& k, JoinType jointype)
|
|||||||
double cosA = (m_normals[k].x() * m_normals[j].x() + m_normals[j].y() * m_normals[k].y() );
|
double cosA = (m_normals[k].x() * m_normals[j].x() + m_normals[j].y() * m_normals[k].y() );
|
||||||
if (cosA > 0) // angle => 0 degrees
|
if (cosA > 0) // angle => 0 degrees
|
||||||
{
|
{
|
||||||
m_destPoly.push_back(IntPoint2d(Round(m_srcPoly[j].x() + m_normals[k].x() * m_delta),
|
m_destPoly.emplace_back(IntPoint2d(Round(m_srcPoly[j].x() + m_normals[k].x() * m_delta),
|
||||||
Round(m_srcPoly[j].y() + m_normals[k].y() * m_delta)));
|
Round(m_srcPoly[j].y() + m_normals[k].y() * m_delta)));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -3668,10 +3668,10 @@ void ClipperOffset::OffsetPoint(int j, int& k, JoinType jointype)
|
|||||||
|
|
||||||
if (m_sinA * m_delta < 0)
|
if (m_sinA * m_delta < 0)
|
||||||
{
|
{
|
||||||
m_destPoly.push_back(IntPoint2d(Round(m_srcPoly[j].x() + m_normals[k].x() * m_delta),
|
m_destPoly.emplace_back(IntPoint2d(Round(m_srcPoly[j].x() + m_normals[k].x() * m_delta),
|
||||||
Round(m_srcPoly[j].y() + m_normals[k].y() * m_delta)));
|
Round(m_srcPoly[j].y() + m_normals[k].y() * m_delta)));
|
||||||
m_destPoly.push_back(m_srcPoly[j]);
|
m_destPoly.emplace_back(m_srcPoly[j]);
|
||||||
m_destPoly.push_back(IntPoint2d(Round(m_srcPoly[j].x() + m_normals[j].x() * m_delta),
|
m_destPoly.emplace_back(IntPoint2d(Round(m_srcPoly[j].x() + m_normals[j].x() * m_delta),
|
||||||
Round(m_srcPoly[j].y() + m_normals[j].y() * m_delta)));
|
Round(m_srcPoly[j].y() + m_normals[j].y() * m_delta)));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -3695,10 +3695,10 @@ void ClipperOffset::DoSquare(int j, int k)
|
|||||||
{
|
{
|
||||||
double dx = std::tan(std::atan2(m_sinA,
|
double dx = std::tan(std::atan2(m_sinA,
|
||||||
m_normals[k].x() * m_normals[j].x() + m_normals[k].y() * m_normals[j].y()) / 4);
|
m_normals[k].x() * m_normals[j].x() + m_normals[k].y() * m_normals[j].y()) / 4);
|
||||||
m_destPoly.push_back(IntPoint2d(
|
m_destPoly.emplace_back(IntPoint2d(
|
||||||
Round(m_srcPoly[j].x() + m_delta * (m_normals[k].x() - m_normals[k].y() * dx)),
|
Round(m_srcPoly[j].x() + m_delta * (m_normals[k].x() - m_normals[k].y() * dx)),
|
||||||
Round(m_srcPoly[j].y() + m_delta * (m_normals[k].y() + m_normals[k].x() * dx))));
|
Round(m_srcPoly[j].y() + m_delta * (m_normals[k].y() + m_normals[k].x() * dx))));
|
||||||
m_destPoly.push_back(IntPoint2d(
|
m_destPoly.emplace_back(IntPoint2d(
|
||||||
Round(m_srcPoly[j].x() + m_delta * (m_normals[j].x() + m_normals[j].y() * dx)),
|
Round(m_srcPoly[j].x() + m_delta * (m_normals[j].x() + m_normals[j].y() * dx)),
|
||||||
Round(m_srcPoly[j].y() + m_delta * (m_normals[j].y() - m_normals[j].x() * dx))));
|
Round(m_srcPoly[j].y() + m_delta * (m_normals[j].y() - m_normals[j].x() * dx))));
|
||||||
}
|
}
|
||||||
@ -3707,7 +3707,7 @@ void ClipperOffset::DoSquare(int j, int k)
|
|||||||
void ClipperOffset::DoMiter(int j, int k, double r)
|
void ClipperOffset::DoMiter(int j, int k, double r)
|
||||||
{
|
{
|
||||||
double q = m_delta / r;
|
double q = m_delta / r;
|
||||||
m_destPoly.push_back(IntPoint2d(Round(m_srcPoly[j].x() + (m_normals[k].x() + m_normals[j].x()) * q),
|
m_destPoly.emplace_back(IntPoint2d(Round(m_srcPoly[j].x() + (m_normals[k].x() + m_normals[j].x()) * q),
|
||||||
Round(m_srcPoly[j].y() + (m_normals[k].y() + m_normals[j].y()) * q)));
|
Round(m_srcPoly[j].y() + (m_normals[k].y() + m_normals[j].y()) * q)));
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -3721,14 +3721,14 @@ void ClipperOffset::DoRound(int j, int k)
|
|||||||
double X = m_normals[k].x(), Y = m_normals[k].y(), X2;
|
double X = m_normals[k].x(), Y = m_normals[k].y(), X2;
|
||||||
for (int i = 0; i < steps; ++i)
|
for (int i = 0; i < steps; ++i)
|
||||||
{
|
{
|
||||||
m_destPoly.push_back(IntPoint2d(
|
m_destPoly.emplace_back(IntPoint2d(
|
||||||
Round(m_srcPoly[j].x() + X * m_delta),
|
Round(m_srcPoly[j].x() + X * m_delta),
|
||||||
Round(m_srcPoly[j].y() + Y * m_delta)));
|
Round(m_srcPoly[j].y() + Y * m_delta)));
|
||||||
X2 = X;
|
X2 = X;
|
||||||
X = X * m_cos - m_sin * Y;
|
X = X * m_cos - m_sin * Y;
|
||||||
Y = X2 * m_sin + Y * m_cos;
|
Y = X2 * m_sin + Y * m_cos;
|
||||||
}
|
}
|
||||||
m_destPoly.push_back(IntPoint2d(
|
m_destPoly.emplace_back(IntPoint2d(
|
||||||
Round(m_srcPoly[j].x() + m_normals[j].x() * m_delta),
|
Round(m_srcPoly[j].x() + m_normals[j].x() * m_delta),
|
||||||
Round(m_srcPoly[j].y() + m_normals[j].y() * m_delta)));
|
Round(m_srcPoly[j].y() + m_normals[j].y() * m_delta)));
|
||||||
}
|
}
|
||||||
@ -3996,8 +3996,8 @@ void Minkowski(const Path& poly, const Path& path,
|
|||||||
Path p;
|
Path p;
|
||||||
p.reserve(polyCnt);
|
p.reserve(polyCnt);
|
||||||
for (size_t j = 0; j < poly.size(); ++j)
|
for (size_t j = 0; j < poly.size(); ++j)
|
||||||
p.push_back(IntPoint2d(path[i].x() + poly[j].x(), path[i].y() + poly[j].y()));
|
p.emplace_back(IntPoint2d(path[i].x() + poly[j].x(), path[i].y() + poly[j].y()));
|
||||||
pp.push_back(p);
|
pp.emplace_back(p);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
for (size_t i = 0; i < pathCnt; ++i)
|
for (size_t i = 0; i < pathCnt; ++i)
|
||||||
@ -4005,8 +4005,8 @@ void Minkowski(const Path& poly, const Path& path,
|
|||||||
Path p;
|
Path p;
|
||||||
p.reserve(polyCnt);
|
p.reserve(polyCnt);
|
||||||
for (size_t j = 0; j < poly.size(); ++j)
|
for (size_t j = 0; j < poly.size(); ++j)
|
||||||
p.push_back(IntPoint2d(path[i].x() - poly[j].x(), path[i].y() - poly[j].y()));
|
p.emplace_back(IntPoint2d(path[i].x() - poly[j].x(), path[i].y() - poly[j].y()));
|
||||||
pp.push_back(p);
|
pp.emplace_back(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
solution.clear();
|
solution.clear();
|
||||||
@ -4016,12 +4016,12 @@ void Minkowski(const Path& poly, const Path& path,
|
|||||||
{
|
{
|
||||||
Path quad;
|
Path quad;
|
||||||
quad.reserve(4);
|
quad.reserve(4);
|
||||||
quad.push_back(pp[i % pathCnt][j % polyCnt]);
|
quad.emplace_back(pp[i % pathCnt][j % polyCnt]);
|
||||||
quad.push_back(pp[(i + 1) % pathCnt][j % polyCnt]);
|
quad.emplace_back(pp[(i + 1) % pathCnt][j % polyCnt]);
|
||||||
quad.push_back(pp[(i + 1) % pathCnt][(j + 1) % polyCnt]);
|
quad.emplace_back(pp[(i + 1) % pathCnt][(j + 1) % polyCnt]);
|
||||||
quad.push_back(pp[i % pathCnt][(j + 1) % polyCnt]);
|
quad.emplace_back(pp[i % pathCnt][(j + 1) % polyCnt]);
|
||||||
if (!Orientation(quad)) ReversePath(quad);
|
if (!Orientation(quad)) ReversePath(quad);
|
||||||
solution.push_back(quad);
|
solution.emplace_back(quad);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@ -4081,7 +4081,7 @@ void AddPolyNodeToPaths(const PolyNode& polynode, NodeType nodetype, Paths& path
|
|||||||
else if (nodetype == ntOpen) return;
|
else if (nodetype == ntOpen) return;
|
||||||
|
|
||||||
if (!polynode.Contour.empty() && match)
|
if (!polynode.Contour.empty() && match)
|
||||||
paths.push_back(polynode.Contour);
|
paths.emplace_back(polynode.Contour);
|
||||||
for (int i = 0; i < polynode.ChildCount(); ++i)
|
for (int i = 0; i < polynode.ChildCount(); ++i)
|
||||||
AddPolyNodeToPaths(*polynode.Childs[i], nodetype, paths);
|
AddPolyNodeToPaths(*polynode.Childs[i], nodetype, paths);
|
||||||
}
|
}
|
||||||
@ -4093,7 +4093,7 @@ void AddPolyNodeToPaths(PolyNode&& polynode, NodeType nodetype, Paths& paths)
|
|||||||
else if (nodetype == ntOpen) return;
|
else if (nodetype == ntOpen) return;
|
||||||
|
|
||||||
if (!polynode.Contour.empty() && match)
|
if (!polynode.Contour.empty() && match)
|
||||||
paths.push_back(std::move(polynode.Contour));
|
paths.emplace_back(std::move(polynode.Contour));
|
||||||
for (int i = 0; i < polynode.ChildCount(); ++i)
|
for (int i = 0; i < polynode.ChildCount(); ++i)
|
||||||
AddPolyNodeToPaths(std::move(*polynode.Childs[i]), nodetype, paths);
|
AddPolyNodeToPaths(std::move(*polynode.Childs[i]), nodetype, paths);
|
||||||
}
|
}
|
||||||
@ -4131,7 +4131,7 @@ void OpenPathsFromPolyTree(PolyTree& polytree, Paths& paths)
|
|||||||
//Open paths are top level only, so ...
|
//Open paths are top level only, so ...
|
||||||
for (int i = 0; i < polytree.ChildCount(); ++i)
|
for (int i = 0; i < polytree.ChildCount(); ++i)
|
||||||
if (polytree.Childs[i]->IsOpen())
|
if (polytree.Childs[i]->IsOpen())
|
||||||
paths.push_back(polytree.Childs[i]->Contour);
|
paths.emplace_back(polytree.Childs[i]->Contour);
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -685,6 +685,8 @@ Slic3r::Polygons diff(const Slic3r::Surfaces &subject, const Slic3r::Polygons &c
|
|||||||
{ return _clipper(ClipperLib::ctDifference, ClipperUtils::SurfacesProvider(subject), ClipperUtils::PolygonsProvider(clip), do_safety_offset); }
|
{ return _clipper(ClipperLib::ctDifference, ClipperUtils::SurfacesProvider(subject), ClipperUtils::PolygonsProvider(clip), do_safety_offset); }
|
||||||
Slic3r::Polygons intersection(const Slic3r::Polygon &subject, const Slic3r::Polygon &clip, ApplySafetyOffset do_safety_offset)
|
Slic3r::Polygons intersection(const Slic3r::Polygon &subject, const Slic3r::Polygon &clip, ApplySafetyOffset do_safety_offset)
|
||||||
{ return _clipper(ClipperLib::ctIntersection, ClipperUtils::SinglePathProvider(subject.points), ClipperUtils::SinglePathProvider(clip.points), do_safety_offset); }
|
{ return _clipper(ClipperLib::ctIntersection, ClipperUtils::SinglePathProvider(subject.points), ClipperUtils::SinglePathProvider(clip.points), do_safety_offset); }
|
||||||
|
Slic3r::Polygons intersection_clipped(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, ApplySafetyOffset do_safety_offset)
|
||||||
|
{ return intersection(subject, ClipperUtils::clip_clipper_polygons_with_subject_bbox(clip, get_extents(subject).inflated(SCALED_EPSILON)), do_safety_offset); }
|
||||||
Slic3r::Polygons intersection(const Slic3r::Polygons &subject, const Slic3r::ExPolygon &clip, ApplySafetyOffset do_safety_offset)
|
Slic3r::Polygons intersection(const Slic3r::Polygons &subject, const Slic3r::ExPolygon &clip, ApplySafetyOffset do_safety_offset)
|
||||||
{ return _clipper(ClipperLib::ctIntersection, ClipperUtils::PolygonsProvider(subject), ClipperUtils::ExPolygonProvider(clip), do_safety_offset); }
|
{ return _clipper(ClipperLib::ctIntersection, ClipperUtils::PolygonsProvider(subject), ClipperUtils::ExPolygonProvider(clip), do_safety_offset); }
|
||||||
Slic3r::Polygons intersection(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, ApplySafetyOffset do_safety_offset)
|
Slic3r::Polygons intersection(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, ApplySafetyOffset do_safety_offset)
|
||||||
|
@ -453,6 +453,9 @@ inline Slic3r::Lines diff_ln(const Slic3r::Lines &subject, const Slic3r::Polygon
|
|||||||
Slic3r::Polygons intersection(const Slic3r::Polygon &subject, const Slic3r::Polygon &clip, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No);
|
Slic3r::Polygons intersection(const Slic3r::Polygon &subject, const Slic3r::Polygon &clip, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No);
|
||||||
Slic3r::Polygons intersection(const Slic3r::Polygons &subject, const Slic3r::ExPolygon &clip, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No);
|
Slic3r::Polygons intersection(const Slic3r::Polygons &subject, const Slic3r::ExPolygon &clip, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No);
|
||||||
Slic3r::Polygons intersection(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No);
|
Slic3r::Polygons intersection(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No);
|
||||||
|
// Optimized version clipping the "clipping" polygon using clip_clipper_polygon_with_subject_bbox().
|
||||||
|
// To be used with complex clipping polygons, where majority of the clipping polygons are outside of the source polygon.
|
||||||
|
Slic3r::Polygons intersection_clipped(const Slic3r::Polygons &subject, const Slic3r::Polygons &clip, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No);
|
||||||
Slic3r::Polygons intersection(const Slic3r::ExPolygon &subject, const Slic3r::ExPolygon &clip, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No);
|
Slic3r::Polygons intersection(const Slic3r::ExPolygon &subject, const Slic3r::ExPolygon &clip, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No);
|
||||||
Slic3r::Polygons intersection(const Slic3r::ExPolygons &subject, const Slic3r::Polygons &clip, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No);
|
Slic3r::Polygons intersection(const Slic3r::ExPolygons &subject, const Slic3r::Polygons &clip, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No);
|
||||||
Slic3r::Polygons intersection(const Slic3r::ExPolygons &subject, const Slic3r::ExPolygons &clip, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No);
|
Slic3r::Polygons intersection(const Slic3r::ExPolygons &subject, const Slic3r::ExPolygons &clip, ApplySafetyOffset do_safety_offset = ApplySafetyOffset::No);
|
||||||
|
@ -40,11 +40,12 @@ template<class L> auto get_b(L &&l) { return Traits<remove_cvref_t<L>>::get_b(l)
|
|||||||
|
|
||||||
// Distance to the closest point of line.
|
// Distance to the closest point of line.
|
||||||
template<class L>
|
template<class L>
|
||||||
double distance_to_squared(const L &line, const Vec<Dim<L>, Scalar<L>> &point, Vec<Dim<L>, Scalar<L>> *nearest_point)
|
inline double distance_to_squared(const L &line, const Vec<Dim<L>, Scalar<L>> &point, Vec<Dim<L>, Scalar<L>> *nearest_point)
|
||||||
{
|
{
|
||||||
const Vec<Dim<L>, double> v = (get_b(line) - get_a(line)).template cast<double>();
|
using VecType = Vec<Dim<L>, double>;
|
||||||
const Vec<Dim<L>, double> va = (point - get_a(line)).template cast<double>();
|
const VecType v = (get_b(line) - get_a(line)).template cast<double>();
|
||||||
const double l2 = v.squaredNorm(); // avoid a sqrt
|
const VecType va = (point - get_a(line)).template cast<double>();
|
||||||
|
const double l2 = v.squaredNorm();
|
||||||
if (l2 == 0.0) {
|
if (l2 == 0.0) {
|
||||||
// a == b case
|
// a == b case
|
||||||
*nearest_point = get_a(line);
|
*nearest_point = get_a(line);
|
||||||
@ -53,19 +54,20 @@ double distance_to_squared(const L &line, const Vec<Dim<L>, Scalar<L>> &point, V
|
|||||||
// Consider the line extending the segment, parameterized as a + t (b - a).
|
// Consider the line extending the segment, parameterized as a + t (b - a).
|
||||||
// We find projection of this point onto the line.
|
// We find projection of this point onto the line.
|
||||||
// It falls where t = [(this-a) . (b-a)] / |b-a|^2
|
// It falls where t = [(this-a) . (b-a)] / |b-a|^2
|
||||||
const double t = va.dot(v) / l2;
|
const double t = va.dot(v);
|
||||||
if (t <= 0.0) {
|
if (t <= 0.0) {
|
||||||
// beyond the 'a' end of the segment
|
// beyond the 'a' end of the segment
|
||||||
*nearest_point = get_a(line);
|
*nearest_point = get_a(line);
|
||||||
return va.squaredNorm();
|
return va.squaredNorm();
|
||||||
} else if (t >= 1.0) {
|
} else if (t >= l2) {
|
||||||
// beyond the 'b' end of the segment
|
// beyond the 'b' end of the segment
|
||||||
*nearest_point = get_b(line);
|
*nearest_point = get_b(line);
|
||||||
return (point - get_b(line)).template cast<double>().squaredNorm();
|
return (point - get_b(line)).template cast<double>().squaredNorm();
|
||||||
}
|
}
|
||||||
|
|
||||||
*nearest_point = (get_a(line).template cast<double>() + t * v).template cast<Scalar<L>>();
|
const VecType w = ((t / l2) * v).eval();
|
||||||
return (t * v - va).squaredNorm();
|
*nearest_point = (get_a(line).template cast<double>() + w).template cast<Scalar<L>>();
|
||||||
|
return (w - va).squaredNorm();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Distance to the closest point of line.
|
// Distance to the closest point of line.
|
||||||
|
@ -106,7 +106,7 @@ bool MultiPoint::remove_duplicate_points()
|
|||||||
Points MultiPoint::douglas_peucker(const Points &pts, const double tolerance)
|
Points MultiPoint::douglas_peucker(const Points &pts, const double tolerance)
|
||||||
{
|
{
|
||||||
Points result_pts;
|
Points result_pts;
|
||||||
double tolerance_sq = tolerance * tolerance;
|
auto tolerance_sq = int64_t(sqr(tolerance));
|
||||||
if (! pts.empty()) {
|
if (! pts.empty()) {
|
||||||
const Point *anchor = &pts.front();
|
const Point *anchor = &pts.front();
|
||||||
size_t anchor_idx = 0;
|
size_t anchor_idx = 0;
|
||||||
@ -120,16 +120,42 @@ Points MultiPoint::douglas_peucker(const Points &pts, const double tolerance)
|
|||||||
dpStack.reserve(pts.size());
|
dpStack.reserve(pts.size());
|
||||||
dpStack.emplace_back(floater_idx);
|
dpStack.emplace_back(floater_idx);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
double max_dist_sq = 0.0;
|
int64_t max_dist_sq = 0;
|
||||||
size_t furthest_idx = anchor_idx;
|
size_t furthest_idx = anchor_idx;
|
||||||
// find point furthest from line seg created by (anchor, floater) and note it
|
// find point furthest from line seg created by (anchor, floater) and note it
|
||||||
|
{
|
||||||
|
const Point a = *anchor;
|
||||||
|
const Point f = *floater;
|
||||||
|
const Vec2i64 v = (f - a).cast<int64_t>();
|
||||||
|
if (const int64_t l2 = v.squaredNorm(); l2 == 0) {
|
||||||
|
for (size_t i = anchor_idx + 1; i < floater_idx; ++ i)
|
||||||
|
if (int64_t dist_sq = (pts[i] - a).cast<int64_t>().squaredNorm(); dist_sq > max_dist_sq) {
|
||||||
|
max_dist_sq = dist_sq;
|
||||||
|
furthest_idx = i;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const double dl2 = double(l2);
|
||||||
|
const Vec2d dv = v.cast<double>();
|
||||||
for (size_t i = anchor_idx + 1; i < floater_idx; ++ i) {
|
for (size_t i = anchor_idx + 1; i < floater_idx; ++ i) {
|
||||||
double dist_sq = Line::distance_to_squared(pts[i], *anchor, *floater);
|
const Point p = pts[i];
|
||||||
|
const Vec2i64 va = (p - a).template cast<int64_t>();
|
||||||
|
const int64_t t = va.dot(v);
|
||||||
|
int64_t dist_sq;
|
||||||
|
if (t <= 0) {
|
||||||
|
dist_sq = va.squaredNorm();
|
||||||
|
} else if (t >= l2) {
|
||||||
|
dist_sq = (p - f).cast<int64_t>().squaredNorm();
|
||||||
|
} else {
|
||||||
|
const Vec2i64 w = ((double(t) / dl2) * dv).cast<int64_t>();
|
||||||
|
dist_sq = (w - va).squaredNorm();
|
||||||
|
}
|
||||||
if (dist_sq > max_dist_sq) {
|
if (dist_sq > max_dist_sq) {
|
||||||
max_dist_sq = dist_sq;
|
max_dist_sq = dist_sq;
|
||||||
furthest_idx = i;
|
furthest_idx = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
// remove point if less than tolerance
|
// remove point if less than tolerance
|
||||||
if (max_dist_sq <= tolerance_sq) {
|
if (max_dist_sq <= tolerance_sq) {
|
||||||
result_pts.emplace_back(*floater);
|
result_pts.emplace_back(*floater);
|
||||||
|
@ -34,6 +34,8 @@ using namespace std::literals;
|
|||||||
// had to use a define beacuse the macro processing inside macro BOOST_LOG_TRIVIAL()
|
// had to use a define beacuse the macro processing inside macro BOOST_LOG_TRIVIAL()
|
||||||
#define error_level_not_in_cache error
|
#define error_level_not_in_cache error
|
||||||
|
|
||||||
|
static constexpr const bool polygons_strictly_simple = false;
|
||||||
|
|
||||||
TreeSupportMeshGroupSettings::TreeSupportMeshGroupSettings(const PrintObject &print_object)
|
TreeSupportMeshGroupSettings::TreeSupportMeshGroupSettings(const PrintObject &print_object)
|
||||||
{
|
{
|
||||||
const PrintConfig &print_config = print_object.print()->config();
|
const PrintConfig &print_config = print_object.print()->config();
|
||||||
@ -175,7 +177,7 @@ TreeModelVolumes::TreeModelVolumes(
|
|||||||
tbb::parallel_for(tbb::blocked_range<size_t>(num_raft_layers, num_layers, std::min<size_t>(1, std::max<size_t>(16, num_layers / (8 * tbb::this_task_arena::max_concurrency())))),
|
tbb::parallel_for(tbb::blocked_range<size_t>(num_raft_layers, num_layers, std::min<size_t>(1, std::max<size_t>(16, num_layers / (8 * tbb::this_task_arena::max_concurrency())))),
|
||||||
[&](const tbb::blocked_range<size_t> &range) {
|
[&](const tbb::blocked_range<size_t> &range) {
|
||||||
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx)
|
for (size_t layer_idx = range.begin(); layer_idx < range.end(); ++ layer_idx)
|
||||||
outlines[layer_idx] = to_polygons(expolygons_simplify(print_object.get_layer(layer_idx - num_raft_layers)->lslices, mesh_settings.resolution));
|
outlines[layer_idx] = polygons_simplify(to_polygons(print_object.get_layer(layer_idx - num_raft_layers)->lslices), mesh_settings.resolution, polygons_strictly_simple);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -424,7 +426,7 @@ const Polygons& TreeModelVolumes::getPlaceableAreas(const coord_t orig_radius, L
|
|||||||
return (*result).get();
|
return (*result).get();
|
||||||
if (m_precalculated) {
|
if (m_precalculated) {
|
||||||
BOOST_LOG_TRIVIAL(error_level_not_in_cache) << "Had to calculate Placeable Areas at radius " << radius << " and layer " << layer_idx << ", but precalculate was called. Performance may suffer!";
|
BOOST_LOG_TRIVIAL(error_level_not_in_cache) << "Had to calculate Placeable Areas at radius " << radius << " and layer " << layer_idx << ", but precalculate was called. Performance may suffer!";
|
||||||
tree_supports_show_error("Not precalculated Placeable areas requested."sv, false);
|
tree_supports_show_error(format("Not precalculated Placeable areas requested, radius %1%, layer %2%", radius, layer_idx), false);
|
||||||
}
|
}
|
||||||
if (orig_radius == 0)
|
if (orig_radius == 0)
|
||||||
// Placable areas for radius 0 are calculated in the general collision code.
|
// Placable areas for radius 0 are calculated in the general collision code.
|
||||||
@ -585,7 +587,7 @@ void TreeModelVolumes::calculateCollision(const coord_t radius, const LayerIndex
|
|||||||
if (processing_last_mesh) {
|
if (processing_last_mesh) {
|
||||||
if (! dst.empty())
|
if (! dst.empty())
|
||||||
collisions = union_(collisions, dst);
|
collisions = union_(collisions, dst);
|
||||||
dst = polygons_simplify(collisions, min_resolution);
|
dst = polygons_simplify(collisions, min_resolution, polygons_strictly_simple);
|
||||||
} else
|
} else
|
||||||
append(dst, std::move(collisions));
|
append(dst, std::move(collisions));
|
||||||
throw_on_cancel();
|
throw_on_cancel();
|
||||||
@ -595,21 +597,24 @@ void TreeModelVolumes::calculateCollision(const coord_t radius, const LayerIndex
|
|||||||
// 3) Optionally calculate placables.
|
// 3) Optionally calculate placables.
|
||||||
if (calculate_placable) {
|
if (calculate_placable) {
|
||||||
// Now calculate the placable areas.
|
// Now calculate the placable areas.
|
||||||
tbb::parallel_for(tbb::blocked_range<LayerIndex>(std::max(data.idx_begin, 1), data.idx_end),
|
tbb::parallel_for(tbb::blocked_range<LayerIndex>(std::max(z_distance_bottom_layers + 1, data.idx_begin), data.idx_end),
|
||||||
[&collision_areas_offsetted, &anti_overhang = m_anti_overhang, processing_last_mesh,
|
[&collision_areas_offsetted, &outlines, &anti_overhang = m_anti_overhang, processing_last_mesh,
|
||||||
min_resolution = m_min_resolution, &data_placeable, &throw_on_cancel]
|
min_resolution = m_min_resolution, z_distance_bottom_layers, xy_distance, &data_placeable, &throw_on_cancel]
|
||||||
(const tbb::blocked_range<LayerIndex>& range) {
|
(const tbb::blocked_range<LayerIndex>& range) {
|
||||||
for (LayerIndex layer_idx = range.begin(); layer_idx != range.end(); ++ layer_idx) {
|
for (LayerIndex layer_idx = range.begin(); layer_idx != range.end(); ++ layer_idx) {
|
||||||
LayerIndex layer_idx_below = layer_idx - 1;
|
LayerIndex layer_idx_below = layer_idx - z_distance_bottom_layers - 1;
|
||||||
assert(layer_idx_below >= 0);
|
assert(layer_idx_below >= 0);
|
||||||
const Polygons ¤t = collision_areas_offsetted[layer_idx];
|
const Polygons ¤t = collision_areas_offsetted[layer_idx];
|
||||||
const Polygons &below = collision_areas_offsetted[layer_idx_below];
|
const Polygons &below = outlines[layer_idx_below];
|
||||||
Polygons placable = diff(below, layer_idx_below < int(anti_overhang.size()) ? union_(current, anti_overhang[layer_idx_below]) : current);
|
Polygons placable = diff(
|
||||||
|
// Inflate the surface to sit on by the separation distance to increase chance of a support being placed on a sloped surface.
|
||||||
|
offset(below, xy_distance),
|
||||||
|
layer_idx_below < int(anti_overhang.size()) ? union_(current, anti_overhang[layer_idx_below]) : current);
|
||||||
auto &dst = data_placeable[layer_idx];
|
auto &dst = data_placeable[layer_idx];
|
||||||
if (processing_last_mesh) {
|
if (processing_last_mesh) {
|
||||||
if (! dst.empty())
|
if (! dst.empty())
|
||||||
placable = union_(placable, dst);
|
placable = union_(placable, dst);
|
||||||
dst = polygons_simplify(placable, min_resolution);
|
dst = polygons_simplify(placable, min_resolution, polygons_strictly_simple);
|
||||||
} else
|
} else
|
||||||
append(dst, placable);
|
append(dst, placable);
|
||||||
throw_on_cancel();
|
throw_on_cancel();
|
||||||
@ -657,7 +662,7 @@ void TreeModelVolumes::calculateCollisionHolefree(const std::vector<RadiusLayerP
|
|||||||
data.emplace_back(RadiusLayerPair(radius, layer_idx), polygons_simplify(
|
data.emplace_back(RadiusLayerPair(radius, layer_idx), polygons_simplify(
|
||||||
offset(union_ex(this->getCollision(m_increase_until_radius, layer_idx, false)),
|
offset(union_ex(this->getCollision(m_increase_until_radius, layer_idx, false)),
|
||||||
5 - increase_radius_ceil, ClipperLib::jtRound, m_min_resolution),
|
5 - increase_radius_ceil, ClipperLib::jtRound, m_min_resolution),
|
||||||
m_min_resolution));
|
m_min_resolution, polygons_strictly_simple));
|
||||||
throw_on_cancel();
|
throw_on_cancel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -744,7 +749,7 @@ void TreeModelVolumes::calculateAvoidance(const std::vector<RadiusLayerPair> &ke
|
|||||||
ClipperLib::jtRound, m_min_resolution));
|
ClipperLib::jtRound, m_min_resolution));
|
||||||
if (task.to_model)
|
if (task.to_model)
|
||||||
latest_avoidance = diff(latest_avoidance, getPlaceableAreas(task.radius, layer_idx, throw_on_cancel));
|
latest_avoidance = diff(latest_avoidance, getPlaceableAreas(task.radius, layer_idx, throw_on_cancel));
|
||||||
latest_avoidance = polygons_simplify(latest_avoidance, m_min_resolution);
|
latest_avoidance = polygons_simplify(latest_avoidance, m_min_resolution, polygons_strictly_simple);
|
||||||
data.emplace_back(RadiusLayerPair{task.radius, layer_idx}, latest_avoidance);
|
data.emplace_back(RadiusLayerPair{task.radius, layer_idx}, latest_avoidance);
|
||||||
throw_on_cancel();
|
throw_on_cancel();
|
||||||
}
|
}
|
||||||
@ -865,12 +870,12 @@ void TreeModelVolumes::calculateWallRestrictions(const std::vector<RadiusLayerPa
|
|||||||
data[layer_idx - min_layer_bottom] = polygons_simplify(
|
data[layer_idx - min_layer_bottom] = polygons_simplify(
|
||||||
// radius contains m_current_min_xy_dist_delta already if required
|
// radius contains m_current_min_xy_dist_delta already if required
|
||||||
intersection(getCollision(0, layer_idx, false), getCollision(radius, layer_idx - 1, true)),
|
intersection(getCollision(0, layer_idx, false), getCollision(radius, layer_idx - 1, true)),
|
||||||
m_min_resolution);
|
m_min_resolution, polygons_strictly_simple);
|
||||||
if (! data_min.empty())
|
if (! data_min.empty())
|
||||||
data_min[layer_idx - min_layer_bottom] =
|
data_min[layer_idx - min_layer_bottom] =
|
||||||
polygons_simplify(
|
polygons_simplify(
|
||||||
intersection(getCollision(0, layer_idx, true), getCollision(radius, layer_idx - 1, true)),
|
intersection(getCollision(0, layer_idx, true), getCollision(radius, layer_idx - 1, true)),
|
||||||
m_min_resolution);
|
m_min_resolution, polygons_strictly_simple);
|
||||||
throw_on_cancel();
|
throw_on_cancel();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -215,6 +215,7 @@ public:
|
|||||||
void clear() {
|
void clear() {
|
||||||
this->clear_all_but_object_collision();
|
this->clear_all_but_object_collision();
|
||||||
m_collision_cache.clear();
|
m_collision_cache.clear();
|
||||||
|
m_placeable_areas_cache.clear();
|
||||||
}
|
}
|
||||||
void clear_all_but_object_collision() {
|
void clear_all_but_object_collision() {
|
||||||
//m_collision_cache.clear_all_but_radius0();
|
//m_collision_cache.clear_all_but_radius0();
|
||||||
@ -223,7 +224,7 @@ public:
|
|||||||
m_avoidance_cache_slow.clear();
|
m_avoidance_cache_slow.clear();
|
||||||
m_avoidance_cache_to_model.clear();
|
m_avoidance_cache_to_model.clear();
|
||||||
m_avoidance_cache_to_model_slow.clear();
|
m_avoidance_cache_to_model_slow.clear();
|
||||||
m_placeable_areas_cache.clear();
|
m_placeable_areas_cache.clear_all_but_radius0();
|
||||||
m_avoidance_cache_holefree.clear();
|
m_avoidance_cache_holefree.clear();
|
||||||
m_avoidance_cache_holefree_to_model.clear();
|
m_avoidance_cache_holefree_to_model.clear();
|
||||||
m_wall_restrictions_cache.clear();
|
m_wall_restrictions_cache.clear();
|
||||||
|
@ -59,6 +59,8 @@ namespace Slic3r
|
|||||||
namespace FFFTreeSupport
|
namespace FFFTreeSupport
|
||||||
{
|
{
|
||||||
|
|
||||||
|
static constexpr const bool polygons_strictly_simple = false;
|
||||||
|
|
||||||
TreeSupportSettings::TreeSupportSettings(const TreeSupportMeshGroupSettings& mesh_group_settings, const SlicingParameters &slicing_params)
|
TreeSupportSettings::TreeSupportSettings(const TreeSupportMeshGroupSettings& mesh_group_settings, const SlicingParameters &slicing_params)
|
||||||
: angle(mesh_group_settings.support_tree_angle),
|
: angle(mesh_group_settings.support_tree_angle),
|
||||||
angle_slow(mesh_group_settings.support_tree_angle_slow),
|
angle_slow(mesh_group_settings.support_tree_angle_slow),
|
||||||
@ -297,7 +299,7 @@ static bool inline g_showed_critical_error = false;
|
|||||||
static bool inline g_showed_performance_warning = false;
|
static bool inline g_showed_performance_warning = false;
|
||||||
void tree_supports_show_error(std::string_view message, bool critical)
|
void tree_supports_show_error(std::string_view message, bool critical)
|
||||||
{ // todo Remove! ONLY FOR PUBLIC BETA!!
|
{ // todo Remove! ONLY FOR PUBLIC BETA!!
|
||||||
|
// printf("Error: %s, critical: %d\n", message.data(), int(critical));
|
||||||
#ifdef TREE_SUPPORT_SHOW_ERRORS_WIN32
|
#ifdef TREE_SUPPORT_SHOW_ERRORS_WIN32
|
||||||
static bool showed_critical = false;
|
static bool showed_critical = false;
|
||||||
static bool showed_performance = false;
|
static bool showed_performance = false;
|
||||||
@ -925,13 +927,13 @@ static std::optional<std::pair<Point, size_t>> polyline_sample_next_point_at_dis
|
|||||||
ret = diff(offset(ret, step_size, ClipperLib::jtRound, scaled<float>(0.01)), collision_trimmed());
|
ret = diff(offset(ret, step_size, ClipperLib::jtRound, scaled<float>(0.01)), collision_trimmed());
|
||||||
// ensure that if many offsets are done the performance does not suffer extremely by the new vertices of jtRound.
|
// ensure that if many offsets are done the performance does not suffer extremely by the new vertices of jtRound.
|
||||||
if (i % 10 == 7)
|
if (i % 10 == 7)
|
||||||
ret = polygons_simplify(ret, scaled<double>(0.015));
|
ret = polygons_simplify(ret, scaled<double>(0.015), polygons_strictly_simple);
|
||||||
}
|
}
|
||||||
// offset the remainder
|
// offset the remainder
|
||||||
float last_offset = distance - steps * step_size;
|
float last_offset = distance - steps * step_size;
|
||||||
if (last_offset > SCALED_EPSILON)
|
if (last_offset > SCALED_EPSILON)
|
||||||
ret = offset(ret, distance - steps * step_size, ClipperLib::jtRound, scaled<float>(0.01));
|
ret = offset(ret, distance - steps * step_size, ClipperLib::jtRound, scaled<float>(0.01));
|
||||||
ret = polygons_simplify(ret, scaled<double>(0.015));
|
ret = polygons_simplify(ret, scaled<double>(0.015), polygons_strictly_simple);
|
||||||
|
|
||||||
if (do_final_difference)
|
if (do_final_difference)
|
||||||
ret = diff(ret, collision_trimmed());
|
ret = diff(ret, collision_trimmed());
|
||||||
@ -1797,7 +1799,7 @@ static Point move_inside_if_outside(const Polygons &polygons, Point from, int di
|
|||||||
}
|
}
|
||||||
if (settings.no_error && settings.move)
|
if (settings.no_error && settings.move)
|
||||||
// as ClipperLib::jtRound has to be used for offsets this simplify is VERY important for performance.
|
// as ClipperLib::jtRound has to be used for offsets this simplify is VERY important for performance.
|
||||||
polygons_simplify(increased, scaled<float>(0.025));
|
polygons_simplify(increased, scaled<float>(0.025), polygons_strictly_simple);
|
||||||
} else
|
} else
|
||||||
// if no movement is done the areas keep parent area as no move == offset(0)
|
// if no movement is done the areas keep parent area as no move == offset(0)
|
||||||
increased = parent.influence_area;
|
increased = parent.influence_area;
|
||||||
@ -1821,6 +1823,7 @@ static Point move_inside_if_outside(const Polygons &polygons, Point from, int di
|
|||||||
BOOST_LOG_TRIVIAL(debug) << "Corrected taint leading to a wrong non gracious value on layer " << layer_idx - 1 << " targeting " <<
|
BOOST_LOG_TRIVIAL(debug) << "Corrected taint leading to a wrong non gracious value on layer " << layer_idx - 1 << " targeting " <<
|
||||||
current_elem.target_height << " with radius " << radius;
|
current_elem.target_height << " with radius " << radius;
|
||||||
} else
|
} else
|
||||||
|
// Cannot route to gracious areas. Push the tree away from object and route it down anyways.
|
||||||
to_model_data = safe_union(diff_clipped(increased, volumes.getCollision(radius, layer_idx - 1, settings.use_min_distance)));
|
to_model_data = safe_union(diff_clipped(increased, volumes.getCollision(radius, layer_idx - 1, settings.use_min_distance)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1966,7 +1969,7 @@ static void increase_areas_one_layer(
|
|||||||
{
|
{
|
||||||
using AvoidanceType = TreeModelVolumes::AvoidanceType;
|
using AvoidanceType = TreeModelVolumes::AvoidanceType;
|
||||||
|
|
||||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, merging_areas.size()),
|
tbb::parallel_for(tbb::blocked_range<size_t>(0, merging_areas.size(), 1),
|
||||||
[&](const tbb::blocked_range<size_t> &range) {
|
[&](const tbb::blocked_range<size_t> &range) {
|
||||||
for (size_t merging_area_idx = range.begin(); merging_area_idx < range.end(); ++ merging_area_idx) {
|
for (size_t merging_area_idx = range.begin(); merging_area_idx < range.end(); ++ merging_area_idx) {
|
||||||
SupportElementMerging &merging_area = merging_areas[merging_area_idx];
|
SupportElementMerging &merging_area = merging_areas[merging_area_idx];
|
||||||
@ -2155,6 +2158,10 @@ static void increase_areas_one_layer(
|
|||||||
" Distance to top: " << parent.state.distance_to_top << " Elephant foot increases " << parent.state.elephant_foot_increases << " use_min_xy_dist " << parent.state.use_min_xy_dist <<
|
" Distance to top: " << parent.state.distance_to_top << " Elephant foot increases " << parent.state.elephant_foot_increases << " use_min_xy_dist " << parent.state.use_min_xy_dist <<
|
||||||
" to buildplate " << parent.state.to_buildplate << " gracious " << parent.state.to_model_gracious << " safe " << parent.state.can_use_safe_radius << " until move " << parent.state.dont_move_until;
|
" to buildplate " << parent.state.to_buildplate << " gracious " << parent.state.to_model_gracious << " safe " << parent.state.can_use_safe_radius << " until move " << parent.state.dont_move_until;
|
||||||
tree_supports_show_error("Potentially lost branch!"sv, true);
|
tree_supports_show_error("Potentially lost branch!"sv, true);
|
||||||
|
#ifdef TREE_SUPPORTS_TRACK_LOST
|
||||||
|
if (result)
|
||||||
|
result->lost = true;
|
||||||
|
#endif // TREE_SUPPORTS_TRACK_LOST
|
||||||
} else
|
} else
|
||||||
result = increase_single_area(volumes, config, settings, layer_idx, parent,
|
result = increase_single_area(volumes, config, settings, layer_idx, parent,
|
||||||
settings.increase_speed == slow_speed ? offset_slow : offset_fast, to_bp_data, to_model_data, inc_wo_collision, 0, mergelayer);
|
settings.increase_speed == slow_speed ? offset_slow : offset_fast, to_bp_data, to_model_data, inc_wo_collision, 0, mergelayer);
|
||||||
@ -2208,10 +2215,14 @@ static void increase_areas_one_layer(
|
|||||||
// But as branches connecting with the model that are to small have to be culled, the bottom most point has to be not set.
|
// But as branches connecting with the model that are to small have to be culled, the bottom most point has to be not set.
|
||||||
// A point can be set on the top most tip layer (maybe more if it should not move for a few layers).
|
// A point can be set on the top most tip layer (maybe more if it should not move for a few layers).
|
||||||
parent.state.result_on_layer_reset();
|
parent.state.result_on_layer_reset();
|
||||||
|
#ifdef TREE_SUPPORTS_TRACK_LOST
|
||||||
|
parent.state.verylost = true;
|
||||||
|
#endif // TREE_SUPPORTS_TRACK_LOST
|
||||||
}
|
}
|
||||||
|
|
||||||
throw_on_cancel();
|
throw_on_cancel();
|
||||||
}
|
}
|
||||||
});
|
}, tbb::simple_partitioner());
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] static SupportElementState merge_support_element_states(
|
[[nodiscard]] static SupportElementState merge_support_element_states(
|
||||||
@ -3325,7 +3336,7 @@ static void finalize_interface_and_support_areas(
|
|||||||
base_layer_polygons = smooth_outward(union_(base_layer_polygons), config.support_line_width); //FIXME was .smooth(50);
|
base_layer_polygons = smooth_outward(union_(base_layer_polygons), config.support_line_width); //FIXME was .smooth(50);
|
||||||
//smooth_outward(closing(std::move(bottom), closing_distance + minimum_island_radius, closing_distance, SUPPORT_SURFACES_OFFSET_PARAMETERS), smoothing_distance) :
|
//smooth_outward(closing(std::move(bottom), closing_distance + minimum_island_radius, closing_distance, SUPPORT_SURFACES_OFFSET_PARAMETERS), smoothing_distance) :
|
||||||
// simplify a bit, to ensure the output does not contain outrageous amounts of vertices. Should not be necessary, just a precaution.
|
// simplify a bit, to ensure the output does not contain outrageous amounts of vertices. Should not be necessary, just a precaution.
|
||||||
base_layer_polygons = polygons_simplify(base_layer_polygons, std::min(scaled<double>(0.03), double(config.resolution)));
|
base_layer_polygons = polygons_simplify(base_layer_polygons, std::min(scaled<double>(0.03), double(config.resolution)), polygons_strictly_simple);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! support_roof_polygons.empty() && ! base_layer_polygons.empty()) {
|
if (! support_roof_polygons.empty() && ! base_layer_polygons.empty()) {
|
||||||
@ -4230,26 +4241,35 @@ static std::vector<Polygons> draw_branches(
|
|||||||
branch.path.emplace_back(&start_element);
|
branch.path.emplace_back(&start_element);
|
||||||
// Traverse each branch until it branches again.
|
// Traverse each branch until it branches again.
|
||||||
SupportElement &first_parent = layer_above[start_element.parents[parent_idx]];
|
SupportElement &first_parent = layer_above[start_element.parents[parent_idx]];
|
||||||
|
assert(! first_parent.state.marked);
|
||||||
assert(branch.path.back()->state.layer_idx + 1 == first_parent.state.layer_idx);
|
assert(branch.path.back()->state.layer_idx + 1 == first_parent.state.layer_idx);
|
||||||
branch.path.emplace_back(&first_parent);
|
branch.path.emplace_back(&first_parent);
|
||||||
if (first_parent.parents.size() < 2)
|
if (first_parent.parents.size() < 2)
|
||||||
first_parent.state.marked = true;
|
first_parent.state.marked = true;
|
||||||
SupportElement *next_branch = nullptr;
|
SupportElement *next_branch = nullptr;
|
||||||
if (first_parent.parents.size() == 1)
|
if (first_parent.parents.size() == 1) {
|
||||||
for (SupportElement *parent = &first_parent;;) {
|
for (SupportElement *parent = &first_parent;;) {
|
||||||
|
assert(parent->state.marked);
|
||||||
SupportElement &next_parent = move_bounds[parent->state.layer_idx + 1][parent->parents.front()];
|
SupportElement &next_parent = move_bounds[parent->state.layer_idx + 1][parent->parents.front()];
|
||||||
|
assert(! next_parent.state.marked);
|
||||||
assert(branch.path.back()->state.layer_idx + 1 == next_parent.state.layer_idx);
|
assert(branch.path.back()->state.layer_idx + 1 == next_parent.state.layer_idx);
|
||||||
branch.path.emplace_back(&next_parent);
|
branch.path.emplace_back(&next_parent);
|
||||||
if (next_parent.parents.size() > 1) {
|
if (next_parent.parents.size() > 1) {
|
||||||
|
// Branching point was reached.
|
||||||
next_branch = &next_parent;
|
next_branch = &next_parent;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
next_parent.state.marked = true;
|
next_parent.state.marked = true;
|
||||||
if (next_parent.parents.size() == 0)
|
if (next_parent.parents.size() == 0)
|
||||||
|
// Tip is reached.
|
||||||
break;
|
break;
|
||||||
parent = &next_parent;
|
parent = &next_parent;
|
||||||
}
|
}
|
||||||
|
} else if (first_parent.parents.size() > 1)
|
||||||
|
// Branching point was reached.
|
||||||
|
next_branch = &first_parent;
|
||||||
assert(branch.path.size() >= 2);
|
assert(branch.path.size() >= 2);
|
||||||
|
assert(next_branch == nullptr || ! next_branch->state.marked);
|
||||||
branch.has_root = root;
|
branch.has_root = root;
|
||||||
branch.has_tip = ! next_branch;
|
branch.has_tip = ! next_branch;
|
||||||
out.branches.emplace_back(std::move(branch));
|
out.branches.emplace_back(std::move(branch));
|
||||||
@ -4259,19 +4279,43 @@ static std::vector<Polygons> draw_branches(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
for (LayerIndex layer_idx = 0; layer_idx + 1 < LayerIndex(move_bounds.size()); ++ layer_idx)
|
for (LayerIndex layer_idx = 0; layer_idx + 1 < LayerIndex(move_bounds.size()); ++ layer_idx) {
|
||||||
for (SupportElement &start_element : move_bounds[layer_idx])
|
// int ielement;
|
||||||
if (! start_element.state.marked && ! start_element.parents.empty()) {
|
for (SupportElement& start_element : move_bounds[layer_idx]) {
|
||||||
|
if (!start_element.state.marked && !start_element.parents.empty()) {
|
||||||
|
#if 0
|
||||||
|
int found = 0;
|
||||||
|
if (layer_idx > 0) {
|
||||||
|
for (auto& el : move_bounds[layer_idx - 1]) {
|
||||||
|
for (auto iparent : el.parents)
|
||||||
|
if (iparent == ielement)
|
||||||
|
++found;
|
||||||
|
}
|
||||||
|
if (found != 0)
|
||||||
|
printf("Found: %d\n", found);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
trees.push_back({});
|
trees.push_back({});
|
||||||
TreeVisitor::visit_recursive(move_bounds, start_element, trees.back());
|
TreeVisitor::visit_recursive(move_bounds, start_element, trees.back());
|
||||||
assert(! trees.back().branches.empty());
|
assert(!trees.back().branches.empty());
|
||||||
|
//FIXME debugging
|
||||||
|
#if 0
|
||||||
|
if (start_element.state.lost) {
|
||||||
|
}
|
||||||
|
else if (start_element.state.verylost) {
|
||||||
|
} else
|
||||||
|
trees.pop_back();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
// ++ ielement;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const SlicingParameters &slicing_params = print_object.slicing_parameters();
|
const SlicingParameters &slicing_params = print_object.slicing_parameters();
|
||||||
MeshSlicingParams mesh_slicing_params;
|
MeshSlicingParams mesh_slicing_params;
|
||||||
mesh_slicing_params.mode = MeshSlicingParams::SlicingMode::Positive;
|
mesh_slicing_params.mode = MeshSlicingParams::SlicingMode::Positive;
|
||||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, trees.size()),
|
tbb::parallel_for(tbb::blocked_range<size_t>(0, trees.size(), 1),
|
||||||
[&trees, &config, &slicing_params, &move_bounds, &mesh_slicing_params, &throw_on_cancel](const tbb::blocked_range<size_t> &range) {
|
[&trees, &volumes, &config, &slicing_params, &move_bounds, &mesh_slicing_params, &throw_on_cancel](const tbb::blocked_range<size_t> &range) {
|
||||||
indexed_triangle_set partial_mesh;
|
indexed_triangle_set partial_mesh;
|
||||||
std::vector<float> slice_z;
|
std::vector<float> slice_z;
|
||||||
for (size_t tree_id = range.begin(); tree_id < range.end(); ++ tree_id) {
|
for (size_t tree_id = range.begin(); tree_id < range.end(); ++ tree_id) {
|
||||||
@ -4293,9 +4337,64 @@ static std::vector<Polygons> draw_branches(
|
|||||||
slice_z.emplace_back(float(0.5 * (bottom_z + print_z)));
|
slice_z.emplace_back(float(0.5 * (bottom_z + print_z)));
|
||||||
}
|
}
|
||||||
std::vector<Polygons> slices = slice_mesh(partial_mesh, slice_z, mesh_slicing_params, throw_on_cancel);
|
std::vector<Polygons> slices = slice_mesh(partial_mesh, slice_z, mesh_slicing_params, throw_on_cancel);
|
||||||
size_t num_empty = std::find_if(slices.begin(), slices.end(), [](auto &s) { return !s.empty(); }) - slices.begin();
|
//FIXME parallelize?
|
||||||
|
for (LayerIndex i = 0; i < LayerIndex(slices.size()); ++ i)
|
||||||
|
slices[i] = diff_clipped(slices[i], volumes.getCollision(0, layer_begin + i, true)); //FIXME parent_uses_min || draw_area.element->state.use_min_xy_dist);
|
||||||
|
|
||||||
|
size_t num_empty = 0;
|
||||||
|
if (layer_begin > 0 && branch.has_root && ! branch.path.front()->state.to_model_gracious && ! slices.front().empty()) {
|
||||||
|
// Drop down areas that do rest non - gracefully on the model to ensure the branch actually rests on something.
|
||||||
|
struct BottomExtraSlice {
|
||||||
|
Polygons polygons;
|
||||||
|
Polygons supported;
|
||||||
|
double area;
|
||||||
|
double supported_area;
|
||||||
|
};
|
||||||
|
std::vector<BottomExtraSlice> bottom_extra_slices;
|
||||||
|
Polygons rest_support;
|
||||||
|
coord_t bottom_radius = config.getRadius(branch.path.front()->state);
|
||||||
|
// Don't propagate further than 1.5 * bottom radius.
|
||||||
|
//LayerIndex layers_propagate_max = 2 * bottom_radius / config.layer_height;
|
||||||
|
LayerIndex layers_propagate_max = 5 * bottom_radius / config.layer_height;
|
||||||
|
LayerIndex layer_bottommost = std::max(0, layer_begin - layers_propagate_max);
|
||||||
|
// Only propagate until the rest area is smaller than this threshold.
|
||||||
|
double support_area_stop = 0.2 * M_PI * sqr(double(bottom_radius));
|
||||||
|
// Only propagate until the rest area is smaller than this threshold.
|
||||||
|
double support_area_min = 0.1 * M_PI * sqr(double(config.min_radius));
|
||||||
|
for (LayerIndex layer_idx = layer_begin - 1; layer_idx >= layer_bottommost; -- layer_idx) {
|
||||||
|
rest_support = diff_clipped(rest_support.empty() ? slices.front() : rest_support, volumes.getCollision(0, layer_idx, false));
|
||||||
|
double rest_support_area = area(rest_support);
|
||||||
|
if (rest_support_area < support_area_stop)
|
||||||
|
// Don't propagate a fraction of the tree contact surface.
|
||||||
|
break;
|
||||||
|
// Measure how much the rest_support is actually supported.
|
||||||
|
/*
|
||||||
|
Polygons supported = intersection_clipped(rest_support, volumes.getPlaceableAreas(0, layer_idx, []{}));
|
||||||
|
double supported_area = area(supported);
|
||||||
|
printf("Supported area: %d, %lf\n", layer_idx, supported_area);
|
||||||
|
*/
|
||||||
|
Polygons supported;
|
||||||
|
double supported_area;
|
||||||
|
bottom_extra_slices.push_back({ rest_support, std::move(supported), rest_support_area, supported_area });
|
||||||
|
}
|
||||||
|
// Now remove those bottom slices that are not supported at all.
|
||||||
|
while (! bottom_extra_slices.empty() &&
|
||||||
|
area(intersection_clipped(bottom_extra_slices.back().polygons, volumes.getPlaceableAreas(0, layer_begin - LayerIndex(bottom_extra_slices.size()), [] {}))) < support_area_min)
|
||||||
|
bottom_extra_slices.pop_back();
|
||||||
|
layer_begin -= LayerIndex(bottom_extra_slices.size());
|
||||||
|
slices.insert(slices.begin(), bottom_extra_slices.size(), {});
|
||||||
|
size_t i = 0;
|
||||||
|
for (auto it = bottom_extra_slices.rbegin(); it != bottom_extra_slices.rend(); ++it, ++i)
|
||||||
|
slices[i] = std::move(it->polygons);
|
||||||
|
} else
|
||||||
|
num_empty = std::find_if(slices.begin(), slices.end(), [](auto &s) { return !s.empty(); }) - slices.begin();
|
||||||
|
|
||||||
layer_begin += LayerIndex(num_empty);
|
layer_begin += LayerIndex(num_empty);
|
||||||
for (; slices.back().empty(); -- layer_end);
|
while (! slices.empty() && slices.back().empty()) {
|
||||||
|
slices.pop_back();
|
||||||
|
-- layer_end;
|
||||||
|
}
|
||||||
|
if (layer_begin < layer_end) {
|
||||||
LayerIndex new_begin = tree.first_layer_id == -1 ? layer_begin : std::min(tree.first_layer_id, layer_begin);
|
LayerIndex new_begin = tree.first_layer_id == -1 ? layer_begin : std::min(tree.first_layer_id, layer_begin);
|
||||||
LayerIndex new_end = tree.first_layer_id == -1 ? layer_end : std::max(tree.first_layer_id + LayerIndex(tree.slices.size()), layer_end);
|
LayerIndex new_end = tree.first_layer_id == -1 ? layer_end : std::max(tree.first_layer_id + LayerIndex(tree.slices.size()), layer_end);
|
||||||
size_t new_size = size_t(new_end - new_begin);
|
size_t new_size = size_t(new_end - new_begin);
|
||||||
@ -4322,9 +4421,10 @@ static std::vector<Polygons> draw_branches(
|
|||||||
tree.first_layer_id = new_begin;
|
tree.first_layer_id = new_begin;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
}, tbb::simple_partitioner());
|
||||||
|
|
||||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, trees.size()),
|
tbb::parallel_for(tbb::blocked_range<size_t>(0, trees.size(), 1),
|
||||||
[&trees, &throw_on_cancel](const tbb::blocked_range<size_t> &range) {
|
[&trees, &throw_on_cancel](const tbb::blocked_range<size_t> &range) {
|
||||||
for (size_t tree_id = range.begin(); tree_id < range.end(); ++ tree_id) {
|
for (size_t tree_id = range.begin(); tree_id < range.end(); ++ tree_id) {
|
||||||
Tree &tree = trees[tree_id];
|
Tree &tree = trees[tree_id];
|
||||||
@ -4335,7 +4435,7 @@ static std::vector<Polygons> draw_branches(
|
|||||||
}
|
}
|
||||||
throw_on_cancel();
|
throw_on_cancel();
|
||||||
}
|
}
|
||||||
});
|
}, tbb::simple_partitioner());
|
||||||
|
|
||||||
size_t num_layers = 0;
|
size_t num_layers = 0;
|
||||||
for (Tree &tree : trees)
|
for (Tree &tree : trees)
|
||||||
@ -4356,14 +4456,14 @@ static std::vector<Polygons> draw_branches(
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Polygons> support_layer_storage(move_bounds.size());
|
std::vector<Polygons> support_layer_storage(move_bounds.size());
|
||||||
tbb::parallel_for(tbb::blocked_range<size_t>(0, std::min(move_bounds.size(), slices.size())),
|
tbb::parallel_for(tbb::blocked_range<size_t>(0, std::min(move_bounds.size(), slices.size()), 1),
|
||||||
[&slices, &support_layer_storage, &throw_on_cancel](const tbb::blocked_range<size_t> &range) {
|
[&slices, &support_layer_storage, &throw_on_cancel](const tbb::blocked_range<size_t> &range) {
|
||||||
for (size_t slice_id = range.begin(); slice_id < range.end(); ++ slice_id) {
|
for (size_t slice_id = range.begin(); slice_id < range.end(); ++ slice_id) {
|
||||||
Slice &slice = slices[slice_id];
|
Slice &slice = slices[slice_id];
|
||||||
support_layer_storage[slice_id] = slice.num_branches > 1 ? union_(slice.polygons) : std::move(slice.polygons);
|
support_layer_storage[slice_id] = slice.num_branches > 1 ? union_(slice.polygons) : std::move(slice.polygons);
|
||||||
throw_on_cancel();
|
throw_on_cancel();
|
||||||
}
|
}
|
||||||
});
|
}, tbb::simple_partitioner());
|
||||||
|
|
||||||
//FIXME simplify!
|
//FIXME simplify!
|
||||||
return support_layer_storage;
|
return support_layer_storage;
|
||||||
|
@ -93,6 +93,8 @@ struct AreaIncreaseSettings
|
|||||||
|
|
||||||
struct TreeSupportSettings;
|
struct TreeSupportSettings;
|
||||||
|
|
||||||
|
// #define TREE_SUPPORTS_TRACK_LOST
|
||||||
|
|
||||||
// C++17 does not support in place initializers of bit values, thus a constructor zeroing the bits is provided.
|
// C++17 does not support in place initializers of bit values, thus a constructor zeroing the bits is provided.
|
||||||
struct SupportElementStateBits {
|
struct SupportElementStateBits {
|
||||||
SupportElementStateBits() :
|
SupportElementStateBits() :
|
||||||
@ -102,6 +104,10 @@ struct SupportElementStateBits {
|
|||||||
supports_roof(false),
|
supports_roof(false),
|
||||||
can_use_safe_radius(false),
|
can_use_safe_radius(false),
|
||||||
skip_ovalisation(false),
|
skip_ovalisation(false),
|
||||||
|
#ifdef TREE_SUPPORTS_TRACK_LOST
|
||||||
|
lost(false),
|
||||||
|
verylost(false),
|
||||||
|
#endif // TREE_SUPPORTS_TRACK_LOST
|
||||||
deleted(false),
|
deleted(false),
|
||||||
marked(false)
|
marked(false)
|
||||||
{}
|
{}
|
||||||
@ -136,6 +142,12 @@ struct SupportElementStateBits {
|
|||||||
*/
|
*/
|
||||||
bool skip_ovalisation : 1;
|
bool skip_ovalisation : 1;
|
||||||
|
|
||||||
|
#ifdef TREE_SUPPORTS_TRACK_LOST
|
||||||
|
// Likely a lost branch, debugging information.
|
||||||
|
bool lost : 1;
|
||||||
|
bool verylost : 1;
|
||||||
|
#endif // TREE_SUPPORTS_TRACK_LOST
|
||||||
|
|
||||||
// Not valid anymore, to be deleted.
|
// Not valid anymore, to be deleted.
|
||||||
bool deleted : 1;
|
bool deleted : 1;
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include <deque>
|
#include <deque>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <new>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include <boost/log/trivial.hpp>
|
#include <boost/log/trivial.hpp>
|
||||||
@ -35,6 +36,13 @@
|
|||||||
#include <boost/thread/mutex.hpp>
|
#include <boost/thread/mutex.hpp>
|
||||||
#include <boost/thread/lock_guard.hpp>
|
#include <boost/thread/lock_guard.hpp>
|
||||||
|
|
||||||
|
#if defined(__cpp_lib_hardware_interference_size) && ! defined(__APPLE__)
|
||||||
|
using std::hardware_destructive_interference_size;
|
||||||
|
#else
|
||||||
|
// 64 bytes on x86-64 │ L1_CACHE_BYTES │ L1_CACHE_SHIFT │ __cacheline_aligned │ ...
|
||||||
|
constexpr std::size_t hardware_destructive_interference_size = 64;
|
||||||
|
#endif
|
||||||
|
|
||||||
// #define SLIC3R_DEBUG_SLICE_PROCESSING
|
// #define SLIC3R_DEBUG_SLICE_PROCESSING
|
||||||
|
|
||||||
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
#ifdef SLIC3R_DEBUG_SLICE_PROCESSING
|
||||||
@ -364,7 +372,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
struct CacheLineAlignedMutex
|
struct CacheLineAlignedMutex
|
||||||
{
|
{
|
||||||
alignas(std::hardware_destructive_interference_size) std::mutex mutex;
|
alignas(hardware_destructive_interference_size) std::mutex mutex;
|
||||||
};
|
};
|
||||||
std::array<CacheLineAlignedMutex, 64> m_mutexes;
|
std::array<CacheLineAlignedMutex, 64> m_mutexes;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user