2013-07-18 17:09:07 +00:00
|
|
|
#ifndef slic3r_ExtrusionEntityCollection_hpp_
|
|
|
|
#define slic3r_ExtrusionEntityCollection_hpp_
|
|
|
|
|
2015-12-07 23:39:54 +00:00
|
|
|
#include "libslic3r.h"
|
2020-09-14 14:27:55 +00:00
|
|
|
#include "Exception.hpp"
|
2013-07-18 17:09:07 +00:00
|
|
|
#include "ExtrusionEntity.hpp"
|
|
|
|
|
|
|
|
namespace Slic3r {
|
|
|
|
|
2020-01-10 14:51:35 +00:00
|
|
|
// Remove those items from extrusion_entities, that do not match role.
|
|
|
|
// Do nothing if role is mixed.
|
|
|
|
// Removed elements are NOT being deleted.
|
|
|
|
void filter_by_extrusion_role_in_place(ExtrusionEntitiesPtr &extrusion_entities, ExtrusionRole role);
|
|
|
|
|
|
|
|
// Return new vector of ExtrusionEntities* with only those items from input extrusion_entities, that match role.
|
|
|
|
// Return all extrusion entities if role is mixed.
|
|
|
|
// Returned extrusion entities are shared with the source vector, they are NOT cloned, they are considered to be owned by extrusion_entities.
|
|
|
|
inline ExtrusionEntitiesPtr filter_by_extrusion_role(const ExtrusionEntitiesPtr &extrusion_entities, ExtrusionRole role)
|
|
|
|
{
|
|
|
|
ExtrusionEntitiesPtr out { extrusion_entities };
|
|
|
|
filter_by_extrusion_role_in_place(out, role);
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
2013-07-18 20:29:12 +00:00
|
|
|
class ExtrusionEntityCollection : public ExtrusionEntity
|
2013-07-18 17:09:07 +00:00
|
|
|
{
|
2016-11-03 23:10:35 +00:00
|
|
|
public:
|
2019-09-11 11:25:50 +00:00
|
|
|
ExtrusionEntity* clone() const override;
|
|
|
|
// Create a new object, initialize it with this object using the move semantics.
|
|
|
|
ExtrusionEntity* clone_move() override { return new ExtrusionEntityCollection(std::move(*this)); }
|
|
|
|
|
2015-07-23 13:53:02 +00:00
|
|
|
ExtrusionEntitiesPtr entities; // we own these entities
|
2013-07-18 17:09:07 +00:00
|
|
|
bool no_sort;
|
2019-10-17 17:09:24 +00:00
|
|
|
ExtrusionEntityCollection(): no_sort(false) {}
|
2019-09-26 07:44:38 +00:00
|
|
|
ExtrusionEntityCollection(const ExtrusionEntityCollection &other) : no_sort(other.no_sort) { this->append(other.entities); }
|
|
|
|
ExtrusionEntityCollection(ExtrusionEntityCollection &&other) : entities(std::move(other.entities)), no_sort(other.no_sort) {}
|
2017-01-20 13:39:44 +00:00
|
|
|
explicit ExtrusionEntityCollection(const ExtrusionPaths &paths);
|
2017-01-19 12:37:15 +00:00
|
|
|
ExtrusionEntityCollection& operator=(const ExtrusionEntityCollection &other);
|
2019-10-17 17:09:24 +00:00
|
|
|
ExtrusionEntityCollection& operator=(ExtrusionEntityCollection &&other)
|
2019-09-26 07:44:38 +00:00
|
|
|
{ this->entities = std::move(other.entities); this->no_sort = other.no_sort; return *this; }
|
2016-11-02 09:47:00 +00:00
|
|
|
~ExtrusionEntityCollection() { clear(); }
|
2017-01-20 13:39:44 +00:00
|
|
|
explicit operator ExtrusionPaths() const;
|
2015-07-06 23:17:31 +00:00
|
|
|
|
2020-03-04 11:48:04 +00:00
|
|
|
bool is_collection() const override { return true; }
|
2018-09-17 13:12:13 +00:00
|
|
|
ExtrusionRole role() const override {
|
2017-04-07 15:37:30 +00:00
|
|
|
ExtrusionRole out = erNone;
|
|
|
|
for (const ExtrusionEntity *ee : entities) {
|
|
|
|
ExtrusionRole er = ee->role();
|
|
|
|
out = (out == erNone || out == er) ? er : erMixed;
|
|
|
|
}
|
|
|
|
return out;
|
|
|
|
}
|
2020-03-04 11:48:04 +00:00
|
|
|
bool can_reverse() const override { return !this->no_sort; }
|
2019-10-17 17:09:24 +00:00
|
|
|
bool empty() const { return this->entities.empty(); }
|
2016-11-02 09:47:00 +00:00
|
|
|
void clear();
|
2014-04-24 14:40:10 +00:00
|
|
|
void swap (ExtrusionEntityCollection &c);
|
2019-09-11 11:25:50 +00:00
|
|
|
void append(const ExtrusionEntity &entity) { this->entities.emplace_back(entity.clone()); }
|
|
|
|
void append(ExtrusionEntity &&entity) { this->entities.emplace_back(entity.clone_move()); }
|
|
|
|
void append(const ExtrusionEntitiesPtr &entities) {
|
2017-01-20 13:39:44 +00:00
|
|
|
this->entities.reserve(this->entities.size() + entities.size());
|
2019-09-11 11:25:50 +00:00
|
|
|
for (const ExtrusionEntity *ptr : entities)
|
|
|
|
this->entities.emplace_back(ptr->clone());
|
2017-01-20 13:39:44 +00:00
|
|
|
}
|
|
|
|
void append(ExtrusionEntitiesPtr &&src) {
|
|
|
|
if (entities.empty())
|
|
|
|
entities = std::move(src);
|
|
|
|
else {
|
|
|
|
std::move(std::begin(src), std::end(src), std::back_inserter(entities));
|
|
|
|
src.clear();
|
|
|
|
}
|
|
|
|
}
|
Removed Point::scale(),translate(),coincides_with(),distance_to(),
distance_to_squared(),perp_distance_to(),negative(),vector_to(),
translate(), distance_to() etc,
replaced with the Eigen equivalents.
2018-08-17 12:14:24 +00:00
|
|
|
void append(const ExtrusionPaths &paths) {
|
2017-01-20 13:39:44 +00:00
|
|
|
this->entities.reserve(this->entities.size() + paths.size());
|
Removed Point::scale(),translate(),coincides_with(),distance_to(),
distance_to_squared(),perp_distance_to(),negative(),vector_to(),
translate(), distance_to() etc,
replaced with the Eigen equivalents.
2018-08-17 12:14:24 +00:00
|
|
|
for (const ExtrusionPath &path : paths)
|
|
|
|
this->entities.emplace_back(path.clone());
|
|
|
|
}
|
|
|
|
void append(ExtrusionPaths &&paths) {
|
|
|
|
this->entities.reserve(this->entities.size() + paths.size());
|
|
|
|
for (ExtrusionPath &path : paths)
|
|
|
|
this->entities.emplace_back(new ExtrusionPath(std::move(path)));
|
2017-01-20 13:39:44 +00:00
|
|
|
}
|
2016-03-19 14:33:58 +00:00
|
|
|
void replace(size_t i, const ExtrusionEntity &entity);
|
|
|
|
void remove(size_t i);
|
2020-01-09 09:00:38 +00:00
|
|
|
static ExtrusionEntityCollection chained_path_from(const ExtrusionEntitiesPtr &extrusion_entities, const Point &start_near, ExtrusionRole role = erMixed);
|
|
|
|
ExtrusionEntityCollection chained_path_from(const Point &start_near, ExtrusionRole role = erMixed) const
|
2020-01-10 14:51:35 +00:00
|
|
|
{ return this->no_sort ? *this : chained_path_from(this->entities, start_near, role); }
|
2020-03-04 11:48:04 +00:00
|
|
|
void reverse() override;
|
|
|
|
const Point& first_point() const override { return this->entities.front()->first_point(); }
|
|
|
|
const Point& last_point() const override { return this->entities.back()->last_point(); }
|
2016-11-03 23:10:35 +00:00
|
|
|
// Produce a list of 2D polygons covered by the extruded paths, offsetted by the extrusion width.
|
|
|
|
// Increase the offset by scaled_epsilon to achieve an overlap, so a union will produce no gaps.
|
2018-09-17 13:12:13 +00:00
|
|
|
void polygons_covered_by_width(Polygons &out, const float scaled_epsilon) const override;
|
2016-11-03 23:10:35 +00:00
|
|
|
// Produce a list of 2D polygons covered by the extruded paths, offsetted by the extrusion spacing.
|
|
|
|
// Increase the offset by scaled_epsilon to achieve an overlap, so a union will produce no gaps.
|
|
|
|
// Useful to calculate area of an infill, which has been really filled in by a 100% rectilinear infill.
|
2018-09-17 13:12:13 +00:00
|
|
|
void polygons_covered_by_spacing(Polygons &out, const float scaled_epsilon) const override;
|
2016-11-03 23:10:35 +00:00
|
|
|
Polygons polygons_covered_by_width(const float scaled_epsilon = 0.f) const
|
|
|
|
{ Polygons out; this->polygons_covered_by_width(out, scaled_epsilon); return out; }
|
|
|
|
Polygons polygons_covered_by_spacing(const float scaled_epsilon = 0.f) const
|
|
|
|
{ Polygons out; this->polygons_covered_by_spacing(out, scaled_epsilon); return out; }
|
2015-04-12 18:16:27 +00:00
|
|
|
size_t items_count() const;
|
2019-10-17 17:09:24 +00:00
|
|
|
/// Returns a flattened copy of this ExtrusionEntityCollection. That is, all of the items in its entities vector are not collections.
|
|
|
|
/// You should be iterating over flatten().entities if you are interested in the underlying ExtrusionEntities (and don't care about hierarchy).
|
|
|
|
/// \param preserve_ordering Flag to method that will flatten if and only if the underlying collection is sortable when True (default: False).
|
|
|
|
ExtrusionEntityCollection flatten(bool preserve_ordering = false) const;
|
2020-03-04 11:48:04 +00:00
|
|
|
double min_mm3_per_mm() const override;
|
2018-09-17 13:12:13 +00:00
|
|
|
double total_volume() const override { double volume=0.; for (const auto& ent : entities) volume+=ent->total_volume(); return volume; }
|
2017-05-03 16:28:22 +00:00
|
|
|
|
|
|
|
// Following methods shall never be called on an ExtrusionEntityCollection.
|
2020-03-04 12:06:21 +00:00
|
|
|
Polyline as_polyline() const override {
|
2020-09-14 14:27:55 +00:00
|
|
|
throw Slic3r::RuntimeError("Calling as_polyline() on a ExtrusionEntityCollection");
|
2015-07-23 13:53:02 +00:00
|
|
|
return Polyline();
|
|
|
|
};
|
2018-09-17 13:12:13 +00:00
|
|
|
|
|
|
|
void collect_polylines(Polylines &dst) const override {
|
|
|
|
for (ExtrusionEntity* extrusion_entity : this->entities)
|
|
|
|
extrusion_entity->collect_polylines(dst);
|
|
|
|
}
|
|
|
|
|
2021-02-24 07:48:33 +00:00
|
|
|
void collect_points(Points &dst) const override {
|
|
|
|
for (ExtrusionEntity* extrusion_entity : this->entities)
|
|
|
|
extrusion_entity->collect_points(dst);
|
|
|
|
}
|
|
|
|
|
2018-09-17 13:12:13 +00:00
|
|
|
double length() const override {
|
2020-09-14 14:27:55 +00:00
|
|
|
throw Slic3r::RuntimeError("Calling length() on a ExtrusionEntityCollection");
|
2016-11-03 23:10:35 +00:00
|
|
|
return 0.;
|
|
|
|
}
|
2013-07-18 17:09:07 +00:00
|
|
|
};
|
|
|
|
|
2020-01-10 14:51:35 +00:00
|
|
|
} // namespace Slic3r
|
2013-07-18 17:09:07 +00:00
|
|
|
|
|
|
|
#endif
|