This commit is contained in:
bubnikv 2018-08-22 15:03:35 +02:00
parent ac72cd779f
commit 6829704475
16 changed files with 539 additions and 908 deletions

View File

@ -25,11 +25,11 @@
#include <string.h> #include <string.h>
#include <math.h> #include <math.h>
#include <boost/detail/endian.hpp>
#include "stl.h" #include "stl.h"
static void stl_match_neighbors_exact(stl_file *stl,
stl_hash_edge *edge_a, stl_hash_edge *edge_b);
static void stl_match_neighbors_nearby(stl_file *stl, static void stl_match_neighbors_nearby(stl_file *stl,
stl_hash_edge *edge_a, stl_hash_edge *edge_b); stl_hash_edge *edge_a, stl_hash_edge *edge_b);
static void stl_record_neighbors(stl_file *stl, static void stl_record_neighbors(stl_file *stl,
@ -43,7 +43,6 @@ static int stl_load_edge_nearby(stl_file *stl, stl_hash_edge *edge,
static void insert_hash_edge(stl_file *stl, stl_hash_edge edge, static void insert_hash_edge(stl_file *stl, stl_hash_edge edge,
void (*match_neighbors)(stl_file *stl, void (*match_neighbors)(stl_file *stl,
stl_hash_edge *edge_a, stl_hash_edge *edge_b)); stl_hash_edge *edge_a, stl_hash_edge *edge_b));
static int stl_get_hash_for_edge(int M, stl_hash_edge *edge);
static int stl_compare_function(stl_hash_edge *edge_a, stl_hash_edge *edge_b); static int stl_compare_function(stl_hash_edge *edge_a, stl_hash_edge *edge_b);
static void stl_free_edges(stl_file *stl); static void stl_free_edges(stl_file *stl);
static void stl_remove_facet(stl_file *stl, int facet_number); static void stl_remove_facet(stl_file *stl, int facet_number);
@ -82,37 +81,20 @@ stl_check_facets_exact(stl_file *stl) {
for(i = 0; i < stl->stats.number_of_facets; i++) { for(i = 0; i < stl->stats.number_of_facets; i++) {
facet = stl->facet_start[i]; facet = stl->facet_start[i];
// Positive and negative zeros are possible in the floats, which are considered equal by the FP unit. // If any two of the three vertices are found to be exactally the same, call them degenerate and remove the facet.
// When using a memcmp on raw floats, those numbers report to be different. if (facet.vertex[0] == facet.vertex[1] ||
// Unify all +0 and -0 to +0 to make the floats equal under memcmp. facet.vertex[1] == facet.vertex[2] ||
{ facet.vertex[0] == facet.vertex[2]) {
uint32_t *f = (uint32_t*)&facet;
for (int j = 0; j < 12; ++ j, ++ f) // 3x vertex + normal: 4x3 = 12 floats
if (*f == 0x80000000)
// Negative zero, switch to positive zero.
*f = 0;
}
/* If any two of the three vertices are found to be exactally the same, call them degenerate and remove the facet. */
if( !memcmp(&facet.vertex[0], &facet.vertex[1],
sizeof(stl_vertex))
|| !memcmp(&facet.vertex[1], &facet.vertex[2],
sizeof(stl_vertex))
|| !memcmp(&facet.vertex[0], &facet.vertex[2],
sizeof(stl_vertex))) {
stl->stats.degenerate_facets += 1; stl->stats.degenerate_facets += 1;
stl_remove_facet(stl, i); stl_remove_facet(stl, i);
i--; -- i;
continue; continue;
} }
for(j = 0; j < 3; j++) { for(j = 0; j < 3; j++) {
edge.facet_number = i; edge.facet_number = i;
edge.which_edge = j; edge.which_edge = j;
stl_load_edge_exact(stl, &edge, &facet.vertex[j], stl_load_edge_exact(stl, &edge, &facet.vertex[j], &facet.vertex[(j + 1) % 3]);
&facet.vertex[(j + 1) % 3]); insert_hash_edge(stl, edge, stl_record_neighbors);
insert_hash_edge(stl, edge, stl_match_neighbors_exact);
} }
} }
stl_free_edges(stl); stl_free_edges(stl);
@ -131,28 +113,33 @@ stl_load_edge_exact(stl_file *stl, stl_hash_edge *edge,
if (stl->error) return; if (stl->error) return;
{ {
float diff_x = ABS(a->x - b->x); stl_vertex diff = (*a - *b).cwiseAbs();
float diff_y = ABS(a->y - b->y); float max_diff = std::max(diff(0), std::max(diff(1), diff(2)));
float diff_z = ABS(a->z - b->z); stl->stats.shortest_edge = std::min(max_diff, stl->stats.shortest_edge);
float max_diff = STL_MAX(diff_x, diff_y);
max_diff = STL_MAX(diff_z, max_diff);
stl->stats.shortest_edge = STL_MIN(max_diff, stl->stats.shortest_edge);
} }
// Ensure identical vertex ordering of equal edges. // Ensure identical vertex ordering of equal edges.
// This method is numerically robust. // This method is numerically robust.
if ((a->x != b->x) ? if (stl_vertex_lower(*a, *b)) {
(a->x < b->x) :
((a->y != b->y) ?
(a->y < b->y) :
(a->z < b->z))) {
memcpy(&edge->key[0], a, sizeof(stl_vertex));
memcpy(&edge->key[3], b, sizeof(stl_vertex));
} else { } else {
memcpy(&edge->key[0], b, sizeof(stl_vertex)); std::swap(a, b);
memcpy(&edge->key[3], a, sizeof(stl_vertex));
edge->which_edge += 3; /* this edge is loaded backwards */ edge->which_edge += 3; /* this edge is loaded backwards */
} }
memcpy(&edge->key[0], a->data(), sizeof(stl_vertex));
memcpy(&edge->key[sizeof(stl_vertex)], b->data(), sizeof(stl_vertex));
// Switch negative zeros to positive zeros, so memcmp will consider them to be equal.
for (size_t i = 0; i < 6; ++ i) {
unsigned char *p = edge->key + i * 4;
#ifdef BOOST_LITTLE_ENDIAN
if (p[0] == 0 && p[1] == 0 && p[2] == 0 && p[3] == 0x80)
// Negative zero, switch to positive zero.
p[3] = 0;
#else /* BOOST_LITTLE_ENDIAN */
if (p[0] == 0x80 && p[1] == 0 && p[2] == 0 && p[3] == 0)
// Negative zero, switch to positive zero.
p[0] = 0;
#endif /* BOOST_LITTLE_ENDIAN */
}
} }
static void static void
@ -188,21 +175,17 @@ stl_initialize_facet_check_exact(stl_file *stl) {
} }
} }
static void static void insert_hash_edge(stl_file *stl, stl_hash_edge edge,
insert_hash_edge(stl_file *stl, stl_hash_edge edge,
void (*match_neighbors)(stl_file *stl, void (*match_neighbors)(stl_file *stl,
stl_hash_edge *edge_a, stl_hash_edge *edge_b)) { stl_hash_edge *edge_a, stl_hash_edge *edge_b))
stl_hash_edge *link; {
stl_hash_edge *new_edge;
stl_hash_edge *temp;
int chain_number;
if (stl->error) return; if (stl->error) return;
chain_number = stl_get_hash_for_edge(stl->M, &edge); int chain_number = edge.hash(stl->M);
stl_hash_edge *link = stl->heads[chain_number];
link = stl->heads[chain_number];
stl_hash_edge *new_edge;
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 = (stl_hash_edge*)malloc(sizeof(stl_hash_edge));
@ -252,30 +235,17 @@ insert_hash_edge(stl_file *stl, stl_hash_edge edge,
} }
} }
// Return 1 if the edges are not matched.
static int static inline int stl_compare_function(stl_hash_edge *edge_a, stl_hash_edge *edge_b)
stl_get_hash_for_edge(int M, stl_hash_edge *edge) { {
return ((edge->key[0] / 23 + edge->key[1] / 19 + edge->key[2] / 17 // Don't match edges of the same facet
+ edge->key[3] /13 + edge->key[4] / 11 + edge->key[5] / 7 ) % M); return (edge_a->facet_number == edge_b->facet_number) || (*edge_a != *edge_b);
} }
static int void stl_check_facets_nearby(stl_file *stl, float tolerance)
stl_compare_function(stl_hash_edge *edge_a, stl_hash_edge *edge_b) { {
if(edge_a->facet_number == edge_b->facet_number) { if (stl->error)
return 1; /* Don't match edges of the same facet */ return;
} else {
return memcmp(edge_a, edge_b, SIZEOF_EDGE_SORT);
}
}
void
stl_check_facets_nearby(stl_file *stl, float tolerance) {
stl_hash_edge edge[3];
stl_facet facet;
int i;
int j;
if (stl->error) return;
if( (stl->stats.connected_facets_1_edge == stl->stats.number_of_facets) if( (stl->stats.connected_facets_1_edge == stl->stats.number_of_facets)
&& (stl->stats.connected_facets_2_edge == stl->stats.number_of_facets) && (stl->stats.connected_facets_2_edge == stl->stats.number_of_facets)
@ -286,27 +256,19 @@ stl_check_facets_nearby(stl_file *stl, float tolerance) {
stl_initialize_facet_check_nearby(stl); stl_initialize_facet_check_nearby(stl);
for(i = 0; i < stl->stats.number_of_facets; i++) { for (int i = 0; i < stl->stats.number_of_facets; ++ i) {
facet = stl->facet_start[i]; //FIXME is the copy necessary?
// Positive and negative zeros are possible in the floats, which are considered equal by the FP unit. stl_facet facet = stl->facet_start[i];
// When using a memcmp on raw floats, those numbers report to be different. for (int j = 0; j < 3; j++) {
// Unify all +0 and -0 to +0 to make the floats equal under memcmp.
{
uint32_t *f = (uint32_t*)&facet;
for (int j = 0; j < 12; ++ j, ++ f) // 3x vertex + normal: 4x3 = 12 floats
if (*f == 0x80000000)
// Negative zero, switch to positive zero.
*f = 0;
}
for(j = 0; j < 3; j++) {
if(stl->neighbors_start[i].neighbor[j] == -1) { if(stl->neighbors_start[i].neighbor[j] == -1) {
edge[j].facet_number = i; stl_hash_edge edge;
edge[j].which_edge = j; edge.facet_number = i;
if(stl_load_edge_nearby(stl, &edge[j], &facet.vertex[j], edge.which_edge = j;
if(stl_load_edge_nearby(stl, &edge, &facet.vertex[j],
&facet.vertex[(j + 1) % 3], &facet.vertex[(j + 1) % 3],
tolerance)) { tolerance)) {
/* only insert edges that have different keys */ /* only insert edges that have different keys */
insert_hash_edge(stl, edge[j], stl_match_neighbors_nearby); insert_hash_edge(stl, edge, stl_match_neighbors_nearby);
} }
} }
} }
@ -315,27 +277,17 @@ stl_check_facets_nearby(stl_file *stl, float tolerance) {
stl_free_edges(stl); stl_free_edges(stl);
} }
static int static int stl_load_edge_nearby(stl_file *stl, stl_hash_edge *edge, stl_vertex *a, stl_vertex *b, float tolerance)
stl_load_edge_nearby(stl_file *stl, stl_hash_edge *edge, {
stl_vertex *a, stl_vertex *b, float tolerance) {
// Index of a grid cell spaced by tolerance. // Index of a grid cell spaced by tolerance.
uint32_t vertex1[3] = { typedef Eigen::Matrix<int32_t, 3, 1, Eigen::DontAlign> Vec3i;
(uint32_t)((a->x - stl->stats.min.x) / tolerance), Vec3i vertex1 = (*a / tolerance).cast<int32_t>();
(uint32_t)((a->y - stl->stats.min.y) / tolerance), Vec3i vertex2 = (*b / tolerance).cast<int32_t>();
(uint32_t)((a->z - stl->stats.min.z) / tolerance) static_assert(sizeof(Vec3i) == 12, "size of Vec3i incorrect");
};
uint32_t vertex2[3] = {
(uint32_t)((b->x - stl->stats.min.x) / tolerance),
(uint32_t)((b->y - stl->stats.min.y) / tolerance),
(uint32_t)((b->z - stl->stats.min.z) / tolerance)
};
if( (vertex1[0] == vertex2[0]) if (vertex1 == vertex2)
&& (vertex1[1] == vertex2[1]) // Both vertices hash to the same value
&& (vertex1[2] == vertex2[2])) {
/* Both vertices hash to the same value */
return 0; return 0;
}
// Ensure identical vertex ordering of edges, which vertices land into equal grid cells. // Ensure identical vertex ordering of edges, which vertices land into equal grid cells.
// This method is numerically robust. // This method is numerically robust.
@ -344,30 +296,27 @@ stl_load_edge_nearby(stl_file *stl, stl_hash_edge *edge,
((vertex1[1] != vertex2[1]) ? ((vertex1[1] != vertex2[1]) ?
(vertex1[1] < vertex2[1]) : (vertex1[1] < vertex2[1]) :
(vertex1[2] < vertex2[2]))) { (vertex1[2] < vertex2[2]))) {
memcpy(&edge->key[0], vertex1, sizeof(stl_vertex)); memcpy(&edge->key[0], vertex1.data(), sizeof(stl_vertex));
memcpy(&edge->key[3], vertex2, sizeof(stl_vertex)); memcpy(&edge->key[sizeof(stl_vertex)], vertex2.data(), sizeof(stl_vertex));
} else { } else {
memcpy(&edge->key[0], vertex2, sizeof(stl_vertex)); memcpy(&edge->key[0], vertex2.data(), sizeof(stl_vertex));
memcpy(&edge->key[3], vertex1, sizeof(stl_vertex)); memcpy(&edge->key[sizeof(stl_vertex)], vertex1.data(), sizeof(stl_vertex));
edge->which_edge += 3; /* this edge is loaded backwards */ edge->which_edge += 3; /* this edge is loaded backwards */
} }
return 1; return 1;
} }
static void static void stl_free_edges(stl_file *stl)
stl_free_edges(stl_file *stl) { {
int i; if (stl->error)
stl_hash_edge *temp; return;
if (stl->error) return;
if(stl->stats.malloced != stl->stats.freed) { if(stl->stats.malloced != stl->stats.freed) {
for(i = 0; i < stl->M; i++) { for (int i = 0; i < stl->M; i++) {
for(temp = stl->heads[i]; stl->heads[i] != stl->tail; for (stl_hash_edge *temp = stl->heads[i]; stl->heads[i] != stl->tail; temp = stl->heads[i]) {
temp = stl->heads[i]) {
stl->heads[i] = stl->heads[i]->next; stl->heads[i] = stl->heads[i]->next;
free(temp); free(temp);
stl->stats.freed++; ++ stl->stats.freed;
} }
} }
} }
@ -375,8 +324,8 @@ stl_free_edges(stl_file *stl) {
free(stl->tail); free(stl->tail);
} }
static void static void stl_initialize_facet_check_nearby(stl_file *stl)
stl_initialize_facet_check_nearby(stl_file *stl) { {
int i; int i;
if (stl->error) return; if (stl->error) return;
@ -467,16 +416,8 @@ stl_record_neighbors(stl_file *stl,
} }
} }
static void static void stl_match_neighbors_nearby(stl_file *stl, stl_hash_edge *edge_a, stl_hash_edge *edge_b)
stl_match_neighbors_exact(stl_file *stl, {
stl_hash_edge *edge_a, stl_hash_edge *edge_b) {
if (stl->error) return;
stl_record_neighbors(stl, edge_a, edge_b);
}
static void
stl_match_neighbors_nearby(stl_file *stl,
stl_hash_edge *edge_a, stl_hash_edge *edge_b) {
int facet1; int facet1;
int facet2; int facet2;
int vertex1; int vertex1;
@ -517,9 +458,7 @@ stl_match_neighbors_nearby(stl_file *stl,
} }
static void static void stl_change_vertices(stl_file *stl, int facet_num, int vnot, stl_vertex new_vertex) {
stl_change_vertices(stl_file *stl, int facet_num, int vnot,
stl_vertex new_vertex) {
int first_facet; int first_facet;
int direction; int direction;
int next_edge; int next_edge;
@ -551,30 +490,30 @@ stl_change_vertices(stl_file *stl, int facet_num, int vnot,
} }
} }
#if 0 #if 0
if (stl->facet_start[facet_num].vertex[pivot_vertex].x == new_vertex.x && if (stl->facet_start[facet_num].vertex[pivot_vertex](0) == new_vertex(0) &&
stl->facet_start[facet_num].vertex[pivot_vertex].y == new_vertex.y && stl->facet_start[facet_num].vertex[pivot_vertex](1) == new_vertex(1) &&
stl->facet_start[facet_num].vertex[pivot_vertex].z == new_vertex.z) stl->facet_start[facet_num].vertex[pivot_vertex](2) == new_vertex(2))
printf("Changing vertex %f,%f,%f: Same !!!\r\n", printf("Changing vertex %f,%f,%f: Same !!!\r\n",
new_vertex.x, new_vertex.y, new_vertex.z); new_vertex(0), new_vertex(1), new_vertex(2));
else { else {
if (stl->facet_start[facet_num].vertex[pivot_vertex].x != new_vertex.x) if (stl->facet_start[facet_num].vertex[pivot_vertex](0) != new_vertex(0))
printf("Changing coordinate x, vertex %e (0x%08x) to %e(0x%08x)\r\n", printf("Changing coordinate x, vertex %e (0x%08x) to %e(0x%08x)\r\n",
stl->facet_start[facet_num].vertex[pivot_vertex].x, stl->facet_start[facet_num].vertex[pivot_vertex](0),
*reinterpret_cast<const int*>(&stl->facet_start[facet_num].vertex[pivot_vertex].x), *reinterpret_cast<const int*>(&stl->facet_start[facet_num].vertex[pivot_vertex](0)),
new_vertex.x, new_vertex(0),
*reinterpret_cast<const int*>(&new_vertex.x)); *reinterpret_cast<const int*>(&new_vertex(0)));
if (stl->facet_start[facet_num].vertex[pivot_vertex].y != new_vertex.y) if (stl->facet_start[facet_num].vertex[pivot_vertex](1) != new_vertex(1))
printf("Changing coordinate x, vertex %e (0x%08x) to %e(0x%08x)\r\n", printf("Changing coordinate x, vertex %e (0x%08x) to %e(0x%08x)\r\n",
stl->facet_start[facet_num].vertex[pivot_vertex].y, stl->facet_start[facet_num].vertex[pivot_vertex](1),
*reinterpret_cast<const int*>(&stl->facet_start[facet_num].vertex[pivot_vertex].y), *reinterpret_cast<const int*>(&stl->facet_start[facet_num].vertex[pivot_vertex](1)),
new_vertex.y, new_vertex(1),
*reinterpret_cast<const int*>(&new_vertex.y)); *reinterpret_cast<const int*>(&new_vertex(1)));
if (stl->facet_start[facet_num].vertex[pivot_vertex].z != new_vertex.z) if (stl->facet_start[facet_num].vertex[pivot_vertex](2) != new_vertex(2))
printf("Changing coordinate x, vertex %e (0x%08x) to %e(0x%08x)\r\n", printf("Changing coordinate x, vertex %e (0x%08x) to %e(0x%08x)\r\n",
stl->facet_start[facet_num].vertex[pivot_vertex].z, stl->facet_start[facet_num].vertex[pivot_vertex](2),
*reinterpret_cast<const int*>(&stl->facet_start[facet_num].vertex[pivot_vertex].z), *reinterpret_cast<const int*>(&stl->facet_start[facet_num].vertex[pivot_vertex](2)),
new_vertex.z, new_vertex(2),
*reinterpret_cast<const int*>(&new_vertex.z)); *reinterpret_cast<const int*>(&new_vertex(2)));
} }
#endif #endif
stl->facet_start[facet_num].vertex[pivot_vertex] = new_vertex; stl->facet_start[facet_num].vertex[pivot_vertex] = new_vertex;
@ -595,7 +534,6 @@ Try using a smaller tolerance or don't do a nearby check\n");
} }
} }
static void static void
stl_which_vertices_to_change(stl_file *stl, stl_hash_edge *edge_a, stl_which_vertices_to_change(stl_file *stl, stl_hash_edge *edge_a,
stl_hash_edge *edge_b, int *facet1, int *vertex1, stl_hash_edge *edge_b, int *facet1, int *vertex1,
@ -622,11 +560,10 @@ stl_which_vertices_to_change(stl_file *stl, stl_hash_edge *edge_a,
v1b = (edge_b->which_edge + 1) % 3; v1b = (edge_b->which_edge + 1) % 3;
} }
/* Of the first pair, which vertex, if any, should be changed */ // Of the first pair, which vertex, if any, should be changed
if(!memcmp(&stl->facet_start[edge_a->facet_number].vertex[v1a], if(stl->facet_start[edge_a->facet_number].vertex[v1a] ==
&stl->facet_start[edge_b->facet_number].vertex[v1b], stl->facet_start[edge_b->facet_number].vertex[v1b]) {
sizeof(stl_vertex))) { // These facets are already equal. No need to change.
/* These facets are already equal. No need to change. */
*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)
@ -644,10 +581,9 @@ stl_which_vertices_to_change(stl_file *stl, stl_hash_edge *edge_a,
} }
/* Of the second pair, which vertex, if any, should be changed */ /* Of the second pair, which vertex, if any, should be changed */
if(!memcmp(&stl->facet_start[edge_a->facet_number].vertex[v2a], if(stl->facet_start[edge_a->facet_number].vertex[v2a] ==
&stl->facet_start[edge_b->facet_number].vertex[v2b], stl->facet_start[edge_b->facet_number].vertex[v2b]) {
sizeof(stl_vertex))) { // These facets are already equal. No need to change.
/* These facets are already equal. No need to change. */
*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)
@ -718,40 +654,35 @@ in stl_remove_facet: neighbor = %d numfacets = %d this is wrong\n",
} }
} }
void void stl_remove_unconnected_facets(stl_file *stl)
stl_remove_unconnected_facets(stl_file *stl) { {
/* A couple of things need to be done here. One is to remove any */ /* A couple of things need to be done here. One is to remove any */
/* completely unconnected facets (0 edges connected) since these are */ /* completely unconnected facets (0 edges connected) since these are */
/* useless and could be completely wrong. The second thing that needs to */ /* useless and could be completely wrong. The second thing that needs to */
/* be done is to remove any degenerate facets that were created during */ /* be done is to remove any degenerate facets that were created during */
/* stl_check_facets_nearby(). */ /* stl_check_facets_nearby(). */
if (stl->error)
return;
int i; // remove degenerate facets
for (int i = 0; i < stl->stats.number_of_facets; ++ i) {
if (stl->error) return; 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] ||
/* remove degenerate facets */ stl->facet_start[i].vertex[1] == stl->facet_start[i].vertex[2]) {
for(i = 0; i < stl->stats.number_of_facets; i++) {
if( !memcmp(&stl->facet_start[i].vertex[0],
&stl->facet_start[i].vertex[1], sizeof(stl_vertex))
|| !memcmp(&stl->facet_start[i].vertex[1],
&stl->facet_start[i].vertex[2], sizeof(stl_vertex))
|| !memcmp(&stl->facet_start[i].vertex[0],
&stl->facet_start[i].vertex[2], sizeof(stl_vertex))) {
stl_remove_degenerate(stl, i); stl_remove_degenerate(stl, i);
i--; i--;
} }
} }
if(stl->stats.connected_facets_1_edge < stl->stats.number_of_facets) { if(stl->stats.connected_facets_1_edge < stl->stats.number_of_facets) {
/* remove completely unconnected facets */ // remove completely unconnected facets
for(i = 0; i < stl->stats.number_of_facets; i++) { for (int i = 0; i < stl->stats.number_of_facets; i++) {
if( (stl->neighbors_start[i].neighbor[0] == -1) if (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) {
/* This facet is completely unconnected. Remove it. */ // This facet is completely unconnected. Remove it.
stl_remove_facet(stl, i); stl_remove_facet(stl, i);
i--; -- i;
} }
} }
} }
@ -771,30 +702,24 @@ stl_remove_degenerate(stl_file *stl, int facet) {
if (stl->error) return; if (stl->error) return;
if( !memcmp(&stl->facet_start[facet].vertex[0], if (stl->facet_start[facet].vertex[0] == stl->facet_start[facet].vertex[1] &&
&stl->facet_start[facet].vertex[1], sizeof(stl_vertex)) stl->facet_start[facet].vertex[1] == stl->facet_start[facet].vertex[2]) {
&& !memcmp(&stl->facet_start[facet].vertex[1],
&stl->facet_start[facet].vertex[2], sizeof(stl_vertex))) {
/* all 3 vertices are equal. Just remove the facet. I don't think*/ /* all 3 vertices are equal. Just remove the facet. I don't think*/
/* this is really possible, but just in case... */ /* this is really possible, but just in case... */
printf("removing a facet in stl_remove_degenerate\n"); printf("removing a facet in stl_remove_degenerate\n");
stl_remove_facet(stl, facet); stl_remove_facet(stl, facet);
return; return;
} }
if(!memcmp(&stl->facet_start[facet].vertex[0], if (stl->facet_start[facet].vertex[0] == stl->facet_start[facet].vertex[1]) {
&stl->facet_start[facet].vertex[1], sizeof(stl_vertex))) {
edge1 = 1; edge1 = 1;
edge2 = 2; edge2 = 2;
edge3 = 0; edge3 = 0;
} else if(!memcmp(&stl->facet_start[facet].vertex[1], } else if (stl->facet_start[facet].vertex[1] == stl->facet_start[facet].vertex[2]) {
&stl->facet_start[facet].vertex[2], sizeof(stl_vertex))) {
edge1 = 0; edge1 = 0;
edge2 = 2; edge2 = 2;
edge3 = 1; edge3 = 1;
} else if(!memcmp(&stl->facet_start[facet].vertex[2], } else if (stl->facet_start[facet].vertex[2] == stl->facet_start[facet].vertex[0]) {
&stl->facet_start[facet].vertex[0], sizeof(stl_vertex))) {
edge1 = 0; edge1 = 0;
edge2 = 1; edge2 = 1;
edge3 = 2; edge3 = 2;
@ -883,7 +808,7 @@ stl_fill_holes(stl_file *stl) {
stl_load_edge_exact(stl, &edge, &facet.vertex[j], stl_load_edge_exact(stl, &edge, &facet.vertex[j],
&facet.vertex[(j + 1) % 3]); &facet.vertex[(j + 1) % 3]);
insert_hash_edge(stl, edge, stl_match_neighbors_exact); insert_hash_edge(stl, edge, stl_record_neighbors);
} }
} }
@ -939,7 +864,7 @@ stl_fill_holes(stl_file *stl) {
stl_load_edge_exact(stl, &edge, &new_facet.vertex[k], stl_load_edge_exact(stl, &edge, &new_facet.vertex[k],
&new_facet.vertex[(k + 1) % 3]); &new_facet.vertex[(k + 1) % 3]);
insert_hash_edge(stl, edge, stl_match_neighbors_exact); insert_hash_edge(stl, edge, stl_record_neighbors);
} }
break; break;
} else { } else {
@ -977,9 +902,7 @@ stl_add_facet(stl_file *stl, stl_facet *new_facet) {
stl->facet_start[stl->stats.number_of_facets] = *new_facet; stl->facet_start[stl->stats.number_of_facets] = *new_facet;
/* note that the normal vector is not set here, just initialized to 0 */ /* note that the normal vector is not set here, just initialized to 0 */
stl->facet_start[stl->stats.number_of_facets].normal.x = 0.0; stl->facet_start[stl->stats.number_of_facets].normal = stl_normal::Zero();
stl->facet_start[stl->stats.number_of_facets].normal.y = 0.0;
stl->facet_start[stl->stats.number_of_facets].normal.z = 0.0;
stl->neighbors_start[stl->stats.number_of_facets].neighbor[0] = -1; 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[1] = -1;

View File

@ -27,12 +27,6 @@
#include "stl.h" #include "stl.h"
static void stl_reverse_vector(float v[]) {
v[0] *= -1;
v[1] *= -1;
v[2] *= -1;
}
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);
static void static void
@ -228,102 +222,52 @@ static int stl_check_normal_vector(stl_file *stl, int facet_num, int normal_fix_
/* Returns 2 if the normal is not within tolerance and backwards */ /* Returns 2 if the normal is not within tolerance and backwards */
/* Returns 4 if the status is unknown. */ /* Returns 4 if the status is unknown. */
float normal[3];
float test_norm[3];
stl_facet *facet; stl_facet *facet;
facet = &stl->facet_start[facet_num]; facet = &stl->facet_start[facet_num];
stl_normal normal;
stl_calculate_normal(normal, facet); stl_calculate_normal(normal, facet);
stl_normalize_vector(normal); stl_normalize_vector(normal);
stl_normal normal_dif = (normal - facet->normal).cwiseAbs();
if( (ABS(normal[0] - facet->normal.x) < 0.001) const float eps = 0.001f;
&& (ABS(normal[1] - facet->normal.y) < 0.001) if (normal_dif(0) < eps && normal_dif(1) < eps && normal_dif(2) < eps) {
&& (ABS(normal[2] - facet->normal.z) < 0.001)) {
/* It is not really necessary to change the values here */ /* It is not really necessary to change the values here */
/* but just for consistency, I will. */ /* but just for consistency, I will. */
facet->normal.x = normal[0]; facet->normal = normal;
facet->normal.y = normal[1];
facet->normal.z = normal[2];
return 0; return 0;
} }
test_norm[0] = facet->normal.x; stl_normal test_norm = facet->normal;
test_norm[1] = facet->normal.y;
test_norm[2] = facet->normal.z;
stl_normalize_vector(test_norm); stl_normalize_vector(test_norm);
if( (ABS(normal[0] - test_norm[0]) < 0.001) normal_dif = (normal - test_norm).cwiseAbs();
&& (ABS(normal[1] - test_norm[1]) < 0.001) if (normal_dif(0) < eps && normal_dif(1) < eps && normal_dif(2) < eps) {
&& (ABS(normal[2] - test_norm[2]) < 0.001)) {
if(normal_fix_flag) { if(normal_fix_flag) {
facet->normal.x = normal[0]; facet->normal = normal;
facet->normal.y = normal[1];
facet->normal.z = normal[2];
stl->stats.normals_fixed += 1; stl->stats.normals_fixed += 1;
} }
return 1; return 1;
} }
stl_reverse_vector(test_norm); test_norm *= -1.f;
if( (ABS(normal[0] - test_norm[0]) < 0.001) normal_dif = (normal - test_norm).cwiseAbs();
&& (ABS(normal[1] - test_norm[1]) < 0.001) if (normal_dif(0) < eps && normal_dif(1) < eps && normal_dif(2) < eps) {
&& (ABS(normal[2] - test_norm[2]) < 0.001)) { // Facet is backwards.
/* Facet is backwards. */
if(normal_fix_flag) { if(normal_fix_flag) {
facet->normal.x = normal[0]; facet->normal = normal;
facet->normal.y = normal[1];
facet->normal.z = normal[2];
stl->stats.normals_fixed += 1; stl->stats.normals_fixed += 1;
} }
return 2; return 2;
} }
if(normal_fix_flag) { if(normal_fix_flag) {
facet->normal.x = normal[0]; facet->normal = normal;
facet->normal.y = normal[1];
facet->normal.z = normal[2];
stl->stats.normals_fixed += 1; stl->stats.normals_fixed += 1;
} }
return 4; return 4;
} }
void stl_calculate_normal(float normal[], stl_facet *facet) { void stl_fix_normal_values(stl_file *stl) {
float v1[3] = {
facet->vertex[1].x - facet->vertex[0].x,
facet->vertex[1].y - facet->vertex[0].y,
facet->vertex[1].z - facet->vertex[0].z
};
float v2[3] = {
facet->vertex[2].x - facet->vertex[0].x,
facet->vertex[2].y - facet->vertex[0].y,
facet->vertex[2].z - facet->vertex[0].z
};
normal[0] = (float)((double)v1[1] * (double)v2[2]) - ((double)v1[2] * (double)v2[1]);
normal[1] = (float)((double)v1[2] * (double)v2[0]) - ((double)v1[0] * (double)v2[2]);
normal[2] = (float)((double)v1[0] * (double)v2[1]) - ((double)v1[1] * (double)v2[0]);
}
void stl_normalize_vector(float v[]) {
double length;
double factor;
float min_normal_length;
length = sqrt((double)v[0] * (double)v[0] + (double)v[1] * (double)v[1] + (double)v[2] * (double)v[2]);
min_normal_length = 0.000000000001;
if(length < min_normal_length) {
v[0] = 0.0;
v[1] = 0.0;
v[2] = 0.0;
return;
}
factor = 1.0 / length;
v[0] *= factor;
v[1] *= factor;
v[2] *= factor;
}
void
stl_fix_normal_values(stl_file *stl) {
int i; int i;
if (stl->error) return; if (stl->error) return;
@ -333,20 +277,16 @@ stl_fix_normal_values(stl_file *stl) {
} }
} }
void void stl_reverse_all_facets(stl_file *stl)
stl_reverse_all_facets(stl_file *stl) { {
int i; if (stl->error)
float normal[3]; return;
if (stl->error) return; stl_normal normal;
for(int i = 0; i < stl->stats.number_of_facets; i++) {
for(i = 0; i < stl->stats.number_of_facets; i++) {
stl_reverse_facet(stl, i); stl_reverse_facet(stl, 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.x = normal[0]; stl->facet_start[i].normal = normal;
stl->facet_start[i].normal.y = normal[1];
stl->facet_start[i].normal.z = normal[2];
} }
} }

View File

@ -169,7 +169,7 @@ stl_write_off(stl_file *stl, char *file) {
for(i = 0; i < stl->stats.shared_vertices; i++) { for(i = 0; i < stl->stats.shared_vertices; i++) {
fprintf(fp, "\t%f %f %f\n", fprintf(fp, "\t%f %f %f\n",
stl->v_shared[i].x, stl->v_shared[i].y, stl->v_shared[i].z); stl->v_shared[i](0), stl->v_shared[i](1), stl->v_shared[i](2));
} }
for(i = 0; i < stl->stats.number_of_facets; i++) { for(i = 0; i < stl->stats.number_of_facets; i++) {
fprintf(fp, "\t3 %d %d %d\n", stl->v_indices[i].vertex[0], fprintf(fp, "\t3 %d %d %d\n", stl->v_indices[i].vertex[0],
@ -216,10 +216,10 @@ stl_write_vrml(stl_file *stl, char *file) {
for(i = 0; i < (stl->stats.shared_vertices - 1); i++) { for(i = 0; i < (stl->stats.shared_vertices - 1); i++) {
fprintf(fp, "\t\t\t\t%f %f %f,\n", fprintf(fp, "\t\t\t\t%f %f %f,\n",
stl->v_shared[i].x, stl->v_shared[i].y, stl->v_shared[i].z); stl->v_shared[i](0), stl->v_shared[i](1), stl->v_shared[i](2));
} }
fprintf(fp, "\t\t\t\t%f %f %f]\n", fprintf(fp, "\t\t\t\t%f %f %f]\n",
stl->v_shared[i].x, stl->v_shared[i].y, stl->v_shared[i].z); stl->v_shared[i](0), stl->v_shared[i](1), stl->v_shared[i](2));
fprintf(fp, "\t\t}\n"); fprintf(fp, "\t\t}\n");
fprintf(fp, "\t\tDEF STLTriangles IndexedFaceSet {\n"); fprintf(fp, "\t\tDEF STLTriangles IndexedFaceSet {\n");
fprintf(fp, "\t\t\tcoordIndex [\n"); fprintf(fp, "\t\t\tcoordIndex [\n");
@ -254,7 +254,7 @@ void stl_write_obj (stl_file *stl, char *file) {
} }
for (i = 0; i < stl->stats.shared_vertices; i++) { for (i = 0; i < stl->stats.shared_vertices; i++) {
fprintf(fp, "v %f %f %f\n", stl->v_shared[i].x, stl->v_shared[i].y, stl->v_shared[i].z); fprintf(fp, "v %f %f %f\n", stl->v_shared[i](0), stl->v_shared[i](1), stl->v_shared[i](2));
} }
for (i = 0; i < stl->stats.number_of_facets; i++) { for (i = 0; i < stl->stats.number_of_facets; i++) {
fprintf(fp, "f %d %d %d\n", stl->v_indices[i].vertex[0]+1, stl->v_indices[i].vertex[1]+1, stl->v_indices[i].vertex[2]+1); fprintf(fp, "f %d %d %d\n", stl->v_indices[i].vertex[0]+1, stl->v_indices[i].vertex[1]+1, stl->v_indices[i].vertex[2]+1);

View File

@ -27,9 +27,7 @@
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
#define STL_MAX(A,B) ((A)>(B)? (A):(B)) #include <Eigen/Geometry>
#define STL_MIN(A,B) ((A)<(B)? (A):(B))
#define ABS(X) ((X) < 0 ? -(X) : (X))
// Size of the binary STL header, free form. // Size of the binary STL header, free form.
#define LABEL_SIZE 80 #define LABEL_SIZE 80
@ -39,31 +37,16 @@
#define HEADER_SIZE 84 #define HEADER_SIZE 84
#define STL_MIN_FILE_SIZE 284 #define STL_MIN_FILE_SIZE 284
#define ASCII_LINES_PER_FACET 7 #define ASCII_LINES_PER_FACET 7
// Comparing an edge by memcmp, 2x3x4 bytes = 24
#define SIZEOF_EDGE_SORT 24
typedef struct {
float x;
float y;
float z;
} stl_vertex;
typedef Eigen::Matrix<float, 3, 1, Eigen::DontAlign> stl_vertex;
typedef Eigen::Matrix<float, 3, 1, Eigen::DontAlign> stl_normal;
static_assert(sizeof(stl_vertex) == 12, "size of stl_vertex incorrect"); static_assert(sizeof(stl_vertex) == 12, "size of stl_vertex incorrect");
typedef struct {
float x;
float y;
float z;
} stl_normal;
static_assert(sizeof(stl_normal) == 12, "size of stl_normal incorrect"); static_assert(sizeof(stl_normal) == 12, "size of stl_normal incorrect");
typedef char stl_extra[2];
typedef struct { typedef struct {
stl_normal normal; stl_normal normal;
stl_vertex vertex[3]; stl_vertex vertex[3];
stl_extra extra; char extra[2];
} stl_facet; } stl_facet;
#define SIZEOF_STL_FACET 50 #define SIZEOF_STL_FACET 50
@ -81,8 +64,12 @@ typedef struct {
} stl_edge; } stl_edge;
typedef struct stl_hash_edge { typedef struct stl_hash_edge {
// Key of a hash edge: 2x binary copy of a floating point vertex. // Key of a hash edge: sorted vertices of the edge.
uint32_t key[6]; unsigned char key[2 * sizeof(stl_vertex)];
// 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 ! (*this == rhs); }
int hash(int M) const { return ((key[0] / 23 + key[1] / 19 + key[2] / 17 + key[3] /13 + key[4] / 11 + key[5] / 7 ) % 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.
@ -91,8 +78,6 @@ typedef struct stl_hash_edge {
struct stl_hash_edge *next; struct stl_hash_edge *next;
} stl_hash_edge; } stl_hash_edge;
static_assert(offsetof(stl_hash_edge, facet_number) == SIZEOF_EDGE_SORT, "size of stl_hash_edge.key incorrect");
typedef struct { typedef struct {
// Index of a neighbor facet. // Index of a neighbor facet.
int neighbor[3]; int neighbor[3];
@ -179,8 +164,8 @@ extern void stl_fix_normal_values(stl_file *stl);
extern void stl_reverse_all_facets(stl_file *stl); extern void stl_reverse_all_facets(stl_file *stl);
extern void stl_translate(stl_file *stl, float x, float y, float z); extern void stl_translate(stl_file *stl, float x, float y, float z);
extern void stl_translate_relative(stl_file *stl, float x, float y, float z); extern void stl_translate_relative(stl_file *stl, float x, float y, float z);
extern void stl_scale_versor(stl_file *stl, float versor[3]); extern void stl_scale_versor(stl_file *stl, const stl_vertex &versor);
extern void stl_scale(stl_file *stl, float factor); inline void stl_scale(stl_file *stl, float factor) { stl_scale_versor(stl, stl_vertex(factor, factor, factor)); }
extern void stl_rotate_x(stl_file *stl, float angle); extern void stl_rotate_x(stl_file *stl, float angle);
extern void stl_rotate_y(stl_file *stl, float angle); extern void stl_rotate_y(stl_file *stl, float angle);
extern void stl_rotate_z(stl_file *stl, float angle); extern void stl_rotate_z(stl_file *stl, float angle);
@ -195,8 +180,20 @@ extern void stl_write_obj(stl_file *stl, char *file);
extern void stl_write_off(stl_file *stl, char *file); extern void stl_write_off(stl_file *stl, char *file);
extern void stl_write_dxf(stl_file *stl, char *file, char *label); extern void stl_write_dxf(stl_file *stl, char *file, char *label);
extern void stl_write_vrml(stl_file *stl, char *file); extern void stl_write_vrml(stl_file *stl, char *file);
extern void stl_calculate_normal(float normal[], stl_facet *facet); inline void stl_calculate_normal(stl_normal &normal, stl_facet *facet) {
extern void stl_normalize_vector(float v[]); normal = (facet->vertex[1] - facet->vertex[0]).cross(facet->vertex[2] - facet->vertex[0]);
}
inline void stl_normalize_vector(stl_normal &normal) {
double length = normal.cast<double>().norm();
if (length < 0.000000000001)
normal = stl_normal::Zero();
else
normal *= (1.0 / length);
}
inline bool stl_vertex_lower(const stl_vertex &a, const stl_vertex &b) {
return (a(0) != b(0)) ? (a(0) < b(0)) :
((a(1) != b(1)) ? (a(1) < b(1)) : (a(2) < b(2)));
}
extern void stl_calculate_volume(stl_file *stl); extern void stl_calculate_volume(stl_file *stl);
extern void stl_repair(stl_file *stl, int fixall_flag, int exact_flag, int tolerance_flag, float tolerance, int increment_flag, float increment, int nearby_flag, int iterations, int remove_unconnected_flag, int fill_holes_flag, int normal_directions_flag, int normal_values_flag, int reverse_all_flag, int verbose_flag); extern void stl_repair(stl_file *stl, int fixall_flag, int exact_flag, int tolerance_flag, float tolerance, int increment_flag, float increment, int nearby_flag, int iterations, int remove_unconnected_flag, int fill_holes_flag, int normal_directions_flag, int normal_values_flag, int reverse_all_flag, int verbose_flag);
@ -204,8 +201,8 @@ extern void stl_repair(stl_file *stl, int fixall_flag, int exact_flag, int toler
extern void stl_initialize(stl_file *stl); extern void stl_initialize(stl_file *stl);
extern void stl_count_facets(stl_file *stl, const char *file); extern void stl_count_facets(stl_file *stl, const char *file);
extern void stl_allocate(stl_file *stl); extern void stl_allocate(stl_file *stl);
extern void stl_read(stl_file *stl, int first_facet, int first); extern void stl_read(stl_file *stl, int first_facet, bool first);
extern void stl_facet_stats(stl_file *stl, stl_facet facet, int 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, stl_facet *new_facet);
extern void stl_get_size(stl_file *stl); extern void stl_get_size(stl_file *stl);

View File

@ -44,9 +44,9 @@ stl_print_edges(stl_file *stl, FILE *file) {
for(i = 0; i < edges_allocated; i++) { for(i = 0; i < edges_allocated; i++) {
fprintf(file, "%d, %f, %f, %f, %f, %f, %f\n", fprintf(file, "%d, %f, %f, %f, %f, %f, %f\n",
stl->edge_start[i].facet_number, stl->edge_start[i].facet_number,
stl->edge_start[i].p1.x, stl->edge_start[i].p1.y, stl->edge_start[i].p1(0), stl->edge_start[i].p1(1),
stl->edge_start[i].p1.z, stl->edge_start[i].p2.x, stl->edge_start[i].p1(2), stl->edge_start[i].p2(0),
stl->edge_start[i].p2.y, stl->edge_start[i].p2.z); stl->edge_start[i].p2(1), stl->edge_start[i].p2(2));
} }
} }
@ -75,11 +75,11 @@ File type : ASCII STL file\n");
Header : %s\n", stl->stats.header); Header : %s\n", stl->stats.header);
fprintf(file, "============== Size ==============\n"); fprintf(file, "============== Size ==============\n");
fprintf(file, "Min X = % f, Max X = % f\n", fprintf(file, "Min X = % f, Max X = % f\n",
stl->stats.min.x, stl->stats.max.x); stl->stats.min(0), stl->stats.max(0));
fprintf(file, "Min Y = % f, Max Y = % f\n", fprintf(file, "Min Y = % f, Max Y = % f\n",
stl->stats.min.y, stl->stats.max.y); stl->stats.min(1), stl->stats.max(1));
fprintf(file, "Min Z = % f, Max Z = % f\n", fprintf(file, "Min Z = % f, Max Z = % f\n",
stl->stats.min.z, stl->stats.max.z); stl->stats.min(2), stl->stats.max(2));
fprintf(file, "\ fprintf(file, "\
========= Facet Status ========== Original ============ Final ====\n"); ========= Facet Status ========== Original ============ Final ====\n");
@ -149,18 +149,18 @@ stl_write_ascii(stl_file *stl, const char *file, const char *label) {
for(i = 0; i < stl->stats.number_of_facets; i++) { for(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.x, stl->facet_start[i].normal.y, stl->facet_start[i].normal(0), stl->facet_start[i].normal(1),
stl->facet_start[i].normal.z); 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].x, stl->facet_start[i].vertex[0].y, stl->facet_start[i].vertex[0](0), stl->facet_start[i].vertex[0](1),
stl->facet_start[i].vertex[0].z); stl->facet_start[i].vertex[0](2));
fprintf(fp, " vertex % .8E % .8E % .8E\n", fprintf(fp, " vertex % .8E % .8E % .8E\n",
stl->facet_start[i].vertex[1].x, stl->facet_start[i].vertex[1].y, stl->facet_start[i].vertex[1](0), stl->facet_start[i].vertex[1](1),
stl->facet_start[i].vertex[1].z); stl->facet_start[i].vertex[1](2));
fprintf(fp, " vertex % .8E % .8E % .8E\n", fprintf(fp, " vertex % .8E % .8E % .8E\n",
stl->facet_start[i].vertex[2].x, stl->facet_start[i].vertex[2].y, stl->facet_start[i].vertex[2](0), stl->facet_start[i].vertex[2](1),
stl->facet_start[i].vertex[2].z); stl->facet_start[i].vertex[2](2));
fprintf(fp, " endloop\n"); fprintf(fp, " endloop\n");
fprintf(fp, " endfacet\n"); fprintf(fp, " endfacet\n");
} }
@ -264,9 +264,9 @@ void
stl_write_vertex(stl_file *stl, int facet, int vertex) { stl_write_vertex(stl_file *stl, int facet, int vertex) {
if (stl->error) return; if (stl->error) return;
printf(" vertex %d/%d % .8E % .8E % .8E\n", vertex, facet, printf(" vertex %d/%d % .8E % .8E % .8E\n", vertex, facet,
stl->facet_start[facet].vertex[vertex].x, stl->facet_start[facet].vertex[vertex](0),
stl->facet_start[facet].vertex[vertex].y, stl->facet_start[facet].vertex[vertex](1),
stl->facet_start[facet].vertex[vertex].z); stl->facet_start[facet].vertex[vertex](2));
} }
void void
@ -309,10 +309,10 @@ stl_write_quad_object(stl_file *stl, char *file) {
int i; int i;
int j; int j;
char *error_msg; char *error_msg;
stl_vertex connect_color; stl_vertex connect_color = stl_vertex::Zero();
stl_vertex uncon_1_color; stl_vertex uncon_1_color = stl_vertex::Zero();
stl_vertex uncon_2_color; stl_vertex uncon_2_color = stl_vertex::Zero();
stl_vertex uncon_3_color; stl_vertex uncon_3_color = stl_vertex::Zero();
stl_vertex color; stl_vertex color;
if (stl->error) return; if (stl->error) return;
@ -330,19 +330,6 @@ stl_write_quad_object(stl_file *stl, char *file) {
return; return;
} }
connect_color.x = 0.0;
connect_color.y = 0.0;
connect_color.z = 1.0;
uncon_1_color.x = 0.0;
uncon_1_color.y = 1.0;
uncon_1_color.z = 0.0;
uncon_2_color.x = 1.0;
uncon_2_color.y = 1.0;
uncon_2_color.z = 1.0;
uncon_3_color.x = 1.0;
uncon_3_color.y = 0.0;
uncon_3_color.z = 0.0;
fprintf(fp, "CQUAD\n"); fprintf(fp, "CQUAD\n");
for(i = 0; i < stl->stats.number_of_facets; i++) { for(i = 0; i < stl->stats.number_of_facets; i++) {
j = ((stl->neighbors_start[i].neighbor[0] == -1) + j = ((stl->neighbors_start[i].neighbor[0] == -1) +
@ -358,21 +345,21 @@ stl_write_quad_object(stl_file *stl, char *file) {
color = uncon_3_color; 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].x, stl->facet_start[i].vertex[0](0),
stl->facet_start[i].vertex[0].y, stl->facet_start[i].vertex[0](1),
stl->facet_start[i].vertex[0].z, color.x, color.y, color.z); 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", fprintf(fp, "%f %f %f %1.1f %1.1f %1.1f 1\n",
stl->facet_start[i].vertex[1].x, stl->facet_start[i].vertex[1](0),
stl->facet_start[i].vertex[1].y, stl->facet_start[i].vertex[1](1),
stl->facet_start[i].vertex[1].z, color.x, color.y, color.z); 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", fprintf(fp, "%f %f %f %1.1f %1.1f %1.1f 1\n",
stl->facet_start[i].vertex[2].x, stl->facet_start[i].vertex[2](0),
stl->facet_start[i].vertex[2].y, stl->facet_start[i].vertex[2](1),
stl->facet_start[i].vertex[2].z, color.x, color.y, color.z); 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", fprintf(fp, "%f %f %f %1.1f %1.1f %1.1f 1\n",
stl->facet_start[i].vertex[2].x, stl->facet_start[i].vertex[2](0),
stl->facet_start[i].vertex[2].y, stl->facet_start[i].vertex[2](1),
stl->facet_start[i].vertex[2].z, color.x, color.y, color.z); stl->facet_start[i].vertex[2](2), color(0), color(1), color(2));
} }
fclose(fp); fclose(fp);
} }
@ -409,17 +396,17 @@ stl_write_dxf(stl_file *stl, char *file, char *label) {
for(i = 0; i < stl->stats.number_of_facets; i++) { for(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].x, stl->facet_start[i].vertex[0].y, stl->facet_start[i].vertex[0](0), stl->facet_start[i].vertex[0](1),
stl->facet_start[i].vertex[0].z); stl->facet_start[i].vertex[0](2));
fprintf(fp, "11\n%f\n21\n%f\n31\n%f\n", fprintf(fp, "11\n%f\n21\n%f\n31\n%f\n",
stl->facet_start[i].vertex[1].x, stl->facet_start[i].vertex[1].y, stl->facet_start[i].vertex[1](0), stl->facet_start[i].vertex[1](1),
stl->facet_start[i].vertex[1].z); stl->facet_start[i].vertex[1](2));
fprintf(fp, "12\n%f\n22\n%f\n32\n%f\n", fprintf(fp, "12\n%f\n22\n%f\n32\n%f\n",
stl->facet_start[i].vertex[2].x, stl->facet_start[i].vertex[2].y, stl->facet_start[i].vertex[2](0), stl->facet_start[i].vertex[2](1),
stl->facet_start[i].vertex[2].z); stl->facet_start[i].vertex[2](2));
fprintf(fp, "13\n%f\n23\n%f\n33\n%f\n", fprintf(fp, "13\n%f\n23\n%f\n33\n%f\n",
stl->facet_start[i].vertex[2].x, stl->facet_start[i].vertex[2].y, stl->facet_start[i].vertex[2](0), stl->facet_start[i].vertex[2](1),
stl->facet_start[i].vertex[2].z); stl->facet_start[i].vertex[2](2));
} }
fprintf(fp, "0\nENDSEC\n0\nEOF\n"); fprintf(fp, "0\nENDSEC\n0\nEOF\n");

View File

@ -40,7 +40,7 @@ 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, 1); stl_read(stl, 0, true);
if (!stl->error) fclose(stl->fp); if (!stl->error) fclose(stl->fp);
} }
@ -227,7 +227,7 @@ stl_open_merge(stl_file *stl, char *file_to_merge) {
Start at num_facets_so_far, the index to the first unused facet. Also say Start at num_facets_so_far, the index to the first unused facet. Also say
that this isn't our first time so we should augment stats like min and max that this isn't our first time so we should augment stats like min and max
instead of erasing them. */ instead of erasing them. */
stl_read(stl, num_facets_so_far, 0); stl_read(stl, num_facets_so_far, false);
/* Restore the stl information we overwrote (for stl_read) so that it still accurately /* Restore the stl information we overwrote (for stl_read) so that it still accurately
reflects the subject part: */ reflects the subject part: */
@ -255,8 +255,7 @@ stl_reallocate(stl_file *stl) {
/* 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. */
void void stl_read(stl_file *stl, int first_facet, bool first) {
stl_read(stl_file *stl, int first_facet, int first) {
stl_facet facet; stl_facet facet;
int i; int i;
@ -294,11 +293,11 @@ stl_read(stl_file *stl, int first_facet, int first) {
assert(res_normal == 3); assert(res_normal == 3);
int res_outer_loop = fscanf(stl->fp, " outer loop"); int res_outer_loop = fscanf(stl->fp, " outer loop");
assert(res_outer_loop == 0); assert(res_outer_loop == 0);
int res_vertex1 = fscanf(stl->fp, " vertex %f %f %f", &facet.vertex[0].x, &facet.vertex[0].y, &facet.vertex[0].z); int res_vertex1 = fscanf(stl->fp, " vertex %f %f %f", &facet.vertex[0](0), &facet.vertex[0](1), &facet.vertex[0](2));
assert(res_vertex1 == 3); assert(res_vertex1 == 3);
int res_vertex2 = fscanf(stl->fp, " vertex %f %f %f", &facet.vertex[1].x, &facet.vertex[1].y, &facet.vertex[1].z); int res_vertex2 = fscanf(stl->fp, " vertex %f %f %f", &facet.vertex[1](0), &facet.vertex[1](1), &facet.vertex[1](2));
assert(res_vertex2 == 3); assert(res_vertex2 == 3);
int res_vertex3 = fscanf(stl->fp, " vertex %f %f %f", &facet.vertex[2].x, &facet.vertex[2].y, &facet.vertex[2].z); int res_vertex3 = fscanf(stl->fp, " vertex %f %f %f", &facet.vertex[2](0), &facet.vertex[2](1), &facet.vertex[2](2));
assert(res_vertex3 == 3); assert(res_vertex3 == 3);
int res_endloop = fscanf(stl->fp, " endloop"); int res_endloop = fscanf(stl->fp, " endloop");
assert(res_endloop == 0); assert(res_endloop == 0);
@ -311,9 +310,9 @@ stl_read(stl_file *stl, int first_facet, int first) {
} }
// The facet normal has been parsed as a single string as to workaround for not a numbers in the normal definition. // The facet normal has been parsed as a single string as to workaround for not a numbers in the normal definition.
if (sscanf(normal_buf[0], "%f", &facet.normal.x) != 1 || if (sscanf(normal_buf[0], "%f", &facet.normal(0)) != 1 ||
sscanf(normal_buf[1], "%f", &facet.normal.y) != 1 || sscanf(normal_buf[1], "%f", &facet.normal(1)) != 1 ||
sscanf(normal_buf[2], "%f", &facet.normal.z) != 1) { sscanf(normal_buf[2], "%f", &facet.normal(2)) != 1) {
// Normal was mangled. Maybe denormals or "not a number" were stored? // Normal was mangled. Maybe denormals or "not a number" were stored?
// Just reset the normal and silently ignore it. // Just reset the normal and silently ignore it.
memset(&facet.normal, 0, sizeof(facet.normal)); memset(&facet.normal, 0, sizeof(facet.normal));
@ -326,104 +325,45 @@ stl_read(stl_file *stl, int first_facet, int first) {
// It may be worth to round these numbers to zero during loading to reduce the number of errors reported // It may be worth to round these numbers to zero during loading to reduce the number of errors reported
// during the STL import. // during the STL import.
for (size_t j = 0; j < 3; ++ j) { for (size_t j = 0; j < 3; ++ j) {
if (facet.vertex[j].x > -1e-12f && facet.vertex[j].x < 1e-12f) if (facet.vertex[j](0) > -1e-12f && facet.vertex[j](0) < 1e-12f)
printf("stl_read: facet %d.x = %e\r\n", j, facet.vertex[j].x); printf("stl_read: facet %d(0) = %e\r\n", j, facet.vertex[j](0));
if (facet.vertex[j].y > -1e-12f && facet.vertex[j].y < 1e-12f) if (facet.vertex[j](1) > -1e-12f && facet.vertex[j](1) < 1e-12f)
printf("stl_read: facet %d.y = %e\r\n", j, facet.vertex[j].y); printf("stl_read: facet %d(1) = %e\r\n", j, facet.vertex[j](1));
if (facet.vertex[j].z > -1e-12f && facet.vertex[j].z < 1e-12f) if (facet.vertex[j](2) > -1e-12f && facet.vertex[j](2) < 1e-12f)
printf("stl_read: facet %d.z = %e\r\n", j, facet.vertex[j].z); printf("stl_read: facet %d(2) = %e\r\n", j, facet.vertex[j](2));
} }
#endif #endif
#if 1
{
// Positive and negative zeros are possible in the floats, which are considered equal by the FP unit.
// When using a memcmp on raw floats, those numbers report to be different.
// Unify all +0 and -0 to +0 to make the floats equal under memcmp.
uint32_t *f = (uint32_t*)&facet;
for (int j = 0; j < 12; ++ j, ++ f) // 3x vertex + normal: 4x3 = 12 floats
if (*f == 0x80000000)
// Negative zero, switch to positive zero.
*f = 0;
}
#else
{
// Due to the nature of the floating point numbers, close to zero values may be represented with singificantly higher precision
// than the rest of the vertices. Round them to zero.
float *f = (float*)&facet;
for (int j = 0; j < 12; ++ j, ++ f) // 3x vertex + normal: 4x3 = 12 floats
if (*f > -1e-12f && *f < 1e-12f)
// Negative zero, switch to positive zero.
*f = 0;
}
#endif
/* Write the facet into memory. */ /* Write the facet into memory. */
memcpy(stl->facet_start+i, &facet, SIZEOF_STL_FACET); stl->facet_start[i] = facet;
stl_facet_stats(stl, facet, first); stl_facet_stats(stl, facet, first);
first = 0;
} }
stl->stats.size.x = stl->stats.max.x - stl->stats.min.x; stl->stats.size = stl->stats.max - stl->stats.min;
stl->stats.size.y = stl->stats.max.y - stl->stats.min.y; stl->stats.bounding_diameter = stl->stats.size.norm();
stl->stats.size.z = stl->stats.max.z - stl->stats.min.z;
stl->stats.bounding_diameter = sqrt(
stl->stats.size.x * stl->stats.size.x +
stl->stats.size.y * stl->stats.size.y +
stl->stats.size.z * stl->stats.size.z
);
} }
void void stl_facet_stats(stl_file *stl, stl_facet facet, bool &first)
stl_facet_stats(stl_file *stl, stl_facet facet, int first) { {
float diff_x; if (stl->error)
float diff_y; return;
float diff_z;
float max_diff;
if (stl->error) return; // While we are going through all of the facets, let's find the
// maximum and minimum values for x, y, and z
/* while we are going through all of the facets, let's find the */
/* maximum and minimum values for x, y, and z */
/* Initialize the max and min values the first time through*/
if (first) { if (first) {
stl->stats.max.x = facet.vertex[0].x; // Initialize the max and min values the first time through
stl->stats.min.x = facet.vertex[0].x; stl->stats.min = facet.vertex[0];
stl->stats.max.y = facet.vertex[0].y; stl->stats.max = facet.vertex[0];
stl->stats.min.y = facet.vertex[0].y; stl_vertex diff = (facet.vertex[1] - facet.vertex[0]).cwiseAbs();
stl->stats.max.z = facet.vertex[0].z; stl->stats.shortest_edge = std::max(diff(0), std::max(diff(1), diff(2)));
stl->stats.min.z = facet.vertex[0].z; first = false;
diff_x = ABS(facet.vertex[0].x - facet.vertex[1].x);
diff_y = ABS(facet.vertex[0].y - facet.vertex[1].y);
diff_z = ABS(facet.vertex[0].z - facet.vertex[1].z);
max_diff = STL_MAX(diff_x, diff_y);
max_diff = STL_MAX(diff_z, max_diff);
stl->stats.shortest_edge = max_diff;
first = 0;
} }
/* now find the max and min values */ // Now find the max and min values.
stl->stats.max.x = STL_MAX(stl->stats.max.x, facet.vertex[0].x); for (size_t i = 0; i < 3; ++ i) {
stl->stats.min.x = STL_MIN(stl->stats.min.x, facet.vertex[0].x); stl->stats.min = stl->stats.min.cwiseMin(facet.vertex[i]);
stl->stats.max.y = STL_MAX(stl->stats.max.y, facet.vertex[0].y); stl->stats.max = stl->stats.max.cwiseMin(facet.vertex[i]);
stl->stats.min.y = STL_MIN(stl->stats.min.y, facet.vertex[0].y); }
stl->stats.max.z = STL_MAX(stl->stats.max.z, facet.vertex[0].z);
stl->stats.min.z = STL_MIN(stl->stats.min.z, facet.vertex[0].z);
stl->stats.max.x = STL_MAX(stl->stats.max.x, facet.vertex[1].x);
stl->stats.min.x = STL_MIN(stl->stats.min.x, facet.vertex[1].x);
stl->stats.max.y = STL_MAX(stl->stats.max.y, facet.vertex[1].y);
stl->stats.min.y = STL_MIN(stl->stats.min.y, facet.vertex[1].y);
stl->stats.max.z = STL_MAX(stl->stats.max.z, facet.vertex[1].z);
stl->stats.min.z = STL_MIN(stl->stats.min.z, facet.vertex[1].z);
stl->stats.max.x = STL_MAX(stl->stats.max.x, facet.vertex[2].x);
stl->stats.min.x = STL_MIN(stl->stats.min.x, facet.vertex[2].x);
stl->stats.max.y = STL_MAX(stl->stats.max.y, facet.vertex[2].y);
stl->stats.min.y = STL_MIN(stl->stats.min.y, facet.vertex[2].y);
stl->stats.max.z = STL_MAX(stl->stats.max.z, facet.vertex[2].z);
stl->stats.min.z = STL_MIN(stl->stats.min.z, facet.vertex[2].z);
} }
void void

View File

@ -62,7 +62,7 @@ stl_verify_neighbors(stl_file *stl) {
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(memcmp(&edge_a, &edge_b, SIZEOF_EDGE_SORT) != 0) { 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", printf("edge %d of facet %d doesn't match edge %d of facet %d\n",
j, i, vnot + 1, neighbor); j, i, vnot + 1, neighbor);
@ -73,114 +73,67 @@ stl_verify_neighbors(stl_file *stl) {
} }
} }
void void stl_translate(stl_file *stl, float x, float y, float z)
stl_translate(stl_file *stl, float x, float y, float z) { {
int i; if (stl->error)
int j; return;
if (stl->error) return;
for(i = 0; i < stl->stats.number_of_facets; i++) {
for(j = 0; j < 3; j++) {
stl->facet_start[i].vertex[j].x -= (stl->stats.min.x - x);
stl->facet_start[i].vertex[j].y -= (stl->stats.min.y - y);
stl->facet_start[i].vertex[j].z -= (stl->stats.min.z - z);
}
}
stl->stats.max.x -= (stl->stats.min.x - x);
stl->stats.max.y -= (stl->stats.min.y - y);
stl->stats.max.z -= (stl->stats.min.z - z);
stl->stats.min.x = x;
stl->stats.min.y = y;
stl->stats.min.z = z;
stl_vertex new_min(x, y, z);
stl_vertex shift = new_min - stl->stats.min;
for (int i = 0; i < stl->stats.number_of_facets; ++ i)
for (int j = 0; j < 3; ++ j)
stl->facet_start[i].vertex[j] += shift;
stl->stats.min = new_min;
stl->stats.max += shift;
stl_invalidate_shared_vertices(stl); stl_invalidate_shared_vertices(stl);
} }
/* 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 void stl_translate_relative(stl_file *stl, float x, float y, float z)
stl_translate_relative(stl_file *stl, float x, float y, float z) { {
int i; if (stl->error)
int j; return;
if (stl->error) return;
for(i = 0; i < stl->stats.number_of_facets; i++) {
for(j = 0; j < 3; j++) {
stl->facet_start[i].vertex[j].x += x;
stl->facet_start[i].vertex[j].y += y;
stl->facet_start[i].vertex[j].z += z;
}
}
stl->stats.min.x += x;
stl->stats.min.y += y;
stl->stats.min.z += z;
stl->stats.max.x += x;
stl->stats.max.y += y;
stl->stats.max.z += z;
stl_vertex shift(x, y, z);
for (int i = 0; i < stl->stats.number_of_facets; ++ i)
for (int j = 0; j < 3; ++ j)
stl->facet_start[i].vertex[j] += shift;
stl->stats.min += shift;
stl->stats.max += shift;
stl_invalidate_shared_vertices(stl); stl_invalidate_shared_vertices(stl);
} }
void void stl_scale_versor(stl_file *stl, const stl_vertex &versor)
stl_scale_versor(stl_file *stl, float versor[3]) { {
int i; if (stl->error)
int j; return;
if (stl->error) return;
/* scale extents */
stl->stats.min.x *= versor[0];
stl->stats.min.y *= versor[1];
stl->stats.min.z *= versor[2];
stl->stats.max.x *= versor[0];
stl->stats.max.y *= versor[1];
stl->stats.max.z *= versor[2];
/* scale size */
stl->stats.size.x *= versor[0];
stl->stats.size.y *= versor[1];
stl->stats.size.z *= versor[2];
/* scale volume */
if (stl->stats.volume > 0.0) {
stl->stats.volume *= (versor[0] * versor[1] * versor[2]);
}
for(i = 0; i < stl->stats.number_of_facets; i++) {
for(j = 0; j < 3; j++) {
stl->facet_start[i].vertex[j].x *= versor[0];
stl->facet_start[i].vertex[j].y *= versor[1];
stl->facet_start[i].vertex[j].z *= versor[2];
}
}
// Scale extents.
auto s = versor.array();
stl->stats.min.array() *= s;
stl->stats.max.array() *= s;
// Scale size.
stl->stats.size.array() *= s;
// Scale volume.
if (stl->stats.volume > 0.0)
stl->stats.volume *= versor(0) * versor(1) * versor(2);
// Scale the mesh.
for (int i = 0; i < stl->stats.number_of_facets; ++ i)
for (int j = 0; j < 3; ++ j)
stl->facet_start[i].vertex[j].array() *= s;
stl_invalidate_shared_vertices(stl); stl_invalidate_shared_vertices(stl);
} }
void static void calculate_normals(stl_file *stl)
stl_scale(stl_file *stl, float factor) { {
float versor[3]; if (stl->error)
return;
if (stl->error) return;
versor[0] = factor;
versor[1] = factor;
versor[2] = factor;
stl_scale_versor(stl, versor);
}
static void calculate_normals(stl_file *stl) {
float normal[3];
if (stl->error) return;
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.x = normal[0]; stl->facet_start[i].normal = normal;
stl->facet_start[i].normal.y = normal[1];
stl->facet_start[i].normal.z = normal[2];
} }
} }
@ -193,9 +146,9 @@ void stl_transform(stl_file *stl, float *trafo3x4) {
for (i_vertex = 0; i_vertex < 3; ++ i_vertex) { for (i_vertex = 0; i_vertex < 3; ++ i_vertex) {
stl_vertex &v_dst = vertices[i_vertex]; stl_vertex &v_dst = vertices[i_vertex];
stl_vertex v_src = v_dst; stl_vertex v_src = v_dst;
v_dst.x = trafo3x4[0] * v_src.x + trafo3x4[1] * v_src.y + trafo3x4[2] * v_src.z + trafo3x4[3]; v_dst(0) = trafo3x4[0] * v_src(0) + trafo3x4[1] * v_src(1) + trafo3x4[2] * v_src(2) + trafo3x4[3];
v_dst.y = trafo3x4[4] * v_src.x + trafo3x4[5] * v_src.y + trafo3x4[6] * v_src.z + trafo3x4[7]; v_dst(1) = trafo3x4[4] * v_src(0) + trafo3x4[5] * v_src(1) + trafo3x4[6] * v_src(2) + trafo3x4[7];
v_dst.z = trafo3x4[8] * v_src.x + trafo3x4[9] * v_src.y + trafo3x4[10] * v_src.z + trafo3x4[11]; v_dst(2) = trafo3x4[8] * v_src(0) + trafo3x4[9] * v_src(1) + trafo3x4[10] * v_src(2) + trafo3x4[11];
} }
} }
stl_get_size(stl); stl_get_size(stl);
@ -214,8 +167,8 @@ stl_rotate_x(stl_file *stl, float angle) {
for(i = 0; i < stl->stats.number_of_facets; i++) { for(i = 0; i < stl->stats.number_of_facets; i++) {
for(j = 0; j < 3; j++) { for(j = 0; j < 3; j++) {
stl_rotate(&stl->facet_start[i].vertex[j].y, stl_rotate(&stl->facet_start[i].vertex[j](1),
&stl->facet_start[i].vertex[j].z, c, s); &stl->facet_start[i].vertex[j](2), c, s);
} }
} }
stl_get_size(stl); stl_get_size(stl);
@ -234,8 +187,8 @@ stl_rotate_y(stl_file *stl, float angle) {
for(i = 0; i < stl->stats.number_of_facets; i++) { for(i = 0; i < stl->stats.number_of_facets; i++) {
for(j = 0; j < 3; j++) { for(j = 0; j < 3; j++) {
stl_rotate(&stl->facet_start[i].vertex[j].z, stl_rotate(&stl->facet_start[i].vertex[j](2),
&stl->facet_start[i].vertex[j].x, c, s); &stl->facet_start[i].vertex[j](0), c, s);
} }
} }
stl_get_size(stl); stl_get_size(stl);
@ -254,8 +207,8 @@ stl_rotate_z(stl_file *stl, float angle) {
for(i = 0; i < stl->stats.number_of_facets; i++) { for(i = 0; i < stl->stats.number_of_facets; i++) {
for(j = 0; j < 3; j++) { for(j = 0; j < 3; j++) {
stl_rotate(&stl->facet_start[i].vertex[j].x, stl_rotate(&stl->facet_start[i].vertex[j](0),
&stl->facet_start[i].vertex[j].y, c, s); &stl->facet_start[i].vertex[j](1), c, s);
} }
} }
stl_get_size(stl); stl_get_size(stl);
@ -272,142 +225,98 @@ stl_rotate(float *x, float *y, const double c, const double s) {
*y = float(s * xold + c * yold); *y = float(s * xold + c * yold);
} }
extern void void stl_get_size(stl_file *stl)
stl_get_size(stl_file *stl) { {
int i; if (stl->error || stl->stats.number_of_facets == 0)
int j; return;
stl->stats.min = stl->facet_start[0].vertex[0];
if (stl->error) return; stl->stats.max = stl->stats.min;
if (stl->stats.number_of_facets == 0) return; for (int i = 0; i < stl->stats.number_of_facets; ++ i) {
const stl_facet &face = stl->facet_start[i];
stl->stats.min.x = stl->facet_start[0].vertex[0].x; for (int j = 0; j < 3; ++ j) {
stl->stats.min.y = stl->facet_start[0].vertex[0].y; stl->stats.min = stl->stats.min.cwiseMin(face.vertex[j]);
stl->stats.min.z = stl->facet_start[0].vertex[0].z; stl->stats.max = stl->stats.max.cwiseMax(face.vertex[j]);
stl->stats.max.x = stl->facet_start[0].vertex[0].x;
stl->stats.max.y = stl->facet_start[0].vertex[0].y;
stl->stats.max.z = stl->facet_start[0].vertex[0].z;
for(i = 0; i < stl->stats.number_of_facets; i++) {
for(j = 0; j < 3; j++) {
stl->stats.min.x = STL_MIN(stl->stats.min.x,
stl->facet_start[i].vertex[j].x);
stl->stats.min.y = STL_MIN(stl->stats.min.y,
stl->facet_start[i].vertex[j].y);
stl->stats.min.z = STL_MIN(stl->stats.min.z,
stl->facet_start[i].vertex[j].z);
stl->stats.max.x = STL_MAX(stl->stats.max.x,
stl->facet_start[i].vertex[j].x);
stl->stats.max.y = STL_MAX(stl->stats.max.y,
stl->facet_start[i].vertex[j].y);
stl->stats.max.z = STL_MAX(stl->stats.max.z,
stl->facet_start[i].vertex[j].z);
} }
} }
stl->stats.size.x = stl->stats.max.x - stl->stats.min.x; stl->stats.size = stl->stats.max - stl->stats.min;
stl->stats.size.y = stl->stats.max.y - stl->stats.min.y; stl->stats.bounding_diameter = stl->stats.size.norm();
stl->stats.size.z = stl->stats.max.z - stl->stats.min.z;
stl->stats.bounding_diameter = sqrt(
stl->stats.size.x * stl->stats.size.x +
stl->stats.size.y * stl->stats.size.y +
stl->stats.size.z * stl->stats.size.z
);
} }
void void stl_mirror_xy(stl_file *stl)
stl_mirror_xy(stl_file *stl) { {
int i; if (stl->error)
int j; return;
float temp_size;
if (stl->error) return; for(int 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->facet_start[i].vertex[j](2) *= -1.0;
for(j = 0; j < 3; j++) {
stl->facet_start[i].vertex[j].z *= -1.0;
} }
} }
temp_size = stl->stats.min.z; float temp_size = stl->stats.min(2);
stl->stats.min.z = stl->stats.max.z; stl->stats.min(2) = stl->stats.max(2);
stl->stats.max.z = temp_size; stl->stats.max(2) = temp_size;
stl->stats.min.z *= -1.0; stl->stats.min(2) *= -1.0;
stl->stats.max.z *= -1.0; stl->stats.max(2) *= -1.0;
stl_reverse_all_facets(stl); stl_reverse_all_facets(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 */
} }
void void stl_mirror_yz(stl_file *stl)
stl_mirror_yz(stl_file *stl) { {
int i;
int j;
float temp_size;
if (stl->error) return; if (stl->error) return;
for(i = 0; i < stl->stats.number_of_facets; i++) { for (int i = 0; i < stl->stats.number_of_facets; i++) {
for(j = 0; j < 3; j++) { for (int j = 0; j < 3; j++) {
stl->facet_start[i].vertex[j].x *= -1.0; stl->facet_start[i].vertex[j](0) *= -1.0;
} }
} }
temp_size = stl->stats.min.x; float temp_size = stl->stats.min(0);
stl->stats.min.x = stl->stats.max.x; stl->stats.min(0) = stl->stats.max(0);
stl->stats.max.x = temp_size; stl->stats.max(0) = temp_size;
stl->stats.min.x *= -1.0; stl->stats.min(0) *= -1.0;
stl->stats.max.x *= -1.0; stl->stats.max(0) *= -1.0;
stl_reverse_all_facets(stl); stl_reverse_all_facets(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 */
} }
void void stl_mirror_xz(stl_file *stl)
stl_mirror_xz(stl_file *stl) { {
int i; if (stl->error)
int j; return;
float temp_size;
if (stl->error) return; for (int 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->facet_start[i].vertex[j](1) *= -1.0;
for(j = 0; j < 3; j++) {
stl->facet_start[i].vertex[j].y *= -1.0;
} }
} }
temp_size = stl->stats.min.y; float temp_size = stl->stats.min(1);
stl->stats.min.y = stl->stats.max.y; stl->stats.min(1) = stl->stats.max(1);
stl->stats.max.y = temp_size; stl->stats.max(1) = temp_size;
stl->stats.min.y *= -1.0; stl->stats.min(1) *= -1.0;
stl->stats.max.y *= -1.0; stl->stats.max(1) *= -1.0;
stl_reverse_all_facets(stl); stl_reverse_all_facets(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_volume(stl_file *stl) { static float get_volume(stl_file *stl)
stl_vertex p0; {
stl_vertex p; if (stl->error)
stl_normal n; return 0;
float height;
float area;
float volume = 0.0;
if (stl->error) return 0; // Choose a point, any point as the reference.
stl_vertex p0 = stl->facet_start[0].vertex[0];
/* Choose a point, any point as the reference */ float volume = 0.f;
p0.x = stl->facet_start[0].vertex[0].x; for(uint32_t i = 0; i < stl->stats.number_of_facets; ++ i) {
p0.y = stl->facet_start[0].vertex[0].y; // Do dot product to get distance from point to plane.
p0.z = stl->facet_start[0].vertex[0].z; float height = stl->facet_start[i].normal.dot(stl->facet_start[i].vertex[0] - p0);
float area = get_area(&stl->facet_start[i]);
for(uint32_t i = 0; i < stl->stats.number_of_facets; i++) {
p.x = stl->facet_start[i].vertex[0].x - p0.x;
p.y = stl->facet_start[i].vertex[0].y - p0.y;
p.z = stl->facet_start[i].vertex[0].z - p0.z;
/* Do dot product to get distance from point to plane */
n = stl->facet_start[i].normal;
height = (n.x * p.x) + (n.y * p.y) + (n.z * p.z);
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)
{
if (stl->error) return; if (stl->error) return;
stl->stats.volume = get_volume(stl); stl->stats.volume = get_volume(stl);
if(stl->stats.volume < 0.0) { if(stl->stats.volume < 0.0) {
@ -416,35 +325,32 @@ void stl_calculate_volume(stl_file *stl) {
} }
} }
static float get_area(stl_facet *facet) { static float get_area(stl_facet *facet)
double cross[3][3]; {
float sum[3];
float n[3];
float area;
int i;
/* cast to double before calculating cross product because large coordinates /* cast to double before calculating cross product because large coordinates
can result in overflowing product can result in overflowing product
(bad area is responsible for bad volume and bad facets reversal) */ (bad area is responsible for bad volume and bad facets reversal) */
for(i = 0; i < 3; i++) { double cross[3][3];
cross[i][0]=(((double)facet->vertex[i].y * (double)facet->vertex[(i + 1) % 3].z) - for (int i = 0; i < 3; i++) {
((double)facet->vertex[i].z * (double)facet->vertex[(i + 1) % 3].y)); cross[i][0]=(((double)facet->vertex[i](1) * (double)facet->vertex[(i + 1) % 3](2)) -
cross[i][1]=(((double)facet->vertex[i].z * (double)facet->vertex[(i + 1) % 3].x) - ((double)facet->vertex[i](2) * (double)facet->vertex[(i + 1) % 3](1)));
((double)facet->vertex[i].x * (double)facet->vertex[(i + 1) % 3].z)); cross[i][1]=(((double)facet->vertex[i](2) * (double)facet->vertex[(i + 1) % 3](0)) -
cross[i][2]=(((double)facet->vertex[i].x * (double)facet->vertex[(i + 1) % 3].y) - ((double)facet->vertex[i](0) * (double)facet->vertex[(i + 1) % 3](2)));
((double)facet->vertex[i].y * (double)facet->vertex[(i + 1) % 3].x)); 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)));
} }
sum[0] = cross[0][0] + cross[1][0] + cross[2][0]; stl_normal sum;
sum[1] = cross[0][1] + cross[1][1] + cross[2][1]; sum(0) = cross[0][0] + cross[1][0] + cross[2][0];
sum[2] = cross[0][2] + cross[1][2] + cross[2][2]; 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 */ // 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_calculate_normal(n, facet);
stl_normalize_vector(n); stl_normalize_vector(n);
return 0.5f * n.dot(sum);
area = 0.5 * (n[0] * sum[0] + n[1] * sum[1] + n[2] * sum[2]);
return area;
} }
void stl_repair(stl_file *stl, void stl_repair(stl_file *stl,

View File

@ -1485,7 +1485,7 @@ namespace Slic3r {
stl_facet& facet = stl.facet_start[i]; stl_facet& facet = stl.facet_start[i];
for (unsigned int v = 0; v < 3; ++v) for (unsigned int v = 0; v < 3; ++v)
{ {
::memcpy((void*)&facet.vertex[v].x, (const void*)&geometry.vertices[geometry.triangles[src_start_id + ii + v] * 3], 3 * sizeof(float)); ::memcpy(facet.vertex[v].data(), (const void*)&geometry.vertices[geometry.triangles[src_start_id + ii + v] * 3], 3 * sizeof(float));
} }
} }
@ -1844,9 +1844,9 @@ namespace Slic3r {
for (int i = 0; i < stl.stats.shared_vertices; ++i) for (int i = 0; i < stl.stats.shared_vertices; ++i)
{ {
stream << " <" << VERTEX_TAG << " "; stream << " <" << VERTEX_TAG << " ";
stream << "x=\"" << stl.v_shared[i].x << "\" "; stream << "x=\"" << stl.v_shared[i](0) << "\" ";
stream << "y=\"" << stl.v_shared[i].y << "\" "; stream << "y=\"" << stl.v_shared[i](1) << "\" ";
stream << "z=\"" << stl.v_shared[i].z << "\" />\n"; stream << "z=\"" << stl.v_shared[i](2) << "\" />\n";
} }
} }

View File

@ -402,7 +402,7 @@ void AMFParserContext::endElement(const char * /* name */)
for (size_t i = 0; i < m_volume_facets.size();) { for (size_t i = 0; i < m_volume_facets.size();) {
stl_facet &facet = stl.facet_start[i/3]; stl_facet &facet = stl.facet_start[i/3];
for (unsigned int v = 0; v < 3; ++ v) for (unsigned int v = 0; v < 3; ++ v)
memcpy(&facet.vertex[v].x, &m_object_vertices[m_volume_facets[i ++] * 3], 3 * sizeof(float)); memcpy(facet.vertex[v].data(), &m_object_vertices[m_volume_facets[i ++] * 3], 3 * sizeof(float));
} }
stl_get_size(&stl); stl_get_size(&stl);
m_volume->mesh.repair(); m_volume->mesh.repair();
@ -760,9 +760,9 @@ bool store_amf(const char *path, Model *model, Print* print, bool export_print_c
for (size_t i = 0; i < stl.stats.shared_vertices; ++ i) { for (size_t i = 0; i < stl.stats.shared_vertices; ++ i) {
stream << " <vertex>\n"; stream << " <vertex>\n";
stream << " <coordinates>\n"; stream << " <coordinates>\n";
stream << " <x>" << stl.v_shared[i].x << "</x>\n"; stream << " <x>" << stl.v_shared[i](0) << "</x>\n";
stream << " <y>" << stl.v_shared[i].y << "</y>\n"; stream << " <y>" << stl.v_shared[i](1) << "</y>\n";
stream << " <z>" << stl.v_shared[i].z << "</z>\n"; stream << " <z>" << stl.v_shared[i](2) << "</z>\n";
stream << " </coordinates>\n"; stream << " </coordinates>\n";
stream << " </vertex>\n"; stream << " </vertex>\n";
} }

View File

@ -57,14 +57,14 @@ bool load_obj(const char *path, Model *model, const char *object_name_in)
continue; continue;
stl_facet &facet = stl.facet_start[i_face ++]; stl_facet &facet = stl.facet_start[i_face ++];
size_t num_normals = 0; size_t num_normals = 0;
stl_normal normal = { 0.f }; stl_normal normal(stl_normal::Zero());
for (unsigned int v = 0; v < 3; ++ v) { for (unsigned int v = 0; v < 3; ++ v) {
const ObjParser::ObjVertex &vertex = data.vertices[i++]; const ObjParser::ObjVertex &vertex = data.vertices[i++];
memcpy(&facet.vertex[v].x, &data.coordinates[vertex.coordIdx*4], 3 * sizeof(float)); memcpy(facet.vertex[v].data(), &data.coordinates[vertex.coordIdx*4], 3 * sizeof(float));
if (vertex.normalIdx != -1) { if (vertex.normalIdx != -1) {
normal.x += data.normals[vertex.normalIdx*3]; normal(0) += data.normals[vertex.normalIdx*3];
normal.y += data.normals[vertex.normalIdx*3+1]; normal(1) += data.normals[vertex.normalIdx*3+1];
normal.z += data.normals[vertex.normalIdx*3+2]; normal(2) += data.normals[vertex.normalIdx*3+2];
++ num_normals; ++ num_normals;
} }
} }
@ -74,33 +74,27 @@ bool load_obj(const char *path, Model *model, const char *object_name_in)
facet2.vertex[0] = facet.vertex[0]; facet2.vertex[0] = facet.vertex[0];
facet2.vertex[1] = facet.vertex[2]; facet2.vertex[1] = facet.vertex[2];
const ObjParser::ObjVertex &vertex = data.vertices[i++]; const ObjParser::ObjVertex &vertex = data.vertices[i++];
memcpy(&facet2.vertex[2].x, &data.coordinates[vertex.coordIdx * 4], 3 * sizeof(float)); memcpy(facet2.vertex[2].data(), &data.coordinates[vertex.coordIdx * 4], 3 * sizeof(float));
if (vertex.normalIdx != -1) { if (vertex.normalIdx != -1) {
normal.x += data.normals[vertex.normalIdx*3]; normal(0) += data.normals[vertex.normalIdx*3];
normal.y += data.normals[vertex.normalIdx*3+1]; normal(1) += data.normals[vertex.normalIdx*3+1];
normal.z += data.normals[vertex.normalIdx*3+2]; normal(2) += data.normals[vertex.normalIdx*3+2];
++ num_normals; ++ num_normals;
} }
if (num_normals == 4) { if (num_normals == 4) {
// Normalize an average normal of a quad. // Normalize an average normal of a quad.
float len = sqrt(facet.normal.x*facet.normal.x + facet.normal.y*facet.normal.y + facet.normal.z*facet.normal.z); float len = facet.normal.norm();
if (len > EPSILON) { if (len > EPSILON) {
normal.x /= len; normal /= len;
normal.y /= len;
normal.z /= len;
facet.normal = normal; facet.normal = normal;
facet2.normal = normal; facet2.normal = normal;
} }
} }
} else if (num_normals == 3) { } else if (num_normals == 3) {
// Normalize an average normal of a triangle. // Normalize an average normal of a triangle.
float len = sqrt(facet.normal.x*facet.normal.x + facet.normal.y*facet.normal.y + facet.normal.z*facet.normal.z); float len = facet.normal.norm();
if (len > EPSILON) { if (len > EPSILON)
normal.x /= len; facet.normal = normal / len;
normal.y /= len;
normal.z /= len;
facet.normal = normal;
}
} }
} }
stl_get_size(&stl); stl_get_size(&stl);

View File

@ -260,8 +260,8 @@ bool load_prus(const char *path, Model *model)
mesh.repair(); mesh.repair();
// Transform the model. // Transform the model.
stl_transform(&stl, &trafo[0][0]); stl_transform(&stl, &trafo[0][0]);
if (std::abs(stl.stats.min.z) < EPSILON) if (std::abs(stl.stats.min(2)) < EPSILON)
stl.stats.min.z = 0.; stl.stats.min(2) = 0.;
// Add a mesh to a model. // Add a mesh to a model.
if (mesh.facets_count() > 0) if (mesh.facets_count() > 0)
mesh_valid = true; mesh_valid = true;
@ -309,11 +309,11 @@ bool load_prus(const char *path, Model *model)
assert(res_normal == 3); assert(res_normal == 3);
int res_outer_loop = line_reader.next_line_scanf(" outer loop"); int res_outer_loop = line_reader.next_line_scanf(" outer loop");
assert(res_outer_loop == 0); assert(res_outer_loop == 0);
int res_vertex1 = line_reader.next_line_scanf(" vertex %f %f %f", &facet.vertex[0].x, &facet.vertex[0].y, &facet.vertex[0].z); int res_vertex1 = line_reader.next_line_scanf(" vertex %f %f %f", &facet.vertex[0](0), &facet.vertex[0](1), &facet.vertex[0](2));
assert(res_vertex1 == 3); assert(res_vertex1 == 3);
int res_vertex2 = line_reader.next_line_scanf(" vertex %f %f %f", &facet.vertex[1].x, &facet.vertex[1].y, &facet.vertex[1].z); int res_vertex2 = line_reader.next_line_scanf(" vertex %f %f %f", &facet.vertex[1](0), &facet.vertex[1](1), &facet.vertex[1](2));
assert(res_vertex2 == 3); assert(res_vertex2 == 3);
int res_vertex3 = line_reader.next_line_scanf(" vertex %f %f %f", &facet.vertex[2].x, &facet.vertex[2].y, &facet.vertex[2].z); int res_vertex3 = line_reader.next_line_scanf(" vertex %f %f %f", &facet.vertex[2](0), &facet.vertex[2](1), &facet.vertex[2](2));
assert(res_vertex3 == 3); assert(res_vertex3 == 3);
int res_endloop = line_reader.next_line_scanf(" endloop"); int res_endloop = line_reader.next_line_scanf(" endloop");
assert(res_endloop == 0); assert(res_endloop == 0);
@ -324,9 +324,9 @@ bool load_prus(const char *path, Model *model)
break; break;
} }
// The facet normal has been parsed as a single string as to workaround for not a numbers in the normal definition. // The facet normal has been parsed as a single string as to workaround for not a numbers in the normal definition.
if (sscanf(normal_buf[0], "%f", &facet.normal.x) != 1 || if (sscanf(normal_buf[0], "%f", &facet.normal(0)) != 1 ||
sscanf(normal_buf[1], "%f", &facet.normal.y) != 1 || sscanf(normal_buf[1], "%f", &facet.normal(1)) != 1 ||
sscanf(normal_buf[2], "%f", &facet.normal.z) != 1) { sscanf(normal_buf[2], "%f", &facet.normal(2)) != 1) {
// Normal was mangled. Maybe denormals or "not a number" were stored? // Normal was mangled. Maybe denormals or "not a number" were stored?
// Just reset the normal and silently ignore it. // Just reset the normal and silently ignore it.
memset(&facet.normal, 0, sizeof(facet.normal)); memset(&facet.normal, 0, sizeof(facet.normal));

View File

@ -642,24 +642,13 @@ BoundingBoxf3 ModelObject::tight_bounding_box(bool include_modifiers) const
{ {
// original point // original point
const stl_vertex& v = facet.vertex[i]; const stl_vertex& v = facet.vertex[i];
Vec3d p((double)v.x, (double)v.y, (double)v.z);
// scale // scale
p(0) *= inst->scaling_factor; Vec3d p = v.cast<double>() * inst->scaling_factor;
p(1) *= inst->scaling_factor; // rotate Z, translate
p(2) *= inst->scaling_factor; Vec3d q(c * p(0) - s * p(1) + inst->offset(0),
s * p(0) + c * p(1) + inst->offset(1),
// rotate Z p(2));
double x = p(0); bb.merge(q);
double y = p(1);
p(0) = c * x - s * y;
p(1) = s * x + c * y;
// translate
p(0) += inst->offset(0);
p(1) += inst->offset(1);
bb.merge(p);
} }
} }
} }
@ -770,7 +759,7 @@ void ModelObject::rotate(float angle, const Axis &axis)
for (ModelVolume *v : this->volumes) for (ModelVolume *v : this->volumes)
{ {
v->mesh.rotate(angle, axis); v->mesh.rotate(angle, axis);
min_z = std::min(min_z, v->mesh.stl.stats.min.z); min_z = std::min(min_z, v->mesh.stl.stats.min(2));
} }
if (min_z != 0.0f) if (min_z != 0.0f)
@ -927,24 +916,13 @@ void ModelObject::check_instances_print_volume_state(const BoundingBoxf3& print_
{ {
// original point // original point
const stl_vertex& v = facet.vertex[i]; const stl_vertex& v = facet.vertex[i];
Vec3d p((double)v.x, (double)v.y, (double)v.z);
// scale // scale
p(0) *= inst->scaling_factor; Vec3d p = v.cast<double>() * inst->scaling_factor;
p(1) *= inst->scaling_factor;
p(2) *= inst->scaling_factor;
// rotate Z // rotate Z
double x = p(0); bb.merge(Vec3d(
double y = p(1); c * p(0) - s * p(1) + inst->offset(0),
p(0) = c * x - s * y; s * p(0) + c * p(1) + inst->offset(1),
p(1) = s * x + c * y; p(2)));
// translate
p(0) += inst->offset(0);
p(1) += inst->offset(1);
bb.merge(p);
} }
} }
@ -1081,7 +1059,7 @@ BoundingBoxf3 ModelInstance::transform_mesh_bounding_box(const TriangleMesh* mes
const stl_facet &facet = mesh->stl.facet_start[i]; const stl_facet &facet = mesh->stl.facet_start[i];
for (int j = 0; j < 3; ++ j) { for (int j = 0; j < 3; ++ j) {
const stl_vertex &v = facet.vertex[j]; const stl_vertex &v = facet.vertex[j];
bbox.merge(Vec3d(c * v.x - s * v.y, s * v.x + c * v.y, v.z)); bbox.merge(Vec3d(c * v(0) - s * v(1), s * v(0) + c * v(1), v(2)));
} }
} }
if (! empty(bbox)) { if (! empty(bbox)) {

View File

@ -15,8 +15,8 @@ void SlicingAdaptive::clear()
std::pair<float, float> face_z_span(const stl_facet *f) std::pair<float, float> face_z_span(const stl_facet *f)
{ {
return std::pair<float, float>( return std::pair<float, float>(
std::min(std::min(f->vertex[0].z, f->vertex[1].z), f->vertex[2].z), std::min(std::min(f->vertex[0](2), f->vertex[1](2)), f->vertex[2](2)),
std::max(std::max(f->vertex[0].z, f->vertex[1].z), f->vertex[2].z)); std::max(std::max(f->vertex[0](2), f->vertex[1](2)), f->vertex[2](2)));
} }
void SlicingAdaptive::prepare() void SlicingAdaptive::prepare()
@ -40,7 +40,7 @@ void SlicingAdaptive::prepare()
// 3) Generate Z components of the facet normals. // 3) Generate Z components of the facet normals.
m_face_normal_z.assign(m_faces.size(), 0.f); m_face_normal_z.assign(m_faces.size(), 0.f);
for (size_t iface = 0; iface < m_faces.size(); ++ iface) for (size_t iface = 0; iface < m_faces.size(); ++ iface)
m_face_normal_z[iface] = m_faces[iface]->normal.z; m_face_normal_z[iface] = m_faces[iface]->normal(2);
} }
float SlicingAdaptive::cusp_height(float z, float cusp_value, int &current_facet) float SlicingAdaptive::cusp_height(float z, float cusp_value, int &current_facet)

View File

@ -51,31 +51,16 @@ TriangleMesh::TriangleMesh(const Pointf3s &points, const std::vector<Vec3crd>& f
for (int i = 0; i < stl.stats.number_of_facets; i++) { for (int i = 0; i < stl.stats.number_of_facets; i++) {
stl_facet facet; stl_facet facet;
facet.vertex[0] = points[facets[i](0)].cast<float>();
const Vec3d& ref_f1 = points[facets[i](0)]; facet.vertex[1] = points[facets[i](1)].cast<float>();
facet.vertex[0].x = ref_f1(0); facet.vertex[2] = points[facets[i](2)].cast<float>();
facet.vertex[0].y = ref_f1(1);
facet.vertex[0].z = ref_f1(2);
const Vec3d& ref_f2 = points[facets[i](1)];
facet.vertex[1].x = ref_f2(0);
facet.vertex[1].y = ref_f2(1);
facet.vertex[1].z = ref_f2(2);
const Vec3d& ref_f3 = points[facets[i](2)];
facet.vertex[2].x = ref_f3(0);
facet.vertex[2].y = ref_f3(1);
facet.vertex[2].z = ref_f3(2);
facet.extra[0] = 0; facet.extra[0] = 0;
facet.extra[1] = 0; facet.extra[1] = 0;
float normal[3]; stl_normal normal;
stl_calculate_normal(normal, &facet); stl_calculate_normal(normal, &facet);
stl_normalize_vector(normal); stl_normalize_vector(normal);
facet.normal.x = normal[0]; facet.normal = normal;
facet.normal.y = normal[1];
facet.normal.z = normal[2];
stl.facet_start[i] = facet; stl.facet_start[i] = facet;
} }
@ -302,11 +287,7 @@ void TriangleMesh::scale(float factor)
void TriangleMesh::scale(const Vec3d &versor) void TriangleMesh::scale(const Vec3d &versor)
{ {
float fversor[3]; stl_scale_versor(&this->stl, versor.cast<float>());
fversor[0] = versor(0);
fversor[1] = versor(1);
fversor[2] = versor(2);
stl_scale_versor(&this->stl, fversor);
stl_invalidate_shared_vertices(&this->stl); stl_invalidate_shared_vertices(&this->stl);
} }
@ -390,10 +371,9 @@ void TriangleMesh::transform(const float* matrix3x4)
void TriangleMesh::align_to_origin() void TriangleMesh::align_to_origin()
{ {
this->translate( this->translate(
-(this->stl.stats.min.x), - this->stl.stats.min(0),
-(this->stl.stats.min.y), - this->stl.stats.min(1),
-(this->stl.stats.min.z) - this->stl.stats.min(2));
);
} }
void TriangleMesh::rotate(double angle, Point* center) void TriangleMesh::rotate(double angle, Point* center)
@ -518,7 +498,7 @@ TriangleMesh::split() const
stl_clear_error(&mesh->stl); stl_clear_error(&mesh->stl);
stl_allocate(&mesh->stl); stl_allocate(&mesh->stl);
int first = 1; bool first = true;
for (std::deque<int>::const_iterator facet = facets.begin(); facet != facets.end(); ++facet) { for (std::deque<int>::const_iterator facet = facets.begin(); facet != facets.end(); ++facet) {
mesh->stl.facet_start[facet - facets.begin()] = this->stl.facet_start[*facet]; mesh->stl.facet_start[facet - facets.begin()] = this->stl.facet_start[*facet];
stl_facet_stats(&mesh->stl, this->stl.facet_start[*facet], first); stl_facet_stats(&mesh->stl, this->stl.facet_start[*facet], first);
@ -561,9 +541,9 @@ ExPolygons TriangleMesh::horizontal_projection() const
stl_facet* facet = &this->stl.facet_start[i]; 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].x, facet->vertex[0].y); p.points[0] = Point::new_scale(facet->vertex[0](0), facet->vertex[0](1));
p.points[1] = Point::new_scale(facet->vertex[1].x, facet->vertex[1].y); p.points[1] = Point::new_scale(facet->vertex[1](0), facet->vertex[1](1));
p.points[2] = Point::new_scale(facet->vertex[2].x, facet->vertex[2].y); 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);
} }
@ -578,8 +558,8 @@ Polygon TriangleMesh::convex_hull()
Points pp; Points pp;
pp.reserve(this->stl.stats.shared_vertices); pp.reserve(this->stl.stats.shared_vertices);
for (int i = 0; i < this->stl.stats.shared_vertices; ++ i) { for (int i = 0; i < this->stl.stats.shared_vertices; ++ i) {
stl_vertex* v = &this->stl.v_shared[i]; const stl_vertex &v = this->stl.v_shared[i];
pp.emplace_back(Point::new_scale(v->x, v->y)); pp.emplace_back(Point::new_scale(v(0), v(1)));
} }
return Slic3r::Geometry::convex_hull(pp); return Slic3r::Geometry::convex_hull(pp);
} }
@ -589,12 +569,8 @@ TriangleMesh::bounding_box() const
{ {
BoundingBoxf3 bb; BoundingBoxf3 bb;
bb.defined = true; bb.defined = true;
bb.min(0) = this->stl.stats.min.x; bb.min = this->stl.stats.min.cast<double>();
bb.min(1) = this->stl.stats.min.y; bb.max = this->stl.stats.max.cast<double>();
bb.min(2) = this->stl.stats.min.z;
bb.max(0) = this->stl.stats.max.x;
bb.max(1) = this->stl.stats.max.y;
bb.max(2) = this->stl.stats.max.z;
return bb; return bb;
} }
@ -619,11 +595,8 @@ TriangleMeshSlicer::TriangleMeshSlicer(TriangleMesh* _mesh) :
facets_edges.assign(_mesh->stl.stats.number_of_facets * 3, -1); facets_edges.assign(_mesh->stl.stats.number_of_facets * 3, -1);
v_scaled_shared.assign(_mesh->stl.v_shared, _mesh->stl.v_shared + _mesh->stl.stats.shared_vertices); v_scaled_shared.assign(_mesh->stl.v_shared, _mesh->stl.v_shared + _mesh->stl.stats.shared_vertices);
// Scale the copied vertices. // Scale the copied vertices.
for (int i = 0; i < this->mesh->stl.stats.shared_vertices; ++ i) { for (int i = 0; i < this->mesh->stl.stats.shared_vertices; ++ i)
this->v_scaled_shared[i].x /= float(SCALING_FACTOR); this->v_scaled_shared[i] *= float(1. / SCALING_FACTOR);
this->v_scaled_shared[i].y /= float(SCALING_FACTOR);
this->v_scaled_shared[i].z /= float(SCALING_FACTOR);
}
// Create a mapping from triangle edge into face. // Create a mapping from triangle edge into face.
struct EdgeToFace { struct EdgeToFace {
@ -779,14 +752,14 @@ void TriangleMeshSlicer::_slice_do(size_t facet_idx, std::vector<IntersectionLin
const 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
const float min_z = fminf(facet.vertex[0].z, fminf(facet.vertex[1].z, facet.vertex[2].z)); const float min_z = fminf(facet.vertex[0](2), fminf(facet.vertex[1](2), facet.vertex[2](2)));
const float max_z = fmaxf(facet.vertex[0].z, fmaxf(facet.vertex[1].z, facet.vertex[2].z)); const float max_z = fmaxf(facet.vertex[0](2), fmaxf(facet.vertex[1](2), facet.vertex[2](2)));
#ifdef SLIC3R_DEBUG #ifdef SLIC3R_DEBUG
printf("\n==> FACET %d (%f,%f,%f - %f,%f,%f - %f,%f,%f):\n", facet_idx, printf("\n==> FACET %d (%f,%f,%f - %f,%f,%f - %f,%f,%f):\n", facet_idx,
facet.vertex[0].x, facet.vertex[0].y, facet.vertex[0].z, facet.vertex[0].x, facet.vertex[0].y, facet.vertex[0](2),
facet.vertex[1].x, facet.vertex[1].y, facet.vertex[1].z, facet.vertex[1].x, facet.vertex[1].y, facet.vertex[1](2),
facet.vertex[2].x, facet.vertex[2].y, facet.vertex[2].z); facet.vertex[2].x, facet.vertex[2].y, facet.vertex[2](2));
printf("z: min = %.2f, max = %.2f\n", min_z, max_z); printf("z: min = %.2f, max = %.2f\n", min_z, max_z);
#endif #endif
@ -806,18 +779,18 @@ void TriangleMeshSlicer::_slice_do(size_t facet_idx, std::vector<IntersectionLin
if (il.edge_type == feHorizontal) { if (il.edge_type == feHorizontal) {
// Insert all three edges of the face. // Insert all three edges of the face.
const int *vertices = this->mesh->stl.v_indices[facet_idx].vertex; const int *vertices = this->mesh->stl.v_indices[facet_idx].vertex;
const bool reverse = this->mesh->stl.facet_start[facet_idx].normal.z < 0; const bool reverse = this->mesh->stl.facet_start[facet_idx].normal(2) < 0;
for (int j = 0; j < 3; ++ j) { for (int j = 0; j < 3; ++ j) {
int a_id = vertices[j % 3]; int a_id = vertices[j % 3];
int b_id = vertices[(j+1) % 3]; int b_id = vertices[(j+1) % 3];
if (reverse) if (reverse)
std::swap(a_id, b_id); std::swap(a_id, b_id);
const stl_vertex *a = &this->v_scaled_shared[a_id]; const stl_vertex &a = this->v_scaled_shared[a_id];
const stl_vertex *b = &this->v_scaled_shared[b_id]; const stl_vertex &b = this->v_scaled_shared[b_id];
il.a(0) = a->x; il.a(0) = a(0);
il.a(1) = a->y; il.a(1) = a(1);
il.b(0) = b->x; il.b(0) = b(0);
il.b(1) = b->y; il.b(1) = b(1);
il.a_id = a_id; il.a_id = a_id;
il.b_id = b_id; il.b_id = b_id;
(*lines)[layer_idx].emplace_back(il); (*lines)[layer_idx].emplace_back(il);
@ -863,66 +836,63 @@ bool 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)
int i = (facet.vertex[1].z == min_z) ? 1 : ((facet.vertex[2].z == min_z) ? 2 : 0); int i = (facet.vertex[1](2) == min_z) ? 1 : ((facet.vertex[2](2) == min_z) ? 2 : 0);
for (int j = i; j - i < 3; ++ j) { // loop through facet edges for (int j = i; j - i < 3; ++ j) { // loop through facet edges
int edge_id = this->facets_edges[facet_idx * 3 + (j % 3)]; int edge_id = this->facets_edges[facet_idx * 3 + (j % 3)];
const int *vertices = this->mesh->stl.v_indices[facet_idx].vertex; const int *vertices = this->mesh->stl.v_indices[facet_idx].vertex;
int a_id = vertices[j % 3]; int a_id = vertices[j % 3];
int b_id = vertices[(j+1) % 3]; int b_id = vertices[(j+1) % 3];
const stl_vertex *a = &this->v_scaled_shared[a_id]; const stl_vertex &a = this->v_scaled_shared[a_id];
const stl_vertex *b = &this->v_scaled_shared[b_id]; const stl_vertex &b = this->v_scaled_shared[b_id];
// Is edge or face aligned with the cutting plane? // Is edge or face aligned with the cutting plane?
if (a->z == slice_z && b->z == slice_z) { if (a(2) == slice_z && b(2) == slice_z) {
// Edge is horizontal and belongs to the current layer. // Edge is horizontal and belongs to the current layer.
const stl_vertex &v0 = this->v_scaled_shared[vertices[0]]; const stl_vertex &v0 = this->v_scaled_shared[vertices[0]];
const stl_vertex &v1 = this->v_scaled_shared[vertices[1]]; const stl_vertex &v1 = this->v_scaled_shared[vertices[1]];
const stl_vertex &v2 = this->v_scaled_shared[vertices[2]]; const stl_vertex &v2 = this->v_scaled_shared[vertices[2]];
bool swap = false;
if (min_z == max_z) { if (min_z == max_z) {
// All three vertices are aligned with slice_z. // All three vertices are aligned with slice_z.
line_out->edge_type = feHorizontal; line_out->edge_type = feHorizontal;
if (this->mesh->stl.facet_start[facet_idx].normal.z < 0) { if (this->mesh->stl.facet_start[facet_idx].normal(2) < 0) {
// If normal points downwards this is a bottom horizontal facet so we reverse its point order. // If normal points downwards this is a bottom horizontal facet so we reverse its point order.
std::swap(a, b); swap = true;
std::swap(a_id, b_id);
} }
} else if (v0.z < slice_z || v1.z < slice_z || v2.z < slice_z) { } else if (v0(2) < slice_z || v1(2) < slice_z || v2(2) < slice_z) {
// Two vertices are aligned with the cutting plane, the third vertex is below the cutting plane. // Two vertices are aligned with the cutting plane, the third vertex is below the cutting plane.
line_out->edge_type = feTop; line_out->edge_type = feTop;
std::swap(a, b); swap = true;
std::swap(a_id, b_id);
} else { } else {
// Two vertices are aligned with the cutting plane, the third vertex is above the cutting plane. // Two vertices are aligned with the cutting plane, the third vertex is above the cutting plane.
line_out->edge_type = feBottom; line_out->edge_type = feBottom;
} }
line_out->a(0) = a->x; line_out->a = to_2d(swap ? b : a).cast<coord_t>();
line_out->a(1) = a->y; line_out->b = to_2d(swap ? a : b).cast<coord_t>();
line_out->b(0) = b->x; line_out->a_id = swap ? b_id : a_id;
line_out->b(1) = b->y; line_out->b_id = swap ? a_id : b_id;
line_out->a_id = a_id;
line_out->b_id = b_id;
return true; return true;
} }
if (a->z == slice_z) { if (a(2) == slice_z) {
// Only point a alings with the cutting plane. // Only point a alings with the cutting plane.
points_on_layer[num_points_on_layer ++] = num_points; points_on_layer[num_points_on_layer ++] = num_points;
IntersectionPoint &point = points[num_points ++]; IntersectionPoint &point = points[num_points ++];
point(0) = a->x; point(0) = a(0);
point(1) = a->y; point(1) = a(1);
point.point_id = a_id; point.point_id = a_id;
} else if (b->z == slice_z) { } else if (b(2) == slice_z) {
// Only point b alings with the cutting plane. // Only point b alings with the cutting plane.
points_on_layer[num_points_on_layer ++] = num_points; points_on_layer[num_points_on_layer ++] = num_points;
IntersectionPoint &point = points[num_points ++]; IntersectionPoint &point = points[num_points ++];
point(0) = b->x; point(0) = b(0);
point(1) = b->y; point(1) = b(1);
point.point_id = b_id; point.point_id = b_id;
} else if ((a->z < slice_z && b->z > slice_z) || (b->z < slice_z && a->z > slice_z)) { } else if ((a(2) < slice_z && b(2) > slice_z) || (b(2) < slice_z && a(2) > slice_z)) {
// A general case. The face edge intersects the cutting plane. Calculate the intersection point. // A general case. The face edge intersects the cutting plane. Calculate the intersection point.
IntersectionPoint &point = points[num_points ++]; IntersectionPoint &point = points[num_points ++];
point(0) = b->x + (a->x - b->x) * (slice_z - b->z) / (a->z - b->z); point(0) = b(0) + (a(0) - b(0)) * (slice_z - b(2)) / (a(2) - b(2));
point(1) = b->y + (a->y - b->y) * (slice_z - b->z) / (a->z - b->z); point(1) = b(1) + (a(1) - b(1)) * (slice_z - b(2)) / (a(2) - b(2));
point.edge_id = edge_id; point.edge_id = edge_id;
} }
} }
@ -1389,8 +1359,8 @@ void TriangleMeshSlicer::cut(float z, TriangleMesh* upper, TriangleMesh* lower)
stl_facet* facet = &this->mesh->stl.facet_start[facet_idx]; stl_facet* facet = &this->mesh->stl.facet_start[facet_idx];
// find facet extents // find facet extents
float min_z = std::min(facet->vertex[0].z, std::min(facet->vertex[1].z, facet->vertex[2].z)); float min_z = std::min(facet->vertex[0](2), std::min(facet->vertex[1](2), facet->vertex[2](2)));
float max_z = std::max(facet->vertex[0].z, std::max(facet->vertex[1].z, facet->vertex[2].z)); float max_z = std::max(facet->vertex[0](2), std::max(facet->vertex[1](2), facet->vertex[2](2)));
// intersect facet with cutting plane // intersect facet with cutting plane
IntersectionLine line; IntersectionLine line;
@ -1417,47 +1387,47 @@ void TriangleMeshSlicer::cut(float z, TriangleMesh* upper, TriangleMesh* lower)
// look for the vertex on whose side of the slicing plane there are no other vertices // look for the vertex on whose side of the slicing plane there are no other vertices
int isolated_vertex; int isolated_vertex;
if ( (facet->vertex[0].z > z) == (facet->vertex[1].z > z) ) { if ( (facet->vertex[0](2) > z) == (facet->vertex[1](2) > z) ) {
isolated_vertex = 2; isolated_vertex = 2;
} else if ( (facet->vertex[1].z > z) == (facet->vertex[2].z > z) ) { } else if ( (facet->vertex[1](2) > z) == (facet->vertex[2](2) > z) ) {
isolated_vertex = 0; isolated_vertex = 0;
} else { } else {
isolated_vertex = 1; isolated_vertex = 1;
} }
// get vertices starting from the isolated one // get vertices starting from the isolated one
stl_vertex* v0 = &facet->vertex[isolated_vertex]; const stl_vertex &v0 = facet->vertex[isolated_vertex];
stl_vertex* v1 = &facet->vertex[(isolated_vertex+1) % 3]; const stl_vertex &v1 = facet->vertex[(isolated_vertex+1) % 3];
stl_vertex* v2 = &facet->vertex[(isolated_vertex+2) % 3]; const stl_vertex &v2 = facet->vertex[(isolated_vertex+2) % 3];
// intersect v0-v1 and v2-v0 with cutting plane and make new vertices // intersect v0-v1 and v2-v0 with cutting plane and make new vertices
stl_vertex v0v1, v2v0; stl_vertex v0v1, v2v0;
v0v1.x = v1->x + (v0->x - v1->x) * (z - v1->z) / (v0->z - v1->z); v0v1(0) = v1(0) + (v0(0) - v1(0)) * (z - v1(2)) / (v0(2) - v1(2));
v0v1.y = v1->y + (v0->y - v1->y) * (z - v1->z) / (v0->z - v1->z); v0v1(1) = v1(1) + (v0(1) - v1(1)) * (z - v1(2)) / (v0(2) - v1(2));
v0v1.z = z; v0v1(2) = z;
v2v0.x = v2->x + (v0->x - v2->x) * (z - v2->z) / (v0->z - v2->z); v2v0(0) = v2(0) + (v0(0) - v2(0)) * (z - v2(2)) / (v0(2) - v2(2));
v2v0.y = v2->y + (v0->y - v2->y) * (z - v2->z) / (v0->z - v2->z); v2v0(1) = v2(1) + (v0(1) - v2(1)) * (z - v2(2)) / (v0(2) - v2(2));
v2v0.z = z; v2v0(2) = z;
// build the triangular facet // build the triangular facet
stl_facet triangle; stl_facet triangle;
triangle.normal = facet->normal; triangle.normal = facet->normal;
triangle.vertex[0] = *v0; triangle.vertex[0] = v0;
triangle.vertex[1] = v0v1; triangle.vertex[1] = v0v1;
triangle.vertex[2] = v2v0; triangle.vertex[2] = v2v0;
// build the facets forming a quadrilateral on the other side // build the facets forming a quadrilateral on the other side
stl_facet quadrilateral[2]; stl_facet quadrilateral[2];
quadrilateral[0].normal = facet->normal; quadrilateral[0].normal = facet->normal;
quadrilateral[0].vertex[0] = *v1; quadrilateral[0].vertex[0] = v1;
quadrilateral[0].vertex[1] = *v2; quadrilateral[0].vertex[1] = v2;
quadrilateral[0].vertex[2] = v0v1; quadrilateral[0].vertex[2] = v0v1;
quadrilateral[1].normal = facet->normal; quadrilateral[1].normal = facet->normal;
quadrilateral[1].vertex[0] = *v2; quadrilateral[1].vertex[0] = v2;
quadrilateral[1].vertex[1] = v2v0; quadrilateral[1].vertex[1] = v2v0;
quadrilateral[1].vertex[2] = v0v1; quadrilateral[1].vertex[2] = v0v1;
if (v0->z > z) { if (v0(2) > z) {
if (upper != NULL) stl_add_facet(&upper->stl, &triangle); if (upper != NULL) stl_add_facet(&upper->stl, &triangle);
if (lower != NULL) { if (lower != NULL) {
stl_add_facet(&lower->stl, &quadrilateral[0]); stl_add_facet(&lower->stl, &quadrilateral[0]);
@ -1489,13 +1459,11 @@ void TriangleMeshSlicer::cut(float z, TriangleMesh* upper, TriangleMesh* lower)
Polygon p = *polygon; Polygon p = *polygon;
p.reverse(); p.reverse();
stl_facet facet; stl_facet facet;
facet.normal.x = 0; facet.normal = stl_normal(0, 0, -1.f);
facet.normal.y = 0;
facet.normal.z = -1;
for (size_t i = 0; i <= 2; ++i) { for (size_t i = 0; i <= 2; ++i) {
facet.vertex[i].x = unscale<float>(p.points[i](0)); facet.vertex[i](0) = unscale<float>(p.points[i](0));
facet.vertex[i].y = unscale<float>(p.points[i](1)); facet.vertex[i](1) = unscale<float>(p.points[i](1));
facet.vertex[i].z = z; facet.vertex[i](2) = z;
} }
stl_add_facet(&upper->stl, &facet); stl_add_facet(&upper->stl, &facet);
} }
@ -1515,13 +1483,11 @@ void TriangleMeshSlicer::cut(float z, TriangleMesh* upper, TriangleMesh* lower)
// convert triangles to facets and append them to mesh // convert triangles to facets and append them to mesh
for (Polygons::const_iterator polygon = triangles.begin(); polygon != triangles.end(); ++polygon) { for (Polygons::const_iterator polygon = triangles.begin(); polygon != triangles.end(); ++polygon) {
stl_facet facet; stl_facet facet;
facet.normal.x = 0; facet.normal = stl_normal(0, 0, 1.f);
facet.normal.y = 0;
facet.normal.z = 1;
for (size_t i = 0; i <= 2; ++i) { for (size_t i = 0; i <= 2; ++i) {
facet.vertex[i].x = unscale<float>(polygon->points[i](0)); facet.vertex[i](0) = unscale<float>(polygon->points[i](0));
facet.vertex[i].y = unscale<float>(polygon->points[i](1)); facet.vertex[i](1) = unscale<float>(polygon->points[i](1));
facet.vertex[i].z = z; facet.vertex[i](2) = z;
} }
stl_add_facet(&lower->stl, &facet); stl_add_facet(&lower->stl, &facet);
} }

View File

@ -39,7 +39,7 @@ void GLIndexedVertexArray::load_mesh_flat_shading(const TriangleMesh &mesh)
for (int i = 0; i < mesh.stl.stats.number_of_facets; ++ i) { for (int i = 0; i < mesh.stl.stats.number_of_facets; ++ i) {
const stl_facet &facet = mesh.stl.facet_start[i]; const stl_facet &facet = mesh.stl.facet_start[i];
for (int j = 0; j < 3; ++ j) for (int j = 0; j < 3; ++ j)
this->push_geometry(facet.vertex[j].x, facet.vertex[j].y, facet.vertex[j].z, facet.normal.x, facet.normal.y, facet.normal.z); this->push_geometry(facet.vertex[j](0), facet.vertex[j](1), facet.vertex[j](2), facet.normal(0), facet.normal(1), facet.normal(2));
} }
} }
@ -55,7 +55,7 @@ void GLIndexedVertexArray::load_mesh_full_shading(const TriangleMesh &mesh)
for (int i = 0; i < mesh.stl.stats.number_of_facets; ++i) { for (int i = 0; i < mesh.stl.stats.number_of_facets; ++i) {
const stl_facet &facet = mesh.stl.facet_start[i]; const stl_facet &facet = mesh.stl.facet_start[i];
for (int j = 0; j < 3; ++j) for (int j = 0; j < 3; ++j)
this->push_geometry(facet.vertex[j].x, facet.vertex[j].y, facet.vertex[j].z, facet.normal.x, facet.normal.y, facet.normal.z); this->push_geometry(facet.vertex[j](0), facet.vertex[j](1), facet.vertex[j](2), facet.normal(0), facet.normal(1), facet.normal(2));
this->push_triangle(vertices_count, vertices_count + 1, vertices_count + 2); this->push_triangle(vertices_count, vertices_count + 1, vertices_count + 2);
vertices_count += 3; vertices_count += 3;

View File

@ -60,14 +60,14 @@ TriangleMesh::ReadFromPerl(vertices, facets)
for (int i = 0; i < stl.stats.number_of_facets; i++) { for (int i = 0; i < stl.stats.number_of_facets; i++) {
AV* facet_av = (AV*)SvRV(*av_fetch(facets_av, i, 0)); AV* facet_av = (AV*)SvRV(*av_fetch(facets_av, i, 0));
stl_facet facet; stl_facet facet;
facet.normal.x = 0; facet.normal(0) = 0;
facet.normal.y = 0; facet.normal(1) = 0;
facet.normal.z = 0; facet.normal(2) = 0;
for (unsigned int v = 0; v <= 2; v++) { for (unsigned int v = 0; v <= 2; v++) {
AV* vertex_av = (AV*)SvRV(*av_fetch(vertices_av, SvIV(*av_fetch(facet_av, v, 0)), 0)); AV* vertex_av = (AV*)SvRV(*av_fetch(vertices_av, SvIV(*av_fetch(facet_av, v, 0)), 0));
facet.vertex[v].x = SvNV(*av_fetch(vertex_av, 0, 0)); facet.vertex[v](0) = SvNV(*av_fetch(vertex_av, 0, 0));
facet.vertex[v].y = SvNV(*av_fetch(vertex_av, 1, 0)); facet.vertex[v](1) = SvNV(*av_fetch(vertex_av, 1, 0));
facet.vertex[v].z = SvNV(*av_fetch(vertex_av, 2, 0)); facet.vertex[v](2) = SvNV(*av_fetch(vertex_av, 2, 0));
} }
facet.extra[0] = 0; facet.extra[0] = 0;
facet.extra[1] = 0; facet.extra[1] = 0;
@ -110,9 +110,9 @@ TriangleMesh::vertices()
AV* vertex = newAV(); AV* vertex = newAV();
av_store(vertices, i, newRV_noinc((SV*)vertex)); av_store(vertices, i, newRV_noinc((SV*)vertex));
av_extend(vertex, 2); av_extend(vertex, 2);
av_store(vertex, 0, newSVnv(THIS->stl.v_shared[i].x)); av_store(vertex, 0, newSVnv(THIS->stl.v_shared[i](0)));
av_store(vertex, 1, newSVnv(THIS->stl.v_shared[i].y)); av_store(vertex, 1, newSVnv(THIS->stl.v_shared[i](1)));
av_store(vertex, 2, newSVnv(THIS->stl.v_shared[i].z)); av_store(vertex, 2, newSVnv(THIS->stl.v_shared[i](2)));
} }
RETVAL = newRV_noinc((SV*)vertices); RETVAL = newRV_noinc((SV*)vertices);
@ -155,9 +155,9 @@ TriangleMesh::normals()
AV* facet = newAV(); AV* facet = newAV();
av_store(normals, i, newRV_noinc((SV*)facet)); av_store(normals, i, newRV_noinc((SV*)facet));
av_extend(facet, 2); av_extend(facet, 2);
av_store(facet, 0, newSVnv(THIS->stl.facet_start[i].normal.x)); av_store(facet, 0, newSVnv(THIS->stl.facet_start[i].normal(0)));
av_store(facet, 1, newSVnv(THIS->stl.facet_start[i].normal.y)); av_store(facet, 1, newSVnv(THIS->stl.facet_start[i].normal(1)));
av_store(facet, 2, newSVnv(THIS->stl.facet_start[i].normal.z)); av_store(facet, 2, newSVnv(THIS->stl.facet_start[i].normal(2)));
} }
RETVAL = newRV_noinc((SV*)normals); RETVAL = newRV_noinc((SV*)normals);
@ -169,9 +169,9 @@ TriangleMesh::size()
CODE: CODE:
AV* size = newAV(); AV* size = newAV();
av_extend(size, 2); av_extend(size, 2);
av_store(size, 0, newSVnv(THIS->stl.stats.size.x)); av_store(size, 0, newSVnv(THIS->stl.stats.size(0)));
av_store(size, 1, newSVnv(THIS->stl.stats.size.y)); av_store(size, 1, newSVnv(THIS->stl.stats.size(1)));
av_store(size, 2, newSVnv(THIS->stl.stats.size.z)); av_store(size, 2, newSVnv(THIS->stl.stats.size(2)));
RETVAL = newRV_noinc((SV*)size); RETVAL = newRV_noinc((SV*)size);
OUTPUT: OUTPUT:
RETVAL RETVAL
@ -216,12 +216,12 @@ TriangleMesh::cut(z, upper, lower)
std::vector<double> std::vector<double>
TriangleMesh::bb3() TriangleMesh::bb3()
CODE: CODE:
RETVAL.push_back(THIS->stl.stats.min.x); RETVAL.push_back(THIS->stl.stats.min(0));
RETVAL.push_back(THIS->stl.stats.min.y); RETVAL.push_back(THIS->stl.stats.min(1));
RETVAL.push_back(THIS->stl.stats.max.x); RETVAL.push_back(THIS->stl.stats.max(0));
RETVAL.push_back(THIS->stl.stats.max.y); RETVAL.push_back(THIS->stl.stats.max(1));
RETVAL.push_back(THIS->stl.stats.min.z); RETVAL.push_back(THIS->stl.stats.min(2));
RETVAL.push_back(THIS->stl.stats.max.z); RETVAL.push_back(THIS->stl.stats.max(2));
OUTPUT: OUTPUT:
RETVAL RETVAL