New extrude-tin utility

This commit is contained in:
Alessandro Ranellucci 2016-07-12 13:44:37 +02:00
parent 5fb23f9b96
commit 5346894acc
10 changed files with 204 additions and 65 deletions

View File

@ -34,49 +34,71 @@ include_directories(${LIBDIR}/admesh/)
include_directories(${LIBDIR}/poly2tri/)
include_directories(${LIBDIR}/poly2tri/sweep)
include_directories(${LIBDIR}/poly2tri/common)
add_library(libslic3r STATIC ${LIBDIR}/libslic3r/BoundingBox.cpp
${LIBDIR}/libslic3r/ExPolygon.cpp
${LIBDIR}/libslic3r/GCode.cpp
${LIBDIR}/libslic3r/LayerRegion.cpp
${LIBDIR}/libslic3r/PerimeterGenerator.cpp
${LIBDIR}/libslic3r/Polyline.cpp
${LIBDIR}/libslic3r/SurfaceCollection.cpp
${LIBDIR}/libslic3r/BridgeDetector.cpp
${LIBDIR}/libslic3r/Extruder.cpp
${LIBDIR}/libslic3r/GCodeSender.cpp
${LIBDIR}/libslic3r/IO.cpp
${LIBDIR}/libslic3r/Line.cpp
${LIBDIR}/libslic3r/PlaceholderParser.cpp
${LIBDIR}/libslic3r/PrintConfig.cpp
${LIBDIR}/libslic3r/Surface.cpp
${LIBDIR}/libslic3r/ClipperUtils.cpp
${LIBDIR}/libslic3r/ExtrusionEntityCollection.cpp
${LIBDIR}/libslic3r/GCodeWriter.cpp
${LIBDIR}/libslic3r/Model.cpp
${LIBDIR}/libslic3r/Point.cpp
${LIBDIR}/libslic3r/Print.cpp
${LIBDIR}/libslic3r/SVG.cpp
${LIBDIR}/libslic3r/SVGExport.cpp
${LIBDIR}/libslic3r/Config.cpp
${LIBDIR}/libslic3r/ExtrusionEntity.cpp
${LIBDIR}/libslic3r/Geometry.cpp
${LIBDIR}/libslic3r/MotionPlanner.cpp
${LIBDIR}/libslic3r/Polygon.cpp
${LIBDIR}/libslic3r/PrintObject.cpp
${LIBDIR}/libslic3r/TriangleMesh.cpp
${LIBDIR}/libslic3r/ExPolygonCollection.cpp
${LIBDIR}/libslic3r/Flow.cpp
${LIBDIR}/libslic3r/Layer.cpp
${LIBDIR}/libslic3r/MultiPoint.cpp
${LIBDIR}/libslic3r/PolylineCollection.cpp
${LIBDIR}/libslic3r/PrintRegion.cpp)
add_library(admesh STATIC ${LIBDIR}/admesh/util.c ${LIBDIR}/admesh/stl_io.c ${LIBDIR}/admesh/stlinit.c ${LIBDIR}/admesh/shared.c ${LIBDIR}/admesh/normals.c ${LIBDIR}/admesh/connect.c)
add_library(libslic3r STATIC
${LIBDIR}/libslic3r/BoundingBox.cpp
${LIBDIR}/libslic3r/BridgeDetector.cpp
${LIBDIR}/libslic3r/ClipperUtils.cpp
${LIBDIR}/libslic3r/Config.cpp
${LIBDIR}/libslic3r/ExPolygon.cpp
${LIBDIR}/libslic3r/ExPolygonCollection.cpp
${LIBDIR}/libslic3r/Extruder.cpp
${LIBDIR}/libslic3r/ExtrusionEntity.cpp
${LIBDIR}/libslic3r/ExtrusionEntityCollection.cpp
${LIBDIR}/libslic3r/Flow.cpp
${LIBDIR}/libslic3r/GCode.cpp
${LIBDIR}/libslic3r/GCodeSender.cpp
${LIBDIR}/libslic3r/GCodeWriter.cpp
${LIBDIR}/libslic3r/Geometry.cpp
${LIBDIR}/libslic3r/IO.cpp
${LIBDIR}/libslic3r/Layer.cpp
${LIBDIR}/libslic3r/LayerRegion.cpp
${LIBDIR}/libslic3r/Line.cpp
${LIBDIR}/libslic3r/Model.cpp
${LIBDIR}/libslic3r/MotionPlanner.cpp
${LIBDIR}/libslic3r/MultiPoint.cpp
${LIBDIR}/libslic3r/PerimeterGenerator.cpp
${LIBDIR}/libslic3r/PlaceholderParser.cpp
${LIBDIR}/libslic3r/Point.cpp
${LIBDIR}/libslic3r/Polygon.cpp
${LIBDIR}/libslic3r/Polyline.cpp
${LIBDIR}/libslic3r/PolylineCollection.cpp
${LIBDIR}/libslic3r/Print.cpp
${LIBDIR}/libslic3r/PrintConfig.cpp
${LIBDIR}/libslic3r/PrintObject.cpp
${LIBDIR}/libslic3r/PrintRegion.cpp
${LIBDIR}/libslic3r/Surface.cpp
${LIBDIR}/libslic3r/SurfaceCollection.cpp
${LIBDIR}/libslic3r/SVG.cpp
${LIBDIR}/libslic3r/SVGExport.cpp
${LIBDIR}/libslic3r/TriangleMesh.cpp
)
add_library(admesh STATIC
${LIBDIR}/admesh/connect.c
${LIBDIR}/admesh/normals.c
${LIBDIR}/admesh/shared.c
${LIBDIR}/admesh/stl_io.c
${LIBDIR}/admesh/stlinit.c
${LIBDIR}/admesh/util.c
)
add_library(clipper STATIC ${LIBDIR}/clipper.cpp)
add_library(polypartition STATIC ${LIBDIR}/polypartition.cpp)
add_library(poly2tri STATIC ${LIBDIR}/poly2tri/sweep/sweep.cc ${LIBDIR}/poly2tri/sweep/sweep_context.cc ${LIBDIR}/poly2tri/sweep/cdt.cc ${LIBDIR}/poly2tri/sweep/advancing_front.cc ${LIBDIR}/poly2tri/common/shapes.cc)
add_library(poly2tri STATIC
${LIBDIR}/poly2tri/common/shapes.cc
${LIBDIR}/poly2tri/sweep/advancing_front.cc
${LIBDIR}/poly2tri/sweep/cdt.cc
${LIBDIR}/poly2tri/sweep/sweep_context.cc
${LIBDIR}/poly2tri/sweep/sweep.cc
)
add_executable(slic3r slic3r.cpp)
set_target_properties(slic3r PROPERTIES LINK_SEARCH_START_STATIC 1)
set_target_properties(slic3r PROPERTIES LINK_SEARCH_END_STATIC 1)
add_executable(extrude-tin utils/extrude-tin.cpp)
set_target_properties(extrude-tin PROPERTIES LINK_SEARCH_START_STATIC 1)
set_target_properties(extrude-tin PROPERTIES LINK_SEARCH_END_STATIC 1)
set(wxWidgets_USE_STATIC)
SET(wxWidgets_USE_LIBS)
@ -109,3 +131,4 @@ ELSE(wxWidgets_FOUND)
#skip gui when no wx included
ENDIF(wxWidgets_FOUND)
target_link_libraries (extrude-tin libslic3r admesh clipper polypartition poly2tri ${Boost_LIBRARIES})

94
src/utils/extrude-tin.cpp Normal file
View File

@ -0,0 +1,94 @@
#include "Config.hpp"
#include "Model.hpp"
#include "IO.hpp"
#include "TriangleMesh.hpp"
#include "libslic3r.h"
using namespace Slic3r;
void confess_at(const char *file, int line, const char *func, const char *pat, ...){}
int
main(const int argc, const char **argv)
{
// read config
ConfigDef config_def;
{
ConfigOptionDef* def;
def = config_def.add("offset", coFloat);
def->label = "Offset from the lowest point (min thickness)";
def->cli = "offset";
def->default_value = new ConfigOptionFloat(1);
def = config_def.add("output", coString);
def->label = "Output File";
def->tooltip = "The file where the output will be written (if not specified, it will be based on the input file).";
def->cli = "output";
def->default_value = new ConfigOptionString("");
}
DynamicConfig config(&config_def);
t_config_option_keys input_files;
config.read_cli(argc, argv, &input_files);
for (t_config_option_keys::const_iterator it = input_files.begin(); it != input_files.end(); ++it) {
TriangleMesh mesh;
Slic3r::IO::STL::read(*it, &mesh);
calculate_normals(&mesh.stl);
if (mesh.facets_count() == 0) {
printf("Error: file is empty: %s\n", it->c_str());
continue;
}
float z = mesh.stl.stats.min.z - config.option("offset", true)->getFloat();
printf("min.z = %f, z = %f\n", mesh.stl.stats.min.z, z);
TriangleMesh mesh2 = mesh;
for (int i = 0; i < mesh.stl.stats.number_of_facets; ++i) {
const stl_facet &facet = mesh.stl.facet_start[i];
if (facet.normal.z < 0) {
printf("Invalid 2.5D mesh / TIN (one facet points downwards = %f)\n", facet.normal.z);
exit(1);
}
for (int j = 0; j < 3; ++j) {
if (mesh.stl.neighbors_start[i].neighbor[j] == -1) {
stl_facet new_facet;
float normal[3];
// first triangle
new_facet.vertex[0] = new_facet.vertex[2] = facet.vertex[(j+1)%3];
new_facet.vertex[1] = facet.vertex[j];
new_facet.vertex[2].z = z;
stl_calculate_normal(normal, &new_facet);
stl_normalize_vector(normal);
new_facet.normal.x = normal[0];
new_facet.normal.y = normal[1];
new_facet.normal.z = normal[2];
stl_add_facet(&mesh2.stl, &new_facet);
// second triangle
new_facet.vertex[0] = new_facet.vertex[1] = facet.vertex[j];
new_facet.vertex[2] = facet.vertex[(j+1)%3];
new_facet.vertex[1].z = new_facet.vertex[2].z = z;
new_facet.normal.x = normal[0];
new_facet.normal.y = normal[1];
new_facet.normal.z = normal[2];
stl_add_facet(&mesh2.stl, &new_facet);
}
}
}
mesh2.repair();
std::string outfile = config.option("output", true)->getString();
if (outfile.empty()) outfile = *it + "_extruded.stl";
Slic3r::IO::STL::write(mesh2, outfile);
printf("Extuded mesh written to %s\n", outfile.c_str());
}
return 0;
}

View File

@ -162,6 +162,7 @@ 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_scale_versor(stl_file *stl, float versor[3]);
extern void stl_scale(stl_file *stl, float factor);
extern void calculate_normals(stl_file *stl);
extern void stl_rotate_x(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);

View File

@ -170,7 +170,7 @@ stl_scale(stl_file *stl, float factor) {
stl_scale_versor(stl, versor);
}
static void calculate_normals(stl_file *stl) {
void calculate_normals(stl_file *stl) {
long i;
float normal[3];

View File

@ -220,7 +220,9 @@ DynamicConfig::optptr(const t_config_option_key &opt_key, bool create) {
const ConfigOptionDef* optdef = this->def->get(opt_key);
if (optdef == NULL) return NULL;
ConfigOption* opt;
if (optdef->type == coFloat) {
if (optdef->default_value != NULL) {
opt = optdef->default_value->clone();
} else if (optdef->type == coFloat) {
opt = new ConfigOptionFloat ();
} else if (optdef->type == coFloats) {
opt = new ConfigOptionFloats ();

View File

@ -28,6 +28,7 @@ class ConfigOption {
virtual double getFloat() const { return 0; };
virtual bool getBool() const { return false; };
virtual void setInt(int val) {};
virtual std::string getString() const { return ""; };
friend bool operator== (const ConfigOption &a, const ConfigOption &b);
friend bool operator!= (const ConfigOption &a, const ConfigOption &b);
};
@ -206,6 +207,8 @@ class ConfigOptionString : public ConfigOptionSingle<std::string>
ConfigOptionString(std::string _value) : ConfigOptionSingle<std::string>(_value) {};
ConfigOptionString* clone() const { return new ConfigOptionString(this->value); };
std::string getString() const { return this->value; };
std::string serialize() const {
std::string str = this->value;

View File

@ -5,6 +5,14 @@
namespace Slic3r { namespace IO {
bool
STL::read(std::string input_file, TriangleMesh* mesh)
{
mesh->ReadSTLFile(input_file);
mesh->check_topology();
return true;
}
bool
STL::read(std::string input_file, Model* model)
{
@ -12,7 +20,7 @@ STL::read(std::string input_file, Model* model)
// TODO: check that file exists
TriangleMesh mesh;
mesh.ReadSTLFile(input_file);
if (!STL::read(input_file, &mesh)) return false;
mesh.repair();
if (mesh.facets_count() == 0)

View File

@ -11,6 +11,7 @@ namespace Slic3r { namespace IO {
class STL
{
public:
static bool read(std::string input_file, TriangleMesh* mesh);
static bool read(std::string input_file, Model* model);
static bool write(TriangleMesh& mesh, std::string output_file, bool binary = true);
};

View File

@ -89,30 +89,7 @@ TriangleMesh::repair() {
// admesh fails when repairing empty meshes
if (this->stl.stats.number_of_facets == 0) return;
// checking exact
stl_check_facets_exact(&stl);
stl.stats.facets_w_1_bad_edge = (stl.stats.connected_facets_2_edge - stl.stats.connected_facets_3_edge);
stl.stats.facets_w_2_bad_edge = (stl.stats.connected_facets_1_edge - stl.stats.connected_facets_2_edge);
stl.stats.facets_w_3_bad_edge = (stl.stats.number_of_facets - stl.stats.connected_facets_1_edge);
// checking nearby
//int last_edges_fixed = 0;
float tolerance = stl.stats.shortest_edge;
float increment = stl.stats.bounding_diameter / 10000.0;
int iterations = 2;
if (stl.stats.connected_facets_3_edge < stl.stats.number_of_facets) {
for (int i = 0; i < iterations; i++) {
if (stl.stats.connected_facets_3_edge < stl.stats.number_of_facets) {
//printf("Checking nearby. Tolerance= %f Iteration=%d of %d...", tolerance, i + 1, iterations);
stl_check_facets_nearby(&stl, tolerance);
//printf(" Fixed %d edges.\n", stl.stats.edges_fixed - last_edges_fixed);
//last_edges_fixed = stl.stats.edges_fixed;
tolerance += increment;
} else {
break;
}
}
}
this->check_topology();
// remove_unconnected
if (stl.stats.connected_facets_3_edge < stl.stats.number_of_facets) {
@ -140,6 +117,35 @@ TriangleMesh::repair() {
this->repaired = true;
}
void
TriangleMesh::check_topology()
{
// checking exact
stl_check_facets_exact(&stl);
stl.stats.facets_w_1_bad_edge = (stl.stats.connected_facets_2_edge - stl.stats.connected_facets_3_edge);
stl.stats.facets_w_2_bad_edge = (stl.stats.connected_facets_1_edge - stl.stats.connected_facets_2_edge);
stl.stats.facets_w_3_bad_edge = (stl.stats.number_of_facets - stl.stats.connected_facets_1_edge);
// checking nearby
//int last_edges_fixed = 0;
float tolerance = stl.stats.shortest_edge;
float increment = stl.stats.bounding_diameter / 10000.0;
int iterations = 2;
if (stl.stats.connected_facets_3_edge < stl.stats.number_of_facets) {
for (int i = 0; i < iterations; i++) {
if (stl.stats.connected_facets_3_edge < stl.stats.number_of_facets) {
//printf("Checking nearby. Tolerance= %f Iteration=%d of %d...", tolerance, i + 1, iterations);
stl_check_facets_nearby(&stl, tolerance);
//printf(" Fixed %d edges.\n", stl.stats.edges_fixed - last_edges_fixed);
//last_edges_fixed = stl.stats.edges_fixed;
tolerance += increment;
} else {
break;
}
}
}
}
void
TriangleMesh::reset_repair_stats() {
this->stl.stats.degenerate_facets = 0;

View File

@ -28,6 +28,7 @@ class TriangleMesh
void write_ascii(const std::string &output_file);
void write_binary(const std::string &output_file);
void repair();
void check_topology();
void WriteOBJFile(const std::string &output_file);
void scale(float factor);
void scale(const Pointf3 &versor);