mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-08-05 21:06:09 +08:00
New extrude-tin utility
This commit is contained in:
parent
5fb23f9b96
commit
5346894acc
@ -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
94
src/utils/extrude-tin.cpp
Normal 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;
|
||||
}
|
@ -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);
|
||||
|
@ -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];
|
||||
|
||||
|
@ -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 ();
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user