d ..
This commit is contained in:
parent
ac72cd779f
commit
6829704475
@ -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;
|
||||||
|
@ -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];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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");
|
||||||
|
@ -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
|
||||||
|
@ -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,
|
||||||
|
@ -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";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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";
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -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));
|
||||||
|
@ -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)) {
|
||||||
|
@ -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 ¤t_facet)
|
float SlicingAdaptive::cusp_height(float z, float cusp_value, int ¤t_facet)
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user