WIP: Admesh - replacement of C memory allocation with std vectors
This commit is contained in:
parent
3ab886b747
commit
8da54139c4
@ -60,7 +60,7 @@ if (MSVC)
|
|||||||
# /bigobj (Increase Number of Sections in .Obj file)
|
# /bigobj (Increase Number of Sections in .Obj file)
|
||||||
# error C3859: virtual memory range for PCH exceeded; please recompile with a command line option of '-Zm90' or greater
|
# error C3859: virtual memory range for PCH exceeded; please recompile with a command line option of '-Zm90' or greater
|
||||||
# Generate symbols at every build target, even for the release.
|
# Generate symbols at every build target, even for the release.
|
||||||
add_compile_options(-bigobj -Zm316 /Zi)
|
add_compile_options(-bigobj -Zm520 /Zi)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
# Display and check CMAKE_PREFIX_PATH
|
# Display and check CMAKE_PREFIX_PATH
|
||||||
|
@ -97,18 +97,10 @@ void stl_check_facets_exact(stl_file *stl)
|
|||||||
stl->stats.freed = 0;
|
stl->stats.freed = 0;
|
||||||
stl->stats.collisions = 0;
|
stl->stats.collisions = 0;
|
||||||
stl->M = (int)hash_size_from_nr_faces(stl->stats.number_of_facets);
|
stl->M = (int)hash_size_from_nr_faces(stl->stats.number_of_facets);
|
||||||
for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i) {
|
for (auto &neighbor : stl->neighbors_start)
|
||||||
// initialize neighbors list to -1 to mark unconnected edges
|
neighbor.reset();
|
||||||
stl->neighbors_start[i].neighbor[0] = -1;
|
stl->heads.assign(stl->M, nullptr);
|
||||||
stl->neighbors_start[i].neighbor[1] = -1;
|
stl->tail = new stl_hash_edge;
|
||||||
stl->neighbors_start[i].neighbor[2] = -1;
|
|
||||||
}
|
|
||||||
stl->heads = (stl_hash_edge**)calloc(stl->M, sizeof(*stl->heads));
|
|
||||||
if (stl->heads == NULL)
|
|
||||||
perror("stl_initialize_facet_check_exact");
|
|
||||||
stl->tail = (stl_hash_edge*)malloc(sizeof(stl_hash_edge));
|
|
||||||
if (stl->tail == NULL)
|
|
||||||
perror("stl_initialize_facet_check_exact");
|
|
||||||
stl->tail->next = stl->tail;
|
stl->tail->next = stl->tail;
|
||||||
for (int i = 0; i < stl->M; ++ i)
|
for (int i = 0; i < stl->M; ++ i)
|
||||||
stl->heads[i] = stl->tail;
|
stl->heads[i] = stl->tail;
|
||||||
@ -180,7 +172,7 @@ static void insert_hash_edge(stl_file *stl, stl_hash_edge edge,
|
|||||||
stl_hash_edge *temp;
|
stl_hash_edge *temp;
|
||||||
if(link == stl->tail) {
|
if(link == stl->tail) {
|
||||||
/* This list doesn't have any edges currently in it. Add this one. */
|
/* This list doesn't have any edges currently in it. Add this one. */
|
||||||
new_edge = (stl_hash_edge*)malloc(sizeof(stl_hash_edge));
|
new_edge = new stl_hash_edge;
|
||||||
if(new_edge == NULL) perror("insert_hash_edge");
|
if(new_edge == NULL) perror("insert_hash_edge");
|
||||||
stl->stats.malloced++;
|
stl->stats.malloced++;
|
||||||
*new_edge = edge;
|
*new_edge = edge;
|
||||||
@ -192,7 +184,7 @@ static void insert_hash_edge(stl_file *stl, stl_hash_edge edge,
|
|||||||
match_neighbors(stl, &edge, link);
|
match_neighbors(stl, &edge, link);
|
||||||
/* Delete the matched edge from the list. */
|
/* Delete the matched edge from the list. */
|
||||||
stl->heads[chain_number] = link->next;
|
stl->heads[chain_number] = link->next;
|
||||||
free(link);
|
delete link;
|
||||||
stl->stats.freed++;
|
stl->stats.freed++;
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
@ -200,7 +192,7 @@ static void insert_hash_edge(stl_file *stl, stl_hash_edge edge,
|
|||||||
for(;;) {
|
for(;;) {
|
||||||
if(link->next == stl->tail) {
|
if(link->next == stl->tail) {
|
||||||
/* This is the last item in the list. Insert a new edge. */
|
/* This is the last item in the list. Insert a new edge. */
|
||||||
new_edge = (stl_hash_edge*)malloc(sizeof(stl_hash_edge));
|
new_edge = new stl_hash_edge;
|
||||||
if(new_edge == NULL) perror("insert_hash_edge");
|
if(new_edge == NULL) perror("insert_hash_edge");
|
||||||
stl->stats.malloced++;
|
stl->stats.malloced++;
|
||||||
*new_edge = edge;
|
*new_edge = edge;
|
||||||
@ -215,7 +207,7 @@ static void insert_hash_edge(stl_file *stl, stl_hash_edge edge,
|
|||||||
/* Delete the matched edge from the list. */
|
/* Delete the matched edge from the list. */
|
||||||
temp = link->next;
|
temp = link->next;
|
||||||
link->next = link->next->next;
|
link->next = link->next->next;
|
||||||
free(temp);
|
delete temp;
|
||||||
stl->stats.freed++;
|
stl->stats.freed++;
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
@ -307,48 +299,38 @@ static void stl_free_edges(stl_file *stl)
|
|||||||
for (int i = 0; i < stl->M; i++) {
|
for (int i = 0; i < stl->M; i++) {
|
||||||
for (stl_hash_edge *temp = stl->heads[i]; stl->heads[i] != stl->tail; temp = stl->heads[i]) {
|
for (stl_hash_edge *temp = stl->heads[i]; stl->heads[i] != stl->tail; temp = stl->heads[i]) {
|
||||||
stl->heads[i] = stl->heads[i]->next;
|
stl->heads[i] = stl->heads[i]->next;
|
||||||
free(temp);
|
delete temp;
|
||||||
++ stl->stats.freed;
|
++ stl->stats.freed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(stl->heads);
|
stl->heads.clear();
|
||||||
stl->heads = nullptr;
|
delete stl->tail;
|
||||||
free(stl->tail);
|
|
||||||
stl->tail = nullptr;
|
stl->tail = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void stl_initialize_facet_check_nearby(stl_file *stl)
|
static void stl_initialize_facet_check_nearby(stl_file *stl)
|
||||||
{
|
{
|
||||||
int i;
|
if (stl->error)
|
||||||
|
return;
|
||||||
|
|
||||||
if (stl->error) return;
|
stl->stats.malloced = 0;
|
||||||
|
stl->stats.freed = 0;
|
||||||
|
stl->stats.collisions = 0;
|
||||||
|
|
||||||
stl->stats.malloced = 0;
|
/* tolerance = STL_MAX(stl->stats.shortest_edge, tolerance);*/
|
||||||
stl->stats.freed = 0;
|
/* tolerance = STL_MAX((stl->stats.bounding_diameter / 500000.0), tolerance);*/
|
||||||
stl->stats.collisions = 0;
|
/* tolerance *= 0.5;*/
|
||||||
|
stl->M = (int)hash_size_from_nr_faces(stl->stats.number_of_facets);
|
||||||
|
|
||||||
/* tolerance = STL_MAX(stl->stats.shortest_edge, tolerance);*/
|
stl->heads.assign(stl->M, nullptr);
|
||||||
/* tolerance = STL_MAX((stl->stats.bounding_diameter / 500000.0), tolerance);*/
|
stl->tail = new stl_hash_edge;
|
||||||
/* tolerance *= 0.5;*/
|
stl->tail->next = stl->tail;
|
||||||
|
|
||||||
stl->M = (int)hash_size_from_nr_faces(stl->stats.number_of_facets);
|
for (int i = 0; i < stl->M; ++ i)
|
||||||
|
stl->heads[i] = stl->tail;
|
||||||
stl->heads = (stl_hash_edge**)calloc(stl->M, sizeof(*stl->heads));
|
|
||||||
if(stl->heads == NULL) perror("stl_initialize_facet_check_nearby");
|
|
||||||
|
|
||||||
stl->tail = (stl_hash_edge*)malloc(sizeof(stl_hash_edge));
|
|
||||||
if(stl->tail == NULL) perror("stl_initialize_facet_check_nearby");
|
|
||||||
|
|
||||||
stl->tail->next = stl->tail;
|
|
||||||
|
|
||||||
for(i = 0; i < stl->M; i++) {
|
|
||||||
stl->heads[i] = stl->tail;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
stl_record_neighbors(stl_file *stl,
|
stl_record_neighbors(stl_file *stl,
|
||||||
stl_hash_edge *edge_a, stl_hash_edge *edge_b) {
|
stl_hash_edge *edge_a, stl_hash_edge *edge_b) {
|
||||||
@ -358,29 +340,19 @@ stl_record_neighbors(stl_file *stl,
|
|||||||
if (stl->error) return;
|
if (stl->error) return;
|
||||||
|
|
||||||
/* Facet a's neighbor is facet b */
|
/* Facet a's neighbor is facet b */
|
||||||
stl->neighbors_start[edge_a->facet_number].neighbor[edge_a->which_edge % 3] =
|
stl->neighbors_start[edge_a->facet_number].neighbor[edge_a->which_edge % 3] = edge_b->facet_number; /* sets the .neighbor part */
|
||||||
edge_b->facet_number; /* sets the .neighbor part */
|
stl->neighbors_start[edge_a->facet_number].which_vertex_not[edge_a->which_edge % 3] = (edge_b->which_edge + 2) % 3; /* sets the .which_vertex_not part */
|
||||||
|
|
||||||
stl->neighbors_start[edge_a->facet_number].
|
|
||||||
which_vertex_not[edge_a->which_edge % 3] =
|
|
||||||
(edge_b->which_edge + 2) % 3; /* sets the .which_vertex_not part */
|
|
||||||
|
|
||||||
/* Facet b's neighbor is facet a */
|
/* Facet b's neighbor is facet a */
|
||||||
stl->neighbors_start[edge_b->facet_number].neighbor[edge_b->which_edge % 3] =
|
stl->neighbors_start[edge_b->facet_number].neighbor[edge_b->which_edge % 3] = edge_a->facet_number; /* sets the .neighbor part */
|
||||||
edge_a->facet_number; /* sets the .neighbor part */
|
stl->neighbors_start[edge_b->facet_number].which_vertex_not[edge_b->which_edge % 3] = (edge_a->which_edge + 2) % 3; /* sets the .which_vertex_not part */
|
||||||
|
|
||||||
stl->neighbors_start[edge_b->facet_number].
|
|
||||||
which_vertex_not[edge_b->which_edge % 3] =
|
|
||||||
(edge_a->which_edge + 2) % 3; /* sets the .which_vertex_not part */
|
|
||||||
|
|
||||||
if( ((edge_a->which_edge < 3) && (edge_b->which_edge < 3))
|
if( ((edge_a->which_edge < 3) && (edge_b->which_edge < 3))
|
||||||
|| ((edge_a->which_edge > 2) && (edge_b->which_edge > 2))) {
|
|| ((edge_a->which_edge > 2) && (edge_b->which_edge > 2))) {
|
||||||
/* these facets are oriented in opposite directions. */
|
/* these facets are oriented in opposite directions. */
|
||||||
/* their normals are probably messed up. */
|
/* their normals are probably messed up. */
|
||||||
stl->neighbors_start[edge_a->facet_number].
|
stl->neighbors_start[edge_a->facet_number].which_vertex_not[edge_a->which_edge % 3] += 3;
|
||||||
which_vertex_not[edge_a->which_edge % 3] += 3;
|
stl->neighbors_start[edge_b->facet_number].which_vertex_not[edge_b->which_edge % 3] += 3;
|
||||||
stl->neighbors_start[edge_b->facet_number].
|
|
||||||
which_vertex_not[edge_b->which_edge % 3] += 3;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -561,8 +533,7 @@ stl_which_vertices_to_change(stl_file *stl, stl_hash_edge *edge_a,
|
|||||||
*facet1 = -1;
|
*facet1 = -1;
|
||||||
} else {
|
} else {
|
||||||
if( (stl->neighbors_start[edge_a->facet_number].neighbor[v1a] == -1)
|
if( (stl->neighbors_start[edge_a->facet_number].neighbor[v1a] == -1)
|
||||||
&& (stl->neighbors_start[edge_a->facet_number].
|
&& (stl->neighbors_start[edge_a->facet_number].neighbor[(v1a + 2) % 3] == -1)) {
|
||||||
neighbor[(v1a + 2) % 3] == -1)) {
|
|
||||||
/* This vertex has no neighbors. This is a good one to change */
|
/* This vertex has no neighbors. This is a good one to change */
|
||||||
*facet1 = edge_a->facet_number;
|
*facet1 = edge_a->facet_number;
|
||||||
*vertex1 = v1a;
|
*vertex1 = v1a;
|
||||||
@ -581,8 +552,7 @@ stl_which_vertices_to_change(stl_file *stl, stl_hash_edge *edge_a,
|
|||||||
*facet2 = -1;
|
*facet2 = -1;
|
||||||
} else {
|
} else {
|
||||||
if( (stl->neighbors_start[edge_a->facet_number].neighbor[v2a] == -1)
|
if( (stl->neighbors_start[edge_a->facet_number].neighbor[v2a] == -1)
|
||||||
&& (stl->neighbors_start[edge_a->facet_number].
|
&& (stl->neighbors_start[edge_a->facet_number].neighbor[(v2a + 2) % 3] == -1)) {
|
||||||
neighbor[(v2a + 2) % 3] == -1)) {
|
|
||||||
/* This vertex has no neighbors. This is a good one to change */
|
/* This vertex has no neighbors. This is a good one to change */
|
||||||
*facet2 = edge_a->facet_number;
|
*facet2 = edge_a->facet_number;
|
||||||
*vertex2 = v2a;
|
*vertex2 = v2a;
|
||||||
@ -595,140 +565,6 @@ stl_which_vertices_to_change(stl_file *stl, stl_hash_edge *edge_a,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void remove_facet(stl_file *stl, int facet_number)
|
|
||||||
{
|
|
||||||
assert(! stl->error);
|
|
||||||
++ stl->stats.facets_removed;
|
|
||||||
/* Update list of connected edges */
|
|
||||||
stl_neighbors &neighbors = stl->neighbors_start[facet_number];
|
|
||||||
// Update statistics on unconnected triangle edges.
|
|
||||||
switch ((neighbors.neighbor[0] == -1) + (neighbors.neighbor[1] == -1) + (neighbors.neighbor[2] == -1)) {
|
|
||||||
case 0: // Facet has 3 neighbors
|
|
||||||
-- stl->stats.connected_facets_3_edge;
|
|
||||||
-- stl->stats.connected_facets_2_edge;
|
|
||||||
-- stl->stats.connected_facets_1_edge;
|
|
||||||
break;
|
|
||||||
case 1: // Facet has 2 neighbors
|
|
||||||
-- stl->stats.connected_facets_2_edge;
|
|
||||||
-- stl->stats.connected_facets_1_edge;
|
|
||||||
break;
|
|
||||||
case 2: // Facet has 1 neighbor
|
|
||||||
-- stl->stats.connected_facets_1_edge;
|
|
||||||
case 3: // Facet has 0 neighbors
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (facet_number == -- stl->stats.number_of_facets)
|
|
||||||
// Removing the last face is easy, just forget the last face.
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Copy the face and neighborship from the last face to facet_number.
|
|
||||||
stl->facet_start[facet_number] = stl->facet_start[stl->stats.number_of_facets];
|
|
||||||
neighbors = stl->neighbors_start[stl->stats.number_of_facets];
|
|
||||||
// Update neighborship of faces, which used to point to the last face, now moved to facet_number.
|
|
||||||
for (int i = 0; i < 3; ++ i)
|
|
||||||
if (neighbors.neighbor[i] != -1) {
|
|
||||||
int &other_face_idx = stl->neighbors_start[neighbors.neighbor[i]].neighbor[(neighbors.which_vertex_not[i] + 1) % 3];
|
|
||||||
if (other_face_idx != stl->stats.number_of_facets) {
|
|
||||||
printf("in remove_facet: neighbor = %d numfacets = %d this is wrong\n", other_face_idx, stl->stats.number_of_facets);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
other_face_idx = facet_number;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void remove_degenerate(stl_file *stl, int facet)
|
|
||||||
{
|
|
||||||
assert(! stl->error);
|
|
||||||
|
|
||||||
// Update statistics on face connectivity.
|
|
||||||
auto stl_update_connects_remove_1 = [stl](int facet_num) {
|
|
||||||
assert(! stl->error);
|
|
||||||
//FIXME when decreasing 3_edge, should I increase 2_edge etc?
|
|
||||||
switch ((stl->neighbors_start[facet_num].neighbor[0] == -1) + (stl->neighbors_start[facet_num].neighbor[1] == -1) + (stl->neighbors_start[facet_num].neighbor[2] == -1)) {
|
|
||||||
case 0: // Facet has 3 neighbors
|
|
||||||
-- stl->stats.connected_facets_3_edge; break;
|
|
||||||
case 1: // Facet has 2 neighbors
|
|
||||||
-- stl->stats.connected_facets_2_edge; break;
|
|
||||||
case 2: // Facet has 1 neighbor
|
|
||||||
-- stl->stats.connected_facets_1_edge; break;
|
|
||||||
case 3: // Facet has 0 neighbors
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
int edge_to_collapse = 0;
|
|
||||||
if (stl->facet_start[facet].vertex[0] == stl->facet_start[facet].vertex[1]) {
|
|
||||||
if (stl->facet_start[facet].vertex[1] == stl->facet_start[facet].vertex[2]) {
|
|
||||||
// All 3 vertices are equal. Collapse the edge with no neighbor if it exists.
|
|
||||||
const int *nbr = stl->neighbors_start[facet].neighbor;
|
|
||||||
edge_to_collapse = (nbr[0] == -1) ? 0 : (nbr[1] == -1) ? 1 : 2;
|
|
||||||
} else {
|
|
||||||
edge_to_collapse = 0;
|
|
||||||
}
|
|
||||||
} else if (stl->facet_start[facet].vertex[1] == stl->facet_start[facet].vertex[2]) {
|
|
||||||
edge_to_collapse = 1;
|
|
||||||
} else if (stl->facet_start[facet].vertex[2] == stl->facet_start[facet].vertex[0]) {
|
|
||||||
edge_to_collapse = 2;
|
|
||||||
} else {
|
|
||||||
// No degenerate. Function shouldn't have been called.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int edge[3] = { (edge_to_collapse + 1) % 3, (edge_to_collapse + 2) % 3, edge_to_collapse };
|
|
||||||
int neighbor[] = {
|
|
||||||
stl->neighbors_start[facet].neighbor[edge[0]],
|
|
||||||
stl->neighbors_start[facet].neighbor[edge[1]],
|
|
||||||
stl->neighbors_start[facet].neighbor[edge[2]]
|
|
||||||
};
|
|
||||||
int vnot[] = {
|
|
||||||
stl->neighbors_start[facet].which_vertex_not[edge[0]],
|
|
||||||
stl->neighbors_start[facet].which_vertex_not[edge[1]],
|
|
||||||
stl->neighbors_start[facet].which_vertex_not[edge[2]]
|
|
||||||
};
|
|
||||||
// Update statistics on edge connectivity.
|
|
||||||
if (neighbor[0] == -1)
|
|
||||||
stl_update_connects_remove_1(neighbor[1]);
|
|
||||||
if (neighbor[1] == -1)
|
|
||||||
stl_update_connects_remove_1(neighbor[0]);
|
|
||||||
|
|
||||||
if (neighbor[0] >= 0) {
|
|
||||||
if (neighbor[1] >= 0) {
|
|
||||||
// Adjust the "flip" flag for the which_vertex_not values.
|
|
||||||
if (vnot[0] > 2) {
|
|
||||||
if (vnot[1] > 2) {
|
|
||||||
// The face to be removed has its normal flipped compared to the left & right neighbors, therefore after removing this face
|
|
||||||
// the two remaining neighbors will be oriented correctly.
|
|
||||||
vnot[0] -= 3;
|
|
||||||
vnot[1] -= 3;
|
|
||||||
} else
|
|
||||||
// One neighbor has its normal inverted compared to the face to be removed, the other is oriented equally.
|
|
||||||
// After removal, the two neighbors will have their normals flipped.
|
|
||||||
vnot[1] += 3;
|
|
||||||
} else if (vnot[1] > 2)
|
|
||||||
// One neighbor has its normal inverted compared to the face to be removed, the other is oriented equally.
|
|
||||||
// After removal, the two neighbors will have their normals flipped.
|
|
||||||
vnot[0] += 3;
|
|
||||||
}
|
|
||||||
stl->neighbors_start[neighbor[0]].neighbor[(vnot[0] + 1) % 3] = (neighbor[0] == neighbor[1]) ? -1 : neighbor[1];
|
|
||||||
stl->neighbors_start[neighbor[0]].which_vertex_not[(vnot[0] + 1) % 3] = vnot[1];
|
|
||||||
}
|
|
||||||
if (neighbor[1] >= 0) {
|
|
||||||
stl->neighbors_start[neighbor[1]].neighbor[(vnot[1] + 1) % 3] = (neighbor[0] == neighbor[1]) ? -1 : neighbor[0];
|
|
||||||
stl->neighbors_start[neighbor[1]].which_vertex_not[(vnot[1] + 1) % 3] = vnot[0];
|
|
||||||
}
|
|
||||||
if (neighbor[2] >= 0) {
|
|
||||||
stl_update_connects_remove_1(neighbor[2]);
|
|
||||||
stl->neighbors_start[neighbor[2]].neighbor[(vnot[2] + 1) % 3] = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
remove_facet(stl, facet);
|
|
||||||
}
|
|
||||||
|
|
||||||
void stl_remove_unconnected_facets(stl_file *stl)
|
void stl_remove_unconnected_facets(stl_file *stl)
|
||||||
{
|
{
|
||||||
// A couple of things need to be done here. One is to remove any completely unconnected facets (0 edges connected) since these are
|
// A couple of things need to be done here. One is to remove any completely unconnected facets (0 edges connected) since these are
|
||||||
@ -737,12 +573,143 @@ void stl_remove_unconnected_facets(stl_file *stl)
|
|||||||
if (stl->error)
|
if (stl->error)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
auto remove_facet = [stl](int facet_number)
|
||||||
|
{
|
||||||
|
++ stl->stats.facets_removed;
|
||||||
|
/* Update list of connected edges */
|
||||||
|
stl_neighbors &neighbors = stl->neighbors_start[facet_number];
|
||||||
|
// Update statistics on unconnected triangle edges.
|
||||||
|
switch ((neighbors.neighbor[0] == -1) + (neighbors.neighbor[1] == -1) + (neighbors.neighbor[2] == -1)) {
|
||||||
|
case 0: // Facet has 3 neighbors
|
||||||
|
-- stl->stats.connected_facets_3_edge;
|
||||||
|
-- stl->stats.connected_facets_2_edge;
|
||||||
|
-- stl->stats.connected_facets_1_edge;
|
||||||
|
break;
|
||||||
|
case 1: // Facet has 2 neighbors
|
||||||
|
-- stl->stats.connected_facets_2_edge;
|
||||||
|
-- stl->stats.connected_facets_1_edge;
|
||||||
|
break;
|
||||||
|
case 2: // Facet has 1 neighbor
|
||||||
|
-- stl->stats.connected_facets_1_edge;
|
||||||
|
case 3: // Facet has 0 neighbors
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (facet_number == -- stl->stats.number_of_facets)
|
||||||
|
// Removing the last face is easy, just forget the last face.
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Copy the face and neighborship from the last face to facet_number.
|
||||||
|
stl->facet_start[facet_number] = stl->facet_start[stl->stats.number_of_facets];
|
||||||
|
neighbors = stl->neighbors_start[stl->stats.number_of_facets];
|
||||||
|
// Update neighborship of faces, which used to point to the last face, now moved to facet_number.
|
||||||
|
for (int i = 0; i < 3; ++ i)
|
||||||
|
if (neighbors.neighbor[i] != -1) {
|
||||||
|
int &other_face_idx = stl->neighbors_start[neighbors.neighbor[i]].neighbor[(neighbors.which_vertex_not[i] + 1) % 3];
|
||||||
|
if (other_face_idx != stl->stats.number_of_facets) {
|
||||||
|
printf("in remove_facet: neighbor = %d numfacets = %d this is wrong\n", other_face_idx, stl->stats.number_of_facets);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
other_face_idx = facet_number;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
auto remove_degenerate = [stl, remove_facet](int facet)
|
||||||
|
{
|
||||||
|
// Update statistics on face connectivity.
|
||||||
|
auto stl_update_connects_remove_1 = [stl](int facet_num) {
|
||||||
|
assert(! stl->error);
|
||||||
|
//FIXME when decreasing 3_edge, should I increase 2_edge etc?
|
||||||
|
switch ((stl->neighbors_start[facet_num].neighbor[0] == -1) + (stl->neighbors_start[facet_num].neighbor[1] == -1) + (stl->neighbors_start[facet_num].neighbor[2] == -1)) {
|
||||||
|
case 0: // Facet has 3 neighbors
|
||||||
|
-- stl->stats.connected_facets_3_edge; break;
|
||||||
|
case 1: // Facet has 2 neighbors
|
||||||
|
-- stl->stats.connected_facets_2_edge; break;
|
||||||
|
case 2: // Facet has 1 neighbor
|
||||||
|
-- stl->stats.connected_facets_1_edge; break;
|
||||||
|
case 3: // Facet has 0 neighbors
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int edge_to_collapse = 0;
|
||||||
|
if (stl->facet_start[facet].vertex[0] == stl->facet_start[facet].vertex[1]) {
|
||||||
|
if (stl->facet_start[facet].vertex[1] == stl->facet_start[facet].vertex[2]) {
|
||||||
|
// All 3 vertices are equal. Collapse the edge with no neighbor if it exists.
|
||||||
|
const int *nbr = stl->neighbors_start[facet].neighbor;
|
||||||
|
edge_to_collapse = (nbr[0] == -1) ? 0 : (nbr[1] == -1) ? 1 : 2;
|
||||||
|
} else {
|
||||||
|
edge_to_collapse = 0;
|
||||||
|
}
|
||||||
|
} else if (stl->facet_start[facet].vertex[1] == stl->facet_start[facet].vertex[2]) {
|
||||||
|
edge_to_collapse = 1;
|
||||||
|
} else if (stl->facet_start[facet].vertex[2] == stl->facet_start[facet].vertex[0]) {
|
||||||
|
edge_to_collapse = 2;
|
||||||
|
} else {
|
||||||
|
// No degenerate. Function shouldn't have been called.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int edge[3] = { (edge_to_collapse + 1) % 3, (edge_to_collapse + 2) % 3, edge_to_collapse };
|
||||||
|
int neighbor[] = {
|
||||||
|
stl->neighbors_start[facet].neighbor[edge[0]],
|
||||||
|
stl->neighbors_start[facet].neighbor[edge[1]],
|
||||||
|
stl->neighbors_start[facet].neighbor[edge[2]]
|
||||||
|
};
|
||||||
|
int vnot[] = {
|
||||||
|
stl->neighbors_start[facet].which_vertex_not[edge[0]],
|
||||||
|
stl->neighbors_start[facet].which_vertex_not[edge[1]],
|
||||||
|
stl->neighbors_start[facet].which_vertex_not[edge[2]]
|
||||||
|
};
|
||||||
|
// Update statistics on edge connectivity.
|
||||||
|
if (neighbor[0] == -1)
|
||||||
|
stl_update_connects_remove_1(neighbor[1]);
|
||||||
|
if (neighbor[1] == -1)
|
||||||
|
stl_update_connects_remove_1(neighbor[0]);
|
||||||
|
|
||||||
|
if (neighbor[0] >= 0) {
|
||||||
|
if (neighbor[1] >= 0) {
|
||||||
|
// Adjust the "flip" flag for the which_vertex_not values.
|
||||||
|
if (vnot[0] > 2) {
|
||||||
|
if (vnot[1] > 2) {
|
||||||
|
// The face to be removed has its normal flipped compared to the left & right neighbors, therefore after removing this face
|
||||||
|
// the two remaining neighbors will be oriented correctly.
|
||||||
|
vnot[0] -= 3;
|
||||||
|
vnot[1] -= 3;
|
||||||
|
} else
|
||||||
|
// One neighbor has its normal inverted compared to the face to be removed, the other is oriented equally.
|
||||||
|
// After removal, the two neighbors will have their normals flipped.
|
||||||
|
vnot[1] += 3;
|
||||||
|
} else if (vnot[1] > 2)
|
||||||
|
// One neighbor has its normal inverted compared to the face to be removed, the other is oriented equally.
|
||||||
|
// After removal, the two neighbors will have their normals flipped.
|
||||||
|
vnot[0] += 3;
|
||||||
|
}
|
||||||
|
stl->neighbors_start[neighbor[0]].neighbor[(vnot[0] + 1) % 3] = (neighbor[0] == neighbor[1]) ? -1 : neighbor[1];
|
||||||
|
stl->neighbors_start[neighbor[0]].which_vertex_not[(vnot[0] + 1) % 3] = vnot[1];
|
||||||
|
}
|
||||||
|
if (neighbor[1] >= 0) {
|
||||||
|
stl->neighbors_start[neighbor[1]].neighbor[(vnot[1] + 1) % 3] = (neighbor[0] == neighbor[1]) ? -1 : neighbor[0];
|
||||||
|
stl->neighbors_start[neighbor[1]].which_vertex_not[(vnot[1] + 1) % 3] = vnot[0];
|
||||||
|
}
|
||||||
|
if (neighbor[2] >= 0) {
|
||||||
|
stl_update_connects_remove_1(neighbor[2]);
|
||||||
|
stl->neighbors_start[neighbor[2]].neighbor[(vnot[2] + 1) % 3] = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
remove_facet(facet);
|
||||||
|
};
|
||||||
|
|
||||||
// remove degenerate facets
|
// remove degenerate facets
|
||||||
for (uint32_t i = 0; i < stl->stats.number_of_facets;)
|
for (uint32_t i = 0; i < stl->stats.number_of_facets;)
|
||||||
if (stl->facet_start[i].vertex[0] == stl->facet_start[i].vertex[1] ||
|
if (stl->facet_start[i].vertex[0] == stl->facet_start[i].vertex[1] ||
|
||||||
stl->facet_start[i].vertex[0] == stl->facet_start[i].vertex[2] ||
|
stl->facet_start[i].vertex[0] == stl->facet_start[i].vertex[2] ||
|
||||||
stl->facet_start[i].vertex[1] == stl->facet_start[i].vertex[2]) {
|
stl->facet_start[i].vertex[1] == stl->facet_start[i].vertex[2]) {
|
||||||
remove_degenerate(stl, i);
|
remove_degenerate(i);
|
||||||
// assert(stl_validate(stl));
|
// assert(stl_validate(stl));
|
||||||
} else
|
} else
|
||||||
++ i;
|
++ i;
|
||||||
@ -754,7 +721,7 @@ void stl_remove_unconnected_facets(stl_file *stl)
|
|||||||
stl->neighbors_start[i].neighbor[1] == -1 &&
|
stl->neighbors_start[i].neighbor[1] == -1 &&
|
||||||
stl->neighbors_start[i].neighbor[2] == -1) {
|
stl->neighbors_start[i].neighbor[2] == -1) {
|
||||||
// This facet is completely unconnected. Remove it.
|
// This facet is completely unconnected. Remove it.
|
||||||
remove_facet(stl, i);
|
remove_facet(i);
|
||||||
assert(stl_validate(stl));
|
assert(stl_validate(stl));
|
||||||
} else
|
} else
|
||||||
++ i;
|
++ i;
|
||||||
@ -850,8 +817,7 @@ stl_fill_holes(stl_file *stl) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
vnot = stl->neighbors_start[facet_num].
|
vnot = stl->neighbors_start[facet_num].which_vertex_not[next_edge];
|
||||||
which_vertex_not[next_edge];
|
|
||||||
facet_num = next_facet;
|
facet_num = next_facet;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -867,27 +833,14 @@ Try using a smaller tolerance or don't do a nearby check\n");
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void stl_add_facet(stl_file *stl, const stl_facet *new_facet)
|
||||||
stl_add_facet(stl_file *stl, stl_facet *new_facet) {
|
{
|
||||||
if (stl->error) return;
|
if (stl->error)
|
||||||
|
return;
|
||||||
stl->stats.facets_added += 1;
|
++ stl->stats.facets_added;
|
||||||
if(stl->stats.facets_malloced < (int)stl->stats.number_of_facets + 1) {
|
++ stl->stats.number_of_facets;
|
||||||
stl->facet_start = (stl_facet*)realloc(stl->facet_start,
|
stl->facet_start.emplace_back(*new_facet);
|
||||||
(sizeof(stl_facet) * (stl->stats.facets_malloced + 256)));
|
// note that the normal vector is not set here, just initialized to 0.
|
||||||
if(stl->facet_start == NULL) perror("stl_add_facet");
|
stl->facet_start[stl->stats.number_of_facets].normal = stl_normal::Zero();
|
||||||
stl->neighbors_start = (stl_neighbors*)realloc(stl->neighbors_start,
|
stl->neighbors_start.emplace_back();
|
||||||
(sizeof(stl_neighbors) * (stl->stats.facets_malloced + 256)));
|
|
||||||
if(stl->neighbors_start == NULL) perror("stl_add_facet");
|
|
||||||
stl->stats.facets_malloced += 256;
|
|
||||||
}
|
|
||||||
stl->facet_start[stl->stats.number_of_facets] = *new_facet;
|
|
||||||
|
|
||||||
/* note that the normal vector is not set here, just initialized to 0 */
|
|
||||||
stl->facet_start[stl->stats.number_of_facets].normal = stl_normal::Zero();
|
|
||||||
|
|
||||||
stl->neighbors_start[stl->stats.number_of_facets].neighbor[0] = -1;
|
|
||||||
stl->neighbors_start[stl->stats.number_of_facets].neighbor[1] = -1;
|
|
||||||
stl->neighbors_start[stl->stats.number_of_facets].neighbor[2] = -1;
|
|
||||||
stl->stats.number_of_facets += 1;
|
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,6 @@ stl_reverse_facet(stl_file *stl, int facet_num) {
|
|||||||
|
|
||||||
void
|
void
|
||||||
stl_fix_normal_directions(stl_file *stl) {
|
stl_fix_normal_directions(stl_file *stl) {
|
||||||
char *norm_sw;
|
|
||||||
/* int edge_num;*/
|
/* int edge_num;*/
|
||||||
/* int vnot;*/
|
/* int vnot;*/
|
||||||
int checked = 0;
|
int checked = 0;
|
||||||
@ -101,7 +100,6 @@ stl_fix_normal_directions(stl_file *stl) {
|
|||||||
struct stl_normal *newn;
|
struct stl_normal *newn;
|
||||||
struct stl_normal *temp;
|
struct stl_normal *temp;
|
||||||
|
|
||||||
int* reversed_ids;
|
|
||||||
int reversed_count = 0;
|
int reversed_count = 0;
|
||||||
int id;
|
int id;
|
||||||
int force_exit = 0;
|
int force_exit = 0;
|
||||||
@ -112,20 +110,15 @@ stl_fix_normal_directions(stl_file *stl) {
|
|||||||
if (stl->stats.number_of_facets == 0) return;
|
if (stl->stats.number_of_facets == 0) return;
|
||||||
|
|
||||||
/* Initialize linked list. */
|
/* Initialize linked list. */
|
||||||
head = (struct stl_normal*)malloc(sizeof(struct stl_normal));
|
head = new stl_normal;
|
||||||
if(head == NULL) perror("stl_fix_normal_directions");
|
tail = new stl_normal;
|
||||||
tail = (struct stl_normal*)malloc(sizeof(struct stl_normal));
|
|
||||||
if(tail == NULL) perror("stl_fix_normal_directions");
|
|
||||||
head->next = tail;
|
head->next = tail;
|
||||||
tail->next = tail;
|
tail->next = tail;
|
||||||
|
|
||||||
/* Initialize list that keeps track of already fixed facets. */
|
/* Initialize list that keeps track of already fixed facets. */
|
||||||
norm_sw = (char*)calloc(stl->stats.number_of_facets, sizeof(char));
|
std::vector<char> norm_sw(stl->stats.number_of_facets, 0);
|
||||||
if(norm_sw == NULL) perror("stl_fix_normal_directions");
|
|
||||||
|
|
||||||
/* Initialize list that keeps track of reversed facets. */
|
/* Initialize list that keeps track of reversed facets. */
|
||||||
reversed_ids = (int*)calloc(stl->stats.number_of_facets, sizeof(int));
|
std::vector<int> reversed_ids(stl->stats.number_of_facets, 0);
|
||||||
if (reversed_ids == NULL) perror("stl_fix_normal_directions reversed_ids");
|
|
||||||
|
|
||||||
facet_num = 0;
|
facet_num = 0;
|
||||||
/* If normal vector is not within tolerance and backwards:
|
/* If normal vector is not within tolerance and backwards:
|
||||||
@ -166,8 +159,7 @@ stl_fix_normal_directions(stl_file *stl) {
|
|||||||
/* If we haven't fixed this facet yet, add it to the list: */
|
/* If we haven't fixed this facet yet, add it to the list: */
|
||||||
if(norm_sw[stl->neighbors_start[facet_num].neighbor[j]] != 1) {
|
if(norm_sw[stl->neighbors_start[facet_num].neighbor[j]] != 1) {
|
||||||
/* Add node to beginning of list. */
|
/* Add node to beginning of list. */
|
||||||
newn = (struct stl_normal*)malloc(sizeof(struct stl_normal));
|
newn = new stl_normal;
|
||||||
if(newn == NULL) perror("stl_fix_normal_directions");
|
|
||||||
newn->facet_num = stl->neighbors_start[facet_num].neighbor[j];
|
newn->facet_num = stl->neighbors_start[facet_num].neighbor[j];
|
||||||
newn->next = head->next;
|
newn->next = head->next;
|
||||||
head->next = newn;
|
head->next = newn;
|
||||||
@ -187,7 +179,7 @@ stl_fix_normal_directions(stl_file *stl) {
|
|||||||
}
|
}
|
||||||
temp = head->next; /* Delete this facet from the list. */
|
temp = head->next; /* Delete this facet from the list. */
|
||||||
head->next = head->next->next;
|
head->next = head->next->next;
|
||||||
free(temp);
|
delete temp;
|
||||||
} else { /* if we ran out of facets to fix: */
|
} else { /* if we ran out of facets to fix: */
|
||||||
/* All of the facets in this part have been fixed. */
|
/* All of the facets in this part have been fixed. */
|
||||||
stl->stats.number_of_parts += 1;
|
stl->stats.number_of_parts += 1;
|
||||||
@ -213,10 +205,8 @@ stl_fix_normal_directions(stl_file *stl) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(head);
|
delete head;
|
||||||
free(tail);
|
delete tail;
|
||||||
free(reversed_ids);
|
|
||||||
free(norm_sw);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int stl_check_normal_vector(stl_file *stl, int facet_num, int normal_fix_flag) {
|
static int stl_check_normal_vector(stl_file *stl, int facet_num, int normal_fix_flag) {
|
||||||
|
@ -31,17 +31,8 @@
|
|||||||
|
|
||||||
void stl_invalidate_shared_vertices(stl_file *stl)
|
void stl_invalidate_shared_vertices(stl_file *stl)
|
||||||
{
|
{
|
||||||
if (stl->error)
|
stl->v_indices.clear();
|
||||||
return;
|
stl->v_shared.clear();
|
||||||
|
|
||||||
if (stl->v_indices != nullptr) {
|
|
||||||
free(stl->v_indices);
|
|
||||||
stl->v_indices = nullptr;
|
|
||||||
}
|
|
||||||
if (stl->v_shared != nullptr) {
|
|
||||||
free(stl->v_shared);
|
|
||||||
stl->v_shared = nullptr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void stl_generate_shared_vertices(stl_file *stl)
|
void stl_generate_shared_vertices(stl_file *stl)
|
||||||
@ -53,23 +44,11 @@ void stl_generate_shared_vertices(stl_file *stl)
|
|||||||
stl_invalidate_shared_vertices(stl);
|
stl_invalidate_shared_vertices(stl);
|
||||||
|
|
||||||
// 3 indices to vertex per face
|
// 3 indices to vertex per face
|
||||||
stl->v_indices = (v_indices_struct*)calloc(stl->stats.number_of_facets, sizeof(v_indices_struct));
|
stl->v_indices.assign(stl->stats.number_of_facets, v_indices_struct());
|
||||||
if (stl->v_indices == nullptr)
|
|
||||||
perror("stl_generate_shared_vertices");
|
|
||||||
// Shared vertices (3D coordinates)
|
// Shared vertices (3D coordinates)
|
||||||
stl->v_shared = (stl_vertex*)calloc((stl->stats.number_of_facets / 2), sizeof(stl_vertex));
|
stl->v_shared.assign(stl->stats.number_of_facets / 2, stl_vertex());
|
||||||
if (stl->v_shared == nullptr)
|
|
||||||
perror("stl_generate_shared_vertices");
|
|
||||||
stl->stats.shared_malloced = stl->stats.number_of_facets / 2;
|
|
||||||
stl->stats.shared_vertices = 0;
|
stl->stats.shared_vertices = 0;
|
||||||
|
|
||||||
for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i) {
|
|
||||||
// vertex index -1 means no shared vertex was assigned yet.
|
|
||||||
stl->v_indices[i].vertex[0] = -1;
|
|
||||||
stl->v_indices[i].vertex[1] = -1;
|
|
||||||
stl->v_indices[i].vertex[2] = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// A degenerate mesh may contain loops: Traversing a fan will end up in an endless loop
|
// A degenerate mesh may contain loops: Traversing a fan will end up in an endless loop
|
||||||
// while never reaching the starting face. To avoid these endless loops, traversed faces at each fan traversal
|
// while never reaching the starting face. To avoid these endless loops, traversed faces at each fan traversal
|
||||||
// are marked with a unique fan_traversal_stamp.
|
// are marked with a unique fan_traversal_stamp.
|
||||||
@ -82,13 +61,7 @@ void stl_generate_shared_vertices(stl_file *stl)
|
|||||||
// Shared vertex was already assigned.
|
// Shared vertex was already assigned.
|
||||||
continue;
|
continue;
|
||||||
// Create a new shared vertex.
|
// Create a new shared vertex.
|
||||||
if (stl->stats.shared_vertices == stl->stats.shared_malloced) {
|
stl->v_shared.emplace_back(stl->facet_start[facet_idx].vertex[j]);
|
||||||
stl->stats.shared_malloced += 1024;
|
|
||||||
stl->v_shared = (stl_vertex*)realloc(stl->v_shared, stl->stats.shared_malloced * sizeof(stl_vertex));
|
|
||||||
if(stl->v_shared == nullptr)
|
|
||||||
perror("stl_generate_shared_vertices");
|
|
||||||
}
|
|
||||||
stl->v_shared[stl->stats.shared_vertices] = stl->facet_start[facet_idx].vertex[j];
|
|
||||||
// Traverse the fan around the j-th vertex of the i-th face, assign the newly created shared vertex index to all the neighboring triangles in the triangle fan.
|
// Traverse the fan around the j-th vertex of the i-th face, assign the newly created shared vertex index to all the neighboring triangles in the triangle fan.
|
||||||
int facet_in_fan_idx = facet_idx;
|
int facet_in_fan_idx = facet_idx;
|
||||||
bool edge_direction = false;
|
bool edge_direction = false;
|
||||||
|
187
src/admesh/stl.h
187
src/admesh/stl.h
@ -27,6 +27,7 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
#include <Eigen/Geometry>
|
#include <Eigen/Geometry>
|
||||||
|
|
||||||
// Size of the binary STL header, free form.
|
// Size of the binary STL header, free form.
|
||||||
@ -44,18 +45,18 @@ static_assert(sizeof(stl_vertex) == 12, "size of stl_vertex incorrect");
|
|||||||
static_assert(sizeof(stl_normal) == 12, "size of stl_normal incorrect");
|
static_assert(sizeof(stl_normal) == 12, "size of stl_normal incorrect");
|
||||||
|
|
||||||
struct stl_facet {
|
struct stl_facet {
|
||||||
stl_normal normal;
|
stl_normal normal;
|
||||||
stl_vertex vertex[3];
|
stl_vertex vertex[3];
|
||||||
char extra[2];
|
char extra[2];
|
||||||
|
|
||||||
stl_facet rotated(const Eigen::Quaternion<float, Eigen::DontAlign> &rot) {
|
stl_facet rotated(const Eigen::Quaternion<float, Eigen::DontAlign> &rot) const {
|
||||||
stl_facet out;
|
stl_facet out;
|
||||||
out.normal = rot * this->normal;
|
out.normal = rot * this->normal;
|
||||||
out.vertex[0] = rot * this->vertex[0];
|
out.vertex[0] = rot * this->vertex[0];
|
||||||
out.vertex[1] = rot * this->vertex[1];
|
out.vertex[1] = rot * this->vertex[1];
|
||||||
out.vertex[2] = rot * this->vertex[2];
|
out.vertex[2] = rot * this->vertex[2];
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SIZEOF_STL_FACET 50
|
#define SIZEOF_STL_FACET 50
|
||||||
@ -67,86 +68,100 @@ static_assert(sizeof(stl_facet) >= SIZEOF_STL_FACET, "size of stl_facet incorrec
|
|||||||
|
|
||||||
typedef enum {binary, ascii, inmemory} stl_type;
|
typedef enum {binary, ascii, inmemory} stl_type;
|
||||||
|
|
||||||
typedef struct {
|
struct stl_edge {
|
||||||
stl_vertex p1;
|
stl_vertex p1;
|
||||||
stl_vertex p2;
|
stl_vertex p2;
|
||||||
int facet_number;
|
int facet_number;
|
||||||
} stl_edge;
|
};
|
||||||
|
|
||||||
typedef struct stl_hash_edge {
|
struct stl_hash_edge {
|
||||||
// Key of a hash edge: sorted vertices of the edge.
|
// Key of a hash edge: sorted vertices of the edge.
|
||||||
uint32_t key[6];
|
uint32_t key[6];
|
||||||
// Compare two keys.
|
// Compare two keys.
|
||||||
bool operator==(const stl_hash_edge &rhs) { return memcmp(key, rhs.key, sizeof(key)) == 0; }
|
bool operator==(const stl_hash_edge &rhs) { return memcmp(key, rhs.key, sizeof(key)) == 0; }
|
||||||
bool operator!=(const stl_hash_edge &rhs) { return ! (*this == rhs); }
|
bool operator!=(const stl_hash_edge &rhs) { return ! (*this == rhs); }
|
||||||
int hash(int M) const { return ((key[0] / 11 + key[1] / 7 + key[2] / 3) ^ (key[3] / 11 + key[4] / 7 + key[5] / 3)) % M; }
|
int hash(int M) const { return ((key[0] / 11 + key[1] / 7 + key[2] / 3) ^ (key[3] / 11 + key[4] / 7 + key[5] / 3)) % M; }
|
||||||
// Index of a facet owning this edge.
|
// Index of a facet owning this edge.
|
||||||
int facet_number;
|
int facet_number;
|
||||||
// Index of this edge inside the facet with an index of facet_number.
|
// Index of this edge inside the facet with an index of facet_number.
|
||||||
// If this edge is stored backwards, which_edge is increased by 3.
|
// If this edge is stored backwards, which_edge is increased by 3.
|
||||||
int which_edge;
|
int which_edge;
|
||||||
struct stl_hash_edge *next;
|
struct stl_hash_edge *next;
|
||||||
} stl_hash_edge;
|
};
|
||||||
|
|
||||||
typedef struct {
|
struct stl_neighbors {
|
||||||
// Index of a neighbor facet.
|
stl_neighbors() { reset(); }
|
||||||
int neighbor[3];
|
void reset() {
|
||||||
// Index of an opposite vertex at the neighbor face.
|
neighbor[0] = -1;
|
||||||
char which_vertex_not[3];
|
neighbor[1] = -1;
|
||||||
} stl_neighbors;
|
neighbor[2] = -1;
|
||||||
|
which_vertex_not[0] = -1;
|
||||||
|
which_vertex_not[1] = -1;
|
||||||
|
which_vertex_not[2] = -1;
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct {
|
// Index of a neighbor facet.
|
||||||
int vertex[3];
|
int neighbor[3];
|
||||||
} v_indices_struct;
|
// Index of an opposite vertex at the neighbor face.
|
||||||
|
char which_vertex_not[3];
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct {
|
struct v_indices_struct {
|
||||||
char header[81];
|
// -1 means no vertex index has been assigned yet
|
||||||
stl_type type;
|
v_indices_struct() { vertex[0] = -1; vertex[1] = -1; vertex[2] = -1; }
|
||||||
uint32_t number_of_facets;
|
int vertex[3];
|
||||||
stl_vertex max;
|
};
|
||||||
stl_vertex min;
|
|
||||||
stl_vertex size;
|
|
||||||
float bounding_diameter;
|
|
||||||
float shortest_edge;
|
|
||||||
float volume;
|
|
||||||
unsigned number_of_blocks;
|
|
||||||
int connected_edges;
|
|
||||||
int connected_facets_1_edge;
|
|
||||||
int connected_facets_2_edge;
|
|
||||||
int connected_facets_3_edge;
|
|
||||||
int facets_w_1_bad_edge;
|
|
||||||
int facets_w_2_bad_edge;
|
|
||||||
int facets_w_3_bad_edge;
|
|
||||||
int original_num_facets;
|
|
||||||
int edges_fixed;
|
|
||||||
int degenerate_facets;
|
|
||||||
int facets_removed;
|
|
||||||
int facets_added;
|
|
||||||
int facets_reversed;
|
|
||||||
int backwards_edges;
|
|
||||||
int normals_fixed;
|
|
||||||
int number_of_parts;
|
|
||||||
int malloced;
|
|
||||||
int freed;
|
|
||||||
int facets_malloced;
|
|
||||||
int collisions;
|
|
||||||
int shared_vertices;
|
|
||||||
int shared_malloced;
|
|
||||||
} stl_stats;
|
|
||||||
|
|
||||||
typedef struct {
|
struct stl_stats {
|
||||||
FILE *fp;
|
char header[81];
|
||||||
stl_facet *facet_start;
|
stl_type type;
|
||||||
stl_hash_edge **heads;
|
uint32_t number_of_facets;
|
||||||
stl_hash_edge *tail;
|
stl_vertex max;
|
||||||
int M;
|
stl_vertex min;
|
||||||
stl_neighbors *neighbors_start;
|
stl_vertex size;
|
||||||
v_indices_struct *v_indices;
|
float bounding_diameter;
|
||||||
stl_vertex *v_shared;
|
float shortest_edge;
|
||||||
stl_stats stats;
|
float volume;
|
||||||
char error;
|
unsigned number_of_blocks;
|
||||||
} stl_file;
|
int connected_edges;
|
||||||
|
int connected_facets_1_edge;
|
||||||
|
int connected_facets_2_edge;
|
||||||
|
int connected_facets_3_edge;
|
||||||
|
int facets_w_1_bad_edge;
|
||||||
|
int facets_w_2_bad_edge;
|
||||||
|
int facets_w_3_bad_edge;
|
||||||
|
int original_num_facets;
|
||||||
|
int edges_fixed;
|
||||||
|
int degenerate_facets;
|
||||||
|
int facets_removed;
|
||||||
|
int facets_added;
|
||||||
|
int facets_reversed;
|
||||||
|
int backwards_edges;
|
||||||
|
int normals_fixed;
|
||||||
|
int number_of_parts;
|
||||||
|
int shared_vertices;
|
||||||
|
|
||||||
|
// hash table statistics
|
||||||
|
int malloced;
|
||||||
|
int freed;
|
||||||
|
int collisions;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct stl_file {
|
||||||
|
FILE *fp;
|
||||||
|
std::vector<stl_facet> facet_start;
|
||||||
|
std::vector<stl_neighbors> neighbors_start;
|
||||||
|
// Hash table on edges
|
||||||
|
std::vector<stl_hash_edge*> heads;
|
||||||
|
stl_hash_edge* tail;
|
||||||
|
int M;
|
||||||
|
// Indexed face set
|
||||||
|
std::vector<v_indices_struct> v_indices;
|
||||||
|
std::vector<stl_vertex> v_shared;
|
||||||
|
// Statistics
|
||||||
|
stl_stats stats;
|
||||||
|
char error;
|
||||||
|
};
|
||||||
|
|
||||||
extern void stl_open(stl_file *stl, const char *file);
|
extern void stl_open(stl_file *stl, const char *file);
|
||||||
extern void stl_close(stl_file *stl);
|
extern void stl_close(stl_file *stl);
|
||||||
@ -272,7 +287,7 @@ extern void stl_allocate(stl_file *stl);
|
|||||||
extern void stl_read(stl_file *stl, int first_facet, bool first);
|
extern void stl_read(stl_file *stl, int first_facet, bool first);
|
||||||
extern void stl_facet_stats(stl_file *stl, stl_facet facet, bool &first);
|
extern void stl_facet_stats(stl_file *stl, stl_facet facet, bool &first);
|
||||||
extern void stl_reallocate(stl_file *stl);
|
extern void stl_reallocate(stl_file *stl);
|
||||||
extern void stl_add_facet(stl_file *stl, stl_facet *new_facet);
|
extern void stl_add_facet(stl_file *stl, const stl_facet *new_facet);
|
||||||
|
|
||||||
extern void stl_clear_error(stl_file *stl);
|
extern void stl_clear_error(stl_file *stl);
|
||||||
extern int stl_get_error(stl_file *stl);
|
extern int stl_get_error(stl_file *stl);
|
||||||
|
@ -109,7 +109,6 @@ Normals fixed : %5d\n", stl->stats.normals_fixed);
|
|||||||
|
|
||||||
void
|
void
|
||||||
stl_write_ascii(stl_file *stl, const char *file, const char *label) {
|
stl_write_ascii(stl_file *stl, const char *file, const char *label) {
|
||||||
int i;
|
|
||||||
char *error_msg;
|
char *error_msg;
|
||||||
|
|
||||||
if (stl->error) return;
|
if (stl->error) return;
|
||||||
@ -129,7 +128,7 @@ stl_write_ascii(stl_file *stl, const char *file, const char *label) {
|
|||||||
|
|
||||||
fprintf(fp, "solid %s\n", label);
|
fprintf(fp, "solid %s\n", label);
|
||||||
|
|
||||||
for(i = 0; i < stl->stats.number_of_facets; i++) {
|
for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i) {
|
||||||
fprintf(fp, " facet normal % .8E % .8E % .8E\n",
|
fprintf(fp, " facet normal % .8E % .8E % .8E\n",
|
||||||
stl->facet_start[i].normal(0), stl->facet_start[i].normal(1),
|
stl->facet_start[i].normal(0), stl->facet_start[i].normal(1),
|
||||||
stl->facet_start[i].normal(2));
|
stl->facet_start[i].normal(2));
|
||||||
@ -154,7 +153,6 @@ stl_write_ascii(stl_file *stl, const char *file, const char *label) {
|
|||||||
|
|
||||||
void
|
void
|
||||||
stl_print_neighbors(stl_file *stl, char *file) {
|
stl_print_neighbors(stl_file *stl, char *file) {
|
||||||
int i;
|
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char *error_msg;
|
char *error_msg;
|
||||||
|
|
||||||
@ -173,7 +171,7 @@ stl_print_neighbors(stl_file *stl, char *file) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(i = 0; i < stl->stats.number_of_facets; i++) {
|
for (uint32_t i = 0; i < stl->stats.number_of_facets; i++) {
|
||||||
fprintf(fp, "%d, %d,%d, %d,%d, %d,%d\n",
|
fprintf(fp, "%d, %d,%d, %d,%d, %d,%d\n",
|
||||||
i,
|
i,
|
||||||
stl->neighbors_start[i].neighbor[0],
|
stl->neighbors_start[i].neighbor[0],
|
||||||
@ -200,7 +198,6 @@ void stl_internal_reverse_quads(char *buf, size_t cnt)
|
|||||||
void
|
void
|
||||||
stl_write_binary(stl_file *stl, const char *file, const char *label) {
|
stl_write_binary(stl_file *stl, const char *file, const char *label) {
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
int i;
|
|
||||||
char *error_msg;
|
char *error_msg;
|
||||||
|
|
||||||
if (stl->error) return;
|
if (stl->error) return;
|
||||||
@ -219,13 +216,13 @@ stl_write_binary(stl_file *stl, const char *file, const char *label) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fprintf(fp, "%s", label);
|
fprintf(fp, "%s", label);
|
||||||
for(i = strlen(label); i < LABEL_SIZE; i++) putc(0, fp);
|
for(size_t i = strlen(label); i < LABEL_SIZE; i++) putc(0, fp);
|
||||||
|
|
||||||
fseek(fp, LABEL_SIZE, SEEK_SET);
|
fseek(fp, LABEL_SIZE, SEEK_SET);
|
||||||
#ifdef BOOST_LITTLE_ENDIAN
|
#ifdef BOOST_LITTLE_ENDIAN
|
||||||
fwrite(&stl->stats.number_of_facets, 4, 1, fp);
|
fwrite(&stl->stats.number_of_facets, 4, 1, fp);
|
||||||
for (i = 0; i < stl->stats.number_of_facets; ++ i)
|
for (const stl_facet &facet : stl->facet_start)
|
||||||
fwrite(stl->facet_start + i, SIZEOF_STL_FACET, 1, fp);
|
fwrite(&facet, SIZEOF_STL_FACET, 1, fp);
|
||||||
#else /* BOOST_LITTLE_ENDIAN */
|
#else /* BOOST_LITTLE_ENDIAN */
|
||||||
char buffer[50];
|
char buffer[50];
|
||||||
// Convert the number of facets to little endian.
|
// Convert the number of facets to little endian.
|
||||||
@ -288,8 +285,6 @@ stl_write_neighbor(stl_file *stl, int facet) {
|
|||||||
void
|
void
|
||||||
stl_write_quad_object(stl_file *stl, char *file) {
|
stl_write_quad_object(stl_file *stl, char *file) {
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
int i;
|
|
||||||
int j;
|
|
||||||
char *error_msg;
|
char *error_msg;
|
||||||
stl_vertex connect_color = stl_vertex::Zero();
|
stl_vertex connect_color = stl_vertex::Zero();
|
||||||
stl_vertex uncon_1_color = stl_vertex::Zero();
|
stl_vertex uncon_1_color = stl_vertex::Zero();
|
||||||
@ -313,10 +308,10 @@ stl_write_quad_object(stl_file *stl, char *file) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fprintf(fp, "CQUAD\n");
|
fprintf(fp, "CQUAD\n");
|
||||||
for(i = 0; i < stl->stats.number_of_facets; i++) {
|
for (uint32_t i = 0; i < stl->stats.number_of_facets; i++) {
|
||||||
j = ((stl->neighbors_start[i].neighbor[0] == -1) +
|
int j = ((stl->neighbors_start[i].neighbor[0] == -1) +
|
||||||
(stl->neighbors_start[i].neighbor[1] == -1) +
|
(stl->neighbors_start[i].neighbor[1] == -1) +
|
||||||
(stl->neighbors_start[i].neighbor[2] == -1));
|
(stl->neighbors_start[i].neighbor[2] == -1));
|
||||||
if(j == 0) {
|
if(j == 0) {
|
||||||
color = connect_color;
|
color = connect_color;
|
||||||
} else if(j == 1) {
|
} else if(j == 1) {
|
||||||
@ -346,9 +341,8 @@ stl_write_quad_object(stl_file *stl, char *file) {
|
|||||||
fclose(fp);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void stl_write_dxf(stl_file *stl, const char *file, char *label)
|
||||||
stl_write_dxf(stl_file *stl, const char *file, char *label) {
|
{
|
||||||
int i;
|
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
char *error_msg;
|
char *error_msg;
|
||||||
|
|
||||||
@ -375,7 +369,7 @@ stl_write_dxf(stl_file *stl, const char *file, char *label) {
|
|||||||
|
|
||||||
fprintf(fp, "0\nSECTION\n2\nENTITIES\n");
|
fprintf(fp, "0\nSECTION\n2\nENTITIES\n");
|
||||||
|
|
||||||
for(i = 0; i < stl->stats.number_of_facets; i++) {
|
for (uint32_t i = 0; i < stl->stats.number_of_facets; i++) {
|
||||||
fprintf(fp, "0\n3DFACE\n8\n0\n");
|
fprintf(fp, "0\n3DFACE\n8\n0\n");
|
||||||
fprintf(fp, "10\n%f\n20\n%f\n30\n%f\n",
|
fprintf(fp, "10\n%f\n20\n%f\n30\n%f\n",
|
||||||
stl->facet_start[i].vertex[0](0), stl->facet_start[i].vertex[0](1),
|
stl->facet_start[i].vertex[0](0), stl->facet_start[i].vertex[0](1),
|
||||||
|
@ -35,22 +35,38 @@
|
|||||||
#error "SEEK_SET not defined"
|
#error "SEEK_SET not defined"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void
|
void stl_open(stl_file *stl, const char *file)
|
||||||
stl_open(stl_file *stl, const char *file) {
|
{
|
||||||
stl_initialize(stl);
|
stl_initialize(stl);
|
||||||
stl_count_facets(stl, file);
|
stl_count_facets(stl, file);
|
||||||
stl_allocate(stl);
|
stl_allocate(stl);
|
||||||
stl_read(stl, 0, true);
|
stl_read(stl, 0, true);
|
||||||
if (stl->fp != nullptr) {
|
if (stl->fp != nullptr) {
|
||||||
fclose(stl->fp);
|
fclose(stl->fp);
|
||||||
stl->fp = nullptr;
|
stl->fp = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void stl_initialize(stl_file *stl)
|
||||||
stl_initialize(stl_file *stl) {
|
{
|
||||||
memset(stl, 0, sizeof(stl_file));
|
stl->fp = nullptr;
|
||||||
stl->stats.volume = -1.0;
|
stl->tail = nullptr;
|
||||||
|
stl->M = 0;
|
||||||
|
stl->error = 0;
|
||||||
|
stl->facet_start.clear();
|
||||||
|
stl->neighbors_start.clear();
|
||||||
|
stl->v_indices.clear();
|
||||||
|
stl->v_shared.clear();
|
||||||
|
memset(&stl->stats, 0, sizeof(stl_stats));
|
||||||
|
stl->stats.volume = -1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void stl_close(stl_file *stl)
|
||||||
|
{
|
||||||
|
assert(stl->fp == nullptr);
|
||||||
|
assert(stl->heads.empty());
|
||||||
|
assert(stl->tail == nullptr);
|
||||||
|
stl_initialize(stl);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef BOOST_LITTLE_ENDIAN
|
#ifndef BOOST_LITTLE_ENDIAN
|
||||||
@ -175,20 +191,14 @@ stl_count_facets(stl_file *stl, const char *file) {
|
|||||||
stl->stats.original_num_facets = stl->stats.number_of_facets;
|
stl->stats.original_num_facets = stl->stats.number_of_facets;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void stl_allocate(stl_file *stl)
|
||||||
stl_allocate(stl_file *stl) {
|
{
|
||||||
if (stl->error) return;
|
if (stl->error)
|
||||||
|
return;
|
||||||
/* Allocate memory for the entire .STL file */
|
// Allocate memory for the entire .STL file.
|
||||||
stl->facet_start = (stl_facet*)calloc(stl->stats.number_of_facets,
|
stl->facet_start.assign(stl->stats.number_of_facets, stl_facet());
|
||||||
sizeof(stl_facet));
|
// Allocate memory for the neighbors list.
|
||||||
if(stl->facet_start == NULL) perror("stl_initialize");
|
stl->neighbors_start.assign(stl->stats.number_of_facets, stl_neighbors());
|
||||||
stl->stats.facets_malloced = stl->stats.number_of_facets;
|
|
||||||
|
|
||||||
/* Allocate memory for the neighbors list */
|
|
||||||
stl->neighbors_start = (stl_neighbors*)
|
|
||||||
calloc(stl->stats.number_of_facets, sizeof(stl_neighbors));
|
|
||||||
if(stl->facet_start == NULL) perror("stl_initialize");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -237,23 +247,14 @@ stl_open_merge(stl_file *stl, char *file_to_merge) {
|
|||||||
stl->fp=origFp;
|
stl->fp=origFp;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern void
|
void stl_reallocate(stl_file *stl)
|
||||||
stl_reallocate(stl_file *stl) {
|
{
|
||||||
if (stl->error) return;
|
if (stl->error)
|
||||||
/* Reallocate more memory for the .STL file(s) */
|
return;
|
||||||
stl->facet_start = (stl_facet*)realloc(stl->facet_start, stl->stats.number_of_facets *
|
stl->facet_start.resize(stl->stats.number_of_facets);
|
||||||
sizeof(stl_facet));
|
stl->neighbors_start.resize(stl->stats.number_of_facets);
|
||||||
if(stl->facet_start == NULL) perror("stl_initialize");
|
|
||||||
stl->stats.facets_malloced = stl->stats.number_of_facets;
|
|
||||||
|
|
||||||
/* Reallocate more memory for the neighbors list */
|
|
||||||
stl->neighbors_start = (stl_neighbors*)
|
|
||||||
realloc(stl->neighbors_start, stl->stats.number_of_facets *
|
|
||||||
sizeof(stl_neighbors));
|
|
||||||
if(stl->facet_start == NULL) perror("stl_initialize");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Reads the contents of the file pointed to by stl->fp into the stl structure,
|
/* Reads the contents of the file pointed to by stl->fp into the stl structure,
|
||||||
starting at facet first_facet. The second argument says if it's our first
|
starting at facet first_facet. The second argument says if it's our first
|
||||||
time running this for the stl and therefore we should reset our max and min stats. */
|
time running this for the stl and therefore we should reset our max and min stats. */
|
||||||
@ -366,20 +367,3 @@ void stl_facet_stats(stl_file *stl, stl_facet facet, bool &first)
|
|||||||
stl->stats.max = stl->stats.max.cwiseMax(facet.vertex[i]);
|
stl->stats.max = stl->stats.max.cwiseMax(facet.vertex[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void stl_close(stl_file *stl)
|
|
||||||
{
|
|
||||||
assert(stl->fp == nullptr);
|
|
||||||
assert(stl->heads == nullptr);
|
|
||||||
assert(stl->tail == nullptr);
|
|
||||||
|
|
||||||
if (stl->facet_start != NULL)
|
|
||||||
free(stl->facet_start);
|
|
||||||
if (stl->neighbors_start != NULL)
|
|
||||||
free(stl->neighbors_start);
|
|
||||||
if (stl->v_indices != NULL)
|
|
||||||
free(stl->v_indices);
|
|
||||||
if (stl->v_shared != NULL)
|
|
||||||
free(stl->v_shared);
|
|
||||||
memset(stl, 0, sizeof(stl_file));
|
|
||||||
}
|
|
||||||
|
@ -32,45 +32,39 @@ static float get_area(stl_facet *facet);
|
|||||||
static float get_volume(stl_file *stl);
|
static float get_volume(stl_file *stl);
|
||||||
|
|
||||||
|
|
||||||
void
|
void stl_verify_neighbors(stl_file *stl)
|
||||||
stl_verify_neighbors(stl_file *stl) {
|
{
|
||||||
int i;
|
if (stl->error)
|
||||||
int j;
|
return;
|
||||||
stl_edge edge_a;
|
|
||||||
stl_edge edge_b;
|
|
||||||
int neighbor;
|
|
||||||
int vnot;
|
|
||||||
|
|
||||||
if (stl->error) return;
|
stl->stats.backwards_edges = 0;
|
||||||
|
|
||||||
stl->stats.backwards_edges = 0;
|
for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i) {
|
||||||
|
for (int j = 0; j < 3; ++ j) {
|
||||||
for(i = 0; i < stl->stats.number_of_facets; i++) {
|
stl_edge edge_a;
|
||||||
for(j = 0; j < 3; j++) {
|
edge_a.p1 = stl->facet_start[i].vertex[j];
|
||||||
edge_a.p1 = stl->facet_start[i].vertex[j];
|
edge_a.p2 = stl->facet_start[i].vertex[(j + 1) % 3];
|
||||||
edge_a.p2 = stl->facet_start[i].vertex[(j + 1) % 3];
|
int neighbor = stl->neighbors_start[i].neighbor[j];
|
||||||
neighbor = stl->neighbors_start[i].neighbor[j];
|
if (neighbor == -1)
|
||||||
vnot = stl->neighbors_start[i].which_vertex_not[j];
|
continue; // this edge has no neighbor... Continue.
|
||||||
|
int vnot = stl->neighbors_start[i].which_vertex_not[j];
|
||||||
if(neighbor == -1)
|
stl_edge edge_b;
|
||||||
continue; /* this edge has no neighbor... Continue. */
|
if (vnot < 3) {
|
||||||
if(vnot < 3) {
|
edge_b.p1 = stl->facet_start[neighbor].vertex[(vnot + 2) % 3];
|
||||||
edge_b.p1 = stl->facet_start[neighbor].vertex[(vnot + 2) % 3];
|
edge_b.p2 = stl->facet_start[neighbor].vertex[(vnot + 1) % 3];
|
||||||
edge_b.p2 = stl->facet_start[neighbor].vertex[(vnot + 1) % 3];
|
} else {
|
||||||
} else {
|
stl->stats.backwards_edges += 1;
|
||||||
stl->stats.backwards_edges += 1;
|
edge_b.p1 = stl->facet_start[neighbor].vertex[(vnot + 1) % 3];
|
||||||
edge_b.p1 = stl->facet_start[neighbor].vertex[(vnot + 1) % 3];
|
edge_b.p2 = stl->facet_start[neighbor].vertex[(vnot + 2) % 3];
|
||||||
edge_b.p2 = stl->facet_start[neighbor].vertex[(vnot + 2) % 3];
|
}
|
||||||
}
|
if (edge_a.p1 != edge_b.p1 || edge_a.p2 != edge_b.p2) {
|
||||||
if (edge_a.p1 != edge_b.p1 || edge_a.p2 != edge_b.p2) {
|
// These edges should match but they don't. Print results.
|
||||||
/* These edges should match but they don't. Print results. */
|
printf("edge %d of facet %d doesn't match edge %d of facet %d\n", j, i, vnot + 1, neighbor);
|
||||||
printf("edge %d of facet %d doesn't match edge %d of facet %d\n",
|
stl_write_facet(stl, (char*)"first facet", i);
|
||||||
j, i, vnot + 1, neighbor);
|
stl_write_facet(stl, (char*)"second facet", neighbor);
|
||||||
stl_write_facet(stl, (char*)"first facet", i);
|
}
|
||||||
stl_write_facet(stl, (char*)"second facet", neighbor);
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void stl_translate(stl_file *stl, float x, float y, float z)
|
void stl_translate(stl_file *stl, float x, float y, float z)
|
||||||
@ -263,21 +257,19 @@ void stl_mirror_yz(stl_file *stl)
|
|||||||
|
|
||||||
void stl_mirror_xz(stl_file *stl)
|
void stl_mirror_xz(stl_file *stl)
|
||||||
{
|
{
|
||||||
if (stl->error)
|
if (stl->error)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (int i = 0; i < stl->stats.number_of_facets; i++) {
|
for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i)
|
||||||
for (int j = 0; j < 3; j++) {
|
for (int j = 0; j < 3; ++ j)
|
||||||
stl->facet_start[i].vertex[j](1) *= -1.0;
|
stl->facet_start[i].vertex[j](1) *= -1.0;
|
||||||
}
|
float temp_size = stl->stats.min(1);
|
||||||
}
|
stl->stats.min(1) = stl->stats.max(1);
|
||||||
float temp_size = stl->stats.min(1);
|
stl->stats.max(1) = temp_size;
|
||||||
stl->stats.min(1) = stl->stats.max(1);
|
stl->stats.min(1) *= -1.0;
|
||||||
stl->stats.max(1) = temp_size;
|
stl->stats.max(1) *= -1.0;
|
||||||
stl->stats.min(1) *= -1.0;
|
stl_reverse_all_facets(stl);
|
||||||
stl->stats.max(1) *= -1.0;
|
stl->stats.facets_reversed -= stl->stats.number_of_facets; // for not altering stats
|
||||||
stl_reverse_all_facets(stl);
|
|
||||||
stl->stats.facets_reversed -= stl->stats.number_of_facets; /* for not altering stats */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static float get_volume(stl_file *stl)
|
static float get_volume(stl_file *stl)
|
||||||
@ -463,18 +455,18 @@ bool stl_validate(stl_file *stl)
|
|||||||
{
|
{
|
||||||
assert(! stl->error);
|
assert(! stl->error);
|
||||||
assert(stl->fp == nullptr);
|
assert(stl->fp == nullptr);
|
||||||
assert(stl->facet_start != nullptr);
|
assert(! stl->facet_start.empty());
|
||||||
assert(stl->heads == nullptr);
|
assert(stl->heads.empty());
|
||||||
assert(stl->tail == nullptr);
|
assert(stl->tail == nullptr);
|
||||||
assert(stl->neighbors_start != nullptr);
|
assert(! stl->neighbors_start.empty());
|
||||||
assert((stl->v_indices == nullptr) == (stl->v_shared == nullptr));
|
assert((stl->v_indices.empty()) == (stl->v_shared.empty()));
|
||||||
assert(stl->stats.number_of_facets > 0);
|
assert(stl->stats.number_of_facets > 0);
|
||||||
|
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
// Verify validity of neighborship data.
|
// Verify validity of neighborship data.
|
||||||
for (int facet_idx = 0; facet_idx < (int)stl->stats.number_of_facets; ++ facet_idx) {
|
for (int facet_idx = 0; facet_idx < (int)stl->stats.number_of_facets; ++ facet_idx) {
|
||||||
const stl_neighbors &nbr = stl->neighbors_start[facet_idx];
|
const stl_neighbors &nbr = stl->neighbors_start[facet_idx];
|
||||||
const int *vertices = (stl->v_indices == nullptr) ? nullptr : stl->v_indices[facet_idx].vertex;
|
const int *vertices = (stl->v_indices.empty()) ? nullptr : stl->v_indices[facet_idx].vertex;
|
||||||
for (int nbr_idx = 0; nbr_idx < 3; ++ nbr_idx) {
|
for (int nbr_idx = 0; nbr_idx < 3; ++ nbr_idx) {
|
||||||
int nbr_face = stl->neighbors_start[facet_idx].neighbor[nbr_idx];
|
int nbr_face = stl->neighbors_start[facet_idx].neighbor[nbr_idx];
|
||||||
assert(nbr_face < (int)stl->stats.number_of_facets);
|
assert(nbr_face < (int)stl->stats.number_of_facets);
|
||||||
|
@ -1885,7 +1885,7 @@ namespace Slic3r {
|
|||||||
volume->mesh.repair();
|
volume->mesh.repair();
|
||||||
|
|
||||||
stl_file& stl = volume->mesh.stl;
|
stl_file& stl = volume->mesh.stl;
|
||||||
if (stl.v_shared == nullptr)
|
if (stl.v_shared.empty())
|
||||||
stl_generate_shared_vertices(&stl);
|
stl_generate_shared_vertices(&stl);
|
||||||
|
|
||||||
if (stl.stats.shared_vertices == 0)
|
if (stl.stats.shared_vertices == 0)
|
||||||
|
@ -926,7 +926,7 @@ bool store_amf(const char *path, Model *model, const DynamicPrintConfig *config)
|
|||||||
if (! volume->mesh.repaired)
|
if (! volume->mesh.repaired)
|
||||||
throw std::runtime_error("store_amf() requires repair()");
|
throw std::runtime_error("store_amf() requires repair()");
|
||||||
auto &stl = volume->mesh.stl;
|
auto &stl = volume->mesh.stl;
|
||||||
if (stl.v_shared == nullptr)
|
if (stl.v_shared.empty())
|
||||||
stl_generate_shared_vertices(&stl);
|
stl_generate_shared_vertices(&stl);
|
||||||
const Transform3d& matrix = volume->get_matrix();
|
const Transform3d& matrix = volume->get_matrix();
|
||||||
for (size_t i = 0; i < stl.stats.shared_vertices; ++i) {
|
for (size_t i = 0; i < stl.stats.shared_vertices; ++i) {
|
||||||
|
@ -167,10 +167,10 @@ static void extract_model_from_archive(
|
|||||||
stl.stats.original_num_facets = header.nTriangles;
|
stl.stats.original_num_facets = header.nTriangles;
|
||||||
stl_allocate(&stl);
|
stl_allocate(&stl);
|
||||||
if (header.nTriangles > 0 && data.size() == 50 * header.nTriangles + sizeof(StlHeader)) {
|
if (header.nTriangles > 0 && data.size() == 50 * header.nTriangles + sizeof(StlHeader)) {
|
||||||
memcpy((char*)stl.facet_start, data.data() + sizeof(StlHeader), 50 * header.nTriangles);
|
memcpy((char*)stl.facet_start.data(), data.data() + sizeof(StlHeader), 50 * header.nTriangles);
|
||||||
if (sizeof(stl_facet) > SIZEOF_STL_FACET) {
|
if (sizeof(stl_facet) > SIZEOF_STL_FACET) {
|
||||||
// The stl.facet_start is not packed tightly. Unpack the array of stl_facets.
|
// The stl.facet_start is not packed tightly. Unpack the array of stl_facets.
|
||||||
unsigned char *data = (unsigned char*)stl.facet_start;
|
unsigned char *data = (unsigned char*)stl.facet_start.data();
|
||||||
for (size_t i = header.nTriangles - 1; i > 0; -- i)
|
for (size_t i = header.nTriangles - 1; i > 0; -- i)
|
||||||
memmove(data + i * sizeof(stl_facet), data + i * SIZEOF_STL_FACET, SIZEOF_STL_FACET);
|
memmove(data + i * sizeof(stl_facet), data + i * SIZEOF_STL_FACET, SIZEOF_STL_FACET);
|
||||||
}
|
}
|
||||||
@ -257,7 +257,7 @@ static void extract_model_from_archive(
|
|||||||
stl.stats.number_of_facets = (uint32_t)facets.size();
|
stl.stats.number_of_facets = (uint32_t)facets.size();
|
||||||
stl.stats.original_num_facets = (int)facets.size();
|
stl.stats.original_num_facets = (int)facets.size();
|
||||||
stl_allocate(&stl);
|
stl_allocate(&stl);
|
||||||
memcpy((void*)stl.facet_start, facets.data(), facets.size() * 50);
|
memcpy((void*)stl.facet_start.data(), facets.data(), facets.size() * 50);
|
||||||
stl_get_size(&stl);
|
stl_get_size(&stl);
|
||||||
mesh.repair();
|
mesh.repair();
|
||||||
// Add a mesh to a model.
|
// Add a mesh to a model.
|
||||||
|
@ -910,18 +910,16 @@ Polygon ModelObject::convex_hull_2d(const Transform3d &trafo_instance) const
|
|||||||
if (v->is_model_part()) {
|
if (v->is_model_part()) {
|
||||||
const stl_file &stl = v->mesh.stl;
|
const stl_file &stl = v->mesh.stl;
|
||||||
Transform3d trafo = trafo_instance * v->get_matrix();
|
Transform3d trafo = trafo_instance * v->get_matrix();
|
||||||
if (stl.v_shared == nullptr) {
|
if (stl.v_shared.empty()) {
|
||||||
// Using the STL faces.
|
// Using the STL faces.
|
||||||
for (unsigned int i = 0; i < stl.stats.number_of_facets; ++ i) {
|
for (const stl_facet &facet : stl.facet_start)
|
||||||
const stl_facet &facet = stl.facet_start[i];
|
|
||||||
for (size_t j = 0; j < 3; ++ j) {
|
for (size_t j = 0; j < 3; ++ j) {
|
||||||
Vec3d p = trafo * facet.vertex[j].cast<double>();
|
Vec3d p = trafo * facet.vertex[j].cast<double>();
|
||||||
pts.emplace_back(coord_t(scale_(p.x())), coord_t(scale_(p.y())));
|
pts.emplace_back(coord_t(scale_(p.x())), coord_t(scale_(p.y())));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// Using the shared vertices should be a bit quicker than using the STL faces.
|
// Using the shared vertices should be a bit quicker than using the STL faces.
|
||||||
for (int i = 0; i < stl.stats.shared_vertices; ++ i) {
|
for (int i = 0; i < stl.stats.shared_vertices; ++ i) {
|
||||||
Vec3d p = trafo * stl.v_shared[i].cast<double>();
|
Vec3d p = trafo * stl.v_shared[i].cast<double>();
|
||||||
pts.emplace_back(coord_t(scale_(p.x())), coord_t(scale_(p.y())));
|
pts.emplace_back(coord_t(scale_(p.x())), coord_t(scale_(p.y())));
|
||||||
}
|
}
|
||||||
@ -1347,13 +1345,9 @@ double ModelObject::get_instance_min_z(size_t instance_idx) const
|
|||||||
|
|
||||||
Transform3d mv = mi * v->get_matrix();
|
Transform3d mv = mi * v->get_matrix();
|
||||||
const TriangleMesh& hull = v->get_convex_hull();
|
const TriangleMesh& hull = v->get_convex_hull();
|
||||||
for (uint32_t f = 0; f < hull.stl.stats.number_of_facets; ++f)
|
for (const stl_facet &facet : hull.stl.facet_start)
|
||||||
{
|
for (int i = 0; i < 3; ++ i)
|
||||||
const stl_facet* facet = hull.stl.facet_start + f;
|
min_z = std::min(min_z, (mv * facet.vertex[i].cast<double>()).z());
|
||||||
min_z = std::min(min_z, Vec3d::UnitZ().dot(mv * facet->vertex[0].cast<double>()));
|
|
||||||
min_z = std::min(min_z, Vec3d::UnitZ().dot(mv * facet->vertex[1].cast<double>()));
|
|
||||||
min_z = std::min(min_z, Vec3d::UnitZ().dot(mv * facet->vertex[2].cast<double>()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return min_z + inst->get_offset(Z);
|
return min_z + inst->get_offset(Z);
|
||||||
|
@ -121,19 +121,10 @@ EigenMesh3D::EigenMesh3D(const TriangleMesh& tmesh): m_aabb(new AABBImpl()) {
|
|||||||
V.resize(3*stl.stats.number_of_facets, 3);
|
V.resize(3*stl.stats.number_of_facets, 3);
|
||||||
F.resize(stl.stats.number_of_facets, 3);
|
F.resize(stl.stats.number_of_facets, 3);
|
||||||
for (unsigned int i = 0; i < stl.stats.number_of_facets; ++i) {
|
for (unsigned int i = 0; i < stl.stats.number_of_facets; ++i) {
|
||||||
const stl_facet* facet = stl.facet_start+i;
|
const stl_facet &facet = stl.facet_start[i];
|
||||||
V(3*i+0, 0) = double(facet->vertex[0](0));
|
V.block<1, 3>(3 * i + 0, 0) = facet.vertex[0].cast<double>();
|
||||||
V(3*i+0, 1) = double(facet->vertex[0](1));
|
V.block<1, 3>(3 * i + 1, 0) = facet.vertex[1].cast<double>();
|
||||||
V(3*i+0, 2) = double(facet->vertex[0](2));
|
V.block<1, 3>(3 * i + 2, 0) = facet.vertex[2].cast<double>();
|
||||||
|
|
||||||
V(3*i+1, 0) = double(facet->vertex[1](0));
|
|
||||||
V(3*i+1, 1) = double(facet->vertex[1](1));
|
|
||||||
V(3*i+1, 2) = double(facet->vertex[1](2));
|
|
||||||
|
|
||||||
V(3*i+2, 0) = double(facet->vertex[2](0));
|
|
||||||
V(3*i+2, 1) = double(facet->vertex[2](1));
|
|
||||||
V(3*i+2, 2) = double(facet->vertex[2](2));
|
|
||||||
|
|
||||||
F(i, 0) = int(3*i+0);
|
F(i, 0) = int(3*i+0);
|
||||||
F(i, 1) = int(3*i+1);
|
F(i, 1) = int(3*i+1);
|
||||||
F(i, 2) = int(3*i+2);
|
F(i, 2) = int(3*i+2);
|
||||||
|
@ -27,8 +27,8 @@ void SlicingAdaptive::prepare()
|
|||||||
nfaces_total += (*it_mesh)->stl.stats.number_of_facets;
|
nfaces_total += (*it_mesh)->stl.stats.number_of_facets;
|
||||||
m_faces.reserve(nfaces_total);
|
m_faces.reserve(nfaces_total);
|
||||||
for (std::vector<const TriangleMesh*>::const_iterator it_mesh = m_meshes.begin(); it_mesh != m_meshes.end(); ++ it_mesh)
|
for (std::vector<const TriangleMesh*>::const_iterator it_mesh = m_meshes.begin(); it_mesh != m_meshes.end(); ++ it_mesh)
|
||||||
for (int i = 0; i < (*it_mesh)->stl.stats.number_of_facets; ++ i)
|
for (const stl_facet &face : (*it_mesh)->stl.facet_start)
|
||||||
m_faces.push_back((*it_mesh)->stl.facet_start + i);
|
m_faces.emplace_back(&face);
|
||||||
|
|
||||||
// 2) Sort faces lexicographically by their Z span.
|
// 2) Sort faces lexicographically by their Z span.
|
||||||
std::sort(m_faces.begin(), m_faces.end(), [](const stl_facet *f1, const stl_facet *f2) {
|
std::sort(m_faces.begin(), m_faces.end(), [](const stl_facet *f1, const stl_facet *f2) {
|
||||||
|
@ -51,7 +51,7 @@ TriangleMesh::TriangleMesh(const Pointf3s &points, const std::vector<Vec3crd>& f
|
|||||||
stl.stats.type = inmemory;
|
stl.stats.type = inmemory;
|
||||||
|
|
||||||
// count facets and allocate memory
|
// count facets and allocate memory
|
||||||
stl.stats.number_of_facets = facets.size();
|
stl.stats.number_of_facets = (uint32_t)facets.size();
|
||||||
stl.stats.original_num_facets = stl.stats.number_of_facets;
|
stl.stats.original_num_facets = stl.stats.number_of_facets;
|
||||||
stl_allocate(&stl);
|
stl_allocate(&stl);
|
||||||
|
|
||||||
@ -78,25 +78,14 @@ TriangleMesh& TriangleMesh::operator=(const TriangleMesh &other)
|
|||||||
stl_close(&this->stl);
|
stl_close(&this->stl);
|
||||||
this->stl = other.stl;
|
this->stl = other.stl;
|
||||||
this->repaired = other.repaired;
|
this->repaired = other.repaired;
|
||||||
this->stl.heads = nullptr;
|
this->stl.heads.clear();
|
||||||
this->stl.tail = nullptr;
|
this->stl.tail = nullptr;
|
||||||
this->stl.error = other.stl.error;
|
this->stl.error = other.stl.error;
|
||||||
if (other.stl.facet_start != nullptr) {
|
this->stl.facet_start = other.stl.facet_start;
|
||||||
this->stl.facet_start = (stl_facet*)calloc(other.stl.stats.number_of_facets, sizeof(stl_facet));
|
this->stl.neighbors_start = other.stl.neighbors_start;
|
||||||
std::copy(other.stl.facet_start, other.stl.facet_start + other.stl.stats.number_of_facets, this->stl.facet_start);
|
this->stl.v_indices = other.stl.v_indices;
|
||||||
}
|
this->stl.v_shared = other.stl.v_shared;
|
||||||
if (other.stl.neighbors_start != nullptr) {
|
this->stl.stats = other.stl.stats;
|
||||||
this->stl.neighbors_start = (stl_neighbors*)calloc(other.stl.stats.number_of_facets, sizeof(stl_neighbors));
|
|
||||||
std::copy(other.stl.neighbors_start, other.stl.neighbors_start + other.stl.stats.number_of_facets, this->stl.neighbors_start);
|
|
||||||
}
|
|
||||||
if (other.stl.v_indices != nullptr) {
|
|
||||||
this->stl.v_indices = (v_indices_struct*)calloc(other.stl.stats.number_of_facets, sizeof(v_indices_struct));
|
|
||||||
std::copy(other.stl.v_indices, other.stl.v_indices + other.stl.stats.number_of_facets, this->stl.v_indices);
|
|
||||||
}
|
|
||||||
if (other.stl.v_shared != nullptr) {
|
|
||||||
this->stl.v_shared = (stl_vertex*)calloc(other.stl.stats.shared_vertices, sizeof(stl_vertex));
|
|
||||||
std::copy(other.stl.v_shared, other.stl.v_shared + other.stl.stats.shared_vertices, this->stl.v_shared);
|
|
||||||
}
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,8 +114,8 @@ void TriangleMesh::repair()
|
|||||||
|
|
||||||
// checking nearby
|
// checking nearby
|
||||||
//int last_edges_fixed = 0;
|
//int last_edges_fixed = 0;
|
||||||
float tolerance = stl.stats.shortest_edge;
|
float tolerance = (float)stl.stats.shortest_edge;
|
||||||
float increment = stl.stats.bounding_diameter / 10000.0;
|
float increment = (float)stl.stats.bounding_diameter / 10000.0f;
|
||||||
int iterations = 2;
|
int iterations = 2;
|
||||||
if (stl.stats.connected_facets_3_edge < (int)stl.stats.number_of_facets) {
|
if (stl.stats.connected_facets_3_edge < (int)stl.stats.number_of_facets) {
|
||||||
for (int i = 0; i < iterations; i++) {
|
for (int i = 0; i < iterations; i++) {
|
||||||
@ -444,7 +433,7 @@ TriangleMeshPtrs TriangleMesh::split() const
|
|||||||
TriangleMesh* mesh = new TriangleMesh;
|
TriangleMesh* mesh = new TriangleMesh;
|
||||||
meshes.emplace_back(mesh);
|
meshes.emplace_back(mesh);
|
||||||
mesh->stl.stats.type = inmemory;
|
mesh->stl.stats.type = inmemory;
|
||||||
mesh->stl.stats.number_of_facets = facets.size();
|
mesh->stl.stats.number_of_facets = (uint32_t)facets.size();
|
||||||
mesh->stl.stats.original_num_facets = mesh->stl.stats.number_of_facets;
|
mesh->stl.stats.original_num_facets = mesh->stl.stats.number_of_facets;
|
||||||
stl_clear_error(&mesh->stl);
|
stl_clear_error(&mesh->stl);
|
||||||
stl_allocate(&mesh->stl);
|
stl_allocate(&mesh->stl);
|
||||||
@ -486,13 +475,12 @@ ExPolygons TriangleMesh::horizontal_projection() const
|
|||||||
{
|
{
|
||||||
Polygons pp;
|
Polygons pp;
|
||||||
pp.reserve(this->stl.stats.number_of_facets);
|
pp.reserve(this->stl.stats.number_of_facets);
|
||||||
for (uint32_t i = 0; i < this->stl.stats.number_of_facets; ++ i) {
|
for (const stl_facet &facet : this->stl.facet_start) {
|
||||||
stl_facet* facet = &this->stl.facet_start[i];
|
|
||||||
Polygon p;
|
Polygon p;
|
||||||
p.points.resize(3);
|
p.points.resize(3);
|
||||||
p.points[0] = Point::new_scale(facet->vertex[0](0), facet->vertex[0](1));
|
p.points[0] = Point::new_scale(facet.vertex[0](0), facet.vertex[0](1));
|
||||||
p.points[1] = Point::new_scale(facet->vertex[1](0), facet->vertex[1](1));
|
p.points[1] = Point::new_scale(facet.vertex[1](0), facet.vertex[1](1));
|
||||||
p.points[2] = Point::new_scale(facet->vertex[2](0), facet->vertex[2](1));
|
p.points[2] = Point::new_scale(facet.vertex[2](0), facet.vertex[2](1));
|
||||||
p.make_counter_clockwise(); // do this after scaling, as winding order might change while doing that
|
p.make_counter_clockwise(); // do this after scaling, as winding order might change while doing that
|
||||||
pp.emplace_back(p);
|
pp.emplace_back(p);
|
||||||
}
|
}
|
||||||
@ -526,17 +514,15 @@ BoundingBoxf3 TriangleMesh::bounding_box() const
|
|||||||
BoundingBoxf3 TriangleMesh::transformed_bounding_box(const Transform3d &trafo) const
|
BoundingBoxf3 TriangleMesh::transformed_bounding_box(const Transform3d &trafo) const
|
||||||
{
|
{
|
||||||
BoundingBoxf3 bbox;
|
BoundingBoxf3 bbox;
|
||||||
if (stl.v_shared == nullptr) {
|
if (stl.v_shared.empty()) {
|
||||||
// Using the STL faces.
|
// Using the STL faces.
|
||||||
for (size_t i = 0; i < this->facets_count(); ++ i) {
|
for (const stl_facet &facet : this->stl.facet_start)
|
||||||
const stl_facet &facet = this->stl.facet_start[i];
|
|
||||||
for (size_t j = 0; j < 3; ++ j)
|
for (size_t j = 0; j < 3; ++ j)
|
||||||
bbox.merge(trafo * facet.vertex[j].cast<double>());
|
bbox.merge(trafo * facet.vertex[j].cast<double>());
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// Using the shared vertices should be a bit quicker than using the STL faces.
|
// Using the shared vertices should be a bit quicker than using the STL faces.
|
||||||
for (int i = 0; i < stl.stats.shared_vertices; ++ i)
|
for (const stl_vertex &v : this->stl.v_shared)
|
||||||
bbox.merge(trafo * this->stl.v_shared[i].cast<double>());
|
bbox.merge(trafo * v.cast<double>());
|
||||||
}
|
}
|
||||||
return bbox;
|
return bbox;
|
||||||
}
|
}
|
||||||
@ -551,18 +537,12 @@ TriangleMesh TriangleMesh::convex_hull_3d() const
|
|||||||
std::vector<PointForQHull> src_vertices;
|
std::vector<PointForQHull> src_vertices;
|
||||||
|
|
||||||
// We will now fill the vector with input points for computation:
|
// We will now fill the vector with input points for computation:
|
||||||
stl_facet* facet_ptr = stl.facet_start;
|
for (const stl_facet &facet : stl.facet_start)
|
||||||
while (facet_ptr < stl.facet_start + stl.stats.number_of_facets)
|
for (int i = 0; i < 3; ++ i) {
|
||||||
{
|
const stl_vertex& v = facet.vertex[i];
|
||||||
for (int i = 0; i < 3; ++i)
|
|
||||||
{
|
|
||||||
const stl_vertex& v = facet_ptr->vertex[i];
|
|
||||||
src_vertices.emplace_back(v(0), v(1), v(2));
|
src_vertices.emplace_back(v(0), v(1), v(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
facet_ptr += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The qhull call:
|
// The qhull call:
|
||||||
orgQhull::Qhull qhull;
|
orgQhull::Qhull qhull;
|
||||||
qhull.disableOutputStream(); // we want qhull to be quiet
|
qhull.disableOutputStream(); // we want qhull to be quiet
|
||||||
@ -606,7 +586,7 @@ void TriangleMesh::require_shared_vertices()
|
|||||||
assert(stl_validate(&this->stl));
|
assert(stl_validate(&this->stl));
|
||||||
if (! this->repaired)
|
if (! this->repaired)
|
||||||
this->repair();
|
this->repair();
|
||||||
if (this->stl.v_shared == nullptr) {
|
if (this->stl.v_shared.empty()) {
|
||||||
BOOST_LOG_TRIVIAL(trace) << "TriangleMeshSlicer::require_shared_vertices - stl_generate_shared_vertices";
|
BOOST_LOG_TRIVIAL(trace) << "TriangleMeshSlicer::require_shared_vertices - stl_generate_shared_vertices";
|
||||||
stl_generate_shared_vertices(&(this->stl));
|
stl_generate_shared_vertices(&(this->stl));
|
||||||
}
|
}
|
||||||
@ -622,10 +602,9 @@ void TriangleMeshSlicer::init(const TriangleMesh *_mesh, throw_on_cancel_callbac
|
|||||||
|
|
||||||
throw_on_cancel();
|
throw_on_cancel();
|
||||||
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.size(), stl_vertex());
|
||||||
// Scale the copied vertices.
|
for (size_t i = 0; i < v_scaled_shared.size(); ++ i)
|
||||||
for (int i = 0; i < this->mesh->stl.stats.shared_vertices; ++ i)
|
this->v_scaled_shared[i] = _mesh->stl.v_shared[i] / float(SCALING_FACTOR);
|
||||||
this->v_scaled_shared[i] *= float(1. / SCALING_FACTOR);
|
|
||||||
|
|
||||||
// Create a mapping from triangle edge into face.
|
// Create a mapping from triangle edge into face.
|
||||||
struct EdgeToFace {
|
struct EdgeToFace {
|
||||||
@ -814,7 +793,7 @@ void TriangleMeshSlicer::slice(const std::vector<float> &z, std::vector<Polygons
|
|||||||
void TriangleMeshSlicer::_slice_do(size_t facet_idx, std::vector<IntersectionLines>* lines, boost::mutex* lines_mutex,
|
void TriangleMeshSlicer::_slice_do(size_t facet_idx, std::vector<IntersectionLines>* lines, boost::mutex* lines_mutex,
|
||||||
const std::vector<float> &z) const
|
const std::vector<float> &z) const
|
||||||
{
|
{
|
||||||
const stl_facet &facet = m_use_quaternion ? this->mesh->stl.facet_start[facet_idx].rotated(m_quaternion) : this->mesh->stl.facet_start[facet_idx];
|
const stl_facet &facet = m_use_quaternion ? (this->mesh->stl.facet_start.data() + facet_idx)->rotated(m_quaternion) : *(this->mesh->stl.facet_start.data() + facet_idx);
|
||||||
|
|
||||||
// find facet extents
|
// find facet extents
|
||||||
const float min_z = fminf(facet.vertex[0](2), fminf(facet.vertex[1](2), facet.vertex[2](2)));
|
const float min_z = fminf(facet.vertex[0](2), fminf(facet.vertex[1](2), facet.vertex[2](2)));
|
||||||
@ -1710,7 +1689,7 @@ void TriangleMeshSlicer::cut(float z, TriangleMesh* upper, TriangleMesh* lower)
|
|||||||
BOOST_LOG_TRIVIAL(trace) << "TriangleMeshSlicer::cut - slicing object";
|
BOOST_LOG_TRIVIAL(trace) << "TriangleMeshSlicer::cut - slicing object";
|
||||||
float scaled_z = scale_(z);
|
float scaled_z = scale_(z);
|
||||||
for (uint32_t facet_idx = 0; facet_idx < this->mesh->stl.stats.number_of_facets; ++ facet_idx) {
|
for (uint32_t facet_idx = 0; facet_idx < this->mesh->stl.stats.number_of_facets; ++ facet_idx) {
|
||||||
stl_facet* facet = &this->mesh->stl.facet_start[facet_idx];
|
const stl_facet* facet = &this->mesh->stl.facet_start[facet_idx];
|
||||||
|
|
||||||
// find facet extents
|
// find facet extents
|
||||||
float min_z = std::min(facet->vertex[0](2), std::min(facet->vertex[1](2), facet->vertex[2](2)));
|
float min_z = std::min(facet->vertex[0](2), std::min(facet->vertex[1](2), facet->vertex[2](2)));
|
||||||
@ -1901,10 +1880,10 @@ TriangleMesh make_cylinder(double r, double h, double fa)
|
|||||||
//FIXME better to discretize an Icosahedron recursively http://www.songho.ca/opengl/gl_sphere.html
|
//FIXME better to discretize an Icosahedron recursively http://www.songho.ca/opengl/gl_sphere.html
|
||||||
TriangleMesh make_sphere(double radius, double fa)
|
TriangleMesh make_sphere(double radius, double fa)
|
||||||
{
|
{
|
||||||
int sectorCount = ceil(2. * M_PI / fa);
|
int sectorCount = int(ceil(2. * M_PI / fa));
|
||||||
int stackCount = ceil(M_PI / fa);
|
int stackCount = int(ceil(M_PI / fa));
|
||||||
float sectorStep = 2. * M_PI / sectorCount;
|
float sectorStep = float(2. * M_PI / sectorCount);
|
||||||
float stackStep = M_PI / stackCount;
|
float stackStep = float(M_PI / stackCount);
|
||||||
|
|
||||||
Pointf3s vertices;
|
Pointf3s vertices;
|
||||||
vertices.reserve((stackCount - 1) * sectorCount + 2);
|
vertices.reserve((stackCount - 1) * sectorCount + 2);
|
||||||
|
@ -58,7 +58,7 @@ public:
|
|||||||
TriangleMeshPtrs split() const;
|
TriangleMeshPtrs split() const;
|
||||||
void merge(const TriangleMesh &mesh);
|
void merge(const TriangleMesh &mesh);
|
||||||
ExPolygons horizontal_projection() const;
|
ExPolygons horizontal_projection() const;
|
||||||
const float* first_vertex() const { return this->stl.facet_start ? &this->stl.facet_start->vertex[0](0) : nullptr; }
|
const float* first_vertex() const { return this->stl.facet_start.empty() ? nullptr : &this->stl.facet_start.front().vertex[0](0); }
|
||||||
// 2D convex hull of a 3D mesh projected into the Z=0 plane.
|
// 2D convex hull of a 3D mesh projected into the Z=0 plane.
|
||||||
Polygon convex_hull();
|
Polygon convex_hull();
|
||||||
BoundingBoxf3 bounding_box() const;
|
BoundingBoxf3 bounding_box() const;
|
||||||
@ -69,7 +69,7 @@ public:
|
|||||||
void reset_repair_stats();
|
void reset_repair_stats();
|
||||||
bool needed_repair() const;
|
bool needed_repair() const;
|
||||||
void require_shared_vertices();
|
void require_shared_vertices();
|
||||||
bool has_shared_vertices() const { return stl.v_shared != NULL; }
|
bool has_shared_vertices() const { return ! stl.v_shared.empty(); }
|
||||||
size_t facets_count() const { return this->stl.stats.number_of_facets; }
|
size_t facets_count() const { return this->stl.stats.number_of_facets; }
|
||||||
bool empty() const { return this->facets_count() == 0; }
|
bool empty() const { return this->facets_count() == 0; }
|
||||||
bool is_splittable() const;
|
bool is_splittable() const;
|
||||||
|
@ -396,10 +396,10 @@ void GLGizmoSlaSupports::update_mesh()
|
|||||||
V.resize(3 * stl.stats.number_of_facets, 3);
|
V.resize(3 * stl.stats.number_of_facets, 3);
|
||||||
F.resize(stl.stats.number_of_facets, 3);
|
F.resize(stl.stats.number_of_facets, 3);
|
||||||
for (unsigned int i=0; i<stl.stats.number_of_facets; ++i) {
|
for (unsigned int i=0; i<stl.stats.number_of_facets; ++i) {
|
||||||
const stl_facet* facet = stl.facet_start+i;
|
const stl_facet &facet = stl.facet_start[i];
|
||||||
V(3*i+0, 0) = facet->vertex[0](0); V(3*i+0, 1) = facet->vertex[0](1); V(3*i+0, 2) = facet->vertex[0](2);
|
V.block<1, 3>(3 * i + 0, 0) = facet.vertex[0];
|
||||||
V(3*i+1, 0) = facet->vertex[1](0); V(3*i+1, 1) = facet->vertex[1](1); V(3*i+1, 2) = facet->vertex[1](2);
|
V.block<1, 3>(3 * i + 1, 0) = facet.vertex[1];
|
||||||
V(3*i+2, 0) = facet->vertex[2](0); V(3*i+2, 1) = facet->vertex[2](1); V(3*i+2, 2) = facet->vertex[2](2);
|
V.block<1, 3>(3 * i + 2, 0) = facet.vertex[2];
|
||||||
F(i, 0) = 3*i+0;
|
F(i, 0) = 3*i+0;
|
||||||
F(i, 1) = 3*i+1;
|
F(i, 1) = 3*i+1;
|
||||||
F(i, 2) = 3*i+2;
|
F(i, 2) = 3*i+2;
|
||||||
|
Loading…
Reference in New Issue
Block a user