#!/usr/bin/perl
use strict;
use warnings;
use Slic3r::XS;
use Test::More;
use IO::Uncompress::Unzip qw(unzip $UnzipError) ;
use Cwd qw(abs_path);
use File::Basename qw(dirname);
# Removes '\n' and '\r\n' from a string.
sub clean {
my $text = shift;
$text =~ s/\n//g;
$text =~ s/\r//g;
return $text;
}
my $current_path = abs_path($0);
my $expected_content_types = " \n"
."\n"
."\n"
."\n"
."\n";
my $expected_relationships = " \n"
."\n"
."\n";
# Test 1: Check read/write.
{
my $input_path = dirname($current_path). "/models/3mf/box.3mf";
my $output_path = dirname($current_path). "/models/3mf/box2.3mf";
# Create a new model.
my $model = Slic3r::Model->new;
my $result = $model->read_tmf($input_path);
is($result, 1, 'Basic 3mf read test.');
$result = $model->write_tmf($output_path);
is($result, 1, 'Basic 3mf write test.');
# Delete the created file.
unlink($output_path);
}
# Test 2: Check read metadata/ objects/ components/ build items w/o or with tansformation matrics.
{
my $input_path = dirname($current_path). "/models/3mf/gimblekeychain.3mf";
# Create a new model.
my $model = Slic3r::Model->new;
$model->read_tmf($input_path);
# Check the number of read matadata.
is($model->metadata_count(), 8, 'Test 2: metadata count check.');
# Check the number of read objects.
is($model->objects_count(), 1, 'Test 2: objects count check.');
# Check the number of read instances.
is($model->get_object(0)->instances_count(), 1, 'Test 2: object instances count check.');
# Check the read object part number.
is($model->get_object(0)->part_number(), -1, 'Test 2: object part number check.');
# Check the number of read volumes.
is($model->get_object(0)->volumes_count(), 3, 'Test 2: object volumes count check.');
# Check the number of read number of facets (triangles).
is($model->get_object(0)->facets_count(), 19884, 'Test 2: object number of facets check.');
# Check the affine transformation matrix decomposition.
# Check translation.
cmp_ok($model->get_object(0)->get_instance(0)->offset()->x(), '<=', 0.0001, 'Test 2: X translation check.');
cmp_ok($model->get_object(0)->get_instance(0)->offset()->y(), '<=', 0.0001, 'Test 2: Y translation check.');
cmp_ok($model->get_object(0)->get_instance(0)->z_translation() - 0.0345364, '<=', 0.0001, 'Test 2: Z translation check.');
# Check scale.
cmp_ok($model->get_object(0)->get_instance(0)->scaling_vector()->x() - 25.4, '<=', 0.0001, 'Test 2: X scale check.');
cmp_ok($model->get_object(0)->get_instance(0)->scaling_vector()->y() - 25.4, '<=', 0.0001, 'Test 2: Y scale check.');
cmp_ok($model->get_object(0)->get_instance(0)->scaling_vector()->z() - 25.4, '<=', 0.0001, 'Test 2: Z scale check.');
# Check X, Y, & Z rotation.
cmp_ok($model->get_object(0)->get_instance(0)->x_rotation() - 6.2828, '<=', 0.0001, 'Test 2: X rotation check.');
cmp_ok($model->get_object(0)->get_instance(0)->y_rotation() - 6.2828, '<=', 0.0001, 'Test 2: Y rotation check.');
cmp_ok($model->get_object(0)->get_instance(0)->rotation(), '<=', 0.0001, 'Test 2: Z rotation check.');
}
# Test 3: Read an STL and write it as 3MF.
{
my $input_path = dirname($current_path). "/models/stl/spikey_top.stl";
my $output_path = dirname($current_path). "/models/3mf/spikey_top.3mf";
my $model = Slic3r::Model->new;
my $result = $model->read_stl($input_path);
is($result, 1, 'Test 3: read the stl model file.');
# Check initialization of 3mf specific atttributes.
is($model->metadata_count(), 0, 'Test 3: read stl model metadata count check .');
is($model->get_object(0)->instances_count(), 0, 'Test 3: object instances count check.');
is($model->get_object(0)->part_number(), -1, 'Test 3: object partnumber check.');
is($model->material_count(), 0, 'Test 3: model materials count check.');
$result = $model->write_tmf($output_path);
is($result, 1, 'Test 3: Write the 3mf model file.');
unlink($output_path);
}
# Test 4: Read an 3MF containig multiple objects and volumes and write it as STL.
{
my $input_path = dirname($current_path). "/models/3mf/gimblekeychain.3mf";
my $output_path = dirname($current_path). "/models/stl/gimblekeychain.stl";
my $model = Slic3r::Model->new;
my $result = $model->read_tmf($input_path);
is($result, 1, 'Test 4: Read 3MF file check.');
$result = $model->write_stl($output_path);
is($result, 1, 'Test 4: convert to stl check.');
unlink($output_path);
}
# Test 5: Basic Test with model containing vertices and triangles.
{
my $amf_test_file = dirname($current_path). "/models/amf/FaceColors.amf.xml";
my $tmf_output_file = dirname($current_path). "/models/3mf/FaceColors.3mf";
my $expected_model = "\n"
." \n"
." \n"
." \n"
." \n"
." \n"
." \n"
." \n"
."\n";
# Create a new model.
my $model = Slic3r::Model->new;
# Read a simple AMF file.
$model->read_amf($amf_test_file);
# Write in 3MF format.
$model->write_tmf($tmf_output_file);
# Check contents in 3dmodel.model.
my $model_output ;
unzip $tmf_output_file => \$model_output, Name => "3D/3dmodel.model"
or die "unzip failed: $UnzipError\n";
is (clean($model_output), clean($expected_model), "Test 5: 3dmodel.model file matching");
# Check contents in content_types.xml.
my $content_types_output ;
unzip $tmf_output_file => \$content_types_output, Name => "[Content_Types].xml"
or die "unzip failed: $UnzipError\n";
is (clean($content_types_output), clean($expected_content_types), "Test 5: [Content_Types].xml file matching");
# Check contents in _rels.xml.
my $relationships_output ;
unzip $tmf_output_file => \$relationships_output, Name => "_rels/.rels"
or die "unzip failed: $UnzipError\n";
is (clean($relationships_output), clean($expected_relationships), "Test 5: _rels/.rels file matching");
unlink($tmf_output_file);
}
# Test 6: Read a Slic3r exported 3MF file.
{
my $input_path = dirname($current_path). "/models/3mf/chess.3mf";
my $output_path = dirname($current_path). "/models/3mf/chess_2.3mf";
# Read a 3MF model.
my $model = Slic3r::Model->new;
my $result = $model->read_tmf($input_path);
is($result, 1, 'Test 6: Read 3MF file check.');
# Export the 3MF file.
$result = $model->write_tmf($output_path);
is($result, 1, 'Test 6: Write 3MF file check.');
# Re-read the exported file.
my $model_2 = Slic3r::Model->new;
$result = $model_2->read_tmf($output_path);
is($result, 1, 'Test 6: Read second 3MF file check.');
is($model->metadata_count(), $model_2->metadata_count(), 'Test 6: metadata match check.');
# Check the number of read objects.
is($model->objects_count(), $model_2->objects_count(), 'Test 6: objects match check.');
unlink($output_path);
}
# Finish finish test cases.
done_testing();
__END__