TriangleMeshSlic3r used unordered_map, which was terribly horribly shamelessly
slow on mingw. Rewrote using std::vector<>, which is blazing fast.
This commit is contained in:
parent
a219ae3d27
commit
1909c75c21
1 changed files with 66 additions and 33 deletions
|
@ -7,7 +7,6 @@
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <unordered_map>
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
@ -555,7 +554,6 @@ TriangleMesh::require_shared_vertices()
|
||||||
TriangleMeshSlicer::TriangleMeshSlicer(TriangleMesh* _mesh) :
|
TriangleMeshSlicer::TriangleMeshSlicer(TriangleMesh* _mesh) :
|
||||||
mesh(_mesh)
|
mesh(_mesh)
|
||||||
{
|
{
|
||||||
BOOST_LOG_TRIVIAL(trace) << "TriangleMeshSlicer::constructor";
|
|
||||||
_mesh->require_shared_vertices();
|
_mesh->require_shared_vertices();
|
||||||
facets_edges.assign(_mesh->stl.stats.number_of_facets * 3, -1);
|
facets_edges.assign(_mesh->stl.stats.number_of_facets * 3, -1);
|
||||||
v_scaled_shared.assign(_mesh->stl.v_shared, _mesh->stl.v_shared + _mesh->stl.stats.shared_vertices);
|
v_scaled_shared.assign(_mesh->stl.v_shared, _mesh->stl.v_shared + _mesh->stl.stats.shared_vertices);
|
||||||
|
@ -566,40 +564,75 @@ TriangleMeshSlicer::TriangleMeshSlicer(TriangleMesh* _mesh) :
|
||||||
this->v_scaled_shared[i].z /= float(SCALING_FACTOR);
|
this->v_scaled_shared[i].z /= float(SCALING_FACTOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
// build a table to map a facet_idx to its three edge indices
|
// Create a mapping from triangle edge into face.
|
||||||
// a_id,b_id => edge_idx
|
struct EdgeToFace {
|
||||||
struct pairhash {
|
// Index of the 1st vertex of the triangle edge. vertex_low <= vertex_high.
|
||||||
std::size_t operator()(const std::pair<int, int> &x) const
|
int vertex_low;
|
||||||
{ return std::hash<int>()(x.first) ^ std::hash<int>()(x.second); }
|
// Index of the 2nd vertex of the triangle edge.
|
||||||
|
int vertex_high;
|
||||||
|
// Index of a triangular face.
|
||||||
|
int face;
|
||||||
|
// Index of edge in the face, starting with 1. Negative indices if the edge was stored reverse in (vertex_low, vertex_high).
|
||||||
|
int face_edge;
|
||||||
|
bool operator==(const EdgeToFace &other) { return vertex_low == other.vertex_low && vertex_high == other.vertex_high; }
|
||||||
|
bool operator<(const EdgeToFace &other) { return vertex_low < other.vertex_low || (vertex_low == other.vertex_low && vertex_high < other.vertex_high); }
|
||||||
};
|
};
|
||||||
std::unordered_map<std::pair<int, int>, int, pairhash> edges_map;
|
std::vector<EdgeToFace> edges_map;
|
||||||
int num_edges = 0;
|
edges_map.assign(this->mesh->stl.stats.number_of_facets * 3, EdgeToFace());
|
||||||
for (int facet_idx = 0; facet_idx < this->mesh->stl.stats.number_of_facets; ++ facet_idx) {
|
for (int facet_idx = 0; facet_idx < this->mesh->stl.stats.number_of_facets; ++ facet_idx)
|
||||||
for (int i = 0; i < 3; ++ i) {
|
for (int i = 0; i < 3; ++ i) {
|
||||||
// Vertex indices of th ith edge of facet_idx.
|
EdgeToFace &e2f = edges_map[facet_idx*3+i];
|
||||||
int a_id = this->mesh->stl.v_indices[facet_idx].vertex[i];
|
e2f.vertex_low = this->mesh->stl.v_indices[facet_idx].vertex[i];
|
||||||
int b_id = this->mesh->stl.v_indices[facet_idx].vertex[(i + 1) % 3];
|
e2f.vertex_high = this->mesh->stl.v_indices[facet_idx].vertex[(i + 1) % 3];
|
||||||
int edge_idx;
|
e2f.face = facet_idx;
|
||||||
auto my_edge = edges_map.find(std::make_pair(b_id, a_id));
|
// 1 based indexing, to be always strictly positive.
|
||||||
if (my_edge == edges_map.end()) {
|
e2f.face_edge = i + 1;
|
||||||
/* admesh can assign the same edge ID to more than two facets (which is
|
if (e2f.vertex_low > e2f.vertex_high) {
|
||||||
still topologically correct), so we have to search for a duplicate of
|
// Sort the vertices
|
||||||
this edge too in case it was already seen in this orientation */
|
std::swap(e2f.vertex_low, e2f.vertex_high);
|
||||||
my_edge = edges_map.find(std::make_pair(a_id, b_id));
|
// and make the face_edge negative to indicate a flipped edge.
|
||||||
if (my_edge != edges_map.end()) {
|
e2f.face_edge = - e2f.face_edge;
|
||||||
edge_idx = my_edge->second;
|
}
|
||||||
} else {
|
|
||||||
// edge isn't listed in table, so we insert it
|
|
||||||
edges_map[std::make_pair(a_id, b_id)] = edge_idx = num_edges ++;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
edge_idx = my_edge->second;
|
|
||||||
this->facets_edges[facet_idx * 3 + i] = edge_idx;
|
|
||||||
|
|
||||||
#ifdef SLIC3R_TRIANGLEMESH_DEBUG
|
|
||||||
printf(" [facet %d, edge %d] a_id = %d, b_id = %d --> edge %d\n", facet_idx, i, a_id, b_id, edge_idx);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
std::sort(edges_map.begin(), edges_map.end());
|
||||||
|
|
||||||
|
// Assign a unique common edge id to touching triangle edges.
|
||||||
|
int num_edges = 0;
|
||||||
|
for (size_t i = 0; i < edges_map.size(); ++ i) {
|
||||||
|
EdgeToFace &edge_i = edges_map[i];
|
||||||
|
if (edge_i.face == -1)
|
||||||
|
// This edge has been connected to some neighbor already.
|
||||||
|
continue;
|
||||||
|
// Unconnected edge. Find its neighbor with the correct orientation.
|
||||||
|
size_t j;
|
||||||
|
bool found = false;
|
||||||
|
for (j = i + 1; j < edges_map.size() && edge_i == edges_map[j]; ++ j)
|
||||||
|
if (edge_i.face_edge * edges_map[j].face_edge < 0 && edges_map[j].face != -1) {
|
||||||
|
// Faces touching with opposite oriented edges and none of the edges is connected yet.
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (! found) {
|
||||||
|
//FIXME Vojtech: Trying to find an edge with equal orientation. This smells.
|
||||||
|
// admesh can assign the same edge ID to more than two facets (which is
|
||||||
|
// still topologically correct), so we have to search for a duplicate of
|
||||||
|
// this edge too in case it was already seen in this orientation
|
||||||
|
for (j = i + 1; j < edges_map.size() && edge_i == edges_map[j]; ++ j)
|
||||||
|
if (edges_map[j].face != -1) {
|
||||||
|
// Faces touching with equally oriented edges and none of the edges is connected yet.
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Assign an edge index to the 1st face.
|
||||||
|
this->facets_edges[edge_i.face * 3 + std::abs(edge_i.face_edge) - 1] = num_edges;
|
||||||
|
if (found) {
|
||||||
|
EdgeToFace &edge_j = edges_map[j];
|
||||||
|
this->facets_edges[edge_j.face * 3 + std::abs(edge_j.face_edge) - 1] = num_edges;
|
||||||
|
// Mark the edge as connected.
|
||||||
|
edge_j.face = -1;
|
||||||
|
}
|
||||||
|
++ num_edges;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue