Prusa Slicer 2.6.0
Loading...
Searching...
No Matches
shared.cpp File Reference
#include <stdlib.h>
#include <string.h>
#include <vector>
#include <boost/log/trivial.hpp>
#include <boost/nowide/cstdio.hpp>
#include "stl.h"
#include "libslic3r/LocalesUtils.hpp"
+ Include dependency graph for shared.cpp:

Go to the source code of this file.

Functions

void stl_generate_shared_vertices (stl_file *stl, indexed_triangle_set &its)
 
bool its_write_off (const indexed_triangle_set &its, const char *file)
 
bool its_write_vrml (const indexed_triangle_set &its, const char *file)
 
bool its_write_obj (const indexed_triangle_set &its, const char *file)
 
bool its_write_obj (const indexed_triangle_set &its, const std::vector< obj_color > &color, const char *file)
 write idexed triangle set into obj file with color
 
bool stl_validate (const stl_file *stl, const indexed_triangle_set &its)
 
bool stl_validate (const stl_file *stl)
 

Function Documentation

◆ its_write_obj() [1/2]

bool its_write_obj ( const indexed_triangle_set its,
const char *  file 
)
194{
195 Slic3r::CNumericLocalesSetter locales_setter;
196 FILE *fp = boost::nowide::fopen(file, "w");
197 if (fp == nullptr) {
198 BOOST_LOG_TRIVIAL(error) << "stl_write_obj: Couldn't open " << file << " for writing";
199 return false;
200 }
201
202 for (size_t i = 0; i < its.vertices.size(); ++ i)
203 fprintf(fp, "v %f %f %f\n", its.vertices[i](0), its.vertices[i](1), its.vertices[i](2));
204 for (size_t i = 0; i < its.indices.size(); ++ i)
205 fprintf(fp, "f %d %d %d\n", its.indices[i][0]+1, its.indices[i][1]+1, its.indices[i][2]+1);
206 fclose(fp);
207 return true;
208}
Definition LocalesUtils.hpp:18
std::vector< stl_vertex > vertices
Definition stl.h:165
std::vector< stl_triangle_vertex_indices > indices
Definition stl.h:164
static char error[256]
Definition tga.cpp:50

References error, indexed_triangle_set::indices, and indexed_triangle_set::vertices.

Referenced by Slic3r::its_store_triangle_to_obj(), Slic3r::its_store_triangles_to_obj(), Slic3r::mmu_segmentation_top_and_bottom_layers(), and Slic3r::TriangleMesh::WriteOBJFile().

+ Here is the caller graph for this function:

◆ its_write_obj() [2/2]

bool its_write_obj ( const indexed_triangle_set its,
const std::vector< obj_color > &  color,
const char *  file 
)

write idexed triangle set into obj file with color

Parameters
itsinput model
colorcolor of stored model
filedefine place to store
Returns
True on success otherwise FALSE
211{
212 Slic3r::CNumericLocalesSetter locales_setter;
213 FILE* fp = boost::nowide::fopen(file, "w");
214 if (fp == nullptr) {
215 BOOST_LOG_TRIVIAL(error) << "stl_write_obj: Couldn't open " << file << " for writing";
216 return false;
217 }
218
219 for (size_t i = 0; i < its.vertices.size(); ++i)
220 fprintf(fp, "v %f %f %f %f %f %f\n",
221 its.vertices[i](0),
222 its.vertices[i](1),
223 its.vertices[i](2),
224 color[i](0),
225 color[i](1),
226 color[i](2));
227 for (size_t i = 0; i < its.indices.size(); ++i)
228 fprintf(fp, "f %d %d %d\n",
229 its.indices[i][0] + 1,
230 its.indices[i][1] + 1,
231 its.indices[i][2] + 1);
232 fclose(fp);
233 return true;
234}

References error, indexed_triangle_set::indices, and indexed_triangle_set::vertices.

◆ its_write_off()

bool its_write_off ( const indexed_triangle_set its,
const char *  file 
)
131{
132 Slic3r::CNumericLocalesSetter locales_setter;
133 /* Open the file */
134 FILE *fp = boost::nowide::fopen(file, "w");
135 if (fp == nullptr) {
136 BOOST_LOG_TRIVIAL(error) << "stl_write_ascii: Couldn't open " << file << " for writing";
137 return false;
138 }
139
140 fprintf(fp, "OFF\n");
141 fprintf(fp, "%d %d 0\n", (int)its.vertices.size(), (int)its.indices.size());
142 for (int i = 0; i < its.vertices.size(); ++ i)
143 fprintf(fp, "\t%f %f %f\n", its.vertices[i](0), its.vertices[i](1), its.vertices[i](2));
144 for (uint32_t i = 0; i < its.indices.size(); ++ i)
145 fprintf(fp, "\t3 %d %d %d\n", its.indices[i][0], its.indices[i][1], its.indices[i][2]);
146 fclose(fp);
147 return true;
148}
unsigned __int32 uint32_t
Definition unistd.h:79

References error, indexed_triangle_set::indices, and indexed_triangle_set::vertices.

◆ its_write_vrml()

bool its_write_vrml ( const indexed_triangle_set its,
const char *  file 
)
151{
152 Slic3r::CNumericLocalesSetter locales_setter;
153 /* Open the file */
154 FILE *fp = boost::nowide::fopen(file, "w");
155 if (fp == nullptr) {
156 BOOST_LOG_TRIVIAL(error) << "stl_write_vrml: Couldn't open " << file << " for writing";
157 return false;
158 }
159
160 fprintf(fp, "#VRML V1.0 ascii\n\n");
161 fprintf(fp, "Separator {\n");
162 fprintf(fp, "\tDEF STLShape ShapeHints {\n");
163 fprintf(fp, "\t\tvertexOrdering COUNTERCLOCKWISE\n");
164 fprintf(fp, "\t\tfaceType CONVEX\n");
165 fprintf(fp, "\t\tshapeType SOLID\n");
166 fprintf(fp, "\t\tcreaseAngle 0.0\n");
167 fprintf(fp, "\t}\n");
168 fprintf(fp, "\tDEF STLModel Separator {\n");
169 fprintf(fp, "\t\tDEF STLColor Material {\n");
170 fprintf(fp, "\t\t\temissiveColor 0.700000 0.700000 0.000000\n");
171 fprintf(fp, "\t\t}\n");
172 fprintf(fp, "\t\tDEF STLVertices Coordinate3 {\n");
173 fprintf(fp, "\t\t\tpoint [\n");
174
175 int i = 0;
176 for (; i + 1 < its.vertices.size(); ++ i)
177 fprintf(fp, "\t\t\t\t%f %f %f,\n", its.vertices[i](0), its.vertices[i](1), its.vertices[i](2));
178 fprintf(fp, "\t\t\t\t%f %f %f]\n", its.vertices[i](0), its.vertices[i](1), its.vertices[i](2));
179 fprintf(fp, "\t\t}\n");
180 fprintf(fp, "\t\tDEF STLTriangles IndexedFaceSet {\n");
181 fprintf(fp, "\t\t\tcoordIndex [\n");
182
183 for (size_t i = 0; i + 1 < its.indices.size(); ++ i)
184 fprintf(fp, "\t\t\t\t%d, %d, %d, -1,\n", its.indices[i][0], its.indices[i][1], its.indices[i][2]);
185 fprintf(fp, "\t\t\t\t%d, %d, %d, -1]\n", its.indices[i][0], its.indices[i][1], its.indices[i][2]);
186 fprintf(fp, "\t\t}\n");
187 fprintf(fp, "\t}\n");
188 fprintf(fp, "}\n");
189 fclose(fp);
190 return true;
191}

References error, indexed_triangle_set::indices, and indexed_triangle_set::vertices.

◆ stl_generate_shared_vertices()

void stl_generate_shared_vertices ( stl_file stl,
indexed_triangle_set its 
)
36{
37 // 3 indices to vertex per face
38 its.indices.assign(stl->stats.number_of_facets, stl_triangle_vertex_indices(-1, -1, -1));
39 // Shared vertices (3D coordinates)
40 its.vertices.clear();
41 its.vertices.reserve(stl->stats.number_of_facets / 2);
42
43 // A degenerate mesh may contain loops: Traversing a fan will end up in an endless loop
44 // while never reaching the starting face. To avoid these endless loops, traversed faces at each fan traversal
45 // are marked with a unique fan_traversal_stamp.
46 unsigned int fan_traversal_stamp = 0;
47 std::vector<unsigned int> fan_traversal_facet_visited(stl->stats.number_of_facets, 0);
48
49 for (uint32_t facet_idx = 0; facet_idx < stl->stats.number_of_facets; ++ facet_idx) {
50 for (int j = 0; j < 3; ++ j) {
51 if (its.indices[facet_idx][j] != -1)
52 // Shared vertex was already assigned.
53 continue;
54 // Create a new shared vertex.
55 its.vertices.emplace_back(stl->facet_start[facet_idx].vertex[j]);
56 // 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.
57 int facet_in_fan_idx = facet_idx;
58 bool edge_direction = false;
59 bool traversal_reversed = false;
60 int vnot = (j + 2) % 3;
61 // Increase the
62 ++ fan_traversal_stamp;
63 for (;;) {
64 // Next edge on facet_in_fan_idx to be traversed. The edge is indexed by its starting vertex index.
65 int next_edge = 0;
66 // Vertex index in facet_in_fan_idx, which is being pivoted around, and which is being assigned a new shared vertex.
67 int pivot_vertex = 0;
68 if (vnot > 2) {
69 // The edge of facet_in_fan_idx opposite to vnot is equally oriented, therefore
70 // the neighboring facet is flipped.
71 if (! edge_direction) {
72 pivot_vertex = (vnot + 2) % 3;
73 next_edge = pivot_vertex;
74 } else {
75 pivot_vertex = (vnot + 1) % 3;
76 next_edge = vnot % 3;
77 }
79 } else {
80 // The neighboring facet is correctly oriented.
81 if (! edge_direction) {
82 pivot_vertex = (vnot + 1) % 3;
83 next_edge = vnot;
84 } else {
85 pivot_vertex = (vnot + 2) % 3;
86 next_edge = pivot_vertex;
87 }
88 }
89 its.indices[facet_in_fan_idx][pivot_vertex] = its.vertices.size() - 1;
90 fan_traversal_facet_visited[facet_in_fan_idx] = fan_traversal_stamp;
91
92 // next_edge is an index of the starting vertex of the edge, not an index of the opposite vertex to the edge!
93 int next_facet = stl->neighbors_start[facet_in_fan_idx].neighbor[next_edge];
94 if (next_facet == -1) {
95 // No neighbor going in the current direction.
96 if (traversal_reversed) {
97 // Went to one limit, then turned back and reached the other limit. Quit the fan traversal.
98 break;
99 } else {
100 // Reached the first limit. Now try to reverse and traverse up to the other limit.
101 edge_direction = true;
102 vnot = (j + 1) % 3;
103 traversal_reversed = true;
104 facet_in_fan_idx = facet_idx;
105 }
106 } else if (next_facet == facet_idx) {
107 // Traversed a closed fan all around.
108// assert(! traversal_reversed);
109 break;
110 } else if (next_facet >= (int)stl->stats.number_of_facets) {
111 // The mesh is not valid!
112 // assert(false);
113 break;
114 } else if (fan_traversal_facet_visited[next_facet] == fan_traversal_stamp) {
115 // Traversed a closed fan all around, but did not reach the starting face.
116 // This indicates an invalid geometry (non-manifold).
117 //assert(false);
118 break;
119 } else {
120 // Continue traversal.
121 // next_edge is an index of the starting vertex of the edge, not an index of the opposite vertex to the edge!
122 vnot = stl->neighbors_start[facet_in_fan_idx].which_vertex_not[next_edge];
123 facet_in_fan_idx = next_facet;
124 }
125 }
126 }
127 }
128}
Vec3d edge_direction(const Vec3d &from, const Vec3d &to)
Definition Measure.hpp:157
std::vector< stl_facet > facet_start
Definition stl.h:150
stl_stats stats
Definition stl.h:153
std::vector< stl_neighbors > neighbors_start
Definition stl.h:151
uint32_t number_of_facets
Definition stl.h:95

References stl_file::facet_start, indexed_triangle_set::indices, stl_file::neighbors_start, stl_stats::number_of_facets, stl_file::stats, and indexed_triangle_set::vertices.

Referenced by Slic3r::TriangleMesh::ReadSTLFile().

+ Here is the caller graph for this function:

◆ stl_validate() [1/2]

bool stl_validate ( const stl_file stl)
285{
287 return stl_validate(stl, its);
288}
bool stl_validate(const stl_file *stl, const indexed_triangle_set &its)
Definition shared.cpp:237
Definition stl.h:157

References stl_validate().

+ Here is the call graph for this function:

◆ stl_validate() [2/2]

bool stl_validate ( const stl_file stl,
const indexed_triangle_set its 
)
238{
239 assert(! stl->facet_start.empty());
240 assert(stl->facet_start.size() == stl->stats.number_of_facets);
241 assert(stl->neighbors_start.size() == stl->stats.number_of_facets);
242 assert(stl->facet_start.size() == stl->neighbors_start.size());
243 assert(! stl->neighbors_start.empty());
244 assert((its.indices.empty()) == (its.vertices.empty()));
245 assert(stl->stats.number_of_facets > 0);
246 assert(its.vertices.empty() || its.indices.size() == stl->stats.number_of_facets);
247
248#ifdef _DEBUG
249 // Verify validity of neighborship data.
250 for (int facet_idx = 0; facet_idx < (int)stl->stats.number_of_facets; ++ facet_idx) {
251 const stl_neighbors &nbr = stl->neighbors_start[facet_idx];
252 const int *vertices = its.indices.empty() ? nullptr : its.indices[facet_idx].data();
253 for (int nbr_idx = 0; nbr_idx < 3; ++ nbr_idx) {
254 int nbr_face = stl->neighbors_start[facet_idx].neighbor[nbr_idx];
255 assert(nbr_face < (int)stl->stats.number_of_facets);
256 if (nbr_face != -1) {
257 int nbr_vnot = nbr.which_vertex_not[nbr_idx];
258 assert(nbr_vnot >= 0 && nbr_vnot < 6);
259 // Neighbor of the neighbor is the original face.
260 assert(stl->neighbors_start[nbr_face].neighbor[(nbr_vnot + 1) % 3] == facet_idx);
261 int vnot_back = stl->neighbors_start[nbr_face].which_vertex_not[(nbr_vnot + 1) % 3];
262 assert(vnot_back >= 0 && vnot_back < 6);
263 assert((nbr_vnot < 3) == (vnot_back < 3));
264 assert(vnot_back % 3 == (nbr_idx + 2) % 3);
265 if (vertices != nullptr) {
266 // Has shared vertices.
267 if (nbr_vnot < 3) {
268 // Faces facet_idx and nbr_face share two vertices accross the common edge. Faces are correctly oriented.
269 assert((its.indices[nbr_face][(nbr_vnot + 1) % 3] == vertices[(nbr_idx + 1) % 3] && its.indices[nbr_face][(nbr_vnot + 2) % 3] == vertices[nbr_idx]));
270 } else {
271 // Faces facet_idx and nbr_face share two vertices accross the common edge. Faces are incorrectly oriented, one of them is flipped.
272 assert((its.indices[nbr_face][(nbr_vnot + 2) % 3] == vertices[(nbr_idx + 1) % 3] && its.indices[nbr_face][(nbr_vnot + 1) % 3] == vertices[nbr_idx]));
273 }
274 }
275 }
276 }
277 }
278#endif /* _DEBUG */
279
280 return true;
281}
Definition stl.h:72
char which_vertex_not[3]
Definition stl.h:87

References stl_file::facet_start, indexed_triangle_set::indices, stl_file::neighbors_start, stl_stats::number_of_facets, stl_file::stats, indexed_triangle_set::vertices, and stl_neighbors::which_vertex_not.

Referenced by stl_remove_unconnected_facets(), stl_validate(), and Slic3r::trianglemesh_repair_on_import().

+ Here is the caller graph for this function: