Skip to content

Commit

Permalink
Support zip-deflated AMF files in libslic3r.
Browse files Browse the repository at this point in the history
Includes basic tests.

Implements slic3r#4511
  • Loading branch information
lordofhyphens committed Sep 2, 2018
1 parent 38b5418 commit 7c58218
Show file tree
Hide file tree
Showing 7 changed files with 223 additions and 2 deletions.
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ set(SLIC3R_TEST_SOURCES
${TESTDIR}/libslic3r/test_test_data.cpp
${TESTDIR}/libslic3r/test_geometry.cpp
${TESTDIR}/libslic3r/test_gcodewriter.cpp
${TESTDIR}/libslic3r/test_amf.cpp
)

add_executable(slic3r slic3r.cpp)
Expand Down
138 changes: 138 additions & 0 deletions src/test/inputs/test_amf/20mmbox.amf
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
<?xml version="1.0" encoding="UTF-8"?>
<amf unit="millimeter">
<metadata type="cad">Slic3r 1.3.1-dev</metadata>
<object id="0">
<metadata type="name">20mmbox.stl</metadata>
<mesh>
<vertices>
<vertex>
<coordinates>
<x>10</x>
<y>10</y>
<z>0</z>
</coordinates>
</vertex>
<vertex>
<coordinates>
<x>-10</x>
<y>-10</y>
<z>0</z>
</coordinates>
</vertex>
<vertex>
<coordinates>
<x>-10</x>
<y>10</y>
<z>0</z>
</coordinates>
</vertex>
<vertex>
<coordinates>
<x>10</x>
<y>-10</y>
<z>0</z>
</coordinates>
</vertex>
<vertex>
<coordinates>
<x>10</x>
<y>-10</y>
<z>10</z>
</coordinates>
</vertex>
<vertex>
<coordinates>
<x>-10</x>
<y>10</y>
<z>10</z>
</coordinates>
</vertex>
<vertex>
<coordinates>
<x>-10</x>
<y>-10</y>
<z>10</z>
</coordinates>
</vertex>
<vertex>
<coordinates>
<x>10</x>
<y>10</y>
<z>10</z>
</coordinates>
</vertex>
</vertices>
<volume>
<metadata type="name">20mmbox.stl</metadata>
<triangle>
<v1>0</v1>
<v2>1</v2>
<v3>2</v3>
</triangle>
<triangle>
<v1>1</v1>
<v2>0</v2>
<v3>3</v3>
</triangle>
<triangle>
<v1>4</v1>
<v2>5</v2>
<v3>6</v3>
</triangle>
<triangle>
<v1>5</v1>
<v2>4</v2>
<v3>7</v3>
</triangle>
<triangle>
<v1>0</v1>
<v2>4</v2>
<v3>3</v3>
</triangle>
<triangle>
<v1>4</v1>
<v2>0</v2>
<v3>7</v3>
</triangle>
<triangle>
<v1>4</v1>
<v2>1</v2>
<v3>3</v3>
</triangle>
<triangle>
<v1>1</v1>
<v2>4</v2>
<v3>6</v3>
</triangle>
<triangle>
<v1>5</v1>
<v2>1</v2>
<v3>6</v3>
</triangle>
<triangle>
<v1>1</v1>
<v2>5</v2>
<v3>2</v3>
</triangle>
<triangle>
<v1>5</v1>
<v2>0</v2>
<v3>2</v3>
</triangle>
<triangle>
<v1>0</v1>
<v2>5</v2>
<v3>7</v3>
</triangle>
</volume>
</mesh>
</object>
<constellation id="1">
<instance objectid="0">
<deltax>67.5</deltax>
<deltay>35</deltay>
<rz>0</rz>
<scale>1</scale>
</instance>
</constellation>
</amf>
Binary file not shown.
Binary file not shown.
Binary file added src/test/inputs/test_amf/20mmbox_deflated.amf
Binary file not shown.
60 changes: 60 additions & 0 deletions src/test/libslic3r/test_amf.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#include <catch.hpp>
#include <test_options.hpp>
#include "IO.hpp"

using namespace Slic3r;
using namespace std::literals::string_literals;

SCENARIO("Reading deflated AMF files") {
GIVEN("Compressed AMF file of a 20mm cube") {
Model model;
WHEN("file is read") {
bool result_code = IO::AMF::read(std::string(testfile_dir) + "test_amf/20mmbox_deflated.amf"s, &model);
THEN("Does not return false.") {
REQUIRE(result_code == true);
}
THEN("Model object contains a single ModelObject.") {
REQUIRE(model.objects.size() == 1);
}
}
WHEN("single file is read with some subdirectories") {
bool result_code = IO::AMF::read(std::string(testfile_dir) + "test_amf/20mmbox_deflated-in_directories.amf"s, &model);
THEN("Read returns false.") {
REQUIRE(result_code == true);
}
THEN("Model object contains no ModelObjects.") {
REQUIRE(model.objects.size() == 1);
}
}
WHEN("file is read with unsupported file structure (multiple files)") {
bool result_code = IO::AMF::read(std::string(testfile_dir) + "test_amf/20mmbox_deflated-mult_files.amf"s, &model);
THEN("Read returns false.") {
REQUIRE(result_code == false);
}
THEN("Model object contains no ModelObjects.") {
REQUIRE(model.objects.size() == 0);
}
}
}
GIVEN("Uncompressed AMF file of a 20mm cube") {
Model model;
WHEN("file is read") {
bool result_code = IO::AMF::read(std::string(testfile_dir) + "test_amf/20mmbox.amf"s, &model);
THEN("Does not return false.") {
REQUIRE(result_code == true);
}
THEN("Model object contains a single ModelObject.") {
REQUIRE(model.objects.size() == 1);
}
}
WHEN("nonexistant file is read") {
bool result_code = IO::AMF::read(std::string(testfile_dir) + "test_amf/20mmbox-doesnotexist.amf"s, &model);
THEN("Read returns false.") {
REQUIRE(result_code == false);
}
THEN("Model object contains no ModelObject.") {
REQUIRE(model.objects.size() == 0);
}
}
}
}
26 changes: 24 additions & 2 deletions xs/src/libslic3r/IO/AMF.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "../IO.hpp"
#include "Zip/ZipArchive.hpp"
#include <iostream>
#include <fstream>
#include <string.h>
Expand Down Expand Up @@ -450,15 +451,31 @@ void AMFParserContext::endDocument()
bool
AMF::read(std::string input_file, Model* model)
{
ZipArchive zip_archive(input_file, 'R');
auto file_list = zip_archive.list_entries();
if (file_list.size() > 1) {
return false; // only support single file archives
}
std::string deflated_input_file {""};
if (file_list.size() == 1) {
// extract the file with ZipArchive
if(!zip_archive.extract_entry(file_list[0], "3dmodel.xml"))
return false;
deflated_input_file = "3dmodel.xml";
} else {
// not a deflated file
deflated_input_file = input_file;
}

XML_Parser parser = XML_ParserCreate(NULL); // encoding
if (! parser) {
printf("Couldn't allocate memory for parser\n");
return false;
}

boost::nowide::ifstream fin(input_file, std::ios::in);
boost::nowide::ifstream fin(deflated_input_file, std::ios::in);
if (!fin.is_open()) {
boost::nowide::cerr << "Cannot open file: " << input_file << std::endl;
boost::nowide::cerr << "Cannot open file: " << deflated_input_file << std::endl;
return false;
}

Expand Down Expand Up @@ -489,6 +506,11 @@ AMF::read(std::string input_file, Model* model)

XML_ParserFree(parser);
fin.close();
if (file_list.size() == 1) {
// Remove the extracted 3dmodel.xml file.
if (remove("3dmodel.xml") != 0)
return false;
}

if (result)
ctx.endDocument();
Expand Down

0 comments on commit 7c58218

Please sign in to comment.