mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-11 08:47:52 -06:00
admesh refactoring: Use Eigen vec3i for indexed triangles.
This commit is contained in:
parent
313ec7424a
commit
af5017c46c
10 changed files with 369 additions and 493 deletions
|
@ -196,13 +196,13 @@ struct HashTableEdges {
|
||||||
|
|
||||||
// Hash table on edges
|
// Hash table on edges
|
||||||
std::vector<HashEdge*> heads;
|
std::vector<HashEdge*> heads;
|
||||||
HashEdge* tail;
|
HashEdge* tail;
|
||||||
int M;
|
int M;
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
size_t malloced = 0;
|
size_t malloced = 0;
|
||||||
size_t freed = 0;
|
size_t freed = 0;
|
||||||
size_t collisions = 0;
|
size_t collisions = 0;
|
||||||
#endif /* NDEBUG */
|
#endif /* NDEBUG */
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -27,19 +27,16 @@
|
||||||
|
|
||||||
#include "stl.h"
|
#include "stl.h"
|
||||||
|
|
||||||
static int stl_check_normal_vector(stl_file *stl, int facet_num, int normal_fix_flag);
|
|
||||||
|
|
||||||
static void reverse_facet(stl_file *stl, int facet_num)
|
static void reverse_facet(stl_file *stl, int facet_num)
|
||||||
{
|
{
|
||||||
stl->stats.facets_reversed += 1;
|
++ stl->stats.facets_reversed;
|
||||||
|
|
||||||
int neighbor[3] = { stl->neighbors_start[facet_num].neighbor[0], stl->neighbors_start[facet_num].neighbor[1], stl->neighbors_start[facet_num].neighbor[2] };
|
int neighbor[3] = { stl->neighbors_start[facet_num].neighbor[0], stl->neighbors_start[facet_num].neighbor[1], stl->neighbors_start[facet_num].neighbor[2] };
|
||||||
int vnot[3] = { stl->neighbors_start[facet_num].which_vertex_not[0], stl->neighbors_start[facet_num].which_vertex_not[1], stl->neighbors_start[facet_num].which_vertex_not[2] };
|
int vnot[3] = { stl->neighbors_start[facet_num].which_vertex_not[0], stl->neighbors_start[facet_num].which_vertex_not[1], stl->neighbors_start[facet_num].which_vertex_not[2] };
|
||||||
|
|
||||||
// reverse the facet
|
// reverse the facet
|
||||||
stl_vertex tmp_vertex = stl->facet_start[facet_num].vertex[0];
|
stl_vertex tmp_vertex = stl->facet_start[facet_num].vertex[0];
|
||||||
stl->facet_start[facet_num].vertex[0] =
|
stl->facet_start[facet_num].vertex[0] = stl->facet_start[facet_num].vertex[1];
|
||||||
stl->facet_start[facet_num].vertex[1];
|
|
||||||
stl->facet_start[facet_num].vertex[1] = tmp_vertex;
|
stl->facet_start[facet_num].vertex[1] = tmp_vertex;
|
||||||
|
|
||||||
// fix the vnots of the neighboring facets
|
// fix the vnots of the neighboring facets
|
||||||
|
@ -64,187 +61,164 @@ static void reverse_facet(stl_file *stl, int facet_num)
|
||||||
stl->neighbors_start[facet_num].which_vertex_not[2] = (stl->neighbors_start[facet_num].which_vertex_not[2] + 3) % 6;
|
stl->neighbors_start[facet_num].which_vertex_not[2] = (stl->neighbors_start[facet_num].which_vertex_not[2] + 3) % 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
void stl_fix_normal_directions(stl_file *stl)
|
// Returns true if the normal was flipped.
|
||||||
|
static bool check_normal_vector(stl_file *stl, int facet_num, int normal_fix_flag)
|
||||||
{
|
{
|
||||||
/* int edge_num;*/
|
stl_facet *facet = &stl->facet_start[facet_num];
|
||||||
/* int vnot;*/
|
|
||||||
int checked = 0;
|
|
||||||
int facet_num;
|
|
||||||
/* int next_facet;*/
|
|
||||||
int i;
|
|
||||||
int j;
|
|
||||||
struct stl_normal {
|
|
||||||
int facet_num;
|
|
||||||
struct stl_normal *next;
|
|
||||||
};
|
|
||||||
struct stl_normal *head;
|
|
||||||
struct stl_normal *tail;
|
|
||||||
struct stl_normal *newn;
|
|
||||||
struct stl_normal *temp;
|
|
||||||
|
|
||||||
int reversed_count = 0;
|
stl_normal normal;
|
||||||
int id;
|
stl_calculate_normal(normal, facet);
|
||||||
int force_exit = 0;
|
stl_normalize_vector(normal);
|
||||||
|
stl_normal normal_dif = (normal - facet->normal).cwiseAbs();
|
||||||
|
|
||||||
// this may happen for malformed models, see: https://github.com/prusa3d/PrusaSlicer/issues/2209
|
const float eps = 0.001f;
|
||||||
if (stl->stats.number_of_facets == 0) return;
|
if (normal_dif(0) < eps && normal_dif(1) < eps && normal_dif(2) < eps) {
|
||||||
|
// Normal is within tolerance. It is not really necessary to change the values here, but just for consistency, I will.
|
||||||
|
facet->normal = normal;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/* Initialize linked list. */
|
stl_normal test_norm = facet->normal;
|
||||||
head = new stl_normal;
|
stl_normalize_vector(test_norm);
|
||||||
tail = new stl_normal;
|
normal_dif = (normal - test_norm).cwiseAbs();
|
||||||
head->next = tail;
|
if (normal_dif(0) < eps && normal_dif(1) < eps && normal_dif(2) < eps) {
|
||||||
tail->next = tail;
|
// The normal is not within tolerance, but direction is OK.
|
||||||
|
if (normal_fix_flag) {
|
||||||
|
facet->normal = normal;
|
||||||
|
++ stl->stats.normals_fixed;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/* Initialize list that keeps track of already fixed facets. */
|
test_norm *= -1.f;
|
||||||
std::vector<char> norm_sw(stl->stats.number_of_facets, 0);
|
normal_dif = (normal - test_norm).cwiseAbs();
|
||||||
/* Initialize list that keeps track of reversed facets. */
|
if (normal_dif(0) < eps && normal_dif(1) < eps && normal_dif(2) < eps) {
|
||||||
std::vector<int> reversed_ids(stl->stats.number_of_facets, 0);
|
// The normal is not within tolerance and backwards.
|
||||||
|
if (normal_fix_flag) {
|
||||||
facet_num = 0;
|
facet->normal = normal;
|
||||||
/* If normal vector is not within tolerance and backwards:
|
++ stl->stats.normals_fixed;
|
||||||
Arbitrarily starts at face 0. If this one is wrong, we're screwed. Thankfully, the chances
|
}
|
||||||
of it being wrong randomly are low if most of the triangles are right: */
|
return true;
|
||||||
if (stl_check_normal_vector(stl, 0, 0) == 2) {
|
}
|
||||||
reverse_facet(stl, 0);
|
if (normal_fix_flag) {
|
||||||
reversed_ids[reversed_count++] = 0;
|
facet->normal = normal;
|
||||||
}
|
++ stl->stats.normals_fixed;
|
||||||
|
}
|
||||||
/* Say that we've fixed this facet: */
|
// Status is unknown.
|
||||||
norm_sw[facet_num] = 1;
|
return false;
|
||||||
checked++;
|
|
||||||
|
|
||||||
for(;;) {
|
|
||||||
/* Add neighbors_to_list.
|
|
||||||
Add unconnected neighbors to the list:a */
|
|
||||||
for(j = 0; j < 3; j++) {
|
|
||||||
/* Reverse the neighboring facets if necessary. */
|
|
||||||
if(stl->neighbors_start[facet_num].which_vertex_not[j] > 2) {
|
|
||||||
/* If the facet has a neighbor that is -1, it means that edge isn't shared by another facet */
|
|
||||||
if(stl->neighbors_start[facet_num].neighbor[j] != -1) {
|
|
||||||
if (norm_sw[stl->neighbors_start[facet_num].neighbor[j]] == 1) {
|
|
||||||
/* trying to modify a facet already marked as fixed, revert all changes made until now and exit (fixes: #716, #574, #413, #269, #262, #259, #230, #228, #206) */
|
|
||||||
for (id = reversed_count - 1; id >= 0; --id) {
|
|
||||||
reverse_facet(stl, reversed_ids[id]);
|
|
||||||
}
|
|
||||||
force_exit = 1;
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
reverse_facet(stl, stl->neighbors_start[facet_num].neighbor[j]);
|
|
||||||
reversed_ids[reversed_count++] = stl->neighbors_start[facet_num].neighbor[j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* If this edge of the facet is connected: */
|
|
||||||
if(stl->neighbors_start[facet_num].neighbor[j] != -1) {
|
|
||||||
/* If we haven't fixed this facet yet, add it to the list: */
|
|
||||||
if(norm_sw[stl->neighbors_start[facet_num].neighbor[j]] != 1) {
|
|
||||||
/* Add node to beginning of list. */
|
|
||||||
newn = new stl_normal;
|
|
||||||
newn->facet_num = stl->neighbors_start[facet_num].neighbor[j];
|
|
||||||
newn->next = head->next;
|
|
||||||
head->next = newn;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* an error occourred, quit the for loop and exit */
|
|
||||||
if (force_exit) break;
|
|
||||||
|
|
||||||
/* Get next facet to fix from top of list. */
|
|
||||||
if(head->next != tail) {
|
|
||||||
facet_num = head->next->facet_num;
|
|
||||||
if(norm_sw[facet_num] != 1) { /* If facet is in list mutiple times */
|
|
||||||
norm_sw[facet_num] = 1; /* Record this one as being fixed. */
|
|
||||||
checked++;
|
|
||||||
}
|
|
||||||
temp = head->next; /* Delete this facet from the list. */
|
|
||||||
head->next = head->next->next;
|
|
||||||
delete temp;
|
|
||||||
} else { /* if we ran out of facets to fix: */
|
|
||||||
/* All of the facets in this part have been fixed. */
|
|
||||||
stl->stats.number_of_parts += 1;
|
|
||||||
if(checked >= stl->stats.number_of_facets) {
|
|
||||||
/* All of the facets have been checked. Bail out. */
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
/* There is another part here. Find it and continue. */
|
|
||||||
for(i = 0; i < stl->stats.number_of_facets; i++) {
|
|
||||||
if(norm_sw[i] == 0) {
|
|
||||||
/* This is the first facet of the next part. */
|
|
||||||
facet_num = i;
|
|
||||||
if(stl_check_normal_vector(stl, i, 0) == 2) {
|
|
||||||
reverse_facet(stl, i);
|
|
||||||
reversed_ids[reversed_count++] = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
norm_sw[facet_num] = 1;
|
|
||||||
checked++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
delete head;
|
|
||||||
delete tail;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int stl_check_normal_vector(stl_file *stl, int facet_num, int normal_fix_flag)
|
void stl_fix_normal_directions(stl_file *stl)
|
||||||
{
|
{
|
||||||
/* Returns 0 if the normal is within tolerance */
|
// This may happen for malformed models, see: https://github.com/prusa3d/PrusaSlicer/issues/2209
|
||||||
/* Returns 1 if the normal is not within tolerance, but direction is OK */
|
if (stl->stats.number_of_facets == 0)
|
||||||
/* Returns 2 if the normal is not within tolerance and backwards */
|
return;
|
||||||
/* Returns 4 if the status is unknown. */
|
|
||||||
|
|
||||||
stl_facet *facet;
|
struct stl_normal {
|
||||||
|
int facet_num;
|
||||||
|
stl_normal *next;
|
||||||
|
};
|
||||||
|
|
||||||
facet = &stl->facet_start[facet_num];
|
// Initialize linked list.
|
||||||
|
stl_normal *head = new stl_normal;
|
||||||
|
stl_normal *tail = new stl_normal;
|
||||||
|
head->next = tail;
|
||||||
|
tail->next = tail;
|
||||||
|
|
||||||
stl_normal normal;
|
// Initialize list that keeps track of already fixed facets.
|
||||||
stl_calculate_normal(normal, facet);
|
std::vector<char> norm_sw(stl->stats.number_of_facets, 0);
|
||||||
stl_normalize_vector(normal);
|
// Initialize list that keeps track of reversed facets.
|
||||||
stl_normal normal_dif = (normal - facet->normal).cwiseAbs();
|
std::vector<int> reversed_ids(stl->stats.number_of_facets, 0);
|
||||||
|
|
||||||
const float eps = 0.001f;
|
int facet_num = 0;
|
||||||
if (normal_dif(0) < eps && normal_dif(1) < eps && normal_dif(2) < eps) {
|
int reversed_count = 0;
|
||||||
/* It is not really necessary to change the values here */
|
// If normal vector is not within tolerance and backwards:
|
||||||
/* but just for consistency, I will. */
|
// Arbitrarily starts at face 0. If this one is wrong, we're screwed. Thankfully, the chances
|
||||||
facet->normal = normal;
|
// of it being wrong randomly are low if most of the triangles are right:
|
||||||
return 0;
|
if (check_normal_vector(stl, 0, 0)) {
|
||||||
}
|
reverse_facet(stl, 0);
|
||||||
|
reversed_ids[reversed_count ++] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
stl_normal test_norm = facet->normal;
|
// Say that we've fixed this facet:
|
||||||
stl_normalize_vector(test_norm);
|
norm_sw[facet_num] = 1;
|
||||||
normal_dif = (normal - test_norm).cwiseAbs();
|
int checked = 1;
|
||||||
if (normal_dif(0) < eps && normal_dif(1) < eps && normal_dif(2) < eps) {
|
|
||||||
if(normal_fix_flag) {
|
|
||||||
facet->normal = normal;
|
|
||||||
stl->stats.normals_fixed += 1;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
test_norm *= -1.f;
|
for (;;) {
|
||||||
normal_dif = (normal - test_norm).cwiseAbs();
|
// Add neighbors_to_list. Add unconnected neighbors to the list.
|
||||||
if (normal_dif(0) < eps && normal_dif(1) < eps && normal_dif(2) < eps) {
|
bool force_exit = false;
|
||||||
// Facet is backwards.
|
for (int j = 0; j < 3; ++ j) {
|
||||||
if(normal_fix_flag) {
|
// Reverse the neighboring facets if necessary.
|
||||||
facet->normal = normal;
|
if (stl->neighbors_start[facet_num].which_vertex_not[j] > 2) {
|
||||||
stl->stats.normals_fixed += 1;
|
// If the facet has a neighbor that is -1, it means that edge isn't shared by another facet
|
||||||
}
|
if (stl->neighbors_start[facet_num].neighbor[j] != -1) {
|
||||||
return 2;
|
if (norm_sw[stl->neighbors_start[facet_num].neighbor[j]] == 1) {
|
||||||
}
|
// trying to modify a facet already marked as fixed, revert all changes made until now and exit (fixes: #716, #574, #413, #269, #262, #259, #230, #228, #206)
|
||||||
if(normal_fix_flag) {
|
for (int id = reversed_count - 1; id >= 0; -- id)
|
||||||
facet->normal = normal;
|
reverse_facet(stl, reversed_ids[id]);
|
||||||
stl->stats.normals_fixed += 1;
|
force_exit = true;
|
||||||
}
|
break;
|
||||||
return 4;
|
}
|
||||||
|
reverse_facet(stl, stl->neighbors_start[facet_num].neighbor[j]);
|
||||||
|
reversed_ids[reversed_count ++] = stl->neighbors_start[facet_num].neighbor[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If this edge of the facet is connected:
|
||||||
|
if (stl->neighbors_start[facet_num].neighbor[j] != -1) {
|
||||||
|
// If we haven't fixed this facet yet, add it to the list:
|
||||||
|
if (norm_sw[stl->neighbors_start[facet_num].neighbor[j]] != 1) {
|
||||||
|
// Add node to beginning of list.
|
||||||
|
stl_normal *newn = new stl_normal;
|
||||||
|
newn->facet_num = stl->neighbors_start[facet_num].neighbor[j];
|
||||||
|
newn->next = head->next;
|
||||||
|
head->next = newn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// an error occourred, quit the for loop and exit
|
||||||
|
if (force_exit)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Get next facet to fix from top of list.
|
||||||
|
if (head->next != tail) {
|
||||||
|
facet_num = head->next->facet_num;
|
||||||
|
if (norm_sw[facet_num] != 1) { // If facet is in list mutiple times
|
||||||
|
norm_sw[facet_num] = 1; // Record this one as being fixed.
|
||||||
|
++ checked;
|
||||||
|
}
|
||||||
|
stl_normal *temp = head->next; // Delete this facet from the list.
|
||||||
|
head->next = head->next->next;
|
||||||
|
delete temp;
|
||||||
|
} else { // If we ran out of facets to fix: All of the facets in this part have been fixed.
|
||||||
|
++ stl->stats.number_of_parts;
|
||||||
|
if (checked >= stl->stats.number_of_facets)
|
||||||
|
// All of the facets have been checked. Bail out.
|
||||||
|
break;
|
||||||
|
// There is another part here. Find it and continue.
|
||||||
|
for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i)
|
||||||
|
if (norm_sw[i] == 0) {
|
||||||
|
// This is the first facet of the next part.
|
||||||
|
facet_num = i;
|
||||||
|
if (check_normal_vector(stl, i, 0)) {
|
||||||
|
reverse_facet(stl, i);
|
||||||
|
reversed_ids[reversed_count++] = i;
|
||||||
|
}
|
||||||
|
norm_sw[facet_num] = 1;
|
||||||
|
++ checked;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delete head;
|
||||||
|
delete tail;
|
||||||
}
|
}
|
||||||
|
|
||||||
void stl_fix_normal_values(stl_file *stl)
|
void stl_fix_normal_values(stl_file *stl)
|
||||||
{
|
{
|
||||||
for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i)
|
for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i)
|
||||||
stl_check_normal_vector(stl, i, 1);
|
check_normal_vector(stl, i, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void stl_reverse_all_facets(stl_file *stl)
|
void stl_reverse_all_facets(stl_file *stl)
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
void stl_generate_shared_vertices(stl_file *stl, indexed_triangle_set &its)
|
void stl_generate_shared_vertices(stl_file *stl, indexed_triangle_set &its)
|
||||||
{
|
{
|
||||||
// 3 indices to vertex per face
|
// 3 indices to vertex per face
|
||||||
its.indices.assign(stl->stats.number_of_facets, v_indices_struct());
|
its.indices.assign(stl->stats.number_of_facets, stl_triangle_vertex_indices(-1, -1, -1));
|
||||||
// Shared vertices (3D coordinates)
|
// Shared vertices (3D coordinates)
|
||||||
its.vertices.clear();
|
its.vertices.clear();
|
||||||
its.vertices.reserve(stl->stats.number_of_facets / 2);
|
its.vertices.reserve(stl->stats.number_of_facets / 2);
|
||||||
|
@ -46,7 +46,7 @@ void stl_generate_shared_vertices(stl_file *stl, indexed_triangle_set &its)
|
||||||
|
|
||||||
for (uint32_t facet_idx = 0; facet_idx < stl->stats.number_of_facets; ++ facet_idx) {
|
for (uint32_t facet_idx = 0; facet_idx < stl->stats.number_of_facets; ++ facet_idx) {
|
||||||
for (int j = 0; j < 3; ++ j) {
|
for (int j = 0; j < 3; ++ j) {
|
||||||
if (its.indices[facet_idx].vertex[j] != -1)
|
if (its.indices[facet_idx][j] != -1)
|
||||||
// Shared vertex was already assigned.
|
// Shared vertex was already assigned.
|
||||||
continue;
|
continue;
|
||||||
// Create a new shared vertex.
|
// Create a new shared vertex.
|
||||||
|
@ -84,7 +84,7 @@ void stl_generate_shared_vertices(stl_file *stl, indexed_triangle_set &its)
|
||||||
next_edge = pivot_vertex;
|
next_edge = pivot_vertex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
its.indices[facet_in_fan_idx].vertex[pivot_vertex] = its.vertices.size() - 1;
|
its.indices[facet_in_fan_idx][pivot_vertex] = its.vertices.size() - 1;
|
||||||
fan_traversal_facet_visited[facet_in_fan_idx] = fan_traversal_stamp;
|
fan_traversal_facet_visited[facet_in_fan_idx] = fan_traversal_stamp;
|
||||||
|
|
||||||
// next_edge is an index of the starting vertex of the edge, not an index of the opposite vertex to the edge!
|
// next_edge is an index of the starting vertex of the edge, not an index of the opposite vertex to the edge!
|
||||||
|
@ -139,7 +139,7 @@ bool its_write_off(const indexed_triangle_set &its, const char *file)
|
||||||
for (int i = 0; i < its.vertices.size(); ++ i)
|
for (int i = 0; i < its.vertices.size(); ++ i)
|
||||||
fprintf(fp, "\t%f %f %f\n", its.vertices[i](0), its.vertices[i](1), its.vertices[i](2));
|
fprintf(fp, "\t%f %f %f\n", its.vertices[i](0), its.vertices[i](1), its.vertices[i](2));
|
||||||
for (uint32_t i = 0; i < its.indices.size(); ++ i)
|
for (uint32_t i = 0; i < its.indices.size(); ++ i)
|
||||||
fprintf(fp, "\t3 %d %d %d\n", its.indices[i].vertex[0], its.indices[i].vertex[1], its.indices[i].vertex[2]);
|
fprintf(fp, "\t3 %d %d %d\n", its.indices[i][0], its.indices[i][1], its.indices[i][2]);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -177,8 +177,8 @@ bool its_write_vrml(const indexed_triangle_set &its, const char *file)
|
||||||
fprintf(fp, "\t\t\tcoordIndex [\n");
|
fprintf(fp, "\t\t\tcoordIndex [\n");
|
||||||
|
|
||||||
for (size_t i = 0; i + 1 < its.indices.size(); ++ i)
|
for (size_t i = 0; i + 1 < its.indices.size(); ++ i)
|
||||||
fprintf(fp, "\t\t\t\t%d, %d, %d, -1,\n", its.indices[i].vertex[0], its.indices[i].vertex[1], its.indices[i].vertex[2]);
|
fprintf(fp, "\t\t\t\t%d, %d, %d, -1,\n", its.indices[i][0], its.indices[i][1], its.indices[i][2]);
|
||||||
fprintf(fp, "\t\t\t\t%d, %d, %d, -1]\n", its.indices[i].vertex[0], its.indices[i].vertex[1], its.indices[i].vertex[2]);
|
fprintf(fp, "\t\t\t\t%d, %d, %d, -1]\n", its.indices[i][0], its.indices[i][1], its.indices[i][2]);
|
||||||
fprintf(fp, "\t\t}\n");
|
fprintf(fp, "\t\t}\n");
|
||||||
fprintf(fp, "\t}\n");
|
fprintf(fp, "\t}\n");
|
||||||
fprintf(fp, "}\n");
|
fprintf(fp, "}\n");
|
||||||
|
@ -198,7 +198,7 @@ bool its_write_obj(const indexed_triangle_set &its, const char *file)
|
||||||
for (size_t i = 0; i < its.vertices.size(); ++ i)
|
for (size_t i = 0; i < its.vertices.size(); ++ i)
|
||||||
fprintf(fp, "v %f %f %f\n", its.vertices[i](0), its.vertices[i](1), its.vertices[i](2));
|
fprintf(fp, "v %f %f %f\n", its.vertices[i](0), its.vertices[i](1), its.vertices[i](2));
|
||||||
for (size_t i = 0; i < its.indices.size(); ++ i)
|
for (size_t i = 0; i < its.indices.size(); ++ i)
|
||||||
fprintf(fp, "f %d %d %d\n", its.indices[i].vertex[0]+1, its.indices[i].vertex[1]+1, its.indices[i].vertex[2]+1);
|
fprintf(fp, "f %d %d %d\n", its.indices[i][0]+1, its.indices[i][1]+1, its.indices[i][2]+1);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -220,7 +220,7 @@ bool stl_validate(const stl_file *stl, const indexed_triangle_set &its)
|
||||||
// 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 = (its.indices.empty()) ? nullptr : its.indices[facet_idx].vertex;
|
const int *vertices = (its.indices.empty()) ? nullptr : its.indices[facet_idx];
|
||||||
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);
|
||||||
|
@ -237,10 +237,10 @@ bool stl_validate(const stl_file *stl, const indexed_triangle_set &its)
|
||||||
// Has shared vertices.
|
// Has shared vertices.
|
||||||
if (nbr_vnot < 3) {
|
if (nbr_vnot < 3) {
|
||||||
// Faces facet_idx and nbr_face share two vertices accross the common edge. Faces are correctly oriented.
|
// Faces facet_idx and nbr_face share two vertices accross the common edge. Faces are correctly oriented.
|
||||||
assert((its.indices[nbr_face].vertex[(nbr_vnot + 1) % 3] == vertices[(nbr_idx + 1) % 3] && its.indices[nbr_face].vertex[(nbr_vnot + 2) % 3] == vertices[nbr_idx]));
|
assert((its.indices[nbr_face][(nbr_vnot + 1) % 3] == vertices[(nbr_idx + 1) % 3] && its.indices[nbr_face][(nbr_vnot + 2) % 3] == vertices[nbr_idx]));
|
||||||
} else {
|
} else {
|
||||||
// Faces facet_idx and nbr_face share two vertices accross the common edge. Faces are incorrectly oriented, one of them is flipped.
|
// Faces facet_idx and nbr_face share two vertices accross the common edge. Faces are incorrectly oriented, one of them is flipped.
|
||||||
assert((its.indices[nbr_face].vertex[(nbr_vnot + 2) % 3] == vertices[(nbr_idx + 1) % 3] && its.indices[nbr_face].vertex[(nbr_vnot + 1) % 3] == vertices[nbr_idx]));
|
assert((its.indices[nbr_face][(nbr_vnot + 2) % 3] == vertices[(nbr_idx + 1) % 3] && its.indices[nbr_face][(nbr_vnot + 1) % 3] == vertices[nbr_idx]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
|
|
||||||
typedef Eigen::Matrix<float, 3, 1, Eigen::DontAlign> stl_vertex;
|
typedef Eigen::Matrix<float, 3, 1, Eigen::DontAlign> stl_vertex;
|
||||||
typedef Eigen::Matrix<float, 3, 1, Eigen::DontAlign> stl_normal;
|
typedef Eigen::Matrix<float, 3, 1, Eigen::DontAlign> stl_normal;
|
||||||
|
typedef Eigen::Matrix<int, 3, 1, Eigen::DontAlign> stl_triangle_vertex_indices;
|
||||||
static_assert(sizeof(stl_vertex) == 12, "size of stl_vertex incorrect");
|
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");
|
||||||
|
|
||||||
|
@ -68,12 +69,6 @@ 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;
|
||||||
|
|
||||||
struct stl_edge {
|
|
||||||
stl_vertex p1;
|
|
||||||
stl_vertex p2;
|
|
||||||
int facet_number;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct stl_neighbors {
|
struct stl_neighbors {
|
||||||
stl_neighbors() { reset(); }
|
stl_neighbors() { reset(); }
|
||||||
void reset() {
|
void reset() {
|
||||||
|
@ -93,12 +88,6 @@ struct stl_neighbors {
|
||||||
char which_vertex_not[3];
|
char which_vertex_not[3];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct v_indices_struct {
|
|
||||||
// -1 means no vertex index has been assigned yet
|
|
||||||
v_indices_struct() { vertex[0] = -1; vertex[1] = -1; vertex[2] = -1; }
|
|
||||||
int vertex[3];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct stl_stats {
|
struct stl_stats {
|
||||||
char header[81];
|
char header[81];
|
||||||
stl_type type;
|
stl_type type;
|
||||||
|
@ -137,8 +126,8 @@ struct stl_file {
|
||||||
struct indexed_triangle_set
|
struct indexed_triangle_set
|
||||||
{
|
{
|
||||||
void clear() { indices.clear(); vertices.clear(); }
|
void clear() { indices.clear(); vertices.clear(); }
|
||||||
std::vector<v_indices_struct> indices;
|
std::vector<stl_triangle_vertex_indices> indices;
|
||||||
std::vector<stl_vertex> vertices;
|
std::vector<stl_vertex> vertices;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern bool stl_open(stl_file *stl, const char *file);
|
extern bool stl_open(stl_file *stl, const char *file);
|
||||||
|
|
|
@ -22,94 +22,55 @@
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "stl.h"
|
|
||||||
|
|
||||||
#include <boost/log/trivial.hpp>
|
#include <boost/log/trivial.hpp>
|
||||||
#include <boost/nowide/cstdio.hpp>
|
#include <boost/nowide/cstdio.hpp>
|
||||||
#include <boost/detail/endian.hpp>
|
#include <boost/detail/endian.hpp>
|
||||||
|
|
||||||
#if !defined(SEEK_SET)
|
#include "stl.h"
|
||||||
#define SEEK_SET 0
|
|
||||||
#define SEEK_CUR 1
|
|
||||||
#define SEEK_END 2
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void stl_stats_out(stl_file *stl, FILE *file, char *input_file)
|
void stl_stats_out(stl_file *stl, FILE *file, char *input_file)
|
||||||
{
|
{
|
||||||
/* this is here for Slic3r, without our config.h
|
// This is here for Slic3r, without our config.h it won't use this part of the code anyway.
|
||||||
it won't use this part of the code anyway */
|
|
||||||
#ifndef VERSION
|
#ifndef VERSION
|
||||||
#define VERSION "unknown"
|
#define VERSION "unknown"
|
||||||
#endif
|
#endif
|
||||||
fprintf(file, "\n\
|
fprintf(file, "\n================= Results produced by ADMesh version " VERSION " ================\n");
|
||||||
================= Results produced by ADMesh version " VERSION " ================\n");
|
fprintf(file, "Input file : %s\n", input_file);
|
||||||
fprintf(file, "\
|
if (stl->stats.type == binary)
|
||||||
Input file : %s\n", input_file);
|
fprintf(file, "File type : Binary STL file\n");
|
||||||
if(stl->stats.type == binary) {
|
else
|
||||||
fprintf(file, "\
|
fprintf(file, "File type : ASCII STL file\n");
|
||||||
File type : Binary STL file\n");
|
fprintf(file, "Header : %s\n", stl->stats.header);
|
||||||
} else {
|
fprintf(file, "============== Size ==============\n");
|
||||||
fprintf(file, "\
|
fprintf(file, "Min X = % f, Max X = % f\n", stl->stats.min(0), stl->stats.max(0));
|
||||||
File type : ASCII STL file\n");
|
fprintf(file, "Min Y = % f, Max Y = % f\n", stl->stats.min(1), stl->stats.max(1));
|
||||||
}
|
fprintf(file, "Min Z = % f, Max Z = % f\n", stl->stats.min(2), stl->stats.max(2));
|
||||||
fprintf(file, "\
|
fprintf(file, "========= Facet Status ========== Original ============ Final ====\n");
|
||||||
Header : %s\n", stl->stats.header);
|
fprintf(file, "Number of facets : %5d %5d\n", stl->stats.original_num_facets, stl->stats.number_of_facets);
|
||||||
fprintf(file, "============== Size ==============\n");
|
fprintf(file, "Facets with 1 disconnected edge : %5d %5d\n",
|
||||||
fprintf(file, "Min X = % f, Max X = % f\n",
|
stl->stats.facets_w_1_bad_edge, stl->stats.connected_facets_2_edge - stl->stats.connected_facets_3_edge);
|
||||||
stl->stats.min(0), stl->stats.max(0));
|
fprintf(file, "Facets with 2 disconnected edges : %5d %5d\n",
|
||||||
fprintf(file, "Min Y = % f, Max Y = % f\n",
|
stl->stats.facets_w_2_bad_edge, stl->stats.connected_facets_1_edge - stl->stats.connected_facets_2_edge);
|
||||||
stl->stats.min(1), stl->stats.max(1));
|
fprintf(file, "Facets with 3 disconnected edges : %5d %5d\n",
|
||||||
fprintf(file, "Min Z = % f, Max Z = % f\n",
|
stl->stats.facets_w_3_bad_edge, stl->stats.number_of_facets - stl->stats.connected_facets_1_edge);
|
||||||
stl->stats.min(2), stl->stats.max(2));
|
fprintf(file, "Total disconnected facets : %5d %5d\n",
|
||||||
|
stl->stats.facets_w_1_bad_edge + stl->stats.facets_w_2_bad_edge + stl->stats.facets_w_3_bad_edge, stl->stats.number_of_facets - stl->stats.connected_facets_3_edge);
|
||||||
fprintf(file, "\
|
fprintf(file, "=== Processing Statistics === ===== Other Statistics =====\n");
|
||||||
========= Facet Status ========== Original ============ Final ====\n");
|
fprintf(file, "Number of parts : %5d Volume : %f\n", stl->stats.number_of_parts, stl->stats.volume);
|
||||||
fprintf(file, "\
|
fprintf(file, "Degenerate facets : %5d\n", stl->stats.degenerate_facets);
|
||||||
Number of facets : %5d %5d\n",
|
fprintf(file, "Edges fixed : %5d\n", stl->stats.edges_fixed);
|
||||||
stl->stats.original_num_facets, stl->stats.number_of_facets);
|
fprintf(file, "Facets removed : %5d\n", stl->stats.facets_removed);
|
||||||
fprintf(file, "\
|
fprintf(file, "Facets added : %5d\n", stl->stats.facets_added);
|
||||||
Facets with 1 disconnected edge : %5d %5d\n",
|
fprintf(file, "Facets reversed : %5d\n", stl->stats.facets_reversed);
|
||||||
stl->stats.facets_w_1_bad_edge, stl->stats.connected_facets_2_edge -
|
fprintf(file, "Backwards edges : %5d\n", stl->stats.backwards_edges);
|
||||||
stl->stats.connected_facets_3_edge);
|
fprintf(file, "Normals fixed : %5d\n", stl->stats.normals_fixed);
|
||||||
fprintf(file, "\
|
|
||||||
Facets with 2 disconnected edges : %5d %5d\n",
|
|
||||||
stl->stats.facets_w_2_bad_edge, stl->stats.connected_facets_1_edge -
|
|
||||||
stl->stats.connected_facets_2_edge);
|
|
||||||
fprintf(file, "\
|
|
||||||
Facets with 3 disconnected edges : %5d %5d\n",
|
|
||||||
stl->stats.facets_w_3_bad_edge, stl->stats.number_of_facets -
|
|
||||||
stl->stats.connected_facets_1_edge);
|
|
||||||
fprintf(file, "\
|
|
||||||
Total disconnected facets : %5d %5d\n",
|
|
||||||
stl->stats.facets_w_1_bad_edge + stl->stats.facets_w_2_bad_edge +
|
|
||||||
stl->stats.facets_w_3_bad_edge, stl->stats.number_of_facets -
|
|
||||||
stl->stats.connected_facets_3_edge);
|
|
||||||
|
|
||||||
fprintf(file,
|
|
||||||
"=== Processing Statistics === ===== Other Statistics =====\n");
|
|
||||||
fprintf(file, "\
|
|
||||||
Number of parts : %5d Volume : % f\n",
|
|
||||||
stl->stats.number_of_parts, stl->stats.volume);
|
|
||||||
fprintf(file, "\
|
|
||||||
Degenerate facets : %5d\n", stl->stats.degenerate_facets);
|
|
||||||
fprintf(file, "\
|
|
||||||
Edges fixed : %5d\n", stl->stats.edges_fixed);
|
|
||||||
fprintf(file, "\
|
|
||||||
Facets removed : %5d\n", stl->stats.facets_removed);
|
|
||||||
fprintf(file, "\
|
|
||||||
Facets added : %5d\n", stl->stats.facets_added);
|
|
||||||
fprintf(file, "\
|
|
||||||
Facets reversed : %5d\n", stl->stats.facets_reversed);
|
|
||||||
fprintf(file, "\
|
|
||||||
Backwards edges : %5d\n", stl->stats.backwards_edges);
|
|
||||||
fprintf(file, "\
|
|
||||||
Normals fixed : %5d\n", stl->stats.normals_fixed);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool stl_write_ascii(stl_file *stl, const char *file, const char *label)
|
bool stl_write_ascii(stl_file *stl, const char *file, const char *label)
|
||||||
{
|
{
|
||||||
FILE *fp = boost::nowide::fopen(file, "w");
|
FILE *fp = boost::nowide::fopen(file, "w");
|
||||||
if (fp == NULL) {
|
if (fp == nullptr) {
|
||||||
BOOST_LOG_TRIVIAL(error) << "stl_write_ascii: Couldn't open " << file << " for writing";
|
BOOST_LOG_TRIVIAL(error) << "stl_write_ascii: Couldn't open " << file << " for writing";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -117,19 +78,11 @@ bool 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 (uint32_t 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(2));
|
||||||
stl->facet_start[i].normal(0), stl->facet_start[i].normal(1),
|
|
||||||
stl->facet_start[i].normal(2));
|
|
||||||
fprintf(fp, " outer loop\n");
|
fprintf(fp, " outer loop\n");
|
||||||
fprintf(fp, " vertex % .8E % .8E % .8E\n",
|
fprintf(fp, " vertex % .8E % .8E % .8E\n", stl->facet_start[i].vertex[0](0), stl->facet_start[i].vertex[0](1), stl->facet_start[i].vertex[0](2));
|
||||||
stl->facet_start[i].vertex[0](0), stl->facet_start[i].vertex[0](1),
|
fprintf(fp, " vertex % .8E % .8E % .8E\n", stl->facet_start[i].vertex[1](0), stl->facet_start[i].vertex[1](1), stl->facet_start[i].vertex[1](2));
|
||||||
stl->facet_start[i].vertex[0](2));
|
fprintf(fp, " vertex % .8E % .8E % .8E\n", stl->facet_start[i].vertex[2](0), stl->facet_start[i].vertex[2](1), stl->facet_start[i].vertex[2](2));
|
||||||
fprintf(fp, " vertex % .8E % .8E % .8E\n",
|
|
||||||
stl->facet_start[i].vertex[1](0), stl->facet_start[i].vertex[1](1),
|
|
||||||
stl->facet_start[i].vertex[1](2));
|
|
||||||
fprintf(fp, " vertex % .8E % .8E % .8E\n",
|
|
||||||
stl->facet_start[i].vertex[2](0), stl->facet_start[i].vertex[2](1),
|
|
||||||
stl->facet_start[i].vertex[2](2));
|
|
||||||
fprintf(fp, " endloop\n");
|
fprintf(fp, " endloop\n");
|
||||||
fprintf(fp, " endfacet\n");
|
fprintf(fp, " endfacet\n");
|
||||||
}
|
}
|
||||||
|
@ -142,7 +95,7 @@ bool stl_write_ascii(stl_file *stl, const char *file, const char *label)
|
||||||
bool stl_print_neighbors(stl_file *stl, char *file)
|
bool stl_print_neighbors(stl_file *stl, char *file)
|
||||||
{
|
{
|
||||||
FILE *fp = boost::nowide::fopen(file, "w");
|
FILE *fp = boost::nowide::fopen(file, "w");
|
||||||
if (fp == NULL) {
|
if (fp == nullptr) {
|
||||||
BOOST_LOG_TRIVIAL(error) << "stl_print_neighbors: Couldn't open " << file << " for writing";
|
BOOST_LOG_TRIVIAL(error) << "stl_print_neighbors: Couldn't open " << file << " for writing";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -175,7 +128,7 @@ void stl_internal_reverse_quads(char *buf, size_t cnt)
|
||||||
bool stl_write_binary(stl_file *stl, const char *file, const char *label)
|
bool stl_write_binary(stl_file *stl, const char *file, const char *label)
|
||||||
{
|
{
|
||||||
FILE *fp = boost::nowide::fopen(file, "wb");
|
FILE *fp = boost::nowide::fopen(file, "wb");
|
||||||
if (fp == NULL) {
|
if (fp == nullptr) {
|
||||||
BOOST_LOG_TRIVIAL(error) << "stl_write_binary: Couldn't open " << file << " for writing";
|
BOOST_LOG_TRIVIAL(error) << "stl_write_binary: Couldn't open " << file << " for writing";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -184,6 +137,9 @@ bool stl_write_binary(stl_file *stl, const char *file, const char *label)
|
||||||
for (size_t i = strlen(label); i < LABEL_SIZE; ++ i)
|
for (size_t i = strlen(label); i < LABEL_SIZE; ++ i)
|
||||||
putc(0, fp);
|
putc(0, fp);
|
||||||
|
|
||||||
|
#if !defined(SEEK_SET)
|
||||||
|
#define SEEK_SET 0
|
||||||
|
#endif
|
||||||
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);
|
||||||
|
@ -242,7 +198,7 @@ bool stl_write_quad_object(stl_file *stl, char *file)
|
||||||
stl_vertex color;
|
stl_vertex color;
|
||||||
|
|
||||||
FILE *fp = boost::nowide::fopen(file, "w");
|
FILE *fp = boost::nowide::fopen(file, "w");
|
||||||
if (fp == NULL) {
|
if (fp == nullptr) {
|
||||||
BOOST_LOG_TRIVIAL(error) << "stl_write_quad_object: Couldn't open " << file << " for writing";
|
BOOST_LOG_TRIVIAL(error) << "stl_write_quad_object: Couldn't open " << file << " for writing";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -255,22 +211,10 @@ bool stl_write_quad_object(stl_file *stl, char *file)
|
||||||
case 2: color = uncon_2_color; break;
|
case 2: color = uncon_2_color; break;
|
||||||
default: color = uncon_3_color;
|
default: color = uncon_3_color;
|
||||||
}
|
}
|
||||||
fprintf(fp, "%f %f %f %1.1f %1.1f %1.1f 1\n",
|
fprintf(fp, "%f %f %f %1.1f %1.1f %1.1f 1\n", stl->facet_start[i].vertex[0](0), stl->facet_start[i].vertex[0](1), stl->facet_start[i].vertex[0](2), color(0), color(1), color(2));
|
||||||
stl->facet_start[i].vertex[0](0),
|
fprintf(fp, "%f %f %f %1.1f %1.1f %1.1f 1\n", stl->facet_start[i].vertex[1](0), stl->facet_start[i].vertex[1](1), stl->facet_start[i].vertex[1](2), color(0), color(1), color(2));
|
||||||
stl->facet_start[i].vertex[0](1),
|
fprintf(fp, "%f %f %f %1.1f %1.1f %1.1f 1\n", stl->facet_start[i].vertex[2](0), stl->facet_start[i].vertex[2](1), stl->facet_start[i].vertex[2](2), color(0), color(1), color(2));
|
||||||
stl->facet_start[i].vertex[0](2), color(0), color(1), color(2));
|
fprintf(fp, "%f %f %f %1.1f %1.1f %1.1f 1\n", stl->facet_start[i].vertex[2](0), stl->facet_start[i].vertex[2](1), stl->facet_start[i].vertex[2](2), color(0), color(1), color(2));
|
||||||
fprintf(fp, "%f %f %f %1.1f %1.1f %1.1f 1\n",
|
|
||||||
stl->facet_start[i].vertex[1](0),
|
|
||||||
stl->facet_start[i].vertex[1](1),
|
|
||||||
stl->facet_start[i].vertex[1](2), color(0), color(1), color(2));
|
|
||||||
fprintf(fp, "%f %f %f %1.1f %1.1f %1.1f 1\n",
|
|
||||||
stl->facet_start[i].vertex[2](0),
|
|
||||||
stl->facet_start[i].vertex[2](1),
|
|
||||||
stl->facet_start[i].vertex[2](2), color(0), color(1), color(2));
|
|
||||||
fprintf(fp, "%f %f %f %1.1f %1.1f %1.1f 1\n",
|
|
||||||
stl->facet_start[i].vertex[2](0),
|
|
||||||
stl->facet_start[i].vertex[2](1),
|
|
||||||
stl->facet_start[i].vertex[2](2), color(0), color(1), color(2));
|
|
||||||
}
|
}
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return true;
|
return true;
|
||||||
|
@ -279,7 +223,7 @@ bool stl_write_quad_object(stl_file *stl, char *file)
|
||||||
bool stl_write_dxf(stl_file *stl, const char *file, char *label)
|
bool stl_write_dxf(stl_file *stl, const char *file, char *label)
|
||||||
{
|
{
|
||||||
FILE *fp = boost::nowide::fopen(file, "w");
|
FILE *fp = boost::nowide::fopen(file, "w");
|
||||||
if (fp == NULL) {
|
if (fp == nullptr) {
|
||||||
BOOST_LOG_TRIVIAL(error) << "stl_write_quad_object: Couldn't open " << file << " for writing";
|
BOOST_LOG_TRIVIAL(error) << "stl_write_quad_object: Couldn't open " << file << " for writing";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -292,20 +236,12 @@ bool 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 (uint32_t 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](2));
|
||||||
stl->facet_start[i].vertex[0](0), stl->facet_start[i].vertex[0](1),
|
fprintf(fp, "11\n%f\n21\n%f\n31\n%f\n", stl->facet_start[i].vertex[1](0), stl->facet_start[i].vertex[1](1), stl->facet_start[i].vertex[1](2));
|
||||||
stl->facet_start[i].vertex[0](2));
|
fprintf(fp, "12\n%f\n22\n%f\n32\n%f\n", stl->facet_start[i].vertex[2](0), stl->facet_start[i].vertex[2](1), stl->facet_start[i].vertex[2](2));
|
||||||
fprintf(fp, "11\n%f\n21\n%f\n31\n%f\n",
|
fprintf(fp, "13\n%f\n23\n%f\n33\n%f\n", stl->facet_start[i].vertex[2](0), stl->facet_start[i].vertex[2](1), stl->facet_start[i].vertex[2](2));
|
||||||
stl->facet_start[i].vertex[1](0), stl->facet_start[i].vertex[1](1),
|
|
||||||
stl->facet_start[i].vertex[1](2));
|
|
||||||
fprintf(fp, "12\n%f\n22\n%f\n32\n%f\n",
|
|
||||||
stl->facet_start[i].vertex[2](0), stl->facet_start[i].vertex[2](1),
|
|
||||||
stl->facet_start[i].vertex[2](2));
|
|
||||||
fprintf(fp, "13\n%f\n23\n%f\n33\n%f\n",
|
|
||||||
stl->facet_start[i].vertex[2](0), stl->facet_start[i].vertex[2](1),
|
|
||||||
stl->facet_start[i].vertex[2](2));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(fp, "0\nENDSEC\n0\nEOF\n");
|
fprintf(fp, "0\nENDSEC\n0\nEOF\n");
|
||||||
|
|
|
@ -29,16 +29,17 @@
|
||||||
|
|
||||||
#include "stl.h"
|
#include "stl.h"
|
||||||
|
|
||||||
static void stl_rotate(float *x, float *y, const double c, const double s);
|
|
||||||
static float get_area(stl_facet *facet);
|
|
||||||
static float get_volume(stl_file *stl);
|
|
||||||
|
|
||||||
void stl_verify_neighbors(stl_file *stl)
|
void stl_verify_neighbors(stl_file *stl)
|
||||||
{
|
{
|
||||||
stl->stats.backwards_edges = 0;
|
stl->stats.backwards_edges = 0;
|
||||||
|
|
||||||
for (uint32_t 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) {
|
||||||
|
struct stl_edge {
|
||||||
|
stl_vertex p1;
|
||||||
|
stl_vertex p2;
|
||||||
|
int facet_number;
|
||||||
|
};
|
||||||
stl_edge edge_a;
|
stl_edge edge_a;
|
||||||
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];
|
||||||
|
@ -67,164 +68,140 @@ void stl_verify_neighbors(stl_file *stl)
|
||||||
|
|
||||||
void stl_translate(stl_file *stl, float x, float y, float z)
|
void stl_translate(stl_file *stl, float x, float y, float z)
|
||||||
{
|
{
|
||||||
stl_vertex new_min(x, y, z);
|
stl_vertex new_min(x, y, z);
|
||||||
stl_vertex shift = new_min - stl->stats.min;
|
stl_vertex shift = new_min - stl->stats.min;
|
||||||
for (int i = 0; i < stl->stats.number_of_facets; ++ i)
|
for (int 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] += shift;
|
stl->facet_start[i].vertex[j] += shift;
|
||||||
stl->stats.min = new_min;
|
stl->stats.min = new_min;
|
||||||
stl->stats.max += shift;
|
stl->stats.max += shift;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Translates the stl by x,y,z, relatively from wherever it is currently */
|
/* Translates the stl by x,y,z, relatively from wherever it is currently */
|
||||||
void stl_translate_relative(stl_file *stl, float x, float y, float z)
|
void stl_translate_relative(stl_file *stl, float x, float y, float z)
|
||||||
{
|
{
|
||||||
stl_vertex shift(x, y, z);
|
stl_vertex shift(x, y, z);
|
||||||
for (int i = 0; i < stl->stats.number_of_facets; ++ i)
|
for (int 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] += shift;
|
stl->facet_start[i].vertex[j] += shift;
|
||||||
stl->stats.min += shift;
|
stl->stats.min += shift;
|
||||||
stl->stats.max += shift;
|
stl->stats.max += shift;
|
||||||
}
|
}
|
||||||
|
|
||||||
void stl_scale_versor(stl_file *stl, const stl_vertex &versor)
|
void stl_scale_versor(stl_file *stl, const stl_vertex &versor)
|
||||||
{
|
{
|
||||||
// Scale extents.
|
// Scale extents.
|
||||||
auto s = versor.array();
|
auto s = versor.array();
|
||||||
stl->stats.min.array() *= s;
|
stl->stats.min.array() *= s;
|
||||||
stl->stats.max.array() *= s;
|
stl->stats.max.array() *= s;
|
||||||
// Scale size.
|
// Scale size.
|
||||||
stl->stats.size.array() *= s;
|
stl->stats.size.array() *= s;
|
||||||
// Scale volume.
|
// Scale volume.
|
||||||
if (stl->stats.volume > 0.0)
|
if (stl->stats.volume > 0.0)
|
||||||
stl->stats.volume *= versor(0) * versor(1) * versor(2);
|
stl->stats.volume *= versor(0) * versor(1) * versor(2);
|
||||||
// Scale the mesh.
|
// Scale the mesh.
|
||||||
for (int i = 0; i < stl->stats.number_of_facets; ++ i)
|
for (int 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].array() *= s;
|
stl->facet_start[i].vertex[j].array() *= s;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void calculate_normals(stl_file *stl)
|
static void calculate_normals(stl_file *stl)
|
||||||
{
|
{
|
||||||
stl_normal normal;
|
stl_normal normal;
|
||||||
for(uint32_t i = 0; i < stl->stats.number_of_facets; i++) {
|
for (uint32_t i = 0; i < stl->stats.number_of_facets; i++) {
|
||||||
stl_calculate_normal(normal, &stl->facet_start[i]);
|
stl_calculate_normal(normal, &stl->facet_start[i]);
|
||||||
stl_normalize_vector(normal);
|
stl_normalize_vector(normal);
|
||||||
stl->facet_start[i].normal = normal;
|
stl->facet_start[i].normal = normal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void rotate_point_2d(float *x, float *y, const double c, const double s)
|
||||||
stl_rotate_x(stl_file *stl, float angle) {
|
{
|
||||||
int i;
|
double xold = *x;
|
||||||
int j;
|
double yold = *y;
|
||||||
double radian_angle = (angle / 180.0) * M_PI;
|
*x = float(c * xold - s * yold);
|
||||||
double c = cos(radian_angle);
|
*y = float(s * xold + c * yold);
|
||||||
double s = sin(radian_angle);
|
|
||||||
|
|
||||||
for(i = 0; i < stl->stats.number_of_facets; i++) {
|
|
||||||
for(j = 0; j < 3; j++) {
|
|
||||||
stl_rotate(&stl->facet_start[i].vertex[j](1),
|
|
||||||
&stl->facet_start[i].vertex[j](2), c, s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stl_get_size(stl);
|
|
||||||
calculate_normals(stl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void stl_rotate_x(stl_file *stl, float angle)
|
||||||
stl_rotate_y(stl_file *stl, float angle) {
|
{
|
||||||
int i;
|
double radian_angle = (angle / 180.0) * M_PI;
|
||||||
int j;
|
double c = cos(radian_angle);
|
||||||
double radian_angle = (angle / 180.0) * M_PI;
|
double s = sin(radian_angle);
|
||||||
double c = cos(radian_angle);
|
for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i)
|
||||||
double s = sin(radian_angle);
|
for (int j = 0; j < 3; ++ j)
|
||||||
|
rotate_point_2d(&stl->facet_start[i].vertex[j](1), &stl->facet_start[i].vertex[j](2), c, s);
|
||||||
for(i = 0; i < stl->stats.number_of_facets; i++) {
|
stl_get_size(stl);
|
||||||
for(j = 0; j < 3; j++) {
|
calculate_normals(stl);
|
||||||
stl_rotate(&stl->facet_start[i].vertex[j](2),
|
|
||||||
&stl->facet_start[i].vertex[j](0), c, s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stl_get_size(stl);
|
|
||||||
calculate_normals(stl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void stl_rotate_y(stl_file *stl, float angle)
|
||||||
stl_rotate_z(stl_file *stl, float angle) {
|
{
|
||||||
int i;
|
double radian_angle = (angle / 180.0) * M_PI;
|
||||||
int j;
|
double c = cos(radian_angle);
|
||||||
double radian_angle = (angle / 180.0) * M_PI;
|
double s = sin(radian_angle);
|
||||||
double c = cos(radian_angle);
|
for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i)
|
||||||
double s = sin(radian_angle);
|
for (int j = 0; j < 3; ++ j)
|
||||||
|
rotate_point_2d(&stl->facet_start[i].vertex[j](2), &stl->facet_start[i].vertex[j](0), c, s);
|
||||||
for(i = 0; i < stl->stats.number_of_facets; i++) {
|
stl_get_size(stl);
|
||||||
for(j = 0; j < 3; j++) {
|
calculate_normals(stl);
|
||||||
stl_rotate(&stl->facet_start[i].vertex[j](0),
|
|
||||||
&stl->facet_start[i].vertex[j](1), c, s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stl_get_size(stl);
|
|
||||||
calculate_normals(stl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void stl_rotate_z(stl_file *stl, float angle)
|
||||||
|
{
|
||||||
static void
|
double radian_angle = (angle / 180.0) * M_PI;
|
||||||
stl_rotate(float *x, float *y, const double c, const double s) {
|
double c = cos(radian_angle);
|
||||||
double xold = *x;
|
double s = sin(radian_angle);
|
||||||
double yold = *y;
|
for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i)
|
||||||
*x = float(c * xold - s * yold);
|
for (int j = 0; j < 3; ++ j)
|
||||||
*y = float(s * xold + c * yold);
|
rotate_point_2d(&stl->facet_start[i].vertex[j](0), &stl->facet_start[i].vertex[j](1), c, s);
|
||||||
|
stl_get_size(stl);
|
||||||
|
calculate_normals(stl);
|
||||||
}
|
}
|
||||||
|
|
||||||
void stl_get_size(stl_file *stl)
|
void stl_get_size(stl_file *stl)
|
||||||
{
|
{
|
||||||
if (stl->stats.number_of_facets == 0)
|
if (stl->stats.number_of_facets == 0)
|
||||||
return;
|
return;
|
||||||
stl->stats.min = stl->facet_start[0].vertex[0];
|
stl->stats.min = stl->facet_start[0].vertex[0];
|
||||||
stl->stats.max = stl->stats.min;
|
stl->stats.max = stl->stats.min;
|
||||||
for (int i = 0; i < stl->stats.number_of_facets; ++ i) {
|
for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i) {
|
||||||
const stl_facet &face = stl->facet_start[i];
|
const stl_facet &face = stl->facet_start[i];
|
||||||
for (int j = 0; j < 3; ++ j) {
|
for (int j = 0; j < 3; ++ j) {
|
||||||
stl->stats.min = stl->stats.min.cwiseMin(face.vertex[j]);
|
stl->stats.min = stl->stats.min.cwiseMin(face.vertex[j]);
|
||||||
stl->stats.max = stl->stats.max.cwiseMax(face.vertex[j]);
|
stl->stats.max = stl->stats.max.cwiseMax(face.vertex[j]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stl->stats.size = stl->stats.max - stl->stats.min;
|
stl->stats.size = stl->stats.max - stl->stats.min;
|
||||||
stl->stats.bounding_diameter = stl->stats.size.norm();
|
stl->stats.bounding_diameter = stl->stats.size.norm();
|
||||||
}
|
}
|
||||||
|
|
||||||
void stl_mirror_xy(stl_file *stl)
|
void stl_mirror_xy(stl_file *stl)
|
||||||
{
|
{
|
||||||
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](2) *= -1.0;
|
stl->facet_start[i].vertex[j](2) *= -1.0;
|
||||||
}
|
float temp_size = stl->stats.min(2);
|
||||||
}
|
stl->stats.min(2) = stl->stats.max(2);
|
||||||
float temp_size = stl->stats.min(2);
|
stl->stats.max(2) = temp_size;
|
||||||
stl->stats.min(2) = stl->stats.max(2);
|
stl->stats.min(2) *= -1.0;
|
||||||
stl->stats.max(2) = temp_size;
|
stl->stats.max(2) *= -1.0;
|
||||||
stl->stats.min(2) *= -1.0;
|
stl_reverse_all_facets(stl);
|
||||||
stl->stats.max(2) *= -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 */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void stl_mirror_yz(stl_file *stl)
|
void stl_mirror_yz(stl_file *stl)
|
||||||
{
|
{
|
||||||
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](0) *= -1.0;
|
stl->facet_start[i].vertex[j](0) *= -1.0;
|
||||||
}
|
float temp_size = stl->stats.min(0);
|
||||||
}
|
stl->stats.min(0) = stl->stats.max(0);
|
||||||
float temp_size = stl->stats.min(0);
|
stl->stats.max(0) = temp_size;
|
||||||
stl->stats.min(0) = stl->stats.max(0);
|
stl->stats.min(0) *= -1.0;
|
||||||
stl->stats.max(0) = temp_size;
|
stl->stats.max(0) *= -1.0;
|
||||||
stl->stats.min(0) *= -1.0;
|
stl_reverse_all_facets(stl);
|
||||||
stl->stats.max(0) *= -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 */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void stl_mirror_xz(stl_file *stl)
|
void stl_mirror_xz(stl_file *stl)
|
||||||
|
@ -241,55 +218,55 @@ void stl_mirror_xz(stl_file *stl)
|
||||||
stl->stats.facets_reversed -= stl->stats.number_of_facets; // for not altering stats
|
stl->stats.facets_reversed -= stl->stats.number_of_facets; // for not altering stats
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static float get_area(stl_facet *facet)
|
||||||
|
{
|
||||||
|
/* cast to double before calculating cross product because large coordinates
|
||||||
|
can result in overflowing product
|
||||||
|
(bad area is responsible for bad volume and bad facets reversal) */
|
||||||
|
double cross[3][3];
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
cross[i][0]=(((double)facet->vertex[i](1) * (double)facet->vertex[(i + 1) % 3](2)) -
|
||||||
|
((double)facet->vertex[i](2) * (double)facet->vertex[(i + 1) % 3](1)));
|
||||||
|
cross[i][1]=(((double)facet->vertex[i](2) * (double)facet->vertex[(i + 1) % 3](0)) -
|
||||||
|
((double)facet->vertex[i](0) * (double)facet->vertex[(i + 1) % 3](2)));
|
||||||
|
cross[i][2]=(((double)facet->vertex[i](0) * (double)facet->vertex[(i + 1) % 3](1)) -
|
||||||
|
((double)facet->vertex[i](1) * (double)facet->vertex[(i + 1) % 3](0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
stl_normal sum;
|
||||||
|
sum(0) = cross[0][0] + cross[1][0] + cross[2][0];
|
||||||
|
sum(1) = cross[0][1] + cross[1][1] + cross[2][1];
|
||||||
|
sum(2) = cross[0][2] + cross[1][2] + cross[2][2];
|
||||||
|
|
||||||
|
// This should already be done. But just in case, let's do it again.
|
||||||
|
//FIXME this is questionable. the "sum" normal should be accurate, while the normal "n" may be calculated with a low accuracy.
|
||||||
|
stl_normal n;
|
||||||
|
stl_calculate_normal(n, facet);
|
||||||
|
stl_normalize_vector(n);
|
||||||
|
return 0.5f * n.dot(sum);
|
||||||
|
}
|
||||||
|
|
||||||
static float get_volume(stl_file *stl)
|
static float get_volume(stl_file *stl)
|
||||||
{
|
{
|
||||||
// Choose a point, any point as the reference.
|
// Choose a point, any point as the reference.
|
||||||
stl_vertex p0 = stl->facet_start[0].vertex[0];
|
stl_vertex p0 = stl->facet_start[0].vertex[0];
|
||||||
float volume = 0.f;
|
float volume = 0.f;
|
||||||
for(uint32_t i = 0; i < stl->stats.number_of_facets; ++ i) {
|
for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i) {
|
||||||
// Do dot product to get distance from point to plane.
|
// Do dot product to get distance from point to plane.
|
||||||
float height = stl->facet_start[i].normal.dot(stl->facet_start[i].vertex[0] - p0);
|
float height = stl->facet_start[i].normal.dot(stl->facet_start[i].vertex[0] - p0);
|
||||||
float area = get_area(&stl->facet_start[i]);
|
float area = get_area(&stl->facet_start[i]);
|
||||||
volume += (area * height) / 3.0f;
|
volume += (area * height) / 3.0f;
|
||||||
}
|
}
|
||||||
return volume;
|
return volume;
|
||||||
}
|
}
|
||||||
|
|
||||||
void stl_calculate_volume(stl_file *stl)
|
void stl_calculate_volume(stl_file *stl)
|
||||||
{
|
{
|
||||||
stl->stats.volume = get_volume(stl);
|
stl->stats.volume = get_volume(stl);
|
||||||
if(stl->stats.volume < 0.0) {
|
if (stl->stats.volume < 0.0) {
|
||||||
stl_reverse_all_facets(stl);
|
stl_reverse_all_facets(stl);
|
||||||
stl->stats.volume = -stl->stats.volume;
|
stl->stats.volume = -stl->stats.volume;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
static float get_area(stl_facet *facet)
|
|
||||||
{
|
|
||||||
/* cast to double before calculating cross product because large coordinates
|
|
||||||
can result in overflowing product
|
|
||||||
(bad area is responsible for bad volume and bad facets reversal) */
|
|
||||||
double cross[3][3];
|
|
||||||
for (int i = 0; i < 3; i++) {
|
|
||||||
cross[i][0]=(((double)facet->vertex[i](1) * (double)facet->vertex[(i + 1) % 3](2)) -
|
|
||||||
((double)facet->vertex[i](2) * (double)facet->vertex[(i + 1) % 3](1)));
|
|
||||||
cross[i][1]=(((double)facet->vertex[i](2) * (double)facet->vertex[(i + 1) % 3](0)) -
|
|
||||||
((double)facet->vertex[i](0) * (double)facet->vertex[(i + 1) % 3](2)));
|
|
||||||
cross[i][2]=(((double)facet->vertex[i](0) * (double)facet->vertex[(i + 1) % 3](1)) -
|
|
||||||
((double)facet->vertex[i](1) * (double)facet->vertex[(i + 1) % 3](0)));
|
|
||||||
}
|
|
||||||
|
|
||||||
stl_normal sum;
|
|
||||||
sum(0) = cross[0][0] + cross[1][0] + cross[2][0];
|
|
||||||
sum(1) = cross[0][1] + cross[1][1] + cross[2][1];
|
|
||||||
sum(2) = cross[0][2] + cross[1][2] + cross[2][2];
|
|
||||||
|
|
||||||
// This should already be done. But just in case, let's do it again.
|
|
||||||
//FIXME this is questionable. the "sum" normal should be accurate, while the normal "n" may be calculated with a low accuracy.
|
|
||||||
stl_normal n;
|
|
||||||
stl_calculate_normal(n, facet);
|
|
||||||
stl_normalize_vector(n);
|
|
||||||
return 0.5f * n.dot(sum);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void stl_repair(
|
void stl_repair(
|
||||||
|
|
|
@ -1928,7 +1928,7 @@ namespace Slic3r {
|
||||||
stream << " <" << TRIANGLE_TAG << " ";
|
stream << " <" << TRIANGLE_TAG << " ";
|
||||||
for (int j = 0; j < 3; ++j)
|
for (int j = 0; j < 3; ++j)
|
||||||
{
|
{
|
||||||
stream << "v" << j + 1 << "=\"" << its.indices[i].vertex[j] + volume_it->second.first_vertex_id << "\" ";
|
stream << "v" << j + 1 << "=\"" << its.indices[i][j] + volume_it->second.first_vertex_id << "\" ";
|
||||||
}
|
}
|
||||||
stream << "/>\n";
|
stream << "/>\n";
|
||||||
}
|
}
|
||||||
|
|
|
@ -958,7 +958,7 @@ bool store_amf(const char *path, Model *model, const DynamicPrintConfig *config)
|
||||||
for (size_t i = 0; i < (int)volume->mesh.its.indices.size(); ++i) {
|
for (size_t i = 0; i < (int)volume->mesh.its.indices.size(); ++i) {
|
||||||
stream << " <triangle>\n";
|
stream << " <triangle>\n";
|
||||||
for (int j = 0; j < 3; ++j)
|
for (int j = 0; j < 3; ++j)
|
||||||
stream << " <v" << j + 1 << ">" << volume->mesh.its.indices[i].vertex[j] + vertices_offset << "</v" << j + 1 << ">\n";
|
stream << " <v" << j + 1 << ">" << volume->mesh.its.indices[i][j] + vertices_offset << "</v" << j + 1 << ">\n";
|
||||||
stream << " </triangle>\n";
|
stream << " </triangle>\n";
|
||||||
}
|
}
|
||||||
stream << " </volume>\n";
|
stream << " </volume>\n";
|
||||||
|
|
|
@ -614,8 +614,8 @@ void TriangleMeshSlicer::init(const TriangleMesh *_mesh, throw_on_cancel_callbac
|
||||||
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)
|
||||||
for (int i = 0; i < 3; ++ i) {
|
for (int i = 0; i < 3; ++ i) {
|
||||||
EdgeToFace &e2f = edges_map[facet_idx*3+i];
|
EdgeToFace &e2f = edges_map[facet_idx*3+i];
|
||||||
e2f.vertex_low = this->mesh->its.indices[facet_idx].vertex[i];
|
e2f.vertex_low = this->mesh->its.indices[facet_idx][i];
|
||||||
e2f.vertex_high = this->mesh->its.indices[facet_idx].vertex[(i + 1) % 3];
|
e2f.vertex_high = this->mesh->its.indices[facet_idx][(i + 1) % 3];
|
||||||
e2f.face = facet_idx;
|
e2f.face = facet_idx;
|
||||||
// 1 based indexing, to be always strictly positive.
|
// 1 based indexing, to be always strictly positive.
|
||||||
e2f.face_edge = i + 1;
|
e2f.face_edge = i + 1;
|
||||||
|
@ -852,7 +852,7 @@ TriangleMeshSlicer::FacetSliceType TriangleMeshSlicer::slice_facet(
|
||||||
// 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
|
||||||
// (external on the right of the line)
|
// (external on the right of the line)
|
||||||
const int *vertices = this->mesh->its.indices[facet_idx].vertex;
|
const stl_triangle_vertex_indices &vertices = this->mesh->its.indices[facet_idx];
|
||||||
int i = (facet.vertex[1].z() == min_z) ? 1 : ((facet.vertex[2].z() == min_z) ? 2 : 0);
|
int i = (facet.vertex[1].z() == min_z) ? 1 : ((facet.vertex[2].z() == min_z) ? 2 : 0);
|
||||||
|
|
||||||
// These are used only if the cut plane is tilted:
|
// These are used only if the cut plane is tilted:
|
||||||
|
|
|
@ -129,9 +129,9 @@ TriangleMesh::facets()
|
||||||
AV* facet = newAV();
|
AV* facet = newAV();
|
||||||
av_store(facets, i, newRV_noinc((SV*)facet));
|
av_store(facets, i, newRV_noinc((SV*)facet));
|
||||||
av_extend(facet, 2);
|
av_extend(facet, 2);
|
||||||
av_store(facet, 0, newSVnv(THIS->its.indices[i].vertex[0]));
|
av_store(facet, 0, newSVnv(THIS->its.indices[i][0]));
|
||||||
av_store(facet, 1, newSVnv(THIS->its.indices[i].vertex[1]));
|
av_store(facet, 1, newSVnv(THIS->its.indices[i][1]));
|
||||||
av_store(facet, 2, newSVnv(THIS->its.indices[i].vertex[2]));
|
av_store(facet, 2, newSVnv(THIS->its.indices[i][2]));
|
||||||
}
|
}
|
||||||
|
|
||||||
RETVAL = newRV_noinc((SV*)facets);
|
RETVAL = newRV_noinc((SV*)facets);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue