admesh refactoring: separation of the shared vertices / indices
into an indexed_triangle_set structure
This commit is contained in:
parent
65238a89b1
commit
6defabea53
@ -29,19 +29,13 @@
|
|||||||
|
|
||||||
#include "stl.h"
|
#include "stl.h"
|
||||||
|
|
||||||
void stl_invalidate_shared_vertices(stl_file *stl)
|
void stl_generate_shared_vertices(stl_file *stl, indexed_triangle_set &its)
|
||||||
{
|
|
||||||
stl->v_indices.clear();
|
|
||||||
stl->v_shared.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void stl_generate_shared_vertices(stl_file *stl)
|
|
||||||
{
|
{
|
||||||
// 3 indices to vertex per face
|
// 3 indices to vertex per face
|
||||||
stl->v_indices.assign(stl->stats.number_of_facets, v_indices_struct());
|
its.indices.assign(stl->stats.number_of_facets, v_indices_struct());
|
||||||
// Shared vertices (3D coordinates)
|
// Shared vertices (3D coordinates)
|
||||||
stl->v_shared.clear();
|
its.vertices.clear();
|
||||||
stl->v_shared.reserve(stl->stats.number_of_facets / 2);
|
its.vertices.reserve(stl->stats.number_of_facets / 2);
|
||||||
|
|
||||||
// A degenerate mesh may contain loops: Traversing a fan will end up in an endless loop
|
// A degenerate mesh may contain loops: Traversing a fan will end up in an endless loop
|
||||||
// while never reaching the starting face. To avoid these endless loops, traversed faces at each fan traversal
|
// while never reaching the starting face. To avoid these endless loops, traversed faces at each fan traversal
|
||||||
@ -51,11 +45,11 @@ void stl_generate_shared_vertices(stl_file *stl)
|
|||||||
|
|
||||||
for (uint32_t facet_idx = 0; facet_idx < stl->stats.number_of_facets; ++ facet_idx) {
|
for (uint32_t facet_idx = 0; facet_idx < stl->stats.number_of_facets; ++ facet_idx) {
|
||||||
for (int j = 0; j < 3; ++ j) {
|
for (int j = 0; j < 3; ++ j) {
|
||||||
if (stl->v_indices[facet_idx].vertex[j] != -1)
|
if (its.indices[facet_idx].vertex[j] != -1)
|
||||||
// Shared vertex was already assigned.
|
// Shared vertex was already assigned.
|
||||||
continue;
|
continue;
|
||||||
// Create a new shared vertex.
|
// Create a new shared vertex.
|
||||||
stl->v_shared.emplace_back(stl->facet_start[facet_idx].vertex[j]);
|
its.vertices.emplace_back(stl->facet_start[facet_idx].vertex[j]);
|
||||||
// Traverse the fan around the j-th vertex of the i-th face, assign the newly created shared vertex index to all the neighboring triangles in the triangle fan.
|
// Traverse the fan around the j-th vertex of the i-th face, assign the newly created shared vertex index to all the neighboring triangles in the triangle fan.
|
||||||
int facet_in_fan_idx = facet_idx;
|
int facet_in_fan_idx = facet_idx;
|
||||||
bool edge_direction = false;
|
bool edge_direction = false;
|
||||||
@ -89,7 +83,7 @@ void stl_generate_shared_vertices(stl_file *stl)
|
|||||||
next_edge = pivot_vertex;
|
next_edge = pivot_vertex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stl->v_indices[facet_in_fan_idx].vertex[pivot_vertex] = stl->v_shared.size() - 1;
|
its.indices[facet_in_fan_idx].vertex[pivot_vertex] = its.vertices.size() - 1;
|
||||||
fan_traversal_facet_visited[facet_in_fan_idx] = fan_traversal_stamp;
|
fan_traversal_facet_visited[facet_in_fan_idx] = fan_traversal_stamp;
|
||||||
|
|
||||||
// next_edge is an index of the starting vertex of the edge, not an index of the opposite vertex to the edge!
|
// next_edge is an index of the starting vertex of the edge, not an index of the opposite vertex to the edge!
|
||||||
@ -130,7 +124,7 @@ void stl_generate_shared_vertices(stl_file *stl)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool stl_write_off(stl_file *stl, const char *file)
|
bool its_write_off(const indexed_triangle_set &its, const char *file)
|
||||||
{
|
{
|
||||||
/* Open the file */
|
/* Open the file */
|
||||||
FILE *fp = boost::nowide::fopen(file, "w");
|
FILE *fp = boost::nowide::fopen(file, "w");
|
||||||
@ -143,16 +137,16 @@ bool stl_write_off(stl_file *stl, const char *file)
|
|||||||
}
|
}
|
||||||
|
|
||||||
fprintf(fp, "OFF\n");
|
fprintf(fp, "OFF\n");
|
||||||
fprintf(fp, "%d %d 0\n", stl->v_shared.size(), stl->stats.number_of_facets);
|
fprintf(fp, "%d %d 0\n", (int)its.vertices.size(), (int)its.indices.size());
|
||||||
for (int i = 0; i < stl->v_shared.size(); ++ i)
|
for (int i = 0; i < its.vertices.size(); ++ i)
|
||||||
fprintf(fp, "\t%f %f %f\n", stl->v_shared[i](0), stl->v_shared[i](1), stl->v_shared[i](2));
|
fprintf(fp, "\t%f %f %f\n", its.vertices[i](0), its.vertices[i](1), its.vertices[i](2));
|
||||||
for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i)
|
for (uint32_t i = 0; i < its.indices.size(); ++ i)
|
||||||
fprintf(fp, "\t3 %d %d %d\n", stl->v_indices[i].vertex[0], stl->v_indices[i].vertex[1], stl->v_indices[i].vertex[2]);
|
fprintf(fp, "\t3 %d %d %d\n", its.indices[i].vertex[0], its.indices[i].vertex[1], its.indices[i].vertex[2]);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool stl_write_vrml(stl_file *stl, const char *file)
|
bool its_write_vrml(const indexed_triangle_set &its, const char *file)
|
||||||
{
|
{
|
||||||
/* Open the file */
|
/* Open the file */
|
||||||
FILE *fp = boost::nowide::fopen(file, "w");
|
FILE *fp = boost::nowide::fopen(file, "w");
|
||||||
@ -180,16 +174,16 @@ bool stl_write_vrml(stl_file *stl, const char *file)
|
|||||||
fprintf(fp, "\t\t\tpoint [\n");
|
fprintf(fp, "\t\t\tpoint [\n");
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (; i + 1 < stl->v_shared.size(); ++ i)
|
for (; i + 1 < its.vertices.size(); ++ i)
|
||||||
fprintf(fp, "\t\t\t\t%f %f %f,\n", 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", its.vertices[i](0), its.vertices[i](1), its.vertices[i](2));
|
||||||
fprintf(fp, "\t\t\t\t%f %f %f]\n", 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", its.vertices[i](0), its.vertices[i](1), its.vertices[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");
|
||||||
|
|
||||||
for (int i = 0; i + 1 < (int)stl->stats.number_of_facets; ++ i)
|
for (size_t i = 0; i + 1 < its.indices.size(); ++ i)
|
||||||
fprintf(fp, "\t\t\t\t%d, %d, %d, -1,\n", stl->v_indices[i].vertex[0], stl->v_indices[i].vertex[1], stl->v_indices[i].vertex[2]);
|
fprintf(fp, "\t\t\t\t%d, %d, %d, -1,\n", its.indices[i].vertex[0], its.indices[i].vertex[1], its.indices[i].vertex[2]);
|
||||||
fprintf(fp, "\t\t\t\t%d, %d, %d, -1]\n", stl->v_indices[i].vertex[0], stl->v_indices[i].vertex[1], stl->v_indices[i].vertex[2]);
|
fprintf(fp, "\t\t\t\t%d, %d, %d, -1]\n", its.indices[i].vertex[0], its.indices[i].vertex[1], its.indices[i].vertex[2]);
|
||||||
fprintf(fp, "\t\t}\n");
|
fprintf(fp, "\t\t}\n");
|
||||||
fprintf(fp, "\t}\n");
|
fprintf(fp, "\t}\n");
|
||||||
fprintf(fp, "}\n");
|
fprintf(fp, "}\n");
|
||||||
@ -197,7 +191,7 @@ bool stl_write_vrml(stl_file *stl, const char *file)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool stl_write_obj(stl_file *stl, const char *file)
|
bool its_write_obj(const indexed_triangle_set &its, const char *file)
|
||||||
{
|
{
|
||||||
|
|
||||||
FILE *fp = boost::nowide::fopen(file, "w");
|
FILE *fp = boost::nowide::fopen(file, "w");
|
||||||
@ -209,10 +203,65 @@ bool stl_write_obj(stl_file *stl, const char *file)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < stl->v_shared.size(); ++ i)
|
for (size_t i = 0; i < its.vertices.size(); ++ i)
|
||||||
fprintf(fp, "v %f %f %f\n", stl->v_shared[i](0), stl->v_shared[i](1), stl->v_shared[i](2));
|
fprintf(fp, "v %f %f %f\n", its.vertices[i](0), its.vertices[i](1), its.vertices[i](2));
|
||||||
for (uint32_t i = 0; i < stl->stats.number_of_facets; ++ i)
|
for (size_t i = 0; i < its.indices.size(); ++ 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", its.indices[i].vertex[0]+1, its.indices[i].vertex[1]+1, its.indices[i].vertex[2]+1);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Check validity of the mesh, assert on error.
|
||||||
|
bool stl_validate(const stl_file *stl, const indexed_triangle_set &its)
|
||||||
|
{
|
||||||
|
assert(! stl->facet_start.empty());
|
||||||
|
assert(stl->facet_start.size() == stl->stats.number_of_facets);
|
||||||
|
assert(stl->neighbors_start.size() == stl->stats.number_of_facets);
|
||||||
|
assert(stl->facet_start.size() == stl->neighbors_start.size());
|
||||||
|
assert(! stl->neighbors_start.empty());
|
||||||
|
assert((its.indices.empty()) == (its.vertices.empty()));
|
||||||
|
assert(stl->stats.number_of_facets > 0);
|
||||||
|
assert(its.vertices.empty() || its.indices.size() == stl->stats.number_of_facets);
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
// Verify validity of neighborship data.
|
||||||
|
for (int facet_idx = 0; facet_idx < (int)stl->stats.number_of_facets; ++ facet_idx) {
|
||||||
|
const stl_neighbors &nbr = stl->neighbors_start[facet_idx];
|
||||||
|
const int *vertices = (its.indices.empty()) ? nullptr : its.indices[facet_idx].vertex;
|
||||||
|
for (int nbr_idx = 0; nbr_idx < 3; ++ nbr_idx) {
|
||||||
|
int nbr_face = stl->neighbors_start[facet_idx].neighbor[nbr_idx];
|
||||||
|
assert(nbr_face < (int)stl->stats.number_of_facets);
|
||||||
|
if (nbr_face != -1) {
|
||||||
|
int nbr_vnot = nbr.which_vertex_not[nbr_idx];
|
||||||
|
assert(nbr_vnot >= 0 && nbr_vnot < 6);
|
||||||
|
// Neighbor of the neighbor is the original face.
|
||||||
|
assert(stl->neighbors_start[nbr_face].neighbor[(nbr_vnot + 1) % 3] == facet_idx);
|
||||||
|
int vnot_back = stl->neighbors_start[nbr_face].which_vertex_not[(nbr_vnot + 1) % 3];
|
||||||
|
assert(vnot_back >= 0 && vnot_back < 6);
|
||||||
|
assert((nbr_vnot < 3) == (vnot_back < 3));
|
||||||
|
assert(vnot_back % 3 == (nbr_idx + 2) % 3);
|
||||||
|
if (vertices != nullptr) {
|
||||||
|
// Has shared vertices.
|
||||||
|
if (nbr_vnot < 3) {
|
||||||
|
// Faces facet_idx and nbr_face share two vertices accross the common edge. Faces are correctly oriented.
|
||||||
|
assert((its.indices[nbr_face].vertex[(nbr_vnot + 1) % 3] == vertices[(nbr_idx + 1) % 3] && its.indices[nbr_face].vertex[(nbr_vnot + 2) % 3] == vertices[nbr_idx]));
|
||||||
|
} else {
|
||||||
|
// Faces facet_idx and nbr_face share two vertices accross the common edge. Faces are incorrectly oriented, one of them is flipped.
|
||||||
|
assert((its.indices[nbr_face].vertex[(nbr_vnot + 2) % 3] == vertices[(nbr_idx + 1) % 3] && its.indices[nbr_face].vertex[(nbr_vnot + 1) % 3] == vertices[nbr_idx]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* _DEBUG */
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check validity of the mesh, assert on error.
|
||||||
|
bool stl_validate(const stl_file *stl)
|
||||||
|
{
|
||||||
|
indexed_triangle_set its;
|
||||||
|
return stl_validate(stl, its);
|
||||||
|
}
|
||||||
|
@ -130,21 +130,22 @@ struct stl_stats {
|
|||||||
struct stl_file {
|
struct stl_file {
|
||||||
std::vector<stl_facet> facet_start;
|
std::vector<stl_facet> facet_start;
|
||||||
std::vector<stl_neighbors> neighbors_start;
|
std::vector<stl_neighbors> neighbors_start;
|
||||||
// Indexed face set
|
|
||||||
std::vector<v_indices_struct> v_indices;
|
|
||||||
std::vector<stl_vertex> v_shared;
|
|
||||||
// Statistics
|
// Statistics
|
||||||
stl_stats stats;
|
stl_stats stats;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct indexed_triangle_set
|
||||||
|
{
|
||||||
|
void clear() { indices.clear(); vertices.clear(); }
|
||||||
|
std::vector<v_indices_struct> indices;
|
||||||
|
std::vector<stl_vertex> vertices;
|
||||||
|
};
|
||||||
|
|
||||||
extern bool stl_open(stl_file *stl, const char *file);
|
extern bool stl_open(stl_file *stl, const char *file);
|
||||||
extern void stl_stats_out(stl_file *stl, FILE *file, char *input_file);
|
extern void stl_stats_out(stl_file *stl, FILE *file, char *input_file);
|
||||||
extern bool stl_print_neighbors(stl_file *stl, char *file);
|
extern bool stl_print_neighbors(stl_file *stl, char *file);
|
||||||
extern void stl_put_little_int(FILE *fp, int value_in);
|
|
||||||
extern void stl_put_little_float(FILE *fp, float value_in);
|
|
||||||
extern bool stl_write_ascii(stl_file *stl, const char *file, const char *label);
|
extern bool stl_write_ascii(stl_file *stl, const char *file, const char *label);
|
||||||
extern bool stl_write_binary(stl_file *stl, const char *file, const char *label);
|
extern bool stl_write_binary(stl_file *stl, const char *file, const char *label);
|
||||||
extern void stl_write_binary_block(stl_file *stl, FILE *fp);
|
|
||||||
extern void stl_check_facets_exact(stl_file *stl);
|
extern void stl_check_facets_exact(stl_file *stl);
|
||||||
extern void stl_check_facets_nearby(stl_file *stl, float tolerance);
|
extern void stl_check_facets_nearby(stl_file *stl, float tolerance);
|
||||||
extern void stl_remove_unconnected_facets(stl_file *stl);
|
extern void stl_remove_unconnected_facets(stl_file *stl);
|
||||||
@ -219,12 +220,12 @@ inline void stl_transform(stl_file *stl, const Eigen::Matrix<T, 3, 3, Eigen::Don
|
|||||||
stl_get_size(stl);
|
stl_get_size(stl);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern void stl_invalidate_shared_vertices(stl_file *stl);
|
extern void stl_generate_shared_vertices(stl_file *stl, indexed_triangle_set &its);
|
||||||
extern void stl_generate_shared_vertices(stl_file *stl);
|
extern bool its_write_obj(const indexed_triangle_set &its, const char *file);
|
||||||
extern bool stl_write_obj(stl_file *stl, const char *file);
|
extern bool its_write_off(const indexed_triangle_set &its, const char *file);
|
||||||
extern bool stl_write_off(stl_file *stl, const char *file);
|
extern bool its_write_vrml(const indexed_triangle_set &its, const char *file);
|
||||||
|
|
||||||
extern bool stl_write_dxf(stl_file *stl, const char *file, char *label);
|
extern bool stl_write_dxf(stl_file *stl, const char *file, char *label);
|
||||||
extern bool stl_write_vrml(stl_file *stl, const char *file);
|
|
||||||
inline void stl_calculate_normal(stl_normal &normal, stl_facet *facet) {
|
inline void stl_calculate_normal(stl_normal &normal, stl_facet *facet) {
|
||||||
normal = (facet->vertex[1] - facet->vertex[0]).cross(facet->vertex[2] - facet->vertex[0]);
|
normal = (facet->vertex[1] - facet->vertex[0]).cross(facet->vertex[2] - facet->vertex[0]);
|
||||||
}
|
}
|
||||||
@ -251,6 +252,7 @@ extern void stl_reallocate(stl_file *stl);
|
|||||||
extern void stl_add_facet(stl_file *stl, const stl_facet *new_facet);
|
extern void stl_add_facet(stl_file *stl, const stl_facet *new_facet);
|
||||||
|
|
||||||
// Validate the mesh, assert on error.
|
// Validate the mesh, assert on error.
|
||||||
extern bool stl_validate(stl_file *stl);
|
extern bool stl_validate(const stl_file *stl);
|
||||||
|
extern bool stl_validate(const stl_file *stl, const indexed_triangle_set &its);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -253,8 +253,6 @@ void stl_reset(stl_file *stl)
|
|||||||
{
|
{
|
||||||
stl->facet_start.clear();
|
stl->facet_start.clear();
|
||||||
stl->neighbors_start.clear();
|
stl->neighbors_start.clear();
|
||||||
stl->v_indices.clear();
|
|
||||||
stl->v_shared.clear();
|
|
||||||
memset(&stl->stats, 0, sizeof(stl_stats));
|
memset(&stl->stats, 0, sizeof(stl_stats));
|
||||||
stl->stats.volume = -1.0;
|
stl->stats.volume = -1.0;
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,6 @@ void stl_translate(stl_file *stl, float x, float y, float z)
|
|||||||
stl->facet_start[i].vertex[j] += shift;
|
stl->facet_start[i].vertex[j] += shift;
|
||||||
stl->stats.min = new_min;
|
stl->stats.min = new_min;
|
||||||
stl->stats.max += shift;
|
stl->stats.max += shift;
|
||||||
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 */
|
||||||
@ -85,7 +84,6 @@ void stl_translate_relative(stl_file *stl, float x, float y, float z)
|
|||||||
stl->facet_start[i].vertex[j] += shift;
|
stl->facet_start[i].vertex[j] += shift;
|
||||||
stl->stats.min += shift;
|
stl->stats.min += shift;
|
||||||
stl->stats.max += shift;
|
stl->stats.max += shift;
|
||||||
stl_invalidate_shared_vertices(stl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void stl_scale_versor(stl_file *stl, const stl_vertex &versor)
|
void stl_scale_versor(stl_file *stl, const stl_vertex &versor)
|
||||||
@ -103,7 +101,6 @@ void stl_scale_versor(stl_file *stl, const stl_vertex &versor)
|
|||||||
for (int i = 0; i < stl->stats.number_of_facets; ++ i)
|
for (int i = 0; i < stl->stats.number_of_facets; ++ i)
|
||||||
for (int j = 0; j < 3; ++ j)
|
for (int j = 0; j < 3; ++ j)
|
||||||
stl->facet_start[i].vertex[j].array() *= s;
|
stl->facet_start[i].vertex[j].array() *= s;
|
||||||
stl_invalidate_shared_vertices(stl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void calculate_normals(stl_file *stl)
|
static void calculate_normals(stl_file *stl)
|
||||||
@ -414,50 +411,3 @@ All facets connected. No further nearby check necessary.\n");
|
|||||||
stl_verify_neighbors(stl);
|
stl_verify_neighbors(stl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check validity of the mesh, assert on error.
|
|
||||||
bool stl_validate(stl_file *stl)
|
|
||||||
{
|
|
||||||
assert(! stl->facet_start.empty());
|
|
||||||
assert(stl->facet_start.size() == stl->stats.number_of_facets);
|
|
||||||
assert(stl->neighbors_start.size() == stl->stats.number_of_facets);
|
|
||||||
assert(stl->facet_start.size() == stl->neighbors_start.size());
|
|
||||||
assert(! stl->neighbors_start.empty());
|
|
||||||
assert((stl->v_indices.empty()) == (stl->v_shared.empty()));
|
|
||||||
assert(stl->stats.number_of_facets > 0);
|
|
||||||
assert(stl->v_shared.empty() || stl->v_indices.size() == stl->stats.number_of_facets);
|
|
||||||
|
|
||||||
#ifdef _DEBUG
|
|
||||||
// Verify validity of neighborship data.
|
|
||||||
for (int facet_idx = 0; facet_idx < (int)stl->stats.number_of_facets; ++ facet_idx) {
|
|
||||||
const stl_neighbors &nbr = stl->neighbors_start[facet_idx];
|
|
||||||
const int *vertices = (stl->v_indices.empty()) ? nullptr : stl->v_indices[facet_idx].vertex;
|
|
||||||
for (int nbr_idx = 0; nbr_idx < 3; ++ nbr_idx) {
|
|
||||||
int nbr_face = stl->neighbors_start[facet_idx].neighbor[nbr_idx];
|
|
||||||
assert(nbr_face < (int)stl->stats.number_of_facets);
|
|
||||||
if (nbr_face != -1) {
|
|
||||||
int nbr_vnot = nbr.which_vertex_not[nbr_idx];
|
|
||||||
assert(nbr_vnot >= 0 && nbr_vnot < 6);
|
|
||||||
// Neighbor of the neighbor is the original face.
|
|
||||||
assert(stl->neighbors_start[nbr_face].neighbor[(nbr_vnot + 1) % 3] == facet_idx);
|
|
||||||
int vnot_back = stl->neighbors_start[nbr_face].which_vertex_not[(nbr_vnot + 1) % 3];
|
|
||||||
assert(vnot_back >= 0 && vnot_back < 6);
|
|
||||||
assert((nbr_vnot < 3) == (vnot_back < 3));
|
|
||||||
assert(vnot_back % 3 == (nbr_idx + 2) % 3);
|
|
||||||
if (vertices != nullptr) {
|
|
||||||
// Has shared vertices.
|
|
||||||
if (nbr_vnot < 3) {
|
|
||||||
// Faces facet_idx and nbr_face share two vertices accross the common edge. Faces are correctly oriented.
|
|
||||||
assert((stl->v_indices[nbr_face].vertex[(nbr_vnot + 1) % 3] == vertices[(nbr_idx + 1) % 3] && stl->v_indices[nbr_face].vertex[(nbr_vnot + 2) % 3] == vertices[nbr_idx]));
|
|
||||||
} else {
|
|
||||||
// Faces facet_idx and nbr_face share two vertices accross the common edge. Faces are incorrectly oriented, one of them is flipped.
|
|
||||||
assert((stl->v_indices[nbr_face].vertex[(nbr_vnot + 2) % 3] == vertices[(nbr_idx + 1) % 3] && stl->v_indices[nbr_face].vertex[(nbr_vnot + 1) % 3] == vertices[nbr_idx]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif /* _DEBUG */
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
@ -1881,27 +1881,23 @@ namespace Slic3r {
|
|||||||
|
|
||||||
volumes_offsets.insert(VolumeToOffsetsMap::value_type(volume, Offsets(vertices_count))).first;
|
volumes_offsets.insert(VolumeToOffsetsMap::value_type(volume, Offsets(vertices_count))).first;
|
||||||
|
|
||||||
if (!volume->mesh.repaired)
|
volume->mesh.require_shared_vertices();
|
||||||
volume->mesh.repair();
|
|
||||||
|
|
||||||
stl_file& stl = volume->mesh.stl;
|
const indexed_triangle_set &its = volume->mesh.its;
|
||||||
if (stl.v_shared.empty())
|
if (its.vertices.empty())
|
||||||
stl_generate_shared_vertices(&stl);
|
|
||||||
|
|
||||||
if (stl.v_shared.empty())
|
|
||||||
{
|
{
|
||||||
add_error("Found invalid mesh");
|
add_error("Found invalid mesh");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
vertices_count += stl.v_shared.size();
|
vertices_count += its.vertices.size();
|
||||||
|
|
||||||
const Transform3d& matrix = volume->get_matrix();
|
const Transform3d& matrix = volume->get_matrix();
|
||||||
|
|
||||||
for (size_t i = 0; i < stl.v_shared.size(); ++i)
|
for (size_t i = 0; i < its.vertices.size(); ++i)
|
||||||
{
|
{
|
||||||
stream << " <" << VERTEX_TAG << " ";
|
stream << " <" << VERTEX_TAG << " ";
|
||||||
Vec3f v = (matrix * stl.v_shared[i].cast<double>()).cast<float>();
|
Vec3f v = (matrix * its.vertices[i].cast<double>()).cast<float>();
|
||||||
stream << "x=\"" << v(0) << "\" ";
|
stream << "x=\"" << v(0) << "\" ";
|
||||||
stream << "y=\"" << v(1) << "\" ";
|
stream << "y=\"" << v(1) << "\" ";
|
||||||
stream << "z=\"" << v(2) << "\" />\n";
|
stream << "z=\"" << v(2) << "\" />\n";
|
||||||
@ -1920,19 +1916,19 @@ namespace Slic3r {
|
|||||||
VolumeToOffsetsMap::iterator volume_it = volumes_offsets.find(volume);
|
VolumeToOffsetsMap::iterator volume_it = volumes_offsets.find(volume);
|
||||||
assert(volume_it != volumes_offsets.end());
|
assert(volume_it != volumes_offsets.end());
|
||||||
|
|
||||||
stl_file& stl = volume->mesh.stl;
|
const indexed_triangle_set &its = volume->mesh.its;
|
||||||
|
|
||||||
// updates triangle offsets
|
// updates triangle offsets
|
||||||
volume_it->second.first_triangle_id = triangles_count;
|
volume_it->second.first_triangle_id = triangles_count;
|
||||||
triangles_count += stl.stats.number_of_facets;
|
triangles_count += its.indices.size();
|
||||||
volume_it->second.last_triangle_id = triangles_count - 1;
|
volume_it->second.last_triangle_id = triangles_count - 1;
|
||||||
|
|
||||||
for (uint32_t i = 0; i < stl.stats.number_of_facets; ++i)
|
for (size_t i = 0; i < its.indices.size(); ++ i)
|
||||||
{
|
{
|
||||||
stream << " <" << TRIANGLE_TAG << " ";
|
stream << " <" << TRIANGLE_TAG << " ";
|
||||||
for (int j = 0; j < 3; ++j)
|
for (int j = 0; j < 3; ++j)
|
||||||
{
|
{
|
||||||
stream << "v" << j + 1 << "=\"" << stl.v_indices[i].vertex[j] + volume_it->second.first_vertex_id << "\" ";
|
stream << "v" << j + 1 << "=\"" << its.indices[i].vertex[j] + volume_it->second.first_vertex_id << "\" ";
|
||||||
}
|
}
|
||||||
stream << "/>\n";
|
stream << "/>\n";
|
||||||
}
|
}
|
||||||
|
@ -925,21 +925,20 @@ bool store_amf(const char *path, Model *model, const DynamicPrintConfig *config)
|
|||||||
vertices_offsets.push_back(num_vertices);
|
vertices_offsets.push_back(num_vertices);
|
||||||
if (! volume->mesh.repaired)
|
if (! volume->mesh.repaired)
|
||||||
throw std::runtime_error("store_amf() requires repair()");
|
throw std::runtime_error("store_amf() requires repair()");
|
||||||
auto &stl = volume->mesh.stl;
|
volume->mesh.require_shared_vertices();
|
||||||
if (stl.v_shared.empty())
|
const indexed_triangle_set &its = volume->mesh.its;
|
||||||
stl_generate_shared_vertices(&stl);
|
|
||||||
const Transform3d& matrix = volume->get_matrix();
|
const Transform3d& matrix = volume->get_matrix();
|
||||||
for (size_t i = 0; i < stl.v_shared.size(); ++i) {
|
for (size_t i = 0; i < its.vertices.size(); ++i) {
|
||||||
stream << " <vertex>\n";
|
stream << " <vertex>\n";
|
||||||
stream << " <coordinates>\n";
|
stream << " <coordinates>\n";
|
||||||
Vec3f v = (matrix * stl.v_shared[i].cast<double>()).cast<float>();
|
Vec3f v = (matrix * its.vertices[i].cast<double>()).cast<float>();
|
||||||
stream << " <x>" << v(0) << "</x>\n";
|
stream << " <x>" << v(0) << "</x>\n";
|
||||||
stream << " <y>" << v(1) << "</y>\n";
|
stream << " <y>" << v(1) << "</y>\n";
|
||||||
stream << " <z>" << v(2) << "</z>\n";
|
stream << " <z>" << v(2) << "</z>\n";
|
||||||
stream << " </coordinates>\n";
|
stream << " </coordinates>\n";
|
||||||
stream << " </vertex>\n";
|
stream << " </vertex>\n";
|
||||||
}
|
}
|
||||||
num_vertices += stl.v_shared.size();
|
num_vertices += its.vertices.size();
|
||||||
}
|
}
|
||||||
stream << " </vertices>\n";
|
stream << " </vertices>\n";
|
||||||
for (size_t i_volume = 0; i_volume < object->volumes.size(); ++i_volume) {
|
for (size_t i_volume = 0; i_volume < object->volumes.size(); ++i_volume) {
|
||||||
@ -956,10 +955,10 @@ bool store_amf(const char *path, Model *model, const DynamicPrintConfig *config)
|
|||||||
if (volume->is_modifier())
|
if (volume->is_modifier())
|
||||||
stream << " <metadata type=\"slic3r.modifier\">1</metadata>\n";
|
stream << " <metadata type=\"slic3r.modifier\">1</metadata>\n";
|
||||||
stream << " <metadata type=\"slic3r.volume_type\">" << ModelVolume::type_to_string(volume->type()) << "</metadata>\n";
|
stream << " <metadata type=\"slic3r.volume_type\">" << ModelVolume::type_to_string(volume->type()) << "</metadata>\n";
|
||||||
for (int i = 0; i < (int)volume->mesh.stl.stats.number_of_facets; ++i) {
|
for (size_t i = 0; i < (int)volume->mesh.its.indices.size(); ++i) {
|
||||||
stream << " <triangle>\n";
|
stream << " <triangle>\n";
|
||||||
for (int j = 0; j < 3; ++j)
|
for (int j = 0; j < 3; ++j)
|
||||||
stream << " <v" << j + 1 << ">" << volume->mesh.stl.v_indices[i].vertex[j] + vertices_offset << "</v" << j + 1 << ">\n";
|
stream << " <v" << j + 1 << ">" << volume->mesh.its.indices[i].vertex[j] + vertices_offset << "</v" << j + 1 << ">\n";
|
||||||
stream << " </triangle>\n";
|
stream << " </triangle>\n";
|
||||||
}
|
}
|
||||||
stream << " </volume>\n";
|
stream << " </volume>\n";
|
||||||
|
@ -908,10 +908,11 @@ Polygon ModelObject::convex_hull_2d(const Transform3d &trafo_instance) const
|
|||||||
Points pts;
|
Points pts;
|
||||||
for (const ModelVolume *v : this->volumes)
|
for (const ModelVolume *v : this->volumes)
|
||||||
if (v->is_model_part()) {
|
if (v->is_model_part()) {
|
||||||
const stl_file &stl = v->mesh.stl;
|
|
||||||
Transform3d trafo = trafo_instance * v->get_matrix();
|
Transform3d trafo = trafo_instance * v->get_matrix();
|
||||||
if (stl.v_shared.empty()) {
|
const indexed_triangle_set &its = v->mesh.its;
|
||||||
|
if (its.vertices.empty()) {
|
||||||
// Using the STL faces.
|
// Using the STL faces.
|
||||||
|
const stl_file& stl = v->mesh.stl;
|
||||||
for (const stl_facet &facet : stl.facet_start)
|
for (const stl_facet &facet : stl.facet_start)
|
||||||
for (size_t j = 0; j < 3; ++ j) {
|
for (size_t j = 0; j < 3; ++ j) {
|
||||||
Vec3d p = trafo * facet.vertex[j].cast<double>();
|
Vec3d p = trafo * facet.vertex[j].cast<double>();
|
||||||
@ -919,8 +920,8 @@ Polygon ModelObject::convex_hull_2d(const Transform3d &trafo_instance) const
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Using the shared vertices should be a bit quicker than using the STL faces.
|
// Using the shared vertices should be a bit quicker than using the STL faces.
|
||||||
for (size_t i = 0; i < stl.v_shared.size(); ++ i) {
|
for (size_t i = 0; i < its.vertices.size(); ++ i) {
|
||||||
Vec3d p = trafo * stl.v_shared[i].cast<double>();
|
Vec3d p = trafo * its.vertices[i].cast<double>();
|
||||||
pts.emplace_back(coord_t(scale_(p.x())), coord_t(scale_(p.y())));
|
pts.emplace_back(coord_t(scale_(p.x())), coord_t(scale_(p.y())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -238,20 +238,20 @@ bool TriangleMesh::needed_repair() const
|
|||||||
|
|
||||||
void TriangleMesh::WriteOBJFile(const char* output_file)
|
void TriangleMesh::WriteOBJFile(const char* output_file)
|
||||||
{
|
{
|
||||||
stl_generate_shared_vertices(&stl);
|
stl_generate_shared_vertices(&stl, its);
|
||||||
stl_write_obj(&stl, output_file);
|
its_write_obj(its, output_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TriangleMesh::scale(float factor)
|
void TriangleMesh::scale(float factor)
|
||||||
{
|
{
|
||||||
stl_scale(&(this->stl), factor);
|
stl_scale(&(this->stl), factor);
|
||||||
stl_invalidate_shared_vertices(&this->stl);
|
this->its.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TriangleMesh::scale(const Vec3d &versor)
|
void TriangleMesh::scale(const Vec3d &versor)
|
||||||
{
|
{
|
||||||
stl_scale_versor(&this->stl, versor.cast<float>());
|
stl_scale_versor(&this->stl, versor.cast<float>());
|
||||||
stl_invalidate_shared_vertices(&this->stl);
|
this->its.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TriangleMesh::translate(float x, float y, float z)
|
void TriangleMesh::translate(float x, float y, float z)
|
||||||
@ -259,7 +259,7 @@ void TriangleMesh::translate(float x, float y, float z)
|
|||||||
if (x == 0.f && y == 0.f && z == 0.f)
|
if (x == 0.f && y == 0.f && z == 0.f)
|
||||||
return;
|
return;
|
||||||
stl_translate_relative(&(this->stl), x, y, z);
|
stl_translate_relative(&(this->stl), x, y, z);
|
||||||
stl_invalidate_shared_vertices(&this->stl);
|
this->its.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TriangleMesh::translate(const Vec3f &displacement)
|
void TriangleMesh::translate(const Vec3f &displacement)
|
||||||
@ -282,7 +282,7 @@ void TriangleMesh::rotate(float angle, const Axis &axis)
|
|||||||
} else if (axis == Z) {
|
} else if (axis == Z) {
|
||||||
stl_rotate_z(&(this->stl), angle);
|
stl_rotate_z(&(this->stl), angle);
|
||||||
}
|
}
|
||||||
stl_invalidate_shared_vertices(&this->stl);
|
this->its.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TriangleMesh::rotate(float angle, const Vec3d& axis)
|
void TriangleMesh::rotate(float angle, const Vec3d& axis)
|
||||||
@ -305,13 +305,13 @@ void TriangleMesh::mirror(const Axis &axis)
|
|||||||
} else if (axis == Z) {
|
} else if (axis == Z) {
|
||||||
stl_mirror_xy(&this->stl);
|
stl_mirror_xy(&this->stl);
|
||||||
}
|
}
|
||||||
stl_invalidate_shared_vertices(&this->stl);
|
this->its.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TriangleMesh::transform(const Transform3d& t, bool fix_left_handed)
|
void TriangleMesh::transform(const Transform3d& t, bool fix_left_handed)
|
||||||
{
|
{
|
||||||
stl_transform(&stl, t);
|
stl_transform(&stl, t);
|
||||||
stl_invalidate_shared_vertices(&stl);
|
this->its.clear();
|
||||||
if (fix_left_handed && t.matrix().block(0, 0, 3, 3).determinant() < 0.) {
|
if (fix_left_handed && t.matrix().block(0, 0, 3, 3).determinant() < 0.) {
|
||||||
// Left handed transformation is being applied. It is a good idea to flip the faces and their normals.
|
// Left handed transformation is being applied. It is a good idea to flip the faces and their normals.
|
||||||
this->repair();
|
this->repair();
|
||||||
@ -322,7 +322,7 @@ void TriangleMesh::transform(const Transform3d& t, bool fix_left_handed)
|
|||||||
void TriangleMesh::transform(const Matrix3d& m, bool fix_left_handed)
|
void TriangleMesh::transform(const Matrix3d& m, bool fix_left_handed)
|
||||||
{
|
{
|
||||||
stl_transform(&stl, m);
|
stl_transform(&stl, m);
|
||||||
stl_invalidate_shared_vertices(&stl);
|
this->its.clear();
|
||||||
if (fix_left_handed && m.determinant() < 0.) {
|
if (fix_left_handed && m.determinant() < 0.) {
|
||||||
// Left handed transformation is being applied. It is a good idea to flip the faces and their normals.
|
// Left handed transformation is being applied. It is a good idea to flip the faces and their normals.
|
||||||
this->repair();
|
this->repair();
|
||||||
@ -443,7 +443,7 @@ void TriangleMesh::merge(const TriangleMesh &mesh)
|
|||||||
{
|
{
|
||||||
// reset stats and metadata
|
// reset stats and metadata
|
||||||
int number_of_facets = this->stl.stats.number_of_facets;
|
int number_of_facets = this->stl.stats.number_of_facets;
|
||||||
stl_invalidate_shared_vertices(&this->stl);
|
this->its.clear();
|
||||||
this->repaired = false;
|
this->repaired = false;
|
||||||
|
|
||||||
// update facet count and allocate more memory
|
// update facet count and allocate more memory
|
||||||
@ -484,9 +484,9 @@ Polygon TriangleMesh::convex_hull()
|
|||||||
{
|
{
|
||||||
this->require_shared_vertices();
|
this->require_shared_vertices();
|
||||||
Points pp;
|
Points pp;
|
||||||
pp.reserve(this->stl.v_shared.size());
|
pp.reserve(this->its.vertices.size());
|
||||||
for (size_t i = 0; i < this->stl.v_shared.size(); ++ i) {
|
for (size_t i = 0; i < this->its.vertices.size(); ++ i) {
|
||||||
const stl_vertex &v = this->stl.v_shared[i];
|
const stl_vertex &v = this->its.vertices[i];
|
||||||
pp.emplace_back(Point::new_scale(v(0), v(1)));
|
pp.emplace_back(Point::new_scale(v(0), v(1)));
|
||||||
}
|
}
|
||||||
return Slic3r::Geometry::convex_hull(pp);
|
return Slic3r::Geometry::convex_hull(pp);
|
||||||
@ -504,14 +504,14 @@ BoundingBoxf3 TriangleMesh::bounding_box() const
|
|||||||
BoundingBoxf3 TriangleMesh::transformed_bounding_box(const Transform3d &trafo) const
|
BoundingBoxf3 TriangleMesh::transformed_bounding_box(const Transform3d &trafo) const
|
||||||
{
|
{
|
||||||
BoundingBoxf3 bbox;
|
BoundingBoxf3 bbox;
|
||||||
if (stl.v_shared.empty()) {
|
if (this->its.vertices.empty()) {
|
||||||
// Using the STL faces.
|
// Using the STL faces.
|
||||||
for (const stl_facet &facet : this->stl.facet_start)
|
for (const stl_facet &facet : this->stl.facet_start)
|
||||||
for (size_t j = 0; j < 3; ++ j)
|
for (size_t j = 0; j < 3; ++ j)
|
||||||
bbox.merge(trafo * facet.vertex[j].cast<double>());
|
bbox.merge(trafo * facet.vertex[j].cast<double>());
|
||||||
} else {
|
} else {
|
||||||
// Using the shared vertices should be a bit quicker than using the STL faces.
|
// Using the shared vertices should be a bit quicker than using the STL faces.
|
||||||
for (const stl_vertex &v : this->stl.v_shared)
|
for (const stl_vertex &v : this->its.vertices)
|
||||||
bbox.merge(trafo * v.cast<double>());
|
bbox.merge(trafo * v.cast<double>());
|
||||||
}
|
}
|
||||||
return bbox;
|
return bbox;
|
||||||
@ -576,11 +576,11 @@ void TriangleMesh::require_shared_vertices()
|
|||||||
assert(stl_validate(&this->stl));
|
assert(stl_validate(&this->stl));
|
||||||
if (! this->repaired)
|
if (! this->repaired)
|
||||||
this->repair();
|
this->repair();
|
||||||
if (this->stl.v_shared.empty()) {
|
if (this->its.vertices.empty()) {
|
||||||
BOOST_LOG_TRIVIAL(trace) << "TriangleMeshSlicer::require_shared_vertices - stl_generate_shared_vertices";
|
BOOST_LOG_TRIVIAL(trace) << "TriangleMeshSlicer::require_shared_vertices - stl_generate_shared_vertices";
|
||||||
stl_generate_shared_vertices(&(this->stl));
|
stl_generate_shared_vertices(&this->stl, this->its);
|
||||||
}
|
}
|
||||||
assert(stl_validate(&this->stl));
|
assert(stl_validate(&this->stl, this->its));
|
||||||
BOOST_LOG_TRIVIAL(trace) << "TriangleMeshSlicer::require_shared_vertices - end";
|
BOOST_LOG_TRIVIAL(trace) << "TriangleMeshSlicer::require_shared_vertices - end";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -592,9 +592,9 @@ void TriangleMeshSlicer::init(const TriangleMesh *_mesh, throw_on_cancel_callbac
|
|||||||
|
|
||||||
throw_on_cancel();
|
throw_on_cancel();
|
||||||
facets_edges.assign(_mesh->stl.stats.number_of_facets * 3, -1);
|
facets_edges.assign(_mesh->stl.stats.number_of_facets * 3, -1);
|
||||||
v_scaled_shared.assign(_mesh->stl.v_shared.size(), stl_vertex());
|
v_scaled_shared.assign(_mesh->its.vertices.size(), stl_vertex());
|
||||||
for (size_t i = 0; i < v_scaled_shared.size(); ++ i)
|
for (size_t i = 0; i < v_scaled_shared.size(); ++ i)
|
||||||
this->v_scaled_shared[i] = _mesh->stl.v_shared[i] / float(SCALING_FACTOR);
|
this->v_scaled_shared[i] = _mesh->its.vertices[i] / float(SCALING_FACTOR);
|
||||||
|
|
||||||
// Create a mapping from triangle edge into face.
|
// Create a mapping from triangle edge into face.
|
||||||
struct EdgeToFace {
|
struct EdgeToFace {
|
||||||
@ -614,8 +614,8 @@ void TriangleMeshSlicer::init(const TriangleMesh *_mesh, throw_on_cancel_callbac
|
|||||||
for (uint32_t facet_idx = 0; facet_idx < this->mesh->stl.stats.number_of_facets; ++ facet_idx)
|
for (uint32_t facet_idx = 0; facet_idx < this->mesh->stl.stats.number_of_facets; ++ facet_idx)
|
||||||
for (int i = 0; i < 3; ++ i) {
|
for (int i = 0; i < 3; ++ i) {
|
||||||
EdgeToFace &e2f = edges_map[facet_idx*3+i];
|
EdgeToFace &e2f = edges_map[facet_idx*3+i];
|
||||||
e2f.vertex_low = this->mesh->stl.v_indices[facet_idx].vertex[i];
|
e2f.vertex_low = this->mesh->its.indices[facet_idx].vertex[i];
|
||||||
e2f.vertex_high = this->mesh->stl.v_indices[facet_idx].vertex[(i + 1) % 3];
|
e2f.vertex_high = this->mesh->its.indices[facet_idx].vertex[(i + 1) % 3];
|
||||||
e2f.face = facet_idx;
|
e2f.face = facet_idx;
|
||||||
// 1 based indexing, to be always strictly positive.
|
// 1 based indexing, to be always strictly positive.
|
||||||
e2f.face_edge = i + 1;
|
e2f.face_edge = i + 1;
|
||||||
@ -852,7 +852,7 @@ TriangleMeshSlicer::FacetSliceType TriangleMeshSlicer::slice_facet(
|
|||||||
// Reorder vertices so that the first one is the one with lowest Z.
|
// Reorder vertices so that the first one is the one with lowest Z.
|
||||||
// This is needed to get all intersection lines in a consistent order
|
// This is needed to get all intersection lines in a consistent order
|
||||||
// (external on the right of the line)
|
// (external on the right of the line)
|
||||||
const int *vertices = this->mesh->stl.v_indices[facet_idx].vertex;
|
const int *vertices = this->mesh->its.indices[facet_idx].vertex;
|
||||||
int i = (facet.vertex[1].z() == min_z) ? 1 : ((facet.vertex[2].z() == min_z) ? 2 : 0);
|
int i = (facet.vertex[1].z() == min_z) ? 1 : ((facet.vertex[2].z() == min_z) ? 2 : 0);
|
||||||
|
|
||||||
// These are used only if the cut plane is tilted:
|
// These are used only if the cut plane is tilted:
|
||||||
|
@ -69,12 +69,13 @@ public:
|
|||||||
void reset_repair_stats();
|
void reset_repair_stats();
|
||||||
bool needed_repair() const;
|
bool needed_repair() const;
|
||||||
void require_shared_vertices();
|
void require_shared_vertices();
|
||||||
bool has_shared_vertices() const { return ! stl.v_shared.empty(); }
|
bool has_shared_vertices() const { return ! this->its.vertices.empty(); }
|
||||||
size_t facets_count() const { return this->stl.stats.number_of_facets; }
|
size_t facets_count() const { return this->stl.stats.number_of_facets; }
|
||||||
bool empty() const { return this->facets_count() == 0; }
|
bool empty() const { return this->facets_count() == 0; }
|
||||||
bool is_splittable() const;
|
bool is_splittable() const;
|
||||||
|
|
||||||
stl_file stl;
|
stl_file stl;
|
||||||
|
indexed_triangle_set its;
|
||||||
bool repaired;
|
bool repaired;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -781,7 +781,7 @@ void PresetBundle::load_config_file_config(const std::string &name_or_path, bool
|
|||||||
if (i == 0)
|
if (i == 0)
|
||||||
suffix[0] = 0;
|
suffix[0] = 0;
|
||||||
else
|
else
|
||||||
sprintf(suffix, "%d", i);
|
sprintf(suffix, "%d", (int)i);
|
||||||
std::string new_name = name + suffix;
|
std::string new_name = name + suffix;
|
||||||
loaded = &this->filaments.load_preset(this->filaments.path_from_name(new_name),
|
loaded = &this->filaments.load_preset(this->filaments.path_from_name(new_name),
|
||||||
new_name, std::move(cfg), i == 0);
|
new_name, std::move(cfg), i == 0);
|
||||||
@ -1379,7 +1379,7 @@ void PresetBundle::export_configbundle(const std::string &path, bool export_syst
|
|||||||
for (size_t i = 0; i < this->filament_presets.size(); ++ i) {
|
for (size_t i = 0; i < this->filament_presets.size(); ++ i) {
|
||||||
char suffix[64];
|
char suffix[64];
|
||||||
if (i > 0)
|
if (i > 0)
|
||||||
sprintf(suffix, "_%d", i);
|
sprintf(suffix, "_%d", (int)i);
|
||||||
else
|
else
|
||||||
suffix[0] = 0;
|
suffix[0] = 0;
|
||||||
c << "filament" << suffix << " = " << this->filament_presets[i] << std::endl;
|
c << "filament" << suffix << " = " << this->filament_presets[i] << std::endl;
|
||||||
|
@ -98,20 +98,18 @@ SV*
|
|||||||
TriangleMesh::vertices()
|
TriangleMesh::vertices()
|
||||||
CODE:
|
CODE:
|
||||||
if (!THIS->repaired) CONFESS("vertices() requires repair()");
|
if (!THIS->repaired) CONFESS("vertices() requires repair()");
|
||||||
|
THIS->require_shared_vertices();
|
||||||
if (THIS->stl.v_shared.empty())
|
|
||||||
stl_generate_shared_vertices(&(THIS->stl));
|
|
||||||
|
|
||||||
// vertices
|
// vertices
|
||||||
AV* vertices = newAV();
|
AV* vertices = newAV();
|
||||||
av_extend(vertices, THIS->stl.v_shared.size());
|
av_extend(vertices, THIS->its.vertices.size());
|
||||||
for (size_t i = 0; i < THIS->stl.v_shared.size(); i++) {
|
for (size_t i = 0; i < THIS->its.vertices.size(); i++) {
|
||||||
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](0)));
|
av_store(vertex, 0, newSVnv(THIS->its.vertices[i](0)));
|
||||||
av_store(vertex, 1, newSVnv(THIS->stl.v_shared[i](1)));
|
av_store(vertex, 1, newSVnv(THIS->its.vertices[i](1)));
|
||||||
av_store(vertex, 2, newSVnv(THIS->stl.v_shared[i](2)));
|
av_store(vertex, 2, newSVnv(THIS->its.vertices[i](2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
RETVAL = newRV_noinc((SV*)vertices);
|
RETVAL = newRV_noinc((SV*)vertices);
|
||||||
@ -122,9 +120,7 @@ SV*
|
|||||||
TriangleMesh::facets()
|
TriangleMesh::facets()
|
||||||
CODE:
|
CODE:
|
||||||
if (!THIS->repaired) CONFESS("facets() requires repair()");
|
if (!THIS->repaired) CONFESS("facets() requires repair()");
|
||||||
|
THIS->require_shared_vertices();
|
||||||
if (THIS->stl.v_shared.empty())
|
|
||||||
stl_generate_shared_vertices(&(THIS->stl));
|
|
||||||
|
|
||||||
// facets
|
// facets
|
||||||
AV* facets = newAV();
|
AV* facets = newAV();
|
||||||
@ -133,9 +129,9 @@ TriangleMesh::facets()
|
|||||||
AV* facet = newAV();
|
AV* facet = newAV();
|
||||||
av_store(facets, i, newRV_noinc((SV*)facet));
|
av_store(facets, i, newRV_noinc((SV*)facet));
|
||||||
av_extend(facet, 2);
|
av_extend(facet, 2);
|
||||||
av_store(facet, 0, newSVnv(THIS->stl.v_indices[i].vertex[0]));
|
av_store(facet, 0, newSVnv(THIS->its.indices[i].vertex[0]));
|
||||||
av_store(facet, 1, newSVnv(THIS->stl.v_indices[i].vertex[1]));
|
av_store(facet, 1, newSVnv(THIS->its.indices[i].vertex[1]));
|
||||||
av_store(facet, 2, newSVnv(THIS->stl.v_indices[i].vertex[2]));
|
av_store(facet, 2, newSVnv(THIS->its.indices[i].vertex[2]));
|
||||||
}
|
}
|
||||||
|
|
||||||
RETVAL = newRV_noinc((SV*)facets);
|
RETVAL = newRV_noinc((SV*)facets);
|
||||||
|
Loading…
Reference in New Issue
Block a user