mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-08-05 19:36:07 +08:00
Clean IO::AMF::write()
This commit is contained in:
parent
4c78e54a46
commit
a6609682fc
@ -1,4 +1,6 @@
|
||||
#include "../IO.hpp"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string.h>
|
||||
#include <map>
|
||||
#include <string>
|
||||
@ -495,109 +497,121 @@ AMF::read(std::string input_file, Model* model)
|
||||
bool
|
||||
AMF::write(Model& model, std::string output_file)
|
||||
{
|
||||
FILE *file = ::fopen(output_file.c_str(), "wb");
|
||||
if (file == NULL)
|
||||
return false;
|
||||
using namespace std;
|
||||
|
||||
ofstream file;
|
||||
file.open(output_file, ios::out | ios::trunc);
|
||||
|
||||
file << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << endl
|
||||
<< "<amf unit=\"millimeter\">" << endl
|
||||
<< "<metadata type=\"cad\">Slic3r " << SLIC3R_VERSION << "</metadata>" << endl;
|
||||
|
||||
fprintf(file, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
|
||||
fprintf(file, "<amf unit=\"millimeter\">\n");
|
||||
fprintf(file, "<metadata type=\"cad\">Slic3r %s</metadata>\n", SLIC3R_VERSION);
|
||||
for (const auto &material : model.materials) {
|
||||
if (material.first.empty())
|
||||
continue;
|
||||
// note that material-id must never be 0 since it's reserved by the AMF spec
|
||||
fprintf(file, " <material id=\"%s\">\n", material.first.c_str());
|
||||
file << " <material id=\"" << material.first << "\">" << endl;
|
||||
for (const auto &attr : material.second->attributes)
|
||||
fprintf(file, " <metadata type=\"%s\">%s</metadata>\n", attr.first.c_str(), attr.second.c_str());
|
||||
file << " <metadata type=\"" << attr.first << "\">" << attr.second << "</metadata>" << endl;
|
||||
for (const std::string &key : material.second->config.keys())
|
||||
fprintf(file, " <metadata type=\"slic3r.%s\">%s</metadata>\n", key.c_str(), material.second->config.serialize(key).c_str());
|
||||
fprintf(file, " </material>\n");
|
||||
file << " <metadata type=\"slic3r." << key << "\">"
|
||||
<< material.second->config.serialize(key) << "</metadata>" << endl;
|
||||
file << " </material>" << endl;
|
||||
}
|
||||
std::string instances;
|
||||
|
||||
ostringstream instances;
|
||||
for (size_t object_id = 0; object_id < model.objects.size(); ++object_id) {
|
||||
ModelObject *object = model.objects[object_id];
|
||||
fprintf(file, " <object id=\"%zu\">\n", object_id);
|
||||
for (const std::string &key : object->config.keys())
|
||||
fprintf(file, " <metadata type=\"slic3r.%s\">%s</metadata>\n", key.c_str(), object->config.serialize(key).c_str());
|
||||
if (! object->name.empty())
|
||||
fprintf(file, " <metadata type=\"name\">%s</metadata>\n", object->name.c_str());
|
||||
file << " <object id=\"" << object_id << "\">" << endl;
|
||||
|
||||
for (const std::string &key : object->config.keys())
|
||||
file << " <metadata type=\"slic3r." << key << "\">"
|
||||
<< object->config.serialize(key) << "</metadata>" << endl;
|
||||
|
||||
if (!object->name.empty())
|
||||
file << " <metadata type=\"name\">" << object->name << "</metadata>" << endl;
|
||||
|
||||
//FIXME: Store the layer height ranges (ModelObject::layer_height_ranges)
|
||||
file << " <mesh>" << endl;
|
||||
file << " <vertices>" << endl;
|
||||
|
||||
std::vector<size_t> vertices_offsets;
|
||||
size_t num_vertices = 0;
|
||||
|
||||
//FIXME Store the layer height ranges (ModelObject::layer_height_ranges)
|
||||
fprintf(file, " <mesh>\n");
|
||||
fprintf(file, " <vertices>\n");
|
||||
std::vector<int> vertices_offsets;
|
||||
int num_vertices = 0;
|
||||
for (ModelVolume *volume : object->volumes) {
|
||||
volume->mesh.check_topology();
|
||||
volume->mesh.require_shared_vertices();
|
||||
vertices_offsets.push_back(num_vertices);
|
||||
auto &stl = volume->mesh.stl;
|
||||
if (stl.v_shared == NULL)
|
||||
stl_generate_shared_vertices(&stl);
|
||||
for (size_t i = 0; i < stl.stats.shared_vertices; ++ i) {
|
||||
const auto &stl = volume->mesh.stl;
|
||||
for (size_t i = 0; i < stl.stats.shared_vertices; ++i)
|
||||
// Subtract origin_translation in order to restore the coordinates of the parts
|
||||
// before they were imported. Otherwise, when this AMF file is reimported parts
|
||||
// will be placed in the plater correctly, but we will have lost origin_translation
|
||||
// thus any additional part added will not align with the others.
|
||||
// In order to do this we compensate for this translation in the instance placement
|
||||
// below.
|
||||
fprintf(file, " <vertex>\n");
|
||||
fprintf(file, " <coordinates>\n");
|
||||
fprintf(file, " <x>%f</x>\n", stl.v_shared[i].x - object->origin_translation.x);
|
||||
fprintf(file, " <y>%f</y>\n", stl.v_shared[i].y - object->origin_translation.y);
|
||||
fprintf(file, " <z>%f</z>\n", stl.v_shared[i].z - object->origin_translation.z);
|
||||
fprintf(file, " </coordinates>\n");
|
||||
fprintf(file, " </vertex>\n");
|
||||
}
|
||||
file << " <vertex>" << endl
|
||||
<< " <coordinates>" << endl
|
||||
<< " <x>" << (stl.v_shared[i].x - object->origin_translation.x) << "</x>" << endl
|
||||
<< " <y>" << (stl.v_shared[i].y - object->origin_translation.y) << "</y>" << endl
|
||||
<< " <z>" << (stl.v_shared[i].z - object->origin_translation.z) << "</z>" << endl
|
||||
<< " </coordinates>" << endl
|
||||
<< " </vertex>" << endl;
|
||||
|
||||
num_vertices += stl.stats.shared_vertices;
|
||||
}
|
||||
fprintf(file, " </vertices>\n");
|
||||
file << " </vertices>" << endl;
|
||||
|
||||
for (size_t i_volume = 0; i_volume < object->volumes.size(); ++i_volume) {
|
||||
ModelVolume *volume = object->volumes[i_volume];
|
||||
int vertices_offset = vertices_offsets[i_volume];
|
||||
|
||||
if (volume->material_id().empty())
|
||||
fprintf(file, " <volume>\n");
|
||||
file << " <volume>" << endl;
|
||||
else
|
||||
fprintf(file, " <volume materialid=\"%s\">\n", volume->material_id().c_str());
|
||||
file << " <volume materialid=\"" << volume->material_id() << "\">" << endl;
|
||||
|
||||
for (const std::string &key : volume->config.keys())
|
||||
fprintf(file, " <metadata type=\"slic3r.%s\">%s</metadata>\n", key.c_str(), volume->config.serialize(key).c_str());
|
||||
file << " <metadata type=\"slic3r." << key << "\">"
|
||||
<< volume->config.serialize(key) << "</metadata>" << endl;
|
||||
|
||||
if (!volume->name.empty())
|
||||
fprintf(file, " <metadata type=\"name\">%s</metadata>\n", volume->name.c_str());
|
||||
file << " <metadata type=\"name\">" << volume->name << "</metadata>" << endl;
|
||||
|
||||
if (volume->modifier)
|
||||
fprintf(file, " <metadata type=\"slic3r.modifier\">1</metadata>\n");
|
||||
file << " <metadata type=\"slic3r.modifier\">1</metadata>" << endl;
|
||||
|
||||
for (int i = 0; i < volume->mesh.stl.stats.number_of_facets; ++i) {
|
||||
fprintf(file, " <triangle>\n");
|
||||
file << " <triangle>" << endl;
|
||||
for (int j = 0; j < 3; ++ j)
|
||||
fprintf(file, " <v%d>%d</v%d>\n", j+1, volume->mesh.stl.v_indices[i].vertex[j] + vertices_offset, j+1);
|
||||
fprintf(file, " </triangle>\n");
|
||||
file << " <v" << (j+1) << ">"
|
||||
<< (volume->mesh.stl.v_indices[i].vertex[j] + vertices_offset)
|
||||
<< "</v" << (j+1) << ">" << endl;
|
||||
file << " </triangle>" << endl;
|
||||
}
|
||||
fprintf(file, " </volume>\n");
|
||||
file << " </volume>" << endl;
|
||||
}
|
||||
fprintf(file, " </mesh>\n");
|
||||
fprintf(file, " </object>\n");
|
||||
for (const ModelInstance* instance : object->instances) {
|
||||
char buf[512];
|
||||
sprintf(buf,
|
||||
" <instance objectid=\"%zu\">\n"
|
||||
" <deltax>%lf</deltax>\n"
|
||||
" <deltay>%lf</deltay>\n"
|
||||
" <rz>%lf</rz>\n"
|
||||
" <scale>%lf</scale>\n"
|
||||
" </instance>\n",
|
||||
object_id,
|
||||
instance->offset.x + object->origin_translation.x,
|
||||
instance->offset.y + object->origin_translation.y,
|
||||
instance->rotation,
|
||||
instance->scaling_factor);
|
||||
instances.append(buf);
|
||||
file << " </mesh>" << endl;
|
||||
file << " </object>" << endl;
|
||||
|
||||
for (const ModelInstance* instance : object->instances)
|
||||
instances
|
||||
<< " <instance objectid=\"" << object_id << "\">" << endl
|
||||
<< " <deltax>" << instance->offset.x + object->origin_translation.x << "</deltax>" << endl
|
||||
<< " <deltay>" << instance->offset.y + object->origin_translation.y << "</deltay>" << endl
|
||||
<< " <rz>%" << instance->rotation << "</rz>" << endl
|
||||
<< " <scale>" << instance->scaling_factor << "</scale>" << endl
|
||||
<< " </instance>" << endl;
|
||||
}
|
||||
}
|
||||
if (! instances.empty()) {
|
||||
fprintf(file, " <constellation id=\"1\">\n");
|
||||
fwrite(instances.data(), instances.size(), 1, file);
|
||||
fprintf(file, " </constellation>\n");
|
||||
}
|
||||
fprintf(file, "</amf>\n");
|
||||
fclose(file);
|
||||
|
||||
std::string instances_str = instances.str();
|
||||
if (!instances_str.empty())
|
||||
file << " <constellation id=\"1\">" << endl
|
||||
<< instances_str
|
||||
<< " </constellation>" << endl;
|
||||
|
||||
file << "</amf>" << endl;
|
||||
|
||||
file.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -58,6 +58,7 @@ class TriangleMesh
|
||||
bool needed_repair() const;
|
||||
size_t facets_count() const;
|
||||
void extrude_tin(float offset);
|
||||
void require_shared_vertices();
|
||||
|
||||
static TriangleMesh make_cube(double x, double y, double z);
|
||||
static TriangleMesh make_cylinder(double r, double h, double fa=(2*PI/360));
|
||||
@ -67,7 +68,6 @@ class TriangleMesh
|
||||
bool repaired;
|
||||
|
||||
private:
|
||||
void require_shared_vertices();
|
||||
friend class TriangleMeshSlicer<X>;
|
||||
friend class TriangleMeshSlicer<Y>;
|
||||
friend class TriangleMeshSlicer<Z>;
|
||||
|
Loading…
x
Reference in New Issue
Block a user