Bugfix: crash when rendering lines with zero length in 3D preview. #2569
This commit is contained in:
parent
a10a554e2a
commit
c264969962
@ -1198,6 +1198,7 @@ sub _extrusionentity_to_verts {
|
|||||||
return;
|
return;
|
||||||
} elsif ($entity->isa('Slic3r::ExtrusionPath')) {
|
} elsif ($entity->isa('Slic3r::ExtrusionPath')) {
|
||||||
my $polyline = $entity->polyline->clone;
|
my $polyline = $entity->polyline->clone;
|
||||||
|
$polyline->remove_duplicate_points;
|
||||||
$polyline->translate(@$copy);
|
$polyline->translate(@$copy);
|
||||||
$lines = $polyline->lines;
|
$lines = $polyline->lines;
|
||||||
$widths = [ map $entity->width, 0..$#$lines ];
|
$widths = [ map $entity->width, 0..$#$lines ];
|
||||||
@ -1210,6 +1211,7 @@ sub _extrusionentity_to_verts {
|
|||||||
$closed = 1;
|
$closed = 1;
|
||||||
foreach my $path (@$entity) {
|
foreach my $path (@$entity) {
|
||||||
my $polyline = $path->polyline->clone;
|
my $polyline = $path->polyline->clone;
|
||||||
|
$polyline->remove_duplicate_points;
|
||||||
$polyline->translate(@$copy);
|
$polyline->translate(@$copy);
|
||||||
my $path_lines = $polyline->lines;
|
my $path_lines = $polyline->lines;
|
||||||
push @$lines, @$path_lines;
|
push @$lines, @$path_lines;
|
||||||
@ -1217,7 +1219,6 @@ sub _extrusionentity_to_verts {
|
|||||||
push @$heights, map $path->height, 0..$#$path_lines;
|
push @$heights, map $path->height, 0..$#$path_lines;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Slic3r::GUI::_3DScene::_extrusionentity_to_verts_do($lines, $widths, $heights,
|
Slic3r::GUI::_3DScene::_extrusionentity_to_verts_do($lines, $widths, $heights,
|
||||||
$closed, $top_z, $copy, $qverts, $tverts);
|
$closed, $top_z, $copy, $qverts, $tverts);
|
||||||
}
|
}
|
||||||
|
@ -172,13 +172,6 @@ ExtrusionPath::grow() const
|
|||||||
return pp;
|
return pp;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExtrusionLoop::operator Polygon() const
|
|
||||||
{
|
|
||||||
Polygon polygon;
|
|
||||||
this->polygon(&polygon);
|
|
||||||
return polygon;
|
|
||||||
}
|
|
||||||
|
|
||||||
ExtrusionLoop*
|
ExtrusionLoop*
|
||||||
ExtrusionLoop::clone() const
|
ExtrusionLoop::clone() const
|
||||||
{
|
{
|
||||||
@ -188,8 +181,7 @@ ExtrusionLoop::clone() const
|
|||||||
bool
|
bool
|
||||||
ExtrusionLoop::make_clockwise()
|
ExtrusionLoop::make_clockwise()
|
||||||
{
|
{
|
||||||
Polygon polygon = *this;
|
bool was_ccw = this->polygon().is_counter_clockwise();
|
||||||
bool was_ccw = polygon.is_counter_clockwise();
|
|
||||||
if (was_ccw) this->reverse();
|
if (was_ccw) this->reverse();
|
||||||
return was_ccw;
|
return was_ccw;
|
||||||
}
|
}
|
||||||
@ -197,8 +189,7 @@ ExtrusionLoop::make_clockwise()
|
|||||||
bool
|
bool
|
||||||
ExtrusionLoop::make_counter_clockwise()
|
ExtrusionLoop::make_counter_clockwise()
|
||||||
{
|
{
|
||||||
Polygon polygon = *this;
|
bool was_cw = this->polygon().is_clockwise();
|
||||||
bool was_cw = polygon.is_clockwise();
|
|
||||||
if (was_cw) this->reverse();
|
if (was_cw) this->reverse();
|
||||||
return was_cw;
|
return was_cw;
|
||||||
}
|
}
|
||||||
@ -223,13 +214,15 @@ ExtrusionLoop::last_point() const
|
|||||||
return this->paths.back().polyline.points.back(); // which coincides with first_point(), by the way
|
return this->paths.back().polyline.points.back(); // which coincides with first_point(), by the way
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
Polygon
|
||||||
ExtrusionLoop::polygon(Polygon* polygon) const
|
ExtrusionLoop::polygon() const
|
||||||
{
|
{
|
||||||
|
Polygon polygon;
|
||||||
for (ExtrusionPaths::const_iterator path = this->paths.begin(); path != this->paths.end(); ++path) {
|
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)
|
// 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
|
double
|
||||||
|
@ -92,14 +92,13 @@ class ExtrusionLoop : public ExtrusionEntity
|
|||||||
bool is_loop() const {
|
bool is_loop() const {
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
operator Polygon() const;
|
|
||||||
ExtrusionLoop* clone() const;
|
ExtrusionLoop* clone() const;
|
||||||
bool make_clockwise();
|
bool make_clockwise();
|
||||||
bool make_counter_clockwise();
|
bool make_counter_clockwise();
|
||||||
void reverse();
|
void reverse();
|
||||||
Point first_point() const;
|
Point first_point() const;
|
||||||
Point last_point() const;
|
Point last_point() const;
|
||||||
void polygon(Polygon* polygon) const;
|
Polygon polygon() const;
|
||||||
double length() const;
|
double length() const;
|
||||||
bool split_at_vertex(const Point &point);
|
bool split_at_vertex(const Point &point);
|
||||||
void split_at(const Point &point);
|
void split_at(const Point &point);
|
||||||
|
@ -2,25 +2,33 @@
|
|||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
|
// caller is responsible for supplying NO lines with zero length
|
||||||
void
|
void
|
||||||
_3DScene::_extrusionentity_to_verts_do(const Lines &lines, const std::vector<double> &widths,
|
_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 ©,
|
const std::vector<double> &heights, bool closed, double top_z, const Point ©,
|
||||||
GLVertexArray* qverts, GLVertexArray* tverts)
|
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;
|
Line prev_line;
|
||||||
Pointf prev_b1, prev_b2;
|
Pointf prev_b1, prev_b2;
|
||||||
Vectorf3 prev_xy_left_normal, prev_xy_right_normal;
|
Vectorf3 prev_xy_left_normal, prev_xy_right_normal;
|
||||||
|
|
||||||
// loop once more in case of closed loops
|
// loop once more in case of closed loops
|
||||||
bool first_done = false;
|
bool first_done = false;
|
||||||
for (int i = 0; i <= lines.size(); ++i) {
|
for (size_t i = 0; i <= lines.size(); ++i) {
|
||||||
if (i == lines.size()) i = 0;
|
if (i == lines.size()) i = 0;
|
||||||
|
|
||||||
const Line &line = lines.at(i);
|
const Line &line = lines.at(i);
|
||||||
if (i == 0 && first_done && !closed) break;
|
if (i == 0 && first_done && !closed) break;
|
||||||
|
|
||||||
double len = line.length();
|
double len = line.length();
|
||||||
if (len == 0) continue;
|
|
||||||
double unscaled_len = unscale(len);
|
double unscaled_len = unscale(len);
|
||||||
|
|
||||||
double bottom_z = top_z - heights.at(i);
|
double bottom_z = top_z - heights.at(i);
|
||||||
@ -52,7 +60,6 @@ _3DScene::_extrusionentity_to_verts_do(const Lines &lines, const std::vector<dou
|
|||||||
// if we're making a ccw turn, draw the triangles on the right side, otherwise draw them on the left side
|
// 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);
|
double ccw = line.b.ccw(prev_line);
|
||||||
if (ccw > EPSILON) {
|
if (ccw > EPSILON) {
|
||||||
tverts->reserve_more(6);
|
|
||||||
// top-right vertex triangle between previous line and this one
|
// top-right vertex triangle between previous line and this one
|
||||||
{
|
{
|
||||||
// use the normal going to the right calculated for the previous line
|
// use the normal going to the right calculated for the previous line
|
||||||
@ -82,7 +89,6 @@ _3DScene::_extrusionentity_to_verts_do(const Lines &lines, const std::vector<dou
|
|||||||
tverts->push_vert(a1.x, a1.y, middle_z);
|
tverts->push_vert(a1.x, a1.y, middle_z);
|
||||||
}
|
}
|
||||||
} else if (ccw < -EPSILON) {
|
} else if (ccw < -EPSILON) {
|
||||||
tverts->reserve_more(6);
|
|
||||||
// top-left vertex triangle between previous line and this one
|
// top-left vertex triangle between previous line and this one
|
||||||
{
|
{
|
||||||
// use the normal going to the left calculated for the previous line
|
// use the normal going to the left calculated for the previous line
|
||||||
@ -126,8 +132,6 @@ _3DScene::_extrusionentity_to_verts_do(const Lines &lines, const std::vector<dou
|
|||||||
if (!closed) {
|
if (!closed) {
|
||||||
// terminate open paths with caps
|
// terminate open paths with caps
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
qverts->reserve_more(4);
|
|
||||||
|
|
||||||
// normal pointing downwards
|
// normal pointing 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(a.x, a.y, bottom_z);
|
||||||
@ -144,8 +148,6 @@ _3DScene::_extrusionentity_to_verts_do(const Lines &lines, const std::vector<dou
|
|||||||
qverts->push_norm(xy_left_normal);
|
qverts->push_norm(xy_left_normal);
|
||||||
qverts->push_vert(a2.x, a2.y, middle_z);
|
qverts->push_vert(a2.x, a2.y, middle_z);
|
||||||
} else if (i == lines.size()-1) {
|
} else if (i == lines.size()-1) {
|
||||||
qverts->reserve_more(4);
|
|
||||||
|
|
||||||
// normal pointing downwards
|
// normal pointing 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(b.x, b.y, bottom_z);
|
||||||
@ -164,8 +166,6 @@ _3DScene::_extrusionentity_to_verts_do(const Lines &lines, const std::vector<dou
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
qverts->reserve_more(16);
|
|
||||||
|
|
||||||
// bottom-right face
|
// bottom-right face
|
||||||
{
|
{
|
||||||
// normal going downwards
|
// normal going downwards
|
||||||
@ -228,7 +228,7 @@ _3DScene::_extrusionentity_to_verts_do(const Lines &lines, const std::vector<dou
|
|||||||
void
|
void
|
||||||
GLVertexArray::load_mesh(const TriangleMesh &mesh)
|
GLVertexArray::load_mesh(const TriangleMesh &mesh)
|
||||||
{
|
{
|
||||||
this->reserve_more(3 * mesh.facets_count());
|
this->reserve_more(3 * 3 * mesh.facets_count());
|
||||||
|
|
||||||
for (int i = 0; i < mesh.stl.stats.number_of_facets; ++i) {
|
for (int i = 0; i < mesh.stl.stats.number_of_facets; ++i) {
|
||||||
stl_facet &facet = mesh.stl.facet_start[i];
|
stl_facet &facet = mesh.stl.facet_start[i];
|
||||||
|
@ -89,6 +89,17 @@ MultiPoint::bounding_box() const
|
|||||||
return 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
|
Points
|
||||||
MultiPoint::_douglas_peucker(const Points &points, const double tolerance)
|
MultiPoint::_douglas_peucker(const Points &points, const double tolerance)
|
||||||
{
|
{
|
||||||
|
@ -32,6 +32,7 @@ class MultiPoint
|
|||||||
int find_point(const Point &point) const;
|
int find_point(const Point &point) const;
|
||||||
bool has_boundary_point(const Point &point) const;
|
bool has_boundary_point(const Point &point) const;
|
||||||
BoundingBox bounding_box() const;
|
BoundingBox bounding_box() const;
|
||||||
|
void remove_duplicate_points();
|
||||||
|
|
||||||
static Points _douglas_peucker(const Points &points, const double tolerance);
|
static Points _douglas_peucker(const Points &points, const double tolerance);
|
||||||
|
|
||||||
|
@ -15,8 +15,7 @@
|
|||||||
bool make_counter_clockwise();
|
bool make_counter_clockwise();
|
||||||
Clone<Point> first_point();
|
Clone<Point> first_point();
|
||||||
Clone<Point> last_point();
|
Clone<Point> last_point();
|
||||||
Clone<Polygon> polygon()
|
Clone<Polygon> polygon();
|
||||||
%code{% RETVAL = Polygon(*THIS); %};
|
|
||||||
void append(ExtrusionPath* path)
|
void append(ExtrusionPath* path)
|
||||||
%code{% THIS->paths.push_back(*path); %};
|
%code{% THIS->paths.push_back(*path); %};
|
||||||
double length();
|
double length();
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
%code{% THIS->split_at(*point, p1, p2); %};
|
%code{% THIS->split_at(*point, p1, p2); %};
|
||||||
bool is_straight();
|
bool is_straight();
|
||||||
Clone<BoundingBox> bounding_box();
|
Clone<BoundingBox> bounding_box();
|
||||||
|
void remove_duplicate_points();
|
||||||
std::string wkt();
|
std::string wkt();
|
||||||
%{
|
%{
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user