mirror of
https://github.com/QIDITECH/QIDISlicer.git
synced 2026-01-30 23:48:44 +03:00
add FillConcentricinternal update solidinfill
This commit is contained in:
@@ -88,6 +88,8 @@ set(SLIC3R_SOURCES
|
|||||||
Fill/FillBase.hpp
|
Fill/FillBase.hpp
|
||||||
Fill/FillConcentric.cpp
|
Fill/FillConcentric.cpp
|
||||||
Fill/FillConcentric.hpp
|
Fill/FillConcentric.hpp
|
||||||
|
Fill/FillConcentricInternal.cpp
|
||||||
|
Fill/FillConcentricInternal.hpp
|
||||||
Fill/FillEnsuring.cpp
|
Fill/FillEnsuring.cpp
|
||||||
Fill/FillEnsuring.hpp
|
Fill/FillEnsuring.hpp
|
||||||
Fill/FillHoneycomb.cpp
|
Fill/FillHoneycomb.cpp
|
||||||
|
|||||||
@@ -376,6 +376,8 @@ inline void extrusion_entities_append_paths(ExtrusionEntitiesPtr &dst, Polylines
|
|||||||
polylines.clear();
|
polylines.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
inline void extrusion_entities_append_loops(ExtrusionEntitiesPtr &dst, Polygons &&loops, const ExtrusionAttributes &attributes)
|
inline void extrusion_entities_append_loops(ExtrusionEntitiesPtr &dst, Polygons &&loops, const ExtrusionAttributes &attributes)
|
||||||
{
|
{
|
||||||
dst.reserve(dst.size() + loops.size());
|
dst.reserve(dst.size() + loops.size());
|
||||||
|
|||||||
@@ -20,6 +20,8 @@
|
|||||||
//w21
|
//w21
|
||||||
#include "../ShortestPath.hpp"
|
#include "../ShortestPath.hpp"
|
||||||
//w11
|
//w11
|
||||||
|
//w29
|
||||||
|
#include "FillConcentricInternal.hpp"
|
||||||
|
|
||||||
#include "LayerRegion.hpp"
|
#include "LayerRegion.hpp"
|
||||||
|
|
||||||
@@ -125,9 +127,10 @@ struct SurfaceFill {
|
|||||||
//w11
|
//w11
|
||||||
static bool is_narrow_infill_area(const ExPolygon &expolygon)
|
static bool is_narrow_infill_area(const ExPolygon &expolygon)
|
||||||
{
|
{
|
||||||
|
//w29
|
||||||
ExPolygons offsets = offset_ex(expolygon, -scale_(NARROW_INFILL_AREA_THRESHOLD));
|
ExPolygons offsets = offset_ex(expolygon, -scale_(NARROW_INFILL_AREA_THRESHOLD));
|
||||||
ExPolygons offsets_min = offset_ex(expolygon, -scale_(NARROW_INFILL_AREA_THRESHOLD_MIN));
|
//ExPolygons offsets_min = offset_ex(expolygon, -scale_(NARROW_INFILL_AREA_THRESHOLD_MIN));
|
||||||
if (offsets.empty() && !offsets_min.empty())
|
if (offsets.empty() )
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -340,33 +343,38 @@ std::vector<SurfaceFill> group_fills(const Layer &layer)
|
|||||||
// Use ipEnsuring pattern for all internal Solids.
|
// Use ipEnsuring pattern for all internal Solids.
|
||||||
//w11
|
//w11
|
||||||
if (layer.object()->config().detect_narrow_internal_solid_infill) {
|
if (layer.object()->config().detect_narrow_internal_solid_infill) {
|
||||||
for (size_t i = 0; i < surface_fills.size(); i++) {
|
size_t surface_fills_size = surface_fills.size();
|
||||||
|
for (size_t i = 0; i < surface_fills_size; i++) {
|
||||||
if (surface_fills[i].surface.surface_type != stInternalSolid)
|
if (surface_fills[i].surface.surface_type != stInternalSolid)
|
||||||
continue;
|
continue;
|
||||||
|
//w29
|
||||||
size_t expolygons_size = surface_fills[i].expolygons.size();
|
size_t expolygons_size = surface_fills[i].expolygons.size();
|
||||||
std::vector<size_t> narrow_expolygons_index;
|
std::vector<size_t> narrow_expolygons_index;
|
||||||
narrow_expolygons_index.reserve(expolygons_size);
|
narrow_expolygons_index.reserve(expolygons_size);
|
||||||
|
|
||||||
for (size_t j = 0; j < expolygons_size; j++)
|
for (size_t j = 0; j < expolygons_size; j++)
|
||||||
if (is_narrow_infill_area(surface_fills[i].expolygons[j]))
|
if (is_narrow_infill_area(surface_fills[i].expolygons[j]))
|
||||||
narrow_expolygons_index.push_back(j);
|
narrow_expolygons_index.push_back(j);
|
||||||
|
|
||||||
if (narrow_expolygons_index.size() == expolygons_size) {
|
if (narrow_expolygons_index.size() == 0) {
|
||||||
surface_fills[i].params.pattern = ipConcentricInternal;
|
continue;
|
||||||
|
} else if (narrow_expolygons_index.size() == expolygons_size) {
|
||||||
|
surface_fills[i].params.pattern = ipConcentric;
|
||||||
} else {
|
} else {
|
||||||
surface_fills[i].params.pattern = ipEnsuring;
|
params = surface_fills[i].params;
|
||||||
}
|
params.pattern = ipConcentric;
|
||||||
//w21
|
surface_fills.emplace_back(params);
|
||||||
if (narrow_expolygons_index.size() != expolygons_size && narrow_expolygons_index.size() != expolygons_size) {
|
surface_fills.back().region_id = surface_fills[i].region_id;
|
||||||
|
surface_fills.back().surface.surface_type = stInternalSolid;
|
||||||
|
surface_fills.back().surface.thickness = surface_fills[i].surface.thickness;
|
||||||
surface_fills.back().region_id_group = surface_fills[i].region_id_group;
|
surface_fills.back().region_id_group = surface_fills[i].region_id_group;
|
||||||
surface_fills.back().no_overlap_expolygons = surface_fills[i].no_overlap_expolygons;
|
surface_fills.back().no_overlap_expolygons = surface_fills[i].no_overlap_expolygons;
|
||||||
|
for (size_t j = 0; j < narrow_expolygons_index.size(); j++) {
|
||||||
|
surface_fills.back().expolygons.emplace_back(std::move(surface_fills[i].expolygons[narrow_expolygons_index[j]]));
|
||||||
|
}
|
||||||
|
for (int j = narrow_expolygons_index.size() - 1; j >= 0; j--) {
|
||||||
|
surface_fills[i].expolygons.erase(surface_fills[i].expolygons.begin() + narrow_expolygons_index[j]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
for (size_t surface_fill_id = 0; surface_fill_id < surface_fills.size(); ++surface_fill_id)
|
|
||||||
if (SurfaceFill &fill = surface_fills[surface_fill_id]; fill.surface.surface_type == stInternalSolid) {
|
|
||||||
fill.params.pattern = ipEnsuring;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return surface_fills;
|
return surface_fills;
|
||||||
@@ -525,14 +533,19 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
|
|||||||
f->print_config = &this->object()->print()->config();
|
f->print_config = &this->object()->print()->config();
|
||||||
f->print_object_config = &this->object()->config();
|
f->print_object_config = &this->object()->config();
|
||||||
|
|
||||||
if (surface_fill.params.pattern == ipLightning)
|
//w29
|
||||||
dynamic_cast<FillLightning::Filler*>(f.get())->generator = lightning_generator;
|
if (surface_fill.params.pattern == ipConcentricInternal) {
|
||||||
|
FillConcentricInternal *fill_concentric = dynamic_cast<FillConcentricInternal *>(f.get());
|
||||||
if (surface_fill.params.pattern == ipEnsuring) {
|
assert(fill_concentric != nullptr);
|
||||||
auto *fill_ensuring = dynamic_cast<FillEnsuring *>(f.get());
|
fill_concentric->print_config = &this->object()->print()->config();
|
||||||
assert(fill_ensuring != nullptr);
|
fill_concentric->print_object_config = &this->object()->config();
|
||||||
fill_ensuring->print_region_config = &m_regions[surface_fill.region_id]->region().config();
|
} else if (surface_fill.params.pattern == ipConcentric) {
|
||||||
}
|
FillConcentric *fill_concentric = dynamic_cast<FillConcentric *>(f.get());
|
||||||
|
assert(fill_concentric != nullptr);
|
||||||
|
fill_concentric->print_config = &this->object()->print()->config();
|
||||||
|
fill_concentric->print_object_config = &this->object()->config();
|
||||||
|
} else if (surface_fill.params.pattern == ipLightning)
|
||||||
|
dynamic_cast<FillLightning::Filler *>(f.get())->generator = lightning_generator;
|
||||||
|
|
||||||
// calculate flow spacing for infill pattern generation
|
// calculate flow spacing for infill pattern generation
|
||||||
bool using_internal_flow = ! surface_fill.surface.is_solid() && ! surface_fill.params.bridge;
|
bool using_internal_flow = ! surface_fill.surface.is_solid() && ! surface_fill.params.bridge;
|
||||||
@@ -562,38 +575,32 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
|
|||||||
params.anchor_length_max = surface_fill.params.anchor_length_max;
|
params.anchor_length_max = surface_fill.params.anchor_length_max;
|
||||||
params.resolution = resolution;
|
params.resolution = resolution;
|
||||||
//w14
|
//w14
|
||||||
params.use_arachne = (perimeter_generator == PerimeterGeneratorType::Arachne && surface_fill.params.pattern == ipConcentric) || surface_fill.params.pattern == ipEnsuring || surface_fill.params.pattern == ipConcentricInternal;
|
params.use_arachne = (perimeter_generator == PerimeterGeneratorType::Arachne && surface_fill.params.pattern == ipConcentric) || surface_fill.params.pattern == ipEnsuring || surface_fill.params.pattern == ipConcentric;
|
||||||
params.layer_height = layerm.layer()->height;
|
params.layer_height = layerm.layer()->height;
|
||||||
|
//w29
|
||||||
|
params.flow = surface_fill.params.flow;
|
||||||
|
params.extrusion_role = surface_fill.params.extrusion_role;
|
||||||
|
params.using_internal_flow = !surface_fill.surface.is_solid() && !surface_fill.params.bridge;
|
||||||
|
|
||||||
for (ExPolygon &expoly : surface_fill.expolygons) {
|
for (ExPolygon &expoly : surface_fill.expolygons) {
|
||||||
// Spacing is modified by the filler to indicate adjustments. Reset it for each expolygon.
|
// Spacing is modified by the filler to indicate adjustments. Reset it for each expolygon.
|
||||||
f->spacing = surface_fill.params.spacing;
|
f->spacing = surface_fill.params.spacing;
|
||||||
//w21
|
// w21
|
||||||
f->no_overlap_expolygons = intersection_ex(surface_fill.no_overlap_expolygons, ExPolygons() = {expoly}, ApplySafetyOffset::Yes);
|
f->no_overlap_expolygons = intersection_ex(surface_fill.no_overlap_expolygons, ExPolygons() = {expoly}, ApplySafetyOffset::Yes);
|
||||||
surface_fill.surface.expolygon = std::move(expoly);
|
surface_fill.surface.expolygon = std::move(expoly);
|
||||||
Polylines polylines;
|
Polylines polylines;
|
||||||
ThickPolylines thick_polylines;
|
ThickPolylines thick_polylines;
|
||||||
//w14
|
// w14
|
||||||
if (this->object()->config().detect_narrow_internal_solid_infill &&
|
//w29
|
||||||
|
/* if (this->object()->config().detect_narrow_internal_solid_infill &&
|
||||||
(surface_fill.params.pattern == ipConcentricInternal || surface_fill.params.pattern == ipEnsuring)) {
|
(surface_fill.params.pattern == ipConcentricInternal || surface_fill.params.pattern == ipEnsuring)) {
|
||||||
layerm.region().config().infill_overlap.percent ?
|
layerm.region().config().infill_overlap.percent ? f->overlap = layerm.region().config().perimeter_extrusion_width *
|
||||||
f->overlap = layerm.region().config().perimeter_extrusion_width * layerm.region().config().infill_overlap.value / 100 * (-1) :
|
layerm.region().config().infill_overlap.value / 100 * (-1) :
|
||||||
f->overlap = float(layerm.region().config().infill_overlap.value);
|
f->overlap = float(layerm.region().config().infill_overlap.value);
|
||||||
} else
|
} else
|
||||||
f->overlap = 0;
|
f->overlap = 0;*/
|
||||||
|
//w29
|
||||||
try {
|
f->fill_surface_extrusion(&surface_fill.surface, params, polylines, thick_polylines);
|
||||||
if (params.use_arachne) {
|
|
||||||
thick_polylines = f->fill_surface_arachne(&surface_fill.surface, params);
|
|
||||||
//w21
|
|
||||||
//if (f->layer_id % 2 == 0 && surface_fill.params.pattern == ipConcentricInternal)
|
|
||||||
// std::reverse(thick_polylines.begin(), thick_polylines.end());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
polylines = f->fill_surface(&surface_fill.surface, params);
|
|
||||||
}
|
|
||||||
} catch (InfillFailedException &) {
|
|
||||||
}
|
|
||||||
if (!polylines.empty() || !thick_polylines.empty()) {
|
if (!polylines.empty() || !thick_polylines.empty()) {
|
||||||
// calculate actual flow from spacing (which might have been adjusted by the infill
|
// calculate actual flow from spacing (which might have been adjusted by the infill
|
||||||
// pattern generator)
|
// pattern generator)
|
||||||
@@ -617,7 +624,10 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
|
|||||||
for (const ThickPolyline &thick_polyline : thick_polylines) {
|
for (const ThickPolyline &thick_polyline : thick_polylines) {
|
||||||
Flow new_flow = surface_fill.params.flow.with_spacing(float(f->spacing));
|
Flow new_flow = surface_fill.params.flow.with_spacing(float(f->spacing));
|
||||||
|
|
||||||
ExtrusionMultiPath multi_path = PerimeterGenerator::thick_polyline_to_multi_path(thick_polyline, surface_fill.params.extrusion_role, new_flow, scaled<float>(0.05), float(SCALED_EPSILON));
|
ExtrusionMultiPath multi_path = PerimeterGenerator::thick_polyline_to_multi_path(thick_polyline,
|
||||||
|
surface_fill.params.extrusion_role,
|
||||||
|
new_flow, scaled<float>(0.05),
|
||||||
|
float(SCALED_EPSILON));
|
||||||
// Append paths to collection.
|
// Append paths to collection.
|
||||||
if (!multi_path.empty()) {
|
if (!multi_path.empty()) {
|
||||||
if (multi_path.paths.front().first_point() == multi_path.paths.back().last_point())
|
if (multi_path.paths.front().first_point() == multi_path.paths.back().last_point())
|
||||||
@@ -633,12 +643,11 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
|
|||||||
delete eec;
|
delete eec;
|
||||||
thick_polylines.clear();
|
thick_polylines.clear();
|
||||||
} else {
|
} else {
|
||||||
extrusion_entities_append_paths(
|
extrusion_entities_append_paths(eec->entities, std::move(polylines),
|
||||||
eec->entities, std::move(polylines),
|
ExtrusionAttributes{surface_fill.params.extrusion_role,
|
||||||
ExtrusionAttributes{ surface_fill.params.extrusion_role,
|
ExtrusionFlow{flow_mm3_per_mm, float(flow_width),
|
||||||
ExtrusionFlow{ flow_mm3_per_mm, float(flow_width), surface_fill.params.flow.height() }
|
surface_fill.params.flow.height()}});
|
||||||
});
|
// w21
|
||||||
//w21
|
|
||||||
if (surface_fill.params.pattern == ipMonotonicLines && surface_fill.surface.surface_type == stTop) {
|
if (surface_fill.params.pattern == ipMonotonicLines && surface_fill.surface.surface_type == stTop) {
|
||||||
ExPolygons unextruded_areas = diff_ex(f->no_overlap_expolygons, union_ex(eec->polygons_covered_by_spacing(10)));
|
ExPolygons unextruded_areas = diff_ex(f->no_overlap_expolygons, union_ex(eec->polygons_covered_by_spacing(10)));
|
||||||
ExPolygons gapfill_areas = union_ex(unextruded_areas);
|
ExPolygons gapfill_areas = union_ex(unextruded_areas);
|
||||||
@@ -674,7 +683,8 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
|
|||||||
}),
|
}),
|
||||||
polylines.end());
|
polylines.end());
|
||||||
|
|
||||||
variable_width_gap(polylines, ExtrusionRole::GapFill, surface_fill.params.flow, gap_fill.entities,filter_gap_infill_value);
|
variable_width_gap(polylines, ExtrusionRole::GapFill, surface_fill.params.flow, gap_fill.entities,
|
||||||
|
filter_gap_infill_value);
|
||||||
|
|
||||||
eec->append(std::move(gap_fill.entities));
|
eec->append(std::move(gap_fill.entities));
|
||||||
}
|
}
|
||||||
@@ -685,23 +695,26 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
|
|||||||
insert_fills_into_islands(*this, uint32_t(surface_fill.region_id), fill_begin, uint32_t(layerm.fills().size()));
|
insert_fills_into_islands(*this, uint32_t(surface_fill.region_id), fill_begin, uint32_t(layerm.fills().size()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (LayerSlice &lslice : this->lslices_ex)
|
for (LayerSlice &lslice : this->lslices_ex)
|
||||||
for (LayerIsland &island : lslice.islands) {
|
for (LayerIsland &island : lslice.islands) {
|
||||||
if (! island.thin_fills.empty()) {
|
if (!island.thin_fills.empty()) {
|
||||||
// Copy thin fills into fills packed as a collection.
|
// Copy thin fills into fills packed as a collection.
|
||||||
// Fills are always stored as collections, the rest of the pipeline (wipe into infill, G-code generator) relies on it.
|
// Fills are always stored as collections, the rest of the pipeline (wipe into infill, G-code generator) relies on it.
|
||||||
LayerRegion &layerm = *this->get_region(island.perimeters.region());
|
LayerRegion & layerm = *this->get_region(island.perimeters.region());
|
||||||
ExtrusionEntityCollection &collection = *(new ExtrusionEntityCollection());
|
ExtrusionEntityCollection &collection = *(new ExtrusionEntityCollection());
|
||||||
layerm.m_fills.entities.push_back(&collection);
|
layerm.m_fills.entities.push_back(&collection);
|
||||||
collection.entities.reserve(island.thin_fills.size());
|
collection.entities.reserve(island.thin_fills.size());
|
||||||
for (uint32_t fill_id : island.thin_fills)
|
for (uint32_t fill_id : island.thin_fills)
|
||||||
collection.entities.push_back(layerm.thin_fills().entities[fill_id]->clone());
|
collection.entities.push_back(layerm.thin_fills().entities[fill_id]->clone());
|
||||||
island.add_fill_range({ island.perimeters.region(), { uint32_t(layerm.m_fills.entities.size() - 1), uint32_t(layerm.m_fills.entities.size()) } });
|
island.add_fill_range(
|
||||||
|
{island.perimeters.region(), {uint32_t(layerm.m_fills.entities.size() - 1), uint32_t(layerm.m_fills.entities.size())}});
|
||||||
}
|
}
|
||||||
// Sort the fills by region ID.
|
// Sort the fills by region ID.
|
||||||
std::sort(island.fills.begin(), island.fills.end(), [](auto &l, auto &r){ return l.region() < r.region() || (l.region() == r.region() && *l.begin() < *r.begin()); });
|
std::sort(island.fills.begin(), island.fills.end(),
|
||||||
|
[](auto &l, auto &r) { return l.region() < r.region() || (l.region() == r.region() && *l.begin() < *r.begin()); });
|
||||||
// Compress continuous fill ranges of the same region.
|
// Compress continuous fill ranges of the same region.
|
||||||
{
|
{
|
||||||
size_t k = 0;
|
size_t k = 0;
|
||||||
@@ -710,9 +723,9 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
|
|||||||
uint32_t begin = *island.fills[i].begin();
|
uint32_t begin = *island.fills[i].begin();
|
||||||
uint32_t end = *island.fills[i].end();
|
uint32_t end = *island.fills[i].end();
|
||||||
size_t j = i + 1;
|
size_t j = i + 1;
|
||||||
for (; j < island.fills.size() && island.fills[j].region() == region_id && *island.fills[j].begin() == end; ++ j)
|
for (; j < island.fills.size() && island.fills[j].region() == region_id && *island.fills[j].begin() == end; ++j)
|
||||||
end = *island.fills[j].end();
|
end = *island.fills[j].end();
|
||||||
island.fills[k ++] = { region_id, { begin, end } };
|
island.fills[k++] = {region_id, {begin, end}};
|
||||||
i = j;
|
i = j;
|
||||||
}
|
}
|
||||||
island.fills.erase(island.fills.begin() + k, island.fills.end());
|
island.fills.erase(island.fills.begin() + k, island.fills.end());
|
||||||
@@ -722,7 +735,7 @@ void Layer::make_fills(FillAdaptive::Octree* adaptive_fill_octree, FillAdaptive:
|
|||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
for (LayerRegion *layerm : m_regions)
|
for (LayerRegion *layerm : m_regions)
|
||||||
for (const ExtrusionEntity *e : layerm->fills())
|
for (const ExtrusionEntity *e : layerm->fills())
|
||||||
assert(dynamic_cast<const ExtrusionEntityCollection*>(e) != nullptr);
|
assert(dynamic_cast<const ExtrusionEntityCollection *>(e) != nullptr);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
//w21
|
//w21
|
||||||
|
|||||||
@@ -21,6 +21,8 @@
|
|||||||
#include "FillAdaptive.hpp"
|
#include "FillAdaptive.hpp"
|
||||||
#include "FillLightning.hpp"
|
#include "FillLightning.hpp"
|
||||||
#include "FillEnsuring.hpp"
|
#include "FillEnsuring.hpp"
|
||||||
|
//w29
|
||||||
|
#include "FillConcentricInternal.hpp"
|
||||||
|
|
||||||
#include <boost/log/trivial.hpp>
|
#include <boost/log/trivial.hpp>
|
||||||
|
|
||||||
@@ -53,7 +55,8 @@ Fill* Fill::new_from_type(const InfillPattern type)
|
|||||||
case ipLightning: return new FillLightning::Filler();
|
case ipLightning: return new FillLightning::Filler();
|
||||||
case ipEnsuring: return new FillEnsuring();
|
case ipEnsuring: return new FillEnsuring();
|
||||||
//w14
|
//w14
|
||||||
case ipConcentricInternal: return new FillConcentric();
|
//w29
|
||||||
|
case ipConcentricInternal: return new FillConcentricInternal();
|
||||||
default: throw Slic3r::InvalidArgument("unknown type");
|
default: throw Slic3r::InvalidArgument("unknown type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -105,6 +108,156 @@ ThickPolylines Fill::fill_surface_arachne(const Surface *surface, const FillPara
|
|||||||
return thick_polylines_out;
|
return thick_polylines_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//w29
|
||||||
|
void Fill::fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, Polylines &polylines, ThickPolylines &thick_polylines)
|
||||||
|
{
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (params.use_arachne)
|
||||||
|
thick_polylines = this->fill_surface_arachne(surface, params);
|
||||||
|
else
|
||||||
|
polylines = this->fill_surface(surface, params);
|
||||||
|
} catch (InfillFailedException &) {}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Fill::variable_width(const ThickPolylines &polylines, ExtrusionRole role, const Flow &flow, std::vector<ExtrusionEntity *> &out)
|
||||||
|
{
|
||||||
|
const float tolerance = float(scale_(0.05));
|
||||||
|
for (const ThickPolyline &p : polylines) {
|
||||||
|
ExtrusionPaths paths = thick_polyline_to_extrusion_paths_2(p, role, flow, tolerance);
|
||||||
|
if (!paths.empty()) {
|
||||||
|
if (paths.front().first_point() == paths.back().last_point())
|
||||||
|
out.emplace_back(new ExtrusionLoop(std::move(paths)));
|
||||||
|
else {
|
||||||
|
for (ExtrusionPath &path : paths)
|
||||||
|
out.emplace_back(new ExtrusionPath(std::move(path)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ExtrusionPaths Fill::thick_polyline_to_extrusion_paths_2(const ThickPolyline &thick_polyline,
|
||||||
|
ExtrusionRole role,
|
||||||
|
const Flow & flow,
|
||||||
|
const float tolerance)
|
||||||
|
{
|
||||||
|
ExtrusionPaths paths;
|
||||||
|
ExtrusionPath path(role);
|
||||||
|
ThickLines lines = thick_polyline.thicklines();
|
||||||
|
|
||||||
|
size_t start_index = 0;
|
||||||
|
double max_width, min_width;
|
||||||
|
|
||||||
|
for (int i = 0; i < (int) lines.size(); ++i) {
|
||||||
|
const ThickLine &line = lines[i];
|
||||||
|
|
||||||
|
if (i == 0) {
|
||||||
|
max_width = line.a_width;
|
||||||
|
min_width = line.a_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
const coordf_t line_len = line.length();
|
||||||
|
if (line_len < SCALED_EPSILON)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
double thickness_delta = std::max(fabs(max_width - line.b_width), fabs(min_width - line.b_width));
|
||||||
|
if (thickness_delta > tolerance) {
|
||||||
|
if (start_index != i) {
|
||||||
|
path = ExtrusionPath(role);
|
||||||
|
double length = lines[start_index].length();
|
||||||
|
double sum = lines[start_index].length() * 0.5 * (lines[start_index].a_width + lines[start_index].b_width);
|
||||||
|
path.polyline.append(lines[start_index].a);
|
||||||
|
for (int idx = start_index + 1; idx < i; idx++) {
|
||||||
|
length += lines[idx].length();
|
||||||
|
sum += lines[idx].length() * 0.5 * (lines[idx].a_width + lines[idx].b_width);
|
||||||
|
path.polyline.append(lines[idx].a);
|
||||||
|
}
|
||||||
|
path.polyline.append(lines[i].a);
|
||||||
|
if (length > SCALED_EPSILON) {
|
||||||
|
double w = sum / length;
|
||||||
|
Flow new_flow = flow.with_width(unscale<float>(w) + flow.height() * float(1. - 0.25 * PI));
|
||||||
|
|
||||||
|
// path.mm3_per_mm = new_flow.mm3_per_mm();
|
||||||
|
path.set_mm3_per_mm(new_flow.mm3_per_mm());
|
||||||
|
// path.width = new_flow.width();
|
||||||
|
path.set_width(new_flow.width());
|
||||||
|
// path.height = new_flow.height();
|
||||||
|
path.set_height(new_flow.height());
|
||||||
|
paths.emplace_back(std::move(path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
start_index = i;
|
||||||
|
max_width = line.a_width;
|
||||||
|
min_width = line.a_width;
|
||||||
|
thickness_delta = fabs(line.a_width - line.b_width);
|
||||||
|
if (thickness_delta > tolerance) {
|
||||||
|
const unsigned int segments = (unsigned int) ceil(thickness_delta / tolerance);
|
||||||
|
const coordf_t seg_len = line_len / segments;
|
||||||
|
Points pp;
|
||||||
|
std::vector<coordf_t> width;
|
||||||
|
{
|
||||||
|
pp.push_back(line.a);
|
||||||
|
width.push_back(line.a_width);
|
||||||
|
for (size_t j = 1; j < segments; ++j) {
|
||||||
|
pp.push_back(
|
||||||
|
(line.a.cast<double>() + (line.b - line.a).cast<double>().normalized() * (j * seg_len)).cast<coord_t>());
|
||||||
|
|
||||||
|
coordf_t w = line.a_width + (j * seg_len) * (line.b_width - line.a_width) / line_len;
|
||||||
|
width.push_back(w);
|
||||||
|
width.push_back(w);
|
||||||
|
}
|
||||||
|
pp.push_back(line.b);
|
||||||
|
width.push_back(line.b_width);
|
||||||
|
|
||||||
|
assert(pp.size() == segments + 1u);
|
||||||
|
assert(width.size() == segments * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
lines.erase(lines.begin() + i);
|
||||||
|
for (size_t j = 0; j < segments; ++j) {
|
||||||
|
ThickLine new_line(pp[j], pp[j + 1]);
|
||||||
|
new_line.a_width = width[2 * j];
|
||||||
|
new_line.b_width = width[2 * j + 1];
|
||||||
|
lines.insert(lines.begin() + i + j, new_line);
|
||||||
|
}
|
||||||
|
--i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
max_width = std::max(max_width, std::max(line.a_width, line.b_width));
|
||||||
|
min_width = std::min(min_width, std::min(line.a_width, line.b_width));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
size_t final_size = lines.size();
|
||||||
|
if (start_index < final_size) {
|
||||||
|
path = ExtrusionPath(role);
|
||||||
|
double length = lines[start_index].length();
|
||||||
|
double sum = lines[start_index].length() * lines[start_index].a_width;
|
||||||
|
path.polyline.append(lines[start_index].a);
|
||||||
|
for (int idx = start_index + 1; idx < final_size; idx++) {
|
||||||
|
length += lines[idx].length();
|
||||||
|
sum += lines[idx].length() * lines[idx].a_width;
|
||||||
|
path.polyline.append(lines[idx].a);
|
||||||
|
}
|
||||||
|
path.polyline.append(lines[final_size - 1].b);
|
||||||
|
if (length > SCALED_EPSILON) {
|
||||||
|
double w = sum / length;
|
||||||
|
Flow new_flow = flow.with_width(unscale<float>(w) + flow.height() * float(1. - 0.25 * PI));
|
||||||
|
// path.mm3_per_mm = new_flow.mm3_per_mm();
|
||||||
|
path.set_mm3_per_mm(new_flow.mm3_per_mm());
|
||||||
|
// path.width = new_flow.width();
|
||||||
|
path.set_width(new_flow.width());
|
||||||
|
// path.height = new_flow.height();
|
||||||
|
path.set_height(new_flow.height());
|
||||||
|
paths.emplace_back(std::move(path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return paths;
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate a new spacing to fill width with possibly integer number of lines,
|
// Calculate a new spacing to fill width with possibly integer number of lines,
|
||||||
// the first and last line being centered at the interval ends.
|
// the first and last line being centered at the interval ends.
|
||||||
// This function possibly increases the spacing, never decreases,
|
// This function possibly increases the spacing, never decreases,
|
||||||
|
|||||||
@@ -15,6 +15,9 @@
|
|||||||
#include "../Utils.hpp"
|
#include "../Utils.hpp"
|
||||||
#include "../ExPolygon.hpp"
|
#include "../ExPolygon.hpp"
|
||||||
#include "../PrintConfig.hpp"
|
#include "../PrintConfig.hpp"
|
||||||
|
//w29
|
||||||
|
#include "../ExtrusionEntity.hpp"
|
||||||
|
#include "../ExtrusionEntityCollection.hpp"
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
@@ -63,6 +66,11 @@ struct FillParams
|
|||||||
bool use_arachne { false };
|
bool use_arachne { false };
|
||||||
// Layer height for Concentric infill with Arachne.
|
// Layer height for Concentric infill with Arachne.
|
||||||
coordf_t layer_height { 0.f };
|
coordf_t layer_height { 0.f };
|
||||||
|
//w29
|
||||||
|
Flow flow;
|
||||||
|
ExtrusionRole extrusion_role{ExtrusionRole::None};
|
||||||
|
bool using_internal_flow{false};
|
||||||
|
//bool can_reverse{true};
|
||||||
};
|
};
|
||||||
static_assert(IsTriviallyCopyable<FillParams>::value, "FillParams class is not POD (and it should be - see constructor).");
|
static_assert(IsTriviallyCopyable<FillParams>::value, "FillParams class is not POD (and it should be - see constructor).");
|
||||||
|
|
||||||
@@ -116,6 +124,13 @@ public:
|
|||||||
// Perform the fill.
|
// Perform the fill.
|
||||||
virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms);
|
virtual Polylines fill_surface(const Surface *surface, const FillParams ¶ms);
|
||||||
virtual ThickPolylines fill_surface_arachne(const Surface *surface, const FillParams ¶ms);
|
virtual ThickPolylines fill_surface_arachne(const Surface *surface, const FillParams ¶ms);
|
||||||
|
//w29
|
||||||
|
virtual void fill_surface_extrusion(const Surface *surface, const FillParams ¶ms, Polylines &polylines,ThickPolylines &thick_polylines);
|
||||||
|
void variable_width(const ThickPolylines &polylines, ExtrusionRole role, const Flow &flow, std::vector<ExtrusionEntity *> &out);
|
||||||
|
ExtrusionPaths thick_polyline_to_extrusion_paths_2(const ThickPolyline &thick_polyline,
|
||||||
|
ExtrusionRole role,
|
||||||
|
const Flow & flow,
|
||||||
|
const float tolerance);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Fill() :
|
Fill() :
|
||||||
|
|||||||
74
src/libslic3r/Fill/FillConcentricInternal.cpp
Normal file
74
src/libslic3r/Fill/FillConcentricInternal.cpp
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
#include "../ClipperUtils.hpp"
|
||||||
|
#include "../ExPolygon.hpp"
|
||||||
|
#include "../Surface.hpp"
|
||||||
|
#include "Arachne/WallToolPaths.hpp"
|
||||||
|
|
||||||
|
#include "FillConcentricInternal.hpp"
|
||||||
|
|
||||||
|
#include <libslic3r/ShortestPath.hpp>
|
||||||
|
|
||||||
|
namespace Slic3r {
|
||||||
|
|
||||||
|
void FillConcentricInternal::fill_surface_extrusion(const Surface * surface,
|
||||||
|
const FillParams ¶ms,
|
||||||
|
Polylines & polylines,
|
||||||
|
ThickPolylines & thick_polylines_out)
|
||||||
|
{
|
||||||
|
assert(this->print_config != nullptr && this->print_object_config != nullptr);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < this->no_overlap_expolygons.size(); ++i) {
|
||||||
|
ExPolygon &expolygon = this->no_overlap_expolygons[i];
|
||||||
|
Point bbox_size = expolygon.contour.bounding_box().size();
|
||||||
|
coord_t min_spacing = params.flow.scaled_spacing();
|
||||||
|
|
||||||
|
coord_t loops_count = std::max(bbox_size.x(), bbox_size.y()) / min_spacing + 1;
|
||||||
|
Polygons polygons = to_polygons(expolygon);
|
||||||
|
|
||||||
|
Arachne::WallToolPaths wallToolPaths(polygons, min_spacing, min_spacing, loops_count, 0, params.layer_height,
|
||||||
|
*this->print_object_config, *this->print_config);
|
||||||
|
|
||||||
|
std::vector<Arachne::VariableWidthLines> loops = wallToolPaths.getToolPaths();
|
||||||
|
std::vector<const Arachne::ExtrusionLine *> all_extrusions;
|
||||||
|
for (Arachne::VariableWidthLines &loop : loops) {
|
||||||
|
if (loop.empty())
|
||||||
|
continue;
|
||||||
|
for (const Arachne::ExtrusionLine &wall : loop)
|
||||||
|
all_extrusions.emplace_back(&wall);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t firts_poly_idx = thick_polylines_out.size();
|
||||||
|
Point last_pos(0, 0);
|
||||||
|
for (const Arachne::ExtrusionLine *extrusion : all_extrusions) {
|
||||||
|
if (extrusion->empty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ThickPolyline thick_polyline = Arachne::to_thick_polyline(*extrusion);
|
||||||
|
if (extrusion->is_closed && thick_polyline.points.front() == thick_polyline.points.back() &&
|
||||||
|
thick_polyline.width.front() == thick_polyline.width.back()) {
|
||||||
|
thick_polyline.points.pop_back();
|
||||||
|
assert(thick_polyline.points.size() * 2 == thick_polyline.width.size());
|
||||||
|
int nearest_idx = last_pos.nearest_point_index(thick_polyline.points);
|
||||||
|
std::rotate(thick_polyline.points.begin(), thick_polyline.points.begin() + nearest_idx, thick_polyline.points.end());
|
||||||
|
std::rotate(thick_polyline.width.begin(), thick_polyline.width.begin() + 2 * nearest_idx, thick_polyline.width.end());
|
||||||
|
thick_polyline.points.emplace_back(thick_polyline.points.front());
|
||||||
|
}
|
||||||
|
thick_polylines_out.emplace_back(std::move(thick_polyline));
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t j = firts_poly_idx;
|
||||||
|
for (size_t i = firts_poly_idx; i < thick_polylines_out.size(); ++i) {
|
||||||
|
thick_polylines_out[i].clip_end(this->loop_clipping);
|
||||||
|
if (thick_polylines_out[i].is_valid()) {
|
||||||
|
if (j < i)
|
||||||
|
thick_polylines_out[j] = std::move(thick_polylines_out[i]);
|
||||||
|
++j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (j < thick_polylines_out.size())
|
||||||
|
thick_polylines_out.erase(thick_polylines_out.begin() + int(j), thick_polylines_out.end());
|
||||||
|
|
||||||
|
reorder_by_shortest_traverse(thick_polylines_out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Slic3r
|
||||||
165
src/libslic3r/Fill/FillConcentricInternal.hpp
Normal file
165
src/libslic3r/Fill/FillConcentricInternal.hpp
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
#ifndef slic3r_FillConcentricInternal_hpp_
|
||||||
|
#define slic3r_FillConcentricInternal_hpp_
|
||||||
|
|
||||||
|
#include "FillBase.hpp"
|
||||||
|
|
||||||
|
namespace Slic3r {
|
||||||
|
|
||||||
|
class FillConcentricInternal : public Fill
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
~FillConcentricInternal() override = default;
|
||||||
|
void fill_surface_extrusion(const Surface * surface,
|
||||||
|
const FillParams ¶ms,
|
||||||
|
Polylines & polylines,
|
||||||
|
ThickPolylines & thick_polylines) override;
|
||||||
|
void variable_width(const ThickPolylines &polylines, ExtrusionRole role, const Flow &flow, std::vector<ExtrusionEntity *> &out)
|
||||||
|
{
|
||||||
|
const float tolerance = float(scale_(0.05));
|
||||||
|
for (const ThickPolyline &p : polylines) {
|
||||||
|
ExtrusionPaths paths = thick_polyline_to_extrusion_paths_2(p, role, flow, tolerance);
|
||||||
|
// Append paths to collection.
|
||||||
|
if (!paths.empty()) {
|
||||||
|
if (paths.front().first_point() == paths.back().last_point())
|
||||||
|
out.emplace_back(new ExtrusionLoop(std::move(paths)));
|
||||||
|
else {
|
||||||
|
for (ExtrusionPath &path : paths)
|
||||||
|
out.emplace_back(new ExtrusionPath(std::move(path)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ExtrusionPaths thick_polyline_to_extrusion_paths_2(const ThickPolyline &thick_polyline,
|
||||||
|
ExtrusionRole role,
|
||||||
|
const Flow & flow,
|
||||||
|
const float tolerance)
|
||||||
|
{
|
||||||
|
ExtrusionPaths paths;
|
||||||
|
ExtrusionPath path(role);
|
||||||
|
ThickLines lines = thick_polyline.thicklines();
|
||||||
|
|
||||||
|
size_t start_index = 0;
|
||||||
|
double max_width, min_width;
|
||||||
|
|
||||||
|
for (int i = 0; i < (int) lines.size(); ++i) {
|
||||||
|
const ThickLine &line = lines[i];
|
||||||
|
|
||||||
|
if (i == 0) {
|
||||||
|
max_width = line.a_width;
|
||||||
|
min_width = line.a_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
const coordf_t line_len = line.length();
|
||||||
|
if (line_len < SCALED_EPSILON)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
double thickness_delta = std::max(fabs(max_width - line.b_width), fabs(min_width - line.b_width));
|
||||||
|
if (thickness_delta > tolerance) {
|
||||||
|
if (start_index != i) {
|
||||||
|
path = ExtrusionPath(role);
|
||||||
|
double length = lines[start_index].length();
|
||||||
|
double sum = lines[start_index].length() * 0.5 * (lines[start_index].a_width + lines[start_index].b_width);
|
||||||
|
path.polyline.append(lines[start_index].a);
|
||||||
|
for (int idx = start_index + 1; idx < i; idx++) {
|
||||||
|
length += lines[idx].length();
|
||||||
|
sum += lines[idx].length() * 0.5 * (lines[idx].a_width + lines[idx].b_width);
|
||||||
|
path.polyline.append(lines[idx].a);
|
||||||
|
}
|
||||||
|
path.polyline.append(lines[i].a);
|
||||||
|
if (length > SCALED_EPSILON) {
|
||||||
|
double w = sum / length;
|
||||||
|
Flow new_flow = flow.with_width(unscale<float>(w) + flow.height() * float(1. - 0.25 * PI));
|
||||||
|
|
||||||
|
// path.mm3_per_mm = new_flow.mm3_per_mm();
|
||||||
|
path.set_mm3_per_mm(new_flow.mm3_per_mm());
|
||||||
|
// path.width = new_flow.width();
|
||||||
|
path.set_width(new_flow.width());
|
||||||
|
// path.height = new_flow.height();
|
||||||
|
path.set_height(new_flow.height());
|
||||||
|
paths.emplace_back(std::move(path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
start_index = i;
|
||||||
|
max_width = line.a_width;
|
||||||
|
min_width = line.a_width;
|
||||||
|
thickness_delta = fabs(line.a_width - line.b_width);
|
||||||
|
if (thickness_delta > tolerance) {
|
||||||
|
const unsigned int segments = (unsigned int) ceil(thickness_delta / tolerance);
|
||||||
|
const coordf_t seg_len = line_len / segments;
|
||||||
|
Points pp;
|
||||||
|
std::vector<coordf_t> width;
|
||||||
|
{
|
||||||
|
pp.push_back(line.a);
|
||||||
|
width.push_back(line.a_width);
|
||||||
|
for (size_t j = 1; j < segments; ++j) {
|
||||||
|
pp.push_back(
|
||||||
|
(line.a.cast<double>() + (line.b - line.a).cast<double>().normalized() * (j * seg_len)).cast<coord_t>());
|
||||||
|
|
||||||
|
coordf_t w = line.a_width + (j * seg_len) * (line.b_width - line.a_width) / line_len;
|
||||||
|
width.push_back(w);
|
||||||
|
width.push_back(w);
|
||||||
|
}
|
||||||
|
pp.push_back(line.b);
|
||||||
|
width.push_back(line.b_width);
|
||||||
|
|
||||||
|
assert(pp.size() == segments + 1u);
|
||||||
|
assert(width.size() == segments * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
lines.erase(lines.begin() + i);
|
||||||
|
for (size_t j = 0; j < segments; ++j) {
|
||||||
|
ThickLine new_line(pp[j], pp[j + 1]);
|
||||||
|
new_line.a_width = width[2 * j];
|
||||||
|
new_line.b_width = width[2 * j + 1];
|
||||||
|
lines.insert(lines.begin() + i + j, new_line);
|
||||||
|
}
|
||||||
|
--i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
max_width = std::max(max_width, std::max(line.a_width, line.b_width));
|
||||||
|
min_width = std::min(min_width, std::min(line.a_width, line.b_width));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
size_t final_size = lines.size();
|
||||||
|
if (start_index < final_size) {
|
||||||
|
path = ExtrusionPath(role);
|
||||||
|
double length = lines[start_index].length();
|
||||||
|
double sum = lines[start_index].length() * lines[start_index].a_width;
|
||||||
|
path.polyline.append(lines[start_index].a);
|
||||||
|
for (int idx = start_index + 1; idx < final_size; idx++) {
|
||||||
|
length += lines[idx].length();
|
||||||
|
sum += lines[idx].length() * lines[idx].a_width;
|
||||||
|
path.polyline.append(lines[idx].a);
|
||||||
|
}
|
||||||
|
path.polyline.append(lines[final_size - 1].b);
|
||||||
|
if (length > SCALED_EPSILON) {
|
||||||
|
double w = sum / length;
|
||||||
|
Flow new_flow = flow.with_width(unscale<float>(w) + flow.height() * float(1. - 0.25 * PI));
|
||||||
|
// path.mm3_per_mm = new_flow.mm3_per_mm();
|
||||||
|
path.set_mm3_per_mm(new_flow.mm3_per_mm());
|
||||||
|
// path.width = new_flow.width();
|
||||||
|
path.set_width(new_flow.width());
|
||||||
|
// path.height = new_flow.height();
|
||||||
|
path.set_height(new_flow.height());
|
||||||
|
paths.emplace_back(std::move(path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return paths;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Fill *clone() const override { return new FillConcentricInternal(*this); };
|
||||||
|
bool no_sort() const override { return true; }
|
||||||
|
|
||||||
|
const PrintConfig * print_config = nullptr;
|
||||||
|
const PrintObjectConfig *print_object_config = nullptr;
|
||||||
|
|
||||||
|
friend class Layer;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Slic3r
|
||||||
|
|
||||||
|
#endif // slic3r_FillConcentricInternal_hpp_
|
||||||
@@ -81,6 +81,52 @@ Points collect_duplicates(Points pts /* Copy */)
|
|||||||
}
|
}
|
||||||
return duplicits;
|
return duplicits;
|
||||||
}
|
}
|
||||||
|
//w29
|
||||||
|
int Point::nearest_point_index(const Points &points) const
|
||||||
|
{
|
||||||
|
PointConstPtrs p;
|
||||||
|
p.reserve(points.size());
|
||||||
|
for (Points::const_iterator it = points.begin(); it != points.end(); ++it)
|
||||||
|
p.push_back(&*it);
|
||||||
|
return this->nearest_point_index(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Point::nearest_point_index(const PointConstPtrs &points) const
|
||||||
|
{
|
||||||
|
int idx = -1;
|
||||||
|
double distance = -1; // double because long is limited to 2147483647 on some platforms and it's not enough
|
||||||
|
|
||||||
|
for (PointConstPtrs::const_iterator it = points.begin(); it != points.end(); ++it) {
|
||||||
|
/* If the X distance of the candidate is > than the total distance of the
|
||||||
|
best previous candidate, we know we don't want it */
|
||||||
|
double d = sqr<double>((*this) (0) - (*it)->x());
|
||||||
|
if (distance != -1 && d > distance)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* If the Y distance of the candidate is > than the total distance of the
|
||||||
|
best previous candidate, we know we don't want it */
|
||||||
|
d += sqr<double>((*this) (1) - (*it)->y());
|
||||||
|
if (distance != -1 && d > distance)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
idx = it - points.begin();
|
||||||
|
distance = d;
|
||||||
|
|
||||||
|
if (distance < EPSILON)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Point::nearest_point_index(const PointPtrs &points) const
|
||||||
|
{
|
||||||
|
PointConstPtrs p;
|
||||||
|
p.reserve(points.size());
|
||||||
|
for (PointPtrs::const_iterator it = points.begin(); it != points.end(); ++it)
|
||||||
|
p.push_back(*it);
|
||||||
|
return this->nearest_point_index(p);
|
||||||
|
}
|
||||||
|
|
||||||
template<bool IncludeBoundary>
|
template<bool IncludeBoundary>
|
||||||
BoundingBox get_extents(const Points &pts)
|
BoundingBox get_extents(const Points &pts)
|
||||||
|
|||||||
@@ -212,6 +212,10 @@ public:
|
|||||||
Point rotated(double angle) const { Point res(*this); res.rotate(angle); return res; }
|
Point rotated(double angle) const { Point res(*this); res.rotate(angle); return res; }
|
||||||
Point rotated(double cos_a, double sin_a) const { Point res(*this); res.rotate(cos_a, sin_a); return res; }
|
Point rotated(double cos_a, double sin_a) const { Point res(*this); res.rotate(cos_a, sin_a); return res; }
|
||||||
Point rotated(double angle, const Point ¢er) const { Point res(*this); res.rotate(angle, center); return res; }
|
Point rotated(double angle, const Point ¢er) const { Point res(*this); res.rotate(angle, center); return res; }
|
||||||
|
//w29
|
||||||
|
int nearest_point_index(const Points &points) const;
|
||||||
|
int nearest_point_index(const PointConstPtrs &points) const;
|
||||||
|
int nearest_point_index(const PointPtrs &points) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool operator<(const Point &l, const Point &r)
|
inline bool operator<(const Point &l, const Point &r)
|
||||||
|
|||||||
@@ -42,6 +42,22 @@ void chain_and_reorder_extrusion_paths(std::vect
|
|||||||
|
|
||||||
Polylines chain_polylines(Polylines &&src, const Point *start_near = nullptr);
|
Polylines chain_polylines(Polylines &&src, const Point *start_near = nullptr);
|
||||||
inline Polylines chain_polylines(const Polylines& src, const Point* start_near = nullptr) { Polylines tmp(src); return chain_polylines(std::move(tmp), start_near); }
|
inline Polylines chain_polylines(const Polylines& src, const Point* start_near = nullptr) { Polylines tmp(src); return chain_polylines(std::move(tmp), start_near); }
|
||||||
|
//w29
|
||||||
|
template<typename T> inline void reorder_by_shortest_traverse(std::vector<T> &polylines_out)
|
||||||
|
{
|
||||||
|
Points start_point;
|
||||||
|
start_point.reserve(polylines_out.size());
|
||||||
|
for (const T contour : polylines_out)
|
||||||
|
start_point.push_back(contour.points.front());
|
||||||
|
|
||||||
|
std::vector<Points::size_type> order = chain_points(start_point);
|
||||||
|
|
||||||
|
std::vector<T> Temp = polylines_out;
|
||||||
|
polylines_out.erase(polylines_out.begin(), polylines_out.end());
|
||||||
|
|
||||||
|
for (size_t i : order)
|
||||||
|
polylines_out.emplace_back(std::move(Temp[i]));
|
||||||
|
}
|
||||||
|
|
||||||
ClipperLib::PolyNodes chain_clipper_polynodes(const Points &points, const ClipperLib::PolyNodes &items);
|
ClipperLib::PolyNodes chain_clipper_polynodes(const Points &points, const ClipperLib::PolyNodes &items);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user