Almost finished porting slice()

This commit is contained in:
Alessandro Ranellucci 2013-09-09 12:18:52 +02:00
parent 46bd407da4
commit dbf739318a
2 changed files with 43 additions and 25 deletions

View File

@ -170,14 +170,14 @@ TriangleMesh::slice(const std::vector<double> &z)
typedef std::vector<t_edge> t_edges; // edge_idx => a_id,b_id typedef std::vector<t_edge> t_edges; // edge_idx => a_id,b_id
typedef std::map<t_edge,int> t_edges_map; // a_id,b_id => edge_idx typedef std::map<t_edge,int> t_edges_map; // a_id,b_id => edge_idx
typedef std::vector< std::vector<int> > t_facets_edges; typedef std::vector< std::vector<int> > t_facets_edges;
t_edges edges;
t_facets_edges facets_edges; t_facets_edges facets_edges;
// reserve() instad of resize() because otherwise we couldn't read .size() below to assign edge_idx
edges.reserve(this->stl.stats.number_of_facets * 3); // number of edges = number of facets * 3
facets_edges.resize(this->stl.stats.number_of_facets); facets_edges.resize(this->stl.stats.number_of_facets);
{ {
t_edges edges;
// reserve() instad of resize() because otherwise we couldn't read .size() below to assign edge_idx
edges.reserve(this->stl.stats.number_of_facets * 3); // number of edges = number of facets * 3
t_edges_map edges_map; t_edges_map edges_map;
for (int facet_idx = 0; facet_idx < this->stl.stats.number_of_facets; facet_idx++) { for (int facet_idx = 0; facet_idx < this->stl.stats.number_of_facets; facet_idx++) {
facets_edges[facet_idx].resize(3); facets_edges[facet_idx].resize(3);
@ -238,6 +238,7 @@ TriangleMesh::slice(const std::vector<double> &z)
double slice_z = *it; double slice_z = *it;
std::vector<IntersectionPoint> points; std::vector<IntersectionPoint> points;
std::vector< std::vector<IntersectionPoint>::size_type > points_on_layer, intersection_points; std::vector< std::vector<IntersectionPoint>::size_type > points_on_layer, intersection_points;
bool found_horizontal_edge = false;
/* reorder vertices so that the first one is the one with lowest Z /* reorder vertices so that the first one is the one with lowest Z
this is needed to get all intersection lines in a consistent order this is needed to get all intersection lines in a consistent order
@ -252,10 +253,10 @@ TriangleMesh::slice(const std::vector<double> &z)
} }
for (int j = i; (j-i) < 3; j++) { // loop through facet edges for (int j = i; (j-i) < 3; j++) { // loop through facet edges
int edge_id = facets_edges[facet_idx][j % 3]; int edge_id = facets_edges[facet_idx][j % 3];
t_edge edge = edges[edge_id]; int a_id = this->stl.v_indices[facet_idx].vertex[j % 3];
int b_id = this->stl.v_indices[facet_idx].vertex[(j+1) % 3];
stl_vertex* a = &(this->stl.v_shared[edge.first]); stl_vertex* a = &(this->stl.v_shared[a_id]);
stl_vertex* b = &(this->stl.v_shared[edge.second]); stl_vertex* b = &(this->stl.v_shared[b_id]);
if (a->z == b->z && a->z == slice_z) { if (a->z == b->z && a->z == slice_z) {
// edge is horizontal and belongs to the current layer // edge is horizontal and belongs to the current layer
@ -266,21 +267,25 @@ TriangleMesh::slice(const std::vector<double> &z)
/* We assume that this method is never being called for horizontal /* We assume that this method is never being called for horizontal
facets, so no other edge is going to be on this layer. */ facets, so no other edge is going to be on this layer. */
IntersectionLine line; IntersectionLine line;
line.a.x = a->x;
line.a.y = a->y;
line.b.x = b->x;
line.b.y = b->y;
line.a_id = edge.first;
line.b_id = edge.second;
if (this->stl.v_indices[facet_idx].vertex[0] < slice_z if (this->stl.v_indices[facet_idx].vertex[0] < slice_z
|| this->stl.v_indices[facet_idx].vertex[1] < slice_z || this->stl.v_indices[facet_idx].vertex[1] < slice_z
|| this->stl.v_indices[facet_idx].vertex[2] < slice_z) { || this->stl.v_indices[facet_idx].vertex[2] < slice_z) {
line.edge_type = feTop; line.edge_type = feTop;
std::swap(a, b);
std::swap(a_id, b_id);
} else { } else {
line.edge_type = feBottom; line.edge_type = feBottom;
} }
line.a.x = a->x;
line.a.y = a->y;
line.b.x = b->x;
line.b.y = b->y;
line.a_id = a_id;
line.b_id = b_id;
lines[layer_idx].push_back(line); lines[layer_idx].push_back(line);
found_horizontal_edge = true;
break;
} else if (a->z == slice_z) { } else if (a->z == slice_z) {
#ifdef SLIC3R_DEBUG #ifdef SLIC3R_DEBUG
printf("A point on plane!\n"); printf("A point on plane!\n");
@ -289,7 +294,7 @@ TriangleMesh::slice(const std::vector<double> &z)
IntersectionPoint point; IntersectionPoint point;
point.x = a->x; point.x = a->x;
point.y = a->y; point.y = a->y;
point.point_id = edge.first; point.point_id = a_id;
points.push_back(point); points.push_back(point);
points_on_layer.push_back(points.size()-1); points_on_layer.push_back(points.size()-1);
} else if (b->z == slice_z) { } else if (b->z == slice_z) {
@ -300,7 +305,7 @@ TriangleMesh::slice(const std::vector<double> &z)
IntersectionPoint point; IntersectionPoint point;
point.x = b->x; point.x = b->x;
point.y = b->y; point.y = b->y;
point.point_id = edge.second; point.point_id = b_id;
points.push_back(point); points.push_back(point);
points_on_layer.push_back(points.size()-1); points_on_layer.push_back(points.size()-1);
} else if ((a->z < slice_z && b->z > slice_z) || (b->z < slice_z && a->z > slice_z)) { } else if ((a->z < slice_z && b->z > slice_z) || (b->z < slice_z && a->z > slice_z)) {
@ -317,18 +322,20 @@ TriangleMesh::slice(const std::vector<double> &z)
intersection_points.push_back(points.size()-1); intersection_points.push_back(points.size()-1);
} }
} }
if (found_horizontal_edge) continue;
if (points_on_layer.size() == 2) { if (points_on_layer.size() == 2) {
if (intersection_points.size() == 1) { if (intersection_points.size() == 1) {
points.erase( points.begin() + points_on_layer[1] ); points.erase( points.begin() + points_on_layer[1] );
} else if (intersection_points.empty()) { } else if (intersection_points.empty()) {
if (points[ points_on_layer[0] ].coincides_with(&points[ points_on_layer[1] ])) continue; if (points[ points_on_layer[0] ].coincides_with(&points[ points_on_layer[1] ])) {
continue;
}
} }
} }
if (!points.empty()) { if (!points.empty()) {
assert(points.size() == 2); // facets must intersect each plane 0 or 2 times assert(points.size() == 2); // facets must intersect each plane 0 or 2 times
IntersectionLine line; IntersectionLine line;
line.a.x = points[1].x; line.a.x = points[1].x;
line.a.y = points[1].y; line.a.y = points[1].y;
@ -349,12 +356,12 @@ TriangleMesh::slice(const std::vector<double> &z)
int layer_idx = it - lines.begin(); int layer_idx = it - lines.begin();
// remove tangent edges // remove tangent edges
for (IntersectionLines::iterator line = (*it).begin(); line != (*it).end(); ++line) { for (IntersectionLines::iterator line = it->begin(); line != it->end(); ++line) {
if (line->skip || line->edge_type == feNone) continue; if (line->skip || line->edge_type == feNone) continue;
/* if the line is a facet edge, find another facet edge /* if the line is a facet edge, find another facet edge
having the same endpoints but in reverse order */ having the same endpoints but in reverse order */
for (IntersectionLines::iterator line2 = line + 1; line2 != (*it).end(); ++line2) { for (IntersectionLines::iterator line2 = line + 1; line2 != it->end(); ++line2) {
if (line2->skip || line2->edge_type == feNone) continue; if (line2->skip || line2->edge_type == feNone) continue;
// are these facets adjacent? (sharing a common edge on this layer) // are these facets adjacent? (sharing a common edge on this layer)
@ -377,9 +384,9 @@ TriangleMesh::slice(const std::vector<double> &z)
// build a map of lines by edge_a_id and a_id // build a map of lines by edge_a_id and a_id
std::vector<IntersectionLinePtrs> by_edge_a_id, by_a_id; std::vector<IntersectionLinePtrs> by_edge_a_id, by_a_id;
by_edge_a_id.resize(edges.size()); by_edge_a_id.resize(this->stl.stats.number_of_facets * 3);
by_a_id.resize(this->stl.stats.shared_vertices); by_a_id.resize(this->stl.stats.shared_vertices);
for (IntersectionLines::iterator line = (*it).begin(); line != (*it).end(); ++line) { for (IntersectionLines::iterator line = it->begin(); line != it->end(); ++line) {
if (line->skip) continue; if (line->skip) continue;
if (line->edge_a_id != -1) by_edge_a_id[line->edge_a_id].push_back(&(*line)); if (line->edge_a_id != -1) by_edge_a_id[line->edge_a_id].push_back(&(*line));
if (line->a_id != -1) by_a_id[line->a_id].push_back(&(*line)); if (line->a_id != -1) by_a_id[line->a_id].push_back(&(*line));
@ -388,7 +395,7 @@ TriangleMesh::slice(const std::vector<double> &z)
CYCLE: while (1) { CYCLE: while (1) {
// take first spare line and start a new loop // take first spare line and start a new loop
IntersectionLine* first_line = NULL; IntersectionLine* first_line = NULL;
for (IntersectionLines::iterator line = (*it).begin(); line != (*it).end(); ++line) { for (IntersectionLines::iterator line = it->begin(); line != it->end(); ++line) {
if (line->skip) continue; if (line->skip) continue;
first_line = &(*line); first_line = &(*line);
break; break;
@ -398,6 +405,12 @@ TriangleMesh::slice(const std::vector<double> &z)
IntersectionLinePtrs loop; IntersectionLinePtrs loop;
loop.push_back(first_line); loop.push_back(first_line);
/*
printf("first_line edge_a_id = %d, edge_b_id = %d, a_id = %d, b_id = %d, a = %d,%d, b = %d,%d\n",
first_line->edge_a_id, first_line->edge_b_id, first_line->a_id, first_line->b_id,
first_line->a.x, first_line->a.y, first_line->b.x, first_line->b.y);
*/
while (1) { while (1) {
// find a line starting where last one finishes // find a line starting where last one finishes
IntersectionLine* next_line = NULL; IntersectionLine* next_line = NULL;
@ -441,6 +454,11 @@ TriangleMesh::slice(const std::vector<double> &z)
//// push @failed_loops, [@loop]; //// push @failed_loops, [@loop];
goto CYCLE; goto CYCLE;
} }
/*
printf("next_line edge_a_id = %d, edge_b_id = %d, a_id = %d, b_id = %d, a = %d,%d, b = %d,%d\n",
next_line->edge_a_id, next_line->edge_b_id, next_line->a_id, next_line->b_id,
next_line->a.x, next_line->a.y, next_line->b.x, next_line->b.y);
*/
loop.push_back(next_line); loop.push_back(next_line);
next_line->skip = true; next_line->skip = true;
} }

View File

@ -4,7 +4,7 @@ use strict;
use warnings; use warnings;
use Slic3r::XS; use Slic3r::XS;
use Test::More tests => 10; use Test::More tests => 43;
is Slic3r::TriangleMesh::XS::hello_world(), 'Hello world!', is Slic3r::TriangleMesh::XS::hello_world(), 'Hello world!',
'hello world'; 'hello world';
@ -44,7 +44,7 @@ my $cube = {
ok abs($m->size->[0] - sqrt(2)*40) < 1E-4, 'rotate'; ok abs($m->size->[0] - sqrt(2)*40) < 1E-4, 'rotate';
} }
if (0) { {
my $m = Slic3r::TriangleMesh::XS->new; my $m = Slic3r::TriangleMesh::XS->new;
$m->ReadFromPerl($cube->{vertices}, $cube->{facets}); $m->ReadFromPerl($cube->{vertices}, $cube->{facets});
$m->Repair; $m->Repair;