Merge branch 'master' into sender

Conflicts:
	Build.PL
This commit is contained in:
Alessandro Ranellucci 2015-02-01 14:07:32 +01:00
commit 3ae6f2630e
106 changed files with 2262 additions and 994 deletions

View file

@ -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

View file

@ -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

View file

@ -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());
}

View file

@ -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;
};
};

View file

@ -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;
}

View file

@ -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

View file

@ -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;
};

View file

@ -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

View file

@ -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;
};
}

View file

@ -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");

View file

@ -22,6 +22,7 @@ class ExtrusionEntityCollection : public ExtrusionEntity
void reverse();
Point first_point() const;
Point last_point() const;
Polygons grow() const;
};
}

View file

@ -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);
}

View file

@ -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);
}

View 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 &copy,
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
}

View 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 &copy,
GLVertexArray* qverts, GLVertexArray* tverts);
};
}
#endif

View file

@ -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
{

View file

@ -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:

View file

@ -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)
{

View file

@ -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();
};

View file

@ -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

View file

@ -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

View file

@ -26,9 +26,10 @@ class Line
void rotate(double angle, const Point &center);
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);

View file

@ -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();
}

View file

@ -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);

View file

@ -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

View file

@ -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);
};
}

View file

@ -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

View file

@ -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);

View file

@ -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 &center);
@ -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);

View file

@ -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

View file

@ -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);

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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)
{

View file

@ -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:

View file

@ -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);
}
}

View file

@ -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;

View file

@ -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

View file

@ -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';
}
}
{

View file

@ -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__

View file

@ -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__

View file

@ -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; %};

View file

@ -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
%}
};

View file

@ -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

View file

@ -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*

View file

@ -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
View 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);
%}

View file

@ -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
%}

View file

@ -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; %};

View file

@ -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);
};

View file

@ -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); %};

View file

@ -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); %};
};

View file

@ -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)

View file

@ -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*

View file

@ -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();
%{

View file

@ -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);

View file

@ -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
%}
};

View file

@ -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();

View file

@ -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*};