mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-10-22 00:01:09 -06:00
Merge branch 'master' into sender
Conflicts: Build.PL
This commit is contained in:
commit
3ae6f2630e
106 changed files with 2262 additions and 994 deletions
|
@ -1677,6 +1677,8 @@ src/libslic3r/GCodeWriter.cpp
|
|||
src/libslic3r/GCodeWriter.hpp
|
||||
src/libslic3r/Geometry.cpp
|
||||
src/libslic3r/Geometry.hpp
|
||||
src/libslic3r/GUI/3DScene.cpp
|
||||
src/libslic3r/GUI/3DScene.hpp
|
||||
src/libslic3r/Layer.cpp
|
||||
src/libslic3r/Layer.hpp
|
||||
src/libslic3r/LayerRegion.cpp
|
||||
|
@ -1765,6 +1767,7 @@ xsp/Flow.xsp
|
|||
xsp/GCodeSender.xsp
|
||||
xsp/GCodeWriter.xsp
|
||||
xsp/Geometry.xsp
|
||||
xsp/GUI_3DScene.xsp
|
||||
xsp/Layer.xsp
|
||||
xsp/Line.xsp
|
||||
xsp/Model.xsp
|
||||
|
|
|
@ -23,6 +23,11 @@ use overload
|
|||
'@{}' => sub { [ $_[0]->x, $_[0]->y, $_[0]->z ] }, #,
|
||||
'fallback' => 1;
|
||||
|
||||
sub pp {
|
||||
my ($self) = @_;
|
||||
return [ @$self ];
|
||||
}
|
||||
|
||||
package Slic3r::Pointf;
|
||||
use overload
|
||||
'@{}' => sub { $_[0]->arrayref },
|
||||
|
@ -33,6 +38,11 @@ use overload
|
|||
'@{}' => sub { [ $_[0]->x, $_[0]->y, $_[0]->z ] }, #,
|
||||
'fallback' => 1;
|
||||
|
||||
sub pp {
|
||||
my ($self) = @_;
|
||||
return [ @$self ];
|
||||
}
|
||||
|
||||
package Slic3r::ExPolygon;
|
||||
use overload
|
||||
'@{}' => sub { $_[0]->arrayref },
|
||||
|
@ -186,6 +196,9 @@ sub new {
|
|||
return $self;
|
||||
}
|
||||
|
||||
package Slic3r::GUI::_3DScene::GLVertexArray;
|
||||
sub CLONE_SKIP { 1 }
|
||||
|
||||
package main;
|
||||
for my $class (qw(
|
||||
Slic3r::BridgeDetector
|
||||
|
|
|
@ -89,8 +89,7 @@ BridgeDetector::detect_angle()
|
|||
{
|
||||
Polygons pp = this->expolygon;
|
||||
for (Polygons::const_iterator p = pp.begin(); p != pp.end(); ++p) {
|
||||
Lines lines;
|
||||
p->lines(&lines);
|
||||
Lines lines = p->lines();
|
||||
for (Lines::const_iterator line = lines.begin(); line != lines.end(); ++line)
|
||||
angles.push_back(line->direction());
|
||||
}
|
||||
|
|
|
@ -295,18 +295,21 @@ class ConfigOptionPoints : public ConfigOption, public ConfigOptionVector<Pointf
|
|||
};
|
||||
|
||||
bool deserialize(std::string str) {
|
||||
std::vector<Pointf> values;
|
||||
this->values.clear();
|
||||
std::istringstream is(str);
|
||||
std::string point_str;
|
||||
while (std::getline(is, point_str, ',')) {
|
||||
Pointf point;
|
||||
std::istringstream iss(point_str);
|
||||
iss >> point.x;
|
||||
iss.ignore(std::numeric_limits<std::streamsize>::max(), 'x');
|
||||
iss >> point.y;
|
||||
values.push_back(point);
|
||||
std::string coord_str;
|
||||
if (std::getline(iss, coord_str, 'x')) {
|
||||
std::istringstream(coord_str) >> point.x;
|
||||
if (std::getline(iss, coord_str, 'x')) {
|
||||
std::istringstream(coord_str) >> point.y;
|
||||
}
|
||||
}
|
||||
this->values.push_back(point);
|
||||
}
|
||||
this->values = values;
|
||||
return true;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -129,14 +129,20 @@ ExPolygon::simplify_p(double tolerance) const
|
|||
pp.reserve(this->holes.size() + 1);
|
||||
|
||||
// contour
|
||||
Polygon p = this->contour;
|
||||
p.points = MultiPoint::_douglas_peucker(p.points, tolerance);
|
||||
pp.push_back(p);
|
||||
{
|
||||
Polygon p = this->contour;
|
||||
p.points.push_back(p.points.front());
|
||||
p.points = MultiPoint::_douglas_peucker(p.points, tolerance);
|
||||
p.points.pop_back();
|
||||
pp.push_back(p);
|
||||
}
|
||||
|
||||
// holes
|
||||
for (Polygons::const_iterator it = this->holes.begin(); it != this->holes.end(); ++it) {
|
||||
p = *it;
|
||||
Polygon p = *it;
|
||||
p.points.push_back(p.points.front());
|
||||
p.points = MultiPoint::_douglas_peucker(p.points, tolerance);
|
||||
p.points.pop_back();
|
||||
pp.push_back(p);
|
||||
}
|
||||
simplify_polygons(pp, &pp);
|
||||
|
@ -167,9 +173,11 @@ ExPolygon::medial_axis(double max_width, double min_width, Polylines* polylines)
|
|||
Slic3r::Geometry::MedialAxis ma(max_width, min_width);
|
||||
|
||||
// populate list of segments for the Voronoi diagram
|
||||
this->contour.lines(&ma.lines);
|
||||
for (Polygons::const_iterator hole = this->holes.begin(); hole != this->holes.end(); ++hole)
|
||||
hole->lines(&ma.lines);
|
||||
ma.lines = this->contour.lines();
|
||||
for (Polygons::const_iterator hole = this->holes.begin(); hole != this->holes.end(); ++hole) {
|
||||
Lines lines = hole->lines();
|
||||
ma.lines.insert(ma.lines.end(), lines.begin(), lines.end());
|
||||
}
|
||||
|
||||
// compute the Voronoi diagram
|
||||
ma.build(polylines);
|
||||
|
@ -384,10 +392,11 @@ ExPolygon::triangulate_p2t(Polygons* polygons) const
|
|||
Lines
|
||||
ExPolygon::lines() const
|
||||
{
|
||||
Lines lines;
|
||||
this->contour.lines(&lines);
|
||||
for (Polygons::const_iterator h = this->holes.begin(); h != this->holes.end(); ++h)
|
||||
h->lines(&lines);
|
||||
Lines lines = this->contour.lines();
|
||||
for (Polygons::const_iterator h = this->holes.begin(); h != this->holes.end(); ++h) {
|
||||
Lines hole_lines = h->lines();
|
||||
lines.insert(lines.end(), hole_lines.begin(), hole_lines.end());
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
|
||||
|
|
|
@ -92,13 +92,13 @@ ExPolygonCollection::simplify(double tolerance)
|
|||
this->expolygons = expp;
|
||||
}
|
||||
|
||||
void
|
||||
ExPolygonCollection::convex_hull(Polygon* hull) const
|
||||
Polygon
|
||||
ExPolygonCollection::convex_hull() const
|
||||
{
|
||||
Points pp;
|
||||
for (ExPolygons::const_iterator it = this->expolygons.begin(); it != this->expolygons.end(); ++it)
|
||||
pp.insert(pp.end(), it->contour.points.begin(), it->contour.points.end());
|
||||
Slic3r::Geometry::convex_hull(pp, hull);
|
||||
return Slic3r::Geometry::convex_hull(pp);
|
||||
}
|
||||
|
||||
Lines
|
||||
|
|
|
@ -28,7 +28,7 @@ class ExPolygonCollection
|
|||
template <class T> bool contains(const T &item) const;
|
||||
bool contains_b(const Point &point) const;
|
||||
void simplify(double tolerance);
|
||||
void convex_hull(Polygon* hull) const;
|
||||
Polygon convex_hull() const;
|
||||
Lines lines() const;
|
||||
};
|
||||
|
||||
|
|
|
@ -164,11 +164,12 @@ ExtrusionPath::gcode(Extruder* extruder, double e, double F,
|
|||
return stream.str();
|
||||
}
|
||||
|
||||
ExtrusionLoop::operator Polygon() const
|
||||
Polygons
|
||||
ExtrusionPath::grow() const
|
||||
{
|
||||
Polygon polygon;
|
||||
this->polygon(&polygon);
|
||||
return polygon;
|
||||
Polygons pp;
|
||||
offset(this->polyline, &pp, +this->width/2);
|
||||
return pp;
|
||||
}
|
||||
|
||||
ExtrusionLoop*
|
||||
|
@ -180,8 +181,7 @@ ExtrusionLoop::clone() const
|
|||
bool
|
||||
ExtrusionLoop::make_clockwise()
|
||||
{
|
||||
Polygon polygon = *this;
|
||||
bool was_ccw = polygon.is_counter_clockwise();
|
||||
bool was_ccw = this->polygon().is_counter_clockwise();
|
||||
if (was_ccw) this->reverse();
|
||||
return was_ccw;
|
||||
}
|
||||
|
@ -189,8 +189,7 @@ ExtrusionLoop::make_clockwise()
|
|||
bool
|
||||
ExtrusionLoop::make_counter_clockwise()
|
||||
{
|
||||
Polygon polygon = *this;
|
||||
bool was_cw = polygon.is_clockwise();
|
||||
bool was_cw = this->polygon().is_clockwise();
|
||||
if (was_cw) this->reverse();
|
||||
return was_cw;
|
||||
}
|
||||
|
@ -215,13 +214,15 @@ ExtrusionLoop::last_point() const
|
|||
return this->paths.back().polyline.points.back(); // which coincides with first_point(), by the way
|
||||
}
|
||||
|
||||
void
|
||||
ExtrusionLoop::polygon(Polygon* polygon) const
|
||||
Polygon
|
||||
ExtrusionLoop::polygon() const
|
||||
{
|
||||
Polygon polygon;
|
||||
for (ExtrusionPaths::const_iterator path = this->paths.begin(); path != this->paths.end(); ++path) {
|
||||
// for each polyline, append all points except the last one (because it coincides with the first one of the next polyline)
|
||||
polygon->points.insert(polygon->points.end(), path->polyline.points.begin(), path->polyline.points.end()-1);
|
||||
polygon.points.insert(polygon.points.end(), path->polyline.points.begin(), path->polyline.points.end()-1);
|
||||
}
|
||||
return polygon;
|
||||
}
|
||||
|
||||
double
|
||||
|
@ -363,6 +364,17 @@ ExtrusionLoop::is_solid_infill() const
|
|||
|| this->paths.front().role == erTopSolidInfill;
|
||||
}
|
||||
|
||||
Polygons
|
||||
ExtrusionLoop::grow() const
|
||||
{
|
||||
Polygons pp;
|
||||
for (ExtrusionPaths::const_iterator path = this->paths.begin(); path != this->paths.end(); ++path) {
|
||||
Polygons path_pp = path->grow();
|
||||
pp.insert(pp.end(), path_pp.begin(), path_pp.end());
|
||||
}
|
||||
return pp;
|
||||
}
|
||||
|
||||
#ifdef SLIC3RXS
|
||||
REGISTER_CLASS(ExtrusionLoop, "ExtrusionLoop");
|
||||
#endif
|
||||
|
|
|
@ -43,6 +43,7 @@ class ExtrusionEntity
|
|||
virtual void reverse() = 0;
|
||||
virtual Point first_point() const = 0;
|
||||
virtual Point last_point() const = 0;
|
||||
virtual Polygons grow() const = 0;
|
||||
};
|
||||
|
||||
typedef std::vector<ExtrusionEntity*> ExtrusionEntitiesPtr;
|
||||
|
@ -73,6 +74,7 @@ class ExtrusionPath : public ExtrusionEntity
|
|||
std::string gcode(Extruder* extruder, double e, double F,
|
||||
double xofs, double yofs, std::string extrusion_axis,
|
||||
std::string gcode_line_suffix) const;
|
||||
Polygons grow() const;
|
||||
|
||||
private:
|
||||
void _inflate_collection(const Polylines &polylines, ExtrusionEntityCollection* collection) const;
|
||||
|
@ -90,14 +92,13 @@ class ExtrusionLoop : public ExtrusionEntity
|
|||
bool is_loop() const {
|
||||
return true;
|
||||
};
|
||||
operator Polygon() const;
|
||||
ExtrusionLoop* clone() const;
|
||||
bool make_clockwise();
|
||||
bool make_counter_clockwise();
|
||||
void reverse();
|
||||
Point first_point() const;
|
||||
Point last_point() const;
|
||||
void polygon(Polygon* polygon) const;
|
||||
Polygon polygon() const;
|
||||
double length() const;
|
||||
bool split_at_vertex(const Point &point);
|
||||
void split_at(const Point &point);
|
||||
|
@ -106,6 +107,7 @@ class ExtrusionLoop : public ExtrusionEntity
|
|||
bool is_perimeter() const;
|
||||
bool is_infill() const;
|
||||
bool is_solid_infill() const;
|
||||
Polygons grow() const;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -110,6 +110,17 @@ ExtrusionEntityCollection::chained_path_from(Point start_near, ExtrusionEntityCo
|
|||
}
|
||||
}
|
||||
|
||||
Polygons
|
||||
ExtrusionEntityCollection::grow() const
|
||||
{
|
||||
Polygons pp;
|
||||
for (ExtrusionEntitiesPtr::const_iterator it = this->entities.begin(); it != this->entities.end(); ++it) {
|
||||
Polygons entity_pp = (*it)->grow();
|
||||
pp.insert(pp.end(), entity_pp.begin(), entity_pp.end());
|
||||
}
|
||||
return pp;
|
||||
}
|
||||
|
||||
#ifdef SLIC3RXS
|
||||
// there is no ExtrusionLoop::Collection or ExtrusionEntity::Collection
|
||||
REGISTER_CLASS(ExtrusionEntityCollection, "ExtrusionPath::Collection");
|
||||
|
|
|
@ -22,6 +22,7 @@ class ExtrusionEntityCollection : public ExtrusionEntity
|
|||
void reverse();
|
||||
Point first_point() const;
|
||||
Point last_point() const;
|
||||
Polygons grow() const;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ Flow::new_from_spacing(float spacing, float nozzle_diameter, float height, bool
|
|||
if (height <= 0 && !bridge) CONFESS("Invalid flow height supplied to new_from_spacing()");
|
||||
|
||||
float w = Flow::_width_from_spacing(spacing, nozzle_diameter, height, bridge);
|
||||
if (bridge) height = w;
|
||||
return Flow(w, height, nozzle_diameter, bridge);
|
||||
}
|
||||
|
||||
|
|
|
@ -60,16 +60,6 @@ GCodeWriter::preamble()
|
|||
} else {
|
||||
gcode << "M82 ; use absolute distances for extrusion\n";
|
||||
}
|
||||
if (this->config.use_volumetric_e && this->config.start_gcode.value.find("M200") == std::string::npos) {
|
||||
for (std::map<unsigned int,Extruder>::const_iterator it = this->extruders.begin(); it != this->extruders.end(); ++it) {
|
||||
unsigned int extruder_id = it->first;
|
||||
gcode << "M200 D" << E_NUM(this->config.filament_diameter.get_at(extruder_id));
|
||||
if (this->multiple_extruders || extruder_id != 0) {
|
||||
gcode << " T" << extruder_id;
|
||||
}
|
||||
gcode << " ; set filament diameter\n";
|
||||
}
|
||||
}
|
||||
gcode << this->reset_e(true);
|
||||
}
|
||||
|
||||
|
|
248
xs/src/libslic3r/GUI/3DScene.cpp
Normal file
248
xs/src/libslic3r/GUI/3DScene.cpp
Normal file
|
@ -0,0 +1,248 @@
|
|||
#include "3DScene.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
// caller is responsible for supplying NO lines with zero length
|
||||
void
|
||||
_3DScene::_extrusionentity_to_verts_do(const Lines &lines, const std::vector<double> &widths,
|
||||
const std::vector<double> &heights, bool closed, double top_z, const Point ©,
|
||||
GLVertexArray* qverts, GLVertexArray* tverts)
|
||||
{
|
||||
/* It looks like it's faster without reserving capacity...
|
||||
// each segment has 4 quads, thus 16 vertices; + 2 caps
|
||||
qverts->reserve_more(3 * 4 * (4 * lines.size() + 2));
|
||||
|
||||
// two triangles for each corner
|
||||
tverts->reserve_more(3 * 3 * 2 * (lines.size() + 1));
|
||||
*/
|
||||
|
||||
Line prev_line;
|
||||
Pointf prev_b1, prev_b2;
|
||||
Vectorf3 prev_xy_left_normal, prev_xy_right_normal;
|
||||
|
||||
// loop once more in case of closed loops
|
||||
bool first_done = false;
|
||||
for (size_t i = 0; i <= lines.size(); ++i) {
|
||||
if (i == lines.size()) i = 0;
|
||||
|
||||
const Line &line = lines.at(i);
|
||||
if (i == 0 && first_done && !closed) break;
|
||||
|
||||
double len = line.length();
|
||||
double unscaled_len = unscale(len);
|
||||
|
||||
double bottom_z = top_z - heights.at(i);
|
||||
double middle_z = (top_z + bottom_z) / 2;
|
||||
double dist = widths.at(i)/2; // scaled
|
||||
|
||||
Vectorf v = Vectorf::new_unscale(line.vector());
|
||||
v.scale(1/unscaled_len);
|
||||
|
||||
Pointf a = Pointf::new_unscale(line.a);
|
||||
Pointf b = Pointf::new_unscale(line.b);
|
||||
Pointf a1 = a;
|
||||
Pointf a2 = a;
|
||||
a1.translate(+dist*v.y, -dist*v.x);
|
||||
a2.translate(-dist*v.y, +dist*v.x);
|
||||
Pointf b1 = b;
|
||||
Pointf b2 = b;
|
||||
b1.translate(+dist*v.y, -dist*v.x);
|
||||
b2.translate(-dist*v.y, +dist*v.x);
|
||||
|
||||
// calculate new XY normals
|
||||
Vector n = line.normal();
|
||||
Vectorf3 xy_right_normal = Vectorf3::new_unscale(n.x, n.y, 0);
|
||||
xy_right_normal.scale(1/unscaled_len);
|
||||
Vectorf3 xy_left_normal = xy_right_normal;
|
||||
xy_left_normal.scale(-1);
|
||||
|
||||
if (first_done) {
|
||||
// if we're making a ccw turn, draw the triangles on the right side, otherwise draw them on the left side
|
||||
double ccw = line.b.ccw(prev_line);
|
||||
if (ccw > EPSILON) {
|
||||
// top-right vertex triangle between previous line and this one
|
||||
{
|
||||
// use the normal going to the right calculated for the previous line
|
||||
tverts->push_norm(prev_xy_right_normal);
|
||||
tverts->push_vert(prev_b1.x, prev_b1.y, middle_z);
|
||||
|
||||
// use the normal going to the right calculated for this line
|
||||
tverts->push_norm(xy_right_normal);
|
||||
tverts->push_vert(a1.x, a1.y, middle_z);
|
||||
|
||||
// normal going upwards
|
||||
tverts->push_norm(0,0,1);
|
||||
tverts->push_vert(a.x, a.y, top_z);
|
||||
}
|
||||
// bottom-right vertex triangle between previous line and this one
|
||||
{
|
||||
// use the normal going to the right calculated for the previous line
|
||||
tverts->push_norm(prev_xy_right_normal);
|
||||
tverts->push_vert(prev_b1.x, prev_b1.y, middle_z);
|
||||
|
||||
// normal going downwards
|
||||
tverts->push_norm(0,0,-1);
|
||||
tverts->push_vert(a.x, a.y, bottom_z);
|
||||
|
||||
// use the normal going to the right calculated for this line
|
||||
tverts->push_norm(xy_right_normal);
|
||||
tverts->push_vert(a1.x, a1.y, middle_z);
|
||||
}
|
||||
} else if (ccw < -EPSILON) {
|
||||
// top-left vertex triangle between previous line and this one
|
||||
{
|
||||
// use the normal going to the left calculated for the previous line
|
||||
tverts->push_norm(prev_xy_left_normal);
|
||||
tverts->push_vert(prev_b2.x, prev_b2.y, middle_z);
|
||||
|
||||
// normal going upwards
|
||||
tverts->push_norm(0,0,1);
|
||||
tverts->push_vert(a.x, a.y, top_z);
|
||||
|
||||
// use the normal going to the right calculated for this line
|
||||
tverts->push_norm(xy_left_normal);
|
||||
tverts->push_vert(a2.x, a2.y, middle_z);
|
||||
}
|
||||
// bottom-left vertex triangle between previous line and this one
|
||||
{
|
||||
// use the normal going to the left calculated for the previous line
|
||||
tverts->push_norm(prev_xy_left_normal);
|
||||
tverts->push_vert(prev_b2.x, prev_b2.y, middle_z);
|
||||
|
||||
// use the normal going to the right calculated for this line
|
||||
tverts->push_norm(xy_left_normal);
|
||||
tverts->push_vert(a2.x, a2.y, middle_z);
|
||||
|
||||
// normal going downwards
|
||||
tverts->push_norm(0,0,-1);
|
||||
tverts->push_vert(a.x, a.y, bottom_z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if this was the extra iteration we were only interested in the triangles
|
||||
if (first_done && i == 0) break;
|
||||
|
||||
prev_line = line;
|
||||
prev_b1 = b1;
|
||||
prev_b2 = b2;
|
||||
prev_xy_right_normal = xy_right_normal;
|
||||
prev_xy_left_normal = xy_left_normal;
|
||||
|
||||
if (!closed) {
|
||||
// terminate open paths with caps
|
||||
if (i == 0) {
|
||||
// normal pointing downwards
|
||||
qverts->push_norm(0,0,-1);
|
||||
qverts->push_vert(a.x, a.y, bottom_z);
|
||||
|
||||
// normal pointing to the right
|
||||
qverts->push_norm(xy_right_normal);
|
||||
qverts->push_vert(a1.x, a1.y, middle_z);
|
||||
|
||||
// normal pointing upwards
|
||||
qverts->push_norm(0,0,1);
|
||||
qverts->push_vert(a.x, a.y, top_z);
|
||||
|
||||
// normal pointing to the left
|
||||
qverts->push_norm(xy_left_normal);
|
||||
qverts->push_vert(a2.x, a2.y, middle_z);
|
||||
}
|
||||
// we don't use 'else' because both cases are true if we have only one line
|
||||
if (i == lines.size()-1) {
|
||||
// normal pointing downwards
|
||||
qverts->push_norm(0,0,-1);
|
||||
qverts->push_vert(b.x, b.y, bottom_z);
|
||||
|
||||
// normal pointing to the left
|
||||
qverts->push_norm(xy_left_normal);
|
||||
qverts->push_vert(b2.x, b2.y, middle_z);
|
||||
|
||||
// normal pointing upwards
|
||||
qverts->push_norm(0,0,1);
|
||||
qverts->push_vert(b.x, b.y, top_z);
|
||||
|
||||
// normal pointing to the right
|
||||
qverts->push_norm(xy_right_normal);
|
||||
qverts->push_vert(b1.x, b1.y, middle_z);
|
||||
}
|
||||
}
|
||||
|
||||
// bottom-right face
|
||||
{
|
||||
// normal going downwards
|
||||
qverts->push_norm(0,0,-1);
|
||||
qverts->push_norm(0,0,-1);
|
||||
qverts->push_vert(a.x, a.y, bottom_z);
|
||||
qverts->push_vert(b.x, b.y, bottom_z);
|
||||
|
||||
qverts->push_norm(xy_right_normal);
|
||||
qverts->push_norm(xy_right_normal);
|
||||
qverts->push_vert(b1.x, b1.y, middle_z);
|
||||
qverts->push_vert(a1.x, a1.y, middle_z);
|
||||
}
|
||||
|
||||
// top-right face
|
||||
{
|
||||
qverts->push_norm(xy_right_normal);
|
||||
qverts->push_norm(xy_right_normal);
|
||||
qverts->push_vert(a1.x, a1.y, middle_z);
|
||||
qverts->push_vert(b1.x, b1.y, middle_z);
|
||||
|
||||
// normal going upwards
|
||||
qverts->push_norm(0,0,1);
|
||||
qverts->push_norm(0,0,1);
|
||||
qverts->push_vert(b.x, b.y, top_z);
|
||||
qverts->push_vert(a.x, a.y, top_z);
|
||||
}
|
||||
|
||||
// top-left face
|
||||
{
|
||||
qverts->push_norm(0,0,1);
|
||||
qverts->push_norm(0,0,1);
|
||||
qverts->push_vert(a.x, a.y, top_z);
|
||||
qverts->push_vert(b.x, b.y, top_z);
|
||||
|
||||
qverts->push_norm(xy_left_normal);
|
||||
qverts->push_norm(xy_left_normal);
|
||||
qverts->push_vert(b2.x, b2.y, middle_z);
|
||||
qverts->push_vert(a2.x, a2.y, middle_z);
|
||||
}
|
||||
|
||||
// bottom-left face
|
||||
{
|
||||
qverts->push_norm(xy_left_normal);
|
||||
qverts->push_norm(xy_left_normal);
|
||||
qverts->push_vert(a2.x, a2.y, middle_z);
|
||||
qverts->push_vert(b2.x, b2.y, middle_z);
|
||||
|
||||
// normal going downwards
|
||||
qverts->push_norm(0,0,-1);
|
||||
qverts->push_norm(0,0,-1);
|
||||
qverts->push_vert(b.x, b.y, bottom_z);
|
||||
qverts->push_vert(a.x, a.y, bottom_z);
|
||||
}
|
||||
|
||||
first_done = true;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
GLVertexArray::load_mesh(const TriangleMesh &mesh)
|
||||
{
|
||||
this->reserve_more(3 * 3 * mesh.facets_count());
|
||||
|
||||
for (int i = 0; i < mesh.stl.stats.number_of_facets; ++i) {
|
||||
stl_facet &facet = mesh.stl.facet_start[i];
|
||||
for (int j = 0; j <= 2; ++j) {
|
||||
this->push_norm(facet.normal.x, facet.normal.y, facet.normal.z);
|
||||
this->push_vert(facet.vertex[j].x, facet.vertex[j].y, facet.vertex[j].z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SLIC3RXS
|
||||
REGISTER_CLASS(GLVertexArray, "GUI::_3DScene::GLVertexArray");
|
||||
#endif
|
||||
|
||||
}
|
56
xs/src/libslic3r/GUI/3DScene.hpp
Normal file
56
xs/src/libslic3r/GUI/3DScene.hpp
Normal file
|
@ -0,0 +1,56 @@
|
|||
#ifndef slic3r_3DScene_hpp_
|
||||
#define slic3r_3DScene_hpp_
|
||||
|
||||
#include <myinit.h>
|
||||
#include "../Point.hpp"
|
||||
#include "../Line.hpp"
|
||||
#include "../TriangleMesh.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
class GLVertexArray {
|
||||
public:
|
||||
std::vector<float> verts, norms;
|
||||
|
||||
void reserve(size_t len) {
|
||||
this->verts.reserve(len);
|
||||
this->norms.reserve(len);
|
||||
};
|
||||
void reserve_more(size_t len) {
|
||||
len += this->verts.size();
|
||||
this->reserve(len);
|
||||
};
|
||||
void push_vert(const Pointf3 &point) {
|
||||
this->verts.push_back(point.x);
|
||||
this->verts.push_back(point.y);
|
||||
this->verts.push_back(point.z);
|
||||
};
|
||||
void push_vert(float x, float y, float z) {
|
||||
this->verts.push_back(x);
|
||||
this->verts.push_back(y);
|
||||
this->verts.push_back(z);
|
||||
};
|
||||
void push_norm(const Pointf3 &point) {
|
||||
this->norms.push_back(point.x);
|
||||
this->norms.push_back(point.y);
|
||||
this->norms.push_back(point.z);
|
||||
};
|
||||
void push_norm(float x, float y, float z) {
|
||||
this->norms.push_back(x);
|
||||
this->norms.push_back(y);
|
||||
this->norms.push_back(z);
|
||||
};
|
||||
void load_mesh(const TriangleMesh &mesh);
|
||||
};
|
||||
|
||||
class _3DScene
|
||||
{
|
||||
public:
|
||||
static void _extrusionentity_to_verts_do(const Lines &lines, const std::vector<double> &widths,
|
||||
const std::vector<double> &heights, bool closed, double top_z, const Point ©,
|
||||
GLVertexArray* qverts, GLVertexArray* tverts);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,4 +1,5 @@
|
|||
#include "Geometry.hpp"
|
||||
#include "ClipperUtils.hpp"
|
||||
#include "ExPolygon.hpp"
|
||||
#include "Line.hpp"
|
||||
#include "PolylineCollection.hpp"
|
||||
|
@ -25,42 +26,45 @@ sort_points (Point a, Point b)
|
|||
}
|
||||
|
||||
/* This implementation is based on Andrew's monotone chain 2D convex hull algorithm */
|
||||
void
|
||||
convex_hull(Points points, Polygon* hull)
|
||||
Polygon
|
||||
convex_hull(Points points)
|
||||
{
|
||||
assert(points.size() >= 3);
|
||||
// sort input points
|
||||
std::sort(points.begin(), points.end(), sort_points);
|
||||
|
||||
int n = points.size(), k = 0;
|
||||
hull->points.resize(2*n);
|
||||
Polygon hull;
|
||||
hull.points.resize(2*n);
|
||||
|
||||
// Build lower hull
|
||||
for (int i = 0; i < n; i++) {
|
||||
while (k >= 2 && points[i].ccw(hull->points[k-2], hull->points[k-1]) <= 0) k--;
|
||||
hull->points[k++] = points[i];
|
||||
while (k >= 2 && points[i].ccw(hull.points[k-2], hull.points[k-1]) <= 0) k--;
|
||||
hull.points[k++] = points[i];
|
||||
}
|
||||
|
||||
// Build upper hull
|
||||
for (int i = n-2, t = k+1; i >= 0; i--) {
|
||||
while (k >= t && points[i].ccw(hull->points[k-2], hull->points[k-1]) <= 0) k--;
|
||||
hull->points[k++] = points[i];
|
||||
while (k >= t && points[i].ccw(hull.points[k-2], hull.points[k-1]) <= 0) k--;
|
||||
hull.points[k++] = points[i];
|
||||
}
|
||||
|
||||
hull->points.resize(k);
|
||||
hull.points.resize(k);
|
||||
|
||||
assert( hull->points.front().coincides_with(hull->points.back()) );
|
||||
hull->points.pop_back();
|
||||
assert( hull.points.front().coincides_with(hull.points.back()) );
|
||||
hull.points.pop_back();
|
||||
|
||||
return hull;
|
||||
}
|
||||
|
||||
void
|
||||
convex_hull(const Polygons &polygons, Polygon* hull)
|
||||
Polygon
|
||||
convex_hull(const Polygons &polygons)
|
||||
{
|
||||
Points pp;
|
||||
for (Polygons::const_iterator p = polygons.begin(); p != polygons.end(); ++p) {
|
||||
pp.insert(pp.end(), p->points.begin(), p->points.end());
|
||||
}
|
||||
convex_hull(pp, hull);
|
||||
return convex_hull(pp);
|
||||
}
|
||||
|
||||
/* accepts an arrayref of points and returns a list of indices
|
||||
|
@ -143,6 +147,20 @@ deg2rad(double angle)
|
|||
return PI * angle / 180.0;
|
||||
}
|
||||
|
||||
void
|
||||
simplify_polygons(const Polygons &polygons, double tolerance, Polygons* retval)
|
||||
{
|
||||
Polygons pp;
|
||||
for (Polygons::const_iterator it = polygons.begin(); it != polygons.end(); ++it) {
|
||||
Polygon p = *it;
|
||||
p.points.push_back(p.points.front());
|
||||
p.points = MultiPoint::_douglas_peucker(p.points, tolerance);
|
||||
p.points.pop_back();
|
||||
pp.push_back(p);
|
||||
}
|
||||
Slic3r::simplify_polygons(pp, retval);
|
||||
}
|
||||
|
||||
Line
|
||||
MedialAxis::edge_to_line(const VD::edge_type &edge) const
|
||||
{
|
||||
|
|
|
@ -11,8 +11,8 @@ using boost::polygon::voronoi_diagram;
|
|||
|
||||
namespace Slic3r { namespace Geometry {
|
||||
|
||||
void convex_hull(Points points, Polygon* hull);
|
||||
void convex_hull(const Polygons &polygons, Polygon* hull);
|
||||
Polygon convex_hull(Points points);
|
||||
Polygon convex_hull(const Polygons &polygons);
|
||||
void chained_path(const Points &points, std::vector<Points::size_type> &retval, Point start_near);
|
||||
void chained_path(const Points &points, std::vector<Points::size_type> &retval);
|
||||
template<class T> void chained_path_items(Points &points, T &items, T &retval);
|
||||
|
@ -21,6 +21,7 @@ template<class T> bool contains(const std::vector<T> &vector, const Point &point
|
|||
double rad2deg(double angle);
|
||||
double rad2deg_dir(double angle);
|
||||
double deg2rad(double angle);
|
||||
void simplify_polygons(const Polygons &polygons, double tolerance, Polygons* retval);
|
||||
|
||||
class MedialAxis {
|
||||
public:
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
namespace Slic3r {
|
||||
|
||||
Layer::Layer(int id, PrintObject *object, coordf_t height, coordf_t print_z,
|
||||
Layer::Layer(size_t id, PrintObject *object, coordf_t height, coordf_t print_z,
|
||||
coordf_t slice_z)
|
||||
: _id(id),
|
||||
_object(object),
|
||||
|
@ -35,12 +35,18 @@ Layer::~Layer()
|
|||
this->clear_regions();
|
||||
}
|
||||
|
||||
int
|
||||
Layer::id()
|
||||
size_t
|
||||
Layer::id() const
|
||||
{
|
||||
return this->_id;
|
||||
}
|
||||
|
||||
void
|
||||
Layer::set_id(size_t id)
|
||||
{
|
||||
this->_id = id;
|
||||
}
|
||||
|
||||
PrintObject*
|
||||
Layer::object()
|
||||
{
|
||||
|
@ -147,7 +153,7 @@ REGISTER_CLASS(Layer, "Layer");
|
|||
#endif
|
||||
|
||||
|
||||
SupportLayer::SupportLayer(int id, PrintObject *object, coordf_t height,
|
||||
SupportLayer::SupportLayer(size_t id, PrintObject *object, coordf_t height,
|
||||
coordf_t print_z, coordf_t slice_z)
|
||||
: Layer(id, object, height, print_z, slice_z)
|
||||
{
|
||||
|
|
|
@ -56,6 +56,7 @@ class LayerRegion
|
|||
|
||||
Flow flow(FlowRole role, bool bridge = false, double width = -1) const;
|
||||
void merge_slices();
|
||||
void prepare_fill_surfaces();
|
||||
|
||||
private:
|
||||
Layer *_layer;
|
||||
|
@ -72,7 +73,8 @@ class Layer {
|
|||
friend class PrintObject;
|
||||
|
||||
public:
|
||||
int id();
|
||||
size_t id() const;
|
||||
void set_id(size_t id);
|
||||
PrintObject* object();
|
||||
|
||||
Layer *upper_layer;
|
||||
|
@ -97,11 +99,11 @@ class Layer {
|
|||
template <class T> bool any_bottom_region_slice_contains(const T &item) const;
|
||||
|
||||
protected:
|
||||
int _id; // sequential number of layer, 0-based
|
||||
size_t _id; // sequential number of layer, 0-based
|
||||
PrintObject *_object;
|
||||
|
||||
|
||||
Layer(int id, PrintObject *object, coordf_t height, coordf_t print_z,
|
||||
Layer(size_t id, PrintObject *object, coordf_t height, coordf_t print_z,
|
||||
coordf_t slice_z);
|
||||
virtual ~Layer();
|
||||
|
||||
|
@ -119,7 +121,7 @@ class SupportLayer : public Layer {
|
|||
ExtrusionEntityCollection support_interface_fills;
|
||||
|
||||
protected:
|
||||
SupportLayer(int id, PrintObject *object, coordf_t height, coordf_t print_z,
|
||||
SupportLayer(size_t id, PrintObject *object, coordf_t height, coordf_t print_z,
|
||||
coordf_t slice_z);
|
||||
virtual ~SupportLayer();
|
||||
};
|
||||
|
|
|
@ -53,6 +53,38 @@ LayerRegion::merge_slices()
|
|||
this->slices.surfaces.push_back(Surface(stInternal, *expoly));
|
||||
}
|
||||
|
||||
void
|
||||
LayerRegion::prepare_fill_surfaces()
|
||||
{
|
||||
/* Note: in order to make the psPrepareInfill step idempotent, we should never
|
||||
alter fill_surfaces boundaries on which our idempotency relies since that's
|
||||
the only meaningful information returned by psPerimeters. */
|
||||
|
||||
// if no solid layers are requested, turn top/bottom surfaces to internal
|
||||
if (this->_region->config.top_solid_layers == 0) {
|
||||
for (Surfaces::iterator surface = this->fill_surfaces.surfaces.begin(); surface != this->fill_surfaces.surfaces.end(); ++surface) {
|
||||
if (surface->surface_type == stTop)
|
||||
surface->surface_type = stInternal;
|
||||
}
|
||||
}
|
||||
if (this->_region->config.bottom_solid_layers == 0) {
|
||||
for (Surfaces::iterator surface = this->fill_surfaces.surfaces.begin(); surface != this->fill_surfaces.surfaces.end(); ++surface) {
|
||||
if (surface->surface_type == stBottom || surface->surface_type == stBottomBridge)
|
||||
surface->surface_type = stInternal;
|
||||
}
|
||||
}
|
||||
|
||||
// turn too small internal regions into solid regions according to the user setting
|
||||
if (this->_region->config.fill_density.value > 0) {
|
||||
// scaling an area requires two calls!
|
||||
double min_area = scale_(scale_(this->_region->config.solid_infill_below_area.value));
|
||||
for (Surfaces::iterator surface = this->fill_surfaces.surfaces.begin(); surface != this->fill_surfaces.surfaces.end(); ++surface) {
|
||||
if (surface->surface_type == stInternal && surface->area() <= min_area)
|
||||
surface->surface_type = stInternalSolid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SLIC3RXS
|
||||
REGISTER_CLASS(LayerRegion, "Layer::Region");
|
||||
#endif
|
||||
|
|
|
@ -64,10 +64,10 @@ Line::length() const
|
|||
return this->a.distance_to(this->b);
|
||||
}
|
||||
|
||||
Point*
|
||||
Point
|
||||
Line::midpoint() const
|
||||
{
|
||||
return new Point ((this->a.x + this->b.x) / 2.0, (this->a.y + this->b.y) / 2.0);
|
||||
return Point((this->a.x + this->b.x) / 2.0, (this->a.y + this->b.y) / 2.0);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -89,6 +89,23 @@ Line::point_at(double distance) const
|
|||
return p;
|
||||
}
|
||||
|
||||
bool
|
||||
Line::intersection_infinite(const Line &other, Point* point) const
|
||||
{
|
||||
Vector x = this->a.vector_to(other.a);
|
||||
Vector d1 = this->vector();
|
||||
Vector d2 = other.vector();
|
||||
|
||||
double cross = d1.x * d2.y - d1.y * d2.x;
|
||||
if (std::fabs(cross) < EPSILON)
|
||||
return false;
|
||||
|
||||
double t1 = (x.x * d2.y - x.y * d2.x)/cross;
|
||||
point->x = this->a.x + d1.x * t1;
|
||||
point->y = this->a.y + d1.y * t1;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
Line::coincides_with(const Line &line) const
|
||||
{
|
||||
|
@ -201,6 +218,13 @@ Linef3::intersect_plane(double z) const
|
|||
);
|
||||
}
|
||||
|
||||
void
|
||||
Linef3::scale(double factor)
|
||||
{
|
||||
this->a.scale(factor);
|
||||
this->b.scale(factor);
|
||||
}
|
||||
|
||||
#ifdef SLIC3RXS
|
||||
REGISTER_CLASS(Linef3, "Linef3");
|
||||
#endif
|
||||
|
|
|
@ -26,9 +26,10 @@ class Line
|
|||
void rotate(double angle, const Point ¢er);
|
||||
void reverse();
|
||||
double length() const;
|
||||
Point* midpoint() const;
|
||||
Point midpoint() const;
|
||||
void point_at(double distance, Point* point) const;
|
||||
Point point_at(double distance) const;
|
||||
bool intersection_infinite(const Line &other, Point* point) const;
|
||||
bool coincides_with(const Line &line) const;
|
||||
double distance_to(const Point &point) const;
|
||||
bool parallel_to(double angle) const;
|
||||
|
@ -47,6 +48,15 @@ class Line
|
|||
#endif
|
||||
};
|
||||
|
||||
class Linef
|
||||
{
|
||||
public:
|
||||
Pointf a;
|
||||
Pointf b;
|
||||
Linef() {};
|
||||
explicit Linef(Pointf _a, Pointf _b): a(_a), b(_b) {};
|
||||
};
|
||||
|
||||
class Linef3
|
||||
{
|
||||
public:
|
||||
|
@ -55,6 +65,7 @@ class Linef3
|
|||
Linef3() {};
|
||||
explicit Linef3(Pointf3 _a, Pointf3 _b): a(_a), b(_b) {};
|
||||
Pointf3 intersect_plane(double z) const;
|
||||
void scale(double factor);
|
||||
|
||||
#ifdef SLIC3RXS
|
||||
void from_SV(SV* line_sv);
|
||||
|
|
|
@ -130,8 +130,7 @@ Model::duplicate_objects_grid(unsigned int x, unsigned int y, coordf_t distance)
|
|||
ModelObject* object = this->objects.front();
|
||||
object->clear_instances();
|
||||
|
||||
BoundingBoxf3 bb;
|
||||
object->bounding_box(&bb);
|
||||
BoundingBoxf3 bb = object->bounding_box();
|
||||
Sizef3 size = bb.size();
|
||||
|
||||
for (unsigned int x_copy = 1; x_copy <= x; ++x_copy) {
|
||||
|
@ -174,21 +173,20 @@ Model::add_default_instances()
|
|||
}
|
||||
|
||||
// this returns the bounding box of the *transformed* instances
|
||||
void
|
||||
Model::bounding_box(BoundingBoxf3* bb)
|
||||
BoundingBoxf3
|
||||
Model::bounding_box() const
|
||||
{
|
||||
BoundingBoxf3 bb;
|
||||
for (ModelObjectPtrs::const_iterator o = this->objects.begin(); o != this->objects.end(); ++o) {
|
||||
BoundingBoxf3 obb;
|
||||
(*o)->bounding_box(&obb);
|
||||
bb->merge(obb);
|
||||
bb.merge((*o)->bounding_box());
|
||||
}
|
||||
return bb;
|
||||
}
|
||||
|
||||
void
|
||||
Model::center_instances_around_point(const Pointf &point)
|
||||
{
|
||||
BoundingBoxf3 bb;
|
||||
this->bounding_box(&bb);
|
||||
BoundingBoxf3 bb = this->bounding_box();
|
||||
|
||||
Sizef3 size = bb.size();
|
||||
double shift_x = -bb.min.x + point.x - size.x/2;
|
||||
|
@ -205,8 +203,7 @@ Model::center_instances_around_point(const Pointf &point)
|
|||
void
|
||||
Model::align_instances_to_origin()
|
||||
{
|
||||
BoundingBoxf3 bb;
|
||||
this->bounding_box(&bb);
|
||||
BoundingBoxf3 bb = this->bounding_box();
|
||||
|
||||
Pointf new_center = (Pointf)bb.size();
|
||||
new_center.translate(-new_center.x/2, -new_center.y/2);
|
||||
|
@ -222,25 +219,25 @@ Model::translate(coordf_t x, coordf_t y, coordf_t z)
|
|||
}
|
||||
|
||||
// flattens everything to a single mesh
|
||||
void
|
||||
Model::mesh(TriangleMesh* mesh) const
|
||||
TriangleMesh
|
||||
Model::mesh() const
|
||||
{
|
||||
TriangleMesh mesh;
|
||||
for (ModelObjectPtrs::const_iterator o = this->objects.begin(); o != this->objects.end(); ++o) {
|
||||
TriangleMesh omesh;
|
||||
(*o)->mesh(&omesh);
|
||||
mesh->merge(omesh);
|
||||
mesh.merge((*o)->mesh());
|
||||
}
|
||||
return mesh;
|
||||
}
|
||||
|
||||
// flattens everything to a single mesh
|
||||
void
|
||||
Model::raw_mesh(TriangleMesh* mesh) const
|
||||
TriangleMesh
|
||||
Model::raw_mesh() const
|
||||
{
|
||||
TriangleMesh mesh;
|
||||
for (ModelObjectPtrs::const_iterator o = this->objects.begin(); o != this->objects.end(); ++o) {
|
||||
TriangleMesh omesh;
|
||||
(*o)->raw_mesh(&omesh);
|
||||
mesh->merge(omesh);
|
||||
mesh.merge((*o)->raw_mesh());
|
||||
}
|
||||
return mesh;
|
||||
}
|
||||
|
||||
#ifdef SLIC3RXS
|
||||
|
@ -393,11 +390,11 @@ ModelObject::clear_instances()
|
|||
}
|
||||
|
||||
// this returns the bounding box of the *transformed* instances
|
||||
void
|
||||
ModelObject::bounding_box(BoundingBoxf3* bb)
|
||||
BoundingBoxf3
|
||||
ModelObject::bounding_box()
|
||||
{
|
||||
if (!this->_bounding_box_valid) this->update_bounding_box();
|
||||
*bb = this->_bounding_box;
|
||||
return this->_bounding_box;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -409,40 +406,40 @@ ModelObject::invalidate_bounding_box()
|
|||
void
|
||||
ModelObject::update_bounding_box()
|
||||
{
|
||||
TriangleMesh mesh;
|
||||
this->mesh(&mesh);
|
||||
|
||||
mesh.bounding_box(&this->_bounding_box);
|
||||
this->_bounding_box = this->mesh().bounding_box();
|
||||
this->_bounding_box_valid = true;
|
||||
}
|
||||
|
||||
// flattens all volumes and instances into a single mesh
|
||||
void
|
||||
ModelObject::mesh(TriangleMesh* mesh) const
|
||||
TriangleMesh
|
||||
ModelObject::mesh() const
|
||||
{
|
||||
TriangleMesh raw_mesh;
|
||||
this->raw_mesh(&raw_mesh);
|
||||
|
||||
TriangleMesh mesh;
|
||||
TriangleMesh raw_mesh = this->raw_mesh();
|
||||
|
||||
for (ModelInstancePtrs::const_iterator i = this->instances.begin(); i != this->instances.end(); ++i) {
|
||||
TriangleMesh m = raw_mesh;
|
||||
(*i)->transform_mesh(&m);
|
||||
mesh->merge(m);
|
||||
mesh.merge(m);
|
||||
}
|
||||
return mesh;
|
||||
}
|
||||
|
||||
void
|
||||
ModelObject::raw_mesh(TriangleMesh* mesh) const
|
||||
TriangleMesh
|
||||
ModelObject::raw_mesh() const
|
||||
{
|
||||
TriangleMesh mesh;
|
||||
for (ModelVolumePtrs::const_iterator v = this->volumes.begin(); v != this->volumes.end(); ++v) {
|
||||
if ((*v)->modifier) continue;
|
||||
mesh->merge((*v)->mesh);
|
||||
mesh.merge((*v)->mesh);
|
||||
}
|
||||
return mesh;
|
||||
}
|
||||
|
||||
void
|
||||
ModelObject::raw_bounding_box(BoundingBoxf3* bb) const
|
||||
BoundingBoxf3
|
||||
ModelObject::raw_bounding_box() const
|
||||
{
|
||||
BoundingBoxf3 bb;
|
||||
for (ModelVolumePtrs::const_iterator v = this->volumes.begin(); v != this->volumes.end(); ++v) {
|
||||
if ((*v)->modifier) continue;
|
||||
TriangleMesh mesh = (*v)->mesh;
|
||||
|
@ -450,22 +447,18 @@ ModelObject::raw_bounding_box(BoundingBoxf3* bb) const
|
|||
if (this->instances.empty()) CONFESS("Can't call raw_bounding_box() with no instances");
|
||||
this->instances.front()->transform_mesh(&mesh, true);
|
||||
|
||||
BoundingBoxf3 mbb;
|
||||
mesh.bounding_box(&mbb);
|
||||
bb->merge(mbb);
|
||||
bb.merge(mesh.bounding_box());
|
||||
}
|
||||
return bb;
|
||||
}
|
||||
|
||||
// this returns the bounding box of the *transformed* given instance
|
||||
void
|
||||
ModelObject::instance_bounding_box(size_t instance_idx, BoundingBoxf3* bb) const
|
||||
BoundingBoxf3
|
||||
ModelObject::instance_bounding_box(size_t instance_idx) const
|
||||
{
|
||||
TriangleMesh mesh;
|
||||
this->raw_mesh(&mesh);
|
||||
|
||||
TriangleMesh mesh = this->raw_mesh();
|
||||
this->instances[instance_idx]->transform_mesh(&mesh);
|
||||
|
||||
mesh.bounding_box(bb);
|
||||
return mesh.bounding_box();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -473,12 +466,7 @@ ModelObject::center_around_origin()
|
|||
{
|
||||
// calculate the displacements needed to
|
||||
// center this object around the origin
|
||||
BoundingBoxf3 bb;
|
||||
{
|
||||
TriangleMesh mesh;
|
||||
this->raw_mesh(&mesh);
|
||||
mesh.bounding_box(&bb);
|
||||
}
|
||||
BoundingBoxf3 bb = this->raw_mesh().bounding_box();
|
||||
|
||||
// first align to origin on XYZ
|
||||
Vectorf3 vector(-bb.min.x, -bb.min.y, -bb.min.z);
|
||||
|
@ -520,6 +508,9 @@ ModelObject::scale(const Pointf3 &versor)
|
|||
for (ModelVolumePtrs::const_iterator v = this->volumes.begin(); v != this->volumes.end(); ++v) {
|
||||
(*v)->mesh.scale(versor);
|
||||
}
|
||||
|
||||
// reset origin translation since it doesn't make sense anymore
|
||||
this->origin_translation = Pointf3(0,0,0);
|
||||
this->invalidate_bounding_box();
|
||||
}
|
||||
|
||||
|
|
|
@ -54,12 +54,12 @@ class Model
|
|||
// void duplicate(size_t copies_num, coordf_t distance, const BoundingBox &bb);
|
||||
bool has_objects_with_no_instances() const;
|
||||
bool add_default_instances();
|
||||
void bounding_box(BoundingBoxf3* bb);
|
||||
BoundingBoxf3 bounding_box() const;
|
||||
void center_instances_around_point(const Pointf &point);
|
||||
void align_instances_to_origin();
|
||||
void translate(coordf_t x, coordf_t y, coordf_t z);
|
||||
void mesh(TriangleMesh* mesh) const;
|
||||
void raw_mesh(TriangleMesh* mesh) const;
|
||||
TriangleMesh mesh() const;
|
||||
TriangleMesh raw_mesh() const;
|
||||
// std::string get_material_name(t_model_material_id material_id);
|
||||
|
||||
|
||||
|
@ -97,7 +97,7 @@ class ModelObject
|
|||
|
||||
/* This vector accumulates the total translation applied to the object by the
|
||||
center_around_origin() method. Callers might want to apply the same translation
|
||||
to new volumes before adding them to this object in order to preset alignment
|
||||
to new volumes before adding them to this object in order to preserve alignment
|
||||
when user expects that. */
|
||||
Pointf3 origin_translation;
|
||||
|
||||
|
@ -118,13 +118,13 @@ class ModelObject
|
|||
void delete_last_instance();
|
||||
void clear_instances();
|
||||
|
||||
void bounding_box(BoundingBoxf3* bb);
|
||||
BoundingBoxf3 bounding_box();
|
||||
void invalidate_bounding_box();
|
||||
|
||||
void mesh(TriangleMesh* mesh) const;
|
||||
void raw_mesh(TriangleMesh* mesh) const;
|
||||
void raw_bounding_box(BoundingBoxf3* bb) const;
|
||||
void instance_bounding_box(size_t instance_idx, BoundingBoxf3* bb) const;
|
||||
TriangleMesh mesh() const;
|
||||
TriangleMesh raw_mesh() const;
|
||||
BoundingBoxf3 raw_bounding_box() const;
|
||||
BoundingBoxf3 instance_bounding_box(size_t instance_idx) const;
|
||||
void center_around_origin();
|
||||
void translate(const Vectorf3 &vector);
|
||||
void translate(coordf_t x, coordf_t y, coordf_t z);
|
||||
|
|
|
@ -82,17 +82,18 @@ MotionPlanner::get_env(size_t island_idx) const
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
MotionPlanner::shortest_path(const Point &from, const Point &to, Polyline* polyline)
|
||||
Polyline
|
||||
MotionPlanner::shortest_path(const Point &from, const Point &to)
|
||||
{
|
||||
// lazy generation of configuration space
|
||||
if (!this->initialized) this->initialize();
|
||||
|
||||
// if we have an empty configuration space, return a straight move
|
||||
if (this->islands.empty()) {
|
||||
polyline->points.push_back(from);
|
||||
polyline->points.push_back(to);
|
||||
return;
|
||||
Polyline p;
|
||||
p.points.push_back(from);
|
||||
p.points.push_back(to);
|
||||
return p;
|
||||
}
|
||||
|
||||
// Are both points in the same island?
|
||||
|
@ -102,9 +103,10 @@ MotionPlanner::shortest_path(const Point &from, const Point &to, Polyline* polyl
|
|||
// since both points are in the same island, is a direct move possible?
|
||||
// if so, we avoid generating the visibility environment
|
||||
if (island->contains(Line(from, to))) {
|
||||
polyline->points.push_back(from);
|
||||
polyline->points.push_back(to);
|
||||
return;
|
||||
Polyline p;
|
||||
p.points.push_back(from);
|
||||
p.points.push_back(to);
|
||||
return p;
|
||||
}
|
||||
island_idx = island - this->islands.begin();
|
||||
break;
|
||||
|
@ -116,9 +118,10 @@ MotionPlanner::shortest_path(const Point &from, const Point &to, Polyline* polyl
|
|||
if (env.expolygons.empty()) {
|
||||
// if this environment is empty (probably because it's too small), perform straight move
|
||||
// and avoid running the algorithms on empty dataset
|
||||
polyline->points.push_back(from);
|
||||
polyline->points.push_back(to);
|
||||
return; // bye bye
|
||||
Polyline p;
|
||||
p.points.push_back(from);
|
||||
p.points.push_back(to);
|
||||
return p; // bye bye
|
||||
}
|
||||
|
||||
// Now check whether points are inside the environment.
|
||||
|
@ -137,10 +140,10 @@ MotionPlanner::shortest_path(const Point &from, const Point &to, Polyline* polyl
|
|||
|
||||
// perform actual path search
|
||||
MotionPlannerGraph* graph = this->init_graph(island_idx);
|
||||
graph->shortest_path(graph->find_node(inner_from), graph->find_node(inner_to), polyline);
|
||||
Polyline polyline = graph->shortest_path(graph->find_node(inner_from), graph->find_node(inner_to));
|
||||
|
||||
polyline->points.insert(polyline->points.begin(), from);
|
||||
polyline->points.push_back(to);
|
||||
polyline.points.insert(polyline.points.begin(), from);
|
||||
polyline.points.push_back(to);
|
||||
|
||||
{
|
||||
// grow our environment slightly in order for simplify_by_visibility()
|
||||
|
@ -149,7 +152,7 @@ MotionPlanner::shortest_path(const Point &from, const Point &to, Polyline* polyl
|
|||
offset(env, &grown_env.expolygons, +SCALED_EPSILON);
|
||||
|
||||
// remove unnecessary vertices
|
||||
polyline->simplify_by_visibility(grown_env);
|
||||
polyline.simplify_by_visibility(grown_env);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -171,6 +174,8 @@ MotionPlanner::shortest_path(const Point &from, const Point &to, Polyline* polyl
|
|||
svg.draw(*polyline, "red");
|
||||
svg.Close();
|
||||
*/
|
||||
|
||||
return polyline;
|
||||
}
|
||||
|
||||
Point
|
||||
|
@ -310,11 +315,11 @@ MotionPlannerGraph::find_node(const Point &point) const
|
|||
return point.nearest_point_index(this->nodes);
|
||||
}
|
||||
|
||||
void
|
||||
MotionPlannerGraph::shortest_path(size_t from, size_t to, Polyline* polyline)
|
||||
Polyline
|
||||
MotionPlannerGraph::shortest_path(size_t from, size_t to)
|
||||
{
|
||||
// this prevents a crash in case for some reason we got here with an empty adjacency list
|
||||
if (this->adjacency_list.empty()) return;
|
||||
if (this->adjacency_list.empty()) return Polyline();
|
||||
|
||||
const weight_t max_weight = std::numeric_limits<weight_t>::infinity();
|
||||
|
||||
|
@ -379,10 +384,12 @@ MotionPlannerGraph::shortest_path(size_t from, size_t to, Polyline* polyline)
|
|||
}
|
||||
}
|
||||
|
||||
Polyline polyline;
|
||||
for (node_t vertex = to; vertex != -1; vertex = previous[vertex])
|
||||
polyline->points.push_back(this->nodes[vertex]);
|
||||
polyline->points.push_back(this->nodes[from]);
|
||||
polyline->reverse();
|
||||
polyline.points.push_back(this->nodes[vertex]);
|
||||
polyline.points.push_back(this->nodes[from]);
|
||||
polyline.reverse();
|
||||
return polyline;
|
||||
}
|
||||
|
||||
#ifdef SLIC3RXS
|
||||
|
|
|
@ -21,7 +21,7 @@ class MotionPlanner
|
|||
public:
|
||||
MotionPlanner(const ExPolygons &islands);
|
||||
~MotionPlanner();
|
||||
void shortest_path(const Point &from, const Point &to, Polyline* polyline);
|
||||
Polyline shortest_path(const Point &from, const Point &to);
|
||||
size_t islands_count() const;
|
||||
|
||||
private:
|
||||
|
@ -58,7 +58,7 @@ class MotionPlannerGraph
|
|||
//std::map<std::pair<size_t,size_t>, double> edges;
|
||||
void add_edge(size_t from, size_t to, double weight);
|
||||
size_t find_node(const Point &point) const;
|
||||
void shortest_path(size_t from, size_t to, Polyline* polyline);
|
||||
Polyline shortest_path(size_t from, size_t to);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -83,10 +83,21 @@ MultiPoint::has_boundary_point(const Point &point) const
|
|||
return dist < SCALED_EPSILON;
|
||||
}
|
||||
|
||||
void
|
||||
MultiPoint::bounding_box(BoundingBox* bb) const
|
||||
BoundingBox
|
||||
MultiPoint::bounding_box() const
|
||||
{
|
||||
*bb = BoundingBox(this->points);
|
||||
return BoundingBox(this->points);
|
||||
}
|
||||
|
||||
void
|
||||
MultiPoint::remove_duplicate_points()
|
||||
{
|
||||
for (size_t i = 1; i < this->points.size(); ++i) {
|
||||
if (this->points.at(i).coincides_with(this->points.at(i-1))) {
|
||||
this->points.erase(this->points.begin() + i);
|
||||
--i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Points
|
||||
|
|
|
@ -31,7 +31,8 @@ class MultiPoint
|
|||
bool is_valid() const;
|
||||
int find_point(const Point &point) const;
|
||||
bool has_boundary_point(const Point &point) const;
|
||||
void bounding_box(BoundingBox* bb) const;
|
||||
BoundingBox bounding_box() const;
|
||||
void remove_duplicate_points();
|
||||
|
||||
static Points _douglas_peucker(const Points &points, const double tolerance);
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
namespace Slic3r {
|
||||
|
||||
class Line;
|
||||
class Linef;
|
||||
class MultiPoint;
|
||||
class Point;
|
||||
class Pointf;
|
||||
|
@ -82,6 +83,12 @@ class Pointf
|
|||
coordf_t x;
|
||||
coordf_t y;
|
||||
explicit Pointf(coordf_t _x = 0, coordf_t _y = 0): x(_x), y(_y) {};
|
||||
static Pointf new_unscale(coord_t x, coord_t y) {
|
||||
return Pointf(unscale(x), unscale(y));
|
||||
};
|
||||
static Pointf new_unscale(const Point &p) {
|
||||
return Pointf(unscale(p.x), unscale(p.y));
|
||||
};
|
||||
void scale(double factor);
|
||||
void translate(double x, double y);
|
||||
void rotate(double angle, const Pointf ¢er);
|
||||
|
@ -100,6 +107,9 @@ class Pointf3 : public Pointf
|
|||
public:
|
||||
coordf_t z;
|
||||
explicit Pointf3(coordf_t _x = 0, coordf_t _y = 0, coordf_t _z = 0): Pointf(_x, _y), z(_z) {};
|
||||
static Pointf3 new_unscale(coord_t x, coord_t y, coord_t z) {
|
||||
return Pointf3(unscale(x), unscale(y), unscale(z));
|
||||
};
|
||||
void scale(double factor);
|
||||
void translate(const Vectorf3 &vector);
|
||||
void translate(double x, double y, double z);
|
||||
|
|
|
@ -14,9 +14,7 @@ Polygon::operator Polygons() const
|
|||
|
||||
Polygon::operator Polyline() const
|
||||
{
|
||||
Polyline polyline;
|
||||
this->split_at_first_point(&polyline);
|
||||
return polyline;
|
||||
return this->split_at_first_point();
|
||||
}
|
||||
|
||||
Point&
|
||||
|
@ -41,55 +39,49 @@ Lines
|
|||
Polygon::lines() const
|
||||
{
|
||||
Lines lines;
|
||||
this->lines(&lines);
|
||||
lines.reserve(this->points.size());
|
||||
for (Points::const_iterator it = this->points.begin(); it != this->points.end()-1; ++it) {
|
||||
lines.push_back(Line(*it, *(it + 1)));
|
||||
}
|
||||
lines.push_back(Line(this->points.back(), this->points.front()));
|
||||
return lines;
|
||||
}
|
||||
|
||||
void
|
||||
Polygon::lines(Lines* lines) const
|
||||
{
|
||||
lines->reserve(lines->size() + this->points.size());
|
||||
for (Points::const_iterator it = this->points.begin(); it != this->points.end()-1; ++it) {
|
||||
lines->push_back(Line(*it, *(it + 1)));
|
||||
}
|
||||
lines->push_back(Line(this->points.back(), this->points.front()));
|
||||
}
|
||||
|
||||
void
|
||||
Polygon::split_at_vertex(const Point &point, Polyline* polyline) const
|
||||
Polyline
|
||||
Polygon::split_at_vertex(const Point &point) const
|
||||
{
|
||||
// find index of point
|
||||
for (Points::const_iterator it = this->points.begin(); it != this->points.end(); ++it) {
|
||||
if (it->coincides_with(point)) {
|
||||
this->split_at_index(it - this->points.begin(), polyline);
|
||||
return;
|
||||
return this->split_at_index(it - this->points.begin());
|
||||
}
|
||||
}
|
||||
CONFESS("Point not found");
|
||||
return Polyline();
|
||||
}
|
||||
|
||||
void
|
||||
Polygon::split_at_index(int index, Polyline* polyline) const
|
||||
{
|
||||
polyline->points.reserve(this->points.size() + 1);
|
||||
for (Points::const_iterator it = this->points.begin() + index; it != this->points.end(); ++it)
|
||||
polyline->points.push_back(*it);
|
||||
for (Points::const_iterator it = this->points.begin(); it != this->points.begin() + index + 1; ++it)
|
||||
polyline->points.push_back(*it);
|
||||
}
|
||||
|
||||
void
|
||||
Polygon::split_at_first_point(Polyline* polyline) const
|
||||
{
|
||||
this->split_at_index(0, polyline);
|
||||
}
|
||||
|
||||
void
|
||||
Polygon::equally_spaced_points(double distance, Points* points) const
|
||||
Polyline
|
||||
Polygon::split_at_index(int index) const
|
||||
{
|
||||
Polyline polyline;
|
||||
this->split_at_first_point(&polyline);
|
||||
polyline.equally_spaced_points(distance, points);
|
||||
polyline.points.reserve(this->points.size() + 1);
|
||||
for (Points::const_iterator it = this->points.begin() + index; it != this->points.end(); ++it)
|
||||
polyline.points.push_back(*it);
|
||||
for (Points::const_iterator it = this->points.begin(); it != this->points.begin() + index + 1; ++it)
|
||||
polyline.points.push_back(*it);
|
||||
return polyline;
|
||||
}
|
||||
|
||||
Polyline
|
||||
Polygon::split_at_first_point() const
|
||||
{
|
||||
return this->split_at_index(0);
|
||||
}
|
||||
|
||||
Points
|
||||
Polygon::equally_spaced_points(double distance) const
|
||||
{
|
||||
return this->split_at_first_point().equally_spaced_points(distance);
|
||||
}
|
||||
|
||||
double
|
||||
|
@ -155,6 +147,7 @@ Polygon::contains(const Point &point) const
|
|||
return result;
|
||||
}
|
||||
|
||||
// this only works on CCW polygons as CW will be ripped out by Clipper's simplify_polygons()
|
||||
Polygons
|
||||
Polygon::simplify(double tolerance) const
|
||||
{
|
||||
|
@ -203,8 +196,7 @@ Polygon::centroid() const
|
|||
double x_temp = 0;
|
||||
double y_temp = 0;
|
||||
|
||||
Polyline polyline;
|
||||
this->split_at_first_point(&polyline);
|
||||
Polyline polyline = this->split_at_first_point();
|
||||
for (Points::const_iterator point = polyline.points.begin(); point != polyline.points.end() - 1; ++point) {
|
||||
x_temp += (double)( point->x + (point+1)->x ) * ( (double)point->x*(point+1)->y - (double)(point+1)->x*point->y );
|
||||
y_temp += (double)( point->y + (point+1)->y ) * ( (double)point->x*(point+1)->y - (double)(point+1)->x*point->y );
|
||||
|
@ -227,55 +219,49 @@ Polygon::wkt() const
|
|||
}
|
||||
|
||||
// find all concave vertices (i.e. having an internal angle greater than the supplied angle) */
|
||||
void
|
||||
Polygon::concave_points(double angle, Points* points) const
|
||||
Points
|
||||
Polygon::concave_points(double angle) const
|
||||
{
|
||||
Points points;
|
||||
angle = 2*PI - angle;
|
||||
|
||||
// check whether first point forms a concave angle
|
||||
if (this->points.front().ccw_angle(this->points.back(), *(this->points.begin()+1)) <= angle)
|
||||
points->push_back(this->points.front());
|
||||
points.push_back(this->points.front());
|
||||
|
||||
// check whether points 1..(n-1) form concave angles
|
||||
for (Points::const_iterator p = this->points.begin()+1; p != this->points.end()-1; ++p) {
|
||||
if (p->ccw_angle(*(p-1), *(p+1)) <= angle) points->push_back(*p);
|
||||
if (p->ccw_angle(*(p-1), *(p+1)) <= angle) points.push_back(*p);
|
||||
}
|
||||
|
||||
// check whether last point forms a concave angle
|
||||
if (this->points.back().ccw_angle(*(this->points.end()-2), this->points.front()) <= angle)
|
||||
points->push_back(this->points.back());
|
||||
}
|
||||
|
||||
void
|
||||
Polygon::concave_points(Points* points) const
|
||||
{
|
||||
this->concave_points(PI, points);
|
||||
points.push_back(this->points.back());
|
||||
|
||||
return points;
|
||||
}
|
||||
|
||||
// find all convex vertices (i.e. having an internal angle smaller than the supplied angle) */
|
||||
void
|
||||
Polygon::convex_points(double angle, Points* points) const
|
||||
Points
|
||||
Polygon::convex_points(double angle) const
|
||||
{
|
||||
Points points;
|
||||
angle = 2*PI - angle;
|
||||
|
||||
// check whether first point forms a convex angle
|
||||
if (this->points.front().ccw_angle(this->points.back(), *(this->points.begin()+1)) >= angle)
|
||||
points->push_back(this->points.front());
|
||||
points.push_back(this->points.front());
|
||||
|
||||
// check whether points 1..(n-1) form convex angles
|
||||
for (Points::const_iterator p = this->points.begin()+1; p != this->points.end()-1; ++p) {
|
||||
if (p->ccw_angle(*(p-1), *(p+1)) >= angle) points->push_back(*p);
|
||||
if (p->ccw_angle(*(p-1), *(p+1)) >= angle) points.push_back(*p);
|
||||
}
|
||||
|
||||
// check whether last point forms a convex angle
|
||||
if (this->points.back().ccw_angle(*(this->points.end()-2), this->points.front()) >= angle)
|
||||
points->push_back(this->points.back());
|
||||
}
|
||||
|
||||
void
|
||||
Polygon::convex_points(Points* points) const
|
||||
{
|
||||
this->convex_points(PI, points);
|
||||
points.push_back(this->points.back());
|
||||
|
||||
return points;
|
||||
}
|
||||
|
||||
#ifdef SLIC3RXS
|
||||
|
|
|
@ -24,11 +24,10 @@ class Polygon : public MultiPoint {
|
|||
explicit Polygon(const Points &points): MultiPoint(points) {};
|
||||
Point last_point() const;
|
||||
Lines lines() const;
|
||||
void lines(Lines* lines) const;
|
||||
void split_at_vertex(const Point &point, Polyline* polyline) const;
|
||||
void split_at_index(int index, Polyline* polyline) const;
|
||||
void split_at_first_point(Polyline* polyline) const;
|
||||
void equally_spaced_points(double distance, Points* points) const;
|
||||
Polyline split_at_vertex(const Point &point) const;
|
||||
Polyline split_at_index(int index) const;
|
||||
Polyline split_at_first_point() const;
|
||||
Points equally_spaced_points(double distance) const;
|
||||
double area() const;
|
||||
bool is_counter_clockwise() const;
|
||||
bool is_clockwise() const;
|
||||
|
@ -41,10 +40,8 @@ class Polygon : public MultiPoint {
|
|||
void triangulate_convex(Polygons* polygons) const;
|
||||
Point centroid() const;
|
||||
std::string wkt() const;
|
||||
void concave_points(double angle, Points* points) const;
|
||||
void concave_points(Points* points) const;
|
||||
void convex_points(double angle, Points* points) const;
|
||||
void convex_points(Points* points) const;
|
||||
Points concave_points(double angle = PI) const;
|
||||
Points convex_points(double angle = PI) const;
|
||||
|
||||
#ifdef SLIC3RXS
|
||||
void from_SV_check(SV* poly_sv);
|
||||
|
|
|
@ -98,10 +98,11 @@ Polyline::extend_start(double distance)
|
|||
|
||||
/* this method returns a collection of points picked on the polygon contour
|
||||
so that they are evenly spaced according to the input distance */
|
||||
void
|
||||
Polyline::equally_spaced_points(double distance, Points* points) const
|
||||
Points
|
||||
Polyline::equally_spaced_points(double distance) const
|
||||
{
|
||||
points->push_back(this->first_point());
|
||||
Points points;
|
||||
points.push_back(this->first_point());
|
||||
double len = 0;
|
||||
|
||||
for (Points::const_iterator it = this->points.begin() + 1; it != this->points.end(); ++it) {
|
||||
|
@ -110,17 +111,18 @@ Polyline::equally_spaced_points(double distance, Points* points) const
|
|||
if (len < distance) continue;
|
||||
|
||||
if (len == distance) {
|
||||
points->push_back(*it);
|
||||
points.push_back(*it);
|
||||
len = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
double take = segment_length - (len - distance); // how much we take of this segment
|
||||
Line segment(*(it-1), *it);
|
||||
points->push_back(segment.point_at(take));
|
||||
points.push_back(segment.point_at(take));
|
||||
it--;
|
||||
len = -take;
|
||||
}
|
||||
return points;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -22,7 +22,7 @@ class Polyline : public MultiPoint {
|
|||
void clip_start(double distance);
|
||||
void extend_end(double distance);
|
||||
void extend_start(double distance);
|
||||
void equally_spaced_points(double distance, Points* points) const;
|
||||
Points equally_spaced_points(double distance) const;
|
||||
void simplify(double tolerance);
|
||||
template <class T> void simplify_by_visibility(const T &area);
|
||||
void split_at(const Point &point, Polyline* p1, Polyline* p2) const;
|
||||
|
|
|
@ -358,8 +358,7 @@ Print::add_model_object(ModelObject* model_object, int idx)
|
|||
// initialize print object and store it at the given position
|
||||
PrintObject* o;
|
||||
{
|
||||
BoundingBoxf3 bb;
|
||||
model_object->raw_bounding_box(&bb);
|
||||
BoundingBoxf3 bb = model_object->raw_bounding_box();
|
||||
if (idx != -1) {
|
||||
// replacing existing object
|
||||
PrintObjectPtrs::iterator old_it = this->objects.begin() + idx;
|
||||
|
@ -569,14 +568,13 @@ Print::validate() const
|
|||
Polygons mesh_convex_hulls;
|
||||
for (size_t i = 0; i < this->regions.size(); ++i) {
|
||||
for (std::vector<int>::const_iterator it = object->region_volumes[i].begin(); it != object->region_volumes[i].end(); ++it) {
|
||||
Polygon hull;
|
||||
object->model_object()->volumes[*it]->mesh.convex_hull(&hull);
|
||||
Polygon hull = object->model_object()->volumes[*it]->mesh.convex_hull();
|
||||
mesh_convex_hulls.push_back(hull);
|
||||
}
|
||||
}
|
||||
|
||||
// make a single convex hull for all of them
|
||||
Slic3r::Geometry::convex_hull(mesh_convex_hulls, &convex_hull);
|
||||
convex_hull = Slic3r::Geometry::convex_hull(mesh_convex_hulls);
|
||||
}
|
||||
|
||||
// apply the same transformations we apply to the actual meshes when slicing them
|
||||
|
|
|
@ -111,7 +111,7 @@ class PrintObject
|
|||
bool delete_all_copies();
|
||||
bool set_copies(const Points &points);
|
||||
bool reload_model_instances();
|
||||
void bounding_box(BoundingBox* bb) const;
|
||||
BoundingBox bounding_box() const;
|
||||
|
||||
// adds region_id, too, if necessary
|
||||
void add_region_volume(int region_id, int volume_id);
|
||||
|
@ -126,7 +126,7 @@ class PrintObject
|
|||
size_t support_layer_count() const;
|
||||
void clear_support_layers();
|
||||
SupportLayer* get_support_layer(int idx);
|
||||
SupportLayer* add_support_layer(int id, coordf_t height, coordf_t print_z, coordf_t slice_z);
|
||||
SupportLayer* add_support_layer(int id, coordf_t height, coordf_t print_z);
|
||||
void delete_support_layer(int idx);
|
||||
|
||||
// methods for handling state
|
||||
|
|
|
@ -22,6 +22,14 @@ PrintConfigDef::build_def() {
|
|||
Options["bed_temperature"].min = 0;
|
||||
Options["bed_temperature"].max = 300;
|
||||
|
||||
Options["before_layer_gcode"].type = coString;
|
||||
Options["before_layer_gcode"].label = "Before layer change G-code";
|
||||
Options["before_layer_gcode"].tooltip = "This custom code is inserted at every layer change, right before the Z move. Note that you can use placeholder variables for all Slic3r settings as well as [layer_num] and [layer_z].";
|
||||
Options["before_layer_gcode"].cli = "before-layer-gcode=s";
|
||||
Options["before_layer_gcode"].multiline = true;
|
||||
Options["before_layer_gcode"].full_width = true;
|
||||
Options["before_layer_gcode"].height = 50;
|
||||
|
||||
Options["bottom_solid_layers"].type = coInt;
|
||||
Options["bottom_solid_layers"].label = "Bottom";
|
||||
Options["bottom_solid_layers"].category = "Layers and Perimeters";
|
||||
|
@ -119,7 +127,7 @@ PrintConfigDef::build_def() {
|
|||
Options["external_fill_pattern"].label = "Top/bottom fill pattern";
|
||||
Options["external_fill_pattern"].category = "Infill";
|
||||
Options["external_fill_pattern"].tooltip = "Fill pattern for top/bottom infill. This only affects the external visible layer, and not its adjacent solid shells.";
|
||||
Options["external_fill_pattern"].cli = "external-fill-pattern=s";
|
||||
Options["external_fill_pattern"].cli = "external-fill-pattern|solid-fill-pattern=s";
|
||||
Options["external_fill_pattern"].enum_keys_map = ConfigOptionEnum<InfillPattern>::get_enum_values();
|
||||
Options["external_fill_pattern"].enum_values.push_back("rectilinear");
|
||||
Options["external_fill_pattern"].enum_values.push_back("concentric");
|
||||
|
@ -318,7 +326,7 @@ PrintConfigDef::build_def() {
|
|||
|
||||
Options["first_layer_extrusion_width"].type = coFloatOrPercent;
|
||||
Options["first_layer_extrusion_width"].label = "First layer";
|
||||
Options["first_layer_extrusion_width"].tooltip = "Set this to a non-zero value to set a manual extrusion width for first layer. You can use this to force fatter extrudates for better adhesion. If expressed as percentage (for example 120%) it will be computed over first layer height.";
|
||||
Options["first_layer_extrusion_width"].tooltip = "Set this to a non-zero value to set a manual extrusion width for first layer. You can use this to force fatter extrudates for better adhesion. If expressed as percentage (for example 120%) it will be computed over first layer height. If set to zero, it will use the Default Extrusion Width.";
|
||||
Options["first_layer_extrusion_width"].sidetext = "mm or % (leave 0 for default)";
|
||||
Options["first_layer_extrusion_width"].cli = "first-layer-extrusion-width=s";
|
||||
Options["first_layer_extrusion_width"].ratio_over = "first_layer_height";
|
||||
|
@ -421,6 +429,14 @@ PrintConfigDef::build_def() {
|
|||
Options["infill_only_where_needed"].tooltip = "This option will limit infill to the areas actually needed for supporting ceilings (it will act as internal support material).";
|
||||
Options["infill_only_where_needed"].cli = "infill-only-where-needed!";
|
||||
|
||||
Options["infill_overlap"].type = coFloatOrPercent;
|
||||
Options["infill_overlap"].label = "Infill/perimeters overlap";
|
||||
Options["infill_overlap"].category = "Advanced";
|
||||
Options["infill_overlap"].tooltip = "This setting applies an additional overlap between infill and perimeters for better bonding. Theoretically this shouldn't be needed, but backlash might cause gaps. If expressed as percentage (example: 15%) it is calculated over perimeter extrusion width.";
|
||||
Options["infill_overlap"].sidetext = "mm or %";
|
||||
Options["infill_overlap"].cli = "infill-overlap=s";
|
||||
Options["infill_overlap"].ratio_over = "perimeter_extrusion_width";
|
||||
|
||||
Options["infill_speed"].type = coFloat;
|
||||
Options["infill_speed"].label = "Infill";
|
||||
Options["infill_speed"].category = "Speed";
|
||||
|
@ -438,9 +454,9 @@ PrintConfigDef::build_def() {
|
|||
Options["interface_shells"].category = "Layers and Perimeters";
|
||||
|
||||
Options["layer_gcode"].type = coString;
|
||||
Options["layer_gcode"].label = "Layer change G-code";
|
||||
Options["layer_gcode"].tooltip = "This custom code is inserted at every layer change, right after the Z move and before the extruder moves to the first layer point. Note that you can use placeholder variables for all Slic3r settings.";
|
||||
Options["layer_gcode"].cli = "layer-gcode=s";
|
||||
Options["layer_gcode"].label = "After layer change G-code";
|
||||
Options["layer_gcode"].tooltip = "This custom code is inserted at every layer change, right after the Z move and before the extruder moves to the first layer point. Note that you can use placeholder variables for all Slic3r settings as well as [layer_num] and [layer_z].";
|
||||
Options["layer_gcode"].cli = "after-layer-gcode|layer-gcode=s";
|
||||
Options["layer_gcode"].multiline = true;
|
||||
Options["layer_gcode"].full_width = true;
|
||||
Options["layer_gcode"].height = 50;
|
||||
|
@ -799,6 +815,19 @@ PrintConfigDef::build_def() {
|
|||
Options["support_material_angle"].min = 0;
|
||||
Options["support_material_angle"].max = 359;
|
||||
|
||||
Options["support_material_contact_distance"].type = coFloat;
|
||||
Options["support_material_contact_distance"].gui_type = "f_enum_open";
|
||||
Options["support_material_contact_distance"].label = "Contact Z distance";
|
||||
Options["support_material_contact_distance"].category = "Support material";
|
||||
Options["support_material_contact_distance"].tooltip = "The vertical distance between object and support material interface. Setting this to 0 will also prevent Slic3r from using bridge flow and speed for the first object layer.";
|
||||
Options["support_material_contact_distance"].sidetext = "mm";
|
||||
Options["support_material_contact_distance"].cli = "support-material-contact-distance=f";
|
||||
Options["support_material_contact_distance"].min = 0;
|
||||
Options["support_material_contact_distance"].enum_values.push_back("0");
|
||||
Options["support_material_contact_distance"].enum_values.push_back("0.2");
|
||||
Options["support_material_contact_distance"].enum_labels.push_back("0 (soluble)");
|
||||
Options["support_material_contact_distance"].enum_labels.push_back("0.2 (detachable)");
|
||||
|
||||
Options["support_material_enforce_layers"].type = coInt;
|
||||
Options["support_material_enforce_layers"].label = "Enforce support for the first";
|
||||
Options["support_material_enforce_layers"].category = "Support material";
|
||||
|
@ -966,7 +995,7 @@ PrintConfigDef::build_def() {
|
|||
|
||||
Options["use_volumetric_e"].type = coBool;
|
||||
Options["use_volumetric_e"].label = "Use volumetric E";
|
||||
Options["use_volumetric_e"].tooltip = "This experimental setting uses outputs the E values in cubic millimeters instead of linear millimeters. The M200 command is prepended to the generated G-code, unless it is found in the configured start G-code. This is only supported in recent Marlin.";
|
||||
Options["use_volumetric_e"].tooltip = "This experimental setting uses outputs the E values in cubic millimeters instead of linear millimeters. If your firmware doesn't already know filament diameter(s), you can put commands like 'M200 D[filament_diameter_0] T0' in your start G-code in order to turn volumetric mode on and use the filament diameter associated to the filament selected in Slic3r. This is only supported in recent Marlin.";
|
||||
Options["use_volumetric_e"].cli = "use-volumetric-e!";
|
||||
|
||||
Options["vibration_limit"].type = coFloat;
|
||||
|
|
|
@ -133,6 +133,7 @@ class PrintObjectConfig : public virtual StaticPrintConfig
|
|||
ConfigOptionEnum<SeamPosition> seam_position;
|
||||
ConfigOptionBool support_material;
|
||||
ConfigOptionInt support_material_angle;
|
||||
ConfigOptionFloat support_material_contact_distance;
|
||||
ConfigOptionInt support_material_enforce_layers;
|
||||
ConfigOptionInt support_material_extruder;
|
||||
ConfigOptionFloatOrPercent support_material_extrusion_width;
|
||||
|
@ -159,6 +160,7 @@ class PrintObjectConfig : public virtual StaticPrintConfig
|
|||
this->seam_position.value = spAligned;
|
||||
this->support_material.value = false;
|
||||
this->support_material_angle.value = 0;
|
||||
this->support_material_contact_distance.value = 0.2;
|
||||
this->support_material_enforce_layers.value = 0;
|
||||
this->support_material_extruder.value = 1;
|
||||
this->support_material_extrusion_width.value = 0;
|
||||
|
@ -186,6 +188,7 @@ class PrintObjectConfig : public virtual StaticPrintConfig
|
|||
if (opt_key == "seam_position") return &this->seam_position;
|
||||
if (opt_key == "support_material") return &this->support_material;
|
||||
if (opt_key == "support_material_angle") return &this->support_material_angle;
|
||||
if (opt_key == "support_material_contact_distance") return &this->support_material_contact_distance;
|
||||
if (opt_key == "support_material_enforce_layers") return &this->support_material_enforce_layers;
|
||||
if (opt_key == "support_material_extruder") return &this->support_material_extruder;
|
||||
if (opt_key == "support_material_extrusion_width") return &this->support_material_extrusion_width;
|
||||
|
@ -221,6 +224,7 @@ class PrintRegionConfig : public virtual StaticPrintConfig
|
|||
ConfigOptionInt infill_extruder;
|
||||
ConfigOptionFloatOrPercent infill_extrusion_width;
|
||||
ConfigOptionInt infill_every_layers;
|
||||
ConfigOptionFloatOrPercent infill_overlap;
|
||||
ConfigOptionFloat infill_speed;
|
||||
ConfigOptionBool overhangs;
|
||||
ConfigOptionInt perimeter_extruder;
|
||||
|
@ -245,38 +249,40 @@ class PrintRegionConfig : public virtual StaticPrintConfig
|
|||
this->external_fill_pattern.value = ipRectilinear;
|
||||
this->external_perimeter_extrusion_width.value = 0;
|
||||
this->external_perimeter_extrusion_width.percent = false;
|
||||
this->external_perimeter_speed.value = 70;
|
||||
this->external_perimeter_speed.value = 50;
|
||||
this->external_perimeter_speed.percent = true;
|
||||
this->external_perimeters_first.value = false;
|
||||
this->extra_perimeters.value = true;
|
||||
this->fill_angle.value = 45;
|
||||
this->fill_density.value = 40;
|
||||
this->fill_density.value = 20;
|
||||
this->fill_pattern.value = ipHoneycomb;
|
||||
this->gap_fill_speed.value = 20;
|
||||
this->infill_extruder.value = 1;
|
||||
this->infill_extrusion_width.value = 0;
|
||||
this->infill_extrusion_width.percent = false;
|
||||
this->infill_every_layers.value = 1;
|
||||
this->infill_speed.value = 60;
|
||||
this->infill_overlap.value = 15;
|
||||
this->infill_overlap.percent = true;
|
||||
this->infill_speed.value = 80;
|
||||
this->overhangs.value = true;
|
||||
this->perimeter_extruder.value = 1;
|
||||
this->perimeter_extrusion_width.value = 0;
|
||||
this->perimeter_extrusion_width.percent = false;
|
||||
this->perimeter_speed.value = 30;
|
||||
this->perimeter_speed.value = 60;
|
||||
this->perimeters.value = 3;
|
||||
this->solid_infill_extruder.value = 1;
|
||||
this->small_perimeter_speed.value = 30;
|
||||
this->small_perimeter_speed.value = 15;
|
||||
this->small_perimeter_speed.percent = false;
|
||||
this->solid_infill_below_area.value = 70;
|
||||
this->solid_infill_extrusion_width.value = 0;
|
||||
this->solid_infill_extrusion_width.percent = false;
|
||||
this->solid_infill_every_layers.value = 0;
|
||||
this->solid_infill_speed.value = 60;
|
||||
this->solid_infill_speed.value = 20;
|
||||
this->solid_infill_speed.percent = false;
|
||||
this->thin_walls.value = true;
|
||||
this->top_infill_extrusion_width.value = 0;
|
||||
this->top_infill_extrusion_width.percent = false;
|
||||
this->top_solid_infill_speed.value = 50;
|
||||
this->top_solid_infill_speed.value = 15;
|
||||
this->top_solid_infill_speed.percent = false;
|
||||
this->top_solid_layers.value = 3;
|
||||
};
|
||||
|
@ -297,6 +303,7 @@ class PrintRegionConfig : public virtual StaticPrintConfig
|
|||
if (opt_key == "infill_extruder") return &this->infill_extruder;
|
||||
if (opt_key == "infill_extrusion_width") return &this->infill_extrusion_width;
|
||||
if (opt_key == "infill_every_layers") return &this->infill_every_layers;
|
||||
if (opt_key == "infill_overlap") return &this->infill_overlap;
|
||||
if (opt_key == "infill_speed") return &this->infill_speed;
|
||||
if (opt_key == "overhangs") return &this->overhangs;
|
||||
if (opt_key == "perimeter_extruder") return &this->perimeter_extruder;
|
||||
|
@ -321,6 +328,7 @@ class PrintRegionConfig : public virtual StaticPrintConfig
|
|||
class GCodeConfig : public virtual StaticPrintConfig
|
||||
{
|
||||
public:
|
||||
ConfigOptionString before_layer_gcode;
|
||||
ConfigOptionString end_gcode;
|
||||
ConfigOptionString extrusion_axis;
|
||||
ConfigOptionFloats extrusion_multiplier;
|
||||
|
@ -343,6 +351,7 @@ class GCodeConfig : public virtual StaticPrintConfig
|
|||
ConfigOptionBool use_volumetric_e;
|
||||
|
||||
GCodeConfig() : StaticPrintConfig() {
|
||||
this->before_layer_gcode.value = "";
|
||||
this->end_gcode.value = "M104 S0 ; turn off temperature\nG28 X0 ; home X axis\nM84 ; disable motors\n";
|
||||
this->extrusion_axis.value = "E";
|
||||
this->extrusion_multiplier.values.resize(1);
|
||||
|
@ -354,7 +363,7 @@ class GCodeConfig : public virtual StaticPrintConfig
|
|||
this->layer_gcode.value = "";
|
||||
this->pressure_advance.value = 0;
|
||||
this->retract_length.values.resize(1);
|
||||
this->retract_length.values[0] = 1;
|
||||
this->retract_length.values[0] = 2;
|
||||
this->retract_length_toolchange.values.resize(1);
|
||||
this->retract_length_toolchange.values[0] = 10;
|
||||
this->retract_lift.values.resize(1);
|
||||
|
@ -364,7 +373,7 @@ class GCodeConfig : public virtual StaticPrintConfig
|
|||
this->retract_restart_extra_toolchange.values.resize(1);
|
||||
this->retract_restart_extra_toolchange.values[0] = 0;
|
||||
this->retract_speed.values.resize(1);
|
||||
this->retract_speed.values[0] = 30;
|
||||
this->retract_speed.values[0] = 40;
|
||||
this->start_gcode.value = "G28 ; home all axes\nG1 Z5 F5000 ; lift nozzle\n";
|
||||
this->toolchange_gcode.value = "";
|
||||
this->travel_speed.value = 130;
|
||||
|
@ -374,6 +383,7 @@ class GCodeConfig : public virtual StaticPrintConfig
|
|||
};
|
||||
|
||||
ConfigOption* option(const t_config_option_key opt_key, bool create = false) {
|
||||
if (opt_key == "before_layer_gcode") return &this->before_layer_gcode;
|
||||
if (opt_key == "end_gcode") return &this->end_gcode;
|
||||
if (opt_key == "extrusion_axis") return &this->extrusion_axis;
|
||||
if (opt_key == "extrusion_multiplier") return &this->extrusion_multiplier;
|
||||
|
@ -476,7 +486,7 @@ class PrintConfig : public GCodeConfig
|
|||
this->complete_objects.value = false;
|
||||
this->cooling.value = true;
|
||||
this->default_acceleration.value = 0;
|
||||
this->disable_fan_first_layers.value = 1;
|
||||
this->disable_fan_first_layers.value = 3;
|
||||
this->duplicate_distance.value = 6;
|
||||
this->extruder_clearance_height.value = 20;
|
||||
this->extruder_clearance_radius.value = 20;
|
||||
|
@ -489,7 +499,7 @@ class PrintConfig : public GCodeConfig
|
|||
this->first_layer_extrusion_width.value = 200;
|
||||
this->first_layer_extrusion_width.percent = true;
|
||||
this->first_layer_speed.value = 30;
|
||||
this->first_layer_speed.percent = true;
|
||||
this->first_layer_speed.percent = false;
|
||||
this->first_layer_temperature.values.resize(1);
|
||||
this->first_layer_temperature.values[0] = 200;
|
||||
this->gcode_arcs.value = false;
|
||||
|
@ -510,11 +520,11 @@ class PrintConfig : public GCodeConfig
|
|||
this->retract_before_travel.values.resize(1);
|
||||
this->retract_before_travel.values[0] = 2;
|
||||
this->retract_layer_change.values.resize(1);
|
||||
this->retract_layer_change.values[0] = true;
|
||||
this->retract_layer_change.values[0] = false;
|
||||
this->skirt_distance.value = 6;
|
||||
this->skirt_height.value = 1;
|
||||
this->skirts.value = 1;
|
||||
this->slowdown_below_layer_time.value = 30;
|
||||
this->slowdown_below_layer_time.value = 5;
|
||||
this->spiral_vase.value = false;
|
||||
this->standby_temperature_delta.value = -5;
|
||||
this->temperature.values.resize(1);
|
||||
|
|
|
@ -110,14 +110,14 @@ PrintObject::reload_model_instances()
|
|||
return this->set_copies(copies);
|
||||
}
|
||||
|
||||
void
|
||||
PrintObject::bounding_box(BoundingBox* bb) const
|
||||
BoundingBox
|
||||
PrintObject::bounding_box() const
|
||||
{
|
||||
// since the object is aligned to origin, bounding box coincides with size
|
||||
Points pp;
|
||||
pp.push_back(Point(0,0));
|
||||
pp.push_back(this->size);
|
||||
*bb = BoundingBox(pp);
|
||||
return BoundingBox(pp);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -190,10 +190,9 @@ PrintObject::get_support_layer(int idx)
|
|||
}
|
||||
|
||||
SupportLayer*
|
||||
PrintObject::add_support_layer(int id, coordf_t height, coordf_t print_z,
|
||||
coordf_t slice_z)
|
||||
PrintObject::add_support_layer(int id, coordf_t height, coordf_t print_z)
|
||||
{
|
||||
SupportLayer* layer = new SupportLayer(id, this, height, print_z, slice_z);
|
||||
SupportLayer* layer = new SupportLayer(id, this, height, print_z, -1);
|
||||
support_layers.push_back(layer);
|
||||
return layer;
|
||||
}
|
||||
|
@ -219,6 +218,7 @@ PrintObject::invalidate_state_by_config_options(const std::vector<t_config_optio
|
|||
|| *opt_key == "overhangs"
|
||||
|| *opt_key == "first_layer_extrusion_width"
|
||||
|| *opt_key == "perimeter_extrusion_width"
|
||||
|| *opt_key == "infill_overlap"
|
||||
|| *opt_key == "thin_walls"
|
||||
|| *opt_key == "external_perimeters_first") {
|
||||
steps.insert(posPerimeters);
|
||||
|
|
|
@ -32,9 +32,17 @@ SVG::draw(const Line &line, std::string stroke)
|
|||
}
|
||||
|
||||
void
|
||||
SVG::AddLine(const IntersectionLine &line)
|
||||
SVG::draw(const Lines &lines, std::string stroke)
|
||||
{
|
||||
this->draw(Line(line.a, line.b));
|
||||
for (Lines::const_iterator it = lines.begin(); it != lines.end(); ++it)
|
||||
this->draw(*it, stroke);
|
||||
}
|
||||
|
||||
void
|
||||
SVG::draw(const IntersectionLines &lines, std::string stroke)
|
||||
{
|
||||
for (IntersectionLines::const_iterator it = lines.begin(); it != lines.end(); ++it)
|
||||
this->draw((Line)*it, stroke);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -50,11 +58,25 @@ SVG::draw(const ExPolygon &expolygon, std::string fill)
|
|||
this->path(d, true);
|
||||
}
|
||||
|
||||
void
|
||||
SVG::draw(const ExPolygons &expolygons, std::string fill)
|
||||
{
|
||||
for (ExPolygons::const_iterator it = expolygons.begin(); it != expolygons.end(); ++it)
|
||||
this->draw(*it, fill);
|
||||
}
|
||||
|
||||
void
|
||||
SVG::draw(const Polygon &polygon, std::string fill)
|
||||
{
|
||||
this->fill = fill;
|
||||
this->path(this->get_path_d(polygon, true), true);
|
||||
this->path(this->get_path_d(polygon, true), !fill.empty());
|
||||
}
|
||||
|
||||
void
|
||||
SVG::draw(const Polygons &polygons, std::string fill)
|
||||
{
|
||||
for (Polygons::const_iterator it = polygons.begin(); it != polygons.end(); ++it)
|
||||
this->draw(*it, fill);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -64,6 +86,13 @@ SVG::draw(const Polyline &polyline, std::string stroke)
|
|||
this->path(this->get_path_d(polyline, false), false);
|
||||
}
|
||||
|
||||
void
|
||||
SVG::draw(const Polylines &polylines, std::string stroke)
|
||||
{
|
||||
for (Polylines::const_iterator it = polylines.begin(); it != polylines.end(); ++it)
|
||||
this->draw(*it, fill);
|
||||
}
|
||||
|
||||
void
|
||||
SVG::draw(const Point &point, std::string fill, unsigned int radius)
|
||||
{
|
||||
|
@ -75,6 +104,13 @@ SVG::draw(const Point &point, std::string fill, unsigned int radius)
|
|||
fprintf(this->f, "%s\n", svg.str().c_str());
|
||||
}
|
||||
|
||||
void
|
||||
SVG::draw(const Points &points, std::string fill, unsigned int radius)
|
||||
{
|
||||
for (Points::const_iterator it = points.begin(); it != points.end(); ++it)
|
||||
this->draw(*it, fill, radius);
|
||||
}
|
||||
|
||||
void
|
||||
SVG::path(const std::string &d, bool fill)
|
||||
{
|
||||
|
|
|
@ -15,12 +15,17 @@ class SVG
|
|||
std::string fill, stroke;
|
||||
|
||||
SVG(const char* filename);
|
||||
void AddLine(const IntersectionLine &line);
|
||||
void draw(const Line &line, std::string stroke = "black");
|
||||
void draw(const Lines &lines, std::string stroke = "black");
|
||||
void draw(const IntersectionLines &lines, std::string stroke = "black");
|
||||
void draw(const ExPolygon &expolygon, std::string fill = "grey");
|
||||
void draw(const ExPolygons &expolygons, std::string fill = "grey");
|
||||
void draw(const Polygon &polygon, std::string fill = "grey");
|
||||
void draw(const Polygons &polygons, std::string fill = "grey");
|
||||
void draw(const Polyline &polyline, std::string stroke = "black");
|
||||
void draw(const Polylines &polylines, std::string stroke = "black");
|
||||
void draw(const Point &point, std::string fill = "black", unsigned int radius = 3);
|
||||
void draw(const Points &points, std::string fill = "black", unsigned int radius = 3);
|
||||
void Close();
|
||||
|
||||
private:
|
||||
|
|
|
@ -181,6 +181,7 @@ TriangleMesh::WriteOBJFile(char* output_file) {
|
|||
void TriangleMesh::scale(float factor)
|
||||
{
|
||||
stl_scale(&(this->stl), factor);
|
||||
stl_invalidate_shared_vertices(&this->stl);
|
||||
}
|
||||
|
||||
void TriangleMesh::scale(const Pointf3 &versor)
|
||||
|
@ -190,41 +191,49 @@ void TriangleMesh::scale(const Pointf3 &versor)
|
|||
fversor[1] = versor.y;
|
||||
fversor[2] = versor.z;
|
||||
stl_scale_versor(&this->stl, fversor);
|
||||
stl_invalidate_shared_vertices(&this->stl);
|
||||
}
|
||||
|
||||
void TriangleMesh::translate(float x, float y, float z)
|
||||
{
|
||||
stl_translate_relative(&(this->stl), x, y, z);
|
||||
stl_invalidate_shared_vertices(&this->stl);
|
||||
}
|
||||
|
||||
void TriangleMesh::rotate_x(float angle)
|
||||
{
|
||||
stl_rotate_x(&(this->stl), angle);
|
||||
stl_invalidate_shared_vertices(&this->stl);
|
||||
}
|
||||
|
||||
void TriangleMesh::rotate_y(float angle)
|
||||
{
|
||||
stl_rotate_y(&(this->stl), angle);
|
||||
stl_invalidate_shared_vertices(&this->stl);
|
||||
}
|
||||
|
||||
void TriangleMesh::rotate_z(float angle)
|
||||
{
|
||||
stl_rotate_z(&(this->stl), angle);
|
||||
stl_invalidate_shared_vertices(&this->stl);
|
||||
}
|
||||
|
||||
void TriangleMesh::flip_x()
|
||||
{
|
||||
stl_mirror_yz(&this->stl);
|
||||
stl_invalidate_shared_vertices(&this->stl);
|
||||
}
|
||||
|
||||
void TriangleMesh::flip_y()
|
||||
{
|
||||
stl_mirror_xz(&this->stl);
|
||||
stl_invalidate_shared_vertices(&this->stl);
|
||||
}
|
||||
|
||||
void TriangleMesh::flip_z()
|
||||
{
|
||||
stl_mirror_xy(&this->stl);
|
||||
stl_invalidate_shared_vertices(&this->stl);
|
||||
}
|
||||
|
||||
void TriangleMesh::align_to_origin()
|
||||
|
@ -319,8 +328,8 @@ TriangleMesh::merge(const TriangleMesh &mesh)
|
|||
}
|
||||
|
||||
/* this will return scaled ExPolygons */
|
||||
void
|
||||
TriangleMesh::horizontal_projection(ExPolygons &retval) const
|
||||
ExPolygons
|
||||
TriangleMesh::horizontal_projection() const
|
||||
{
|
||||
Polygons pp;
|
||||
pp.reserve(this->stl.stats.number_of_facets);
|
||||
|
@ -337,11 +346,13 @@ TriangleMesh::horizontal_projection(ExPolygons &retval) const
|
|||
|
||||
// the offset factor was tuned using groovemount.stl
|
||||
offset(pp, &pp, 0.01 / SCALING_FACTOR);
|
||||
ExPolygons retval;
|
||||
union_(pp, &retval, true);
|
||||
return retval;
|
||||
}
|
||||
|
||||
void
|
||||
TriangleMesh::convex_hull(Polygon* hull)
|
||||
Polygon
|
||||
TriangleMesh::convex_hull()
|
||||
{
|
||||
this->require_shared_vertices();
|
||||
Points pp;
|
||||
|
@ -350,25 +361,19 @@ TriangleMesh::convex_hull(Polygon* hull)
|
|||
stl_vertex* v = &this->stl.v_shared[i];
|
||||
pp.push_back(Point(v->x / SCALING_FACTOR, v->y / SCALING_FACTOR));
|
||||
}
|
||||
Slic3r::Geometry::convex_hull(pp, hull);
|
||||
}
|
||||
|
||||
void
|
||||
TriangleMesh::bounding_box(BoundingBoxf3* bb) const
|
||||
{
|
||||
bb->min.x = this->stl.stats.min.x;
|
||||
bb->min.y = this->stl.stats.min.y;
|
||||
bb->min.z = this->stl.stats.min.z;
|
||||
bb->max.x = this->stl.stats.max.x;
|
||||
bb->max.y = this->stl.stats.max.y;
|
||||
bb->max.z = this->stl.stats.max.z;
|
||||
return Slic3r::Geometry::convex_hull(pp);
|
||||
}
|
||||
|
||||
BoundingBoxf3
|
||||
TriangleMesh::bounding_box() const
|
||||
{
|
||||
BoundingBoxf3 bb;
|
||||
this->bounding_box(&bb);
|
||||
bb.min.x = this->stl.stats.min.x;
|
||||
bb.min.y = this->stl.stats.min.y;
|
||||
bb.min.z = this->stl.stats.min.z;
|
||||
bb.max.x = this->stl.stats.max.x;
|
||||
bb.max.y = this->stl.stats.max.y;
|
||||
bb.max.z = this->stl.stats.max.z;
|
||||
return bb;
|
||||
}
|
||||
|
||||
|
@ -511,7 +516,7 @@ TriangleMeshSlicer::slice(const std::vector<float> &z, std::vector<ExPolygons>*
|
|||
for (std::vector<Polygons>::const_iterator loops = layers_p.begin(); loops != layers_p.end(); ++loops) {
|
||||
#ifdef SLIC3R_DEBUG
|
||||
size_t layer_id = loops - layers_p.begin();
|
||||
printf("Layer %zu (slice_z = %.2f): ", layer_id, z[layer_id]);
|
||||
printf("Layer %zu (slice_z = %.2f):\n", layer_id, z[layer_id]);
|
||||
#endif
|
||||
|
||||
this->make_expolygons(*loops, &(*layers)[ loops - layers_p.begin() ]);
|
||||
|
@ -546,15 +551,19 @@ TriangleMeshSlicer::slice_facet(float slice_z, const stl_facet &facet, const int
|
|||
if (a->z == b->z && a->z == slice_z) {
|
||||
// edge is horizontal and belongs to the current layer
|
||||
|
||||
/* We assume that this method is never being called for horizontal
|
||||
facets, so no other edge is going to be on this layer. */
|
||||
stl_vertex* v0 = &this->v_scaled_shared[ this->mesh->stl.v_indices[facet_idx].vertex[0] ];
|
||||
stl_vertex* v1 = &this->v_scaled_shared[ this->mesh->stl.v_indices[facet_idx].vertex[1] ];
|
||||
stl_vertex* v2 = &this->v_scaled_shared[ this->mesh->stl.v_indices[facet_idx].vertex[2] ];
|
||||
stl_vertex &v0 = this->v_scaled_shared[ this->mesh->stl.v_indices[facet_idx].vertex[0] ];
|
||||
stl_vertex &v1 = this->v_scaled_shared[ this->mesh->stl.v_indices[facet_idx].vertex[1] ];
|
||||
stl_vertex &v2 = this->v_scaled_shared[ this->mesh->stl.v_indices[facet_idx].vertex[2] ];
|
||||
IntersectionLine line;
|
||||
if (min_z == max_z) {
|
||||
line.edge_type = feHorizontal;
|
||||
} else if (v0->z < slice_z || v1->z < slice_z || v2->z < slice_z) {
|
||||
if (this->mesh->stl.facet_start[facet_idx].normal.z < 0) {
|
||||
/* if normal points downwards this is a bottom horizontal facet so we reverse
|
||||
its point order */
|
||||
std::swap(a, b);
|
||||
std::swap(a_id, b_id);
|
||||
}
|
||||
} else if (v0.z < slice_z || v1.z < slice_z || v2.z < slice_z) {
|
||||
line.edge_type = feTop;
|
||||
std::swap(a, b);
|
||||
std::swap(a_id, b_id);
|
||||
|
@ -628,12 +637,9 @@ TriangleMeshSlicer::slice_facet(float slice_z, const stl_facet &facet, const int
|
|||
void
|
||||
TriangleMeshSlicer::make_loops(std::vector<IntersectionLine> &lines, Polygons* loops)
|
||||
{
|
||||
|
||||
/*
|
||||
SVG svg("lines.svg");
|
||||
for (IntersectionLines::iterator line = lines.begin(); line != lines.end(); ++line) {
|
||||
svg.AddLine(*line);
|
||||
}
|
||||
svg.draw(lines);
|
||||
svg.Close();
|
||||
*/
|
||||
|
||||
|
@ -704,16 +710,16 @@ TriangleMeshSlicer::make_loops(std::vector<IntersectionLine> &lines, Polygons* l
|
|||
// find a line starting where last one finishes
|
||||
IntersectionLine* next_line = NULL;
|
||||
if (loop.back()->edge_b_id != -1) {
|
||||
IntersectionLinePtrs* candidates = &(by_edge_a_id[loop.back()->edge_b_id]);
|
||||
for (IntersectionLinePtrs::iterator lineptr = candidates->begin(); lineptr != candidates->end(); ++lineptr) {
|
||||
IntersectionLinePtrs &candidates = by_edge_a_id[loop.back()->edge_b_id];
|
||||
for (IntersectionLinePtrs::iterator lineptr = candidates.begin(); lineptr != candidates.end(); ++lineptr) {
|
||||
if ((*lineptr)->skip) continue;
|
||||
next_line = *lineptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (next_line == NULL && loop.back()->b_id != -1) {
|
||||
IntersectionLinePtrs* candidates = &(by_a_id[loop.back()->b_id]);
|
||||
for (IntersectionLinePtrs::iterator lineptr = candidates->begin(); lineptr != candidates->end(); ++lineptr) {
|
||||
IntersectionLinePtrs &candidates = by_a_id[loop.back()->b_id];
|
||||
for (IntersectionLinePtrs::iterator lineptr = candidates.begin(); lineptr != candidates.end(); ++lineptr) {
|
||||
if ((*lineptr)->skip) continue;
|
||||
next_line = *lineptr;
|
||||
break;
|
||||
|
@ -841,9 +847,9 @@ TriangleMeshSlicer::make_expolygons(const Polygons &loops, ExPolygons* slices)
|
|||
of the loops, since the Orientation() function provided by Clipper
|
||||
would do the same, thus repeating the calculation */
|
||||
Polygons::const_iterator loop = loops.begin() + *loop_idx;
|
||||
if (area[*loop_idx] >= 0) {
|
||||
if (area[*loop_idx] > +EPSILON) {
|
||||
p_slices.push_back(*loop);
|
||||
} else {
|
||||
} else if (area[*loop_idx] < -EPSILON) {
|
||||
diff(p_slices, *loop, &p_slices);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,9 +42,8 @@ class TriangleMesh
|
|||
void rotate(double angle, Point* center);
|
||||
TriangleMeshPtrs split() const;
|
||||
void merge(const TriangleMesh &mesh);
|
||||
void horizontal_projection(ExPolygons &retval) const;
|
||||
void convex_hull(Polygon* hull);
|
||||
void bounding_box(BoundingBoxf3* bb) const;
|
||||
ExPolygons horizontal_projection() const;
|
||||
Polygon convex_hull();
|
||||
BoundingBoxf3 bounding_box() const;
|
||||
void reset_repair_stats();
|
||||
bool needed_repair() const;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#define SLIC3R_VERSION "1.2.5-dev"
|
||||
#define SLIC3R_VERSION "1.2.6-dev"
|
||||
|
||||
#define EPSILON 1e-4
|
||||
#define SCALING_FACTOR 0.000001
|
||||
|
|
|
@ -4,7 +4,7 @@ use strict;
|
|||
use warnings;
|
||||
|
||||
use Slic3r::XS;
|
||||
use Test::More tests => 46;
|
||||
use Test::More tests => 49;
|
||||
|
||||
is Slic3r::TriangleMesh::hello_world(), 'Hello world!',
|
||||
'hello world';
|
||||
|
@ -79,7 +79,7 @@ my $cube = {
|
|||
my $m = Slic3r::TriangleMesh->new;
|
||||
$m->ReadFromPerl($cube->{vertices}, $cube->{facets});
|
||||
$m->repair;
|
||||
my @z = (2,4,8,6,8,10,12,14,16,18,20);
|
||||
my @z = (0,2,4,8,6,8,10,12,14,16,18,20);
|
||||
my $result = $m->slice(\@z);
|
||||
my $SCALING_FACTOR = 0.000001;
|
||||
for my $i (0..$#z) {
|
||||
|
@ -95,8 +95,19 @@ my $cube = {
|
|||
[ [0,1,2],[2,1,3],[1,0,4],[5,1,4],[0,2,4],[4,2,6],[7,6,8],[4,6,7],[9,4,7],[7,8,10],[2,3,6],[11,3,12],[7,12,9],[13,12,7],[6,3,11],[11,12,13],[3,1,5],[12,3,5],[5,4,9],[12,5,9],[13,7,10],[14,13,10],[8,15,10],[10,15,14],[6,11,8],[8,11,15],[15,11,13],[14,15,13] ],
|
||||
);
|
||||
$m->repair;
|
||||
my $slices = $m->slice([ 5, 10 ]);
|
||||
is $slices->[0][0]->area, $slices->[1][0]->area, 'slicing a tangent plane includes its area';
|
||||
{
|
||||
# at Z = 10 we have a top horizontal surface
|
||||
my $slices = $m->slice([ 5, 10 ]);
|
||||
is $slices->[0][0]->area, $slices->[1][0]->area, 'slicing a top tangent plane includes its area';
|
||||
}
|
||||
$m->flip_z;
|
||||
{
|
||||
# this second test also checks that performing a second slice on a mesh after
|
||||
# a transformation works properly (shared_vertices is correctly invalidated);
|
||||
# at Z = -10 we have a bottom horizontal surface
|
||||
my $slices = $m->slice([ -5, -10 ]);
|
||||
is $slices->[0][0]->area, $slices->[1][0]->area, 'slicing a bottom tangent plane includes its area';
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
|
|
|
@ -4,7 +4,7 @@ use strict;
|
|||
use warnings;
|
||||
|
||||
use Slic3r::XS;
|
||||
use Test::More tests => 39;
|
||||
use Test::More tests => 40;
|
||||
|
||||
use constant PI => 4 * atan2(1, 1);
|
||||
use constant EPSILON => 1E-4;
|
||||
|
@ -71,4 +71,11 @@ foreach my $base_angle (0, PI/4, PI/2, PI) {
|
|||
}
|
||||
}
|
||||
|
||||
{
|
||||
my $a = Slic3r::Line->new([100, 0], [200, 0]);
|
||||
my $b = Slic3r::Line->new([300, 300], [300, 100]);
|
||||
my $r = $a->intersection_infinite($b);
|
||||
is_deeply $r->pp, [300, 0], 'intersection_infinite';
|
||||
}
|
||||
|
||||
__END__
|
||||
|
|
|
@ -4,7 +4,7 @@ use strict;
|
|||
use warnings;
|
||||
|
||||
use Slic3r::XS;
|
||||
use Test::More tests => 18;
|
||||
use Test::More tests => 19;
|
||||
|
||||
my $square = Slic3r::Polygon->new( # ccw
|
||||
[200, 100],
|
||||
|
@ -155,8 +155,8 @@ if (0) { # Clipper does not preserve polyline orientation
|
|||
}
|
||||
}
|
||||
|
||||
# Disabled until Clipper bug #96 (our issue #2028) is fixed
|
||||
if (0) {
|
||||
{
|
||||
# Clipper bug #96 (our issue #2028)
|
||||
my $subject = Slic3r::Polyline->new(
|
||||
[44735000,31936670],[55270000,31936670],[55270000,25270000],[74730000,25270000],[74730000,44730000],[68063296,44730000],[68063296,55270000],[74730000,55270000],[74730000,74730000],[55270000,74730000],[55270000,68063296],[44730000,68063296],[44730000,74730000],[25270000,74730000],[25270000,55270000],[31936670,55270000],[31936670,44730000],[25270000,44730000],[25270000,25270000],[44730000,25270000],[44730000,31936670]
|
||||
);
|
||||
|
@ -178,4 +178,19 @@ if (0) {
|
|||
is scalar(@$result), 1, 'intersection_ppl - result is not empty';
|
||||
}
|
||||
|
||||
if (0) {
|
||||
# Disabled until Clipper bug #122 is fixed
|
||||
my $subject = [
|
||||
Slic3r::Polyline->new([1975,1975],[25,1975],[25,25],[1975,25],[1975,1975]),
|
||||
];
|
||||
my $clip = [
|
||||
Slic3r::Polygon->new([2025,2025],[-25,2025],[-25,-25],[2025,-25]),
|
||||
Slic3r::Polygon->new([525,525],[525,1475],[1475,1475],[1475,525]),
|
||||
];
|
||||
my $result = Slic3r::Geometry::Clipper::intersection_pl($subject, $clip);
|
||||
###use XXX; YYY $subject->[0]->wkt, [map $_->wkt, @$clip], $result->[0]->wkt;
|
||||
is scalar(@$result), 1, 'intersection_pl - result is not empty';
|
||||
is scalar(@{$result->[0]}), 5, 'intersection_pl - result is not empty';
|
||||
}
|
||||
|
||||
__END__
|
||||
|
|
|
@ -16,8 +16,7 @@
|
|||
void scale(double factor);
|
||||
void translate(double x, double y);
|
||||
void offset(double delta);
|
||||
Polygon* polygon()
|
||||
%code{% RETVAL = new Polygon(); THIS->polygon(RETVAL); %};
|
||||
Clone<Polygon> polygon();
|
||||
Clone<Point> size();
|
||||
Clone<Point> center();
|
||||
Clone<Point> min_point() %code{% RETVAL = THIS->min; %};
|
||||
|
@ -88,6 +87,8 @@ new_from_points(CLASS, points)
|
|||
void translate(double x, double y, double z);
|
||||
Clone<Pointf3> size();
|
||||
Clone<Pointf3> center();
|
||||
Clone<Pointf3> min_point() %code{% RETVAL = THIS->min; %};
|
||||
Clone<Pointf3> max_point() %code{% RETVAL = THIS->max; %};
|
||||
double x_min() %code{% RETVAL = THIS->min.x; %};
|
||||
double x_max() %code{% RETVAL = THIS->max.x; %};
|
||||
double y_min() %code{% RETVAL = THIS->min.y; %};
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
void simplify(double tolerance);
|
||||
Polygons polygons()
|
||||
%code{% RETVAL = *THIS; %};
|
||||
Clone<Polygon> convex_hull();
|
||||
%{
|
||||
|
||||
ExPolygonCollection*
|
||||
|
@ -76,13 +77,5 @@ ExPolygonCollection::append(...)
|
|||
THIS->expolygons.push_back(expolygon);
|
||||
}
|
||||
|
||||
Polygon*
|
||||
ExPolygonCollection::convex_hull()
|
||||
CODE:
|
||||
RETVAL = new Polygon ();
|
||||
THIS->convex_hull(RETVAL);
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
%}
|
||||
};
|
||||
|
|
|
@ -24,8 +24,11 @@
|
|||
Clone<Point> last_point();
|
||||
int count()
|
||||
%code{% RETVAL = THIS->entities.size(); %};
|
||||
bool empty()
|
||||
%code{% RETVAL = THIS->entities.empty(); %};
|
||||
std::vector<size_t> orig_indices()
|
||||
%code{% RETVAL = THIS->orig_indices; %};
|
||||
Polygons grow();
|
||||
%{
|
||||
|
||||
void
|
||||
|
|
|
@ -15,8 +15,7 @@
|
|||
bool make_counter_clockwise();
|
||||
Clone<Point> first_point();
|
||||
Clone<Point> last_point();
|
||||
Polygon* polygon()
|
||||
%code{% RETVAL = new Polygon (*THIS); %};
|
||||
Clone<Polygon> polygon();
|
||||
void append(ExtrusionPath* path)
|
||||
%code{% THIS->paths.push_back(*path); %};
|
||||
double length();
|
||||
|
@ -31,6 +30,7 @@
|
|||
bool is_perimeter();
|
||||
bool is_infill();
|
||||
bool is_solid_infill();
|
||||
Polygons grow();
|
||||
%{
|
||||
|
||||
SV*
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
std::string gcode(Extruder* extruder, double e, double F,
|
||||
double xofs, double yofs, std::string extrusion_axis,
|
||||
std::string gcode_line_suffix);
|
||||
Polygons grow();
|
||||
%{
|
||||
|
||||
ExtrusionPath*
|
||||
|
|
28
xs/xsp/GUI_3DScene.xsp
Normal file
28
xs/xsp/GUI_3DScene.xsp
Normal file
|
@ -0,0 +1,28 @@
|
|||
%module{Slic3r::XS};
|
||||
|
||||
#include <myinit.h>
|
||||
#include "libslic3r/GUI/3DScene.hpp"
|
||||
|
||||
%name{Slic3r::GUI::_3DScene::GLVertexArray} class GLVertexArray {
|
||||
GLVertexArray();
|
||||
~GLVertexArray();
|
||||
void load_mesh(TriangleMesh* mesh) const
|
||||
%code%{ THIS->load_mesh(*mesh); %};
|
||||
size_t size() const
|
||||
%code%{ RETVAL = THIS->verts.size(); %};
|
||||
void* verts_ptr() const
|
||||
%code%{ RETVAL = THIS->verts.empty() ? 0 : &THIS->verts.front(); %};
|
||||
void* norms_ptr() const
|
||||
%code%{ RETVAL = THIS->verts.empty() ? 0 : &THIS->norms.front(); %};
|
||||
};
|
||||
|
||||
%package{Slic3r::GUI::_3DScene};
|
||||
%{
|
||||
|
||||
void
|
||||
_extrusionentity_to_verts_do(Lines lines, std::vector<double> widths, std::vector<double> heights, bool closed, double top_z, Point* copy, GLVertexArray* qverts, GLVertexArray* tverts)
|
||||
CODE:
|
||||
_3DScene::_extrusionentity_to_verts_do(lines, widths, heights, closed,
|
||||
top_z, *copy, qverts, tverts);
|
||||
|
||||
%}
|
|
@ -29,12 +29,11 @@ directions_parallel_within(angle1, angle2, max_diff)
|
|||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
Polygon*
|
||||
Clone<Polygon>
|
||||
convex_hull(points)
|
||||
Points points
|
||||
CODE:
|
||||
RETVAL = new Polygon ();
|
||||
Slic3r::Geometry::convex_hull(points, RETVAL);
|
||||
RETVAL = Slic3r::Geometry::convex_hull(points);
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
|
@ -79,4 +78,13 @@ deg2rad(angle)
|
|||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
Polygons
|
||||
simplify_polygons(polygons, tolerance)
|
||||
Polygons polygons
|
||||
double tolerance
|
||||
CODE:
|
||||
Slic3r::Geometry::simplify_polygons(polygons, tolerance, &RETVAL);
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
%}
|
||||
|
|
|
@ -26,15 +26,17 @@
|
|||
Ref<ExtrusionEntityCollection> fills()
|
||||
%code%{ RETVAL = &THIS->fills; %};
|
||||
|
||||
Flow* flow(FlowRole role, bool bridge = false, double width = -1)
|
||||
%code%{ RETVAL = new Flow(THIS->flow(role, bridge, width)); %};
|
||||
Clone<Flow> flow(FlowRole role, bool bridge = false, double width = -1)
|
||||
%code%{ RETVAL = THIS->flow(role, bridge, width); %};
|
||||
void merge_slices();
|
||||
void prepare_fill_surfaces();
|
||||
};
|
||||
|
||||
%name{Slic3r::Layer} class Layer {
|
||||
// owned by PrintObject, no constructor/destructor
|
||||
|
||||
int id();
|
||||
void set_id(int id);
|
||||
Ref<PrintObject> object();
|
||||
Ref<Layer> upper_layer()
|
||||
%code%{ RETVAL = THIS->upper_layer; %};
|
||||
|
@ -89,6 +91,7 @@
|
|||
// copies of some Layer methods, because the parameter wrapper code
|
||||
// gets confused about getting a Layer::Support instead of a Layer
|
||||
int id();
|
||||
void set_id(int id);
|
||||
Ref<PrintObject> object();
|
||||
Ref<SupportLayer> upper_layer()
|
||||
%code%{ RETVAL = (SupportLayer*)THIS->upper_layer; %};
|
||||
|
|
|
@ -28,11 +28,19 @@
|
|||
bool parallel_to(double angle);
|
||||
bool parallel_to_line(Line* line)
|
||||
%code{% RETVAL = THIS->parallel_to(*line); %};
|
||||
Point* midpoint();
|
||||
Clone<Point> midpoint();
|
||||
Clone<Point> point_at(double distance);
|
||||
Polyline* as_polyline()
|
||||
%code{% RETVAL = new Polyline(*THIS); %};
|
||||
Clone<Point> intersection_infinite(Line* other)
|
||||
%code{%
|
||||
Point p;
|
||||
bool res = THIS->intersection_infinite(*other, &p);
|
||||
if (!res) CONFESS("Intersection failed");
|
||||
RETVAL = p;
|
||||
%};
|
||||
Clone<Polyline> as_polyline()
|
||||
%code{% RETVAL = Polyline(*THIS); %};
|
||||
Clone<Point> normal();
|
||||
Clone<Point> vector();
|
||||
%{
|
||||
|
||||
Line*
|
||||
|
@ -79,4 +87,5 @@ Line::coincides_with(line_sv)
|
|||
Ref<Pointf3> b()
|
||||
%code{% RETVAL = &THIS->b; %};
|
||||
Clone<Pointf3> intersect_plane(double z);
|
||||
void scale(double factor);
|
||||
};
|
||||
|
|
|
@ -59,19 +59,13 @@
|
|||
// void duplicate(size_t copies_num, coordf_t distance, const BoundingBox &bb);
|
||||
bool has_objects_with_no_instances();
|
||||
bool add_default_instances();
|
||||
BoundingBoxf3* bounding_box()
|
||||
%code%{
|
||||
RETVAL = new BoundingBoxf3();
|
||||
THIS->bounding_box(RETVAL);
|
||||
%};
|
||||
Clone<BoundingBoxf3> bounding_box();
|
||||
void center_instances_around_point(Pointf* point)
|
||||
%code%{ THIS->center_instances_around_point(*point); %};
|
||||
void align_instances_to_origin();
|
||||
void translate(double x, double y, double z);
|
||||
TriangleMesh* mesh()
|
||||
%code%{ RETVAL = new TriangleMesh(); THIS->mesh(RETVAL); %};
|
||||
TriangleMesh* raw_mesh()
|
||||
%code%{ RETVAL = new TriangleMesh(); THIS->raw_mesh(RETVAL); %};
|
||||
Clone<TriangleMesh> mesh();
|
||||
Clone<TriangleMesh> raw_mesh();
|
||||
// void split_meshes();
|
||||
// std::string get_material_name(t_model_material_id material_id);
|
||||
|
||||
|
@ -119,20 +113,10 @@ ModelMaterial::attributes()
|
|||
|
||||
void invalidate_bounding_box();
|
||||
void update_bounding_box();
|
||||
TriangleMesh* mesh()
|
||||
%code%{ RETVAL = new TriangleMesh(); THIS->mesh(RETVAL); %};
|
||||
TriangleMesh* raw_mesh()
|
||||
%code%{ RETVAL = new TriangleMesh(); THIS->raw_mesh(RETVAL); %};
|
||||
BoundingBoxf3* raw_bounding_box()
|
||||
%code%{
|
||||
RETVAL = new BoundingBoxf3();
|
||||
THIS->raw_bounding_box(RETVAL);
|
||||
%};
|
||||
BoundingBoxf3* instance_bounding_box(int idx)
|
||||
%code%{
|
||||
RETVAL = new BoundingBoxf3();
|
||||
THIS->instance_bounding_box(idx, RETVAL);
|
||||
%};
|
||||
Clone<TriangleMesh> mesh();
|
||||
Clone<TriangleMesh> raw_mesh();
|
||||
Clone<BoundingBoxf3> raw_bounding_box();
|
||||
Clone<BoundingBoxf3> instance_bounding_box(int idx);
|
||||
|
||||
Ref<BoundingBoxf3> _bounding_box(BoundingBoxf3* new_bbox = NULL)
|
||||
%code{%
|
||||
|
@ -147,11 +131,7 @@ ModelMaterial::attributes()
|
|||
|
||||
RETVAL = &THIS->_bounding_box;
|
||||
%};
|
||||
BoundingBoxf3* bounding_box()
|
||||
%code%{
|
||||
RETVAL = new BoundingBoxf3();
|
||||
THIS->bounding_box(RETVAL);
|
||||
%};
|
||||
Clone<BoundingBoxf3> bounding_box();
|
||||
|
||||
%name{_add_volume} Ref<ModelVolume> add_volume(TriangleMesh* mesh)
|
||||
%code%{ RETVAL = THIS->add_volume(*mesh); %};
|
||||
|
|
|
@ -10,6 +10,6 @@
|
|||
~MotionPlanner();
|
||||
|
||||
int islands_count();
|
||||
Polyline* shortest_path(Point* from, Point* to)
|
||||
%code%{ RETVAL = new Polyline(); THIS->shortest_path(*from, *to, RETVAL); %};
|
||||
Clone<Polyline> shortest_path(Point* from, Point* to)
|
||||
%code%{ RETVAL = THIS->shortest_path(*from, *to); %};
|
||||
};
|
||||
|
|
|
@ -22,9 +22,13 @@
|
|||
%code{% RETVAL = THIS->x; %};
|
||||
long y()
|
||||
%code{% RETVAL = THIS->y; %};
|
||||
void set_x(long val)
|
||||
%code{% THIS->x = val; %};
|
||||
void set_y(long val)
|
||||
%code{% THIS->y = val; %};
|
||||
int nearest_point_index(Points points);
|
||||
Point* nearest_point(Points points)
|
||||
%code{% RETVAL = new Point(); THIS->nearest_point(points, RETVAL); %};
|
||||
Clone<Point> nearest_point(Points points)
|
||||
%code{% Point p; THIS->nearest_point(points, &p); RETVAL = p; %};
|
||||
double distance_to(Point* point)
|
||||
%code{% RETVAL = THIS->distance_to(*point); %};
|
||||
double distance_to_line(Line* line)
|
||||
|
|
|
@ -19,14 +19,11 @@
|
|||
void translate(double x, double y);
|
||||
void reverse();
|
||||
Lines lines();
|
||||
Polyline* split_at_vertex(Point* point)
|
||||
%code{% RETVAL = new Polyline(); THIS->split_at_vertex(*point, RETVAL); %};
|
||||
Polyline* split_at_index(int index)
|
||||
%code{% RETVAL = new Polyline(); THIS->split_at_index(index, RETVAL); %};
|
||||
Polyline* split_at_first_point()
|
||||
%code{% RETVAL = new Polyline(); THIS->split_at_first_point(RETVAL); %};
|
||||
Points equally_spaced_points(double distance)
|
||||
%code{% THIS->equally_spaced_points(distance, &RETVAL); %};
|
||||
Clone<Polyline> split_at_vertex(Point* point)
|
||||
%code{% RETVAL = THIS->split_at_vertex(*point); %};
|
||||
Clone<Polyline> split_at_index(int index);
|
||||
Clone<Polyline> split_at_first_point();
|
||||
Points equally_spaced_points(double distance);
|
||||
double length();
|
||||
double area();
|
||||
bool is_counter_clockwise();
|
||||
|
@ -41,16 +38,10 @@
|
|||
Polygons triangulate_convex()
|
||||
%code{% THIS->triangulate_convex(&RETVAL); %};
|
||||
Clone<Point> centroid();
|
||||
BoundingBox* bounding_box()
|
||||
%code{%
|
||||
RETVAL = new BoundingBox();
|
||||
THIS->bounding_box(RETVAL);
|
||||
%};
|
||||
Clone<BoundingBox> bounding_box();
|
||||
std::string wkt();
|
||||
Points concave_points(double angle)
|
||||
%code{% THIS->concave_points(angle, &RETVAL); %};
|
||||
Points convex_points(double angle)
|
||||
%code{% THIS->convex_points(angle, &RETVAL); %};
|
||||
Points concave_points(double angle);
|
||||
Points convex_points(double angle);
|
||||
%{
|
||||
|
||||
Polygon*
|
||||
|
|
|
@ -23,8 +23,7 @@
|
|||
Lines lines();
|
||||
Clone<Point> first_point();
|
||||
Clone<Point> last_point();
|
||||
Points equally_spaced_points(double distance)
|
||||
%code{% THIS->equally_spaced_points(distance, &RETVAL); %};
|
||||
Points equally_spaced_points(double distance);
|
||||
double length();
|
||||
bool is_valid();
|
||||
void clip_end(double distance);
|
||||
|
@ -37,11 +36,8 @@
|
|||
void split_at(Point* point, Polyline* p1, Polyline* p2)
|
||||
%code{% THIS->split_at(*point, p1, p2); %};
|
||||
bool is_straight();
|
||||
BoundingBox* bounding_box()
|
||||
%code{%
|
||||
RETVAL = new BoundingBox();
|
||||
THIS->bounding_box(RETVAL);
|
||||
%};
|
||||
Clone<BoundingBox> bounding_box();
|
||||
void remove_duplicate_points();
|
||||
std::string wkt();
|
||||
%{
|
||||
|
||||
|
|
|
@ -35,8 +35,8 @@ _constant()
|
|||
%code%{ RETVAL = &THIS->config; %};
|
||||
Ref<Print> print();
|
||||
|
||||
Flow* flow(FlowRole role, double layer_height, bool bridge, bool first_layer, double width, PrintObject* object)
|
||||
%code%{ RETVAL = new Flow(THIS->flow(role, layer_height, bridge, first_layer, width, *object)); %};
|
||||
Clone<Flow> flow(FlowRole role, double layer_height, bool bridge, bool first_layer, double width, PrintObject* object)
|
||||
%code%{ RETVAL = THIS->flow(role, layer_height, bridge, first_layer, width, *object); %};
|
||||
};
|
||||
|
||||
|
||||
|
@ -61,11 +61,7 @@ _constant()
|
|||
%code%{ RETVAL = THIS->layer_height_ranges; %};
|
||||
Ref<Point3> size()
|
||||
%code%{ RETVAL = &THIS->size; %};
|
||||
BoundingBox* bounding_box()
|
||||
%code{%
|
||||
RETVAL = new BoundingBox();
|
||||
THIS->bounding_box(RETVAL);
|
||||
%};
|
||||
Clone<BoundingBox> bounding_box();
|
||||
Ref<Point> _copies_shift()
|
||||
%code%{ RETVAL = &THIS->_copies_shift; %};
|
||||
|
||||
|
@ -99,7 +95,7 @@ _constant()
|
|||
size_t support_layer_count();
|
||||
void clear_support_layers();
|
||||
Ref<SupportLayer> get_support_layer(int idx);
|
||||
Ref<SupportLayer> add_support_layer(int id, coordf_t height, coordf_t print_z, coordf_t slice_z);
|
||||
Ref<SupportLayer> add_support_layer(int id, coordf_t height, coordf_t print_z);
|
||||
void delete_support_layer(int idx);
|
||||
|
||||
bool invalidate_state_by_config_options(std::vector<std::string> opt_keys);
|
||||
|
|
|
@ -31,19 +31,11 @@
|
|||
TriangleMeshPtrs split();
|
||||
void merge(TriangleMesh* mesh)
|
||||
%code{% THIS->merge(*mesh); %};
|
||||
ExPolygons horizontal_projection()
|
||||
%code{% THIS->horizontal_projection(RETVAL); %};
|
||||
BoundingBoxf3* bounding_box()
|
||||
%code{%
|
||||
RETVAL = new BoundingBoxf3();
|
||||
THIS->bounding_box(RETVAL);
|
||||
%};
|
||||
Pointf3* center()
|
||||
%code{%
|
||||
BoundingBoxf3 bb;
|
||||
THIS->bounding_box(&bb);
|
||||
RETVAL = new Pointf3(bb.center());
|
||||
%};
|
||||
ExPolygons horizontal_projection();
|
||||
Clone<Polygon> convex_hull();
|
||||
Clone<BoundingBoxf3> bounding_box();
|
||||
Clone<Pointf3> center()
|
||||
%code{% RETVAL = THIS->bounding_box().center(); %};
|
||||
int facets_count();
|
||||
void reset_repair_stats();
|
||||
%{
|
||||
|
@ -196,14 +188,6 @@ TriangleMesh::bb3()
|
|||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
Polygon*
|
||||
TriangleMesh::convex_hull()
|
||||
CODE:
|
||||
RETVAL = new Polygon ();
|
||||
THIS->convex_hull(RETVAL);
|
||||
OUTPUT:
|
||||
RETVAL
|
||||
|
||||
%}
|
||||
};
|
||||
|
||||
|
|
|
@ -186,6 +186,8 @@ BridgeDetector* O_OBJECT_SLIC3R
|
|||
Ref<BridgeDetector> O_OBJECT_SLIC3R_T
|
||||
Clone<BridgeDetector> O_OBJECT_SLIC3R_T
|
||||
|
||||
GLVertexArray* O_OBJECT_SLIC3R
|
||||
|
||||
ExtrusionLoopRole T_UV
|
||||
ExtrusionRole T_UV
|
||||
FlowRole T_UV
|
||||
|
@ -329,13 +331,11 @@ T_ARRAYREF
|
|||
if (SvROK($arg) && SvTYPE(SvRV($arg)) == SVt_PVAV) {
|
||||
AV* av = (AV*)SvRV($arg);
|
||||
const unsigned int len = av_len(av)+1;
|
||||
$type* tmp = new $type(len);
|
||||
$var.resize(len);
|
||||
for (unsigned int i = 0; i < len; i++) {
|
||||
SV** elem = av_fetch(av, i, 0);
|
||||
(*tmp)[i].from_SV_check(*elem);
|
||||
$var\[i].from_SV_check(*elem);
|
||||
}
|
||||
$var = *tmp;
|
||||
delete tmp;
|
||||
} else
|
||||
Perl_croak(aTHX_ \"%s: %s is not an array reference\",
|
||||
${$ALIAS?\q[GvNAME(CvGV(cv))]:\qq[\"$pname\"]},
|
||||
|
@ -396,6 +396,7 @@ T_STD_STRING
|
|||
T_STD_VECTOR_STD_STRING
|
||||
AV* av = newAV();
|
||||
$arg = newRV_noinc((SV*)av);
|
||||
sv_2mortal($arg);
|
||||
const unsigned int len = $var.size();
|
||||
if (len)
|
||||
av_extend(av, len-1);
|
||||
|
@ -408,6 +409,7 @@ T_STD_VECTOR_STD_STRING
|
|||
T_STD_VECTOR_INT
|
||||
AV* av = newAV();
|
||||
$arg = newRV_noinc((SV*)av);
|
||||
sv_2mortal($arg);
|
||||
const unsigned int len = $var.size();
|
||||
if (len)
|
||||
av_extend(av, len-1);
|
||||
|
@ -418,6 +420,7 @@ T_STD_VECTOR_INT
|
|||
T_STD_VECTOR_UINT
|
||||
AV* av = newAV();
|
||||
$arg = newRV_noinc((SV*)av);
|
||||
sv_2mortal($arg);
|
||||
const unsigned int len = $var.size();
|
||||
if (len)
|
||||
av_extend(av, len-1);
|
||||
|
@ -428,6 +431,7 @@ T_STD_VECTOR_UINT
|
|||
T_STD_VECTOR_DOUBLE
|
||||
AV* av = newAV();
|
||||
$arg = newRV_noinc((SV*)av);
|
||||
sv_2mortal($arg);
|
||||
const unsigned int len = $var.size();
|
||||
if (len)
|
||||
av_extend(av, len-1);
|
||||
|
@ -458,7 +462,6 @@ T_ARRAYREF
|
|||
for (${type}::const_iterator it = $var.begin(); it != $var.end(); ++it) {
|
||||
av_store(av, i++, perl_to_SV_clone_ref(*it));
|
||||
}
|
||||
$var.clear();
|
||||
|
||||
T_ARRAYREF_PTR
|
||||
AV* av = newAV();
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
%typemap{std::vector<unsigned int>*};
|
||||
%typemap{std::vector<std::string>};
|
||||
%typemap{t_layer_height_ranges};
|
||||
%typemap{void*};
|
||||
%typemap{SV*};
|
||||
%typemap{AV*};
|
||||
%typemap{Point*};
|
||||
|
@ -167,6 +168,7 @@
|
|||
%typemap{ModelInstancePtrs*};
|
||||
%typemap{Ref<ModelInstancePtrs>}{simple};
|
||||
%typemap{Clone<ModelInstancePtrs>}{simple};
|
||||
%typemap{GLVertexArray*};
|
||||
|
||||
%typemap{PrintRegionPtrs*};
|
||||
%typemap{PrintObjectPtrs*};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue